diff --git a/code/datums/observation/stat_set.dm b/code/datums/observation/stat_set.dm
new file mode 100644
index 0000000000..b980d06ecc
--- /dev/null
+++ b/code/datums/observation/stat_set.dm
@@ -0,0 +1,24 @@
+// Observer Pattern Implementation: Stat Set
+// Registration type: /mob/living
+//
+// Raised when: A /mob/living changes stat, using the set_stat() proc
+//
+// Arguments that the called proc should expect:
+// /mob/living/stat_mob: The mob whose stat changed
+// /old_stat: Status before the change.
+// /new_stat: Status after the change.
+
+GLOBAL_DATUM_INIT(stat_set_event, /decl/observ/stat_set, new)
+
+/decl/observ/stat_set
+ name = "Stat Set"
+ expected_type = /mob/living
+
+/****************
+* Stat Handling *
+****************/
+/mob/living/set_stat(var/new_stat)
+ var/old_stat = stat
+ . = ..()
+ if(stat != old_stat)
+ GLOB.stat_set_event.raise_event(src, old_stat, new_stat)
diff --git a/code/game/dna/genes/monkey.dm b/code/game/dna/genes/monkey.dm
index 45e852551d..0089355ed3 100644
--- a/code/game/dna/genes/monkey.dm
+++ b/code/game/dna/genes/monkey.dm
@@ -69,7 +69,7 @@
O.take_overall_damage(M.getBruteLoss() + 40, M.getFireLoss())
O.adjustToxLoss(M.getToxLoss() + 20)
O.adjustOxyLoss(M.getOxyLoss())
- O.stat = M.stat
+ O.set_stat(M.stat)
O.a_intent = I_HURT
for (var/obj/item/weapon/implant/I in implants)
I.loc = O
@@ -154,7 +154,7 @@
O.take_overall_damage(M.getBruteLoss(), M.getFireLoss())
O.adjustToxLoss(M.getToxLoss())
O.adjustOxyLoss(M.getOxyLoss())
- O.stat = M.stat
+ O.set_stat(M.stat)
for (var/obj/item/weapon/implant/I in implants)
I.loc = O
I.implanted = O
diff --git a/code/game/gamemodes/changeling/powers/epinephrine_overdose.dm b/code/game/gamemodes/changeling/powers/epinephrine_overdose.dm
index d5be03c6b1..5d3c1a3be9 100644
--- a/code/game/gamemodes/changeling/powers/epinephrine_overdose.dm
+++ b/code/game/gamemodes/changeling/powers/epinephrine_overdose.dm
@@ -29,7 +29,7 @@
var/mob/living/carbon/human/C = src
to_chat(C, "Energy rushes through us. [C.lying ? "We arise." : ""]")
- C.stat = 0
+ C.set_stat(CONSCIOUS)
C.SetParalysis(0)
C.SetStunned(0)
C.SetWeakened(0)
diff --git a/code/game/gamemodes/changeling/powers/lesser_form.dm b/code/game/gamemodes/changeling/powers/lesser_form.dm
index 9d7c4de3d1..d7b9cb0489 100644
--- a/code/game/gamemodes/changeling/powers/lesser_form.dm
+++ b/code/game/gamemodes/changeling/powers/lesser_form.dm
@@ -100,7 +100,7 @@
O.adjustBruteLoss(C.getBruteLoss())
O.setOxyLoss(C.getOxyLoss())
O.adjustFireLoss(C.getFireLoss())
- O.stat = C.stat
+ O.set_stat(C.stat)
for (var/obj/item/weapon/implant/I in implants)
I.loc = O
I.implanted = O
diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm
index 2439fbe38a..61a061170e 100644
--- a/code/game/gamemodes/changeling/powers/revive.dm
+++ b/code/game/gamemodes/changeling/powers/revive.dm
@@ -79,7 +79,7 @@
C.update_canmove()
C.mind.changeling.purchased_powers -= C
feedback_add_details("changeling_powers","CR")
- C.stat = CONSCIOUS
+ C.set_stat(CONSCIOUS)
C.forbid_seeing_deadchat = FALSE
C.timeofdeath = null
src.verbs -= /mob/proc/changeling_revive
diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm
index ded5d20073..bf05da7a3b 100644
--- a/code/game/gamemodes/gameticker.dm
+++ b/code/game/gamemodes/gameticker.dm
@@ -203,10 +203,10 @@ var/global/datum/controller/gameticker/ticker
var/turf/T = get_turf(M)
if(T && T.z in using_map.station_levels) //we don't use M.death(0) because it calls a for(/mob) loop and
M.health = 0
- M.stat = DEAD
+ M.set_stat(DEAD)
if(1) //on a z-level 1 turf.
M.health = 0
- M.stat = DEAD
+ M.set_stat(DEAD)
//Now animate the cinematic
switch(station_missed)
diff --git a/code/game/gamemodes/technomancer/spells/resurrect.dm b/code/game/gamemodes/technomancer/spells/resurrect.dm
index cc0374b4d6..02c072b90d 100644
--- a/code/game/gamemodes/technomancer/spells/resurrect.dm
+++ b/code/game/gamemodes/technomancer/spells/resurrect.dm
@@ -32,7 +32,7 @@
if(istype(L, /mob/living/simple_mob))
var/mob/living/simple_mob/SM = L
SM.health = SM.getMaxHealth() / 3
- SM.stat = CONSCIOUS
+ SM.set_stat(CONSCIOUS)
dead_mob_list -= SM
living_mob_list += SM
SM.update_icon()
@@ -52,7 +52,7 @@
sleep(10 SECONDS)
if(H.client)
- L.stat = CONSCIOUS //Note that if whatever killed them in the first place wasn't fixed, they're likely to die again.
+ L.set_stat(CONSCIOUS) //Note that if whatever killed them in the first place wasn't fixed, they're likely to die again.
dead_mob_list -= H
living_mob_list += H
H.timeofdeath = null
diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm
index 5af8e2320c..874055afc2 100644
--- a/code/game/machinery/computer/aifixer.dm
+++ b/code/game/machinery/computer/aifixer.dm
@@ -110,7 +110,7 @@
src.occupant.adjustBruteLoss(-1)
src.occupant.updatehealth()
if (src.occupant.health >= 0 && src.occupant.stat == DEAD)
- src.occupant.stat = CONSCIOUS
+ src.occupant.set_stat(CONSCIOUS)
src.occupant.lying = 0
dead_mob_list -= src.occupant
living_mob_list += src.occupant
diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm
index 4ef92f4c04..9db22b9270 100644
--- a/code/game/machinery/cryo.dm
+++ b/code/game/machinery/cryo.dm
@@ -232,7 +232,7 @@
return
occupant.bodytemperature += 2*(air_contents.temperature - occupant.bodytemperature)*current_heat_capacity/(current_heat_capacity + air_contents.heat_capacity())
occupant.bodytemperature = max(occupant.bodytemperature, air_contents.temperature) // this is so ugly i'm sorry for doing it i'll fix it later i promise
- occupant.stat = UNCONSCIOUS
+ occupant.set_stat(UNCONSCIOUS)
occupant.dir = SOUTH
if(occupant.bodytemperature < T0C)
occupant.sleeping = max(5, (1/occupant.bodytemperature)*2000)
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 8eaf406201..d8cf77d53c 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -1881,7 +1881,7 @@
O.aiRestorePowerRoutine = 0
O.control_disabled = 1 // Can't control things remotely if you're stuck in a card!
O.laws = AI.laws
- O.stat = AI.stat
+ O.set_stat(AI.stat)
O.oxyloss = AI.getOxyLoss()
O.fireloss = AI.getFireLoss()
O.bruteloss = AI.getBruteLoss()
diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm
index fefa0475a7..9d95fd2304 100644
--- a/code/game/objects/items/devices/defib.dm
+++ b/code/game/objects/items/devices/defib.dm
@@ -495,7 +495,7 @@
living_mob_list += M
M.timeofdeath = 0
- M.stat = UNCONSCIOUS //Life() can bring them back to consciousness if it needs to.
+ M.set_stat(UNCONSCIOUS) //Life() can bring them back to consciousness if it needs to.
M.failed_last_breath = 0 //So mobs that died of oxyloss don't revive and have perpetual out of breath.
M.reload_fullscreen()
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index fe1685ec70..602f6e3a66 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -66,7 +66,7 @@
if(ghost.mind && ghost.mind.current == R)
R.key = ghost.key
- R.stat = CONSCIOUS
+ R.set_stat(CONSCIOUS)
dead_mob_list -= R
living_mob_list |= R
R.notify_ai(ROBOT_NOTIFICATION_NEW_UNIT)
diff --git a/code/modules/clothing/gloves/antagonist.dm b/code/modules/clothing/gloves/antagonist.dm
index b11a29313d..d1a01d0e68 100644
--- a/code/modules/clothing/gloves/antagonist.dm
+++ b/code/modules/clothing/gloves/antagonist.dm
@@ -146,7 +146,7 @@
living_mob_list += H
H.timeofdeath = 0
- H.stat = UNCONSCIOUS
+ H.set_stat(UNCONSCIOUS)
H.failed_last_breath = 0
H.reload_fullscreen()
diff --git a/code/modules/hydroponics/seed_mobs.dm b/code/modules/hydroponics/seed_mobs.dm
index 0c9441dbac..8b5c4a56a1 100644
--- a/code/modules/hydroponics/seed_mobs.dm
+++ b/code/modules/hydroponics/seed_mobs.dm
@@ -12,7 +12,7 @@
spawn(75)
if(!host.ckey && !host.client)
host.death() // This seems redundant, but a lot of mobs don't
- host.stat = DEAD // handle death() properly. Better safe than etc.
+ host.set_stat(DEAD) // handle death() properly. Better safe than etc.
host.visible_message("[host] is malformed and unable to survive. It expires pitifully, leaving behind some seeds.")
var/total_yield = rand(1,3)
diff --git a/code/modules/mob/dead/corpse.dm b/code/modules/mob/dead/corpse.dm
index 81a51214a7..18d81bf484 100644
--- a/code/modules/mob/dead/corpse.dm
+++ b/code/modules/mob/dead/corpse.dm
@@ -33,7 +33,7 @@
/obj/effect/landmark/mobcorpse/proc/createCorpse() //Creates a mob and checks for gear in each slot before attempting to equip it.
var/mob/living/carbon/human/M = new /mob/living/carbon/human (src.loc)
M.real_name = src.name
- M.stat = 2 //Kills the new mob
+ M.set_stat(DEAD) //Kills the new mob
if(src.corpseuniform)
M.equip_to_slot_or_del(new src.corpseuniform(M), slot_w_uniform)
if(src.corpsesuit)
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index b41331c37e..fb2af26527 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -94,8 +94,6 @@
plane = PLANE_GHOSTS //Why doesn't the var above work...???
verbs += /mob/observer/dead/proc/dead_tele
- stat = DEAD
-
var/turf/T
if(ismob(body))
T = get_turf(body) //Where is the body located?
@@ -149,6 +147,11 @@
/mob/observer/dead/CanPass(atom/movable/mover, turf/target)
return TRUE
+
+/mob/observer/dead/set_stat(var/new_stat)
+ if(new_stat != DEAD)
+ CRASH("It is best if observers stay dead, thank you.")
+
/*
Transfer_mind is there to check if mob is being deleted/not going to have a body.
Works together with spawning an observer, noted above.
diff --git a/code/modules/mob/death.dm b/code/modules/mob/death.dm
index 43695a03ac..c2f5c586eb 100644
--- a/code/modules/mob/death.dm
+++ b/code/modules/mob/death.dm
@@ -76,7 +76,7 @@
if(!gibbed && deathmessage != "no message") // This is gross, but reliable. Only brains use it.
src.visible_message("\The [src.name] [deathmessage]")
- stat = DEAD
+ set_stat(DEAD)
update_canmove()
diff --git a/code/modules/mob/living/bot/bot.dm b/code/modules/mob/living/bot/bot.dm
index 7d71c92343..5e9f496646 100644
--- a/code/modules/mob/living/bot/bot.dm
+++ b/code/modules/mob/living/bot/bot.dm
@@ -79,7 +79,7 @@
/mob/living/bot/updatehealth()
if(status_flags & GODMODE)
health = getMaxHealth()
- stat = CONSCIOUS
+ set_stat(CONSCIOUS)
else
health = getMaxHealth() - getFireLoss() - getBruteLoss()
oxyloss = 0
diff --git a/code/modules/mob/living/carbon/alien/life.dm b/code/modules/mob/living/carbon/alien/life.dm
index 2c39964ad6..3b57c6a5f7 100644
--- a/code/modules/mob/living/carbon/alien/life.dm
+++ b/code/modules/mob/living/carbon/alien/life.dm
@@ -51,7 +51,7 @@
if(paralysis && paralysis > 0)
blinded = 1
- stat = UNCONSCIOUS
+ set_stat(UNCONSCIOUS)
if(halloss > 0)
adjustHalLoss(-3)
@@ -61,13 +61,13 @@
if(mind.active && client != null)
sleeping = max(sleeping-1, 0)
blinded = 1
- stat = UNCONSCIOUS
+ set_stat(UNCONSCIOUS)
else if(resting)
if(halloss > 0)
adjustHalLoss(-3)
else
- stat = CONSCIOUS
+ set_stat(CONSCIOUS)
if(halloss > 0)
adjustHalLoss(-1)
diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm
index 1833216ec7..d3d84db25a 100644
--- a/code/modules/mob/living/carbon/brain/MMI.dm
+++ b/code/modules/mob/living/carbon/brain/MMI.dm
@@ -64,7 +64,7 @@
B.brainmob = null
brainmob.loc = src
brainmob.container = src
- brainmob.stat = 0
+ brainmob.set_stat(CONSCIOUS)
dead_mob_list -= brainmob//Update dem lists
living_mob_list += brainmob
@@ -185,7 +185,7 @@
src.brainmob.add_language(LANGUAGE_EAL)
src.brainmob.loc = src
src.brainmob.container = src
- src.brainmob.stat = 0
+ src.brainmob.set_stat(CONSCIOUS)
src.brainmob.silent = 0
radio = new(src)
dead_mob_list -= src.brainmob
@@ -230,7 +230,7 @@
/obj/item/device/mmi/digital/transfer_identity(var/mob/living/carbon/H)
brainmob.dna = H.dna
brainmob.timeofhostdeath = H.timeofdeath
- brainmob.stat = 0
+ brainmob.set_stat(CONSCIOUS)
if(H.mind)
H.mind.transfer_to(brainmob)
return
diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm
index d1baabbe8b..7cf2027025 100644
--- a/code/modules/mob/living/carbon/human/human_damage.dm
+++ b/code/modules/mob/living/carbon/human/human_damage.dm
@@ -4,7 +4,7 @@
if(status_flags & GODMODE)
health = getMaxHealth()
- stat = CONSCIOUS
+ set_stat(CONSCIOUS)
return
var/total_burn = 0
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index e4127c9a02..2d816a9a94 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -1104,9 +1104,9 @@
return 1
-/mob/living/carbon/human/proc/set_stat(var/new_stat)
- stat = new_stat
- if(stat)
+/mob/living/carbon/human/set_stat(var/new_stat)
+ . = ..()
+ if(. && stat)
update_skin(1)
/mob/living/carbon/human/handle_regular_hud_updates()
diff --git a/code/modules/mob/living/carbon/metroid/life.dm b/code/modules/mob/living/carbon/metroid/life.dm
index f11d9d137d..7643ea3d2e 100644
--- a/code/modules/mob/living/carbon/metroid/life.dm
+++ b/code/modules/mob/living/carbon/metroid/life.dm
@@ -102,18 +102,18 @@
else
if (src.paralysis || src.stunned || src.weakened || (status_flags & FAKEDEATH)) //Stunned etc.
if (src.stunned > 0)
- src.stat = 0
+ src.set_stat(CONSCIOUS)
if (src.weakened > 0)
src.lying = 0
- src.stat = 0
+ src.set_stat(CONSCIOUS)
if (src.paralysis > 0)
src.blinded = 0
src.lying = 0
- src.stat = 0
+ src.set_stat(CONSCIOUS)
else
src.lying = 0
- src.stat = 0
+ src.set_stat(CONSCIOUS)
if (src.stuttering) src.stuttering = 0
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index 350097e141..1e66f65478 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -99,11 +99,11 @@
updatehealth()
if(stat != DEAD)
if(paralysis)
- stat = UNCONSCIOUS
+ set_stat(UNCONSCIOUS)
else if (status_flags & FAKEDEATH)
- stat = UNCONSCIOUS
+ set_stat(UNCONSCIOUS)
else
- stat = CONSCIOUS
+ set_stat(CONSCIOUS)
return 1
/mob/living/proc/handle_statuses()
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index dd2bb820ea..4a03fd6adf 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -247,11 +247,10 @@ default behaviour is:
/mob/living/proc/updatehealth()
if(status_flags & GODMODE)
health = 100
- stat = CONSCIOUS
+ set_stat(CONSCIOUS)
else
health = getMaxHealth() - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - getCloneLoss() - halloss
-
//This proc is used for mobs which are affected by pressure to calculate the amount of pressure that actually
//affects them once clothing is factored in. ~Errorage
/mob/living/proc/calculate_affecting_pressure(var/pressure)
@@ -744,7 +743,7 @@ default behaviour is:
timeofdeath = 0
// restore us to conciousness
- stat = CONSCIOUS
+ set_stat(CONSCIOUS)
// make the icons look correct
regenerate_icons()
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index 0d429fa089..b1398d3170 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -169,7 +169,7 @@
/mob/living/silicon/ai/updatehealth()
if(status_flags & GODMODE)
health = 100
- stat = CONSCIOUS
+ set_stat(CONSCIOUS)
setOxyLoss(0)
else
health = 100 - getFireLoss() - getBruteLoss() // Oxyloss is not part of health as it represents AIs backup power. AI is immune against ToxLoss as it is machine.
diff --git a/code/modules/mob/living/silicon/decoy/life.dm b/code/modules/mob/living/silicon/decoy/life.dm
index d62d5d15da..07683eb2dc 100644
--- a/code/modules/mob/living/silicon/decoy/life.dm
+++ b/code/modules/mob/living/silicon/decoy/life.dm
@@ -10,6 +10,6 @@
/mob/living/silicon/decoy/updatehealth()
if(status_flags & GODMODE)
health = 100
- stat = CONSCIOUS
+ set_stat(CONSCIOUS)
else
health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss()
diff --git a/code/modules/mob/living/silicon/pai/life.dm b/code/modules/mob/living/silicon/pai/life.dm
index 42888a3827..e159308d1b 100644
--- a/code/modules/mob/living/silicon/pai/life.dm
+++ b/code/modules/mob/living/silicon/pai/life.dm
@@ -30,6 +30,6 @@
/mob/living/silicon/pai/updatehealth()
if(status_flags & GODMODE)
health = 100
- stat = CONSCIOUS
+ set_stat(CONSCIOUS)
else
health = 100 - getBruteLoss() - getFireLoss()
diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm
index ec7d840663..5f097ef50a 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone.dm
@@ -256,7 +256,7 @@ var/list/mob_hat_cache = list()
/mob/living/silicon/robot/drone/updatehealth()
if(status_flags & GODMODE)
health = maxHealth
- stat = CONSCIOUS
+ set_stat(CONSCIOUS)
return
health = maxHealth - (getBruteLoss() + getFireLoss())
return
diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm
index d745b400de..dbffa182fe 100644
--- a/code/modules/mob/living/silicon/robot/life.dm
+++ b/code/modules/mob/living/silicon/robot/life.dm
@@ -88,7 +88,7 @@
if (src.stat != 2) //Alive.
if (src.paralysis || src.stunned || src.weakened || !src.has_power) //Stunned etc.
- src.stat = 1
+ src.set_stat(UNCONSCIOUS)
if (src.stunned > 0)
AdjustStunned(-1)
if (src.weakened > 0)
@@ -100,7 +100,7 @@
src.blinded = 0
else //Not stunned.
- src.stat = 0
+ src.set_stat(CONSCIOUS)
AdjustConfused(-1)
diff --git a/code/modules/mob/living/silicon/robot/robot_damage.dm b/code/modules/mob/living/silicon/robot/robot_damage.dm
index c27d7e36b6..67ab5dd3c4 100644
--- a/code/modules/mob/living/silicon/robot/robot_damage.dm
+++ b/code/modules/mob/living/silicon/robot/robot_damage.dm
@@ -1,7 +1,7 @@
/mob/living/silicon/robot/updatehealth()
if(status_flags & GODMODE)
health = getMaxHealth()
- stat = CONSCIOUS
+ set_stat(CONSCIOUS)
return
health = getMaxHealth() - (getBruteLoss() + getFireLoss())
return
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm b/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm
index a5e58e2510..12b70f6048 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm
@@ -76,7 +76,7 @@
/mob/living/simple_mob/animal/passive/mouse/proc/splat()
src.health = 0
- src.stat = DEAD
+ src.set_stat(DEAD)
src.icon_dead = "mouse_[body_color]_splat"
src.icon_state = "mouse_[body_color]_splat"
layer = MOB_LAYER
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 04525d2f9b..3bc69b20ee 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1007,6 +1007,11 @@ mob/proc/yank_out_object()
/mob/proc/updateicon()
return
+// Please always use this proc, never just set the var directly.
+/mob/proc/set_stat(var/new_stat)
+ . = (stat != new_stat)
+ stat = new_stat
+
/mob/verb/face_direction()
set name = "Face Direction"
diff --git a/code/modules/organs/subtypes/machine.dm b/code/modules/organs/subtypes/machine.dm
index 0397a4e172..0e3a60fdd5 100644
--- a/code/modules/organs/subtypes/machine.dm
+++ b/code/modules/organs/subtypes/machine.dm
@@ -14,7 +14,7 @@
..()
// This is very ghetto way of rebooting an IPC. TODO better way.
if(owner && owner.stat == DEAD)
- owner.stat = 0
+ owner.set_stat(CONSCIOUS)
owner.visible_message("\The [owner] twitches visibly!")
/obj/item/organ/internal/cell/emp_act(severity)
@@ -68,7 +68,7 @@
stored_mmi.brainmob.languages = owner.languages
if(owner && owner.stat == DEAD)
- owner.stat = 0
+ owner.set_stat(CONSCIOUS)
dead_mob_list -= owner
living_mob_list |= owner
owner.visible_message("\The [owner] twitches visibly!")
diff --git a/code/modules/research/prosfab_designs.dm b/code/modules/research/prosfab_designs.dm
index d038736b96..da9cc05509 100644
--- a/code/modules/research/prosfab_designs.dm
+++ b/code/modules/research/prosfab_designs.dm
@@ -53,7 +53,7 @@
newspecies = prosfab.species
var/mob/living/carbon/human/H = new(newloc,newspecies)
- H.stat = DEAD
+ H.set_stat(DEAD)
H.gender = gender
for(var/obj/item/organ/external/EO in H.organs)
if(EO.organ_tag == BP_TORSO || EO.organ_tag == BP_GROIN)
diff --git a/code/modules/xenobio2/mob/xeno.dm b/code/modules/xenobio2/mob/xeno.dm
index 648c1f1e10..74a35aacc4 100644
--- a/code/modules/xenobio2/mob/xeno.dm
+++ b/code/modules/xenobio2/mob/xeno.dm
@@ -93,7 +93,7 @@ Also includes Life and New
traitdat.source = name
if(!health)
- stat = DEAD
+ set_stat(DEAD)
/mob/living/simple_mob/xeno/bullet_act(var/obj/item/projectile/Proj)
if(istype(Proj, /obj/item/projectile/beam/stun/xeno))
diff --git a/maps/RandomZLevels/wildwest.dm b/maps/RandomZLevels/wildwest.dm
index f2f48bf9fc..0450cd84a1 100644
--- a/maps/RandomZLevels/wildwest.dm
+++ b/maps/RandomZLevels/wildwest.dm
@@ -1,173 +1,173 @@
-/* Code for the Wild West map by Brotemis
- * Contains:
- * Wish Granter
- * Meat Grinder
- */
-
-/*
- * Wish Granter
- */
-/obj/machinery/wish_granter_dark
- name = "Wish Granter"
- desc = "You're not so sure about this, anymore..."
- icon = 'icons/obj/device.dmi'
- icon_state = "syndbeacon"
-
- anchored = 1
- density = 1
- use_power = USE_POWER_OFF
-
- var/chargesa = 1
- var/insistinga = 0
-
-/obj/machinery/wish_granter_dark/attack_hand(var/mob/living/carbon/human/user as mob)
- usr.set_machine(src)
-
- if(chargesa <= 0)
- to_chat(user, "The Wish Granter lies silent.")
- return
-
- else if(!istype(user, /mob/living/carbon/human))
- to_chat(user, "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.")
- return
-
- else if(is_special_character(user))
- to_chat(user, "Even to a heart as dark as yours, you know nothing good will come of this. Something instinctual makes you pull away.")
-
- else if (!insistinga)
- to_chat(user, "Your first touch makes the Wish Granter stir, listening to you. Are you really sure you want to do this?")
- insistinga++
-
- else
- chargesa--
- insistinga = 0
- var/wish = input("You want...","Wish") as null|anything in list("Power","Wealth","Immortality","To Kill","Peace")
- switch(wish)
- if("Power")
- to_chat(user, "Your wish is granted, but at a terrible cost...")
- to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart.")
- if (!(LASER in user.mutations))
- user.mutations.Add(LASER)
- to_chat(user, "You feel pressure building behind your eyes.")
- if (!(COLD_RESISTANCE in user.mutations))
- user.mutations.Add(COLD_RESISTANCE)
- to_chat(user, "Your body feels warm.")
- if (!(XRAY in user.mutations))
- user.mutations.Add(XRAY)
- user.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS)
- user.see_in_dark = 8
- user.see_invisible = SEE_INVISIBLE_LEVEL_TWO
- to_chat(user, "The walls suddenly disappear.")
- user.dna.mutantrace = "shadow"
- user.update_mutantrace()
- if("Wealth")
- to_chat(user, "Your wish is granted, but at a terrible cost...")
- to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart.")
- new /obj/structure/closet/syndicate/resources/everything(loc)
- user.dna.mutantrace = "shadow"
- user.update_mutantrace()
- if("Immortality")
- to_chat(user, "Your wish is granted, but at a terrible cost...")
- to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart.")
- user.verbs += /mob/living/carbon/proc/immortality
- user.dna.mutantrace = "shadow"
- user.update_mutantrace()
- if("To Kill")
- to_chat(user, "Your wish is granted, but at a terrible cost...")
- to_chat(user, "The Wish Granter punishes you for your wickedness, claiming your soul and warping your body to match the darkness in your heart.")
- ticker.mode.traitors += user.mind
- user.mind.special_role = "traitor"
- var/datum/objective/hijack/hijack = new
- hijack.owner = user.mind
- user.mind.objectives += hijack
- to_chat(user, "Your inhibitions are swept away, the bonds of loyalty broken, you are free to murder as you please!")
- var/obj_count = 1
- for(var/datum/objective/OBJ in user.mind.objectives)
- to_chat(user, "Objective #[obj_count]: [OBJ.explanation_text]")
- obj_count++
- user.dna.mutantrace = "shadow"
- user.update_mutantrace()
- if("Peace")
- to_chat(user, "Whatever alien sentience that the Wish Granter possesses is satisfied with your wish. There is a distant wailing as the last of the Faithless begin to die, then silence.")
- to_chat(user, "You feel as if you just narrowly avoided a terrible fate...")
- for(var/mob/living/simple_mob/faithless/F in living_mob_list)
- F.health = -10
- F.set_stat(DEAD)
- F.icon_state = "faithless_dead"
-
-
-///////////////Meatgrinder//////////////
-
-
-/obj/effect/meatgrinder
- name = "Meat Grinder"
- desc = "What is that thing?"
- density = 1
- anchored = 1
- icon = 'icons/mob/critter.dmi'
- icon_state = "blob"
- var/triggerproc = "explode" //name of the proc thats called when the mine is triggered
- var/triggered = 0
-
-/obj/effect/meatgrinder/New()
- icon_state = "blob"
-
-/obj/effect/meatgrinder/HasEntered(AM as mob|obj)
- Bumped(AM)
-
-/obj/effect/meatgrinder/Bumped(mob/M as mob|obj)
-
- if(triggered) return
-
- if(istype(M, /mob/living/carbon/human) || istype(M, /mob/living/carbon/monkey))
- for(var/mob/O in viewers(world.view, src.loc))
- to_chat(O, "[M] triggered the \icon[src] [src]")
- triggered = 1
- call(src,triggerproc)(M)
-
-/obj/effect/meatgrinder/proc/triggerrad1(mob)
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- for(var/mob/O in viewers(world.view, src.loc))
- s.set_up(3, 1, src)
- s.start()
- explosion(mob, 1, 0, 0, 0)
- spawn(0)
- qdel(src)
-
-/obj/effect/meatgrinder
- name = "Meat Grinder"
- icon_state = "blob"
- triggerproc = "triggerrad1"
-
-
-/////For the Wishgranter///////////
-
-/mob/living/carbon/proc/immortality()
- set category = "Immortality"
- set name = "Resurrection"
-
- var/mob/living/carbon/C = usr
- if(!C.stat)
- to_chat(C, "You're not dead yet!")
- return
- to_chat(C, "Death is not your end!")
-
- spawn(rand(800,1200))
- if(C.stat == DEAD)
- dead_mob_list -= C
- living_mob_list += C
- C.set_stat(CONSCIOUS)
- C.tod = null
- C.setToxLoss(0)
- C.setOxyLoss(0)
- C.setCloneLoss(0)
- C.SetParalysis(0)
- C.SetStunned(0)
- C.SetWeakened(0)
- C.radiation = 0
- C.heal_overall_damage(C.getBruteLoss(), C.getFireLoss())
- C.reagents.clear_reagents()
- to_chat(C, "You have regenerated.")
- C.visible_message("[usr] appears to wake from the dead, having healed all wounds.")
- C.update_canmove()
- return 1
+/* Code for the Wild West map by Brotemis
+ * Contains:
+ * Wish Granter
+ * Meat Grinder
+ */
+
+/*
+ * Wish Granter
+ */
+/obj/machinery/wish_granter_dark
+ name = "Wish Granter"
+ desc = "You're not so sure about this, anymore..."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "syndbeacon"
+
+ anchored = 1
+ density = 1
+ use_power = USE_POWER_OFF
+
+ var/chargesa = 1
+ var/insistinga = 0
+
+/obj/machinery/wish_granter_dark/attack_hand(var/mob/living/carbon/human/user as mob)
+ usr.set_machine(src)
+
+ if(chargesa <= 0)
+ to_chat(user, "The Wish Granter lies silent.")
+ return
+
+ else if(!istype(user, /mob/living/carbon/human))
+ to_chat(user, "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.")
+ return
+
+ else if(is_special_character(user))
+ to_chat(user, "Even to a heart as dark as yours, you know nothing good will come of this. Something instinctual makes you pull away.")
+
+ else if (!insistinga)
+ to_chat(user, "Your first touch makes the Wish Granter stir, listening to you. Are you really sure you want to do this?")
+ insistinga++
+
+ else
+ chargesa--
+ insistinga = 0
+ var/wish = input("You want...","Wish") as null|anything in list("Power","Wealth","Immortality","To Kill","Peace")
+ switch(wish)
+ if("Power")
+ to_chat(user, "Your wish is granted, but at a terrible cost...")
+ to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart.")
+ if (!(LASER in user.mutations))
+ user.mutations.Add(LASER)
+ to_chat(user, "You feel pressure building behind your eyes.")
+ if (!(COLD_RESISTANCE in user.mutations))
+ user.mutations.Add(COLD_RESISTANCE)
+ to_chat(user, "Your body feels warm.")
+ if (!(XRAY in user.mutations))
+ user.mutations.Add(XRAY)
+ user.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS)
+ user.see_in_dark = 8
+ user.see_invisible = SEE_INVISIBLE_LEVEL_TWO
+ to_chat(user, "The walls suddenly disappear.")
+ user.dna.mutantrace = "shadow"
+ user.update_mutantrace()
+ if("Wealth")
+ to_chat(user, "Your wish is granted, but at a terrible cost...")
+ to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart.")
+ new /obj/structure/closet/syndicate/resources/everything(loc)
+ user.dna.mutantrace = "shadow"
+ user.update_mutantrace()
+ if("Immortality")
+ to_chat(user, "Your wish is granted, but at a terrible cost...")
+ to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart.")
+ user.verbs += /mob/living/carbon/proc/immortality
+ user.dna.mutantrace = "shadow"
+ user.update_mutantrace()
+ if("To Kill")
+ to_chat(user, "Your wish is granted, but at a terrible cost...")
+ to_chat(user, "The Wish Granter punishes you for your wickedness, claiming your soul and warping your body to match the darkness in your heart.")
+ ticker.mode.traitors += user.mind
+ user.mind.special_role = "traitor"
+ var/datum/objective/hijack/hijack = new
+ hijack.owner = user.mind
+ user.mind.objectives += hijack
+ to_chat(user, "Your inhibitions are swept away, the bonds of loyalty broken, you are free to murder as you please!")
+ var/obj_count = 1
+ for(var/datum/objective/OBJ in user.mind.objectives)
+ to_chat(user, "Objective #[obj_count]: [OBJ.explanation_text]")
+ obj_count++
+ user.dna.mutantrace = "shadow"
+ user.update_mutantrace()
+ if("Peace")
+ to_chat(user, "Whatever alien sentience that the Wish Granter possesses is satisfied with your wish. There is a distant wailing as the last of the Faithless begin to die, then silence.")
+ to_chat(user, "You feel as if you just narrowly avoided a terrible fate...")
+ for(var/mob/living/simple_mob/faithless/F in living_mob_list)
+ F.health = -10
+ F.set_stat(DEAD)
+ F.icon_state = "faithless_dead"
+
+
+///////////////Meatgrinder//////////////
+
+
+/obj/effect/meatgrinder
+ name = "Meat Grinder"
+ desc = "What is that thing?"
+ density = 1
+ anchored = 1
+ icon = 'icons/mob/critter.dmi'
+ icon_state = "blob"
+ var/triggerproc = "explode" //name of the proc thats called when the mine is triggered
+ var/triggered = 0
+
+/obj/effect/meatgrinder/New()
+ icon_state = "blob"
+
+/obj/effect/meatgrinder/HasEntered(AM as mob|obj)
+ Bumped(AM)
+
+/obj/effect/meatgrinder/Bumped(mob/M as mob|obj)
+
+ if(triggered) return
+
+ if(istype(M, /mob/living/carbon/human) || istype(M, /mob/living/carbon/monkey))
+ for(var/mob/O in viewers(world.view, src.loc))
+ to_chat(O, "[M] triggered the \icon[src] [src]")
+ triggered = 1
+ call(src,triggerproc)(M)
+
+/obj/effect/meatgrinder/proc/triggerrad1(mob)
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ for(var/mob/O in viewers(world.view, src.loc))
+ s.set_up(3, 1, src)
+ s.start()
+ explosion(mob, 1, 0, 0, 0)
+ spawn(0)
+ qdel(src)
+
+/obj/effect/meatgrinder
+ name = "Meat Grinder"
+ icon_state = "blob"
+ triggerproc = "triggerrad1"
+
+
+/////For the Wishgranter///////////
+
+/mob/living/carbon/proc/immortality()
+ set category = "Immortality"
+ set name = "Resurrection"
+
+ var/mob/living/carbon/C = usr
+ if(!C.stat)
+ to_chat(C, "You're not dead yet!")
+ return
+ to_chat(C, "Death is not your end!")
+
+ spawn(rand(800,1200))
+ if(C.stat == DEAD)
+ dead_mob_list -= C
+ living_mob_list += C
+ C.set_stat(CONSCIOUS)
+ C.tod = null
+ C.setToxLoss(0)
+ C.setOxyLoss(0)
+ C.setCloneLoss(0)
+ C.SetParalysis(0)
+ C.SetStunned(0)
+ C.SetWeakened(0)
+ C.radiation = 0
+ C.heal_overall_damage(C.getBruteLoss(), C.getFireLoss())
+ C.reagents.clear_reagents()
+ to_chat(C, "You have regenerated.")
+ C.visible_message("[usr] appears to wake from the dead, having healed all wounds.")
+ C.update_canmove()
+ return 1
diff --git a/vorestation.dme b/vorestation.dme
index 782dd211af..3ad9cff74d 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -344,6 +344,7 @@
#include "code\datums\observation\observation.dm"
#include "code\datums\observation\shuttle_added.dm"
#include "code\datums\observation\shuttle_moved.dm"
+#include "code\datums\observation\stat_set.dm"
#include "code\datums\observation\turf_changed.dm"
#include "code\datums\observation\unequipped.dm"
#include "code\datums\observation\z_moved.dm"