From fd13f520a846ae0bb1d5dfc96700042f25618901 Mon Sep 17 00:00:00 2001
From: Tsar-Salat <62388554+Tsar-Salat@users.noreply.github.com>
Date: Sun, 28 Apr 2024 04:58:25 -0400
Subject: [PATCH] Mobility Atomization 7: Crit Status and Succumbing alert
(#10900)
* https://github.com/tgstation/tgstation/pull/53117
* https://github.com/tgstation/tgstation/pull/52892
* thanks ryll
* fix blindness
* fix broken succumb
---
code/__DEFINES/mobs.dm | 3 ++
code/__DEFINES/stat.dm | 3 +-
code/__DEFINES/traits.dm | 4 ++
code/_onclick/hud/alert.dm | 17 ++++++
code/datums/diseases/advance/symptoms/heal.dm | 9 ++--
code/datums/emotes.dm | 2 +-
code/game/data_huds.dm | 2 +-
code/game/gamemodes/game_mode.dm | 2 +-
code/game/machinery/computer/Operating.dm | 2 +-
code/game/machinery/computer/aifixer.dm | 2 +-
code/modules/admin/admin_more_info.dm | 4 +-
.../blob/blobstrains/zombifying_pods.dm | 2 +-
.../changeling/changeling_power.dm | 3 +-
.../changeling/powers/fleshmend.dm | 2 +-
.../antagonists/changeling/powers/panacea.dm | 2 +-
.../changeling/powers/regenerate.dm | 2 +-
code/modules/antagonists/cult/runes.dm | 2 +-
.../antagonists/heretic/heretic_antag.dm | 2 +-
.../heretic/magic/nightwatcher_rebirth.dm | 2 +-
.../holoparasite/holoparasite_team.dm | 2 +-
.../components/unary_devices/cryo.dm | 2 +-
code/modules/awaymissions/capture_the_flag.dm | 15 +++---
.../awaymissions/mission_code/TheFactory.dm | 6 +--
code/modules/client/verbs/suicide.dm | 2 +-
code/modules/client/verbs/who.dm | 2 +-
code/modules/events/heart_attack.dm | 12 +++--
code/modules/flufftext/Dreaming.dm | 2 +-
code/modules/holoparasite/_holoparasite.dm | 2 +-
.../holoparasite/holoparasite_damage.dm | 2 +-
.../holoparasite/holoparasite_holder.dm | 2 +-
.../carbon/alien/humanoid/update_icons.dm | 2 +-
code/modules/mob/living/carbon/carbon.dm | 13 ++---
.../mob/living/carbon/carbon_defense.dm | 4 +-
code/modules/mob/living/carbon/examine.dm | 9 ++--
.../mob/living/carbon/human/examine.dm | 13 ++---
.../mob/living/carbon/human/human_defense.dm | 2 +-
.../carbon/human/species_types/zombies.dm | 4 +-
code/modules/mob/living/init_signals.dm | 23 +++++++-
code/modules/mob/living/living.dm | 50 +++++++++++-------
code/modules/mob/living/say.dm | 42 +++++----------
code/modules/mob/living/silicon/ai/life.dm | 2 +-
.../mob/living/silicon/robot/examine.dm | 2 +-
.../mob/living/simple_animal/constructs.dm | 2 +-
.../simple_animal/hostile/bosses/boss.dm | 2 +-
.../simple_animal/hostile/cat_butcher.dm | 2 +-
.../living/simple_animal/hostile/faithless.dm | 2 +-
.../simple_animal/hostile/gorilla/gorilla.dm | 2 +-
.../mob/living/simple_animal/hostile/heart.dm | 2 +-
.../living/simple_animal/hostile/hostile.dm | 3 +-
.../simple_animal/hostile/jungle/leaper.dm | 2 +-
.../simple_animal/hostile/jungle/mook.dm | 2 +-
.../simple_animal/hostile/jungle/seedling.dm | 2 +-
.../simple_animal/hostile/megafauna/legion.dm | 12 +++--
.../hostile/megafauna/megafauna.dm | 2 +-
.../hostile/mining_mobs/basilisk.dm | 2 +-
.../hostile/mining_mobs/elites/elite.dm | 2 +-
.../hostile/mining_mobs/goliath.dm | 2 +-
.../hostile/mining_mobs/gutlunch.dm | 2 +-
.../hostile/mining_mobs/hivelord.dm | 22 +++++---
.../simple_animal/hostile/nanotrasen.dm | 2 +-
.../simple_animal/hostile/retaliate/clown.dm | 2 +-
.../hostile/retaliate/spaceman.dm | 2 +-
.../living/simple_animal/hostile/skeleton.dm | 2 +-
.../living/simple_animal/hostile/stickman.dm | 2 +-
.../living/simple_animal/hostile/syndicate.dm | 2 +-
.../living/simple_animal/hostile/zombie.dm | 2 +-
.../mob/living/simple_animal/slime/life.dm | 37 +++++++------
.../mob/living/simple_animal/slime/slime.dm | 11 ++--
code/modules/mob/mob.dm | 4 +-
code/modules/mob/status_procs.dm | 30 +++++++----
.../nanites/nanite_programs/sensor.dm | 15 +++---
code/modules/research/nanites/rules.dm | 4 +-
code/modules/surgery/bodyparts/bodyparts.dm | 2 +-
.../surgery/bodyparts/dismemberment.dm | 8 ---
code/modules/surgery/bodyparts/head.dm | 2 +-
code/modules/surgery/organs/augments_chest.dm | 33 ++++++------
icons/mob/screen_alert.dmi | Bin 122740 -> 123162 bytes
77 files changed, 290 insertions(+), 217 deletions(-)
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index 51d9cc95802f2..9d8e16b6d5e88 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -570,3 +570,6 @@ GLOBAL_LIST_INIT(available_random_trauma_list, list(
/// Messages when (something) lays an egg
#define EGG_LAYING_MESSAGES list("lays an egg.","squats down and croons.","begins making a huge racket.","begins clucking raucously.")
+
+/// Returns whether or not the given mob can succumb
+#define CAN_SUCCUMB(target) (HAS_TRAIT(target, TRAIT_CRITICAL_CONDITION) && !HAS_TRAIT(target, TRAIT_NODEATH))
diff --git a/code/__DEFINES/stat.dm b/code/__DEFINES/stat.dm
index 9c42e2a4dc873..889c183b21e92 100644
--- a/code/__DEFINES/stat.dm
+++ b/code/__DEFINES/stat.dm
@@ -6,7 +6,8 @@
#define CONSCIOUS 0
#define SOFT_CRIT 1
#define UNCONSCIOUS 2
-#define DEAD 3
+#define HARD_CRIT 3
+#define DEAD 4
//Maximum healthiness an individual can have
#define MAX_SATIETY 600
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index b0fe2d1f7c879..1f27dea77191d 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -143,6 +143,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_RESTRAINED "restrained"
*/
#define TRAIT_INCAPACITATED "incapacitated"
+//In some kind of critical condition. Is able to succumb.
+#define TRAIT_CRITICAL_CONDITION "critical-condition"
//mob traits
#define TRAIT_BLIND "blind"
@@ -385,6 +387,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define CHOKEHOLD_TRAIT "chokehold"
//trait associated to resting
#define RESTING_TRAIT "resting"
+//trait associated to a stat value or range of
+#define STAT_TRAIT "stat"
#define GLASSES_TRAIT "glasses"
#define CURSE_TRAIT "eldritch"
#define STATION_TRAIT "station-trait"
diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm
index 1bf046db6bafc..fe90cfb073746 100644
--- a/code/_onclick/hud/alert.dm
+++ b/code/_onclick/hud/alert.dm
@@ -328,6 +328,23 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
balloon_alert(owner, "You moved out of range of [offerer]!")
owner.clear_alert("[offerer]")
+/// Gives the player the option to succumb while in critical condition
+/atom/movable/screen/alert/succumb
+ name = "Succumb"
+ desc = "Shuffle off this mortal coil."
+ icon_state = "succumb"
+
+/atom/movable/screen/alert/succumb/Click()
+ if (isobserver(usr))
+ return
+ var/mob/living/living_owner = owner
+ var/last_whisper = tgui_input_text(usr, "Do you have any last words?", "Goodnight, Sweet Prince")
+ if (isnull(last_whisper) || !CAN_SUCCUMB(living_owner))
+ return
+ if (length(last_whisper))
+ living_owner.say("#[last_whisper]")
+ living_owner.succumb(whispered = length(last_whisper) > 0)
+
//ALIENS
/atom/movable/screen/alert/alien_tox
diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm
index 7ea3f13657656..d3081a124e5a9 100644
--- a/code/datums/diseases/advance/symptoms/heal.dm
+++ b/code/datums/diseases/advance/symptoms/heal.dm
@@ -123,10 +123,11 @@
return power
if(M.IsSleeping())
return power * 0.25 //Voluntary unconsciousness yields lower healing.
- if(M.stat == UNCONSCIOUS)
- return power * 0.9
- if(M.stat == SOFT_CRIT)
- return power * 0.5
+ switch(M.stat)
+ if(UNCONSCIOUS, HARD_CRIT)
+ return power * 0.9
+ if(SOFT_CRIT)
+ return power * 0.5
if(M.getBruteLoss() + M.getFireLoss() >= 70 && !active_coma)
if(M.stat != DEAD)
to_chat(M, "You feel yourself slip into a deep, regenerative slumber.")
diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm
index c9bca7be5b732..0c53aea611c97 100644
--- a/code/datums/emotes.dm
+++ b/code/datums/emotes.dm
@@ -161,7 +161,7 @@
switch(user.stat)
if(SOFT_CRIT)
to_chat(user, "You cannot [key] while in a critical condition.")
- if(UNCONSCIOUS)
+ if(UNCONSCIOUS, HARD_CRIT)
to_chat(user, "You cannot [key] while unconscious.")
if(DEAD)
to_chat(user, "You cannot [key] while dead.")
diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm
index ec1e01760f10b..6247c56e05f28 100644
--- a/code/game/data_huds.dm
+++ b/code/game/data_huds.dm
@@ -355,7 +355,7 @@
switch(stat)
if(CONSCIOUS)
holder.icon_state = "hudstat"
- if(UNCONSCIOUS)
+ if(UNCONSCIOUS, HARD_CRIT)
holder.icon_state = "hudoffline"
else
holder.icon_state = "huddead2"
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 4e1fbb3eb4f60..dcf555e3bb7a8 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -714,7 +714,7 @@
if(L.suiciding) //Suicider
msg += "[L.name] ([L.key]), the [L.job] (Suicide)\n"
failed = TRUE //Disconnected client
- if(!failed && L.stat == UNCONSCIOUS)
+ if(!failed && (L.stat == UNCONSCIOUS || L.stat == HARD_CRIT))
msg += "[L.name] ([L.key]), the [L.job] (Dying)\n"
failed = TRUE //Unconscious
if(!failed && L.stat == DEAD)
diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm
index bc00f8f9d6e47..2cb0c5c1c178c 100644
--- a/code/game/machinery/computer/Operating.dm
+++ b/code/game/machinery/computer/Operating.dm
@@ -121,7 +121,7 @@
if(SOFT_CRIT)
data["patient"]["stat"] = "Conscious"
data["patient"]["statstate"] = "average"
- if(UNCONSCIOUS)
+ if(UNCONSCIOUS, HARD_CRIT)
data["patient"]["stat"] = "Unconscious"
data["patient"]["statstate"] = "average"
if(DEAD)
diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm
index 6ae9cc445868e..40275522c39c4 100644
--- a/code/game/machinery/computer/aifixer.dm
+++ b/code/game/machinery/computer/aifixer.dm
@@ -103,7 +103,7 @@
switch (occupier.stat)
if (CONSCIOUS)
add_overlay("ai-fixer-full")
- if (UNCONSCIOUS)
+ if (UNCONSCIOUS, HARD_CRIT)
add_overlay("ai-fixer-404")
else
add_overlay("ai-fixer-empty")
diff --git a/code/modules/admin/admin_more_info.dm b/code/modules/admin/admin_more_info.dm
index 2bbc33639bad2..dae31031eaaaa 100644
--- a/code/modules/admin/admin_more_info.dm
+++ b/code/modules/admin/admin_more_info.dm
@@ -32,7 +32,9 @@
if(SOFT_CRIT)
status = "Dying"
if(UNCONSCIOUS)
- status = "[L.InCritical() ? "Unconscious and Dying" : "Unconscious"]"
+ status = "Unconscious"
+ if(HARD_CRIT)
+ status = "Unconscious and Dying"
if(DEAD)
status = "Dead"
health_description = "Status = [status]"
diff --git a/code/modules/antagonists/blob/blobstrains/zombifying_pods.dm b/code/modules/antagonists/blob/blobstrains/zombifying_pods.dm
index 41a28d5204e14..66625f40fbdaf 100644
--- a/code/modules/antagonists/blob/blobstrains/zombifying_pods.dm
+++ b/code/modules/antagonists/blob/blobstrains/zombifying_pods.dm
@@ -35,7 +35,7 @@
/datum/reagent/blob/zombifying_pods/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
reac_volume = ..()
M.apply_damage(0.6*reac_volume, TOX)
- if(O && ishuman(M) && M.stat == UNCONSCIOUS)
+ if(O && ishuman(M) && (M.stat == UNCONSCIOUS || M.stat == HARD_CRIT))
M.investigate_log("has been killed by distributed neurons (blob).", INVESTIGATE_DEATHS)
M.death() //sleeping in a fight? bad plan.
var/points = rand(5, 10)
diff --git a/code/modules/antagonists/changeling/changeling_power.dm b/code/modules/antagonists/changeling/changeling_power.dm
index 4cdf3e9c94aa8..0575741d4fe6d 100644
--- a/code/modules/antagonists/changeling/changeling_power.dm
+++ b/code/modules/antagonists/changeling/changeling_power.dm
@@ -13,7 +13,8 @@
var/req_dna = 0 //amount of dna needed to use this ability. Changelings always have atleast 1
var/req_human = 0 //if you need to be human to use this ability
var/req_absorbs = 0 //similar to req_dna, but only gained from absorbing, not DNA sting
- var/req_stat = CONSCIOUS // CONSCIOUS, UNCONSCIOUS or DEAD
+ ///Maximum stat before the ability is blocked. For example, `UNCONSCIOUS` prevents it from being used when in hard crit or dead, while `DEAD` allows the ability to be used on any stat values.
+ var/req_stat = CONSCIOUS
var/ignores_fakedeath = FALSE // usable with the FAKEDEATH flag
var/active = FALSE//used by a few powers that toggle
diff --git a/code/modules/antagonists/changeling/powers/fleshmend.dm b/code/modules/antagonists/changeling/powers/fleshmend.dm
index ebb46704f096c..29563833a1607 100644
--- a/code/modules/antagonists/changeling/powers/fleshmend.dm
+++ b/code/modules/antagonists/changeling/powers/fleshmend.dm
@@ -5,7 +5,7 @@
button_icon_state = "fleshmend"
chemical_cost = 25
dna_cost = 2
- req_stat = UNCONSCIOUS
+ req_stat = HARD_CRIT
//Starts healing you every second for 10 seconds.
//Can be used whilst unconscious.
diff --git a/code/modules/antagonists/changeling/powers/panacea.dm b/code/modules/antagonists/changeling/powers/panacea.dm
index 4b91eaff2cf3d..182570df096dd 100644
--- a/code/modules/antagonists/changeling/powers/panacea.dm
+++ b/code/modules/antagonists/changeling/powers/panacea.dm
@@ -5,7 +5,7 @@
button_icon_state = "panacea"
chemical_cost = 20
dna_cost = 1
- req_stat = UNCONSCIOUS
+ req_stat = HARD_CRIT
//Heals the things that the other regenerative abilities don't.
/datum/action/changeling/panacea/sting_action(mob/user)
diff --git a/code/modules/antagonists/changeling/powers/regenerate.dm b/code/modules/antagonists/changeling/powers/regenerate.dm
index 483751c0e792d..787e04af944b6 100644
--- a/code/modules/antagonists/changeling/powers/regenerate.dm
+++ b/code/modules/antagonists/changeling/powers/regenerate.dm
@@ -5,7 +5,7 @@
button_icon_state = "regenerate"
chemical_cost = 10
dna_cost = 1
- req_stat = UNCONSCIOUS
+ req_stat = HARD_CRIT
/datum/action/changeling/regenerate/sting_action(mob/living/user)
..()
diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm
index f97c938e930fc..fe1df7332da53 100644
--- a/code/modules/antagonists/cult/runes.dm
+++ b/code/modules/antagonists/cult/runes.dm
@@ -930,7 +930,7 @@ structure_check() searches for nearby cultist structures required for the invoca
to_chat(new_human, "You are a servant of the Geometer. You have been made semi-corporeal by the cult of Nar'Sie, and you are to serve them at all costs.")
while(!QDELETED(src) && !QDELETED(user) && !QDELETED(new_human) && (user in T))
- if(user.stat || new_human.InCritical())
+ if(user.stat != CONSCIOUS || HAS_TRAIT(new_human, TRAIT_CRITICAL_CONDITION))
break
user.apply_damage(0.1, BRUTE)
sleep(1)
diff --git a/code/modules/antagonists/heretic/heretic_antag.dm b/code/modules/antagonists/heretic/heretic_antag.dm
index 333f86952315c..65e1aa44d4c56 100644
--- a/code/modules/antagonists/heretic/heretic_antag.dm
+++ b/code/modules/antagonists/heretic/heretic_antag.dm
@@ -404,7 +404,7 @@
continue
if(possible_target in target_blacklist)
continue
- if(player.stat == DEAD || player.InFullCritical())
+ if(player.stat >= HARD_CRIT) //Hardcrit or worse (like being dead lmao)
continue
. += possible_target
diff --git a/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm b/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm
index 5a3ea9317ee01..313c32721aa97 100644
--- a/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm
+++ b/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm
@@ -24,7 +24,7 @@
if(!target.mind || !target.client || target.stat == DEAD || !target.on_fire || IS_HERETIC_OR_MONSTER(target))
continue
//This is essentially a death mark, use this to finish your opponent quicker.
- if(target.InCritical() && !HAS_TRAIT(target, TRAIT_NODEATH))
+ if(HAS_TRAIT(target, TRAIT_CRITICAL_CONDITION) && !HAS_TRAIT(target, TRAIT_NODEATH))
target.investigate_log("has been killed by fiery rebirth.", INVESTIGATE_DEATHS)
target.death()
diff --git a/code/modules/antagonists/holoparasite/holoparasite_team.dm b/code/modules/antagonists/holoparasite/holoparasite_team.dm
index b54dafd77aab5..2f049cee9f068 100644
--- a/code/modules/antagonists/holoparasite/holoparasite_team.dm
+++ b/code/modules/antagonists/holoparasite/holoparasite_team.dm
@@ -80,7 +80,7 @@
info["escaped"] = holder.owner.force_escaped || summoner_turf.onCentCom() || summoner_turf.onSyndieBase()
if(summoner.stat != DEAD)
info["stat"] = "alive"
- info["crit"] = summoner.InCritical()
+ info["crit"] = HAS_TRAIT(summoner, TRAIT_CRITICAL_CONDITION)
SSblackbox.record_feedback("associative", "holoparasite_user_roundend_stat", 1, info)
SSblackbox.record_feedback("tally", "holoparasites_per_summoner", 1, length(members))
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
index d5b08e4659ba3..5c20e4d4fe45a 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
@@ -374,7 +374,7 @@
if(SOFT_CRIT)
data["occupant"]["stat"] = "Conscious"
data["occupant"]["statstate"] = "average"
- if(UNCONSCIOUS)
+ if(UNCONSCIOUS, HARD_CRIT)
data["occupant"]["stat"] = "Unconscious"
data["occupant"]["statstate"] = "average"
if(DEAD)
diff --git a/code/modules/awaymissions/capture_the_flag.dm b/code/modules/awaymissions/capture_the_flag.dm
index 31581bd2fed07..2faed8d4b7e34 100644
--- a/code/modules/awaymissions/capture_the_flag.dm
+++ b/code/modules/awaymissions/capture_the_flag.dm
@@ -216,18 +216,19 @@
AddElement(/datum/element/point_of_interest)
/obj/machinery/capture_the_flag/process(delta_time)
- for(var/mob/living/M as() in spawned_mobs)
- if(QDELETED(M))
- spawned_mobs -= M
+ for(var/mob/living/living_participant as anything in spawned_mobs)
+ if(QDELETED(living_participant))
+ spawned_mobs -= living_participant
continue
// Anyone in crit, automatically reap
- if(M.InCritical() || M.stat == DEAD)
- ctf_dust_old(M)
+
+ if(HAS_TRAIT(living_participant, TRAIT_CRITICAL_CONDITION) || living_participant.stat == DEAD)
+ ctf_dust_old(living_participant)
else
// The changes that you've been hit with no shield but not
// instantly critted are low, but have some healing.
- M.adjustBruteLoss(-2.5 * delta_time)
- M.adjustFireLoss(-2.5 * delta_time)
+ living_participant.adjustBruteLoss(-2.5 * delta_time)
+ living_participant.adjustFireLoss(-2.5 * delta_time)
/obj/machinery/capture_the_flag/red
name = "Red CTF Controller"
diff --git a/code/modules/awaymissions/mission_code/TheFactory.dm b/code/modules/awaymissions/mission_code/TheFactory.dm
index c1bcc91e721fe..e9d250f822b1f 100644
--- a/code/modules/awaymissions/mission_code/TheFactory.dm
+++ b/code/modules/awaymissions/mission_code/TheFactory.dm
@@ -247,7 +247,7 @@
maxHealth = 100
health = 100
melee_damage = 12
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
faction = list("nanotrasenprivate")
status_flags = CANPUSH
atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0)
@@ -415,7 +415,7 @@
environment_smash = ENVIRONMENT_SMASH_NONE
obj_damage = 5
sidestep_per_cycle = 0
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
melee_damage = 15
lose_patience_timeout = 350
loot = list(/obj/effect/mob_spawn/human/corpse/psychost)
@@ -634,7 +634,7 @@
melee_damage = null
attack_sound = null
del_on_death = TRUE
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
a_intent = INTENT_HARM
var/det_time = 30
var/active = 0
diff --git a/code/modules/client/verbs/suicide.dm b/code/modules/client/verbs/suicide.dm
index 93e95ab50e35a..608e350ce5b4a 100644
--- a/code/modules/client/verbs/suicide.dm
+++ b/code/modules/client/verbs/suicide.dm
@@ -261,7 +261,7 @@
return TRUE
if(SOFT_CRIT)
to_chat(src, "You can't commit suicide while in a critical condition!")
- if(UNCONSCIOUS)
+ if(UNCONSCIOUS, HARD_CRIT)
to_chat(src, "You need to be conscious to commit suicide!")
if(DEAD)
to_chat(src, "You're already dead!")
diff --git a/code/modules/client/verbs/who.dm b/code/modules/client/verbs/who.dm
index e06e58bbae91c..31d19f3675415 100644
--- a/code/modules/client/verbs/who.dm
+++ b/code/modules/client/verbs/who.dm
@@ -20,7 +20,7 @@
else
entry += " - Playing as [C.mob.real_name]"
switch(C.mob.stat)
- if(UNCONSCIOUS)
+ if(UNCONSCIOUS, HARD_CRIT)
entry += " - Unconscious"
if(DEAD)
if(isobserver(C.mob))
diff --git a/code/modules/events/heart_attack.dm b/code/modules/events/heart_attack.dm
index b12a30a257da9..8a92930af552c 100644
--- a/code/modules/events/heart_attack.dm
+++ b/code/modules/events/heart_attack.dm
@@ -7,13 +7,15 @@
/datum/round_event/heart_attack/start()
var/list/heart_attack_contestants = list()
- for(var/mob/living/carbon/human/H in shuffle(GLOB.player_list))
- if(!H.client || H.stat == DEAD || H.InCritical() || !H.can_heartattack() || H.has_status_effect(STATUS_EFFECT_EXERCISED) || (/datum/disease/heart_failure in H.diseases) || H.undergoing_cardiac_arrest())
+ for(var/mob/living/carbon/human/victim in shuffle(GLOB.player_list))
+ if(victim.stat == DEAD || HAS_TRAIT(victim, TRAIT_CRITICAL_CONDITION) || !victim.can_heartattack() || victim.has_status_effect(STATUS_EFFECT_EXERCISED) || (/datum/disease/heart_failure in victim.diseases) || victim.undergoing_cardiac_arrest())
continue
- if(H.satiety <= -60) //Multiple junk food items recently
- heart_attack_contestants[H] = 3
+ if(!SSjob.GetJob(victim.mind.assigned_role) || (victim.mind.assigned_role in GLOB.nonhuman_positions))//only crewmembers can get one, a bit unfair for some ghost roles and it wastes the event
+ continue
+ if(victim.satiety <= -60) //Multiple junk food items recently
+ heart_attack_contestants[victim] = 3
else
- heart_attack_contestants[H] = 1
+ heart_attack_contestants[victim] = 1
if(LAZYLEN(heart_attack_contestants))
var/mob/living/carbon/human/winner = pick_weight(heart_attack_contestants)
diff --git a/code/modules/flufftext/Dreaming.dm b/code/modules/flufftext/Dreaming.dm
index 43f1234dc833e..aac348eb79233 100644
--- a/code/modules/flufftext/Dreaming.dm
+++ b/code/modules/flufftext/Dreaming.dm
@@ -57,7 +57,7 @@
dream_sequence(dream_fragments)
/mob/living/carbon/proc/dream_sequence(list/dream_fragments)
- if(stat != UNCONSCIOUS || InCritical())
+ if(stat != UNCONSCIOUS || HAS_TRAIT(src, TRAIT_CRITICAL_CONDITION))
dreaming = FALSE
return
var/next_message = dream_fragments[1]
diff --git a/code/modules/holoparasite/_holoparasite.dm b/code/modules/holoparasite/_holoparasite.dm
index 56c565aaaa0f2..99fdb77fbe344 100644
--- a/code/modules/holoparasite/_holoparasite.dm
+++ b/code/modules/holoparasite/_holoparasite.dm
@@ -187,7 +187,7 @@ GLOBAL_LIST_EMPTY_TYPED(holoparasites, /mob/living/simple_animal/hostile/holopar
else
health_percent = round((current.health / current.maxHealth) * 100, 0.5)
var/stat_text = "[health_percent]%"
- if(current.InCritical())
+ if(HAS_TRAIT(current, TRAIT_CRITICAL_CONDITION))
stat_text += " (!! CRITICAL !!)"
.["Summoner Health"] = GENERATE_STAT_TEXT(stat_text)
if(!COOLDOWN_FINISHED(src, manifest_cooldown))
diff --git a/code/modules/holoparasite/holoparasite_damage.dm b/code/modules/holoparasite/holoparasite_damage.dm
index f23b52f8e305a..4b273f893617a 100644
--- a/code/modules/holoparasite/holoparasite_damage.dm
+++ b/code/modules/holoparasite/holoparasite_damage.dm
@@ -85,7 +85,7 @@
*/
/mob/living/simple_animal/hostile/holoparasite/proc/extra_host_damage(amount)
// NOTE: checking unconscious and not sleeping here is intentional! ~Lucy
- if(!summoner.current || !(summoner.current.IsUnconscious() || summoner.current.InCritical()))
+ if(!summoner.current || !(summoner.current.IsUnconscious() || HAS_TRAIT(summoner.current, TRAIT_CRITICAL_CONDITION)))
return
// No brain? Ah whatever, just deal clone damage.
var/obj/item/organ/brain/brain = summoner.current.getorganslot(ORGAN_SLOT_BRAIN)
diff --git a/code/modules/holoparasite/holoparasite_holder.dm b/code/modules/holoparasite/holoparasite_holder.dm
index 34557a3455cf0..8b21df445d6c7 100644
--- a/code/modules/holoparasite/holoparasite_holder.dm
+++ b/code/modules/holoparasite/holoparasite_holder.dm
@@ -186,7 +186,7 @@
* * new_body: The slimeperson's new body.
*/
/datum/holoparasite_holder/proc/handle_slime_cheese(mob/living/carbon/human/old_body, mob/living/carbon/human/new_body)
- if(!isslimeperson(old_body) || !isslimeperson(new_body) || (old_body.stat != DEAD && !old_body.InCritical()))
+ if(!isslimeperson(old_body) || !isslimeperson(new_body) || (old_body.stat != DEAD && !HAS_TRAIT(old_body, TRAIT_CRITICAL_CONDITION)))
return
var/datum/species/oozeling/slime/old_slime = old_body.dna.species
var/datum/species/oozeling/slime/new_slime = new_body.dna.species
diff --git a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm
index 5b4376a70e890..b21d8a356b2c1 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm
@@ -12,7 +12,7 @@
else
icon_state = "alien[caste]_dead"
- else if((stat == UNCONSCIOUS && !asleep) || stat == SOFT_CRIT || IsParalyzed())
+ else if((stat == UNCONSCIOUS && !asleep) || stat == HARD_CRIT || stat == SOFT_CRIT || IsParalyzed())
icon_state = "alien[caste]_unconscious"
else if(leap_on_click)
icon_state = "alien[caste]_pounce"
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index ae840004a3c39..3a5104e107302 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -639,7 +639,7 @@
severity = 9
if(-INFINITY to -95)
severity = 10
- if(!InFullCritical())
+ if(stat != HARD_CRIT)
var/visionseverity = 4
switch(health)
if(-8 to -4)
@@ -755,13 +755,14 @@
if(health <= HEALTH_THRESHOLD_DEAD && !HAS_TRAIT(src, TRAIT_NODEATH))
death()
return
- if(HAS_TRAIT(src, TRAIT_KNOCKEDOUT))
+ if(health <= hardcrit_threshold && !HAS_TRAIT(src, TRAIT_NOHARDCRIT))
+ set_stat(HARD_CRIT)
+ else if(HAS_TRAIT(src, TRAIT_KNOCKEDOUT))
set_stat(UNCONSCIOUS)
+ else if(health <= crit_threshold && !HAS_TRAIT(src, TRAIT_NOSOFTCRIT))
+ set_stat(SOFT_CRIT)
else
- if(health <= crit_threshold && !HAS_TRAIT(src, TRAIT_NOSOFTCRIT))
- set_stat(SOFT_CRIT)
- else
- set_stat(CONSCIOUS)
+ set_stat(CONSCIOUS)
if(!is_blind())
var/datum/component/blind_sense/B = GetComponent(/datum/component/blind_sense)
B?.RemoveComponent()
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 8eca2fef03ea3..24adf825d4053 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -323,11 +323,11 @@
AdjustImmobilized(-60)
set_resting(FALSE)
- playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
+ playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, TRUE, -1)
/// Check ourselves to see if we've got any shrapnel, return true if we do. This is a much simpler version of what humans do, we only indicate we're checking ourselves if there's actually shrapnel
/mob/living/carbon/proc/check_self_for_injuries()
- if(stat == DEAD || stat == UNCONSCIOUS)
+ if(stat >= UNCONSCIOUS)
return
var/embeds = FALSE
diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm
index 8f1bde077b50f..6d1d236fa8e86 100644
--- a/code/modules/mob/living/carbon/examine.dm
+++ b/code/modules/mob/living/carbon/examine.dm
@@ -107,10 +107,11 @@
. += msg.Join("")
if(!appears_dead)
- if(stat == UNCONSCIOUS)
- . += "[t_He] [t_is]n't responding to anything around [t_him] and seems to be asleep."
- else if(InCritical())
- . += "[t_His] breathing is shallow and labored."
+ switch(stat)
+ if(SOFT_CRIT)
+ . += "[t_His] breathing is shallow and labored."
+ if(UNCONSCIOUS, HARD_CRIT)
+ . += "[t_He] [t_is]n't responding to anything around [t_him] and seems to be asleep."
var/trait_exam = common_trait_examine()
if(!isnull(trait_exam))
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index eb0afc831d983..aef1d2d2a2764 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -302,13 +302,14 @@
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "religious_comfort", /datum/mood_event/religiously_comforted)
if(!appears_dead)
- if(stat == UNCONSCIOUS)
- msg += "[t_He] [t_is]n't responding to anything around [t_him] and seem[p_s()] to be asleep.\n"
- else
- if(HAS_TRAIT(src, TRAIT_DUMB))
- msg += "[t_He] [t_has] a stupid expression on [t_his] face.\n"
- if(InCritical())
+ switch(stat)
+ if(UNCONSCIOUS, HARD_CRIT)
+ msg += "[t_He] [t_is]n't responding to anything around [t_him] and seem[p_s()] to be asleep.\n"
+ if(SOFT_CRIT)
msg += "[t_He] [t_is] barely conscious.\n"
+ if(CONSCIOUS)
+ if(HAS_TRAIT(src, TRAIT_DUMB))
+ msg += "[t_He] [t_has] a stupid expression on [t_his] face.\n"
if(getorgan(/obj/item/organ/brain))
if(ai_controller?.ai_status == AI_STATUS_ON)
msg += "[t_He] do[t_es]n't appear to be [t_him]self.\n"
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index ac50c774a2d12..9c0a3ac3f1c3d 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -701,7 +701,7 @@
..()
/mob/living/carbon/human/check_self_for_injuries()
- if(stat == DEAD || stat == UNCONSCIOUS)
+ if(stat >= UNCONSCIOUS)
return
visible_message("[src] examines [p_them()]self.", \
diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm
index 52e0b37c4cc8c..915675b096a9b 100644
--- a/code/modules/mob/living/carbon/human/species_types/zombies.dm
+++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm
@@ -71,12 +71,12 @@
//They must be restrained, beheaded or gibbed to stop being a threat.
if(regen_cooldown < world.time)
var/heal_amt = heal_rate
- if(C.InCritical())
+ if(HAS_TRAIT(C, TRAIT_CRITICAL_CONDITION))
heal_amt *= 2
C.heal_overall_damage(heal_amt,heal_amt)
C.adjustToxLoss(-heal_amt)
C.adjustOrganLoss(ORGAN_SLOT_BRAIN, -heal_amt)
- if(!C.InCritical() && prob(4))
+ if(!HAS_TRAIT(C, TRAIT_CRITICAL_CONDITION) && prob(4))
playsound(C, pick(spooks), 50, TRUE, 10)
//Congrats you somehow died so hard you stopped being a zombie
diff --git a/code/modules/mob/living/init_signals.dm b/code/modules/mob/living/init_signals.dm
index 0d4013b78790e..b8a13c7e8eb9f 100644
--- a/code/modules/mob/living/init_signals.dm
+++ b/code/modules/mob/living/init_signals.dm
@@ -6,22 +6,43 @@
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_DEATHCOMA), PROC_REF(on_deathcoma_trait_gain))
RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_DEATHCOMA), PROC_REF(on_deathcoma_trait_loss))
+ RegisterSignals(src, list(
+ SIGNAL_ADDTRAIT(TRAIT_CRITICAL_CONDITION),
+ SIGNAL_REMOVETRAIT(TRAIT_CRITICAL_CONDITION),
+
+ SIGNAL_ADDTRAIT(TRAIT_NODEATH),
+ SIGNAL_REMOVETRAIT(TRAIT_NODEATH),
+ ), PROC_REF(update_succumb_action))
+
///Called when TRAIT_KNOCKEDOUT is added to the mob.
/mob/living/proc/on_knockedout_trait_gain(datum/source)
+ SIGNAL_HANDLER
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)
+ SIGNAL_HANDLER
+ if(stat <= UNCONSCIOUS)
update_stat()
///Called when TRAIT_DEATHCOMA is added to the mob.
/mob/living/proc/on_deathcoma_trait_gain(datum/source)
+ SIGNAL_HANDLER
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)
+ SIGNAL_HANDLER
REMOVE_TRAIT(src, TRAIT_KNOCKEDOUT, TRAIT_DEATHCOMA)
+
+/// Called when traits that alter succumbing are added/removed.
+/// Will show or hide the succumb alert prompt.
+/mob/living/proc/update_succumb_action()
+ SIGNAL_HANDLER
+ if (CAN_SUCCUMB(src))
+ throw_alert("succumb", /atom/movable/screen/alert/succumb)
+ else
+ clear_alert("succumb")
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 33ba095df18d7..b9f78997e3810 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -413,20 +413,23 @@
visible_message("[src] points at [A].", "You point at [A].")
return TRUE
+
/mob/living/verb/succumb(whispered as null)
set hidden = TRUE
- if (InCritical())
- log_message("Has [whispered ? "whispered his final words" : "succumbed to death"] while in [InFullCritical() ? "hard":"soft"] critical with [round(health, 0.1)] points of health!", LOG_ATTACK)
- adjustOxyLoss(health - HEALTH_THRESHOLD_DEAD)
- updatehealth()
- if(!whispered)
- to_chat(src, "You have given up life and succumbed to death.")
+ if (!CAN_SUCCUMB(src))
+ return
+
+ log_message("Has [whispered ? "whispered his final words" : "succumbed to death"] with [round(health, 0.1)] points of health!", LOG_ATTACK)
+ adjustOxyLoss(health - HEALTH_THRESHOLD_DEAD)
+ updatehealth()
+ if(!whispered)
+ to_chat(src, "You have given up life and succumbed to death.")
- if (src.client)
- client.give_award(/datum/award/achievement/misc/succumb, client.mob)
+ if (src.client)
+ client.give_award(/datum/award/achievement/misc/succumb, client.mob)
- investigate_log("has succumbed to death.", INVESTIGATE_DEATHS)
- death()
+ investigate_log("has succumbed to death.", INVESTIGATE_DEATHS)
+ death()
/mob/living/incapacitated(ignore_restraints = FALSE, ignore_grab = FALSE, ignore_stasis = FALSE)
if(stat || HAS_TRAIT(src, TRAIT_INCAPACITATED) || (!ignore_restraints && restrained(ignore_grab)) || (!ignore_stasis && IS_IN_STASIS(src)))
@@ -437,12 +440,6 @@
return FALSE
return TRUE
-/mob/living/proc/InCritical()
- return (health <= crit_threshold && (stat == SOFT_CRIT || stat == UNCONSCIOUS))
-
-/mob/living/proc/InFullCritical()
- return (health <= HEALTH_THRESHOLD_FULLCRIT && stat == UNCONSCIOUS)
-
//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(pressure)
@@ -1330,19 +1327,36 @@
if(pulledby)
REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, PULLED_WHILE_SOFTCRIT_TRAIT)
if(UNCONSCIOUS)
- cure_blind(UNCONSCIOUS_TRAIT)
+ if(stat != HARD_CRIT)
+ cure_blind(UNCONSCIOUS_TRAIT)
+ if(HARD_CRIT)
+ if(stat != UNCONSCIOUS)
+ cure_blind(UNCONSCIOUS_TRAIT)
switch(stat) //Current stat.
if(CONSCIOUS)
if(. >= UNCONSCIOUS)
REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT)
REMOVE_TRAIT(src, TRAIT_FLOORED, UNCONSCIOUS_TRAIT)
+ REMOVE_TRAIT(src, TRAIT_CRITICAL_CONDITION, STAT_TRAIT)
if(SOFT_CRIT)
if(pulledby)
ADD_TRAIT(src, TRAIT_IMMOBILIZED, PULLED_WHILE_SOFTCRIT_TRAIT) //adding trait sources should come before removing to avoid unnecessary updates
if(. >= UNCONSCIOUS)
REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT)
+ ADD_TRAIT(src, TRAIT_CRITICAL_CONDITION, STAT_TRAIT)
if(UNCONSCIOUS)
- become_blind(UNCONSCIOUS_TRAIT)
+ if(. != HARD_CRIT)
+ become_blind(UNCONSCIOUS_TRAIT)
+ if(health <= crit_threshold && !HAS_TRAIT(src, TRAIT_NOSOFTCRIT))
+ ADD_TRAIT(src, TRAIT_CRITICAL_CONDITION, STAT_TRAIT)
+ else
+ REMOVE_TRAIT(src, TRAIT_CRITICAL_CONDITION, STAT_TRAIT)
+ if(HARD_CRIT)
+ if(. != UNCONSCIOUS)
+ become_blind(UNCONSCIOUS_TRAIT)
+ ADD_TRAIT(src, TRAIT_CRITICAL_CONDITION, STAT_TRAIT)
+ if(DEAD)
+ REMOVE_TRAIT(src, TRAIT_CRITICAL_CONDITION, STAT_TRAIT)
///Reports the event of the change in value of the buckled variable.
/mob/living/proc/set_buckled(new_buckled)
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 082e4fe7fe260..87de7f252b1de 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -75,8 +75,6 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
return new_msg
/mob/living/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language, ignore_spam = FALSE, forced)
- var/static/list/crit_allowed_modes = list(WHISPER_MODE = TRUE, MODE_ALIEN = TRUE)
- var/static/list/unconscious_allowed_modes = list(MODE_ALIEN = TRUE)
var/ic_blocked = FALSE
if(client && !forced && CHAT_FILTER_CHECK(message))
@@ -99,16 +97,24 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
var/original_message = message
message = get_message_mods(message, message_mods)
var/datum/saymode/saymode = SSradio.saymodes[message_mods[RADIO_KEY]]
- var/in_critical = InCritical()
if(!message)
return
message = check_for_custom_say_emote(message, message_mods)
- if(stat == DEAD)
- say_dead(original_message)
- return
+ switch(stat)
+ if(SOFT_CRIT)
+ message_mods[WHISPER_MODE] = MODE_WHISPER
+ if(UNCONSCIOUS)
+ if(!(message_mods[MODE_ALIEN]))
+ return
+ if(HARD_CRIT)
+ if(!(message_mods[WHISPER_MODE] || message_mods[MODE_ALIEN]))
+ return
+ if(DEAD)
+ say_dead(original_message)
+ return
if(saymode && saymode.early && !saymode.handle_message(src, message, language))
return
@@ -116,23 +122,6 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
if(is_muted(original_message, ignore_spam, forced) || check_emote(original_message, forced))
return
- if(in_critical) //There are cheaper ways to do this, but they're less flexible, and this isn't ran all that often
- var/end = TRUE
- for(var/index in message_mods)
- if(crit_allowed_modes[index])
- end = FALSE
- break
- if(end)
- return
- else if(stat == UNCONSCIOUS)
- var/end = TRUE
- for(var/index in message_mods)
- if(unconscious_allowed_modes[index])
- end = FALSE
- break
- if(end)
- return
-
if(!language) // get_message_mods() proc finds a language key, and add the language to LANGUAGE_EXTENSION
language = message_mods[LANGUAGE_EXTENSION]
@@ -155,15 +144,12 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
log_message(message_mods[MODE_CUSTOM_SAY_EMOTE], LOG_RADIO_EMOTE)
if(!message_mods[MODE_CUSTOM_SAY_ERASE_INPUT])
- var/fullcrit = InFullCritical()
- if((in_critical && !fullcrit) || message_mods[WHISPER_MODE] == MODE_WHISPER)
+ if(message_mods[WHISPER_MODE] == MODE_WHISPER)
if(saymode || message_mods[RADIO_EXTENSION]) //no radio while in crit
saymode = null
message_mods -= RADIO_EXTENSION
message_range = 1
- message_mods[WHISPER_MODE] = MODE_WHISPER
- log_talk(message, LOG_WHISPER, custom_say_emote = message_mods[MODE_CUSTOM_SAY_EMOTE])
- if(fullcrit)
+ if(stat == HARD_CRIT)
var/health_diff = round(-HEALTH_THRESHOLD_DEAD + health)
// If we cut our message short, abruptly end it with a-..
var/message_len = length_char(message)
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index 2ea45213c9758..2ddcbde6fe95d 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -76,7 +76,7 @@
if(health <= HEALTH_THRESHOLD_DEAD)
death()
return
- else if(stat == UNCONSCIOUS)
+ else if(stat >= UNCONSCIOUS)
set_stat(CONSCIOUS)
diag_hud_set_status()
diff --git a/code/modules/mob/living/silicon/robot/examine.dm b/code/modules/mob/living/silicon/robot/examine.dm
index c206591f427ad..d05061352dbf7 100644
--- a/code/modules/mob/living/silicon/robot/examine.dm
+++ b/code/modules/mob/living/silicon/robot/examine.dm
@@ -39,7 +39,7 @@
. += "It appears to be an [deployed ? "active" : "empty"] AI shell."
else if(!client)
. += "It appears to be in stand-by mode." //afk
- if(UNCONSCIOUS)
+ if(SOFT_CRIT, UNCONSCIOUS, HARD_CRIT)
. += "It doesn't seem to be responding."
if(DEAD)
. += "It looks like its system is corrupted and requires a reset."
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index a14b8be87f8c5..067c92f2898cf 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -238,7 +238,7 @@
var/refund = 0
if(QDELETED(L) || (L.stat == DEAD && prev_stat != DEAD)) //they're dead, you killed them
refund += kill_refund
- else if(L.InCritical() && prev_stat == CONSCIOUS) //you knocked them into critical
+ else if(HAS_TRAIT(L, TRAIT_CRITICAL_CONDITION) && prev_stat == CONSCIOUS) //you knocked them into critical
refund += crit_refund
if(L.stat != DEAD && prev_stat != DEAD)
refund += attack_refund
diff --git a/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm b/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm
index 4f0a1fe6a3c62..8eb1c7212184e 100644
--- a/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm
@@ -2,7 +2,7 @@
name = "\improper A Perfectly Generic Boss Placeholder"
desc = ""
robust_searching = 1
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
status_flags = 0
a_intent = INTENT_HARM
gender = NEUTER
diff --git a/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm b/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm
index d03eab4ca56f9..a8a5d7da1a4de 100644
--- a/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm
+++ b/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm
@@ -18,7 +18,7 @@
response_disarm = "shoves"
response_harm = "hits"
speed = 0
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
robust_searching = 1
maxHealth = 100
health = 100
diff --git a/code/modules/mob/living/simple_animal/hostile/faithless.dm b/code/modules/mob/living/simple_animal/hostile/faithless.dm
index 57e42b4c74709..6688fde07d651 100644
--- a/code/modules/mob/living/simple_animal/hostile/faithless.dm
+++ b/code/modules/mob/living/simple_animal/hostile/faithless.dm
@@ -17,7 +17,7 @@
maxHealth = 80
health = 80
spacewalk = TRUE
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
robust_searching = 1
obj_damage = 50
diff --git a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm
index 85ca2b882c0c7..6661246c29a48 100644
--- a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm
+++ b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm
@@ -30,7 +30,7 @@
possible_a_intents = list(INTENT_HELP, INTENT_GRAB, INTENT_DISARM, INTENT_HARM)
faction = list("jungle")
robust_searching = TRUE
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
minbodytemp = 270
maxbodytemp = 350
unique_name = TRUE
diff --git a/code/modules/mob/living/simple_animal/hostile/heart.dm b/code/modules/mob/living/simple_animal/hostile/heart.dm
index 7ca09c012a641..f955d20acdfad 100644
--- a/code/modules/mob/living/simple_animal/hostile/heart.dm
+++ b/code/modules/mob/living/simple_animal/hostile/heart.dm
@@ -21,7 +21,7 @@
attacktext = "beats"
ventcrawler = VENTCRAWLER_ALWAYS
attack_sound = 'sound/effects/singlebeat.ogg'
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
attack_same = 1
gold_core_spawnable = HOSTILE_SPAWN
see_in_dark = 8
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 3273d02408ac6..c4adc619b768c 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -43,7 +43,8 @@
var/search_objects_timer_id //Timer for regaining our old search_objects value after being attacked
var/search_objects_regain_time = 30 //the delay between being attacked and gaining our old search_objects value back
var/list/wanted_objects = list() //A typecache of objects types that will be checked against to attack, should we have search_objects enabled
- var/stat_attack = CONSCIOUS //Mobs with stat_attack to UNCONSCIOUS will attempt to attack things that are unconscious, Mobs with stat_attack set to DEAD will attempt to attack the dead.
+ ///Mobs ignore mob/living targets with a stat lower than that of stat_attack. If set to DEAD, then they'll include corpses in their targets, if to HARD_CRIT they'll keep attacking until they kill, and so on.
+ var/stat_attack = CONSCIOUS
var/stat_exclusive = FALSE //Mobs with this set to TRUE will exclusively attack things defined by stat_attack, stat_attack DEAD means they will only attack corpses
var/attack_same = 0 //Set us to 1 to allow us to attack our own faction
//Use GET_TARGETS_FROM(mob) to access this
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
index e6a64102c6fad..e12c6e9011f98 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
@@ -21,7 +21,7 @@
base_pixel_x = -16
layer = LARGE_MOB_LAYER
speed = 10
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
robust_searching = 1
var/hopping = FALSE
var/hop_cooldown = 0 //Strictly for player controlled leapers
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm
index 8b50d7fc54656..514ebf22504a2 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm
@@ -22,7 +22,7 @@
ranged_cooldown_time = 10
pass_flags_self = LETPASSTHROW
robust_searching = TRUE
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
attack_sound = 'sound/weapons/rapierhit.ogg'
deathsound = 'sound/voice/mook_death.ogg'
aggro_vision_range = 15 //A little more aggressive once in combat to balance out their really low HP
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm b/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm
index fd1922dd89049..e21457265a009 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm
@@ -26,7 +26,7 @@
projectiletype = /obj/projectile/seedling
projectilesound = 'sound/weapons/pierce.ogg'
robust_searching = TRUE
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
move_resist = MOVE_FORCE_EXTREMELY_STRONG
var/combatant_state = SEEDLING_STATE_NEUTRAL
var/obj/seedling_weakpoint/weak_point
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
index 3c6869f664992..7184569458639 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
@@ -105,11 +105,13 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/legion/AttackingTarget()
. = ..()
- if(. && ishuman(target))
- var/mob/living/L = target
- if(L.stat == UNCONSCIOUS)
- var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new(loc)
- A.infest(L)
+ if(!. || !ishuman(target))
+ return
+ var/mob/living/living_target = target
+ switch(living_target.stat)
+ if(UNCONSCIOUS, HARD_CRIT)
+ var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/legion = new(loc)
+ legion.infest(living_target)
/mob/living/simple_animal/hostile/megafauna/legion/proc/reset_charge()
ranged = TRUE
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
index 3356538ca7c31..90b948f3e0d15 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
@@ -15,7 +15,7 @@
movement_type = FLYING
robust_searching = TRUE
ranged_ignores_vision = TRUE
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
damage_coeff = list(BRUTE = 1, BURN = 0.5, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
minbodytemp = 0
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
index 44af7d8b8b987..ba1a973306c90 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
@@ -76,7 +76,7 @@
a_intent = INTENT_HARM
speak_emote = list("telepathically cries")
attack_sound = 'sound/weapons/bladeslice.ogg'
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
movement_type = FLYING
robust_searching = 1
crusher_loot = /obj/item/crusher_trophy/watcher_wing
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
index ed14b01ad5f84..4766f9269d10b 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
@@ -15,7 +15,7 @@
vision_range = 6
aggro_vision_range = 18
environment_smash = ENVIRONMENT_SMASH_NONE //This is to prevent elites smashing up the mining station, we'll make sure they can smash minerals fine below.
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
layer = LARGE_MOB_LAYER
sentience_type = SENTIENCE_BOSS
hud_type = /datum/hud/lavaland_elite
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm
index 3dce29204e2a8..dd7f054f8be9f 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm
@@ -95,7 +95,7 @@
butcher_results = list(/obj/item/food/meat/slab/goliath = 2, /obj/item/stack/sheet/bone = 2)
guaranteed_butcher_results = list(/obj/item/stack/sheet/animalhide/goliath_hide = 1)
loot = list()
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
robust_searching = 1
/mob/living/simple_animal/hostile/asteroid/goliath/beast/random/Initialize(mapload)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm
index c87121b9e2933..e65cbd6ee616b 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm
@@ -25,7 +25,7 @@
a_intent = INTENT_HELP
ventcrawler = VENTCRAWLER_ALWAYS
gold_core_spawnable = FRIENDLY_SPAWN
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
gender = NEUTER
stop_automated_movement = FALSE
stop_automated_movement_when_pulled = TRUE
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm
index c9cfd437ab0b3..96f45457005f6 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm
@@ -107,7 +107,7 @@
loot = list(/obj/item/organ/regenerative_core/legion)
brood_type = /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion
del_on_death = TRUE
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
robust_searching = 1
var/dwarf_mob = FALSE
var/mob/living/carbon/human/stored_mob
@@ -170,16 +170,24 @@
throw_message = "is shrugged off by"
pass_flags = PASSTABLE
del_on_death = TRUE
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
robust_searching = 1
var/can_infest_dead = FALSE
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/Life()
- if(isturf(loc))
- for(var/mob/living/carbon/human/H in viewers(1, src)) //Only for corpse right next to/on same tile
- if(H.stat == UNCONSCIOUS || (can_infest_dead && H.stat == DEAD))
- infest(H)
- ..()
+ . = ..()
+ if(stat == DEAD || !isturf(loc))
+ return
+
+ for(var/mob/living/carbon/human/victim in viewers(1, src)) //Only for corpse right next to/on same tile
+ switch(victim.stat)
+ if(UNCONSCIOUS, HARD_CRIT)
+ infest(victim)
+ return //This will qdelete the legion.
+ if(DEAD)
+ if(can_infest_dead)
+ infest(victim)
+ return //This will qdelete the legion.
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/proc/infest(mob/living/carbon/human/H)
visible_message("[name] burrows into the flesh of [H]!")
diff --git a/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm b/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm
index 33a2109927b93..b3b02061b6366 100644
--- a/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm
+++ b/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm
@@ -13,7 +13,7 @@
response_disarm = "shoves"
response_harm = "hits"
speed = 0
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
robust_searching = 1
maxHealth = 100
health = 100
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
index d7742984d65a9..d36021d7a6fec 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
@@ -231,7 +231,7 @@
speed = 5
melee_damage = 30
armour_penetration = 30
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
attacktext = "acts out divine vengeance on"
obj_damage = 50
environment_smash = ENVIRONMENT_SMASH_RWALLS
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm
index 658cd5701d00c..1ffe61a4a9514 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm
@@ -36,7 +36,7 @@
response_disarm = "shoves"
response_harm = "hits"
speed = 0
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
robust_searching = 1
vision_range = 3
maxHealth = 100
diff --git a/code/modules/mob/living/simple_animal/hostile/skeleton.dm b/code/modules/mob/living/simple_animal/hostile/skeleton.dm
index b59a33cddc592..ddb56921b76f2 100644
--- a/code/modules/mob/living/simple_animal/hostile/skeleton.dm
+++ b/code/modules/mob/living/simple_animal/hostile/skeleton.dm
@@ -23,7 +23,7 @@
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
unsuitable_atmos_damage = 10
robust_searching = 1
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
gold_core_spawnable = HOSTILE_SPAWN
faction = list("skeleton")
see_in_dark = 8
diff --git a/code/modules/mob/living/simple_animal/hostile/stickman.dm b/code/modules/mob/living/simple_animal/hostile/stickman.dm
index 288d069bebd8c..2b9bf5c926728 100644
--- a/code/modules/mob/living/simple_animal/hostile/stickman.dm
+++ b/code/modules/mob/living/simple_animal/hostile/stickman.dm
@@ -13,7 +13,7 @@
response_disarm = "shoves"
response_harm = "hits"
speed = 0
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
robust_searching = 1
environment_smash = ENVIRONMENT_SMASH_NONE
maxHealth = 100
diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
index 4716c1d72bc04..b3c458a614054 100644
--- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
@@ -29,7 +29,7 @@
response_disarm = "shoves"
response_harm = "hits"
speed = 0
- stat_attack = UNCONSCIOUS
+ stat_attack = HARD_CRIT
robust_searching = 1
maxHealth = 100
health = 100
diff --git a/code/modules/mob/living/simple_animal/hostile/zombie.dm b/code/modules/mob/living/simple_animal/hostile/zombie.dm
index e446b65169bb3..217750b056447 100644
--- a/code/modules/mob/living/simple_animal/hostile/zombie.dm
+++ b/code/modules/mob/living/simple_animal/hostile/zombie.dm
@@ -6,7 +6,7 @@
icon_living = "zombie"
mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID)
speak_chance = 0
- stat_attack = UNCONSCIOUS //braains
+ stat_attack = HARD_CRIT //braains
maxHealth = 100
health = 100
melee_damage = 21
diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm
index ec700c523c358..7eb8018945080 100644
--- a/code/modules/mob/living/simple_animal/slime/life.dm
+++ b/code/modules/mob/living/simple_animal/slime/life.dm
@@ -26,11 +26,13 @@
handle_mood()
handle_speech()
-// Unlike most of the simple animals, slimes support UNCONSCIOUS
+// Unlike most of the simple animals, slimes support UNCONSCIOUS. This is an ugly hack.
/mob/living/simple_animal/slime/update_stat()
- if(stat == UNCONSCIOUS && health > 0)
- return
- ..()
+ switch(stat)
+ if(UNCONSCIOUS, HARD_CRIT)
+ if(health > 0)
+ return
+ return ..()
/mob/living/simple_animal/slime/process()
if(stat == DEAD || !Target || client || buckled)
@@ -101,18 +103,21 @@
environment.adjust_moles(GAS_O2, plas_amt)
adjustBruteLoss(plas_amt ? -2 : 0)
- if(stat == CONSCIOUS && stasis)
- to_chat(src, "Nerve gas in the air has put you in stasis!")
- set_stat(UNCONSCIOUS)
- powerlevel = 0
- rabid = 0
- update_mobility()
- regenerate_icons()
- else if(stat == UNCONSCIOUS && !stasis)
- to_chat(src, "You wake up from the stasis.")
- set_stat(CONSCIOUS)
- update_mobility()
- regenerate_icons()
+ switch(stat)
+ if(CONSCIOUS)
+ if(stasis)
+ to_chat(src, "Nerve gas in the air has put you in stasis!")
+ set_stat(UNCONSCIOUS)
+ powerlevel = 0
+ rabid = FALSE
+ update_mobility()
+ regenerate_icons()
+ if(UNCONSCIOUS, HARD_CRIT)
+ if(!stasis)
+ to_chat(src, "You wake up from the stasis.")
+ set_stat(CONSCIOUS)
+ update_mobility()
+ regenerate_icons()
updatehealth()
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index cbbb9c3b539c8..651a7b3cf3ea9 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -250,10 +250,11 @@
else
tab_data["Slime Status"] = GENERATE_STAT_TEXT("You can evolve!")
- if(stat == UNCONSCIOUS)
- tab_data["Unconscious"] = GENERATE_STAT_TEXT("You are knocked out by high levels of BZ!")
- else
- tab_data["Power Level"] = GENERATE_STAT_TEXT("[powerlevel]")
+ switch(stat)
+ if(HARD_CRIT, UNCONSCIOUS)
+ tab_data["Unconscious"] = GENERATE_STAT_TEXT("You are knocked out by high levels of BZ!")
+ else
+ tab_data["Power Level"] = GENERATE_STAT_TEXT("[powerlevel]")
return tab_data
/mob/living/simple_animal/slime/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE)
@@ -453,7 +454,7 @@
if (stat == DEAD)
. += "It is limp and unresponsive."
else
- if (stat == UNCONSCIOUS) // Slime stasis
+ if (stat == UNCONSCIOUS || stat == HARD_CRIT) // Slime stasis
. += "It appears to be alive but unresponsive."
if (getBruteLoss())
. += ""
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 67be1d596f061..1b60348ca4ba4 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -177,7 +177,7 @@
if(type & MSG_VISUAL && is_blind())
return
// voice muffling
- if(stat == UNCONSCIOUS)
+ if(stat == UNCONSCIOUS || stat == HARD_CRIT)
if(type & MSG_AUDIBLE) //audio
to_chat(src, "... You can almost hear something ...")
return
@@ -807,7 +807,7 @@
/mob/proc/canface()
if(world.time < client.last_turn)
return FALSE
- if(stat == DEAD || stat == UNCONSCIOUS)
+ if(stat >= UNCONSCIOUS)
return FALSE
if(anchored)
return FALSE
diff --git a/code/modules/mob/status_procs.dm b/code/modules/mob/status_procs.dm
index df83a10c1cb70..ba8365c964a17 100644
--- a/code/modules/mob/status_procs.dm
+++ b/code/modules/mob/status_procs.dm
@@ -46,22 +46,34 @@
update_blindness()
/// proc that adds and removes blindness overlays when necessary
-/mob/proc/update_blindness(overlay = /atom/movable/screen/fullscreen/blind, add_color = TRUE, var/can_see = TRUE)
- if(stat == UNCONSCIOUS || HAS_TRAIT(src, TRAIT_BLIND) || eye_blind) // UNCONSCIOUS or has blind trait, or has temporary blindness
- if((stat == CONSCIOUS || stat == SOFT_CRIT) && istype(overlay, /atom/movable/screen/alert))
- throw_alert("blind", overlay)
- overlay_fullscreen("blind", overlay)
+/mob/proc/update_blindness(overlay = /atom/movable/screen/fullscreen/blind, add_color = TRUE, can_see = TRUE)
+ switch(stat)
+ if(CONSCIOUS, SOFT_CRIT)
+ if(HAS_TRAIT(src, TRAIT_BLIND) || eye_blind && istype(overlay, /atom/movable/screen/alert))
+ throw_alert("blind", /atom/movable/screen/alert/blind)
+ do_set_blindness(FALSE, overlay, add_color)
+ else
+ do_set_blindness(TRUE, overlay, add_color)
+ if(UNCONSCIOUS, HARD_CRIT)
+ do_set_blindness(FALSE, overlay, add_color)
+ if(DEAD)
+ do_set_blindness(TRUE, overlay, add_color)
+
+///Proc that handles adding and removing the blindness overlays.
+/mob/proc/do_set_blindness(can_see, overlay_setter, add_color_setter)
+ if(!can_see)
+ overlay_fullscreen("blind", overlay_setter)
// You are blind why should you be able to make out details like color, only shapes near you
- if(add_color)
+ if(add_color_setter)
add_client_colour(/datum/client_colour/monochrome/blind)
- var/datum/component/blind_sense/B = GetComponent(/datum/component/blind_sense)
+ var/datum/component/blind_sense/B = GetComponent(/datum/component/blind_sense)
if(!B && !QDELING(src) && !QDELETED(src))
AddComponent(/datum/component/blind_sense)
- else if(can_see) // CONSCIOUS no blind trait, no blindness
+ else
clear_alert("blind")
clear_fullscreen("blind")
remove_client_colour(/datum/client_colour/monochrome/blind)
- var/datum/component/blind_sense/B = GetComponent(/datum/component/blind_sense)
+ var/datum/component/blind_sense/B = GetComponent(/datum/component/blind_sense)
B?.RemoveComponent()
/**
diff --git a/code/modules/research/nanites/nanite_programs/sensor.dm b/code/modules/research/nanites/nanite_programs/sensor.dm
index dfbecbfb451bb..5ecd5b43a2ac8 100644
--- a/code/modules/research/nanites/nanite_programs/sensor.dm
+++ b/code/modules/research/nanites/nanite_programs/sensor.dm
@@ -110,14 +110,13 @@
var/spent = FALSE
/datum/nanite_program/sensor/crit/check_event()
- if(host_mob.InCritical())
- if(!spent)
- spent = TRUE
- return TRUE
- return FALSE
- else
- spent = FALSE
- return FALSE
+ if(HAS_TRAIT(host_mob, TRAIT_CRITICAL_CONDITION))
+ if(spent)
+ return FALSE
+ spent = TRUE
+ return TRUE
+ spent = FALSE
+ return FALSE
/datum/nanite_program/sensor/crit/make_rule(datum/nanite_program/target)
var/datum/nanite_rule/crit/rule = new(target)
diff --git a/code/modules/research/nanites/rules.dm b/code/modules/research/nanites/rules.dm
index 34903a9b30d44..974e9c8d930c0 100644
--- a/code/modules/research/nanites/rules.dm
+++ b/code/modules/research/nanites/rules.dm
@@ -55,9 +55,7 @@
desc = "Checks if the host is in critical condition."
/datum/nanite_rule/crit/check_rule()
- if(program.host_mob.InCritical())
- return TRUE
- return FALSE
+ return HAS_TRAIT(program.host_mob, TRAIT_CRITICAL_CONDITION)
/datum/nanite_rule/death
name = "Death"
diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm
index 0189c0810d00d..7a8926d6130fc 100644
--- a/code/modules/surgery/bodyparts/bodyparts.dm
+++ b/code/modules/surgery/bodyparts/bodyparts.dm
@@ -489,7 +489,7 @@
var/obj/item/cavity_item
/obj/item/bodypart/chest/can_dismember(obj/item/I)
- if(!((owner.stat == DEAD) || owner.InFullCritical()))
+ if(owner.stat < HARD_CRIT)
return FALSE
return ..()
diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm
index 86deb37be5a1c..56a1fc0f1346a 100644
--- a/code/modules/surgery/bodyparts/dismemberment.dm
+++ b/code/modules/surgery/bodyparts/dismemberment.dm
@@ -60,7 +60,6 @@
if(HAS_TRAIT(C, TRAIT_NODISMEMBER))
return FALSE
. = list()
- var/organ_spilled = 0
var/turf/T = get_turf(C)
C.add_splatter_floor(T)
playsound(get_turf(C), 'sound/misc/splort.ogg', 80, 1)
@@ -71,18 +70,11 @@
continue
O.Remove(C)
O.forceMove(T)
- organ_spilled = 1
. += X
if(cavity_item)
cavity_item.forceMove(T)
. += cavity_item
cavity_item = null
- organ_spilled = 1
-
- if(organ_spilled)
- C.visible_message("[C]'s internal organs spill out onto the floor!")
-
-
//limb removal. The "special" argument is used for swapping a limb with a new one without the effects of losing a limb kicking in.
/obj/item/bodypart/proc/drop_limb(special, dismembered)
diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm
index 470ef9dd89132..dfea115b83e7b 100644
--- a/code/modules/surgery/bodyparts/head.dm
+++ b/code/modules/surgery/bodyparts/head.dm
@@ -94,7 +94,7 @@
/obj/item/bodypart/head/can_dismember(obj/item/I)
- if(!((owner.stat == DEAD) || owner.InFullCritical()))
+ if(owner.stat < HARD_CRIT)
return FALSE
return ..()
diff --git a/code/modules/surgery/organs/augments_chest.dm b/code/modules/surgery/organs/augments_chest.dm
index 588b64fece84b..eca93f0723ede 100644
--- a/code/modules/surgery/organs/augments_chest.dm
+++ b/code/modules/surgery/organs/augments_chest.dm
@@ -51,29 +51,28 @@
implant_color = "#AD0000"
slot = ORGAN_SLOT_HEART_AID
var/revive_cost = 0
- var/reviving = 0
- var/cooldown = 0
+ var/reviving = FALSE
+ COOLDOWN_DECLARE(reviver_cooldown)
/obj/item/organ/cyberimp/chest/reviver/on_life()
if(reviving)
- if(owner.stat)
- addtimer(CALLBACK(src, PROC_REF(heal)), 30)
- else
- cooldown = revive_cost + world.time
- reviving = FALSE
- to_chat(owner, "Your reviver implant shuts down and starts recharging. It will be ready again in [DisplayTimeText(revive_cost)].")
+ switch(owner.stat)
+ if(UNCONSCIOUS, HARD_CRIT)
+ addtimer(CALLBACK(src, PROC_REF(heal)), 30)
+ else
+ COOLDOWN_START(src, reviver_cooldown, revive_cost)
+ reviving = FALSE
+ to_chat(owner, "Your reviver implant shuts down and starts recharging. It will be ready again in [DisplayTimeText(revive_cost)].")
return
- if(cooldown > world.time)
- return
- if(!owner.stat)
- return
- if(owner.suiciding)
+ if(!COOLDOWN_FINISHED(src, reviver_cooldown) || owner.suiciding)
return
- revive_cost = 0
- reviving = TRUE
- to_chat(owner, "You feel a faint buzzing as your reviver implant starts patching your wounds...")
+ switch(owner.stat)
+ if(UNCONSCIOUS, HARD_CRIT)
+ revive_cost = 0
+ reviving = TRUE
+ to_chat(owner, "You feel a faint buzzing as your reviver implant starts patching your wounds...")
/obj/item/organ/cyberimp/chest/reviver/proc/heal()
if(owner.getOxyLoss())
@@ -97,7 +96,7 @@
if(reviving)
revive_cost += 200
else
- cooldown += 200
+ reviver_cooldown += 20 SECONDS
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi
index 76c07e66b97122d26be7da974f8b235ba7e42cd2..4c71ed24455b1c15ab693b26a56d65e38f39d337 100644
GIT binary patch
delta 13677
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