diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 87bbf5a1bcc..aff6571082d 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -76,6 +76,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
*/
//mob traits
+#define TRAIT_KNOCKEDOUT "knockedout" //Forces the user to stay unconscious.
#define TRAIT_INCAPACITATED "incapacitated"
#define TRAIT_BLIND "blind"
#define TRAIT_MUTE "mute"
@@ -257,6 +258,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define GLASSES_TRAIT "glasses"
#define VEHICLE_TRAIT "vehicle" // inherited from riding vehicles
#define INNATE_TRAIT "innate"
+#define CRIT_HEALTH_TRAIT "crit_health"
+#define OXYLOSS_TRAIT "oxyloss"
// unique trait sources, still defines
#define CLONING_POD_TRAIT "cloning-pod"
diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm
index a113fad7857..ffd0df158c6 100644
--- a/code/_onclick/cyborg.dm
+++ b/code/_onclick/cyborg.dm
@@ -14,7 +14,7 @@
if(check_click_intercept(params,A))
return
- if(stat || lockcharge || IsParalyzed() || IsStun() || IsUnconscious())
+ if(stat || lockcharge || IsParalyzed() || IsStun())
return
var/list/modifiers = params2list(params)
diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm
index c49a953a9d8..a7eb39505d1 100644
--- a/code/datums/diseases/advance/symptoms/heal.dm
+++ b/code/datums/diseases/advance/symptoms/heal.dm
@@ -267,20 +267,19 @@
var/mob/living/M = A.affected_mob
if(HAS_TRAIT(M, TRAIT_DEATHCOMA))
return power
- else if(M.IsUnconscious() || M.stat == UNCONSCIOUS)
+ if(M.IsSleeping())
+ return power * 0.25 //Voluntary unconsciousness yields lower healing.
+ if(M.stat == UNCONSCIOUS)
return power * 0.9
- else if(M.stat == SOFT_CRIT)
+ if(M.stat == SOFT_CRIT)
return power * 0.5
- else if(M.IsSleeping())
- return power * 0.25
- else if(M.getBruteLoss() + M.getFireLoss() >= 70 && !active_coma)
+ if(M.getBruteLoss() + M.getFireLoss() >= 70 && !active_coma)
to_chat(M, "You feel yourself slip into a regenerative coma...")
active_coma = TRUE
addtimer(CALLBACK(src, .proc/coma, M), 60)
/datum/symptom/heal/coma/proc/coma(mob/living/M)
M.fakedeath("regenerative_coma", !deathgasp)
- M.update_stat()
M.update_mobility()
addtimer(CALLBACK(src, .proc/uncoma, M), 300)
@@ -289,7 +288,6 @@
return
active_coma = FALSE
M.cure_fakedeath("regenerative_coma")
- M.update_stat()
M.update_mobility()
/datum/symptom/heal/coma/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power)
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index 3ed89d946bf..6ccf07e32b2 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -68,10 +68,10 @@
. = ..()
if(!.)
return
- ADD_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id))
+ ADD_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id))
/datum/status_effect/incapacitating/unconscious/on_remove()
- REMOVE_TRAIT(owner, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(id))
+ REMOVE_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id))
return ..()
/datum/status_effect/incapacitating/unconscious/tick()
@@ -99,6 +99,16 @@
human_owner = null
return ..()
+/datum/status_effect/incapacitating/sleeping/on_apply()
+ . = ..()
+ if(!.)
+ return
+ ADD_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id))
+
+/datum/status_effect/incapacitating/sleeping/on_remove()
+ REMOVE_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id))
+ return ..()
+
/datum/status_effect/incapacitating/sleeping/tick()
if(owner.maxHealth)
var/health_ratio = owner.health / owner.maxHealth
diff --git a/code/modules/antagonists/changeling/powers/fakedeath.dm b/code/modules/antagonists/changeling/powers/fakedeath.dm
index f4c1a1f23f2..63b59c6440e 100644
--- a/code/modules/antagonists/changeling/powers/fakedeath.dm
+++ b/code/modules/antagonists/changeling/powers/fakedeath.dm
@@ -24,7 +24,6 @@
else
to_chat(user, "We begin our stasis, preparing energy to arise once more.")
user.fakedeath("changeling") //play dead
- user.update_stat()
user.update_mobility()
addtimer(CALLBACK(src, .proc/ready_to_regenerate, user), LING_FAKEDEATH_TIME, TIMER_UNIQUE)
return TRUE
diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm
index e46b345e6ea..56cc502fa8a 100644
--- a/code/modules/clothing/head/misc_special.dm
+++ b/code/modules/clothing/head/misc_special.dm
@@ -355,7 +355,7 @@
if(target.get_item_by_slot(ITEM_SLOT_HEAD) != src)
return
QDEL_NULL(paranoia)
- if(!target.IsUnconscious())
+ if(target.stat < UNCONSCIOUS)
to_chat(target, "Your zealous conspirationism rapidly dissipates as the donned hat warps up into a ruined mess. All those theories starting to sound like nothing but a ridicolous fanfare.")
/obj/item/clothing/head/foilhat/attack_hand(mob/user)
diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm
index c5c8a8038a6..02a2b093d07 100644
--- a/code/modules/mob/living/carbon/alien/larva/larva.dm
+++ b/code/modules/mob/living/carbon/alien/larva/larva.dm
@@ -9,6 +9,7 @@
maxHealth = 25
health = 25
+ hardcrit_threshold = HEALTH_THRESHOLD_CRIT
var/amount_grown = 0
var/max_grown = 100
diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm
index e9d71604262..aada8030b9c 100644
--- a/code/modules/mob/living/carbon/alien/larva/life.dm
+++ b/code/modules/mob/living/carbon/alien/larva/life.dm
@@ -18,15 +18,12 @@
if(health<= -maxHealth || !getorgan(/obj/item/organ/brain))
death()
return
- if(IsUnconscious() || IsSleeping() || getOxyLoss() > 50 || (HAS_TRAIT(src, TRAIT_DEATHCOMA)) || health <= crit_threshold)
- if(stat == CONSCIOUS)
- set_stat(UNCONSCIOUS)
- become_blind(UNCONSCIOUS_BLIND)
- update_mobility()
+ if((HAS_TRAIT(src, TRAIT_KNOCKEDOUT)))
+ set_stat(UNCONSCIOUS)
else
if(stat == UNCONSCIOUS)
- set_stat(CONSCIOUS)
- cure_blind(UNCONSCIOUS_BLIND)
set_resting(FALSE)
+ set_stat(CONSCIOUS)
+ update_mobility()
update_damage_hud()
update_health_hud()
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index b1391dd34a0..df4e83d4ec4 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -514,7 +514,7 @@
total_brute += (BP.brute_dam * BP.body_damage_coeff)
total_burn += (BP.burn_dam * BP.body_damage_coeff)
total_stamina += (BP.stamina_dam * BP.stam_damage_coeff)
- health = round(maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute, DAMAGE_PRECISION)
+ set_health(round(maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute, DAMAGE_PRECISION))
staminaloss = round(total_stamina, DAMAGE_PRECISION)
update_stat()
update_mobility()
@@ -756,28 +756,37 @@
if(hud_used && hud_used.spacesuit)
hud_used.spacesuit.icon_state = "spacesuit_[cell_state]"
+
+/mob/living/carbon/set_health(new_value)
+ . = ..()
+ if(. > hardcrit_threshold)
+ if(health <= hardcrit_threshold && !HAS_TRAIT(src, TRAIT_NOHARDCRIT))
+ ADD_TRAIT(src, TRAIT_KNOCKEDOUT, CRIT_HEALTH_TRAIT)
+ else if(health > hardcrit_threshold)
+ REMOVE_TRAIT(src, TRAIT_KNOCKEDOUT, CRIT_HEALTH_TRAIT)
+ if(CONFIG_GET(flag/near_death_experience))
+ if(. > HEALTH_THRESHOLD_NEARDEATH)
+ if(health <= HEALTH_THRESHOLD_NEARDEATH && !HAS_TRAIT(src, TRAIT_NODEATH))
+ ADD_TRAIT(src, TRAIT_SIXTHSENSE, "near-death")
+ else if(health > HEALTH_THRESHOLD_NEARDEATH)
+ REMOVE_TRAIT(src, TRAIT_SIXTHSENSE, "near-death")
+
+
+
/mob/living/carbon/update_stat()
if(status_flags & GODMODE)
return
if(stat != DEAD)
if(health <= HEALTH_THRESHOLD_DEAD && !HAS_TRAIT(src, TRAIT_NODEATH))
death()
- cure_blind(UNCONSCIOUS_BLIND)
return
- if(IsUnconscious() || IsSleeping() || getOxyLoss() > 50 || (HAS_TRAIT(src, TRAIT_DEATHCOMA)) || (health <= HEALTH_THRESHOLD_FULLCRIT && !HAS_TRAIT(src, TRAIT_NOHARDCRIT)))
+ if(HAS_TRAIT(src, TRAIT_KNOCKEDOUT))
set_stat(UNCONSCIOUS)
- become_blind(UNCONSCIOUS_BLIND)
- if(CONFIG_GET(flag/near_death_experience) && health <= HEALTH_THRESHOLD_NEARDEATH && !HAS_TRAIT(src, TRAIT_NODEATH))
- ADD_TRAIT(src, TRAIT_SIXTHSENSE, "near-death")
- else
- REMOVE_TRAIT(src, TRAIT_SIXTHSENSE, "near-death")
else
if(health <= crit_threshold && !HAS_TRAIT(src, TRAIT_NOSOFTCRIT))
set_stat(SOFT_CRIT)
else
set_stat(CONSCIOUS)
- cure_blind(UNCONSCIOUS_BLIND)
- REMOVE_TRAIT(src, TRAIT_SIXTHSENSE, "near-death")
update_mobility()
update_damage_hud()
update_health_hud()
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 3915dbce699..a741720b9b1 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -431,3 +431,25 @@
var/obj/item/organ/ears/ears = getorganslot(ORGAN_SLOT_EARS)
if(istype(ears) && !ears.deaf)
. = TRUE
+
+
+/mob/living/carbon/adjustOxyLoss(amount, updating_health = TRUE, forced = FALSE)
+ . = ..()
+ if(isnull(.))
+ return
+ if(. <= 50)
+ if(getOxyLoss() > 50)
+ ADD_TRAIT(src, TRAIT_KNOCKEDOUT, OXYLOSS_TRAIT)
+ else if(getOxyLoss() <= 50)
+ REMOVE_TRAIT(src, TRAIT_KNOCKEDOUT, OXYLOSS_TRAIT)
+
+
+/mob/living/carbon/setOxyLoss(amount, updating_health = TRUE, forced = FALSE)
+ . = ..()
+ if(isnull(.))
+ return
+ if(. <= 50)
+ if(getOxyLoss() > 50)
+ ADD_TRAIT(src, TRAIT_KNOCKEDOUT, OXYLOSS_TRAIT)
+ else if(getOxyLoss() <= 50)
+ REMOVE_TRAIT(src, TRAIT_KNOCKEDOUT, OXYLOSS_TRAIT)
diff --git a/code/modules/mob/living/carbon/monkey/combat.dm b/code/modules/mob/living/carbon/monkey/combat.dm
index a43a514d468..3b0d946adae 100644
--- a/code/modules/mob/living/carbon/monkey/combat.dm
+++ b/code/modules/mob/living/carbon/monkey/combat.dm
@@ -54,8 +54,6 @@
return 1
if(health <= 0 && checkDead)
return 1
- if(IsUnconscious())
- return 1
if(IsStun() || IsParalyzed())
return 1
if(stat)
diff --git a/code/modules/mob/living/carbon/monkey/monkey_defense.dm b/code/modules/mob/living/carbon/monkey/monkey_defense.dm
index 2f92032dd8f..37e6c119e43 100644
--- a/code/modules/mob/living/carbon/monkey/monkey_defense.dm
+++ b/code/modules/mob/living/carbon/monkey/monkey_defense.dm
@@ -64,7 +64,7 @@
"You avoid [M]'s punch!", "You hear a swoosh!", COMBAT_MESSAGE_RANGE, M)
to_chat(M, "Your punch misses [name]!")
if("disarm")
- if(!IsUnconscious())
+ if(stat < UNCONSCIOUS)
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
if (prob(25))
Paralyze(40)
diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm
index 65d27edf672..c6720838a99 100644
--- a/code/modules/mob/living/damage_procs.dm
+++ b/code/modules/mob/living/damage_procs.dm
@@ -167,19 +167,21 @@
/mob/living/proc/adjustOxyLoss(amount, updating_health = TRUE, forced = FALSE)
if(!forced && (status_flags & GODMODE))
- return FALSE
+ return
+ . = oxyloss
oxyloss = clamp((oxyloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
if(updating_health)
updatehealth()
- return amount
+
/mob/living/proc/setOxyLoss(amount, updating_health = TRUE, forced = FALSE)
- if(status_flags & GODMODE)
- return 0
+ if(!forced && status_flags & GODMODE)
+ return
+ . = oxyloss
oxyloss = amount
if(updating_health)
updatehealth()
- return amount
+
/mob/living/proc/getToxLoss()
return toxloss
diff --git a/code/modules/mob/living/init_signals.dm b/code/modules/mob/living/init_signals.dm
new file mode 100644
index 00000000000..4b5cc7989f5
--- /dev/null
+++ b/code/modules/mob/living/init_signals.dm
@@ -0,0 +1,28 @@
+///Called on /mob/living/Initialize(), for the mob to register to relevant signals.
+/mob/living/proc/register_init_signals()
+ RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_KNOCKEDOUT), .proc/on_knockedout_trait_gain)
+ RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_KNOCKEDOUT), .proc/on_knockedout_trait_loss)
+
+ RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_DEATHCOMA), .proc/on_deathcoma_trait_gain)
+ RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_DEATHCOMA), .proc/on_deathcoma_trait_loss)
+
+
+///Called when TRAIT_KNOCKEDOUT is added to the mob.
+/mob/living/proc/on_knockedout_trait_gain(datum/source)
+ if(stat < UNCONSCIOUS)
+ set_stat(UNCONSCIOUS)
+
+///Called when TRAIT_KNOCKEDOUT is removed from the mob.
+/mob/living/proc/on_knockedout_trait_loss(datum/source)
+ if(stat < DEAD)
+ update_stat()
+
+
+///Called when TRAIT_DEATHCOMA is added to the mob.
+/mob/living/proc/on_deathcoma_trait_gain(datum/source)
+ ADD_TRAIT(src, TRAIT_KNOCKEDOUT, TRAIT_DEATHCOMA)
+
+///Called when TRAIT_DEATHCOMA is removed from the mob.
+/mob/living/proc/on_deathcoma_trait_loss(datum/source)
+ REMOVE_TRAIT(src, TRAIT_KNOCKEDOUT, TRAIT_DEATHCOMA)
+
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 0314418bef9..9b10fe0ee70 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -1,5 +1,6 @@
/mob/living/Initialize()
. = ..()
+ register_init_signals()
if(unique_name)
set_name()
var/datum/atom_hud/data/human/medical/advanced/medhud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
@@ -375,8 +376,6 @@
/mob/living/pointed(atom/A as mob|obj|turf in view(client.view, src))
if(incapacitated())
return FALSE
- if(HAS_TRAIT(src, TRAIT_DEATHCOMA))
- return FALSE
if(!..())
return FALSE
visible_message("[src] points at [A].", "You point at [A].")
@@ -480,10 +479,17 @@
/mob/living/is_drawable(mob/user, allowmobs = TRUE)
return (allowmobs && reagents && can_inject(user))
+
+///Sets the current mob's health value. Do not call directly if you don't know what you are doing, use the damage procs, instead.
+/mob/living/proc/set_health(new_value)
+ . = health
+ health = new_value
+
+
/mob/living/proc/updatehealth()
if(status_flags & GODMODE)
return
- health = maxHealth - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - getCloneLoss()
+ set_health(maxHealth - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - getCloneLoss())
staminaloss = getStaminaLoss()
update_stat()
med_hud_set_health()
@@ -895,7 +901,7 @@
if(c.clothing_flags & DANGEROUS_OBJECT)
who.visible_message("[src] tries to put [what] on [who].", \
"[src] tries to put [what] on you.", null, null, src)
- else
+ else
who.visible_message("[src] tries to put [what] on [who].", \
"[src] tries to put [what] on you.", null, null, src)
to_chat(src, "You try to put [what] on [who]...")
@@ -1168,7 +1174,6 @@
/mob/living/proc/update_mobility()
var/stat_softcrit = stat == SOFT_CRIT
var/stat_conscious = (stat == CONSCIOUS) || stat_softcrit
- var/conscious = !IsUnconscious() && stat_conscious && !HAS_TRAIT(src, TRAIT_DEATHCOMA)
var/chokehold = pulledby && pulledby.grab_state >= GRAB_NECK
var/restrained = restrained()
var/has_legs = get_num_legs()
@@ -1177,12 +1182,12 @@
var/stun = IsStun()
var/knockdown = IsKnockdown()
var/ignore_legs = get_leg_ignore()
- var/canmove = !IsImmobilized() && !stun && conscious && !paralyzed && !buckled && (!stat_softcrit || !pulledby) && !chokehold && !IsFrozen() && !IS_IN_STASIS(src) && (has_arms || ignore_legs || has_legs)
+ var/canmove = !IsImmobilized() && !stun && stat_conscious && !paralyzed && !buckled && (!stat_softcrit || !pulledby) && !chokehold && !IsFrozen() && !IS_IN_STASIS(src) && (has_arms || ignore_legs || has_legs)
if(canmove)
mobility_flags |= MOBILITY_MOVE
else
mobility_flags &= ~MOBILITY_MOVE
- var/canstand_involuntary = conscious && !stat_softcrit && !knockdown && !chokehold && !paralyzed && (ignore_legs || has_legs) && !(buckled && buckled.buckle_lying)
+ var/canstand_involuntary = stat_conscious && !stat_softcrit && !knockdown && !chokehold && !paralyzed && (ignore_legs || has_legs) && !(buckled && buckled.buckle_lying)
var/canstand = canstand_involuntary && !resting
if(buckled && buckled.buckle_lying != -1)
@@ -1208,7 +1213,7 @@
- var/canitem = !paralyzed && !stun && conscious && !chokehold && !restrained && has_arms
+ var/canitem = !paralyzed && !stun && stat_conscious && !chokehold && !restrained && has_arms
if(canitem)
mobility_flags |= (MOBILITY_USE | MOBILITY_PICKUP | MOBILITY_STORAGE)
else
@@ -1533,3 +1538,15 @@
/mob/living/proc/stop_look_up()
reset_perspective()
UnregisterSignal(src, COMSIG_MOVABLE_PRE_MOVE)
+
+
+/mob/living/set_stat(new_stat)
+ . = ..()
+ if(isnull(.))
+ return
+ switch(.) //Previous stat.
+ if(UNCONSCIOUS)
+ cure_blind(UNCONSCIOUS_BLIND)
+ switch(stat) //Current stat.
+ if(UNCONSCIOUS)
+ become_blind(UNCONSCIOUS_BLIND)
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index 242eeddc1af..2a8c6f8096a 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -23,6 +23,8 @@
var/cloneloss = 0 ///Damage caused by being cloned or ejected from the cloner early. slimes also deal cloneloss damage to victims
var/staminaloss = 0 ///Stamina damage, or exhaustion. You recover it slowly naturally, and are knocked down if it gets too high. Holodeck and hallucinations deal this.
var/crit_threshold = HEALTH_THRESHOLD_CRIT /// when the mob goes from "normal" to crit
+ ///When the mob enters hard critical state and is fully incapacitated.
+ var/hardcrit_threshold = HEALTH_THRESHOLD_FULLCRIT
var/mobility_flags = MOBILITY_FLAGS_DEFAULT
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index 7e12289d0aa..b084ba0a851 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -62,7 +62,7 @@
/mob/living/silicon/ai/updatehealth()
if(status_flags & GODMODE)
return
- health = maxHealth - getOxyLoss() - getToxLoss() - getBruteLoss() - getFireLoss()
+ set_health(maxHealth - getOxyLoss() - getToxLoss() - getBruteLoss() - getFireLoss())
update_stat()
diag_hud_set_health()
disconnect_shell()
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index 6c4c731e859..56e0a25fd02 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -281,7 +281,7 @@
/mob/living/silicon/pai/updatehealth()
if(status_flags & GODMODE)
return
- health = maxHealth - getBruteLoss() - getFireLoss()
+ set_health(maxHealth - getBruteLoss() - getFireLoss())
update_stat()
/mob/living/silicon/pai/process()
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index b94aff4e674..fa610aa5bcd 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -422,7 +422,7 @@
/mob/living/silicon/robot/update_icons()
cut_overlays()
icon_state = module.cyborg_base_icon
- if(stat != DEAD && !(IsUnconscious() || IsStun() || IsParalyzed() || low_power_mode)) //Not dead, not stunned.
+ if(stat != DEAD && !(HAS_TRAIT(src, TRAIT_KNOCKEDOUT) || IsStun() || IsParalyzed() || low_power_mode)) //Not dead, not stunned.
if(!eye_lights)
eye_lights = new()
if(lamp_intensity > 2)
@@ -771,18 +771,12 @@
if(health <= -maxHealth) //die only once
death()
return
- if(IsUnconscious() || IsStun() || IsKnockdown() || IsParalyzed() || getOxyLoss() > maxHealth*0.5)
- if(stat == CONSCIOUS)
- set_stat(UNCONSCIOUS)
- become_blind(UNCONSCIOUS_BLIND)
- update_mobility()
- update_headlamp()
+ if(HAS_TRAIT(src, TRAIT_KNOCKEDOUT) || IsStun() || IsKnockdown() || IsParalyzed())
+ set_stat(UNCONSCIOUS)
else
- if(stat == UNCONSCIOUS)
- set_stat(CONSCIOUS)
- cure_blind(UNCONSCIOUS_BLIND)
- update_mobility()
- update_headlamp()
+ set_stat(CONSCIOUS)
+ update_mobility()
+ update_headlamp()
diag_hud_set_status()
diag_hud_set_health()
diag_hud_set_aishell()
diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm
index 7124551f927..45407da2e2f 100644
--- a/code/modules/mob/living/silicon/robot/robot_defense.dm
+++ b/code/modules/mob/living/silicon/robot/robot_defense.dm
@@ -399,3 +399,25 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real
updatehealth()
if(prob(75) && Proj.damage > 0)
spark_system.start()
+
+
+/mob/living/silicon/robot/adjustOxyLoss(amount, updating_health = TRUE, forced = FALSE)
+ . = ..()
+ if(isnull(.))
+ return
+ if(. <= (maxHealth * 0.5))
+ if(getOxyLoss() > (maxHealth * 0.5))
+ ADD_TRAIT(src, TRAIT_KNOCKEDOUT, OXYLOSS_TRAIT)
+ else if(getOxyLoss() <= (maxHealth * 0.5))
+ REMOVE_TRAIT(src, TRAIT_KNOCKEDOUT, OXYLOSS_TRAIT)
+
+
+/mob/living/silicon/robot/setOxyLoss(amount, updating_health = TRUE, forced = FALSE)
+ . = ..()
+ if(isnull(.))
+ return
+ if(. <= (maxHealth * 0.5))
+ if(getOxyLoss() > (maxHealth * 0.5))
+ ADD_TRAIT(src, TRAIT_KNOCKEDOUT, OXYLOSS_TRAIT)
+ else if(getOxyLoss() <= (maxHealth * 0.5))
+ REMOVE_TRAIT(src, TRAIT_KNOCKEDOUT, OXYLOSS_TRAIT)
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 313b6738c53..4880727a2c7 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -197,9 +197,6 @@
if(stat == DEAD)
. += "Upon closer examination, [p_they()] appear[p_s()] to be dead."
-/mob/living/simple_animal/updatehealth()
- ..()
- health = clamp(health, 0, maxHealth)
/mob/living/simple_animal/update_stat()
if(status_flags & GODMODE)
@@ -515,7 +512,7 @@
..()
/mob/living/simple_animal/update_mobility(value_otherwise = TRUE)
- if(IsUnconscious() || IsParalyzed() || IsStun() || IsKnockdown() || IsParalyzed() || stat || resting)
+ if(HAS_TRAIT(src, TRAIT_KNOCKEDOUT) || IsParalyzed() || IsStun() || IsKnockdown() || IsParalyzed() || stat || resting)
drop_all_held_items()
mobility_flags = NONE
else if(buckled)
diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm
index a8087487e6d..27e0ed8fa79 100644
--- a/code/modules/mob/living/status_procs.dm
+++ b/code/modules/mob/living/status_procs.dm
@@ -445,7 +445,7 @@
REMOVE_TRAIT(src, TRAIT_DEATHCOMA, source)
if(stat != DEAD)
tod = null
- update_stat()
+
/mob/living/proc/fakedeath(source, silent = FALSE)
if(stat == DEAD)
@@ -455,7 +455,7 @@
ADD_TRAIT(src, TRAIT_FAKEDEATH, source)
ADD_TRAIT(src, TRAIT_DEATHCOMA, source)
tod = station_time_timestamp()
- update_stat()
+
///Unignores all slowdowns that lack the IGNORE_NOSLOW flag.
/mob/living/proc/unignore_slowdown(source)
diff --git a/code/modules/research/nanites/nanite_programs/protocols.dm b/code/modules/research/nanites/nanite_programs/protocols.dm
index 73976abe092..216a1349797 100644
--- a/code/modules/research/nanites/nanite_programs/protocols.dm
+++ b/code/modules/research/nanites/nanite_programs/protocols.dm
@@ -91,9 +91,7 @@
/datum/nanite_program/protocol/offline/check_conditions()
var/is_offline = FALSE
- if(nanites.host_mob.IsSleeping() || nanites.host_mob.IsUnconscious())
- is_offline = TRUE
- if(nanites.host_mob.stat == DEAD || HAS_TRAIT(nanites.host_mob, TRAIT_DEATHCOMA))
+ if(nanites.host_mob.stat >= UNCONSCIOUS) //DEAD or UNCONSCIOUS
is_offline = TRUE
if(nanites.host_mob.InCritical() && !HAS_TRAIT(nanites.host_mob, TRAIT_NOSOFTCRIT))
is_offline = TRUE
diff --git a/tgstation.dme b/tgstation.dme
index 1f5ec6ca3c2..b8b9109bb3f 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -2130,6 +2130,7 @@
#include "code\modules\mob\living\death.dm"
#include "code\modules\mob\living\emote.dm"
#include "code\modules\mob\living\inhand_holder.dm"
+#include "code\modules\mob\living\init_signals.dm"
#include "code\modules\mob\living\life.dm"
#include "code\modules\mob\living\living.dm"
#include "code\modules\mob\living\living_defense.dm"