diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm
index 4f36ddbb1e..2e1524ebac 100644
--- a/code/__DEFINES/status_effects.dm
+++ b/code/__DEFINES/status_effects.dm
@@ -64,6 +64,8 @@
#define STATUS_EFFECT_KINDLE /datum/status_effect/kindle //A knockdown reduced by 1 second for every 3 points of damage the target takes.
+#define STATUS_EFFECT_ICHORIAL_STAIN /datum/status_effect/ichorial_stain //Prevents a servant from being revived by vitality matrices for one minute.
+
/////////////
// NEUTRAL //
/////////////
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index cc64cc2eb8..22868f855f 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -479,3 +479,27 @@
desc = "Blinding light dances in your vision, stunning and silencing you. Any damage taken will shorten the light's effects!"
icon_state = "kindle"
alerttooltipstyle = "clockcult"
+
+
+//Ichorial Stain: Applied to servants revived by a vitality matrix. Prevents them from being revived by one again until the effect fades.
+/datum/status_effect/ichorial_stain
+ id = "ichorial_stain"
+ status_type = STATUS_EFFECT_UNIQUE
+ duration = 600
+ examine_text = "SUBJECTPRONOUN is drenched in thick, blue ichor!"
+ alert_type = /obj/screen/alert/status_effect/ichorial_stain
+
+/datum/status_effect/ichorial_stain/on_apply()
+ owner.visible_message("[owner] gets back up, [owner.p_their()] body dripping blue ichor!", \
+ "Thick blue ichor covers your body; you can't be revived like this again until it dries!")
+ return TRUE
+
+/datum/status_effect/ichorial_stain/on_remove()
+ owner.visible_message("The blue ichor on [owner]'s body dries out!", \
+ "The ichor on your body is dry - you can now be revived by vitality matrices again!")
+
+/obj/screen/alert/status_effect/ichorial_stain
+ name = "Ichorial Stain"
+ desc = "Your body is covered in blue ichor! You can't be revived by vitality matrices."
+ icon_state = "ichorial_stain"
+ alerttooltipstyle = "clockcult"
diff --git a/code/datums/status_effects/status_effect.dm b/code/datums/status_effects/status_effect.dm
index 19bd880a77..e24359d18c 100644
--- a/code/datums/status_effects/status_effect.dm
+++ b/code/datums/status_effects/status_effect.dm
@@ -9,6 +9,7 @@
var/mob/living/owner //The mob affected by the status effect.
var/status_type = STATUS_EFFECT_UNIQUE //How many of the effect can be on one mob, and what happens when you try to add another
var/on_remove_on_mob_delete = FALSE //if we call on_remove() when the mob is deleted
+ var/examine_text //If defined, this text will appear when the mob is examined - to use he, she etc. use "SUBJECTPRONOUN" and replace it in the examines themselves
var/alert_type = /obj/screen/alert/status_effect //the alert thrown by the status effect, contains name and description
var/obj/screen/alert/status_effect/linked_alert = null //the alert itself, if it exists
diff --git a/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm b/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm
index 29655a0ac9..3237cf5d35 100644
--- a/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm
+++ b/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm
@@ -278,7 +278,7 @@
animate(src, alpha = 255, time = 10, flags = ANIMATION_END_NOW) //we may have a previous animation going. finish it first, then do this one without delay.
sleep(10)
//as long as they're still on the sigil and are either not a servant or they're a servant AND it has remaining vitality
- while(L && (!is_servant_of_ratvar(L) || (is_servant_of_ratvar(L) && (GLOB.ratvar_awakens || GLOB.clockwork_vitality))) && get_turf(L) == get_turf(src))
+ while(L && (!is_servant_of_ratvar(L) || (is_servant_of_ratvar(L) && (GLOB.ratvar_awakens || GLOB.clockwork_vitality))) && get_turf(L) == get_turf(src) && !L.buckled)
sigil_active = TRUE
if(animation_number >= 4)
new /obj/effect/temp_visual/ratvar/sigil/vitality(get_turf(src))
@@ -313,21 +313,28 @@
revival_cost = 0
var/mob/dead/observer/ghost = L.get_ghost(TRUE)
if(GLOB.clockwork_vitality >= revival_cost && (ghost || (L.mind && L.mind.active)))
- if(ghost)
- ghost.reenter_corpse()
- L.revive(1, 1)
- var/obj/effect/temp_visual/ratvar/sigil/vitality/V = new /obj/effect/temp_visual/ratvar/sigil/vitality(get_turf(src))
- animate(V, alpha = 0, transform = matrix()*2, time = 8)
- playsound(L, 'sound/magic/staff_healing.ogg', 50, 1)
- L.visible_message("[L] suddenly gets back up, [L.p_their()] body dripping blue ichor!", "\"[text2ratvar("You will be okay, child.")]\"")
- GLOB.clockwork_vitality -= revival_cost
+ if(L.has_status_effect(STATUS_EFFECT_ICHORIAL_STAIN))
+ visible_message("[src] strains, but nothing happens...")
+ if(L.pulledby)
+ to_chat(L.pulledby, "[L] was already revived recently by a vitality matrix! Wait a bit longer!")
+ break
+ else
+ if(ghost)
+ ghost.reenter_corpse()
+ L.revive(1, 1)
+ var/obj/effect/temp_visual/ratvar/sigil/vitality/V = new /obj/effect/temp_visual/ratvar/sigil/vitality(get_turf(src))
+ animate(V, alpha = 0, transform = matrix()*2, time = 8)
+ playsound(L, 'sound/magic/staff_healing.ogg', 50, 1)
+ to_chat(L, "\"[text2ratvar("You will be okay, child.")]\"")
+ L.apply_status_effect(STATUS_EFFECT_ICHORIAL_STAIN)
+ GLOB.clockwork_vitality -= revival_cost
break
if(!L.client || L.client.is_afk())
set waitfor = FALSE
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [L.name], an inactive clock cultist?", "[name]", null, "Clock Cultist", 50, L)
var/mob/dead/observer/theghost = null
if(candidates.len)
- to_chat(L, "Your physical form has been taken over by another soul due to your inactivity! Ahelp if you wish to regain your form!")
+ to_chat(L, "Your physical form has been taken over by another soul due to your inactivity! Ahelp if you wish to regain your form!")
message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(L)]) to replace an inactive clock cultist.")
L.ghostize(0)
L.key = theghost.key
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 09cfeb99d3..c4774fe0ad 100644
--- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm
+++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm
@@ -70,6 +70,12 @@
quickbind = TRUE
quickbind_desc = "Creates a Vitality Matrix, which drains non-Servants on it to heal Servants that cross it."
+/datum/clockwork_scripture/create_object/vitality_matrix/check_special_requirements()
+ if(locate(object_path) in range(1, invoker))
+ to_chat(invoker, "Vitality matrices placed next to each other could interfere and cause a feedback loop! Move away from the other ones!")
+ return FALSE
+ return ..()
+
//Judicial Visor: Creates a judicial visor, which can smite an area.
/datum/clockwork_scripture/create_object/judicial_visor
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
index f6a7b8e347..fffabe8f5c 100644
--- 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
@@ -3,7 +3,7 @@
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
+ max_integrity = 5
icon_state = "pressure_sensor"
alpha = 80
layer = LOW_ITEM_LAYER
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
index d79ca88ecb..c91cf594e8 100644
--- a/code/game/gamemodes/clock_cult/clock_structures/traps/brass_skewer.dm
+++ b/code/game/gamemodes/clock_cult/clock_structures/traps/brass_skewer.dm
@@ -21,9 +21,10 @@
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)
+ if(iscarbon(L))
+ 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 ..()
@@ -48,14 +49,22 @@
/obj/structure/destructible/clockwork/trap/brass_skewer/activate()
if(density)
return
- var/mob/living/carbon/squirrel = locate() in get_turf(src)
+ var/mob/living/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")
+ if(iscyborg(squirrel))
+ if(!squirrel.stat)
+ squirrel.visible_message("A massive brass spike erupts from the ground, rending [squirrel]'s chassis but shattering into pieces!", \
+ "A massive brass spike rips through your chassis and bursts into shrapnel in your casing!")
+ squirrel.adjustBruteLoss(50)
+ squirrel.Stun(20)
+ addtimer(CALLBACK(src, .proc/take_damage, max_integrity), 1)
+ else
+ 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
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index bc4fd83334..9999d8c330 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -121,6 +121,9 @@
if(wear_id)
msg += "[t_He] [t_is] wearing [icon2html(wear_id, user)] \a [wear_id].\n"
+ //Status effects
+ msg += status_effect_examines()
+
//Jitters
switch(jitteriness)
if(300 to INFINITY)
@@ -354,3 +357,16 @@
msg += "*---------*"
to_chat(user, msg)
+
+/mob/living/proc/status_effect_examines(pronoun_replacement) //You can include this in any mob's examine() to show the examine texts of status effects!
+ var/list/dat = list()
+ if(!pronoun_replacement)
+ pronoun_replacement = p_they(TRUE)
+ for(var/V in status_effects)
+ var/datum/status_effect/E = V
+ if(E.examine_text)
+ var/new_text = replacetext(E.examine_text, "SUBJECTPRONOUN", pronoun_replacement)
+ new_text = replacetext(new_text, "[pronoun_replacement] is", "[pronoun_replacement] [p_are()]") //To make sure something become "They are" or "She is", not "They are" and "She are"
+ dat += "[new_text]\n" //dat.Join("\n") doesn't work here, for some reason
+ if(dat.len)
+ return dat.Join()
diff --git a/code/modules/mob/living/silicon/robot/examine.dm b/code/modules/mob/living/silicon/robot/examine.dm
index 788a8f4255..3f5b12ae20 100644
--- a/code/modules/mob/living/silicon/robot/examine.dm
+++ b/code/modules/mob/living/silicon/robot/examine.dm
@@ -6,6 +6,7 @@
var/obj/act_module = get_active_held_item()
if(act_module)
msg += "It is holding [icon2html(act_module, user)] \a [act_module].\n"
+ msg += status_effect_examines()
msg += ""
if (src.getBruteLoss())
if (src.getBruteLoss() < maxHealth*0.5)
diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi
index ef680c266a..e6d40977a7 100644
Binary files a/icons/mob/screen_alert.dmi and b/icons/mob/screen_alert.dmi differ