diff --git a/code/__DEFINES/pai.dm b/code/__DEFINES/pai.dm new file mode 100644 index 00000000000..4359cf9d8ea --- /dev/null +++ b/code/__DEFINES/pai.dm @@ -0,0 +1,2 @@ +/// Total percent required to hack a door. +#define HACK_COMPLETE 100 diff --git a/code/controllers/subsystem/pai.dm b/code/controllers/subsystem/pai.dm index 3171a27ebbf..3c66d28dc15 100644 --- a/code/controllers/subsystem/pai.dm +++ b/code/controllers/subsystem/pai.dm @@ -3,16 +3,26 @@ SUBSYSTEM_DEF(pai) flags = SS_NO_INIT|SS_NO_FIRE + /// List of pAI candidates, including those not submitted. var/list/candidates = list() + /// Prevents a crew member from hitting "request pAI" var/request_spam = FALSE + /// Prevents a pAI from submitting itself repeatedly and sounding an alert. var/submit_spam = FALSE + /// All pAI cards on the map. var/list/pai_card_list = list() +/// Created when a user clicks the "pAI candidate" window /datum/pai_candidate + /// User inputted OOC comments var/comments + /// User inputted behavior description var/description + /// User's ckey - not input var/key + /// User's pAI name. If blank, ninja name. var/name + /// If the user has hit "submit" var/ready = FALSE /** @@ -53,11 +63,9 @@ SUBSYSTEM_DEF(pai) candidates.Add(candidate) ui_interact(user) -/// Ensures an observer has the window open /datum/controller/subsystem/pai/ui_state(mob/user) return GLOB.observer_state -/// Opens the TGUI window /datum/controller/subsystem/pai/ui_interact(mob/user, datum/tgui/ui) . = ..() ui = SStgui.try_update_ui(user, src, ui) @@ -65,7 +73,6 @@ SUBSYSTEM_DEF(pai) ui = new(user, src, "PaiSubmit") ui.open() -/// The data sent to the window. /datum/controller/subsystem/pai/ui_static_data(mob/user) . = ..() var/list/data = list() @@ -78,7 +85,6 @@ SUBSYSTEM_DEF(pai) data["name"] = candidate.name return data -/// Actions sent by TGUI /datum/controller/subsystem/pai/ui_act(action, list/params, datum/tgui/ui) . = ..() if(.) @@ -86,6 +92,8 @@ SUBSYSTEM_DEF(pai) /// The matching candidate from search var/datum/pai_candidate/candidate = check_candidate(usr) if(isnull(candidate)) + to_chat(usr, span_warning("There was an error. Please resubmit.")) + ui.close() return FALSE switch(action) if("submit") @@ -100,7 +108,6 @@ SUBSYSTEM_DEF(pai) candidate.description = params["candidate"]["description"] candidate.name = params["candidate"]["name"] candidate.savefile_save(usr) - to_chat(usr, span_boldnotice("You have saved pAI information locally.")) if("load") candidate.savefile_load(usr) //In case people have saved unsanitized stuff. diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 5be3455948f..5accfb8efc9 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -678,6 +678,7 @@ GLOBAL_LIST_EMPTY(PDAs) pai.attack_self(U) if("2") // Eject pAI device usr.put_in_hands(pai) + pai.slotted = FALSE to_chat(usr, span_notice("You remove the pAI from the [name].")) //SKILL FUNCTIONS=================================== @@ -1085,6 +1086,7 @@ GLOBAL_LIST_EMPTY(PDAs) if(!user.transferItemToLoc(C, src)) return pai = C + pai.slotted = TRUE to_chat(user, span_notice("You slot \the [C] into [src].")) update_appearance() updateUsrDialog() diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm index efc25807657..32e6db7dbc1 100644 --- a/code/game/objects/items/devices/paicard.dm +++ b/code/game/objects/items/devices/paicard.dm @@ -11,8 +11,12 @@ custom_premium_price = PAYCHECK_HARD * 1.25 ///don't spam alert messages. var/alert_cooldown + /// If the pAIcard is slotted in a PDA + var/slotted = FALSE + /// Any pAI personalities inserted var/mob/living/silicon/pai/pai - var/emotion_icon = "off" ///what emotion icon we have. handled in /mob/living/silicon/pai/Topic() + ///what emotion icon we have. handled in /mob/living/silicon/pai/Topic() + var/emotion_icon = "off" resistance_flags = FIRE_PROOF | ACID_PROOF | INDESTRUCTIBLE /obj/item/paicard/suicide_act(mob/living/user) @@ -63,7 +67,7 @@ ui.open() /obj/item/paicard/ui_state(mob/user) - return GLOB.inventory_state + return GLOB.paicard_state /obj/item/paicard/ui_data(mob/user) . = ..() diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 920cf9e8c19..ddd88e42018 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -34,6 +34,8 @@ var/obj/item/paicard/card /// Are we hacking a door? var/hacking = FALSE + /// The progress for hacking + var/datum/progressbar/hackbar /// Changes the display to syndi if true var/emagged = FALSE @@ -174,22 +176,27 @@ aiPDA.name = real_name + " (" + aiPDA.ownjob + ")" /mob/living/silicon/pai/proc/process_hack(delta_time, times_fired) - if(hacking_cable && hacking_cable.machine && istype(hacking_cable.machine, /obj/machinery/door) && hacking_cable.machine == hackdoor && get_dist(src, hackdoor) <= 1) - hackprogress = clamp(hackprogress + (2 * delta_time), 0, 100) + if(hacking_cable?.machine && istype(hacking_cable.machine, /obj/machinery/door) && hacking_cable.machine == hackdoor && get_dist(src, hackdoor) <= 1) + hackprogress = clamp(hackprogress + (2 * delta_time), 0, HACK_COMPLETE) + hackbar.update(hackprogress) else to_chat(src, span_notice("Door Jack: Connection to airlock has been lost. Hack aborted.")) hackprogress = 0 hacking = FALSE hackdoor = null + hackbar.end_progress() + QDEL_NULL(hackbar) QDEL_NULL(hacking_cable) if(!QDELETED(card)) card.update_appearance() return - if(hackprogress >= 100) + if(hackprogress >= HACK_COMPLETE) hackprogress = 0 - var/obj/machinery/door/D = hacking_cable.machine - D.open() hacking = FALSE + hackbar.end_progress() + var/obj/machinery/door/door = hacking_cable.machine + door.open() + QDEL_NULL(hackbar) QDEL_NULL(hacking_cable) /mob/living/silicon/pai/make_laws() diff --git a/code/modules/mob/living/silicon/pai/personality.dm b/code/modules/mob/living/silicon/pai/personality.dm index 57f248cba48..b00fe994c10 100644 --- a/code/modules/mob/living/silicon/pai/personality.dm +++ b/code/modules/mob/living/silicon/pai/personality.dm @@ -12,17 +12,14 @@ /datum/pai_candidate/proc/savefile_save(mob/user) if(is_guest_key(user.key)) + to_chat(usr, span_warning("You cannot save pAI information as a guest.")) return FALSE - var/savefile/F = new /savefile(src.savefile_path(user)) - - WRITE_FILE(F["name"], name) WRITE_FILE(F["description"], description) WRITE_FILE(F["comments"], comments) - WRITE_FILE(F["version"], 1) - + to_chat(usr, span_boldnotice("You have saved pAI information locally.")) return TRUE // loads the savefile corresponding to the mob's ckey diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index 3a52930f388..433dae8614d 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -277,6 +277,8 @@ to_chat(AI, "Network Alert: Brute-force security override in progress in [turf.loc].") else to_chat(AI, "Network Alert: Brute-force security override in progress. Unable to pinpoint location.") + if(!hackbar) + hackbar = new(src, HACK_COMPLETE, hacking_cable.machine) hacking = TRUE /** diff --git a/code/modules/tgui/states/paicard.dm b/code/modules/tgui/states/paicard.dm new file mode 100644 index 00000000000..a2450b7588c --- /dev/null +++ b/code/modules/tgui/states/paicard.dm @@ -0,0 +1,20 @@ +/** + * tgui state: paicard_state + * + * Checks that the paicard is in the user's top-level + * (hand, ear, pocket, belt, etc) inventory OR + * if the paicard has been slotted into a PDA which + * is also on the user's person. + * + */ + +GLOBAL_DATUM_INIT(paicard_state, /datum/ui_state/paicard_state, new) + +/datum/ui_state/paicard_state/can_use_topic(obj/item/paicard/paicard, mob/user) + /// paicard is in the user's closest inventory + if(!paicard.slotted && (paicard in user)) + return user.shared_ui_interaction(paicard) + /// paicard is in a pda slot which is in the user's closest inventory + if(paicard.slotted && (paicard.loc in user)) + return user.shared_ui_interaction(paicard) + return UI_CLOSE diff --git a/tgstation.dme b/tgstation.dme index 44aa93739be..ef03c15dbce 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -109,6 +109,7 @@ #include "code\__DEFINES\networks.dm" #include "code\__DEFINES\nitrile.dm" #include "code\__DEFINES\obj_flags.dm" +#include "code\__DEFINES\pai.dm" #include "code\__DEFINES\pinpointers.dm" #include "code\__DEFINES\pipe_construction.dm" #include "code\__DEFINES\plumbing.dm" @@ -3851,6 +3852,7 @@ #include "code\modules\tgui\states\not_incapacitated.dm" #include "code\modules\tgui\states\notcontained.dm" #include "code\modules\tgui\states\observer.dm" +#include "code\modules\tgui\states\paicard.dm" #include "code\modules\tgui\states\physical.dm" #include "code\modules\tgui\states\self.dm" #include "code\modules\tgui\states\zlevel.dm" diff --git a/tgui/packages/tgui/interfaces/PaiCard.tsx b/tgui/packages/tgui/interfaces/PaiCard.tsx index e0fb1f56839..a46017eb750 100644 --- a/tgui/packages/tgui/interfaces/PaiCard.tsx +++ b/tgui/packages/tgui/interfaces/PaiCard.tsx @@ -169,7 +169,7 @@ const PaiOptions = (_, context) => { )} - {master && {dna}} + {!!master && {dna}} {laws}