Files
VOREStation/code/modules/mob/living/silicon/pai/software_modules.dm
T
Guti 8a1a482c2b Removes Gender (#18628)
* Removes Gender

* Adds herm back
2025-10-14 18:34:35 -07:00

485 lines
15 KiB
Plaintext

/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(!ispAI(user))
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 = ui.user
if(!istype(P))
return TRUE
if(..())
return TRUE
if(action == "getdna")
var/mob/living/M = P.loc
var/count = 0
// Find the carrier
while(!isliving(M))
if(!M || !M.loc || count > 6)
//For a runtime where M ends up in nullspace (similar to bluespace but less colourful)
to_chat(src, span_infoplain("You are not being carried by anyone!"))
return 0
M = M.loc
count++
// Check the carrier
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(span_notice("[M] presses [M.p_their()] thumb against [P]."), 3, span_notice("[P] makes a sharp clicking sound as it extracts DNA material from [M]."), 2)
var/datum/dna/dna = M.dna
to_chat(P, span_infoplain(span_red("<h3>[M]'s UE string : [dna.unique_enzymes]</h3>")))
if(dna.unique_enzymes == P.master_dna)
to_chat(P, span_infoplain(span_bold("DNA is a match to stored Master DNA.")))
else
to_chat(P, span_infoplain(span_bold("DNA does not match stored Master DNA.")))
else
to_chat(P, span_infoplain("[M] does not seem like [M.p_theyre()] 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(GLOB.data_core)
GLOB.data_core.get_manifest_list()
data["manifest"] = GLOB.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(GLOB.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 = ui.user
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 (!( GLOB.data_core.general.Find(R) ))
P.medical_cannotfind = 1
else
P.medical_cannotfind = 0
for(var/datum/data/record/E in GLOB.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(GLOB.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 = ui.user
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 (!( GLOB.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 GLOB.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 = ui.user
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/pai_cable(T)
for(var/mob/M in viewers(T))
M.show_message(span_warning("A port on [P] opens to reveal [P.cable], which promptly falls to the floor."), 3,
span_warning("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 GLOB.player_list)
if(T.loc)
to_chat(AI, span_bolddanger("Network Alert: Brute-force encryption crack in progress in [T.loc]."))
else
to_chat(AI, span_bolddanger("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 = ..()
data["aircontents"] = get_gas_mixture_default_scan_data(get_turf(user))
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(LANGUAGE_MOUSE)
user.add_language(LANGUAGE_ANIMAL)
user.add_language(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(LANGUAGE_MOUSE)
user.remove_language(LANGUAGE_ANIMAL)
user.remove_language(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 = ui.user
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("[icon2html(R,O.client)] *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
/datum/pai_software/deathalarm
name = "Death Alarm"
ram_cost = 25
id = "death_alarm"
/datum/pai_software/deathalarm/toggle(mob/living/silicon/pai/user)
user.paiDA = !user.paiDA
/datum/pai_software/deathalarm/is_active(mob/living/silicon/pai/user)
return user.paiDA