diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm
index 15a8ed20949..d6ab9543d76 100644
--- a/code/__DEFINES/flags.dm
+++ b/code/__DEFINES/flags.dm
@@ -68,6 +68,7 @@
#define MUTCOLORS_PARTSONLY 15 //Used if we want the mutant colour to be only used by mutant bodyparts. Don't combine this with MUTCOLORS, or it will be useless.
#define NODISMEMBER 16
#define NOHUNGER 17
+#define NOCRITDAMAGE 18
/*
These defines are used specifically with the atom/movable/languages bitmask.
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 08490c0f980..ae46a77d33f 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -843,18 +843,19 @@
return
src.visible_message("[src] performs CPR on [C.name]!", "You perform CPR on [C.name].")
+ C.cpr_time = world.time
+ add_logs(src, C, "CPRed")
+
if(they_breathe && they_lung)
- C.cpr_time = world.time
var/suff = min(C.getOxyLoss(), 7)
C.adjustOxyLoss(-suff)
C.updatehealth()
C << "You feel a breath of fresh air enter your lungs... It feels good..."
- add_logs(src, C, "CPRed")
else if(they_breathe && !they_lung)
- C << "You feel a breath of fresh air... \
- but it doesn't go anywhere..."
+ C << "You feel a breath of fresh air... \
+ but you don't feel any better..."
else
- C << "You feel a breath of fresh air... \
+ C << "You feel a breath of fresh air... \
which is a sensation you don't recognise..."
/mob/living/carbon/human/generateStaticOverlay()
@@ -1005,14 +1006,32 @@
hud_used.healthdoll.icon_state = "healthdoll_DEAD"
/mob/living/carbon/human/fully_heal(admin_revive = 0)
+ CHECK_DNA_AND_SPECIES(src)
+
if(admin_revive)
regenerate_limbs()
- if(!getorganslot("lungs"))
- var/obj/item/organ/lungs/L = new()
- L.Insert(src)
- if(!getorganslot("tongue"))
- var/obj/item/organ/tongue/T = new()
- T.Insert(src)
+
+ if(!(NOBREATH in dna.species.specflags) && !getorganslot("lungs"))
+ var/obj/item/organ/lungs/L = new()
+ L.Insert(src)
+
+ if(!(NOBLOOD in dna.species.specflags) && !getorganslot("heart"))
+ var/obj/item/organ/heart/H = new()
+ H.Insert(src)
+
+ if(!getorganslot("tongue"))
+ var/obj/item/organ/tongue/T
+
+ for(var/obj/item/organ/tongue/tongue_type in \
+ dna.species.mutant_organs)
+ T = new tongue_type()
+ T.Insert(src)
+
+ // if they have no mutant tongues, give them a regular one
+ if(!T)
+ T = new()
+ T.Insert(src)
+
restore_blood()
remove_all_embedded_objects()
drunkenness = 0
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 99d99f6b6d6..db2397676c0 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -305,13 +305,26 @@
clear_alert("embeddedobject")
/mob/living/carbon/human/proc/handle_heart()
- if(!heart_attack)
- return
- else
- if(losebreath < 3)
- losebreath += 2
- adjustOxyLoss(5)
- adjustBruteLoss(1)
+ CHECK_DNA_AND_SPECIES(src)
+ var/needs_heart = (!(NOBLOOD in dna.species.specflags))
+ var/we_breath = (!(NOBREATH in dna.species.specflags))
+
+ if(heart_attack)
+ if(!needs_heart)
+ heart_attack = FALSE
+ else if(we_breath)
+ if(losebreath < 3)
+ losebreath += 2
+ adjustOxyLoss(5)
+ adjustBruteLoss(1)
+ else
+ // even though we don't require oxygen, our blood still needs
+ // circulation, and without it, our tissues die and start
+ // gaining toxins
+ adjustBruteLoss(3)
+ if(src.reagents)
+ src.reagents.add_reagent("toxin", 2)
+ src.reagents.reaction(src, INJECT)
/*
Alcohol Poisoning Chart
diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm
index 047f46481c0..32a5b9c694f 100644
--- a/code/modules/mob/living/carbon/human/say.dm
+++ b/code/modules/mob/living/carbon/human/say.dm
@@ -48,7 +48,10 @@
return real_name
/mob/living/carbon/human/IsVocal()
- if(!getorganslot("lungs"))
+ CHECK_DNA_AND_SPECIES(src)
+
+ // how do species that don't breathe talk? magic, that's what.
+ if(!(NOBREATH in dna.species.specflags) && !getorganslot("lungs"))
return 0
if(mind)
return !mind.miming
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index e8f53b42a3a..068289e0dd7 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -128,6 +128,21 @@
C.regenerate_limbs() //if we don't handle dismemberment, we grow our missing limbs back
if(exotic_blood)
C.reagents.add_reagent(exotic_blood, 80)
+
+ var/obj/item/organ/heart/heart = C.getorganslot("heart")
+ var/obj/item/organ/lungs/lungs = C.getorganslot("lungs")
+ var/obj/item/organ/appendix/appendix = C.getorganslot("appendix")
+
+ if(NOBLOOD in specflags && heart)
+ heart.Remove(C)
+ qdel(heart)
+ if(NOBREATH in specflags && lungs)
+ lungs.Remove(C)
+ qdel(lungs)
+ if(NOHUNGER in specflags && appendix)
+ appendix.Remove(C)
+ qdel(appendix)
+
for(var/path in mutant_organs)
var/obj/item/organ/I = new path()
I.Insert(C)
@@ -471,7 +486,13 @@
H.apply_overlay(BODY_FRONT_LAYER)
/datum/species/proc/spec_life(mob/living/carbon/human/H)
- return
+ if(NOBREATH in specflags)
+ H.setOxyLoss(0)
+ H.losebreath = 0
+
+ var/takes_crit_damage = (!(NOCRITDAMAGE in specflags))
+ if((H.health < config.health_threshold_crit) && takes_crit_damage)
+ H.adjustBruteLoss(1)
/datum/species/proc/spec_death(gibbed, mob/living/carbon/human/H)
return
@@ -1184,11 +1205,10 @@
H.adjustOxyLoss(HUMAN_MAX_OXYLOSS)
if(!lungs)
H.adjustOxyLoss(1)
- H.failed_last_breath = 1
- else
+ else if(!(NOCRITDAMAGE in specflags))
H.adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS)
- H.failed_last_breath = 1
+ H.failed_last_breath = 1
H.throw_alert("oxy", /obj/screen/alert/oxy)
return 0
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index 5bfe942374d..966481e1b2d 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -89,14 +89,21 @@
toxpwr = 0
/datum/reagent/toxin/lexorin/on_mob_life(mob/living/M)
- M.adjustOxyLoss(5, 0)
+ . = TRUE
+ var/mob/living/carbon/C
if(iscarbon(M))
- var/mob/living/carbon/C = M
- C.losebreath += 2
- if(prob(20))
- M.emote("gasp")
+ C = M
+ CHECK_DNA_AND_SPECIES(C)
+ if(NOBREATH in C.dna.species.specflags)
+ . = FALSE
+
+ if(.)
+ M.adjustOxyLoss(5, 0)
+ if(C)
+ C.losebreath += 2
+ if(prob(20))
+ M.emote("gasp")
..()
- . = 1
/datum/reagent/toxin/slimejelly
name = "Slime Jelly"