From 224e8ef3f62625ff37dc980d1d580fa0b04c477c Mon Sep 17 00:00:00 2001 From: lessthanthree <83487515+lessthnthree@users.noreply.github.com> Date: Fri, 3 Feb 2023 17:01:55 -0800 Subject: [PATCH] [MANUAL MIRROR] Fixes plasmamen dying from liver damage when consuming plasma (#19074) Fixes plasmamen dying from liver damage when consuming plasma & other organic toxins, fixes plasma fixation for plasmamen and other species (#72644) ## About The Pull Request (edited for brevity---AS BEST I COULD, this turned into a lot more fixes than I set out to do) Instead of actually removing and metabolizing plasma in the liver, plasmamen were having plasma removed in a special handle_chemicals proc. The issue with this is that the liver's on_life proc would still fire off alongside it, detecting reagents in the mob (because handle_chemicals removes them little by little, at the same rate as the liver does). And because the liver code sees it as a toxin, it takes damage until it fails, leading to death as described in #72229. Not actually metabolizing plasma also led to another issue, as mentioned in #61424. The solution after much faffing around ended up being to move the actual reagent removal from handle_chemicals to the liver code, and to compare a toxin's affected_organtype to the liver's 'status' var to check if the toxin can damage the liver. There was currently only an ORGAN_ORGANIC and ORGAN_ROBOTIC defined for this, so I added ORGAN_MINERAL for plasma livers. It still works as before, but now the reagent will actually get all the metabolism procs called on it and be removed by the liver. And mobs with mineral livers (currently only plasmamen) do not suffer organ failure from processing organic toxins. Plasma fixation itself also needed some TLC, as it was likely written before liver damage was a thing. A lot of this comes down to rogue livers operating independently of their species now that I think about it... Fixed it so you no longer take liver damage from injected/consumed plasma when under the effects of the stage 4+ virus by making use of the new PLASMA_LOVER_METABOLISM liver trait. --- On top of that made it so that breathing in plasma through internals also contributes to plasma fixation healing. This is a slight buff to virology (especially for plasmamen) but it didn't seem busted or anything from my testing. Can lead to some interesting subtle approaches to healing for virologists as they can use internals rather than just flooding rooms with plasma... Some notes: - due to the way lungs are coded, non-plasma breathing species take a significant amount of tox damage from breathing plasma through internals in most cases and still need the right gas to be present so as to not asphyxiate. - During my testing this damage did not get healed fast enough to make it viable for humans to wear plasma internals as found in spawned tanks and such. - I did not play around with creating custom internals mixes of O2 and plasma but in theory that could possibly allow humans to heal faster than the tox damage is applied. I think the tox damage on breath is based on the amount of mols in the tank so perhaps a small amount of plasma in the mix could work. - As it stands the heal is very slight at 4kpa which is the typical tank pressure for plasma internals. Going up to 15kpa can result in a stronger heal (on par with injecting plasma) but going further offers no additional benefit, and internals will be consumed much more quickly. - This heal bonus is multiplicative with the rest, but from my testing it still stays within reasonable numbers even with all 3 sources going at once so as to not feel broken. - Plasma fixation does not heal organ damage, but if I could add that in easily enough should it be wanted. The numbers themselves can be easily tweaked if desired, should people find it too strong or what have you! ## Why It's Good For The Game Fixes #72229 Fixes #61424 Fixes #70460 --not sure if this PR fixed it but I was able to infect monkeys and plasmamen with a virus containing Inorganic Biology in my testing, so this may be closed Plasmamen dying from plasma is a travesty and reparations must be made. ## Changelog :cl: fix: plasmamen no longer can suffer liver failure from injecting themselves with plasma (unless they have a human liver for some reason). fix: a person who is infected with a plasma fixation disease can no longer can suffer liver failure from injecting themselves with plasma. fix: plasmamen no longer can suffer liver failure from consuming other organic toxins, which they are not supposed to be affected by. fix: plasma fixation heal-through-inject-or-consumption now works for plasmamen by letting the metabolism procs take care of removing it from their systems. fix: hot ice now has the same wound-healing and nontoxic properties as plasma to plasmamen, since it is described as "frozen plasma". It is also nontoxic to plasma fixation virus sufferers. fix: plasma breathed through internals now contributes to the healing amount from plasma fixation. /:cl: Co-authored-by: Bloop --- code/__DEFINES/mobs.dm | 1 + code/__DEFINES/traits.dm | 2 + code/_globalvars/traits.dm | 1 + code/datums/diseases/advance/symptoms/heal.dm | 68 ++++++++++++++++--- .../game/machinery/dna_infuser/dna_infuser.dm | 2 +- .../heretic/heretic_living_heart.dm | 2 +- .../heretic/knowledge/starting_lore.dm | 2 +- .../heretic/structures/mawed_crucible.dm | 2 +- .../carbon/human/species_types/plasmamen.dm | 5 +- .../chemistry/reagents/toxin_reagents.dm | 14 ++++ code/modules/surgery/organs/liver.dm | 3 + 11 files changed, 86 insertions(+), 16 deletions(-) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 21389f72482..75e5bba3386 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -56,6 +56,7 @@ //Organ defines for carbon mobs #define ORGAN_ORGANIC 1 #define ORGAN_ROBOTIC 2 +#define ORGAN_MINERAL 3 // Used for the plasmaman liver #define DEFAULT_BODYPART_ICON_ORGANIC 'icons/mob/species/human/bodyparts_greyscale.dmi' #define DEFAULT_BODYPART_ICON_ROBOTIC 'icons/mob/augmentation/augments.dmi' diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index a709b32c0ca..9e7c02b2f07 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -219,6 +219,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai ///This carbon doesn't bleed #define TRAIT_NOBLOOD "noblood" #define TRAIT_NOMETABOLISM "no_metabolism" +// Use when you want a mob to be able to metabolize plasma temporarily (e.g. plasma fixation disease symptom) +#define TRAIT_PLASMA_LOVER_METABOLISM "plasma_lover_metabolism" #define TRAIT_NOCLONELOSS "no_cloneloss" #define TRAIT_TOXIMMUNE "toxin_immune" #define TRAIT_EASYDISMEMBER "easy_dismember" diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index 7979091511b..dfde04baa2a 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -62,6 +62,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_NOGUNS" = TRAIT_NOGUNS, "TRAIT_NOHUNGER" = TRAIT_NOHUNGER, "TRAIT_NOMETABOLISM" = TRAIT_NOMETABOLISM, + "TRAIT_PLASMA_LOVER_METABOLISM" = TRAIT_PLASMA_LOVER_METABOLISM, "TRAIT_NOCLONELOSS" = TRAIT_NOCLONELOSS, "TRAIT_TOXIMMUNE" = TRAIT_TOXIMMUNE, "TRAIT_EASYDISMEMBER" = TRAIT_EASYDISMEMBER, diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm index 745ca0d9d2f..c83bcd001fe 100644 --- a/code/datums/diseases/advance/symptoms/heal.dm +++ b/code/datums/diseases/advance/symptoms/heal.dm @@ -476,8 +476,18 @@ return TRUE return FALSE -///Determines the rate at which Plasma Fixation heals based on the amount of plasma in the air +/// Determines the rate at which Plasma Fixation heals based on the amount of plasma in the air #define HEALING_PER_MOL 1.1 +/// Determines the rate at which Plasma Fixation heals based on the amount of plasma being breathed through internals +#define HEALING_PER_BREATH_PRESSURE 0.05 +/// Determines the highest amount you can be healed for when breathing plasma from internals +#define MAX_HEAL_COEFFICIENT_INTERNALS 0.75 +/// Determines the highest amount you can be healed for from pulling plasma from the environment +#define MAX_HEAL_COEFFICIENT_ENVIRONMENT 0.5 +/// Determines the highest amount you can be healed for when there is plasma in the bloodstream +#define MAX_HEAL_COEFFICIENT_BLOODSTREAM 0.75 +/// This is the base heal amount before being multiplied by the healing coefficients +#define BASE_HEAL_PLASMA_FIXATION 4 /datum/symptom/heal/plasma name = "Plasma Fixation" @@ -503,24 +513,59 @@ if(A.totalTransmittable() >= 6) temp_rate = 4 -/datum/symptom/heal/plasma/CanHeal(datum/disease/advance/A) - var/mob/living/M = A.affected_mob +// We do this to prevent liver damage from injecting plasma when plasma fixation virus reaches stage 4 and beyond +/datum/symptom/heal/plasma/on_stage_change(datum/disease/advance/advanced_disease) + . = ..() + if(!.) + return FALSE + + if(advanced_disease.stage >= 4) + ADD_TRAIT(advanced_disease.affected_mob, TRAIT_PLASMA_LOVER_METABOLISM, DISEASE_TRAIT) + else + REMOVE_TRAIT(advanced_disease.affected_mob, TRAIT_PLASMA_LOVER_METABOLISM, DISEASE_TRAIT) + return TRUE + +/datum/symptom/heal/plasma/End(datum/disease/advance/advanced_disease) + . = ..() + if(!.) + return + + REMOVE_TRAIT(advanced_disease.affected_mob, TRAIT_PLASMA_LOVER_METABOLISM, DISEASE_TRAIT) + +// Check internals breath, environmental plasma, and plasma in bloodstream to determine the heal power +/datum/symptom/heal/plasma/CanHeal(datum/disease/advance/advanced_disease) + var/mob/living/diseased_mob = advanced_disease.affected_mob var/datum/gas_mixture/environment var/list/gases . = 0 - if(M.loc) - environment = M.loc.return_air() + // Check internals + /// the amount of mols in a breath is significantly lower than in the environment so we are just going to use the tank's + /// distribution pressure as an abstraction rather than calculate it using the ideal gas equation. + /// balanced around a tank set to 4kpa = about 0.2 healing power. maxes out at 0.75 healing power, or 15kpa. + if(iscarbon(diseased_mob)) + var/mob/living/carbon/breather = diseased_mob + var/obj/item/tank/internals/internals_tank = breather.internal + if(internals_tank) + var/datum/gas_mixture/tank_contents = internals_tank.return_air() + if(tank_contents && round(tank_contents.return_pressure())) // make sure the tank is not empty or 0 pressure + if(tank_contents.gases[/datum/gas/plasma]) + // higher tank distribution pressure leads to more healing, but once you get to about 15kpa you reach the max + . += power * min(MAX_HEAL_COEFFICIENT_INTERNALS, internals_tank.distribute_pressure * HEALING_PER_BREATH_PRESSURE) + // Check environment + if(diseased_mob.loc) + environment = diseased_mob.loc.return_air() if(environment) gases = environment.gases if(gases[/datum/gas/plasma]) - . += power * min(0.5, gases[/datum/gas/plasma][MOLES] * HEALING_PER_MOL) - if(M.reagents.has_reagent(/datum/reagent/toxin/plasma, needs_metabolizing = TRUE)) - . += power * 0.75 //Determines how much the symptom heals if injected or ingested + . += power * min(MAX_HEAL_COEFFICIENT_INTERNALS, gases[/datum/gas/plasma][MOLES] * HEALING_PER_MOL) + // Check for reagents in bloodstream + if(diseased_mob.reagents.has_reagent(/datum/reagent/toxin/plasma, needs_metabolizing = TRUE)) + . += power * MAX_HEAL_COEFFICIENT_BLOODSTREAM //Determines how much the symptom heals if injected or ingested /datum/symptom/heal/plasma/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power) - var/heal_amt = 4 * actual_power + var/heal_amt = BASE_HEAL_PLASMA_FIXATION * actual_power if(prob(5)) to_chat(M, span_notice("You feel yourself absorbing plasma inside and around you...")) @@ -549,6 +594,11 @@ ///Plasma End #undef HEALING_PER_MOL +#undef HEALING_PER_BREATH_PRESSURE +#undef MAX_HEAL_COEFFICIENT_INTERNALS +#undef MAX_HEAL_COEFFICIENT_ENVIRONMENT +#undef MAX_HEAL_COEFFICIENT_BLOODSTREAM +#undef BASE_HEAL_PLASMA_FIXATION /datum/symptom/heal/radiation name = "Radioactive Resonance" diff --git a/code/game/machinery/dna_infuser/dna_infuser.dm b/code/game/machinery/dna_infuser/dna_infuser.dm index 03fec110ac2..bb279178f05 100644 --- a/code/game/machinery/dna_infuser/dna_infuser.dm +++ b/code/game/machinery/dna_infuser/dna_infuser.dm @@ -127,7 +127,7 @@ for(var/obj/item/organ/new_organ in infusing_into.output_organs) var/obj/item/organ/old_organ = target.getorganslot(initial(new_organ.slot)) if(old_organ) - if((old_organ.type != new_organ) && (old_organ.status == ORGAN_ORGANIC)) + if((old_organ.type != new_organ) && (old_organ.status != ORGAN_ROBOTIC)) continue // Old organ can be mutated! else if(isexternalorgan(new_organ)) continue // External organ can be grown! diff --git a/code/modules/antagonists/heretic/heretic_living_heart.dm b/code/modules/antagonists/heretic/heretic_living_heart.dm index 4dda1a2f73a..063303c49b6 100644 --- a/code/modules/antagonists/heretic/heretic_living_heart.dm +++ b/code/modules/antagonists/heretic/heretic_living_heart.dm @@ -55,7 +55,7 @@ /datum/component/living_heart/proc/on_organ_replaced(obj/item/organ/source, obj/item/organ/replacement) SIGNAL_HANDLER - if(replacement.status != ORGAN_ORGANIC || (replacement.organ_flags & ORGAN_SYNTHETIC)) + if(replacement.status == ORGAN_ROBOTIC || (replacement.organ_flags & ORGAN_SYNTHETIC)) qdel(src) return diff --git a/code/modules/antagonists/heretic/knowledge/starting_lore.dm b/code/modules/antagonists/heretic/knowledge/starting_lore.dm index 65f5bc8201d..deb2deacb52 100644 --- a/code/modules/antagonists/heretic/knowledge/starting_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/starting_lore.dm @@ -183,7 +183,7 @@ GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge()) return FALSE if(!new_heart.useable) return FALSE - if(new_heart.status != ORGAN_ORGANIC) + if(new_heart.status == ORGAN_ROBOTIC) return FALSE if(new_heart.organ_flags & (ORGAN_SYNTHETIC|ORGAN_FAILING)) return FALSE diff --git a/code/modules/antagonists/heretic/structures/mawed_crucible.dm b/code/modules/antagonists/heretic/structures/mawed_crucible.dm index a409c38d1b9..1b720cd9940 100644 --- a/code/modules/antagonists/heretic/structures/mawed_crucible.dm +++ b/code/modules/antagonists/heretic/structures/mawed_crucible.dm @@ -84,7 +84,7 @@ if(isorgan(weapon)) var/obj/item/organ/consumed = weapon - if(consumed.status != ORGAN_ORGANIC || (consumed.organ_flags & ORGAN_SYNTHETIC)) + if(consumed.status == ORGAN_ROBOTIC || (consumed.organ_flags & ORGAN_SYNTHETIC)) balloon_alert(user, "not organic!") return if(consumed.organ_flags & ORGAN_VITAL) // Basically, don't eat organs like brains diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm index 93ef929ce36..14c72099a02 100644 --- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm +++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm @@ -136,12 +136,11 @@ /datum/species/plasmaman/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, delta_time, times_fired) . = ..() - if(istype(chem, /datum/reagent/toxin/plasma)) - H.reagents.remove_reagent(chem.type, chem.metabolization_rate * delta_time) + if(istype(chem, /datum/reagent/toxin/plasma) || istype(chem, /datum/reagent/toxin/hot_ice)) for(var/i in H.all_wounds) var/datum/wound/iter_wound = i iter_wound.on_xadone(4 * REAGENTS_EFFECT_MULTIPLIER * delta_time) // plasmamen use plasma to reform their bones or whatever - return TRUE + return FALSE // do normal metabolism if(istype(chem, /datum/reagent/toxin/bonehurtingjuice)) H.adjustStaminaLoss(7.5 * REAGENTS_EFFECT_MULTIPLIER * delta_time, 0) diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index e16216b4edd..0bfbffc0a70 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -105,6 +105,13 @@ affected_mob.adjustPlasma(20 * REM * delta_time) return ..() +/datum/reagent/toxin/plasma/on_mob_metabolize(mob/living/carbon/affected_mob) + if(HAS_TRAIT(affected_mob, TRAIT_PLASMA_LOVER_METABOLISM)) // sometimes mobs can temporarily metabolize plasma (e.g. plasma fixation disease symptom) + toxpwr = 0 + +/datum/reagent/toxin/plasma/on_mob_end_metabolize(mob/living/carbon/affected_mob) + toxpwr = initial(toxpwr) + /// Handles plasma boiling. /datum/reagent/toxin/plasma/proc/on_temp_change(datum/reagents/_holder, old_temp) SIGNAL_HANDLER @@ -153,6 +160,13 @@ humi.adjust_coretemperature(-7 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * delta_time, affected_mob.get_body_temp_normal()) return ..() +/datum/reagent/toxin/hot_ice/on_mob_metabolize(mob/living/carbon/affected_mob) + if(HAS_TRAIT(affected_mob, TRAIT_PLASMA_LOVER_METABOLISM)) + toxpwr = 0 + +/datum/reagent/toxin/hot_ice/on_mob_end_metabolize(mob/living/carbon/affected_mob) + toxpwr = initial(toxpwr) + /datum/reagent/toxin/lexorin name = "Lexorin" description = "A powerful poison used to stop respiration." diff --git a/code/modules/surgery/organs/liver.dm b/code/modules/surgery/organs/liver.dm index c7b7f148126..50562c28b35 100755 --- a/code/modules/surgery/organs/liver.dm +++ b/code/modules/surgery/organs/liver.dm @@ -107,6 +107,8 @@ if(filterToxins && !HAS_TRAIT(liver_owner, TRAIT_TOXINLOVER)) for(var/datum/reagent/toxin/toxin in cached_reagents) + if(status != toxin.affected_organtype) //this particular toxin does not affect this type of organ + continue var/amount = round(toxin.volume, CHEMICAL_QUANTISATION_LEVEL) // this is an optimization if(belly) amount += belly.reagents.get_reagent_amount(toxin.type) @@ -217,6 +219,7 @@ name = "reagent processing crystal" icon_state = "liver-p" desc = "A large crystal that is somehow capable of metabolizing chemicals, these are found in plasmamen." + status = ORGAN_MINERAL // alien livers can ignore up to 15u of toxins, but they take x3 liver damage /obj/item/organ/internal/liver/alien