From d4c37ff1647465a1b5020c394c1736e602fee3a8 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Mon, 27 Jul 2026 08:58:36 -0800 Subject: [PATCH 1/6] this is basically it --- code/datums/heritage/family_curse.dm | 2 +- .../antagonists/villain/maniac/_maniac.dm | 4 +- .../villain/neu_vampires/clan/_base_clan.dm | 4 +- .../adventurer/types/pilgrim/briar.dm | 2 +- code/modules/mob/living/blood.dm | 2 +- code/modules/mob/living/carbon/human/human.dm | 4 +- .../mob/living/carbon/human/human_defense.dm | 7 +- code/modules/mob/living/carbon/human/life.dm | 2 +- .../mob/living/carbon/human/physiology.dm | 30 --- .../human/physiology/modifiers/_base.dm | 83 ++++++++ .../human/physiology/modifiers/briar.dm | 3 + .../human/physiology/modifiers/curses.dm | 3 + .../human/physiology/modifiers/maniac.dm | 3 + .../human/physiology/modifiers/species.dm | 28 +++ .../physiology/modifiers/status_effects.dm | 16 ++ .../human/physiology/modifiers/vampire.dm | 3 + .../carbon/human/physiology/physiology.dm | 187 ++++++++++++++++++ .../mob/living/carbon/human/species.dm | 39 ++-- .../species_types/automatons/_automaton.dm | 2 +- .../human/species_types/halfling/_halfling.dm | 2 +- .../human/species_types/other/aasimar.dm | 3 +- .../human/species_types/other/halforc.dm | 3 +- .../human/species_types/other/werewolf.dm | 3 +- .../human/species_types/vulture/_vulture.dm | 2 +- .../spell_types/pointed/numbing_pleasure.dm | 4 +- .../spells/spell_types/pointed/persistence.dm | 10 +- .../organs/external/wings/functional_wings.dm | 4 +- .../surgery/organs/internal/artery/_artery.dm | 2 +- .../organs/organ_processing/stomach.dm | 4 +- vanderlin.dme | 9 +- 30 files changed, 380 insertions(+), 90 deletions(-) delete mode 100644 code/modules/mob/living/carbon/human/physiology.dm create mode 100644 code/modules/mob/living/carbon/human/physiology/modifiers/_base.dm create mode 100644 code/modules/mob/living/carbon/human/physiology/modifiers/briar.dm create mode 100644 code/modules/mob/living/carbon/human/physiology/modifiers/curses.dm create mode 100644 code/modules/mob/living/carbon/human/physiology/modifiers/maniac.dm create mode 100644 code/modules/mob/living/carbon/human/physiology/modifiers/species.dm create mode 100644 code/modules/mob/living/carbon/human/physiology/modifiers/status_effects.dm create mode 100644 code/modules/mob/living/carbon/human/physiology/modifiers/vampire.dm create mode 100644 code/modules/mob/living/carbon/human/physiology/physiology.dm diff --git a/code/datums/heritage/family_curse.dm b/code/datums/heritage/family_curse.dm index cf94d30d822..975a593395c 100644 --- a/code/datums/heritage/family_curse.dm +++ b/code/datums/heritage/family_curse.dm @@ -77,7 +77,7 @@ . = ..() if(ishuman(owner)) var/mob/living/carbon/human/H = owner - H.dna.species.nutrition_mod += 1.1 + H.physiology.add_physiology_modifier(/datum/physiology_modifier/hunger_curse) /atom/movable/screen/alert/status_effect/family_curse/hunger name = "Insatiable Appetite" diff --git a/code/modules/antagonists/villain/maniac/_maniac.dm b/code/modules/antagonists/villain/maniac/_maniac.dm index 2329c2d1a26..a0089d27af6 100644 --- a/code/modules/antagonists/villain/maniac/_maniac.dm +++ b/code/modules/antagonists/villain/maniac/_maniac.dm @@ -121,7 +121,7 @@ GLOBAL_VAR_INIT(maniac_highlander, 0) // THERE CAN ONLY BE ONE! dreamer.set_patron(/datum/patron/inhumen/graggar_zizo) old_cm = dreamer.cmode_music dreamer.cmode_music = 'sound/music/cmode/antag/combat_maniac.ogg' - phy.bleed_mod *= 0.5 + phy.add_physiology_modifier(/datum/physiology_modifier/maniac) for(var/datum/status_effect/effect in dreamer.status_effects) //necessary to prevent exploits dreamer.remove_status_effect(effect) dreamer.attributes?.add_sheet(/datum/attribute_holder/sheet/job/maniac) @@ -175,7 +175,7 @@ GLOBAL_VAR_INIT(maniac_highlander, 0) // THERE CAN ONLY BE ONE! dreamer.cmode_music = old_cm dreamer.remove_stat_modifier("[type]") qdel(dreamer.GetComponent(/datum/component/theme_music)) - phy.bleed_mod *= 2 + phy.remove_physiology_modifier(/datum/physiology_modifier/maniac) UnregisterSignal(dreamer, COMSIG_LIVING_DEATH) var/client/client = dreamer?.client if(client) //clear screenshake animation diff --git a/code/modules/antagonists/villain/neu_vampires/clan/_base_clan.dm b/code/modules/antagonists/villain/neu_vampires/clan/_base_clan.dm index 41b2806adf3..6964e245893 100644 --- a/code/modules/antagonists/villain/neu_vampires/clan/_base_clan.dm +++ b/code/modules/antagonists/villain/neu_vampires/clan/_base_clan.dm @@ -125,7 +125,7 @@ And it also helps for the character set panel H.has_reflection = FALSE H.cut_overlay(H.reflective_icon) H.mob_biotypes |= MOB_UNDEAD - H.physiology?.bleed_mod /= 2 + H.physiology?.add_physiology_modifier(/datum/physiology_modifier/clan) if(alt_sprite) if (!alt_sprite_greyscale) @@ -290,7 +290,7 @@ And it also helps for the character set panel vampire.has_reflection = TRUE vampire.create_reflection() vampire.update_reflection() - vampire.physiology?.bleed_mod *= 2 + vampire.physiology?.remove_physiology_modifier(/datum/physiology_modifier/clan) vampire.mob_biotypes &= ~MOB_UNDEAD clan_members -= vampire diff --git a/code/modules/jobs/job_types/adventurer/types/pilgrim/briar.dm b/code/modules/jobs/job_types/adventurer/types/pilgrim/briar.dm index 7ed8eae7c9d..dba1ff1b86f 100644 --- a/code/modules/jobs/job_types/adventurer/types/pilgrim/briar.dm +++ b/code/modules/jobs/job_types/adventurer/types/pilgrim/briar.dm @@ -311,7 +311,7 @@ to_chat(user, span_good("The rumblings of a troll echo through the trees, your offering was acknowledged by the ancient dwellers of the forest.")) user.emote("rage", forced = TRUE) ADD_TRAIT(user, TRAIT_CRITICAL_RESISTANCE, TRAIT_GENERIC) - user.physiology.pain_mod *= 0.6 + user.physiology.add_physiology_modifier(/datum/physiology_modifier/black_briar) user.remove_spell(/datum/action/cooldown/spell/healing) user.add_spell(/datum/action/cooldown/spell/undirected/shapeshift/troll_form) to_chat(user, span_warning("I no longer care for mending wounds, let the lords of the forest be known!")) diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index e84d66395c3..12ebb6b58c4 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -148,7 +148,7 @@ #undef BLOOD_DRIP_RATE_MOD /mob/living/carbon/human/bleed(amount) - amount *= physiology?.bleed_mod + amount *= physiology?.get_bleed_mod() return ..() /mob/living/proc/restore_blood() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index cfecc989500..8b5e8271a83 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -115,6 +115,7 @@ add_verb(src, /mob/living/proc/lay_down) status_flags |= BUILDING_ORGANS + physiology = new() ///this is now core for species //initialize limbs first create_bodyparts() @@ -126,7 +127,6 @@ //initialise organs create_internal_organs() //most of it is done in set_species now, this is only for parent call - physiology = new() status_flags &= ~BUILDING_ORGANS culture = GLOB.culture_singletons[culture] @@ -865,7 +865,7 @@ /mob/living/carbon/human/do_after_coefficent() . = ..() - . *= physiology?.do_after_speed + . *= physiology?.get_do_after_speed() /mob/living/carbon/human/proc/skele_look() dna.species.go_bald() diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index b36f3131745..7bfa7b4ba8f 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -430,8 +430,7 @@ else if(!(flags & SHOCK_NOGLOVES)) //This gets the siemens_coeff for all non tesla shocks if(gloves) siemens_coeff *= gloves.siemens_coefficient - siemens_coeff *= physiology.siemens_coeff - siemens_coeff *= dna.species.siemens_coeff + siemens_coeff *= physiology.get_siemens_coeff() . = ..() //Don't go further if the shock was blocked/too weak. if(!.) @@ -774,5 +773,5 @@ /mob/living/carbon/human/getShock(painkiller_included) . = ..() - if(dna?.species) - return . * dna?.species.pain_mod + if(physiology) + return . * physiology.get_pain_mod() diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 89ea6020ac9..0b2cdd9394c 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -145,7 +145,7 @@ /mob/living/carbon/human/proc/handle_hygiene() if(stat == DEAD || HAS_TRAIT(src, TRAIT_NOHYGIENE)) return - var/dirt_factor = HYGIENE_FACTOR * dna.species.hygiene_mod + var/dirt_factor = HYGIENE_FACTOR * physiology.get_hygiene_mod() if(HAS_TRAIT(src, TRAIT_ALWAYS_CLEAN)) set_hygiene(HYGIENE_LEVEL_CLEAN) diff --git a/code/modules/mob/living/carbon/human/physiology.dm b/code/modules/mob/living/carbon/human/physiology.dm deleted file mode 100644 index 447e7954f67..00000000000 --- a/code/modules/mob/living/carbon/human/physiology.dm +++ /dev/null @@ -1,30 +0,0 @@ -//Stores several modifiers in a way that isn't cleared by changing species - -/datum/physiology - var/brute_mod = 1 // % of brute damage taken from all sources - var/burn_mod = 1 // % of burn damage taken from all sources - var/tox_mod = 1 // % of toxin damage taken from all sources - var/oxy_mod = 1 // % of oxygen damage taken from all sources - var/clone_mod = 1 // % of clone damage taken from all sources - var/stamina_mod = 1 // % of stamina damage taken from all sources - var/brain_mod = 1 // % of brain damage taken from all sources - - var/pressure_mod = 1 // % of brute damage taken from low or high pressure (stacks with brute_mod) - var/heat_mod = 1 // % of burn damage taken from heat (stacks with burn_mod) - var/cold_mod = 1 // % of burn damage taken from cold (stacks with burn_mod) - - var/damage_resistance = 0 // %damage reduction from all sources - - var/siemens_coeff = 1 // resistance to shocks - - var/stun_mod = 1 // % stun modifier - var/bleed_mod = 1 // % bleeding modifier - var/pain_mod = 1 // % pain modifier - var/datum/armor/armor // internal armor datum - - var/hunger_mod = 1 //% of hunger rate taken per tick. - - var/do_after_speed = 1 //Speed mod for do_after. Lower is better. If temporarily adjusting, please only modify using *= and /=, so you don't interrupt other calculations. - -/datum/physiology/New() - armor = new diff --git a/code/modules/mob/living/carbon/human/physiology/modifiers/_base.dm b/code/modules/mob/living/carbon/human/physiology/modifiers/_base.dm new file mode 100644 index 00000000000..c011c136b49 --- /dev/null +++ b/code/modules/mob/living/carbon/human/physiology/modifiers/_base.dm @@ -0,0 +1,83 @@ +GLOBAL_LIST_EMPTY(physiology_modification_cache) + +/datum/physiology_modifier + /// Whether or not this is a variable modifier. Variable modifiers can NOT be ever auto-cached. ONLY CHECKED VIA INITIAL(), EFFECTIVELY READ ONLY (and for very good reason) + var/variable = FALSE + + /// Unique ID. You can never have different modifications with the same ID. By default, this SHOULD NOT be set. Only set it for cases where you're dynamically making modifiers/need to have two types overwrite each other. If unset, uses path (converted to text) as ID. + var/id + + /// Higher ones override lower priorities. This is NOT used for ID, ID must be unique, if it isn't unique the newer one overwrites automatically if overriding. + var/priority = 0 + var/flags = NONE + + /// % of brute damage taken from all sources + var/brute_mod = 1 + /// % of burn damage taken from all sources + var/burn_mod = 1 + /// % of toxin damage taken from all sources + var/tox_mod = 1 + /// % of oxygen damage taken from all sources + var/oxy_mod = 1 + /// % of clone damage taken from all sources + var/clone_mod = 1 + /// % of stamina damage taken from all sources + var/stamina_mod = 1 + /// % of brain damage taken from all sources + var/brain_mod = 1 + + /// % of burn damage taken from heat (stacks with burn_mod) + var/heat_mod = 1 + /// % of burn damage taken from cold (stacks with burn_mod) + var/cold_mod = 1 + + /// % damage reduction from all sources. Additive, not multiplicative - see ADDITIVE_PHYSIOLOGY_STATS + var/damage_resistance = 0 + + /// Resistance to shocks + var/siemens_coeff = 1 + + /// % stun modifier + var/stun_mod = 1 + /// % bleeding modifier + var/bleed_mod = 1 + /// % pain modifier + var/pain_mod = 1 + + /// % of hygiene rate taken per tick + var/hygiene_mod = 1 + /// % of hunger rate taken per tick + var/hunger_mod = 1 + + /// Speed mod for do_after. Lower is better. If temporarily adjusting, please only modify using *= and /=, so you don't interrupt other calculations. + var/do_after_speed = 1 + +/datum/physiology_modifier/New() + . = ..() + if(!id) + id = "[type]" //We turn the path into a string. + +/// Checks if we should actually apply our modification at this moment +/datum/physiology_modifier/proc/applies_to(datum/physiology/holder) + return TRUE + +/// Grabs a STATIC MODIFIER datum from cache. YOU MUST NEVER EDIT THESE DATUMS, OR IT WILL AFFECT ANYTHING ELSE USING IT TOO! +/proc/get_cached_physiology_modifier(modtype) + if(!ispath(modtype, /datum/physiology_modifier)) + CRASH("[modtype] is not a physiology modifier typepath.") + var/datum/physiology_modifier/phys_mod = modtype + if(initial(phys_mod.variable)) + CRASH("[modtype] is a variable modifier, and can never be cached.") + phys_mod = GLOB.physiology_modification_cache[modtype] + if(!phys_mod) + phys_mod = GLOB.physiology_modification_cache[modtype] = new modtype + return phys_mod + +/// The "always on" variable modifier every physiology gets on creation. This is what species defaults + direct/admin edits get written to, so nothing gets wiped when species changes. +/datum/physiology_modifier/base + id = "base" + variable = TRUE + priority = 0 + +/datum/physiology_modifier/base/applies_to(datum/physiology/holder) + return TRUE //this special snowflake ALWAYS applies diff --git a/code/modules/mob/living/carbon/human/physiology/modifiers/briar.dm b/code/modules/mob/living/carbon/human/physiology/modifiers/briar.dm new file mode 100644 index 00000000000..219e120fa09 --- /dev/null +++ b/code/modules/mob/living/carbon/human/physiology/modifiers/briar.dm @@ -0,0 +1,3 @@ +/datum/physiology_modifier/black_briar + id = "black_briar" + pain_mod = 0.6 diff --git a/code/modules/mob/living/carbon/human/physiology/modifiers/curses.dm b/code/modules/mob/living/carbon/human/physiology/modifiers/curses.dm new file mode 100644 index 00000000000..4de0cef3199 --- /dev/null +++ b/code/modules/mob/living/carbon/human/physiology/modifiers/curses.dm @@ -0,0 +1,3 @@ +/datum/physiology_modifier/hunger_curse + id = "hunger_curse" + hunger_mod = 2.1 diff --git a/code/modules/mob/living/carbon/human/physiology/modifiers/maniac.dm b/code/modules/mob/living/carbon/human/physiology/modifiers/maniac.dm new file mode 100644 index 00000000000..3be3931b33d --- /dev/null +++ b/code/modules/mob/living/carbon/human/physiology/modifiers/maniac.dm @@ -0,0 +1,3 @@ +/datum/physiology_modifier/maniac + id = "maniac" + bleed_mod = 0.5 diff --git a/code/modules/mob/living/carbon/human/physiology/modifiers/species.dm b/code/modules/mob/living/carbon/human/physiology/modifiers/species.dm new file mode 100644 index 00000000000..7aa13530f6e --- /dev/null +++ b/code/modules/mob/living/carbon/human/physiology/modifiers/species.dm @@ -0,0 +1,28 @@ +/datum/physiology_modifier/species + id = "species" + variable = TRUE + priority = 0 + +/datum/physiology_modifier/species/applies_to(datum/physiology/holder) + return TRUE + +/datum/physiology_modifier/species/halfling + hunger_mod = 2 + +/datum/physiology_modifier/species/horc + hunger_mod = 2 + hygiene_mod = 1.5 + +/datum/physiology_modifier/species/medicator + hygiene_mod = 1.25 + +/datum/physiology_modifier/species/werewolf + bleed_mod = 0.6 + pain_mod = 0.2 + +/datum/physiology_modifier/species/automaton + bleed_mod = 0.7 + +/datum/physiology_modifier/species/aasimar + bleed_mod = 0.8 + pain_mod = 0.9 diff --git a/code/modules/mob/living/carbon/human/physiology/modifiers/status_effects.dm b/code/modules/mob/living/carbon/human/physiology/modifiers/status_effects.dm new file mode 100644 index 00000000000..49604bcac71 --- /dev/null +++ b/code/modules/mob/living/carbon/human/physiology/modifiers/status_effects.dm @@ -0,0 +1,16 @@ +/datum/physiology_modifier/painkiller + id = "painkiller" + pain_mod = 0.5 + +/datum/physiology_modifier/persistence + id = "persistence" + pain_mod = 1.5 + bleed_mod = 1.5 + +/datum/physiology_modifier/persistence_buff + id = "persistence_buff" + pain_mod = 0.85 + +/datum/physiology_modifier/flight + id = "flight" + stun_mod = 2 diff --git a/code/modules/mob/living/carbon/human/physiology/modifiers/vampire.dm b/code/modules/mob/living/carbon/human/physiology/modifiers/vampire.dm new file mode 100644 index 00000000000..caa403de0d0 --- /dev/null +++ b/code/modules/mob/living/carbon/human/physiology/modifiers/vampire.dm @@ -0,0 +1,3 @@ +/datum/physiology_modifier/clan + id = "vampire" + bleed_mod = 0.5 diff --git a/code/modules/mob/living/carbon/human/physiology/physiology.dm b/code/modules/mob/living/carbon/human/physiology/physiology.dm new file mode 100644 index 00000000000..5e701576d66 --- /dev/null +++ b/code/modules/mob/living/carbon/human/physiology/physiology.dm @@ -0,0 +1,187 @@ + +/* + Stores several modifiers in a way that isn't cleared by changing species. + Final stat values are computed by stacking every active /datum/physiology_modifier on + physiology_modification: multiplicative stats multiply together, additive stats (see + ADDITIVE_PHYSIOLOGY_STATS) sum together. Species defaults get written into {/datum/physiology_modifier/species}, + not baked directly into base_modifier, so re-applying/removing a species is non-destructive + to anything else that's modifying you (chems, traumas, admin edits, etc). +*/ +/datum/physiology + /// Assoc list of id -> /datum/physiology_modifier, sorted by priority (highest first) + var/list/physiology_modification + /// Assoc list of id -> list of sources ignoring that modifier id + var/list/physiology_mod_immunities + + /// The always-present variable modifier holding defaullts and direct edits + var/datum/physiology_modifier/base/base_modifier + + /// Internal armor datum + var/datum/armor/armor + +/datum/physiology/New() + . = ..() + armor = new + base_modifier = new + add_physiology_modifier(base_modifier) + +/// Direct access to the always-on base modifier, for species seeding or admin/genetic edits +/datum/physiology/proc/get_base_modifier() + return base_modifier + +/// Add a physiology modifier to this holder. If a variable subtype is passed in as the first argument, it will make a new datum. If ID conflicts, it will overwrite the old ID. +/datum/physiology/proc/add_physiology_modifier(datum/physiology_modifier/type_or_datum) + if(ispath(type_or_datum)) + if(!initial(type_or_datum.variable)) + type_or_datum = get_cached_physiology_modifier(type_or_datum) + else + type_or_datum = new type_or_datum + var/datum/physiology_modifier/existing = LAZYACCESS(physiology_modification, type_or_datum.id) + if(existing) + if(existing == type_or_datum) //same thing don't need to touch + return TRUE + remove_physiology_modifier(existing) + if(length(physiology_modification)) + BINARY_INSERT(type_or_datum.id, physiology_modification, /datum/physiology_modifier, type_or_datum, priority, COMPARE_VALUE) + LAZYSET(physiology_modification, type_or_datum.id, type_or_datum) + return TRUE + +/// Remove a physiology modifier from a holder, whether static or variable. +/datum/physiology/proc/remove_physiology_modifier(datum/physiology_modifier/type_id_datum) + var/key + if(ispath(type_id_datum)) + key = initial(type_id_datum.id) || "[type_id_datum]" + else if(!istext(type_id_datum)) + key = type_id_datum.id + else + key = type_id_datum + if(!LAZYACCESS(physiology_modification, key)) + return FALSE + LAZYREMOVE(physiology_modification, key) + return TRUE + +/// Used for variable modification like chems/traumas. Returns the modifier datum if successful. +/datum/physiology/proc/add_or_update_variable_physiology_modifier(datum/physiology_modifier/type_id_datum, list/new_values) + var/inject = FALSE + var/datum/physiology_modifier/final + if(istext(type_id_datum)) + final = LAZYACCESS(physiology_modification, type_id_datum) + if(!final) + CRASH("Couldn't find existing modification when provided a text ID.") + else if(ispath(type_id_datum)) + if(!initial(type_id_datum.variable)) + CRASH("Not a variable modifier") + final = LAZYACCESS(physiology_modification, initial(type_id_datum.id) || "[type_id_datum]") + if(!final) + final = new type_id_datum + inject = TRUE + else + if(!initial(type_id_datum.variable)) + CRASH("Not a variable modifier") + final = type_id_datum + if(!LAZYACCESS(physiology_modification, final.id)) + inject = TRUE + if(islist(new_values)) + for(var/stat in new_values) + final.vars[stat] = new_values[stat] + if(inject) + add_physiology_modifier(final) + return final + +/// Is there a physiology modifier with this id/type on this holder +/datum/physiology/proc/has_physiology_modifier(datum/physiology_modifier/datum_type_id) + var/key + if(ispath(datum_type_id)) + key = initial(datum_type_id.id) || "[datum_type_id]" + else if(istext(datum_type_id)) + key = datum_type_id + else + key = datum_type_id.id + return LAZYACCESS(physiology_modification, key) + +/// Get the physiology modifiers list, minus anything we're immune to +/datum/physiology/proc/get_physiology_modification() + . = LAZYCOPY(physiology_modification) + for(var/id in physiology_mod_immunities) + . -= id + +/// Ignore specific physiology mods - accepts a single id/type or a list of them +/datum/physiology/proc/add_physiology_mod_immunities(source, mod_type) + if(islist(mod_type)) + for(var/listed_type in mod_type) + if(ispath(listed_type)) + listed_type = "[listed_type]" + LAZYADDASSOCLIST(physiology_mod_immunities, listed_type, source) + else + if(ispath(mod_type)) + mod_type = "[mod_type]" + LAZYADDASSOCLIST(physiology_mod_immunities, mod_type, source) + +/// Unignore specific physiology mods - accepts a single id/type or a list of them +/datum/physiology/proc/remove_physiology_mod_immunities(source, mod_type) + if(islist(mod_type)) + for(var/listed_type in mod_type) + if(ispath(listed_type)) + listed_type = "[listed_type]" + LAZYREMOVEASSOC(physiology_mod_immunities, listed_type, source) + else + if(ispath(mod_type)) + mod_type = "[mod_type]" + LAZYREMOVEASSOC(physiology_mod_immunities, mod_type, source) + +/// Stats that stack additively (baseline 0) instead of multiplicatively (baseline 1) +#define ADDITIVE_PHYSIOLOGY_STATS list("damage_resistance") + +/// Combines every active modifier's value for one stat into a final number +/datum/physiology/proc/get_stat_modifier(stat) + var/static/list/additive_stats = ADDITIVE_PHYSIOLOGY_STATS + . = (stat in additive_stats) ? 0 : 1 + for(var/key in get_physiology_modification()) + var/datum/physiology_modifier/modifier = physiology_modification[key] + if(!modifier.applies_to(src)) + continue + var/mod_value = modifier.vars[stat] //this is really wonky but far far better then the alternative + if(isnull(mod_value)) + continue + if(stat in additive_stats) + . += mod_value + else + . *= mod_value + +/// Actual hell but like idk man +/datum/physiology/proc/get_brute_mod() + return get_stat_modifier("brute_mod") +/datum/physiology/proc/get_burn_mod() + return get_stat_modifier("burn_mod") +/datum/physiology/proc/get_tox_mod() + return get_stat_modifier("tox_mod") +/datum/physiology/proc/get_oxy_mod() + return get_stat_modifier("oxy_mod") +/datum/physiology/proc/get_clone_mod() + return get_stat_modifier("clone_mod") +/datum/physiology/proc/get_stamina_mod() + return get_stat_modifier("stamina_mod") +/datum/physiology/proc/get_brain_mod() + return get_stat_modifier("brain_mod") +/datum/physiology/proc/get_heat_mod() + return get_stat_modifier("heat_mod") +/datum/physiology/proc/get_cold_mod() + return get_stat_modifier("cold_mod") +/datum/physiology/proc/get_damage_resistance() + return get_stat_modifier("damage_resistance") +/datum/physiology/proc/get_siemens_coeff() + return get_stat_modifier("siemens_coeff") +/datum/physiology/proc/get_stun_mod() + return get_stat_modifier("stun_mod") +/datum/physiology/proc/get_bleed_mod() + return get_stat_modifier("bleed_mod") +/datum/physiology/proc/get_pain_mod() + return get_stat_modifier("pain_mod") +/datum/physiology/proc/get_hygiene_mod() + return get_stat_modifier("hygiene_mod") +/datum/physiology/proc/get_hunger_mod() + return get_stat_modifier("hunger_mod") +/datum/physiology/proc/get_do_after_speed() + return get_stat_modifier("do_after_speed") + +#undef ADDITIVE_PHYSIOLOGY_STATS diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 95d6467d5cf..aecf51aea73 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -133,17 +133,8 @@ /// Prefix for spoken messages var/say_mod = "says" - /// Multipler for how quickly nutrition decreases - var/nutrition_mod = 1 - /// Multiplier for how quickly hygiene decreases - var/hygiene_mod = 1 - /// Multipler for blood loss - var/bleed_mod = 1 - /// Multipler for pain - var/pain_mod = 1 - /// Electrocution coeffcient - var/siemens_coeff = 1 - + ///our physiology species modifier + var/datum/physiology_modifier/species/species_mod /// Type of damage melee attacks do var/attack_type = BRUTE @@ -771,7 +762,7 @@ var/datum/customizer_choice/customizer_choice = CUSTOMIZER_CHOICE(entry.customizer_choice_type) customizer_choice.validate_entry(human, entry) -/datum/species/proc/on_species_gain(mob/living/carbon/C, datum/species/old_species, datum/preferences/pref_load) +/datum/species/proc/on_species_gain(mob/living/carbon/human/C, datum/species/old_species, datum/preferences/pref_load) // Drop the items the new species can't wear if((AGENDER in species_traits)) C.gender = PLURAL @@ -849,6 +840,8 @@ apply_customizers_to_character(C) on_gender_update(C) + if(species_mod) + C.physiology.add_physiology_modifier(species_mod) C.update_organ_requirements() //post species trait gains if(!(C.status_flags & BUILDING_ORGANS)) @@ -887,6 +880,8 @@ if(inherent_factions) C.remove_faction(inherent_factions) + if(species_mod) + C.physiology.remove_physiology_modifier(species_mod) SEND_SIGNAL(C, COMSIG_SPECIES_LOSS, src) @@ -1969,7 +1964,7 @@ SEND_SIGNAL(H, COMSIG_MOB_APPLY_DAMAGE, damage, damagetype, def_zone) var/hit_percent = 1 damage = max(damage - (blocked),0) - hit_percent = (hit_percent * (100-H.physiology.damage_resistance))/100 + hit_percent = (hit_percent * (100-H.physiology.get_damage_resistance()))/100 if(!damage || (!forced && hit_percent <= 0)) return 0 @@ -1991,7 +1986,7 @@ switch(damagetype) if(BRUTE) H.damageoverlaytemp = 20 - damage_amount = forced ? damage : damage * hit_percent * H.physiology.brute_mod + damage_amount = forced ? damage : damage * hit_percent * H.physiology.get_brute_mod() if(H.can_feel_pain()) if(damage_amount > 5) H.AdjustSleeping(-50) @@ -2026,7 +2021,7 @@ if(BURN) H.damageoverlaytemp = 20 - damage_amount = forced ? damage : damage * hit_percent * H.physiology.burn_mod + damage_amount = forced ? damage : damage * hit_percent * H.physiology.get_burn_mod() if(damage_amount > 10 && prob(damage_amount)) H.emote("pain") if(flashes) @@ -2046,19 +2041,19 @@ else H.adjustFireLoss(damage_amount) if(TOX) - damage_amount = forced ? damage : damage * hit_percent * H.physiology.tox_mod + damage_amount = forced ? damage : damage * hit_percent * H.physiology.get_tox_mod() H.adjustToxLoss(damage_amount) if(OXY) - damage_amount = forced ? damage : damage * hit_percent * H.physiology.oxy_mod + damage_amount = forced ? damage : damage * hit_percent * H.physiology.get_oxy_mod() H.adjustOxyLoss(damage_amount) if(CLONE) - damage_amount = forced ? damage : damage * hit_percent * H.physiology.clone_mod + damage_amount = forced ? damage : damage * hit_percent * H.physiology.get_clone_mod() H.adjustCloneLoss(damage_amount) if(BRAIN) - damage_amount = forced ? damage : damage * hit_percent * H.physiology.brain_mod + damage_amount = forced ? damage : damage * hit_percent * H.physiology.get_brain_mod() H.adjustOrganLoss(ORGAN_SLOT_BRAIN, damage_amount) return damage_amount @@ -2155,7 +2150,7 @@ debuff_level = calculate_heat_debuff_level(heat_excess) // Apply damage if(burn_damage > 0) - var/final_damage = CLAMP(burn_damage * H.physiology.heat_mod, 0, CONFIG_GET(number/per_tick/max_fire_damage)) + var/final_damage = CLAMP(burn_damage * H.physiology.get_heat_mod(), 0, CONFIG_GET(number/per_tick/max_fire_damage)) INVOKE_ASYNC(H, PROC_REF(apply_damage), final_damage, BURN, spread_damage = TRUE, flashes = FALSE) if(H.stat < UNCONSCIOUS && prob(burn_damage * 10 / 4)) INVOKE_ASYNC(H, TYPE_PROC_REF(/mob, emote), "pain") @@ -2172,7 +2167,7 @@ debuff_level = calculate_cold_debuff_level(cold_deficit) // Apply damage if(cold_damage > 0) - INVOKE_ASYNC(H, PROC_REF(apply_damage), cold_damage * H.physiology.cold_mod, BURN, flashes = FALSE) + INVOKE_ASYNC(H, PROC_REF(apply_damage), cold_damage * H.physiology.get_cold_mod(), BURN, flashes = FALSE) // Apply building cold debuffs apply_cold_debuffs(H, debuff_level, cold_deficit) // Clear effects when in safe range @@ -2426,7 +2421,7 @@ //////////// /datum/species/proc/spec_stun(mob/living/carbon/human/H,amount) - . = H.physiology.stun_mod * amount + . = H.physiology.get_stun_mod() * amount ////////////// //Space Move// diff --git a/code/modules/mob/living/carbon/human/species_types/automatons/_automaton.dm b/code/modules/mob/living/carbon/human/species_types/automatons/_automaton.dm index 1a6f0ab9d7b..0719d508192 100644 --- a/code/modules/mob/living/carbon/human/species_types/automatons/_automaton.dm +++ b/code/modules/mob/living/carbon/human/species_types/automatons/_automaton.dm @@ -129,7 +129,7 @@ inherent_biotypes = MOB_ROBOTIC | MOB_HUMANOID exotic_bloodtype = /datum/blood_type/oil - bleed_mod = 0.7 + species_mod = /datum/physiology_modifier/species/automaton punch_damage = 5 kick_damage = 5 diff --git a/code/modules/mob/living/carbon/human/species_types/halfling/_halfling.dm b/code/modules/mob/living/carbon/human/species_types/halfling/_halfling.dm index f22d3a70172..bf26b1b971a 100644 --- a/code/modules/mob/living/carbon/human/species_types/halfling/_halfling.dm +++ b/code/modules/mob/living/carbon/human/species_types/halfling/_halfling.dm @@ -103,7 +103,7 @@ /datum/body_marking/tonage, ) - nutrition_mod = 2 + species_mod = /datum/physiology_modifier/species/halfling /datum/species/halfling/check_roundstart_eligible() return TRUE diff --git a/code/modules/mob/living/carbon/human/species_types/other/aasimar.dm b/code/modules/mob/living/carbon/human/species_types/other/aasimar.dm index a1321f89f36..7d8700f1bd7 100644 --- a/code/modules/mob/living/carbon/human/species_types/other/aasimar.dm +++ b/code/modules/mob/living/carbon/human/species_types/other/aasimar.dm @@ -111,8 +111,7 @@ /datum/body_marking/tonage, ) - pain_mod = 0.9 // 10% less pain from wounds - bleed_mod = 0.8 // 20% less bleed rate from injuries + species_mod = /datum/physiology_modifier/species/aasimar /datum/species/aasimar/check_roundstart_eligible() return TRUE diff --git a/code/modules/mob/living/carbon/human/species_types/other/halforc.dm b/code/modules/mob/living/carbon/human/species_types/other/halforc.dm index efa3f639446..1d5e5c06d79 100644 --- a/code/modules/mob/living/carbon/human/species_types/other/halforc.dm +++ b/code/modules/mob/living/carbon/human/species_types/other/halforc.dm @@ -123,8 +123,7 @@ ORGAN_SLOT_GUTS = /obj/item/organ/guts, ) - nutrition_mod = 2 // 200% higher hunger rate. Hungry, hungry horcs - hygiene_mod = 1.5 + species_mod = /datum/physiology_modifier/species/horc /datum/species/halforc/check_roundstart_eligible() return TRUE diff --git a/code/modules/mob/living/carbon/human/species_types/other/werewolf.dm b/code/modules/mob/living/carbon/human/species_types/other/werewolf.dm index 60d13685b88..2cd40de43f9 100644 --- a/code/modules/mob/living/carbon/human/species_types/other/werewolf.dm +++ b/code/modules/mob/living/carbon/human/species_types/other/werewolf.dm @@ -77,8 +77,7 @@ meat = list(/obj/item/reagent_containers/food/snacks/meat/steak/human = 1, /obj/item/reagent_containers/food/snacks/meat/steak = 3) changesource_flags = WABBAJACK - bleed_mod = 0.6 - pain_mod = 0.2 + species_mod = /datum/physiology_modifier/species/werewolf /datum/species/werewolf/send_voice(mob/living/carbon/human/H) playsound(H, pick('sound/vo/mobs/wwolf/wolftalk1.ogg', 'sound/vo/mobs/wwolf/wolftalk2.ogg'), 100, TRUE, -1) diff --git a/code/modules/mob/living/carbon/human/species_types/vulture/_vulture.dm b/code/modules/mob/living/carbon/human/species_types/vulture/_vulture.dm index 4d036339162..c1ff9846612 100644 --- a/code/modules/mob/living/carbon/human/species_types/vulture/_vulture.dm +++ b/code/modules/mob/living/carbon/human/species_types/vulture/_vulture.dm @@ -40,7 +40,7 @@ default_color = "3e3e3e" use_skintones = TRUE - hygiene_mod = 1.25 + species_mod = /datum/physiology_modifier/species/medicator species_traits = list(NO_UNDERWEAR, HAIR, OLDGREY) inherent_traits = list(TRAIT_NOMOBSWAP, TRAIT_DEADNOSE, TRAIT_NASTY_EATER) diff --git a/code/modules/spells/spell_types/pointed/numbing_pleasure.dm b/code/modules/spells/spell_types/pointed/numbing_pleasure.dm index d4698d885e5..2714402243a 100644 --- a/code/modules/spells/spell_types/pointed/numbing_pleasure.dm +++ b/code/modules/spells/spell_types/pointed/numbing_pleasure.dm @@ -31,6 +31,6 @@ if(cast_on.mob_biotypes & MOB_UNDEAD) return //No, you don't get to feel good. You're an undead mob. Feel bad. cast_on.visible_message(span_info("[cast_on] begins to twitch as warmth radiates from them!"), span_notice("The pain from my wounds fade, every new one being a mere pleasant warmth!")) - phy.pain_mod *= 0.5 //Literally halves your pain modifier. - addtimer(VARSET_CALLBACK(phy, pain_mod, phy.pain_mod /= 0.5), 1 MINUTES) //Adds back the 0.5 of pain, basically setting it back to 1. + phy.add_physiology_modifier(/datum/physiology_modifier/painkiller) + addtimer(CALLBACK(phy, TYPE_PROC_REF(/datum/physiology, remove_physiology_modifier), /datum/physiology_modifier/painkiller), 1 MINUTES) cast_on.apply_status_effect(/datum/status_effect/buff/lux_drank/baothavitae) //Basically lowers fortune by 2 but +3 speed, it's powerful. Drugs cus Baotha. diff --git a/code/modules/spells/spell_types/pointed/persistence.dm b/code/modules/spells/spell_types/pointed/persistence.dm index 4ca2e6b6256..e57f80f11d1 100644 --- a/code/modules/spells/spell_types/pointed/persistence.dm +++ b/code/modules/spells/spell_types/pointed/persistence.dm @@ -31,10 +31,8 @@ if(ishuman(cast_on)) //BLEED AND PAIN var/mob/living/carbon/human/human_target = cast_on var/datum/physiology/phy = human_target.physiology - phy.bleed_mod *= 1.5 - phy.pain_mod *= 1.5 - addtimer(VARSET_CALLBACK(phy, bleed_mod, phy.bleed_mod /= 1.5), 19 SECONDS) - addtimer(VARSET_CALLBACK(phy, pain_mod, phy.pain_mod /= 1.5), 19 SECONDS) + phy.add_physiology_modifier(/datum/physiology_modifier/persistence) + addtimer(CALLBACK(phy, TYPE_PROC_REF(/datum/physiology, remove_physiology_modifier), /datum/physiology_modifier/persistence), 19 SECONDS) human_target.visible_message(span_danger("[cast_on]'s wounds become inflamed as their vitality is sapped away!"), span_userdanger("Ravox inflames my wounds and weakens my body!")) return @@ -57,8 +55,8 @@ if(ishuman(C)) var/mob/living/carbon/human/human_target = C var/datum/physiology/phy = human_target.physiology - phy.pain_mod *= 0.85 // 15% pain reduction - addtimer(VARSET_CALLBACK(phy, pain_mod, phy.pain_mod /= 0.85), 19 SECONDS) + phy.add_physiology_modifier(/datum/physiology_modifier/persistence_buff) + addtimer(CALLBACK(phy, TYPE_PROC_REF(/datum/physiology, remove_physiology_modifier), /datum/physiology_modifier/persistence_buff), 19 SECONDS) else if(HAS_TRAIT(cast_on, TRAIT_SIMPLE_WOUNDS)) for(var/datum/wound/bleeder in cast_on.simple_wounds) bleeder.woundpain = max(bleeder.sewn_woundpain, bleeder.woundpain * 0.5) diff --git a/code/modules/surgery/organs/external/wings/functional_wings.dm b/code/modules/surgery/organs/external/wings/functional_wings.dm index 511980363ac..642f858b8a0 100644 --- a/code/modules/surgery/organs/external/wings/functional_wings.dm +++ b/code/modules/surgery/organs/external/wings/functional_wings.dm @@ -98,7 +98,7 @@ wings_open = TRUE human.update_body_parts() - human.physiology.stun_mod *= 2 + human.physiology.add_physiology_modifier(/datum/physiology_modifier/flight) init_signals(human) passtable_on(human, SPECIES_FLIGHT_TRAIT) human.set_resting(FALSE, TRUE) @@ -123,7 +123,7 @@ wings_open = FALSE human.update_body_parts() - human.physiology.stun_mod *= 0.5 + human.physiology.remove_physiology_modifier(/datum/physiology_modifier/flight) passtable_off(human, SPECIES_FLIGHT_TRAIT) deltimer(flight_timer) diff --git a/code/modules/surgery/organs/internal/artery/_artery.dm b/code/modules/surgery/organs/internal/artery/_artery.dm index 5e17c5ff37c..643621b4052 100644 --- a/code/modules/surgery/organs/internal/artery/_artery.dm +++ b/code/modules/surgery/organs/internal/artery/_artery.dm @@ -55,7 +55,7 @@ if(ishuman(owner)) var/mob/living/carbon/human/human_owner = owner if(human_owner.physiology) - bleed_mod *= human_owner.physiology.bleed_mod + bleed_mod *= human_owner.physiology.get_bleed_mod() switch(owner.pulse) if(PULSE_NONE) bleed_mod *= 0 diff --git a/code/modules/surgery/organs/organ_processing/stomach.dm b/code/modules/surgery/organs/organ_processing/stomach.dm index cc7e904c2d5..25a6dd6ed11 100644 --- a/code/modules/surgery/organs/organ_processing/stomach.dm +++ b/code/modules/surgery/organs/organ_processing/stomach.dm @@ -43,10 +43,8 @@ if(SPT_PROB(round(-owner.satiety/77), delta_time)) owner.set_jitter_if_lower(10 SECONDS) hunger_rate *= 3 - hunger_rate *= owner.physiology.hunger_mod + hunger_rate *= owner.physiology.get_hunger_mod() hunger_rate *= optimal_threshold/max(stomach_efficiency, failing_threshold) - if (ishuman(owner)) - hunger_rate *= owner.dna.species.nutrition_mod owner.adjust_nutrition(-hunger_rate * delta_time) if(owner.hydration > 0) var/thirst_rate = owner.total_hydration_req diff --git a/vanderlin.dme b/vanderlin.dme index 39b9c65d95d..1d6a02499cc 100644 --- a/vanderlin.dme +++ b/vanderlin.dme @@ -3775,7 +3775,6 @@ #include "code\modules\mob\living\carbon\human\init_signals.dm" #include "code\modules\mob\living\carbon\human\inventory.dm" #include "code\modules\mob\living\carbon\human\life.dm" -#include "code\modules\mob\living\carbon\human\physiology.dm" #include "code\modules\mob\living\carbon\human\species.dm" #include "code\modules\mob\living\carbon\human\status_procs.dm" #include "code\modules\mob\living\carbon\human\topic.dm" @@ -3816,6 +3815,14 @@ #include "code\modules\mob\living\carbon\human\npc\species_hostile\rakshari_hostile.dm" #include "code\modules\mob\living\carbon\human\npc\species_hostile\tiefling_hostile.dm" #include "code\modules\mob\living\carbon\human\npc\species_hostile\triton_hostile.dm" +#include "code\modules\mob\living\carbon\human\physiology\physiology.dm" +#include "code\modules\mob\living\carbon\human\physiology\modifiers\_base.dm" +#include "code\modules\mob\living\carbon\human\physiology\modifiers\briar.dm" +#include "code\modules\mob\living\carbon\human\physiology\modifiers\curses.dm" +#include "code\modules\mob\living\carbon\human\physiology\modifiers\maniac.dm" +#include "code\modules\mob\living\carbon\human\physiology\modifiers\species.dm" +#include "code\modules\mob\living\carbon\human\physiology\modifiers\status_effects.dm" +#include "code\modules\mob\living\carbon\human\physiology\modifiers\vampire.dm" #include "code\modules\mob\living\carbon\human\species_types\automatons\_automaton.dm" #include "code\modules\mob\living\carbon\human\species_types\automatons\action.dm" #include "code\modules\mob\living\carbon\human\species_types\automatons\assembly.dm" From 2557b60f1456dcd3ae9708e83ecbe9f8ea82aa06 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Mon, 27 Jul 2026 09:01:12 -0800 Subject: [PATCH 2/6] removes untrue comments since species is standalone --- .../mob/living/carbon/human/physiology/modifiers/_base.dm | 2 +- code/modules/mob/living/carbon/human/physiology/physiology.dm | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/code/modules/mob/living/carbon/human/physiology/modifiers/_base.dm b/code/modules/mob/living/carbon/human/physiology/modifiers/_base.dm index c011c136b49..99ca7522ae9 100644 --- a/code/modules/mob/living/carbon/human/physiology/modifiers/_base.dm +++ b/code/modules/mob/living/carbon/human/physiology/modifiers/_base.dm @@ -73,7 +73,7 @@ GLOBAL_LIST_EMPTY(physiology_modification_cache) phys_mod = GLOB.physiology_modification_cache[modtype] = new modtype return phys_mod -/// The "always on" variable modifier every physiology gets on creation. This is what species defaults + direct/admin edits get written to, so nothing gets wiped when species changes. +/// The "always on" variable modifier every physiology gets on creation. This is what direct/admin edits get written to. /datum/physiology_modifier/base id = "base" variable = TRUE diff --git a/code/modules/mob/living/carbon/human/physiology/physiology.dm b/code/modules/mob/living/carbon/human/physiology/physiology.dm index 5e701576d66..6ffd6659cc0 100644 --- a/code/modules/mob/living/carbon/human/physiology/physiology.dm +++ b/code/modules/mob/living/carbon/human/physiology/physiology.dm @@ -25,10 +25,6 @@ base_modifier = new add_physiology_modifier(base_modifier) -/// Direct access to the always-on base modifier, for species seeding or admin/genetic edits -/datum/physiology/proc/get_base_modifier() - return base_modifier - /// Add a physiology modifier to this holder. If a variable subtype is passed in as the first argument, it will make a new datum. If ID conflicts, it will overwrite the old ID. /datum/physiology/proc/add_physiology_modifier(datum/physiology_modifier/type_or_datum) if(ispath(type_or_datum)) From 0956f4a80c7a7b350e8bdca052305dd490c2b93c Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Mon, 27 Jul 2026 15:52:08 -0800 Subject: [PATCH 3/6] adds a mana_regen_mod to physiology which is applied to positive mana regeneration --- code/datums/mana/mana_pool.dm | 4 ++++ .../mob/living/carbon/human/physiology/modifiers/_base.dm | 2 ++ code/modules/mob/living/carbon/human/physiology/physiology.dm | 2 ++ 3 files changed, 8 insertions(+) diff --git a/code/datums/mana/mana_pool.dm b/code/datums/mana/mana_pool.dm index ec19e02bf04..d7d7984a5ca 100644 --- a/code/datums/mana/mana_pool.dm +++ b/code/datums/mana/mana_pool.dm @@ -408,6 +408,10 @@ if (amount == 0) return amount + if(amount > 0 && ishuman(parent)) + var/mob/living/carbon/human/mob = parent + amount *= mob.physiology?.get_mana_regen_mod() + var/result = clamp(src.amount + amount, 0, maximum_mana_capacity) . = result - src.amount // Return the amount that was used src.amount = result diff --git a/code/modules/mob/living/carbon/human/physiology/modifiers/_base.dm b/code/modules/mob/living/carbon/human/physiology/modifiers/_base.dm index 99ca7522ae9..d52c246fc5e 100644 --- a/code/modules/mob/living/carbon/human/physiology/modifiers/_base.dm +++ b/code/modules/mob/living/carbon/human/physiology/modifiers/_base.dm @@ -25,6 +25,8 @@ GLOBAL_LIST_EMPTY(physiology_modification_cache) var/stamina_mod = 1 /// % of brain damage taken from all sources var/brain_mod = 1 + /// multiplier applied to mana regen + var/mana_regen_mod = 1 /// % of burn damage taken from heat (stacks with burn_mod) var/heat_mod = 1 diff --git a/code/modules/mob/living/carbon/human/physiology/physiology.dm b/code/modules/mob/living/carbon/human/physiology/physiology.dm index 6ffd6659cc0..3ede1c8762b 100644 --- a/code/modules/mob/living/carbon/human/physiology/physiology.dm +++ b/code/modules/mob/living/carbon/human/physiology/physiology.dm @@ -179,5 +179,7 @@ return get_stat_modifier("hunger_mod") /datum/physiology/proc/get_do_after_speed() return get_stat_modifier("do_after_speed") +/datum/physiology/proc/get_mana_regen_mod() + return get_stat_modifier("mana_regen_mod") #undef ADDITIVE_PHYSIOLOGY_STATS From 634385314080ce62759dbcae874a680077892363 Mon Sep 17 00:00:00 2001 From: Borbop <82520990+dwasint@users.noreply.github.com> Date: Thu, 30 Jul 2026 04:08:13 -0800 Subject: [PATCH 4/6] Update code/modules/mob/living/carbon/human/physiology/physiology.dm Co-authored-by: CheffieGithub <113442598+CheffieGithub@users.noreply.github.com> --- .../carbon/human/physiology/physiology.dm | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/code/modules/mob/living/carbon/human/physiology/physiology.dm b/code/modules/mob/living/carbon/human/physiology/physiology.dm index 3ede1c8762b..279be334f00 100644 --- a/code/modules/mob/living/carbon/human/physiology/physiology.dm +++ b/code/modules/mob/living/carbon/human/physiology/physiology.dm @@ -147,38 +147,55 @@ /// Actual hell but like idk man /datum/physiology/proc/get_brute_mod() return get_stat_modifier("brute_mod") + /datum/physiology/proc/get_burn_mod() return get_stat_modifier("burn_mod") + /datum/physiology/proc/get_tox_mod() return get_stat_modifier("tox_mod") + /datum/physiology/proc/get_oxy_mod() return get_stat_modifier("oxy_mod") + /datum/physiology/proc/get_clone_mod() return get_stat_modifier("clone_mod") + /datum/physiology/proc/get_stamina_mod() return get_stat_modifier("stamina_mod") + /datum/physiology/proc/get_brain_mod() return get_stat_modifier("brain_mod") + /datum/physiology/proc/get_heat_mod() return get_stat_modifier("heat_mod") + /datum/physiology/proc/get_cold_mod() return get_stat_modifier("cold_mod") + /datum/physiology/proc/get_damage_resistance() return get_stat_modifier("damage_resistance") + /datum/physiology/proc/get_siemens_coeff() return get_stat_modifier("siemens_coeff") + /datum/physiology/proc/get_stun_mod() return get_stat_modifier("stun_mod") + /datum/physiology/proc/get_bleed_mod() return get_stat_modifier("bleed_mod") + /datum/physiology/proc/get_pain_mod() return get_stat_modifier("pain_mod") + /datum/physiology/proc/get_hygiene_mod() return get_stat_modifier("hygiene_mod") + /datum/physiology/proc/get_hunger_mod() return get_stat_modifier("hunger_mod") + /datum/physiology/proc/get_do_after_speed() return get_stat_modifier("do_after_speed") + /datum/physiology/proc/get_mana_regen_mod() return get_stat_modifier("mana_regen_mod") From 9ccfe13641b742722ef95ba4893ef1dcc200c4cf Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 11 Aug 2026 08:11:45 -0800 Subject: [PATCH 5/6] Update human.dm --- code/modules/mob/living/carbon/human/human.dm | 2 -- 1 file changed, 2 deletions(-) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index e241dc2de45..9840e62994d 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -126,8 +126,6 @@ if(dna.species) set_species(dna.species.type, initial_set = TRUE) - //initialise organs - create_internal_organs() //most of it is done in set_species now, this is only for parent call status_flags &= ~BUILDING_ORGANS culture = GLOB.culture_singletons[culture] From 1a3dc84f777f5bd7d06f94490c5f60be53b21d64 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Tue, 11 Aug 2026 22:12:50 -0800 Subject: [PATCH 6/6] phys mods --- code/datums/status_effects/buffs/adrenaline_rush.dm | 4 ++-- .../carbon/human/physiology/modifiers/status_effects.dm | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/code/datums/status_effects/buffs/adrenaline_rush.dm b/code/datums/status_effects/buffs/adrenaline_rush.dm index 71157c553e2..346f9b7f9b9 100644 --- a/code/datums/status_effects/buffs/adrenaline_rush.dm +++ b/code/datums/status_effects/buffs/adrenaline_rush.dm @@ -17,7 +17,7 @@ var/mob/living/carbon/human/human = owner if(istype(human)) human.blood_volume = min((human.blood_volume + blood_restore), BLOOD_VOLUME_NORMAL) - human.physiology.pain_mod *= 0.5 + human.physiology.add_physiology_modifier(/datum/physiology_modifier/adrenaline_rush) /datum/status_effect/buff/adrenaline_rush/on_remove() . = ..() @@ -30,7 +30,7 @@ /datum/status_effect/buff/adrenaline_rush/proc/clear_adrenaline_rush() var/mob/living/carbon/human/human = owner if(istype(human)) - human.physiology.pain_mod *= 2 + human.physiology.remove_physiology_modifier(/datum/physiology_modifier/adrenaline_rush) /datum/status_effect/buff/adrenaline_rush/ranged effectedstats = list(STAT_SPEED = 2) diff --git a/code/modules/mob/living/carbon/human/physiology/modifiers/status_effects.dm b/code/modules/mob/living/carbon/human/physiology/modifiers/status_effects.dm index 49604bcac71..17d248bde3a 100644 --- a/code/modules/mob/living/carbon/human/physiology/modifiers/status_effects.dm +++ b/code/modules/mob/living/carbon/human/physiology/modifiers/status_effects.dm @@ -14,3 +14,7 @@ /datum/physiology_modifier/flight id = "flight" stun_mod = 2 + +/datum/physiology_modifier/adrenaline_rush + id = "adrenaline_rush" + pain_mod = 0.5