Fix some Guardian bugs (#94715)

## About The Pull Request

Fixes #94699
This resolves two long-standing bugs where Support holoparasites could
heal their hosts while recalled, and Dextrous holoparasites could use
items on their hosts while recalled.
However because these bugs have been present _at least_ since the basic
mob refactor (I suspect I accidentally introduced them, although they
may even predate that) I've marked this as a balance update. What do I
care about GBP anyway.

In addition I've fixed two more visual bugs;
Gaseous Holoparasites now use a particle holder instead of setting
`particles` on the mob directly, which fixes a visual issue where the
particles would persist if you cancelled them via recalling and might
trick you into thinking you were still emitting gas after manifesting
again.
I also forced the health hud to update upon spawn, because as-is until
your host took any damage or healing it would just look like an empty
box hovering on your UI.

## Why It's Good For The Game

Support Guardian healing you could argue is a feature, but personally I
don't think that being constantly healed by your buddy in a way that
nobody can possibly prevent could have been intended, and if we _want_
to canonise it then it should be done in a way that it's a passive
effect of being recalled and not an effect of spamming right click.

Dextrous Guardians being able to use items while recalled was much more
clearly a bug; Dextrous Guardians drop all items when they recall and it
was an oversight that they could just put an item on their belt and get
it out while recalled, then freely use it on their host (but nothing
else, from inside the host that's the only thing in their range). The
reasoning that this is bad is pretty much the same as for the Support
guardian, except more so because it can use the instant full heal staff
or any other similar item.

## Changelog

🆑
balance: Support Guardians cannot heal their owner while recalled.
balance: Dextrous Guardians cannot use their hands while recalled.
fix: Gaseous Guardian particles will correctly dismiss when you recall.
fix: Guardian health hud will display the correct value when you are
first summoned.
/🆑
This commit is contained in:
Jacquerel
2026-01-04 11:43:23 -07:00
committed by GitHub
parent 9c4f253836
commit d71fd7bfb1
6 changed files with 21 additions and 7 deletions
@@ -135,6 +135,7 @@ GLOBAL_LIST_INIT(guardian_radial_images, setup_guardian_radial())
to_chat(user, guardian_theme.get_fluff_string(summoned_guardian.guardian_type))
to_chat(user, replacetext(success_message, "%GUARDIAN", mob_name))
summoned_guardian.client?.init_verbs()
summoned_guardian.updatehealth() // Set the initial health hud
return summoned_guardian
/// Checks to ensure we're still capable of using the radial selector
@@ -30,9 +30,14 @@
return
. += span_info("It is holding [internal_storage.examine_title(user)] in its internal storage.")
/mob/living/basic/guardian/dextrous/manifest_effects()
. = ..()
REMOVE_TRAIT(src, TRAIT_HANDS_BLOCKED, GUARDIAN_RECALLED)
/mob/living/basic/guardian/dextrous/recall_effects()
. = ..()
drop_all_held_items()
ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, GUARDIAN_RECALLED)
// Bullshit related to having a fake pocket begins here
@@ -82,6 +82,8 @@
button_icon_state = "smoke"
cooldown_time = 0 SECONDS // We're here for the interface not the cooldown
click_to_activate = FALSE
/// Particle effect we use to show smoke
VAR_PRIVATE/obj/effect/abstract/particle_holder/mob_smoke
/// Gas being expelled.
var/active_gas = null
/// Associative list of types of gases to moles we create every life tick.
@@ -132,13 +134,10 @@
owner.investigate_log("set their gas type to [picked_gas].", INVESTIGATE_ATMOS)
var/had_gas = !isnull(active_gas)
active_gas = gas_type
if(isnull(owner.particles))
owner.particles = new /particles/smoke/steam()
owner.particles.position = list(-1, 8, 0)
owner.particles.fadein = 5
owner.particles.height = 200
if(isnull(mob_smoke))
mob_smoke = new(owner, /particles/smoke/steam/guardian)
var/datum/gas/chosen_gas = active_gas // Casting it so that we can access gas vars in initial, it's still a typepath
owner.particles.color = initial(chosen_gas.primary_color)
mob_smoke.color = initial(chosen_gas.primary_color)
if (!had_gas)
RegisterSignal(owner, COMSIG_LIVING_LIFE, PROC_REF(on_life))
@@ -148,7 +147,7 @@
if (!isnull(active_gas))
to_chat(src, span_notice("You stop releasing gas."))
active_gas = null
QDEL_NULL(owner.particles)
QDEL_NULL(mob_smoke)
UnregisterSignal(owner, COMSIG_LIVING_LIFE)
/// Release gas every life tick while active
@@ -24,6 +24,7 @@
action_text = "",\
complete_text = "",\
required_modifier = RIGHT_CLICK,\
extra_checks = CALLBACK(src, PROC_REF(is_deployed)),\
after_healed = CALLBACK(src, PROC_REF(after_healed)),\
)