/datum/pai_software // Name for the software. This is used as the button text when buying or opening/toggling the software var/name = "pAI software module" // RAM cost; pAIs start with 100 RAM, spending it on programs var/ram_cost = 0 // ID for the software. This must be unique var/id = "" // Whether this software is a toggle or not // Toggled software should override toggle() and is_active() // Non-toggled software should override on_ui_interact() and Topic() var/toggle = 1 // Whether pAIs should automatically receive this module at no cost var/default = 0 /datum/pai_software/proc/toggle(mob/living/silicon/pai/user) return /datum/pai_software/proc/is_active(mob/living/silicon/pai/user) return 0 /datum/pai_software/tgui_state(mob/user) return GLOB.tgui_always_state /datum/pai_software/tgui_status(mob/user) if(!istype(user, /mob/living/silicon/pai)) return STATUS_CLOSE return ..() /datum/pai_software/directives name = "Directives" ram_cost = 0 id = "directives" toggle = 0 default = 1 /datum/pai_software/directives/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "pAIDirectives", name, parent_ui) ui.open() /datum/pai_software/directives/tgui_data(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui_state/state) var/list/data = list() data["master"] = user.master data["dna"] = user.master_dna data["prime"] = user.pai_law0 data["supplemental"] = user.pai_laws return data /datum/pai_software/directives/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) var/mob/living/silicon/pai/P = usr if(!istype(P)) return TRUE if(..()) return TRUE if(action == "getdna") var/mob/living/M = P.loc var/count = 0 // Find the carrier while(!istype(M, /mob/living)) if(!M || !M.loc || count > 6) //For a runtime where M ends up in nullspace (similar to bluespace but less colourful) to_chat(src, "You are not being carried by anyone!") return 0 M = M.loc count++ // Check the carrier var/datum/gender/TM = gender_datums[M.get_visible_gender()] var/answer = tgui_alert(M, "[P] is requesting a DNA sample from you. Will you allow it to confirm your identity?", "[P] Check DNA", list("Yes", "No")) if(answer == "Yes") var/turf/T = get_turf(P.loc) for (var/mob/v in viewers(T)) v.show_message("[M] presses [TM.his] thumb against [P].", 3, "[P] makes a sharp clicking sound as it extracts DNA material from [M].", 2) var/datum/dna/dna = M.dna to_chat(P, "

[M]'s UE string : [dna.unique_enzymes]

