Skip to content

Commit

Permalink
Merge pull request #3234 from MistakeNot4892/breathedeep
Browse files Browse the repository at this point in the history
Collapsing human and carbon breathing down to /mob/living.
  • Loading branch information
out-of-phaze authored Aug 11, 2023
2 parents bc5b3c6 + a38f534 commit a52c5df
Show file tree
Hide file tree
Showing 19 changed files with 204 additions and 235 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@
H.co2_alert = 0
else if(istype(H))
H.co2_alert = 0
if(istype(H) && dosage > 1 && H.losebreath < 15)
H.losebreath++
if(istype(H) && dosage > 1 && H.ticks_since_last_successful_breath < 15)
H.ticks_since_last_successful_breath++
if(warning_message && prob(warning_prob))
to_chat(M, SPAN_WARNING("You feel [warning_message]."))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.stat != UNCONSCIOUS)
if(H.losebreath >= 10)
H.losebreath = max(10, H.losebreath-10)
if(H.ticks_since_last_successful_breath >= 10)
H.ticks_since_last_successful_breath = max(10, H.ticks_since_last_successful_breath-10)
H.adjustOxyLoss(2)
SET_STATUS_MAX(H, STAT_WEAK, 10)
M.add_chemical_effect(CE_NOPULSE, 1)
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/grab/normal/norm_kill.dm
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@
SET_STATUS_MAX(affecting, STAT_WEAK, 5) //Should keep you down unless you get help.
if(iscarbon(affecting))
var/mob/living/carbon/C = affecting
C.losebreath = max(C.losebreath + 2, 3)
C.ticks_since_last_successful_breath = max(C.ticks_since_last_successful_breath + 2, 3)
7 changes: 5 additions & 2 deletions code/modules/mob/living/carbon/brain/life.dm
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
/mob/living/carbon/brain/handle_breathing()
return
/mob/living/carbon/brain/need_breathe()
return FALSE

/mob/living/carbon/brain/should_breathe()
return FALSE

/mob/living/carbon/brain/handle_mutations_and_radiation()
..()
Expand Down
107 changes: 2 additions & 105 deletions code/modules/mob/living/carbon/breathe.dm
Original file line number Diff line number Diff line change
@@ -1,106 +1,3 @@
//Common breathing procs

#define MOB_BREATH_DELAY 2

//Start of a breath chain, calls breathe()
/mob/living/carbon/handle_breathing()
if((life_tick % MOB_BREATH_DELAY) == 0 || failed_last_breath || is_asystole()) //First, resolve location and get a breath
breathe()

/mob/living/carbon/proc/breathe(var/active_breathe = 1)

if(!need_breathe()) return

var/datum/gas_mixture/breath = null

//First, check if we can breathe at all
if(handle_drowning() || (is_asystole() && !GET_CHEMICAL_EFFECT(src, CE_STABLE) && active_breathe)) //crit aka circulatory shock
losebreath = max(2, losebreath + 1)

if(losebreath>0) //Suffocating so do not take a breath
losebreath--
if (prob(10) && !is_asystole() && active_breathe) //Gasp per 10 ticks? Sounds about right.
INVOKE_ASYNC(src, .proc/emote, "gasp")
else
//Okay, we can breathe, now check if we can get air
var/volume_needed = get_breath_volume()
breath = get_breath_from_internal(volume_needed) //First, check for air from internals
if(!breath)
breath = get_breath_from_environment(volume_needed) //No breath from internals so let's try to get air from our location
if(!breath)
var/static/datum/gas_mixture/vacuum //avoid having to create a new gas mixture for each breath in space
if(!vacuum) vacuum = new

breath = vacuum //still nothing? must be vacuum

handle_breath(breath)
handle_post_breath(breath)

/mob/living/carbon/proc/get_breath_from_internal(var/volume_needed=STD_BREATH_VOLUME) //hopefully this will allow overrides to specify a different default volume without breaking any cases where volume is passed in.
if(internal)
if (!contents.Find(internal))
set_internals(null)
var/obj/item/mask = get_equipped_item(slot_wear_mask_str)
if (!mask || !(mask.item_flags & ITEM_FLAG_AIRTIGHT))
set_internals(null)
if(internal)
if (internals)
internals.icon_state = "internal1"
return internal.remove_air_volume(volume_needed)
else
if (internals)
internals.icon_state = "internal0"
return null

