mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 17:52:36 +00:00
## About The Pull Request - added a signal - `COMSIG_ATOM_DENSITY_CHANGED`, is sent when set_density is called and doesn't early return - changed all manual assignments of .density to use `set_density` so the signal is sent - airlocks get the leanable component, if the airlock opens while you are leaning on it - you will fall - computers get the leanable component ## Why It's Good For The Game can lean on more stuff, roleplay! Immersion! *John Tider leans on the airlock* ## Changelog 🆑 grungussuss add: computers and airlocks are now leanable refactor: changed how density/collision of some objects is changed, report any oddities! /🆑 --------- Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
154 lines
5.4 KiB
Plaintext
154 lines
5.4 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, 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)
|
|
if(sinked || is_sinking)
|
|
unsink()
|
|
. = ..()
|
|
if(ground_sinking_start_timer)
|
|
deltimer(ground_sinking_start_timer)
|
|
|
|
/// When you move, 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(sinking_progress), living_target)
|
|
|
|
/// Makes the mob try to sink three times. Unsinks if interrupted.
|
|
/datum/component/ground_sinking/proc/sinking_progress(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(QDELETED(living_target))
|
|
return
|
|
if(!do_after(living_target, sink_speed, living_target))
|
|
unsink()
|
|
return
|
|
sink_count += 1
|
|
living_target.icon_state = "[target_icon_state]_burried_[sink_count]"
|
|
sink_count = 0
|
|
finish_sinking(living_target)
|
|
|
|
/// The mob has fully sunk, updates its regeneration, damage resistance and density
|
|
/datum/component/ground_sinking/proc/finish_sinking(mob/living/basic/living_target)
|
|
sinked = TRUE
|
|
is_sinking = FALSE
|
|
living_target.set_density(FALSE)
|
|
living_target.damage_coeff = damage_res_sinked
|
|
if(heal_when_sinked)
|
|
start_regenerating()
|
|
|
|
/// The mob pops out of the ground
|
|
/datum/component/ground_sinking/proc/unsink()
|
|
var/mob/living/basic/living_target = parent
|
|
if(QDELETED(parent))
|
|
return
|
|
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, STAMINA = 0, OXY = 1)
|
|
living_target.set_density(TRUE)
|
|
sinked = FALSE
|
|
|
|
/// The mop starts regaining health
|
|
/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)
|
|
|
|
/// Stops regaining health
|
|
/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(seconds_per_tick = 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 * seconds_per_tick)
|
|
|
|
#undef REGENERATION_FILTER
|