[MIRROR] Ground sinking sanity checks and doc cleanup [MDB IGNORE] (#24632)

* Ground sinking sanity checks and doc cleanup (#79214)

## About The Pull Request

The asynchronous sinking component of garden gnomes did not check if the
gnome still existed, when the sinking timer ran out, which caused null
exception runtimes. I have added sanity checks to this. In addition, the
sinking used do_after, but failing the do_after had no effect on
anything, and infact, made the mob sink even faster into the ground, so
I have added an early return, and a call for unsinking.

Also tweaked proc names and documentation.

Funny story: the only reason I have found out about this bug is because
sometimes garden gnomes spawn on a downstream map, and they cause a CI
failure when the nuke cinematic unit test explodes them. 😔

## Why It's Good For The Game
Runtimes bad. Also if an action has a do_after call, it should probably
fail if it the timer fails.

## Changelog

🆑
fix: Gnomes no longer runtime if they explode while sinking into the
ground
/🆑

* Ground sinking sanity checks and doc cleanup

---------

Co-authored-by: Profakos <profakos@gmail.com>
This commit is contained in:
SkyratBot
2023-10-28 20:06:14 -04:00
committed by GitHub
co-authored by Profakos
parent 35782c631c
commit 3b695cf65e
+19 -8
View File
@@ -66,7 +66,7 @@
if(ground_sinking_start_timer)
deltimer(ground_sinking_start_timer)
/// When you take damage, reset the cooldown and start processing
/// 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)
@@ -79,18 +79,24 @@
/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)
INVOKE_ASYNC(src, PROC_REF(sinking_progress), living_target)
/datum/component/ground_sinking/proc/sink_once(mob/living/basic/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(do_after(living_target, sink_speed, living_target))
sink_count += 1
living_target.icon_state = "[target_icon_state]_burried_[sink_count]"
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
is_sinked(living_target)
finish_sinking(living_target)
/datum/component/ground_sinking/proc/is_sinked(mob/living/basic/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.density = FALSE
@@ -98,8 +104,11 @@
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
@@ -107,6 +116,7 @@
living_target.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)
@@ -122,6 +132,7 @@
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