From 470ec5d62bb21418a6a71dd32d3886dcd8992eb0 Mon Sep 17 00:00:00 2001 From: shellspeed1 <46614774+shellspeed1@users.noreply.github.com> Date: Mon, 14 Oct 2019 18:46:06 -0700 Subject: [PATCH] whew --- code/__DEFINES/DNA.dm | 5 + code/__DEFINES/flags.dm | 2 + code/__DEFINES/misc.dm | 2 +- code/__DEFINES/mobs.dm | 6 +- code/__DEFINES/obj_flags.dm | 9 + code/__DEFINES/stat.dm | 3 + code/__HELPERS/game.dm | 37 +++ code/_globalvars/bitfields.dm | 10 + code/controllers/subsystem/blackbox.dm | 4 +- code/datums/components/earhealing.dm | 4 +- code/datums/datumvars.dm | 45 ++- .../diseases/advance/symptoms/choking.dm | 2 +- .../diseases/advance/symptoms/confusion.dm | 2 +- .../diseases/advance/symptoms/deafness.dm | 4 +- .../diseases/advance/symptoms/sensory.dm | 6 +- .../diseases/advance/symptoms/vision.dm | 14 +- code/datums/diseases/appendicitis.dm | 2 + code/datums/diseases/brainrot.dm | 6 +- code/datums/martial/cqc.dm | 2 +- code/datums/martial/psychotic_brawl.dm | 2 +- code/datums/martial/sleeping_carp.dm | 2 +- code/datums/status_effects/buffs.dm | 4 +- code/datums/traits/negative.dm | 5 +- code/game/machinery/Sleeper.dm | 2 +- code/game/machinery/cloning.dm | 13 +- .../mecha/equipment/tools/medical_tools.dm | 2 +- code/game/objects/items.dm | 8 +- code/game/objects/items/body_egg.dm | 13 +- .../circuitboards/machine_circuitboards.dm | 1 + code/game/objects/items/defib.dm | 57 ++-- .../objects/items/devices/dogborg_sleeper.dm | 2 +- code/game/objects/items/devices/scanners.dm | 105 +++++-- code/game/objects/items/robot/robot_parts.dm | 2 +- code/game/objects/items/storage/book.dm | 2 +- code/game/objects/items/twohanded.dm | 2 +- .../crates_lockers/closets/secure/freezer.dm | 18 ++ code/game/objects/structures/morgue.dm | 4 + code/modules/admin/secrets.dm | 2 +- code/modules/admin/topic.dm | 2 +- code/modules/admin/verbs/randomverbs.dm | 2 +- .../antagonists/abductor/equipment/gland.dm | 2 +- .../antagonists/changeling/changeling.dm | 4 +- .../changeling/powers/regenerate.dm | 2 +- .../clockcult/clock_items/clockwork_armor.dm | 2 +- .../antagonists/slaughter/slaughter.dm | 1 + .../kitchen_machinery/smartfridge.dm | 54 +++- .../jobs/job_types/civilian_chaplain.dm | 2 +- code/modules/library/lib_codex_gigas.dm | 4 +- code/modules/mob/living/brain/MMI.dm | 4 +- code/modules/mob/living/brain/brain_item.dm | 155 +++++++++- code/modules/mob/living/brain/life.dm | 2 +- .../carbon/alien/special/alien_embryo.dm | 1 + code/modules/mob/living/carbon/carbon.dm | 2 +- .../mob/living/carbon/carbon_defense.dm | 10 +- .../modules/mob/living/carbon/damage_procs.dm | 55 +++- .../mob/living/carbon/human/human_defense.dm | 56 +++- code/modules/mob/living/carbon/human/life.dm | 2 +- .../mob/living/carbon/human/species.dm | 268 +++++++++++++++--- .../carbon/human/species_types/dullahan.dm | 2 +- .../human/species_types/shadowpeople.dm | 8 +- code/modules/mob/living/carbon/life.dm | 58 ++-- code/modules/mob/living/damage_procs.dm | 17 +- code/modules/mob/living/emote.dm | 2 +- code/modules/mob/living/living.dm | 8 +- .../mob/living/silicon/damage_procs.dm | 4 +- .../mob/living/silicon/pai/pai_defense.dm | 8 +- code/modules/mob/living/taste.dm | 6 +- code/modules/mob/transform_procs.dm | 4 +- .../projectile/special/mindflayer.dm | 2 +- code/modules/reagents/chemistry/holder.dm | 6 +- .../chemistry/reagents/alcohol_reagents.dm | 55 +++- .../chemistry/reagents/drug_reagents.dm | 32 +-- .../chemistry/reagents/food_reagents.dm | 2 +- .../chemistry/reagents/medicine_reagents.dm | 22 +- .../chemistry/reagents/other_reagents.dm | 237 ++++++++++++---- .../chemistry/reagents/toxin_reagents.dm | 42 ++- .../reagents/chemistry/recipes/medicine.dm | 36 +++ .../research/designs/medical_designs.dm | 33 +++ .../nanites/nanite_programs/healing.dm | 26 +- .../research/nanites/nanite_programs/rogue.dm | 2 +- code/modules/research/techweb/all_nodes.dm | 12 +- .../xenobiology/crossbreeding/consuming.dm | 2 +- code/modules/surgery/advanced/brainwashing.dm | 4 +- code/modules/surgery/advanced/lobotomy.dm | 5 +- code/modules/surgery/advanced/revival.dm | 4 +- code/modules/surgery/brain_surgery.dm | 4 +- code/modules/surgery/coronary_bypass.dm | 77 +++++ code/modules/surgery/eye_surgery.dm | 2 +- code/modules/surgery/graft_synthtissue.dm | 70 +++++ code/modules/surgery/lobectomy.dm | 46 +++ code/modules/surgery/organs/appendix.dm | 20 +- code/modules/surgery/organs/augments_arms.dm | 5 +- code/modules/surgery/organs/augments_chest.dm | 2 +- .../surgery/organs/augments_internal.dm | 7 +- code/modules/surgery/organs/ears.dm | 42 ++- code/modules/surgery/organs/eyes.dm | 59 +++- code/modules/surgery/organs/heart.dm | 56 +++- code/modules/surgery/organs/liver.dm | 16 +- code/modules/surgery/organs/lungs.dm | 104 +++++-- code/modules/surgery/organs/organ_internal.dm | 135 ++++++++- code/modules/surgery/organs/stomach.dm | 37 ++- code/modules/surgery/organs/tongue.dm | 53 ++-- code/modules/surgery/organs/vocal_cords.dm | 9 +- code/modules/vehicles/scooter.dm | 4 +- code/modules/zombie/items.dm | 2 +- .../code/datums/status_effects/chems.dm | 43 +-- .../reagents/chemistry/reagents/MKUltra.dm | 16 +- .../reagents/chemistry/reagents/SDGF.dm | 48 ++-- .../chemistry/reagents/fermi_reagents.dm | 102 ++----- .../reagents/chemistry/reagents/healing.dm | 64 ++++- .../reagents/chemistry/recipes/fermi.dm | 2 +- .../modules/reagents/reagents/cit_reagents.dm | 6 +- .../modules/vore/resizing/sizechemicals.dm | 2 +- tgstation.dme | 3 + 114 files changed, 2124 insertions(+), 592 deletions(-) create mode 100644 code/modules/surgery/coronary_bypass.dm create mode 100644 code/modules/surgery/graft_synthtissue.dm create mode 100644 code/modules/surgery/lobectomy.dm diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index 4ed099d9..39f70246 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -99,6 +99,7 @@ #define NOEYES 16 #define MARKINGS 17 +//organ slots #define ORGAN_SLOT_BRAIN "brain" #define ORGAN_SLOT_APPENDIX "appendix" #define ORGAN_SLOT_RIGHT_ARM_AUG "r_arm_device" @@ -122,3 +123,7 @@ #define ORGAN_SLOT_BRAIN_ANTISTUN "brain_antistun" #define ORGAN_SLOT_TAIL "tail" #define ORGAN_SLOT_PENIS "penis" +////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 \ No newline at end of file diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index dfd3685a..7644a21b 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -10,6 +10,8 @@ #define CHECK_BITFIELD(variable, flag) (variable & (flag)) #define TOGGLE_BITFIELD(variable, flag) (variable ^= (flag)) +#define CHECK_MULTIPLE_BITFIELDS(flagvar, flags) (((flagvar) & (flags)) == (flags)) + GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768)) // for /datum/var/datum_flags diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index c71780e7..7821e5ad 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -314,7 +314,7 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S #define MAP_MAXZ 6 // Defib stats -#define DEFIB_TIME_LIMIT 120 +#define DEFIB_TIME_LIMIT 960 #define DEFIB_TIME_LOSS 60 // Diagonal movement diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 1d1dda6d..1a7340d0 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -203,9 +203,6 @@ #define MAX_CHICKENS 50 -#define UNHEALING_EAR_DAMAGE 100 - - #define INCORPOREAL_MOVE_BASIC 1 #define INCORPOREAL_MOVE_SHADOW 2 // leaves a trail of shadows #define INCORPOREAL_MOVE_JAUNT 3 // is blocked by holy water/salt @@ -256,6 +253,9 @@ #define MAX_QUIRKS 6 //The maximum amount of quirks one character can have at roundstart +#define MAX_REVIVE_FIRE_DAMAGE 180 +#define MAX_REVIVE_BRUTE_DAMAGE 180 + // AI Toggles #define AI_CAMERA_LUMINOSITY 5 #define AI_VOX // Comment out if you don't want VOX to be enabled and have players download the voice sounds. diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm index 01d95d7f..a365d13b 100644 --- a/code/__DEFINES/obj_flags.dm +++ b/code/__DEFINES/obj_flags.dm @@ -38,3 +38,12 @@ #define THICKMATERIAL (1<<5) //prevents syringes, parapens and hypos if the external suit or helmet (if targeting head) has this flag. Example: space suits, biosuit, bombsuits, thick suits that cover your body. #define VOICEBOX_TOGGLABLE (1<<6) // The voicebox in this clothing can be toggled. #define VOICEBOX_DISABLED (1<<7) // The voicebox is currently turned off. + +// 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 +#define ORGAN_NO_SPOIL (1<<5) //Currently only the brain \ No newline at end of file diff --git a/code/__DEFINES/stat.dm b/code/__DEFINES/stat.dm index c55616e3..2dade082 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 af687bfa..a7655a71 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/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 583f722e..8a2bbf82 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -177,4 +177,14 @@ GLOBAL_LIST_INIT(bitfields, list( "CAN_CARRY" = CAN_CARRY, "CAN_RESIST" = CAN_RESIST ), + )) + + "organ_flags" = list( + "ORGAN_SYNTHETIC" = ORGAN_SYNTHETIC, + "ORGAN_FROZEN" = ORGAN_FROZEN, + "ORGAN_FAILING" = ORGAN_FAILING, + "ORGAN_EXTERNAL" = ORGAN_EXTERNAL, + "ORGAN_VITAL" = ORGAN_VITAL, + "ORGAN_NO_SPOIL" = ORGAN_NO_SPOIL + ), )) \ No newline at end of file diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm index 688b7945..d6991a40 100644 --- a/code/controllers/subsystem/blackbox.dm +++ b/code/controllers/subsystem/blackbox.dm @@ -294,7 +294,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() @@ -308,7 +308,7 @@ Versioning if(!SSdbcore.Connect()) return - + sqlname = sanitizeSQL(sqlname) sqlkey = sanitizeSQL(sqlkey) sqljob = sanitizeSQL(sqljob) diff --git a/code/datums/components/earhealing.dm b/code/datums/components/earhealing.dm index 6eb71285..bd3d5748 100644 --- a/code/datums/components/earhealing.dm +++ b/code/datums/components/earhealing.dm @@ -26,5 +26,5 @@ if(!HAS_TRAIT(wearer, TRAIT_DEAF)) var/obj/item/organ/ears/ears = wearer.getorganslot(ORGAN_SLOT_EARS) if (ears) - ears.deaf = max(ears.deaf - 1, (ears.ear_damage < UNHEALING_EAR_DAMAGE ? 0 : 1)) // Do not clear deafness while above the unhealing ear damage threshold - ears.ear_damage = max(ears.ear_damage - 0.1, 0) + ears.deaf = max(ears.deaf - 1, (ears.damage < ears.maxHealth ? 0 : 1)) // Do not clear deafness if our ears are too damaged + ears.damage = max(ears.damage - 0.1, 0) diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 8960d1db..dc95d473 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -94,10 +94,23 @@ TOXIN:[M.getToxLoss()] OXY:[M.getOxyLoss()] CLONE:[M.getCloneLoss()] - BRAIN:[M.getBrainLoss()] + BRAIN:[M.getOrganLoss(ORGAN_SLOT_BRAIN)] STAMINA:[M.getStaminaLoss()] AROUSAL:[M.getArousalLoss()] - + "} + if(GLOB.Debug2) + atomsnowflake += {" + HEART:[M.getOrganLoss(ORGAN_SLOT_HEART)] + LIVER:[M.getOrganLoss(ORGAN_SLOT_LIVER)] + LUNGS:[M.getOrganLoss(ORGAN_SLOT_LUNGS)] + EYES:[M.getOrganLoss(ORGAN_SLOT_EYES)] + EARS:[M.getOrganLoss(ORGAN_SLOT_EARS)] + STOMACH:[M.getOrganLoss(ORGAN_SLOT_STOMACH)] + TONGUE:[M.getOrganLoss(ORGAN_SLOT_TONGUE)] + APPENDIX:[M.getOrganLoss(ORGAN_SLOT_APPENDIX)] + "} + atomsnowflake += {" + "} else atomsnowflake += "[D]" @@ -1334,8 +1347,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() @@ -1345,6 +1358,30 @@ if("arousal") L.adjustArousalLoss(amount) newamt = L.getArousalLoss() + if("heart") + L.adjustOrganLoss(ORGAN_SLOT_HEART, amount) + newamt = L.getOrganLoss(ORGAN_SLOT_HEART) + if("liver") + L.adjustOrganLoss(ORGAN_SLOT_LIVER, amount) + newamt = L.getOrganLoss(ORGAN_SLOT_LIVER) + if("lungs") + L.adjustOrganLoss(ORGAN_SLOT_LUNGS, amount) + newamt = L.getOrganLoss(ORGAN_SLOT_LUNGS) + if("eye_sight") + L.adjustOrganLoss(ORGAN_SLOT_EYES, amount) + newamt = L.getOrganLoss(ORGAN_SLOT_EYES) + if("ears") + L.adjustOrganLoss(ORGAN_SLOT_EARS, amount) + newamt = L.getOrganLoss(ORGAN_SLOT_EARS) + if("stomach") + L.adjustOrganLoss(ORGAN_SLOT_STOMACH, amount) + newamt = L.getOrganLoss(ORGAN_SLOT_STOMACH) + if("tongue") + L.adjustOrganLoss(ORGAN_SLOT_TONGUE, amount) + newamt = L.getOrganLoss(ORGAN_SLOT_TONGUE) + if("appendix") + L.adjustOrganLoss(ORGAN_SLOT_APPENDIX, amount) + newamt = L.getOrganLoss(ORGAN_SLOT_APPENDIX) else to_chat(usr, "You caused an error. DEBUG: Text:[Text] Mob:[L]") return diff --git a/code/datums/diseases/advance/symptoms/choking.dm b/code/datums/diseases/advance/symptoms/choking.dm index 82dedcf8..43938500 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 665017f5..eb6c5342 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/deafness.dm b/code/datums/diseases/advance/symptoms/deafness.dm index 541ced85..e0336506 100644 --- a/code/datums/diseases/advance/symptoms/deafness.dm +++ b/code/datums/diseases/advance/symptoms/deafness.dm @@ -50,9 +50,9 @@ Bonus if(5) if(power > 2) var/obj/item/organ/ears/ears = M.getorganslot(ORGAN_SLOT_EARS) - if(istype(ears) && ears.ear_damage < UNHEALING_EAR_DAMAGE) + if(istype(ears) && ears.damage < ears.maxHealth) to_chat(M, "Your ears pop painfully and start bleeding!") - ears.ear_damage = max(ears.ear_damage, UNHEALING_EAR_DAMAGE) + ears.damage = max(ears.damage, ears.maxHealth) M.emote("scream") else to_chat(M, "Your ears pop and begin ringing loudly!") diff --git a/code/datums/diseases/advance/symptoms/sensory.dm b/code/datums/diseases/advance/symptoms/sensory.dm index 8d7cc5ed..a6194f41 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)) @@ -100,8 +100,8 @@ else if(M.eye_blind || M.eye_blurry) M.set_blindness(0) M.set_blurriness(0) - else if(eyes.eye_damage > 0) - M.adjust_eye_damage(-1) + else if(eyes.damage > 0) + eyes.applyOrganDamage(-1) else if(prob(base_message_chance)) to_chat(M, "[pick("Your eyes feel great.","You feel like your eyes can focus more clearly.", "You don't feel the need to blink.","Your ears feel great.","Your healing feels more acute.")]") \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/vision.dm b/code/datums/diseases/advance/symptoms/vision.dm index d1cc6905..b4a33cb8 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) @@ -53,20 +53,20 @@ Bonus if(3, 4) to_chat(M, "Your eyes burn!") M.blur_eyes(10) - M.adjust_eye_damage(1) + eyes.applyOrganDamage(1) else M.blur_eyes(20) - M.adjust_eye_damage(5) - if(eyes.eye_damage >= 10) + eyes.applyOrganDamage(5) + if(eyes.damage >= 10) M.become_nearsighted(EYE_DAMAGE) - if(prob(eyes.eye_damage - 10 + 1)) + if(prob(eyes.damage - 10 + 1)) if(!remove_eyes) if(!HAS_TRAIT(M, TRAIT_BLIND)) to_chat(M, "You go blind!") - M.become_blind(EYE_DAMAGE) + eyes.applyOrganDamage(eyes.maxHealth) else M.visible_message("[M]'s eyes fall off their sockets!", "Your eyes fall off their sockets!") eyes.Remove(M) eyes.forceMove(get_turf(M)) else - to_chat(M, "Your eyes burn horrifically!") \ No newline at end of file + to_chat(M, "Your eyes burn horrifically!") diff --git a/code/datums/diseases/appendicitis.dm b/code/datums/diseases/appendicitis.dm index 870aee53..7a6ea142 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 9a5a8a44..da8aa61f 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/martial/cqc.dm b/code/datums/martial/cqc.dm index 71545476..c7644997 100644 --- a/code/datums/martial/cqc.dm +++ b/code/datums/martial/cqc.dm @@ -79,7 +79,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) diff --git a/code/datums/martial/psychotic_brawl.dm b/code/datums/martial/psychotic_brawl.dm index 8f1a33a8..34301516 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), BRUTE, BODY_ZONE_HEAD) A.apply_damage(rand(5,10), BRUTE, 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.Knockdown(rand(5,30))//CIT CHANGE - makes stuns from martial arts always use Knockdown instead of Stun for the sake of consistency if(5,6) diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm index e205d7a4..801e8c8c 100644 --- a/code/datums/martial/sleeping_carp.dm +++ b/code/datums/martial/sleeping_carp.dm @@ -224,7 +224,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 0512977d..77735847 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -520,7 +520,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)) @@ -532,7 +532,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 f77fe373..f57b8823 100644 --- a/code/datums/traits/negative.dm +++ b/code/datums/traits/negative.dm @@ -119,7 +119,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/nearsighted //t. errorage name = "Nearsighted" @@ -345,9 +345,12 @@ gain_text = "You find yourself unable to speak!" lose_text = "You feel a growing strength in your vocal chords." medical_record_text = "Functionally mute, patient is unable to use their voice in any capacity." + var/datum/brain_trauma/severe/mute/mute /datum/quirk/mute/add() var/mob/living/carbon/human/H = quirk_holder + mute = new + H.gain_trauma(mute, TRAUMA_RESILIENCE_SURGERY) H.gain_trauma(TRAIT_MUTE, TRAUMA_RESILIENCE_SURGERY) /datum/quirk/mute/on_process() diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 04af40f1..aaf03ff1 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -146,7 +146,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 1f6cb2ff..cc796fdc 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -241,13 +241,15 @@ 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 BP.attach_limb(mob_occupant) //Premature clones may have brain damage. - mob_occupant.adjustBrainLoss(-((speed_coeff / 2) * dmg_mult)) + mob_occupant.adjustOrganLoss(ORGAN_SLOT_BRAIN, -((speed_coeff / 2) * dmg_mult)) + use_power(7500) //This might need tweaking. @@ -261,6 +263,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 @@ -344,6 +347,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)) @@ -440,7 +446,7 @@ unattached_flesh.Cut() H.setCloneLoss(CLONE_INITIAL_DAMAGE) //Yeah, clones start with very low health, not with random, because why would they start with random health - H.setBrainLoss(CLONE_INITIAL_DAMAGE) + //H.setOrganLoss(ORGAN_SLOT_BRAIN, CLONE_INITIAL_DAMAGE) // In addition to being cellularly damaged and having barely any // brain function, they also have no limbs or internal organs. @@ -456,8 +462,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 c0ca575b..29a5100b 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -166,7 +166,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.dm b/code/game/objects/items.dm index a82e128a..eec9ca8b 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -513,12 +513,12 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) log_combat(user, M, "attacked", "[src.name]", "(INTENT: [uppertext(user.a_intent)])") - M.adjust_blurriness(3) - M.adjust_eye_damage(rand(2,4)) var/obj/item/organ/eyes/eyes = M.getorganslot(ORGAN_SLOT_EYES) if (!eyes) return - if(eyes.eye_damage >= 10) + M.adjust_blurriness(3) + eyes.applyOrganDamage(rand(2,4)) + if(eyes.damage >= 10) M.adjust_blurriness(15) if(M.stat != DEAD) to_chat(M, "Your eyes start to bleed profusely!") @@ -532,7 +532,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) M.adjust_blurriness(10) M.Unconscious(20) M.Knockdown(40) - if (prob(eyes.eye_damage - 10 + 1)) + if (prob(eyes.damage - 10 + 1)) M.become_blind(EYE_DAMAGE) to_chat(M, "You go blind!") diff --git a/code/game/objects/items/body_egg.dm b/code/game/objects/items/body_egg.dm index 80fc0f43..ea72197c 100644 --- a/code/game/objects/items/body_egg.dm +++ b/code/game/objects/items/body_egg.dm @@ -17,26 +17,27 @@ /obj/item/organ/body_egg/Insert(var/mob/living/carbon/M, special = 0) ..() ADD_TRAIT(owner, TRAIT_XENO_HOST, TRAIT_GENERIC) - START_PROCESSING(SSobj, src) owner.med_hud_set_status() INVOKE_ASYNC(src, .proc/AddInfectionImages, owner) /obj/item/organ/body_egg/Remove(var/mob/living/carbon/M, special = 0) - STOP_PROCESSING(SSobj, src) if(owner) REMOVE_TRAIT(owner, TRAIT_XENO_HOST, TRAIT_GENERIC) owner.med_hud_set_status() INVOKE_ASYNC(src, .proc/RemoveInfectionImages, owner) ..() -/obj/item/organ/body_egg/process() +/obj/item/organ/body_egg/on_death() + . = ..() if(!owner) return - if(!(src in owner.internal_organs)) - Remove(owner) - return egg_process() +/obj/item/organ/body_egg/on_life() + . = ..() + egg_process() + + /obj/item/organ/body_egg/proc/egg_process() return diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm index 36d85edb..0496b282 100644 --- a/code/game/objects/items/circuitboards/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm @@ -407,6 +407,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 55e75b39..a4f286bf 100644 --- a/code/game/objects/items/defib.dm +++ b/code/game/objects/items/defib.dm @@ -140,12 +140,10 @@ return ..() /obj/item/defibrillator/emag_act(mob/user) - if(safety) - safety = FALSE - to_chat(user, "You silently disable [src]'s safety protocols with the cryptographic sequencer.") - else - safety = TRUE - to_chat(user, "You silently enable [src]'s safety protocols with the cryptographic sequencer.") + . = ..() + safety = !safety + to_chat(user, "You silently [safety ? "enable" : "disable"] [src]'s safety protocols with the cryptographic sequencer.") + return TRUE /obj/item/defibrillator/emp_act(severity) . = ..() @@ -442,9 +440,20 @@ do_help(H, user) -/obj/item/twohanded/shockpaddles/proc/can_defib(mob/living/carbon/H) +/obj/item/twohanded/shockpaddles/proc/can_defib(mob/living/carbon/H) //Our code here is different than tg, if it breaks in testing; BUG_PROBABLE_CAUSE + 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(!heart || (heart.organ_flags & ORGAN_FAILING)) + return var/obj/item/organ/brain/BR = H.getorgan(/obj/item/organ/brain) - return (!H.suiciding && !(HAS_TRAIT(H, TRAIT_NOCLONE)) && !H.hellbound && ((world.time - H.timeofdeath) < tlimit) && (H.getBruteLoss() < 180) && (H.getFireLoss() < 180) && H.getorgan(/obj/item/organ/heart) && BR && !BR.damaged_brain) + if(QDELETED(BR) || BR.brain_death || (BR.organ_flags & ORGAN_FAILING) || H.suiciding) + return + return TRUE /obj/item/twohanded/shockpaddles/proc/shock_touching(dmg, mob/H) if(req_defib) @@ -559,14 +568,12 @@ if(do_after(user, primetimer, 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 + // patients rot when they are killed, and die when they are dead + var/tplus = world.time - H.timeofdeath //length of time spent dead var/tloss = deathtimer var/total_burn = 0 var/total_brute = 0 + var/obj/item/organ/heart = H.getorgan(/obj/item/organ/heart) if(do_after(user, primetimer2, 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)) @@ -591,16 +598,26 @@ 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 >= 180 || total_brute >= 180) 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()) failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - No activity in patient's brain. Further attempts may be successful." else var/obj/item/organ/brain/BR = H.getorgan(/obj/item/organ/brain) - if(!BR || BR.damaged_brain) - failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's brain is missing or damaged beyond point of no return. Further attempts futile." + if(BR) //BUG_PROBABLE_CAUSE - slight difference between us and tg + 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." + if(H.suiciding || BR.brainmob?.suiciding) + failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - No intelligence pattern can be detected in patient's brain. Further attempts futile." + else + failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's brain is missing. Further attempts futile." + if(failed) user.visible_message(failed) @@ -625,7 +642,7 @@ H.Jitter(100) SEND_SIGNAL(H, COMSIG_LIVING_MINOR_SHOCK) if(tplus > tloss) - H.adjustBrainLoss( max(0, min(99, ((tlimit - tplus) / tlimit * 100))), 150) + H.adjustOrganLoss(ORGAN_SLOT_BRAIN, max(0, min(99, ((tlimit - tplus) / tlimit * 100))), 150) log_combat(user, H, "revived", defib) if(req_defib) if(defib.healdisk) @@ -643,7 +660,11 @@ 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.") + 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.") playsound(src, 'sound/machines/defib_zap.ogg', 50, 1, -1) diff --git a/code/game/objects/items/devices/dogborg_sleeper.dm b/code/game/objects/items/devices/dogborg_sleeper.dm index 7f3c7f3b..ca1648bb 100644 --- a/code/game/objects/items/devices/dogborg_sleeper.dm +++ b/code/game/objects/items/devices/dogborg_sleeper.dm @@ -211,7 +211,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.reagent_list.len) for(var/datum/reagent/R in mob_occupant.reagents.reagent_list) diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 9f80ee18..81bd44ca 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -135,7 +135,7 @@ SLIME 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!") - if(H.undergoing_liver_failure() && H.stat != DEAD) + if(H.undergoing_liver_failure() && H.stat != DEAD) //might be depreciated BUG_PROBABLE_CAUSE to_chat(user, "Subject is suffering from liver failure: Apply Corazone and begin a liver transplant immediately!") var/msg = "*---------*\nAnalyzing results for [M]:\n\tOverall status: [mob_status]\n" @@ -157,12 +157,8 @@ SLIME SCANNER msg += "\tSubject appears to have [M.getCloneLoss() > 30 ? "Severe" : "Minor"] cellular damage.\n" if(advanced) msg += "\tCellular Damage Level: [M.getCloneLoss()].\n" - if (M.getBrainLoss() >= 200 || !M.getorgan(/obj/item/organ/brain)) - msg += "\tSubject's brain function is non-existent.\n" - else if (M.getBrainLoss() >= 120) - msg += "\tSevere brain damage detected. Subject likely to have mental traumas.\n" - else if (M.getBrainLoss() >= 45) - msg += "\tBrain damage detected.\n" + if (!M.getorgan(/obj/item/organ/brain)) + to_chat(user, "\tSubject lacks a brain.") //Unsure how this won't proc for 50% of the cit playerbase (This is a joke everyone on cit a cute.) if(ishuman(M) && advanced) // Should I make this not advanced? var/mob/living/carbon/human/H = M var/obj/item/organ/liver/L = H.getorganslot("liver") @@ -194,6 +190,14 @@ SLIME SCANNER if(Br.cached_size>5) msg += "\tSubject has a sizeable bosom with a [Br.size] cup.\n" + if (M.getOrganLoss(ORGAN_SLOT_BRAIN) >= 200 || !M.getorgan(/obj/item/organ/brain)) + msg += "\tSubject's brain function is non-existent.\n" + else if (M.getOrganLoss(ORGAN_SLOT_BRAIN) >= 120) + msg += "\tSevere brain damage detected. Subject likely to have mental traumas.\n" + else if (M.getOrganLoss(ORGAN_SLOT_BRAIN) >= 45) + msg += "\tBrain damage detected.\n" + + if(iscarbon(M)) var/mob/living/carbon/C = M if(LAZYLEN(C.get_traumas())) var/list/trauma_text = list() @@ -212,11 +216,10 @@ SLIME SCANNER if(C.roundstart_quirks.len) msg += "\tSubject has the following physiological traits: [C.get_trait_string()].\n" if(advanced) - msg += "\tBrain Activity Level: [(200 - M.getBrainLoss())/2]%.\n" + msg += "\tBrain Activity Level: [(200 - M.getOrganLoss(ORGAN_SLOT_BRAIN))/2]%.\n" if(M.radiation) msg += "\tSubject is irradiated.\n" - if(advanced) - msg += "\tRadiation Level: [M.radiation]%.\n" + msg += "\tRadiation Level: [M.radiation] rad\n" if(advanced && M.hallucinating()) msg += "\tSubject is hallucinating.\n" @@ -247,11 +250,11 @@ SLIME SCANNER healthy = FALSE msg += "\tSubject is deaf.\n" else - if(ears.ear_damage) - msg += "\tSubject has [ears.ear_damage > UNHEALING_EAR_DAMAGE? "permanent ": "temporary "]hearing damage.\n" + if(ears.damage) + to_chat(user, "\tSubject has [ears.damage > ears.maxHealth ? "permanent ": "temporary "]hearing damage.") healthy = FALSE if(ears.deaf) - msg += "\tSubject is [ears.ear_damage > UNHEALING_EAR_DAMAGE ? "permanently ": "temporarily "] deaf.\n" + to_chat(user, "\tSubject is [ears.damage > ears.maxHealth ? "permanently ": "temporarily "] deaf.") healthy = FALSE if(healthy) msg += "\tHealthy.\n" @@ -267,13 +270,13 @@ SLIME SCANNER if(HAS_TRAIT(C, TRAIT_NEARSIGHT)) msg += "\tSubject is nearsighted.\n" healthy = FALSE - if(eyes.eye_damage > 30) + if(eyes.damage > 30) msg += "\tSubject has severe eye damage.\n" healthy = FALSE - else if(eyes.eye_damage > 20) + else if(eyes.damage > 20) msg += "\tSubject has significant eye damage.\n" healthy = FALSE - else if(eyes.eye_damage) + else if(eyes.damage) msg += "\tSubject has minor eye damage.\n" healthy = FALSE if(healthy) @@ -297,6 +300,59 @@ SLIME SCANNER for(var/obj/item/bodypart/org in damaged) msg += "\t\t[capitalize(org.name)]: [(org.brute_dam > 0) ? "[org.brute_dam]" : "0"]-[(org.burn_dam > 0) ? "[org.burn_dam]" : "0"]\n" + //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 += "" + msg += "[minor_damage]" + msg += "[major_damage]" + msg += "[max_damage]" + // Species and body temperature if(ishuman(M)) @@ -385,7 +441,7 @@ SLIME SCANNER if(M.reagents.reagent_list.len) var/list/datum/reagent/reagents = list() for(var/datum/reagent/R in M.reagents.reagent_list) - if(R.invisible) + if(R.chemical_flags & REAGENT_INVISIBLE) continue reagents += R @@ -404,6 +460,21 @@ SLIME SCANNER msg += "[R.name]\n" else msg += "Subject is not addicted to any reagents.\n" + + if(M.reagents.has_reagent("fermiTox")) + var/datum/reagent/fermiTox = M.reagents.has_reagent("fermiTox") + switch(fermiTox.volume) + if(5 to 10) + msg += "Subject contains a low amount of toxic isomers.\n" + if(10 to 25) + msg += "Subject contains toxic isomers.\n" + if(25 to 50) + msg += "Subject contains a substantial amount of toxic isomers.\n" + if(50 to 95) + msg += "Subject contains a high amount of toxic isomers.\n" + if(95 to INFINITY) + msg += "Subject contains a extremely dangerous amount of toxic isomers.\n" + msg += "*---------*" to_chat(user, msg) diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index b3cda9b8..06cc7d52 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -254,7 +254,7 @@ to_chat(user, "The MMI indicates that their mind is currently inactive; it might change!") return - if(BM.stat == DEAD || (M.brain && M.brain.damaged_brain)) + if(BM.stat == DEAD || (M.brain && M.brain.organ_flags & ORGAN_FAILING)) to_chat(user, "Sticking a dead brain into the frame would sort of defeat the purpose!") return diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm index df7b203f..85a06f0c 100644 --- a/code/game/objects/items/storage/book.dm +++ b/code/game/objects/items/storage/book.dm @@ -140,7 +140,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible", else if(iscarbon(M)) var/mob/living/carbon/C = M if(!istype(C.head, /obj/item/clothing/head)) - C.adjustBrainLoss(10, 80) + C.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10, 80) to_chat(C, "You feel dumber.") if(smack) diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm index 781a8251..9c038f3e 100644 --- a/code/game/objects/items/twohanded.dm +++ b/code/game/objects/items/twohanded.dm @@ -304,7 +304,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 83551eab..00cea58a 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/morgue.dm b/code/game/objects/structures/morgue.dm index 519c5400..c590fcff 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) @@ -134,6 +137,7 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an for(var/atom/movable/AM in connected.loc) if(!AM.anchored || AM == connected) 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 7d74387c..9dc8b73d 100644 --- a/code/modules/admin/secrets.dm +++ b/code/modules/admin/secrets.dm @@ -458,7 +458,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 d4e137a4..1d52739e 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1752,7 +1752,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 1fc811f0..5b9af57d 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -1264,7 +1264,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits target.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/gland.dm b/code/modules/antagonists/abductor/equipment/gland.dm index 8a3ff218..35a1135b 100644 --- a/code/modules/antagonists/abductor/equipment/gland.dm +++ b/code/modules/antagonists/abductor/equipment/gland.dm @@ -151,7 +151,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 252e2b5c..b6e3d66c 100644 --- a/code/modules/antagonists/changeling/changeling.dm +++ b/code/modules/antagonists/changeling/changeling.dm @@ -83,7 +83,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() . = ..() @@ -340,7 +340,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 a1f8e1ef..1b27fa96 100644 --- a/code/modules/antagonists/changeling/powers/regenerate.dm +++ b/code/modules/antagonists/changeling/powers/regenerate.dm @@ -35,7 +35,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) if(ishuman(user)) diff --git a/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm b/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm index 0ac96c47..88cf4204 100644 --- a/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm +++ b/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm @@ -50,7 +50,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 4f313461..03a176b0 100644 --- a/code/modules/antagonists/slaughter/slaughter.dm +++ b/code/modules/antagonists/slaughter/slaughter.dm @@ -80,6 +80,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 18c5075b..ceb7a01e 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm @@ -144,6 +144,13 @@ else O.forceMove(src) return TRUE + +///Really simple proc, just moves the object "O" into the hands of mob "M" if able, done so I could modify the proc a little for the organ fridge +/obj/machinery/smartfridge/proc/dispense(obj/item/O, var/mob/M) + if(!M.put_in_hands(O)) + 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) @@ -197,9 +204,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() @@ -209,8 +214,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() @@ -378,6 +382,44 @@ /obj/machinery/smartfridge/extract/preloaded initial_contents = list(/obj/item/slime_scanner = 2) +// ------------------------- You think you're better than Chem, huh? +// Organ Surgery Smartfridge +// ------------------------- Just wait till Tamiorgans +/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 + return + 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/process() + for(var/organ in contents) + var/obj/item/organ/O = organ + if(!istype(O)) + return + O.applyOrganDamage(-repair_rate) + +/obj/machinery/smartfridge/organ/Exited(obj/item/organ/AM, atom/newLoc) + . = ..() + if(istype(AM)) + AM.organ_flags &= ~ORGAN_FROZEN + // ----------------------------- // Chemistry Medical Smartfridge // ----------------------------- @@ -399,7 +441,7 @@ return TRUE if(!O.reagents || !O.reagents.reagent_list.len) // other empty containers not accepted return FALSE - if(istype(O, /obj/item/reagent_containers/syringe) || istype(O, /obj/item/reagent_containers/glass/bottle) || istype(O, /obj/item/reagent_containers/glass/beaker) || istype(O, /obj/item/reagent_containers/spray) || istype(O, /obj/item/reagent_containers/medspray)|| istype(O, /obj/item/reagent_containers/chem_pack)) + if(istype(O, /obj/item/reagent_containers/syringe) || istype(O, /obj/item/reagent_containers/glass/bottle) || istype(O, /obj/item/reagent_containers/glass/beaker) || istype(O, /obj/item/reagent_containers/spray) || istype(O, /obj/item/reagent_containers/medspray)) return TRUE return FALSE diff --git a/code/modules/jobs/job_types/civilian_chaplain.dm b/code/modules/jobs/job_types/civilian_chaplain.dm index effb4ba1..0ae7f5f5 100644 --- a/code/modules/jobs/job_types/civilian_chaplain.dm +++ b/code/modules/jobs/job_types/civilian_chaplain.dm @@ -69,7 +69,7 @@ Chaplain B.name = "Guys Gone Wild" 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") - H.adjustBrainLoss(100) // starts off retarded as fuck + H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 100) // starts off retarded as fuck if("science") B.name = pick("Principle of Relativity", "Quantum Enigma: Physics Encounters Consciousness", "Programming the Universe", "Quantum Physics and Theology", "String Theory for Dummies", "How To: Build Your Own Warp Drive", "The Mysteries of Bluespace", "Playing God: Collector's Edition") else diff --git a/code/modules/library/lib_codex_gigas.dm b/code/modules/library/lib_codex_gigas.dm index d3d95db9..57bf37d5 100644 --- a/code/modules/library/lib_codex_gigas.dm +++ b/code/modules/library/lib_codex_gigas.dm @@ -50,8 +50,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/mob/living/brain/MMI.dm b/code/modules/mob/living/brain/MMI.dm index bacdc452..47f44bca 100644 --- a/code/modules/mob/living/brain/MMI.dm +++ b/code/modules/mob/living/brain/MMI.dm @@ -57,13 +57,14 @@ newbrain.brainmob = null brainmob.forceMove(src) brainmob.container = src - if(!newbrain.damaged_brain) // the brain organ hasn't been beaten to death. + if(!(newbrain.organ_flags & ORGAN_FAILING)) // the brain organ hasn't been beaten to death. brainmob.stat = CONSCIOUS //we manually revive the brain mob GLOB.dead_mob_list -= brainmob GLOB.alive_mob_list += brainmob brainmob.reset_perspective() brain = newbrain + brain.organ_flags |= ORGAN_FROZEN name = "Man-Machine Interface: [brainmob.real_name]" update_icon() @@ -100,6 +101,7 @@ user.put_in_hands(brain) //puts brain in the user's hand or otherwise drops it on the user's turf else brain.forceMove(get_turf(src)) + brain.organ_flags &= ~ORGAN_FROZEN brain = null //No more brain in here diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index dafc6cf5..41a89440 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -7,11 +7,19 @@ 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 / 4 //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/mob/living/brain/brainmob = null - var/damaged_brain = FALSE //whether the brain organ is damaged. + var/brain_death = FALSE //if the brainmob was intentionally killed by attacking the brain after removal, or by severe braindamage var/decoy_override = FALSE //I apologize to the security players, and myself, who abused this, but this is going to go. + //two variables necessary for calculating whether we get a brain trauma or not + var/damage_delta = 0 var/list/datum/brain_trauma/traumas = list() @@ -34,7 +42,7 @@ if(brainmob.mind) brainmob.mind.transfer_to(C) else - C.key = brainmob.key + brainmob.transfer_ckey(C) QDEL_NULL(brainmob) @@ -90,22 +98,89 @@ if(brainmob) O.attack(brainmob, user) //Oh noooeeeee -/obj/item/organ/brain/examine(mob/user) - ..() + if(istype(O, /obj/item/organ_storage)) //BUG_PROBABLE_CAUSE + return //Borg organ bags shouldn't be killing brains - if(brainmob) - if(brainmob.client) - if(brainmob.health <= HEALTH_THRESHOLD_DEAD) - to_chat(user, "It's lifeless and severely damaged.") + if((organ_flags & ORGAN_FAILING) && O.is_drainable() && O.reagents.has_reagent("neurine")) //Neurine fixes dead brains + . = TRUE //don't do attack animation. + var/cached_Bdamage = brainmob?.health + var/datum/reagent/medicine/neurine/N = reagents.has_reagent("neurine") + var/datum/reagent/medicine/mannitol/M1 = reagents.has_reagent("mannitol") + + if(O.reagents.has_reagent("mannitol"))//Just a quick way to bolster the effects if someone mixes up a batch. + N.volume *= (M1.volume*0.5) + + if(!O.reagents.has_reagent("neurine", 10)) + to_chat(user, "There's not enough neurine in [O] to restore [src]!") + return + + user.visible_message("[user] starts to pour the contents of [O] onto [src].", "You start to slowly pour the contents of [O] onto [src].") + if(!do_after(user, 60, TRUE, src)) + to_chat(user, "You failed to pour [O] onto [src]!") + 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.") + setOrganDamage((damage - (0.10 * maxHealth)*(N.volume/10))) //heals a small amount, and by using "setorgandamage", we clear the failing variable if that was up + O.reagents.clear_reagents() + + if(cached_Bdamage <= HEALTH_THRESHOLD_DEAD) //Fixing dead brains yeilds a trauma + if((cached_Bdamage <= HEALTH_THRESHOLD_DEAD) && (brainmob.health > HEALTH_THRESHOLD_DEAD)) + if(prob(80)) + gain_trauma_type(BRAIN_TRAUMA_MILD) + else if(prob(50)) + gain_trauma_type(BRAIN_TRAUMA_SEVERE) + else + gain_trauma_type(BRAIN_TRAUMA_SPECIAL) + return + + if((organ_flags & ORGAN_FAILING) && O.is_drainable() && O.reagents.has_reagent("mannitol")) //attempt to heal the brain + . = TRUE //don't do attack animation. + var/datum/reagent/medicine/mannitol/M = reagents.has_reagent("mannitol") + if(brain_death || brainmob?.health <= HEALTH_THRESHOLD_DEAD) //if the brain is fucked anyway, do nothing + to_chat(user, "[src] is far too damaged, you'll have to use neurine on it!") + return + + if(!O.reagents.has_reagent("mannitol", 10)) + to_chat(user, "There's not enough mannitol in [O] to restore [src]!") + return + + user.visible_message("[user] starts to pour the contents of [O] onto [src].", "You start to slowly pour the contents of [O] onto [src].") + if(!do_after(user, 60, TRUE, src)) + to_chat(user, "You failed to pour [O] onto [src]!") + 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.") + setOrganDamage((damage - (0.05 * maxHealth)*(M.volume/10))) //heals a small amount, and by using "setorgandamage", we clear the failing variable if that was up + O.reagents.clear_reagents() + return + + + +/obj/item/organ/brain/examine(mob/user)//BUG_PROBABLE_CAUSE to_chats changed to . += + . = ..() + + if(user.suiciding) + . += "It's started turning slightly grey. They must not have been able to handle the stress of it all." + else if(brainmob) + if(brainmob.get_ghost(FALSE, TRUE)) + if(brain_death || brainmob.health <= HEALTH_THRESHOLD_DEAD) + . += "It's lifeless and severely damaged, only the strongest of chems will save it." + 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 - to_chat(user, "You can feel the small spark of life still left in this one.") + . += "You can feel the small spark of life still left in this one." + 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 - to_chat(user, "This one seems particularly lifeless. Perhaps it will regain some of its luster later.") + . += "This one seems particularly lifeless. Perhaps it will regain some of its luster later." else if(decoy_override) - to_chat(user, "This one seems particularly lifeless. Perhaps it will regain some of its luster later.") + 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 - to_chat(user, "This one is completely devoid of life.") + . += "This one is completely devoid of life." /obj/item/organ/brain/attack(mob/living/carbon/C, mob/user) if(!istype(C)) @@ -141,7 +216,7 @@ Insert(C) else ..() - +/* TO BE REMOVED, KEPT IN CASE OF BUGS /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) @@ -165,6 +240,54 @@ else if(adjusted_amount <= -DAMAGE_PRECISION) obj_integrity = min(max_integrity, obj_integrity-adjusted_amount) . = adjusted_amount +*/ + +/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/on_death() + if(damage <= BRAIN_DAMAGE_DEATH) //rip + brain_death = FALSE + applyOrganDamage(maxHealth * decay_factor) + + +/obj/item/organ/brain/applyOrganDamage(var/d, var/maximum = maxHealth) + ..() + + +/obj/item/organ/brain/check_damage_thresholds(mob/M) + . = ..() + //if we're not more injured than before, return without gambling for a trauma + if(damage <= prev_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 + var/brain_message + if(prev_damage < BRAIN_DAMAGE_MILD && damage >= BRAIN_DAMAGE_MILD) + brain_message = "You feel lightheaded." + else if(prev_damage < BRAIN_DAMAGE_SEVERE && damage >= BRAIN_DAMAGE_SEVERE) + brain_message = "You feel less in control of your thoughts." + else if(prev_damage < (BRAIN_DAMAGE_DEATH - 20) && damage >= (BRAIN_DAMAGE_DEATH - 20)) + brain_message = "You can feel your mind flickering on and off..." + + if(.) + . += "\n[brain_message]" + else + return brain_message /obj/item/organ/brain/Destroy() //copypasted from MMIs. if(brainmob) @@ -200,6 +323,10 @@ return FALSE if(!resilience) resilience = initial(trauma.resilience) + if(!owner) + return FALSE + if(owner.stat == DEAD) + return FALSE var/resilience_tier_count = 0 for(var/X in traumas) diff --git a/code/modules/mob/living/brain/life.dm b/code/modules/mob/living/brain/life.dm index 786bb0b5..51be1f69 100644 --- a/code/modules/mob/living/brain/life.dm +++ b/code/modules/mob/living/brain/life.dm @@ -20,7 +20,7 @@ else if(istype(loc, /obj/item/organ/brain)) BR = loc if(BR) - BR.damaged_brain = 1 //beaten to a pulp + BR.brain_death = TRUE /mob/living/brain/proc/handle_emp_damage() if(emp_damage) diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm index 35142396..22ad146d 100644 --- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm +++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm @@ -22,6 +22,7 @@ return S /obj/item/organ/body_egg/alien_embryo/on_life() + .=..() switch(stage) if(2, 3) if(prob(2)) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 4f9b1abd..500be0a5 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -814,7 +814,7 @@ reagents.clear_reagents() var/obj/item/organ/brain/B = getorgan(/obj/item/organ/brain) if(B) - B.damaged_brain = FALSE + B.brain_death = 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/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 9d366ee4..2c757c6e 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -405,16 +405,16 @@ if(istype(ears) && (deafen_pwr || damage_pwr)) var/ear_damage = damage_pwr * effect_amount - var/deaf = max(ears.deaf, deafen_pwr * effect_amount) + var/deaf = deafen_pwr * effect_amount adjustEarDamage(ear_damage,deaf) - if(ears.ear_damage >= 15) + if(ears.damage >= 15) to_chat(src, "Your ears start to ring badly!") - if(prob(ears.ear_damage - 5)) + if(prob(ears.damage - 5)) to_chat(src, "You can't hear anything!") - ears.ear_damage = min(ears.ear_damage, UNHEALING_EAR_DAMAGE) + ears.damage = min(ears.damage, ears.maxHealth) // you need earmuffs, inacusiate, or replacement - else if(ears.ear_damage >= 5) + else if(ears.damage >= 5) to_chat(src, "Your ears start to ring!") SEND_SOUND(src, sound('sound/weapons/flash_ring.ogg',0,1,0,250)) return effect_amount //how soundbanged we are diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm index 749ae3b5..219c5ba7 100644 --- a/code/modules/mob/living/carbon/damage_procs.dm +++ b/code/modules/mob/living/carbon/damage_procs.dm @@ -47,7 +47,6 @@ adjustArousalLoss(damage * hit_percent) return TRUE - //These procs fetch a cumulative total damage from all bodyparts /mob/living/carbon/getBruteLoss() var/amount = 0 @@ -63,7 +62,6 @@ amount += BP.burn_dam return amount - /mob/living/carbon/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE) if(!forced && (status_flags & GODMODE)) return FALSE @@ -113,6 +111,50 @@ return adjustStaminaLoss(diff, updating, 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) + var/obj/item/organ/O = getorganslot(slot) + if(O && !(status_flags & GODMODE)) + if(!maximum) + maximum = O.maxHealth + O.applyOrganDamage(amount, maximum) + O.onDamage(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) + O.onSetDamage(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 + +/mob/living/carbon/proc/adjustAllOrganLoss(amount, maximum) + for(var/obj/item/organ/O in internal_organs) + if(O && !(status_flags & GODMODE)) + continue + if(!maximum) + maximum = O.maxHealth + O.applyOrganDamage(amount, maximum) + O.onDamage(amount, maximum) + //////////////////////////////////////////// //Returns a list of damaged bodyparts @@ -213,24 +255,25 @@ update_damage_overlays() update_stamina() -/mob/living/carbon/getBrainLoss() +/* TO_REMOVE +/mob/living/carbon/getOrganLoss(ORGAN_SLOT_BRAIN) . = 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) +/mob/living/carbon/adjustOrganLoss(ORGAN_SLOT_BRAIN, amount, maximum = BRAIN_DAMAGE_DEATH) if(status_flags & GODMODE) return FALSE - var/prev_brainloss = getBrainLoss() + var/prev_brainloss = getOrganLoss(ORGAN_SLOT_BRAIN) 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() + var/brainloss = getOrganLoss(ORGAN_SLOT_BRAIN) if(brainloss > BRAIN_DAMAGE_MILD) if(prob(amount * ((2 * (100 + brainloss - BRAIN_DAMAGE_MILD)) / 100))) //Base chance is the hit damage; for every point of damage past the threshold the chance is increased by 2% gain_trauma_type(BRAIN_TRAUMA_MILD) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 20cb7bd5..2a9a60f3 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -348,10 +348,15 @@ if(temp) var/update = 0 var/dmg = rand(M.force/2, M.force) + var/atom/throw_target = get_edge_target_turf(src, M.dir) switch(M.damtype) if("brute") - if(M.force > 20) - Unconscious(20) + if(M.force > 35) // durand and other heavy mechas + Knockdown(50) + src.throw_at(throw_target, rand(1,5), 7) + else if(M.force >= 20 && !IsKnockdown()) // lightweight mechas like gygax + Knockdown(30) + src.throw_at(throw_target, rand(1,3), 7) update |= temp.receive_damage(dmg, 0) playsound(src, 'sound/weapons/punch4.ogg', 50, 1) if("fire") @@ -746,9 +751,54 @@ if(0 to NUTRITION_LEVEL_STARVING) to_send += "You're starving!\n" + + //TODO: Convert these messages into vague messages, thereby encouraging actual dignosis. + //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_send += "You have these quirks: [get_trait_string()].\n" - + to_chat(src, to_send) else if(wear_suit) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 0a325859..5a0dce99 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -71,7 +71,7 @@ else if(eye_blurry) //blurry eyes heal slowly adjust_blurriness(-1) - if (getBrainLoss() >= 30) //Citadel change to make memes more often. + if (getOrganLoss(ORGAN_SLOT_BRAIN) >= 30) //Citadel change to make memes more often. SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "brain_damage", /datum/mood_event/brain_damage) if(prob(3)) if(prob(25)) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 3efcf5e5..01f7ecb6 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -1,6 +1,7 @@ // This code handles different species in the game. GLOBAL_LIST_EMPTY(roundstart_races) +GLOBAL_LIST_EMPTY(roundstart_race_names) /datum/species var/id // if the game needs to manually check your race to do something not included in a proc here, it will use this @@ -8,13 +9,35 @@ GLOBAL_LIST_EMPTY(roundstart_races) var/name // this is the fluff name. these will be left generic (such as 'Lizardperson' for the lizard race) so servers can change them to whatever var/default_color = "#FFF" // if alien colors are disabled, this is the color that will be used by that race - var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows + var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows - var/list/offset_features = list(OFFSET_UNIFORM = list(0,0), OFFSET_ID = list(0,0), OFFSET_GLOVES = list(0,0), OFFSET_GLASSES = list(0,0), OFFSET_EARS = list(0,0), OFFSET_SHOES = list(0,0), OFFSET_S_STORE = list(0,0), OFFSET_FACEMASK = list(0,0), OFFSET_HEAD = list(0,0), OFFSET_FACE = list(0,0), OFFSET_BELT = list(0,0), OFFSET_BACK = list(0,0), OFFSET_SUIT = list(0,0), OFFSET_NECK = list(0,0)) + //Species Icon Drawing Offsets - Pixel X, Pixel Y, Aka X = Horizontal and Y = Vertical, from bottom left corner + var/list/offset_features = list( + OFFSET_UNIFORM = list(0,0), + OFFSET_ID = list(0,0), + OFFSET_GLOVES = list(0,0), + OFFSET_GLASSES = list(0,0), + OFFSET_EARS = list(0,0), + OFFSET_SHOES = list(0,0), + OFFSET_S_STORE = list(0,0), + OFFSET_FACEMASK = list(0,0), + OFFSET_HEAD = list(0,0), + OFFSET_EYES = list(0,0), + OFFSET_LIPS = list(0,0), + OFFSET_BELT = list(0,0), + OFFSET_BACK = list(0,0), + OFFSET_HAIR = list(0,0), + OFFSET_FHAIR = list(0,0), + OFFSET_SUIT = list(0,0), + OFFSET_NECK = list(0,0), + OFFSET_MUTPARTS = list(0,0) + ) var/hair_color // this allows races to have specific hair colors... if null, it uses the H's hair/facial hair colors. if "mutcolor", it uses the H's mutant_color var/hair_alpha = 255 // the alpha used by the hair. 255 is completely solid, 0 is transparent. + var/horn_color //specific horn colors, because why not? + var/use_skintones = 0 // does it use skintones or not? (spoiler alert this is only used by humans) var/exotic_blood = "" // If your race wants to bleed something other than bog standard blood, change this to reagent id. var/exotic_bloodtype = "" //If your race uses a non standard bloodtype (A+, O-, AB-, etc) @@ -79,7 +102,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) var/fixed_mut_color3 = "" var/whitelisted = 0 //Is this species restricted to certain players? var/whitelist = list() //List the ckeys that can use this species, if it's whitelisted.: list("John Doe", "poopface666", "SeeALiggerPullTheTrigger") Spaces & capitalization can be included or ignored entirely for each key as it checks for both. - + var/should_draw_citadel = FALSE /////////// // PROCS // @@ -98,6 +121,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) var/datum/species/S = new I if(S.check_roundstart_eligible()) GLOB.roundstart_races += S.id + GLOB.roundstart_race_names["[S.name]"] = S.id qdel(S) if(!GLOB.roundstart_races.len) GLOB.roundstart_races += "human" @@ -129,10 +153,10 @@ GLOBAL_LIST_EMPTY(roundstart_races) return //Please override this locally if you want to define when what species qualifies for what rank if human authority is enforced. -/datum/species/proc/qualifies_for_rank(rank, list/features) - if(rank in GLOB.command_positions) - return 0 - return 1 +/datum/species/proc/qualifies_for_rank(rank, list/features) //SPECIES JOB RESTRICTIONS + //if(rank in GLOB.command_positions) Left as an example: The format qualifies for rank takes. + // return 0 //It returns false when it runs the proc so they don't get jobs from the global list. + return 1 //It returns 1 to say they are a-okay to continue. //Will regenerate missing organs /datum/species/proc/regenerate_organs(mob/living/carbon/C,datum/species/old_species,replace_current=TRUE) @@ -260,7 +284,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) C.hud_used.update_locked_slots() // this needs to be FIRST because qdel calls update_body which checks if we have DIGITIGRADE legs or not and if not then removes DIGITIGRADE from species_traits - if(("legs" in C.dna.species.mutant_bodyparts) && C.dna.features["legs"] == "Digitigrade Legs") + if(("legs" in C.dna.species.mutant_bodyparts) && (C.dna.features["legs"] == "Digitigrade" || C.dna.features["legs"] == "Avian")) species_traits += DIGITIGRADE if(DIGITIGRADE in species_traits) C.Digitigrade_Leg_Swap(FALSE) @@ -294,8 +318,6 @@ GLOBAL_LIST_EMPTY(roundstart_races) for(var/datum/disease/A in C.diseases) A.cure(FALSE) - SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species) - //CITADEL EDIT if(NOAROUSAL in species_traits) C.canbearoused = FALSE @@ -306,6 +328,11 @@ GLOBAL_LIST_EMPTY(roundstart_races) var/mob/living/carbon/human/H = C if(NOGENITALS in H.dna.species.species_traits) H.give_genitals(TRUE) //call the clean up proc to delete anything on the mob then return. + if("meat_type" in default_features) //I can't believe it's come to the meat + H.type_of_meat = GLOB.meat_types[H.dna.features["meat_type"]] + + SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species) + // EDIT ENDS @@ -317,6 +344,11 @@ GLOBAL_LIST_EMPTY(roundstart_races) for(var/X in inherent_traits) REMOVE_TRAIT(C, X, SPECIES_TRAIT) + if("meat_type" in default_features) + C.type_of_meat = GLOB.meat_types[C.dna.features["meat_type"]] + else + C.type_of_meat = initial(meat) + SEND_SIGNAL(C, COMSIG_SPECIES_LOSS, src) /datum/species/proc/handle_hair(mob/living/carbon/human/H, forced_colour) @@ -389,6 +421,10 @@ GLOBAL_LIST_EMPTY(roundstart_races) facial_overlay.alpha = hair_alpha + if(OFFSET_FHAIR in H.dna.species.offset_features) + facial_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FHAIR][1] + facial_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FHAIR][2] + standing += facial_overlay if(H.head) @@ -446,9 +482,11 @@ GLOBAL_LIST_EMPTY(roundstart_races) else hair_overlay.color = forced_colour hair_overlay.alpha = hair_alpha - if(OFFSET_FACE in H.dna.species.offset_features) - hair_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1] - hair_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2] + + if(OFFSET_HAIR in H.dna.species.offset_features) + hair_overlay.pixel_x += H.dna.species.offset_features[OFFSET_HAIR][1] + hair_overlay.pixel_y += H.dna.species.offset_features[OFFSET_HAIR][2] + if(hair_overlay.icon) standing += hair_overlay @@ -469,9 +507,11 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(H.lip_style && (LIPS in species_traits)) var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/human_face.dmi', "lips_[H.lip_style]", -BODY_LAYER) lip_overlay.color = H.lip_color - if(OFFSET_FACE in H.dna.species.offset_features) - lip_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1] - lip_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2] + + if(OFFSET_LIPS in H.dna.species.offset_features) + lip_overlay.pixel_x += H.dna.species.offset_features[OFFSET_LIPS][1] + lip_overlay.pixel_y += H.dna.species.offset_features[OFFSET_LIPS][2] + standing += lip_overlay // eyes @@ -484,9 +524,11 @@ GLOBAL_LIST_EMPTY(roundstart_races) eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes", -BODY_LAYER) if((EYECOLOR in species_traits) && has_eyes) eye_overlay.color = "#" + H.eye_color - if(OFFSET_FACE in H.dna.species.offset_features) - eye_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1] - eye_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2] + + if(OFFSET_EYES in H.dna.species.offset_features) + eye_overlay.pixel_x += H.dna.species.offset_features[OFFSET_EYES][1] + eye_overlay.pixel_y += H.dna.species.offset_features[OFFSET_EYES][2] + standing += eye_overlay //Underwear, Undershirts & Socks @@ -529,7 +571,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) var/digilegs = (DIGITIGRADE in species_traits) ? "_d" : "" var/mutable_appearance/MA = mutable_appearance(S.icon, "[S.icon_state][digilegs]", -BODY_LAYER) if(UNDIE_COLORABLE(S)) - MA.color = "[H.socks_color]" + MA.color = "#[H.socks_color]" standing += MA if(standing.len) @@ -612,6 +654,10 @@ GLOBAL_LIST_EMPTY(roundstart_races) else if ("wings" in mutant_bodyparts) bodyparts_to_add -= "wings_open" + if("insect_fluff" in mutant_bodyparts) + if(!H.dna.features["insect_fluff"] || H.dna.features["insect_fluff"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT)) + bodyparts_to_add -= "insect_fluff" + //CITADEL EDIT //Race specific bodyparts: //Xenos @@ -715,12 +761,14 @@ GLOBAL_LIST_EMPTY(roundstart_races) S = GLOB.wings_list[H.dna.features["wings"]] if("wingsopen") S = GLOB.wings_open_list[H.dna.features["wings"]] + if("deco_wings") + S = GLOB.deco_wings_list[H.dna.features["deco_wings"]] if("legs") S = GLOB.legs_list[H.dna.features["legs"]] - if("moth_wings") - S = GLOB.moth_wings_list[H.dna.features["moth_wings"]] - if("moth_markings") - S = GLOB.moth_markings_list[H.dna.features["moth_markings"]] + if("insect_wings") + S = GLOB.insect_wings_list[H.dna.features["insect_wings"]] + if("insect_fluff") + S = GLOB.insect_fluffs_list[H.dna.features["insect_fluff"]] if("caps") S = GLOB.caps_list[H.dna.features["caps"]] if("ipc_screen") @@ -817,6 +865,8 @@ GLOBAL_LIST_EMPTY(roundstart_races) accessory_overlay.color = "#[H.facial_hair_color]" if(EYECOLOR) accessory_overlay.color = "#[H.eye_color]" + if(HORNCOLOR) + accessory_overlay.color = "#[H.horn_color]" else accessory_overlay.color = forced_colour else @@ -833,6 +883,11 @@ GLOBAL_LIST_EMPTY(roundstart_races) for(var/index=1, index<=husklist.len, index++) husklist[index] = husklist[index]/255 accessory_overlay.color = husklist + + if(OFFSET_MUTPARTS in H.dna.species.offset_features) + accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1] + accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2] + standing += accessory_overlay if(S.hasinner) @@ -845,6 +900,10 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(S.center) inner_accessory_overlay = center_image(inner_accessory_overlay, S.dimension_x, S.dimension_y) + if(OFFSET_MUTPARTS in H.dna.species.offset_features) + inner_accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1] + inner_accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2] + standing += inner_accessory_overlay if(S.extra) //apply the extra overlay, if there is one @@ -882,6 +941,14 @@ GLOBAL_LIST_EMPTY(roundstart_races) extra_accessory_overlay.color = "#[H.facial_hair_color]" if(EYECOLOR) extra_accessory_overlay.color = "#[H.eye_color]" + + if(HORNCOLOR) + extra_accessory_overlay.color = "#[H.horn_color]" + + if(OFFSET_MUTPARTS in H.dna.species.offset_features) + extra_accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1] + extra_accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2] + standing += extra_accessory_overlay if(S.extra2) //apply the extra overlay, if there is one @@ -914,6 +981,13 @@ GLOBAL_LIST_EMPTY(roundstart_races) extra2_accessory_overlay.color = "#[H.dna.features["mcolor"]]" else extra2_accessory_overlay.color = "#[H.hair_color]" + if(HORNCOLOR) + extra2_accessory_overlay.color = "#[H.horn_color]" + + if(OFFSET_MUTPARTS in H.dna.species.offset_features) + extra2_accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1] + extra2_accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2] + standing += extra2_accessory_overlay @@ -1198,9 +1272,14 @@ GLOBAL_LIST_EMPTY(roundstart_races) 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) @@ -1316,9 +1395,9 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(!istype(J) && istype(C)) J = C.jetpack if(istype(J) && J.full_speed && J.allow_thrust(0.01, H)) //Prevents stacking - . -= 2 + . -= 0.4 else if(istype(T) && T.allow_thrust(0.01, H)) - . -= 2 + . -= 0.4 if(!ignoreslow && gravity) if(H.wear_suit) @@ -1685,7 +1764,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!") @@ -1694,11 +1773,11 @@ 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.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) - var/datum/antagonist/gang/gang = H.mind.has_antag_datum(/datum/antagonist/gang/) + var/datum/antagonist/gang/gang = H.mind.has_antag_datum(/datum/antagonist/gang && !/datum/antagonist/gang/boss) if(rev) rev.remove_revolutionary(FALSE, user) if(gang) @@ -1734,6 +1813,130 @@ GLOBAL_LIST_EMPTY(roundstart_races) H.forcesay(GLOB.hit_appends) //forcesay checks stat already. return TRUE +/datum/species/proc/alt_spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style) + if(!istype(M)) + return TRUE + CHECK_DNA_AND_SPECIES(M) + CHECK_DNA_AND_SPECIES(H) + + if(!istype(M)) //sanity check for drones. + return TRUE + if(M.mind) + attacker_style = M.mind.martial_art + if((M != H) && M.a_intent != INTENT_HELP && H.check_shields(M, 0, M.name, attack_type = UNARMED_ATTACK)) + log_combat(M, H, "attempted to touch") + H.visible_message("[M] attempted to touch [H]!") + return TRUE + switch(M.a_intent) + if(INTENT_HELP) + if(M == H) + althelp(M, H, attacker_style) + return TRUE + return FALSE + if(INTENT_DISARM) + altdisarm(M, H, attacker_style) + return TRUE + return FALSE + +/datum/species/proc/althelp(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) + if(user == target && istype(user)) + if(user.getStaminaLoss() >= STAMINA_SOFTCRIT) + to_chat(user, "You're too exhausted for that.") + return + if(!user.resting) + to_chat(user, "You can only force yourself up if you're on the ground.") + return + user.visible_message("[user] forces [p_them()]self up to [p_their()] feet!", "You force yourself up to your feet!") + user.resting = 0 + user.update_canmove() + user.adjustStaminaLossBuffered(user.stambuffer) //Rewards good stamina management by making it easier to instantly get up from resting + playsound(user, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + +/datum/species/proc/altdisarm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) + if(user.getStaminaLoss() >= STAMINA_SOFTCRIT) + to_chat(user, "You're too exhausted.") + return FALSE + if(target.check_block()) + target.visible_message("[target] blocks [user]'s shoving attempt!") + return FALSE + if(attacker_style && attacker_style.disarm_act(user,target)) + return TRUE + if(user.resting) + return FALSE + else + if(user == target) + return + user.do_attack_animation(target, ATTACK_EFFECT_DISARM) + user.adjustStaminaLossBuffered(4) + playsound(target, 'sound/weapons/thudswoosh.ogg', 50, TRUE, -1) + + if(target.w_uniform) + target.w_uniform.add_fingerprint(user) + SEND_SIGNAL(target, COMSIG_HUMAN_DISARM_HIT, user, user.zone_selected) + + if(!target.resting) + target.adjustStaminaLoss(5) + + if(target.is_shove_knockdown_blocked()) + return + + var/turf/target_oldturf = target.loc + var/shove_dir = get_dir(user.loc, target_oldturf) + var/turf/target_shove_turf = get_step(target.loc, shove_dir) + var/mob/living/carbon/human/target_collateral_human + var/shove_blocked = FALSE //Used to check if a shove is blocked so that if it is knockdown logic can be applied + + //Thank you based whoneedsspace + target_collateral_human = locate(/mob/living/carbon/human) in target_shove_turf.contents + if(target_collateral_human && !target_collateral_human.resting) + shove_blocked = TRUE + else + target_collateral_human = null + target.Move(target_shove_turf, shove_dir) + if(get_turf(target) == target_oldturf) + shove_blocked = TRUE + + if(shove_blocked && !target.buckled) + var/directional_blocked = !target.Adjacent(target_shove_turf) + var/targetatrest = target.resting + if((directional_blocked || !(target_collateral_human || target_shove_turf.shove_act(target, user))) && !targetatrest) + target.Knockdown(SHOVE_KNOCKDOWN_SOLID) + user.visible_message("[user.name] shoves [target.name], knocking them down!", + "You shove [target.name], knocking them down!", null, COMBAT_MESSAGE_RANGE) + log_combat(user, target, "shoved", "knocking them down") + else if(target_collateral_human && !targetatrest) + target.Knockdown(SHOVE_KNOCKDOWN_HUMAN) + target_collateral_human.Knockdown(SHOVE_KNOCKDOWN_COLLATERAL) + user.visible_message("[user.name] shoves [target.name] into [target_collateral_human.name]!", + "You shove [target.name] into [target_collateral_human.name]!", null, COMBAT_MESSAGE_RANGE) + log_combat(user, target, "shoved", "into [target_collateral_human.name]") + + else + user.visible_message("[user.name] shoves [target.name]!", + "You shove [target.name]!", null, COMBAT_MESSAGE_RANGE) + var/target_held_item = target.get_active_held_item() + var/knocked_item = FALSE + if(!is_type_in_typecache(target_held_item, GLOB.shove_disarming_types)) + target_held_item = null + if(!target.has_movespeed_modifier(SHOVE_SLOWDOWN_ID)) + target.add_movespeed_modifier(SHOVE_SLOWDOWN_ID, multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH) + if(target_held_item) + target.visible_message("[target.name]'s grip on \the [target_held_item] loosens!", + "Your grip on \the [target_held_item] loosens!", null, COMBAT_MESSAGE_RANGE) + addtimer(CALLBACK(target, /mob/living/carbon/human/proc/clear_shove_slowdown), SHOVE_SLOWDOWN_LENGTH) + else if(target_held_item) + target.dropItemToGround(target_held_item) + knocked_item = TRUE + target.visible_message("[target.name] drops \the [target_held_item]!!", + "You drop \the [target_held_item]!!", null, COMBAT_MESSAGE_RANGE) + var/append_message = "" + if(target_held_item) + if(knocked_item) + append_message = "causing them to drop [target_held_item]" + else + append_message = "loosening their grip on [target_held_item]" + log_combat(user, target, "shoved", append_message) + /datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H) var/hit_percent = (100-(blocked+armor))/100 hit_percent = (hit_percent * (100-H.physiology.damage_resistance))/100 @@ -1783,14 +1986,13 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(CLONE) H.adjustCloneLoss(damage * hit_percent * H.physiology.clone_mod) if(STAMINA) - H.stamdamageoverlaytemp = 20 if(BP) if(damage > 0 ? BP.receive_damage(0, 0, damage * hit_percent * H.physiology.stamina_mod) : BP.heal_damage(0, 0, abs(damage * hit_percent * H.physiology.stamina_mod), only_robotic = FALSE, only_organic = FALSE)) H.update_stamina() else H.adjustStaminaLoss(damage * hit_percent * H.physiology.stamina_mod) if(BRAIN) - H.adjustBrainLoss(damage * hit_percent * H.physiology.brain_mod) + H.adjustOrganLoss(ORGAN_SLOT_BRAIN, damage * hit_percent * H.physiology.brain_mod) if(AROUSAL) //Citadel edit - arousal H.adjustArousalLoss(damage * hit_percent) return 1 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 4a7580e9..9d641b57 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 b7897c13..324e1109 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -102,6 +102,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) @@ -122,10 +123,8 @@ if(special != HEART_SPECIAL_SHADOWIFY) blade = new/obj/item/light_eater M.put_in_hands(blade) - START_PROCESSING(SSobj, src) /obj/item/organ/heart/nightmare/Remove(mob/living/carbon/M, special = 0) - STOP_PROCESSING(SSobj, src) respawn_progress = 0 if(blade && special != HEART_SPECIAL_SHADOWIFY) QDEL_NULL(blade) @@ -138,9 +137,8 @@ /obj/item/organ/heart/nightmare/update_icon() return //always beating visually -/obj/item/organ/heart/nightmare/process() - if(QDELETED(owner) || owner.stat != DEAD) - respawn_progress = 0 +/obj/item/organ/heart/nightmare/on_death() + if(!owner) return var/turf/T = get_turf(owner) if(istype(T)) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 2ef5f2f7..a6f5412e 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -9,9 +9,10 @@ stamdamageoverlaytemp = 0 update_damage_hud() + if(!IsInStasis()) - if(stat != DEAD) //Reagent processing needs to come before breathing, to prevent edge cases. - handle_organs() + //Reagent processing needs to come before breathing, to prevent edge cases. + handle_organs() . = ..() @@ -49,8 +50,22 @@ //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 + SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "suffocation") else if(istype(loc, /obj/)) var/obj/location_as_object = loc @@ -58,6 +73,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("lexorin")) return if(istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell)) @@ -76,7 +92,7 @@ var/datum/gas_mixture/breath if(!getorganslot(ORGAN_SLOT_BREATHING_TUBE)) - if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL)) + if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL) || 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) @@ -128,7 +144,7 @@ if((status_flags & GODMODE)) return - var/lungs = getorganslot(ORGAN_SLOT_LUNGS) + var/obj/item/organ/lungs = getorganslot(ORGAN_SLOT_LUNGS) if(!lungs) adjustOxyLoss(2) @@ -368,9 +384,18 @@ . |= BP.on_life() /mob/living/carbon/proc/handle_organs() - for(var/V in internal_organs) - var/obj/item/organ/O = V - O.on_life() + if(stat != DEAD) + for(var/V in internal_organs) + var/obj/item/organ/O = V + if(O) + O.on_life() + else + for(var/V in internal_organs) + var/obj/item/organ/O = V + if(O) + O.on_death() //Needed so organs decay while inside the body. + + /mob/living/carbon/handle_diseases() for(var/thing in diseases) @@ -615,7 +640,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put to_chat(src, "Maybe you should lie down for a bit...") if(drunkenness >= 91) - adjustBrainLoss(0.4, 60) + adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.4, 60) 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...") @@ -649,8 +674,8 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put if((!dna && !liver) || (NOLIVER in dna.species.species_traits)) return if(liver) - if(liver.damage >= liver.maxHealth) - liver.failing = TRUE + if(liver.damage < liver.maxHealth) + liver.organ_flags |= ORGAN_FAILING liver_failure() else liver_failure() @@ -689,13 +714,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.damaged_brain = TRUE - ///////////////////////////////////// //MONKEYS WITH TOO MUCH CHOLOESTROL// ///////////////////////////////////// @@ -704,7 +722,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 8c2e7824..ef92a04c 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -25,8 +25,6 @@ adjustCloneLoss(damage * hit_percent) if(STAMINA) adjustStaminaLoss(damage * hit_percent) - if(BRAIN) - adjustBrainLoss(damage * hit_percent) return 1 /mob/living/proc/apply_damage_type(damage = 0, damagetype = BRUTE) //like apply damage except it always uses the damage procs @@ -43,8 +41,6 @@ return adjustCloneLoss(damage) if(STAMINA) return adjustStaminaLoss(damage) - if(BRAIN) - return adjustBrainLoss(damage) /mob/living/proc/get_damage_amount(damagetype = BRUTE) switch(damagetype) @@ -60,9 +56,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) if(blocked >= 100) @@ -218,13 +211,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 701b011c..af65d317 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -255,7 +255,7 @@ H.Knockdown(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 9bbe7914..714c6df3 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -473,7 +473,6 @@ setToxLoss(0, 0) //zero as second argument not automatically call updatehealth(). setOxyLoss(0, 0) setCloneLoss(0, 0) - setBrainLoss(0) setStaminaLoss(0, 0) SetUnconscious(0, FALSE) set_disgust(0) @@ -500,6 +499,13 @@ QDEL_LIST_ASSOC_VAL(mood.mood_events) mood.sanity = SANITY_GREAT mood.update_mood() + //Heal all organs + if(iscarbon(src)) + var/mob/living/carbon/C = src + if(C.internal_organs) + for(var/organ in C.internal_organs) + var/obj/item/organ/O = organ + O.setOrganDamage(0) //proc called by revive(), to check if we can actually ressuscitate the mob (we don't want to revive him and have him instantly die again) diff --git a/code/modules/mob/living/silicon/damage_procs.dm b/code/modules/mob/living/silicon/damage_procs.dm index 1190a006..69d150b3 100644 --- a/code/modules/mob/living/silicon/damage_procs.dm +++ b/code/modules/mob/living/silicon/damage_procs.dm @@ -35,8 +35,8 @@ /mob/living/silicon/setStaminaLoss(amount, updating_stamina = 1) 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 f20ccbc7..f36e996b 100644 --- a/code/modules/mob/living/silicon/pai/pai_defense.dm +++ b/code/modules/mob/living/silicon/pai/pai_defense.dm @@ -84,7 +84,7 @@ /mob/living/silicon/pai/adjustStaminaLoss(amount) take_holo_damage(amount & 0.25) -/mob/living/silicon/pai/adjustBrainLoss(amount) +/mob/living/silicon/pai/adjustOrganLoss(slot, amount, maximum = 500) //I kept this in, unlike tg Knockdown(amount * 0.2) /mob/living/silicon/pai/getBruteLoss() @@ -102,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() return FALSE diff --git a/code/modules/mob/living/taste.dm b/code/modules/mob/living/taste.dm index 282fe0a7..8b0c5465 100644 --- a/code/modules/mob/living/taste.dm +++ b/code/modules/mob/living/taste.dm @@ -43,7 +43,7 @@ .=..() if ((from.pH > 12.5) || (from.pH < 1.5)) to_chat(src, "You taste chemical burns!") - T.adjustTongueLoss(src, 4) + T.applyOrganDamage(5) if(istype(T, /obj/item/organ/tongue/cybernetic)) to_chat(src, "Your tongue moves on it's own in response to the liquid.") say("The pH is appropriately [round(from.pH, 1)].") @@ -52,13 +52,13 @@ switch(from.pH) if(11.5 to INFINITY) to_chat(src, "You taste a strong alkaline flavour!") - T.adjustTongueLoss(src, 1) + T.applyOrganDamage(1) if(8.5 to 11.5) to_chat(src, "You taste a sort of soapy tone in the mixture.") if(2.5 to 5.5) to_chat(src, "You taste a sort of acid tone in the mixture.") if(-INFINITY to 2.5) to_chat(src, "You taste a strong acidic flavour!") - T.adjustTongueLoss(src, 1) + T.applyOrganDamage(1) #undef DEFAULT_TASTE_SENSITIVITY diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 0e62e0ae..e6f79198 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -75,7 +75,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), 0) O.adjustStaminaLoss(getStaminaLoss(), 0)//CIT CHANGE - makes monkey transformations inherit stamina O.updatehealth() O.radiation = radiation @@ -236,7 +236,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), 0) O.adjustStaminaLoss(getStaminaLoss(), 0)//CIT CHANGE - makes monkey transformations inherit stamina O.updatehealth() O.radiation = radiation diff --git a/code/modules/projectiles/projectile/special/mindflayer.dm b/code/modules/projectiles/projectile/special/mindflayer.dm index a0f9d75f..84276e72 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/holder.dm b/code/modules/reagents/chemistry/holder.dm index d1eec39f..476fc60c 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -550,6 +550,10 @@ if (multiplier == 0) fermiEnd() return + for(var/P in C.required_catalysts) + if(!has_reagent(P)) + fermiEnd() + return for(var/P in cached_results) targetVol = cached_results[P]*multiplier @@ -676,7 +680,7 @@ STOP_PROCESSING(SSprocessing, src) return 0 - C.FermiCreate(src)//proc that calls when step is done + C.FermiCreate(src, addChemAmmount, purity)//proc that calls when step is done //Apply pH changes and thermal output of reaction to beaker chem_temp = round(cached_temp + (C.ThermicConstant * addChemAmmount)) diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index 79b6f967..94aca411 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -1373,6 +1373,7 @@ All effects don't start immediately, but rather get worse over time; the rate is /datum/reagent/consumable/ethanol/neurotoxin name = "Neurotoxin" + id = "neurotoxin" description = "A strong neurotoxin that puts the subject into a death-like state." color = "#2E2E61" // rgb: 46, 46, 97 boozepwr = 50 @@ -1382,6 +1383,10 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_icon_state = "neurotoxinglass" glass_name = "Neurotoxin" glass_desc = "A drink that is guaranteed to knock you silly." + //SplitChem = TRUE + impure_chem = "neuroweak" + inverse_chem_val = 0.5 //Clear conversion + inverse_chem = "neuroweak" /datum/reagent/consumable/ethanol/neurotoxin/proc/pickt() return (pick(TRAIT_PARALYSIS_L_ARM,TRAIT_PARALYSIS_R_ARM,TRAIT_PARALYSIS_R_LEG,TRAIT_PARALYSIS_L_LEG)) @@ -1389,18 +1394,18 @@ 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) - if(prob(20)) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1*REM, 150) + if(prob(20) && !holder.has_reagent("neuroweak")) M.adjustStaminaLoss(10) M.drop_all_held_items() to_chat(M, "You cant feel your hands!") if(current_cycle > 5) - if(prob(20)) + if(prob(20) && !holder.has_reagent("neuroweak")) var/t = pickt() 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) @@ -1417,6 +1422,25 @@ All effects don't start immediately, but rather get worse over time; the rate is M.adjustStaminaLoss(10) ..() +/datum/reagent/consumable/ethanol/neuroweak + name = "Neuro-Smash" + id = "neuroweak" + description = "A mostly safe alcoholic drink for the true daredevils. Counteracts Neurotoxins." + boozepwr = 60 + pH = 8 + +/datum/reagent/consumable/ethanol/neuroweak/on_mob_life(mob/living/carbon/M) + if(holder.has_reagent("neurotoxin")) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1*REM, 150) + M.reagents.remove_reagent("neurotoxin", 1.5 * REAGENTS_METABOLISM, FALSE) + if(holder.has_reagent("fentanyl")) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1*REM, 150) + M.reagents.remove_reagent("fentanyl", 0.75 * REAGENTS_METABOLISM, FALSE) + else + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -0.5*REM, 150) + M.dizziness +=2 + ..() + /datum/reagent/consumable/ethanol/hippies_delight name = "Hippie's Delight" id = "hippiesdelight" @@ -2122,6 +2146,29 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_name = "Planet Cracker" glass_desc = "Although historians believe the drink was originally created to commemorate the end of an important conflict in man's past, its origins have largely been forgotten and it is today seen more as a general symbol of human supremacy." +/datum/reagent/consumable/ethanol/commander_and_chief + name = "Commander and Chief" + id = "commander_and_chief" + description = "A cocktail for the captain on the go." + color = "#ffffc9" + boozepwr = 50 + quality = DRINK_FANTASTIC + taste_description = "Tastes like...duty and responsibility?" + glass_icon_state = "commander_and_chief" + glass_name = "Commander and Chief" + glass_desc = "The gems of this majestic chalice represent the departments and their Heads." + +/datum/reagent/consumable/ethanol/commander_and_chief/on_mob_life(mob/living/carbon/M) + if(M.mind && HAS_TRAIT(M.mind, TRAIT_CAPTAIN_METABOLISM)) + M.heal_bodypart_damage(2,2,2) + M.adjustBruteLoss(-3.5,0) + M.adjustOxyLoss(-3.5,0) + M.adjustFireLoss(-3.5,0) + M.adjustToxLoss(-3.5,0) + M.radiation = max(M.radiation - 25, 0) + . = 1 + return ..() + /datum/reagent/consumable/ethanol/fruit_wine name = "Fruit Wine" id = "fruit_wine" diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index 5b067104..f3df72cd 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -80,14 +80,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, 0) ..() . = 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) @@ -101,7 +101,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) ..() @@ -125,13 +125,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 @@ if(jitter) M.Jitter(2) if(brain_damage) - M.adjustBrainLoss(rand(1,4)) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, rand(1,4)) M.heal_overall_damage(2, 2) if(prob(5)) M.emote(pick("twitch", "shiver")) @@ -210,7 +210,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) @@ -289,7 +289,7 @@ if(prob(5)) to_chat(M, "[high_message]") M.adjustStaminaLoss(-5, 0) - M.adjustBrainLoss(4) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 4) M.hallucination += 5 if(M.canmove && !ismovableatom(M.loc)) step(M, pick(GLOB.cardinals)) @@ -314,7 +314,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")) ..() @@ -326,7 +326,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")) ..() @@ -338,7 +338,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")) ..() @@ -351,7 +351,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")) ..() @@ -401,7 +401,7 @@ M.jitteriness = 0 M.confused = 0 M.disgust = 0 - M.adjustBrainLoss(0.2) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.2) ..() . = 1 @@ -418,7 +418,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 @@ -490,7 +490,7 @@ H.dna.species.punchdamagehigh *= 0.2 /datum/reagent/drug/skooma/on_mob_life(mob/living/carbon/M) - M.adjustBrainLoss(1*REM) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1*REM) M.adjustToxLoss(1*REM) if(prob(10)) M.adjust_blurriness(2) @@ -522,7 +522,7 @@ M.Dizzy(50) M.adjust_blurriness(10) if(prob(50)) //This proc will be called about 200 times and the adjustbrainloss() below only has to be called 40 times to kill. This will make surviving skooma addiction pretty rare without mannitol usage. - M.adjustBrainLoss(5) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5) if(prob(40)) M.emote(pick("twitch","drool","moan")) ..() diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index 19aeaeb2..cebc8f09 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -684,7 +684,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 eb7438aa..951a77b0 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -44,7 +44,7 @@ M.heal_bodypart_damage(5,5) M.adjustToxLoss(-5, 0, TRUE) M.hallucination = 0 - M.setBrainLoss(0) + M.setOrganLoss(ORGAN_SLOT_BRAIN, 0) REMOVE_TRAITS_NOT_IN(M, list(SPECIES_TRAIT, ROUNDSTART_TRAIT, ORGAN_TRAIT)) M.set_blurriness(0) M.set_blindness(0) @@ -64,6 +64,10 @@ if(M.blood_volume < (BLOOD_VOLUME_NORMAL*M.blood_ratio)) M.blood_volume = (BLOOD_VOLUME_NORMAL*M.blood_ratio) + 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) @@ -852,10 +856,16 @@ if(M.notify_ghost_cloning(source = M)) spawn (100) //so the ghost has time to re-enter return + else M.adjustOxyLoss(-20, 0) M.adjustToxLoss(-20, 0) + var/mob/living/carbon/H = M + for(var/organ in H.internal_organs) + var/obj/item/organ/O = organ + O.setOrganDamage(0) M.updatehealth() + if(M.revive()) M.emote("gasp") log_combat(M, M, "revived", src) @@ -875,7 +885,7 @@ pH = 10.4 /datum/reagent/medicine/mannitol/on_mob_life(mob/living/carbon/C) - C.adjustBrainLoss(-2*REM) + C.adjustOrganLoss(ORGAN_SLOT_BRAIN, -2*REM) if(prob(10)) C.cure_trauma_type(resilience = TRAUMA_RESILIENCE_BASIC) ..() @@ -1130,7 +1140,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) M.adjustStaminaLoss(-20*REM,0) ..() @@ -1175,9 +1185,9 @@ M.adjustFireLoss(-3 * REM, 0) M.adjustOxyLoss(-15 * REM, 0) M.adjustToxLoss(-3 * REM, 0, TRUE) //Heals TOXINLOVERS - 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.adjustStaminaLoss(-13 * REM, 0) M.jitteriness = min(max(0, M.jitteriness + 3), 30) M.druggy = min(max(0, M.druggy + 10), 15) //See above ..() @@ -1207,7 +1217,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 diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 07c9b166..95b4a33c 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -3,6 +3,7 @@ name = "Blood" id = "blood" color = "#C80000" // rgb: 200, 0, 0 + description = "Blood from a human, or otherwise." metabolization_rate = 5 //fast rate so it disappears fast. taste_description = "iron" taste_mult = 1.3 @@ -200,22 +201,20 @@ pH = 7.5 //God is alkaline /datum/reagent/water/holywater/on_mob_metabolize(mob/living/L) - ..() + . = ..() ADD_TRAIT(L, TRAIT_HOLY, id) + if(is_servant_of_ratvar(L)) + to_chat(L, "A fog spreads through your mind, purging the Justiciar's influence!") + else if(iscultist(L)) + to_chat(L, "A fog spreads through your mind, weakening your connection to the veil and purging Nar-sie's influence") + /datum/reagent/water/holywater/on_mob_end_metabolize(mob/living/L) REMOVE_TRAIT(L, TRAIT_HOLY, id) - ..() - -/datum/reagent/water/holywater/reaction_mob(mob/living/M, method=TOUCH, reac_volume) - if(is_servant_of_ratvar(M)) - to_chat(M, "A fog spreads through your mind, purging the Justiciar's influence!") - ..() - -/datum/reagent/water/holywater/reaction_mob(mob/living/M, method=TOUCH, reac_volume) - if(iscultist(M)) - to_chat(M, "A fog spreads through your mind, weakening your connection to the veil and purging Nar-sie's influence") - ..() + if(iscultist(L)) + for(var/datum/action/innate/cult/blood_magic/BM in L.actions) + BM.holy_dispel = FALSE + return ..() /datum/reagent/water/holywater/on_mob_life(mob/living/carbon/M) if(!data) @@ -224,9 +223,11 @@ M.jitteriness = min(M.jitteriness+4,10) if(iscultist(M)) for(var/datum/action/innate/cult/blood_magic/BM in M.actions) - to_chat(M, "Your blood rites falter as holy water scours your body!") - for(var/datum/action/innate/cult/blood_spell/BS in BM.spells) - qdel(BS) + if(!BM.holy_dispel) + BM.holy_dispel = TRUE + to_chat(M, "Your blood rites falter as holy water scours your body!") + for(var/datum/action/innate/cult/blood_spell/BS in BM.spells) + qdel(BS) if(data >= 25) // 10 units, 45 seconds @ metabolism 0.4 units & tick rate 1.8 sec if(!M.stuttering) M.stuttering = 1 @@ -296,7 +297,7 @@ if(ishuman(M) && M.blood_volume < (BLOOD_VOLUME_NORMAL*M.blood_ratio)) 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) @@ -315,7 +316,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(id, 1) pH = 0.1 @@ -536,12 +537,12 @@ race = /datum/species/fly mutationtext = "The pain subsides. You feel... buzzy." -/datum/reagent/mutationtoxin/moth - name = "Moth Mutation Toxin" +/datum/reagent/mutationtoxin/insect + name = "Insect Mutation Toxin" id = "mothmutationtoxin" description = "A glowing toxin." color = "#5EFF3B" //RGB: 94, 255, 59 - race = /datum/species/moth + race = /datum/species/insect mutationtext = "The pain subsides. You feel... attracted to light." /datum/reagent/mutationtoxin/pod @@ -805,7 +806,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 @@ -1172,7 +1173,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)) @@ -1222,7 +1223,7 @@ description = "A perfluoronated sulfonic acid that forms a foam when mixed with water." color = "#9E6B38" // rgb: 158, 107, 56 taste_description = "metal" - pH = 13 + pH = 11 /datum/reagent/foaming_agent// Metal foaming agent. This is lithium hydride. Add other recipes (e.g. LiH + H2O -> LiOH + H2) eventually. name = "Foaming agent" @@ -1231,7 +1232,7 @@ reagent_state = SOLID color = "#664B63" // rgb: 102, 75, 99 taste_description = "metal" - pH = 12.5 + pH = 11.5 /datum/reagent/smart_foaming_agent //Smart foaming agent. Functions similarly to metal foam, but conforms to walls. name = "Smart foaming agent" @@ -1445,9 +1446,6 @@ color = "#FFFFFF" // white random_color_list = list("#FFFFFF") //doesn't actually change appearance at all - - - //////////////////////////////////Hydroponics stuff/////////////////////////////// /datum/reagent/plantnutriment @@ -1489,16 +1487,8 @@ tox_prob = 15 pH = 1 - - - - - - // GOON OTHERS - - /datum/reagent/oil name = "Oil" id = "oil" @@ -1530,20 +1520,6 @@ taste_description = "metal" pH = 4.5 -/datum/reagent/carpet - name = "Carpet" - id = "carpet" - description = "For those that need a more creative way to roll out a red carpet." - reagent_state = LIQUID - color = "#b51d05" - taste_description = "carpet" // Your tounge feels furry. - -/datum/reagent/carpet/reaction_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(/turf/open/floor/carpet) - ..() - /datum/reagent/bromine name = "Bromine" id = "bromine" @@ -1676,7 +1652,7 @@ reagent_state = LIQUID color = "#FFFFD6" // very very light yellow taste_description = "alkali" //who put ACID for NaOH ???? - pH = 13 + pH = 11.9 /datum/reagent/drying_agent name = "Drying agent" @@ -1697,6 +1673,143 @@ qdel(O) new /obj/item/clothing/shoes/galoshes/dry(t_loc) +// Liquid Carpets +/datum/reagent/carpet + name = "Liquid Carpet" + id = "carpet" + description = "For those that need a more creative way to roll out a carpet." + reagent_state = LIQUID + color = "#b51d05" + taste_description = "carpet" // Your tounge feels furry. + +/datum/reagent/carpet/reaction_turf(turf/T, reac_volume) + if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) + var/turf/open/floor/F = T + F.PlaceOnTop(/turf/open/floor/carpet) + ..() + +/datum/reagent/carpet/black + name = "Liquid Black Carpet" + id = "blackcarpet" + color = "#363636" + +/datum/reagent/carpet/black/reaction_turf(turf/T, reac_volume) + if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) + var/turf/open/floor/F = T + F.PlaceOnTop(/turf/open/floor/carpet/black) + ..() + +/datum/reagent/carpet/blackred + name = "Liquid Red Black Carpet" + id = "blackredcarpet" + color = "#342125" + +/datum/reagent/carpet/blackred/reaction_turf(turf/T, reac_volume) + if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) + var/turf/open/floor/F = T + F.PlaceOnTop(/turf/open/floor/carpet/blackred) + ..() + +/datum/reagent/carpet/monochrome + name = "Liquid Monochrome Carpet" + id = "monochromecarpet" + color = "#b4b4b4" + +/datum/reagent/carpet/monochrome/reaction_turf(turf/T, reac_volume) + if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) + var/turf/open/floor/F = T + F.PlaceOnTop(/turf/open/floor/carpet/monochrome) + ..() + +/datum/reagent/carpet/blue + name = "Liquid Blue Carpet" + id = "bluecarpet" + color = "#1256ff" + +/datum/reagent/carpet/blue/reaction_turf(turf/T, reac_volume) + if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) + var/turf/open/floor/F = T + F.PlaceOnTop(/turf/open/floor/carpet/blue) + ..() + +/datum/reagent/carpet/cyan + name = "Liquid Cyan Carpet" + id = "cyancarpet" + color = "#3acfb9" + +/datum/reagent/carpet/cyan/reaction_turf(turf/T, reac_volume) + if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) + var/turf/open/floor/F = T + F.PlaceOnTop(/turf/open/floor/carpet/cyan) + ..() + +/datum/reagent/carpet/green + name = "Liquid Green Carpet" + id = "greencarpet" + color = "#619b62" + +/datum/reagent/carpet/green/reaction_turf(turf/T, reac_volume) + if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) + var/turf/open/floor/F = T + F.PlaceOnTop(/turf/open/floor/carpet/green) + ..() + +/datum/reagent/carpet/orange + name = "Liquid Orange Carpet" + id = "orangecarpet" + color = "#cc7900" + +/datum/reagent/carpet/orange/reaction_turf(turf/T, reac_volume) + if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) + var/turf/open/floor/F = T + F.PlaceOnTop(/turf/open/floor/carpet/orange) + ..() + +/datum/reagent/carpet/purple + name = "Liquid Purple Carpet" + id = "purplecarpet" + color = "#6d3392" + +/datum/reagent/carpet/purple/reaction_turf(turf/T, reac_volume) + if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) + var/turf/open/floor/F = T + F.PlaceOnTop(/turf/open/floor/carpet/purple) + ..() + +/datum/reagent/carpet/red + name = "Liquid Red Carpet" + id = "redcarpet" + color = "#871515" + +/datum/reagent/carpet/red/reaction_turf(turf/T, reac_volume) + if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) + var/turf/open/floor/F = T + F.PlaceOnTop(/turf/open/floor/carpet/red) + ..() + +/datum/reagent/carpet/royalblack + name = "Liquid Royal Black Carpet" + id = "royalblackcarpet" + color = "#483d05" + +/datum/reagent/carpet/royalblack/reaction_turf(turf/T, reac_volume) + if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) + var/turf/open/floor/F = T + F.PlaceOnTop(/turf/open/floor/carpet/royalblack) + ..() + +/datum/reagent/carpet/royalblue + name = "Liquid Royal Blue Carpet" + id = "royalbluecarpet" + color = "#24227e" + +/datum/reagent/carpet/royalblue/reaction_turf(turf/T, reac_volume) + if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) + var/turf/open/floor/F = T + F.PlaceOnTop(/turf/open/floor/carpet/royalblue) + ..() + + // Virology virus food chems. /datum/reagent/toxin/mutagen/mutagenvirusfood @@ -2003,7 +2116,7 @@ can_synth = FALSE var/datum/dna/original_dna var/reagent_ticks = 0 - invisible = TRUE + chemical_flags = REAGENT_INVISIBLE /datum/reagent/changeling_string/on_mob_metabolize(mob/living/carbon/C) if(C && C.dna && data["desired_dna"]) @@ -2031,3 +2144,25 @@ /datum/reagent/changeling_string/Destroy() qdel(original_dna) return ..() + +/datum/reagent/mustardgrind + name = "Mustardgrind" + id = "mustardgrind" + description = "A powerd that is mixed with water and enzymes to make mustard." + color = "#BCC740" //RGB: 188, 199, 64 + taste_description = "plant dust" + +/datum/reagent/pax/catnip + name = "catnip" + id = "catnip" + taste_description = "grass" + description = "A colorless liquid that makes people more peaceful and felines more happy." + metabolization_rate = 1.75 * REAGENTS_METABOLISM + +/datum/reagent/pax/catnip/on_mob_life(mob/living/carbon/M) + if(prob(20)) + M.emote("nya") + if(prob(20)) + to_chat(M, "[pick("Headpats feel nice.", "The feeling of a hairball...", "Backrubs would be nice.", "Whats behind those doors?")]") + M.adjustArousalLoss(2) + ..() diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 2848c336..2b50ecc0 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -313,25 +313,6 @@ . = 1 ..() -/datum/reagent/toxin/chloralhydratedelayed //sedates half as quickly and does not cause toxloss. same name/desc so it doesn't give away sleepypens - name = "Chloral Hydrate" - id = "chloralhydratedelayed" - description = "A powerful sedative that induces confusion and drowsiness before putting its target to sleep." - reagent_state = SOLID - color = "#000067" // rgb: 0, 0, 103 - toxpwr = 0 - metabolization_rate = 1 * REAGENTS_METABOLISM - -/datum/reagent/toxin/chloralhydratedelayed/on_mob_life(mob/living/carbon/M) - switch(current_cycle) - if(10 to 20) - M.confused += 1 - M.drowsyness += 1 - M.adjustStaminaLoss(7.5) - if(20 to INFINITY) - M.Sleeping(40, 0) - ..() - /datum/reagent/toxin/fakebeer //disguised as normal beer for use by emagged brobots name = "Beer" id = "fakebeer" @@ -389,12 +370,12 @@ id = "tirizene" description = "A nonlethal poison that causes extreme fatigue and weakness in its victim." color = "#6E2828" - data = 13 + data = 15 toxpwr = 0 /datum/reagent/toxin/staminatoxin/on_mob_life(mob/living/carbon/M) M.adjustStaminaLoss(REM * data, 0) - data = max(data - 1, 3) + data = max(data - 1, 5) ..() . = 1 @@ -490,7 +471,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 >= 18) @@ -969,3 +950,20 @@ to_chat(M, "Your missing arm aches from wherever you left it.") M.emote("sigh") return ..() + +/datum/reagent/toxin/brainhurtingjuice //oof ouch + name = "Brain Hurting Juice" + id = "brainhurtingjuice" + color = "#AAAAAA77" //RGBA: 170, 170, 170, 77 + toxpwr = 0 + taste_description = "brain hurting" + metabolization_rate = 5 + +/datum/reagent/toxin/brainhurtingjuice/on_mob_life(mob/living/carbon/M) + if(prob(50)) + M.gain_trauma_type(BRAIN_TRAUMA_MILD) + else if(prob(50)) + M.gain_trauma_type(BRAIN_TRAUMA_SEVERE) + else + M.gain_trauma_type(BRAIN_TRAUMA_SPECIAL) + ..() diff --git a/code/modules/reagents/chemistry/recipes/medicine.dm b/code/modules/reagents/chemistry/recipes/medicine.dm index 59865dd1..11dd8b74 100644 --- a/code/modules/reagents/chemistry/recipes/medicine.dm +++ b/code/modules/reagents/chemistry/recipes/medicine.dm @@ -68,6 +68,42 @@ results = list("synthflesh" = 3) required_reagents = list("blood" = 1, "carbon" = 1, "styptic_powder" = 1) +/datum/chemical_reaction/synthtissue + name = "Synthtissue" + id = "synthtissue" + results = list("synthtissue" = 0.05) + required_reagents = list("synthflesh" = 0.01) + required_catalysts = list("nutriment" = 0.1) + //FermiChem vars: + OptimalTempMin = 305 // Lower area of bell curve for determining heat based rate reactions + OptimalTempMax = 315 // Upper end for above + ExplodeTemp = 1050 // Temperature at which reaction explodes + OptimalpHMin = 8.5 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase) + OptimalpHMax = 9.5 // Higest value for above + ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase) + CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) + CurveSharpT = 1 // How sharp the temperature exponential curve is (to the power of value) + CurveSharppH = 2.5 // How sharp the pH exponential curve is (to the power of value) + ThermicConstant = 0.01 // Temperature change per 1u produced + HIonRelease = 0.015 // pH change per 1u reaction (inverse for some reason) + RateUpLim = 0.05 // Optimal/max rate possible if all conditions are perfect + FermiChem = TRUE // If the chemical uses the Fermichem reaction mechanics + PurityMin = 0 + +/datum/chemical_reaction/synthtissue/FermiCreate(datum/reagents/holder, added_volume, added_purity) + var/datum/reagent/synthtissue/St = holder.has_reagent("synthtissue") + var/datum/reagent/N = holder.has_reagent("nutriment") + if(!St) + return + if(holder.chem_temp > 320) + var/temp_ratio = 1-(330 - holder.chem_temp)/10 + holder.remove_reagent(src.id, added_volume*temp_ratio) + if(St.purity < 1) + St.volume *= St.purity + St.purity = 1 + N.volume -= 0.002 + St.data["grown_volume"] = St.data["grown_volume"] + added_volume + /datum/chemical_reaction/styptic_powder name = "Styptic Powder" id = "styptic_powder" diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 0cd18e12..ee4e9eb6 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -534,6 +534,17 @@ category = list("Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL +/datum/design/cybernetic_heart_u + name = "Upgraded Cybernetic Heart" + desc = "An upgraded cybernetic heart" + id = "cybernetic_heart_u" + build_type = PROTOLATHE | MECHFAB + construction_time = 50 + materials = list(MAT_METAL = 500, MAT_GLASS = 500, MAT_SILVER = 500) + build_path = /obj/item/organ/heart/cybernetic/upgraded + category = list("Misc", "Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL + /datum/design/cybernetic_liver_u name = "Upgraded Cybernetic Liver" desc = "An upgraded cybernetic liver" @@ -712,6 +723,28 @@ category = list("Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL +/datum/design/cybernetic_ears + name = "Cybernetic Ears" + desc = "A pair of cybernetic ears." + id = "cybernetic_ears" + build_type = PROTOLATHE | MECHFAB + construction_time = 30 + materials = list(MAT_METAL = 250, MAT_GLASS = 400) + build_path = /obj/item/organ/ears/cybernetic + category = list("Misc", "Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL + +/datum/design/cybernetic_ears_u + name = "Upgraded Cybernetic Ears" + desc = "A pair of upgraded cybernetic ears." + id = "cybernetic_ears_u" + build_type = PROTOLATHE | MECHFAB + construction_time = 40 + materials = list(MAT_METAL = 500, MAT_GLASS = 500, MAT_SILVER = 500) + build_path = /obj/item/organ/ears/cybernetic/upgraded + category = list("Misc", "Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL + ///////////////////// ///Surgery Designs/// ///////////////////// diff --git a/code/modules/research/nanites/nanite_programs/healing.dm b/code/modules/research/nanites/nanite_programs/healing.dm index 8aab7f1e..1113f11e 100644 --- a/code/modules/research/nanites/nanite_programs/healing.dm +++ b/code/modules/research/nanites/nanite_programs/healing.dm @@ -72,14 +72,16 @@ /datum/nanite_program/brain_heal/check_conditions() if(iscarbon(host_mob)) var/mob/living/carbon/C = host_mob - if(length(C.get_traumas())) - return ..() - if(host_mob.getBrainLoss()) + for(var/X in C.get_traumas()) + var/datum/brain_trauma/BT = X + if(BT.resilience <= TRAUMA_RESILIENCE_BASIC) + return ..() + if(host_mob.getOrganLoss(ORGAN_SLOT_BRAIN)) return ..() return FALSE /datum/nanite_program/brain_heal/active_effect() - host_mob.adjustBrainLoss(-1, TRUE) + host_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1, TRUE) if(iscarbon(host_mob) && prob(10)) var/mob/living/carbon/C = host_mob C.cure_trauma_type(resilience = TRAUMA_RESILIENCE_BASIC) @@ -193,14 +195,16 @@ /datum/nanite_program/brain_heal_advanced/check_conditions() if(iscarbon(host_mob)) var/mob/living/carbon/C = host_mob - if(length(C.get_traumas())) - return ..() - if(host_mob.getBrainLoss()) + for(var/X in C.get_traumas()) + var/datum/brain_trauma/BT = X + if(BT.resilience <= TRAUMA_RESILIENCE_LOBOTOMY) + return ..() + if(host_mob.getOrganLoss(ORGAN_SLOT_BRAIN)) return ..() return FALSE - + /datum/nanite_program/brain_heal_advanced/active_effect() - host_mob.adjustBrainLoss(-2, TRUE) + host_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, -2, TRUE) if(iscarbon(host_mob) && prob(10)) var/mob/living/carbon/C = host_mob C.cure_trauma_type(resilience = TRAUMA_RESILIENCE_LOBOTOMY) @@ -232,7 +236,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.damaged_brain) + if(QDELETED(BR) || BR.brain_death || (BR.organ_flags & ORGAN_FAILING) || C.suiciding) return FALSE if(C.get_ghost()) return FALSE @@ -252,7 +256,7 @@ 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) + C.adjustOrganLoss(ORGAN_SLOT_BRAIN, 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 f64c7e87..287aed36 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/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 389a5650..e351c8fb 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -526,10 +526,18 @@ display_name = "Cybernetic Organs" description = "We have the technology to rebuild him." prereq_ids = list("adv_biotech") - design_ids = list("cybernetic_heart", "cybernetic_liver", "cybernetic_liver_u", "cybernetic_lungs", "cybernetic_lungs_u", "cybernetic_tongue") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + design_ids = list("cybernetic_ears", "cybernetic_heart", "cybernetic_liver", "cybernetic_lungs", "cybernetic_tongue") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) export_price = 5000 +/datum/techweb_node/cyber_organs_upgraded + id = "cyber_organs_upgraded" + display_name = "Upgraded Cybernetic Organs" + description = "We have the technology to upgrade him." + prereq_ids = list("cyber_organs") + design_ids = list("cybernetic_ears_u", "cybernetic_heart_u", "cybernetic_liver_u", "cybernetic_lungs_u") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) + /datum/techweb_node/cyber_implants id = "cyber_implants" display_name = "Cybernetic Implants" diff --git a/code/modules/research/xenobiology/crossbreeding/consuming.dm b/code/modules/research/xenobiology/crossbreeding/consuming.dm index 0b2d60da..d6536f4f 100644 --- a/code/modules/research/xenobiology/crossbreeding/consuming.dm +++ b/code/modules/research/xenobiology/crossbreeding/consuming.dm @@ -119,7 +119,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 730a9121..a2b50d9b 100644 --- a/code/modules/surgery/advanced/brainwashing.dm +++ b/code/modules/surgery/advanced/brainwashing.dm @@ -12,7 +12,7 @@ /datum/surgery_step/clamp_bleeders, /datum/surgery_step/brainwash, /datum/surgery_step/close) - + species = list(/mob/living/carbon/human) possible_locs = list(BODY_ZONE_HEAD) /datum/surgery/advanced/brainwashing/can_start(mob/user, mob/living/carbon/target) @@ -56,7 +56,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 diff --git a/code/modules/surgery/advanced/lobotomy.dm b/code/modules/surgery/advanced/lobotomy.dm index 1c09f5f7..12c5e4da 100644 --- a/code/modules/surgery/advanced/lobotomy.dm +++ b/code/modules/surgery/advanced/lobotomy.dm @@ -51,11 +51,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 01c30f17..b31a7518 100644 --- a/code/modules/surgery/advanced/revival.dm +++ b/code/modules/surgery/advanced/revival.dm @@ -63,7 +63,7 @@ user.visible_message("...[target] wakes up, alive and aware!", "IT'S ALIVE!") 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 user.visible_message("...[target.p_they()] convulses, then lies still.") @@ -75,5 +75,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, 199) return FALSE diff --git a/code/modules/surgery/brain_surgery.dm b/code/modules/surgery/brain_surgery.dm index e6527157..c553d054 100644 --- a/code/modules/surgery/brain_surgery.dm +++ b/code/modules/surgery/brain_surgery.dm @@ -31,7 +31,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 @@ -40,7 +40,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 00000000..3e36e9aa --- /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 \ No newline at end of file diff --git a/code/modules/surgery/eye_surgery.dm b/code/modules/surgery/eye_surgery.dm index 6dcda5e0..16bbceb9 100644 --- a/code/modules/surgery/eye_surgery.dm +++ b/code/modules/surgery/eye_surgery.dm @@ -37,7 +37,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/graft_synthtissue.dm b/code/modules/surgery/graft_synthtissue.dm new file mode 100644 index 00000000..8826de71 --- /dev/null +++ b/code/modules/surgery/graft_synthtissue.dm @@ -0,0 +1,70 @@ +//Organ reconstruction, limited to the chest region as most organs in the head have their own repair method (eyes/brain). We require synthflesh for these +//steps since fixing internal organs aren't as simple as mending exterior flesh, though in the future it would be neat to add more chems to the viable list. +//TBD: Add heart damage, have heart reconstruction seperate from organ reconstruction, and find a better name for this. I can imagine people getting it confused with manipulation. + +/datum/surgery/graft_synthtissue + name = "Graft synthtissue" + species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN, BODY_ZONE_PRECISE_EYES) + steps = list( + /datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/saw, + /datum/surgery_step/clamp_bleeders, + /datum/surgery_step/incise, + /datum/surgery_step/graft_synthtissue, + /datum/surgery_step/close + ) + +//repair organs +/datum/surgery_step/graft_synthtissue + name = "graft synthtissue" + implements = list(/obj/item/hemostat = 100, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15) + repeatable = TRUE + time = 75 + chems_needed = list("synthtissue") + var/obj/item/organ/chosen_organ + var/health_restored = 10 + +/datum/surgery_step/graft_synthtissue/preop(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) + if(implement_type in implements) + var/list/organs = target.getorganszone(target_zone) + if(!organs.len) + to_chat(user, "There are no targetable organs in [target]'s [parse_zone(target_zone)]!") + return -1 + else + for(var/obj/item/organ/O in organs) + O.on_find(user) + organs -= O + organs[O.name] = O + chosen_organ = input("Target which organ?", "Surgery", null, null) as null|anything in organs + chosen_organ = organs[chosen_organ] + if(!chosen_organ) + return -1 + if(!target.reagents.has_reagent("synthtissue")) + to_chat(user, "There's no synthtissue available for use on [chosen_organ]") + return -1 + var/datum/reagent/synthtissue/Sf = locate(/datum/reagent/synthtissue) in target.reagents.reagent_list + if(Sf.volume < 10) + to_chat(user, "There's not enough synthtissue to perform the operation! There needs to be at least 10u.") + return -1 + + if((chosen_organ.organ_flags & ORGAN_FAILING) && !(Sf.data["grown_volume"] >= 115)) + to_chat(user, "[chosen_organ] is too damaged to graft onto!") + return -1 + + if(health_restored != 10) + health_restored = 10 + health_restored += (Sf.data["grown_volume"]/10) + + user.visible_message("[user] begins to graft synthtissue onto [chosen_organ].") + target.reagents.remove_reagent("synthtissue", 10) + +/datum/surgery_step/graft_synthtissue/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] successfully repairs part of [chosen_organ].", "You succeed in repairing parts of [chosen_organ].") + chosen_organ.applyOrganDamage(health_restored) + +/datum/surgery_step/graft_synthtissue/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] accidentally damages part of [chosen_organ]!", "You damage [chosen_organ]! Apply more synthtissue if it's run out.") + chosen_organ.applyOrganDamage(10) + return FALSE diff --git a/code/modules/surgery/lobectomy.dm b/code/modules/surgery/lobectomy.dm new file mode 100644 index 00000000..7d8b8a53 --- /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 \ No newline at end of file diff --git a/code/modules/surgery/organs/appendix.dm b/code/modules/surgery/organs/appendix.dm index 34a7e16e..fcb0427b 100644 --- a/code/modules/surgery/organs/appendix.dm +++ b/code/modules/surgery/organs/appendix.dm @@ -3,7 +3,23 @@ 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/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/update_icon() if(inflamed) @@ -16,7 +32,7 @@ /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 33e62d21..44864dd9 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(crit_fail || (!holder && !contents.len)) + if(crit_fail || (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 && !crit_fail) + 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) @@ -154,6 +154,7 @@ owner.IgniteMob() owner.adjustFireLoss(25) crit_fail = 1 + 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 ea336bea..7156b818 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(crit_fail) + if(crit_fail || (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 06d52372..114b92f1 100644 --- a/code/modules/surgery/organs/augments_internal.dm +++ b/code/modules/surgery/organs/augments_internal.dm @@ -4,6 +4,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. @@ -102,7 +103,7 @@ /obj/item/organ/cyberimp/brain/anti_stun/on_life() ..() - if(crit_fail) + if(crit_fail || !(organ_flags & ORGAN_FAILING)) return owner.adjustStaminaLoss(-3.5) //Citadel edit, makes it more useful in Stamina based combat if(owner.AmountStun() > STUN_SET_AMOUNT) @@ -112,13 +113,15 @@ /obj/item/organ/cyberimp/brain/anti_stun/emp_act(severity) . = ..() - if(crit_fail || . & EMP_PROTECT_SELF) + if(crit_fail || (organ_flags & ORGAN_FAILING) || . & EMP_PROTECT_SELF) return crit_fail = TRUE + organ_flags |= ORGAN_FAILING addtimer(CALLBACK(src, .proc/reboot), 90 / severity) /obj/item/organ/cyberimp/brain/anti_stun/proc/reboot() crit_fail = FALSE + organ_flags &= ~ORGAN_FAILING //[[[[MOUTH]]]] diff --git a/code/modules/surgery/organs/ears.dm b/code/modules/surgery/organs/ears.dm index 8e191a41..0d300291 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 @@ -23,17 +31,26 @@ /obj/item/organ/ears/on_life() if(!iscarbon(owner)) return + ..() var/mob/living/carbon/C = owner + 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(ear_damage < UNHEALING_EAR_DAMAGE) // if higher than UNHEALING_EAR_DAMAGE, no natural healing occurs. - ear_damage = max(ear_damage - 0.05, 0) + 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 ear_damage = 0 + organ_flags &= ~ORGAN_FAILING var/mob/living/carbon/C = owner @@ -99,4 +116,23 @@ name = "tin ears" desc = "The robust ears of a bronze golem. " damage_multiplier = 0.1 //STRONK - bang_protect = 1 //Fear me weaklings. + bang_protect = 1 //Fear me weaklings. + +/obj/item/organ/ears/cybernetic + name = "cybernetic ears" + icon_state = "ears-c" + desc = "a basic cybernetic designed to mimic the operation of ears." + damage_multiplier = 0.9 + organ_flags = ORGAN_SYNTHETIC + +/obj/item/organ/ears/cybernetic/upgraded + name = "upgraded cybernetic ears" + icon_state = "ears-c-u" + desc = "an advanced cybernetic ear, surpassing the performance of organic ears" + damage_multiplier = 0.5 + +/obj/item/organ/ears/cybernetic/emp_act(severity) + . = ..() + if(. & EMP_PROTECT_SELF) + return + damage += 40/severity diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index eeaaaf2a..95258c70 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.15 * STANDARD_ORGAN_THRESHOLD //threshold at 15 + + 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/eye_damage = 0 @@ -15,9 +28,12 @@ var/flash_protect = 0 var/see_invisible = SEE_INVISIBLE_LIVING var/lighting_alpha + var/damaged = FALSE //damaged indicates that our eyes are undergoing some level of negative effect /obj/item/organ/eyes/Insert(mob/living/carbon/M, special = FALSE, drop_if_replaced = FALSE) ..() + if(damage == initial(damage)) + clear_eye_trauma() if(ishuman(owner)) var/mob/living/carbon/human/HMN = owner old_eye_color = HMN.eye_color @@ -32,7 +48,9 @@ M.update_tint() owner.update_sight() + /obj/item/organ/eyes/Remove(mob/living/carbon/M, special = 0) + clear_eye_trauma() ..() if(ishuman(M) && eye_color) var/mob/living/carbon/human/HMN = M @@ -41,6 +59,34 @@ 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((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(organ_flags & ORGAN_FAILING) + C.become_blind(EYE_DAMAGE) + else if(damage > 30) + C.overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 2) + else + C.overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 1) + //called once since we don't want to keep clearing the screen of eye damage for people who are below 20 damage + else if(damaged) + damaged = FALSE + C.clear_fullscreen("eye_damage") + return + +/obj/item/organ/eyes/proc/clear_eye_trauma() + var/mob/living/carbon/C = owner + C.clear_fullscreen("eye_damage") + C.cure_blind(EYE_DAMAGE) + damaged = FALSE + /obj/item/organ/eyes/night_vision name = "shadow eyes" desc = "A spooky set of eyes that can see in the dark." @@ -71,6 +117,7 @@ /obj/item/organ/eyes/night_vision/zombie name = "undead eyes" desc = "Somewhat counterintuitively, these half-rotten eyes actually have superior vision to those of a living human." + sight_flags = SEE_MOBS /obj/item/organ/eyes/night_vision/nightmare name = "burning red eyes" @@ -88,15 +135,17 @@ icon_state = "cybernetic_eyeballs" desc = "Your vision is augmented." status = ORGAN_ROBOTIC + organ_flags = ORGAN_SYNTHETIC /obj/item/organ/eyes/robotic/emp_act(severity) . = ..() if(!owner || . & EMP_PROTECT_SELF) return - if(prob(10 * severity)) - return to_chat(owner, "Static obfuscates your vision!") owner.flash_act(visual = 1) + if(severity == EMP_HEAVY) + owner.adjustOrganLoss(ORGAN_SLOT_EYES, 20) + /obj/item/organ/eyes/robotic/xray name = "\improper X-ray eyes" @@ -137,7 +186,7 @@ M.become_blind("flashlight_eyes") -/obj/item/organ/eyes/robotic/flashlight/Remove(var/mob/living/carbon/M, var/special = 0) +/obj/item/organ/eyes/robotic/flashlight/Remove(var/mob/living/carbon/M, special = FALSE) eye.on = FALSE eye.update_brightness(M) eye.forceMove(src) @@ -321,7 +370,7 @@ if(!istype(parent)) return INITIALIZE_HINT_QDEL -/obj/item/organ/eyes/moth - name = "moth eyes" +/obj/item/organ/eyes/insect + name = "insect eyes" desc = "These eyes seem to have increased sensitivity to bright light, with no improvement to low light vision." flash_protect = -1 diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm index 5852cba0..5fea801b 100644 --- a/code/modules/surgery/organs/heart.dm +++ b/code/modules/surgery/organs/heart.dm @@ -4,12 +4,24 @@ icon_state = "heart-on" zone = BODY_ZONE_CHEST slot = ORGAN_SLOT_HEART + + healing_factor = STANDARD_ORGAN_HEALING + decay_factor = 4 * 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) icon_state = "[icon_base]-on" @@ -50,6 +62,7 @@ /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 @@ -70,11 +83,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 @@ -153,18 +173,48 @@ name = "cybernetic heart" desc = "An electronic device designed to mimic the functions of an organic human heart. Offers no benefit over an organic heart other than being easy to make." icon_state = "heart-c" - synthetic = TRUE + organ_flags = ORGAN_SYNTHETIC -/obj/item/organ/heart/cybernetic/emp_act() +/obj/item/organ/heart/cybernetic/emp_act(severity) . = ..() if(. & EMP_PROTECT_SELF) return Stop() + addtimer(CALLBACK(src, .proc/Restart), 20/severity SECONDS) + damage += 100/severity + +/obj/item/organ/heart/cybernetic/upgraded + name = "upgraded 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. This upgraded model can regenerate its dose after use." + icon_state = "heart-c-u" + maxHealth = 2 * STANDARD_ORGAN_THRESHOLD + + //I put it on upgraded for now. + var/dose_available = TRUE + var/rid = /datum/reagent/medicine/epinephrine + var/ramount = 10 + +obj/item/organ/heart/cybernetic/upgraded/on_life() + . = ..() + if(dose_available && owner.health <= owner.crit_threshold && !owner.reagents.has_reagent(rid)) + owner.reagents.add_reagent(rid, ramount) + used_dose() + if(ramount < 10) //eats your nutrition to regen epinephrine + var/regen_amount = owner.nutrition/2000 + owner.nutrition -= regen_amount + ramount += regen_amount + +/obj/item/organ/heart/cybernetic/upgraded/proc/used_dose() + . = ..() + addtimer(VARSET_CALLBACK(src, dose_available, TRUE), 5 MINUTES) + ramount = 0 + + /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 20b0462b..bfffe9b6 100644 --- a/code/modules/surgery/organs/liver.dm +++ b/code/modules/surgery/organs/liver.dm @@ -10,10 +10,13 @@ zone = BODY_ZONE_CHEST slot = ORGAN_SLOT_LIVER desc = "Pairing suggestion: chianti and fava beans." - var/damage = 0 //liver damage, 0 is no damage, damage=maxHealth causes liver failure + + 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/failing //is this liver failing? - var/maxHealth = LIVER_DEFAULT_HEALTH 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 @@ -24,7 +27,7 @@ var/mob/living/carbon/C = owner 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 //slowly heal liver damage damage = max(0, damage - 0.1) @@ -69,7 +72,7 @@ if(moveCalc == cachedmoveCalc)//reduce calculations return if(prob(5)) - to_chat(owner, "You feel a stange ache in your side, almost like a sitch. This pain is affecting your movements and making you feel lightheaded.") + to_chat(owner, "You feel a stange ache in your side, almost like a stitch. This pain is affecting your movements and making you feel lightheaded.") var/mob/living/carbon/human/H = owner H.add_movespeed_modifier(LIVER_SWELLING_MOVE_MODIFY, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc) H.AdjustBloodVol(moveCalc/3) @@ -97,14 +100,15 @@ name = "cybernetic liver" icon_state = "liver-c" desc = "An electronic device designed to mimic the functions of a human liver. It has no benefits over an organic liver, but is easy to produce." - synthetic = TRUE + organ_flags = ORGAN_SYNTHETIC + maxHealth = 1.1 * STANDARD_ORGAN_THRESHOLD /obj/item/organ/liver/cybernetic/upgraded name = "upgraded cybernetic liver" icon_state = "liver-c-u" desc = "An upgraded version of the cybernetic liver, designed to improve 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 cfbb530e..f3eaba1a 100644 --- a/code/modules/surgery/organs/lungs.dm +++ b/code/modules/surgery/organs/lungs.dm @@ -8,6 +8,19 @@ gender = PLURAL w_class = WEIGHT_CLASS_NORMAL + var/failed = FALSE + var/operated = FALSE //whether we can still have our damages fixed through surgery + + //health + maxHealth = LUNGS_MAX_HEALTH + + 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 @@ -56,36 +69,35 @@ var/crit_stabilizing_reagent = "epinephrine" - //health - var/maxHealth = LUNGS_MAX_HEALTH - var/damage = 0 + //TODO: lung health affects lung function -/obj/item/organ/lungs/proc/adjustLungLoss(damage_mod, mob/living/carbon/M) //damage might be too low atm. +/obj/item/organ/lungs/onDamage(damage_mod) //damage might be too low atm. + var/cached_damage = damage if (maxHealth == INFINITY) return - if(damage+damage_mod < 0) - damage = 0 + if(cached_damage+damage_mod < 0) + cached_damage = 0 return - damage += damage_mod - if ((damage / maxHealth) > 1) - to_chat(M, "You feel your lungs collapse within your chest as you gasp for air, unable to inflate them anymore!") - M.emote("gasp") + cached_damage += damage_mod + if ((cached_damage/ maxHealth) > 1) + to_chat(owner, "You feel your lungs collapse within your chest as you gasp for air, unable to inflate them anymore!") + owner.emote("gasp") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Lungs lost") - qdel(src) - else if ((damage / maxHealth) > 0.75) - to_chat(M, "It's getting really hard to breathe!!") - M.emote("gasp") - M.Dizzy(3) - else if ((damage / maxHealth) > 0.5) - M.Dizzy(2) - to_chat(M, "Your chest is really starting to hurt.") - M.emote("cough") - else if ((damage / maxHealth) > 0.2) - to_chat(M, "You feel an ache within your chest.") - M.emote("cough") - M.Dizzy(1) + //qdel(src) - Handled elsewhere for now. + else if ((cached_damage / maxHealth) > 0.75) + to_chat(owner, "It's getting really hard to breathe!!") + owner.emote("gasp") + owner.Dizzy(3) + else if ((cached_damage / maxHealth) > 0.5) + owner.Dizzy(2) + to_chat(owner, "Your chest is really starting to hurt.") + owner.emote("cough") + else if ((cached_damage / maxHealth) > 0.2) + to_chat(owner, "You feel an ache within your chest.") + owner.emote("cough") + owner.Dizzy(1) /obj/item/organ/lungs/proc/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/H) //TODO: add lung damage = less oxygen gains @@ -289,7 +301,7 @@ H.hallucination += 10 H.reagents.add_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 @@ -405,13 +417,13 @@ var/cold_modifier = H.dna.species.coldmod if(breath_temperature < cold_level_3_threshold) H.apply_damage_type(cold_level_3_damage*cold_modifier, cold_damage_type) - adjustLungLoss((cold_level_3_damage*cold_modifier*2), H) + H.adjustOrganLoss(ORGAN_SLOT_LUNGS, (cold_level_3_damage*cold_modifier*2)) if(breath_temperature > cold_level_3_threshold && breath_temperature < cold_level_2_threshold) H.apply_damage_type(cold_level_2_damage*cold_modifier, cold_damage_type) - adjustLungLoss((cold_level_2_damage*cold_modifier*2), H) + H.adjustOrganLoss(ORGAN_SLOT_LUNGS, (cold_level_2_damage*cold_modifier*2)) if(breath_temperature > cold_level_2_threshold && breath_temperature < cold_level_1_threshold) H.apply_damage_type(cold_level_1_damage*cold_modifier, cold_damage_type) - adjustLungLoss((cold_level_1_damage*cold_modifier*2), H) + H.adjustOrganLoss(ORGAN_SLOT_LUNGS, (cold_level_1_damage*cold_modifier*2)) if(breath_temperature < cold_level_1_threshold) if(prob(20)) to_chat(H, "You feel [cold_message] in your [name]!") @@ -420,17 +432,29 @@ var/heat_modifier = H.dna.species.heatmod if(breath_temperature > heat_level_1_threshold && breath_temperature < heat_level_2_threshold) H.apply_damage_type(heat_level_1_damage*heat_modifier, heat_damage_type) - adjustLungLoss((heat_level_1_damage*heat_modifier*2), H) + H.adjustOrganLoss(ORGAN_SLOT_LUNGS, (heat_level_1_damage*heat_modifier*2)) if(breath_temperature > heat_level_2_threshold && breath_temperature < heat_level_3_threshold) H.apply_damage_type(heat_level_2_damage*heat_modifier, heat_damage_type) - adjustLungLoss((heat_level_2_damage*heat_modifier*2), H) + H.adjustOrganLoss(ORGAN_SLOT_LUNGS, (heat_level_2_damage*heat_modifier*2)) if(breath_temperature > heat_level_3_threshold) H.apply_damage_type(heat_level_3_damage*heat_modifier, heat_damage_type) - adjustLungLoss((heat_level_3_damage*heat_modifier*2), H) + H.adjustOrganLoss(ORGAN_SLOT_LUNGS, (heat_level_3_damage*heat_modifier*2)) if(breath_temperature > heat_level_1_threshold) 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!", \ + "You suddenly feel like you can't breathe!") + failed = TRUE + else if(!(organ_flags & ORGAN_FAILING)) + failed = FALSE + return + /obj/item/organ/lungs/prepare_eat() var/obj/S = ..() S.reagents.add_reagent("salbutamol", 5) @@ -451,14 +475,16 @@ name = "cybernetic lungs" desc = "A cybernetic version of the lungs found in traditional humanoid entities. It functions the same as an organic lung and is merely meant as a replacement." icon_state = "lungs-c" - synthetic = TRUE + organ_flags = ORGAN_SYNTHETIC maxHealth = 400 + safe_oxygen_min = 13 /obj/item/organ/lungs/cybernetic/emp_act() . = ..() if(. & EMP_PROTECT_SELF) return owner.losebreath = 20 + owner.adjustOrganLoss(ORGAN_SLOT_LUNGS, 25) /obj/item/organ/lungs/cybernetic/upgraded @@ -495,8 +521,24 @@ safe_toxins_max = 0 //We breathe this to gain POWER. + cold_level_1_threshold = 285 // Remember when slimes used to be succeptable to cold? Well.... + cold_level_2_threshold = 260 + cold_level_3_threshold = 230 + + maxHealth = 250 + /obj/item/organ/lungs/slime/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/H) . = ..() if (breath && breath.gases[/datum/gas/plasma]) var/plasma_pp = breath.get_breath_partial_pressure(breath.gases[/datum/gas/plasma]) owner.blood_volume += (0.2 * plasma_pp) // 10/s when breathing literally nothing but plasma, which will suffocate you. + +/obj/item/organ/lungs/yamerol + name = "Yamerol lungs" + desc = "A temporary pair of lungs made from self assembling yamerol molecules." + maxHealth = 200 + color = "#68e83a" + +/obj/item/organ/lungs/yamerol/on_life() + ..() + damage += 2 //Yamerol lungs are temporary diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 9f910de9..a17d4906 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -1,3 +1,6 @@ +#define STANDARD_ORGAN_THRESHOLD 100 +#define STANDARD_ORGAN_HEALING 0.001 + /obj/item/organ name = "organ" icon = 'icons/obj/surgery.dmi' @@ -8,11 +11,23 @@ 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 + ///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 + ///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) @@ -33,31 +48,53 @@ for(var/X in actions) var/datum/action/A = X A.Grant(M) + STOP_PROCESSING(SSobj, src) //Special is for instant replacement like autosurgeons -/obj/item/organ/proc/Remove(mob/living/carbon/M, special = 0) +/obj/item/organ/proc/Remove(mob/living/carbon/M, special = FALSE) owner = null if(M) 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 A.Remove(M) + START_PROCESSING(SSobj, src) /obj/item/organ/proc/on_find(mob/living/finder) return -/obj/item/organ/proc/on_life() - return +/obj/item/organ/process() + on_death() //Kinda hate doing it like this, but I really don't want to call process directly. + +/obj/item/organ/proc/on_death() //runs decay when outside of a person + if(organ_flags & (ORGAN_SYNTHETIC | ORGAN_FROZEN | ORGAN_NO_SPOIL)) + return + applyOrganDamage(maxHealth * decay_factor) + +/obj/item/organ/proc/on_life() //repair organ damage if the organ is not failing + if(!(organ_flags & ORGAN_FAILING)) + ///Damage decrements by a percent of its maxhealth + var/healing_amount = -(maxHealth * healing_factor) + ///Damage decrements again by a percent of its maxhealth, up to a total of 4 extra times depending on the owner's health + healing_amount -= owner.satiety > 0 ? 4 * healing_factor * owner.satiety / MAX_SATIETY : 0 + applyOrganDamage(healing_amount) //to FERMI_TWEAK + //Make it so each threshold is stuck. /obj/item/organ/examine(mob/user) - ..() - if(status == ORGAN_ROBOTIC && crit_fail) - to_chat(user, "[src] seems to be broken!") + . = ..() + if(!organ_flags & ORGAN_FAILING) + if(status == ORGAN_ROBOTIC) + . += "[src] seems to be broken!" + return + . += "[src] has decayed for too long, and has turned a sickly color! It doesn't look like it will work anymore!" + return + if(damage > high_threshold) + . += "[src] is starting to look discolored." /obj/item/organ/proc/prepare_eat() @@ -78,6 +115,10 @@ foodtype = RAW | MEAT | GROSS +/obj/item/organ/Initialize() + . = ..() + START_PROCESSING(SSobj, src) + /obj/item/organ/Destroy() if(owner) // The special flag is important, because otherwise mobs can die @@ -100,13 +141,64 @@ /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. +///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(!d) //Micro-optimization. + return + if(maximum < damage) + return + damage = CLAMP(damage + d, 0, maximum) + var/mess = check_damage_thresholds(owner) + prev_damage = damage + if(mess && owner) + to_chat(owner, mess) + +///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 + applyOrganDamage(d - damage) + +/** check_damage_thresholds + * input: M (a mob, the owner of the organ we call the proc on) + * output: returns a message should get displayed. + * 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) + organ_flags |= ORGAN_FAILING + return now_failing + if(damage > high_threshold && prev_damage <= high_threshold) + return high_threshold_passed + if(damage > low_threshold && prev_damage <= low_threshold) + return low_threshold_passed + else + organ_flags &= ~ORGAN_FAILING + if(prev_damage > low_threshold && damage <= low_threshold) + return low_threshold_cleared + if(prev_damage > high_threshold && damage <= high_threshold) + return high_threshold_cleared + if(prev_damage == maxHealth) + return now_fixed + +//Runs some code on the organ when damage is taken/healed +/obj/item/organ/proc/onDamage(var/d, var/maximum = maxHealth) + return + +//Runs some code on the organ when damage is taken/healed +/obj/item/organ/proc/onSetDamage(var/d, var/maximum = maxHealth) + return + //Looking for brains? //Try code/modules/mob/living/carbon/brain/brain_item.dm /mob/living/proc/regenerate_organs() return 0 -/mob/living/carbon/regenerate_organs() +/mob/living/carbon/regenerate_organs(only_one = FALSE) var/breathes = TRUE var/blooded = TRUE if(dna && dna.species) @@ -125,6 +217,8 @@ else LI = new() LI.Insert(src) + if(only_one) + return TRUE if(has_stomach && !getorganslot(ORGAN_SLOT_STOMACH)) var/obj/item/organ/stomach/S @@ -134,14 +228,20 @@ else S = new() S.Insert(src) + if(only_one) + return TRUE if(breathes && !getorganslot(ORGAN_SLOT_LUNGS)) var/obj/item/organ/lungs/L = new() L.Insert(src) + if(only_one) + return TRUE if(blooded && !getorganslot(ORGAN_SLOT_HEART)) var/obj/item/organ/heart/H = new() H.Insert(src) + if(only_one) + return TRUE if(!getorganslot(ORGAN_SLOT_TONGUE)) var/obj/item/organ/tongue/T @@ -153,7 +253,10 @@ // if they have no mutant tongues, give them a regular one T.Insert(src) - else + if(only_one) + return TRUE + + else if (!only_one) var/obj/item/organ/tongue/oT = getorganslot(ORGAN_SLOT_TONGUE) if(oT.name == "fluffy tongue") var/obj/item/organ/tongue/T @@ -174,6 +277,8 @@ else E = new() E.Insert(src) + if(only_one) + return TRUE if(!getorganslot(ORGAN_SLOT_EARS)) var/obj/item/organ/ears/ears @@ -183,9 +288,13 @@ ears = new ears.Insert(src) + if(only_one) + return TRUE if(!getorganslot(ORGAN_SLOT_TAIL)) var/obj/item/organ/tail/tail if(dna && dna.species && dna.species.mutanttail) tail = new dna.species.mutanttail tail.Insert(src) + if(only_one) + return TRUE diff --git a/code/modules/surgery/organs/stomach.dm b/code/modules/surgery/organs/stomach.dm index c0806def..4cb2cd21 100644 --- a/code/modules/surgery/organs/stomach.dm +++ b/code/modules/surgery/organs/stomach.dm @@ -8,12 +8,41 @@ desc = "Onaka ga suite imasu." var/disgust_metabolism = 1 -/obj/item/organ/stomach/on_life() - var/mob/living/carbon/human/H = owner + healing_factor = STANDARD_ORGAN_HEALING + decay_factor = STANDARD_ORGAN_DECAY - if(istype(H)) - H.dna.species.handle_digestion(H) + 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." + +/obj/item/organ/stomach/on_life() + var/datum/reagent/consumable/nutriment/Nutri + if(ishuman(owner)) + var/mob/living/carbon/human/H = owner + if(!(organ_flags & ORGAN_FAILING)) + H.dna.species.handle_digestion(H) handle_disgust(H) + 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!") + + + else if(iscarbon(owner)) + var/mob/living/carbon/C = owner + Nutri = locate(/datum/reagent/consumable/nutriment) in C.reagents.reagent_list + + if(damage < low_threshold) + return + /obj/item/organ/stomach/proc/handle_disgust(mob/living/carbon/human/H) if(H.disgust) diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm index 3eaaa8de..3dd5c7b2 100644 --- a/code/modules/surgery/organs/tongue.dm +++ b/code/modules/surgery/organs/tongue.dm @@ -10,8 +10,7 @@ var/list/languages_possible var/say_mod = null var/taste_sensitivity = 15 // lower is more sensitive. - var/maxHealth = TONGUE_MAX_HEALTH - var/damage = 0 + maxHealth = TONGUE_MAX_HEALTH var/modifies_speech = FALSE var/static/list/languages_possible_base = typecacheof(list( /datum/language/common, @@ -31,27 +30,34 @@ /obj/item/organ/tongue/proc/handle_speech(datum/source, list/speech_args) -/obj/item/organ/tongue/proc/adjustTongueLoss(mob/living/carbon/M, damage_mod) - if (maxHealth == "alien") - return - if (maxHealth == "bone") - var/target = M.get_bodypart(BODY_ZONE_HEAD) - M.apply_damage(damage_mod, BURN, target) - to_chat(M, "The drink burns your skull! Oof, your bones!") - return - if(damage+damage_mod < 0) - damage = 0 +/obj/item/organ/tongue/emp_act(severity) + . = ..() + if(. & EMP_PROTECT_SELF) return + if(organ_flags & ORGAN_SYNTHETIC) + var/errormessage = list("Runtime in tongue.dm, line 39: Undefined operation \"zapzap ow my tongue\"", "afhsjifksahgjkaslfhashfjsak", "-1.#IND", "Graham's number", "inside you all along", "awaiting at least 1 approving review before merging this taste request") + owner.say("The pH is appropriately [pick(errormessage)].") + +/obj/item/organ/tongue/applyOrganDamage(var/d, var/maximum = maxHealth) + + if(!d) //Micro-optimization. + return + if(maximum < damage) + return + damage = CLAMP(damage + d, 0, maximum) + var/mess = check_damage_thresholds(owner) + prev_damage = damage + if(mess && owner) + to_chat(owner, mess) - damage += damage_mod if ((damage / maxHealth) > 1) - to_chat(M, "Your tongue is singed beyond recognition, and disintegrates!") + to_chat(owner, "Your tongue is singed beyond recognition, and disintegrates!") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Tongues lost to Fermi") qdel(src) else if ((damage / maxHealth) > 0.85) - to_chat(M, "Your tongue feels like it's about to fall out!.") + to_chat(owner, "Your tongue feels like it's about to fall out!.") else if ((damage / maxHealth) > 0.5) - to_chat(M, "Your tongue is really starting to hurt.") + to_chat(owner, "Your tongue is really starting to hurt.") /obj/item/organ/tongue/Insert(mob/living/carbon/M, special = 0) @@ -168,7 +174,7 @@ icon_state = "tonguexeno" say_mod = "hisses" taste_sensitivity = 10 // LIZARDS ARE ALIENS CONFIRMED - maxHealth = "alien" //Their blood is acid, so, no, though a tongueless xeno might be funny + maxHealth = 500 //They've a little mouth for a tongue, so it's pretty rhobust modifies_speech = TRUE // not really, they just hiss var/static/list/languages_possible_alien = typecacheof(list( /datum/language/xenocommon, @@ -189,9 +195,10 @@ desc = "Apparently skeletons alter the sounds they produce through oscillation of their teeth, hence their characteristic rattling." icon_state = "tonguebone" say_mod = "rattles" + organ_flags = ORGAN_NO_SPOIL attack_verb = list("bitten", "chattered", "chomped", "enamelled", "boned") taste_sensitivity = 101 // skeletons cannot taste anything - maxHealth = "bone" //Take brute damage instead + maxHealth = 75 //Take brute damage instead modifies_speech = TRUE var/chattering = FALSE var/phomeme_type = "sans" @@ -201,6 +208,14 @@ . = ..() phomeme_type = pick(phomeme_types) +/obj/item/organ/tongue/bone/applyOrganDamage(var/d, var/maximum = maxHealth) + if(!owner) + return + var/target = owner.get_bodypart(BODY_ZONE_HEAD) + owner.apply_damage(d, BURN, target) + to_chat(owner, "You feel your skull burning! Oof, your bones!") + return + /obj/item/organ/tongue/bone/handle_speech(datum/source, list/speech_args) if (chattering) chatter(speech_args[SPEECH_MESSAGE], phomeme_type, source) @@ -262,6 +277,7 @@ icon_state = "tonguecybernetic" taste_sensitivity = 10 maxHealth = 60 //It's robotic! + organ_flags = ORGAN_SYNTHETIC /obj/item/organ/tongue/cybernetic/handle_speech(datum/source, list/speech_args) speech_args[SPEECH_SPANS] |= SPAN_ROBOT @@ -271,3 +287,4 @@ say_mod = "beeps" desc = "A voice synthesizer used by IPCs to smoothly interface with organic lifeforms." electronics_magic = FALSE + organ_flags = ORGAN_SYNTHETIC diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index 81032243..009cfce0 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -26,12 +26,14 @@ zone = BODY_ZONE_HEAD slot = ORGAN_SLOT_ADAMANTINE_RESONATOR icon_state = "adamantine_resonator" + decay_factor = 0 /obj/item/organ/vocal_cords/adamantine name = "adamantine vocal cords" desc = "When adamantine resonates, it causes all nearby pieces of adamantine to resonate as well. Adamantine golems use this to broadcast messages to nearby golems." actions_types = list(/datum/action/item_action/organ_action/use/adamantine_vocal_cords) icon_state = "adamantine_cords" + decay_factor = 0 /datum/action/item_action/organ_action/use/adamantine_vocal_cords/Trigger() if(!IsAvailable()) @@ -62,6 +64,7 @@ var/cooldown_mod = 1 var/base_multiplier = 1 spans = list("colossus","yell") + decay_factor = 0 /datum/action/item_action/organ_action/colossus name = "Voice of God" @@ -623,10 +626,6 @@ /datum/action/item_action/organ_action/velvet name = "Velvet chords" var/obj/item/organ/vocal_cords/velvet/cords = null - //icon_icon = 'icons/mob/screen_alert.dmi' - //button_icon_state = "velvet_chords" - //icon = 'icons/mob/screen_alert.dmi' - //icon_state = "in_love" /datum/action/item_action/organ_action/velvet/New() ..() @@ -991,7 +990,7 @@ if (HAS_TRAIT(H, TRAIT_DEAF))//How the heck you managed to get here I have no idea, but just in case! speaktrigger += "I can barely hear you! " //And the brain damage. And the brain damage. And the brain damage. And the brain damage. And the brain damage. - switch(H.getBrainLoss()) + switch(H.getOrganLoss(ORGAN_SLOT_BRAIN)) if(20 to 40) speaktrigger += "I have a mild head ache, " if(40 to 80) diff --git a/code/modules/vehicles/scooter.dm b/code/modules/vehicles/scooter.dm index 9af5b13a..8c21b050 100644 --- a/code/modules/vehicles/scooter.dm +++ b/code/modules/vehicles/scooter.dm @@ -75,7 +75,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) @@ -201,7 +201,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 ae53f29a..0f6ef14c 100644 --- a/code/modules/zombie/items.dm +++ b/code/modules/zombie/items.dm @@ -73,5 +73,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.nutrition = min(user.nutrition + hp_gained, NUTRITION_LEVEL_FULL) diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index cda9c174..1b188617 100644 --- a/modular_citadel/code/datums/status_effects/chems.dm +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -46,7 +46,7 @@ if(W == o.w_uniform || W == o.wear_suit) o.dropItemToGround(W, TRUE) playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1) - to_chat(o, "Your clothes give, ripping into pieces under the strain of your swelling breasts! Unless you manage to reduce the size of your breasts, there's no way you're going to be able to put anything on over these melons..!") + to_chat(o, "Your clothes give, ripping into peices under the strain of your swelling breasts! Unless you manage to reduce the size of your breasts, there's no way you're going to be able to put anything on over these melons..!") o.visible_message("[o]'s chest suddenly bursts forth, ripping their clothes off!'") else to_chat(o, "Your bountiful bosom is so rich with mass, you seriously doubt you'll be able to fit any clothes over it.") @@ -55,21 +55,17 @@ /datum/status_effect/chem/breast_enlarger/tick(mob/living/carbon/human/H)//If you try to wear clothes, you fail. Slows you down if you're comically huge var/mob/living/carbon/human/o = owner var/obj/item/organ/genital/breasts/B = o.getorganslot("breasts") - - // HYPER CHANGE: Speed modifier and damage removed. - /*moveCalc = 1+((round(B.cached_size) - 9)/3) //Afffects how fast you move, and how often you can click. + moveCalc = 1+((round(B.cached_size) - 9)/3) //Afffects how fast you move, and how often you can click. if(!B) o.remove_movespeed_modifier(BREAST_MOVEMENT_SPEED) sizeMoveMod(1) owner.remove_status_effect(src) - */ var/items = o.get_contents() for(var/obj/item/W in items) if(W == o.w_uniform || W == o.wear_suit) o.dropItemToGround(W, TRUE) playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1) to_chat(owner, "Your enormous breasts are way too large to fit anything over them!") - /* if (B.size == "huge") if(prob(1)) to_chat(owner, "Your back is feeling sore.") @@ -85,7 +81,6 @@ else if (B.breast_values[B.size] < B.breast_values[B.prev_size]) o.add_movespeed_modifier(BREAST_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc) sizeMoveMod(moveCalc) - */ if((B.cached_size) < 16) switch(round(B.cached_size)) if(9) @@ -98,7 +93,6 @@ to_chat(owner, "Your back is feeling a little sore.") ..() -/* /datum/status_effect/chem/breast_enlarger/on_remove(mob/living/carbon/M) log_game("FERMICHEM: [owner]'s breasts has reduced to an acceptable size. ID: [owner.key]") owner.remove_movespeed_modifier(BREAST_MOVEMENT_SPEED) @@ -110,7 +104,7 @@ owner.next_move_modifier /= cachedmoveCalc owner.next_move_modifier *= value cachedmoveCalc = value -*/ + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /datum/status_effect/chem/penis_enlarger @@ -119,7 +113,6 @@ var/bloodCalc var/moveCalc - /datum/status_effect/chem/penis_enlarger/on_apply(mob/living/carbon/human/H)//Removes clothes, they're too small to contain you. You belong to space now. log_game("FERMICHEM: [owner]'s dick has reached comical sizes. ID: [owner.key]") var/mob/living/carbon/human/o = owner @@ -136,10 +129,8 @@ return ..() - /datum/status_effect/chem/penis_enlarger/tick(mob/living/carbon/M) var/mob/living/carbon/human/o = owner - /* HYPER CHANGE: Removes blood loss and movement penalties var/obj/item/organ/genital/penis/P = o.getorganslot("penis") moveCalc = 1+((round(P.length) - 21)/3) //effects how fast you can move bloodCalc = 1+((round(P.length) - 21)/15) //effects how much blood you need (I didn' bother adding an arousal check because I'm spending too much time on this organ already.) @@ -147,15 +138,12 @@ o.remove_movespeed_modifier(DICK_MOVEMENT_SPEED) o.ResetBloodVol() owner.remove_status_effect(src) - */ - var/items = o.get_contents() for(var/obj/item/W in items) if(W == o.w_uniform || W == o.wear_suit) o.dropItemToGround(W, TRUE) playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1) to_chat(owner, "Your enormous package is way to large to fit anything over!") -/* switch(round(P.cached_length)) if(21) to_chat(o, "Your rascally willy has become a more managable size, liberating your movements.") @@ -166,15 +154,13 @@ to_chat(o, "Your indulgent johnson is so substantial, it's taking all your blood and affecting your movements!") o.add_movespeed_modifier(DICK_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc) o.AdjustBloodVol(bloodCalc) -*/ ..() -/* /datum/status_effect/chem/penis_enlarger/on_remove(mob/living/carbon/human/o) log_game("FERMICHEM: [owner]'s dick has reduced to an acceptable size. ID: [owner.key]") owner.remove_movespeed_modifier(DICK_MOVEMENT_SPEED) owner.ResetBloodVol() -*/ + /*////////////////////////////////////////// Mind control functions @@ -244,8 +230,7 @@ // owner.remove_status_effect(src)//At the moment, a user can enthrall themselves, toggle this back in if that should be removed. redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/owner_resist)))) //Do resistance calc if resist is pressed# RegisterSignal(owner, COMSIG_MOVABLE_HEAR, .proc/owner_hear) - var/obj/item/organ/brain/B = M.getorganslot(ORGAN_SLOT_BRAIN) //It's their brain! - mental_capacity = 500 - B.get_brain_damage() + mental_capacity = 500 - M.getOrganLoss(ORGAN_SLOT_BRAIN)//It's their brain! var/mob/living/carbon/human/H = owner if(H)//Prefs if(!H.canbearoused) @@ -348,7 +333,7 @@ if(owner.client?.prefs.lewdchem && !customEcho) to_chat(owner, "[pick("I belong to [enthrallGender].", "[enthrallGender] knows whats best for me.", "Obedence is pleasure.", "I exist to serve [enthrallGender].", "[enthrallGender] is so dominant, it feels right to obey them.")].") if (4) //mindbroken - if (mental_capacity >= 499 && (owner.getBrainLoss() <=0 || HAS_TRAIT(M, TRAIT_MINDSHIELD)) && !owner.reagents.has_reagent("MKUltra")) + if (mental_capacity >= 499 && (owner.getOrganLoss(ORGAN_SLOT_BRAIN) <=0 || HAS_TRAIT(M, TRAIT_MINDSHIELD)) && !owner.reagents.has_reagent("MKUltra")) phase = 2 mental_capacity = 500 customTriggers = list() @@ -387,8 +372,8 @@ M.hallucination = max(0, M.hallucination - 5) M.stuttering = max(0, M.stuttering - 5) M.jitteriness = max(0, M.jitteriness - 5) - if(owner.getBrainLoss() >=20) - owner.adjustBrainLoss(-0.2) + if(owner.getOrganLoss(ORGAN_SLOT_BRAIN) >=20) + owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, -0.2) if(withdrawal == TRUE) REMOVE_TRAIT(owner, TRAIT_PACIFISM, "MKUltra") SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "EnthMissing1") @@ -409,7 +394,7 @@ if(prob(5)) to_chat(owner, "You're starting to miss [(owner.client?.prefs.lewdchem?"your [enthrallGender]":"[master]")].") if(prob(5)) - owner.adjustBrainLoss(0.1) + owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.1) to_chat(owner, "[(owner.client?.prefs.lewdchem?"[enthrallGender]":"[master]")] will surely be back soon") //denial if(36) var/message = "[(owner.client?.prefs.lewdchem?"I feel empty when [enthrallGender]'s not around..":"I miss [master]'s presence")]" @@ -417,11 +402,11 @@ if(37 to 65)//barganing if(prob(10)) to_chat(owner, "They are coming back, right...?") - owner.adjustBrainLoss(0.5) + owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.5) if(prob(10)) if(owner.client?.prefs.lewdchem) to_chat(owner, "I just need to be a good pet for [enthrallGender], they'll surely return if I'm a good pet.") - owner.adjustBrainLoss(-1.5) + owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1.5) if(66) SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "EnthMissing1") var/message = "[(owner.client?.prefs.lewdchem?"I feel so lost in this complicated world without [enthrallGender]..":"I have to return to [master]!")]" @@ -466,7 +451,7 @@ to_chat(owner, "You're unable to hold back your tears, suddenly sobbing as the desire to see your [enthrallGender] oncemore overwhelms you.") else to_chat(owner, "You are overwheled with withdrawl from [master].") - owner.adjustBrainLoss(1) + owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1) owner.stuttering += 35 owner.jitteriness += 35 if(prob(10))//2% chance @@ -482,14 +467,14 @@ if(140 to INFINITY) //acceptance if(prob(15)) deltaResist += 5 - owner.adjustBrainLoss(-1) + owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1) if(prob(20)) if(owner.client?.prefs.lewdchem) to_chat(owner, "Maybe you'll be okay without your [enthrallGender].") else to_chat(owner, "You feel your mental functions slowly begin to return.") if(prob(5)) - owner.adjustBrainLoss(1) + owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1) M.hallucination += 30 withdrawalTick += 0.5//Enough to leave you with a major brain trauma, but not kill you. diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm index 1508a5d5..4e80f42d 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm @@ -136,7 +136,6 @@ Creating a chem with a low purity will make you permanently fall in love with so color = "#660015" // rgb: , 0, 255 taste_description = "synthetic chocolate, a base tone of alcohol, and high notes of roses" overdose_threshold = 100 //If this is too easy to get 100u of this, then double it please. - DoNotSplit = TRUE metabolization_rate = 0.1//It has to be slow, so there's time for the effect. data = list("creatorID" = null, "creatorGender" = null, "creatorName" = null) var/creatorID //ckey @@ -144,20 +143,19 @@ Creating a chem with a low purity will make you permanently fall in love with so var/creatorName var/mob/living/creator pH = 10 - OnMobMergeCheck = TRUE //Procs on_mob_add when merging into a human + chemical_flags = REAGENT_ONMOBMERGE | REAGENT_DONOTSPLIT //Procs on_mob_add when merging into a human can_synth = FALSE /datum/reagent/fermi/enthrall/test name = "MKUltraTest" id = "enthrallTest" - description = "A forbidden deep red mixture that overwhelms a foreign body with waves of joy, intoxicating them into servitude. When taken by the creator, it will enhance the draw of their voice to those affected by it." + description = "A forbidden deep red mixture that makes you like Fermis a little too much. Unobtainable and due to be removed from the wiki." data = list("creatorID" = "honkatonkbramblesnatch", "creatorGender" = "Mistress", "creatorName" = "Fermis Yakumo") creatorID = "honkatonkbramblesnatch"//ckey creatorGender = "Mistress" creatorName = "Fermis Yakumo" purity = 1 - DoNotSplit = TRUE /datum/reagent/fermi/enthrall/test/on_new() id = "enthrall" @@ -295,18 +293,18 @@ Creating a chem with a low purity will make you permanently fall in love with so SSblackbox.record_feedback("tally", "fermi_chem", 1, "Thralls mindbroken") /datum/reagent/fermi/enthrall/overdose_process(mob/living/carbon/M) - M.adjustBrainLoss(0.2)//should be ~30 in total + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.2)//should be ~30 in total ..() //Creates a gas cloud when the reaction blows up, causing everyone in it to fall in love with someone/something while it's in their system. /datum/reagent/fermi/enthrallExplo//Created in a gas cloud when it explodes - name = "MKUltra" + name = "Gaseous MKUltra" id = "enthrallExplo" - description = "A forbidden deep red mixture that overwhelms a foreign body with waves of desire, inducing a chemial love for another. Also, how the HECC did you get this?" + description = "A forbidden deep red gas that overwhelms a foreign body, causing the person they next lay their eyes on to become more interesting. Studies have shown that people are 66% more likely to make friends with this in the air. Produced when MKUltra explodes." color = "#2C051A" // rgb: , 0, 255 metabolization_rate = 0.1 taste_description = "synthetic chocolate, a base tone of alcohol, and high notes of roses." - DoNotSplit = TRUE + chemical_flags = REAGENT_DONOTSPLIT can_synth = FALSE var/mob/living/carbon/love @@ -342,7 +340,7 @@ Creating a chem with a low purity will make you permanently fall in love with so M.Stun(10) M.emote("whimper")//does this exist? to_chat(M, "[(M.client?.prefs.lewdchem?"":"")] You're overcome with a desire to see [love].") - M.adjustBrainLoss(0.5)//I found out why everyone was so damaged! + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.5)//I found out why everyone was so damaged! ..() /datum/reagent/fermi/enthrallExplo/on_mob_delete(mob/living/carbon/M) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm index 499510b5..a7e1ac8e 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm @@ -54,9 +54,9 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING var/pollStarted = FALSE var/location_created var/startHunger - ImpureChem = "SDGFtox" - InverseChemVal = 0.5 - InverseChem = "SDZF" + impure_chem = "SDGFtox" + inverse_chem_val = 0.5 + inverse_chem = "SDZF" can_synth = TRUE @@ -81,9 +81,19 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING SM.real_name = M.real_name M.dna.transfer_identity(SM) SM.updateappearance(mutcolor_update=1) - var/mob/dead/observer/C = pick(candies) - message_admins("Ghost candidate found! [C] key [C.key] is becoming a clone of [M] key: [M.key] (They agreed to respect the character they're becoming, and agreed to not ERP without express permission from the original.)") - SM.key = C.key + + + candies = shuffle(candies)//Shake those ghosts up! + for(var/mob/dead/observer/C2 in candies) + if(C2.key && C2) + C2.transfer_ckey(SM, FALSE) + message_admins("Ghost candidate found! [C2] key [C2.key] is becoming a clone of [M] key: [M.key] (They agreed to respect the character they're becoming, and agreed to not ERP without express permission from the original.)") + log_game("FERMICHEM: [M] ckey: [M.key] is creating a clone, controlled by [C2]") + break + else + candies =- C2 + if(!SM.mind) //Something went wrong, use alt mechanics + return ..() SM.mind.enslave_mind_to_creator(M) //If they're a zombie, they can try to negate it with this. @@ -113,7 +123,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING //Damage the clone SM.blood_volume = (BLOOD_VOLUME_NORMAL*SM.blood_ratio)/2 SM.adjustCloneLoss(60, 0) - SM.setBrainLoss(40) + SM.setOrganLoss(ORGAN_SLOT_BRAIN, 40) SM.nutrition = startHunger/2 //Transfer remaining reagent to clone. I think around 30u will make a healthy clone, otherwise they'll have clone damage, blood loss, brain damage and hunger. @@ -239,7 +249,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING SM.adjustToxLoss(-(bodydamage/10), 0) SM.blood_volume = (BLOOD_VOLUME_NORMAL*SM.blood_ratio)/1.5 SM.adjustCloneLoss((bodydamage/10), 0) - SM.setBrainLoss((bodydamage/10)) + SM.setOrganLoss(ORGAN_SLOT_BRAIN, (bodydamage/10)) SM.nutrition = 400 if(bodydamage>200) SM.gain_trauma_type(BRAIN_TRAUMA_MILD) @@ -270,8 +280,9 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING //Unobtainable, used in clone spawn. /datum/reagent/fermi/SDGFheal - name = "synthetic-derived growth factor" + name = "synthetic-derived healing factor" id = "SDGFheal" + description = "Leftover SDGF is transferred into the resulting clone, which quickly heals up the stresses from suddenly splitting. Restores blood, nutrition, and repaires brain and clone damage quickly. Only obtainable from using excess SDGF, and only enters the cloned body." metabolization_rate = 1 can_synth = FALSE @@ -279,34 +290,35 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING if(M.blood_volume < (BLOOD_VOLUME_NORMAL*M.blood_ratio)) M.blood_volume += 10 M.adjustCloneLoss(-2, 0) - M.setBrainLoss(-1) + M.setOrganLoss(ORGAN_SLOT_BRAIN, -1) M.nutrition += 10 ..() //Unobtainable, used if SDGF is impure but not too impure -/datum/reagent/fermi/SDGFtox - name = "synthetic-derived growth factor" +/datum/reagent/impure/SDGFtox + name = "Synthetic-derived apoptosis factor" id = "SDGFtox" - description = "A chem that makes a certain chemcat angry at you if you're reading this, how did you get this???"//i.e. tell me please, figure it's a good way to get pinged for bugfixes. + description = "Impure synthetic-derived growth factor causes certain cells to undergo cell death, causing clone damage, and damaging blood cells."//i.e. tell me please, figure it's a good way to get pinged for bugfixes. metabolization_rate = 1 can_synth = FALSE -/datum/reagent/fermi/SDGFtox/on_mob_life(mob/living/carbon/M)//Damages the taker if their purity is low. Extended use of impure chemicals will make the original die. (thus can't be spammed unless you've very good) +/datum/reagent/impure/SDGFtox/on_mob_life(mob/living/carbon/M)//Damages the taker if their purity is low. Extended use of impure chemicals will make the original die. (thus can't be spammed unless you've very good) M.blood_volume -= 10 M.adjustCloneLoss(2, 0) ..() //Fail state of SDGF -/datum/reagent/fermi/SDZF - name = "synthetic-derived growth factor" +/datum/reagent/impure/SDZF + name = "synthetic-derived zombie factor" id = "SDZF" - description = "A horribly peverse mass of Embryonic stem cells made real by the hands of a failed chemist. This message should never appear, how did you manage to get a hold of this?" + description = "A horribly peverse mass of Embryonic stem cells made real by the hands of a failed chemist. Emulates normal synthetic-derived growth factor, but produces a hostile zombie at the end of it." color = "#a502e0" // rgb: 96, 0, 255 metabolization_rate = 0.5 * REAGENTS_METABOLISM var/startHunger can_synth = TRUE + chemical_flags = REAGENT_SNEAKYNAME -/datum/reagent/fermi/SDZF/on_mob_life(mob/living/carbon/M) //If you're bad at fermichem, turns your clone into a zombie instead. +/datum/reagent/impure/SDZF/on_mob_life(mob/living/carbon/M) //If you're bad at fermichem, turns your clone into a zombie instead. switch(current_cycle)//Pretends to be normal if(20) to_chat(M, "You feel the synethic cells rest uncomfortably within your body as they start to pulse and grow rapidly.") diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 275c244a..4acfda05 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -6,58 +6,20 @@ id = "fermi" taste_description = "affection and love!" can_synth = FALSE + //SplitChem = TRUE + impure_chem = "fermiTox"// What chemical is metabolised with an inpure reaction + inverse_chem_val = 0.25 // If the impurity is below 0.5, replace ALL of the chem with inverse_chemupon metabolising + inverse_chem = "fermiTox" //This should process fermichems to find out how pure they are and what effect to do. /datum/reagent/fermi/on_mob_add(mob/living/carbon/M, amount) . = ..() - if(!M) - return - if(purity < 0) - CRASH("Purity below 0 for chem: [id], Please let Fermis Know!") - if (purity == 1 || DoNotSplit == TRUE) - log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume]u of [id]") - return - else if (InverseChemVal > purity)//Turns all of a added reagent into the inverse chem - M.reagents.remove_reagent(id, amount, FALSE) - M.reagents.add_reagent(InverseChem, amount, FALSE, other_purity = 1) - log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume]u of [InverseChem]") - return - else - var/impureVol = amount * (1 - purity) //turns impure ratio into impure chem - M.reagents.remove_reagent(id, (impureVol), FALSE) - M.reagents.add_reagent(ImpureChem, impureVol, FALSE, other_purity = 1) - log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume - impureVol]u of [id]") - log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume]u of [ImpureChem]") - return + //When merging two fermichems, see above /datum/reagent/fermi/on_merge(data, amount, mob/living/carbon/M, purity)//basically on_mob_add but for merging . = ..() - if(!ishuman(M)) - return - if (purity < 0) - CRASH("Purity below 0 for chem: [id], Please let Fermis Know!") - if (purity == 1 || DoNotSplit == TRUE) - log_game("FERMICHEM: [M] ckey: [M.key] has merged [volume]u of [id] in themselves") - return - else if (InverseChemVal > purity) - M.reagents.remove_reagent(id, amount, FALSE) - M.reagents.add_reagent(InverseChem, amount, FALSE, other_purity = 1) - for(var/datum/reagent/fermi/R in M.reagents.reagent_list) - if(R.name == "") - R.name = name//Negative effects are hidden - log_game("FERMICHEM: [M] ckey: [M.key] has merged [volume]u of [InverseChem]") - return - else - var/impureVol = amount * (1 - purity) - M.reagents.remove_reagent(id, impureVol, FALSE) - M.reagents.add_reagent(ImpureChem, impureVol, FALSE, other_purity = 1) - for(var/datum/reagent/fermi/R in M.reagents.reagent_list) - if(R.name == "") - R.name = name//Negative effects are hidden - log_game("FERMICHEM: [M] ckey: [M.key] has merged [volume - impureVol]u of [id]") - log_game("FERMICHEM: [M] ckey: [M.key] has merged [volume]u of [ImpureChem]") - return + //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -77,7 +39,7 @@ taste_description = "like jerky, whiskey and an off aftertaste of a crypt." metabolization_rate = 0.2 overdose_threshold = 25 - DoNotSplit = TRUE + chemical_flags = REAGENT_DONOTSPLIT pH = 4 can_synth = TRUE @@ -122,9 +84,9 @@ color = "#f9b9bc" // rgb: , 0, 255 taste_description = "dewicious degenyewacy" metabolization_rate = 0.5 * REAGENTS_METABOLISM - InverseChemVal = 0 + inverse_chem_val = 0 var/obj/item/organ/tongue/nT - DoNotSplit = TRUE + chemical_flags = REAGENT_DONOTSPLIT pH = 5 var/obj/item/organ/tongue/T can_synth = TRUE @@ -206,14 +168,14 @@ //Writen by Trilby!! Embellsished a little by me. /datum/reagent/fermi/nanite_b_gone - name = "Naninte bane" + name = "Nanite bane" id = "nanite_b_gone" description = "A stablised EMP that is highly volatile, shocking small nano machines that will kill them off at a rapid rate in a patient's system." color = "#708f8f" overdose_threshold = 15 - ImpureChem = "nanite_b_goneTox" //If you make an inpure chem, it stalls growth - InverseChemVal = 0.25 - InverseChem = "nanite_b_goneTox" //At really impure vols, it just becomes 100% inverse + impure_chem = "nanite_b_goneTox" //If you make an inpure chem, it stalls growth + inverse_chem_val = 0.25 + inverse_chem = "nanite_b_goneTox" //At really impure vols, it just becomes 100% inverse taste_description = "what can only be described as licking a battery." pH = 9 can_synth = FALSE @@ -236,7 +198,7 @@ //empulse((get_turf(C)), 3, 2)//So the nanites randomize var/atom/T = C T.emp_act(EMP_HEAVY) - to_chat(C, "The nanites short circuit within your system!") + to_chat(C, "You feel a strange tingling sensation come from your core.") if(isnull(N)) return ..() N.nanite_volume = -2 @@ -246,10 +208,11 @@ O.emp_act(EMP_HEAVY) /datum/reagent/fermi/nanite_b_goneTox - name = "Naninte bain" + name = "Electromagnetic crystals" id = "nanite_b_goneTox" - description = "Poorly made, and shocks you!" - metabolization_rate = 1 + description = "Causes items upon the patient to sometimes short out, as well as causing a shock in the patient, if the residual charge between the crystals builds up to sufficient quantities" + metabolization_rate = 0.5 + chemical_flags = REAGENT_INVISIBLE //Increases shock events. /datum/reagent/fermi/nanite_b_goneTox/on_mob_life(mob/living/carbon/C)//Damages the taker if their purity is low. Extended use of impure chemicals will make the original die. (thus can't be spammed unless you've very good) @@ -287,8 +250,7 @@ if((method==VAPOR) && (!C.wear_mask)) if(prob(20)) to_chat(C, "You can feel your lungs burning!") - var/obj/item/organ/lungs/L = C.getorganslot(ORGAN_SLOT_LUNGS) - L.adjustLungLoss(acidstr*2, C) + C.adjustOrganLoss(ORGAN_SLOT_LUNGS, acidstr*2) C.apply_damage(acidstr/5, BURN, target) C.acid_act(acidstr, volume) ..() @@ -315,7 +277,7 @@ name = "Fermis Test Reagent" id = "fermiTest" description = "You should be really careful with this...! Also, how did you get this?" - addProc = TRUE + chemical_flags = REAGENT_FORCEONNEW can_synth = FALSE /datum/reagent/fermi/fermiTest/on_new(datum/reagents/holder) @@ -346,22 +308,6 @@ playsound(get_turf(M), 'modular_citadel/sound/voice/merowr.ogg', 50, 1) holder.clear_reagents() -/datum/reagent/fermi/fermiTox - name = "FermiTox" - id = "fermiTox" - description = "You should be really careful with this...! Also, how did you get this? You shouldn't have this!" - data = "merge" - color = "FFFFFF" - can_synth = FALSE - -//I'm concerned this is too weak, but I also don't want deathmixes. -/datum/reagent/fermi/fermiTox/on_mob_life(mob/living/carbon/C, method) - if(C.dna && istype(C.dna.species, /datum/species/jelly)) - C.adjustToxLoss(-2) - else - C.adjustToxLoss(2) - ..() - /datum/reagent/fermi/acidic_buffer name = "Acidic buffer" id = "acidic_buffer" @@ -372,9 +318,11 @@ //Consumes self on addition and shifts pH /datum/reagent/fermi/acidic_buffer/on_new(datapH) + if(holder.has_reagent("stabilizing_agent")) + return ..() data = datapH if(LAZYLEN(holder.reagent_list) == 1) - return + return ..() holder.pH = ((holder.pH * holder.total_volume)+(pH * (volume)))/(holder.total_volume + (volume)) var/list/seen = viewers(5, get_turf(holder)) for(var/mob/M in seen) @@ -392,9 +340,11 @@ can_synth = TRUE /datum/reagent/fermi/basic_buffer/on_new(datapH) + if(holder.has_reagent("stabilizing_agent")) + return ..() data = datapH if(LAZYLEN(holder.reagent_list) == 1) - return + return ..() holder.pH = ((holder.pH * holder.total_volume)+(pH * (volume)))/(holder.total_volume + (volume)) var/list/seen = viewers(5, get_turf(holder)) for(var/mob/M in seen) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm index b717948a..fd0770d5 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm @@ -16,9 +16,9 @@ var/obj/item/organ/lungs/L = C.getorganslot(ORGAN_SLOT_LUNGS) if(T) - T.adjustTongueLoss(C, -2)//Fix the inputs me! + T.applyOrganDamage(-2) if(L) - L.adjustLungLoss(-5, C) + C.adjustOrganLoss(ORGAN_SLOT_LUNGS, -5) C.adjustOxyLoss(-2) else C.adjustOxyLoss(-10) @@ -65,9 +65,9 @@ holder.remove_reagent(src.id, "10") if(!C.getorganslot(ORGAN_SLOT_LUNGS)) - var/obj/item/organ/lungs/L = new() + var/obj/item/organ/lungs/yamerol/L = new() L.Insert(C) - to_chat(C, "You feel your lungs reform in your chest.") + to_chat(C, "You feel the yamerol merge in your chest.") holder.remove_reagent(src.id, "10") C.adjustOxyLoss(-3) @@ -86,10 +86,62 @@ var/obj/item/organ/lungs/L = C.getorganslot(ORGAN_SLOT_LUNGS) if(T) - T.adjustTongueLoss(C, 1) + T.applyOrganDamage(1) if(L) - L.adjustLungLoss(4, C) + C.adjustOrganLoss(ORGAN_SLOT_LUNGS, 4) C.adjustOxyLoss(3) else C.adjustOxyLoss(10) ..() + +/datum/reagent/synthtissue + name = "Synthtissue" + id = "synthtissue" + description = "Synthetic tissue used for grafting onto damaged organs during surgery, or for treating limb damage. Has a very tight growth window between 305-320, any higher and the temperature will cause the cells to die. Additionally, growth time is considerably long, so chemists are encouraged to leave beakers with said reaction ongoing, while they tend to their other duties." + pH = 7.6 + metabolization_rate = 0.1 + data = list("grown_volume" = 0, "injected_vol" = 0) + +/datum/reagent/synthtissue/reaction_mob(mob/living/M, method=TOUCH, reac_volume,show_message = 1) + if(iscarbon(M)) + var/target = M.zone_selected + if (M.stat == DEAD) + show_message = 0 + if(method in list(PATCH, TOUCH)) + M.apply_damage(reac_volume*-1.5, BRUTE, target) + M.apply_damage(reac_volume*-1.5, BURN, target) + if(show_message) + to_chat(M, "You feel your [target] heal! It stings like hell!") + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "painful_medicine", /datum/mood_event/painful_medicine) + if(method==INJECT) + data["injected_vol"] = data["injected_vol"] + reac_volume + ..() + +/datum/reagent/synthtissue/on_mob_life(mob/living/carbon/C) + if(!iscarbon(C)) + return ..() + if(data["injected_vol"] > 14) + if(data["grown_volume"] > 175) //I don't think this is even possible, but damn to I want to see if someone can (bare in mind it takes 2s to grow 0.05u) + if(volume >= 14) + if(C.regenerate_organs(only_one = TRUE)) + C.reagents.remove_reagent(id, 15) + to_chat(C, "You feel something reform inside of you!") + + data["injected_vol"] -= metabolization_rate + ..() + +/datum/reagent/synthtissue/on_merge(passed_data) + if(!passed_data) + return ..() + if(passed_data["grown_volume"] > data["grown_volume"]) + data["grown_volume"] = passed_data["grown_volume"] + ..() + +/datum/reagent/synthtissue/on_new(passed_data) + if(!passed_data) + return ..() + if(passed_data["grown_volume"] > data["grown_volume"]) + data["grown_volume"] = passed_data["grown_volume"] + ..() + +//NEEDS ON_MOB_DEAD() \ No newline at end of file diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index 078e1c8a..9e009390 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -2,7 +2,7 @@ mix_sound = 'sound/effects/bubbles.ogg' //Called for every reaction step -/datum/chemical_reaction/fermi/proc/FermiCreate(holder) +/datum/chemical_reaction/proc/FermiCreate(datum/reagents/holder, added_volume, added_purity) return //Called when reaction STOP_PROCESSING diff --git a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm index c4c1cff1..0e823a65 100644 --- a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm +++ b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm @@ -138,16 +138,16 @@ /datum/reagent/drug/aphrodisiacplus/addiction_act_stage2(mob/living/M) if(prob(30)) - M.adjustBrainLoss(2) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2) ..() /datum/reagent/drug/aphrodisiacplus/addiction_act_stage3(mob/living/M) if(prob(30)) - M.adjustBrainLoss(3) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3) ..() /datum/reagent/drug/aphrodisiacplus/addiction_act_stage4(mob/living/M) if(prob(30)) - M.adjustBrainLoss(4) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 4) ..() /datum/reagent/drug/aphrodisiacplus/overdose_process(mob/living/M) diff --git a/modular_citadel/code/modules/vore/resizing/sizechemicals.dm b/modular_citadel/code/modules/vore/resizing/sizechemicals.dm index 1164bf65..f83ba2ce 100644 --- a/modular_citadel/code/modules/vore/resizing/sizechemicals.dm +++ b/modular_citadel/code/modules/vore/resizing/sizechemicals.dm @@ -84,7 +84,7 @@ return /datum/reagent/medicine/sizeoxadone/overdose_process(mob/living/M) - M.adjustBrainLoss(1) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1) M.adjustToxLoss(1) ..() . = 1 diff --git a/tgstation.dme b/tgstation.dme index c80bb0fb..17e8524a 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -2706,12 +2706,15 @@ #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\eye_surgery.dm" +#include "code\modules\surgery\graft_synthtissue.dm" #include "code\modules\surgery\helpers.dm" #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\nutcracker.dm" #include "code\modules\surgery\organ_manipulation.dm"