diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_carbon.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_carbon.dm index d882230c82e0..ffcac102f55a 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_carbon.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_carbon.dm @@ -60,6 +60,8 @@ #define COMSIG_CARBON_GAIN_ORGAN "carbon_gain_organ" ///from /item/organ/proc/Remove() (/obj/item/organ/) #define COMSIG_CARBON_LOSE_ORGAN "carbon_lose_organ" +///from on_mob_metabolize and mob_end_metabolize for the liver +#define COMSIG_CARBON_UPDATE_TOXINS "carbon_update_toxins_cache" ///from /mob/living/carbon/doUnEquip(obj/item/I, force, newloc, no_move, invdrop, silent) #define COMSIG_CARBON_EQUIP_HAT "carbon_equip_hat" ///from /mob/living/carbon/doUnEquip(obj/item/I, force, newloc, no_move, invdrop, silent) diff --git a/code/modules/mob/living/carbon/human/species_types/polysmorphs.dm b/code/modules/mob/living/carbon/human/species_types/polysmorphs.dm index 8d16f1f25d68..efb932731964 100644 --- a/code/modules/mob/living/carbon/human/species_types/polysmorphs.dm +++ b/code/modules/mob/living/carbon/human/species_types/polysmorphs.dm @@ -19,6 +19,7 @@ coldmod = 0.75 heatmod = 1.5 pressuremod = 0.75 //Xenos are completely pressure immune, they're bargain bin xenos + toxmod = 0.8 //their blood is acid, their liver is pretty used to fucked up things acidmod = 0.2 //Their blood is literally acid action_speed_coefficient = 1.1 //claws aren't dextrous like hands speedmod = -0.1 //apex predator humanoid hybrid diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index d1135520daf3..08dda660f177 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -8,15 +8,18 @@ taste_description = "bitterness" taste_mult = 1.2 evaporation_rate = 3 //6x faster than normal chems + /// Handled by the liver, does full damage for the highest toxpwr, and reduced for every following one var/toxpwr = 1.5 var/silent_toxin = FALSE //won't produce a pain message when processed by liver/Life(seconds_per_tick = SSMOBS_DT, times_fired) if there isn't another non-silent toxin present. -/datum/reagent/toxin/on_mob_life(mob/living/carbon/M) - if(toxpwr) - M.adjustToxLoss(toxpwr*REM, 0) - . = TRUE - ..() +/datum/reagent/toxin/on_mob_metabolize(mob/living/L) + . = ..() + SEND_SIGNAL(L, COMSIG_CARBON_UPDATE_TOXINS) +/datum/reagent/toxin/on_mob_end_metabolize(mob/living/L) + . = ..() + SEND_SIGNAL(L, COMSIG_CARBON_UPDATE_TOXINS) + /datum/reagent/toxin/amatoxin name = "Amatoxin" description = "A powerful poison derived from certain species of mushroom." @@ -916,7 +919,7 @@ /datum/reagent/toxin/delayed/on_mob_life(mob/living/carbon/M) if(current_cycle > delay) holder.remove_reagent(type, actual_metaboliztion_rate * M.metabolism_efficiency) - M.adjustToxLoss(actual_toxpwr*REM, 0) + toxpwr = actual_toxpwr if(prob(10)) M.Paralyze(20, 0) . = 1 diff --git a/code/modules/surgery/organs/liver.dm b/code/modules/surgery/organs/liver.dm index b57493a2f019..15178576ede3 100755 --- a/code/modules/surgery/organs/liver.dm +++ b/code/modules/surgery/organs/liver.dm @@ -1,5 +1,4 @@ -#define LIVER_DEFAULT_TOX_TOLERANCE 3 //amount of toxins the liver can filter out -#define LIVER_DEFAULT_TOX_LETHALITY 0.01 //lower values lower how harmful toxins are to the liver +#define LIVER_DEFAULT_TOX_LETHALITY 1 //lower values lower how harmful toxins are to the liver /obj/item/organ/liver name = "liver" @@ -12,40 +11,44 @@ maxHealth = STANDARD_ORGAN_THRESHOLD healing_factor = STANDARD_ORGAN_HEALING decay_factor = STANDARD_ORGAN_DECAY // smack in the middle of decay times - var/operated = FALSE //whether we can still have our damages fixed through surgery - var/alcohol_tolerance = ALCOHOL_RATE//affects how much damage the liver takes from alcohol - var/toxTolerance = LIVER_DEFAULT_TOX_TOLERANCE//maximum amount of toxins the liver can just shrug off - var/toxLethality = LIVER_DEFAULT_TOX_LETHALITY//affects how much damage toxins do to the liver - var/filterToxins = TRUE //whether to filter toxins + /// whether we can still have our damages fixed through surgery + var/operated = FALSE + /// affects how much damage the liver takes from alcohol + var/alcohol_tolerance = ALCOHOL_RATE + /// modifier to toxpwr for liver and toxin damage taken + var/toxLethality = LIVER_DEFAULT_TOX_LETHALITY + /// cached list of the toxinpower of toxins + var/list/cached_toxpower = list() + /// whether or not the toxin process can provide a message + var/provide_pain_message = FALSE + +/obj/item/organ/liver/Insert(mob/living/carbon/M, special, drop_if_replaced, special_zone) + . = ..() + RegisterSignal(M, COMSIG_CARBON_UPDATE_TOXINS, PROC_REF(update_toxin_cache), override = TRUE) + +/obj/item/organ/liver/Remove(mob/living/carbon/M, special) + UnregisterSignal(M, COMSIG_CARBON_UPDATE_TOXINS) + return ..() + +/obj/item/organ/liver/proc/update_toxin_cache() + var/mob/living/carbon/C = owner + if(!istype(C)) + return -#define HAS_SILENT_TOXIN 0 //don't provide a feedback message if this is the only toxin present -#define HAS_NO_TOXIN 1 -#define HAS_PAINFUL_TOXIN 2 + provide_pain_message = FALSE + cached_toxpower = list() + + for(var/datum/reagent/toxin/T in C.reagents.reagent_list) + cached_toxpower += T.toxpwr + provide_pain_message = provide_pain_message || !T.silent_toxin + + sort_list(cached_toxpower, cmp = /proc/cmp_numeric_dsc) //sort all toxpowers scaling from highest to lowest /obj/item/organ/liver/on_life() var/mob/living/carbon/C = owner ..() //perform general on_life() if(istype(C)) - if(!(organ_flags & ORGAN_FAILING))//can't process reagents with a failing liver - - var/provide_pain_message = HAS_NO_TOXIN - if(filterToxins && !HAS_TRAIT(owner, TRAIT_TOXINLOVER)) - //handle liver toxin filtration - for(var/datum/reagent/toxin/T in C.reagents.reagent_list) - var/thisamount = C.reagents.get_reagent_amount(T.type) - if (thisamount && thisamount <= toxTolerance) - C.reagents.remove_reagent(T.type, 1) - else - damage += (thisamount*toxLethality) - if(provide_pain_message != HAS_PAINFUL_TOXIN) - provide_pain_message = T.silent_toxin ? HAS_SILENT_TOXIN : HAS_PAINFUL_TOXIN - - //metabolize reagents - C.reagents.metabolize(C, can_overdose=TRUE) - - if(provide_pain_message && damage > 10 && prob(damage/3))//the higher the damage the higher the probability - to_chat(C, span_warning("You feel a dull pain in your abdomen.")) - else //for when our liver's failing + if(organ_flags & ORGAN_FAILING)//for when our liver's failing C.reagents.end_metabolization(C, keep_liverless = TRUE) //Stops trait-based effects on reagents, to prevent permanent buffs C.reagents.metabolize(C, can_overdose=FALSE, liverless = TRUE) if(HAS_TRAIT(C, TRAIT_STABLELIVER)) @@ -53,14 +56,27 @@ C.adjustToxLoss(4, TRUE, TRUE) if(prob(30)) to_chat(C, span_warning("You feel a stabbing pain in your abdomen!")) + + else + if(length(cached_toxpower)) //deal with toxins + var/damage_multiplier = 1 //reduced for every subsequent toxin + + for(var/dmg in cached_toxpower) + var/real_damage = dmg * toxLethality * damage_multiplier + damage_multiplier *= 0.5 //reduce the damage dealt for every subsequent toxin + C.adjustToxLoss(real_damage) + if(!HAS_TRAIT(owner, TRAIT_TOXINLOVER)) //don't hurt the liver if they like toxins + damage += (real_damage / 2) + + //metabolize reagents + C.reagents.metabolize(C, can_overdose=TRUE) + + if(provide_pain_message && damage > 10 && !HAS_TRAIT(owner, TRAIT_TOXINLOVER) && prob(damage/3))//the higher the damage the higher the probability + to_chat(C, span_warning("You feel a dull pain in your abdomen.")) if(damage > maxHealth)//cap liver damage damage = maxHealth -#undef HAS_SILENT_TOXIN -#undef HAS_NO_TOXIN -#undef HAS_PAINFUL_TOXIN - /obj/item/organ/liver/prepare_eat() var/obj/S = ..() S.reagents.add_reagent(/datum/reagent/iron, 5) @@ -84,8 +100,7 @@ name = "alien liver" // doesnt matter for actual aliens because they dont take toxin damage icon_state = "liver-x" // Same sprite as fly-person liver. desc = "A liver that used to belong to a killer alien, who knows what it used to eat." - toxLethality = LIVER_DEFAULT_TOX_LETHALITY * 2.5 // rejects its owner early after too much punishment - toxTolerance = 15 // complete toxin immunity like xenos have would be too powerful + toxLethality = LIVER_DEFAULT_TOX_LETHALITY * 0.5 /obj/item/organ/liver/cybernetic name = "cybernetic liver" @@ -94,8 +109,7 @@ organ_flags = ORGAN_SYNTHETIC alcohol_tolerance = 0.001 maxHealth = 2 * STANDARD_ORGAN_THRESHOLD - toxTolerance = 3.3 - toxLethality = 0.009 + toxLethality = LIVER_DEFAULT_TOX_LETHALITY * 0.9 /obj/item/organ/liver/cybernetic/upgraded name = "upgraded cybernetic liver" @@ -104,8 +118,7 @@ alcohol_tolerance = 0.0005 maxHealth = 3 * STANDARD_ORGAN_THRESHOLD //300% health of a normal liver healing_factor = 2 * STANDARD_ORGAN_HEALING //Can regenerate from damage quicker - toxTolerance = 20 - toxLethality = 0.007 + toxLethality = LIVER_DEFAULT_TOX_LETHALITY * 0.7 /obj/item/organ/liver/cybernetic/upgraded/on_life() . = ..() @@ -125,7 +138,6 @@ attack_verb = list("processed") desc = "A machine component, installed in the chest. This grants the machine the ability to process chemicals that enter its systems." alcohol_tolerance = 0 - toxTolerance = -1 toxLethality = 0 status = ORGAN_ROBOTIC compatible_biotypes = ALL_BIOTYPES