From bbaf55a8f530e43b980bc432f36be99cc96d5027 Mon Sep 17 00:00:00 2001 From: Jerry Wester Date: Sat, 10 Dec 2022 22:30:46 -0700 Subject: [PATCH] Fix pAI shenanigans --- code/modules/mod/mod_actions.dm | 16 +----- code/modules/mod/mod_activation.dm | 3 + code/modules/mod/mod_ai.dm | 70 +++++++++++++++--------- code/modules/mod/mod_control.dm | 27 +++++++-- code/modules/mod/mod_ui.dm | 10 +++- tgui/packages/tgui/interfaces/MODsuit.js | 18 +++++- 6 files changed, 95 insertions(+), 49 deletions(-) diff --git a/code/modules/mod/mod_actions.dm b/code/modules/mod/mod_actions.dm index b280ffdd70..ee28771ef1 100644 --- a/code/modules/mod/mod_actions.dm +++ b/code/modules/mod/mod_actions.dm @@ -5,8 +5,6 @@ var/obj/item/mod/control/mod /// Whether this action is intended for the AI. Stuff breaks a lot if this is done differently. var/ai_action = FALSE - /// Whether this action is intended for the inserted pAI. Stuff breaks a lot if this is done differently. - var/pai_action = FALSE /datum/action/item_action/mod/New(Target) ..() @@ -14,7 +12,7 @@ qdel(src) return if(ai_action) - background_icon_state = ACTION_BUTTON_DEFAULT_BACKGROUND + background_icon_state = "bg_tech" /datum/action/item_action/mod/Grant(mob/user) mod = target @@ -53,9 +51,6 @@ /datum/action/item_action/mod/deploy/ai ai_action = TRUE -/datum/action/item_action/mod/deploy/pai - pai_action = TRUE - /datum/action/item_action/mod/activate name = "Activate MODsuit" desc = "Activate/Deactivate the MODsuit." @@ -70,9 +65,6 @@ /datum/action/item_action/mod/activate/ai ai_action = TRUE -/datum/action/item_action/mod/activate/pai - pai_action = TRUE - /datum/action/item_action/mod/module name = "Toggle Module" desc = "Toggle a MODsuit module." @@ -87,9 +79,6 @@ /datum/action/item_action/mod/module/ai ai_action = TRUE -/datum/action/item_action/mod/module/pai - pai_action = TRUE - /datum/action/item_action/mod/panel name = "MODsuit Panel" desc = "Open the MODsuit's panel." @@ -103,6 +92,3 @@ /datum/action/item_action/mod/panel/ai ai_action = TRUE - -/datum/action/item_action/mod/panel/pai - pai_action = TRUE diff --git a/code/modules/mod/mod_activation.dm b/code/modules/mod/mod_activation.dm index c0b1300dc4..ef897d77ab 100644 --- a/code/modules/mod/mod_activation.dm +++ b/code/modules/mod/mod_activation.dm @@ -122,6 +122,9 @@ module.on_deactivation() activating = TRUE to_chat(wearer, span_notice("MODsuit [active ? "shutting down" : "starting up"].")) + if(ai) + to_chat(ai, span_notice("MODsuit [active ? "shutting down" : "starting up"].")) + if(do_after(wearer, MOD_ACTIVATION_STEP_TIME, target = wearer, required_mobility_flags = NONE)) to_chat(wearer, span_notice("[boots] [active ? "relax their grip on your legs" : "seal around your feet"].")) playsound(src, 'sound/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) diff --git a/code/modules/mod/mod_ai.dm b/code/modules/mod/mod_ai.dm index c7356e41f0..8bc431146b 100644 --- a/code/modules/mod/mod_ai.dm +++ b/code/modules/mod/mod_ai.dm @@ -10,6 +10,9 @@ if(!ai) balloon_alert(user, "no AI in suit!") return + if(!isAI(ai)) + balloon_alert(user, "onboard AI cannot fit in this card!") + return balloon_alert(user, "transferring to card...") if(!do_after(user, 5 SECONDS, target = src)) balloon_alert(user, "interrupted!") @@ -65,7 +68,7 @@ ai = new_ai balloon_alert(new_ai, "transferred to a suit") for(var/datum/action/action as anything in actions) - action.Grant(new_ai) + action.Grant(ai) /** * Simple proc to insert the pAI into the MODsuit. @@ -75,8 +78,8 @@ */ /obj/item/mod/control/proc/insert_pai(mob/user, obj/item/paicard/card) - if(mod_pai) - balloon_alert(user, "pAI already installed!") + if(ai) + balloon_alert(user, "AI already installed!") return if(!card.pai || !card.pai.mind) balloon_alert(user, "pAI unresponsive!") @@ -88,13 +91,13 @@ if(!user.transferItemToLoc(card, src)) return - mod_pai = card.pai + card.pai.canholo = FALSE + ai = card.pai balloon_alert(user, "pAI transferred to suit") - balloon_alert(mod_pai, "transferred to a suit") - mod_pai.canholo = FALSE - mod_pai.remote_control = src + balloon_alert(ai, "transferred to a suit") + ai.remote_control = src for(var/datum/action/action as anything in actions) - action.Grant(mod_pai) + action.Grant(ai) return TRUE /** @@ -106,10 +109,14 @@ * feedback - Whether to give feedback via balloon alerts or not. Defaults to TRUE. */ /obj/item/mod/control/proc/extract_pai(mob/user, forced = FALSE, feedback = TRUE) - if(!mod_pai) + if(!ai) if(user && feedback) balloon_alert(user, "no pAI to remove!") return + if(!ispAI(ai)) + if(user && feedback) + balloon_alert(user, "onboard AI cannot fit in this card!") + return if(!forced) if(!open) if(user && feedback) @@ -129,41 +136,48 @@ * Simple proc that handles the safe removal of the pAI from a MOD control unit. * * Arguments: - * * feedback - Whether or not we want to give balloon alert feedback to the mod_pai. Defaults to FALSE. + * * feedback - Whether or not we want to give balloon alert feedback to the ai. Defaults to FALSE. */ /obj/item/mod/control/proc/remove_pai(feedback = FALSE) + if(!ispAI(ai)) + return + var/mob/living/silicon/pai/pai = ai var/turf/drop_off = get_turf(src) if(drop_off) // In case there's no drop_off, the pAI will simply get deleted. - mod_pai.card.forceMove(drop_off) + pai.card.forceMove(drop_off) for(var/datum/action/action as anything in actions) - if(action.owner == mod_pai) - action.Remove(mod_pai) + if(action.owner == pai) + action.Remove(pai) if(feedback) - balloon_alert(mod_pai, "removed from a suit") - mod_pai.remote_control = null - mod_pai.canholo = TRUE - mod_pai = null + balloon_alert(pai, "removed from a suit") + pai.remote_control = null + pai.canholo = TRUE + pai = null #define MOVE_DELAY 2 #define WEARER_DELAY 1 #define LONE_DELAY 5 #define CELL_PER_STEP (DEFAULT_CHARGE_DRAIN * 2.5) +#define AI_FALL_TIME (1 SECONDS) /obj/item/mod/control/relaymove(mob/user, direction) if((!active && wearer) || !cell || cell.charge < CELL_PER_STEP || user != ai || !COOLDOWN_FINISHED(src, cooldown_mod_move) || (wearer?.pulledby?.grab_state > GRAB_PASSIVE)) return FALSE - if(wearer && (wearer.pulledby?.grab_state || wearer.incapacitated() || wearer.stat)) - return FALSE var/timemodifier = MOVE_DELAY * (ISDIAGONALDIR(direction) ? SQRT_2 : 1) * (wearer ? WEARER_DELAY : LONE_DELAY) - COOLDOWN_START(src, cooldown_mod_move, movedelay * timemodifier + slowdown) - playsound(src, 'sound/mecha/mechmove01.ogg', 25, TRUE) - cell.charge = max(0, cell.charge - CELL_PER_STEP) - if(ismovable(wearer?.loc)) - return wearer.loc.relaymove(wearer, direction) if(wearer && !wearer.Process_Spacemove(direction)) return FALSE + else if(!wearer && (!has_gravity() || !isturf(loc))) + return FALSE + COOLDOWN_START(src, cooldown_mod_move, movedelay * timemodifier + slowdown) + cell.charge = max(0, cell.charge - CELL_PER_STEP) + playsound(src, 'sound/mecha/mechmove01.ogg', 25, TRUE) + if(ismovable(wearer?.loc)) + return wearer.loc.relaymove(wearer, direction) + else if(wearer) + ADD_TRAIT(wearer, TRAIT_MOBILITY_NOREST, MOD_TRAIT) + addtimer(CALLBACK(src, .proc/ai_fall), AI_FALL_TIME, TIMER_UNIQUE | TIMER_OVERRIDE) var/atom/movable/mover = wearer || src return step(mover, direction) @@ -171,8 +185,14 @@ #undef WEARER_DELAY #undef LONE_DELAY #undef CELL_PER_STEP +#undef AI_FALL_TIME + +/obj/item/mod/control/proc/ai_fall() + if(!wearer) + return + REMOVE_TRAIT(wearer, TRAIT_MOBILITY_NOREST, MOD_TRAIT) /obj/item/mod/control/ui_state(mob/user) - if(user == mod_pai) + if(user == ai) return GLOB.contained_state return ..() diff --git a/code/modules/mod/mod_control.dm b/code/modules/mod/mod_control.dm index ca4ec2a468..5b0fda2a13 100644 --- a/code/modules/mod/mod_control.dm +++ b/code/modules/mod/mod_control.dm @@ -19,7 +19,16 @@ strip_delay = 10 SECONDS slowdown = 2 armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 100, FIRE = 25, ACID = 25, WOUND = 10) - actions_types = list(/datum/action/item_action/mod/deploy, /datum/action/item_action/mod/activate, /datum/action/item_action/mod/module, /datum/action/item_action/mod/panel) + actions_types = list( + /datum/action/item_action/mod/deploy, + /datum/action/item_action/mod/activate, + /datum/action/item_action/mod/module, + /datum/action/item_action/mod/panel, + /datum/action/item_action/mod/deploy/ai, + /datum/action/item_action/mod/activate/ai, + /datum/action/item_action/mod/module/ai, + /datum/action/item_action/mod/panel/ai, + ) resistance_flags = NONE max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT @@ -74,10 +83,8 @@ var/list/modules = list() /// Currently used module. var/obj/item/mod/module/selected_module - /// AI mob inhabiting the MOD. - var/mob/living/silicon/ai/ai - /// pAI mob inhabiting the MOD. - var/mob/living/silicon/pai/mod_pai + /// AI/pAI mob inhabiting the MOD. + var/mob/living/silicon/ai /// Delay between moves as AI. var/movedelay = 0 /// Cooldown for AI moves. @@ -167,6 +174,7 @@ for(var/obj/item/mod/module/module as anything in modules) module.mod = null modules -= module + QDEL_NULL(ai) QDEL_NULL(wires) QDEL_NULL(cell) return ..() @@ -261,7 +269,8 @@ . = ..() /obj/item/mod/control/screwdriver_act(mob/living/user, obj/item/screwdriver) - if(..()) + . = ..() + if(.) return TRUE if(active || activating) balloon_alert(user, "deactivate suit first!") @@ -307,6 +316,12 @@ return FALSE /obj/item/mod/control/attackby(obj/item/attacking_item, mob/living/user, params) + if(istype(attacking_item, /obj/item/paicard)) + if(!open) //mod must be open + balloon_alert(user, "suit must be open to transfer!") + return FALSE + insert_pai(user, attacking_item) + return TRUE if(istype(attacking_item, /obj/item/mod/module)) if(!open) balloon_alert(user, "open the panel first!") diff --git a/code/modules/mod/mod_ui.dm b/code/modules/mod/mod_ui.dm index 065f3f6748..f119a895b3 100644 --- a/code/modules/mod/mod_ui.dm +++ b/code/modules/mod/mod_ui.dm @@ -4,7 +4,7 @@ ui = new(user, src, "MODsuit", name) ui.open() -/obj/item/mod/control/ui_data() +/obj/item/mod/control/ui_data(mob/user) var/data = list() data["interface_break"] = interface_break data["malfunctioning"] = malfunctioning @@ -16,6 +16,8 @@ data["wearer_name"] = wearer ? (wearer.get_authentification_name("Unknown") || "Unknown") : "No Occupant" data["wearer_job"] = wearer ? wearer.get_assignment("Unknown", "Unknown", FALSE) : "No Job" data["AI"] = ai?.name + data["is_pAI"] = ai ? ispAI(ai) : FALSE + data["is_user_AI"] = ai ? user == ai : FALSE data["cell"] = cell?.name data["charge"] = cell ? round(cell.percent(), 1) : 0 data["modules"] = list() @@ -54,7 +56,7 @@ . = ..() if(.) return - if(locked && !allowed(usr)) + if((!allowed(usr) || !ispAI(usr)) && locked) balloon_alert(usr, "insufficient access!") playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return @@ -77,4 +79,8 @@ if(!module) return module.configure_edit(params["key"], params["value"]) + if("remove_pai") + if(ishuman(usr)) // Only the MODsuit's wearer should be removing the pAI. + var/mob/user = usr + extract_pai(user) return TRUE diff --git a/tgui/packages/tgui/interfaces/MODsuit.js b/tgui/packages/tgui/interfaces/MODsuit.js index 1ddef04399..3d64a6773f 100644 --- a/tgui/packages/tgui/interfaces/MODsuit.js +++ b/tgui/packages/tgui/interfaces/MODsuit.js @@ -467,6 +467,8 @@ const ParametersSection = (props, context) => { wearer_name, wearer_job, AI, + is_pAI, + is_user_AI, } = data; const status = malfunctioning ? 'Malfunctioning' @@ -510,7 +512,21 @@ const ParametersSection = (props, context) => { {wearer_name}, {wearer_job} - {AI || 'None'} + act('remove_pai')} + /> + ) : ( + <> + ) + }> + {AI || 'None'} + );