/mob/living/carbon/proc/get_breath_from_environment(var/volume_needed=STD_BREATH_VOLUME, var/atom/location = src.loc)
if(volume_needed <= 0)
return
var/datum/gas_mixture/breath = null

var/datum/gas_mixture/environment
if(location)
environment = location.return_air()

if(environment)
breath = environment.remove_volume(volume_needed)
handle_chemical_smoke(environment) //handle chemical smoke while we're at it

if(breath && breath.total_moles)
//handle mask filtering
var/obj/item/clothing/mask/M = get_equipped_item(slot_wear_mask_str)
if(istype(M) && breath)
var/datum/gas_mixture/filtered = M.filter_air(breath)
location.assume_air(filtered)
return breath
return null

//Handle possble chem smoke effect
/mob/living/carbon/proc/handle_chemical_smoke(var/datum/gas_mixture/environment)
if(species && environment.return_pressure() < species.breath_pressure/5)
return //pressure is too low to even breathe in.
var/obj/item/mask = get_equipped_item(slot_wear_mask_str)
if(mask && (mask.item_flags & ITEM_FLAG_BLOCK_GAS_SMOKE_EFFECT))
return

for(var/obj/effect/effect/smoke/chem/smoke in view(1, src))
if(smoke.reagents.total_volume)
smoke.reagents.trans_to_mob(src, 5, CHEM_INGEST, copy = 1)
smoke.reagents.trans_to_mob(src, 5, CHEM_INJECT, copy = 1)
// I dunno, maybe the reagents enter the blood stream through the lungs?
break // If they breathe in the nasty stuff once, no need to continue checking

/mob/living/carbon/proc/get_breath_volume()
return STD_BREATH_VOLUME

/mob/living/carbon/proc/handle_breath(datum/gas_mixture/breath)
return

/mob/living/carbon/proc/handle_post_breath(datum/gas_mixture/breath)
if(breath)
//by default, exhale
var/datum/gas_mixture/internals_air = internal?.return_air()
var/datum/gas_mixture/loc_air = loc?.return_air()
if(internals_air && (internals_air.return_pressure() < loc_air.return_pressure())) // based on the assumption it has a one-way valve for gas release
internals_air?.merge(breath)
else
loc_air?.merge(breath)
/mob/living/carbon/should_breathe()
return ((life_tick % MOB_BREATH_DELAY) == 0 || failed_last_breath || is_asystole())
3 changes: 0 additions & 3 deletions code/modules/mob/living/carbon/carbon.dm
Original file line number Diff line number Diff line change
Expand Up @@ -300,9 +300,6 @@
/mob/living/carbon/proc/can_devour(atom/movable/victim)
return FALSE

/mob/living/carbon/proc/need_breathe()
return

/mob/living/carbon/check_has_mouth()
// carbon mobs have mouths by default
// behavior of this proc for humans is overridden in human.dm
Expand Down
1 change: 0 additions & 1 deletion code/modules/mob/living/carbon/carbon_defines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
var/pose = null
var/datum/reagents/metabolism/bloodstr
var/datum/reagents/metabolism/touching
var/losebreath = 0 //if we failed to breathe last tick

var/coughedtime = null
var/ignore_rads = FALSE
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/living/carbon/human/examine.dm
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@

if (src.stat)
msg += "<span class='warning'>[use_He] [use_is]n't responding to anything around [use_him] and seems to be unconscious.</span>\n"
if((stat == DEAD || is_asystole() || src.losebreath) && distance <= 3)
if((stat == DEAD || is_asystole() || src.ticks_since_last_successful_breath) && distance <= 3)
msg += "<span class='warning'>[use_He] [use_does] not appear to be breathing.</span>\n"
if(ishuman(user) && !user.incapacitated() && Adjacent(user))
spawn(0)
Expand Down
45 changes: 1 addition & 44 deletions code/modules/mob/living/carbon/human/human.dm
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@
brain.mind.transfer_to(src)
qdel(brain.loc)
break
losebreath = 0
ticks_since_last_successful_breath = 0
UpdateAppearance()
..()

