mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-28 15:39:57 +01:00
Splitting human life into organs + removes the advanced operating table (#7473)
This commit is contained in:
@@ -9,7 +9,6 @@ var/const/BLOOD_VOLUME_BAD = 224
|
||||
var/const/BLOOD_VOLUME_SURVIVE = 122
|
||||
|
||||
/mob/living/carbon/human/var/datum/reagents/vessel //Container for blood and BLOOD ONLY. Do not transfer other chems here.
|
||||
/mob/living/carbon/human/var/var/pale = 0 //Should affect how mob sprite is drawn, but currently doesn't.
|
||||
|
||||
//Initializes blood vessels
|
||||
/mob/living/carbon/human/proc/make_blood()
|
||||
@@ -43,140 +42,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
|
||||
)
|
||||
B.color = B.data["blood_colour"]
|
||||
|
||||
// Takes care blood loss and regeneration
|
||||
/mob/living/carbon/human/handle_blood()
|
||||
if(in_stasis)
|
||||
return
|
||||
|
||||
if(species && species.flags & NO_BLOOD)
|
||||
return
|
||||
|
||||
if(stat != DEAD && bodytemperature >= 170) //Dead or cryosleep people do not pump the blood.
|
||||
var/blood_volume = round(vessel.get_reagent_amount("blood"))
|
||||
|
||||
//Blood regeneration if there is some space
|
||||
if(blood_volume < BLOOD_VOLUME_NORMAL && blood_volume)
|
||||
var/datum/reagent/blood/B = locate() in vessel.reagent_list //Grab some blood
|
||||
if(B) // Make sure there's some blood at all
|
||||
if(weakref && B.data["donor"] != weakref) //If it's not theirs, then we look for theirs - donor is a weakref here, but it should be safe to just directly compare it.
|
||||
for(var/datum/reagent/blood/D in vessel.reagent_list)
|
||||
if(weakref && D.data["donor"] == weakref)
|
||||
B = D
|
||||
break
|
||||
|
||||
B.volume += 0.1 // regenerate blood VERY slowly
|
||||
if(blood_volume <= BLOOD_VOLUME_SAFE) //We loose nutrition and hydration very slowly if our blood is too low
|
||||
adjustNutritionLoss(2)
|
||||
adjustHydrationLoss(1)
|
||||
if(CE_BLOODRESTORE in chem_effects)
|
||||
B.volume += chem_effects[CE_BLOODRESTORE]
|
||||
|
||||
//The heartfix to end all heartfixes
|
||||
if(species && species.has_organ[BP_HEART])
|
||||
var/obj/item/organ/internal/heart/heart = internal_organs_by_name[BP_HEART]
|
||||
// Before we do that, we check for lifesupport.
|
||||
var/onlifesupport = 0
|
||||
if (buckled && istype(buckled, /obj/machinery/optable/lifesupport))
|
||||
var/obj/machinery/optable/lifesupport/A = buckled
|
||||
onlifesupport = A.onlifesupport()
|
||||
|
||||
|
||||
if (!onlifesupport)
|
||||
if(!heart)
|
||||
blood_volume = 0
|
||||
else if (heart.is_damaged())
|
||||
blood_volume = min(BLOOD_VOLUME_SAFE - 1,blood_volume)
|
||||
blood_volume = (BLOOD_VOLUME_SURVIVE + (BLOOD_VOLUME_NORMAL-BLOOD_VOLUME_SURVIVE) * max(1 - heart.damage/heart.min_broken_damage,0)) * (blood_volume/BLOOD_VOLUME_NORMAL)
|
||||
|
||||
//Effects of bloodloss
|
||||
if(blood_volume < BLOOD_VOLUME_SAFE && oxyloss < 100 * (1 - blood_volume/BLOOD_VOLUME_NORMAL))
|
||||
oxyloss += 3
|
||||
|
||||
switch(blood_volume)
|
||||
if(BLOOD_VOLUME_SAFE to 10000)
|
||||
if(pale)
|
||||
pale = 0
|
||||
update_body()
|
||||
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
|
||||
if(!pale)
|
||||
pale = 1
|
||||
update_body()
|
||||
var/word = pick("dizzy","woosey","faint")
|
||||
to_chat(src, "<span class='warning'>You feel [word]...</span>")
|
||||
if(prob(1))
|
||||
var/word = pick("dizzy","woosey","faint")
|
||||
to_chat(src, "<span class='warning'>You feel [word]...</span>")
|
||||
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
|
||||
if(!pale)
|
||||
pale = 1
|
||||
update_body()
|
||||
eye_blurry = max(eye_blurry,6)
|
||||
oxyloss += 1
|
||||
if(prob(15))
|
||||
Paralyse(rand(1,3))
|
||||
var/word = pick("dizzy","woosey","faint")
|
||||
to_chat(src, "<span class='warning'>You feel extremely [word]...</span>")
|
||||
if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
|
||||
oxyloss += 3
|
||||
toxloss += 3
|
||||
if(prob(15))
|
||||
var/word = pick("dizzy","woosey","faint")
|
||||
to_chat(src, "<span class='warning'>You feel extremely [word]...</span>")
|
||||
if(0 to BLOOD_VOLUME_SURVIVE)
|
||||
// There currently is a strange bug here. If the mob is not below -100 health
|
||||
// when death() is called, apparently they will be just fine, and this way it'll
|
||||
// spam deathgasp. Adjusting toxloss ensures the mob will stay dead.
|
||||
toxloss += 300 // just to be safe!
|
||||
death()
|
||||
|
||||
//Bleeding out
|
||||
var/blood_max = 0
|
||||
var/open_wound
|
||||
var/list/do_spray = list()
|
||||
for(var/obj/item/organ/external/temp in organs)
|
||||
if(!(temp.status & ORGAN_BLEEDING) || temp.status & ORGAN_ROBOT)
|
||||
continue
|
||||
for(var/datum/wound/W in temp.wounds)
|
||||
if(W.bleeding())
|
||||
open_wound = TRUE
|
||||
if(temp.applied_pressure)
|
||||
if(ishuman(temp.applied_pressure))
|
||||
var/mob/living/carbon/human/H = temp.applied_pressure
|
||||
H.bloody_hands(src, 0)
|
||||
var/min_eff_damage = max(0, W.damage - 10) / 6
|
||||
blood_max += max(min_eff_damage, W.damage - 30) / 40
|
||||
else
|
||||
blood_max += ((W.damage / 40) * species.bleed_mod)
|
||||
if(temp.status & ORGAN_ARTERY_CUT)
|
||||
var/bleed_amount = Floor(vessel.total_volume / (temp.applied_pressure || !open_wound ? 450 : 300))
|
||||
if(bleed_amount)
|
||||
if(open_wound)
|
||||
blood_max += bleed_amount
|
||||
do_spray += temp.name
|
||||
else
|
||||
blood_max += W.damage / 40
|
||||
if (temp.open)
|
||||
blood_max += 2 * species.bleed_mod //Yer stomach is cut open
|
||||
|
||||
if(world.time >= next_blood_squirt && istype(loc, /turf) && do_spray.len)
|
||||
visible_message("<span class='danger'>Blood squirts from \the [src]'s [pick(do_spray)]!</span>", "<span class='danger'><font size='3'>Blood is squirting out of your [pick(do_spray)]!</font></span>")
|
||||
eye_blurry = 2
|
||||
Stun(1)
|
||||
next_blood_squirt = world.time + 100
|
||||
var/turf/sprayloc = get_turf(src)
|
||||
blood_max -= drip(Ceiling(blood_max/3), sprayloc)
|
||||
if(blood_max > 0)
|
||||
blood_max -= blood_squirt(blood_max, sprayloc)
|
||||
if(blood_max > 0)
|
||||
drip(blood_max, get_turf(src))
|
||||
else
|
||||
drip(blood_max)
|
||||
|
||||
/mob/living/carbon/human
|
||||
var/next_blood_squirt = 0
|
||||
|
||||
//Makes a blood drop, leaking amt units of blood from the mob
|
||||
|
||||
/mob/living/carbon/human/proc/drip(var/amt as num, var/tar = src, var/spraydir)
|
||||
|
||||
if(species && species.flags & NO_BLOOD) //TODO: Make drips come from the reagents instead.
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/obj/item/organ/internal/brain
|
||||
name = "brain"
|
||||
health = 400 //They need to live awhile longer than other organs. Is this even used by organ code anymore?
|
||||
desc = "A piece of juicy meat found in a person's head."
|
||||
organ_tag = BP_BRAIN
|
||||
parent_organ = BP_HEAD
|
||||
vital = 1
|
||||
icon_state = "brain"
|
||||
force = 1.0
|
||||
w_class = 2.0
|
||||
throwforce = 1.0
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
origin_tech = list(TECH_BIO = 3)
|
||||
attack_verb = list("attacked", "slapped", "whacked")
|
||||
var/mob/living/carbon/brain/brainmob = null
|
||||
var/list/datum/brain_trauma/traumas = list()
|
||||
var/lobotomized = 0
|
||||
var/can_lobotomize = 1
|
||||
|
||||
/obj/item/organ/internal/brain/process()
|
||||
..()
|
||||
|
||||
if(!owner)
|
||||
return
|
||||
|
||||
if(lobotomized && (owner.getBrainLoss() < 40)) //lobotomized brains cannot be healed with chemistry. Part of the brain is irrevocably missing. Can be fixed magically with cloning, ofc.
|
||||
owner.setBrainLoss(40)
|
||||
|
||||
for(var/T in owner.get_traumas())
|
||||
var/datum/brain_trauma/BT = T
|
||||
if(!BT.suppressed)
|
||||
BT.on_life()
|
||||
|
||||
var/blood_volume = round(owner.vessel.get_reagent_amount("blood"))
|
||||
switch(blood_volume)
|
||||
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
|
||||
var/word = pick("dizzy","woosey","faint")
|
||||
to_chat(owner, "<span class='warning'>You feel [word]...</span>")
|
||||
if(prob(1))
|
||||
word = pick("dizzy","woosey","faint")
|
||||
to_chat(owner, "<span class='warning'>You feel [word]...</span>")
|
||||
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
|
||||
owner.eye_blurry = max(owner.eye_blurry,6)
|
||||
owner.oxyloss += 1
|
||||
if(prob(15))
|
||||
owner.Paralyse(rand(1,3))
|
||||
var/word = pick("dizzy","woosey","faint")
|
||||
to_chat(owner, "<span class='warning'>You feel extremely [word]...</span>")
|
||||
if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
|
||||
owner.oxyloss += 3
|
||||
owner.toxloss += 3
|
||||
if(prob(15))
|
||||
var/word = pick("dizzy","woosey","faint")
|
||||
to_chat(owner, "<span class='warning'>You feel extremely [word]...</span>")
|
||||
if(0 to BLOOD_VOLUME_SURVIVE)
|
||||
// There currently is a strange bug here. If the mob is not below -100 health
|
||||
// when death() is called, apparently they will be just fine, and this way it'll
|
||||
// spam deathgasp. Adjusting toxloss ensures the mob will stay dead.
|
||||
owner.toxloss += 300 // just to be safe!
|
||||
owner.death()
|
||||
|
||||
if(owner.species.has_organ[BP_HEART]) //This is where the bad times start if you have no heart.
|
||||
var/obj/item/organ/internal/heart/H = owner.internal_organs_by_name[BP_HEART]
|
||||
if(!istype(H))
|
||||
var/damprob
|
||||
owner.eye_blurry = max(owner.eye_blurry,6)
|
||||
damprob = owner.chem_effects[CE_STABLE] ? 80 : 100
|
||||
if(prob(10))
|
||||
to_chat(owner, "<span class='danger'><font size=3>You jerk and gasp for breath, yet you still feel like you're suffocating!</font></span>")
|
||||
owner.emote("jerks and gasps!")
|
||||
if(prob(damprob))
|
||||
owner.adjustOxyLoss(15)
|
||||
|
||||
|
||||
@@ -6,10 +6,149 @@
|
||||
dead_icon = "heart-off"
|
||||
robotic_name = "circulatory pump"
|
||||
robotic_sprite = "heart-prosthetic"
|
||||
var/pulse = PULSE_NORM //current pulse level
|
||||
var/heartbeat = 0
|
||||
var/next_blood_squirt = 0
|
||||
|
||||
/obj/item/organ/internal/heart/process()
|
||||
//Check if we're on lifesupport, and whether or not organs should be processing.
|
||||
if(owner && owner.isonlifesupport())
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
if(owner)
|
||||
handle_pulse()
|
||||
if(pulse)
|
||||
handle_heartbeat()
|
||||
handle_blood()
|
||||
..()
|
||||
|
||||
/obj/item/organ/internal/heart/proc/handle_pulse()
|
||||
if((species && species.flags & NO_BLOOD)) //No heart, no pulse, buddy.
|
||||
pulse = PULSE_NONE
|
||||
|
||||
var/temp = PULSE_NORM
|
||||
|
||||
if(round(owner.vessel.get_reagent_amount("blood")) <= BLOOD_VOLUME_BAD) //how much blood do we have
|
||||
temp = PULSE_THREADY //not enough :(
|
||||
|
||||
if(owner.status_flags & FAKEDEATH)
|
||||
temp = PULSE_NONE //pretend that we're dead. unlike actual death, can be inflienced by meds
|
||||
|
||||
//handles different chems' influence on pulse
|
||||
for(var/datum/reagent/R in owner.reagents.reagent_list)
|
||||
if(R.id in bradycardics)
|
||||
if(temp <= PULSE_THREADY && temp >= PULSE_NORM)
|
||||
temp--
|
||||
if(R.id in tachycardics)
|
||||
if(temp <= PULSE_FAST && temp >= PULSE_NONE)
|
||||
temp++
|
||||
if(R.id in heartstopper) //To avoid using fakedeath
|
||||
if(rand(0,6) == 3)
|
||||
take_internal_damage(5)
|
||||
if(R.id in cheartstopper) //Conditional heart-stoppage
|
||||
if(R.volume >= R.overdose)
|
||||
if(rand(0,6) == 3)
|
||||
take_internal_damage(5)
|
||||
|
||||
pulse = temp
|
||||
|
||||
/obj/item/organ/internal/heart/proc/handle_heartbeat()
|
||||
if(pulse == PULSE_NONE || !owner.species.has_organ[BP_HEART])
|
||||
return
|
||||
|
||||
if(!src || status & ORGAN_ROBOT)
|
||||
return
|
||||
|
||||
if(pulse >= PULSE_2FAST || owner.shock_stage >= 10 || istype(get_turf(src), /turf/space))
|
||||
//PULSE_THREADY - maximum value for pulse, currently it 5.
|
||||
//High pulse value corresponds to a fast rate of heartbeat.
|
||||
//Divided by 2, otherwise it is too slow.
|
||||
var/rate = (PULSE_THREADY - pulse) / 2
|
||||
|
||||
if(heartbeat >= rate)
|
||||
heartbeat = 0
|
||||
sound_to(owner, sound('sound/effects/singlebeat.ogg', 0, 0, 0, 50))
|
||||
else
|
||||
heartbeat++
|
||||
|
||||
/obj/item/organ/internal/heart/proc/handle_blood()
|
||||
if(owner.in_stasis)
|
||||
return
|
||||
|
||||
if(owner.species && owner.species.flags & NO_BLOOD)
|
||||
return
|
||||
|
||||
if(owner.stat == DEAD && owner.bodytemperature < 170) //Dead or cryosleep people do not pump the blood.
|
||||
return
|
||||
|
||||
if(pulse != PULSE_NONE || BP_IS_ROBOTIC(src))
|
||||
var/blood_volume = round(owner.vessel.get_reagent_amount("blood"))
|
||||
|
||||
//Blood regeneration if there is some space
|
||||
if(blood_volume < BLOOD_VOLUME_NORMAL && blood_volume)
|
||||
var/datum/reagent/blood/B = locate() in owner.vessel.reagent_list //Grab some blood
|
||||
if(B) // Make sure there's some blood at all
|
||||
if(weakref && B.data["donor"] != weakref) //If it's not theirs, then we look for theirs - donor is a weakref here, but it should be safe to just directly compare it.
|
||||
for(var/datum/reagent/blood/D in owner.vessel.reagent_list)
|
||||
if(weakref && D.data["donor"] == weakref)
|
||||
B = D
|
||||
break
|
||||
|
||||
B.volume += 0.1 // regenerate blood VERY slowly
|
||||
if(blood_volume <= BLOOD_VOLUME_SAFE) //We loose nutrition and hydration very slowly if our blood is too low
|
||||
owner.adjustNutritionLoss(2)
|
||||
owner.adjustHydrationLoss(1)
|
||||
if(CE_BLOODRESTORE in owner.chem_effects)
|
||||
B.volume += owner.chem_effects[CE_BLOODRESTORE]
|
||||
|
||||
//Effects of bloodloss
|
||||
if(blood_volume < BLOOD_VOLUME_SAFE && owner.oxyloss < 100 * (1 - blood_volume/BLOOD_VOLUME_NORMAL))
|
||||
owner.oxyloss += 3
|
||||
|
||||
//Bleeding out
|
||||
var/blood_max = 0
|
||||
var/open_wound
|
||||
var/list/do_spray = list()
|
||||
for(var/obj/item/organ/external/temp in owner.organs)
|
||||
if((temp.status & ORGAN_BLEEDING) && !BP_IS_ROBOTIC(temp))
|
||||
for(var/datum/wound/W in temp.wounds)
|
||||
if(W.bleeding())
|
||||
open_wound = TRUE
|
||||
if(temp.applied_pressure)
|
||||
if(ishuman(temp.applied_pressure))
|
||||
var/mob/living/carbon/human/H = temp.applied_pressure
|
||||
H.bloody_hands(src, 0)
|
||||
var/min_eff_damage = max(0, W.damage - 10) / 6
|
||||
blood_max += max(min_eff_damage, W.damage - 30) / 40
|
||||
else
|
||||
blood_max += ((W.damage / 40) * species.bleed_mod)
|
||||
|
||||
if(temp.status & ORGAN_ARTERY_CUT)
|
||||
var/bleed_amount = Floor(owner.vessel.total_volume / (temp.applied_pressure || !open_wound ? 450 : 300))
|
||||
if(bleed_amount)
|
||||
if(open_wound)
|
||||
blood_max += bleed_amount
|
||||
do_spray += "[temp.name]"
|
||||
else
|
||||
owner.vessel.remove_reagent("blood", bleed_amount)
|
||||
|
||||
switch(pulse)
|
||||
if(PULSE_SLOW)
|
||||
blood_max *= 0.8
|
||||
if(PULSE_FAST)
|
||||
blood_max *= 1.25
|
||||
if(PULSE_2FAST, PULSE_THREADY)
|
||||
blood_max *= 1.5
|
||||
|
||||
if(CE_STABLE in owner.chem_effects)
|
||||
blood_max *= 0.8
|
||||
|
||||
if(world.time >= next_blood_squirt && istype(owner.loc, /turf) && do_spray.len)
|
||||
owner.visible_message("<span class='danger'>Blood squirts from \the [owner]'s [pick(do_spray)]!</span>", "<span class='danger'><font size='3'>Blood is squirting out of your [pick(do_spray)]!</font></span>")
|
||||
owner.eye_blurry = 2
|
||||
owner.Stun(1)
|
||||
next_blood_squirt = world.time + 100
|
||||
var/turf/sprayloc = get_turf(src)
|
||||
blood_max -= owner.drip(Ceiling(blood_max/3), sprayloc)
|
||||
if(blood_max > 0)
|
||||
blood_max -= owner.blood_squirt(blood_max, sprayloc)
|
||||
if(blood_max > 0)
|
||||
owner.drip(blood_max, get_turf(src))
|
||||
else
|
||||
owner.drip(blood_max)
|
||||
@@ -1,3 +1,6 @@
|
||||
#define HUMAN_MAX_OXYLOSS 1 //Defines how much oxyloss humans can get per tick. A tile with no air at all (such as space) applies this value, otherwise it's a percentage of it.
|
||||
#define HUMAN_CRIT_MAX_OXYLOSS ( 2.0 / 6) //The amount of damage you'll get when in critical condition. We want this to be a 5 minute deal = 300s. There are 50HP to get through, so (1/6)*last_tick_duration per second. Breaths however only happen every 4 ticks. last_tick_duration = ~2.0 on average
|
||||
|
||||
/obj/item/organ/internal/lungs
|
||||
name = "lungs"
|
||||
icon_state = "lungs"
|
||||
@@ -30,4 +33,233 @@
|
||||
if(prob(4))
|
||||
to_chat(owner, span("warning", "It feels hard to breathe..."))
|
||||
if (owner.losebreath < 5)
|
||||
owner.losebreath = min(owner.losebreath + 1, 5) // it's still not good, but it's much better than an untreated collapsed lung
|
||||
owner.losebreath = min(owner.losebreath + 1, 5) // it's still not good, but it's much better than an untreated collapsed lung
|
||||
|
||||
/obj/item/organ/internal/lungs/proc/handle_breath(datum/gas_mixture/breath)
|
||||
if(!owner)
|
||||
return 1
|
||||
|
||||
//exposure to extreme pressures can rupture lungs
|
||||
if(breath && (breath.total_moles/(owner.species?.breath_vol_mul || 1) < BREATH_MOLES / 5 || breath.total_moles/(owner.species?.breath_vol_mul || 1) > BREATH_MOLES * 5))
|
||||
if(!is_bruised() && prob(5))
|
||||
bruise()
|
||||
|
||||
//check if we actually need to process breath
|
||||
if(!breath || (breath.total_moles == 0))
|
||||
owner.failed_last_breath = 1
|
||||
if(owner.health > config.health_threshold_crit)
|
||||
owner.adjustOxyLoss(HUMAN_MAX_OXYLOSS)
|
||||
else
|
||||
owner.adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS)
|
||||
|
||||
owner.oxygen_alert = max(owner.oxygen_alert, 1)
|
||||
return 0
|
||||
|
||||
var/safe_pressure_min = owner.species.breath_pressure // Minimum safe partial pressure of breathable gas in kPa
|
||||
|
||||
if(is_broken())
|
||||
safe_pressure_min *= 1.5
|
||||
else if(is_bruised())
|
||||
safe_pressure_min *= 1.25
|
||||
|
||||
var/safe_exhaled_max = 10
|
||||
var/safe_toxins_max = 0.2
|
||||
var/SA_para_min = 1
|
||||
var/SA_sleep_min = 5
|
||||
var/inhaled_gas_used = 0
|
||||
|
||||
var/breath_pressure = (breath.total_moles*R_IDEAL_GAS_EQUATION*breath.temperature)/(BREATH_VOLUME * owner.species.breath_vol_mul)
|
||||
|
||||
var/inhaling
|
||||
var/poison
|
||||
var/exhaling
|
||||
|
||||
var/breath_type
|
||||
var/poison_type
|
||||
var/exhale_type
|
||||
|
||||
var/failed_inhale = 0
|
||||
var/failed_exhale = 0
|
||||
|
||||
if(owner.species.breath_type)
|
||||
breath_type = species.breath_type
|
||||
else
|
||||
breath_type = "oxygen"
|
||||
|
||||
inhaling = breath.gas[breath_type]
|
||||
|
||||
if(owner.species.poison_type)
|
||||
poison_type = species.poison_type
|
||||
else
|
||||
poison_type = "phoron"
|
||||
poison = breath.gas[poison_type]
|
||||
|
||||
if(owner.species.exhale_type)
|
||||
exhale_type = species.exhale_type
|
||||
exhaling = breath.gas[exhale_type]
|
||||
else
|
||||
exhaling = 0
|
||||
|
||||
var/inhale_pp = (inhaling/breath.total_moles)*breath_pressure
|
||||
var/toxins_pp = (poison/breath.total_moles)*breath_pressure
|
||||
var/exhaled_pp = (exhaling/breath.total_moles)*breath_pressure
|
||||
|
||||
// Not enough to breathe
|
||||
if(inhale_pp < safe_pressure_min)
|
||||
if(prob(20))
|
||||
spawn(0)
|
||||
owner.emote("gasp")
|
||||
|
||||
var/ratio = inhale_pp/safe_pressure_min
|
||||
// Don't fuck them up too fast (space only does HUMAN_MAX_OXYLOSS after all!)
|
||||
owner.adjustOxyLoss(max(HUMAN_MAX_OXYLOSS*(1-ratio), 0))
|
||||
failed_inhale = 1
|
||||
|
||||
owner.oxygen_alert = max(owner.oxygen_alert, 1)
|
||||
else
|
||||
// We're in safe limits
|
||||
owner.oxygen_alert = 0
|
||||
|
||||
inhaled_gas_used = inhaling/6 * (owner.species?.breath_eff_mul || 1)
|
||||
|
||||
breath.adjust_gas(breath_type, -inhaled_gas_used, update = 0) //update afterwards
|
||||
|
||||
if(exhale_type)
|
||||
breath.adjust_gas_temp(exhale_type, inhaled_gas_used, owner.bodytemperature, update = 0) //update afterwards
|
||||
|
||||
// Too much exhaled gas in the air
|
||||
if(exhaled_pp > safe_exhaled_max)
|
||||
if (!owner.co2_alert|| prob(15))
|
||||
var/word = pick("extremely dizzy","short of breath","faint","confused")
|
||||
to_chat(owner, "<span class='danger'>You feel [word].</span>")
|
||||
|
||||
owner.adjustOxyLoss(HUMAN_MAX_OXYLOSS)
|
||||
owner.co2_alert = 1
|
||||
failed_exhale = 1
|
||||
|
||||
else if(exhaled_pp > safe_exhaled_max * 0.7)
|
||||
if (!owner.co2_alert || prob(1))
|
||||
var/word = pick("dizzy","short of breath","faint","momentarily confused")
|
||||
to_chat(owner, "<span class='warning'>You feel [word].</span>")
|
||||
|
||||
//scale linearly from 0 to 1 between safe_exhaled_max and safe_exhaled_max*0.7
|
||||
var/ratio = 1.0 - (safe_exhaled_max - exhaled_pp)/(safe_exhaled_max*0.3)
|
||||
|
||||
//give them some oxyloss, up to the limit - we don't want people falling unconcious due to CO2 alone until they're pretty close to safe_exhaled_max.
|
||||
if (owner.getOxyLoss() < 50*ratio)
|
||||
owner.adjustOxyLoss(HUMAN_MAX_OXYLOSS)
|
||||
owner.co2_alert = 1
|
||||
failed_exhale = 1
|
||||
|
||||
else if(exhaled_pp > safe_exhaled_max * 0.6)
|
||||
if (prob(0.3))
|
||||
var/word = pick("a little dizzy","short of breath")
|
||||
to_chat(owner, "<span class='warning'>You feel [word].</span>")
|
||||
|
||||
else
|
||||
owner.co2_alert = 0
|
||||
|
||||
// Too much poison in the air.
|
||||
if(toxins_pp > safe_toxins_max)
|
||||
var/ratio = (poison/safe_toxins_max) * 10
|
||||
if(reagents)
|
||||
reagents.add_reagent("toxin", Clamp(ratio, MIN_TOXIN_DAMAGE, MAX_TOXIN_DAMAGE))
|
||||
breath.adjust_gas(poison_type, -poison/6, update = 0) //update after
|
||||
owner.phoron_alert = max(owner.phoron_alert, 1)
|
||||
else
|
||||
owner.phoron_alert = 0
|
||||
|
||||
// If there's some other shit in the air lets deal with it here.
|
||||
if(breath.gas["sleeping_agent"])
|
||||
var/SA_pp = (breath.gas["sleeping_agent"] / breath.total_moles) * breath_pressure
|
||||
|
||||
// Enough to make us paralysed for a bit
|
||||
if(SA_pp > SA_para_min)
|
||||
|
||||
// 3 gives them one second to wake up and run away a bit!
|
||||
owner.Paralyse(3)
|
||||
|
||||
// Enough to make us sleep as well
|
||||
if(SA_pp > SA_sleep_min)
|
||||
owner.Sleeping(10)
|
||||
|
||||
// There is sleeping gas in their lungs, but only a little, so give them a bit of a warning
|
||||
else if(SA_pp > 0.15)
|
||||
if(prob(20))
|
||||
spawn(0)
|
||||
owner.emote(pick("giggle", "laugh"))
|
||||
breath.adjust_gas("sleeping_agent", -breath.gas["sleeping_agent"]/6, update = 0) //update after
|
||||
|
||||
// Were we able to breathe?
|
||||
if (failed_inhale || failed_exhale)
|
||||
owner.failed_last_breath = 1
|
||||
else
|
||||
owner.failed_last_breath = 0
|
||||
if(owner.disabilities & ASTHMA)
|
||||
owner.adjustOxyLoss(rand(-5,0))
|
||||
else
|
||||
owner.adjustOxyLoss(-5)
|
||||
|
||||
|
||||
// Hot air hurts :(
|
||||
handle_temperature_effects(breath)
|
||||
|
||||
breath.update_values()
|
||||
|
||||
var/failed_breath = failed_inhale || failed_exhale
|
||||
|
||||
return failed_breath
|
||||
|
||||
/obj/item/organ/internal/lungs/proc/handle_temperature_effects(datum/gas_mixture/breath)
|
||||
if((breath.temperature < species.cold_level_1 || breath.temperature > species.heat_level_1) && !(COLD_RESISTANCE in owner.mutations))
|
||||
|
||||
if(breath.temperature <= owner.species.cold_level_1)
|
||||
if(prob(20))
|
||||
to_chat(owner, "<span class='danger'>You feel your face freezing and icicles forming in your lungs!</span>")
|
||||
else if(breath.temperature >= owner.species.heat_level_1)
|
||||
if(prob(20))
|
||||
to_chat(owner, "<span class='danger'>You feel your face burning and a searing heat in your lungs!</span>")
|
||||
|
||||
if(breath.temperature >= owner.species.heat_level_1)
|
||||
if(breath.temperature < owner.species.heat_level_2)
|
||||
owner.apply_damage(HEAT_GAS_DAMAGE_LEVEL_1, BURN, BP_HEAD, used_weapon = "Excessive Heat")
|
||||
owner.fire_alert = max(owner.fire_alert, 2)
|
||||
else if(breath.temperature < species.heat_level_3)
|
||||
owner.apply_damage(HEAT_GAS_DAMAGE_LEVEL_2, BURN, BP_HEAD, used_weapon = "Excessive Heat")
|
||||
owner.fire_alert = max(owner.fire_alert, 2)
|
||||
else
|
||||
owner.apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, BP_HEAD, used_weapon = "Excessive Heat")
|
||||
owner.fire_alert = max(owner.fire_alert, 2)
|
||||
|
||||
else if(breath.temperature <= owner.species.cold_level_1)
|
||||
if(breath.temperature > species.cold_level_2)
|
||||
owner.apply_damage(COLD_GAS_DAMAGE_LEVEL_1, BURN, BP_HEAD, used_weapon = "Excessive Cold")
|
||||
owner.fire_alert = max(owner.fire_alert, 1)
|
||||
else if(breath.temperature > species.cold_level_3)
|
||||
owner.apply_damage(COLD_GAS_DAMAGE_LEVEL_2, BURN, BP_HEAD, used_weapon = "Excessive Cold")
|
||||
owner.fire_alert = max(owner.fire_alert, 1)
|
||||
else
|
||||
owner.apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, BP_HEAD, used_weapon = "Excessive Cold")
|
||||
owner.fire_alert = max(owner.fire_alert, 1)
|
||||
|
||||
//breathing in hot/cold air also heats/cools you a bit
|
||||
var/temp_adj = breath.temperature - owner.bodytemperature
|
||||
if (temp_adj < 0)
|
||||
temp_adj /= (BODYTEMP_COLD_DIVISOR * 5) //don't raise temperature as much as if we were directly exposed
|
||||
else
|
||||
temp_adj /= (BODYTEMP_HEAT_DIVISOR * 5) //don't raise temperature as much as if we were directly exposed
|
||||
|
||||
var/relative_density = breath.total_moles / (MOLES_CELLSTANDARD * BREATH_PERCENTAGE)
|
||||
temp_adj *= relative_density
|
||||
|
||||
if (temp_adj > BODYTEMP_HEATING_MAX) temp_adj = BODYTEMP_HEATING_MAX
|
||||
if (temp_adj < BODYTEMP_COOLING_MAX) temp_adj = BODYTEMP_COOLING_MAX
|
||||
owner.bodytemperature += temp_adj
|
||||
|
||||
else if(breath.temperature >= owner.species.heat_discomfort_level)
|
||||
owner.species.get_environment_discomfort(src,"heat")
|
||||
else if(breath.temperature <= owner.species.cold_discomfort_level)
|
||||
owner.species.get_environment_discomfort(src,"cold")
|
||||
|
||||
#undef HUMAN_MAX_OXYLOSS
|
||||
#undef HUMAN_CRIT_MAX_OXYLOSS
|
||||
@@ -363,9 +363,6 @@
|
||||
owner.update_action_buttons()
|
||||
owner = null
|
||||
|
||||
if(!owner.isonlifesupport())
|
||||
owner.death()
|
||||
|
||||
/obj/item/organ/proc/replaced(var/mob/living/carbon/human/target,var/obj/item/organ/external/affected)
|
||||
|
||||
if(!istype(target)) return
|
||||
|
||||
Reference in New Issue
Block a user