From d71fd7bfb1c32505ab12c1d2e544a5e75fc6a514 Mon Sep 17 00:00:00 2001 From: Jacquerel Date: Sun, 4 Jan 2026 18:43:23 +0000 Subject: [PATCH] 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 :cl: 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. /:cl: --- code/__DEFINES/traits/sources.dm | 3 +++ code/game/objects/effects/particles/smoke.dm | 5 +++++ .../mob/living/basic/guardian/guardian_creator.dm | 1 + .../basic/guardian/guardian_types/dextrous.dm | 5 +++++ .../living/basic/guardian/guardian_types/gaseous.dm | 13 ++++++------- .../living/basic/guardian/guardian_types/support.dm | 1 + 6 files changed, 21 insertions(+), 7 deletions(-) diff --git a/code/__DEFINES/traits/sources.dm b/code/__DEFINES/traits/sources.dm index 153e7c389f0..8f40c3c8b8e 100644 --- a/code/__DEFINES/traits/sources.dm +++ b/code/__DEFINES/traits/sources.dm @@ -335,3 +335,6 @@ /// Trait gained from skeleton "limbs", such as husking from a butchered chest #define SKELETON_TRAIT "skeleton" + +/// Trait gained by a guardian who is recalled +#define GUARDIAN_RECALLED "guardian_recalled" diff --git a/code/game/objects/effects/particles/smoke.dm b/code/game/objects/effects/particles/smoke.dm index 323e4ffbdce..c5626ef646c 100644 --- a/code/game/objects/effects/particles/smoke.dm +++ b/code/game/objects/effects/particles/smoke.dm @@ -27,6 +27,11 @@ icon_state = list("steam_1" = 1, "steam_2" = 1, "steam_3" = 2) fade = 1.5 SECONDS +/particles/smoke/steam/guardian + position = list(-1, 8, 0) + fadein = 5 + height = 200 + /particles/smoke/steam/mild spawning = 1 velocity = list(0, 0.3, 0) diff --git a/code/modules/mob/living/basic/guardian/guardian_creator.dm b/code/modules/mob/living/basic/guardian/guardian_creator.dm index 7dddd03f685..ff83c69a75e 100644 --- a/code/modules/mob/living/basic/guardian/guardian_creator.dm +++ b/code/modules/mob/living/basic/guardian/guardian_creator.dm @@ -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 diff --git a/code/modules/mob/living/basic/guardian/guardian_types/dextrous.dm b/code/modules/mob/living/basic/guardian/guardian_types/dextrous.dm index 138d09cf324..206b7b79e12 100644 --- a/code/modules/mob/living/basic/guardian/guardian_types/dextrous.dm +++ b/code/modules/mob/living/basic/guardian/guardian_types/dextrous.dm @@ -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 diff --git a/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm b/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm index fb9a3964b4b..8bf00ef4362 100644 --- a/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm +++ b/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm @@ -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 diff --git a/code/modules/mob/living/basic/guardian/guardian_types/support.dm b/code/modules/mob/living/basic/guardian/guardian_types/support.dm index 3e05b403fbc..5ddc07e809b 100644 --- a/code/modules/mob/living/basic/guardian/guardian_types/support.dm +++ b/code/modules/mob/living/basic/guardian/guardian_types/support.dm @@ -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)),\ )