Merge pull request #4250 from Citadel-Station-13/upstream-merge-32935

[MIRROR] Clockwork Cult Defenses Patch - Leader role, traps and wiring, hulk and mech soft-counters, +more
This commit is contained in:
deathride58
2017-12-10 22:43:58 +00:00
committed by GitHub
41 changed files with 1122 additions and 401 deletions
+10 -5
View File
@@ -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)
@@ -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
@@ -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
View File
@@ -144,6 +144,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
+7
View File
@@ -1507,3 +1507,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
+5 -13
View File
@@ -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)
+36 -19
View File
@@ -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)
@@ -61,11 +61,11 @@ 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
@@ -73,7 +73,7 @@ Credit where due:
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)
@@ -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
@@ -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")
@@ -202,11 +203,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 = ""
@@ -224,9 +226,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)
@@ -246,14 +250,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)
@@ -265,7 +269,8 @@ 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
@@ -273,8 +278,15 @@ Credit where due:
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"
@@ -304,14 +316,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>")
@@ -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))))
@@ -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"
origin_tech = "materials=2;magnets=5"
flags_1 = DROPDEL_1
@@ -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"
@@ -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
@@ -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)
@@ -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
@@ -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()
@@ -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))
@@ -0,0 +1,264 @@
//The Eminence is a unique mob that functions like the leader of the cult. It's incorporeal but can interact with the world in several ways.
/mob/camera/eminence
name = "\the Emininence"
real_name = "\the Eminence"
desc = "The leader-elect of the servants of Ratvar."
icon = 'icons/effects/clockwork_effects.dmi'
icon_state = "eminence"
mouse_opacity = MOUSE_OPACITY_OPAQUE
move_on_shuttle = TRUE
see_in_dark = 8
invisibility = INVISIBILITY_OBSERVER
layer = FLY_LAYER
faction = list("ratvar")
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
var/static/superheated_walls = 0
/mob/camera/eminence/Initialize()
if(SSticker.mode.eminence)
return INITIALIZE_HINT_QDEL
. = ..()
/mob/camera/eminence/Destroy(force)
if(!force && mind && SSticker.mode.eminence == mind)
return QDEL_HINT_LETMELIVE
return ..()
/mob/camera/eminence/CanPass(atom/movable/mover, turf/target)
return TRUE
/mob/camera/eminence/Move(NewLoc, direct)
var/OldLoc = loc
if(NewLoc && !istype(NewLoc, /turf/open/indestructible/reebe_void))
forceMove(get_turf(NewLoc))
Moved(OldLoc, direct)
if(GLOB.ratvar_awakens)
for(var/turf/T in range(5, src))
if(prob(166 - (get_dist(src, T) * 33)))
T.ratvar_act() //Causes moving to leave a swath of proselytized area behind the Eminence
/mob/camera/eminence/Login()
..()
add_servant_of_ratvar(src, TRUE)
to_chat(src, "<span class='bold large_brass'>You have been selected as the Eminence!</span>")
to_chat(src, "<span class='brass'>As the Eminence, you lead the servants. Anything you say will be heard by the entire cult.</span>")
to_chat(src, "<span class='brass'>Though you can move through walls, you're also incorporeal, and largely can't interact with the world except for a few ways.</span>")
to_chat(src, "<span class='brass'>Additionally, unless the herald's beacon is activated, you can't understand any speech while away from Reebe.</span>")
SSticker.mode.eminence = mind
eminence_help()
for(var/V in actions)
var/datum/action/A = V
A.Remove(src) //So we get rid of duplicate actions; this also removes Hierophant network, since our say() goes across it anyway
var/datum/action/innate/eminence/E
for(var/V in subtypesof(/datum/action/innate/eminence))
E = new V
E.Grant(src)
/mob/camera/eminence/say(message)
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
if(!message)
return
log_talk(src, "[key_name(src)] : [message]", LOGSAY)
if(GLOB.ratvar_awakens)
visible_message("<span class='brass'><b>You feel light slam into your mind and form words:</b> \"[capitalize(message)]\"</span>")
playsound(src, 'sound/machines/clockcult/ark_scream.ogg', 50, FALSE)
hierophant_message("<span class='large_brass'><b>The Eminence:</b> \"[message]\"</span>")
/mob/camera/eminence/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
if(z == ZLEVEL_CITYOFCOGS || is_servant_of_ratvar(speaker) || GLOB.ratvar_approaches || GLOB.ratvar_awakens) //Away from Reebe, the Eminence can't hear anything
to_chat(src, message)
return
to_chat(src, "<i>[speaker] says something, but you can't understand any of it...</i>")
/mob/camera/eminence/ClickOn(atom/A, params)
var/list/modifiers = params2list(params)
if(modifiers["shift"])
A.examine(src)
return
if(modifiers["alt"] && istype(A, /turf/closed/wall/clockwork))
superheat_wall(A)
return
if(modifiers["middle"] || modifiers["ctrl"])
issue_command(A)
return
if(GLOB.ark_of_the_clockwork_justiciar == A)
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
if(G.recalling)
return
if(!G.recalls_remaining)
to_chat(src, "<span class='warning'>The Ark can no longer recall!</span>")
return
if(alert(src, "Initiate mass recall?", "Mass Recall", "Yes", "No") != "Yes" || QDELETED(src) || QDELETED(G) || !G.obj_integrity)
return
G.initiate_mass_recall() //wHOOPS LOOKS LIKE A HULK GOT THROUGH
else if(istype(A, /obj/structure/destructible/clockwork/trap/trigger))
var/obj/structure/destructible/clockwork/trap/trigger/T = A
T.visible_message("<span class='danger'>[T] clunks as it's activated remotely.</span>")
to_chat(src, "<span class='brass'>You activate [T].</span>")
T.activate()
/mob/camera/eminence/ratvar_act()
name = "\improper Radiance"
real_name = "\improper Radiance"
desc = "The light, forgotten."
transform = matrix() * 2
invisibility = SEE_INVISIBLE_MINIMUM
/mob/camera/eminence/proc/issue_command(atom/movable/A)
var/list/commands
var/atom/movable/command_location
if(A == src)
commands = list("Defend the Ark!", "Advance!", "Retreat!", "Generate Power", "Build Defenses (Bottom-Up)", "Build Defenses (Top-Down)")
else
command_location = A
commands = list("Rally Here", "Regroup Here", "Avoid This Area", "Reinforce This Area")
if(istype(A, /obj/structure/destructible/clockwork/powered))
var/obj/structure/destructible/clockwork/powered/P = A
if(!can_access_clockwork_power(P))
commands += "Power This Structure"
if(P.obj_integrity < P.max_integrity)
commands += "Repair This Structure"
var/roma_invicta = input(src, "Choose a command to issue to your cult!", "Issue Commands") as null|anything in commands
if(!roma_invicta)
return
var/command_text = ""
var/marker_icon
switch(roma_invicta)
if("Rally Here")
command_text = "The Eminence orders an offensive rally at [command_location] to the GETDIR!"
marker_icon = "eminence_rally"
if("Regroup Here")
command_text = "The Eminence orders a regroup to [command_location] to the GETDIR!"
marker_icon = "eminence_rally"
if("Avoid This Area")
command_text = "The Eminence has designated the area to your GETDIR as dangerous and to be avoided!"
marker_icon = "eminence_avoid"
if("Reinforce This Area")
command_text = "The Eminence orders the defense and fortification of the area to your GETDIR!"
marker_icon = "eminence_reinforce"
if("Power This Structure")
command_text = "[command_location] to your GETDIR has no power! Turn it on and make sure there's a sigil of transmission nearby!"
marker_icon = "eminence_unlimited_power"
if("Repair This Structure")
command_text = "The Eminence orders that [command_location] to your GETDIR should be repaired ASAP!"
marker_icon = "eminence_repair"
if("Defend the Ark!")
command_text = "The Eminence orders immediate defense of the Ark!"
if("Advance!")
command_text = "The Eminence commands you push forward!"
if("Retreat!")
command_text = "The Eminence has sounded the retreat! Fall back!"
if("Generate Power")
command_text = "The Eminence orders more power! Build power generations on the station!"
if("Build Defenses (Bottom-Up)")
command_text = "The Eminence orders that defenses should be built starting from the bottom of Reebe!"
if("Build Defenses (Top-Down)")
command_text = "The Eminence orders that defenses should be built starting from the top of Reebe!"
if(marker_icon)
new/obj/effect/temp_visual/ratvar/command_point(get_turf(A), marker_icon)
for(var/mob/M in servants_and_ghosts())
to_chat(M, "<span class='large_brass'>[replacetext(command_text, "GETDIR", dir2text(get_dir(M, command_location)))]</span>")
M.playsound_local(M, 'sound/machines/clockcult/eminence_command.ogg', 75, FALSE, pressure_affected = FALSE)
else
hierophant_message("<span class='bold large_brass'>[command_text]</span>")
for(var/mob/M in servants_and_ghosts())
M.playsound_local(M, 'sound/machines/clockcult/eminence_command.ogg', 75, FALSE, pressure_affected = FALSE)
/mob/camera/eminence/proc/superheat_wall(turf/closed/wall/clockwork/wall)
if(!istype(wall))
return
if(superheated_walls >= SUPERHEATED_CLOCKWORK_WALL_LIMIT && !wall.heated)
to_chat(src, "<span class='warning'>You're exerting all of your power superheating this many walls already! Cool some down first!</span>")
return
wall.turn_up_the_heat()
if(wall.heated)
superheated_walls++
to_chat(src, "<span class='neovgre_small'>You superheat [wall]. <b>Superheated walls:</b> [superheated_walls]/[SUPERHEATED_CLOCKWORK_WALL_LIMIT]")
else
superheated_walls--
to_chat(src, "<span class='neovgre_small'>You cool [wall]. <b>Superheated walls:</b> [superheated_walls]/[SUPERHEATED_CLOCKWORK_WALL_LIMIT]")
/mob/camera/eminence/proc/eminence_help()
to_chat(src, "<span class='bold alloy'>You can make use of certain shortcuts to perform different actions:</span>")
to_chat(src, "<span class='alloy'><b>Alt-Click a clockwork wall</b> to superheat or cool it down. \
Superheated walls can't be destroyed by hulks or mechs and are much slower to deconstruct, and are marked by a bright red glow. \
This lasts indefinitely, but only [SUPERHEATED_CLOCKWORK_WALL_LIMIT] clockwork walls can be superheated at once.</span>")
to_chat(src, "<span class='alloy'><b>Interact with the Ark</b> to initiate an emergency recall that teleports all servants directly to its location after a short delay. \
This can only be used a single time, or twice if the herald's beacon was activated,</span>")
to_chat(src, "<span class='alloy'><b>Middle or Ctrl-Click anywhere</b> to allow you to issue a variety of contextual commands to your cult. Different objects allow for different \
commands. <i>Doing this on yourself will provide commands that tell the entire cult a goal.</i></span>")
//Eminence actions below this point
/datum/action/innate/eminence
name = "Eminence Action"
desc = "You shouldn't see this. File a bug report!"
icon_icon = 'icons/mob/actions/actions_clockcult.dmi'
background_icon_state = "bg_clock"
buttontooltipstyle = "clockcult"
/datum/action/innate/eminence/IsAvailable()
if(!iseminence(owner))
qdel(src)
return
return ..()
//Lists available powers
/datum/action/innate/eminence/power_list
name = "Eminence Powers"
desc = "Forgot what you can do? This refreshes you on your powers as Eminence."
button_icon_state = "eminence_rally"
/datum/action/innate/eminence/power_list/Activate()
var/mob/camera/eminence/E = owner
E.eminence_help()
//Returns to the Ark
/datum/action/innate/eminence/ark_jump
name = "Return to Ark"
desc = "Warps you to the Ark."
button_icon_state = "Abscond"
/datum/action/innate/eminence/ark_jump/Activate()
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
if(G)
owner.forceMove(get_turf(G))
owner.playsound_local(owner, 'sound/magic/magic_missile.ogg', 50, TRUE)
flash_color(owner, flash_color = "#AF0AAF", flash_time = 25)
else
to_chat(owner, "<span class='warning'>There is no Ark!</span>")
//Warps to the Station
/datum/action/innate/eminence/station_jump
name = "Warp to Station"
desc = "Warps to Space Station 13. You cannot hear anything while there!</span>"
button_icon_state = "warp_down"
/datum/action/innate/eminence/station_jump/Activate()
if(owner.z == ZLEVEL_CITYOFCOGS)
owner.forceMove(get_turf(pick(GLOB.generic_event_spawns)))
owner.playsound_local(owner, 'sound/magic/magic_missile.ogg', 50, TRUE)
flash_color(owner, flash_color = "#AF0AAF", flash_time = 25)
else
to_chat(owner, "<span class='warning'>You're already on the station!</span>")
//A quick-use button for recalling the servants to the Ark
/datum/action/innate/eminence/mass_recall
name = "Mass Recall"
desc = "Initiates a mass recall, warping all servants to the Ark after a short delay. This can only be used once."
button_icon_state = "Spatial Gateway"
/datum/action/innate/eminence/mass_recall/IsAvailable()
. = ..()
if(.)
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
if(G)
return G.recalls_remaining && !G.recalling
return FALSE
/datum/action/innate/eminence/mass_recall/Activate()
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
if(G && !G.recalling && G.recalls_remaining)
if(alert(owner, "Initiate mass recall?", "Mass Recall", "Yes", "No") != "Yes" || QDELETED(owner) || QDELETED(G) || !G.obj_integrity)
return
G.initiate_mass_recall()
@@ -3,6 +3,70 @@
//////////////////
//Sigil of Transmission: Creates a sigil of transmission that can drain and store power for clockwork structures.
/datum/clockwork_scripture/create_object/sigil_of_transmission
descname = "Powers Nearby Structures - Important!"
name = "Sigil of Transmission"
desc = "Places a sigil that can drain and will store energy to power clockwork structures."
invocations = list("Divinity...", "...power our creations!")
channel_time = 70
power_cost = 200
whispered = TRUE
object_path = /obj/effect/clockwork/sigil/transmission
creator_message = "<span class='brass'>A sigil silently appears below you. It will automatically power clockwork structures near it and will drain power when activated.</span>"
usage_tip = "Cyborgs can charge from this sigil by remaining over it for 5 seconds."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 1
quickbind = TRUE
quickbind_desc = "Creates a Sigil of Transmission, which can drain and will store power for clockwork structures."
//Mania Motor: Creates a malevolent transmitter that will broadcast the whispers of Sevtug into the minds of nearby nonservants, causing a variety of mental effects at a power cost.
/datum/clockwork_scripture/create_object/mania_motor
descname = "Powered Structure, Area Denial"
name = "Mania Motor"
desc = "Creates a mania motor which causes minor damage and a variety of negative mental effects in nearby non-Servant humans, potentially up to and including conversion."
invocations = list("May this transmitter...", "...break the will of all who oppose us!")
channel_time = 80
power_cost = 750
object_path = /obj/structure/destructible/clockwork/powered/mania_motor
creator_message = "<span class='brass'>You form a mania motor, which causes minor damage and negative mental effects in non-Servants.</span>"
observer_message = "<span class='warning'>A two-pronged machine rises from the ground!</span>"
invokers_required = 2
multiple_invokers_used = TRUE
usage_tip = "It will also cure hallucinations and brain damage in nearby Servants."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 2
quickbind = TRUE
quickbind_desc = "Creates a Mania Motor, which causes minor damage and negative mental effects in non-Servants."
//Clockwork Obelisk: Creates a powerful obelisk that can be used to broadcast messages or open a gateway to any servant or clockwork obelisk at a power cost.
/datum/clockwork_scripture/create_object/clockwork_obelisk
descname = "Powered Structure, Teleportation Hub"
name = "Clockwork Obelisk"
desc = "Creates a clockwork obelisk that can broadcast messages over the Hierophant Network or open a Spatial Gateway to any living Servant or clockwork obelisk."
invocations = list("May this obelisk...", "...take us to all places!")
channel_time = 80
power_cost = 300
object_path = /obj/structure/destructible/clockwork/powered/clockwork_obelisk
creator_message = "<span class='brass'>You form a clockwork obelisk which can broadcast messages or produce Spatial Gateways.</span>"
observer_message = "<span class='warning'>A brass obelisk appears hanging in midair!</span>"
invokers_required = 2
multiple_invokers_used = TRUE
usage_tip = "Producing a gateway has a high power cost. Gateways to or between clockwork obelisks receive double duration and uses."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 3
quickbind = TRUE
quickbind_desc = "Creates a Clockwork Obelisk, which can send messages or open Spatial Gateways with power."
//Clockwork Marauder: Creates a construct shell for a clockwork marauder, a well-rounded frontline fighter.
/datum/clockwork_scripture/create_object/construct/clockwork_marauder
descname = "Well-Rounded Combat Construct"
@@ -16,7 +80,7 @@
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
primary_component = BELLIGERENT_EYE
sort_priority = 1
sort_priority = 4
quickbind = TRUE
quickbind_desc = "Creates a clockwork marauder, used for frontline combat."
object_path = /obj/item/clockwork/construct_chassis/clockwork_marauder
@@ -59,67 +123,3 @@
time_since_last_marauder = world.time //So that it can't be spammed to make the marauder exclusion plummet; this emulates "ticking"
recent_marauders = max(0, recent_marauders - marauders_to_exclude)
scaled_recital_time = min(recent_marauders * MARAUDER_SCRIPTURE_SCALING_TIME, MARAUDER_SCRIPTURE_SCALING_MAX)
//Mania Motor: Creates a malevolent transmitter that will broadcast the whispers of Sevtug into the minds of nearby nonservants, causing a variety of mental effects at a power cost.
/datum/clockwork_scripture/create_object/mania_motor
descname = "Powered Structure, Area Denial"
name = "Mania Motor"
desc = "Creates a mania motor which causes minor damage and a variety of negative mental effects in nearby non-Servant humans, potentially up to and including conversion."
invocations = list("May this transmitter...", "...break the will of all who oppose us!")
channel_time = 80
power_cost = 750
object_path = /obj/structure/destructible/clockwork/powered/mania_motor
creator_message = "<span class='brass'>You form a mania motor, which causes minor damage and negative mental effects in non-Servants.</span>"
observer_message = "<span class='warning'>A two-pronged machine rises from the ground!</span>"
invokers_required = 2
multiple_invokers_used = TRUE
usage_tip = "It will also cure hallucinations and brain damage in nearby Servants."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
primary_component = GEIS_CAPACITOR
sort_priority = 2
quickbind = TRUE
quickbind_desc = "Creates a Mania Motor, which causes minor damage and negative mental effects in non-Servants."
//Sigil of Transmission: Creates a sigil of transmission that can drain and store power for clockwork structures.
/datum/clockwork_scripture/create_object/sigil_of_transmission
descname = "Structure Power Generator & Battery"
name = "Sigil of Transmission"
desc = "Places a sigil that can drain and will store energy to power clockwork structures."
invocations = list("Divinity...", "...power our creations!")
channel_time = 70
power_cost = 200
whispered = TRUE
object_path = /obj/effect/clockwork/sigil/transmission
creator_message = "<span class='brass'>A sigil silently appears below you. It will automatically power clockwork structures near it and will drain power when activated.</span>"
usage_tip = "Cyborgs can charge from this sigil by remaining over it for 5 seconds."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 3
quickbind = TRUE
quickbind_desc = "Creates a Sigil of Transmission, which can drain and will store power for clockwork structures."
//Clockwork Obelisk: Creates a powerful obelisk that can be used to broadcast messages or open a gateway to any servant or clockwork obelisk at a power cost.
/datum/clockwork_scripture/create_object/clockwork_obelisk
descname = "Powered Structure, Teleportation Hub"
name = "Clockwork Obelisk"
desc = "Creates a clockwork obelisk that can broadcast messages over the Hierophant Network or open a Spatial Gateway to any living Servant or clockwork obelisk."
invocations = list("May this obelisk...", "...take us to all places!")
channel_time = 80
power_cost = 300
object_path = /obj/structure/destructible/clockwork/powered/clockwork_obelisk
creator_message = "<span class='brass'>You form a clockwork obelisk which can broadcast messages or produce Spatial Gateways.</span>"
observer_message = "<span class='warning'>A brass obelisk appears hanging in midair!</span>"
invokers_required = 2
multiple_invokers_used = TRUE
usage_tip = "Producing a gateway has a high power cost. Gateways to or between clockwork obelisks receive double duration and uses."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 4
quickbind = TRUE
quickbind_desc = "Creates a Clockwork Obelisk, which can send messages or open Spatial Gateways with power."
@@ -2,27 +2,52 @@
// DRIVERS //
/////////////
//Hateful Manacles: Applies restraints from melee over several seconds. The restraints function like handcuffs and break on removal.
/datum/clockwork_scripture/ranged_ability/hateful_manacles
descname = "Handcuffs"
name = "Hateful Manacles"
desc = "Forms replicant manacles around a target's wrists that function like handcuffs."
invocations = list("Shackle the heretic!", "Break them in body and spirit!")
channel_time = 15
power_cost = 25
whispered = TRUE
usage_tip = "The manacles are about as strong as zipties, and break when removed."
//Stargazer: Creates a stargazer, a cheap power generator that utilizes starlight.
/datum/clockwork_scripture/create_object/stargazer
descname = "Generates Power From Starlight - Important!"
name = "Stargazer"
desc = "Forms a weak structure that generates power every second while within three tiles of starlight."
invocations = list("Capture their inferior light for us!")
channel_time = 50
power_cost = 50
object_path = /obj/structure/destructible/clockwork/stargazer
creator_message = "<span class='brass'>You form a stargazer, which will generate power near starlight.</span>"
observer_message = "<span class='warning'>A large lantern-shaped machine forms!</span>"
usage_tip = "For obvious reasons, make sure to place this near a window or somewhere else that can see space!"
tier = SCRIPTURE_DRIVER
primary_component = BELLIGERENT_EYE
one_per_tile = TRUE
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 1
ranged_type = /obj/effect/proc_holder/slab/hateful_manacles
slab_overlay = "hateful_manacles"
ranged_message = "<span class='neovgre_small'><i>You charge the clockwork slab with divine energy.</i>\n\
<b>Left-click a target within melee range to shackle!\n\
Click your slab to cancel.</b></span>"
timeout_time = 200
quickbind = TRUE
quickbind_desc = "Applies handcuffs to a struck target."
quickbind_desc = "Creates a stargazer, which generates power when near starlight."
/datum/clockwork_scripture/create_object/stargazer/check_special_requirements()
var/area/A = get_area(invoker)
if(A.outdoors || A.map_name == "Space" || !A.blob_allowed)
to_chat(invoker, "<span class='danger'>Stargazers can't be built off-station.</span>")
return
return ..()
//Integration Cog: Creates an integration cog that can be inserted into APCs to passively siphon power.
/datum/clockwork_scripture/create_object/integration_cog
descname = "APC Power Siphoner"
name = "Integration Cog"
desc = "Fabricates an integration cog, which can be used on an open APC to replace its innards and passively siphon its power."
invocations = list("Take that which sustains them!")
channel_time = 10
power_cost = 10
whispered = TRUE
object_path = /obj/item/clockwork/integration_cog
creator_message = "<span class='brass'>You form an integration cog, which can be inserted into an open APC to passively siphon power.</span>"
usage_tip = "Tampering isn't visible unless the APC is opened."
tier = SCRIPTURE_DRIVER
space_allowed = TRUE
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 2
quickbind = TRUE
quickbind_desc = "Creates an integration cog, which can be used to siphon power from an open APC."
//Sigil of Transgression: Creates a sigil of transgression, which briefly stuns and applies Belligerent to the first non-servant to cross it.
@@ -39,12 +64,78 @@
usage_tip = "The sigil does not silence its victim, and is generally used to soften potential converts or would-be invaders."
tier = SCRIPTURE_DRIVER
one_per_tile = TRUE
primary_component = BELLIGERENT_EYE
sort_priority = 2
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 3
quickbind = TRUE
quickbind_desc = "Creates a Sigil of Transgression, which will briefly stun and slow the next non-Servant to cross it."
//Sigil of Submission: Creates a sigil of submission, which converts one heretic above it after a delay.
/datum/clockwork_scripture/create_object/sigil_of_submission
descname = "Trap, Conversion"
name = "Sigil of Submission"
desc = "Places a luminous sigil that will convert any non-Servants that remain on it for 8 seconds."
invocations = list("Divinity, enlighten...", "...those who trespass here!")
channel_time = 60
power_cost = 125
whispered = TRUE
object_path = /obj/effect/clockwork/sigil/submission
creator_message = "<span class='brass'>A luminous sigil appears below you. Any non-Servants to cross it will be converted after 8 seconds if they do not move.</span>"
usage_tip = "This is the primary conversion method, though it will not penetrate mindshield implants."
tier = SCRIPTURE_DRIVER
one_per_tile = TRUE
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 4
quickbind = TRUE
quickbind_desc = "Creates a Sigil of Submission, which will convert non-Servants that remain on it."
//Kindle: Charges the slab with blazing energy. It can be released to stun and silence a target.
/datum/clockwork_scripture/ranged_ability/kindle
descname = "Short-Range Single-Target Stun"
name = "Kindle"
desc = "Charges your slab with divine energy, allowing you to overwhelm a target with Ratvar's light."
invocations = list("Divinity, show them your light!")
whispered = TRUE
channel_time = 30
power_cost = 125
usage_tip = "The light can be used from up to two tiles away. Damage taken will GREATLY REDUCE the stun's duration."
tier = SCRIPTURE_DRIVER
primary_component = BELLIGERENT_EYE
sort_priority = 5
slab_overlay = "volt"
ranged_type = /obj/effect/proc_holder/slab/kindle
ranged_message = "<span class='brass'><i>You charge the clockwork slab with divine energy.</i>\n\
<b>Left-click a target within melee range to stun!\n\
Click your slab to cancel.</b></span>"
timeout_time = 150
quickbind = TRUE
quickbind_desc = "Stuns and mutes a target from a short range."
//Hateful Manacles: Applies restraints from melee over several seconds. The restraints function like handcuffs and break on removal.
/datum/clockwork_scripture/ranged_ability/hateful_manacles
descname = "Handcuffs"
name = "Hateful Manacles"
desc = "Forms replicant manacles around a target's wrists that function like handcuffs."
invocations = list("Shackle the heretic!", "Break them in body and spirit!")
channel_time = 15
power_cost = 25
whispered = TRUE
usage_tip = "The manacles are about as strong as zipties, and break when removed."
tier = SCRIPTURE_DRIVER
primary_component = BELLIGERENT_EYE
sort_priority = 6
ranged_type = /obj/effect/proc_holder/slab/hateful_manacles
slab_overlay = "hateful_manacles"
ranged_message = "<span class='neovgre_small'><i>You charge the clockwork slab with divine energy.</i>\n\
<b>Left-click a target within melee range to shackle!\n\
Click your slab to cancel.</b></span>"
timeout_time = 200
quickbind = TRUE
quickbind_desc = "Applies handcuffs to a struck target."
//Vanguard: Provides twenty seconds of stun immunity. At the end of the twenty seconds, 25% of all stuns absorbed are applied to the invoker.
/datum/clockwork_scripture/vanguard
descname = "Self Stun Immunity"
@@ -57,7 +148,7 @@
usage_tip = "You cannot reactivate Vanguard while still shielded by it."
tier = SCRIPTURE_DRIVER
primary_component = VANGUARD_COGWHEEL
sort_priority = 3
sort_priority = 7
quickbind = TRUE
quickbind_desc = "Allows you to temporarily absorb stuns. All stuns absorbed will affect you when disabled."
@@ -89,7 +180,7 @@
usage_tip = "The Compromise is very fast to invoke, and will remove holy water from the target Servant."
tier = SCRIPTURE_DRIVER
primary_component = VANGUARD_COGWHEEL
sort_priority = 4
sort_priority = 8
quickbind = TRUE
quickbind_desc = "Allows you to convert a Servant's brute, burn, and oxygen damage to half toxin damage.<br><b>Click your slab to disable.</b>"
slab_overlay = "compromise"
@@ -101,7 +192,7 @@
//Abscond: Used to return to Reebe.
/datum/clockwork_scripture/abscond
descname = "Return to Reebe"
descname = "Return to Reebe - Important!"
name = "Abscond"
desc = "Yanks you through space, returning you to home base."
invocations = list("As we bid farewell, and return to the stars...", "...we shall find our way home.")
@@ -113,7 +204,7 @@
usage_tip = "This can't be used while on Reebe, for obvious reasons."
tier = SCRIPTURE_DRIVER
primary_component = GEIS_CAPACITOR
sort_priority = 5
sort_priority = 9
quickbind = TRUE
quickbind_desc = "Returns you to Reebe."
@@ -153,52 +244,9 @@
animate(invoker.client, color = initial(invoker.client.color), time = 10)
//Kindle: Charges the slab with blazing energy. It can be released to stun and silence a target.
/datum/clockwork_scripture/ranged_ability/kindle
descname = "Short-Range Single-Target Stun"
name = "Kindle"
desc = "Charges your slab with divine energy, allowing you to overwhelm a target with Ratvar's light."
invocations = list("Divinity, show them your light!")
whispered = TRUE
channel_time = 30
power_cost = 125
usage_tip = "The light can be used from up to two tiles away. Damage taken will GREATLY REDUCE the stun's duration."
tier = SCRIPTURE_DRIVER
primary_component = GEIS_CAPACITOR
sort_priority = 6
slab_overlay = "volt"
ranged_type = /obj/effect/proc_holder/slab/kindle
ranged_message = "<span class='brass'><i>You charge the clockwork slab with divine energy.</i>\n\
<b>Left-click a target within melee range to stun!\n\
Click your slab to cancel.</b></span>"
timeout_time = 150
quickbind = TRUE
quickbind_desc = "Stuns and mutes a target from a short range."
//Sigil of Submission: Creates a sigil of submission, which converts one heretic above it after a delay.
/datum/clockwork_scripture/create_object/sigil_of_submission
descname = "Trap, Conversion"
name = "Sigil of Submission"
desc = "Places a luminous sigil that will convert any non-Servants that remain on it for 8 seconds."
invocations = list("Divinity, enlighten...", "...those who trespass here!")
channel_time = 60
power_cost = 125
whispered = TRUE
object_path = /obj/effect/clockwork/sigil/submission
creator_message = "<span class='brass'>A luminous sigil appears below you. Any non-Servants to cross it will be converted after 8 seconds if they do not move.</span>"
usage_tip = "This is the primary conversion method, though it will not penetrate mindshield implants."
tier = SCRIPTURE_DRIVER
one_per_tile = TRUE
primary_component = GEIS_CAPACITOR
sort_priority = 6
quickbind = TRUE
quickbind_desc = "Creates a Sigil of Submission, which will convert non-Servants that remain on it."
//Replicant: Creates a new clockwork slab.
/datum/clockwork_scripture/create_object/replicant
descname = "New Clockwork Slab"
descname = "New Clockwork Slab - Important!"
name = "Replicant"
desc = "Creates a new clockwork slab."
invocations = list("Metal, become greater!")
@@ -210,59 +258,12 @@
usage_tip = "This is inefficient as a way to produce components, as the slab produced must be held by someone with no other slabs to produce components."
tier = SCRIPTURE_DRIVER
space_allowed = TRUE
primary_component = REPLICANT_ALLOY
sort_priority = 7
primary_component = GEIS_CAPACITOR
sort_priority = 10
quickbind = TRUE
quickbind_desc = "Creates a new Clockwork Slab."
//Stargazer: Creates a stargazer, a cheap power generator that utilizes starlight.
/datum/clockwork_scripture/create_object/stargazer
descname = "Necessary Structure, Generates Power From Starlight"
name = "Stargazer"
desc = "Forms a weak structure that generates power every second while within three tiles of starlight."
invocations = list("Capture their inferior light for us!")
channel_time = 50
power_cost = 50
object_path = /obj/structure/destructible/clockwork/stargazer
creator_message = "<span class='brass'>You form a stargazer, which will generate power near starlight.</span>"
observer_message = "<span class='warning'>A large lantern-shaped machine forms!</span>"
usage_tip = "For obvious reasons, make sure to place this near a window or somewhere else that can see space!"
tier = SCRIPTURE_DRIVER
one_per_tile = TRUE
primary_component = REPLICANT_ALLOY
sort_priority = 8
quickbind = TRUE
quickbind_desc = "Creates a stargazer, which generates power when near starlight."
/datum/clockwork_scripture/create_object/stargazer/check_special_requirements()
var/area/A = get_area(invoker)
if(A.outdoors || A.map_name == "Space" || !A.blob_allowed)
to_chat(invoker, "<span class='danger'>Stargazers can't be built off-station.</span>")
return
return ..()
//Integration Cog: Creates an integration cog that can be inserted into APCs to passively siphon power.
/datum/clockwork_scripture/create_object/integration_cog
descname = "APC Power Siphoner"
name = "Integration Cog"
desc = "Fabricates an integration cog, which can be used on an open APC to replace its innards and passively siphon its power."
invocations = list("Take that which sustains them!")
channel_time = 10
power_cost = 10
whispered = TRUE
object_path = /obj/item/clockwork/integration_cog
creator_message = "<span class='brass'>You form an integration cog, which can be inserted into an open APC to passively siphon power.</span>"
usage_tip = "Tampering isn't visible unless the APC is opened."
tier = SCRIPTURE_DRIVER
space_allowed = TRUE
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 9
quickbind = TRUE
quickbind_desc = "Creates an integration cog, which can be used to siphon power from an open APC."
//Wraith Spectacles: Creates a pair of wraith spectacles, which grant xray vision but damage vision slowly.
/datum/clockwork_scripture/create_object/wraith_spectacles
descname = "Limited Xray Vision Glasses"
@@ -277,7 +278,7 @@
usage_tip = "\"True sight\" means that you are able to see through walls and in darkness."
tier = SCRIPTURE_DRIVER
space_allowed = TRUE
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 10
primary_component = GEIS_CAPACITOR
sort_priority = 11
quickbind = TRUE
quickbind_desc = "Creates a pair of Wraith Spectacles, which grant true sight but cause gradual vision loss."
@@ -2,6 +2,27 @@
// SCRIPTS //
/////////////
//Replica Fabricator: Creates a replica fabricator, used to convert objects and repair clockwork structures.
/datum/clockwork_scripture/create_object/replica_fabricator
descname = "Creates Brass and Converts Objects - Important!"
name = "Replica Fabricator"
desc = "Forms a device that, when used on certain objects, replaces them with their Ratvarian equivalents. It requires power to function."
invocations = list("With this device...", "...his presence shall be made known.")
channel_time = 20
power_cost = 250
whispered = TRUE
object_path = /obj/item/clockwork/replica_fabricator
creator_message = "<span class='brass'>You form a replica fabricator.</span>"
usage_tip = "Clockwork Walls cause nearby Tinkerer's Caches to generate components passively, making this a vital tool. Clockwork Floors heal toxin damage in Servants standing on them."
tier = SCRIPTURE_SCRIPT
space_allowed = TRUE
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 1
quickbind = TRUE
quickbind_desc = "Creates a Replica Fabricator, which can convert various objects to Ratvarian variants."
//Ocular Warden: Creates an ocular warden, which defends a small area near it.
/datum/clockwork_scripture/create_object/ocular_warden
descname = "Structure, Turret"
@@ -17,8 +38,8 @@
tier = SCRIPTURE_SCRIPT
one_per_tile = TRUE
space_allowed = TRUE
primary_component = BELLIGERENT_EYE
sort_priority = 1
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 2
quickbind = TRUE
quickbind_desc = "Creates an Ocular Warden, which will automatically attack nearby unrestrained non-Servants that can see it."
@@ -29,26 +50,6 @@
return ..()
//Judicial Visor: Creates a judicial visor, which can smite an area.
/datum/clockwork_scripture/create_object/judicial_visor
descname = "Delayed Area Knockdown Glasses"
name = "Judicial Visor"
desc = "Creates a visor that can smite an area, applying Belligerent and briefly stunning. The smote area will explode after 3 seconds."
invocations = list("Grant me the flames of Engine!")
channel_time = 10
power_cost = 400
whispered = TRUE
object_path = /obj/item/clothing/glasses/judicial_visor
creator_message = "<span class='brass'>You form a judicial visor, which is capable of smiting a small area.</span>"
usage_tip = "The visor has a thirty-second cooldown once used."
tier = SCRIPTURE_SCRIPT
space_allowed = TRUE
primary_component = BELLIGERENT_EYE
sort_priority = 2
quickbind = TRUE
quickbind_desc = "Creates a Judicial Visor, which can smite an area, applying Belligerent and briefly stunning."
//Vitality Matrix: Creates a sigil which will drain health from nonservants and can use that health to heal or even revive servants.
/datum/clockwork_scripture/create_object/vitality_matrix
descname = "Trap, Damage to Healing"
@@ -64,147 +65,35 @@
usage_tip = "The sigil will be consumed upon reviving a Servant."
tier = SCRIPTURE_SCRIPT
one_per_tile = TRUE
primary_component = VANGUARD_COGWHEEL
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 3
quickbind = TRUE
quickbind_desc = "Creates a Vitality Matrix, which drains non-Servants on it to heal Servants that cross it."
//Mending Mantra: Channeled for up to ten times over twenty seconds to repair structures and heal allies
/datum/clockwork_scripture/channeled/mending_mantra
descname = "Channeled, Area Healing and Repair"
name = "Mending Mantra"
desc = "Repairs nearby structures and constructs. Servants wearing clockwork armor will also be healed. Channeled every two seconds for a maximum of twenty seconds."
chant_invocations = list("Mend our dents!", "Heal our scratches!", "Repair our gears!")
chant_amount = 10
chant_interval = 20
power_cost = 1000
usage_tip = "This is a very effective way to rapidly reinforce a base after an attack."
tier = SCRIPTURE_SCRIPT
primary_component = VANGUARD_COGWHEEL
sort_priority = 4
quickbind = TRUE
quickbind_desc = "Repairs nearby structures and constructs. Servants wearing clockwork armor will also be healed.<br><b>Maximum 10 chants.</b>"
var/heal_attempts = 4
var/heal_amount = 2.5
var/static/list/damage_heal_order = list(BRUTE, BURN, OXY)
var/static/list/heal_finish_messages = list("There, all mended!", "Try not to get too damaged.", "No more dents and scratches for you!", "Champions never die.", "All patched up.", \
"Ah, child, it's okay now.", "Pain is temporary.", "What you do for the Justiciar is eternal.", "Bear this for me.", "Be strong, child.", "Please, be careful!", \
"If you die, you will be remembered.")
var/static/list/heal_target_typecache = typecacheof(list(
/obj/structure/destructible/clockwork,
/obj/machinery/door/airlock/clockwork,
/obj/machinery/door/window/clockwork,
/obj/structure/window/reinforced/clockwork,
/obj/structure/table/reinforced/brass))
var/static/list/ratvarian_armor_typecache = typecacheof(list(
/obj/item/clothing/suit/armor/clockwork,
/obj/item/clothing/head/helmet/clockwork,
/obj/item/clothing/gloves/clockwork,
/obj/item/clothing/shoes/clockwork))
/datum/clockwork_scripture/channeled/mending_mantra/chant_effects(chant_number)
var/turf/T
for(var/atom/movable/M in range(7, invoker))
if(isliving(M))
if(isclockmob(M) || istype(M, /mob/living/simple_animal/drone/cogscarab))
var/mob/living/simple_animal/S = M
if(S.health == S.maxHealth || S.stat == DEAD)
continue
T = get_turf(M)
for(var/i in 1 to heal_attempts)
if(S.health < S.maxHealth)
S.adjustHealth(-heal_amount)
new /obj/effect/temp_visual/heal(T, "#1E8CE1")
if(i == heal_attempts && S.health >= S.maxHealth) //we finished healing on the last tick, give them the message
to_chat(S, "<span class='inathneq'>\"[text2ratvar(pick(heal_finish_messages))]\"</span>")
break
else
to_chat(S, "<span class='inathneq'>\"[text2ratvar(pick(heal_finish_messages))]\"</span>")
break
else if(issilicon(M))
var/mob/living/silicon/S = M
if(S.health == S.maxHealth || S.stat == DEAD || !is_servant_of_ratvar(S))
continue
T = get_turf(M)
for(var/i in 1 to heal_attempts)
if(S.health < S.maxHealth)
S.heal_ordered_damage(heal_amount, damage_heal_order)
new /obj/effect/temp_visual/heal(T, "#1E8CE1")
if(i == heal_attempts && S.health >= S.maxHealth)
to_chat(S, "<span class='inathneq'>\"[text2ratvar(pick(heal_finish_messages))]\"</span>")
break
else
to_chat(S, "<span class='inathneq'>\"[text2ratvar(pick(heal_finish_messages))]\"</span>")
break
else if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.health == H.maxHealth || H.stat == DEAD || !is_servant_of_ratvar(H))
continue
T = get_turf(M)
var/heal_ticks = 0 //one heal tick for each piece of ratvarian armor worn
var/obj/item/I = H.get_item_by_slot(slot_wear_suit)
if(is_type_in_typecache(I, ratvarian_armor_typecache))
heal_ticks++
I = H.get_item_by_slot(slot_head)
if(is_type_in_typecache(I, ratvarian_armor_typecache))
heal_ticks++
I = H.get_item_by_slot(slot_gloves)
if(is_type_in_typecache(I, ratvarian_armor_typecache))
heal_ticks++
I = H.get_item_by_slot(slot_shoes)
if(is_type_in_typecache(I, ratvarian_armor_typecache))
heal_ticks++
if(heal_ticks)
for(var/i in 1 to heal_ticks)
if(H.health < H.maxHealth)
H.heal_ordered_damage(heal_amount, damage_heal_order)
new /obj/effect/temp_visual/heal(T, "#1E8CE1")
if(i == heal_ticks && H.health >= H.maxHealth)
to_chat(H, "<span class='inathneq'>\"[text2ratvar(pick(heal_finish_messages))]\"</span>")
break
else
to_chat(H, "<span class='inathneq'>\"[text2ratvar(pick(heal_finish_messages))]\"</span>")
break
else if(is_type_in_typecache(M, heal_target_typecache))
var/obj/structure/destructible/clockwork/C = M
if(C.obj_integrity == C.max_integrity || (istype(C) && !C.can_be_repaired))
continue
T = get_turf(M)
for(var/i in 1 to heal_attempts)
if(C.obj_integrity < C.max_integrity)
C.obj_integrity = min(C.obj_integrity + 5, C.max_integrity)
C.update_icon()
new /obj/effect/temp_visual/heal(T, "#1E8CE1")
else
break
new /obj/effect/temp_visual/ratvar/mending_mantra(get_turf(invoker))
return TRUE
//Replica Fabricator: Creates a replica fabricator, used to convert objects and repair clockwork structures.
/datum/clockwork_scripture/create_object/replica_fabricator
descname = "Replaces Objects with Ratvarian Versions"
name = "Replica Fabricator"
desc = "Forms a device that, when used on certain objects, replaces them with their Ratvarian equivalents. It requires power to function."
invocations = list("With this device...", "...his presence shall be made known.")
channel_time = 20
power_cost = 250
//Judicial Visor: Creates a judicial visor, which can smite an area.
/datum/clockwork_scripture/create_object/judicial_visor
descname = "Delayed Area Knockdown Glasses"
name = "Judicial Visor"
desc = "Creates a visor that can smite an area, applying Belligerent and briefly stunning. The smote area will explode after 3 seconds."
invocations = list("Grant me the flames of Engine!")
channel_time = 10
power_cost = 400
whispered = TRUE
object_path = /obj/item/clockwork/replica_fabricator
creator_message = "<span class='brass'>You form a replica fabricator.</span>"
usage_tip = "Clockwork Walls cause nearby Tinkerer's Caches to generate components passively, making this a vital tool. Clockwork Floors heal toxin damage in Servants standing on them."
object_path = /obj/item/clothing/glasses/judicial_visor
creator_message = "<span class='brass'>You form a judicial visor, which is capable of smiting a small area.</span>"
usage_tip = "The visor has a thirty-second cooldown once used."
tier = SCRIPTURE_SCRIPT
space_allowed = TRUE
primary_component = REPLICANT_ALLOY
sort_priority = 5
primary_component = BELLIGERENT_EYE
sort_priority = 4
quickbind = TRUE
quickbind_desc = "Creates a Replica Fabricator, which can convert various objects to Ratvarian variants."
quickbind_desc = "Creates a Judicial Visor, which can smite an area, applying Belligerent and briefly stunning."
//Clockwork Arnaments: Grants the invoker the ability to call forth a Ratvarian spear and clockwork armor.
/datum/clockwork_scripture/clockwork_arnaments
descname = "Summonable Armor and Weapons"
descname = "Summonable Armor and Weapons - Important!"
name = "Clockwork Arnaments"
desc = "Allows the invoker to summon clockwork armor and a Ratvarian spear at will. The spear's attacks will generate Vitality, used for healing."
invocations = list("Grant me arnaments...", "...from the forge of Armorer!")
@@ -213,8 +102,8 @@
whispered = TRUE
usage_tip = "Throwing the spear at a mob will do massive damage and knock them down, but break the spear. You will need to wait for 30 seconds before resummoning it."
tier = SCRIPTURE_SCRIPT
primary_component = REPLICANT_ALLOY
sort_priority = 6
primary_component = VANGUARD_COGWHEEL
sort_priority = 5
quickbind = TRUE
quickbind_desc = "Permanently binds clockwork armor and a Ratvarian spear to you."
@@ -312,8 +201,8 @@
multiple_invokers_optional = TRUE
usage_tip = "This gateway is strictly one-way and will only allow things through the invoker's portal."
tier = SCRIPTURE_SCRIPT
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 9
primary_component = GEIS_CAPACITOR
sort_priority = 6
quickbind = TRUE
quickbind_desc = "Allows you to create a one-way Spatial Gateway to a living Servant or Clockwork Obelisk."
@@ -0,0 +1,86 @@
//No, not that kind.
/obj/structure/destructible/clockwork/trap
name = "base clockwork trap"
desc = "You shouldn't see this. File a bug report!"
clockwork_desc = "A trap that shouldn't exist, and you should report this as a bug."
var/list/wired_to
/obj/structure/destructible/clockwork/trap/Initialize()
. = ..()
wired_to = list()
/obj/structure/destructible/clockwork/trap/Destroy()
for(var/V in wired_to)
var/obj/structure/destructible/clockwork/trap/T = V
T.wired_to -= src
return ..()
/obj/structure/destructible/clockwork/trap/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
to_chat(user, "It's wired to:")
if(!wired_to.len)
to_chat(user, "Nothing.")
else
for(var/V in wired_to)
var/obj/O = V
var/distance = get_dist(src, O)
to_chat(user, "[O] ([distance == 0 ? "same tile" : "[distance] tiles [dir2text(get_dir(src, O))]"])")
/obj/structure/destructible/clockwork/trap/wrench_act(mob/living/user, obj/item/wrench)
if(!is_servant_of_ratvar(user))
return ..()
to_chat(user, "<span class='notice'>You break down the delicate components of [src] into brass.</span>")
playsound(src, wrench.usesound, 50, TRUE)
new/obj/item/stack/tile/brass(get_turf(src))
qdel(src)
return TRUE
/obj/structure/destructible/clockwork/trap/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/clockwork/slab) && is_servant_of_ratvar(user))
var/obj/item/clockwork/slab/F = I
if(!F.linking)
to_chat(user, "<span class='notice'>Beginning link. Alt-click the slab to cancel, or use it on another trap object to link the two.</span>")
F.linking = src
else
if(F.linking in wired_to)
to_chat(user, "<span class='warning'>These two objects are already connected!</span>")
return
if(F.linking.z != z)
to_chat(user, "<span class='warning'>You'd need a <b>much</b> tougher slab to link two objects in different sectors.</span>")
return
to_chat(user, "<span class='notice'>You link [F.linking] with [src].</span>")
wired_to += F.linking
F.linking.wired_to += src
F.linking = null
return
..()
/obj/structure/destructible/clockwork/trap/wirecutter_act(mob/living/user, obj/item/wirecutters)
if(!is_servant_of_ratvar(user))
return
if(!wired_to.len)
to_chat(user, "<span class='warning'>[src] has no connections!</span>")
return
to_chat(user, "<span class='notice'>You sever all connections to [src].</span>")
playsound(src, wirecutters.usesound, 50, TRUE)
for(var/V in wired_to)
var/obj/structure/destructible/clockwork/trap/T = V
T.wired_to -= src
wired_to -= T
return TRUE
/obj/structure/destructible/clockwork/trap/proc/activate()
//These objects send signals to normal traps to activate
/obj/structure/destructible/clockwork/trap/trigger
name = "base trap trigger"
max_integrity = 5
break_message = "<span class='warning'>The trigger breaks apart!</span>"
density = FALSE
/obj/structure/destructible/clockwork/trap/trigger/activate()
for(var/obj/structure/destructible/clockwork/trap/T in wired_to)
if(istype(T, /obj/structure/destructible/clockwork/trap/trigger)) //Triggers don't go off multiple times
continue
T.activate()
@@ -26,6 +26,9 @@
var/fourth_sound_played = FALSE
var/obj/effect/clockwork/overlay/gateway_glow/glow
var/obj/effect/countdown/clockworkgate/countdown
var/last_scream = 0
var/recalls_remaining = 1
var/recalling
/obj/structure/destructible/clockwork/massive/celestial_gateway/Initialize()
. = ..()
@@ -34,7 +37,21 @@
GLOB.ark_of_the_clockwork_justiciar = src
START_PROCESSING(SSprocessing, src)
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/final_countdown(ark_time)
/obj/structure/destructible/clockwork/massive/celestial_gateway/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
. = ..()
if(.)
flick("clockwork_gateway_damaged", glow)
playsound(src, 'sound/machines/clockcult/ark_damage.ogg', 75, FALSE)
if(last_scream < world.time)
audible_message("<span class='boldwarning'>An unearthly screaming sound resonates throughout Reebe!</span>")
for(var/V in GLOB.player_list)
var/mob/M = V
if(M.z == z || is_servant_of_ratvar(M) || isobserver(M))
M.playsound_local(M, 'sound/machines/clockcult/ark_scream.ogg', 100, FALSE, pressure_affected = FALSE)
hierophant_message("<span class='big boldwarning'>The Ark is taking damage!</span>")
last_scream = world.time + ARK_SCREAM_COOLDOWN
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/final_countdown(ark_time) //WE'RE LEAVING TOGETHEEEEEEEEER
if(!ark_time)
ark_time = 30 //minutes
initial_activation_delay = ark_time * 60
@@ -58,13 +75,17 @@
active = TRUE
priority_announce("Massive [Gibberish("bluespace", 100)] anomaly detected on all frequencies. All crew are directed to \
@!$, [text2ratvar("PURGE ALL UNTRUTHS")] <&. the anomalies and destroy their source to prevent further damage to corporate property. This is \
not a drill.[grace_period ? " Estimated time of appearance: [grace_period] seconds. Use this time to prepare." : ""]", \
not a drill.[grace_period ? " Estimated time of appearance: [grace_period] seconds. Use this time to prepare for an attack on [station_name()]." : ""]", \
"Central Command Higher Dimensional Affairs", 'sound/magic/clockwork/ark_activation.ogg')
set_security_level("delta")
for(var/V in SSticker.mode.servants_of_ratvar)
var/datum/mind/M = V
if(ishuman(M.current))
M.current.add_overlay(mutable_appearance('icons/effects/genetics.dmi', "servitude", -MUTATIONS_LAYER))
for(var/V in GLOB.brass_recipes)
var/datum/stack_recipe/R = V
if(R.title == "wall gear")
R.time *= 2 //Building walls becomes slower when the Ark activates
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/open_portal(turf/T)
new/obj/effect/clockwork/city_of_cogs_rift(T)
@@ -83,6 +104,25 @@
seconds_until_activation = 0
SSshuttle.registerHostileEnvironment(src)
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/initiate_mass_recall()
recalling = TRUE
sound_to_playing_players('sound/machines/clockcult/ark_recall.ogg', 75, FALSE)
hierophant_message("<span class='bold large_brass'>The Eminence has initiated a mass recall! You are being transported to the Ark!</span>")
addtimer(CALLBACK(src, .proc/mass_recall), 100)
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/mass_recall()
for(var/V in SSticker.mode.servants_of_ratvar)
var/datum/mind/M = V
if(!M.current.stat)
M.current.forceMove(get_turf(src))
M.current.overlay_fullscreen("flash", /obj/screen/fullscreen/flash)
M.current.clear_fullscreen("flash", 5)
playsound(src, 'sound/magic/clockwork/invoke_general.ogg', 50, FALSE)
recalls_remaining--
recalling = FALSE
transform = matrix() * 2
animate(src, transform = matrix() * 0.5, time = 30, flags = ANIMATION_END_NOW)
/obj/structure/destructible/clockwork/massive/celestial_gateway/Destroy()
STOP_PROCESSING(SSprocessing, src)
SSshuttle.clearHostileEnvironment(src)
@@ -117,6 +157,9 @@
countdown.stop()
visible_message("<span class='userdanger'>[src] begins to pulse uncontrollably... you might want to run!</span>")
sound_to_playing_players(volume = 50, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_disrupted.ogg'))
for(var/mob/M in GLOB.player_list)
if(M.z == z || is_servant_of_ratvar(M))
M.playsound_local(M, 'sound/machines/clockcult/ark_deathrattle.ogg', 100, FALSE, pressure_affected = FALSE)
make_glow()
glow.icon_state = "clockwork_gateway_disrupted"
resistance_flags |= INDESTRUCTIBLE
@@ -0,0 +1,126 @@
//Used to nominate oneself or ghosts for the role of Eminence.
/obj/structure/destructible/clockwork/eminence_spire
name = "eminence spire"
desc = "A hulking machine made of powerful alloy, with three small obelisks and a huge plate in the center."
clockwork_desc = "This spire is used to become the Eminence, who functions as an invisible leader of the cult. Activate it to nominate yourself or propose that the Eminence should be \
selected from available ghosts. Once an Eminence is selected, they can't normally be changed."
icon_state = "tinkerers_daemon"
break_message = "<span class='warning'>The spire screeches with crackling power and collapses into scrap!</span>"
max_integrity = 400
var/mob/eminence_nominee
var/selection_timer //Timer ID; this is canceled if the vote is canceled
var/kingmaking
/obj/structure/destructible/clockwork/eminence_spire/attack_hand(mob/living/user)
if(!is_servant_of_ratvar(user))
to_chat(user, "<span class='notice'>You can tell how powerful [src] is; you know better than to touch it.</span>")
return
if(kingmaking)
return
if(SSticker.mode.eminence)
to_chat(user, "<span class='warning'>There's already an Eminence!</span>")
return
if(!GLOB.servants_active)
to_chat(user, "<span class='warning'>The Ark isn't active!</span>")
return
if(eminence_nominee) //This could be one large proc, but is split into three for ease of reading
if(eminence_nominee == user)
cancelation(user)
else
objection(user)
else
nomination(user)
/obj/structure/destructible/clockwork/eminence_spire/attack_ghost(mob/user)
if(!IsAdminGhost(user))
return
if(SSticker.mode.eminence)
to_chat(user, "<span class='warning'>There's already an Eminence - too late!</span>")
return
if(!GLOB.servants_active)
to_chat(user, "<span class='warning'>The Ark must be active first!</span>")
return
if(alert(user, "Become the Eminence using admin?", "Become Eminence", "Yes", "No") != "Yes")
return
message_admins("<span class='danger'>Admin [key_name_admin(user)] directly became the Eminence of the cult!</span>")
log_admin("Admin [key_name(user)] made themselves the Eminence.")
var/mob/camera/eminence/eminence = new(get_turf(src))
eminence.key = user.key
hierophant_message("<span class='bold large_brass'>Ratvar has directly assigned the Eminence!</span>")
for(var/mob/M in servants_and_ghosts())
M.playsound_local(M, 'sound/machines/clockcult/eminence_selected.ogg', 50, FALSE)
/obj/structure/destructible/clockwork/eminence_spire/proc/nomination(mob/living/nominee) //A user is nominating themselves or ghosts to become Eminence
var/nomination_choice = alert(nominee, "Who would you like to nominate?", "Eminence Nomination", "Nominate Yourself", "Nominate Ghosts", "Cancel")
if(!is_servant_of_ratvar(nominee) || !nominee.canUseTopic(src) || eminence_nominee)
return
switch(nomination_choice)
if("Cancel")
return
if("Nominate Yourself")
eminence_nominee = nominee
hierophant_message("<span class='brass'><b>[nominee] nominates themselves as the Eminence!</b> You may object by interacting with the eminence spire. The vote will otherwise pass in 30 seconds.</span>")
if("Nominate Ghosts")
eminence_nominee = "ghosts"
hierophant_message("<span class='brass'><b>[nominee] proposes selecting an Eminence from ghosts!</b> You may object by interacting with the eminence spire. The vote will otherwise pass in 30 seconds.</span>")
for(var/mob/M in servants_and_ghosts())
M.playsound_local(M, 'sound/machines/clockcult/ocularwarden-target.ogg', 50, FALSE)
selection_timer = addtimer(CALLBACK(src, .proc/kingmaker), 300, TIMER_STOPPABLE)
/obj/structure/destructible/clockwork/eminence_spire/proc/objection(mob/living/wright)
if(alert(wright, "Object to the selection of [eminence_nominee] as Eminence?", "Objection!", "Object", "Cancel") == "Cancel" || !is_servant_of_ratvar(wright) || !wright.canUseTopic(src) || !eminence_nominee)
return
hierophant_message("<span class='brass'><b>[wright] objects to the nomination of [eminence_nominee]!</b> The eminence spire has been reset.</span>")
for(var/mob/M in servants_and_ghosts())
M.playsound_local(M, 'sound/machines/clockcult/integration_cog_install.ogg', 50, FALSE)
eminence_nominee = null
deltimer(selection_timer)
/obj/structure/destructible/clockwork/eminence_spire/proc/cancelation(mob/living/cold_feet)
if(alert(cold_feet, "Cancel your nomination?", "Cancel Nomination", "Withdraw Nomination", "Cancel") == "Cancel" || !is_servant_of_ratvar(cold_feet) || !cold_feet.canUseTopic(src) || !eminence_nominee)
return
hierophant_message("<span class='brass'><b>[eminence_nominee] has withdrawn their nomination!</b> The eminence spire has been reset.</span>")
for(var/mob/M in servants_and_ghosts())
M.playsound_local(M, 'sound/machines/clockcult/integration_cog_install.ogg', 50, FALSE)
eminence_nominee = null
deltimer(selection_timer)
/obj/structure/destructible/clockwork/eminence_spire/proc/kingmaker()
if(!eminence_nominee)
return
if(ismob(eminence_nominee))
if(!eminence_nominee.client || !eminence_nominee.mind)
hierophant_message("<span class='brass'><b>[eminence_nominee] somehow lost their sentience!</b> The eminence spire has been reset.</span>")
for(var/mob/M in servants_and_ghosts())
M.playsound_local(M, 'sound/machines/clockcult/integration_cog_install.ogg', 50, FALSE)
eminence_nominee = null
return
playsound(eminence_nominee, 'sound/machines/clockcult/ark_damage.ogg', 50, FALSE)
eminence_nominee.visible_message("<span class='warning'>A blast of white-hot light flows into [eminence_nominee], vaporizing them in an instant!</span>", \
"<span class='userdanger'>allthelightintheuniverseflowing.into.YOU</span>")
for(var/obj/item/I in eminence_nominee)
eminence_nominee.dropItemToGround(I)
var/mob/camera/eminence/eminence = new(get_turf(src))
eminence_nominee.mind.transfer_to(eminence)
eminence_nominee.dust()
hierophant_message("<span class='bold large_brass'>[eminence_nominee] has ascended into the Eminence!</span>")
else if(eminence_nominee == "ghosts")
kingmaking = TRUE
hierophant_message("<span class='brass'><b>The eminence spire is now selecting a ghost to be the Eminence...</b></span>")
var/list/candidates = pollGhostCandidates("Would you like to play as the servants' Eminence?", "Servant of Ratvar", null, ROLE_SERVANT_OF_RATVAR, poll_time = 100)
kingmaking = FALSE
if(!candidates.len)
for(var/mob/M in servants_and_ghosts())
M.playsound_local(M, 'sound/machines/clockcult/integration_cog_install.ogg', 50, FALSE)
hierophant_message("<span class='brass'><b>No ghosts accepted the offer!</b> The eminence spire has been reset.</span>")
eminence_nominee = null
return
visible_message("<span class='warning'>A blast of white-hot light spirals from [src] in waves!</span>")
playsound(src, 'sound/machines/clockcult/ark_damage.ogg', 50, FALSE)
var/mob/camera/eminence/eminence = new(get_turf(src))
eminence_nominee = pick(candidates)
eminence.key = eminence_nominee.key
hierophant_message("<span class='bold large_brass'>A ghost has ascended into the Eminence!</span>")
for(var/mob/M in servants_and_ghosts())
M.playsound_local(M, 'sound/machines/clockcult/eminence_selected.ogg', 50, FALSE)
eminence_nominee = null
@@ -106,3 +106,4 @@
H.set_species(/datum/species/golem/clockwork/no_scrap)
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
G.grace_period = FALSE //no grace period if we've declared war
G.recalls_remaining++
@@ -0,0 +1,14 @@
//Lever: Do I really need to explain this?
/obj/structure/destructible/clockwork/trap/trigger/lever
name = "lever"
desc = "A fancy lever made of wood and capped with brass."
clockwork_desc = "A fancy lever.that activates when pulled."
max_integrity = 75
icon_state = "lever"
/obj/structure/destructible/clockwork/trap/trigger/lever/attack_hand(mob/living/user)
user.visible_message("<span class='notice'>[user] pulls [src]!</span>", "<span class='notice'>You pull [src]. It clicks, then lifts back upwards.</span>")
if(wired_to.len)
audible_message("<i>You hear gears clanking.</i>")
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
activate()
@@ -0,0 +1,26 @@
//Pressure sensor: Activates when stepped on.
/obj/structure/destructible/clockwork/trap/trigger/pressure_sensor
name = "pressure sensor"
desc = "A thin plate of brass, barely visible but clearly distinct."
clockwork_desc = "A trigger that will activate when a non-servant runs across it."
max_integrity = 25
icon_state = "pressure_sensor"
alpha = 80
layer = LOW_ITEM_LAYER
/obj/structure/destructible/clockwork/trap/trigger/Initialize()
. = ..()
for(var/obj/structure/destructible/clockwork/trap/T in get_turf(src))
if(!istype(T, /obj/structure/destructible/clockwork/trap/trigger))
wired_to += T
T.wired_to += src
to_chat(usr, "<span class='alloy'>[src] automatically links with [T] beneath it.</span>")
/obj/structure/destructible/clockwork/trap/trigger/pressure_sensor/Crossed(atom/movable/AM)
if(isliving(AM) && !is_servant_of_ratvar(AM))
var/mob/living/L = AM
if(L.stat || L.m_intent == MOVE_INTENT_WALK || L.lying)
return
audible_message("<i>*click*</i>")
playsound(src, 'sound/items/screwdriver2.ogg', 50, TRUE)
activate()
@@ -0,0 +1,27 @@
//Repeater: Activates every second.
/obj/structure/destructible/clockwork/trap/trigger/repeater
name = "repeater"
desc = "A small black prism with a gem in the center."
clockwork_desc = "A repeater that will send an activation signal every second."
max_integrity = 15 //Fragile!
icon_state = "repeater"
/obj/structure/destructible/clockwork/trap/trigger/repeater/attack_hand(mob/living/user)
if(!is_servant_of_ratvar(user))
return
if(!isprocessing)
START_PROCESSING(SSprocessing, src)
to_chat(user, "<span class='notice'>You activate [src].</span>")
icon_state = "[icon_state]_on"
else
STOP_PROCESSING(SSprocessing, src)
to_chat(user, "<span class='notice'>You halt [src]'s ticking.</span>")
icon_state = initial(icon_state)
/obj/structure/destructible/clockwork/trap/trigger/repeater/process()
activate()
playsound(src, 'sound/items/screwdriver2.ogg', 25, FALSE)
/obj/structure/destructible/clockwork/trap/trigger/repeater/Destroy()
STOP_PROCESSING(SSprocessing, src)
return ..()
@@ -0,0 +1,106 @@
//Non-servants standing over this will get spikes through the feet, immobilizing them until they're freed.
/obj/structure/destructible/clockwork/trap/brass_skewer
name = "brass skewer"
desc = "A deadly brass spike, cleverly concealed in the floor. You think you should be safe if you disarm whatever's meant to set it off."
clockwork_desc = "A barbaric but undeniably effective weapon: a spear through the chest. It immobilizes anyone unlucky enough to step on it and keeps them in place until they get help.."
icon_state = "brass_skewer"
break_message = "<span class='warning'>The skewer snaps in two!</span>"
max_integrity = 40
density = FALSE
can_buckle = TRUE
buckle_prevents_pull = TRUE
buckle_lying = FALSE
var/wiggle_wiggle
var/mutable_appearance/impale_overlay //This is applied to any mob impaled so that they visibly have the skewer coming through their chest
/obj/structure/destructible/clockwork/trap/brass_skewer/Initialize()
. = ..()
START_PROCESSING(SSfastprocess, src)
/obj/structure/destructible/clockwork/trap/brass_skewer/Destroy()
STOP_PROCESSING(SSfastprocess, src)
if(buckled_mobs && buckled_mobs.len)
var/mob/living/L = buckled_mobs[1]
L.Knockdown(100)
L.visible_message("<span class='warning'>[L] is maimed as the skewer shatters while still in their body!</span>")
L.adjustBruteLoss(15)
unbuckle_mob(L)
return ..()
/obj/structure/destructible/clockwork/trap/brass_skewer/process()
if(density)
if(buckled_mobs.len)
var/mob/living/spitroast = buckled_mobs[1]
spitroast.adjustBruteLoss(0.1)
/obj/structure/destructible/clockwork/trap/attackby(obj/item/I, mob/living/user, params)
if(user in buckled_mobs)
to_chat(user, "<span class='warning'>You can't reach!</span>")
return
..()
/obj/structure/destructible/clockwork/trap/brass_skewer/bullet_act(obj/item/projectile/P)
if(buckled_mobs.len)
var/mob/living/L = buckled_mobs[1]
return L.bullet_act(P)
return ..()
/obj/structure/destructible/clockwork/trap/brass_skewer/activate()
if(density)
return
var/mob/living/carbon/squirrel = locate() in get_turf(src)
if(squirrel)
squirrel.visible_message("<span class='boldwarning'>A massive brass spike erupts from the ground, impaling [squirrel]!</span>", \
"<span class='userdanger'>A massive brass spike rams through your chest, hoisting you into the air!</span>")
squirrel.emote("scream")
playsound(squirrel, 'sound/effects/splat.ogg', 50, TRUE)
playsound(squirrel, 'sound/misc/desceration-03.ogg', 50, TRUE)
squirrel.apply_damage(20, BRUTE, "chest")
mouse_opacity = MOUSE_OPACITY_OPAQUE //So players can interact with the tile it's on to pull them off
buckle_mob(squirrel, TRUE)
else
visible_message("<span class='danger'>A massive brass spike erupts from the ground!</span>")
playsound(src, 'sound/machines/clockcult/brass_skewer.ogg', 75, FALSE)
icon_state = "[initial(icon_state)]_extended"
density = TRUE //Skewers are one-use only
desc = "A vicious brass spike protruding from the ground like a stala[pick("gm", "ct")]ite. It makes you sick to look at." //is stalagmite the ground one? or the ceiling one? who can ever remember?
/obj/structure/destructible/clockwork/trap/brass_skewer/user_buckle_mob()
return
/obj/structure/destructible/clockwork/trap/brass_skewer/post_buckle_mob(mob/living/L)
if(L in buckled_mobs)
L.pixel_y = 3
impale_overlay = mutable_appearance('icons/obj/clockwork_objects.dmi', "brass_skewer_pokeybit", ABOVE_MOB_LAYER)
add_overlay(impale_overlay)
else
L.pixel_y = initial(L.pixel_y)
L.cut_overlay(impale_overlay)
/obj/structure/destructible/clockwork/trap/brass_skewer/user_unbuckle_mob(mob/living/skewee, mob/living/user)
if(user == skewee)
if(wiggle_wiggle)
return
user.visible_message("<span class='warning'>[user] starts wriggling off of [src]!</span>", \
"<span class='danger'>You start agonizingly working your way off of [src]...</span>")
wiggle_wiggle = TRUE
if(!do_after(user, 300, target = user))
user.visible_message("<span class='warning'>[user] slides back down [src]!</span>")
user.emote("scream")
user.apply_damage(10, BRUTE, "chest")
playsound(user, 'sound/misc/desceration-03.ogg', 50, TRUE)
wiggle_wiggle = FALSE
return
wiggle_wiggle = FALSE
else
user.visible_message("<span class='danger'>You start tenderly lifting [user] off of [src]...</span>", \
"<span class='danger'>You start tenderly lifting [user] off of [src]...</span>")
if(!do_after(user, 60, target = skewee))
skewee.visible_message("<span class='warning'>[skewee] painfully slides back down [src].</span>")
skewee.emote("moan")
return
skewee.visible_message("<span class='danger'>[skewee] comes free of [src] with a squelching pop!</span>", \
"<span class='boldannounce'>You come free of [src]!</span>")
skewee.Knockdown(30)
playsound(skewee, 'sound/misc/desceration-03.ogg', 50, TRUE)
unbuckle_mob(skewee)
@@ -0,0 +1,23 @@
//This doesn't function like a "trap" in of itself, but obscures vision when active.
/obj/structure/destructible/clockwork/trap/steam_vent
name = "steam vent"
desc = "Some wired slats embedded in the floor. They feel warm to the touch."
icon_state = "steam_vent_0"
clockwork_desc = "When active, these vents will billow out clouds of excess steam from Reebe, obscuring vision."
break_message = "<span class='warning'>The vent snaps and collapses!</span>"
max_integrity = 100
density = FALSE
/obj/structure/destructible/clockwork/trap/steam_vent/activate()
opacity = !opacity
icon_state = "steam_vent_[opacity]"
if(opacity)
playsound(src, 'sound/machines/clockcult/steam_whoosh.ogg', 50, TRUE)
else
playsound(src, 'sound/machines/clockcult/integration_cog_install.ogg', 50, TRUE)
/obj/structure/destructible/clockwork/trap/steam_vent/Crossed(atom/movable/AM)
if(isliving(AM) && opacity)
var/mob/living/L = AM
L.adjust_fire_stacks(-1) //It's wet!
@@ -253,3 +253,17 @@
. = ..()
animate(src, alpha = 255, time = 50)
//Used by the Eminence to coordinate the cult
/obj/effect/temp_visual/ratvar/command_point
name = "command marker"
desc = "An area of importance marked by the Eminence."
icon = 'icons/mob/actions/actions_clockcult.dmi'
icon_state = "eminence"
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
resistance_flags = INDESTRUCTIBLE
layer = MASSIVE_OBJ_LAYER
duration = 300
/obj/effect/temp_visual/ratvar/command_point/Initialize(mapload, appearance)
. = ..()
icon_state = appearance
@@ -333,7 +333,7 @@ GLOBAL_LIST_INIT(runed_metal_recipes, list ( \
* Brass
*/
GLOBAL_LIST_INIT(brass_recipes, list ( \
new/datum/stack_recipe("wall gear", /obj/structure/destructible/clockwork/wall_gear, 3, time = 30, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("wall gear", /obj/structure/destructible/clockwork/wall_gear, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE), \
null,
new/datum/stack_recipe("pinion airlock", /obj/machinery/door/airlock/clockwork, 5, time = 50, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("brass pinion airlock", /obj/machinery/door/airlock/clockwork/brass, 5, time = 50, one_per_turf = TRUE, on_floor = TRUE), \
@@ -342,7 +342,14 @@ GLOBAL_LIST_INIT(brass_recipes, list ( \
new/datum/stack_recipe("directional brass window", /obj/structure/window/reinforced/clockwork/unanchored, time = 0, on_floor = TRUE, window_checks = TRUE), \
new/datum/stack_recipe("fulltile brass window", /obj/structure/window/reinforced/clockwork/fulltile/unanchored, 2, time = 0, on_floor = TRUE, window_checks = TRUE), \
new/datum/stack_recipe("brass chair", /obj/structure/chair/brass, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("brass table frame", /obj/structure/table_frame/brass, 1, time = 5, one_per_turf = TRUE, on_floor = TRUE) \
new/datum/stack_recipe("brass table frame", /obj/structure/table_frame/brass, 1, time = 5, one_per_turf = TRUE, on_floor = TRUE), \
null,
new/datum/stack_recipe("sender - pressure sensor", /obj/structure/destructible/clockwork/trap/trigger/pressure_sensor, 2, time = 20, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("sender - lever", /obj/structure/destructible/clockwork/trap/trigger/lever, 1, time = 10, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("sender - repeater", /obj/structure/destructible/clockwork/trap/trigger/repeater, 2, time = 20, one_per_turf = TRUE, on_floor = TRUE), \
null,
new/datum/stack_recipe("receiver - brass skewer", /obj/structure/destructible/clockwork/trap/brass_skewer, 2, time = 20, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("receiver - steam vent", /obj/structure/destructible/clockwork/trap/steam_vent, 3, time = 30, one_per_turf = TRUE, on_floor = TRUE), \
))
/obj/item/stack/tile/brass
@@ -56,6 +56,7 @@
sheet_amount = 1
girder_type = /obj/structure/destructible/clockwork/wall_gear
baseturf = /turf/open/floor/clockwork/reebe
var/heated
var/obj/effect/clockwork/overlay/wall/realappearence
/turf/closed/wall/clockwork/Initialize()
@@ -110,6 +111,36 @@
for(var/i in 1 to 3)
new/obj/item/clockwork/alloy_shards/small(src)
/turf/closed/wall/clockwork/attack_hulk(mob/living/user, does_attack_animation = 0)
..()
if(heated)
to_chat(user, "<span class='userdanger'>The wall is searing hot to the touch!</span>")
user.adjustFireLoss(5)
playsound(src, 'sound/machines/fryer/deep_fryer_emerge.ogg', 50, TRUE)
/turf/closed/wall/clockwork/mech_melee_attack(obj/mecha/M)
..()
if(heated)
to_chat(M.occupant, "<span class='userdanger'>The wall's intense heat completely reflects your [M.name]'s attack!</span>")
M.take_damage(20, BURN)
/turf/closed/wall/clockwork/proc/turn_up_the_heat()
if(!heated)
name = "superheated [name]"
visible_message("<span class='warning'>[src] sizzles with heat!</span>")
playsound(src, 'sound/machines/fryer/deep_fryer_emerge.ogg', 50, TRUE)
heated = TRUE
hardness = -100 //Lower numbers are tougher, so this makes the wall essentially impervious to smashing
slicing_duration = 150
animate(realappearence, color = "#FFC3C3", time = 5)
else
name = initial(name)
visible_message("<span class='notice'>[src] cools down.</span>")
heated = FALSE
hardness = initial(hardness)
slicing_duration = initial(slicing_duration)
animate(realappearence, color = initial(realappearence.color), time = 25)
/turf/closed/wall/vault
icon = 'icons/turf/walls.dmi'
@@ -962,7 +962,7 @@
playsound(src, 'sound/magic/clockwork/fellowship_armory.ogg', 75, TRUE)
var/mob/living/simple_animal/parrot/clock_hawk/H = new(loc)
H.setDir(dir)
dust()
qdel(src)
/mob/living/simple_animal/parrot/Poly/ghost
name = "The Ghost of Poly"