diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index a8701553123..cabc7957bbe 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -31636,6 +31636,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, +/obj/machinery/smartfridge/organ, /turf/open/floor/plasteel/white/side{ dir = 4 }, diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 19891947c65..2d49e3b83c1 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -97233,6 +97233,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/smartfridge/organ, /turf/open/floor/plasteel/dark, /area/medical/surgery) "dyK" = ( diff --git a/_maps/map_files/Donutstation/Donutstation.dmm b/_maps/map_files/Donutstation/Donutstation.dmm index 8a717fbdb27..6c35a9ae1c5 100644 --- a/_maps/map_files/Donutstation/Donutstation.dmm +++ b/_maps/map_files/Donutstation/Donutstation.dmm @@ -14577,6 +14577,7 @@ /turf/open/floor/plasteel/dark, /area/bridge) "aKj" = ( +/obj/machinery/smartfridge/organ, /turf/open/floor/plasteel/white/side{ dir = 4 }, diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 7f52847a430..a5b4c0f7ceb 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -53201,16 +53201,19 @@ /area/maintenance/port/aft) "cnm" = ( /obj/structure/table, -/obj/item/hemostat, /obj/structure/extinguisher_cabinet{ pixel_x = -27 }, +/obj/item/surgicaldrill, +/obj/item/clothing/suit/apron/surgical, +/obj/item/clothing/mask/surgical, +/obj/item/clothing/gloves/color/latex, /turf/open/floor/plasteel, /area/medical/surgery) "cnn" = ( /obj/structure/table, -/obj/item/surgicaldrill, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/item/hemostat, /turf/open/floor/plasteel/white/side, /area/medical/surgery) "cno" = ( @@ -53899,10 +53902,6 @@ /turf/open/floor/plasteel, /area/hallway/secondary/service) "coy" = ( -/obj/structure/table, -/obj/item/clothing/gloves/color/latex, -/obj/item/clothing/mask/surgical, -/obj/item/clothing/suit/apron/surgical, /obj/machinery/airalarm{ dir = 4; pixel_x = -22 @@ -53910,6 +53909,7 @@ /obj/machinery/light{ dir = 8 }, +/obj/machinery/smartfridge/organ, /turf/open/floor/plasteel/white/side{ dir = 4 }, diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index 91553c52279..620ca426c33 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -36048,6 +36048,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 8 }, +/obj/item/surgical_drapes, /turf/open/floor/plasteel/white, /area/medical/surgery) "bLN" = ( @@ -36070,12 +36071,11 @@ /turf/open/floor/plasteel/white, /area/medical/surgery) "bLQ" = ( -/obj/structure/table, -/obj/item/surgical_drapes, /obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ dir = 4 }, +/obj/machinery/smartfridge/organ, /turf/open/floor/plasteel/white, /area/medical/surgery) "bLR" = ( diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index a5010ea8fe2..fbff91eefe2 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -120,6 +120,7 @@ #define AGENDER 17 #define NOEYESPRITES 18 //Do not draw eyes or eyeless overlay +//organ slots #define ORGAN_SLOT_BRAIN "brain" #define ORGAN_SLOT_APPENDIX "appendix" #define ORGAN_SLOT_RIGHT_ARM_AUG "r_arm_device" @@ -144,6 +145,10 @@ #define ORGAN_SLOT_TAIL "tail" #define ORGAN_SLOT_PARASITE_EGG "parasite_egg" +//organ defines +#define STANDARD_ORGAN_THRESHOLD 100 +#define STANDARD_ORGAN_HEALING 0.001 +#define STANDARD_ORGAN_DECAY 0.00222 //designed to fail organs when left to decay for ~15 minutes //used for the can_chromosome var on mutations #define CHROMOSOME_NEVER 0 diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 861ed313fcc..16b196b4200 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -262,7 +262,7 @@ GLOBAL_LIST_INIT(pda_styles, list(MONO, VT, ORBITRON, SHARE)) #define MAP_MAXZ 6 // Defib stats -#define DEFIB_TIME_LIMIT 120 +#define DEFIB_TIME_LIMIT 900 #define DEFIB_TIME_LOSS 60 // Diagonal movement diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm index 97eae9f71d2..b30d4370286 100644 --- a/code/__DEFINES/obj_flags.dm +++ b/code/__DEFINES/obj_flags.dm @@ -42,3 +42,11 @@ #define BLOCKS_SHOVE_KNOCKDOWN (1<<10) // Prevents shovies against a dense object from knocking the wearer down. #define SNUG_FIT (1<<11) //Prevents knock-off from things like hat-throwing. #define ANTI_TINFOIL_MANEUVER (1<<12) //Hats with negative effects when worn (i.e the tinfoil hat). + +/// Flags for the organ_flags var on /obj/item/organ + +#define ORGAN_SYNTHETIC (1<<0) //Synthetic organs, or cybernetic organs. Reacts to EMPs and don't deteriorate or heal +#define ORGAN_FROZEN (1<<1) //Frozen organs, don't deteriorate +#define ORGAN_FAILING (1<<2) //Failing organs perform damaging effects until replaced or fixed +#define ORGAN_EXTERNAL (1<<3) //Was this organ implanted/inserted/etc, if true will not be removed during species change. +#define ORGAN_VITAL (1<<4) //Currently only the brain diff --git a/code/__DEFINES/stat.dm b/code/__DEFINES/stat.dm index 1d3ea1347a0..b975aa1f89b 100644 --- a/code/__DEFINES/stat.dm +++ b/code/__DEFINES/stat.dm @@ -8,6 +8,9 @@ #define UNCONSCIOUS 2 #define DEAD 3 +//Maximum healthiness an individual can have +#define MAX_SATIETY 600 + // bitflags for machine stat variable #define BROKEN (1<<0) #define NOPOWER (1<<1) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index e6f0bfef03d..74e7e241dc3 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -159,6 +159,43 @@ processing_list.Cut(1, 2) processing_list += A.contents +/** recursive_organ_check + * inputs: O (object to start with) + * outputs: + * description: A pseudo-recursive loop based off of the recursive mob check, this check looks for any organs held + * within 'O', toggling their frozen flag. This check excludes items held within other safe organ + * storage units, so that only the lowest level of container dictates whether we do or don't decompose + */ +/proc/recursive_organ_check(atom/O) + + var/list/processing_list = list(O) + var/list/processed_list = list() + var/index = 1 + var/obj/item/organ/found_organ + + while(index <= length(processing_list)) + + var/atom/A = processing_list[index] + + if(istype(A, /obj/item/organ)) + found_organ = A + found_organ.organ_flags ^= ORGAN_FROZEN + + else if(istype(A, /mob/living/carbon)) + var/mob/living/carbon/Q = A + for(var/organ in Q.internal_organs) + found_organ = organ + found_organ.organ_flags ^= ORGAN_FROZEN + + for(var/atom/B in A) //objects held within other objects are added to the processing list, unless that object is something that can hold organs safely + if(!processed_list[B] && !istype(B, /obj/structure/closet/crate/freezer) && !istype(B, /obj/structure/closet/secure_closet/freezer)) + processing_list+= B + + index++ + processed_list[A] = A + + return + // Better recursive loop, technically sort of not actually recursive cause that shit is retarded, enjoy. //No need for a recursive limit either /proc/recursive_mob_check(atom/O,client_check=1,sight_check=1,include_radio=1) diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 4140d5b04f1..5c0a8e5587c 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -42,8 +42,12 @@ for(var/path in subtypesof(/datum/surgery)) GLOB.surgeries_list += new path() + //Materials + for(var/path in subtypesof(/datum/material)) + var/datum/material/D = new path() + GLOB.materials_list[D.id] = D + GLOB.emote_list = init_emote_list() - init_subtypes(/datum/crafting_recipe, GLOB.crafting_recipes) diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm index 1ea47134cd6..14c752613bf 100644 --- a/code/_globalvars/lists/objects.dm +++ b/code/_globalvars/lists/objects.dm @@ -16,6 +16,7 @@ GLOBAL_LIST_EMPTY(singularities) //list of all singularities on the stati GLOBAL_LIST(chemical_reactions_list) //list of all /datum/chemical_reaction datums. Used during chemical reactions GLOBAL_LIST(chemical_reagents_list) //list of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff +GLOBAL_LIST_EMPTY(materials_list) //list of all /datum/material datums indexed by material id. GLOBAL_LIST_EMPTY(tech_list) //list of all /datum/tech datums indexed by id. GLOBAL_LIST_EMPTY(surgeries_list) //list of all surgeries by name, associated with their path. GLOBAL_LIST_EMPTY(crafting_recipes) //list of all table craft recipes diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm index 728308e286d..df8a07eb124 100644 --- a/code/controllers/subsystem/blackbox.dm +++ b/code/controllers/subsystem/blackbox.dm @@ -296,7 +296,7 @@ Versioning var/lakey = L.lastattackerckey var/sqlbrute = L.getBruteLoss() var/sqlfire = L.getFireLoss() - var/sqlbrain = L.getBrainLoss() + var/sqlbrain = L.getOrganLoss(ORGAN_SLOT_BRAIN) var/sqloxy = L.getOxyLoss() var/sqltox = L.getToxLoss() var/sqlclone = L.getCloneLoss() diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 00074a3267b..2af8c12fda6 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -86,6 +86,7 @@ atomsnowflake += "[D]" atomsnowflake += "
<< [dir2text(A.dir) || A.dir] >>" var/mob/living/M = A + atomsnowflake += {"
[M.ckey || "No ckey"] / [M.real_name || "No real name"]
@@ -94,7 +95,7 @@ TOXIN:[M.getToxLoss()] OXY:[M.getOxyLoss()] CLONE:[M.getCloneLoss()] - BRAIN:[M.getBrainLoss()] + BRAIN:[M.getOrganLoss(ORGAN_SLOT_BRAIN)] STAMINA:[M.getStaminaLoss()] "} @@ -1356,8 +1357,8 @@ L.adjustOxyLoss(amount) newamt = L.getOxyLoss() if("brain") - L.adjustBrainLoss(amount) - newamt = L.getBrainLoss() + L.adjustOrganLoss(ORGAN_SLOT_BRAIN, amount) + newamt = L.getOrganLoss(ORGAN_SLOT_BRAIN) if("clone") L.adjustCloneLoss(amount) newamt = L.getCloneLoss() diff --git a/code/datums/diseases/advance/symptoms/choking.dm b/code/datums/diseases/advance/symptoms/choking.dm index 93cf0acd106..8fa3bed016d 100644 --- a/code/datums/diseases/advance/symptoms/choking.dm +++ b/code/datums/diseases/advance/symptoms/choking.dm @@ -144,5 +144,5 @@ Bonus /datum/symptom/asphyxiation/proc/Asphyxiate_death(mob/living/M, datum/disease/advance/A) var/get_damage = rand(25,35) * power M.adjustOxyLoss(get_damage) - M.adjustBrainLoss(get_damage/2) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, get_damage/2) return 1 diff --git a/code/datums/diseases/advance/symptoms/confusion.dm b/code/datums/diseases/advance/symptoms/confusion.dm index e7315c6bb1d..1049e1a31a5 100644 --- a/code/datums/diseases/advance/symptoms/confusion.dm +++ b/code/datums/diseases/advance/symptoms/confusion.dm @@ -55,7 +55,7 @@ Bonus to_chat(M, "You can't think straight!") M.confused = min(100 * power, M.confused + 8) if(brain_damage) - M.adjustBrainLoss(3 * power, 80) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN,3 * power, 80) M.updatehealth() return diff --git a/code/datums/diseases/advance/symptoms/sensory.dm b/code/datums/diseases/advance/symptoms/sensory.dm index bcc46f4bd26..58b64ae4903 100644 --- a/code/datums/diseases/advance/symptoms/sensory.dm +++ b/code/datums/diseases/advance/symptoms/sensory.dm @@ -51,7 +51,7 @@ M.hallucination = max(0, M.hallucination - 10) if(A.stage >= 5) - M.adjustBrainLoss(-3) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -3) if(trauma_heal_mild && iscarbon(M)) var/mob/living/carbon/C = M if(prob(10)) diff --git a/code/datums/diseases/advance/symptoms/vision.dm b/code/datums/diseases/advance/symptoms/vision.dm index d2b33858cb7..b4759117d3f 100644 --- a/code/datums/diseases/advance/symptoms/vision.dm +++ b/code/datums/diseases/advance/symptoms/vision.dm @@ -45,7 +45,7 @@ Bonus return var/mob/living/carbon/M = A.affected_mob var/obj/item/organ/eyes/eyes = M.getorganslot(ORGAN_SLOT_EYES) - if(istype(eyes)) + if(eyes) switch(A.stage) if(1, 2) if(prob(base_message_chance) && !suppress_warning) diff --git a/code/datums/diseases/appendicitis.dm b/code/datums/diseases/appendicitis.dm index 57084475423..be7e6ceecdb 100644 --- a/code/datums/diseases/appendicitis.dm +++ b/code/datums/diseases/appendicitis.dm @@ -27,8 +27,10 @@ A.update_icon() if(prob(3)) to_chat(affected_mob, "You feel a stabbing pain in your abdomen!") + affected_mob.adjustOrganLoss(ORGAN_SLOT_APPENDIX, 5) affected_mob.Stun(rand(40,60)) affected_mob.adjustToxLoss(1) if(3) if(prob(1)) affected_mob.vomit(95) + affected_mob.adjustOrganLoss(ORGAN_SLOT_APPENDIX, 15) diff --git a/code/datums/diseases/brainrot.dm b/code/datums/diseases/brainrot.dm index fc4c057ce5c..1028d1fff4c 100644 --- a/code/datums/diseases/brainrot.dm +++ b/code/datums/diseases/brainrot.dm @@ -24,7 +24,7 @@ if(prob(2)) to_chat(affected_mob, "You don't feel like yourself.") if(prob(5)) - affected_mob.adjustBrainLoss(1, 170) + affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1, 170) affected_mob.updatehealth() if(3) if(prob(2)) @@ -32,7 +32,7 @@ if(prob(2)) affected_mob.emote("drool") if(prob(10)) - affected_mob.adjustBrainLoss(2, 170) + affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2, 170) affected_mob.updatehealth() if(prob(2)) to_chat(affected_mob, "Your try to remember something important...but can't.") @@ -43,7 +43,7 @@ if(prob(2)) affected_mob.emote("drool") if(prob(15)) - affected_mob.adjustBrainLoss(3, 170) + affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3, 170) affected_mob.updatehealth() if(prob(2)) to_chat(affected_mob, "Strange buzzing fills your head, removing all thoughts.") diff --git a/code/datums/diseases/decloning.dm b/code/datums/diseases/decloning.dm index 70d10bc7de8..b332876c010 100644 --- a/code/datums/diseases/decloning.dm +++ b/code/datums/diseases/decloning.dm @@ -40,7 +40,7 @@ if(prob(2)) affected_mob.emote("drool") if(prob(5)) - affected_mob.adjustBrainLoss(1, 170) + affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1, 170) affected_mob.adjustCloneLoss(2) if(prob(15)) affected_mob.stuttering += 3 @@ -53,7 +53,7 @@ to_chat(affected_mob, "Your skin starts degrading!") if(prob(10)) affected_mob.adjustCloneLoss(5) - affected_mob.adjustBrainLoss(2, 170) + affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2, 170) if(affected_mob.cloneloss >= 100) affected_mob.visible_message("[affected_mob] skin turns to dust!", "Your skin turns to dust!") affected_mob.dust() \ No newline at end of file diff --git a/code/datums/dna.dm b/code/datums/dna.dm index d26da2463c9..11607b8dddc 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -649,4 +649,4 @@ eyes.Remove(src) qdel(eyes) visible_message("[src] looks up and their eyes melt away!", "='userdanger'>I understand now.") - addtimer(CALLBACK(src, .proc/adjustBrainLoss, 200), 20) + addtimer(CALLBACK(src, .proc/adjustOrganLoss, ORGAN_SLOT_BRAIN, 200), 20) diff --git a/code/datums/martial/cqc.dm b/code/datums/martial/cqc.dm index ed3471c79bf..eb47a74491a 100644 --- a/code/datums/martial/cqc.dm +++ b/code/datums/martial/cqc.dm @@ -11,7 +11,7 @@ block_chance = 75 var/just_a_cook = FALSE var/old_grab_state = null - + /datum/martial_art/cqc/under_siege name = "Close Quarters Cooking" just_a_cook = TRUE @@ -78,7 +78,7 @@ "[A] kicks your head, knocking you out!") playsound(get_turf(A), 'sound/weapons/genhit1.ogg', 50, 1, -1) D.SetSleeping(300) - D.adjustBrainLoss(15, 150) + D.adjustOrganLoss(ORGAN_SLOT_BRAIN, 15, 150) return TRUE /datum/martial_art/cqc/proc/Pressure(mob/living/carbon/human/A, mob/living/carbon/human/D) @@ -125,7 +125,7 @@ add_to_streak("G",D) if(check_streak(A,D)) //if a combo is made no grab upgrade is done return TRUE - old_grab_state = A.grab_state + old_grab_state = A.grab_state D.grabbedby(A, 1) if(old_grab_state == GRAB_PASSIVE) D.drop_all_held_items() diff --git a/code/datums/martial/psychotic_brawl.dm b/code/datums/martial/psychotic_brawl.dm index a6e42e3c3e0..41f79dc6dbf 100644 --- a/code/datums/martial/psychotic_brawl.dm +++ b/code/datums/martial/psychotic_brawl.dm @@ -46,7 +46,7 @@ D.apply_damage(rand(5,10), A.dna.species.attack_type, BODY_ZONE_HEAD) A.apply_damage(rand(5,10), A.dna.species.attack_type, BODY_ZONE_HEAD) if(!istype(D.head,/obj/item/clothing/head/helmet/) && !istype(D.head,/obj/item/clothing/head/hardhat)) - D.adjustBrainLoss(5) + D.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5) A.Stun(rand(10,45)) D.Stun(rand(5,30)) if(5,6) diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm index 777a01243e3..1a6b8324b23 100644 --- a/code/datums/martial/sleeping_carp.dm +++ b/code/datums/martial/sleeping_carp.dm @@ -242,7 +242,7 @@ H.visible_message("[user] delivers a heavy hit to [H]'s head, knocking [H.p_them()] out cold!", \ "[user] knocks you unconscious!") H.SetSleeping(600) - H.adjustBrainLoss(15, 150) + H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 15, 150) else return ..() diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index 80ade7fb5b9..5771b2cf8f8 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -525,7 +525,7 @@ itemUser.adjustToxLoss(-1.5, forced = TRUE) //Because Slime People are people too itemUser.adjustOxyLoss(-1.5) itemUser.adjustStaminaLoss(-1.5) - itemUser.adjustBrainLoss(-1.5) + itemUser.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1.5) itemUser.adjustCloneLoss(-0.5) //Becasue apparently clone damage is the bastion of all health //Heal all those around you, unbiased for(var/mob/living/L in view(7, owner)) @@ -537,7 +537,7 @@ L.adjustToxLoss(-3.5, forced = TRUE) //Because Slime People are people too L.adjustOxyLoss(-3.5) L.adjustStaminaLoss(-3.5) - L.adjustBrainLoss(-3.5) + L.adjustOrganLoss(ORGAN_SLOT_BRAIN, -3.5) L.adjustCloneLoss(-1) //Becasue apparently clone damage is the bastion of all health else if(issilicon(L)) L.adjustBruteLoss(-3.5) diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm index 2d60b35e160..c03f297e3ff 100644 --- a/code/datums/traits/negative.dm +++ b/code/datums/traits/negative.dm @@ -59,7 +59,7 @@ medical_record_text = "Patient has a tumor in their brain that is slowly driving them to brain death." /datum/quirk/brainproblems/on_process() - quirk_holder.adjustBrainLoss(0.2) + quirk_holder.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.2) /datum/quirk/deafness name = "Deaf" diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index d8e669f4dfb..19066176685 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -195,7 +195,7 @@ data["occupant"]["toxLoss"] = mob_occupant.getToxLoss() data["occupant"]["fireLoss"] = mob_occupant.getFireLoss() data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss() - data["occupant"]["brainLoss"] = mob_occupant.getBrainLoss() + data["occupant"]["brainLoss"] = mob_occupant.getOrganLoss(ORGAN_SLOT_BRAIN) data["occupant"]["reagents"] = list() if(mob_occupant.reagents && mob_occupant.reagents.reagent_list.len) for(var/datum/reagent/R in mob_occupant.reagents.reagent_list) diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 85ae13751b2..1e60f12d30d 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -290,6 +290,7 @@ var/obj/item/I = pick_n_take(unattached_flesh) if(isorgan(I)) var/obj/item/organ/O = I + O.organ_flags &= ~ORGAN_FROZEN O.Insert(mob_occupant) else if(isbodypart(I)) var/obj/item/bodypart/BP = I @@ -307,6 +308,7 @@ for(var/i in unattached_flesh) if(isorgan(i)) var/obj/item/organ/O = i + O.organ_flags &= ~ORGAN_FROZEN O.Insert(mob_occupant) else if(isbodypart(i)) var/obj/item/bodypart/BP = i @@ -397,6 +399,9 @@ if(mess) //Clean that mess and dump those gibs! for(var/obj/fl in unattached_flesh) fl.forceMove(T) + if(istype(fl, /obj/item/organ)) + var/obj/item/organ/O = fl + O.organ_flags &= ~ORGAN_FROZEN unattached_flesh.Cut() mess = FALSE new /obj/effect/gibspawner/generic(get_turf(src), mob_occupant) @@ -419,8 +424,6 @@ to_chat(occupant, "There is a bright flash!
You feel like a new being.
") mob_occupant.flash_act() - mob_occupant.adjustBrainLoss(mob_occupant.getCloneLoss()) - occupant.forceMove(T) icon_state = "pod_0" mob_occupant.domutcheck(1) //Waiting until they're out before possible monkeyizing. The 1 argument forces powers to manifest. @@ -516,8 +519,9 @@ for(var/o in H.internal_organs) var/obj/item/organ/organ = o - if(!istype(organ) || organ.vital) + if(!istype(organ) || (organ.organ_flags & ORGAN_VITAL)) continue + organ.organ_flags |= ORGAN_FROZEN organ.Remove(H, special=TRUE) organ.forceMove(src) unattached_flesh += organ diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index d4ecbe67eec..bb936d6ba05 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -168,7 +168,7 @@ Toxin Content: [patient.getToxLoss()]%
Burn Severity: [patient.getFireLoss()]%
[patient.getCloneLoss() ? "Subject appears to have cellular damage." : ""]
- [patient.getBrainLoss() ? "Significant brain damage detected." : ""]
+ [patient.getOrganLoss(ORGAN_SLOT_BRAIN) ? "Significant brain damage detected." : ""]
[length(patient.get_traumas()) ? "Brain Traumas detected." : ""]
"} diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm index 0c9bbc54734..8e006ab2b2b 100644 --- a/code/game/objects/items/circuitboards/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm @@ -449,6 +449,7 @@ /obj/machinery/smartfridge/food = "food", /obj/machinery/smartfridge/drinks = "drinks", /obj/machinery/smartfridge/extract = "slimes", + /obj/machinery/smartfridge/organ = "organs", /obj/machinery/smartfridge/chemistry = "chems", /obj/machinery/smartfridge/chemistry/virology = "viruses", /obj/machinery/smartfridge/disks = "disks") diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm index a640408bd96..04f64a6e6de 100644 --- a/code/game/objects/items/defib.dm +++ b/code/game/objects/items/defib.dm @@ -455,16 +455,17 @@ do_help(H, user) /obj/item/twohanded/shockpaddles/proc/can_defib(mob/living/carbon/H) + var/obj/item/organ/heart = H.getorgan(/obj/item/organ/heart) if(H.suiciding || H.hellbound || HAS_TRAIT(H, TRAIT_HUSK)) return if((world.time - H.timeofdeath) > tlimit) return if((H.getBruteLoss() >= MAX_REVIVE_BRUTE_DAMAGE) || (H.getFireLoss() >= MAX_REVIVE_FIRE_DAMAGE)) return - if(!H.getorgan(/obj/item/organ/heart)) + if(!heart || (heart.organ_flags & ORGAN_FAILING)) return var/obj/item/organ/brain/BR = H.getorgan(/obj/item/organ/brain) - if(QDELETED(BR) || BR.brain_death || BR.damaged_brain || BR.suicided) + if(QDELETED(BR) || BR.brain_death || (BR.organ_flags & ORGAN_FAILING) || BR.suicided) return return TRUE @@ -561,14 +562,10 @@ if(do_after(user, 30, target = H)) //beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process user.visible_message("[user] places [src] on [H]'s chest.", "You place [src] on [H]'s chest.") playsound(src, 'sound/machines/defib_charge.ogg', 75, 0) - var/tplus = world.time - H.timeofdeath - // past this much time the patient is unrecoverable - // (in deciseconds) - // brain damage starts setting in on the patient after - // some time left rotting - var/tloss = DEFIB_TIME_LOSS * 10 var/total_burn = 0 var/total_brute = 0 + var/tplus = world.time - H.timeofdeath //length of time spent dead + var/obj/item/organ/heart = H.getorgan(/obj/item/organ/heart) if(do_after(user, 20, target = H)) //placed on chest and short delay to shock for dramatic effect, revive time is 5sec total for(var/obj/item/carried_item in H.contents) if(istype(carried_item, /obj/item/clothing/suit/space)) @@ -593,8 +590,10 @@ failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's soul appears to be on another plane of existence. Further attempts futile." else if (tplus > tlimit) failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Body has decayed for too long. Further attempts futile." - else if (!H.getorgan(/obj/item/organ/heart)) + else if (!heart) failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's heart is missing." + else if (heart.organ_flags & ORGAN_FAILING) + failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's heart too damaged." else if(total_burn >= MAX_REVIVE_FIRE_DAMAGE || total_brute >= MAX_REVIVE_BRUTE_DAMAGE || HAS_TRAIT(H, TRAIT_HUSK)) failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Severe tissue damage makes recovery of patient impossible via defibrillator. Further attempts futile." else if(H.get_ghost()) @@ -602,7 +601,7 @@ else var/obj/item/organ/brain/BR = H.getorgan(/obj/item/organ/brain) if(BR) - if(BR.damaged_brain) + if(BR.organ_flags & ORGAN_FAILING) failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's brain tissue is damaged making recovery of patient impossible via defibrillator. Further attempts futile." if(BR.brain_death) failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's brain damaged beyond point of no return. Further attempts futile." @@ -633,8 +632,6 @@ H.emote("gasp") H.Jitter(100) SEND_SIGNAL(H, COMSIG_LIVING_MINOR_SHOCK) - if(tplus > tloss) - H.adjustBrainLoss( max(0, min(99, ((tlimit - tplus) / tlimit * 100))), 150) log_combat(user, H, "revived", defib) if(req_defib) defib.deductcharge(revivecost) @@ -648,10 +645,12 @@ user.visible_message("[req_defib ? "[defib]" : "[src]"] buzzes: Patient's heart is missing. Operation aborted.") playsound(src, 'sound/machines/defib_failed.ogg', 50, 0) else if(H.undergoing_cardiac_arrest()) - H.set_heartattack(FALSE) - user.visible_message("[req_defib ? "[defib]" : "[src]"] pings: Patient's heart is now beating again.") playsound(src, 'sound/machines/defib_zap.ogg', 50, 1, -1) - + if(!(heart.organ_flags & ORGAN_FAILING)) + H.set_heartattack(FALSE) + user.visible_message("[req_defib ? "[defib]" : "[src]"] pings: Patient's heart is now beating again.") + else + user.visible_message("[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed, heart damage detected.") else user.visible_message("[req_defib ? "[defib]" : "[src]"] buzzes: Patient is not in a valid state. Operation aborted.") diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index c12209b5813..9fe74be049d 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -144,12 +144,6 @@ GENE SCANNER var/mob/living/carbon/human/H = M if(H.undergoing_cardiac_arrest() && H.stat != DEAD) to_chat(user, "Subject suffering from heart attack: Apply defibrillation or other electric shock immediately!") - //organ failure messages - for(var/O in H.internal_organs) - var/obj/item/organ/organ = O - if(!istype(organ, /obj/item/organ/heart)) - if(organ.failing) - to_chat(user, organ.Assemble_Failure_Message()) to_chat(user, "Analyzing results for [M]:\n\tOverall status: [mob_status]") @@ -170,12 +164,8 @@ GENE SCANNER to_chat(user, "\tSubject appears to have [M.getCloneLoss() > 30 ? "Severe" : "Minor"] cellular damage.") if(advanced) to_chat(user, "\tCellular Damage Level: [M.getCloneLoss()].") - if (M.getBrainLoss() >= 200 || !M.getorgan(/obj/item/organ/brain)) - to_chat(user, "\tSubject's brain function is non-existent.") - else if (M.getBrainLoss() >= 120) - to_chat(user, "\tSevere brain damage detected. Subject likely to have mental traumas.") - else if (M.getBrainLoss() >= 45) - to_chat(user, "\tBrain damage detected.") + if (!M.getorgan(/obj/item/organ/brain)) + to_chat(user, "\tSubject lacks a brain.") if(iscarbon(M)) var/mob/living/carbon/C = M if(LAZYLEN(C.get_traumas())) @@ -195,7 +185,7 @@ GENE SCANNER if(C.roundstart_quirks.len) to_chat(user, "\tSubject has the following physiological traits: [C.get_trait_string()].") if(advanced) - to_chat(user, "\tBrain Activity Level: [(200 - M.getBrainLoss())/2]%.") + to_chat(user, "\tBrain Activity Level: [(200 - M.getOrganLoss(ORGAN_SLOT_BRAIN))/2]%.") if (M.radiation) to_chat(user, "\tSubject is irradiated.") @@ -255,15 +245,6 @@ GENE SCANNER to_chat(user, "\tSubject does not have eyes.") - if(ishuman(M)) - var/mob/living/carbon/human/H = M - for(var/O in H.internal_organs) - var/obj/item/organ/organ = O - if((organ.damage > organ.low_threshold)&&(!istype(organ, /obj/item/organ/brain))) - to_chat(user, "\t[organ.damage > organ.high_threshold ? "Severe" : "Minor"] damaged detected within [organ].") - if(advanced && H.has_dna()) - to_chat(user, "\tGenetic Stability: [H.dna.stability]%.") - // Body part damage report if(iscarbon(M) && mode == 1) var/mob/living/carbon/C = M @@ -273,6 +254,62 @@ GENE SCANNER for(var/obj/item/bodypart/org in damaged) to_chat(user, "\t\t[capitalize(org.name)]: [(org.brute_dam > 0) ? "[org.brute_dam]" : "0"]-[(org.burn_dam > 0) ? "[org.burn_dam]" : "0"]") + //Organ damages report + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/minor_damage + var/major_damage + var/max_damage + var/report_organs = FALSE + + //Piece together the lists to be reported + for(var/O in H.internal_organs) + var/obj/item/organ/organ = O + if(organ.organ_flags & ORGAN_FAILING) + report_organs = TRUE //if we report one organ, we report all organs, even if the lists are empty, just for consistency + if(max_damage) + max_damage += ", " //prelude the organ if we've already reported an organ + max_damage += organ.name //this just slaps the organ name into the string of text + else + max_damage = "\tNon-Functional Organs: " //our initial statement + max_damage += organ.name + else if(organ.damage > organ.high_threshold) + report_organs = TRUE + if(major_damage) + major_damage += ", " + major_damage += organ.name + else + major_damage = "\tSeverely Damaged Organs: " + major_damage += organ.name + else if(organ.damage > organ.low_threshold) + report_organs = TRUE + if(minor_damage) + minor_damage += ", " + minor_damage += organ.name + else + minor_damage = "\tMildly Damaged Organs: " + minor_damage += organ.name + + if(report_organs) //we either finish the list, or set it to be empty if no organs were reported in that category + if(!max_damage) + max_damage = "\tNon-Functional Organs: " + else + max_damage += "" + if(!major_damage) + major_damage = "\tSeverely Damaged Organs: " + else + major_damage += "" + if(!minor_damage) + minor_damage = "\tMildly Damaged Organs: " + else + minor_damage += "" + to_chat(user, minor_damage) + to_chat(user, major_damage) + to_chat(user, max_damage) + //Genetic damage + if(advanced && H.has_dna()) + to_chat(user, "\tGenetic Stability: [H.dna.stability]%.") + // Species and body temperature if(ishuman(M)) var/mob/living/carbon/human/H = M diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index a734a08fa68..725efbbe704 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -259,7 +259,7 @@ to_chat(user, "Sticking a dead brain into the frame would sort of defeat the purpose!") return - if(M.brain?.damaged_brain) + if(M.brain?.organ_flags & ORGAN_FAILING) to_chat(user, "The MMI indicates that the brain is damaged!") return diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm index d9c1f31c40d..8ecd0e15637 100644 --- a/code/game/objects/items/storage/book.dm +++ b/code/game/objects/items/storage/book.dm @@ -148,7 +148,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "burning", else if(iscarbon(M)) var/mob/living/carbon/C = M if(!istype(C.head, /obj/item/clothing/head/helmet)) - C.adjustBrainLoss(5, 60) + C.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5, 60) to_chat(C, "You feel dumber.") if(smack) @@ -221,9 +221,9 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "burning", SS.icon_state = "purified_soulstone2" for(var/mob/living/simple_animal/shade/EX in SS) EX.icon_state = "ghost1" - EX.name = "Purified [initial(EX.name)]" + EX.name = "Purified [initial(EX.name)]" user.visible_message("[user] has purified [SS]!") - + /obj/item/storage/book/bible/booze desc = "To be applied to the head repeatedly." diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm index fe40c352491..1de64dcd2c5 100644 --- a/code/game/objects/items/twohanded.dm +++ b/code/game/objects/items/twohanded.dm @@ -298,7 +298,7 @@ var/obj/item/bodypart/head/myhead = user.get_bodypart(BODY_ZONE_HEAD)//stole from chainsaw code var/obj/item/organ/brain/B = user.getorganslot(ORGAN_SLOT_BRAIN) - B.vital = FALSE//this cant possibly be a good idea + B.organ_flags &= ~ORGAN_VITAL //this cant possibly be a good idea var/randdir for(var/i in 1 to 24)//like a headless chicken! if(user.is_holding(src)) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm b/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm index 6607a0e8ea9..7255cdb0a2f 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm @@ -2,6 +2,24 @@ icon_state = "freezer" var/jones = FALSE +/obj/structure/closet/secure_closet/freezer/Destroy() + recursive_organ_check(src) + ..() + +/obj/structure/closet/secure_closet/freezer/Initialize() + ..() + recursive_organ_check(src) + +/obj/structure/closet/secure_closet/freezer/open(mob/living/user) + if(opened || !can_open(user)) //dupe check just so we don't let the organs decay when someone fails to open the locker + return FALSE + recursive_organ_check(src) + return ..() + +/obj/structure/closet/secure_closet/freezer/close(mob/living/user) + if(..()) //if we actually closed the locker + recursive_organ_check(src) + /obj/structure/closet/secure_closet/freezer/ex_act() if(!jones) jones = TRUE diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index f8135538c30..6aa741ed8b5 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -93,6 +93,27 @@ name = "freezer" icon_state = "freezer" +//Snowflake organ freezer code +//Order is important, since we check source, we need to do the check whenever we have all the organs in the crate + +/obj/structure/closet/crate/freezer/open() + recursive_organ_check(src) + ..() + +/obj/structure/closet/crate/freezer/close() + ..() + recursive_organ_check(src) + +/obj/structure/closet/crate/freezer/Destroy() + recursive_organ_check(src) + ..() + +/obj/structure/closet/crate/freezer/Initialize() + ..() + recursive_organ_check(src) + + + /obj/structure/closet/crate/freezer/blood name = "blood freezer" desc = "A freezer containing packs of blood." diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index f9bef821e7a..4017584f05e 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -31,6 +31,7 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an /obj/structure/bodycontainer/Initialize() . = ..() GLOB.bodycontainers += src + recursive_organ_check(src) /obj/structure/bodycontainer/Destroy() GLOB.bodycontainers -= src @@ -101,6 +102,7 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an /obj/structure/bodycontainer/deconstruct(disassembled = TRUE) new /obj/item/stack/sheet/metal (loc, 5) + recursive_organ_check(src) qdel(src) /obj/structure/bodycontainer/container_resist(mob/living/user) @@ -120,6 +122,7 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an open() /obj/structure/bodycontainer/proc/open() + recursive_organ_check(src) playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1) playsound(src, 'sound/effects/roll.ogg', 5, 1) var/turf/T = get_step(src, dir) @@ -136,6 +139,7 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an if(ismob(AM) && !isliving(AM)) continue AM.forceMove(src) + recursive_organ_check(src) update_icon() /obj/structure/bodycontainer/get_remote_view_fullscreens(mob/user) diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm index b6e8b3248d1..bbbc998b0c7 100644 --- a/code/modules/admin/secrets.dm +++ b/code/modules/admin/secrets.dm @@ -453,7 +453,7 @@ SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Mass Braindamage")) for(var/mob/living/carbon/human/H in GLOB.player_list) to_chat(H, "You suddenly feel stupid.") - H.adjustBrainLoss(60, 80) + H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 60, 80) message_admins("[key_name_admin(usr)] made everybody retarded") if("eagles")//SCRAW diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 393799dd0fa..b5682b7b559 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1015,7 +1015,7 @@ if(DEAD) status = "Dead" health_description = "Status = [status]" - health_description += "
Oxy: [L.getOxyLoss()] - Tox: [L.getToxLoss()] - Fire: [L.getFireLoss()] - Brute: [L.getBruteLoss()] - Clone: [L.getCloneLoss()] - Brain: [L.getBrainLoss()] - Stamina: [L.getStaminaLoss()]" + health_description += "
Oxy: [L.getOxyLoss()] - Tox: [L.getToxLoss()] - Fire: [L.getFireLoss()] - Brute: [L.getBruteLoss()] - Clone: [L.getCloneLoss()] - Brain: [L.getOrganLoss(ORGAN_SLOT_BRAIN)] - Stamina: [L.getStaminaLoss()]" else health_description = "This mob type has no health to speak of." diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 8f4411511fa..2e8a21ea69e 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -1081,7 +1081,7 @@ Traitors and the like can also be revived with the previous role mostly intact. H.electrocution_animation(40) to_chat(target, "The gods have punished you for your sins!") if(ADMIN_PUNISHMENT_BRAINDAMAGE) - target.adjustBrainLoss(199, 199) + target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 199, 199) if(ADMIN_PUNISHMENT_GIB) target.gib(FALSE) if(ADMIN_PUNISHMENT_BSA) diff --git a/code/modules/antagonists/abductor/equipment/glands/mindshock.dm b/code/modules/antagonists/abductor/equipment/glands/mindshock.dm index a27e1ee4369..fa63e2c82ad 100644 --- a/code/modules/antagonists/abductor/equipment/glands/mindshock.dm +++ b/code/modules/antagonists/abductor/equipment/glands/mindshock.dm @@ -22,7 +22,7 @@ if(2) to_chat(H, "You hear an annoying buzz in your head.") H.confused += 15 - H.adjustBrainLoss(10, 160) + H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10, 160) if(3) H.hallucination += 60 diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm index 6677165a920..76c51fed150 100644 --- a/code/modules/antagonists/changeling/changeling.dm +++ b/code/modules/antagonists/changeling/changeling.dm @@ -97,7 +97,7 @@ if(istype(C)) var/obj/item/organ/brain/B = C.getorganslot(ORGAN_SLOT_BRAIN) if(B && (B.decoy_override != initial(B.decoy_override))) - B.vital = TRUE + B.organ_flags |= ORGAN_VITAL B.decoy_override = FALSE remove_changeling_powers() . = ..() @@ -350,7 +350,7 @@ if(istype(C)) var/obj/item/organ/brain/B = C.getorganslot(ORGAN_SLOT_BRAIN) if(B) - B.vital = FALSE + B.organ_flags &= ~ORGAN_VITAL B.decoy_override = TRUE update_changeling_icons_added() return diff --git a/code/modules/antagonists/changeling/powers/regenerate.dm b/code/modules/antagonists/changeling/powers/regenerate.dm index 78fc7ec9af9..bd023bb5b2e 100644 --- a/code/modules/antagonists/changeling/powers/regenerate.dm +++ b/code/modules/antagonists/changeling/powers/regenerate.dm @@ -30,7 +30,7 @@ B = new C.dna.species.mutant_brain() else B = new() - B.vital = FALSE + B.organ_flags &= ~ORGAN_VITAL B.decoy_override = TRUE B.Insert(C) C.regenerate_organs() diff --git a/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm b/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm index 5e5cc52c190..694f46f6039 100644 --- a/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm +++ b/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm @@ -49,7 +49,7 @@ to_chat(user, "The helmet tries to drive a spike through your head as you scramble to remove it!") user.emote("scream") user.apply_damage(30, BRUTE, BODY_ZONE_HEAD) - user.adjustBrainLoss(30) + user.adjustOrganLoss(ORGAN_SLOT_BRAIN, 30) addtimer(CALLBACK(user, /mob/living.proc/dropItemToGround, src, TRUE), 1) //equipped happens before putting stuff on(but not before picking items up), 1). thus, we need to wait for it to be on before forcing it off. /obj/item/clothing/head/helmet/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0) diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm index cc410d17b38..9dda8142e5e 100644 --- a/code/modules/antagonists/slaughter/slaughter.dm +++ b/code/modules/antagonists/slaughter/slaughter.dm @@ -73,6 +73,7 @@ desc = "Still it beats furiously, emanating an aura of utter hate." icon = 'icons/obj/surgery.dmi' icon_state = "demon_heart-on" + decay_factor = 0 /obj/item/organ/heart/demon/update_icon() return //always beating visually diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm index 9c684a63761..094f574695c 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm @@ -154,6 +154,13 @@ 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)) + O.forceMove(drop_location()) + adjust_item_drop_location(O) + + /obj/machinery/smartfridge/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) @@ -206,9 +213,7 @@ if(desired == 1 && Adjacent(usr) && !issilicon(usr)) for(var/obj/item/O in src) if(O.name == params["name"]) - if(!usr.put_in_hands(O)) - O.forceMove(drop_location()) - adjust_item_drop_location(O) + dispense(O, usr) break if (visible_contents) update_icon() @@ -218,8 +223,7 @@ if(desired <= 0) break if(O.name == params["name"]) - O.forceMove(drop_location()) - adjust_item_drop_location(O) + dispense(O, usr) desired-- if (visible_contents) update_icon() @@ -387,6 +391,55 @@ /obj/machinery/smartfridge/extract/preloaded initial_contents = list(/obj/item/slime_scanner = 2) +// ------------------------- +// Organ Surgery Smartfridge +// ------------------------- +/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 + var/repair_rate = 0 + +/obj/machinery/smartfridge/organ/accept_check(obj/item/O) + if(istype(O, /obj/item/organ)) + return TRUE + return FALSE + +/obj/machinery/smartfridge/organ/load(obj/item/O) + if(..()) //if the item loads, clear can_decompose + var/obj/item/organ/organ = O + organ.organ_flags |= ORGAN_FROZEN + +/obj/machinery/smartfridge/organ/dispense(obj/item/O, var/mob/M) + 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) + max_n_of_items = 20 * B.rating + repair_rate = max(0, STANDARD_ORGAN_HEALING * (B.rating - 1)) + +/obj/machinery/smartfridge/organ/Destroy() + for(var/organ in src) + var/obj/item/organ/O = organ + if(O) + O.organ_flags &= ~ORGAN_FROZEN + ..() + +/obj/machinery/smartfridge/organ/process() + for(var/organ in src) + var/obj/item/organ/O = organ + if(O) + O.damage = max(0, O.damage - repair_rate) + +/obj/machinery/smartfridge/organ/deconstruct() + for(var/organ in src) + var/obj/item/organ/O = organ + if(O) + O.organ_flags &= ~ORGAN_FROZEN + ..() + // ----------------------------- // Chemistry Medical Smartfridge // ----------------------------- diff --git a/code/modules/jobs/job_types/chaplain.dm b/code/modules/jobs/job_types/chaplain.dm index 9ae72795b72..fdf2fb02a46 100644 --- a/code/modules/jobs/job_types/chaplain.dm +++ b/code/modules/jobs/job_types/chaplain.dm @@ -74,7 +74,7 @@ B.name = "Fluorescent Incandescence" if("lol", "wtf", "gay", "penis", "ass", "poo", "badmin", "shitmin", "deadmin", "cock", "cocks", "meme", "memes") B.name = pick("Woodys Got Wood: The Aftermath", "War of the Cocks", "Sweet Bro and Hella Jef: Expanded Edition","F.A.T.A.L. Rulebook") - H.adjustBrainLoss(100) // starts off retarded as fuck + H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 100) // starts off retarded as fuck if("monkeyism","apism","gorillism","primatism") B.name = pick("Going Bananas", "Bananas Out For Harambe") if("mormonism") diff --git a/code/modules/library/lib_codex_gigas.dm b/code/modules/library/lib_codex_gigas.dm index 7a33e3afd99..45ed205c280 100644 --- a/code/modules/library/lib_codex_gigas.dm +++ b/code/modules/library/lib_codex_gigas.dm @@ -46,8 +46,8 @@ if(U.job in list("Curator")) // the curator is both faster, and more accurate than normal crew members at research speed = 100 correctness = 100 - correctness -= U.getBrainLoss() *0.5 //Brain damage makes researching hard. - speed += U.getBrainLoss() * 3 + correctness -= U.getOrganLoss(ORGAN_SLOT_BRAIN) * 0.5 //Brain damage makes researching hard. + speed += U.getOrganLoss(ORGAN_SLOT_BRAIN) * 3 if(do_after(user, speed, 0, user)) var/usedName = devilName if(!prob(correctness)) diff --git a/code/modules/mapping/mapping_helpers.dm b/code/modules/mapping/mapping_helpers.dm index 125eb4331e9..615da4c43e9 100644 --- a/code/modules/mapping/mapping_helpers.dm +++ b/code/modules/mapping/mapping_helpers.dm @@ -225,9 +225,12 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava) var/obj/structure/bodycontainer/morgue/j = pick(trays) var/mob/living/carbon/human/h = new /mob/living/carbon/human(j, 1) h.death() - for (var/part in h.internal_organs) //randomly remove organs from each body + for (var/part in h.internal_organs) //randomly remove organs from each body, set those we keep to be in stasis if (prob(40)) qdel(part) + else + var/obj/item/organ/O = part + O.organ_flags |= ORGAN_FROZEN j.update_icon() qdel(src) diff --git a/code/modules/mob/living/brain/MMI.dm b/code/modules/mob/living/brain/MMI.dm index 3dbca561e96..5cb3a803356 100644 --- a/code/modules/mob/living/brain/MMI.dm +++ b/code/modules/mob/living/brain/MMI.dm @@ -58,11 +58,11 @@ brainmob.forceMove(src) brainmob.container = src var/fubar_brain = newbrain.brain_death && newbrain.suicided && brainmob.suiciding //brain is damaged beyond repair or from a suicider - if(!fubar_brain && !newbrain.damaged_brain) // the brain organ hasn't been beaten to death, nor was from a suicider. + if(!fubar_brain && !(newbrain.organ_flags & ORGAN_FAILING)) // the brain organ hasn't been beaten to death, nor was from a suicider. brainmob.stat = CONSCIOUS //we manually revive the brain mob GLOB.dead_mob_list -= brainmob GLOB.alive_mob_list += brainmob - else if(!fubar_brain && newbrain.damaged_brain) // the brain is damaged, but not from a suicider + else if(!fubar_brain && newbrain.organ_flags & ORGAN_FAILING) // the brain is damaged, but not from a suicider to_chat(user, "[src]'s indicator light turns yellow and its brain integrity alarm beeps softly. Perhaps you should check [newbrain] for damage.") playsound(src, "sound/machines/synth_no.ogg", 5, TRUE) else diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index 896d4cda314..fab32565e56 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -7,13 +7,23 @@ layer = ABOVE_MOB_LAYER zone = BODY_ZONE_HEAD slot = ORGAN_SLOT_BRAIN - vital = TRUE + organ_flags = ORGAN_VITAL attack_verb = list("attacked", "slapped", "whacked") + + ///The brain's organ variables are significantly more different than the other organs, with half the decay rate for balance reasons, and twice the maxHealth + decay_factor = STANDARD_ORGAN_DECAY / 2 //30 minutes of decaying to result in a fully damaged brain, since a fast decay rate would be unfun gameplay-wise + + maxHealth = BRAIN_DAMAGE_DEATH + low_threshold = 45 + high_threshold = 120 + var/suicided = FALSE var/mob/living/brain/brainmob = null var/brain_death = FALSE //if the brainmob was intentionally killed by attacking the brain after removal, or by severe braindamage - var/damaged_brain = FALSE //if the brain was injured after removal. Can be healed with mannitol. var/decoy_override = FALSE //if it's a fake brain with no brainmob assigned. Feedback messages will be faked as if it does have a brainmob. See changelings & dullahans. + //two variables necessary for calculating whether we get a brain trauma or not + var/damage_delta = 0 + var/list/datum/brain_trauma/traumas = list() @@ -94,7 +104,7 @@ if(istype(O, /obj/item/organ_storage)) return //Borg organ bags shouldn't be killing brains - if(damaged_brain && O.is_drainable() && O.reagents.has_reagent(/datum/reagent/medicine/mannitol)) //attempt to heal the brain + if((organ_flags & ORGAN_FAILING) && O.is_drainable() && O.reagents.has_reagent(/datum/reagent/medicine/mannitol)) //attempt to heal the brain . = TRUE //don't do attack animation. if(brain_death || brainmob?.health <= HEALTH_THRESHOLD_DEAD) //if the brain is fucked anyway, do nothing to_chat(user, "[src] is far too damaged, there's nothing else we can do for it!") @@ -110,16 +120,15 @@ return user.visible_message("[user] pours the contents of [O] onto [src], causing it to reform its original shape and turn a slightly brighter shade of pink.", "You pour the contents of [O] onto [src], causing it to reform its original shape and turn a slightly brighter shade of pink.") - damaged_brain = FALSE //heal the superficial damage. - + setOrganDamage(damage - (0.05 * maxHealth)) //heals a small amount, and by using "setorgandamage", we clear the failing variable if that was up O.reagents.clear_reagents() return if(brainmob) //if we aren't trying to heal the brain, pass the attack onto the brainmob. O.attack(brainmob, user) //Oh noooeeeee - - if(O.force != 0 && !(O.item_flags & NOBLUDGEON)) - damaged_brain = TRUE //brain was attacked, they're pretty fragile. + + if(O.force != 0 && !(O.item_flags & NOBLUDGEON)) + setOrganDamage(maxHealth) //fails the brain as the brain was attacked, they're pretty fragile. /obj/item/organ/brain/examine(mob/user) . = ..() @@ -130,17 +139,17 @@ if(brainmob.get_ghost(FALSE, TRUE)) if(brain_death || brainmob.health <= HEALTH_THRESHOLD_DEAD) . += "It's lifeless and severely damaged." - else if(damaged_brain) + else if(organ_flags & ORGAN_FAILING) . += "It seems to still have a bit of energy within it, but it's rather damaged... You may be able to restore it with some mannitol." else . += "You can feel the small spark of life still left in this one." - else if(damaged_brain) + else if(organ_flags & ORGAN_FAILING) . += "It seems particularly lifeless and is rather damaged... You may be able to restore it with some mannitol incase it becomes functional again later." else . += "This one seems particularly lifeless. Perhaps it will regain some of its luster later." else if(decoy_override) - if(damaged_brain) + if(organ_flags & ORGAN_FAILING) . += "It seems particularly lifeless and is rather damaged... You may be able to restore it with some mannitol incase it becomes functional again later." else . += "This one seems particularly lifeless. Perhaps it will regain some of its luster later." @@ -184,36 +193,47 @@ else ..() -/obj/item/organ/brain/proc/get_brain_damage() - var/brain_damage_threshold = max_integrity * BRAIN_DAMAGE_INTEGRITY_MULTIPLIER - var/offset_integrity = obj_integrity - (max_integrity - brain_damage_threshold) - . = round((1 - (offset_integrity / brain_damage_threshold)) * BRAIN_DAMAGE_DEATH, DAMAGE_PRECISION) - -/obj/item/organ/brain/proc/adjust_brain_damage(amount, maximum) - var/adjusted_amount - if(amount >= 0 && maximum) - var/brainloss = get_brain_damage() - var/new_brainloss = CLAMP(brainloss + amount, 0, maximum) - if(brainloss > new_brainloss) //brainloss is over the cap already - return 0 - adjusted_amount = new_brainloss - brainloss - else - adjusted_amount = amount - - adjusted_amount = round(adjusted_amount * BRAIN_DAMAGE_INTEGRITY_MULTIPLIER, DAMAGE_PRECISION) - if(adjusted_amount) - if(adjusted_amount >= DAMAGE_PRECISION) - take_damage(adjusted_amount) - else if(adjusted_amount <= -DAMAGE_PRECISION) - obj_integrity = min(max_integrity, obj_integrity-adjusted_amount) - . = adjusted_amount - /obj/item/organ/brain/Destroy() //copypasted from MMIs. if(brainmob) QDEL_NULL(brainmob) QDEL_LIST(traumas) return ..() +/obj/item/organ/brain/on_life() + if(damage >= BRAIN_DAMAGE_DEATH) //rip + to_chat(owner, "The last spark of life in your brain fizzles out...") + owner.death() + brain_death = TRUE + +/obj/item/organ/brain/process() //needs to run in life AND death + ..() + //if we're not more injured than before, return without gambling for a trauma + if(damage <= prev_damage) + prev_damage = damage + return + damage_delta = damage - prev_damage + if(damage > BRAIN_DAMAGE_MILD) + if(prob(damage_delta * (1 + max(0, (damage - BRAIN_DAMAGE_MILD)/100)))) //Base chance is the hit damage; for every point of damage past the threshold the chance is increased by 1% //learn how to do your bloody math properly goddamnit + gain_trauma_type(BRAIN_TRAUMA_MILD) + if(damage > BRAIN_DAMAGE_SEVERE) + if(prob(damage_delta * (1 + max(0, (damage - BRAIN_DAMAGE_SEVERE)/100)))) //Base chance is the hit damage; for every point of damage past the threshold the chance is increased by 1% + if(prob(20)) + gain_trauma_type(BRAIN_TRAUMA_SPECIAL) + else + gain_trauma_type(BRAIN_TRAUMA_SEVERE) + + if (owner) + if(owner.stat < UNCONSCIOUS) //conscious or soft-crit + if(prev_damage < BRAIN_DAMAGE_MILD && damage >= BRAIN_DAMAGE_MILD) + to_chat(owner, "You feel lightheaded.") + else if(prev_damage < BRAIN_DAMAGE_SEVERE && damage >= BRAIN_DAMAGE_SEVERE) + to_chat(owner, "You feel less in control of your thoughts.") + else if(prev_damage < (BRAIN_DAMAGE_DEATH - 20) && damage >= (BRAIN_DAMAGE_DEATH - 20)) + to_chat(owner, "You can feel your mind flickering on and off...") + //update our previous damage holder after we've checked our boundaries + prev_damage = damage + return + /obj/item/organ/brain/alien name = "alien brain" desc = "We barely understand the brains of terrestial animals. Who knows what we may find in the brain of such an advanced species?" diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 12926fb9e3c..c5ab00c37c8 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -803,7 +803,6 @@ var/obj/item/organ/brain/B = getorgan(/obj/item/organ/brain) if(B) B.brain_death = FALSE - B.damaged_brain = FALSE for(var/thing in diseases) var/datum/disease/D = thing if(D.severity != DISEASE_SEVERITY_POSITIVE) diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm index 3886d23d30f..56383c2bc53 100644 --- a/code/modules/mob/living/carbon/damage_procs.dm +++ b/code/modules/mob/living/carbon/damage_procs.dm @@ -43,8 +43,6 @@ update_damage_overlays() else adjustStaminaLoss(damage_amount, forced = forced) - if(BRAIN) - adjustBrainLoss(damage_amount) return TRUE @@ -115,6 +113,37 @@ return adjustStaminaLoss(diff, updating_health, forced) +/** adjustOrganLoss + * inputs: slot (organ slot, like ORGAN_SLOT_HEART), amount (damage to be done), and maximum (currently an arbitrarily large number, can be set so as to limit damage) + * outputs: + * description: If an organ exists in the slot requested, and we are capable of taking damage (we don't have GODMODE on), call the damage proc on that organ. + */ +/mob/living/carbon/adjustOrganLoss(slot, amount, maximum = 500) + var/obj/item/organ/O = getorganslot(slot) + if(O && !(status_flags & GODMODE)) + O.applyOrganDamage(amount, maximum) + +/** setOrganLoss + * inputs: slot (organ slot, like ORGAN_SLOT_HEART), amount(damage to be set to) + * outputs: + * description: If an organ exists in the slot requested, and we are capable of taking damage (we don't have GODMODE on), call the set damage proc on that organ, which can + * set or clear the failing variable on that organ, making it either cease or start functions again, unlike adjustOrganLoss. + */ +/mob/living/carbon/setOrganLoss(slot, amount) + var/obj/item/organ/O = getorganslot(slot) + if(O && !(status_flags & GODMODE)) + O.setOrganDamage(amount) + +/** getOrganLoss + * inputs: slot (organ slot, like ORGAN_SLOT_HEART) + * outputs: organ damage + * description: If an organ exists in the slot requested, return the amount of damage that organ has + */ +/mob/living/carbon/getOrganLoss(slot) + var/obj/item/organ/O = getorganslot(slot) + if(O) + return O.damage + //////////////////////////////////////////// //Returns a list of damaged bodyparts @@ -216,70 +245,3 @@ if(update) update_damage_overlays() update_stamina() - -/mob/living/carbon/getBrainLoss() - . = 0 - var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN) - if(B) - . = B.get_brain_damage() - -//Some sources of brain damage shouldn't be deadly -/mob/living/carbon/adjustBrainLoss(amount, maximum = BRAIN_DAMAGE_DEATH) - if(status_flags & GODMODE) - return FALSE - var/prev_brainloss = getBrainLoss() - var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN) - if(!B) - return - B.adjust_brain_damage(amount, maximum) - if(amount <= 0) //cut this early - return - var/brainloss = getBrainLoss() - if(brainloss > BRAIN_DAMAGE_MILD) - if(prob(amount * (1 + max(0, (brainloss - BRAIN_DAMAGE_MILD)/100)))) //Base chance is the hit damage; for every point of damage past the threshold the chance is increased by 1% //learn how to do your bloody math properly goddamnit - gain_trauma_type(BRAIN_TRAUMA_MILD) - if(brainloss > BRAIN_DAMAGE_SEVERE) - if(prob(amount * (1 + max(0, (brainloss - BRAIN_DAMAGE_SEVERE)/100)))) //Base chance is the hit damage; for every point of damage past the threshold the chance is increased by 1% - if(prob(20)) - gain_trauma_type(BRAIN_TRAUMA_SPECIAL) - else - gain_trauma_type(BRAIN_TRAUMA_SEVERE) - - if (stat < UNCONSCIOUS) // conscious or soft-crit - if(prev_brainloss < BRAIN_DAMAGE_MILD && brainloss >= BRAIN_DAMAGE_MILD) - to_chat(src, "You feel lightheaded.") - else if(prev_brainloss < BRAIN_DAMAGE_SEVERE && brainloss >= BRAIN_DAMAGE_SEVERE) - to_chat(src, "You feel less in control of your thoughts.") - else if(prev_brainloss < (BRAIN_DAMAGE_DEATH - 20) && brainloss >= (BRAIN_DAMAGE_DEATH - 20)) - to_chat(src, "You can feel your mind flickering on and off...") - -/mob/living/carbon/setBrainLoss(amount) - var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN) - if(B) - var/adjusted_amount = amount - B.get_brain_damage() - B.adjust_brain_damage(adjusted_amount, null) - -/mob/living/carbon/proc/getLiverLoss() - . = 0 - var/obj/item/organ/liver/L = getorganslot(ORGAN_SLOT_LIVER) - if(L) - . = L.damage - -/mob/living/carbon/proc/adjustLiverLoss(amount, check_toxres = TRUE, rev_failure = FALSE) - if(status_flags & GODMODE) - return 0 - var/obj/item/organ/liver/L = getorganslot(ORGAN_SLOT_LIVER) - if(!L) - return - - if(amount < 0 && L.failing && !rev_failure) - return 0 - - var/adjusted_amount = amount - - if(check_toxres) - adjusted_amount *= 100 * L.toxLethality - - L.damage += adjusted_amount - - return adjusted_amount diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index eaa9df7044c..246a558463b 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -753,6 +753,49 @@ if(0 to NUTRITION_LEVEL_STARVING) to_chat(src, "You're starving!") + //Compiles then shows the list of damaged organs and broken organs + var/list/broken = list() + var/list/damaged = list() + var/broken_message + var/damaged_message + var/broken_plural + var/damaged_plural + //Sets organs into their proper list + for(var/O in internal_organs) + var/obj/item/organ/organ = O + if(organ.organ_flags & ORGAN_FAILING) + if(broken.len) + broken += ", " + broken += organ.name + else if(organ.damage > organ.low_threshold) + if(damaged.len) + damaged += ", " + damaged += organ.name + //Checks to enforce proper grammar, inserts words as necessary into the list + if(broken.len) + if(broken.len > 1) + broken.Insert(broken.len, "and ") + broken_plural = TRUE + else + var/holder = broken[1] //our one and only element + if(holder[lentext(holder)] == "s") + broken_plural = TRUE + //Put the items in that list into a string of text + for(var/B in broken) + broken_message += B + to_chat(src, " Your [broken_message] [broken_plural ? "are" : "is"] non-functional!") + if(damaged.len) + if(damaged.len > 1) + damaged.Insert(damaged.len, "and ") + damaged_plural = TRUE + else + var/holder = damaged[1] + if(holder[lentext(holder)] == "s") + damaged_plural = TRUE + for(var/D in damaged) + damaged_message += D + to_chat(src, "Your [damaged_message] [damaged_plural ? "are" : "is"] hurt.") + if(roundstart_quirks.len) to_chat(src, "You have these quirks: [get_trait_string()].") diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 12e2e2b1cfe..99d22f0e470 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -69,7 +69,7 @@ else if(eye_blurry) //blurry eyes heal slowly adjust_blurriness(-1) - if (getBrainLoss() >= 60) + if (getOrganLoss(ORGAN_SLOT_BRAIN) >= 60) SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "brain_damage", /datum/mood_event/brain_damage) else SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "brain_damage") diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 0aa1f4eabab..62ed94da6c4 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -1004,10 +1004,14 @@ GLOBAL_LIST_EMPTY(roundstart_races) var/datum/component/mood/mood = H.GetComponent(/datum/component/mood) if(mood && mood.sanity > SANITY_DISTURBED) hunger_rate *= max(0.5, 1 - 0.002 * mood.sanity) //0.85 to 0.75 - - if(H.satiety > 0) + // Whether we cap off our satiety or move it towards 0 + if(H.satiety > MAX_SATIETY) + H.satiety = MAX_SATIETY + else if(H.satiety > 0) H.satiety-- - if(H.satiety < 0) + else if(H.satiety < -MAX_SATIETY) + H.satiety = -MAX_SATIETY + else if(H.satiety < 0) H.satiety++ if(prob(round(-H.satiety/40))) H.Jitter(5) @@ -1446,7 +1450,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(BODY_ZONE_HEAD) if(!I.is_sharp() && armor_block < 50) if(prob(I.force)) - H.adjustBrainLoss(20) + H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 20) if(H.stat == CONSCIOUS) H.visible_message("[H] has been knocked senseless!", \ "[H] has been knocked senseless!") @@ -1455,7 +1459,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(prob(10)) H.gain_trauma(/datum/brain_trauma/mild/concussion) else - H.adjustBrainLoss(I.force * 0.2) + H.adjustOrganLoss(ORGAN_SLOT_BRAIN, I.force * 0.2) if(H.mind && H.stat == CONSCIOUS && H != user && prob(I.force + ((100 - H.health) * 0.5))) // rev deconversion through blunt trauma. var/datum/antagonist/rev/rev = H.mind.has_antag_datum(/datum/antagonist/rev) @@ -1545,7 +1549,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) H.adjustStaminaLoss(damage_amount) if(BRAIN) var/damage_amount = forced ? damage : damage * hit_percent * H.physiology.brain_mod - H.adjustBrainLoss(damage_amount) + H.adjustOrganLoss(ORGAN_SLOT_BRAIN, damage_amount) return 1 /datum/species/proc/on_hit(obj/item/projectile/P, mob/living/carbon/human/H) diff --git a/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/code/modules/mob/living/carbon/human/species_types/dullahan.dm index 7e7e1411502..a699354b7ae 100644 --- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm +++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm @@ -64,7 +64,7 @@ /obj/item/organ/brain/dullahan decoy_override = TRUE - vital = FALSE + organ_flags = 0 /obj/item/organ/tongue/dullahan zone = "abstract" diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm index 2b2b30793d4..8944c7c4f70 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -96,6 +96,7 @@ color = "#1C1C1C" var/respawn_progress = 0 var/obj/item/light_eater/blade + decay_factor = 0 /obj/item/organ/heart/nightmare/attack(mob/M, mob/living/carbon/user, obj/target) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 8c20d880316..d3763456fc4 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -30,9 +30,6 @@ if(stat != DEAD) handle_brain_damage() - if(stat != DEAD) - handle_liver() - else . = ..() @@ -54,8 +51,18 @@ //Start of a breath chain, calls breathe() /mob/living/carbon/handle_breathing(times_fired) - if((times_fired % 4) == 2 || failed_last_breath) - breathe() //Breathe per 4 ticks, unless suffocating + var/next_breath = 4 + var/obj/item/organ/lungs/L = getorganslot(ORGAN_SLOT_LUNGS) + var/obj/item/organ/heart/H = getorganslot(ORGAN_SLOT_HEART) + if(L) + if(L.damage > L.high_threshold) + next_breath-- + if(H) + if(H.damage > H.high_threshold) + next_breath-- + + if((times_fired % next_breath) == 0 || failed_last_breath) + breathe() //Breathe per 4 ticks if healthy, down to 2 if our lungs or heart are damaged, unless suffocating if(failed_last_breath) SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "suffocation", /datum/mood_event/suffocation) else @@ -67,6 +74,7 @@ //Second link in a breath chain, calls check_breath() /mob/living/carbon/proc/breathe() + var/obj/item/organ/lungs = getorganslot(ORGAN_SLOT_LUNGS) if(reagents.has_reagent(/datum/reagent/toxin/lexorin, needs_metabolizing = TRUE)) return if(istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell)) @@ -79,7 +87,7 @@ var/datum/gas_mixture/breath if(!getorganslot(ORGAN_SLOT_BREATHING_TUBE)) - if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL) || HAS_TRAIT(src, TRAIT_MAGIC_CHOKE)) + if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL) || HAS_TRAIT(src, TRAIT_MAGIC_CHOKE) || lungs.organ_flags & ORGAN_FAILING) losebreath++ //You can't breath at all when in critical or when being choked, so you're going to miss a breath else if(health <= crit_threshold) @@ -133,7 +141,7 @@ if(HAS_TRAIT(src, TRAIT_NOBREATH)) return - var/lungs = getorganslot(ORGAN_SLOT_LUNGS) + var/obj/item/organ/lungs = getorganslot(ORGAN_SLOT_LUNGS) if(!lungs) adjustOxyLoss(2) @@ -552,7 +560,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put if(drunkenness >= 91) adjustToxLoss(1) - adjustBrainLoss(0.4, 60) + adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.4) if(prob(20) && !stat) if(SSshuttle.emergency.mode == SHUTTLE_DOCKED && is_station_level(z)) //QoL mainly to_chat(src, "You're so tired... but you can't miss that shuttle...") @@ -575,6 +583,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put return min(body_temperature_difference * metabolism_efficiency / BODYTEMP_AUTORECOVERY_DIVISOR, max(body_temperature_difference, -BODYTEMP_AUTORECOVERY_MINIMUM/4)) if(BODYTEMP_HEAT_DAMAGE_LIMIT to INFINITY) return min((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), -BODYTEMP_AUTORECOVERY_MINIMUM) //We're dealing with negative numbers + ///////// //LIVER// ///////// @@ -587,12 +596,12 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put if(liver) if(liver.damage < liver.maxHealth) return - liver.failing = TRUE + liver.organ_flags |= ORGAN_FAILING liver_failure() /mob/living/carbon/proc/undergoing_liver_failure() var/obj/item/organ/liver/liver = getorganslot(ORGAN_SLOT_LIVER) - if(liver && liver.failing) + if(liver && (liver.organ_flags & ORGAN_FAILING)) return TRUE /mob/living/carbon/proc/liver_failure() @@ -668,13 +677,6 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put var/datum/brain_trauma/BT = T BT.on_life() - if(getBrainLoss() >= BRAIN_DAMAGE_DEATH) //rip - to_chat(src, "The last spark of life in your brain fizzles out...") - death() - var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN) - if(B) - B.brain_death = TRUE - ///////////////////////////////////// //MONKEYS WITH TOO MUCH CHOLOESTROL// ///////////////////////////////////// @@ -683,7 +685,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put if(!needs_heart()) return FALSE var/obj/item/organ/heart/heart = getorganslot(ORGAN_SLOT_HEART) - if(!heart || heart.synthetic) + if(!heart || (heart.organ_flags & ORGAN_SYNTHETIC)) return FALSE return TRUE diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 32133d07ae5..a5d0970f646 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -27,8 +27,6 @@ adjustCloneLoss(damage_amount, forced = forced) if(STAMINA) adjustStaminaLoss(damage_amount, forced = forced) - if(BRAIN) - adjustBrainLoss(damage_amount) return 1 /mob/living/proc/apply_damage_type(damage = 0, damagetype = BRUTE) //like apply damage except it always uses the damage procs @@ -45,8 +43,6 @@ return adjustCloneLoss(damage) if(STAMINA) return adjustStaminaLoss(damage) - if(BRAIN) - return adjustBrainLoss(damage) /mob/living/proc/get_damage_amount(damagetype = BRUTE) switch(damagetype) @@ -62,8 +58,6 @@ return getCloneLoss() if(STAMINA) return getStaminaLoss() - if(BRAIN) - return getBrainLoss() /mob/living/proc/apply_damages(brute = 0, burn = 0, tox = 0, oxy = 0, clone = 0, def_zone = null, blocked = FALSE, stamina = 0, brain = 0) @@ -232,13 +226,13 @@ updatehealth() return amount -/mob/living/proc/getBrainLoss() - . = 0 - -/mob/living/proc/adjustBrainLoss(amount, maximum = BRAIN_DAMAGE_DEATH) +/mob/living/proc/adjustOrganLoss(slot, amount, maximum) return -/mob/living/proc/setBrainLoss(amount) +/mob/living/proc/setOrganLoss(slot, amount, maximum) + return + +/mob/living/proc/getOrganLoss(slot) return /mob/living/proc/getStaminaLoss() diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index bc78fc7afe7..18beeeecf08 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -250,7 +250,7 @@ H.Paralyze(20) else message_param = "bumps [user.p_their()] head on the ground trying to motion towards %t." - H.adjustBrainLoss(5) + H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5) ..() /datum/emote/living/pout diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 5e087142885..448be7692b7 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -539,7 +539,6 @@ setToxLoss(0, 0) //zero as second argument not automatically call updatehealth(). setOxyLoss(0, 0) setCloneLoss(0, 0) - setBrainLoss(0) remove_CC(FALSE) set_disgust(0) radiation = 0 diff --git a/code/modules/mob/living/silicon/damage_procs.dm b/code/modules/mob/living/silicon/damage_procs.dm index 50fd975cc04..53e32fc3b49 100644 --- a/code/modules/mob/living/silicon/damage_procs.dm +++ b/code/modules/mob/living/silicon/damage_procs.dm @@ -36,8 +36,8 @@ /mob/living/silicon/setStaminaLoss(amount, updating_health = TRUE) return FALSE -/mob/living/silicon/adjustBrainLoss(amount) +/mob/living/silicon/adjustOrganLoss(slot, amount, maximum = 500) return FALSE -/mob/living/silicon/setBrainLoss(amount) +/mob/living/silicon/setOrganLoss(slot, amount) return FALSE diff --git a/code/modules/mob/living/silicon/pai/pai_defense.dm b/code/modules/mob/living/silicon/pai/pai_defense.dm index f3be04599f0..04f3499bd79 100644 --- a/code/modules/mob/living/silicon/pai/pai_defense.dm +++ b/code/modules/mob/living/silicon/pai/pai_defense.dm @@ -87,9 +87,6 @@ else take_holo_damage(amount * 0.25) -/mob/living/silicon/pai/adjustBrainLoss(amount) - Paralyze(amount * 0.2) - /mob/living/silicon/pai/getBruteLoss() return emittermaxhealth - emitterhealth @@ -105,18 +102,12 @@ /mob/living/silicon/pai/getCloneLoss() return FALSE -/mob/living/silicon/pai/getBrainLoss() - return FALSE - /mob/living/silicon/pai/getStaminaLoss() return FALSE /mob/living/silicon/pai/setCloneLoss() return FALSE -/mob/living/silicon/pai/setBrainLoss() - return FALSE - /mob/living/silicon/pai/setStaminaLoss(amount, updating_health = TRUE) return FALSE diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index af538cac605..24d0d0f19f1 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -73,7 +73,7 @@ O.setOxyLoss(getOxyLoss(), 0) O.setCloneLoss(getCloneLoss(), 0) O.adjustFireLoss(getFireLoss(), 0) - O.setBrainLoss(getBrainLoss(), 0) + O.setOrganLoss(ORGAN_SLOT_BRAIN, getOrganLoss(ORGAN_SLOT_BRAIN)) O.updatehealth() O.radiation = radiation @@ -246,7 +246,7 @@ O.setOxyLoss(getOxyLoss(), 0) O.setCloneLoss(getCloneLoss(), 0) O.adjustFireLoss(getFireLoss(), 0) - O.setBrainLoss(getBrainLoss(), 0) + O.adjustOrganLoss(ORGAN_SLOT_BRAIN, getOrganLoss(ORGAN_SLOT_BRAIN)) O.updatehealth() O.radiation = radiation diff --git a/code/modules/projectiles/projectile/special/mindflayer.dm b/code/modules/projectiles/projectile/special/mindflayer.dm index d717bed39e9..ac4488cae06 100644 --- a/code/modules/projectiles/projectile/special/mindflayer.dm +++ b/code/modules/projectiles/projectile/special/mindflayer.dm @@ -5,5 +5,5 @@ . = ..() if(ishuman(target)) var/mob/living/carbon/human/M = target - M.adjustBrainLoss(20) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 20) M.hallucination += 30 diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index 0cc76ef40bf..24b3e0f7a0a 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -1287,7 +1287,7 @@ All effects don't start immediately, but rather get worse over time; the rate is /datum/reagent/consumable/ethanol/neurotoxin/on_mob_life(mob/living/carbon/M) M.set_drugginess(50) M.dizziness +=2 - M.adjustBrainLoss(1*REM, 150) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1*REM, 150) if(prob(20)) M.adjustStaminaLoss(10) M.drop_all_held_items() @@ -1298,7 +1298,7 @@ All effects don't start immediately, but rather get worse over time; the rate is ADD_TRAIT(M, t, type) M.adjustStaminaLoss(10) if(current_cycle > 30) - M.adjustBrainLoss(2*REM) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2*REM) if(current_cycle > 50 && prob(15)) if(!M.undergoing_cardiac_arrest() && M.can_heartattack()) M.set_heartattack(TRUE) diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index 297d25a9fc1..1c80a5358bf 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -85,14 +85,14 @@ . = 1 /datum/reagent/drug/crank/overdose_process(mob/living/M) - M.adjustBrainLoss(2*REM) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2*REM) M.adjustToxLoss(2*REM, 0) M.adjustBruteLoss(2*REM, FALSE, FALSE, BODYPART_ORGANIC) ..() . = 1 /datum/reagent/drug/crank/addiction_act_stage1(mob/living/M) - M.adjustBrainLoss(5*REM) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5*REM) ..() /datum/reagent/drug/crank/addiction_act_stage2(mob/living/M) @@ -106,7 +106,7 @@ . = 1 /datum/reagent/drug/crank/addiction_act_stage4(mob/living/M) - M.adjustBrainLoss(3*REM) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3*REM) M.adjustToxLoss(5*REM, 0) M.adjustBruteLoss(5*REM, 0) ..() @@ -129,13 +129,13 @@ ..() /datum/reagent/drug/krokodil/overdose_process(mob/living/M) - M.adjustBrainLoss(0.25*REM) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.25*REM) M.adjustToxLoss(0.25*REM, 0) ..() . = 1 /datum/reagent/drug/krokodil/addiction_act_stage1(mob/living/M) - M.adjustBrainLoss(2*REM) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2*REM) M.adjustToxLoss(2*REM, 0) ..() . = 1 @@ -192,7 +192,7 @@ M.AdjustImmobilized(-40, FALSE) M.adjustStaminaLoss(-2, 0) M.Jitter(2) - M.adjustBrainLoss(rand(1,4)) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, rand(1,4)) if(prob(5)) M.emote(pick("twitch", "shiver")) ..() @@ -209,7 +209,7 @@ M.drop_all_held_items() ..() M.adjustToxLoss(1, 0) - M.adjustBrainLoss(pick(0.5, 0.6, 0.7, 0.8, 0.9, 1)) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, pick(0.5, 0.6, 0.7, 0.8, 0.9, 1)) . = 1 /datum/reagent/drug/methamphetamine/addiction_act_stage1(mob/living/M) @@ -279,7 +279,7 @@ to_chat(M, "[high_message]") SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "salted", /datum/mood_event/stimulant_heavy, name) M.adjustStaminaLoss(-5, 0) - M.adjustBrainLoss(4) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 4) M.hallucination += 5 if((M.mobility_flags & MOBILITY_MOVE) && !ismovableatom(M.loc)) step(M, pick(GLOB.cardinals)) @@ -304,7 +304,7 @@ for(var/i = 0, i < 8, i++) step(M, pick(GLOB.cardinals)) M.Jitter(5) - M.adjustBrainLoss(10) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10) if(prob(20)) M.emote(pick("twitch","drool","moan")) ..() @@ -316,7 +316,7 @@ step(M, pick(GLOB.cardinals)) M.Jitter(10) M.Dizzy(10) - M.adjustBrainLoss(10) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10) if(prob(30)) M.emote(pick("twitch","drool","moan")) ..() @@ -328,7 +328,7 @@ step(M, pick(GLOB.cardinals)) M.Jitter(15) M.Dizzy(15) - M.adjustBrainLoss(10) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10) if(prob(40)) M.emote(pick("twitch","drool","moan")) ..() @@ -341,7 +341,7 @@ M.Jitter(50) M.Dizzy(50) M.adjustToxLoss(5, 0) - M.adjustBrainLoss(10) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10) if(prob(50)) M.emote(pick("twitch","drool","moan")) ..() @@ -387,7 +387,7 @@ M.jitteriness = 0 M.confused = 0 M.disgust = 0 - M.adjustBrainLoss(0.2) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.2) ..() . = 1 @@ -404,7 +404,7 @@ if(3) M.emote("frown") SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "happiness_drug", /datum/mood_event/happiness_drug_bad_od) - M.adjustBrainLoss(0.5) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.5) ..() . = 1 diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index d6218e67789..3e79a1147cb 100755 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -644,7 +644,7 @@ . = 1 if(prob(20)) M.losebreath += 4 - M.adjustBrainLoss(2*REM, 150) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2*REM, 150) M.adjustToxLoss(3*REM,0) M.adjustStaminaLoss(10*REM,0) M.blur_eyes(5) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 8c2fa40d3e9..0277ab7cc5a 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -41,7 +41,6 @@ M.heal_bodypart_damage(5,5) M.adjustToxLoss(-5, 0, TRUE) M.hallucination = 0 - M.setBrainLoss(0) REMOVE_TRAITS_NOT_IN(M, list(SPECIES_TRAIT, ROUNDSTART_TRAIT, ORGAN_TRAIT)) M.set_blurriness(0) M.set_blindness(0) @@ -63,6 +62,9 @@ M.blood_volume = BLOOD_VOLUME_NORMAL M.cure_all_traumas(TRAUMA_RESILIENCE_MAGIC) + for(var/organ in M.internal_organs) + var/obj/item/organ/O = organ + O.setOrganDamage(0) for(var/thing in M.diseases) var/datum/disease/D = thing if(D.severity == DISEASE_SEVERITY_POSITIVE) @@ -846,6 +848,13 @@ addtimer(CALLBACK(M, /mob/living/carbon.proc/do_jitter_animation, 10), 40) //jitter immediately, then again after 4 and 8 seconds addtimer(CALLBACK(M, /mob/living/carbon.proc/do_jitter_animation, 10), 80) sleep(100) //so the ghost has time to re-enter + + + var/mob/living/carbon/H = M + for(var/organ in H.internal_organs) + var/obj/item/organ/O = organ + O.setOrganDamage(0) + M.adjustOxyLoss(-20, 0) M.adjustToxLoss(-20, 0) M.updatehealth() @@ -866,7 +875,7 @@ color = "#DCDCFF" /datum/reagent/medicine/mannitol/on_mob_life(mob/living/carbon/C) - C.adjustBrainLoss(-2*REM) + C.adjustOrganLoss(ORGAN_SLOT_BRAIN, -2*REM) ..() /datum/reagent/medicine/neurine @@ -1016,7 +1025,7 @@ M.adjustFireLoss(-5*REM, 0) M.adjustOxyLoss(-15, 0) M.adjustToxLoss(-5*REM, 0) - M.adjustBrainLoss(-15*REM) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -15*REM) M.adjustCloneLoss(-3*REM, 0) ..() . = 1 @@ -1039,7 +1048,7 @@ M.adjustFireLoss(-3 * REM, 0) M.adjustOxyLoss(-15 * REM, 0) M.adjustToxLoss(-3 * REM, 0) - M.adjustBrainLoss(2 * REM, 150) //This does, after all, come from ambrosia, and the most powerful ambrosia in existence, at that! + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2 * REM, 150) //This does, after all, come from ambrosia, and the most powerful ambrosia in existence, at that! M.adjustCloneLoss(-1 * REM, 0) M.adjustStaminaLoss(-30 * REM, 0) M.jitteriness = min(max(0, M.jitteriness + 3), 30) @@ -1069,7 +1078,7 @@ if (M.hallucination >= 5) M.hallucination -= 5 if(prob(20)) - M.adjustBrainLoss(1*REM, 50) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1*REM, 50) M.adjustStaminaLoss(2.5*REM, 0) ..() return TRUE @@ -1345,15 +1354,15 @@ if(trans_volume >= 0.6) //prevents cheesing with ultralow doses. C.adjustToxLoss(-1.5 * min(2, trans_volume) * REM, 0) //This is to promote iv pole use for that chemotherapy feel. var/obj/item/organ/liver/L = C.internal_organs_slot[ORGAN_SLOT_LIVER] - if(L.failing || !L) + if((L.organ_flags & ORGAN_FAILING) || !L) return - conversion_amount = trans_volume * (min(100 -C.getLiverLoss(), 80) / 100) //the more damaged the liver the worse we metabolize. + conversion_amount = trans_volume * (min(100 -C.getOrganLoss(ORGAN_SLOT_LIVER), 80) / 100) //the more damaged the liver the worse we metabolize. C.reagents.remove_reagent(/datum/reagent/medicine/thializid, conversion_amount) C.reagents.add_reagent(/datum/reagent/medicine/oxalizid, conversion_amount) ..() /datum/reagent/medicine/thializid/on_mob_life(mob/living/carbon/M) - M.adjustLiverLoss(0.8) + M.adjustOrganLoss(ORGAN_SLOT_LIVER, 0.8) M.adjustToxLoss(-1*REM, 0) for(var/datum/reagent/toxin/R in M.reagents.reagent_list) M.reagents.remove_reagent(R.type,1) @@ -1362,7 +1371,7 @@ . = 1 /datum/reagent/medicine/thializid/overdose_process(mob/living/carbon/M) - M.adjustLiverLoss(1.5) + M.adjustOrganLoss(ORGAN_SLOT_LIVER, 1.5) M.adjust_disgust(3) M.reagents.add_reagent(/datum/reagent/medicine/oxalizid, 0.225 * REM) ..() @@ -1378,7 +1387,7 @@ var/datum/brain_trauma/mild/muscle_weakness/U /datum/reagent/medicine/oxalizid/on_mob_life(mob/living/carbon/M) - M.adjustLiverLoss(0.1) + M.adjustOrganLoss(ORGAN_SLOT_LIVER, 0.1) M.adjustToxLoss(-1*REM, 0) for(var/datum/reagent/toxin/R in M.reagents.reagent_list) M.reagents.remove_reagent(R.type,1) @@ -1396,7 +1405,7 @@ return ..() /datum/reagent/medicine/oxalizid/overdose_process(mob/living/carbon/M) - M.adjustLiverLoss(1.5) + M.adjustOrganLoss(ORGAN_SLOT_LIVER, 1.5) M.adjust_disgust(3) ..() . = 1 diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 5b4174082d1..e8a8ce2b7f2 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -274,7 +274,7 @@ if(ishuman(M) && M.blood_volume < BLOOD_VOLUME_NORMAL) M.blood_volume += 3 else // Will deal about 90 damage when 50 units are thrown - M.adjustBrainLoss(3, 150) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3, 150) M.adjustToxLoss(2, 0) M.adjustFireLoss(2, 0) M.adjustOxyLoss(2, 0) @@ -292,7 +292,7 @@ M.IgniteMob() //Only problem with igniting people is currently the commonly availible fire suits make you immune to being on fire M.adjustToxLoss(1, 0) M.adjustFireLoss(1, 0) //Hence the other damages... ain't I a bastard? - M.adjustBrainLoss(5, 150) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5, 150) holder.remove_reagent(type, 1) /datum/reagent/medicine/omnizine/godblood @@ -714,7 +714,7 @@ step(M, pick(GLOB.cardinals)) if(prob(5)) M.emote(pick("twitch","drool","moan")) - M.adjustBrainLoss(1) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1) ..() /datum/reagent/sulfur @@ -1030,7 +1030,7 @@ /datum/reagent/impedrezene/on_mob_life(mob/living/carbon/M) M.jitteriness = max(M.jitteriness-5,0) if(prob(80)) - M.adjustBrainLoss(2*REM) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2*REM) if(prob(50)) M.drowsyness = max(M.drowsyness, 3) if(prob(10)) diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 9f0bb82441c..3780443d37c 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -432,7 +432,7 @@ toxpwr = 0 /datum/reagent/toxin/fentanyl/on_mob_life(mob/living/carbon/M) - M.adjustBrainLoss(3*REM, 150) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3*REM, 150) if(M.toxloss <= 60) M.adjustToxLoss(1*REM, 0) if(current_cycle >= 4) diff --git a/code/modules/research/nanites/nanite_programs/healing.dm b/code/modules/research/nanites/nanite_programs/healing.dm index 48f9fd91f0e..2f8a07dbe84 100644 --- a/code/modules/research/nanites/nanite_programs/healing.dm +++ b/code/modules/research/nanites/nanite_programs/healing.dm @@ -75,12 +75,12 @@ var/mob/living/carbon/C = host_mob if(length(C.get_traumas())) problems = TRUE - if(host_mob.getBrainLoss()) + if(host_mob.getOrganLoss(ORGAN_SLOT_BRAIN) > 0) problems = TRUE return problems ? ..() : FALSE /datum/nanite_program/brain_heal/active_effect() - host_mob.adjustBrainLoss(-1, TRUE) + host_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1) if(iscarbon(host_mob) && prob(10)) var/mob/living/carbon/C = host_mob C.cure_trauma_type(resilience = TRAUMA_RESILIENCE_BASIC) @@ -197,12 +197,12 @@ var/mob/living/carbon/C = host_mob if(length(C.get_traumas())) problems = TRUE - if(host_mob.getBrainLoss()) + if(host_mob.getOrganLoss(ORGAN_SLOT_BRAIN) > 0) problems = TRUE return problems ? ..() : FALSE /datum/nanite_program/brain_heal_advanced/active_effect() - host_mob.adjustBrainLoss(-2, TRUE) + host_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, -2) if(iscarbon(host_mob) && prob(10)) var/mob/living/carbon/C = host_mob C.cure_trauma_type(resilience = TRAUMA_RESILIENCE_LOBOTOMY) @@ -234,7 +234,7 @@ if(!C.getorgan(/obj/item/organ/heart)) //what are we even shocking return FALSE var/obj/item/organ/brain/BR = C.getorgan(/obj/item/organ/brain) - if(QDELETED(BR) || BR.brain_death || BR.damaged_brain || BR.suicided) + if(QDELETED(BR) || BR.brain_death || (BR.organ_flags & ORGAN_FAILING) || BR.suicided) return FALSE if(C.get_ghost()) return FALSE @@ -252,9 +252,6 @@ C.emote("gasp") C.Jitter(100) SEND_SIGNAL(C, COMSIG_LIVING_MINOR_SHOCK) - var/tplus = world.time - C.timeofdeath - if(tplus > 600) - C.adjustBrainLoss( max(0, ((1800 - tplus) / 1800 * 150)), 150) log_game("[C] has been successfully defibrillated by nanites.") else playsound(C, 'sound/machines/defib_failed.ogg', 50, 0) diff --git a/code/modules/research/nanites/nanite_programs/rogue.dm b/code/modules/research/nanites/nanite_programs/rogue.dm index a77944f2f44..baf5634db84 100644 --- a/code/modules/research/nanites/nanite_programs/rogue.dm +++ b/code/modules/research/nanites/nanite_programs/rogue.dm @@ -59,7 +59,7 @@ /datum/nanite_program/brain_decay/active_effect() if(prob(4)) host_mob.hallucination = min(15, host_mob.hallucination) - host_mob.adjustBrainLoss(1) + host_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1) //Generic brain-affecting programs can also decay into this /datum/nanite_program/brain_misfire diff --git a/code/modules/research/xenobiology/crossbreeding/_misc.dm b/code/modules/research/xenobiology/crossbreeding/_misc.dm index 6a249ec2058..d2204cc98b2 100644 --- a/code/modules/research/xenobiology/crossbreeding/_misc.dm +++ b/code/modules/research/xenobiology/crossbreeding/_misc.dm @@ -53,11 +53,11 @@ Slimecrossing Items for(var/_part in bodyparts) var/obj/item/bodypart/part = _part var/datum/saved_bodypart/saved_part = new(part) - + ret[part.body_zone] = saved_part return ret - + /datum/component/dejavu var/integrity //for objects @@ -84,7 +84,7 @@ Slimecrossing Items clone_loss = L.getCloneLoss() tox_loss = L.getToxLoss() oxy_loss = L.getOxyLoss() - brain_loss = L.getBrainLoss() + brain_loss = L.getOrganLoss(ORGAN_SLOT_BRAIN) if(iscarbon(parent)) var/mob/living/carbon/C = parent saved_bodyparts = C.save_bodyparts() @@ -104,7 +104,7 @@ Slimecrossing Items L.setCloneLoss(clone_loss) L.setToxLoss(tox_loss) L.setOxyLoss(oxy_loss) - L.setBrainLoss(brain_loss) + L.setOrganLoss(ORGAN_SLOT_BRAIN, brain_loss) if(iscarbon(parent)) if(saved_bodyparts) @@ -142,13 +142,13 @@ Slimecrossing Items to_chat(user, "You take a photo with [target]!") to_chat(target, "[user] takes a photo with you!") to_chat(target, "You'll remember this moment forever!") - + used = TRUE target.AddComponent(/datum/component/dejavu, 2) .=..() - - - + + + //Timefreeze camera - Old Burning Sepia result. Kept in case admins want to spawn it /obj/item/camera/timefreeze name = "sepia-tinted camera" diff --git a/code/modules/research/xenobiology/crossbreeding/consuming.dm b/code/modules/research/xenobiology/crossbreeding/consuming.dm index 4307ef98882..6cc76b4734f 100644 --- a/code/modules/research/xenobiology/crossbreeding/consuming.dm +++ b/code/modules/research/xenobiology/crossbreeding/consuming.dm @@ -125,7 +125,7 @@ Consuming extracts: M.adjustToxLoss(-5, forced=1) //To heal slimepeople. M.adjustOxyLoss(-5) M.adjustCloneLoss(-5) - M.adjustBrainLoss(-5) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -5) /obj/item/slimecross/consuming/blue colour = "blue" diff --git a/code/modules/surgery/advanced/brainwashing.dm b/code/modules/surgery/advanced/brainwashing.dm index 1362b51bf1a..8629dbd080f 100644 --- a/code/modules/surgery/advanced/brainwashing.dm +++ b/code/modules/surgery/advanced/brainwashing.dm @@ -60,7 +60,7 @@ display_results(user, target, "You screw up, bruising the brain tissue!", "[user] screws up, causing brain damage!", "[user] completes the surgery on [target]'s brain.") - target.adjustBrainLoss(40) + target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 40) else user.visible_message("[user] suddenly notices that the brain [user.p_they()] [user.p_were()] working on is not there anymore.", "You suddenly notice that the brain you were working on is not there anymore.") return FALSE \ No newline at end of file diff --git a/code/modules/surgery/advanced/lobotomy.dm b/code/modules/surgery/advanced/lobotomy.dm index 15221604ba5..9382f2932e2 100644 --- a/code/modules/surgery/advanced/lobotomy.dm +++ b/code/modules/surgery/advanced/lobotomy.dm @@ -54,11 +54,12 @@ return TRUE /datum/surgery_step/lobotomize/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - if(target.getorganslot(ORGAN_SLOT_BRAIN)) + var/obj/item/organ/brain/B = target.getorganslot(ORGAN_SLOT_BRAIN) + if(B) display_results(user, target, "You remove the wrong part, causing more damage!", "[user] successfully lobotomizes [target]!", "[user] completes the surgery on [target]'s brain.") - target.adjustBrainLoss(80) + B.applyOrganDamage(80) switch(rand(1,3)) if(1) target.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_MAGIC) diff --git a/code/modules/surgery/advanced/revival.dm b/code/modules/surgery/advanced/revival.dm index 28467f6e009..ead27f5b9e1 100644 --- a/code/modules/surgery/advanced/revival.dm +++ b/code/modules/surgery/advanced/revival.dm @@ -66,7 +66,7 @@ if(target.revive()) target.visible_message("...[target] wakes up, alive and aware!") target.emote("gasp") - target.adjustBrainLoss(50, 199) //MAD SCIENCE + target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 50, 199) //MAD SCIENCE return TRUE else target.visible_message("...[target.p_they()] convulses, then lies still.") @@ -77,5 +77,5 @@ "[user] send a powerful shock to [target]'s brain with [tool], but [target.p_they()] doesn't react.", "[user] send a powerful shock to [target]'s brain with [tool], but [target.p_they()] doesn't react.") playsound(get_turf(target), 'sound/magic/lightningbolt.ogg', 50, 1) - target.adjustBrainLoss(15, 199) + target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 15, 180) return FALSE diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index 478183efef8..a8e1d490b7a 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -110,7 +110,7 @@ brainmob = null if(violent_removal && prob(rand(80, 100))) //ghetto surgery can damage the brain. to_chat(user, "[brain] was damaged in the process!") - brain.damaged_brain = TRUE + brain.setOrganDamage(brain.maxHealth) brain.forceMove(T) brain = null update_icon_dropped() diff --git a/code/modules/surgery/brain_surgery.dm b/code/modules/surgery/brain_surgery.dm index 71c580ffb4d..a92e5daac54 100644 --- a/code/modules/surgery/brain_surgery.dm +++ b/code/modules/surgery/brain_surgery.dm @@ -34,7 +34,7 @@ "[user] completes the surgery on [target]'s brain.") if(target.mind && target.mind.has_antag_datum(/datum/antagonist/brainwashed)) target.mind.remove_antag_datum(/datum/antagonist/brainwashed) - target.adjustBrainLoss(-60) + target.setOrganLoss(ORGAN_SLOT_BRAIN, target.getOrganLoss(ORGAN_SLOT_BRAIN) - 60) //we set damage in this case in order to clear the "failing" flag target.cure_all_traumas(TRAUMA_RESILIENCE_SURGERY) return TRUE @@ -43,7 +43,7 @@ display_results(user, target, "You screw up, causing more damage!", "[user] screws up, causing brain damage!", "[user] completes the surgery on [target]'s brain.") - target.adjustBrainLoss(60) + target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 60) target.gain_trauma_type(BRAIN_TRAUMA_SEVERE, TRAUMA_RESILIENCE_LOBOTOMY) else user.visible_message("[user] suddenly notices that the brain [user.p_they()] [user.p_were()] working on is not there anymore.", "You suddenly notice that the brain you were working on is not there anymore.") diff --git a/code/modules/surgery/coronary_bypass.dm b/code/modules/surgery/coronary_bypass.dm new file mode 100644 index 00000000000..03dc4603140 --- /dev/null +++ b/code/modules/surgery/coronary_bypass.dm @@ -0,0 +1,77 @@ +/datum/surgery/coronary_bypass + name = "Coronary Bypass" + 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/coronary_bypass, /datum/surgery_step/close) + possible_locs = list(BODY_ZONE_CHEST) + +/datum/surgery/coronary_bypass/can_start(mob/user, mob/living/carbon/target) + var/obj/item/organ/heart/H = target.getorganslot(ORGAN_SLOT_HEART) + if(H) + if(H.damage > 60 && !H.operated) + return TRUE + return FALSE + + +//an incision but with greater bleed, and a 90% base success chance +/datum/surgery_step/incise_heart + name = "incise heart" + implements = list(/obj/item/scalpel = 90, /obj/item/melee/transforming/energy/sword = 45, /obj/item/kitchen/knife = 45, + /obj/item/shard = 25) + time = 16 + +/datum/surgery_step/incise_heart/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to make an incision in [target]'s heart...", + "[user] begins to make an incision in [target]'s heart.", + "[user] begins to make an incision in [target]'s heart.") + +/datum/surgery_step/incise_heart/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + if(ishuman(target)) + var/mob/living/carbon/human/H = target + if (!(NOBLOOD in H.dna.species.species_traits)) + display_results(user, target, "Blood pools around the incision in [H]'s heart.", + "Blood pools around the incision in [H]'s heart.", + "") + H.bleed_rate += 10 + H.adjustBruteLoss(10) + return TRUE + +/datum/surgery_step/incise_heart/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + if(ishuman(target)) + var/mob/living/carbon/human/H = target + display_results(user, target, "You screw up, cutting too deeply into the heart!", + "[user] screws up, causing blood to spurt out of [H]'s chest!", + "[user] screws up, causing blood to spurt out of [H]'s chest!") + H.bleed_rate += 20 + H.adjustOrganLoss(ORGAN_SLOT_HEART, 10) + H.adjustBruteLoss(10) + +//grafts a coronary bypass onto the individual's heart, success chance is 90% base again +/datum/surgery_step/coronary_bypass + name = "graft coronary bypass" + implements = list(/obj/item/hemostat = 90, TOOL_WIRECUTTER = 35, /obj/item/stack/packageWrap = 15, /obj/item/stack/cable_coil = 5) + time = 90 + +/datum/surgery_step/coronary_bypass/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to graft a bypass onto [target]'s heart...", + "[user] begins to graft something onto [target]'s heart!", + "[user] begins to graft something onto [target]'s heart!") + +/datum/surgery_step/coronary_bypass/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + target.setOrganLoss(ORGAN_SLOT_HEART, 60) + var/obj/item/organ/heart/heart = target.getorganslot(ORGAN_SLOT_HEART) + if(heart) //slightly worrying if we lost our heart mid-operation, but that's life + heart.operated = TRUE + display_results(user, target, "You successfully graft a bypass onto [target]'s heart.", + "[user] finishes grafting something onto [target]'s heart.", + "[user] finishes grafting something onto [target]'s heart.") + return TRUE + +/datum/surgery_step/coronary_bypass/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + if(ishuman(target)) + var/mob/living/carbon/human/H = target + display_results(user, target, "You screw up in attaching the graft, and it tears off, tearing part of the heart!", + "[user] screws up, causing blood to spurt out of [H]'s chest profusely!", + "[user] screws up, causing blood to spurt out of [H]'s chest profusely!") + H.adjustOrganLoss(ORGAN_SLOT_HEART, 20) + H.bleed_rate += 30 + return FALSE diff --git a/code/modules/surgery/eye_surgery.dm b/code/modules/surgery/eye_surgery.dm index c52e92bb170..f75960cd421 100644 --- a/code/modules/surgery/eye_surgery.dm +++ b/code/modules/surgery/eye_surgery.dm @@ -41,7 +41,7 @@ display_results(user, target, "You accidentally stab [target] right in the brain!", "[user] accidentally stabs [target] right in the brain!", "[user] accidentally stabs [target] right in the brain!") - target.adjustBrainLoss(70) + target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 70) else display_results(user, target, "You accidentally stab [target] right in the brain! Or would have, if [target] had a brain.", "[user] accidentally stabs [target] right in the brain! Or would have, if [target] had a brain.", diff --git a/code/modules/surgery/lobectomy.dm b/code/modules/surgery/lobectomy.dm new file mode 100644 index 00000000000..dd67c707a00 --- /dev/null +++ b/code/modules/surgery/lobectomy.dm @@ -0,0 +1,46 @@ +/datum/surgery/lobectomy + name = "Lobectomy" //not to be confused with lobotomy + steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/clamp_bleeders, + /datum/surgery_step/lobectomy, /datum/surgery_step/close) + possible_locs = list(BODY_ZONE_CHEST) + +/datum/surgery/lobectomy/can_start(mob/user, mob/living/carbon/target) + var/obj/item/organ/lungs/L = target.getorganslot(ORGAN_SLOT_LUNGS) + if(L) + if(L.damage > 60 && !L.operated) + return TRUE + return FALSE + + +//lobectomy, removes the most damaged lung lobe with a 95% base success chance +/datum/surgery_step/lobectomy + name = "excise damaged lung node" + implements = list(/obj/item/scalpel = 95, /obj/item/melee/transforming/energy/sword = 65, /obj/item/kitchen/knife = 45, + /obj/item/shard = 35) + time = 42 + +/datum/surgery_step/lobectomy/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You begin to make an incision in [target]'s lungs...", + "[user] begins to make an incision in [target].", + "[user] begins to make an incision in [target].") + +/datum/surgery_step/lobectomy/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + if(ishuman(target)) + var/mob/living/carbon/human/H = target + var/obj/item/organ/lungs/L = H.getorganslot(ORGAN_SLOT_LUNGS) + L.operated = TRUE + H.setOrganLoss(ORGAN_SLOT_LUNGS, 60) + display_results(user, target, "You successfully excise [H]'s most damaged lobe.", + "Successfully removes a piece of [H]'s lungs.", + "") + return TRUE + +/datum/surgery_step/lobectomy/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + if(ishuman(target)) + var/mob/living/carbon/human/H = target + display_results(user, target, "You screw up, failing to excise [H]'s damaged lobe!", + "[user] screws up!", + "[user] screws up!") + H.losebreath += 4 + H.adjustOrganLoss(ORGAN_SLOT_LUNGS, 10) + return FALSE diff --git a/code/modules/surgery/organs/appendix.dm b/code/modules/surgery/organs/appendix.dm index 7c1f37c1ba7..23d3a2ceb08 100644 --- a/code/modules/surgery/organs/appendix.dm +++ b/code/modules/surgery/organs/appendix.dm @@ -3,7 +3,14 @@ icon_state = "appendix" zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_APPENDIX - var/inflamed = 0 + + healing_factor = STANDARD_ORGAN_HEALING + decay_factor = STANDARD_ORGAN_DECAY + + now_failing = "An explosion of pain erupts in your lower right abdomen!" + now_fixed = "The pain in your abdomen has subsided." + + var/inflamed /obj/item/organ/appendix/update_icon() if(inflamed) @@ -13,10 +20,18 @@ icon_state = "appendix" name = "appendix" +/obj/item/organ/appendix/on_life() + ..() + if(!(organ_flags & ORGAN_FAILING)) + return + var/mob/living/carbon/M = owner + if(M) + M.adjustToxLoss(4, TRUE, TRUE) //forced to ensure people don't use it to gain tox as slime person + /obj/item/organ/appendix/Remove(mob/living/carbon/M, special = 0) for(var/datum/disease/appendicitis/A in M.diseases) A.cure() - inflamed = 1 + inflamed = TRUE update_icon() ..() diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm index 03bafe3938e..fb9b11174c9 100644 --- a/code/modules/surgery/organs/augments_arms.dm +++ b/code/modules/surgery/organs/augments_arms.dm @@ -121,7 +121,7 @@ playsound(get_turf(owner), 'sound/mecha/mechmove03.ogg', 50, 1) /obj/item/organ/cyberimp/arm/ui_action_click() - if(broken_cyber_organ || (!holder && !contents.len)) + if((organ_flags & ORGAN_FAILING) || (!holder && !contents.len)) to_chat(owner, "The implant doesn't respond. It seems to be broken...") return @@ -145,7 +145,7 @@ . = ..() if(. & EMP_PROTECT_SELF) return - if(prob(30/severity) && owner && !broken_cyber_organ) + if(prob(30/severity) && owner && !(organ_flags & ORGAN_FAILING)) Retract() owner.visible_message("A loud bang comes from [owner]\'s [zone == BODY_ZONE_R_ARM ? "right" : "left"] arm!") playsound(get_turf(owner), 'sound/weapons/flashbang.ogg', 100, 1) @@ -153,7 +153,7 @@ owner.adjust_fire_stacks(20) owner.IgniteMob() owner.adjustFireLoss(25) - broken_cyber_organ = TRUE + organ_flags |= ORGAN_FAILING /obj/item/organ/cyberimp/arm/gun/laser diff --git a/code/modules/surgery/organs/augments_chest.dm b/code/modules/surgery/organs/augments_chest.dm index 4571d749684..0a1bfb71477 100644 --- a/code/modules/surgery/organs/augments_chest.dm +++ b/code/modules/surgery/organs/augments_chest.dm @@ -144,7 +144,7 @@ /obj/item/organ/cyberimp/chest/thrusters/proc/toggle(silent = FALSE) if(!on) - if(broken_cyber_organ) + if((organ_flags & ORGAN_FAILING)) if(!silent) to_chat(owner, "Your thrusters set seems to be broken!") return 0 diff --git a/code/modules/surgery/organs/augments_internal.dm b/code/modules/surgery/organs/augments_internal.dm index 9a0d17854d4..dcb11a7b567 100644 --- a/code/modules/surgery/organs/augments_internal.dm +++ b/code/modules/surgery/organs/augments_internal.dm @@ -3,6 +3,7 @@ name = "cybernetic implant" desc = "A state-of-the-art implant that improves a baseline's functionality." status = ORGAN_ROBOTIC + organ_flags = ORGAN_SYNTHETIC var/implant_color = "#FFFFFF" var/implant_overlay var/syndicate_implant = FALSE //Makes the implant invisible to health analyzers and medical HUDs. @@ -117,11 +118,11 @@ RegisterSignal(owner, signalCache, .proc/on_signal) /obj/item/organ/cyberimp/brain/anti_stun/proc/on_signal(datum/source, amount) - if(!broken_cyber_organ && amount > 0) + if(!(organ_flags & ORGAN_FAILING) && amount > 0) addtimer(CALLBACK(src, .proc/clear_stuns), stun_cap_amount, TIMER_UNIQUE|TIMER_OVERRIDE) /obj/item/organ/cyberimp/brain/anti_stun/proc/clear_stuns() - if(owner || !broken_cyber_organ) + if(owner || !(organ_flags & ORGAN_FAILING)) owner.SetStun(0) owner.SetKnockdown(0) owner.SetImmobilized(0) @@ -129,13 +130,13 @@ /obj/item/organ/cyberimp/brain/anti_stun/emp_act(severity) . = ..() - if(broken_cyber_organ || . & EMP_PROTECT_SELF) + if((organ_flags & ORGAN_FAILING) || . & EMP_PROTECT_SELF) return - broken_cyber_organ = TRUE + organ_flags |= ORGAN_FAILING addtimer(CALLBACK(src, .proc/reboot), 90 / severity) /obj/item/organ/cyberimp/brain/anti_stun/proc/reboot() - broken_cyber_organ = FALSE + organ_flags &= ~ORGAN_FAILING //[[[[MOUTH]]]] /obj/item/organ/cyberimp/mouth diff --git a/code/modules/surgery/organs/ears.dm b/code/modules/surgery/organs/ears.dm index 61024765817..a23c8322179 100644 --- a/code/modules/surgery/organs/ears.dm +++ b/code/modules/surgery/organs/ears.dm @@ -6,6 +6,14 @@ slot = ORGAN_SLOT_EARS gender = PLURAL + healing_factor = STANDARD_ORGAN_HEALING + decay_factor = STANDARD_ORGAN_DECAY + + low_threshold_passed = "Your ears begin to resonate with an internal ring sometimes." + now_failing = "You are unable to hear at all!" + now_fixed = "Noise slowly begins filling your ears once more." + low_threshold_cleared = "The ringing in your ears has died down." + // `deaf` measures "ticks" of deafness. While > 0, the person is unable // to hear anything. var/deaf = 0 @@ -24,18 +32,24 @@ return ..() var/mob/living/carbon/C = owner - if((damage < maxHealth) && failing) //ear damage can be repaired from the failing condition - failing = FALSE + if((damage < maxHealth) && (organ_flags & ORGAN_FAILING)) //ear damage can be repaired from the failing condition + organ_flags &= ~ORGAN_FAILING // genetic deafness prevents the body from using the ears, even if healthy if(HAS_TRAIT(C, TRAIT_DEAF)) deaf = max(deaf, 1) - else if(!failing) // if this organ is failing, do not clear deaf stacks. + else if(!(organ_flags & ORGAN_FAILING)) // if this organ is failing, do not clear deaf stacks. deaf = max(deaf - 1, 0) + if(prob(damage / 20) && (damage > low_threshold)) + adjustEarDamage(0, 4) + SEND_SOUND(C, sound('sound/weapons/flash_ring.ogg')) + to_chat(C, "The ringing in your ears grows louder, blocking out any external noises for a moment.") + else if((organ_flags & ORGAN_FAILING) && (deaf == 0)) + deaf = 1 //stop being not deaf you deaf idiot /obj/item/organ/ears/proc/restoreEars() deaf = 0 damage = 0 - failing = FALSE + organ_flags &= ~ORGAN_FAILING var/mob/living/carbon/C = owner diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index c8434ba03ec..6b4d6bc3c99 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -6,6 +6,19 @@ slot = ORGAN_SLOT_EYES gender = PLURAL + healing_factor = STANDARD_ORGAN_HEALING + decay_factor = STANDARD_ORGAN_DECAY + maxHealth = 0.5 * STANDARD_ORGAN_THRESHOLD //half the normal health max since we go blind at 30, a permanent blindness at 50 therefore makes sense unless medicine is administered + high_threshold = 0.3 * STANDARD_ORGAN_THRESHOLD //threshold at 30 + low_threshold = 0.2 * STANDARD_ORGAN_THRESHOLD //threshold at 20 + + low_threshold_passed = "Distant objects become somewhat less tangible." + high_threshold_passed = "Everything starts to look a lot less clear." + now_failing = "Darkness envelopes you, as your eyes go blind!" + now_fixed = "Color and shapes are once again perceivable." + high_threshold_cleared = "Your vision functions passably once more." + low_threshold_cleared = "Your vision is cleared of any ailment." + var/sight_flags = 0 var/see_in_dark = 2 var/tint = 0 @@ -17,9 +30,6 @@ var/lighting_alpha var/no_glasses var/damaged = FALSE //damaged indicates that our eyes are undergoing some level of negative effect - maxHealth = 50 //half the normal health max since we go blind at 30, a permanent blindness at 50 therefore makes sense unless medicine is administered - high_threshold = 20 - low_threshold = 10 /obj/item/organ/eyes/Insert(mob/living/carbon/M, special = FALSE, drop_if_replaced = FALSE, initialising) . = ..() @@ -50,19 +60,19 @@ M.set_blurriness(0) M.update_tint() M.update_sight() - + /obj/item/organ/eyes/on_life() ..() var/mob/living/carbon/C = owner //since we can repair fully damaged eyes, check if healing has occurred - if(failing && (damage < maxHealth)) - failing = FALSE + if((organ_flags & ORGAN_FAILING) && (damage < maxHealth)) + organ_flags &= ~ORGAN_FAILING C.cure_blind(EYE_DAMAGE) //various degrees of "oh fuck my eyes", from "point a laser at your eye" to "staring at the Sun" intensities if(damage > 20) damaged = TRUE - if(failing) + if((organ_flags & ORGAN_FAILING)) C.become_blind(EYE_DAMAGE) else if(damage > 30) C.overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 2) @@ -122,6 +132,7 @@ icon_state = "cybernetic_eyeballs" desc = "Your vision is augmented." status = ORGAN_ROBOTIC + organ_flags = ORGAN_SYNTHETIC /obj/item/organ/eyes/robotic/emp_act(severity) . = ..() diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm index f38cc108862..ddd3a3d9c58 100644 --- a/code/modules/surgery/organs/heart.dm +++ b/code/modules/surgery/organs/heart.dm @@ -4,11 +4,22 @@ icon_state = "heart-on" zone = BODY_ZONE_CHEST slot = ORGAN_SLOT_HEART + + healing_factor = STANDARD_ORGAN_HEALING + decay_factor = 5 * STANDARD_ORGAN_DECAY //designed to fail about 5 minutes after death + + low_threshold_passed = "Prickles of pain appear then die out from within your chest..." + high_threshold_passed = "Something inside your chest hurts, and the pain isn't subsiding. You notice yourself breathing far faster than before." + now_fixed = "Your heart begins to beat again." + high_threshold_cleared = "The pain in your chest has died down, and your breathing becomes more relaxed." + // Heart attack code is in code/modules/mob/living/carbon/human/life.dm var/beating = 1 var/icon_base = "heart" attack_verb = list("beat", "thumped") var/beat = BEAT_NONE//is this mob having a heatbeat sound played? if so, which? + var/failed = FALSE //to prevent constantly running failing code + var/operated = FALSE //whether the heart's been operated on to fix some of its damages /obj/item/organ/heart/update_icon() if(beating) @@ -51,10 +62,11 @@ /obj/item/organ/heart/on_life() ..() if(owner.client && beating) + failed = FALSE var/sound/slowbeat = sound('sound/health/slowbeat.ogg', repeat = TRUE) var/sound/fastbeat = sound('sound/health/fastbeat.ogg', repeat = TRUE) var/mob/living/carbon/H = owner - + if(H.health <= H.crit_threshold && beat != BEAT_SLOW) beat = BEAT_SLOW @@ -72,11 +84,18 @@ H.stop_sound_channel(CHANNEL_HEARTBEAT) beat = BEAT_NONE + if(organ_flags & ORGAN_FAILING) //heart broke, stopped beating, death imminent + if(owner.stat == CONSCIOUS) + owner.visible_message("[owner] clutches at [owner.p_their()] chest as if [owner.p_their()] heart is stopping!") + owner.set_heartattack(TRUE) + failed = TRUE + /obj/item/organ/heart/cursed name = "cursed heart" desc = "A heart that, when inserted, will force you to pump it manually." icon_state = "cursedheart-off" icon_base = "cursedheart" + decay_factor = 0 actions_types = list(/datum/action/item_action/organ_action/cursed_heart) var/last_pump = 0 var/add_colour = TRUE //So we're not constantly recreating colour datums @@ -155,9 +174,9 @@ name = "cybernetic heart" desc = "An electronic device designed to mimic the functions of an organic human heart. Also holds an emergency dose of epinephrine, used automatically after facing severe trauma." icon_state = "heart-c" - synthetic = TRUE - var/dose_available = TRUE + organ_flags = ORGAN_SYNTHETIC + var/dose_available = TRUE var/rid = /datum/reagent/medicine/epinephrine var/ramount = 10 @@ -188,7 +207,7 @@ /obj/item/organ/heart/freedom name = "heart of freedom" desc = "This heart pumps with the passion to give... something freedom." - synthetic = TRUE //the power of freedom prevents heart attacks + organ_flags = ORGAN_SYNTHETIC //the power of freedom prevents heart attacks var/min_next_adrenaline = 0 /obj/item/organ/heart/freedom/on_life() diff --git a/code/modules/surgery/organs/liver.dm b/code/modules/surgery/organs/liver.dm index 5f16202e518..d288220791c 100755 --- a/code/modules/surgery/organs/liver.dm +++ b/code/modules/surgery/organs/liver.dm @@ -1,4 +1,3 @@ -#define LIVER_DEFAULT_HEALTH 100 //amount of damage required for liver failure #define LIVER_DEFAULT_TOX_TOLERANCE 3 //amount of toxins the liver can filter out #define LIVER_DEFAULT_TOX_LETHALITY 0.01 //lower values lower how harmful toxins are to the liver @@ -9,12 +8,15 @@ zone = BODY_ZONE_CHEST slot = ORGAN_SLOT_LIVER desc = "Pairing suggestion: chianti and fava beans." + + maxHealth = STANDARD_ORGAN_THRESHOLD + healing_factor = STANDARD_ORGAN_HEALING + decay_factor = STANDARD_ORGAN_DECAY + var/alcohol_tolerance = ALCOHOL_RATE//affects how much damage the liver takes from alcohol var/toxTolerance = LIVER_DEFAULT_TOX_TOLERANCE//maximum amount of toxins the liver can just shrug off var/toxLethality = LIVER_DEFAULT_TOX_LETHALITY//affects how much damage toxins do to the liver var/filterToxins = TRUE //whether to filter toxins - maxHealth = LIVER_DEFAULT_HEALTH - Unique_Failure_Msg = "Subject is suffering from liver failure: Apply Corazone and begin a liver transplant immediately!" #define HAS_SILENT_TOXIN 0 //don't provide a feedback message if this is the only toxin present #define HAS_NO_TOXIN 1 @@ -23,11 +25,11 @@ /obj/item/organ/liver/on_life() if(HAS_TRAIT(owner, TRAIT_NOMETABOLISM)) return - + var/mob/living/carbon/C = owner ..() //perform general on_life() if(istype(C)) - if(!failing)//can't process reagents with a failing liver + if(!(organ_flags & ORGAN_FAILING))//can't process reagents with a failing liver var/provide_pain_message = HAS_NO_TOXIN if(filterToxins && !HAS_TRAIT(owner, TRAIT_TOXINLOVER)) @@ -47,6 +49,15 @@ if(provide_pain_message && damage > 10 && prob(damage/3))//the higher the damage the higher the probability to_chat(C, "You feel a dull pain in your abdomen.") + else //for when our liver's failing + reagents.end_metabolization(C, keep_liverless = TRUE) //Stops trait-based effects on reagents, to prevent permanent buffs + reagents.metabolize(C, can_overdose=FALSE, liverless = TRUE) + if(HAS_TRAIT(C, TRAIT_STABLELIVER)) + return + C.adjustToxLoss(4, TRUE, TRUE) + if(prob(30)) + to_chat(C, "You feel a stabbing pain in your abdomen!") + if(damage > maxHealth)//cap liver damage damage = maxHealth @@ -81,8 +92,8 @@ name = "cybernetic liver" icon_state = "liver-c" desc = "An electronic device designed to mimic the functions of a human liver. Handles toxins slightly better than an organic liver." - synthetic = TRUE - maxHealth = 110 + organ_flags = ORGAN_SYNTHETIC + maxHealth = 1.1 * STANDARD_ORGAN_THRESHOLD toxTolerance = 3.3 toxLethality = 0.009 @@ -91,7 +102,7 @@ icon_state = "liver-c-u" desc = "An upgraded version of the cybernetic liver, designed to improve further upon organic livers. It is resistant to alcohol poisoning and is very robust at filtering toxins." alcohol_tolerance = 0.001 - maxHealth = 200 //double the health of a normal liver + maxHealth = 2 * STANDARD_ORGAN_THRESHOLD toxTolerance = 15 //can shrug off up to 15u of toxins toxLethality = 0.008 //20% less damage than a normal liver diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm index cf78c0467c4..816e55e5de2 100644 --- a/code/modules/surgery/organs/lungs.dm +++ b/code/modules/surgery/organs/lungs.dm @@ -1,4 +1,6 @@ /obj/item/organ/lungs + var/failed = FALSE + var/operated = FALSE //whether we can still have our damages fixed through surgery name = "lungs" icon_state = "lungs" zone = BODY_ZONE_CHEST @@ -6,6 +8,13 @@ gender = PLURAL w_class = WEIGHT_CLASS_NORMAL + healing_factor = STANDARD_ORGAN_HEALING + decay_factor = STANDARD_ORGAN_DECAY + + high_threshold_passed = "You feel some sort of constriction around your chest as your breathing becomes shallow and rapid." + now_fixed = "Your lungs seem to once again be able to hold air." + high_threshold_cleared = "The constriction around your chest loosens as your breathing calms down." + //Breath damage var/safe_oxygen_min = 16 // Minimum safe partial pressure of O2, in kPa @@ -243,7 +252,7 @@ H.hallucination += 10 H.reagents.add_reagent(/datum/reagent/bz_metabolites,5) if(prob(33)) - H.adjustBrainLoss(3, 150) + H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3, 150) else if(bz_pp > 0.01) H.hallucination += 5 @@ -379,6 +388,16 @@ if(prob(20)) to_chat(H, "You feel [hot_message] in your [name]!") +/obj/item/organ/lungs/on_life() + ..() + if((!failed) && ((organ_flags & ORGAN_FAILING))) + if(owner.stat == CONSCIOUS) + owner.visible_message("[owner] grabs [owner.p_their()] throat, struggling for breath!") + failed = TRUE + else if(!(organ_flags & ORGAN_FAILING)) + failed = FALSE + return + /obj/item/organ/lungs/prepare_eat() var/obj/S = ..() S.reagents.add_reagent(/datum/reagent/medicine/salbutamol, 5) @@ -409,7 +428,8 @@ name = "cybernetic lungs" desc = "A cybernetic version of the lungs found in traditional humanoid entities. Allows for greater intakes of oxygen than organic lungs, requiring slightly less pressure." icon_state = "lungs-c" - synthetic = TRUE + organ_flags = ORGAN_SYNTHETIC + maxHealth = 1.1 * STANDARD_ORGAN_THRESHOLD safe_oxygen_min = 13 /obj/item/organ/lungs/cybernetic/emp_act() @@ -425,6 +445,7 @@ icon_state = "lungs-c-u" safe_toxins_max = 20 safe_co2_max = 20 + maxHealth = 2 * STANDARD_ORGAN_THRESHOLD cold_level_1_threshold = 200 cold_level_2_threshold = 140 diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 22ad518d406..047ae376743 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -1,6 +1,3 @@ -#define STANDARD_ORGAN_THRESHOLD 100 -#define STANDARD_ORGAN_HEALING 0.001 - /obj/item/organ name = "organ" icon = 'icons/obj/surgery.dmi' @@ -8,32 +5,26 @@ var/status = ORGAN_ORGANIC w_class = WEIGHT_CLASS_SMALL throwforce = 0 - var/broken_cyber_organ = FALSE //if the organ stopped working. var/zone = BODY_ZONE_CHEST var/slot // DO NOT add slots with matching names to different zones - it will break internal_organs_slot list! - var/vital = 0 - //Was this organ implanted/inserted/etc, if true will not be removed during species change. - var/external = FALSE - var/synthetic = FALSE // To distinguish between organic and synthetic organs + var/organ_flags = 0 var/maxHealth = STANDARD_ORGAN_THRESHOLD var/damage = 0 //total damage this organ has sustained - var/failing = FALSE //is this organ failing or not - var/healing_factor = STANDARD_ORGAN_HEALING //fraction of maxhealth healed per on_life() + ///Healing factor and decay factor function on % of maxhealth, and do not work by applying a static number per tick + var/healing_factor = 0 //fraction of maxhealth healed per on_life(), set to 0 for generic organs + var/decay_factor = 0 //same as above but when without a living owner, set to 0 for generic organs var/high_threshold = STANDARD_ORGAN_THRESHOLD * 0.45 //when severe organ damage occurs var/low_threshold = STANDARD_ORGAN_THRESHOLD * 0.1 //when minor organ damage occurs - var/Unique_Failure_Msg //certain organs may want unique failure messages for details on how to fix them -/obj/item/organ/proc/Assemble_Failure_Message() //need to assemble a failure message since we can't have variables be based off of the same object's variables - var/name_length - //if no unique failure message is set, output the generic one, otherwise give the one we have set - if(!Unique_Failure_Msg) - name_length = lentext(name) - if(name[name_length] == "s") //plural case, done without much sanitization since I don't know any organ that ends with an "s" that isn't plural at the moment - Unique_Failure_Msg = "Subject's [name] are too damaged to function, and needs to be replaced or fixed!" - else - Unique_Failure_Msg = "Subject's [name] is too damaged to function, and needs to be replaced or fixed!" - return Unique_Failure_Msg + ///Organ variables for determining what we alert the owner with when they pass/clear the damage thresholds + var/prev_damage = 0 + var/low_threshold_passed + var/high_threshold_passed + var/now_failing + var/now_fixed + var/high_threshold_cleared + var/low_threshold_cleared /obj/item/organ/proc/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE) if(!iscarbon(M) || owner == M) @@ -62,7 +53,7 @@ M.internal_organs -= src if(M.internal_organs_slot[slot] == src) M.internal_organs_slot.Remove(slot) - if(vital && !special && !(M.status_flags & GODMODE)) + if((organ_flags & ORGAN_VITAL) && !special && !(M.status_flags & GODMODE)) M.death() for(var/X in actions) var/datum/action/A = X @@ -72,22 +63,89 @@ /obj/item/organ/proc/on_find(mob/living/finder) return -/obj/item/organ/proc/on_life() - var/mob/living/carbon/C = owner - //if we start to fail, cap our damage and fail the organ - if(damage > maxHealth) - failing = TRUE +/obj/item/organ/process() //runs decay when outside of a person + if((organ_flags & (ORGAN_SYNTHETIC | ORGAN_FROZEN)) || istype(loc, /obj/item/mmi)) + return + if(damage >= maxHealth) + organ_flags |= ORGAN_FAILING damage = maxHealth - //repair organ damage if the organ is not failing - if((!failing) && C) - damage = max(0, damage - (maxHealth * healing_factor) ) + return + else if(!owner) + damage = min(maxHealth, damage + (maxHealth * decay_factor)) + + else + var/mob/living/carbon/C = owner + if(!C) + return + if(C.stat == DEAD && !IS_IN_STASIS(C)) + if(damage >= maxHealth) + organ_flags |= ORGAN_FAILING + damage = maxHealth + return + damage = min(maxHealth, damage + (maxHealth * decay_factor)) + +/obj/item/organ/proc/on_life() //repair organ damage if the organ is not failing + var/mob/living/carbon/C = owner + if(!C) + return + if(damage >= maxHealth) + organ_flags |= ORGAN_FAILING + damage = maxHealth + check_damage_thresholds(C) + prev_damage = damage + return + if((!(organ_flags & ORGAN_FAILING)) && (C.stat !=DEAD)) + ///Damage decrements by a percent of its maxhealth + damage = max(0, damage - (maxHealth * healing_factor)) + if(C.satiety > 0) + ///Damage decrements again by a percent of its maxhealth, up to a total of 4 extra times depending on the owner's health + damage = max(0, damage - ((maxHealth * healing_factor) * (C.satiety / MAX_SATIETY) * 4)) + check_damage_thresholds(C) + prev_damage = damage return +/** check_damage_thresholds + * input: M (a mob, the owner of the organ we call the proc on) + * output: + * description: By checking our current damage against our previous damage, we can decide whether we've passed an organ threshold. + * If we have, send the corresponding threshold message to the owner, if such a message exists. + */ +/obj/item/organ/proc/check_damage_thresholds(var/M) + if(damage == prev_damage) + return + var/delta = damage - prev_damage + if(delta > 0) + if(damage == maxHealth) + if(now_failing) + to_chat(M, now_failing) + else if(damage > high_threshold && prev_damage <= high_threshold) + if(high_threshold_passed) + to_chat(M, high_threshold_passed) + else if(damage > low_threshold && prev_damage <= low_threshold) + if(low_threshold_passed) + to_chat(M, low_threshold_passed) + else if(delta < 0) + if(prev_damage > low_threshold && damage <= low_threshold) + if(low_threshold_cleared) + to_chat(M, low_threshold_cleared) + else if(prev_damage > high_threshold && damage <= high_threshold) + if(high_threshold_cleared) + to_chat(M, high_threshold_cleared) + else if(prev_damage == maxHealth) + if(now_fixed) + to_chat(M, now_fixed) + /obj/item/organ/examine(mob/user) . = ..() - if(status == ORGAN_ROBOTIC && broken_cyber_organ) + if(status == ORGAN_ROBOTIC && (organ_flags & ORGAN_FAILING)) . += "[src] seems to be broken!" + else if(organ_flags & ORGAN_FAILING) + . += "[src] has decayed for too long, and has turned a sickly color! It doesn't look like it will work anymore!" + + else if(damage > high_threshold) + . += "[src] is starting to look discolored." + /obj/item/organ/proc/prepare_eat() var/obj/item/reagent_containers/food/snacks/organ/S = new @@ -106,8 +164,12 @@ list_reagents = list(/datum/reagent/consumable/nutriment = 5) foodtype = RAW | MEAT | GROSS +/obj/item/organ/Initialize() + START_PROCESSING(SSobj, src) + return ..() /obj/item/organ/Destroy() + STOP_PROCESSING(SSobj, src) if(owner) // The special flag is important, because otherwise mobs can die // while undergoing transformation into different mobs. @@ -129,15 +191,19 @@ /obj/item/organ/item_action_slot_check(slot,mob/user) return //so we don't grant the organ's action to mobs who pick up the organ. -/obj/item/organ/proc/applyOrganDamage(var/d) //use for damaging effects +///Adjusts an organ's damage by the amount "d", up to a maximum amount, which is by default max damage +/obj/item/organ/proc/applyOrganDamage(var/d, var/maximum = maxHealth) //use for damaging effects + if(maximum < d + damage) + d = max(0, maximum - damage) damage = max(0, damage + d) +///SETS an organ's damage to the amount "d", and in doing so clears or sets the failing flag, good for when you have an effect that should fix an organ if broken /obj/item/organ/proc/setOrganDamage(var/d) //use mostly for admin heals damage = CLAMP(d, 0 ,maxHealth) if(d >= maxHealth) - failing = TRUE + organ_flags |= ORGAN_FAILING else - failing = FALSE + organ_flags &= ~ORGAN_FAILING //Looking for brains? //Try code/modules/mob/living/carbon/brain/brain_item.dm diff --git a/code/modules/surgery/organs/stomach.dm b/code/modules/surgery/organs/stomach.dm index a52e99ec152..10aca4c5841 100755 --- a/code/modules/surgery/organs/stomach.dm +++ b/code/modules/surgery/organs/stomach.dm @@ -6,16 +6,42 @@ slot = ORGAN_SLOT_STOMACH attack_verb = list("gored", "squished", "slapped", "digested") desc = "Onaka ga suite imasu." + + healing_factor = STANDARD_ORGAN_HEALING + decay_factor = STANDARD_ORGAN_DECAY + + low_threshold_passed = "Your stomach flashes with pain before subsiding. Food doesn't seem like a good idea right now." + high_threshold_passed = "Your stomach flares up with constant pain- you can hardly stomach the idea of food right now!" + high_threshold_cleared = "The pain in your stomach dies down for now, but food still seems unappealing." + low_threshold_cleared = "The last bouts of pain in your stomach have died out." + var/disgust_metabolism = 1 /obj/item/organ/stomach/on_life() var/mob/living/carbon/human/H = owner + var/datum/reagent/Nutri ..() if(istype(H)) - H.dna.species.handle_digestion(H) + if(!(organ_flags & ORGAN_FAILING)) + H.dna.species.handle_digestion(H) handle_disgust(H) + if(damage < low_threshold) + return + + Nutri = locate(/datum/reagent/consumable/nutriment) in H.reagents.reagent_list + + if(Nutri) + if(prob((damage/40) * Nutri.volume * Nutri.volume)) + H.vomit(damage) + to_chat(H, "Your stomach reels in pain as you're incapable of holding down all that food!") + + else if(Nutri && damage > high_threshold) + if(prob((damage/10) * Nutri.volume * Nutri.volume)) + H.vomit(damage) + to_chat(H, "Your stomach reels in pain as you're incapable of holding down all that food!") + /obj/item/organ/stomach/proc/handle_disgust(mob/living/carbon/human/H) if(H.disgust) var/pukeprob = 5 + 0.05 * H.disgust diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index 4582a9ac50f..404bd340354 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -9,6 +9,8 @@ zone = BODY_ZONE_PRECISE_MOUTH slot = ORGAN_SLOT_VOICE gender = PLURAL + decay_factor = 0 //we don't want decaying vocal cords to somehow matter or appear on scanners since they don't do anything damaged + healing_factor = 0 var/list/spans = null /obj/item/organ/vocal_cords/proc/can_speak_with() //if there is any limitation to speaking with these cords diff --git a/code/modules/vehicles/scooter.dm b/code/modules/vehicles/scooter.dm index 5489c43b965..d8a91b46fed 100644 --- a/code/modules/vehicles/scooter.dm +++ b/code/modules/vehicles/scooter.dm @@ -79,7 +79,7 @@ H.adjustStaminaLoss(40) var/head_slot = H.get_item_by_slot(SLOT_HEAD) if(!head_slot || !(istype(head_slot,/obj/item/clothing/head/helmet) || istype(head_slot,/obj/item/clothing/head/hardhat))) - H.adjustBrainLoss(3) + H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3) H.updatehealth() visible_message("[src] crashes into [A], sending [H] flying!") playsound(src, 'sound/effects/bang.ogg', 50, 1) @@ -205,7 +205,7 @@ H.adjustStaminaLoss(10) var/head_slot = H.get_item_by_slot(SLOT_HEAD) if(!head_slot || !(istype(head_slot,/obj/item/clothing/head/helmet) || istype(head_slot,/obj/item/clothing/head/hardhat))) - H.adjustBrainLoss(1) + H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1) H.updatehealth() visible_message("[src] crashes into [A], sending [H] flying!") playsound(src, 'sound/effects/bang.ogg', 50, 1) diff --git a/code/modules/zombie/items.dm b/code/modules/zombie/items.dm index abe9f984f3b..6b46542020a 100644 --- a/code/modules/zombie/items.dm +++ b/code/modules/zombie/items.dm @@ -72,5 +72,5 @@ user.adjustFireLoss(-hp_gained, 0) user.adjustCloneLoss(-hp_gained, 0) user.updatehealth() - user.adjustBrainLoss(-hp_gained) // Zom Bee gibbers "BRAAAAISNSs!1!" + user.adjustOrganLoss(ORGAN_SLOT_BRAIN, -hp_gained) // Zom Bee gibbers "BRAAAAISNSs!1!" user.set_nutrition(min(user.nutrition + hp_gained, NUTRITION_LEVEL_FULL)) diff --git a/tgstation.dme b/tgstation.dme index 773e7c93934..fa36073b5ca 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -2751,6 +2751,7 @@ #include "code\modules\surgery\brain_surgery.dm" #include "code\modules\surgery\cavity_implant.dm" #include "code\modules\surgery\core_removal.dm" +#include "code\modules\surgery\coronary_bypass.dm" #include "code\modules\surgery\dental_implant.dm" #include "code\modules\surgery\experimental_dissection.dm" #include "code\modules\surgery\eye_surgery.dm" @@ -2759,6 +2760,7 @@ #include "code\modules\surgery\implant_removal.dm" #include "code\modules\surgery\limb_augmentation.dm" #include "code\modules\surgery\lipoplasty.dm" +#include "code\modules\surgery\lobectomy.dm" #include "code\modules\surgery\mechanic_steps.dm" #include "code\modules\surgery\organ_manipulation.dm" #include "code\modules\surgery\organic_steps.dm"