From e6aa18531a2254e38fc0bb66852e183b214cb22c Mon Sep 17 00:00:00 2001 From: SmArtKar <44720187+SmArtKar@users.noreply.github.com> Date: Thu, 23 Jan 2025 19:14:30 +0100 Subject: [PATCH] Tether improvements and fixes (#89174) ## About The Pull Request Fixes tether stacking via beacons, you can freely cut your tether while moving, and cutting/snapping MODsuit tethers now also snaps the beacon they're connected to if said beacon was generated by a MODsuit projectile. Retracting the gloves or deactivating your MODsuit also snaps MODtethers you've created using it. Closes #88869 Closes #88866 Closes #89170 ## Changelog :cl: qol: Snapping tethers now also removes their beacons qol: You can now cut tethers that you're attached to while in motion qol: Tethers now snap when you retract your gloves or disable your MODsuit fix: Fixed tether stacking issues /:cl: --- .../signals/signals_atom/signals_atom_main.dm | 3 ++ code/datums/components/tether.dm | 15 +++++-- .../mod/modules/modules_engineering.dm | 40 ++++++++++++++++++- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm index 586a67e2395..1497960d194 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm @@ -148,3 +148,6 @@ /// From /atom/proc/set_density(new_value) for when an atom changes density #define COMSIG_ATOM_DENSITY_CHANGED "atom_density_change" + +/// From /datum/component/tether/UnregisterFromParent() +#define COMSIG_ATOM_TETHER_SNAPPED "atom_tether_snapped" diff --git a/code/datums/components/tether.dm b/code/datums/components/tether.dm index ba11306cd89..d04716a0af0 100644 --- a/code/datums/components/tether.dm +++ b/code/datums/components/tether.dm @@ -62,6 +62,7 @@ if (!isnull(parent_module)) RegisterSignals(parent_module, list(COMSIG_QDELETING, COMSIG_MOVABLE_MOVED, COMSIG_MOD_TETHER_SNAP), PROC_REF(snap)) + RegisterSignal(parent_module, COMSIG_MODULE_TRIGGERED, PROC_REF(on_parent_use)) /datum/component/tether/UnregisterFromParent() UnregisterSignal(parent, list(COMSIG_MOVABLE_PRE_MOVE, COMSIG_MOVABLE_MOVED)) @@ -71,11 +72,13 @@ UnregisterSignal(tether_target, list(COMSIG_MOVABLE_PRE_MOVE, COMSIG_MOVABLE_MOVED, COMSIG_QDELETING)) if (!isnull(tether_trait_source) && !no_target_trait) REMOVE_TRAIT(tether_target, TRAIT_TETHER_ATTACHED, tether_trait_source) + SEND_SIGNAL(tether_target, COMSIG_ATOM_TETHER_SNAPPED, tether_trait_source) if (!QDELETED(tether_beam)) UnregisterSignal(tether_beam.visuals, list(COMSIG_CLICK, COMSIG_QDELETING)) qdel(tether_beam) if (!QDELETED(embed_target)) UnregisterSignal(embed_target, list(COMSIG_ITEM_UNEMBEDDED, COMSIG_QDELETING)) + SEND_SIGNAL(parent, COMSIG_ATOM_TETHER_SNAPPED, tether_trait_source) /datum/component/tether/proc/check_tether(atom/source, new_loc) SIGNAL_HANDLER @@ -143,6 +146,12 @@ playsound(atom_target, 'sound/effects/snap.ogg', 50, TRUE) qdel(src) +/datum/component/tether/proc/on_parent_use(obj/item/mod/module/module, atom/target) + SIGNAL_HANDLER + + if (get_turf(target) == get_turf(tether_target)) + return MOD_ABORT_USE + /datum/component/tether/proc/on_delete() SIGNAL_HANDLER qdel(src) @@ -174,7 +183,7 @@ var/list/modifiers = params2list(params) if(LAZYACCESS(modifiers, CTRL_CLICK)) location.balloon_alert(user, "cutting the tether...") - if (!do_after(user, 2 SECONDS, user)) + if (!do_after(user, 2 SECONDS, user, (user == parent || user == tether_target) ? IGNORE_USER_LOC_CHANGE|IGNORE_TARGET_LOC_CHANGE : NONE)) return qdel(src) @@ -190,11 +199,11 @@ location.balloon_alert(user, "tether extended") return - if (cur_dist <= 1) + if (cur_dist <= 0) location.balloon_alert(user, "too short!") return - if (cur_dist > get_dist(parent, tether_target)) + if (cur_dist > CEILING(get_dist(parent, tether_target), 1)) cur_dist -= 1 location.balloon_alert(user, "tether shortened") return diff --git a/code/modules/mod/modules/modules_engineering.dm b/code/modules/mod/modules/modules_engineering.dm index 7ffda55fbb0..af22a60d383 100644 --- a/code/modules/mod/modules/modules_engineering.dm +++ b/code/modules/mod/modules/modules_engineering.dm @@ -114,8 +114,10 @@ .["cut_tethers"] = add_ui_configuration("Cut Tethers", "button", "scissors") /obj/item/mod/module/tether/configure_edit(key, value) - if (key != "cut_tethers") - return + if (key == "cut_tethers") + SEND_SIGNAL(src, COMSIG_MOD_TETHER_SNAP) + +/obj/item/mod/module/tether/on_deactivation(display_message, deleting) SEND_SIGNAL(src, COMSIG_MOD_TETHER_SNAP) /obj/projectile/tether @@ -197,6 +199,7 @@ anchor.pixel_x = hitx anchor.pixel_y = hity anchor.anchored = TRUE + anchor.parent_module = parent_module firer.AddComponent(/datum/component/tether, anchor, 7, "MODtether", parent_module = parent_module, tether_trait_source = REF(parent_module)) /obj/projectile/tether/Destroy() @@ -210,6 +213,17 @@ icon = 'icons/obj/clothing/modsuit/mod_modules.dmi' max_integrity = 60 interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_UI_INTERACT + /// MODsuit tether module that created our projectile + var/obj/item/mod/module/tether/parent_module + +/obj/item/tether_anchor/Initialize(mapload) + . = ..() + RegisterSignal(src, COMSIG_ATOM_TETHER_SNAPPED, PROC_REF(tether_snapped)) + +/obj/item/tether_anchor/Destroy(force) + // We don't need to worry about hanging refs in case our parent gets destroyed because then it snaps all tethers, which in turn destroys us + parent_module = null + return ..() /obj/item/tether_anchor/examine(mob/user) . = ..() @@ -229,6 +243,10 @@ balloon_alert(user, "already tethered!") return + if (parent_module && HAS_TRAIT_FROM(user, TRAIT_TETHER_ATTACHED, REF(parent_module))) + balloon_alert(user, "already tethered!") + return + balloon_alert(user, "attached tether") user.AddComponent(/datum/component/tether, src, 7, "tether", tether_trait_source = REF(src)) return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN @@ -244,6 +262,10 @@ balloon_alert(user, "already tethered!") return + if (parent_module && HAS_TRAIT_FROM(user, TRAIT_TETHER_ATTACHED, REF(parent_module))) + balloon_alert(user, "already tethered!") + return + if (target == user) balloon_alert(user, "attached tether") user.AddComponent(/datum/component/tether, src, 7, "tether", tether_trait_source = REF(src), no_target_trait = TRUE) @@ -258,10 +280,24 @@ balloon_alert(user, "already tethered!") return + if (parent_module && HAS_TRAIT_FROM(user, TRAIT_TETHER_ATTACHED, REF(parent_module))) + balloon_alert(user, "already tethered!") + return + balloon_alert(user, "attached tether") to_chat(target, span_userdanger("[user] attaches a tether to you!")) target.AddComponent(/datum/component/tether, src, 7, "tether", tether_trait_source = REF(src), no_target_trait = TRUE) +/obj/item/tether_anchor/proc/tether_snapped(datum/component/tether/tether, tether_source) + SIGNAL_HANDLER + + if (!parent_module || tether_source != REF(parent_module)) + return + + // Destroy self if we've been created by a tether module + do_sparks(3, TRUE, src) + qdel(src) + /datum/embedding/tether_projectile embed_chance = 65 //spiky fall_chance = 2