[MIRROR] pAIs can be inserted into a MODsuit [MDB IGNORE] (#22852)

* pAIs can be inserted into a MODsuit

* Update MODsuit.tsx

* Update objective_items.dm

* Update mod_actions.dm

* Update mod_activation.dm

* Update mod_control.dm

* Update mod_ui.dm

* Update MODsuit.tsx

* Update modules_ninja.dm

* prettier

* Update mod_control.dm

* This is torture

* Removes most of the overrides for pAIs in MODsuits, to use the procs from upstream (and reduce the amount of clutter/duplication)

* Damnit keyboard

* Good catch Vinyl!

Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com>

---------

Co-authored-by: Jacquerel <hnevard@gmail.com>
Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com>
Co-authored-by: GoldenAlpharex <jerego1234@hotmail.com>
Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com>
This commit is contained in:
SkyratBot
2023-08-09 00:24:17 +02:00
committed by GitHub
parent 08398a3e47
commit 3e0a36e038
10 changed files with 196 additions and 274 deletions
+22 -23
View File
@@ -11,24 +11,22 @@
if(!istype(Target, /obj/item/mod/control))
qdel(src)
return
// SKYRAT EDIT START - pAIs in MODsuits
if(pai_action)
background_icon_state = "bg_tech"
// SKYRAT EDIT END
if(ai_action)
background_icon_state = ACTION_BUTTON_DEFAULT_BACKGROUND
/datum/action/item_action/mod/Grant(mob/user)
var/obj/item/mod/control/mod = target
if(pai_action && user != mod.mod_pai) // SKYRAT EDIT - pAIs in MODsuits
if(ai_action && user != mod.ai_assistant)
return
else if(!pai_action && user == mod.mod_pai) // SKYRAT EDIT - pAIs in MODsuits
else if(!ai_action && user == mod.ai_assistant)
return
return ..()
/datum/action/item_action/mod/Remove(mob/user)
var/obj/item/mod/control/mod = target
if(pai_action && user != mod.mod_pai) // SKYRAT EDIT - pAIs in MODsuits
if(ai_action && user != mod.ai_assistant)
return
else if(!pai_action && user == mod.mod_pai) // SKYRAT EDIT - pAIs in MODsuits
else if(!ai_action && user == mod.ai_assistant)
return
return ..()
@@ -125,40 +123,36 @@
var/override = FALSE
/// Module we are linked to.
var/obj/item/mod/module/module
/// A ref to the mob we are pinned to.
var/pinner_ref
/// A reference to the mob we are pinned to.
var/mob/pinner
/datum/action/item_action/mod/pinned_module/New(Target, obj/item/mod/module/linked_module, mob/user)
// SKYRAT EDIT START - pAIs in MODsuits
var/obj/item/mod/control/mod = Target // We have to do this otherwise it's going to runtime
if(user == mod.mod_pai)
pai_action = TRUE
// SKYRAT EDIT END
if(isAI(user))
var/obj/item/mod/control/mod = Target
if(user == mod.ai_assistant)
ai_action = TRUE
button_icon = linked_module.icon
button_icon_state = linked_module.icon_state
..()
. = ..()
module = linked_module
pinner = user
module.pinned_to[REF(user)] = src
if(linked_module.allow_flags & MODULE_ALLOW_INCAPACITATED)
// clears check hands and check conscious
check_flags = NONE
name = "Activate [capitalize(linked_module.name)]"
desc = "Quickly activate [linked_module]."
RegisterSignals(linked_module, list(COMSIG_MODULE_ACTIVATED, COMSIG_MODULE_DEACTIVATED, COMSIG_MODULE_USED), PROC_REF(module_interacted_with))
RegisterSignal(user, COMSIG_QDELETING, PROC_REF(pinner_deleted))
/datum/action/item_action/mod/pinned_module/Destroy()
UnregisterSignal(module, list(COMSIG_MODULE_ACTIVATED, COMSIG_MODULE_DEACTIVATED, COMSIG_MODULE_USED))
module.pinned_to -= pinner_ref
module.pinned_to -= REF(pinner)
module = null
pinner = null
return ..()
/datum/action/item_action/mod/pinned_module/Grant(mob/user)
var/user_ref = REF(user)
if(!pinner_ref)
pinner_ref = user_ref
module.pinned_to[pinner_ref] = src
else if(pinner_ref != user_ref)
if(pinner != user)
return
return ..()
@@ -168,6 +162,11 @@
return
module.on_select()
/// If the guy whose UI we are pinned to got deleted
/datum/action/item_action/mod/pinned_module/proc/pinner_deleted()
pinner = null
qdel(src)
/datum/action/item_action/mod/pinned_module/apply_button_overlay(atom/movable/screen/movable/action_button/current_button, force)
current_button.cut_overlays()
if(override)
+7 -8
View File
@@ -70,6 +70,9 @@
/// Deploys a part of the suit onto the user.
/obj/item/mod/control/proc/deploy(mob/user, obj/item/part)
if(!wearer)
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return FALSE // pAI is trying to deploy it from your hands
if(part.loc != src)
if(!user)
return FALSE
@@ -162,11 +165,9 @@
module.on_deactivation(display_message = FALSE)
activating = TRUE
to_chat(wearer, span_notice("MODsuit [active ? "shutting down" : "starting up"]."))
// SKYRAT EDIT START - pAIs in MODsuits
if(mod_pai)
to_chat(mod_pai, span_notice("MODsuit [active ? "shutting down" : "starting up"]."))
// SKYRAT EDIT END
if (ai_assistant)
to_chat(ai_assistant, span_notice("MODsuit [active ? "shutting down" : "starting up"]."))
if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, PROC_REF(has_wearer))))
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)
@@ -185,10 +186,8 @@
seal_part(helmet, seal = !active)
if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, PROC_REF(has_wearer))))
to_chat(wearer, span_notice("Systems [active ? "shut down. Parts unsealed. Goodbye" : "started up. Parts sealed. Welcome"], [wearer]."))
// SKYRAT EDIT START - pAIs in MODsuits
if(mod_pai)
to_chat(mod_pai, span_notice("<b>SYSTEMS [active ? "DEACTIVATED. GOODBYE" : "ACTIVATED. WELCOME"]: \"[mod_pai]\"</b>"))
// SKYRAT EDIT END
if(ai_assistant)
to_chat(ai_assistant, span_notice("<b>SYSTEMS [active ? "DEACTIVATED. GOODBYE" : "ACTIVATED. WELCOME"]: \"[ai_assistant]\"</b>"))
finish_activation(on = !active)
if(active)
playsound(src, 'sound/machines/synth_yes.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, frequency = 6000)
+96 -24
View File
@@ -1,43 +1,35 @@
/* SKYRAT EDIT REMOVAL - pAIs in MODsuits
/obj/item/mod/control/transfer_ai(interaction, mob/user, mob/living/silicon/ai/intAI, obj/item/aicard/card)
. = ..()
if(!.)
return
// SKYRAT EDIT ADDITION START - No AIs in MODsuits
if(!allow_ai)
return
// SKYRAT EDIT END
if(!open) //mod must be open
balloon_alert(user, "suit must be open to transfer!")
return
switch(interaction)
if(AI_TRANS_TO_CARD)
if(!ai)
if(!ai_assistant)
balloon_alert(user, "no ai in suit!")
return
balloon_alert(user, "transferring to card...")
if(!do_after(user, 5 SECONDS, target = src))
balloon_alert(user, "interrupted!")
return
if(!ai)
if(!ai_assistant)
balloon_alert(user, "no ai in suit!")
return
intAI = ai
intAI.ai_restore_power()//So the AI initially has power.
intAI.control_disabled = TRUE
intAI.radio_enabled = FALSE
intAI.disconnect_shell()
intAI.forceMove(card)
card.AI = intAI
for(var/datum/action/action as anything in actions)
action.Remove(intAI)
intAI.controlled_equipment = null
intAI.remote_control = null
balloon_alert(intAI, "transferred to a card")
balloon_alert(user, "ai transferred to card")
ai = null
ai_exit_mod(card)
if(AI_TRANS_FROM_CARD) //Using an AI card to upload to the suit.
intAI = card.AI
if(!intAI)
balloon_alert(user, "no ai in card!")
return
if(ai)
if(ai_assistant)
balloon_alert(user, "already has ai!")
return
if(intAI.deployed_shell) //Recall AI if shelled so it can be checked for a client
@@ -49,12 +41,13 @@
if(!do_after(user, 5 SECONDS, target = src))
balloon_alert(user, "interrupted!")
return
if(ai)
if(ai_assistant)
return
balloon_alert(user, "ai transferred to suit")
ai_enter_mod(intAI)
card.AI = null
/// Place an AI in control of your suit functions
/obj/item/mod/control/proc/ai_enter_mod(mob/living/silicon/ai/new_ai)
new_ai.control_disabled = FALSE
new_ai.radio_enabled = TRUE
@@ -63,10 +56,84 @@
new_ai.controlled_equipment = src
new_ai.remote_control = src
new_ai.forceMove(src)
ai = new_ai
balloon_alert(new_ai, "transferred to a suit")
on_gained_assistant(new_ai)
/// Remove an AI's control of your suit functions
/obj/item/mod/control/proc/ai_exit_mod(obj/item/aicard/card)
var/mob/living/silicon/ai/old_ai = ai_assistant
old_ai.ai_restore_power()//So the AI initially has power.
old_ai.control_disabled = TRUE
old_ai.radio_enabled = FALSE
old_ai.disconnect_shell()
old_ai.forceMove(card)
card.AI = old_ai
old_ai.controlled_equipment = null
on_removed_assistant(old_ai)
/// Place a pAI in control of your suit functions
/obj/item/mod/control/proc/insert_pai(mob/user, obj/item/pai_card/card)
if (!isnull(ai_assistant))
balloon_alert(user, "slot occupied!")
return FALSE
if (isnull(card.pai?.mind))
balloon_alert(user, "pAI unresponsive!")
return FALSE
balloon_alert(user, "transferring to suit...")
if (!do_after(user, 5 SECONDS, target = src))
balloon_alert(user, "interrupted!")
return FALSE
if (!user.transferItemToLoc(card, src))
balloon_alert(user, "transfer failed!")
return FALSE
balloon_alert(user, "pAI transferred to suit")
var/mob/living/silicon/pai/pai_assistant = card.pai
pai_assistant.can_transmit = TRUE
pai_assistant.can_receive = TRUE
pai_assistant.can_holo = FALSE
if (pai_assistant.holoform)
pai_assistant.fold_in()
// SKYRAT EDIT ADDITION START - pAIs in MODsuits
if(can_pai_move_suit)
pai_assistant.remote_control = src
// SKYRAT EDIT END
SStgui.close_uis(card)
on_gained_assistant(card.pai)
return TRUE
/// Removes pAI control from a modsuit
/obj/item/mod/control/proc/remove_pai(mob/user, forced = FALSE)
if (isnull(ai_assistant))
balloon_alert(user, "no pAI!")
return FALSE
if (!forced)
if (!open)
balloon_alert(user, "suit panel closed!")
return FALSE
balloon_alert(user, "uninstalling card...")
if (!do_after(user, 5 SECONDS, target = src))
balloon_alert(user, "interrupted!")
return FALSE
balloon_alert(user, "pAI removed from suit")
var/mob/living/silicon/pai/pai_helper = ai_assistant
pai_helper.can_holo = TRUE
pai_helper.card.forceMove(get_turf(src))
on_removed_assistant()
/// Called when a new ai assistant is inserted
/obj/item/mod/control/proc/on_gained_assistant(mob/living/silicon/new_helper)
ai_assistant = new_helper
balloon_alert(new_helper, "transferred to a suit")
for(var/datum/action/action as anything in actions)
action.Grant(new_ai)
action.Grant(new_helper)
/// Called when an existing ai assistant is removed
/obj/item/mod/control/proc/on_removed_assistant()
for(var/datum/action/action as anything in actions)
action.Remove(ai_assistant)
ai_assistant.remote_control = null
balloon_alert(ai_assistant, "transferred to a card")
ai_assistant = null
#define MOVE_DELAY 2
#define WEARER_DELAY 1
@@ -75,8 +142,12 @@
#define AI_FALL_TIME (1 SECONDS)
/obj/item/mod/control/relaymove(mob/user, direction)
if((!active && wearer) || get_charge() < CHARGE_PER_STEP || user != ai || !COOLDOWN_FINISHED(src, cooldown_mod_move) || (wearer?.pulledby?.grab_state > GRAB_PASSIVE))
if((!active && wearer) || get_charge() < CHARGE_PER_STEP || user != ai_assistant || !COOLDOWN_FINISHED(src, cooldown_mod_move) || (wearer?.pulledby?.grab_state > GRAB_PASSIVE))
return FALSE
// SKYRAT EDIT START - pAIs in MODsuits with a bit more functionalities
if(active && !can_pai_move_suit && ispAI(ai_assistant))
return FALSE
// SKYRAT EDIT END
var/timemodifier = MOVE_DELAY * (ISDIAGONALDIR(direction) ? sqrt(2) : 1) * (wearer ? WEARER_DELAY : LONE_DELAY)
if(wearer && !wearer.Process_Spacemove(direction))
return FALSE
@@ -112,8 +183,10 @@
/obj/item/mod/ai_minicard/Initialize(mapload, mob/living/silicon/ai/ai)
. = ..()
if(!ai)
if(isnull(ai))
return
ai.controlled_equipment = null
ai.remote_control = null
ai.apply_damage(150, BURN)
INVOKE_ASYNC(ai, TYPE_PROC_REF(/mob/living/silicon/ai, death))
ai.forceMove(src)
@@ -149,4 +222,3 @@
balloon_alert(user, "ai transferred to card")
stored_ai = null
#undef AI_FALL_TIME
*/
+27 -27
View File
@@ -21,10 +21,10 @@
/datum/action/item_action/mod/sprite_accessories, // SKYRAT EDIT - Hide mutant parts action
/datum/action/item_action/mod/panel,
/datum/action/item_action/mod/module,
/datum/action/item_action/mod/deploy/pai, // SKYRAT EDIT - pAIs in MODsuits
/datum/action/item_action/mod/activate/pai, // SKYRAT EDIT - pAIs in MODsuits
/datum/action/item_action/mod/panel/pai, // SKYRAT EDIT - pAIs in MODsuits
/datum/action/item_action/mod/module/pai, // SKYRAT EDIT - pAIs in MODsuits
/datum/action/item_action/mod/deploy/ai,
/datum/action/item_action/mod/activate/ai,
/datum/action/item_action/mod/panel/ai,
/datum/action/item_action/mod/module/ai,
)
resistance_flags = NONE
max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT
@@ -83,10 +83,8 @@
var/list/modules = list()
/// Currently used module.
var/obj/item/mod/module/selected_module
/* SKYRAT EDIT REMOVAL - MODsuit pAIs
/// AI mob inhabiting the MOD.
var/mob/living/silicon/ai/ai
*/ // SKYRAT EDIT END
/// AI or pAI mob inhabiting the MOD.
var/mob/living/silicon/ai_assistant
/// Delay between moves as AI.
var/static/movedelay = 0
/// Cooldown for AI moves.
@@ -189,7 +187,14 @@
var/obj/item/overslot = overslotting_parts[part]
overslot.forceMove(drop_location())
overslotting_parts[part] = null
remove_pai() // SKYRAT EDIT - pAIs in MODsuits
if(ai_assistant)
if(ispAI(ai_assistant))
INVOKE_ASYNC(src, PROC_REF(remove_pai), /* user = */ null, /* forced = */ TRUE) // async to appease spaceman DMM because the branch we don't run has a do_after
else
for(var/datum/action/action as anything in actions)
if(action.owner == ai_assistant)
action.Remove(ai_assistant)
new /obj/item/mod/ai_minicard(drop_location(), ai_assistant)
return ..()
/obj/item/mod/control/examine(mob/user)
@@ -211,12 +216,10 @@
. += span_notice("You could remove [core] with a <b>wrench</b>.")
else
. += span_notice("You could use a <b>MOD core</b> on it to install one.")
if(!mod_pai) // SKYRAT EDIT BEGIN - PAI in Modsuits
. += span_notice("You could install a pAI with a <b>pAI card</b>.")
/* if(ai)
. += span_notice("You could remove [ai] with an <b>intellicard</b>.")
else
. += span_notice("You could install an AI with an <b>intellicard</b>.") SKYRAT EDIT END */
if(isnull(ai_assistant))
. += span_notice("You could install a pAI with a <b>pAI card</b>.") // SKYRAT EDIT CHANGE - ORIGINAL: . += span_notice("You could install an AI or pAI using their <b>storage card</b>.")
else if(isAI(ai_assistant))
. += span_notice("You could remove [ai_assistant] with an <b>intellicard</b>.")
. += span_notice("<i>You could examine it more thoroughly...</i>")
/obj/item/mod/control/examine_more(mob/user)
@@ -256,6 +259,13 @@
if(slot & slot_flags)
return TRUE
// Grant pinned actions to pin owners, gives AI pinned actions to the AI and not the wearer
/obj/item/mod/control/grant_action_to_bearer(datum/action/action)
if (!istype(action, /datum/action/item_action/mod/pinned_module))
return ..()
var/datum/action/item_action/mod/pinned_module/pinned = action
give_item_action(action, pinned.pinner, slot_flags)
/obj/item/mod/control/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE)
. = ..()
if(!wearer || old_loc != wearer || loc == wearer)
@@ -317,10 +327,8 @@
return ..()
/obj/item/mod/control/screwdriver_act(mob/living/user, obj/item/screwdriver)
// SKYRAT EDIT START - pAIs in MODsuits
. = ..()
if(.)
// SKYRAT EDIT END
return TRUE
if(active || activating || ai_controller)
balloon_alert(user, "deactivate suit first!")
@@ -370,14 +378,12 @@
return FALSE
/obj/item/mod/control/attackby(obj/item/attacking_item, mob/living/user, params)
// SKYRAT EDIT START - pAIs in MODsuits
if(istype(attacking_item, /obj/item/pai_card))
if(!open) //mod must be open
balloon_alert(user, "suit must be open to transfer!")
if(!open)
balloon_alert(user, "open the cover first!")
return FALSE
insert_pai(user, attacking_item)
return TRUE
// SKYRAT EDIT END
if(istype(attacking_item, /obj/item/mod/module))
if(!open)
balloon_alert(user, "open the cover first!")
@@ -576,12 +582,6 @@
new_module.on_equip()
if(active)
new_module.on_suit_activation()
// SKYRAT EDIT START - pAIs in MODsuits
if(mod_pai)
var/datum/action/item_action/mod/pinned_module/action = new_module.pinned_to[ref(mod_pai)]
if(action)
action.Grant(mod_pai)
// SKYRAT EDIT END
if(user)
balloon_alert(user, "[new_module] added")
playsound(src, 'sound/machines/click.ogg', 50, TRUE, SILENCED_SOUND_EXTRARANGE)
+13 -13
View File
@@ -12,7 +12,9 @@
"cell_charge_current" = get_charge(),
"cell_charge_max" = get_max_charge(),
"active" = active,
//"ai_name" = ai?.name, // SKYRAT EDIT REMOVAL - pAIs in MODsuits
"ai_name" = ai_assistant?.name,
"has_pai" = ispAI(ai_assistant),
"is_ai" = ai_assistant && ai_assistant == user,
// Wires
"open" = open,
"seconds_electrified" = seconds_electrified,
@@ -21,10 +23,6 @@
"interface_break" = interface_break,
// Modules
"complexity" = complexity,
// SKYRAT EDIT START - pAIs in MODsuits
"pAI" = mod_pai?.name,
"ispAI" = mod_pai ? mod_pai == user : FALSE,
// SKYRAT EDIT END
)
data["suit_status"] = suit_status
// User information
@@ -69,12 +67,16 @@
data["boots"] = boots?.name
return data
/obj/item/mod/control/ui_state(mob/user)
if(user == ai_assistant)
return GLOB.contained_state
return ..()
/obj/item/mod/control/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(.)
return
// allowed() doesn't allow for pAIs
if(((locked && !ispAI(usr)) && !allowed(usr))) // SKYRAT EDIT CHANGE - ORIGINAL: if(locked && !allowed(usr))
if(locked && (!allowed(usr) || !ispAI(usr))) // pAIs automatically fail out of allowed()
balloon_alert(usr, "insufficient access!")
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return
@@ -102,10 +104,8 @@
if(!module)
return
module.pin(usr)
// SKYRAT EDIT START - pAIs in MODsuits
if("remove_pai")
if(ishuman(usr)) // Only the MODsuit's wearer should be removing the pAI.
var/mob/user = usr
extract_pai(user)
// SKYRAT EDIT END
if("eject_pai")
if (!ishuman(usr))
return
remove_pai(usr)
return TRUE
+2 -4
View File
@@ -257,11 +257,9 @@
. = ..()
if(. != MOD_CANCEL_ACTIVATE || !isliving(user))
return
// SKYRAT EDIT CHANGE BEGIN - pAIs in MODsuits - `ai` replaced with `mod_pai`
if(mod.mod_pai == user)
to_chat(mod.mod_pai, span_danger("<B>fATaL EERRoR</B>: 381200-*#00CODE <B>BLUE</B>\nAI INTErFERenCE DEtECted\nACTi0N DISrEGArdED"))
if(mod.ai_assistant == user)
to_chat(mod.ai_assistant, span_danger("<B>fATaL EERRoR</B>: 381200-*#00CODE <B>BLUE</B>\nAI INTErFERenCE DEtECted\nACTi0N DISrEGArdED"))
return
// SKYRAT EDIT CHANGE END
var/mob/living/living_user = user
to_chat(living_user, span_danger("<B>fATaL EERRoR</B>: 382200-*#00CODE <B>RED</B>\nUNAUTHORIZED USE DETECteD\nCoMMENCING SUB-R0UTIN3 13...\nTERMInATING U-U-USER..."))
living_user.investigate_log("has been gibbed by using a MODsuit equipped with [src].", INVESTIGATE_DEATHS)