diff --git a/_maps/map_files/generic/City_of_Cogs.dmm b/_maps/map_files/generic/City_of_Cogs.dmm index 68f45f5472..421d03cf9d 100644 --- a/_maps/map_files/generic/City_of_Cogs.dmm +++ b/_maps/map_files/generic/City_of_Cogs.dmm @@ -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 @@ -31739,7 +31743,7 @@ aj aj ai aj -aj +az aj ai aj @@ -31996,7 +32000,7 @@ aj aj ap aj -az +aj aj ap aj @@ -32253,7 +32257,7 @@ aj aj ai aj -aj +bj aj ai aj diff --git a/code/__DEFINES/clockcult.dm b/code/__DEFINES/clockcult.dm index fe804c44f9..d51dbfd047 100644 --- a/code/__DEFINES/clockcult.dm +++ b/code/__DEFINES/clockcult.dm @@ -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 diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 77425e14dd..da25d34880 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -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 diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 6fb7b08611..9ec23fa966 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -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 diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index da2fae9882..0006d72d3b 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -388,23 +388,15 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." desc = "CHETR
NYY
HAGEHUGF-NAQ-UBABE
RATVAR.
" 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("[servants] Servants, [validservants] of which count towards scripture.
") - else - textlist = list("[servants] Servants, [validservants ? "[validservants] of which counts":"none of which count"] towards scripture.
") - else - textlist = list("[servants] Servant, who [validservants ? "counts":"does not count"] towards scripture.
") - for(var/i in SSticker.scripture_states) - if(i != SCRIPTURE_DRIVER) //ignore the always-unlocked stuff - textlist += "[i] Scripture: [SSticker.scripture_states[i] ? "UNLOCKED":"LOCKED"]
" + textlist = list("[SSticker.mode.eminence ? "There is an Eminence." : "There is no Eminence! Get one ASAP!"]
") + textlist += "There are currently [servants] servant[servants > 1 ? "s" : ""] of Ratvar.
" + for(var/i in SSticker.scripture_states) + if(i != SCRIPTURE_DRIVER) //ignore the always-unlocked stuff + textlist += "[i] Scripture: [SSticker.scripture_states[i] ? "UNLOCKED":"LOCKED"]
" 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) diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm index 63900d0f89..61bd9bb496 100644 --- a/code/game/gamemodes/clock_cult/clock_cult.dm +++ b/code/game/gamemodes/clock_cult/clock_cult.dm @@ -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, "There is a paper in your backpack! Read it!") + to_chat(L, "There is a paper in your backpack! It'll tell you if anything's changed, as well as what to expect.") to_chat(L, "[slot] is a clockwork slab, 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.") to_chat(L, "If you want more information, you can find a wiki link here! 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.

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 += "
[i] scripture was: [SSticker.scripture_states[i] ? "UN":""]LOCKED" + if(SSticker.mode.eminence) + text += "
The Eminence was: [printplayer(SSticker.mode.eminence)]" if(servants_of_ratvar.len) text += "
Ratvar's servants were:" - 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:
\

Things that have changed:

