From 21e0c7372822412fd4f6553accfbe64e2bebb0e0 Mon Sep 17 00:00:00 2001 From: Oblisk234 <61151679+Oblisk234@users.noreply.github.com> Date: Sun, 8 Dec 2024 22:58:36 +0000 Subject: [PATCH 01/14] Who thought it was a good idea to name those fields that? --- code/modules/mob/living/silicon/pai/pai.dm | 24 +++++------- .../mob/living/silicon/pai/software.dm | 31 ++++++++++++++- .../modular_computers/hardware/paicard.dm | 4 +- .../packages/tgui/interfaces/PaiInterface.tsx | 39 +++++++++++++++++++ 4 files changed, 80 insertions(+), 18 deletions(-) diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 9b220cb114a7..0e386359bc34 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -41,19 +41,6 @@ // Various software-specific vars - var/temp // General error reporting text contained here will typically be shown once and cleared - var/screen // Which screen our main window displays - var/subscreen // Which specific function of the main screen is being displayed - - var/secHUD = 0 // Toggles whether the Security HUD is active or not - var/medHUD = 0 // Toggles whether the Medical HUD is active or not - - var/datum/data/record/medicalActive1 // Datacore record declarations for record software - var/datum/data/record/medicalActive2 - - var/datum/data/record/securityActive1 // Could probably just combine all these into one - var/datum/data/record/securityActive2 - var/obj/machinery/door/hackdoor // The airlock being hacked var/hackprogress = 0 // Possible values: 0 - 100, >= 100 means the hack is complete and will be reset upon next check @@ -64,10 +51,14 @@ var/obj/machinery/newscaster //pAI Newscaster var/obj/item/healthanalyzer/hostscan //pAI healthanalyzer + //Whether the pAI has bought the encryption slot module or not var/encryptmod = FALSE var/holoform = FALSE + //Can pAI use their holoprojector? var/canholo = TRUE + //Can pAI transmit radio messages? var/can_transmit = TRUE + //Can pAI receive radio messages? var/can_receive = TRUE var/obj/item/card/id/access_card = null var/chassis = "repairbot" @@ -153,7 +144,6 @@ if(cable && cable.machine && istype(cable.machine, /obj/machinery/door) && cable.machine == hackdoor && get_dist(src, hackdoor) <= 1) hackprogress = clamp(hackprogress + 20, 0, 100) else - temp = "Door Jack: Connection to airlock has been lost. Hack aborted." hackprogress = 0 hacking = FALSE hackdoor = null @@ -283,6 +273,10 @@ /mob/living/silicon/pai/examine(mob/user) . = ..() . += "A personal AI in holochassis mode. Its master ID string seems to be [master]." + if(software && isobserver(user)) + . += "[src] has the following modules:" + for(var/list/module in software) + . += "[module["module_name"]]" /mob/living/silicon/pai/Life(seconds_per_tick = SSMOBS_DT, times_fired) if(stat == DEAD) @@ -307,7 +301,7 @@ emitterhealth = clamp((emitterhealth + (emitter_regen_per_second * delta_time)), -50, emittermaxhealth) /obj/item/computer_hardware/paicard/attackby(obj/item/W, mob/user, params) - ..() + . = ..() user.set_machine(src) if(pai.encryptmod == TRUE) if(W.tool_behaviour == TOOL_SCREWDRIVER) diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index e8e0db8d1209..33b834d1fc90 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -15,8 +15,8 @@ list("module_name" = "atmosphere sensor", "tab"=TRUE, "title"="Atmospheric sensor", "cost" = 5), list("module_name" = "photography module", "tab"=FALSE, "cost" = 5), list("module_name" = "remote signaller", "tab"=TRUE, "title"="Remote signaller", "cost" = 10), - //list("module_name" = "medical records", "tab"=TRUE, "title"="Medical records", "cost" = 10), - //list("module_name" = "security records", "tab"=TRUE, "title"="Security records", "cost" = 10), + list("module_name" = "medical records", "tab"=TRUE, "title"="Medical records", "cost" = 10), + list("module_name" = "security records", "tab"=TRUE, "title"="Security records", "cost" = 10), list("module_name" = "camera zoom", "tab"=FALSE, "cost" = 10), list("module_name" = "host scan", "tab"=TRUE, "title"="Host Bioscan settings", "cost" = 10), //"camera jack" = 10, @@ -41,6 +41,9 @@ /mob/living/silicon/pai/var/cable_status = "Retracted" +/mob/living/silicon/pai/var/med_record = list() +/mob/living/silicon/pai/var/sec_record = list() + /mob/living/silicon/pai/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) @@ -78,6 +81,30 @@ data["minFrequency"] = MIN_FREE_FREQ data["maxFrequency"] = MAX_FREE_FREQ data["color"] = signaler.label_color + if(GLOB.data_core.general && GLOB.data_core.medical) + for(var/datum/data/record/M in sortRecord(GLOB.data_core.medical)) + for(var/datum/data/record/R in sortRecord(GLOB.data_core.general)) + if(R.fields["name"] == M.fields["name"]) + var/new_record = list("name" = R.fields["name"], "id" = R.fields["id"], "gender" = R.fields["gender"], "age" = R.fields["age"], "fingerprint" = R.fields["fingerprint"], "p_state" = R.fields["p_state"], "m_state" = R.fields["m_state"], "blood_type" = M.fields["blood_type"], "dna" = M.fields["b_dna"], "minor_disabilities" = M.fields["mi_dis"], "minor_disabilities_details" = M.fields["mi_dis_d"], "major_disabilities" = M.fields["ma_dis"], "major_disabilities_details" = M.fields["ma_dis_d"], "allergies" = M.fields["alg"], "allergies_details" = M.fields["alg_d"], "current_diseases" = M.fields["cdi"], "current_diseases_details" = M.fields["cdi_d"], "important_notes" = M.fields["notes"]) + med_record += list(new_record) + qdel(new_record) + break + if(GLOB.data_core.general && GLOB.data_core.security) + for(var/datum/data/record/S in sortRecord(GLOB.data_core.security)) + for(var/datum/data/record/R in sortRecord(GLOB.data_core.general)) + if(R.fields["name"] == S.fields["name"]) + var/list/crimes = list() + for(var/datum/data/crime/crime in S.fields["crimes"]) + crimes += list("[crime.crimeName]: [crime.crimeDetails]") + var/list/comments = list() + for(var/datum/data/comment/comment in S.fields["comments"]) + comments += list("[comment.commentText] - [comment.author] [comment.time]") + var/new_record = list("name" = R.fields["name"], "id" = R.fields["id"], "gender" = R.fields["gender"], "age" = R.fields["age"], "rank" = R.fields["rank"], "fingerprint" = R.fields["fingerprint"], "p_state" = R.fields["p_state"], "criminal_status" = S.fields["criminal"], "crimes" = crimes, "important_notes" = S.fields["notes"], "comments" = comments) + sec_record += list(new_record) + qdel(new_record) + break + data["med_records"] = med_record + data["sec_records"] = sec_record return data /mob/living/silicon/pai/ui_act(action, params) diff --git a/code/modules/modular_computers/hardware/paicard.dm b/code/modules/modular_computers/hardware/paicard.dm index 90af65421fb9..76c1a7d1f51e 100644 --- a/code/modules/modular_computers/hardware/paicard.dm +++ b/code/modules/modular_computers/hardware/paicard.dm @@ -88,6 +88,7 @@ if("wipe") var/confirm = tgui_alert(usr, "Are you CERTAIN you wish to delete the current personality? This action cannot be undone.", "Personality Wipe", list("Yes", "No")) if(confirm == "Yes") + candidates_ready = null if(pai) to_chat(pai, span_warning("You feel yourself slipping away from reality.")) to_chat(pai, span_danger("Byte by byte you lose your sense of self.")) @@ -117,8 +118,9 @@ pai.key = candidate.key card.setPersonality(pai) + candidates.Remove(candidate) candidate = list("name" = candidate.name, "description"=candidate.description, "prefrole"=candidate.role, "ooccomments"=candidate.comments) - candidates.Remove(list(candidate)) + SSpai.candidates.Remove(candidate) if("setlaws") var/newlaw = stripped_multiline_input(usr, "Enter any additional directives you would like your pAI personality to follow. Note that these directives will not override the personality's allegiance to its imprinted master. Conflicting directives will be ignored.", "pAI Directive Configuration", pai.laws.supplied[1], MAX_MESSAGE_LEN) if(newlaw && pai) diff --git a/tgui/packages/tgui/interfaces/PaiInterface.tsx b/tgui/packages/tgui/interfaces/PaiInterface.tsx index dd394697aacf..6d43b73e49a5 100644 --- a/tgui/packages/tgui/interfaces/PaiInterface.tsx +++ b/tgui/packages/tgui/interfaces/PaiInterface.tsx @@ -10,6 +10,43 @@ type Module = { cost: number; } +type MedRecord = { /* This should probably be cut down, but it's all valid medical record information */ + name: string; + id: string; + gender: string; + age: number; + fingerprint: string; + p_state: string; + m_state: string; + blood_type: string; + dna: string; + minor_disabilities: string; + minor_disabilities_details: string; + major_disabilities: string; + major_disabilities_details: string; + allergies: string; + allergies_details: string; + current_diseases: string; + current_diseases_details: string; + important_notes: string; + comments: string[]; +} + +type SecRecord = { + name: string; + id: string; + gender: string; + age: number; + rank: string; + fingerprint: string; + p_state: string; + m_state: string; + criminal_status: string; + crimes: string[]; + important_notes: string; + comments: string[]; +} + type Data = { modules: Data[]; modules_list: Module[]; @@ -31,6 +68,8 @@ type Data = { minFrequency: number; maxFrequency: number; color: string; + med_records: MedRecord[]; + sec_records: SecRecord[]; } export const AirlockJackTextSwitch = params => { From 08cdafbe16ed2b3f87bcaeabc77f5925a5555daa Mon Sep 17 00:00:00 2001 From: Oblisk234 <61151679+Oblisk234@users.noreply.github.com> Date: Tue, 10 Dec 2024 07:05:37 +0000 Subject: [PATCH 02/14] I guess it doesn't want to work --- code/modules/mob/living/silicon/pai/software.dm | 15 +++++++++++---- .../modules/modular_computers/hardware/paicard.dm | 4 ++-- tgui/packages/tgui/interfaces/PaiInterface.tsx | 7 +++++++ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index 33b834d1fc90..eb7d1068ed57 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -41,8 +41,8 @@ /mob/living/silicon/pai/var/cable_status = "Retracted" -/mob/living/silicon/pai/var/med_record = list() -/mob/living/silicon/pai/var/sec_record = list() +/mob/living/silicon/pai/var/list/med_record = list() +/mob/living/silicon/pai/var/list/sec_record = list() /mob/living/silicon/pai/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) @@ -82,14 +82,21 @@ data["maxFrequency"] = MAX_FREE_FREQ data["color"] = signaler.label_color if(GLOB.data_core.general && GLOB.data_core.medical) + med_record = list() //Important to reset it here so it doesn't readd records endlessly for(var/datum/data/record/M in sortRecord(GLOB.data_core.medical)) for(var/datum/data/record/R in sortRecord(GLOB.data_core.general)) if(R.fields["name"] == M.fields["name"]) - var/new_record = list("name" = R.fields["name"], "id" = R.fields["id"], "gender" = R.fields["gender"], "age" = R.fields["age"], "fingerprint" = R.fields["fingerprint"], "p_state" = R.fields["p_state"], "m_state" = R.fields["m_state"], "blood_type" = M.fields["blood_type"], "dna" = M.fields["b_dna"], "minor_disabilities" = M.fields["mi_dis"], "minor_disabilities_details" = M.fields["mi_dis_d"], "major_disabilities" = M.fields["ma_dis"], "major_disabilities_details" = M.fields["ma_dis_d"], "allergies" = M.fields["alg"], "allergies_details" = M.fields["alg_d"], "current_diseases" = M.fields["cdi"], "current_diseases_details" = M.fields["cdi_d"], "important_notes" = M.fields["notes"]) + message_admins("Made new med record") + message_admins("Name: [R.fields["name"]]") + var/list/new_record = list("name" = R.fields["name"], "id" = R.fields["id"], "gender" = R.fields["gender"], "age" = R.fields["age"], "fingerprint" = R.fields["fingerprint"], "p_state" = R.fields["p_state"], "m_state" = R.fields["m_state"], "blood_type" = M.fields["blood_type"], "dna" = M.fields["b_dna"], "minor_disabilities" = M.fields["mi_dis"], "minor_disabilities_details" = M.fields["mi_dis_d"], "major_disabilities" = M.fields["ma_dis"], "major_disabilities_details" = M.fields["ma_dis_d"], "allergies" = M.fields["alg"], "allergies_details" = M.fields["alg_d"], "current_diseases" = M.fields["cdi"], "current_diseases_details" = M.fields["cdi_d"], "important_notes" = M.fields["notes"]) + message_admins("New record name: [new_record["name"]]") med_record += list(new_record) qdel(new_record) break + message_admins("Len: [med_record.len]") + message_admins("Record test: [med_record[0]") if(GLOB.data_core.general && GLOB.data_core.security) + sec_record = list() for(var/datum/data/record/S in sortRecord(GLOB.data_core.security)) for(var/datum/data/record/R in sortRecord(GLOB.data_core.general)) if(R.fields["name"] == S.fields["name"]) @@ -99,7 +106,7 @@ var/list/comments = list() for(var/datum/data/comment/comment in S.fields["comments"]) comments += list("[comment.commentText] - [comment.author] [comment.time]") - var/new_record = list("name" = R.fields["name"], "id" = R.fields["id"], "gender" = R.fields["gender"], "age" = R.fields["age"], "rank" = R.fields["rank"], "fingerprint" = R.fields["fingerprint"], "p_state" = R.fields["p_state"], "criminal_status" = S.fields["criminal"], "crimes" = crimes, "important_notes" = S.fields["notes"], "comments" = comments) + var/list/new_record = list("name" = R.fields["name"], "id" = R.fields["id"], "gender" = R.fields["gender"], "age" = R.fields["age"], "rank" = R.fields["rank"], "fingerprint" = R.fields["fingerprint"], "p_state" = R.fields["p_state"], "criminal_status" = S.fields["criminal"], "crimes" = crimes, "important_notes" = S.fields["notes"], "comments" = comments) sec_record += list(new_record) qdel(new_record) break diff --git a/code/modules/modular_computers/hardware/paicard.dm b/code/modules/modular_computers/hardware/paicard.dm index 76c1a7d1f51e..b0de370b7f47 100644 --- a/code/modules/modular_computers/hardware/paicard.dm +++ b/code/modules/modular_computers/hardware/paicard.dm @@ -118,9 +118,9 @@ pai.key = candidate.key card.setPersonality(pai) - candidates.Remove(candidate) - candidate = list("name" = candidate.name, "description"=candidate.description, "prefrole"=candidate.role, "ooccomments"=candidate.comments) SSpai.candidates.Remove(candidate) + candidate = list("name" = candidate.name, "description"=candidate.description, "prefrole"=candidate.role, "ooccomments"=candidate.comments) + candidates.Remove(candidate) if("setlaws") var/newlaw = stripped_multiline_input(usr, "Enter any additional directives you would like your pAI personality to follow. Note that these directives will not override the personality's allegiance to its imprinted master. Conflicting directives will be ignored.", "pAI Directive Configuration", pai.laws.supplied[1], MAX_MESSAGE_LEN) if(newlaw && pai) diff --git a/tgui/packages/tgui/interfaces/PaiInterface.tsx b/tgui/packages/tgui/interfaces/PaiInterface.tsx index 6d43b73e49a5..4774bc9aa53d 100644 --- a/tgui/packages/tgui/interfaces/PaiInterface.tsx +++ b/tgui/packages/tgui/interfaces/PaiInterface.tsx @@ -126,6 +126,7 @@ const PaiBox = (props, context) => { const { pressure, gases, temperature } = data; const { hacking, hackprogress, cable, door } = data; const { code, frequency, minFrequency, maxFrequency, color } = data; + const { med_records, sec_records } = data; switch(modules_tabs[selectedMainTab].module_name) { case "directives": return ( @@ -345,6 +346,12 @@ const PaiBox = (props, context) => { ); + case "medical records": + return ( +
+ {med_records[0].name} +
+ ); case "host scan": return (
From faf8fdc05624d98cffdcbba767dd524701247a21 Mon Sep 17 00:00:00 2001 From: 30178812 <61151679+Oblisk234@users.noreply.github.com> Date: Tue, 10 Dec 2024 12:21:10 +0000 Subject: [PATCH 03/14] Improvements + access copying --- code/modules/mob/living/silicon/pai/pai.dm | 27 +++++++++++++------ .../mob/living/silicon/pai/software.dm | 13 +++++---- .../packages/tgui/interfaces/PaiInterface.tsx | 8 +++--- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 0e386359bc34..544e838403ab 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -272,7 +272,7 @@ /mob/living/silicon/pai/examine(mob/user) . = ..() - . += "A personal AI in holochassis mode. Its master ID string seems to be [master]." + . += "A personal AI in holochassis mode. Its master ID string seems to be [master ? master : "empty"]." if(software && isobserver(user)) . += "[src] has the following modules:" for(var/list/module in software) @@ -287,7 +287,7 @@ T.visible_message(span_warning("[src.cable] rapidly retracts back into its spool."), span_italics("You hear a click and the sound of wire spooling rapidly.")) qdel(src.cable) cable = null - cable_status = "Retracted" + cable_status = PAI_CABLE_RETRACTED silent = max(silent - 1, 0) . = ..() @@ -303,10 +303,21 @@ /obj/item/computer_hardware/paicard/attackby(obj/item/W, mob/user, params) . = ..() user.set_machine(src) - if(pai.encryptmod == TRUE) - if(W.tool_behaviour == TOOL_SCREWDRIVER) + if(W.tool_behaviour == TOOL_SCREWDRIVER||istype(W, /obj/item/encryptionkey)) + if(pai.encryptmod == TRUE) pai.radio.attackby(W, user, params) - else if(istype(W, /obj/item/encryptionkey)) - pai.radio.attackby(W, user, params) - else - to_chat(user, "Encryption Key ports not configured.") + else + to_chat(user, "Encryption Key ports not configured.") + else if(istype(W, /obj/item/card/id)) + var/obj/item/card/id/id_card = W + pai.copy_access(id_card, user) + +/mob/living/silicon/pai/attackby(obj/item/W, mob/user, params) + . = ..() + if(istype(W, /obj/item/card/id)) + var/obj/item/card/id/id_card = W + copy_access(id_card, user) + +/mob/living/silicon/pai/proc/copy_access(obj/item/card/id/ID, mob/user) + pai.access_card.access += ID.access + to_chat(user, "Copied access from [ID]!") diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index eb7d1068ed57..94b3bdc6f0a6 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -2,7 +2,8 @@ // - Potentially roll HUDs and Records into one // - Shock collar/lock system for prisoner pAIs? // - Camera jack - +#define PAI_CABLE_RETRACTED 0 +#define PAI_CABLE_EXTENDED 1 /mob/living/silicon/pai/var/list/available_software = list( //Nightvision @@ -39,7 +40,7 @@ /mob/living/silicon/pai/var/pressure /mob/living/silicon/pai/var/gases -/mob/living/silicon/pai/var/cable_status = "Retracted" +/mob/living/silicon/pai/var/cable_status = PAI_CABLE_RETRACTED /mob/living/silicon/pai/var/list/med_record = list() /mob/living/silicon/pai/var/list/sec_record = list() @@ -94,7 +95,7 @@ qdel(new_record) break message_admins("Len: [med_record.len]") - message_admins("Record test: [med_record[0]") + message_admins("Record test: [med_record[0]]") if(GLOB.data_core.general && GLOB.data_core.security) sec_record = list() for(var/datum/data/record/S in sortRecord(GLOB.data_core.security)) @@ -212,13 +213,15 @@ internal_instrument = new(src) internal_instrument.interact(src) if("cable") + if(cable_status == PAI_CABLE_EXTENDED) + return var/turf/T = get_turf(loc) cable = new /obj/item/pai_cable(T) if(get(card, /mob/living/carbon/human)) var/mob/living/carbon/human/H = get(card, /mob/living/carbon/human) H.put_in_hands(cable) T.visible_message(span_warning("A port on [src] opens to reveal [cable], which promptly falls to the floor."), span_italics("You hear the soft click of something light and hard falling to the ground.")) - cable_status = "Extended" + cable_status = PAI_CABLE_EXTENDED if("jack") if(cable && cable.machine) hackdoor = cable.machine @@ -231,7 +234,7 @@ qdel(cable) hackdoor = null cable = null - cable_status = "Retracted" + cable_status = PAI_CABLE_RETRACTED update_appearance(UPDATE_ICON) /mob/living/silicon/pai/ui_state(mob/user) diff --git a/tgui/packages/tgui/interfaces/PaiInterface.tsx b/tgui/packages/tgui/interfaces/PaiInterface.tsx index 4774bc9aa53d..af209ea19e01 100644 --- a/tgui/packages/tgui/interfaces/PaiInterface.tsx +++ b/tgui/packages/tgui/interfaces/PaiInterface.tsx @@ -61,7 +61,7 @@ type Data = { temperature: number; hacking: boolean; hackprogress: number; - cable: string; + cable: boolean; door: string[]; code: number; frequency: number; @@ -381,17 +381,17 @@ const PaiBox = (props, context) => { maxValue={100}> {AirlockJackTextSwitch(hackprogress)} - {cable === "Retracted" && ( + {cable === false && ( )} - {cable === "Extended" && ( + {cable === true && ( )} - {cable === "Extended" && door !== null && ( + {cable === true && door !== null && ( hacking ? ( )} - {cable === true && ( + {cable === "Extended" && ( )} - {cable === true && door !== null && ( + {cable === "Extended" && door !== null && ( hacking ? (
); case "medical records": - return ( -
- {med_records[0].name} - - - - Name: - - - ID: - - - Fingerprint: - - - Blood type: - - - Physical state: - - - Mental state: - - - {med_records.map(MedRecord => ( - - - {MedRecord.name} - - - {MedRecord.id} - - - {MedRecord.fingerprint} - - - {MedRecord.blood_type} - - - {MedRecord.p_state} - - - {MedRecord.m_state} - - - ))} -
-
- ); + if(selected_med_record) { + return ( +
+ + + + Name: {selected_med_record.name} + + + ID: {selected_med_record.id} + + + Gender: {selected_med_record.gender} + + + Physical status: {selected_med_record.p_state} + + + Mental status: {selected_med_record.m_state} + + + Blood type: {selected_med_record.blood_type} + + + DNA: {selected_med_record.dna} + +
+ + Minor disabilities: {selected_med_record.minor_disabilities} + + + Details: {selected_med_record.minor_disabilities_details} + + + Major disabilities: {selected_med_record.major_disabilities} + + + Details: {selected_med_record.major_disabilities_details} + + + Allergies: {selected_med_record.allergies} + + + Details: {selected_med_record.allergies_details} + + + Current diseases: {selected_med_record.current_diseases} + + + Details: {selected_med_record.current_diseases_details} + + + Important notes: {selected_med_record.important_notes} + + + Comments: {selected_med_record.comments} + +
+
+ ); + } else { + return ( +
+ + + + Name: + + + ID: + + + Blood type: + + + Physical status: + + + Mental status: + + + {med_records.map(MedRecord => ( + + + + + + {MedRecord.id} + + + {MedRecord.blood_type} + + + {MedRecord.p_state} + + + {MedRecord.m_state} + + + ))} +
+
+ ); + } case "host scan": return (
From 91f75ff1c71555c6892d8d21b00d8490f1538b7c Mon Sep 17 00:00:00 2001 From: Oblisk234 <61151679+Oblisk234@users.noreply.github.com> Date: Wed, 18 Dec 2024 00:20:14 +0000 Subject: [PATCH 10/14] Sec records --- .../mob/living/silicon/pai/software.dm | 32 ++- .../packages/tgui/interfaces/PaiInterface.tsx | 253 +++++++++++++++++- 2 files changed, 270 insertions(+), 15 deletions(-) diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index 47fc3632aee7..a851462f4ef4 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -88,14 +88,16 @@ sec_record = list() for(var/datum/data/record/S in sortRecord(GLOB.data_core.security)) for(var/datum/data/record/R in sortRecord(GLOB.data_core.general)) - if(R.fields["name"] == S.fields["name"]) + if(R.fields["id"] == S.fields["id"]) var/list/crimes = list() for(var/datum/data/crime/crime in S.fields["crimes"]) - crimes += list("[crime.crimeName]: [crime.crimeDetails]") + crime = list("crime_name" = crime.crimeName, "crime_details" = crime.crimeDetails, "author" = crime.author, "time_added" = crime.time) + crimes += list(crime) var/list/comments = list() for(var/datum/data/comment/comment in S.fields["comments"]) - comments += list("[comment.commentText] - [comment.author] [comment.time]") - var/list/new_record = list("name" = R.fields["name"], "id" = R.fields["id"], "gender" = R.fields["gender"], "age" = R.fields["age"], "rank" = R.fields["rank"], "fingerprint" = R.fields["fingerprint"], "p_state" = R.fields["p_stat"], "criminal_status" = S.fields["criminal"], "crimes" = crimes, "important_notes" = S.fields["notes"], "comments" = comments) + comment = list("comment_text" = comment.commentText, "author" = comment.author, "time" = comment.time) + comments += list(comment) + var/list/new_record = list("name" = R.fields["name"], "id" = R.fields["id"], "gender" = R.fields["gender"], "age" = R.fields["age"], "rank" = R.fields["rank"], "fingerprint" = R.fields["fingerprint"], "p_state" = R.fields["p_stat"], "m_state" = R.fields["m_stat"], "criminal_status" = S.fields["criminal"], "crimes" = crimes, "important_notes" = S.fields["notes"], "comments" = comments) sec_record += list(new_record) break data["med_records"] = med_record @@ -243,6 +245,28 @@ break if("med_record back") selected_med_record = null + if("sec_record") + if(!GLOB.data_core.general||!GLOB.data_core.medical) + return + for(var/datum/data/record/S in sortRecord(GLOB.data_core.security)) + var/done = FALSE + for(var/datum/data/record/R in sortRecord(GLOB.data_core.general)) + if(S.fields["id"] == params["record"]) + var/list/crimes = list() + for(var/datum/data/crime/crime in S.fields["crimes"]) + crime = list("crime_name" = crime.crimeName, "crime_details" = crime.crimeDetails, "author" = crime.author, "time_added" = crime.time) + crimes += list(crime) + var/list/comments = list() + for(var/datum/data/comment/comment in S.fields["comments"]) + comment = list("comment_text" = comment.commentText, "author" = comment.author, "time" = comment.time) + comments += list(comment) + selected_sec_record = list("name" = R.fields["name"], "id" = R.fields["id"], "gender" = R.fields["gender"], "age" = R.fields["age"], "rank" = R.fields["rank"], "fingerprint" = R.fields["fingerprint"], "p_state" = R.fields["p_stat"], "m_state" = R.fields["m_stat"], "criminal_status" = S.fields["criminal"], "crimes" = crimes, "important_notes" = S.fields["notes"], "comments" = comments) + done = TRUE + break + if(done) + break + if("sec_record back") + selected_sec_record = null update_appearance(UPDATE_ICON) /mob/living/silicon/pai/ui_state(mob/user) diff --git a/tgui/packages/tgui/interfaces/PaiInterface.tsx b/tgui/packages/tgui/interfaces/PaiInterface.tsx index f580d65e6a96..7424d968c43b 100644 --- a/tgui/packages/tgui/interfaces/PaiInterface.tsx +++ b/tgui/packages/tgui/interfaces/PaiInterface.tsx @@ -1,7 +1,7 @@ import { toFixed } from 'common/math'; import { capitalize } from 'common/string'; import { useBackend, useLocalState } from '../backend'; -import { Box, Button, Section, Flex, Tabs, Stack, BlockQuote, Table, Dropdown, ProgressBar, NumberInput } from '../components'; +import { Box, Button, Section, Flex, Tabs, Stack, BlockQuote, Table, Dropdown, ProgressBar, NumberInput, Icon } from '../components'; import { Window } from '../layouts'; type Module = { @@ -42,13 +42,26 @@ type SecRecord = { p_state: string; m_state: string; criminal_status: string; - crimes: string[]; + crimes: Crime[]; important_notes: string; - comments: string[]; + comments: Comment[]; +} + +type Crime = { + crime_name: string; + crime_details: string; + author: string; + time_added: string; +} + +type Comment = { + comment_text: string; + author: string; + time: string; } type Data = { - modules: Data[]; + modules: string[]; modules_list: Module[]; modules_tabs: Module[]; laws_zeroth: string; @@ -70,11 +83,11 @@ type Data = { color: string; med_records: MedRecord[]; sec_records: SecRecord[]; - selected_med_record: MedRecord[]; - selected_sec_record: SecRecord[]; + selected_med_record: MedRecord; + selected_sec_record: SecRecord; } -export const AirlockJackTextSwitch = params => { +const AirlockJackTextSwitch = params => { switch (params) { case 0: return "Connection handshake"; @@ -101,12 +114,54 @@ export const MedRecordColour = (mental, physical) => { } }; +export const SecRecordColour = criminal_status => { + switch (criminal_status) { + case "Arrest": + return "#990000;"; + case "Discharged": + return "#5C4949;"; + case "None": + return "#740349;"; + case "Search": + return "#5C4949;"; + case "Parole": + return "#046713;"; + case "Incarcerated": + return "#181818;"; + case "Suspected": + return "#CD6500;"; + } +}; + +const SecRecordIcon = criminal_status => { + switch (criminal_status) { + case "Arrest": + return "fingerprint"; + case "Discharged": + return "dove"; + case "None": + return ""; + case "Search": + return "search"; + case "Parole": + return "unlink"; + case "Incarcerated": + return "dungeon"; + case "Suspected": + return "exclamation"; + } + return ""; +}; + +let custom_width; +custom_width = 650; + export const PaiInterface = (props, context) => { const { act, data } = useBackend(context); const { modules_tabs = [] } = data; const [selectedMainTab, setMainTab] = useLocalState(context, "selectedMainTab", 0); return ( - {/* Width matters for medical records, height matters for download more software */} + {/* Width matters for records, height matters for download more software */} @@ -141,8 +196,17 @@ const PaiBox = (props, context) => { const { hacking, hackprogress, cable, door } = data; const { code, frequency, minFrequency, maxFrequency, color } = data; const { med_records, sec_records } = data; - const [record_view, set_record_view] = useLocalState(context, "record_view", 0); - const { selected_med_record } = data; + const { selected_med_record, selected_sec_record } = data; + switch(modules_tabs[selectedMainTab].module_name) { // To actually make records readable without extending every other module unnecessarily + case "medical records": + custom_width = 960; + break; + case "security records": + custom_width = 850; + break; + default: + custom_width = 650; + } switch(modules_tabs[selectedMainTab].module_name) { case "directives": return ( @@ -437,6 +501,9 @@ const PaiBox = (props, context) => { ID: + + Fingerprints (F) | DNA (D): + Blood type: @@ -460,6 +527,10 @@ const PaiBox = (props, context) => { {MedRecord.id} + + F: {MedRecord.fingerprint} + D: {MedRecord.dna} + {MedRecord.blood_type} @@ -475,6 +546,166 @@ const PaiBox = (props, context) => {
); } + case "security records": + if(selected_sec_record) { + const { crimes } = data.selected_sec_record; + const { comments } = data.selected_sec_record; + return ( +
+ + + + Name: {selected_sec_record.name} + + + ID: {selected_sec_record.id} + + + Gender: {selected_sec_record.gender} + + + Age: {selected_sec_record.age} + + + Rank: {selected_sec_record.rank} + + + Fingerprint: {selected_sec_record.fingerprint} + + + Physical Status: {selected_sec_record.p_state} + + + Mental Status: {selected_sec_record.m_state} + +
+ + Criminal Status: + +
+ + + + Crime: + + + Details: + + + Author: + + + Time Added: + + + {crimes.map(crime => ( + + + {crime.crime_name} + + + {crime.crime_details} + + + {crime.author} + + + {crime.time_added} + + + ))} +
+
+ + + + Comment: + + + Author: + + + Time Added: + + + {comments.map(comment => ( + + + {comment.comment_text} + + + {comment.author} + + + {comment.time} + + + ))} +
+
+
+ ); + } else { + return ( +
+ + + + Name: + + + ID: + + + Rank: + + + Fingerprints: + + + Criminal Status: + + + {sec_records.map(SecRecord => ( + + + + + + {SecRecord.id} + + + {SecRecord.rank} + + + {SecRecord.fingerprint} + + + + {SecRecord.criminal_status} + + {SecRecordIcon(SecRecord.criminal_status) && ( + + + + )} + + + ))} +
+
+ ); + } case "host scan": return (
@@ -572,5 +803,5 @@ const PaiBox = (props, context) => { ); } } - return null; + return null; // Necessary to avoid "PaiBox cannot be used as a JSX Element. It's Return type 'Element | Undefined' is not a valid JSX component" runtiming }; From 78e11837958f2a88b85a4d36c000f8cb2ef36d5a Mon Sep 17 00:00:00 2001 From: Oblisk234 <61151679+Oblisk234@users.noreply.github.com> Date: Sun, 29 Dec 2024 19:02:02 +0000 Subject: [PATCH 11/14] Reorganises remote signaller --- .../packages/tgui/interfaces/PaiInterface.tsx | 129 ++++++++++-------- 1 file changed, 70 insertions(+), 59 deletions(-) diff --git a/tgui/packages/tgui/interfaces/PaiInterface.tsx b/tgui/packages/tgui/interfaces/PaiInterface.tsx index 7424d968c43b..ec27e03e1ee2 100644 --- a/tgui/packages/tgui/interfaces/PaiInterface.tsx +++ b/tgui/packages/tgui/interfaces/PaiInterface.tsx @@ -360,70 +360,81 @@ const PaiBox = (props, context) => { case "remote signaller": return (
- - - Frequency: - toFixed(value, 1)} - width="80px" - onDrag={(e, value) => act('signallerfreq', { - freq: value, - })} /> -
); case "medical records": From 03b0b6fb1f0b9dd8c749c835f17a704c2a6e2958 Mon Sep 17 00:00:00 2001 From: Oblisk234 <61151679+Oblisk234@users.noreply.github.com> Date: Sun, 29 Dec 2024 19:04:40 +0000 Subject: [PATCH 12/14] Autodoc comment support --- code/modules/mob/living/silicon/pai/pai.dm | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 11925453a0f2..d4300d9a084d 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -23,14 +23,14 @@ var/network = "ss13" var/obj/machinery/camera/current = null - // Used as currency to purchase different abilities + ///Used as currency to purchase different abilities var/ram = 100 var/list/software = list() - // The DNA string of our assigned user + ///The DNA string of our assigned user var/userDNA - // The card we inhabit + ///The card we inhabit var/obj/item/computer_hardware/paicard/card - //Are we hacking a door? + ///Are we hacking a door? var/hacking = FALSE var/speakStatement = "states" @@ -38,38 +38,38 @@ var/speakDoubleExclamation = "alarms" var/speakQuery = "queries" - // The cable we produce and use when door or camera jacking + ///The cable we produce and use when door or camera jacking var/obj/item/pai_cable/cable - // Name of the one who commands us + ///Name of the one who commands us var/master - // DNA string for owner verification + ///DNA string for owner verification var/master_dna // Various software-specific vars - // The airlock being hacked + ///The airlock being hacked var/obj/machinery/door/hackdoor - // Possible values: 0 - 100, >= 100 means the hack is complete and will be reset upon next check + ///Possible values: 0 - 100, >= 100 means the hack is complete and will be reset upon next check var/hackprogress = 0 - /// Remote signaler + ///Remote signaler var/obj/item/assembly/signaler/internal/signaler var/obj/item/instrument/piano_synth/internal_instrument - //pAI Newscaster + ///pAI Newscaster var/obj/machinery/newscaster - //pAI healthanalyzer + ///pAI healthanalyzer var/obj/item/healthanalyzer/hostscan - //Whether the pAI has bought the encryption slot module or not + ///Whether the pAI has bought the encryption slot module or not var/encryptmod = FALSE var/holoform = FALSE - //Can pAI use their holoprojector? + ///Can pAI use their holoprojector? var/canholo = TRUE - //Can pAI transmit radio messages? + ///Can pAI transmit radio messages? var/can_transmit = TRUE - //Can pAI receive radio messages? + ///Can pAI receive radio messages? var/can_receive = TRUE var/obj/item/card/id/access_card = new /obj/item/card/id var/chassis = "repairbot" From d6e9cf79c13a6b1c46978c6408a7df6becba862d Mon Sep 17 00:00:00 2001 From: Oblisk234 <61151679+Oblisk234@users.noreply.github.com> Date: Sun, 29 Dec 2024 20:41:57 +0000 Subject: [PATCH 13/14] Minor adjustments --- .../mob/living/silicon/pai/software.dm | 57 ------------------- .../packages/tgui/interfaces/PaiInterface.tsx | 6 +- 2 files changed, 2 insertions(+), 61 deletions(-) diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index a851462f4ef4..62d41b4d74a1 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -293,63 +293,6 @@ else to_chat(P, "[M] does not seem like [M.p_theyre()] going to provide a DNA sample willingly.") -//Leaving the medical & security records stuff commented out till they can be added back -// -//// Medical Records -///mob/living/silicon/pai/proc/softwareMedicalRecord() -// switch(subscreen) -// if(0) -// . += "

Medical Records


" -// if(GLOB.data_core.general) -// for(var/datum/data/record/R in sortRecord(GLOB.data_core.general)) -// . += "[R.fields["id"]]: [R.fields["name"]]
" -// if(1) -// . += "
Medical Record

" -// if(medicalActive1 in GLOB.data_core.general) -// . += "Name: [medicalActive1.fields["name"]] ID: [medicalActive1.fields["id"]]
\nGender: [medicalActive1.fields["gender"]]
\nAge: [medicalActive1.fields["age"]]
\nFingerprint: [medicalActive1.fields["fingerprint"]]
\nPhysical Status: [medicalActive1.fields["p_stat"]]
\nMental Status: [medicalActive1.fields["m_stat"]]
" -// else -// . += "
Requested medical record not found.

" -// if(medicalActive2 in GLOB.data_core.medical) -// . += "
\n
Medical Data

\nBlood Type:
[medicalActive2.fields["blood_type"]]
\nDNA: [medicalActive2.fields["b_dna"]]
\n
\nMinor Disabilities: [medicalActive2.fields["mi_dis"]]
\nDetails: [medicalActive2.fields["mi_dis_d"]]
\n
\nMajor Disabilities: [medicalActive2.fields["ma_dis"]]
\nDetails: [medicalActive2.fields["ma_dis_d"]]
\n
\nAllergies: [medicalActive2.fields["alg"]]
\nDetails: [medicalActive2.fields["alg_d"]]
\n
\nCurrent Diseases: [medicalActive2.fields["cdi"]] (per disease info placed in log/comment section)
\nDetails: [medicalActive2.fields["cdi_d"]]
\n
\nImportant Notes:
\n\t[medicalActive2.fields["notes"]]
\n
\n
Comments/Log

" -// else -// . += "
Requested medical record not found.

" -// . += "
\nBack
" -// return . -// -//// Security Records -///mob/living/silicon/pai/proc/softwareSecurityRecord() -// . = "" -// switch(subscreen) -// if(0) -// . += "

Security Records


" -// if(GLOB.data_core.general) -// for(var/datum/data/record/R in sortRecord(GLOB.data_core.general)) -// . += "[R.fields["id"]]: [R.fields["name"]]
" -// if(1) -// . += "

Security Record

" -// if(securityActive1 in GLOB.data_core.general) -// . += "Name:
[securityActive1.fields["name"]] ID: [securityActive1.fields["id"]]
\nGender: [securityActive1.fields["gender"]]
\nAge: [securityActive1.fields["age"]]
\nRank: [securityActive1.fields["rank"]]
\nFingerprint: [securityActive1.fields["fingerprint"]]
\nPhysical Status: [securityActive1.fields["p_stat"]]
\nMental Status: [securityActive1.fields["m_stat"]]
" -// else -// . += "
Requested security record not found,

" -// if(securityActive2 in GLOB.data_core.security) -// . += "
" -// . += "Security Data
" -// . += "Criminal Status: [securityActive2.fields["criminal"]]

" -// . += "Crimes:
" -// for(var/datum/data/crime/crime in securityActive2.fields["crimes"]) -// . += "\t[crime.crimeName]: [crime.crimeDetails]
" -// . += "
" -// . += "Important Notes:
" -// . += "\t[securityActive2.fields["notes"]]

" -// . += "
Comments/Log

" -// for(var/datum/data/comment/comment in securityActive2.fields["comments"]) -// . += "\t[comment.commentText] - [comment.author] [comment.time]
" -// else -// . += "
Requested security record not found,

" -// . += "
\nBack
" -// return . -// -// //// Camera Jack - Clearly not finished ///mob/living/silicon/pai/proc/softwareCamera() // var/dat = "

Camera Jack

" diff --git a/tgui/packages/tgui/interfaces/PaiInterface.tsx b/tgui/packages/tgui/interfaces/PaiInterface.tsx index ec27e03e1ee2..7ace05178b1f 100644 --- a/tgui/packages/tgui/interfaces/PaiInterface.tsx +++ b/tgui/packages/tgui/interfaces/PaiInterface.tsx @@ -379,10 +379,9 @@ const PaiBox = (props, context) => { onDrag={(e, value) => act('signallerfreq', { freq: value, })} /> - -