") if(dna.unique_enzymes == P.master_dna) to_chat(P, "DNA is a match to stored Master DNA.") else to_chat(P, "DNA does not match stored Master DNA.") else to_chat(P, "[M] does not seem like [TM.he] is going to provide a DNA sample willingly.") return TRUE /datum/pai_software/radio_config name = "Radio Configuration" ram_cost = 0 id = "radio" toggle = 0 default = 1 /datum/pai_software/radio_config/tgui_interact(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui/parent_ui) return user.radio.tgui_interact(user, parent_ui = parent_ui) /datum/pai_software/crew_manifest name = "Crew Manifest" ram_cost = 0 id = "manifest" toggle = 0 default = 1 //Comes with the communicator already, also why not /datum/pai_software/crew_manifest/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "CrewManifest", name, parent_ui) ui.open() /datum/pai_software/crew_manifest/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) var/list/data = ..() if(data_core) data_core.get_manifest_list() data["manifest"] = PDA_Manifest return data /datum/pai_software/messenger name = "Digital Messenger" ram_cost = 0 id = "messenger" toggle = 0 default = 1 //Can already be accessed through verbs, and also why not /datum/pai_software/messenger/tgui_interact(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui/parent_ui) return user.pda.tgui_interact(user, parent_ui = parent_ui) /datum/pai_software/med_records name = "Medical Records" ram_cost = 15 id = "med_records" toggle = 0 /datum/pai_software/med_records/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "pAIMedrecords", name, parent_ui) ui.open() /datum/pai_software/med_records/tgui_data(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui_state/state) var/list/data = ..() var/list/records = list() for(var/datum/data/record/general in sortRecord(data_core.general)) var/list/record = list() record["name"] = general.fields["name"] record["ref"] = "\ref[general]" records.Add(list(record)) data["records"] = records var/datum/data/record/G = user.medicalActive1 var/datum/data/record/M = user.medicalActive2 data["general"] = G ? G.fields : null data["medical"] = M ? M.fields : null data["could_not_find"] = user.medical_cannotfind return data /datum/pai_software/med_records/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) . = ..() var/mob/living/silicon/pai/P = usr if(!istype(P)) return if(action == "select") var/datum/data/record/record = locate(params["select"]) if(record) var/datum/data/record/R = record var/datum/data/record/M = null if (!( data_core.general.Find(R) )) P.medical_cannotfind = 1 else P.medical_cannotfind = 0 for(var/datum/data/record/E in data_core.medical) if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) M = E P.medicalActive1 = R P.medicalActive2 = M else P.medical_cannotfind = 1 return 1 /datum/pai_software/sec_records name = "Security Records" ram_cost = 15 id = "sec_records" toggle = 0 /datum/pai_software/sec_records/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "pAISecrecords", name, parent_ui) ui.open() /datum/pai_software/sec_records/tgui_data(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui_state/state) var/list/data = ..() var/list/records = list() for(var/datum/data/record/general in sortRecord(data_core.general)) var/list/record = list() record["name"] = general.fields["name"] record["ref"] = "\ref[general]" records.Add(list(record)) data["records"] = records var/datum/data/record/G = user.securityActive1 var/datum/data/record/S = user.securityActive2 data["general"] = G ? G.fields : null data["security"] = S ? S.fields : null data["could_not_find"] = user.security_cannotfind return data /datum/pai_software/sec_records/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) . = ..() var/mob/living/silicon/pai/P = usr if(!istype(P)) return if(action == "select") var/datum/data/record/record = locate(params["select"]) if(record) var/datum/data/record/R = record var/datum/data/record/S = null if (!( data_core.general.Find(R) )) P.securityActive1 = null P.securityActive2 = null P.security_cannotfind = 1 else P.security_cannotfind = 0 for(var/datum/data/record/E in data_core.security) if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) S = E P.securityActive1 = R P.securityActive2 = S else P.securityActive1 = null P.securityActive2 = null P.security_cannotfind = 1 return TRUE /datum/pai_software/door_jack name = "Door Jack" ram_cost = 30 id = "door_jack" toggle = 0 /datum/pai_software/door_jack/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "pAIDoorjack", "Door Jack", parent_ui) ui.open() /datum/pai_software/door_jack/tgui_data(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui_state/state) var/list/data = ..() data["cable"] = user.cable != null data["machine"] = user.cable && (user.cable.machine != null) data["inprogress"] = user.hackdoor != null data["progress_a"] = round(user.hackprogress / 10) data["progress_b"] = user.hackprogress % 10 data["aborted"] = user.hack_aborted return data /datum/pai_software/door_jack/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) var/mob/living/silicon/pai/P = usr if(!istype(P) || ..()) return TRUE switch(action) if("jack") if(P.cable && P.cable.machine) P.hackdoor = P.cable.machine P.hackloop() return 1 if("cancel") P.hackdoor = null return 1 if("cable") var/turf/T = get_turf(P) P.hack_aborted = 0 P.cable = new /obj/item/weapon/pai_cable(T) for(var/mob/M in viewers(T)) M.show_message("A port on [P] opens to reveal [P.cable], which promptly falls to the floor.", 3, "You hear the soft click of something light and hard falling to the ground.", 2) return 1 /mob/living/silicon/pai/proc/hackloop() var/turf/T = get_turf(src) for(var/mob/living/silicon/ai/AI in player_list) if(T.loc) to_chat(AI, "Network Alert: Brute-force encryption crack in progress in [T.loc].") else to_chat(AI, "Network Alert: Brute-force encryption crack in progress. Unable to pinpoint location.") var/obj/machinery/door/D = cable.machine if(!istype(D)) hack_aborted = 1 hackprogress = 0 cable.machine = null hackdoor = null return while(hackprogress < 1000) if(cable && cable.machine == D && cable.machine == hackdoor && get_dist(src, hackdoor) <= 1) hackprogress = min(hackprogress+rand(1, 20), 1000) else hack_aborted = 1 hackprogress = 0 hackdoor = null return if(hackprogress >= 1000) hackprogress = 0 D.open() cable.machine = null return sleep(10) // Update every second /datum/pai_software/atmosphere_sensor name = "Atmosphere Sensor" ram_cost = 5 id = "atmos_sense" toggle = 0 /datum/pai_software/atmosphere_sensor/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "pAIAtmos", name, parent_ui) ui.open() /datum/pai_software/atmosphere_sensor/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) var/list/data = ..() var/list/results = list() var/turf/T = get_turf(user) if(!isnull(T)) var/datum/gas_mixture/environment = T.return_air() var/pressure = environment.return_pressure() var/total_moles = environment.total_moles if (total_moles) var/o2_level = environment.gas["oxygen"]/total_moles var/n2_level = environment.gas["nitrogen"]/total_moles var/co2_level = environment.gas["carbon_dioxide"]/total_moles var/phoron_level = environment.gas["phoron"]/total_moles var/unknown_level = 1-(o2_level+n2_level+co2_level+phoron_level) // entry is what the element is describing // Type identifies which unit or other special characters to use // Val is the information reported // Bad_high/_low are the values outside of which the entry reports as dangerous // Poor_high/_low are the values outside of which the entry reports as unideal // Values were extracted from the template itself results = list( list("entry" = "Pressure", "units" = "kPa", "val" = "[round(pressure,0.1)]", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80), list("entry" = "Temperature", "units" = "°C", "val" = "[round(environment.temperature-T0C,0.1)]", "bad_high" = 35, "poor_high" = 25, "poor_low" = 15, "bad_low" = 5), list("entry" = "Oxygen", "units" = "kPa", "val" = "[round(o2_level*100,0.1)]", "bad_high" = 140, "poor_high" = 135, "poor_low" = 19, "bad_low" = 17), list("entry" = "Nitrogen", "units" = "kPa", "val" = "[round(n2_level*100,0.1)]", "bad_high" = 105, "poor_high" = 85, "poor_low" = 50, "bad_low" = 40), list("entry" = "Carbon Dioxide", "units" = "kPa", "val" = "[round(co2_level*100,0.1)]", "bad_high" = 10, "poor_high" = 5, "poor_low" = 0, "bad_low" = 0), list("entry" = "Phoron", "units" = "kPa", "val" = "[round(phoron_level*100,0.01)]", "bad_high" = 0.5, "poor_high" = 0, "poor_low" = 0, "bad_low" = 0), list("entry" = "Other", "units" = "kPa", "val" = "[round(unknown_level, 0.01)]", "bad_high" = 1, "poor_high" = 0.5, "poor_low" = 0, "bad_low" = 0) ) if(isnull(results)) results = list(list("entry" = "pressure", "units" = "kPa", "val" = "0", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80)) data["aircontents"] = results return data /datum/pai_software/pai_hud name = "AR HUD" ram_cost = 30 id = "ar_hud" /datum/pai_software/pai_hud/toggle(mob/living/silicon/pai/user) user.paiHUD = !user.paiHUD user.plane_holder.set_vis(VIS_CH_ID,user.paiHUD) user.plane_holder.set_vis(VIS_CH_WANTED,user.paiHUD) user.plane_holder.set_vis(VIS_CH_IMPTRACK,user.paiHUD) user.plane_holder.set_vis(VIS_CH_IMPCHEM,user.paiHUD) user.plane_holder.set_vis(VIS_CH_STATUS_R,user.paiHUD) user.plane_holder.set_vis(VIS_CH_HEALTH_VR,user.paiHUD) user.plane_holder.set_vis(VIS_CH_BACKUP,user.paiHUD) //backup stuff from silicon_vr is here now user.plane_holder.set_vis(VIS_AUGMENTED,user.paiHUD) /datum/pai_software/pai_hud/is_active(mob/living/silicon/pai/user) return user.paiHUD /datum/pai_software/translator name = "Universal Translator" ram_cost = 35 id = "translator" /datum/pai_software/translator/toggle(mob/living/silicon/pai/user) // Sol Common, Tradeband, Terminus and Gutter are added with New() and are therefore the current default, always active languages user.translator_on = !user.translator_on if(user.translator_on) user.add_language(LANGUAGE_UNATHI) user.add_language(LANGUAGE_SIIK) user.add_language(LANGUAGE_AKHANI) user.add_language(LANGUAGE_SKRELLIAN) user.add_language(LANGUAGE_ZADDAT) user.add_language(LANGUAGE_SCHECHI) user.add_language(LANGUAGE_DRUDAKAR) user.add_language(LANGUAGE_BIRDSONG) user.add_language(LANGUAGE_SAGARU) user.add_language(LANGUAGE_CANILUNZT) user.add_language(LANGUAGE_ECUREUILIAN) user.add_language(LANGUAGE_DAEMON) user.add_language(LANGUAGE_ENOCHIAN) user.add_language(LANGUAGE_VESPINAE) user.add_language(LANGUAGE_SPACER) user.add_language(LANGUAGE_TAVAN) user.add_language(LANGUAGE_ECHOSONG) user.add_language(LANGUAGE_ROOTLOCAL) user.add_language(LANGUAGE_VOX) user.add_language(LANGUAGE_MINBUS) user.add_language(LANGUAGE_ALAI) user.add_language(LANGUAGE_PROMETHEAN) user.add_language(LANGUAGE_GIBBERISH) user.add_language("Animal") user.add_language("Teppi") else user.remove_language(LANGUAGE_UNATHI) user.remove_language(LANGUAGE_SIIK) user.remove_language(LANGUAGE_AKHANI) user.remove_language(LANGUAGE_SKRELLIAN) user.remove_language(LANGUAGE_ZADDAT) user.remove_language(LANGUAGE_SCHECHI) user.remove_language(LANGUAGE_DRUDAKAR) user.remove_language(LANGUAGE_BIRDSONG) user.remove_language(LANGUAGE_SAGARU) user.remove_language(LANGUAGE_CANILUNZT) user.remove_language(LANGUAGE_ECUREUILIAN) user.remove_language(LANGUAGE_DAEMON) user.remove_language(LANGUAGE_ENOCHIAN) user.remove_language(LANGUAGE_VESPINAE) user.remove_language(LANGUAGE_SPACER) user.remove_language(LANGUAGE_TAVAN) user.remove_language(LANGUAGE_ECHOSONG) user.remove_language(LANGUAGE_ROOTLOCAL) user.remove_language(LANGUAGE_VOX) user.remove_language(LANGUAGE_MINBUS) user.remove_language(LANGUAGE_ALAI) user.remove_language(LANGUAGE_PROMETHEAN) user.remove_language(LANGUAGE_GIBBERISH) user.remove_language("Animal") user.remove_language("Teppi") /datum/pai_software/translator/is_active(mob/living/silicon/pai/user) return user.translator_on /datum/pai_software/signaller name = "Remote Signaler" ram_cost = 5 id = "signaller" toggle = 0 /datum/pai_software/signaller/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "Signaler", "Signaler", parent_ui) ui.open() /datum/pai_software/signaller/tgui_data(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui_state/state) var/list/data = ..() var/obj/item/radio/integrated/signal/R = user.sradio data["frequency"] = R.frequency data["minFrequency"] = RADIO_LOW_FREQ data["maxFrequency"] = RADIO_HIGH_FREQ data["code"] = R.code return data /datum/pai_software/signaller/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) if(..()) return TRUE var/mob/living/silicon/pai/user = usr if(istype(user)) var/obj/item/radio/integrated/signal/R = user.sradio switch(action) if("signal") spawn(0) R.send_signal("ACTIVATE") for(var/mob/O in hearers(1, R.loc)) O.show_message("\icon[R][bicon(R)] *beep* *beep*", 3, "*beep* *beep*", 2) if("freq") var/frequency = unformat_frequency(params["freq"]) frequency = sanitize_frequency(frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ) R.set_frequency(frequency) . = TRUE if("code") R.code = clamp(round(text2num(params["code"])), 1, 100) . = TRUE if("reset") if(params["reset"] == "freq") R.set_frequency(initial(R.frequency)) else R.code = initial(R.code) . = TRUE