\ \
\ Good luck!" +/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 += "
  • [entry]
  • " + 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, "You can't understand any of the words on [src].") diff --git a/code/game/gamemodes/clock_cult/clock_helpers/scripture_checks.dm b/code/game/gamemodes/clock_cult/clock_helpers/scripture_checks.dm index c6f3f0f7f3..0b94d34ab1 100644 --- a/code/game/gamemodes/clock_cult/clock_helpers/scripture_checks.dm +++ b/code/game/gamemodes/clock_cult/clock_helpers/scripture_checks.dm @@ -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)))) diff --git a/code/game/gamemodes/clock_cult/clock_helpers/slab_abilities.dm b/code/game/gamemodes/clock_cult/clock_helpers/slab_abilities.dm index 4ca8f7f35b..45065cd757 100644 --- a/code/game/gamemodes/clock_cult/clock_helpers/slab_abilities.dm +++ b/code/game/gamemodes/clock_cult/clock_helpers/slab_abilities.dm @@ -65,8 +65,13 @@ /obj/item/restraints/handcuffs/clockwork name = "replicant manacles" +<<<<<<< HEAD desc = "Cold, heavy manacles made out of some strange black metal." origin_tech = "materials=2;magnets=5" +======= + desc = "Heavy manacles made out of freezing-cold metal. It looks like brass, but feels much more solid." + icon_state = "brass_manacles" +>>>>>>> 32c68a6... Clockwork Cult Defenses Patch - Leader role, traps and wiring, hulk and mech soft-counters, +more (#32935) flags_1 = DROPDEL_1 /obj/item/restraints/handcuffs/clockwork/dropped(mob/user) diff --git a/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm b/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm index 70aeaa6520..0111567122 100644 --- a/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm +++ b/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm @@ -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.
    \ + 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 transfer 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, "Object link canceled.") + /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"] = "Unlock these optional scriptures by converting another servant or if [DisplayPower(APPLICATION_UNLOCK_THRESHOLD)] of power is reached.." data["selected"] = selected_scripture - + data["scripturecolors"] = "Scriptures in yellow are related to construction and building.
    \ + Scriptures in red are related to attacking and offense.
    \ + Scriptures in blue are related to healing and defense.
    \ + Scriptures in purple are niche but still important!" generate_all_scripture() data["scripture"] = list() diff --git a/code/game/gamemodes/clock_cult/clock_items/judicial_visor.dm b/code/game/gamemodes/clock_cult/clock_items/judicial_visor.dm index 4f6485310b..d6b2ddce0d 100644 --- a/code/game/gamemodes/clock_cult/clock_items/judicial_visor.dm +++ b/code/game/gamemodes/clock_cult/clock_items/judicial_visor.dm @@ -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)) diff --git a/code/game/gamemodes/clock_cult/clock_mobs/_eminence.dm b/code/game/gamemodes/clock_cult/clock_mobs/_eminence.dm new file mode 100644 index 0000000000..cc91feeb98 --- /dev/null +++ b/code/game/gamemodes/clock_cult/clock_mobs/_eminence.dm @@ -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, "You have been selected as the Eminence!") + to_chat(src, "As the Eminence, you lead the servants. Anything you say will be heard by the entire cult.") + to_chat(src, "Though you can move through walls, you're also incorporeal, and largely can't interact with the world except for a few ways.") + to_chat(src, "Additionally, unless the herald's beacon is activated, you can't understand any speech while away from Reebe.") + 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("You feel light slam into your mind and form words: \"[capitalize(message)]\"") + playsound(src, 'sound/machines/clockcult/ark_scream.ogg', 50, FALSE) + hierophant_message("The Eminence: \"[message]\"") + +/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, "[speaker] says something, but you can't understand any of it...") + +/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, "The Ark can no longer recall!") + 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("[T] clunks as it's activated remotely.") + to_chat(src, "You activate [T].") + 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, "[replacetext(command_text, "GETDIR", dir2text(get_dir(M, command_location)))]") + M.playsound_local(M, 'sound/machines/clockcult/eminence_command.ogg', 75, FALSE, pressure_affected = FALSE) + else + hierophant_message("[command_text]") + 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, "You're exerting all of your power superheating this many walls already! Cool some down first!") + return + wall.turn_up_the_heat() + if(wall.heated) + superheated_walls++ + to_chat(src, "You superheat [wall]. Superheated walls: [superheated_walls]/[SUPERHEATED_CLOCKWORK_WALL_LIMIT]") + else + superheated_walls-- + to_chat(src, "You cool [wall]. Superheated walls: [superheated_walls]/[SUPERHEATED_CLOCKWORK_WALL_LIMIT]") + +/mob/camera/eminence/proc/eminence_help() + to_chat(src, "You can make use of certain shortcuts to perform different actions:") + to_chat(src, "Alt-Click a clockwork wall 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.") + to_chat(src, "Interact with the Ark 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,") + to_chat(src, "Middle or Ctrl-Click anywhere to allow you to issue a variety of contextual commands to your cult. Different objects allow for different \ + commands. Doing this on yourself will provide commands that tell the entire cult a goal.") + + +//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, "There is no Ark!") + +//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!" + 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, "You're already on the station!") + +//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() diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm index bcb9d1d1df..5aa626bac5 100644 --- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm +++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm @@ -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 = "A sigil silently appears below you. It will automatically power clockwork structures near it and will drain power when activated." + 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 = "You form a mania motor, which causes minor damage and negative mental effects in non-Servants." + observer_message = "A two-pronged machine rises from the ground!" + 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 = "You form a clockwork obelisk which can broadcast messages or produce Spatial Gateways." + observer_message = "A brass obelisk appears hanging in midair!" + 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 = "You form a mania motor, which causes minor damage and negative mental effects in non-Servants." - observer_message = "A two-pronged machine rises from the ground!" - 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 = "A sigil silently appears below you. It will automatically power clockwork structures near it and will drain power when activated." - 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 = "You form a clockwork obelisk which can broadcast messages or produce Spatial Gateways." - observer_message = "A brass obelisk appears hanging in midair!" - 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." diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_drivers.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_drivers.dm index 93d203aba0..8275e4d20e 100644 --- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_drivers.dm +++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_drivers.dm @@ -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 = "You form a stargazer, which will generate power near starlight." + observer_message = "A large lantern-shaped machine forms!" + 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 = "You charge the clockwork slab with divine energy.\n\ - Left-click a target within melee range to shackle!\n\ - Click your slab to cancel." - 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, "Stargazers can't be built off-station.") + 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 = "You form an integration cog, which can be inserted into an open APC to passively siphon power." + 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 = "A luminous sigil appears below you. Any non-Servants to cross it will be converted after 8 seconds if they do not move." + 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 = "You charge the clockwork slab with divine energy.\n\ + Left-click a target within melee range to stun!\n\ + Click your slab to cancel." + 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 = "You charge the clockwork slab with divine energy.\n\ + Left-click a target within melee range to shackle!\n\ + Click your slab to cancel." + 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.
    Click your slab to disable." 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 = "You charge the clockwork slab with divine energy.\n\ - Left-click a target within melee range to stun!\n\ - Click your slab to cancel." - 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 = "A luminous sigil appears below you. Any non-Servants to cross it will be converted after 8 seconds if they do not move." - 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 = "You form a stargazer, which will generate power near starlight." - observer_message = "A large lantern-shaped machine forms!" - 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, "Stargazers can't be built off-station.") - 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 = "You form an integration cog, which can be inserted into an open APC to passively siphon power." - 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." diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm index a172f4ca41..09cfeb99d3 100644 --- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm +++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm @@ -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 = "You form a replica fabricator." + 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 = "You form a judicial visor, which is capable of smiting a small area." - 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.
    Maximum 10 chants." - 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, "\"[text2ratvar(pick(heal_finish_messages))]\"") - break - else - to_chat(S, "\"[text2ratvar(pick(heal_finish_messages))]\"") - 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, "\"[text2ratvar(pick(heal_finish_messages))]\"") - break - else - to_chat(S, "\"[text2ratvar(pick(heal_finish_messages))]\"") - 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, "\"[text2ratvar(pick(heal_finish_messages))]\"") - break - else - to_chat(H, "\"[text2ratvar(pick(heal_finish_messages))]\"") - 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 = "You form a replica fabricator." - 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 = "You form a judicial visor, which is capable of smiting a small area." + 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." diff --git a/code/game/gamemodes/clock_cult/clock_structures/_trap_object.dm b/code/game/gamemodes/clock_cult/clock_structures/_trap_object.dm new file mode 100644 index 0000000000..63c0182f7f --- /dev/null +++ b/code/game/gamemodes/clock_cult/clock_structures/_trap_object.dm @@ -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, "You break down the delicate components of [src] into brass.") + 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, "Beginning link. Alt-click the slab to cancel, or use it on another trap object to link the two.") + F.linking = src + else + if(F.linking in wired_to) + to_chat(user, "These two objects are already connected!") + return + if(F.linking.z != z) + to_chat(user, "You'd need a much tougher slab to link two objects in different sectors.") + return + to_chat(user, "You link [F.linking] with [src].") + 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, "[src] has no connections!") + return + to_chat(user, "You sever all connections to [src].") + 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 = "The trigger breaks apart!" + 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() diff --git a/code/game/gamemodes/clock_cult/clock_structures/ark_of_the_clockwork_justicar.dm b/code/game/gamemodes/clock_cult/clock_structures/ark_of_the_clockwork_justicar.dm index 0f13ac66ac..63fea1eeb6 100644 --- a/code/game/gamemodes/clock_cult/clock_structures/ark_of_the_clockwork_justicar.dm +++ b/code/game/gamemodes/clock_cult/clock_structures/ark_of_the_clockwork_justicar.dm @@ -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("An unearthly screaming sound resonates throughout Reebe!") + 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("The Ark is taking damage!") + 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("The Eminence has initiated a mass recall! You are being transported to the Ark!") + 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("[src] begins to pulse uncontrollably... you might want to run!") 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 diff --git a/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm b/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm new file mode 100644 index 0000000000..8d4e936658 --- /dev/null +++ b/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm @@ -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 = "The spire screeches with crackling power and collapses into scrap!" + 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, "You can tell how powerful [src] is; you know better than to touch it.") + return + if(kingmaking) + return + if(SSticker.mode.eminence) + to_chat(user, "There's already an Eminence!") + return + if(!GLOB.servants_active) + to_chat(user, "The Ark isn't active!") + 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, "There's already an Eminence - too late!") + return + if(!GLOB.servants_active) + to_chat(user, "The Ark must be active first!") + return + if(alert(user, "Become the Eminence using admin?", "Become Eminence", "Yes", "No") != "Yes") + return + message_admins("Admin [key_name_admin(user)] directly became the Eminence of the cult!") + 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("Ratvar has directly assigned the Eminence!") + 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("[nominee] nominates themselves as the Eminence! You may object by interacting with the eminence spire. The vote will otherwise pass in 30 seconds.") + if("Nominate Ghosts") + eminence_nominee = "ghosts" + hierophant_message("[nominee] proposes selecting an Eminence from ghosts! You may object by interacting with the eminence spire. The vote will otherwise pass in 30 seconds.") + 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("[wright] objects to the nomination of [eminence_nominee]! The eminence spire has been reset.") + 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("[eminence_nominee] has withdrawn their nomination! The eminence spire has been reset.") + 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("[eminence_nominee] somehow lost their sentience! The eminence spire has been reset.") + 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("A blast of white-hot light flows into [eminence_nominee], vaporizing them in an instant!", \ + "allthelightintheuniverseflowing.into.YOU") + 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("[eminence_nominee] has ascended into the Eminence!") + else if(eminence_nominee == "ghosts") + kingmaking = TRUE + hierophant_message("The eminence spire is now selecting a ghost to be the Eminence...") + 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("No ghosts accepted the offer! The eminence spire has been reset.") + eminence_nominee = null + return + visible_message("A blast of white-hot light spirals from [src] in waves!") + 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("A ghost has ascended into the Eminence!") + for(var/mob/M in servants_and_ghosts()) + M.playsound_local(M, 'sound/machines/clockcult/eminence_selected.ogg', 50, FALSE) + eminence_nominee = null diff --git a/code/game/gamemodes/clock_cult/clock_structures/heralds_beacon.dm b/code/game/gamemodes/clock_cult/clock_structures/heralds_beacon.dm index 9f18ff1669..2be948d7ca 100644 --- a/code/game/gamemodes/clock_cult/clock_structures/heralds_beacon.dm +++ b/code/game/gamemodes/clock_cult/clock_structures/heralds_beacon.dm @@ -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++ diff --git a/code/game/gamemodes/clock_cult/clock_structures/trap_triggers/lever.dm b/code/game/gamemodes/clock_cult/clock_structures/trap_triggers/lever.dm new file mode 100644 index 0000000000..4d11cc5f39 --- /dev/null +++ b/code/game/gamemodes/clock_cult/clock_structures/trap_triggers/lever.dm @@ -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("[user] pulls [src]!", "You pull [src]. It clicks, then lifts back upwards.") + if(wired_to.len) + audible_message("You hear gears clanking.") + playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE) + activate() diff --git a/code/game/gamemodes/clock_cult/clock_structures/trap_triggers/pressure_sensor.dm b/code/game/gamemodes/clock_cult/clock_structures/trap_triggers/pressure_sensor.dm new file mode 100644 index 0000000000..f6a7b8e347 --- /dev/null +++ b/code/game/gamemodes/clock_cult/clock_structures/trap_triggers/pressure_sensor.dm @@ -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, "[src] automatically links with [T] beneath it.") + +/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("*click*") + playsound(src, 'sound/items/screwdriver2.ogg', 50, TRUE) + activate() diff --git a/code/game/gamemodes/clock_cult/clock_structures/trap_triggers/repeater.dm b/code/game/gamemodes/clock_cult/clock_structures/trap_triggers/repeater.dm new file mode 100644 index 0000000000..68e8cc00e8 --- /dev/null +++ b/code/game/gamemodes/clock_cult/clock_structures/trap_triggers/repeater.dm @@ -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, "You activate [src].") + icon_state = "[icon_state]_on" + else + STOP_PROCESSING(SSprocessing, src) + to_chat(user, "You halt [src]'s ticking.") + 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 ..() diff --git a/code/game/gamemodes/clock_cult/clock_structures/traps/brass_skewer.dm b/code/game/gamemodes/clock_cult/clock_structures/traps/brass_skewer.dm new file mode 100644 index 0000000000..d79ca88ecb --- /dev/null +++ b/code/game/gamemodes/clock_cult/clock_structures/traps/brass_skewer.dm @@ -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 = "The skewer snaps in two!" + 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("[L] is maimed as the skewer shatters while still in their body!") + 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, "You can't reach!") + 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("A massive brass spike erupts from the ground, impaling [squirrel]!", \ + "A massive brass spike rams through your chest, hoisting you into the air!") + 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("A massive brass spike erupts from the ground!") + 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("[user] starts wriggling off of [src]!", \ + "You start agonizingly working your way off of [src]...") + wiggle_wiggle = TRUE + if(!do_after(user, 300, target = user)) + user.visible_message("[user] slides back down [src]!") + 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("You start tenderly lifting [user] off of [src]...", \ + "You start tenderly lifting [user] off of [src]...") + if(!do_after(user, 60, target = skewee)) + skewee.visible_message("[skewee] painfully slides back down [src].") + skewee.emote("moan") + return + skewee.visible_message("[skewee] comes free of [src] with a squelching pop!", \ + "You come free of [src]!") + skewee.Knockdown(30) + playsound(skewee, 'sound/misc/desceration-03.ogg', 50, TRUE) + unbuckle_mob(skewee) diff --git a/code/game/gamemodes/clock_cult/clock_structures/traps/steam_vent.dm b/code/game/gamemodes/clock_cult/clock_structures/traps/steam_vent.dm new file mode 100644 index 0000000000..6aede1592e --- /dev/null +++ b/code/game/gamemodes/clock_cult/clock_structures/traps/steam_vent.dm @@ -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 = "The vent snaps and collapses!" + 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! diff --git a/code/game/objects/effects/temporary_visuals/clockcult.dm b/code/game/objects/effects/temporary_visuals/clockcult.dm index 49e962eba2..d9861d827d 100644 --- a/code/game/objects/effects/temporary_visuals/clockcult.dm +++ b/code/game/objects/effects/temporary_visuals/clockcult.dm @@ -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 diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 88bccfe204..c22cbbc0bc 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -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 diff --git a/code/game/turfs/simulated/wall/misc_walls.dm b/code/game/turfs/simulated/wall/misc_walls.dm index bb45e2df20..4d48c86934 100644 --- a/code/game/turfs/simulated/wall/misc_walls.dm +++ b/code/game/turfs/simulated/wall/misc_walls.dm @@ -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, "The wall is searing hot to the touch!") + 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, "The wall's intense heat completely reflects your [M.name]'s attack!") + M.take_damage(20, BURN) + +/turf/closed/wall/clockwork/proc/turn_up_the_heat() + if(!heated) + name = "superheated [name]" + visible_message("[src] sizzles with heat!") + 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("[src] cools down.") + 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' diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index ffbeb1f503..de5d38e0bb 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -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" diff --git a/icons/effects/96x96.dmi b/icons/effects/96x96.dmi index 102fc01000..644d2a0860 100644 Binary files a/icons/effects/96x96.dmi and b/icons/effects/96x96.dmi differ diff --git a/icons/effects/clockwork_effects.dmi b/icons/effects/clockwork_effects.dmi index fa3bfa36e6..5d6082dc2b 100644 Binary files a/icons/effects/clockwork_effects.dmi and b/icons/effects/clockwork_effects.dmi differ diff --git a/icons/mob/actions/actions_clockcult.dmi b/icons/mob/actions/actions_clockcult.dmi index 19fd68f836..4aad4ba569 100644 Binary files a/icons/mob/actions/actions_clockcult.dmi and b/icons/mob/actions/actions_clockcult.dmi differ diff --git a/icons/obj/clockwork_objects.dmi b/icons/obj/clockwork_objects.dmi index 561359959b..784c0f55eb 100644 Binary files a/icons/obj/clockwork_objects.dmi and b/icons/obj/clockwork_objects.dmi differ diff --git a/sound/machines/clockcult/ark_damage.ogg b/sound/machines/clockcult/ark_damage.ogg new file mode 100644 index 0000000000..40ccfc6219 Binary files /dev/null and b/sound/machines/clockcult/ark_damage.ogg differ diff --git a/sound/machines/clockcult/ark_deathrattle.ogg b/sound/machines/clockcult/ark_deathrattle.ogg new file mode 100644 index 0000000000..916ff0429e Binary files /dev/null and b/sound/machines/clockcult/ark_deathrattle.ogg differ diff --git a/sound/machines/clockcult/ark_recall.ogg b/sound/machines/clockcult/ark_recall.ogg new file mode 100644 index 0000000000..a38a0b765b Binary files /dev/null and b/sound/machines/clockcult/ark_recall.ogg differ diff --git a/sound/machines/clockcult/ark_scream.ogg b/sound/machines/clockcult/ark_scream.ogg new file mode 100644 index 0000000000..acdc7c85db Binary files /dev/null and b/sound/machines/clockcult/ark_scream.ogg differ diff --git a/sound/machines/clockcult/brass_skewer.ogg b/sound/machines/clockcult/brass_skewer.ogg new file mode 100644 index 0000000000..927bf9b275 Binary files /dev/null and b/sound/machines/clockcult/brass_skewer.ogg differ diff --git a/sound/machines/clockcult/eminence_command.ogg b/sound/machines/clockcult/eminence_command.ogg new file mode 100644 index 0000000000..59a4e3f26d Binary files /dev/null and b/sound/machines/clockcult/eminence_command.ogg differ diff --git a/sound/machines/clockcult/eminence_selected.ogg b/sound/machines/clockcult/eminence_selected.ogg new file mode 100644 index 0000000000..6d1175faf7 Binary files /dev/null and b/sound/machines/clockcult/eminence_selected.ogg differ diff --git a/strings/clockwork_cult_changelog.txt b/strings/clockwork_cult_changelog.txt new file mode 100644 index 0000000000..b5d2ca10e3 --- /dev/null +++ b/strings/clockwork_cult_changelog.txt @@ -0,0 +1,7 @@ +Added the Eminence, a leader role that servants can become by interacting with the new eminence spire structure in Reebe. +Scripture has been re-colored in the slab interface to show its niche at a glance. +Added traps, including the brass skewer and steam vent. +Added trap triggers, including the pressure sensor, lever, and repeater. +Traps and trap triggers can be linked by using your clockwork slab on them. Traps chained to each other will cause those traps to activate as well. +You can instantly remove traps you misplace by using a wrench on them. +Mending Mantra has been removed. \ No newline at end of file diff --git a/tgstation.dme b/tgstation.dme index e8b81cbbb8..d78d24b53e 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -556,13 +556,16 @@ #include "code\game\gamemodes\clock_cult\clock_items\wraith_spectacles.dm" #include "code\game\gamemodes\clock_cult\clock_items\clock_weapons\_call_weapon.dm" #include "code\game\gamemodes\clock_cult\clock_items\clock_weapons\ratvarian_spear.dm" +#include "code\game\gamemodes\clock_cult\clock_mobs\_eminence.dm" #include "code\game\gamemodes\clock_cult\clock_mobs\clockwork_marauder.dm" #include "code\game\gamemodes\clock_cult\clock_scriptures\scripture_applications.dm" #include "code\game\gamemodes\clock_cult\clock_scriptures\scripture_cyborg.dm" #include "code\game\gamemodes\clock_cult\clock_scriptures\scripture_drivers.dm" #include "code\game\gamemodes\clock_cult\clock_scriptures\scripture_scripts.dm" +#include "code\game\gamemodes\clock_cult\clock_structures\_trap_object.dm" #include "code\game\gamemodes\clock_cult\clock_structures\ark_of_the_clockwork_justicar.dm" #include "code\game\gamemodes\clock_cult\clock_structures\clockwork_obelisk.dm" +#include "code\game\gamemodes\clock_cult\clock_structures\eminence_spire.dm" #include "code\game\gamemodes\clock_cult\clock_structures\heralds_beacon.dm" #include "code\game\gamemodes\clock_cult\clock_structures\mania_motor.dm" #include "code\game\gamemodes\clock_cult\clock_structures\ocular_warden.dm" @@ -570,6 +573,11 @@ #include "code\game\gamemodes\clock_cult\clock_structures\stargazer.dm" #include "code\game\gamemodes\clock_cult\clock_structures\taunting_trail.dm" #include "code\game\gamemodes\clock_cult\clock_structures\wall_gear.dm" +#include "code\game\gamemodes\clock_cult\clock_structures\trap_triggers\lever.dm" +#include "code\game\gamemodes\clock_cult\clock_structures\trap_triggers\pressure_sensor.dm" +#include "code\game\gamemodes\clock_cult\clock_structures\trap_triggers\repeater.dm" +#include "code\game\gamemodes\clock_cult\clock_structures\traps\brass_skewer.dm" +#include "code\game\gamemodes\clock_cult\clock_structures\traps\steam_vent.dm" #include "code\game\gamemodes\cult\cult.dm" #include "code\game\gamemodes\cult\cult_comms.dm" #include "code\game\gamemodes\cult\cult_items.dm" diff --git a/tgui/src/interfaces/clockwork_slab.ract b/tgui/src/interfaces/clockwork_slab.ract index af429cc904..48f6ae02f6 100644 --- a/tgui/src/interfaces/clockwork_slab.ract +++ b/tgui/src/interfaces/clockwork_slab.ract @@ -22,6 +22,9 @@ Scripts Applications
    {{{data.tier_info}}} + + + {{{data.scripturecolors}}}
    {{#each data.scripture}}