Expand Down Expand Up @@ -896,20 +896,6 @@
var/decl/bodytype/root_bodytype = get_bodytype()
return root_bodytype?.has_organ[organ_check]

/mob/living/carbon/human/get_breath_volume()
. = ..()
var/obj/item/organ/internal/heart/H = get_organ(BP_HEART, /obj/item/organ/internal/heart)
if(H && !H.open)
. *= (!BP_IS_PROSTHETIC(H)) ? get_pulse()/PULSE_NORM : 1.5

/mob/living/carbon/human/need_breathe()
if(mNobreath in mutations)
return FALSE
var/breathing_organ = get_bodytype().breathing_organ
if(!breathing_organ || !should_have_organ(breathing_organ))
return FALSE
return TRUE

/mob/living/carbon/human/get_adjusted_metabolism(metabolism)
return ..() * (species ? species.metabolism_mod : 1)

Expand Down Expand Up @@ -1040,35 +1026,6 @@
if(skill_check(SKILL_WEAPONS, SKILL_PROF))
. += 2

/mob/living/carbon/human/can_drown()
var/obj/item/clothing/mask/mask = get_equipped_item(slot_wear_mask_str)
if(!internal && (!istype(mask) || !mask.filters_water()))
var/obj/item/organ/internal/lungs/L = get_organ(BP_LUNGS, /obj/item/organ/internal/lungs)
return (!L || L.can_drown())
return FALSE

/mob/living/carbon/human/get_breath_from_environment(var/volume_needed = STD_BREATH_VOLUME, var/atom/location = src.loc)
var/datum/gas_mixture/breath = ..(volume_needed, location)
var/turf/T = get_turf(src)
if(istype(T) && T.is_flooded(lying) && should_have_organ(BP_LUNGS))
if(T == location) //Can we surface?
if(!lying && T.above && !T.above.is_flooded() && T.above.is_open() && can_overcome_gravity())
return ..(volume_needed, T.above)
var/obj/item/clothing/mask/mask = get_equipped_item(slot_wear_mask_str)
var/can_breathe_water = (istype(mask) && mask.filters_water()) ? TRUE : FALSE
if(!can_breathe_water)
var/obj/item/organ/internal/lungs/lungs = get_organ(BP_LUNGS, /obj/item/organ/internal/lungs)
if(lungs && lungs.can_drown())
can_breathe_water = TRUE
if(can_breathe_water)
if(!breath)
breath = new
breath.volume = volume_needed
breath.temperature = T.temperature
breath.adjust_gas(/decl/material/gas/oxygen, ONE_ATMOSPHERE*volume_needed/(R_IDEAL_GAS_EQUATION*T20C))
T.show_bubbles()
return breath

/mob/living/carbon/human/fluid_act(var/datum/reagents/fluids)
..()
if(!QDELETED(src) && fluids?.total_volume)
Expand Down
12 changes: 5 additions & 7 deletions code/modules/mob/living/carbon/human/human_attackhand.dm
Original file line number Diff line number Diff line change
Expand Up @@ -263,15 +263,13 @@
if(!need_breathe())
return TRUE

var/obj/item/organ/internal/lungs/L = get_organ(root_bodytype.breathing_organ, /obj/item/organ/internal/lungs)
if(!L)
var/obj/item/organ/internal/lungs/lungs = get_organ(root_bodytype.breathing_organ, /obj/item/organ/internal/lungs)
if(!lungs)
return

var/datum/gas_mixture/breath = H.get_breath_from_environment()
var/fail = L.handle_breath(breath, 1)
if(!fail)
if(!L.is_bruised())
losebreath = 0
if(!lungs.handle_owner_breath(H.get_breath_from_environment(), 1))
if(!lungs.is_bruised())
ticks_since_last_successful_breath = 0
to_chat(src, SPAN_NOTICE("You feel a breath of fresh air enter your lungs. It feels good."))

// Again.
Expand Down
57 changes: 0 additions & 57 deletions code/modules/mob/living/carbon/human/life.dm
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,6 @@
if(old_stat == UNCONSCIOUS && stat == CONSCIOUS)
playsound_local(null, 'sound/effects/bells.ogg', 100, is_global=TRUE)

