Files
Bubberstation/code/datums/components/ground_sinking.dm
Comxy b485ad1e47 New Mob [Garden Gnomes] (#72672)
## About The Pull Request
Garden gnomes can go into the ground when they stand still for a while.
If they are damaged and underground they will heal. If they are
underground they will also gain damage resistance. They can make people
trip when underground and deal some damage. They are available through
golden slime cores or you can collect them from cargo with an emag. If
one of them gets damaged they will all retaliate against the attacker.

They have a very realistic colour pallet based on online gathered data.
Depending on their colour pallets some of them have a very low chance of
spawning.
## Why It's Good For The Game
These new garden gnomes come with expanding the world building of space
station 13. These gnomes will add more variety to the game play and use
an interesting AI and behavior that interacts with the player.

![gnome_promo1](https://user-images.githubusercontent.com/25363960/212195653-0b434f17-e73c-4a87-b8b8-e96dcf057269.PNG)

![gnome_promo2](https://user-images.githubusercontent.com/25363960/212195658-4cbcd863-dcab-4643-9e3b-686e79dcb435.PNG)
## Changelog
🆑
add: Adds garden gnomes.
imageadd: Adds garden gnome sprites.
/🆑
2023-01-17 10:02:20 -08:00

143 lines
5.0 KiB
Plaintext

#define REGENERATION_FILTER "healing_glow"
/**
* # Ground sinking component (basicly only for garden gnomes ever at this point)
*
* A basic mob with this component will sink into the ground, once sinked into the ground it will regenerate and
* might gain damage resistence. Can be combined with caltrop.
*/
/datum/component/ground_sinking
/// The icon state of the parent
var/target_icon_state
/// You will only sink if you haven't been walking for this many seconds
var/ground_sinking_delay
/// The speed at which the mob will sink
var/sink_speed
/// If we will heal once we are sinked
var/heal_when_sinked
/// Health to regenerate per second
var/health_per_second
/// Outline colour of the regeneration
var/outline_colour
/// Our damage_coeffs when we are sinked
var/damage_res_sinked
/// If we sinked into the ground right now
var/sinked = FALSE
/// If we sinking into the ground right now
var/is_sinking = FALSE
/// How far we have sinked
var/sink_count = 0
/// When this timer completes we start sinking
var/ground_sinking_start_timer
/datum/component/ground_sinking/Initialize(target_icon_state,
ground_sinking_delay = 8 SECONDS,
sink_speed = 1 SECONDS,
heal_when_sinked = TRUE,
health_per_second = 1,
outline_colour = COLOR_PALE_GREEN,
damage_res_sinked = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1))
if (!isbasicmob(parent))
return COMPONENT_INCOMPATIBLE
src.target_icon_state = target_icon_state
src.ground_sinking_delay = ground_sinking_delay
src.sink_speed = sink_speed
src.heal_when_sinked = heal_when_sinked
src.health_per_second = health_per_second
src.outline_colour = outline_colour
src.damage_res_sinked = damage_res_sinked
/datum/component/ground_sinking/RegisterWithParent()
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved))
/datum/component/ground_sinking/UnregisterFromParent()
if(sinked || is_sinking)
unsink()
if(ground_sinking_start_timer)
deltimer(ground_sinking_start_timer)
UnregisterSignal(parent, COMSIG_MOVABLE_MOVED)
/datum/component/ground_sinking/Destroy(force, silent)
if(sinked || is_sinking)
unsink()
. = ..()
if(ground_sinking_start_timer)
deltimer(ground_sinking_start_timer)
/// When you take damage, reset the cooldown and start processing
/datum/component/ground_sinking/proc/on_moved(mob/living/basic/living_target, atom/OldLoc, Dir, Forced)
SIGNAL_HANDLER
if(sinked || is_sinking)
unsink()
if(ground_sinking_start_timer)
deltimer(ground_sinking_start_timer)
ground_sinking_start_timer = addtimer(CALLBACK(src, PROC_REF(start_sinking), living_target), ground_sinking_delay, TIMER_STOPPABLE)
/// Start processing health regeneration, and show animation if provided
/datum/component/ground_sinking/proc/start_sinking(mob/living/basic/living_target)
if(!sinked || is_sinking)
is_sinking = TRUE
INVOKE_ASYNC(src, PROC_REF(sink_once), living_target)
/datum/component/ground_sinking/proc/sink_once(mob/living/basic/living_target)
living_target.visible_message(span_notice("[living_target] starts sinking into the ground!"))
for(var/i in 1 to 3)
if(do_after(living_target, sink_speed, living_target))
sink_count += 1
living_target.icon_state = "[target_icon_state]_burried_[sink_count]"
sink_count = 0
is_sinked(living_target)
/datum/component/ground_sinking/proc/is_sinked(mob/living/basic/living_target)
sinked = TRUE
is_sinking = FALSE
living_target.density = FALSE
living_target.damage_coeff = damage_res_sinked
if(heal_when_sinked)
start_regenerating()
/datum/component/ground_sinking/proc/unsink()
var/mob/living/basic/living_target = parent
if(sinked && heal_when_sinked)
stop_regenerating()
living_target.icon_state = target_icon_state
living_target.damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
living_target.density = TRUE
sinked = FALSE
/datum/component/ground_sinking/proc/start_regenerating()
var/mob/living/basic/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/ground_sinking/proc/stop_regenerating()
STOP_PROCESSING(SSobj, src)
var/mob/living/basic/living_parent = parent
var/filter = living_parent.get_filter(REGENERATION_FILTER)
animate(filter)
living_parent.remove_filter(REGENERATION_FILTER)
/datum/component/ground_sinking/process(delta_time = SSMOBS_DT)
var/mob/living/basic/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