Skip to content

Commit

Permalink
Clockwork Cult Defenses Patch - Leader role, traps and wiring, hulk a…
Browse files Browse the repository at this point in the history
…nd mech soft-counters, +more (tgstation#32935)

* Adds the Eminence

* New abilities and a command system

* More stuff

* I did something in this commit but I dunno what

* Beginning work on trap setups

* This is good for now until arm gets his sprites

* I did something here!

* Manacle sprites

* R.I.P. R&D

* Maintainer review

* QoL, slabbin' it up

* Conflicts

* Conflicts

* <

* Now it compiles!

* TGUI

* TGUI, again

* 🥝

* that should be all, but I'll do some quick testing...

* aha!
  • Loading branch information
Ashe Higgs authored and optimumtact committed Dec 6, 2017
1 parent 8359708 commit 32c68a6
Show file tree
Hide file tree
Showing 43 changed files with 1,122 additions and 401 deletions.
10 changes: 7 additions & 3 deletions _maps/map_files/generic/City_of_Cogs.dmm
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,10 @@
/obj/item/clockwork/component/vanguard_cogwheel/onyx_prism,
/turf/open/indestructible/reebe_void,
/area/reebe)
"bj" = (
/obj/structure/destructible/clockwork/eminence_spire,
/turf/open/floor/clockwork/reebe,
/area/reebe/city_of_cogs)

