mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-28 10:01:58 +00:00
* Basic Mob Carp Part II: Regenerator (#71437) ## About The Pull Request <details> <summary>Video</summary> https://user-images.githubusercontent.com/7483112/203324325-5bf46e0f-b294-4832-9016-aec275036ca9.mp4 </details> Adds a "Regenerator" component, applies it to carp, and removes the previous implementation from megacarp. The function of this component is that any time you take damage a timer is reset, when that timer expires you will begin regenerating health and display an animated border for visual feedback. This was previously a function of mega carp but was extremely obscure because there was _no_ feedback, so it would only be visible that it was happening if you were wearing a medical hud. Additionally because mega carp will pursue a target until it dies you probably wouldn't notice it even then, it had to survive a fight in order to gain any value from this. This will still be true for all carp until AI changes are pushed, so until then this isn't going to do very much for NPCs but might be a small buff to player controlled carp (though those can all retreat to a carp rift for a similar effect). This also modifies a few "defence" procs which were either directly setting HP or neglecting to call signals from a base proc, as they would bypass triggering the effect. This should make them more reliable for other things which rely on those signals too. ## Why It's Good For The Game Gives an iconic creature some more unique behaviour than "moves directly towards you and bites". Gives visual feedback to some behaviour which has existed invisibly for a long time. ## Changelog 🆑 add: All Space Carp will now start regenerating health after 6 seconds of not taking any damage, until they're back to full health. This behaviour was previously unique to mega carp. /🆑 * Basic Mob Carp Part II: Regenerator Co-authored-by: Jacquerel <hnevard@gmail.com>
94 lines
3.4 KiB
Plaintext
94 lines
3.4 KiB
Plaintext
#define REGENERATION_FILTER "healing_glow"
|
|
|
|
/**
|
|
* # Regenerator component
|
|
*
|
|
* A mob with this component will regenerate its health over time, as long as it has not received damage
|
|
* in the last X seconds. Taking any damage will reset this cooldown.
|
|
*/
|
|
/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
|
|
/// 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
|
|
var/outline_colour
|
|
/// 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)
|
|
if (!isliving(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
src.regeneration_delay = regeneration_delay
|
|
src.health_per_second = health_per_second
|
|
src.ignore_damage_types = ignore_damage_types
|
|
src.outline_colour = outline_colour
|
|
|
|
/datum/component/regenerator/RegisterWithParent()
|
|
. = ..()
|
|
RegisterSignal(parent, COMSIG_MOB_APPLY_DAMAGE, PROC_REF(on_take_damage))
|
|
|
|
/datum/component/regenerator/UnregisterFromParent()
|
|
. = ..()
|
|
if(regeneration_start_timer)
|
|
deltimer(regeneration_start_timer)
|
|
UnregisterSignal(parent, COMSIG_MOB_APPLY_DAMAGE)
|
|
stop_regenerating()
|
|
|
|
/datum/component/regenerator/Destroy(force, silent)
|
|
stop_regenerating()
|
|
. = ..()
|
|
if(regeneration_start_timer)
|
|
deltimer(regeneration_start_timer)
|
|
|
|
/// When you take damage, reset the cooldown and start processing
|
|
/datum/component/regenerator/proc/on_take_damage(datum/source, damage, damagetype)
|
|
SIGNAL_HANDLER
|
|
|
|
if (damage <= 0)
|
|
return
|
|
if (locate(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)
|
|
|
|
/// Start processing health regeneration, and show animation if provided
|
|
/datum/component/regenerator/proc/start_regenerating()
|
|
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)
|
|
if (!outline_colour)
|
|
return
|
|
living_parent.add_filter(REGENERATION_FILTER, 2, list("type" = "outline", "color" = outline_colour, "alpha" = 0, "size" = 1))
|
|
var/filter = living_parent.get_filter(REGENERATION_FILTER)
|
|
animate(filter, alpha = 200, time = 0.5 SECONDS, loop = -1)
|
|
animate(alpha = 0, time = 0.5 SECONDS)
|
|
|
|
/datum/component/regenerator/proc/stop_regenerating()
|
|
STOP_PROCESSING(SSobj, src)
|
|
var/mob/living/living_parent = parent
|
|
var/filter = living_parent.get_filter(REGENERATION_FILTER)
|
|
animate(filter)
|
|
living_parent.remove_filter(REGENERATION_FILTER)
|
|
|
|
/datum/component/regenerator/process(delta_time = SSMOBS_DT)
|
|
var/mob/living/living_parent = parent
|
|
if (living_parent.stat == DEAD)
|
|
stop_regenerating()
|
|
return
|
|
if (living_parent.health == living_parent.maxHealth)
|
|
stop_regenerating()
|
|
return
|
|
living_parent.heal_overall_damage(health_per_second * delta_time)
|
|
|
|
#undef REGENERATION_FILTER
|