diff --git a/code/datums/components/regenerator.dm b/code/datums/components/regenerator.dm index ab0dca757386..e527e847f6d4 100644 --- a/code/datums/components/regenerator.dm +++ b/code/datums/components/regenerator.dm @@ -9,8 +9,16 @@ /datum/component/regenerator /// You will only regain health if you haven't been hurt for this many seconds var/regeneration_delay - /// Health to regenerate per second - var/health_per_second + /// Brute reagined every second + var/brute_per_second + /// Burn reagined every second + var/burn_per_second + /// Toxin reagined every second + var/tox_per_second + /// Oxygen reagined every second + var/oxy_per_second + /// If TRUE, we'll try to heal wounds as well. Useless for non-humans. + var/heals_wounds = FALSE /// List of damage types we don't care about, in case you want to only remove this with fire damage or something var/list/ignore_damage_types /// Colour of regeneration animation, or none if you don't want one @@ -18,12 +26,25 @@ /// When this timer completes we start restoring health, it is a timer rather than a cooldown so we can do something on its completion var/regeneration_start_timer -/datum/component/regenerator/Initialize(regeneration_delay = 6 SECONDS, health_per_second = 2, ignore_damage_types = list(STAMINA), outline_colour = COLOR_PALE_GREEN) +/datum/component/regenerator/Initialize( + regeneration_delay = 6 SECONDS, + brute_per_second = 2, + burn_per_second = 0, + tox_per_second = 0, + oxy_per_second = 0, + heals_wounds = FALSE, + ignore_damage_types = list(STAMINA), + outline_colour = COLOR_PALE_GREEN, +) if (!isliving(parent)) return COMPONENT_INCOMPATIBLE src.regeneration_delay = regeneration_delay - src.health_per_second = health_per_second + src.brute_per_second = brute_per_second + src.burn_per_second = burn_per_second + src.tox_per_second = tox_per_second + src.oxy_per_second = oxy_per_second + src.heals_wounds = heals_wounds src.ignore_damage_types = ignore_damage_types src.outline_colour = outline_colour @@ -48,24 +69,20 @@ /datum/component/regenerator/proc/on_take_damage(datum/source, damage, damagetype, ...) SIGNAL_HANDLER - if (damage <= 0) - return - if (locate(damagetype) in ignore_damage_types) + if (damagetype in ignore_damage_types) return stop_regenerating() - if(regeneration_start_timer) - deltimer(regeneration_start_timer) - regeneration_start_timer = addtimer(CALLBACK(src, PROC_REF(start_regenerating)), regeneration_delay, TIMER_STOPPABLE) + regeneration_start_timer = addtimer(CALLBACK(src, PROC_REF(start_regenerating)), regeneration_delay, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE) /// Start processing health regeneration, and show animation if provided /datum/component/regenerator/proc/start_regenerating() + . = TRUE + if (!should_be_regenning(parent)) + return FALSE var/mob/living/living_parent = parent - if (living_parent.stat == DEAD) - return - if (living_parent.health == living_parent.maxHealth) - return living_parent.visible_message(span_notice("[living_parent]'s wounds begin to knit closed!")) START_PROCESSING(SSobj, src) + regeneration_start_timer = null if (!outline_colour) return living_parent.add_filter(REGENERATION_FILTER, 2, list("type" = "outline", "color" = outline_colour, "alpha" = 0, "size" = 1)) @@ -81,19 +98,44 @@ living_parent.remove_filter(REGENERATION_FILTER) /datum/component/regenerator/process(seconds_per_tick = SSMOBS_DT) - var/mob/living/living_parent = parent - if (living_parent.stat == DEAD) + if (!should_be_regenning(parent)) stop_regenerating() return - if (living_parent.health == living_parent.maxHealth) - stop_regenerating() - return - do_heal(health_per_second * seconds_per_tick) // monkestation edit: minor refactor -// monkestation start: minor refactor -/datum/component/regenerator/proc/do_heal(amt) var/mob/living/living_parent = parent - living_parent.heal_overall_damage(amt) -// monkestation end + // Heal bonus for being in crit. Only applies to carbons + var/heal_mod = HAS_TRAIT(living_parent, TRAIT_CRITICAL_CONDITION) ? 2 : 1 + + var/need_mob_update = FALSE + if(brute_per_second) + need_mob_update += living_parent.adjustBruteLoss(-1 * heal_mod * brute_per_second * seconds_per_tick, updating_health = FALSE) + if(burn_per_second) + need_mob_update += living_parent.adjustFireLoss(-1 * heal_mod * burn_per_second * seconds_per_tick, updating_health = FALSE) + if(tox_per_second) + need_mob_update += living_parent.adjustToxLoss(-1 * heal_mod * tox_per_second * seconds_per_tick, updating_health = FALSE) + if(oxy_per_second) + need_mob_update += living_parent.adjustOxyLoss(-1 * heal_mod * oxy_per_second * seconds_per_tick, updating_health = FALSE) + + if(heals_wounds && iscarbon(parent)) + var/mob/living/carbon/carbon_parent = living_parent + for(var/datum/wound/iter_wound as anything in carbon_parent.all_wounds) + if(SPT_PROB(2 - (iter_wound.severity / 2), seconds_per_tick)) + iter_wound.remove_wound() + need_mob_update++ + + if(need_mob_update) + living_parent.updatehealth() + +/// Checks if the passed mob is in a valid state to be regenerating +/datum/component/regenerator/proc/should_be_regenning(mob/living/who) + if(who.stat == DEAD) + return FALSE + if(heals_wounds && iscarbon(who)) + var/mob/living/carbon/carbon_who = who + if(length(carbon_who.all_wounds) > 0) + return TRUE + if(who.health != who.maxHealth) + return TRUE + return FALSE #undef REGENERATION_FILTER diff --git a/code/modules/mob/living/basic/space_fauna/bear/_bear.dm b/code/modules/mob/living/basic/space_fauna/bear/_bear.dm index 5995844362a0..8e33d13dc79c 100644 --- a/code/modules/mob/living/basic/space_fauna/bear/_bear.dm +++ b/code/modules/mob/living/basic/space_fauna/bear/_bear.dm @@ -125,7 +125,7 @@ AddComponent(/datum/component/regenerator,\ regeneration_delay = 1 SECONDS,\ - health_per_second = 5,\ + brute_per_second = 5,\ outline_colour = COLOR_YELLOW,\ ) diff --git a/code/modules/mob/living/basic/space_fauna/changeling/flesh_spider.dm b/code/modules/mob/living/basic/space_fauna/changeling/flesh_spider.dm index febba8130541..86a24e922801 100644 --- a/code/modules/mob/living/basic/space_fauna/changeling/flesh_spider.dm +++ b/code/modules/mob/living/basic/space_fauna/changeling/flesh_spider.dm @@ -59,7 +59,7 @@ AddComponent(\ /datum/component/regenerator,\ regeneration_delay = 4 SECONDS,\ - health_per_second = maxHealth / 6,\ + brute_per_second = maxHealth / 6,\ outline_colour = COLOR_PINK,\ ) diff --git a/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm b/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm index 0c7101f90962..d2dbf4a78460 100644 --- a/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm +++ b/monkestation/code/modules/mob/living/carbon/human/species_type/teratoma.dm @@ -88,11 +88,19 @@ /obj/item/organ/internal/liver/teratoma name = "horribly malformed liver" desc = "It seems to pulse as if existed out of spite of nature itself." - var/datum/component/regenerator/teratoma/oh_god_why + var/datum/component/regenerator/oh_god_why /obj/item/organ/internal/liver/teratoma/on_insert(mob/living/carbon/organ_owner, special) . = ..() - oh_god_why = organ_owner.AddComponent(/datum/component/regenerator/teratoma, health_per_second = 1, ignore_damage_types = list(OXY, STAMINA), outline_colour = COLOR_RED_LIGHT) // ignore oxy damage so they can regen while in crit if you just leave them there + oh_god_why = organ_owner.AddComponent(\ + /datum/component/regenerator,\ + brute_per_second = 2,\ + burn_per_second = 2,\ + tox_per_second = 1,\ + heals_wounds = TRUE,\ + ignore_damage_types = list(OXY, STAMINA),\ + outline_colour = COLOR_RED_LIGHT\ + ) // ignore oxy damage so they can regen while in crit if you just leave them there RegisterSignal(organ_owner, COMSIG_ATOM_EXPOSE_REAGENTS, PROC_REF(prevent_banned_reagent_exposure)) if(ishuman(organ_owner)) var/mob/living/carbon/human/human_owner = organ_owner @@ -137,8 +145,3 @@ incidents_left = INFINITY luck_mod = 0.75 damage_mod = 0.2 - -/datum/component/regenerator/teratoma/do_heal(amt) - var/mob/living/living_parent = parent - living_parent.heal_overall_damage(brute = amt, burn = amt, updating_health = FALSE) - living_parent.adjustToxLoss(-(amt * 0.5), updating_health = TRUE)