(1,1,1) = {"
aa
Expand Down Expand Up @@ -31739,7 +31743,7 @@ aj
aj
ai
aj
aj
az
aj
ai
aj
Expand Down Expand Up @@ -31996,7 +32000,7 @@ aj
aj
ap
aj
az
aj
aj
ap
aj
Expand Down Expand Up @@ -32253,7 +32257,7 @@ aj
aj
ai
aj
aj
bj
aj
ai
aj
Expand Down
15 changes: 10 additions & 5 deletions code/__DEFINES/clockcult.dm
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//component id defines
#define BELLIGERENT_EYE "belligerent_eye"
#define VANGUARD_COGWHEEL "vanguard_cogwheel"
#define GEIS_CAPACITOR "geis_capacitor"
//component id defines; sometimes these may not make sense in regards to their use in scripture but important ones are bright
#define BELLIGERENT_EYE "belligerent_eye" //Use this for offensive and damaging scripture!
#define VANGUARD_COGWHEEL "vanguard_cogwheel" //Use this for defensive and healing scripture!
#define GEIS_CAPACITOR "geis_capacitor" //Use this for niche scripture!
#define REPLICANT_ALLOY "replicant_alloy"
#define HIEROPHANT_ANSIBLE "hierophant_ansible"
#define HIEROPHANT_ANSIBLE "hierophant_ansible" //Use this for construction-related scripture!

GLOBAL_VAR_INIT(clockwork_construction_value, 0) //The total value of all structures built by the clockwork cult
GLOBAL_VAR_INIT(clockwork_caches, 0) //How many clockwork caches exist in the world (not each individual)
Expand Down Expand Up @@ -69,6 +69,9 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
//Objective text define
#define CLOCKCULT_OBJECTIVE "Construct the Ark of the Clockwork Justicar and free Ratvar."

//Eminence defines
#define SUPERHEATED_CLOCKWORK_WALL_LIMIT 20 //How many walls can be superheated at once

//misc clockcult stuff

#define SIGIL_ACCESS_RANGE 2 //range at which transmission sigils can access power
Expand All @@ -86,3 +89,5 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
#define MARAUDER_SCRIPTURE_SCALING_TIME 50 //The amount of extra deciseconds tacked on to the marauder scripture recital time per recent marauder

#define MARAUDER_SCRIPTURE_SCALING_MAX 300 //The maximum extra time applied to the marauder scripture

#define ARK_SCREAM_COOLDOWN 600 //This much time has to pass between instances of the Ark taking damage before it will "scream" again
2 changes: 2 additions & 0 deletions code/__DEFINES/is_helpers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@

#define iscameramob(A) (istype(A, /mob/camera))

#define iseminence(A) (istype(A, /mob/camera/eminence))

//Objects
#define isobj(A) istype(A, /obj) //override the byond proc because it returns true on children of /atom/movable that aren't objs

Expand Down
7 changes: 7 additions & 0 deletions code/__HELPERS/unsorted.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1510,3 +1510,10 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
else
return "\[[url_encode(thing.tag)]\]"
return "\ref[input]"

//Returns a list of all servants of Ratvar and observers.
/proc/servants_and_ghosts()
. = list()
for(var/V in GLOB.player_list)
if(is_servant_of_ratvar(V) || isobserver(V))
. += V
18 changes: 5 additions & 13 deletions code/_onclick/hud/alert.dm
Original file line number Diff line number Diff line change
Expand Up @@ -388,23 +388,15 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
desc = "<font size=3><b>CHETR<br>NYY<br>HAGEHUGF-NAQ-UBABE<br>RATVAR.</b></font>"
else
var/servants = 0
var/validservants = 0
var/list/textlist
for(var/mob/living/L in GLOB.alive_mob_list)
if(is_servant_of_ratvar(L))
servants++
if(ishuman(L) || issilicon(L))
validservants++
if(servants > 1)
if(validservants > 1)
textlist = list("<b>[servants]</b> Servants, <b>[validservants]</b> of which count towards scripture.<br>")
else
textlist = list("<b>[servants]</b> Servants, [validservants ? "<b>[validservants]</b> of which counts":"none of which count"] towards scripture.<br>")
else
textlist = list("<b>[servants]</b> Servant, who [validservants ? "counts":"does not count"] towards scripture.<br>")
for(var/i in SSticker.scripture_states)
if(i != SCRIPTURE_DRIVER) //ignore the always-unlocked stuff
textlist += "[i] Scripture: <b>[SSticker.scripture_states[i] ? "UNLOCKED":"LOCKED"]</b><br>"
textlist = list("[SSticker.mode.eminence ? "There is an Eminence." : "<b>There is no Eminence! Get one ASAP!</b>"]<br>")
textlist += "There are currently <b>[servants]</b> servant[servants > 1 ? "s" : ""] of Ratvar.<br>"
for(var/i in SSticker.scripture_states)
if(i != SCRIPTURE_DRIVER) //ignore the always-unlocked stuff
textlist += "[i] Scripture: <b>[SSticker.scripture_states[i] ? "UNLOCKED":"LOCKED"]</b><br>"
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
if(G)
var/time_info = G.get_arrival_time(FALSE)
Expand Down
55 changes: 36 additions & 19 deletions code/game/gamemodes/clock_cult/clock_cult.dm
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ Credit where due:
// PROCS //
///////////

/proc/is_servant_of_ratvar(mob/living/M)
/proc/is_servant_of_ratvar(mob/M)
return istype(M) && M.mind && M.mind.has_antag_datum(ANTAG_DATUM_CLOCKCULT)

/proc/is_eligible_servant(mob/living/M)
/proc/is_eligible_servant(mob/M)
if(!istype(M))
return FALSE
if(M.mind)
Expand All @@ -61,19 +61,19 @@ Credit where due:
return FALSE
if(iscultist(M) || isconstruct(M) || M.isloyal() || ispAI(M))
return FALSE
if(ishuman(M) || isbrain(M) || isguardian(M) || issilicon(M) || isclockmob(M) || istype(M, /mob/living/simple_animal/drone/cogscarab))
if(ishuman(M) || isbrain(M) || isguardian(M) || issilicon(M) || isclockmob(M) || istype(M, /mob/living/simple_animal/drone/cogscarab) || istype(M, /mob/camera/eminence))
return TRUE
return FALSE

/proc/add_servant_of_ratvar(mob/living/L, silent = FALSE)
/proc/add_servant_of_ratvar(mob/L, silent = FALSE)
if(!L || !L.mind)
return
var/update_type = ANTAG_DATUM_CLOCKCULT
if(silent)
update_type = ANTAG_DATUM_CLOCKCULT_SILENT
. = L.mind.add_antag_datum(update_type)

/proc/remove_servant_of_ratvar(mob/living/L, silent = FALSE)
/proc/remove_servant_of_ratvar(mob/L, silent = FALSE)
if(!L || !L.mind)
return
var/datum/antagonist/clockcult/clock_datum = L.mind.has_antag_datum(ANTAG_DATUM_CLOCKCULT)
Expand All @@ -88,6 +88,7 @@ Credit where due:
///////////////

/datum/game_mode
var/datum/mind/eminence //The clockwork Eminence
var/list/servants_of_ratvar = list() //The Enlightened servants of Ratvar
var/clockwork_explanation = "Defend the Ark of the Clockwork Justiciar and free Ratvar." //The description of the current objective

Expand Down Expand Up @@ -176,7 +177,7 @@ Credit where due:
if(!S.forceMove(get_turf(L)))
qdel(S)
if(S && !QDELETED(S))
to_chat(L, "<span class='bold large_brass'>There is a paper in your backpack! Read it!</span>")
to_chat(L, "<span class='bold large_brass'>There is a paper in your backpack! It'll tell you if anything's changed, as well as what to expect.</span>")
to_chat(L, "<span class='alloy'>[slot] is a <b>clockwork slab</b>, a multipurpose tool used to construct machines and invoke ancient words of power. If this is your first time \
as a servant, you can find a concise tutorial in the Recollection category of its interface.</span>")
to_chat(L, "<span class='alloy italics'>If you want more information, you can find a wiki link here!</span> https://tgstation13.org/wiki/Clockwork_Cult")
Expand All @@ -201,11 +202,12 @@ Credit where due:
return //Doesn't end until the round does

/datum/game_mode/clockwork_cult/generate_report()
return "We have lost contact with multiple stations in your sector. They have gone dark and do not respond to all transmissions, although they appear intact and the crew's life \
signs remain uninterrupted. Those that have managed to send a transmission or have had some of their crew escape tell tales of a machine cult creating sapient automatons and seeking \
to brainwash the crew to summon their god, Ratvar. If evidence of this cult is dicovered aboard your station, extreme caution and extreme vigilance must be taken going forward, and \
all resources should be devoted to stopping this cult. Note that holy water seems to weaken and eventually return the minds of cultists that ingest it, and mindshield implants will \
prevent conversion altogether."
return "Bluespace monitors near your sector have detected a continuous stream of patterned fluctuations since the station was completed. It is most probable that a powerful entity \
from a very far distance away is using to the station as a vector to cross that distance through bluespace. The theoretical power required for this would be monumental, and if \
the entity is hostile, it would need to rely on a single central power source - disrupting or destroying that power source would be the best way to prevent said entity from causing \
harm to company personnel or property.<br><br>Keep a sharp on any crew that appear to be oddly-dressed or using what appear to be magical powers, as these crew may be defectors \
working for this entity and utilizing highly-advanced technology to cross the great distance at will. If they should turn out to be a credible threat, the task falls on you and \
your crew to dispatch it in a timely manner."

/datum/game_mode/proc/auto_declare_completion_clockwork_cult()
var/text = ""
Expand All @@ -223,9 +225,11 @@ Credit where due:
for(var/i in SSticker.scripture_states)
if(i != SCRIPTURE_DRIVER)
text += "<br><b>[i] scripture</b> was: <b>[SSticker.scripture_states[i] ? "UN":""]LOCKED</b>"
if(SSticker.mode.eminence)
text += "<br><b>The Eminence was:</b> [printplayer(SSticker.mode.eminence)]"
if(servants_of_ratvar.len)
text += "<br><b>Ratvar's servants were:</b>"
for(var/datum/mind/M in servants_of_ratvar)
for(var/datum/mind/M in servants_of_ratvar - SSticker.mode.eminence)
text += printplayer(M)
to_chat(world, text)

Expand All @@ -245,14 +249,14 @@ Credit where due:
/datum/outfit/servant_of_ratvar
name = "Servant of Ratvar"
uniform = /obj/item/clothing/under/chameleon/ratvar
shoes = /obj/item/clothing/shoes/workboots
shoes = /obj/item/clothing/shoes/sneakers/black
back = /obj/item/storage/backpack
ears = /obj/item/device/radio/headset
gloves = /obj/item/clothing/gloves/color/yellow
belt = /obj/item/storage/belt/utility/servant
backpack_contents = list(/obj/item/storage/box/engineer = 1, \
/obj/item/clockwork/replica_fabricator = 1, /obj/item/stack/tile/brass/fifty = 1, /obj/item/paper/servant_primer = 1)
id = /obj/item/card/id
id = /obj/item/device/pda
var/plasmaman //We use this to determine if we should activate internals in post_equip()

/datum/outfit/servant_of_ratvar/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
Expand All @@ -264,16 +268,24 @@ Credit where due:
plasmaman = TRUE

/datum/outfit/servant_of_ratvar/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
var/obj/item/card/id/W = H.wear_id
var/obj/item/card/id/W = new(H)
var/obj/item/device/pda/PDA = H.wear_id
W.assignment = "Assistant"
W.access += ACCESS_MAINT_TUNNELS
W.registered_name = H.real_name
W.update_label()
if(plasmaman && !visualsOnly) //If we need to breathe from the plasma tank, we should probably start doing that
H.internal = H.get_item_for_held_index(2)
H.update_internals_hud_icon(1)
PDA.owner = H.real_name
PDA.ownjob = "Assistant"
PDA.update_label()
PDA.id_check(H, W)
H.sec_hud_set_ID()


//This paper serves as a quick run-down to the cult as well as a changelog to refer to.
//Check strings/clockwork_cult_changelog.txt for the changelog, and update it when you can!
/obj/item/paper/servant_primer
name = "The Ark And You: A Primer On Servitude"
color = "#DAAA18"
Expand Down Expand Up @@ -303,14 +315,19 @@ Credit where due:
<hr>\
<h2>Things that have changed:</h2>\
<ul>\
<li><b><i>Scripture no longer requires components, and instead uses power.</i></b></li>\
<li>Added a <b>5-minute grace period</b> for the crew to prepare for the assault when the Ark activates.</li>\
<li>Script and Application scriptures can now be unlocked with enough power.</li>\
<li><b>Added the Hateful Manacles scripture</b>, which handcuffs targets!</li>\
CLOCKCULTCHANGELOG\
</ul>\
<hr>\
<b>Good luck!</b>"

/obj/item/paper/servant_primer/Initialize()
. = ..()
var/changelog = world.file2list("strings/clockwork_cult_changelog.txt")
var/changelog_contents = ""
for(var/entry in changelog)
changelog_contents += "<li>[entry]</li>"
info = replacetext(info, "CLOCKCULTCHANGELOG", changelog_contents)

/obj/item/paper/servant_primer/examine(mob/user)
if(!is_servant_of_ratvar(user) && !isobserver(user))
to_chat(user, "<span class='danger'>You can't understand any of the words on [src].</span>")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@

//changes construction value
/proc/change_construction_value(amount)
GLOB.clockwork_construction_value += amount
if(!SSticker.current_state != GAME_STATE_PLAYING) //This is primarily so that structures added pre-roundstart don't contribute to construction value
return
GLOB.clockwork_construction_value = max(0, GLOB.clockwork_construction_value + amount)

/proc/can_recite_scripture(mob/living/L, can_potentially)
return (is_servant_of_ratvar(L) && (can_potentially || (L.stat == CONSCIOUS && L.can_speak_vocal())) && (GLOB.ratvar_awakens || (ishuman(L) || issilicon(L))))
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@

/obj/item/restraints/handcuffs/clockwork
name = "replicant manacles"
desc = "Cold, heavy manacles made out of some strange black metal."
desc = "Heavy manacles made out of freezing-cold metal. It looks like brass, but feels much more solid."
icon_state = "brass_manacles"
flags_1 = DROPDEL_1

/obj/item/restraints/handcuffs/clockwork/dropped(mob/user)
Expand Down
29 changes: 22 additions & 7 deletions code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
/obj/item/clockwork/slab //Clockwork slab: The most important tool in Ratvar's arsenal. Allows scripture recital, tutorials, and generates components.
name = "clockwork slab"
desc = "A strange metal tablet. A clock in the center turns around and around."
clockwork_desc = "A link between you and the Celestial Derelict. It contains information, recites scripture, and is your most vital tool as a Servant."
clockwork_desc = "A link between you and the Celestial Derelict. It contains information, recites scripture, and is your most vital tool as a Servant.<br>\
It can be used to link traps and triggers by attacking them with the slab. Keep in mind that traps linked with one another will activate in tandem!"

icon_state = "dread_ipad"
lefthand_file = 'icons/mob/inhands/antag/clockwork_lefthand.dmi'
righthand_file = 'icons/mob/inhands/antag/clockwork_righthand.dmi'
var/inhand_overlay //If applicable, this overlay will be applied to the slab's inhand

slot_flags = SLOT_BELT
w_class = WEIGHT_CLASS_SMALL

var/busy //If the slab is currently being used by something
var/no_cost = FALSE //If the slab is admin-only and needs no components and has no scripture locks
var/speed_multiplier = 1 //multiples how fast this slab recites scripture
var/selected_scripture = SCRIPTURE_DRIVER
var/recollecting = FALSE //if we're looking at fancy recollection
var/obj/effect/proc_holder/slab/slab_ability //the slab's current bound ability, for certain scripture

var/recollecting = FALSE //if we're looking at fancy recollection
var/recollection_category = "Default"

var/list/quickbound = list(/datum/clockwork_scripture/abscond, \
/datum/clockwork_scripture/ranged_ability/kindle, /datum/clockwork_scripture/ranged_ability/hateful_manacles) //quickbound scripture, accessed by index
var/maximum_quickbound = 5 //how many quickbound scriptures we can have
var/recollection_category = "Default"

var/obj/structure/destructible/clockwork/trap/linking //If we're linking traps together, which ones we're doing

/obj/item/clockwork/slab/internal //an internal motor for mobs running scripture
name = "scripture motor"
Expand All @@ -34,8 +42,7 @@
add_servant_of_ratvar(user)

/obj/item/clockwork/slab/cyborg //three scriptures, plus a spear and fabricator
clockwork_desc = "A divine link to the Celestial Derelict, allowing for limited recital of scripture.\n\
Hitting a slab, a Servant with a slab, or a cache will <b>transfer</b> this slab's components into the target, the target's slab, or the global cache, respectively."
clockwork_desc = "A divine link to the Celestial Derelict, allowing for limited recital of scripture."
quickbound = list(/datum/clockwork_scripture/ranged_ability/judicial_marker, /datum/clockwork_scripture/ranged_ability/linked_vanguard, \
/datum/clockwork_scripture/create_object/stargazer)
maximum_quickbound = 6 //we usually have one or two unique scriptures, so if ratvar is up let us bind one more
Expand All @@ -46,7 +53,7 @@

/obj/item/clockwork/slab/cyborg/medical //five scriptures, plus a spear
quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/ranged_ability/linked_vanguard, /datum/clockwork_scripture/ranged_ability/sentinels_compromise, \
/datum/clockwork_scripture/create_object/vitality_matrix, /datum/clockwork_scripture/channeled/mending_mantra)
/datum/clockwork_scripture/create_object/vitality_matrix)