/mob/living/carbon/human/breathe()
var/breathing_organ = get_bodytype().breathing_organ

if(breathing_organ)
var/active_breaths = 0
var/obj/item/organ/internal/lungs/L = get_organ(breathing_organ, /obj/item/organ/internal/lungs)
if(L)
active_breaths = L.active_breathing
..(active_breaths)

// Calculate how vulnerable the human is to the current pressure.
// Returns 0 (equals 0 %) if sealed in an undamaged suit that's rated for the pressure, 1 if unprotected (equals 100%).
// Suitdamage can modifiy this in 10% steps.
Expand Down Expand Up @@ -198,53 +188,6 @@

..()

/** breathing **/
/mob/living/carbon/human/handle_chemical_smoke(var/datum/gas_mixture/environment)
for(var/slot in global.standard_headgear_slots)
var/obj/item/gear = get_equipped_item(slot)
if(istype(gear) && (gear.item_flags & ITEM_FLAG_BLOCK_GAS_SMOKE_EFFECT))
return
..()

/mob/living/carbon/human/get_breath_from_internal(volume_needed=STD_BREATH_VOLUME)
if(internal)

var/obj/item/tank/rig_supply
var/obj/item/rig/rig = get_rig()
if(rig && !rig.offline && (rig.air_supply && internal == rig.air_supply))
rig_supply = rig.air_supply

if(!rig_supply)
if(!contents.Find(internal))
set_internals(null)
else
var/found_mask = FALSE
for(var/slot in global.airtight_slots)
var/obj/item/gear = get_equipped_item(slot)
if(gear && (gear.item_flags & ITEM_FLAG_AIRTIGHT))
found_mask = TRUE
break
if(!found_mask)
set_internals(null)

if(internal)
return internal.remove_air_volume(volume_needed)
return null

/mob/living/carbon/human/handle_breath(datum/gas_mixture/breath)
if(status_flags & GODMODE)
return
var/breathing_organ = get_bodytype().breathing_organ
if(!breathing_organ)
return

var/obj/item/organ/internal/lungs/L = get_organ(breathing_organ, /obj/item/organ/internal/lungs)
if(!L || nervous_system_failure())
failed_last_breath = 1
else
failed_last_breath = L.handle_breath(breath) //if breath is null or vacuum, the lungs will handle it for us
return !failed_last_breath

/mob/living/carbon/human/handle_environment(datum/gas_mixture/environment)

..()
Expand Down
3 changes: 0 additions & 3 deletions code/modules/mob/living/carbon/life.dm
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@
germ_level++

if(stat != DEAD && !is_in_stasis())
//Breathing, if applicable
handle_breathing()

//Mutations and radiation
handle_mutations_and_radiation()

Expand Down
5 changes: 2 additions & 3 deletions code/modules/mob/living/life.dm
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
handle_environment(loc.return_air())

if(stat != DEAD && !is_in_stasis())
//Breathing, if applicable
handle_breathing()
handle_nutrition_and_hydration()
handle_immunity()
//Body temperature adjusts itself (self-regulation)
Expand Down Expand Up @@ -79,9 +81,6 @@
if(thirst_factor)
adjust_hydration(-(thirst_factor))

/mob/living/proc/handle_breathing()
return

#define RADIATION_SPEED_COEFFICIENT 0.025
/mob/living/proc/handle_mutations_and_radiation()
SHOULD_CALL_PARENT(TRUE)
Expand Down
8 changes: 7 additions & 1 deletion code/modules/mob/living/living.dm
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,13 @@ default behaviour is:
. -= 3

/mob/living/can_drown()
return TRUE
if(get_internals())
return FALSE
var/obj/item/clothing/mask/mask = get_equipped_item(slot_wear_mask_str)
if(istype(mask) && mask.filters_water())
return FALSE
var/obj/item/organ/internal/lungs/L = get_organ(BP_LUNGS, /obj/item/organ/internal/lungs)
return (!L || L.can_drown())

/mob/living/handle_drowning()
var/turf/T = get_turf(src)
Expand Down
Loading

0 comments on commit a52c5df

Please sign in to comment.