diff --git a/code/controllers/subsystem/pai.dm b/code/controllers/subsystem/pai.dm index 906d714b03e3..c70749e719dd 100644 --- a/code/controllers/subsystem/pai.dm +++ b/code/controllers/subsystem/pai.dm @@ -9,27 +9,6 @@ SUBSYSTEM_DEF(pai) var/list/paicard_list = list() /datum/controller/subsystem/pai/Topic(href, href_list[]) - if(href_list["download"]) - var/datum/paiCandidate/candidate = locate(href_list["candidate"]) in candidates - var/obj/item/computer_hardware/paicard/card = locate(href_list["device"]) in paicard_list - if(card.pai) - return - if(istype(card, /obj/item/computer_hardware/paicard) && istype(candidate, /datum/paiCandidate)) - if(check_ready(candidate) != candidate) - return FALSE - var/mob/living/silicon/pai/pai = new(card) - if(!candidate.name) - pai.name = pick(GLOB.ninja_names) - else - pai.name = candidate.name - pai.real_name = pai.name - pai.key = candidate.key - - card.setPersonality(pai) - - candidates -= candidate - usr << browse(null, "window=findPai") - if(href_list["new"]) var/datum/paiCandidate/candidate = locate(href_list["candidate"]) in candidates var/option = href_list["option"] diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 04711dc951be..10b0409e546d 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -244,6 +244,9 @@ return TRUE if(unrestricted_side(M)) return TRUE + if(ispAI(M)) + var/mob/living/silicon/pai/P = M + return check_access(P.access_card) return ..() /// Returns the opposite of '/allowed', but makes exceptions for things like IsAdminGhost(). diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 9b220cb114a7..d4300d9a084d 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -7,7 +7,7 @@ hud_type = /datum/hud/pai pass_flags = PASSTABLE | PASSMOB mob_size = MOB_SIZE_TINY - desc = "A generic pAI mobile hard-light holographics emitter. It seems to be deactivated." + desc = "A generic pAI mobile hard-light holographics emitter. It seems to be activated." weather_immunities = WEATHER_STORM light_on = FALSE light_flags = LIGHT_ATTACHED @@ -23,53 +23,55 @@ var/network = "ss13" var/obj/machinery/camera/current = null - var/ram = 100 // Used as currency to purchase different abilities + ///Used as currency to purchase different abilities + var/ram = 100 var/list/software = list() - var/userDNA // The DNA string of our assigned user - var/obj/item/computer_hardware/paicard/card // The card we inhabit - var/hacking = FALSE //Are we hacking a door? + ///The DNA string of our assigned user + var/userDNA + ///The card we inhabit + var/obj/item/computer_hardware/paicard/card + ///Are we hacking a door? + var/hacking = FALSE var/speakStatement = "states" var/speakExclamation = "declares" var/speakDoubleExclamation = "alarms" var/speakQuery = "queries" - var/obj/item/pai_cable/cable // 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 - var/master // Name of the one who commands us - var/master_dna // DNA string for owner verification + ///Name of the one who commands us + var/master + ///DNA string for owner verification + var/master_dna // 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 + ///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 + var/hackprogress = 0 - 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 - - /// Remote signaler + ///Remote signaler var/obj/item/assembly/signaler/internal/signaler var/obj/item/instrument/piano_synth/internal_instrument - var/obj/machinery/newscaster //pAI Newscaster - var/obj/item/healthanalyzer/hostscan //pAI healthanalyzer + ///pAI Newscaster + var/obj/machinery/newscaster + ///pAI healthanalyzer + var/obj/item/healthanalyzer/hostscan + ///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/obj/item/card/id/access_card = new /obj/item/card/id var/chassis = "repairbot" var/list/possible_chassis = list("cat" = TRUE, "mouse" = TRUE, "monkey" = TRUE, "corgi" = FALSE, "fox" = FALSE, "repairbot" = TRUE, "rabbit" = TRUE, "frog" = TRUE) //assoc value is whether it can be picked up. @@ -81,7 +83,8 @@ var/emittersemicd = FALSE var/overload_ventcrawl = 0 - var/overload_bulletblock = 0 //Why is this a good idea? + //Why is this a good idea? + var/overload_bulletblock = 0 var/overload_maxhealth = 0 var/silent = FALSE var/brightness_power = 5 @@ -127,7 +130,6 @@ . = ..() - create_modularInterface() emittersemicd = TRUE addtimer(CALLBACK(src, PROC_REF(emittercool)), 600) @@ -153,7 +155,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 @@ -282,7 +283,11 @@ /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/module in software) + . += "[module]" /mob/living/silicon/pai/Life(seconds_per_tick = SSMOBS_DT, times_fired) if(stat == DEAD) @@ -307,12 +312,31 @@ 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) - pai.radio.attackby(W, user, params) - else if(istype(W, /obj/item/encryptionkey)) + if(W.tool_behaviour == TOOL_SCREWDRIVER||istype(W, /obj/item/encryptionkey)) + if(pai.encryptmod == TRUE) 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) + access_card.access += ID.access + to_chat(user, span_info("Copied access from [ID]!")) + to_chat(src, span_notice("Data transfer complete: New access encryption keys stored in memory.")) + +/mob/living/silicon/pai/Bump(atom/A) //Copied from bot.dm + . = ..() + if((istype(A, /obj/machinery/door/airlock) || istype(A, /obj/machinery/door/window)) && (!isnull(access_card))) + var/obj/machinery/door/D = A + if(D.check_access(access_card)) + D.open() diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index e8e0db8d1209..62d41b4d74a1 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -9,20 +9,21 @@ //T-Ray //radiation eyes //chem goggs - //mesons list("module_name" = "crew manifest", "tab"=FALSE, "cost" = 5), list("module_name" = "digital messenger", "tab"=FALSE, "cost" = 5), 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, //"heartbeat sensor" = 10, //"projection array" = 15, list("module_name" = "medical HUD", "tab"=FALSE, "cost" = 20), + list("module_name" = "meson HUD", "tab"=FALSE, "cost" = 20), + list("module_name" = "nightvision HUD", "tab"=FALSE, "cost" = 20), list("module_name" = "security HUD", "tab"=FALSE, "cost" = 20), list("module_name" = "loudness booster", "tab"=TRUE, "title"="Sound Synthesizer", "cost" = 20), list("module_name" = "newscaster", "tab"=FALSE, "cost" = 20), @@ -41,6 +42,11 @@ /mob/living/silicon/pai/var/cable_status = "Retracted" +/mob/living/silicon/pai/var/list/med_record = list() +/mob/living/silicon/pai/var/list/sec_record = list() +/mob/living/silicon/pai/var/selected_med_record +/mob/living/silicon/pai/var/selected_sec_record + /mob/living/silicon/pai/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) @@ -58,26 +64,46 @@ data["master"] = master data["masterdna"] = master_dna data["ram"] = ram - if(!isnull(environment)) - data["pressure"] = round(pressure,0.1) - data["gases"] = gases - data["temperature"] = round(environment.return_temperature()-T0C) - else - data["pressure"] = pressure - data["gases"] = gases - data["temperature"] = null + data["pressure"] = !isnull(environment) ? round(pressure,0.1) : pressure + data["gases"] = gases + data["temperature"] = !isnull(environment) ? round(environment.return_temperature()-T0C) : null data["hacking"] = hacking data["hackprogress"] = hackprogress data["cable"] = cable_status - if(isnull(cable)) - data["door"] = null - else - data["door"] = cable.machine + data["door"] = isnull(cable) ? null : cable.machine data["code"] = signaler.code data["frequency"] = signaler.frequency data["minFrequency"] = MIN_FREE_FREQ 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["id"] == M.fields["id"]) + 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_stat"], "m_state" = R.fields["m_stat"], "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) + break + 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["id"] == S.fields["id"]) + 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) + 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 + data["sec_records"] = sec_record + data["selected_med_record"] = selected_med_record + data["selected_sec_record"] = selected_sec_record return data /mob/living/silicon/pai/ui_act(action, params) @@ -89,7 +115,6 @@ CheckDNA(get(card, /mob/living/carbon/human), src) //you should only be able to check when directly in hand, muh immersions? else to_chat(src, "You are not being carried by anyone!") - return 0 // FALSE ? If you return here you won't call paiinterface() below if("update_image") card.setEmotion(params["updated_image"]) if("buy") @@ -99,9 +124,15 @@ return software.Add(params["name"]) ram -= params["cost"] + if(params["name"] == "digital messenger") + create_modularInterface() if(params["name"] == "medical HUD") var/datum/atom_hud/med = GLOB.huds[med_hud] med.show_to(src) + if(params["name"] == "meson HUD") + sight |= SEE_TURFS + if(params["name"] == "nightvision HUD") + lighting_cutoff = LIGHTING_CUTOFF_HIGH if(params["name"] == "security HUD") var/datum/atom_hud/sec = GLOB.huds[sec_hud] sec.show_to(src) @@ -178,6 +209,8 @@ internal_instrument = new(src) internal_instrument.interact(src) if("cable") + if(cable_status == "Extended") + return var/turf/T = get_turf(loc) cable = new /obj/item/pai_cable(T) if(get(card, /mob/living/carbon/human)) @@ -198,6 +231,42 @@ hackdoor = null cable = null cable_status = "Retracted" + if("med_record") + if(!GLOB.data_core.general||!GLOB.data_core.medical) + return + for(var/datum/data/record/M in sortRecord(GLOB.data_core.medical)) + var/done = FALSE + for(var/datum/data/record/R in sortRecord(GLOB.data_core.general)) + if(M.fields["id"] == params["record"]) + selected_med_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_stat"], "m_state" = R.fields["m_stat"], "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"]) + done = TRUE + break + if(done) + 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) @@ -224,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) -// . += "
Requested medical record not found.
Requested medical record not found.
Requested security record not found,
Requested security record not found,