diff --git a/code/modules/mod/mod_activation.dm b/code/modules/mod/mod_activation.dm index 2935aeb0913..c3674801e36 100644 --- a/code/modules/mod/mod_activation.dm +++ b/code/modules/mod/mod_activation.dm @@ -50,11 +50,7 @@ balloon_alert(user, "currently [active ? "unsealing" : "sealing"]!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return FALSE - var/deploy = TRUE - for(var/obj/item/part as anything in get_parts()) - if(part.loc != src) - deploy = FALSE - break + var/deploy = check_retracted() wearer.visible_message(span_notice("[wearer]'s [src] [deploy ? "deploys" : "retracts"] its parts with a mechanical hiss."), span_notice("[src] [deploy ? "deploys" : "retracts"] its parts with a mechanical hiss."), span_hear("You hear a mechanical hiss.")) @@ -325,4 +321,12 @@ for(var/obj/item/part as anything in get_parts()) deploy(null, part, instant = TRUE) +/// Checks if the suit is fully retracted, with no parts outside +/obj/item/mod/control/proc/check_retracted() + for(var/obj/item/part as anything in get_parts()) + if(part.loc != src) + return FALSE + return TRUE + + #undef MOD_ACTIVATION_STEP_FLAGS diff --git a/code/modules/mod/mod_control.dm b/code/modules/mod/mod_control.dm index 397ca5c4d19..e2554be5646 100644 --- a/code/modules/mod/mod_control.dm +++ b/code/modules/mod/mod_control.dm @@ -100,8 +100,12 @@ locked = TRUE new_core?.install(src) update_speed() + RegisterSignal(src, COMSIG_ATOM_EXITED, PROC_REF(on_exit)) RegisterSignal(src, COMSIG_SPEED_POTION_APPLIED, PROC_REF(on_potion)) + RegisterSignal(src, COMSIG_ITEM_GET_STRIPPABLE_ALT_ACTIONS, PROC_REF(get_strippable_alternate_actions)) + RegisterSignal(src, COMSIG_ITEM_STRIPPABLE_ALT_ACTION, PROC_REF(do_strippable_action)) + for(var/obj/item/mod/module/module as anything in theme.inbuilt_modules) module = new module(src) install(module) @@ -402,6 +406,68 @@ icon_state = "[skin]-[base_icon_state][active ? "-sealed" : ""]" return ..() +/obj/item/mod/control/proc/get_strippable_alternate_actions(obj/item/source, atom/owner, mob/user, list/alt_actions) + SIGNAL_HANDLER + if(active) + alt_actions += "deactivate_mod" + else + alt_actions += "activate_mod" + if(check_retracted()) + alt_actions += "deploy" + else + alt_actions += "undeploy" + + +/obj/item/mod/control/proc/do_strippable_action(obj/item/source, atom/owner, mob/user, action_key) + SIGNAL_HANDLER + if(!isliving(user)) + return NONE + switch(action_key) + + if("deploy", "undeploy") + owner.visible_message( + span_warning("[user] tries to [action_key] [owner]'s [src]..."), + span_userdanger("[user] is trying to [action_key] your [src]!"), + blind_message = span_hear("You hear rustling."), + ignored_mobs = user, + ) + INVOKE_ASYNC(src, PROC_REF(attempt_strip_deploy), owner, user, action_key) + return COMPONENT_ALT_ACTION_DONE + + if("activate_mod", "deactivate_mod") + owner.visible_message( + span_warning("[user] tries to press [owner]'s [src]'s power button..."), + span_userdanger("[user] is trying to press your [src]'s power button!"), + blind_message = span_hear("You hear rustling."), + ignored_mobs = user, + ) + INVOKE_ASYNC(src, PROC_REF(attempt_strip_activate), owner, user) + return COMPONENT_ALT_ACTION_DONE + + else + return NONE + +/obj/item/mod/control/proc/attempt_strip_deploy(atom/owner, mob/user, message) + if(!do_after(user, strip_delay, owner)) + return + owner.visible_message( + span_warning("[user] [message]s [owner]'s [src]."), + span_userdanger("[user] [message]s your [src]!"), + ignored_mobs = user, + ) + quick_deploy(user) + +/obj/item/mod/control/proc/attempt_strip_activate(atom/owner, mob/user) + if(!do_after(user, strip_delay, owner)) + return + owner.visible_message( + span_warning("[user] presses [owner]'s [src]'s power button."), + span_userdanger("[user] presses your [src]'s power button!"), + ignored_mobs = user, + ) + toggle_activate(user) + + /obj/item/mod/control/proc/get_parts(all = FALSE) . = list() for(var/key in mod_parts) diff --git a/code/modules/mod/modules/modules_ninja.dm b/code/modules/mod/modules/modules_ninja.dm index ae72a93df3a..04df80eb540 100644 --- a/code/modules/mod/modules/modules_ninja.dm +++ b/code/modules/mod/modules/modules_ninja.dm @@ -779,7 +779,7 @@ /obj/item/mod/module/dna_lock/reinforced/on_mod_activation(datum/source, mob/user) . = ..() - if(. != MOD_CANCEL_ACTIVATE || !isliving(user)) + if(. != MOD_CANCEL_ACTIVATE || !isliving(user) || user != mod.wearer) return if(mod.ai_assistant == user) to_chat(mod.ai_assistant, span_danger("fATaL EERRoR: 381200-*#00CODE BLUE\nAI INTErFERenCE DEtECted\nACTi0N DISrEGArdED")) diff --git a/code/modules/mod/modules/modules_timeline.dm b/code/modules/mod/modules/modules_timeline.dm index 3bc992ecfe6..bfca6e421b7 100644 --- a/code/modules/mod/modules/modules_timeline.dm +++ b/code/modules/mod/modules/modules_timeline.dm @@ -39,10 +39,12 @@ /obj/item/mod/module/eradication_lock/proc/on_mod_activation(datum/source, mob/user) SIGNAL_HANDLER - if(true_owner_ckey && user.ckey != true_owner_ckey) + if(!true_owner_ckey || user.ckey == true_owner_ckey) + return NONE + if(user == mod.wearer) to_chat(mod.wearer, span_userdanger("\"MODsuit compromised by timeline inhabitant! Eradicating...\"")) new /obj/structure/chrono_field(user.loc, user) - return MOD_CANCEL_ACTIVATE + return MOD_CANCEL_ACTIVATE ///Signal fired when the modsuit tries removing a module. /obj/item/mod/module/eradication_lock/proc/on_mod_removal(datum/source, mob/user) diff --git a/tgui/packages/tgui/interfaces/StripMenu.tsx b/tgui/packages/tgui/interfaces/StripMenu.tsx index a0975730f63..480de878b40 100644 --- a/tgui/packages/tgui/interfaces/StripMenu.tsx +++ b/tgui/packages/tgui/interfaces/StripMenu.tsx @@ -88,6 +88,25 @@ const ALTERNATE_ACTIONS: Record = { icon: 'ribbon', text: 'Strip accessory', }, + + deploy: { + icon: 'plus', + text: 'Deploy MOD', + }, + + undeploy: { + icon: 'minus', + text: 'Undeploy MOD', + }, + + activate_mod: { + icon: 'power-off', + text: 'Activate MOD', + }, + deactivate_mod: { + icon: 'power-off', + text: 'Deactivate MOD', + }, }; const SLOTS: Record<