mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-24 21:40:55 +01:00
@@ -4,6 +4,8 @@
|
||||
/obj/item/organ/internal
|
||||
var/dead_icon // Icon to use when the organ has died.
|
||||
var/damage_reduction = 0.5 //modifier for internal organ injury
|
||||
var/toxin_type = "undefined"
|
||||
var/relative_size = 25 //Used for size calcs
|
||||
|
||||
min_broken_damage = 10 //Internal organs are frail, man.
|
||||
|
||||
@@ -42,9 +44,15 @@
|
||||
if((status & ORGAN_DEAD) && dead_icon)
|
||||
icon_state = dead_icon
|
||||
|
||||
/obj/item/organ/internal/proc/is_usable()
|
||||
/obj/item/organ/internal/proc/surgical_fix() //to be used for scarring -mattatlas
|
||||
heal_damage(damage)
|
||||
|
||||
/obj/item/organ/internal/is_usable()
|
||||
return ..() && !is_broken()
|
||||
|
||||
/obj/item/organ/internal/proc/is_damaged()
|
||||
return damage > 0
|
||||
|
||||
/obj/item/organ/internal/robotize()
|
||||
..()
|
||||
min_bruised_damage += 5
|
||||
@@ -75,7 +83,7 @@
|
||||
degree = " a lot"
|
||||
if(damage < 5)
|
||||
degree = " a bit"
|
||||
owner.custom_pain("Something inside your [parent.name] hurts[degree].", amount, affecting = parent)
|
||||
owner.custom_pain("Something inside your [parent.name] hurts[degree].", amount)
|
||||
|
||||
/obj/item/organ/internal/proc/get_visible_state()
|
||||
if(damage > max_damage)
|
||||
@@ -95,10 +103,12 @@
|
||||
|
||||
/obj/item/organ/internal/process()
|
||||
..()
|
||||
if(istype(owner) && (toxin_type in owner.chem_effects))
|
||||
take_damage(owner.chem_effects[toxin_type] * 0.1 * PROCESS_ACCURACY, prob(1))
|
||||
handle_regeneration()
|
||||
|
||||
/obj/item/organ/internal/proc/handle_regeneration()
|
||||
if(!damage || BP_IS_ROBOTIC(src) || !owner || owner.chem_effects[CE_TOXIN])
|
||||
if(!damage || BP_IS_ROBOTIC(src) || !owner || owner.chem_effects[CE_TOXIN] || owner.is_asystole())
|
||||
return
|
||||
if(damage < 0.1*max_damage)
|
||||
heal_damage(0.02)
|
||||
heal_damage(0.1)
|
||||
@@ -1,10 +1,10 @@
|
||||
/obj/item/organ/appendix
|
||||
/obj/item/organ/internal/appendix
|
||||
name = "appendix"
|
||||
icon_state = "appendix"
|
||||
parent_organ = BP_GROIN
|
||||
organ_tag = "appendix"
|
||||
|
||||
/obj/item/organ/appendix/removed()
|
||||
/obj/item/organ/internal/appendix/removed()
|
||||
if(owner)
|
||||
var/inflamed = 0
|
||||
for(var/datum/disease/appendicitis/appendicitis in owner.viruses)
|
||||
|
||||
@@ -13,62 +13,148 @@
|
||||
throw_range = 5
|
||||
origin_tech = list(TECH_BIO = 3)
|
||||
attack_verb = list("attacked", "slapped", "whacked")
|
||||
toxin_type = CE_NEUROTOXIC
|
||||
|
||||
damage_reduction = 0
|
||||
relative_size = 85
|
||||
|
||||
var/mob/living/carbon/brain/brainmob = null
|
||||
var/list/datum/brain_trauma/traumas = list()
|
||||
var/lobotomized = 0
|
||||
var/can_lobotomize = 1
|
||||
|
||||
var/const/damage_threshold_count = 10
|
||||
var/damage_threshold_value
|
||||
var/healed_threshold = 1
|
||||
var/oxygen_reserve = 6
|
||||
|
||||
/obj/item/organ/internal/brain/can_recover()
|
||||
return ~status & ORGAN_DEAD
|
||||
|
||||
/obj/item/organ/internal/brain/proc/get_current_damage_threshold()
|
||||
return round(damage / damage_threshold_value)
|
||||
|
||||
/obj/item/organ/internal/brain/proc/past_damage_threshold(var/threshold)
|
||||
return (get_current_damage_threshold() > threshold)
|
||||
|
||||
/obj/item/organ/internal/brain/set_max_damage(var/ndamage)
|
||||
..()
|
||||
damage_threshold_value = round(max_damage / damage_threshold_count)
|
||||
|
||||
/obj/item/organ/internal/brain/Initialize(mapload)
|
||||
. = ..()
|
||||
if(species)
|
||||
set_max_damage(species.total_health)
|
||||
else
|
||||
set_max_damage(200)
|
||||
if(!mapload)
|
||||
addtimer(CALLBACK(src, .proc/clear_screen), 5)
|
||||
|
||||
/obj/item/organ/internal/brain/process()
|
||||
if(owner)
|
||||
if(damage > max_damage / 2 && healed_threshold)
|
||||
handle_severe_brain_damage()
|
||||
|
||||
if(damage < (max_damage / 4))
|
||||
healed_threshold = 1
|
||||
|
||||
handle_damage_effects()
|
||||
|
||||
// Brain damage from low oxygenation or lack of blood.
|
||||
if(owner.should_have_organ(BP_HEART))
|
||||
|
||||
// No heart? You are going to have a very bad time. Not 100% lethal because heart transplants should be a thing.
|
||||
var/blood_volume = owner.get_blood_oxygenation()
|
||||
if(blood_volume < BLOOD_VOLUME_SURVIVE)
|
||||
if(!owner.chem_effects[CE_STABLE] || prob(60))
|
||||
oxygen_reserve = max(0, oxygen_reserve-1)
|
||||
else
|
||||
oxygen_reserve = min(initial(oxygen_reserve), oxygen_reserve+1)
|
||||
if(!oxygen_reserve) //(hardcrit)
|
||||
owner.Paralyse(3)
|
||||
var/can_heal = damage && damage < max_damage && (damage % damage_threshold_value || owner.chem_effects[CE_BRAIN_REGEN] || (!past_damage_threshold(3) && owner.chem_effects[CE_STABLE]))
|
||||
var/damprob
|
||||
//Effects of bloodloss
|
||||
switch(blood_volume)
|
||||
|
||||
if(BLOOD_VOLUME_SAFE to INFINITY)
|
||||
if(can_heal)
|
||||
damage = max(damage-1, 0)
|
||||
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
|
||||
if(prob(1))
|
||||
to_chat(owner, "<span class='warning'>You feel [pick("dizzy","woozy","faint")]...</span>")
|
||||
damprob = owner.chem_effects[CE_STABLE] ? 30 : 60
|
||||
if(!past_damage_threshold(2) && prob(damprob))
|
||||
take_internal_damage(1)
|
||||
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
|
||||
owner.eye_blurry = max(owner.eye_blurry,6)
|
||||
damprob = owner.chem_effects[CE_STABLE] ? 40 : 80
|
||||
if(!past_damage_threshold(4) && prob(damprob))
|
||||
take_internal_damage(1)
|
||||
if(!owner.paralysis && prob(10))
|
||||
owner.Paralyse(rand(1,3))
|
||||
to_chat(owner, "<span class='warning'>You feel extremely [pick("dizzy","woozy","faint")]...</span>")
|
||||
if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
|
||||
owner.eye_blurry = max(owner.eye_blurry,6)
|
||||
damprob = owner.chem_effects[CE_STABLE] ? 60 : 100
|
||||
if(!past_damage_threshold(6) && prob(damprob))
|
||||
take_internal_damage(1)
|
||||
if(!owner.paralysis && prob(15))
|
||||
owner.Paralyse(3,5)
|
||||
to_chat(owner, "<span class='warning'>You feel extremely [pick("dizzy","woozy","faint")]...</span>")
|
||||
if(-(INFINITY) to BLOOD_VOLUME_SURVIVE) // Also see heart.dm, being below this point puts you into cardiac arrest.
|
||||
owner.eye_blurry = max(owner.eye_blurry,6)
|
||||
damprob = owner.chem_effects[CE_STABLE] ? 80 : 100
|
||||
if(prob(damprob))
|
||||
take_internal_damage(1)
|
||||
if(prob(damprob))
|
||||
take_internal_damage(1)
|
||||
..()
|
||||
|
||||
/obj/item/organ/internal/brain/take_internal_damage(var/damage, var/silent)
|
||||
set waitfor = 0
|
||||
..()
|
||||
if(damage >= 10) //This probably won't be triggered by oxyloss or mercury. Probably.
|
||||
var/damage_secondary = damage * 0.20
|
||||
owner.eye_blurry += damage_secondary
|
||||
owner.confused += damage_secondary * 2
|
||||
owner.Paralyse(damage_secondary)
|
||||
owner.Weaken(round(damage, 1))
|
||||
if(prob(30))
|
||||
addtimer(CALLBACK(src, .proc/brain_damage_callback, damage), rand(6, 20) SECONDS, TIMER_UNIQUE)
|
||||
|
||||
/obj/item/organ/internal/brain/proc/brain_damage_callback(var/damage) //Confuse them as a somewhat uncommon aftershock. Side note: Only here so a spawn isn't used. Also, for the sake of a unique timer.
|
||||
to_chat(owner, "<span class = 'notice' font size='10'><B>I can't remember which way is forward...</B></span>")
|
||||
owner.confused += damage
|
||||
|
||||
/obj/item/organ/internal/brain/proc/handle_severe_brain_damage()
|
||||
set waitfor = FALSE
|
||||
healed_threshold = 0
|
||||
to_chat(owner, "<span class = 'notice' font size='10'><B>Where am I...?</B></span>")
|
||||
sleep(5 SECONDS)
|
||||
if(!owner)
|
||||
return
|
||||
to_chat(owner, "<span class = 'notice' font size='10'><B>What's going on...?</B></span>")
|
||||
sleep(10 SECONDS)
|
||||
if(!owner)
|
||||
return
|
||||
to_chat(owner, "<span class = 'notice' font size='10'><B>What happened...?</B></span>")
|
||||
alert(owner, "You have taken massive brain damage! You will not be able to remember the events leading up to your injury.", "Brain Damaged")
|
||||
|
||||
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)
|
||||
|
||||
/obj/item/organ/internal/brain/proc/handle_damage_effects()
|
||||
if(owner.stat)
|
||||
return
|
||||
if(damage > 0 && prob(1))
|
||||
owner.custom_pain("Your head feels numb and painful.",10)
|
||||
if(is_bruised() && prob(1) && owner.eye_blurry <= 0)
|
||||
to_chat(owner, "<span class='warning'>It becomes hard to see for some reason.</span>")
|
||||
owner.eye_blurry = 10
|
||||
if(damage >= 0.5*max_damage && prob(1) && owner.get_active_hand())
|
||||
to_chat(owner, "<span class='danger'>Your hand won't respond properly, and you drop what you are holding!</span>")
|
||||
owner.drop_item()
|
||||
if(damage >= 0.6*max_damage)
|
||||
owner.slurring = max(owner.slurring, 2)
|
||||
if(is_broken())
|
||||
if(!owner.lying)
|
||||
to_chat(owner, "<span class='danger'>You black out!</span>")
|
||||
owner.Paralyse(10)
|
||||
@@ -6,6 +6,8 @@
|
||||
parent_organ = BP_HEAD
|
||||
robotic_name = "visual prosthesis"
|
||||
robotic_sprite = "eyes-prosthetic"
|
||||
max_damage = 45
|
||||
relative_size = 5
|
||||
var/list/eye_colour = list(0,0,0)
|
||||
var/singular_name = "eye"
|
||||
|
||||
|
||||
@@ -6,60 +6,98 @@
|
||||
dead_icon = "heart-off"
|
||||
robotic_name = "circulatory pump"
|
||||
robotic_sprite = "heart-prosthetic"
|
||||
toxin_type = CE_CARDIOTOXIC
|
||||
|
||||
max_damage = 45
|
||||
relative_size = 5
|
||||
damage_reduction = 0.7
|
||||
|
||||
var/pulse = PULSE_NORM //current pulse level
|
||||
var/heartbeat = 0
|
||||
var/next_blood_squirt = 0
|
||||
var/list/external_pump
|
||||
|
||||
/obj/item/organ/internal/heart/process()
|
||||
if(owner)
|
||||
handle_pulse()
|
||||
if(pulse)
|
||||
if(pulse == PULSE_2FAST && prob(1))
|
||||
take_internal_damage(0.5)
|
||||
if(pulse == PULSE_THREADY && prob(5))
|
||||
take_internal_damage(0.5)
|
||||
handle_heartbeat()
|
||||
handle_blood()
|
||||
..()
|
||||
|
||||
/obj/item/organ/internal/heart/proc/handle_pulse()
|
||||
if((species && species.flags & NO_BLOOD)) //No heart, no pulse, buddy.
|
||||
if((species && species.flags & NO_BLOOD) || BP_IS_ROBOTIC(src)) //No heart, no pulse, buddy. Or if the heart is robotic.
|
||||
pulse = PULSE_NONE
|
||||
return
|
||||
|
||||
var/temp = PULSE_NORM
|
||||
// pulse mod starts out as just the chemical effect amount
|
||||
var/pulse_mod = owner.chem_effects[CE_PULSE]
|
||||
var/is_stable = owner.chem_effects[CE_STABLE]
|
||||
|
||||
if(round(owner.vessel.get_reagent_amount("blood")) <= BLOOD_VOLUME_BAD) //how much blood do we have
|
||||
temp = PULSE_THREADY //not enough :(
|
||||
// If you have enough heart chemicals to be over 2, you're likely to take extra damage.
|
||||
if(pulse_mod > 2 && !is_stable)
|
||||
var/damage_chance = (pulse_mod - 2) ** 2
|
||||
if(prob(damage_chance))
|
||||
take_internal_damage(0.5)
|
||||
|
||||
if(owner.status_flags & FAKEDEATH)
|
||||
temp = PULSE_NONE //pretend that we're dead. unlike actual death, can be inflienced by meds
|
||||
// Now pulse mod is impacted by shock stage and other things too
|
||||
if(owner.shock_stage > 30)
|
||||
pulse_mod++
|
||||
if(owner.shock_stage > 80)
|
||||
pulse_mod++
|
||||
|
||||
//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)
|
||||
var/oxy = owner.get_blood_oxygenation()
|
||||
if(oxy < BLOOD_VOLUME_OKAY) //brain wants us to get MOAR OXY
|
||||
pulse_mod++
|
||||
if(oxy < BLOOD_VOLUME_BAD) //MOAR
|
||||
pulse_mod++
|
||||
|
||||
pulse = temp
|
||||
if(owner.status_flags & FAKEDEATH || owner.chem_effects[CE_NOPULSE])
|
||||
pulse = Clamp(PULSE_NONE + pulse_mod, PULSE_NONE, PULSE_2FAST) //pretend that we're dead. unlike actual death, can be inflienced by meds
|
||||
return
|
||||
|
||||
//If heart is stopped, it isn't going to restart itself randomly.
|
||||
if(pulse == PULSE_NONE)
|
||||
return
|
||||
else //and if it's beating, let's see if it should
|
||||
var/should_stop = prob(80) && owner.get_blood_circulation() < BLOOD_VOLUME_SURVIVE //cardiovascular shock, not enough liquid to pump
|
||||
should_stop = should_stop || prob(max(0, owner.getBrainLoss() - owner.maxHealth * 0.75)) //brain failing to work heart properly
|
||||
should_stop = should_stop || (prob(5) && pulse == PULSE_THREADY) //erratic heart patterns, usually caused by oxyloss
|
||||
if(should_stop) // The heart has stopped due to going into traumatic or cardiovascular shock.
|
||||
to_chat(owner, "<span class='danger'>Your heart has stopped!</span>")
|
||||
pulse = PULSE_NONE
|
||||
return
|
||||
|
||||
// Pulse normally shouldn't go above PULSE_2FAST
|
||||
pulse = Clamp(PULSE_NORM + pulse_mod, PULSE_SLOW, PULSE_2FAST)
|
||||
|
||||
// If fibrillation, then it can be PULSE_THREADY
|
||||
var/fibrillation = oxy <= BLOOD_VOLUME_SURVIVE || (prob(30) && owner.shock_stage > 120)
|
||||
if(pulse && fibrillation) //I SAID MOAR OXYGEN
|
||||
pulse = PULSE_THREADY
|
||||
|
||||
// Stablising chemicals pull the heartbeat towards the center
|
||||
if(pulse != PULSE_NORM && is_stable)
|
||||
if(pulse > PULSE_NORM)
|
||||
pulse--
|
||||
else
|
||||
pulse++
|
||||
|
||||
/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.
|
||||
if(pulse >= PULSE_2FAST || owner.shock_stage >= 10)
|
||||
//PULSE_THREADY - maximum value for pulse, currently it is 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
|
||||
var/rate = (PULSE_THREADY - pulse)/2
|
||||
switch(owner.chem_effects[CE_PULSE])
|
||||
if(2 to INFINITY)
|
||||
heartbeat++
|
||||
if(-INFINITY to -2)
|
||||
heartbeat--
|
||||
|
||||
if(heartbeat >= rate)
|
||||
heartbeat = 0
|
||||
@@ -68,20 +106,20 @@
|
||||
heartbeat++
|
||||
|
||||
/obj/item/organ/internal/heart/proc/handle_blood()
|
||||
if(owner.in_stasis)
|
||||
if(!owner)
|
||||
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.
|
||||
if(!owner || owner.stat == DEAD || owner.bodytemperature < 170 || owner.in_stasis) //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)
|
||||
if(blood_volume < DEFAULT_BLOOD_SPECIES && 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.
|
||||
@@ -97,10 +135,6 @@
|
||||
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
|
||||
@@ -144,11 +178,17 @@
|
||||
owner.eye_blurry = 2
|
||||
owner.Stun(1)
|
||||
next_blood_squirt = world.time + 100
|
||||
var/turf/sprayloc = get_turf(src)
|
||||
var/turf/sprayloc = get_turf(owner)
|
||||
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))
|
||||
owner.drip(blood_max, get_turf(owner))
|
||||
else
|
||||
owner.drip(blood_max)
|
||||
owner.drip(blood_max)
|
||||
|
||||
/obj/item/organ/internal/heart/proc/is_working()
|
||||
if(!is_usable())
|
||||
return FALSE
|
||||
|
||||
return pulse > PULSE_NONE || BP_IS_ROBOTIC(src) || (owner.status_flags & FAKEDEATH)
|
||||
@@ -6,6 +6,11 @@
|
||||
parent_organ = BP_GROIN
|
||||
robotic_name = "prosthetic kidneys"
|
||||
robotic_sprite = "kidneys-prosthetic"
|
||||
min_bruised_damage = 25
|
||||
min_broken_damage = 45
|
||||
max_damage = 70
|
||||
relative_size = 10
|
||||
toxin_type = CE_NEPHROTOXIC
|
||||
|
||||
/obj/item/organ/internal/kidneys/process()
|
||||
|
||||
@@ -22,4 +27,19 @@
|
||||
if(is_bruised())
|
||||
owner.adjustToxLoss(0.1 * PROCESS_ACCURACY)
|
||||
else if(is_broken())
|
||||
owner.adjustToxLoss(0.3 * PROCESS_ACCURACY)
|
||||
owner.adjustToxLoss(0.3 * PROCESS_ACCURACY)
|
||||
|
||||
if(is_bruised())
|
||||
if(prob(5) && reagents.get_reagent_amount("potassium") < 5)
|
||||
reagents.add_reagent("potassium", REM*5)
|
||||
if(is_broken())
|
||||
if(owner.reagents.get_reagent_amount("potassium") < 15)
|
||||
owner.reagents.add_reagent("potassium", REM*2)
|
||||
|
||||
//If your kidneys aren't working, your body's going to have a hard time cleaning your blood.
|
||||
if(!owner.chem_effects[CE_ANTITOXIN])
|
||||
if(prob(33))
|
||||
if(is_broken())
|
||||
owner.adjustToxLoss(0.5)
|
||||
if(status & ORGAN_DEAD)
|
||||
owner.adjustToxLoss(1)
|
||||
@@ -5,6 +5,13 @@
|
||||
parent_organ = BP_GROIN
|
||||
robotic_name = "toxin filter"
|
||||
robotic_sprite = "liver-prosthetic"
|
||||
toxin_type = CE_HEPATOTOXIC
|
||||
min_bruised_damage = 25
|
||||
min_broken_damage = 45
|
||||
|
||||
max_damage = 70
|
||||
relative_size = 60
|
||||
|
||||
var/tolerance = 5
|
||||
|
||||
/obj/item/organ/internal/liver/process()
|
||||
@@ -21,58 +28,61 @@
|
||||
if(prob(1))
|
||||
spawn owner.delayed_vomit()
|
||||
|
||||
if(owner.life_tick % PROCESS_ACCURACY == 0)
|
||||
if(!(owner.life_tick % PROCESS_ACCURACY == 0))
|
||||
return
|
||||
|
||||
//A liver's duty is to get rid of toxins
|
||||
if(owner.getToxLoss() > 0 && owner.getToxLoss() <= tolerance)
|
||||
owner.adjustToxLoss(-0.2) //there isn't a lot of toxin damage, so we're going to be chill and slowly filter it out
|
||||
else if(owner.getToxLoss() > tolerance)
|
||||
if(is_bruised())
|
||||
//damaged liver works less efficiently
|
||||
owner.adjustToxLoss(-0.5)
|
||||
if(!owner.reagents.has_reagent("anti_toxin")) //no damage to liver if anti-toxin is present
|
||||
src.damage += 0.1 * PROCESS_ACCURACY
|
||||
else if(is_broken())
|
||||
//non-functioning liver ADDS toxins
|
||||
owner.adjustToxLoss(-0.1) //roughly 33 minutes to kill someone straight out, stacks with 60+ tox proc tho
|
||||
else
|
||||
//functioning liver removes toxins at a cost
|
||||
owner.adjustToxLoss(-1)
|
||||
if(!owner.reagents.has_reagent("anti_toxin")) //no damage to liver if anti-toxin is present
|
||||
src.damage += 0.05 * PROCESS_ACCURACY
|
||||
|
||||
|
||||
//High toxins levels are super dangerous
|
||||
if(owner.getToxLoss() >= 60 && !owner.reagents.has_reagent("anti_toxin"))
|
||||
//Healthy liver suffers on its own
|
||||
if (src.damage < min_broken_damage)
|
||||
src.damage += 0.2 * PROCESS_ACCURACY
|
||||
//Damaged one shares the fun
|
||||
else
|
||||
var/obj/item/organ/O = pick(owner.internal_organs)
|
||||
if(O)
|
||||
O.damage += 0.2 * PROCESS_ACCURACY
|
||||
|
||||
//Detox can heal small amounts of damage
|
||||
if (src.damage && src.damage < src.min_bruised_damage && owner.reagents.has_reagent("anti_toxin"))
|
||||
src.damage -= 0.2 * PROCESS_ACCURACY
|
||||
|
||||
if(src.damage < 0)
|
||||
src.damage = 0
|
||||
|
||||
var/filter_strength = INTOX_FILTER_HEALTHY
|
||||
//A liver's duty is to get rid of toxins
|
||||
if(owner.getToxLoss() > 0 && owner.getToxLoss() <= tolerance)
|
||||
owner.adjustToxLoss(-0.2) //there isn't a lot of toxin damage, so we're going to be chill and slowly filter it out
|
||||
else if(owner.getToxLoss() > tolerance)
|
||||
if(is_bruised())
|
||||
filter_strength = INTOX_FILTER_BRUISED
|
||||
if(is_broken())
|
||||
filter_strength = INTOX_FILTER_DAMAGED
|
||||
//damaged liver works less efficiently
|
||||
owner.adjustToxLoss(-0.5)
|
||||
if(!owner.chem_effects[CE_ANTITOXIN]) //no damage to liver if anti-toxin is present
|
||||
src.damage += 0.1 * PROCESS_ACCURACY
|
||||
else if(is_broken())
|
||||
//non-functioning liver ADDS toxins
|
||||
owner.adjustToxLoss(-0.1) //roughly 33 minutes to kill someone straight out, stacks with 60+ tox proc tho
|
||||
else
|
||||
//functioning liver removes toxins at a cost
|
||||
owner.adjustToxLoss(-1)
|
||||
if(!owner.chem_effects[CE_ANTITOXIN]) //no damage to liver if anti-toxin is present
|
||||
src.damage += 0.05 * PROCESS_ACCURACY
|
||||
|
||||
if (owner.intoxication > 0)
|
||||
owner.intoxication -= filter_strength*PROCESS_ACCURACY
|
||||
owner.intoxication = max(owner.intoxication, 0)
|
||||
if (!owner.intoxication)
|
||||
owner.handle_intoxication()
|
||||
|
||||
if(owner.chem_effects[CE_ALCOHOL_TOXIC])
|
||||
take_damage(owner.chem_effects[CE_ALCOHOL_TOXIC] * 0.1 * PROCESS_ACCURACY, prob(1))
|
||||
if(is_damaged())
|
||||
owner.adjustToxLoss(owner.chem_effects[CE_ALCOHOL_TOXIC] * 0.1 * PROCESS_ACCURACY)
|
||||
//High toxins levels are super dangerous
|
||||
if(owner.getToxLoss() >= 100 && !owner.chem_effects[CE_ANTITOXIN])
|
||||
//Healthy liver suffers on its own
|
||||
if (src.damage < min_broken_damage)
|
||||
src.damage += 0.2 * PROCESS_ACCURACY
|
||||
//Damaged one shares the fun
|
||||
else
|
||||
var/obj/item/organ/O = pick(owner.internal_organs)
|
||||
if(O)
|
||||
O.damage += 0.2 * PROCESS_ACCURACY
|
||||
|
||||
//Detox can heal small amounts of damage
|
||||
if (src.damage && src.damage < src.min_bruised_damage && owner.chem_effects[CE_ANTITOXIN])
|
||||
src.damage -= 0.2 * PROCESS_ACCURACY
|
||||
|
||||
if(src.damage < 0)
|
||||
src.damage = 0
|
||||
|
||||
var/filter_strength = INTOX_FILTER_HEALTHY
|
||||
if(is_bruised())
|
||||
filter_strength = INTOX_FILTER_BRUISED
|
||||
if(is_broken())
|
||||
filter_strength = INTOX_FILTER_DAMAGED
|
||||
|
||||
if (owner.intoxication > 0)
|
||||
owner.intoxication -= min(owner.intoxication, filter_strength*PROCESS_ACCURACY)
|
||||
if (!owner.intoxication)
|
||||
owner.handle_intoxication()
|
||||
|
||||
if(toxin_type in owner.chem_effects)
|
||||
if(is_damaged())
|
||||
owner.adjustToxLoss(owner.chem_effects[toxin_type] * 0.1 * PROCESS_ACCURACY) // as actual organ damage is handled elsewhere
|
||||
|
||||
//We got it covered in Process with more detailed thing
|
||||
/obj/item/organ/internal/liver/handle_regeneration()
|
||||
return
|
||||
@@ -9,19 +9,45 @@
|
||||
parent_organ = BP_CHEST
|
||||
robotic_name = "gas exchange system"
|
||||
robotic_sprite = "lungs-prosthetic"
|
||||
min_bruised_damage = 25
|
||||
min_broken_damage = 45
|
||||
toxin_type = CE_PNEUMOTOXIC
|
||||
|
||||
max_damage = 70
|
||||
relative_size = 60
|
||||
|
||||
var/rescued = FALSE // whether or not a collapsed lung has been rescued with a syringe
|
||||
var/oxygen_deprivation = 0
|
||||
var/last_successful_breath
|
||||
var/breath_fail_ratio //How badly they failed a breath
|
||||
|
||||
/obj/item/organ/internal/lungs/proc/remove_oxygen_deprivation(var/amount)
|
||||
var/last_suffocation = oxygen_deprivation
|
||||
oxygen_deprivation = min(species.total_health,max(0,oxygen_deprivation - amount))
|
||||
return -(oxygen_deprivation - last_suffocation)
|
||||
|
||||
/obj/item/organ/internal/lungs/proc/add_oxygen_deprivation(var/amount)
|
||||
var/last_suffocation = oxygen_deprivation
|
||||
oxygen_deprivation = min(species.total_health,max(0,oxygen_deprivation + amount))
|
||||
return (oxygen_deprivation - last_suffocation)
|
||||
|
||||
// Returns a percentage value for use by GetOxyloss().
|
||||
/obj/item/organ/internal/lungs/proc/get_oxygen_deprivation()
|
||||
if(status & ORGAN_DEAD)
|
||||
return 100
|
||||
return round((oxygen_deprivation/species.total_health)*100)
|
||||
|
||||
/obj/item/organ/internal/lungs/process()
|
||||
..()
|
||||
|
||||
if(!owner)
|
||||
return
|
||||
|
||||
if (germ_level > INFECTION_LEVEL_ONE)
|
||||
|
||||
if(germ_level > INFECTION_LEVEL_ONE)
|
||||
if(prob(5))
|
||||
owner.emote("cough") //Respiratory tract infection
|
||||
|
||||
if(is_broken() || (is_bruised() && !rescued)) // a thoracostomy can only help with a collapsed lung, not a mangled one
|
||||
if(is_broken() || (is_bruised() && !rescued) && !owner.is_asystole()) // a thoracostomy can only help with a collapsed lung, not a mangled one
|
||||
if(prob(2))
|
||||
spawn owner.emote("me", 1, "coughs up blood!")
|
||||
owner.drip(10)
|
||||
@@ -35,25 +61,36 @@
|
||||
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
|
||||
|
||||
/obj/item/organ/internal/lungs/proc/rupture()
|
||||
var/obj/item/organ/external/parent = owner.get_organ(parent_organ)
|
||||
if(istype(parent))
|
||||
owner.custom_pain("You feel a stabbing pain in your [parent.name]!", 50, affecting = parent)
|
||||
bruise()
|
||||
|
||||
/obj/item/organ/internal/lungs/proc/handle_failed_breath()
|
||||
if(prob(15) && !owner.nervous_system_failure())
|
||||
if(!owner.is_asystole())
|
||||
owner.emote("gasp")
|
||||
else
|
||||
owner.emote(pick("shiver","twitch"))
|
||||
|
||||
if(damage || world.time > last_successful_breath + 2 MINUTES)
|
||||
owner.adjustOxyLoss(HUMAN_MAX_OXYLOSS*breath_fail_ratio)
|
||||
|
||||
owner.oxygen_alert = max(owner.oxygen_alert, 2)
|
||||
|
||||
/obj/item/organ/internal/lungs/proc/handle_breath(datum/gas_mixture/breath)
|
||||
if(!owner)
|
||||
return 1
|
||||
|
||||
if(!breath || (max_damage <= 0))
|
||||
breath_fail_ratio = 1
|
||||
handle_failed_breath()
|
||||
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
|
||||
rupture()
|
||||
|
||||
var/safe_pressure_min = owner.species.breath_pressure // Minimum safe partial pressure of breathable gas in kPa
|
||||
|
||||
@@ -100,25 +137,24 @@
|
||||
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
|
||||
|
||||
var/inhale_efficiency = min(round(((inhaling/breath.total_moles)*breath_pressure)/safe_pressure_min, 0.001), 3)
|
||||
|
||||
// Not enough to breathe
|
||||
if(inhale_pp < safe_pressure_min)
|
||||
if(inhale_efficiency < 1)
|
||||
if(prob(20))
|
||||
spawn(0)
|
||||
if(inhale_efficiency < 0.8)
|
||||
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))
|
||||
else if(prob(20))
|
||||
to_chat(owner, span("warning", "It's hard to breathe..."))
|
||||
breath_fail_ratio = 1 - inhale_efficiency
|
||||
failed_inhale = 1
|
||||
|
||||
owner.oxygen_alert = max(owner.oxygen_alert, 1)
|
||||
else
|
||||
// We're in safe limits
|
||||
owner.oxygen_alert = 0
|
||||
breath_fail_ratio = 0
|
||||
|
||||
owner.oxygen_alert = failed_inhale * 2
|
||||
|
||||
inhaled_gas_used = inhaling/6 * (owner.species?.breath_eff_mul || 1)
|
||||
|
||||
@@ -208,6 +244,11 @@
|
||||
|
||||
var/failed_breath = failed_inhale || failed_exhale
|
||||
|
||||
if(failed_breath)
|
||||
handle_failed_breath()
|
||||
else
|
||||
last_successful_breath = world.time
|
||||
owner.oxygen_alert = 0
|
||||
return failed_breath
|
||||
|
||||
/obj/item/organ/internal/lungs/proc/handle_temperature_effects(datum/gas_mixture/breath)
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/obj/item/organ/internal/stomach
|
||||
name = "stomach"
|
||||
desc = "Gross. This is hard to stomach."
|
||||
icon_state = "stomach"
|
||||
dead_icon = "stomach"
|
||||
organ_tag = BP_STOMACH
|
||||
parent_organ = BP_GROIN
|
||||
var/stomach_capacity
|
||||
var/datum/reagents/metabolism/ingested
|
||||
var/next_cramp = 0
|
||||
|
||||
/obj/item/organ/internal/stomach/Destroy()
|
||||
QDEL_NULL(ingested)
|
||||
. = ..()
|
||||
|
||||
/obj/item/organ/internal/stomach/Initialize()
|
||||
..()
|
||||
ingested = new /datum/reagents/metabolism(240, owner, CHEM_INGEST)
|
||||
if(!ingested.my_atom)
|
||||
ingested.my_atom = src
|
||||
|
||||
/obj/item/organ/internal/stomach/removed()
|
||||
. = ..()
|
||||
ingested.my_atom = src
|
||||
ingested.parent = null
|
||||
|
||||
/obj/item/organ/internal/stomach/replaced()
|
||||
. = ..()
|
||||
ingested.my_atom = owner
|
||||
ingested.parent = owner
|
||||
|
||||
/obj/item/organ/internal/stomach/proc/can_eat_atom(var/atom/movable/food)
|
||||
return !isnull(get_devour_time(food))
|
||||
|
||||
/obj/item/organ/internal/stomach/proc/is_full(var/atom/movable/food)
|
||||
var/total = Floor(ingested.total_volume / 10)
|
||||
for(var/a in contents + food)
|
||||
if(ismob(a))
|
||||
var/mob/M = a
|
||||
total += M.mob_size
|
||||
else if(isobj(a))
|
||||
var/obj/item/I = a
|
||||
total += I.get_storage_cost()
|
||||
else
|
||||
continue
|
||||
if(total > species.stomach_capacity)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/organ/internal/stomach/proc/get_devour_time(var/atom/movable/food)
|
||||
if(iscarbon(food) || isanimal(food))
|
||||
var/mob/living/L = food
|
||||
if((species.gluttonous & GLUT_TINY) && (L.mob_size <= MOB_TINY) && !ishuman(food)) // Anything MOB_TINY or smaller
|
||||
return DEVOUR_SLOW
|
||||
else if((species.gluttonous & GLUT_SMALLER) && owner.mob_size > L.mob_size) // Anything we're larger than
|
||||
return DEVOUR_SLOW
|
||||
else if(species.gluttonous & GLUT_ANYTHING) // Eat anything ever
|
||||
return DEVOUR_FAST
|
||||
else if(istype(food, /obj/item) && !istype(food, /obj/item/holder)) //Don't eat holders. They are special.
|
||||
var/obj/item/I = food
|
||||
var/cost = I.get_storage_cost()
|
||||
if(cost != INFINITY) // i blame bay - geeves
|
||||
if((species.gluttonous & GLUT_ITEM_TINY) && cost < 4)
|
||||
return DEVOUR_SLOW
|
||||
else if((species.gluttonous & GLUT_ITEM_NORMAL) && cost <= 4)
|
||||
return DEVOUR_SLOW
|
||||
else if(species.gluttonous & GLUT_ITEM_ANYTHING)
|
||||
return DEVOUR_FAST
|
||||
|
||||
/obj/item/organ/internal/stomach/return_air()
|
||||
return null
|
||||
|
||||
// This call needs to be split out to make sure that all the ingested things are metabolised
|
||||
// before the process call is made on any of the other organs
|
||||
/obj/item/organ/internal/stomach/proc/metabolize()
|
||||
if(is_usable())
|
||||
ingested.metabolize()
|
||||
|
||||
#define STOMACH_VOLUME 65
|
||||
|
||||
/obj/item/organ/internal/stomach/process()
|
||||
..()
|
||||
if(owner)
|
||||
var/functioning = is_usable()
|
||||
if(damage >= min_bruised_damage && prob((damage / max_damage) * 100))
|
||||
functioning = FALSE
|
||||
|
||||
if(functioning)
|
||||
for(var/mob/living/M in contents)
|
||||
if(M.stat == DEAD)
|
||||
qdel(M)
|
||||
continue
|
||||
|
||||
M.adjustBruteLoss(3)
|
||||
M.adjustFireLoss(3)
|
||||
M.adjustToxLoss(3)
|
||||
|
||||
var/digestion_product = M.get_digestion_product()
|
||||
if(digestion_product)
|
||||
ingested.add_reagent(digestion_product, rand(1,3))
|
||||
|
||||
else if(world.time >= next_cramp)
|
||||
next_cramp = world.time + rand(200,800)
|
||||
owner.custom_pain("Your stomach cramps agonizingly!",1)
|
||||
|
||||
var/alcohol_volume = ingested.get_reagent_amount(/datum/reagent/alcohol/ethanol)
|
||||
|
||||
// Alcohol counts as double volume for the purposes of vomit probability
|
||||
var/effective_volume = ingested.total_volume + alcohol_volume
|
||||
|
||||
// Just over the limit, the probability will be low. It rises a lot such that at double ingested it's 64% chance.
|
||||
var/vomit_probability = (effective_volume / STOMACH_VOLUME) ** 6
|
||||
if(prob(vomit_probability))
|
||||
owner.vomit()
|
||||
|
||||
#undef STOMACH_VOLUME
|
||||
Reference in New Issue
Block a user