Merge pull request #9895 from Thalpy/OrganQoL
[READY] Organ quality of life fixes. Adds Organ fridges with items, Tweaks scanner, new surgery, tweaks chems
This commit is contained in:
@@ -144,7 +144,7 @@
|
||||
else
|
||||
O.forceMove(src)
|
||||
return TRUE
|
||||
|
||||
|
||||
///Really simple proc, just moves the object "O" into the hands of mob "M" if able, done so I could modify the proc a little for the organ fridge
|
||||
/obj/machinery/smartfridge/proc/dispense(obj/item/O, var/mob/M)
|
||||
if(!M.put_in_hands(O))
|
||||
@@ -388,20 +388,27 @@
|
||||
/obj/machinery/smartfridge/organ
|
||||
name = "smart organ storage"
|
||||
desc = "A refrigerated storage unit for organ storage."
|
||||
max_n_of_items = 20 //vastly lower to prevent processing too long
|
||||
max_n_of_items = 25 //vastly lower to prevent processing too long
|
||||
var/repair_rate = 0
|
||||
|
||||
/obj/machinery/smartfridge/organ/accept_check(obj/item/O)
|
||||
if(istype(O, /obj/item/organ))
|
||||
return TRUE
|
||||
if(istype(O, /obj/item/reagent_containers/syringe))
|
||||
return TRUE
|
||||
if(istype(O, /obj/item/reagent_containers/glass/bottle))
|
||||
return TRUE
|
||||
if(istype(O, /obj/item/reagent_containers/medspray))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/smartfridge/organ/load(obj/item/O)
|
||||
. = ..()
|
||||
if(!.) //if the item loads, clear can_decompose
|
||||
return
|
||||
var/obj/item/organ/organ = O
|
||||
organ.organ_flags |= ORGAN_FROZEN
|
||||
if(istype(O, /obj/item/organ))
|
||||
var/obj/item/organ/organ = O
|
||||
organ.organ_flags |= ORGAN_FROZEN
|
||||
|
||||
/obj/machinery/smartfridge/organ/RefreshParts()
|
||||
for(var/obj/item/stock_parts/matter_bin/B in component_parts)
|
||||
@@ -420,6 +427,17 @@
|
||||
if(istype(AM))
|
||||
AM.organ_flags &= ~ORGAN_FROZEN
|
||||
|
||||
/obj/machinery/smartfridge/organ/preloaded
|
||||
initial_contents = list(
|
||||
/obj/item/reagent_containers/medspray/synthtissue = 1,
|
||||
/obj/item/reagent_containers/medspray/sterilizine = 1)
|
||||
|
||||
/obj/machinery/smartfridge/organ/preloaded/Initialize()
|
||||
..()
|
||||
var/list = list(/obj/item/organ/tongue, /obj/item/organ/brain, /obj/item/organ/heart, /obj/item/organ/liver, /obj/item/organ/ears, /obj/item/organ/eyes, /obj/item/organ/tail, /obj/item/organ/stomach)
|
||||
var/newtype = pick(list)
|
||||
load(new newtype(src.loc))
|
||||
|
||||
// -----------------------------
|
||||
// Chemistry Medical Smartfridge
|
||||
// -----------------------------
|
||||
|
||||
@@ -940,6 +940,21 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
|
||||
description = "Reacts with neural tissue, helping reform damaged connections. Can cure minor traumas."
|
||||
color = "#EEFF8F"
|
||||
|
||||
/datum/reagent/medicine/neurine/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
|
||||
if(!(method == INJECT))
|
||||
return
|
||||
var/obj/item/organ/brain/B = M.getorganslot(ORGAN_SLOT_BRAIN)
|
||||
if(!B || (!(B.organ_flags & ORGAN_FAILING)))
|
||||
return
|
||||
B.applyOrganDamage(-20)
|
||||
if(prob(80))
|
||||
B.gain_trauma_type(BRAIN_TRAUMA_MILD)
|
||||
else if(prob(50))
|
||||
B.gain_trauma_type(BRAIN_TRAUMA_SEVERE)
|
||||
else
|
||||
B.gain_trauma_type(BRAIN_TRAUMA_SPECIAL)
|
||||
|
||||
|
||||
/datum/reagent/medicine/neurine/on_mob_life(mob/living/carbon/C)
|
||||
if(holder.has_reagent("neurotoxin"))
|
||||
holder.remove_reagent("neurotoxin", 5)
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
id = "synthtissue"
|
||||
results = list("synthtissue" = 5)
|
||||
required_reagents = list("synthflesh" = 1)
|
||||
required_catalysts = list("nutriment" = 0.1)
|
||||
required_catalysts = list("sugar" = 0.1)
|
||||
//FermiChem vars:
|
||||
OptimalTempMin = 305 // Lower area of bell curve for determining heat based rate reactions
|
||||
OptimalTempMax = 315 // Upper end for above
|
||||
@@ -86,13 +86,13 @@
|
||||
CurveSharppH = 2.5 // How sharp the pH exponential curve is (to the power of value)
|
||||
ThermicConstant = 0.01 // Temperature change per 1u produced
|
||||
HIonRelease = 0.015 // pH change per 1u reaction (inverse for some reason)
|
||||
RateUpLim = 0.05 // Optimal/max rate possible if all conditions are perfect
|
||||
RateUpLim = 0.1 // Optimal/max rate possible if all conditions are perfect
|
||||
FermiChem = TRUE // If the chemical uses the Fermichem reaction mechanics
|
||||
PurityMin = 0
|
||||
|
||||
/datum/chemical_reaction/synthtissue/FermiCreate(datum/reagents/holder, added_volume, added_purity)
|
||||
var/datum/reagent/synthtissue/St = holder.has_reagent("synthtissue")
|
||||
var/datum/reagent/N = holder.has_reagent("nutriment")
|
||||
var/datum/reagent/N = holder.has_reagent("sugar")
|
||||
if(!St)
|
||||
return
|
||||
if(holder.chem_temp > 320)
|
||||
|
||||
@@ -100,3 +100,8 @@
|
||||
name = "sterilizer spray"
|
||||
desc = "Spray bottle loaded with non-toxic sterilizer. Useful in preparation for surgery."
|
||||
list_reagents = list("sterilizine" = 60)
|
||||
|
||||
/obj/item/reagent_containers/medspray/synthtissue
|
||||
name = "Synthtissue young culture spray"
|
||||
desc = "Spray bottle loaded with synthtissue. Useful in synthtissue grafting surgeries."
|
||||
list_reagents = list("synthtissue" = 60)
|
||||
|
||||
@@ -65,6 +65,9 @@
|
||||
target.visible_message("...[target] wakes up, alive and aware!")
|
||||
target.emote("gasp")
|
||||
target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 50, 199) //MAD SCIENCE
|
||||
for(var/obj/item/organ/O in target.internal_organs)//zap those buggers back to life!
|
||||
if(O.organ_flags & ORGAN_FAILING)
|
||||
O.applyOrganDamage(-5)
|
||||
return TRUE
|
||||
else
|
||||
user.visible_message("...[target.p_they()] convulses, then lies still.")
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/datum/surgery/cardioversion
|
||||
name = "Emergency Cardioversion Induction"
|
||||
steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/clamp_bleeders,
|
||||
/datum/surgery_step/incise_heart, /datum/surgery_step/ventricular_electrotherapy, /datum/surgery_step/close)
|
||||
possible_locs = list(BODY_ZONE_CHEST)
|
||||
|
||||
/datum/surgery_step/ventricular_electrotherapy
|
||||
name = "ventricular electrotherapy"
|
||||
implements = list(/obj/item/twohanded/shockpaddles = 90, /obj/item/defibrillator = 75, /obj/item/inducer = 55, /obj/item/stock_parts/cell = 25) //Just because the idea of a new player using the whole magine to defib is hillarious to me
|
||||
time = 50
|
||||
repeatable = TRUE //So you can retry
|
||||
|
||||
/datum/surgery_step/ventricular_electrotherapy/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
|
||||
if(istype(tool, /obj/item/twohanded/shockpaddles))
|
||||
var/obj/item/twohanded/shockpaddles/pads = tool
|
||||
if(!pads.wielded)
|
||||
to_chat(user, "<span class='warning'>You need to wield the paddles in both hands before you can use them!</span>")
|
||||
return FALSE
|
||||
display_results(user, target, "<span class='notice'>You begin to apply the [tool] onto the heart directly...</span>",
|
||||
"[user] begin to prepare the heart for contact with the [tool].",
|
||||
"[user] begin to prepare the heart for contact with the [tool]. ")
|
||||
target.notify_ghost_cloning("Your heart is undergoing Emergency Cardioversion Induction Surgery!")
|
||||
playsound(src, 'sound/machines/defib_charge.ogg', 75, 0)
|
||||
|
||||
/datum/surgery_step/ventricular_electrotherapy/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
|
||||
if(istype(tool, /obj/item/twohanded/shockpaddles))
|
||||
var/obj/item/twohanded/shockpaddles/pads = tool
|
||||
if(!pads.wielded)
|
||||
return FALSE
|
||||
var/mob/living/carbon/human/H = target
|
||||
playsound(src, 'sound/machines/defib_zap.ogg', 75, 1, -1)
|
||||
playsound(src, "bodyfall", 50, 1)
|
||||
if(H.stat != DEAD)
|
||||
display_results(user, target, "<span class='warning'>You can't use this procedure on the living! [H]'s body flops madly like a wild fish on the table from the current, and your crazed surgical methods.</span>",
|
||||
"<span class='warning'>[user] screws up, causing [H] to flop around violently as they're zapped!</span>",
|
||||
"<span class='warning'>[user] screws up, causing [H] to flop around violently as they're zapped!</span>")
|
||||
H.emote("scream")
|
||||
H.electrocute_act(25, (tool), 1, FALSE, FALSE, FALSE, TRUE)
|
||||
H.adjustFireLoss(10)
|
||||
H.emote("flip")
|
||||
H.Jitter(100)
|
||||
return FALSE
|
||||
display_results(user, target, "<span class='notice'>You attach the [tool] to [target]'s heart and prepare to pulse.</span>",
|
||||
"[user] attaches the [tool] to [H]'s heart and prepares to pulse.",
|
||||
"")
|
||||
H.adjustBruteLoss(10)
|
||||
var/obj/item/organ/heart = H.getorgan(/obj/item/organ/heart)
|
||||
if(heart.organ_flags & ORGAN_FAILING)
|
||||
H.adjustOrganLoss(ORGAN_SLOT_HEART, -15)
|
||||
var/obj/item/organ/brain/BR = H.getorgan(/obj/item/organ/brain)
|
||||
if(BR.organ_flags & ORGAN_FAILING)
|
||||
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, -5)
|
||||
H.electrocute_act(0, (tool), 1, FALSE, FALSE, FALSE, TRUE)
|
||||
//If we're using a defib, let the defib handle the revive.
|
||||
if(istype(tool, /obj/item/twohanded/shockpaddles))
|
||||
return
|
||||
//Otherwise, we're ad hocing it
|
||||
if(!(do_after(user, 50, target = target)))
|
||||
return FALSE
|
||||
if(!ghetto_defib(user, H, tool))
|
||||
playsound(src, 'sound/machines/defib_failed.ogg', 50, 0)
|
||||
return FALSE
|
||||
log_combat(user, H, "revived", "Emergency Cardioversion Induction")
|
||||
return TRUE
|
||||
|
||||
/datum/surgery_step/ventricular_electrotherapy/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
|
||||
playsound(src, 'sound/machines/defib_zap.ogg', 75, 1, -1)
|
||||
playsound(src, "bodyfall", 50, 1)
|
||||
var/mob/living/carbon/human/H = target
|
||||
display_results(user, target, "<span class='warning'>You screw up, sending a current through their body!</span>",
|
||||
"<span class='warning'>[user] screws up, causing [H] to flop around violently as they're zapped!</span>",
|
||||
"<span class='warning'>[user] screws up, causing [H] to flop around violently as they're zapped!</span>")
|
||||
H.electrocute_act(25, (tool), 1, FALSE, FALSE, FALSE, TRUE)
|
||||
H.adjustFireLoss(10)
|
||||
H.emote("flip")
|
||||
H.adjustOrganLoss(ORGAN_SLOT_HEART, 10)
|
||||
|
||||
/datum/surgery_step/ventricular_electrotherapy/proc/ghetto_defib(mob/user, mob/living/carbon/human/H, obj/item/tool)
|
||||
H.visible_message("<span class='warning'>[H]'s body convulses a bit.</span>")
|
||||
var/total_brute = H.getBruteLoss()
|
||||
var/total_burn = H.getFireLoss()
|
||||
var/failed
|
||||
var/tdelta = round(world.time - H.timeofdeath)
|
||||
|
||||
if (H.suiciding || (HAS_TRAIT(H, TRAIT_NOCLONE)))
|
||||
failed = "<span class='warning'>The heart is zapped by the [tool], but nothing happens. You feel like the spark of life has fully left [H].</span>"
|
||||
else if (H.hellbound)
|
||||
failed = "<span class='warning'>The heart is zapped by the [tool], but nothing happens. You notice a small tatoo with the words \"Property of Satan\" branded just above the right ventricle.</span>"
|
||||
else if(tdelta > (DEFIB_TIME_LIMIT * 10))
|
||||
failed = "<span class='warning'>The heart is zapped by the [tool], but nothing happens. It appears their body decomposed beyond repair.</span>"
|
||||
else if(total_burn >= 180 || total_brute >= 180)
|
||||
failed = "<span class='warning'>The [tool] zaps the heart, inducing a sudden contraction, but it appears [H]'s body is too damaged to revive presently.</span>"
|
||||
else if(H.get_ghost())
|
||||
failed = "<span class='warning'>The [tool] zaps the heart, inducing several contractions before dying down, but there's no spark of life in [H]'s eyes. It may be worth it to try again, however.</span>"
|
||||
else
|
||||
var/obj/item/organ/brain/BR = H.getorgan(/obj/item/organ/brain)
|
||||
if(BR)
|
||||
if(H.suiciding || BR.brainmob?.suiciding)
|
||||
failed = "<span class='warning'>The heart is zapped by the [tool], but nothing happens. You feel like the spark of life has fully left [H].</span>"
|
||||
else
|
||||
failed = "<span class='warning'>The [tool] zaps the heart, restarting the heart, but without a brain the contractions quickly die out.</span>"
|
||||
|
||||
|
||||
if(failed)
|
||||
to_chat(user, failed)
|
||||
playsound(src, 'sound/machines/defib_failed.ogg', 50, 0)
|
||||
else
|
||||
//If the body has been fixed so that they would not be in crit when defibbed, give them oxyloss to put them back into crit
|
||||
if (H.health > HALFWAYCRITDEATH)
|
||||
H.adjustOxyLoss(H.health - HALFWAYCRITDEATH, 0)
|
||||
else
|
||||
var/overall_damage = total_brute + total_burn + H.getToxLoss() + H.getOxyLoss()
|
||||
var/mobhealth = H.health
|
||||
H.adjustOxyLoss((mobhealth - HALFWAYCRITDEATH) * (H.getOxyLoss() / overall_damage), 0)
|
||||
H.adjustToxLoss((mobhealth - HALFWAYCRITDEATH) * (H.getToxLoss() / overall_damage), 0)
|
||||
H.adjustFireLoss((mobhealth - HALFWAYCRITDEATH) * (total_burn / overall_damage), 0)
|
||||
H.adjustBruteLoss((mobhealth - HALFWAYCRITDEATH) * (total_brute / overall_damage), 0)
|
||||
H.updatehealth() // Previous "adjust" procs don't update health, so we do it manually.
|
||||
H.visible_message("<span class='notice'>The [tool] zaps the heart, inducing several contractions before speeding up into a regular rhythm, [H]'s eyes snapping open with a loud gasp!</span>")
|
||||
playsound(src, 'sound/machines/defib_success.ogg', 50, 0)
|
||||
H.set_heartattack(FALSE)
|
||||
H.revive()
|
||||
H.emote("gasp")
|
||||
H.Jitter(100)
|
||||
SEND_SIGNAL(H, COMSIG_LIVING_MINOR_SHOCK)
|
||||
@@ -49,7 +49,7 @@
|
||||
to_chat(user, "<span class='notice'>There's not enough synthtissue to perform the operation! There needs to be at least 10u.</span>")
|
||||
return -1
|
||||
|
||||
if((chosen_organ.organ_flags & ORGAN_FAILING) && !(Sf.data["grown_volume"] >= 115))
|
||||
if((chosen_organ.organ_flags & ORGAN_FAILING) && !(Sf.data["grown_volume"] >= 80))
|
||||
to_chat(user, "<span class='notice'>[chosen_organ] is too damaged to graft onto!</span>")
|
||||
return -1
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
slot = ORGAN_SLOT_HEART
|
||||
|
||||
healing_factor = STANDARD_ORGAN_HEALING
|
||||
decay_factor = 3 * STANDARD_ORGAN_DECAY //designed to fail about 5 minutes after death
|
||||
decay_factor = 2.5 * STANDARD_ORGAN_DECAY //designed to fail about 5 minutes after death
|
||||
|
||||
low_threshold_passed = "<span class='info'>Prickles of pain appear then die out from within your chest...</span>"
|
||||
high_threshold_passed = "<span class='warning'>Something inside your chest hurts, and the pain isn't subsiding. You notice yourself breathing far faster than before.</span>"
|
||||
|
||||
@@ -95,13 +95,12 @@
|
||||
|
||||
//Checks to see if the organ is frozen from temperature
|
||||
/obj/item/organ/proc/is_cold()
|
||||
var/freezing_objects = list(/obj/structure/closet/crate/freezer, /obj/structure/closet/secure_closet/freezer, /obj/structure/bodycontainer, /obj/item/autosurgeon)
|
||||
if(istype(loc, /obj/))//Freezer of some kind, I hope.
|
||||
if(is_type_in_list(loc, freezing_objects))
|
||||
if(is_type_in_typecache(loc, GLOB.freezing_objects))
|
||||
if(!(organ_flags & ORGAN_FROZEN))//Incase someone puts them in when cold, but they warm up inside of the thing. (i.e. they have the flag, the thing turns it off, this rights it.)
|
||||
organ_flags |= ORGAN_FROZEN
|
||||
return TRUE
|
||||
return
|
||||
return (organ_flags & ORGAN_FROZEN) //Incase something else toggles it
|
||||
|
||||
var/local_temp
|
||||
if(istype(loc, /turf/))//Only concern is adding an organ to a freezer when the area around it is cold.
|
||||
@@ -111,7 +110,7 @@
|
||||
|
||||
else if(istype(loc, /mob/) && !owner)
|
||||
var/mob/M = loc
|
||||
if(is_type_in_list(M.loc, freezing_objects))
|
||||
if(is_type_in_typecache(M.loc, GLOB.freezing_objects))
|
||||
if(!(organ_flags & ORGAN_FROZEN))
|
||||
organ_flags |= ORGAN_FROZEN
|
||||
return TRUE
|
||||
@@ -121,7 +120,7 @@
|
||||
|
||||
if(owner)
|
||||
//Don't interfere with bodies frozen by structures.
|
||||
if(is_type_in_list(owner.loc, freezing_objects))
|
||||
if(is_type_in_typecache(owner.loc, GLOB.freezing_objects))
|
||||
if(!(organ_flags & ORGAN_FROZEN))
|
||||
organ_flags |= ORGAN_FROZEN
|
||||
return TRUE
|
||||
@@ -232,6 +231,8 @@
|
||||
if(delta > 0)
|
||||
if(damage >= maxHealth)
|
||||
organ_flags |= ORGAN_FAILING
|
||||
if(owner)
|
||||
owner.med_hud_set_status()
|
||||
return now_failing
|
||||
if(damage > high_threshold && prev_damage <= high_threshold)
|
||||
return high_threshold_passed
|
||||
@@ -239,6 +240,8 @@
|
||||
return low_threshold_passed
|
||||
else
|
||||
organ_flags &= ~ORGAN_FAILING
|
||||
if(owner)
|
||||
owner.med_hud_set_status()
|
||||
if(!owner)//Processing is stopped when the organ is dead and outside of someone. This hopefully should restart it if a removed organ is repaired outside of a body.
|
||||
START_PROCESSING(SSobj, src)
|
||||
if(prev_damage > low_threshold && damage <= low_threshold)
|
||||
@@ -273,6 +276,12 @@
|
||||
var/has_liver = (!(NOLIVER in dna.species.species_traits))
|
||||
var/has_stomach = (!(NOSTOMACH in dna.species.species_traits))
|
||||
|
||||
for(var/obj/item/organ/O in internal_organs)
|
||||
if(O.organ_flags & ORGAN_FAILING)
|
||||
O.setOrganDamage(0)
|
||||
if(only_one)
|
||||
return TRUE
|
||||
|
||||
if(has_liver && !getorganslot(ORGAN_SLOT_LIVER))
|
||||
var/obj/item/organ/liver/LI
|
||||
|
||||
@@ -362,3 +371,15 @@
|
||||
tail.Insert(src)
|
||||
if(only_one)
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/organ/random
|
||||
name = "Illegal organ"
|
||||
desc = "Something hecked up"
|
||||
|
||||
/obj/item/organ/random/Initialize()
|
||||
..()
|
||||
var/list = list(/obj/item/organ/tongue, /obj/item/organ/brain, /obj/item/organ/heart, /obj/item/organ/liver, /obj/item/organ/ears, /obj/item/organ/eyes, /obj/item/organ/tail, /obj/item/organ/stomach)
|
||||
var/newtype = pick(list)
|
||||
new newtype(loc)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
Reference in New Issue
Block a user