From 249df481162dbd3f73b4173cdd2ed5ec19c7c8a4 Mon Sep 17 00:00:00 2001 From: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Date: Sun, 26 May 2024 13:58:16 -0500 Subject: [PATCH] Deletes `handle_random_events`, saving us from 1 whole proc call in `Life` (#83421) ## About The Pull Request Dumps `handle_random_events` in the bin, giving us one less proc in `Life`, that's a free proc call optimization baby. Replaces its only implementation with a status effect conditionally applied when gaining / losing tox dam. ## Changelog :cl: Melbert refactor: Refactored the way high toxins cause you to vomit. /:cl: --- code/__DEFINES/mobs.dm | 3 ++ .../status_effects/debuffs/tox_vomit.dm | 23 +++++++++++++++ .../modules/mob/living/carbon/damage_procs.dm | 29 ++++++++++--------- .../mob/living/carbon/human/human_defines.dm | 2 +- code/modules/mob/living/carbon/human/life.dm | 13 --------- code/modules/mob/living/damage_procs.dm | 17 +++++++++++ code/modules/mob/living/life.dm | 7 ----- code/modules/unit_tests/mob_damage.dm | 19 ++++++++++++ tgstation.dme | 1 + 9 files changed, 79 insertions(+), 35 deletions(-) create mode 100644 code/datums/status_effects/debuffs/tox_vomit.dm diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 5ab16b5a5ff..7f007e5b30e 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -954,6 +954,9 @@ GLOBAL_LIST_INIT(layers_to_offset, list( /// Types of bullets that mining mobs take full damage from #define MINING_MOB_PROJECTILE_VULNERABILITY list(BRUTE) +/// Helper macro that determines if the mob is at the threshold to start vomitting due to high toxin levels +#define AT_TOXIN_VOMIT_THRESHOLD(mob) (mob.getToxLoss() > 45 && mob.nutrition > 20) + /// The duration of the flip emote animation #define FLIP_EMOTE_DURATION 0.7 SECONDS diff --git a/code/datums/status_effects/debuffs/tox_vomit.dm b/code/datums/status_effects/debuffs/tox_vomit.dm new file mode 100644 index 00000000000..c1f5aa651ef --- /dev/null +++ b/code/datums/status_effects/debuffs/tox_vomit.dm @@ -0,0 +1,23 @@ +/// Simple status effect applied when a mob has high toxins and starts to vomit regularly +/datum/status_effect/tox_vomit + id = "vomitting_from_toxins" + tick_interval = 2 SECONDS + alert_type = null + /// Has a chance to count up every tick, until it reaches a threshold, which causes the mob to vomit and resets + VAR_PRIVATE/puke_counter = 0 + +/datum/status_effect/tox_vomit/tick(seconds_between_ticks) + if(!AT_TOXIN_VOMIT_THRESHOLD(owner)) + qdel(src) + return + + if(owner.stat == DEAD || HAS_TRAIT(owner, TRAIT_STASIS)) + return + + puke_counter += SPT_PROB(30, seconds_between_ticks) + if(puke_counter < 50) // This is like 150 seconds apparently according to old comments + return + + var/mob/living/carbon/human/sick_guy = owner + sick_guy.vomit(VOMIT_CATEGORY_DEFAULT, lost_nutrition = 20) + puke_counter = 0 diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm index 30ff21ccc39..aeba381703b 100644 --- a/code/modules/mob/living/carbon/damage_procs.dm +++ b/code/modules/mob/living/carbon/damage_procs.dm @@ -128,20 +128,21 @@ return FALSE return adjustFireLoss(diff, updating_health, forced, required_bodytype) -/mob/living/carbon/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype = ALL) - if(!can_adjust_tox_loss(amount, forced, required_biotype)) - return 0 - if(!forced && HAS_TRAIT(src, TRAIT_TOXINLOVER)) //damage becomes healing and healing becomes damage - amount = -amount - if(HAS_TRAIT(src, TRAIT_TOXIMMUNE)) //Prevents toxin damage, but not healing - amount = min(amount, 0) - if(amount > 0) - blood_volume = max(blood_volume - (5*amount), 0) - else - blood_volume = max(blood_volume - amount, 0) - else if(!forced && HAS_TRAIT(src, TRAIT_TOXIMMUNE)) //Prevents toxin damage, but not healing - amount = min(amount, 0) - return ..() +/mob/living/carbon/human/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype = ALL) + . = ..() + if(. >= 0) // 0 = no damage, + values = healed damage + return . + + if(AT_TOXIN_VOMIT_THRESHOLD(src)) + apply_status_effect(/datum/status_effect/tox_vomit) + +/mob/living/carbon/human/setToxLoss(amount, updating_health, forced, required_biotype) + . = ..() + if(. >= 0) + return . + + if(AT_TOXIN_VOMIT_THRESHOLD(src)) + apply_status_effect(/datum/status_effect/tox_vomit) /mob/living/carbon/adjustStaminaLoss(amount, updating_stamina, forced, required_biotype = ALL) . = ..() diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 84d1c454668..5ee91f88d1b 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -71,7 +71,7 @@ /mob/living/carbon/human, /mob/living/basic/slime, )) - var/lastpuke = 0 + var/account_id var/hardcore_survival_score = 0 diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index be355bddbea..d8119c6a527 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -270,19 +270,6 @@ return min(1, thermal_protection) -/mob/living/carbon/human/handle_random_events(seconds_per_tick, times_fired) - //Puke if toxloss is too high - if(stat) - return - if(getToxLoss() < 45 || nutrition <= 20) - return - - lastpuke += SPT_PROB(30, seconds_per_tick) - if(lastpuke >= 50) // about 25 second delay I guess // This is actually closer to 150 seconds - vomit(VOMIT_CATEGORY_DEFAULT, lost_nutrition = 20) - lastpuke = 0 - - /mob/living/carbon/human/has_smoke_protection() if(isclothing(wear_mask)) if(wear_mask.clothing_flags & BLOCK_GAS_SMOKE_EFFECT) diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 286a3b30ed8..49f7a7d7701 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -359,14 +359,31 @@ /mob/living/proc/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype = ALL) if(!can_adjust_tox_loss(amount, forced, required_biotype)) return 0 + + if(!forced && HAS_TRAIT(src, TRAIT_TOXINLOVER)) //damage becomes healing and healing becomes damage + amount = -amount + if(HAS_TRAIT(src, TRAIT_TOXIMMUNE)) //Prevents toxin damage, but not healing + amount = min(amount, 0) + if(blood_volume) + if(amount > 0) + blood_volume = max(blood_volume - (5 * amount), 0) + else + blood_volume = max(blood_volume - amount, 0) + + else if(!forced && HAS_TRAIT(src, TRAIT_TOXIMMUNE)) //Prevents toxin damage, but not healing + amount = min(amount, 0) + . = toxloss toxloss = clamp((toxloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2) . -= toxloss + if(!.) // no change, no need to update return FALSE + if(updating_health) updatehealth() + /mob/living/proc/setToxLoss(amount, updating_health = TRUE, forced = FALSE, required_biotype = ALL) if(!forced && (status_flags & GODMODE)) return FALSE diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index dd7e8a17c9b..7c2af9a1572 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -53,10 +53,6 @@ if (QDELETED(src)) // diseases can qdel the mob via transformations return - if(stat != DEAD) - //Random events (vomiting etc) - handle_random_events(seconds_per_tick, times_fired) - //Handle temperature/pressure differences between body and environment var/datum/gas_mixture/environment = loc.return_air() if(environment) @@ -82,9 +78,6 @@ /mob/living/proc/handle_wounds(seconds_per_tick, times_fired) return -/mob/living/proc/handle_random_events(seconds_per_tick, times_fired) - return - // Base mob environment handler for body temperature /mob/living/proc/handle_environment(datum/gas_mixture/environment, seconds_per_tick, times_fired) var/loc_temp = get_temperature(environment) diff --git a/code/modules/unit_tests/mob_damage.dm b/code/modules/unit_tests/mob_damage.dm index c27bc31ffe0..64b12b8f477 100644 --- a/code/modules/unit_tests/mob_damage.dm +++ b/code/modules/unit_tests/mob_damage.dm @@ -580,3 +580,22 @@ if(!verify_damage(gusgus, 0, included_types = BRUTELOSS)) TEST_FAIL("heal_overall_damage did not apply its healing correctly on the mouse!") + +/// Tests that humans get the tox_vomit status effect when heavily poisoned +/datum/unit_test/human_tox_damage + +/datum/unit_test/human_tox_damage/Run() + // Spawn a dummy, give it a bunch of tox damage. It should get the status effect. + var/mob/living/carbon/human/dummy = allocate(/mob/living/carbon/human/consistent) + dummy.setToxLoss(75) + var/datum/status_effect/tox_effect = dummy.has_status_effect(/datum/status_effect/tox_vomit) + TEST_ASSERT_NOTNULL(tox_effect, "Dummy didn't get tox_vomit status effect despite at [dummy.getToxLoss()] toxin damage (Method: SET)!") + // Clear the toxin damage away, and force a status effect tick: It should delete itself + dummy.setToxLoss(0) + tox_effect.tick(initial(tox_effect.tick_interval)) + TEST_ASSERT(QDELETED(tox_effect), "Dummy still has tox_vomit status effect despite at [dummy.getToxLoss()] toxin damage (Method: SET)!") + // Test another method of gaining tox damage, use an entirely clean slate just to be sure + var/mob/living/carbon/human/dummy_two = allocate(/mob/living/carbon/human/consistent) + dummy_two.adjustToxLoss(75) + var/datum/status_effect/tox_effect_two = dummy_two.has_status_effect(/datum/status_effect/tox_vomit) + TEST_ASSERT_NOTNULL(tox_effect_two, "Dummy didn't get tox_vomit status effect at [dummy_two.getToxLoss()] toxin damage (METHOD: ADJUST)!") diff --git a/tgstation.dme b/tgstation.dme index 100561f0759..d35ffe575fa 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1843,6 +1843,7 @@ #include "code\datums\status_effects\debuffs\strandling.dm" #include "code\datums\status_effects\debuffs\terrified.dm" #include "code\datums\status_effects\debuffs\tower_of_babel.dm" +#include "code\datums\status_effects\debuffs\tox_vomit.dm" #include "code\datums\status_effects\debuffs\slime\slime_food.dm" #include "code\datums\status_effects\debuffs\slime\slime_leech.dm" #include "code\datums\status_effects\debuffs\slime\slimed.dm"