/obj/item/clockwork/slab/cyborg/security //twoscriptures, plus a spear
quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/ranged_ability/hateful_manacles, /datum/clockwork_scripture/ranged_ability/judicial_marker)
Expand Down Expand Up @@ -153,6 +160,11 @@
return 0
access_display(user)

/obj/item/clockwork/slab/AltClick(mob/living/user)
if(is_servant_of_ratvar(user) && linking)
linking = null
to_chat(user, "<span class='notice'>Object link canceled.</span>")

/obj/item/clockwork/slab/proc/access_display(mob/living/user)
if(!is_servant_of_ratvar(user))
return FALSE
Expand Down Expand Up @@ -410,7 +422,10 @@
data["tier_info"] = "<font color=#B18B25><i>Unlock these optional scriptures by converting another servant or if [DisplayPower(APPLICATION_UNLOCK_THRESHOLD)] of power is reached..</i></font>"

data["selected"] = selected_scripture

data["scripturecolors"] = "<font color=#DAAA18>Scriptures in <b>yellow</b> are related to construction and building.</font><br>\
<font color=#6E001A>Scriptures in <b>red</b> are related to attacking and offense.</font><br>\
<font color=#1E8CE1>Scriptures in <b>blue</b> are related to healing and defense.</font><br>\
<font color=#AF0AAF>Scriptures in <b>purple</b> are niche but still important!</font>"
generate_all_scripture()

data["scripture"] = list()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@
sleep(13)
name = "judicial explosion"
var/targetsjudged = 0
playsound(src, 'sound/effects/explosionfar.ogg', 100, 1, 1, 1)
playsound(src, 'sound/effects/explosion_distant.ogg', 100, 1, 1, 1)
set_light(0)
for(var/mob/living/L in range(1, src))
if(is_servant_of_ratvar(L))
Expand Down
Loading

0 comments on commit 32c68a6

Please sign in to comment.