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 01/12] 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" From 6a0cb72b6ac30531b6e32876ba8c009caf848ab9 Mon Sep 17 00:00:00 2001 From: shellspeed1 <46614774+shellspeed1@users.noreply.github.com> Date: Tue, 15 Oct 2019 11:59:46 -0700 Subject: [PATCH 02/12] error fixing --- code/_globalvars/bitfields.dm | 1 - code/game/objects/items/devices/scanners.dm | 30 +-- code/modules/mob/living/brain/MMI.dm | 2 +- code/modules/mob/living/brain/brain_item.dm | 2 +- .../modules/mob/living/carbon/damage_procs.dm | 7 +- .../mob/living/carbon/human/species.dm | 252 ++---------------- .../carbon/human/species_types/mothmen.dm | 1 - code/modules/mob/living/damage_procs.dm | 1 + .../chemistry/reagents/alcohol_reagents.dm | 51 +--- .../chemistry/reagents/other_reagents.dm | 236 ++++------------ .../reagents/chemistry/reagents/MKUltra.dm | 12 +- .../reagents/chemistry/reagents/SDGF.dm | 42 ++- .../chemistry/reagents/fermi_reagents.dm | 99 +++++-- .../modules/vore/resizing/sizechemicals.dm | 2 +- 14 files changed, 195 insertions(+), 543 deletions(-) diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 8a2bbf82..b5cd75a5 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -177,7 +177,6 @@ GLOBAL_LIST_INIT(bitfields, list( "CAN_CARRY" = CAN_CARRY, "CAN_RESIST" = CAN_RESIST ), - )) "organ_flags" = list( "ORGAN_SYNTHETIC" = ORGAN_SYNTHETIC, diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 81bd44ca..5bc03ab5 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -189,7 +189,6 @@ SLIME SCANNER if(Br) 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) @@ -198,6 +197,7 @@ SLIME SCANNER msg += "\tBrain damage detected.\n" if(iscarbon(M)) + var/mob/living/carbon/C = M if(LAZYLEN(C.get_traumas())) var/list/trauma_text = list() @@ -219,7 +219,8 @@ SLIME SCANNER msg += "\tBrain Activity Level: [(200 - M.getOrganLoss(ORGAN_SLOT_BRAIN))/2]%.\n" if(M.radiation) msg += "\tSubject is irradiated.\n" - msg += "\tRadiation Level: [M.radiation] rad\n" + if(advanced) + msg += "\tRadiation Level: [M.radiation]%.\n" if(advanced && M.hallucinating()) msg += "\tSubject is hallucinating.\n" @@ -300,7 +301,7 @@ 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 +//Organ damages report if(ishuman(M)) var/mob/living/carbon/human/H = M var/minor_damage @@ -353,7 +354,6 @@ SLIME SCANNER msg += "[major_damage]" msg += "[max_damage]" - // Species and body temperature if(ishuman(M)) var/mob/living/carbon/human/H = M @@ -441,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.chemical_flags & REAGENT_INVISIBLE) + if(R.invisible) continue reagents += R @@ -460,21 +460,6 @@ 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) @@ -683,10 +668,9 @@ SLIME SCANNER to_chat(user, "[target] is empty!") if(cached_scan_results && cached_scan_results["fusion"]) //notify the user if a fusion reaction was detected - var/fusion_power = round(cached_scan_results["fusion"], 0.01) - var/tier = fusionpower2text(fusion_power) + var/instability = round(cached_scan_results["fusion"], 0.01) to_chat(user, "Large amounts of free neutrons detected in the air indicate that a fusion reaction took place.") - to_chat(user, "Power of the last fusion reaction: [fusion_power]\n This power indicates it was a [tier]-tier fusion reaction.") + to_chat(user, "Instability of the last fusion reaction: [instability].") return //slime scanner diff --git a/code/modules/mob/living/brain/MMI.dm b/code/modules/mob/living/brain/MMI.dm index 47f44bca..d84ba0d7 100644 --- a/code/modules/mob/living/brain/MMI.dm +++ b/code/modules/mob/living/brain/MMI.dm @@ -57,7 +57,7 @@ newbrain.brainmob = null brainmob.forceMove(src) brainmob.container = src - if(!(newbrain.organ_flags & ORGAN_FAILING)) // 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 diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index 41a89440..17f81981 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -42,7 +42,7 @@ if(brainmob.mind) brainmob.mind.transfer_to(C) else - brainmob.transfer_ckey(C) + C.key = brainmob.key QDEL_NULL(brainmob) diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm index 219c5ba7..cc0c0d74 100644 --- a/code/modules/mob/living/carbon/damage_procs.dm +++ b/code/modules/mob/living/carbon/damage_procs.dm @@ -40,13 +40,13 @@ update_damage_overlays() else adjustStaminaLoss(damage * hit_percent) - if(BRAIN) - adjustBrainLoss(damage * hit_percent) //citadel code if(AROUSAL) adjustArousalLoss(damage * hit_percent) return TRUE + + //These procs fetch a cumulative total damage from all bodyparts /mob/living/carbon/getBruteLoss() var/amount = 0 @@ -62,6 +62,7 @@ amount += BP.burn_dam return amount + /mob/living/carbon/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE) if(!forced && (status_flags & GODMODE)) return FALSE @@ -155,6 +156,7 @@ O.applyOrganDamage(amount, maximum) O.onDamage(amount, maximum) + //////////////////////////////////////////// //Returns a list of damaged bodyparts @@ -296,3 +298,4 @@ if(B) var/adjusted_amount = amount - B.get_brain_damage() B.adjust_brain_damage(adjusted_amount, null) +*/ diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 01f7ecb6..33b419de 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -1,7 +1,6 @@ // 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 @@ -9,35 +8,13 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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 - //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/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)) 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) @@ -102,7 +79,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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 // @@ -121,7 +98,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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" @@ -153,10 +129,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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) //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. +/datum/species/proc/qualifies_for_rank(rank, list/features) + if(rank in GLOB.command_positions) + return 0 + return 1 //Will regenerate missing organs /datum/species/proc/regenerate_organs(mob/living/carbon/C,datum/species/old_species,replace_current=TRUE) @@ -284,7 +260,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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" || C.dna.features["legs"] == "Avian")) + if(("legs" in C.dna.species.mutant_bodyparts) && C.dna.features["legs"] == "Digitigrade Legs") species_traits += DIGITIGRADE if(DIGITIGRADE in species_traits) C.Digitigrade_Leg_Swap(FALSE) @@ -318,6 +294,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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 @@ -328,11 +306,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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 @@ -344,11 +317,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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) @@ -421,10 +389,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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) @@ -482,11 +446,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) else hair_overlay.color = forced_colour hair_overlay.alpha = hair_alpha - - 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(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(hair_overlay.icon) standing += hair_overlay @@ -507,11 +469,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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_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] - + 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] standing += lip_overlay // eyes @@ -524,11 +484,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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_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] - + 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] standing += eye_overlay //Underwear, Undershirts & Socks @@ -571,7 +529,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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) @@ -654,10 +612,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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 @@ -761,14 +715,12 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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("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("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("caps") S = GLOB.caps_list[H.dna.features["caps"]] if("ipc_screen") @@ -865,8 +817,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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 @@ -883,11 +833,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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) @@ -900,10 +845,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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 @@ -941,14 +882,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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 @@ -981,13 +914,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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 @@ -1395,9 +1321,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(!istype(J) && istype(C)) J = C.jetpack if(istype(J) && J.full_speed && J.allow_thrust(0.01, H)) //Prevents stacking - . -= 0.4 + . -= 2 else if(istype(T) && T.allow_thrust(0.01, H)) - . -= 0.4 + . -= 2 if(!ignoreslow && gravity) if(H.wear_suit) @@ -1777,7 +1703,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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 && !/datum/antagonist/gang/boss) + var/datum/antagonist/gang/gang = H.mind.has_antag_datum(/datum/antagonist/gang/) if(rev) rev.remove_revolutionary(FALSE, user) if(gang) @@ -1813,130 +1739,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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 diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm index d15d9893..3ad2a4bd 100644 --- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm +++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm @@ -14,7 +14,6 @@ liked_food = VEGETABLES | DAIRY disliked_food = FRUIT | GROSS toxic_food = MEAT | RAW - mutanteyes = /obj/item/organ/eyes/moth /datum/species/moth/on_species_gain(mob/living/carbon/C) . = ..() diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index ef92a04c..91161175 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -57,6 +57,7 @@ if(STAMINA) return getStaminaLoss() + /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) return 0 diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index 94aca411..2445bd29 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -1373,7 +1373,6 @@ 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 @@ -1383,10 +1382,6 @@ 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)) @@ -1395,12 +1390,12 @@ All effects don't start immediately, but rather get worse over time; the rate is M.set_drugginess(50) M.dizziness +=2 M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1*REM, 150) - if(prob(20) && !holder.has_reagent("neuroweak")) + if(prob(20)) M.adjustStaminaLoss(10) M.drop_all_held_items() to_chat(M, "You cant feel your hands!") if(current_cycle > 5) - if(prob(20) && !holder.has_reagent("neuroweak")) + if(prob(20)) var/t = pickt() ADD_TRAIT(M, t, type) M.adjustStaminaLoss(10) @@ -1422,25 +1417,6 @@ 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" @@ -2146,29 +2122,6 @@ 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/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 95b4a33c..fe309b42 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -3,7 +3,6 @@ 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 @@ -201,20 +200,22 @@ 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) - if(iscultist(L)) - for(var/datum/action/innate/cult/blood_magic/BM in L.actions) - BM.holy_dispel = FALSE - return ..() + ..() + +/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") + ..() /datum/reagent/water/holywater/on_mob_life(mob/living/carbon/M) if(!data) @@ -223,11 +224,9 @@ M.jitteriness = min(M.jitteriness+4,10) if(iscultist(M)) for(var/datum/action/innate/cult/blood_magic/BM in M.actions) - 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) + 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 @@ -537,12 +536,12 @@ race = /datum/species/fly mutationtext = "The pain subsides. You feel... buzzy." -/datum/reagent/mutationtoxin/insect - name = "Insect Mutation Toxin" +/datum/reagent/mutationtoxin/moth + name = "Moth Mutation Toxin" id = "mothmutationtoxin" description = "A glowing toxin." color = "#5EFF3B" //RGB: 94, 255, 59 - race = /datum/species/insect + race = /datum/species/moth mutationtext = "The pain subsides. You feel... attracted to light." /datum/reagent/mutationtoxin/pod @@ -1223,7 +1222,7 @@ description = "A perfluoronated sulfonic acid that forms a foam when mixed with water." color = "#9E6B38" // rgb: 158, 107, 56 taste_description = "metal" - pH = 11 + pH = 13 /datum/reagent/foaming_agent// Metal foaming agent. This is lithium hydride. Add other recipes (e.g. LiH + H2O -> LiOH + H2) eventually. name = "Foaming agent" @@ -1232,7 +1231,7 @@ reagent_state = SOLID color = "#664B63" // rgb: 102, 75, 99 taste_description = "metal" - pH = 11.5 + pH = 12.5 /datum/reagent/smart_foaming_agent //Smart foaming agent. Functions similarly to metal foam, but conforms to walls. name = "Smart foaming agent" @@ -1329,10 +1328,12 @@ ..() ADD_TRAIT(L, TRAIT_STUNIMMUNE, id) ADD_TRAIT(L, TRAIT_SLEEPIMMUNE, id) + ADD_TRAIT(L, TRAIT_NOSLIPALL, id) /datum/reagent/stimulum/on_mob_end_metabolize(mob/living/L) REMOVE_TRAIT(L, TRAIT_STUNIMMUNE, id) REMOVE_TRAIT(L, TRAIT_SLEEPIMMUNE, id) + REMOVE_TRAIT(L, TRAIT_NOSLIPALL, id) ..() /datum/reagent/stimulum/on_mob_life(mob/living/carbon/M) @@ -1359,6 +1360,11 @@ REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id) ..() +/datum/reagent/nitryl/on_mob_life(mob/living/carbon/M) + current_cycle++ + holder.remove_reagent(id, 0.99) //Gives time for the next tick of life(). + . = TRUE //Update status effects. + /////////////////////////Coloured Crayon Powder//////////////////////////// //For colouring in /proc/mix_color_from_reagents @@ -1446,6 +1452,9 @@ color = "#FFFFFF" // white random_color_list = list("#FFFFFF") //doesn't actually change appearance at all + + + //////////////////////////////////Hydroponics stuff/////////////////////////////// /datum/reagent/plantnutriment @@ -1487,8 +1496,16 @@ tox_prob = 15 pH = 1 + + + + + + // GOON OTHERS + + /datum/reagent/oil name = "Oil" id = "oil" @@ -1520,6 +1537,20 @@ 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" @@ -1652,7 +1683,7 @@ reagent_state = LIQUID color = "#FFFFD6" // very very light yellow taste_description = "alkali" //who put ACID for NaOH ???? - pH = 11.9 + pH = 13 /datum/reagent/drying_agent name = "Drying agent" @@ -1673,143 +1704,6 @@ 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 @@ -2116,7 +2010,7 @@ can_synth = FALSE var/datum/dna/original_dna var/reagent_ticks = 0 - chemical_flags = REAGENT_INVISIBLE + invisible = TRUE /datum/reagent/changeling_string/on_mob_metabolize(mob/living/carbon/C) if(C && C.dna && data["desired_dna"]) @@ -2144,25 +2038,3 @@ /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/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm index 4e80f42d..76d0951d 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm @@ -136,6 +136,7 @@ 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 @@ -143,19 +144,20 @@ Creating a chem with a low purity will make you permanently fall in love with so var/creatorName var/mob/living/creator pH = 10 - chemical_flags = REAGENT_ONMOBMERGE | REAGENT_DONOTSPLIT //Procs on_mob_add when merging into a human + OnMobMergeCheck = TRUE //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 makes you like Fermis a little too much. Unobtainable and due to be removed from the wiki." + 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." 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" @@ -298,13 +300,13 @@ Creating a chem with a low purity will make you permanently fall in love with so //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 = "Gaseous MKUltra" + name = "MKUltra" id = "enthrallExplo" - 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." + 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?" color = "#2C051A" // rgb: , 0, 255 metabolization_rate = 0.1 taste_description = "synthetic chocolate, a base tone of alcohol, and high notes of roses." - chemical_flags = REAGENT_DONOTSPLIT + DoNotSplit = TRUE can_synth = FALSE var/mob/living/carbon/love diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm index a7e1ac8e..0924f00f 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 - impure_chem = "SDGFtox" - inverse_chem_val = 0.5 - inverse_chem = "SDZF" + ImpureChem = "SDGFtox" + InverseChemVal = 0.5 + InverseChem = "SDZF" can_synth = TRUE @@ -81,19 +81,9 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING SM.real_name = M.real_name M.dna.transfer_identity(SM) SM.updateappearance(mutcolor_update=1) - - - 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 ..() + 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 SM.mind.enslave_mind_to_creator(M) //If they're a zombie, they can try to negate it with this. @@ -280,9 +270,8 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING //Unobtainable, used in clone spawn. /datum/reagent/fermi/SDGFheal - name = "synthetic-derived healing factor" + name = "synthetic-derived growth 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 @@ -295,30 +284,29 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING ..() //Unobtainable, used if SDGF is impure but not too impure -/datum/reagent/impure/SDGFtox - name = "Synthetic-derived apoptosis factor" +/datum/reagent/fermi/SDGFtox + name = "synthetic-derived growth factor" id = "SDGFtox" - 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. + 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. metabolization_rate = 1 can_synth = FALSE -/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) +/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) M.blood_volume -= 10 M.adjustCloneLoss(2, 0) ..() //Fail state of SDGF -/datum/reagent/impure/SDZF - name = "synthetic-derived zombie factor" +/datum/reagent/fermi/SDZF + name = "synthetic-derived growth factor" id = "SDZF" - 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." + 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?" color = "#a502e0" // rgb: 96, 0, 255 metabolization_rate = 0.5 * REAGENTS_METABOLISM var/startHunger can_synth = TRUE - chemical_flags = REAGENT_SNEAKYNAME -/datum/reagent/impure/SDZF/on_mob_life(mob/living/carbon/M) //If you're bad at fermichem, turns your clone into a zombie instead. +/datum/reagent/fermi/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 4acfda05..a7c4ea00 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -6,20 +6,58 @@ 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 //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -39,7 +77,7 @@ taste_description = "like jerky, whiskey and an off aftertaste of a crypt." metabolization_rate = 0.2 overdose_threshold = 25 - chemical_flags = REAGENT_DONOTSPLIT + DoNotSplit = TRUE pH = 4 can_synth = TRUE @@ -84,9 +122,9 @@ color = "#f9b9bc" // rgb: , 0, 255 taste_description = "dewicious degenyewacy" metabolization_rate = 0.5 * REAGENTS_METABOLISM - inverse_chem_val = 0 + InverseChemVal = 0 var/obj/item/organ/tongue/nT - chemical_flags = REAGENT_DONOTSPLIT + DoNotSplit = TRUE pH = 5 var/obj/item/organ/tongue/T can_synth = TRUE @@ -168,14 +206,14 @@ //Writen by Trilby!! Embellsished a little by me. /datum/reagent/fermi/nanite_b_gone - name = "Nanite bane" + name = "Naninte 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 - 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 + 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 taste_description = "what can only be described as licking a battery." pH = 9 can_synth = FALSE @@ -198,7 +236,7 @@ //empulse((get_turf(C)), 3, 2)//So the nanites randomize var/atom/T = C T.emp_act(EMP_HEAVY) - to_chat(C, "You feel a strange tingling sensation come from your core.") + to_chat(C, "The nanites short circuit within your system!") if(isnull(N)) return ..() N.nanite_volume = -2 @@ -208,11 +246,10 @@ O.emp_act(EMP_HEAVY) /datum/reagent/fermi/nanite_b_goneTox - name = "Electromagnetic crystals" + name = "Naninte bain" id = "nanite_b_goneTox" - 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 + description = "Poorly made, and shocks you!" + metabolization_rate = 1 //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) @@ -277,7 +314,7 @@ name = "Fermis Test Reagent" id = "fermiTest" description = "You should be really careful with this...! Also, how did you get this?" - chemical_flags = REAGENT_FORCEONNEW + addProc = TRUE can_synth = FALSE /datum/reagent/fermi/fermiTest/on_new(datum/reagents/holder) @@ -308,6 +345,22 @@ 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" @@ -318,11 +371,9 @@ //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) @@ -340,11 +391,9 @@ 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/vore/resizing/sizechemicals.dm b/modular_citadel/code/modules/vore/resizing/sizechemicals.dm index f83ba2ce..1f5dbf2b 100644 --- a/modular_citadel/code/modules/vore/resizing/sizechemicals.dm +++ b/modular_citadel/code/modules/vore/resizing/sizechemicals.dm @@ -12,7 +12,7 @@ overdose_threshold = 20 /datum/reagent/medicine/macrocillin/on_mob_life(mob/living/M, method=INGEST) - for(var/size in list(SIZESCALE_SMALL, SIZESCALE_NORMAL, SIZESCALE_BIG, SIZESCALE_HUGE)) + for(var/size in list(SIZESCALE_SMALL, SIZESCALE_NORMAL, SIZESCALE_BIG, SIZESCALE_HUGE)) if(M.size_multiplier < size) M.sizescale(size) M << "You grow!" From 984417ea6337be7e5b53c781d7a7df49a1358805 Mon Sep 17 00:00:00 2001 From: shellspeed1 <46614774+shellspeed1@users.noreply.github.com> Date: Tue, 15 Oct 2019 13:42:18 -0700 Subject: [PATCH 03/12] oh god oh fuck oh god --- code/__DEFINES/misc.dm | 2 +- code/__DEFINES/obj_flags.dm | 2 +- code/game/objects/items/storage/backpack.dm | 3 ++ .../structures/crates_lockers/crates.dm | 19 ++++++++++ code/modules/mob/living/brain/brain_item.dm | 5 ++- .../modules/mob/living/carbon/alien/organs.dm | 1 + code/modules/mob/living/taste.dm | 2 - .../reagents/chemistry/recipes/medicine.dm | 1 + .../research/designs/medical_designs.dm | 7 ++++ code/modules/research/techweb/all_nodes.dm | 2 +- code/modules/surgery/advanced/toxichealing.dm | 37 +++++++++++++++++++ code/modules/surgery/coronary_bypass.dm | 2 +- code/modules/surgery/embalming.dm | 30 +++++++++++++++ .../reagents/chemistry/reagents/healing.dm | 7 +++- tgstation.dme | 2 + 15 files changed, 113 insertions(+), 9 deletions(-) create mode 100644 code/modules/surgery/advanced/toxichealing.dm create mode 100644 code/modules/surgery/embalming.dm diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 7821e5ad..97886591 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 960 +#define DEFIB_TIME_LIMIT 1500 #define DEFIB_TIME_LOSS 60 // Diagonal movement diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm index a365d13b..6aad30b7 100644 --- a/code/__DEFINES/obj_flags.dm +++ b/code/__DEFINES/obj_flags.dm @@ -46,4 +46,4 @@ #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 +#define ORGAN_NO_SPOIL (1<<5) //Do not spoil under any circumstances \ No newline at end of file diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index 51ebdcd7..30e0c7df 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -357,6 +357,7 @@ new /obj/item/surgical_drapes(src) new /obj/item/clothing/mask/surgical(src) new /obj/item/razor(src) + new /obj/item/reagent_containers/medspray/sterilizine(src) /obj/item/storage/backpack/duffelbag/sec name = "security duffel bag" @@ -377,6 +378,7 @@ new /obj/item/cautery(src) new /obj/item/surgical_drapes(src) new /obj/item/clothing/mask/surgical(src) + new /obj/item/reagent_containers/medspray/sterilizine(src) /obj/item/storage/backpack/duffelbag/engineering name = "industrial duffel bag" @@ -470,6 +472,7 @@ new /obj/item/mmi/syndie(src) new /obj/item/implantcase(src) new /obj/item/implanter(src) + new /obj/item/reagent_containers/medspray/sterilizine(src) /obj/item/storage/backpack/duffelbag/syndie/surgery_adv name = "advanced surgery duffel bag" diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index dd484b3f..36ff16d5 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -99,6 +99,25 @@ name = "freezer" icon_state = "freezer" + //Snowflake organ freezer code +//Order is important, since we check source, we need to do the check whenever we have all the organs in the crate + +/obj/structure/closet/crate/freezer/open() + recursive_organ_check(src) + ..() + +/obj/structure/closet/crate/freezer/close() + ..() + recursive_organ_check(src) + +/obj/structure/closet/crate/freezer/Destroy() + recursive_organ_check(src) + ..() + +/obj/structure/closet/crate/freezer/Initialize() + . = ..() + recursive_organ_check(src) + /obj/structure/closet/crate/freezer/blood name = "blood freezer" desc = "A freezer containing packs of blood." diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index 17f81981..1b421054 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -11,6 +11,7 @@ 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 + healing_factor = STANDARD_ORGAN_HEALING / 2 maxHealth = BRAIN_DAMAGE_DEATH low_threshold = 45 @@ -247,11 +248,13 @@ to_chat(owner, "The last spark of life in your brain fizzles out...") owner.death() brain_death = TRUE + return + ..() /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) diff --git a/code/modules/mob/living/carbon/alien/organs.dm b/code/modules/mob/living/carbon/alien/organs.dm index 155f2037..df1be454 100644 --- a/code/modules/mob/living/carbon/alien/organs.dm +++ b/code/modules/mob/living/carbon/alien/organs.dm @@ -1,6 +1,7 @@ /obj/item/organ/alien icon_state = "xgibmid2" var/list/alien_powers = list() + organ_flags = ORGAN_NO_SPOIL /obj/item/organ/alien/Initialize() . = ..() diff --git a/code/modules/mob/living/taste.dm b/code/modules/mob/living/taste.dm index 8b0c5465..e4d1aa94 100644 --- a/code/modules/mob/living/taste.dm +++ b/code/modules/mob/living/taste.dm @@ -52,13 +52,11 @@ switch(from.pH) if(11.5 to INFINITY) to_chat(src, "You taste a strong alkaline flavour!") - 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.applyOrganDamage(1) #undef DEFAULT_TASTE_SENSITIVITY diff --git a/code/modules/reagents/chemistry/recipes/medicine.dm b/code/modules/reagents/chemistry/recipes/medicine.dm index 11dd8b74..cbebf1fd 100644 --- a/code/modules/reagents/chemistry/recipes/medicine.dm +++ b/code/modules/reagents/chemistry/recipes/medicine.dm @@ -103,6 +103,7 @@ St.purity = 1 N.volume -= 0.002 St.data["grown_volume"] = St.data["grown_volume"] + added_volume + St.name = "[initial(St.name)] [round(St.data["grown_volume"], 0.1)]u colony" /datum/chemical_reaction/styptic_powder name = "Styptic Powder" diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index ee4e9eb6..1d822263 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -785,6 +785,13 @@ surgery = /datum/surgery/advanced/reconstruction research_icon_state = "surgery_chest" +/datum/design/surgery/surgery_toxinhealing + name = "Body Rejuvenation" + desc = "A surgical procedure that helps deal with oxygen deprecation, and treat toxic damaged. Works on corpses and alive alike without chemicals." + id = "surgery_toxinhealing" + surgery = /datum/surgery/advanced/toxichealing + research_icon_state = "surgery_chest" + /datum/design/surgery/revival name = "Revival" desc = "An experimental surgical procedure which involves reconstruction and reactivation of the patient's brain even long after death. The body must still be able to sustain life." diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index e351c8fb..7f333265 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -115,7 +115,7 @@ display_name = "Advanced Surgery" description = "When simple medicine doesn't cut it." prereq_ids = list("adv_biotech") - design_ids = list("surgery_lobotomy", "surgery_reconstruction", "organbox") + design_ids = list("surgery_lobotomy", "surgery_reconstruction","surgery_toxinhealing", "organbox",) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) export_price = 5000 diff --git a/code/modules/surgery/advanced/toxichealing.dm b/code/modules/surgery/advanced/toxichealing.dm new file mode 100644 index 00000000..998ca47b --- /dev/null +++ b/code/modules/surgery/advanced/toxichealing.dm @@ -0,0 +1,37 @@ +/datum/surgery/advanced/toxichealing + name = "Body Rejuvenation" + desc = "A surgical procedure that helps deal with oxygen deprivation, and treats parts damaged due to toxic compounds. Works on corpses and alive alike without chemicals." + steps = list(/datum/surgery_step/incise, + /datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/incise, + /datum/surgery_step/clamp_bleeders, + /datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/toxichealing, + /datum/surgery_step/close) + + species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + possible_locs = list(BODY_ZONE_CHEST) + requires_bodypart_type = 0 + +/datum/surgery_step/toxichealing + name = "rejuvenate body" + implements = list(TOOL_HEMOSTAT = 100, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15) + repeatable = TRUE + time = 25 + +/datum/surgery_step/toxichealing/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] starts rejuvenating some of [target]'s flesh back to life.", "You start knitting some of [target]'s flesh back to life.") + +/datum/surgery_step/toxichealing/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] fixes some of [target]'s wounds.", "You succeed in fixing some of [target]'s wounds.") + target.heal_bodypart_damage(0,0,30) //Heals stam + target.adjustToxLoss(-15, 0, TRUE) + target.adjustOxyLoss(-20, 0) + return TRUE + +/datum/surgery_step/toxichealing/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] screws up!", "You screwed up!") + target.take_bodypart_damage(25,0) + return FALSE \ No newline at end of file diff --git a/code/modules/surgery/coronary_bypass.dm b/code/modules/surgery/coronary_bypass.dm index 3e36e9aa..5aeeb322 100644 --- a/code/modules/surgery/coronary_bypass.dm +++ b/code/modules/surgery/coronary_bypass.dm @@ -15,7 +15,7 @@ //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, + implements = list(TOOL_SCALPEL = 90, /obj/item/melee/transforming/energy/sword = 45, /obj/item/kitchen/knife = 45, /obj/item/shard = 25) time = 16 diff --git a/code/modules/surgery/embalming.dm b/code/modules/surgery/embalming.dm new file mode 100644 index 00000000..d65abc9d --- /dev/null +++ b/code/modules/surgery/embalming.dm @@ -0,0 +1,30 @@ +/datum/surgery/embalming //Fast and easy way to husk bodys + name = "Embalming" + desc = "A surgical procedure that prevents a corpse from producing miasma." + steps = list(/datum/surgery_step/incise, + /datum/surgery_step/embalming, + /datum/surgery_step/close) + + species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + possible_locs = list(BODY_ZONE_CHEST) + requires_bodypart_type = 0 + +/datum/surgery_step/embalming + name = "embalming body" + implements = list(/obj/item/reagent_containers/syringe = 100, /obj/item/pen = 30) + time = 10 + chems_needed = list("drying_agent", "sterilizine") + require_all_chems = FALSE + +/datum/surgery_step/embalming/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] starts to embalm [target]'s body.", "You start embalming [target]'s body.") + +/datum/surgery_step/embalming/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] embalms [target]'s body.", "You succeed in embalming [target]'s body.") + ADD_TRAIT(target, TRAIT_HUSK, MAGIC_TRAIT) //Husk's prevent body smell + return FALSE + +/datum/surgery_step/embalming/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + user.visible_message("[user] screws up!", "You screwed up!") + ADD_TRAIT(target, TRAIT_NOCLONE, MAGIC_TRAIT) //That body is ruined, but still gives miasma + return FALSE \ No newline at end of file diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm index fd0770d5..d5c675ea 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm @@ -99,7 +99,7 @@ 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 + metabolization_rate = 0.05 // gives time to craft by lowing it from .1 data = list("grown_volume" = 0, "injected_vol" = 0) /datum/reagent/synthtissue/reaction_mob(mob/living/M, method=TOUCH, reac_volume,show_message = 1) @@ -114,7 +114,7 @@ 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 + data["injected_vol"] = reac_volume ..() /datum/reagent/synthtissue/on_mob_life(mob/living/carbon/C) @@ -135,6 +135,9 @@ return ..() if(passed_data["grown_volume"] > data["grown_volume"]) data["grown_volume"] = passed_data["grown_volume"] + if(iscarbon(holder.my_atom)) + data["injected_vol"] = data["injected_vol"] + passed_data["injected_vol"] + passed_data["injected_vol"] = 0 ..() /datum/reagent/synthtissue/on_new(passed_data) diff --git a/tgstation.dme b/tgstation.dme index 17e8524a..4027a9df 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -2708,6 +2708,7 @@ #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\embalming.dm" #include "code\modules\surgery\eye_surgery.dm" #include "code\modules\surgery\graft_synthtissue.dm" #include "code\modules\surgery\helpers.dm" @@ -2731,6 +2732,7 @@ #include "code\modules\surgery\advanced\pacification.dm" #include "code\modules\surgery\advanced\reconstruction.dm" #include "code\modules\surgery\advanced\revival.dm" +#include "code\modules\surgery\advanced\toxichealing.dm" #include "code\modules\surgery\advanced\viral_bonding.dm" #include "code\modules\surgery\advanced\bioware\bioware.dm" #include "code\modules\surgery\advanced\bioware\bioware_surgery.dm" From 187d22ca9b1071fabd64a9c1b88a554ae69bc4e4 Mon Sep 17 00:00:00 2001 From: shellspeed1 <46614774+shellspeed1@users.noreply.github.com> Date: Tue, 15 Oct 2019 14:55:52 -0700 Subject: [PATCH 04/12] sprite update and bug testing --- code/modules/surgery/organs/organ_internal.dm | 82 +++++++++++++++--- icons/obj/surgery.dmi | Bin 35071 -> 37061 bytes 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index a17d4906..991e5562 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -68,26 +68,82 @@ /obj/item/organ/proc/on_find(mob/living/finder) return -/obj/item/organ/process() - on_death() //Kinda hate doing it like this, but I really don't want to call process directly. +//Sources; life.dm process_organs +/obj/item/organ/proc/on_death() //Runs when outside AND inside. + decay() -/obj/item/organ/proc/on_death() //runs decay when outside of a person - if(organ_flags & (ORGAN_SYNTHETIC | ORGAN_FROZEN | ORGAN_NO_SPOIL)) +//Applys the slow damage over time decay +/obj/item/organ/proc/decay() + if(!can_decay()) + STOP_PROCESSING(SSobj, src) + return + is_cold() + if(organ_flags & ORGAN_FROZEN) return applyOrganDamage(maxHealth * decay_factor) +/obj/item/organ/proc/can_decay() + if(CHECK_BITFIELD(organ_flags, ORGAN_NO_SPOIL | ORGAN_SYNTHETIC | ORGAN_FAILING)) + return FALSE + return TRUE + +//Checks to see if the organ is frozen from temperature +/obj/item/organ/proc/is_cold() + var/freezing_objects = list(/obj/structure/closet/crate/freezer, /obj/structure/closet/secure_closet/freezer, /obj/structure/bodycontainer, /obj/item/autosurgeon) + if(istype(loc, /obj/))//Freezer of some kind, I hope. + if(is_type_in_list(loc, freezing_objects)) + if(!(organ_flags & ORGAN_FROZEN))//Incase someone puts them in when cold, but they warm up inside of the thing. (i.e. they have the flag, the thing turns it off, this rights it.) + organ_flags |= ORGAN_FROZEN + return TRUE + return + + var/local_temp + if(istype(loc, /turf/))//Only concern is adding an organ to a freezer when the area around it is cold. + var/turf/T = loc + var/datum/gas_mixture/enviro = T.return_air() + local_temp = enviro.temperature + + else if(istype(loc, /mob/) && !owner) + var/mob/M = loc + if(is_type_in_list(M.loc, freezing_objects)) + if(!(organ_flags & ORGAN_FROZEN)) + organ_flags |= ORGAN_FROZEN + return TRUE + var/turf/T = M.loc + var/datum/gas_mixture/enviro = T.return_air() + local_temp = enviro.temperature + + if(owner) + //Don't interfere with bodies frozen by structures. + if(is_type_in_list(owner.loc, freezing_objects)) + if(!(organ_flags & ORGAN_FROZEN)) + organ_flags |= ORGAN_FROZEN + return TRUE + local_temp = owner.bodytemperature + + if(!local_temp)//Shouldn't happen but in case + return + if(local_temp < 154)//I have a pretty shaky citation that states -120 allows indefinite cyrostorage + organ_flags |= ORGAN_FROZEN + return TRUE + organ_flags &= ~ORGAN_FROZEN + return FALSE + /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. + if(organ_flags & ORGAN_FAILING) + return + if(is_cold()) + return + ///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(!organ_flags & ORGAN_FAILING) + if(organ_flags & ORGAN_FAILING) if(status == ORGAN_ROBOTIC) . += "[src] seems to be broken!" return @@ -177,6 +233,8 @@ return low_threshold_passed else organ_flags &= ~ORGAN_FAILING + if(!owner)//Processing is stopped when the organ is dead and outside of someone. This hopefully should restart it if a removed organ is repaired outside of a body. + START_PROCESSING(SSobj, src) if(prev_damage > low_threshold && damage <= low_threshold) return low_threshold_cleared if(prev_damage > high_threshold && damage <= high_threshold) diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index eed8ee64e7228757af820e8285e69003dbe23d56..7af16bea0b318d14ef4fc6a0c0225cb411b42671 100644 GIT binary patch literal 37061 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Ξ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�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 qa8P}!&oa;>jvYOwf$CF60{ Date: Tue, 15 Oct 2019 16:28:43 -0700 Subject: [PATCH 05/12] fixed livers --- code/modules/mob/living/carbon/life.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index a6f5412e..2b6d8c55 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -30,10 +30,10 @@ if(stat != DEAD) handle_brain_damage() - +/* Bug cause? if(stat != DEAD) handle_liver() - +*/ if(stat == DEAD) stop_sound_channel(CHANNEL_HEARTBEAT) rot() From 3252b1c85b8bc54812caf1e06412c63fd03c8ec3 Mon Sep 17 00:00:00 2001 From: shellspeed1 <46614774+shellspeed1@users.noreply.github.com> Date: Tue, 15 Oct 2019 16:36:02 -0700 Subject: [PATCH 06/12] error fix 1 --- icons/obj/surgery.dmi | Bin 37061 -> 37898 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index 7af16bea0b318d14ef4fc6a0c0225cb411b42671..d55b329e56222c858e3f393f89fdf9f95fc081f9 100644 GIT binary patch delta 18583 zcmZ^KRao49)F$qf;_k(ZySsbw0;LppcL@cGyA*eKE$+p&xV!7%GT6@l+ue)3*o&F` zo=GM-Ir^SACj)sf5v4G3pMXejO0k&5Fv_6RWfk2z!oY9Rp8`Oa*Wh^fDTaw z(VB?4)p&2$=J9_db8_y;>F8w^0ysX z&-khj-8qEzq}LtAd76G`Ym`(bUZ`DQ>$A>4vW918LVdDM_xzQ*lrLJ}*ydE4oZt;Dg>LDaF=&g&vBuCZWXy|(+dcvTHvG4W8Pu$+dS11M zT=x-_sbMe6G`rwl$v6wj$w#`%Jmlpdp)Mu_{5iUgym^bI4+Te8)de_+3d;;kWHPo8A)Pn_J)r675h;X|Y4rJ(#UJl%>}*k)&SIFd9h29#NWfzKY; z2<7`Gb#~O2V1K|8eUd;hG=k`crIFTcSlCwPh9z{AiZ%9uAIC{zP~fMAE7wJIXemKW zPp3Si^TY<(jvj0VC>5bL<1FTCN1~IVq!nFwU%IPmL{cu)rhBH%gWxD1V~|qJQQm3F z@M+L%qTu@gp`m3MbNySGAfZ>%Qatqn_<5K3tr^r7E&&Ms$Tdpt5nP(Yb?({Q^EQAZ z66J|rTYc-n0r|s>xpk%I{n@6wOHRy~f%z-+OeQD)-jgfMgz}X*l`-LT#N?DdRc=?t zH)lh{dbDFWmOO$O;#C>3{SV$`*Ho<6B`*LF5gI$+9`N~@GrqyHl)dW5sLBzY(x7`` zYsq#LF5t-;R5S2>jsq!Tqs|~Xnc8;*h6auM_G1F7B>^@3zt3MUf-4yV=ZB562Fpp| zuWbe3o)oJu9jq>_lp<0VlAB0n_}{gOS{8|S)UPDkd#h`1x#(HqFj-_&;!h=1#lPuz z6J;$5YfensaBcn$Kyf#OE&pdGOeL!Auy>&Ar$am&QF0wI zFin;rOm0Yrl~M#QOUqy0yDtir6XYqAaj?E(#fcq-^^_w;Pz(g3yXkmnxzEo_8@k!G zw^g^bRo}H&+briSox%i?N)=+qVJW}_i+NLsvPVW7-EGFi5Y%IpkcFA@Xe!R==%}vO z!!dMaiMNK9N44rDG_qqVhq%$(Hi;@5M#g z=~~J&zT~`LLyPT|Stg%T;JJR2%knJ1E=2lXIuD>CRqaZlgD-6-|6QRhr`=`)*y$~c6&rQlcexxsIT`d1_OES%RVC`>`=bX z=gs5U!mDJjzTo2$$ST93`*oo!nyge^S2jL{DE?OJkT*q`zWUj3HGaMY^-GfBCOOsz zKr7bdc6Np2%h~g(O5uV!{|Zxv_R4wP{h UqIS!2|Y;u~(+H4=4+K!9h9ii}J0! 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 From 0593de4dd3d2b2717419730da3618a56a987bf62 Mon Sep 17 00:00:00 2001 From: shellspeed1 <46614774+shellspeed1@users.noreply.github.com> Date: Tue, 15 Oct 2019 16:50:29 -0700 Subject: [PATCH 07/12] aaaaa --- .../code/datums/status_effects/chems.dm | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index 1b188617..bbdfd120 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 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..!") + 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..!") 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,17 +55,21 @@ /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") - moveCalc = 1+((round(B.cached_size) - 9)/3) //Afffects how fast you move, and how often you can click. + + // 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. 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.") @@ -81,6 +85,7 @@ 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) @@ -93,6 +98,7 @@ 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) @@ -104,7 +110,7 @@ owner.next_move_modifier /= cachedmoveCalc owner.next_move_modifier *= value cachedmoveCalc = value - +*/ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /datum/status_effect/chem/penis_enlarger @@ -113,6 +119,7 @@ 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 @@ -129,8 +136,10 @@ 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.) @@ -138,12 +147,19 @@ 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!") + if (o.arousalloss > 32) // warning that your shaft is getting errect! + if(W == o.w_uniform || W == o.wear_suit ) + to_chat(M, "Your swelling cock begins to strain against your clothes tightly!") + if (o.arousalloss > 33) + 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 erect member is way to large to fit anything over! You will need to be flaccid again to wear clothes!") +/* switch(round(P.cached_length)) if(21) to_chat(o, "Your rascally willy has become a more managable size, liberating your movements.") @@ -154,13 +170,15 @@ 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 @@ -230,6 +248,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 - M.getOrganLoss(ORGAN_SLOT_BRAIN)//It's their brain! var/mob/living/carbon/human/H = owner if(H)//Prefs From 22e7d9dee88841a9c2101e6c1128db122e0a0589 Mon Sep 17 00:00:00 2001 From: shellspeed1 <46614774+shellspeed1@users.noreply.github.com> Date: Tue, 15 Oct 2019 17:10:52 -0700 Subject: [PATCH 08/12] fixes --- .../reagents/chemistry/reagents/medicine_reagents.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 951a77b0..bf04935f 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.setOrganLoss(ORGAN_SLOT_BRAIN, 0) + M.setOrganM.blood REMOVE_TRAITS_NOT_IN(M, list(SPECIES_TRAIT, ROUNDSTART_TRAIT, ORGAN_TRAIT)) M.set_blurriness(0) M.set_blindness(0) @@ -856,7 +856,6 @@ 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) @@ -1180,6 +1179,7 @@ overdose_threshold = 25 pH = 11 +//Hyperstation 13 nerf. /datum/reagent/medicine/earthsblood/on_mob_life(mob/living/carbon/M) M.adjustBruteLoss(-3 * REM, 0) M.adjustFireLoss(-3 * REM, 0) @@ -1187,7 +1187,7 @@ M.adjustToxLoss(-3 * REM, 0, TRUE) //Heals TOXINLOVERS 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(-13 * REM, 0) + M.adjustStaminaLoss(-3 * REM, 0) M.jitteriness = min(max(0, M.jitteriness + 3), 30) M.druggy = min(max(0, M.druggy + 10), 15) //See above ..() From b27d7c015586f0c52920623f51767c2801eddceb Mon Sep 17 00:00:00 2001 From: shellspeed1 <46614774+shellspeed1@users.noreply.github.com> Date: Fri, 18 Oct 2019 13:17:02 -0700 Subject: [PATCH 09/12] fermi said this was fine to comment out --- modular_citadel/code/datums/status_effects/chems.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index bbdfd120..099d4559 100644 --- a/modular_citadel/code/datums/status_effects/chems.dm +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -248,7 +248,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! + //var/obj/item/organ/brain/B = M.getorganslot(ORGAN_SLOT_BRAIN) //removing this, may cause some issues unsure. mental_capacity = 500 - M.getOrganLoss(ORGAN_SLOT_BRAIN)//It's their brain! var/mob/living/carbon/human/H = owner if(H)//Prefs From 0e0f5e642fae02dd53236b745e04a430f851898e Mon Sep 17 00:00:00 2001 From: shellspeed1 <46614774+shellspeed1@users.noreply.github.com> Date: Fri, 18 Oct 2019 13:24:24 -0700 Subject: [PATCH 10/12] Ooof --- code/modules/reagents/chemistry/reagents/medicine_reagents.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index bf04935f..0ad83652 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.setOrganM.blood + 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) From c4acea562983dd41e9949bd412e93f79ebaa7500 Mon Sep 17 00:00:00 2001 From: shellspeed1 <46614774+shellspeed1@users.noreply.github.com> Date: Fri, 18 Oct 2019 13:28:13 -0700 Subject: [PATCH 11/12] aaaa --- tgstation.dme | 1 + 1 file changed, 1 insertion(+) diff --git a/tgstation.dme b/tgstation.dme index 4027a9df..4424c492 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1961,6 +1961,7 @@ #include "code\modules\mob\living\carbon\death.dm" #include "code\modules\mob\living\carbon\emote.dm" #include "code\modules\mob\living\carbon\examine.dm" +#include "code\modules\mob\living\carbon\give.dm" #include "code\modules\mob\living\carbon\inventory.dm" #include "code\modules\mob\living\carbon\life.dm" #include "code\modules\mob\living\carbon\say.dm" From 1fb33fd598e93fac65f3bb5d7c90128805d7b441 Mon Sep 17 00:00:00 2001 From: shellspeed1 <46614774+shellspeed1@users.noreply.github.com> Date: Fri, 18 Oct 2019 13:29:10 -0700 Subject: [PATCH 12/12] maybe this will fix icons? --- icons/obj/surgery.dmi | Bin 37898 -> 37764 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index d55b329e56222c858e3f393f89fdf9f95fc081f9..0722b0793875764d78e4d3fbefeda5f252b311b0 100644 GIT binary patch literal 37764 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