diff --git a/code/__DEFINES/dcs/signals/signals_mod.dm b/code/__DEFINES/dcs/signals/signals_mod.dm index c08377d50db..70c434adae3 100644 --- a/code/__DEFINES/dcs/signals/signals_mod.dm +++ b/code/__DEFINES/dcs/signals/signals_mod.dm @@ -8,7 +8,8 @@ /// Called when a MOD deploys a part. (mob/user, datum/mod_part/part) #define COMSIG_MOD_PART_DEPLOYED "mod_part_deployed" /// Called when a MOD retracts a part. (mob/user, datum/mod_part/part) -#define COMSIG_MOD_PART_RETRACTED "mod_part_retracted" +#define COMSIG_MOD_PART_RETRACTING "mod_part_retracting" + #define MOD_CANCEL_RETRACTION (1 << 0) /// Called when a MOD seals/unseals a part. (datum/mod_part/part) #define COMSIG_MOD_PART_SEALED "mod_part_sealed" /// Called when a MOD is finished toggling itself. diff --git a/code/modules/mod/mod_activation.dm b/code/modules/mod/mod_activation.dm index ecc3eaaedc2..4c145da4f1b 100644 --- a/code/modules/mod/mod_activation.dm +++ b/code/modules/mod/mod_activation.dm @@ -127,6 +127,8 @@ balloon_alert(user, "already retracted!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return FALSE + if(SEND_SIGNAL(src, COMSIG_MOD_PART_RETRACTING, user, part_datum) & MOD_CANCEL_RETRACTION) + return FALSE if(active && part_datum.sealed) if(instant) seal_part(part, is_sealed = FALSE) @@ -141,7 +143,6 @@ if(!QDELING(wearer) && !wearer.equip_to_slot_if_possible(overslot, overslot.slot_flags, qdel_on_fail = FALSE, disable_warning = TRUE)) wearer.dropItemToGround(overslot, force = TRUE, silent = TRUE) wearer.update_clothing(slot_flags) - SEND_SIGNAL(src, COMSIG_MOD_PART_RETRACTED, user, part_datum) if(!user) return TRUE wearer.visible_message(span_notice("[wearer]'s [part.name] retract[part.p_s()] back into [src] with a mechanical hiss."), diff --git a/code/modules/mod/modules/modules_maint.dm b/code/modules/mod/modules/modules_maint.dm index afc472b7604..f1b9154358b 100644 --- a/code/modules/mod/modules/modules_maint.dm +++ b/code/modules/mod/modules/modules_maint.dm @@ -32,12 +32,23 @@ ///Registers the signal COMSIG_MOD_ACTIVATE and calls the proc snap_shut() after a timer /obj/item/mod/module/springlock/proc/snap_signal() - if(set_off || mod.wearer.stat == DEAD) + if (set_off || mod.wearer.stat == DEAD) return + + var/found_part = FALSE + for (var/obj/item/part as anything in mod.get_parts()) + // Don't snap if no parts besides the MOD itself are active + if (part.loc != mod && mod.get_part_datum(part)?.sealed) + found_part = TRUE + break + + if (!found_part) + return + to_chat(mod.wearer, span_danger("[src] makes an ominous click sound...")) playsound(src, 'sound/items/modsuit/springlock.ogg', 75, TRUE) addtimer(CALLBACK(src, PROC_REF(snap_shut)), rand(3 SECONDS, 5 SECONDS)) - RegisterSignal(mod, COMSIG_MOD_ACTIVATE, PROC_REF(on_activate_spring_block)) + RegisterSignals(mod, list(COMSIG_MOD_ACTIVATE, COMSIG_MOD_PART_RETRACTING), PROC_REF(on_activate_spring_block)) set_off = TRUE ///Calls snap_signal() when exposed to a reagent via VAPOR, PATCH or TOUCH @@ -66,7 +77,7 @@ ///Delayed death proc of the suit after the wearer is exposed to reagents /obj/item/mod/module/springlock/proc/snap_shut() - UnregisterSignal(mod, COMSIG_MOD_ACTIVATE) + UnregisterSignal(mod, list(COMSIG_MOD_ACTIVATE, COMSIG_MOD_PART_RETRACTING)) if(!mod.wearer) //while there is a guaranteed user when on_wearer_exposed() fires, that isn't the same case for this proc return mod.wearer.visible_message("[src] inside [mod.wearer]'s [mod.name] snaps shut, mutilating the user inside!", span_userdanger("*SNAP*")) @@ -74,7 +85,16 @@ playsound(mod.wearer, 'sound/effects/snap.ogg', 75, TRUE, frequency = 0.5) playsound(mod.wearer, 'sound/effects/splat.ogg', 50, TRUE, frequency = 0.5) mod.wearer.client?.give_award(/datum/award/achievement/misc/springlock, mod.wearer) - mod.wearer.apply_damage(500, BRUTE, forced = TRUE, spread_damage = TRUE, sharpness = SHARP_POINTY) //boggers, bogchamp, etc + + mod.wearer.get_bodypart(BODY_ZONE_CHEST)?.receive_damage(200, forced = TRUE, sharpness = SHARP_POINTY) // Chest always gets hit, from the back piece you're wearing + for (var/obj/item/part as anything in mod.get_parts()) + if (part.loc == mod || !mod.get_part_datum(part)?.sealed) + continue + + for (var/obj/item/bodypart/bodypart as anything in mod.wearer.get_damageable_bodyparts()) + if (part.body_parts_covered & bodypart.body_part) // can hit chest again + bodypart.receive_damage(100, forced = TRUE, sharpness = SHARP_POINTY) //boggers, bogchamp, etc + if(!HAS_TRAIT(mod.wearer, TRAIT_NODEATH)) mod.wearer.investigate_log("has been killed by [src].", INVESTIGATE_DEATHS) mod.wearer.death() //just in case, for some reason, they're still alive