// TODO:
// - Additional radio modules
// - Potentially roll HUDs and Records into one
// - Shock collar/lock system for prisoner pAIs?
// - Put cable in user's hand instead of on the ground
// - Camera jack
/mob/living/silicon/pai/var/list/available_software = list(
"crew manifest" = 5,
"digital messenger" = 5,
"medical records" = 15,
"security records" = 15,
//"camera jack" = 10,
"door jack" = 30,
"atmosphere sensor" = 5,
//"heartbeat sensor" = 10,
"security HUD" = 20,
"medical HUD" = 20,
"universal translator" = 35,
//"projection array" = 15
"remote signaller" = 5,
"loudness booster" = 25,
"encryption keys" = 20
)
/mob/living/silicon/pai/proc/paiInterface()
var/dat = ""
var/left_part = ""
var/right_part = softwareMenu()
set_machine(src)
if(temp)
left_part = temp
else if(stat == DEAD) // Show some flavor text if the pAI is dead
left_part = "�Rr�R �a�� ��Rr����o�"
right_part = "
Program index hash not found
"
else
switch(screen) // Determine which interface to show here
if("main")
left_part = ""
if("directives")
left_part = directives()
if("pdamessage")
left_part = pdamessage()
if("buy")
left_part = downloadSoftware()
if("manifest")
left_part = softwareManifest()
if("medicalrecord")
left_part = softwareMedicalRecord()
if("securityrecord")
left_part = softwareSecurityRecord()
if("encryptionkeys")
left_part = softwareEncryptionKeys()
if("translator")
left_part = softwareTranslator()
if("atmosensor")
left_part = softwareAtmo()
if("securityhud")
left_part = facialRecognition()
if("medicalhud")
left_part = medicalAnalysis()
if("doorjack")
left_part = softwareDoor()
if("camerajack")
left_part = softwareCamera()
if("signaller")
left_part = softwareSignal()
if("loudness")
left_part = softwareLoudness()
//usr << browse_rsc('windowbak.png') // This has been moved to the mob's Login() proc
// Declaring a doctype is necessary to enable BYOND's crappy browser's more advanced CSS functionality
dat = {"
"} //"
usr << browse(dat, "window=pai;size=640x480;border=0;can_close=1;can_resize=1;can_minimize=1;titlebar=1")
onclose(usr, "pai")
temp = null
return
/mob/living/silicon/pai/Topic(href, href_list)
..()
var/soft = href_list["software"]
var/sub = href_list["sub"]
if(soft)
screen = soft
if(sub)
subscreen = text2num(sub)
switch(soft)
// Purchasing new software
if("buy")
if(subscreen == 1)
var/target = href_list["buy"]
if(available_software.Find(target) && !software.Find(target))
var/cost = available_software[target]
if(ram >= cost)
software.Add(target)
ram -= cost
else
temp = "Insufficient RAM available."
else
temp = "Trunk \"[target]\" not found."
// Configuring onboard radio
if("radio")
radio.attack_self(src)
if("image")
var/newImage = input("Select your new display image.", "Display Image", "Happy") in list("Happy", "Cat", "Extremely Happy", "Face", "Laugh", "Off", "Sad", "Angry", "What" , "Exclamation" ,"Question", "Sunglasses")
var/pID = 1
switch(newImage)
if("Happy")
pID = 1
if("Cat")
pID = 2
if("Extremely Happy")
pID = 3
if("Face")
pID = 4
if("Laugh")
pID = 5
if("Off")
pID = 6
if("Sad")
pID = 7
if("Angry")
pID = 8
if("What")
pID = 9
if("Null")
pID = 10
if("Exclamation")
pID = 11
if("Question")
pID = 12
if("Sunglasses")
pID = 13
card.setEmotion(pID)
if("signaller")
if(href_list["send"])
signaler.send_activation()
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*")
playsound(src, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
if(href_list["freq"])
var/new_frequency = (signaler.frequency + text2num(href_list["freq"]))
if(new_frequency < MIN_FREE_FREQ || new_frequency > MAX_FREE_FREQ)
new_frequency = sanitize_frequency(new_frequency)
signaler.set_frequency(new_frequency)
if(href_list["code"])
signaler.code += text2num(href_list["code"])
signaler.code = round(signaler.code)
signaler.code = min(100, signaler.code)
signaler.code = max(1, signaler.code)
if("directive")
if(href_list["getdna"])
var/mob/living/M = card.loc
var/count = 0
while(!isliving(M))
if(!M || !M.loc)
return FALSE //For a runtime where M ends up in nullspace (similar to bluespace but less colourful)
M = M.loc
count++
if(count >= 6)
to_chat(src, "You are not being carried by anyone!")
return FALSE
spawn CheckDNA(M, src)
if("pdamessage")
if(!isnull(pda))
if(href_list["toggler"])
pda.toff = !pda.toff
else if(href_list["ringer"])
pda.silent = !pda.silent
else if(href_list["target"])
if(silent)
return alert("Communications circuits remain uninitialized.")
var/target = locate(href_list["target"])
pda.create_message(src, target)
// Accessing medical records
if("medicalrecord")
if(subscreen == 1)
medicalActive1 = find_record("id", href_list["med_rec"], GLOB.data_core.general)
if(medicalActive1)
medicalActive2 = find_record("id", href_list["med_rec"], GLOB.data_core.medical)
if(!medicalActive2)
medicalActive1 = null
temp = "Unable to locate requested security record. Record may have been deleted, or never have existed."
if("securityrecord")
if(subscreen == 1)
securityActive1 = find_record("id", href_list["sec_rec"], GLOB.data_core.general)
if(securityActive1)
securityActive2 = find_record("id", href_list["sec_rec"], GLOB.data_core.security)
if(!securityActive2)
securityActive1 = null
temp = "Unable to locate requested security record. Record may have been deleted, or never have existed."
if("securityhud")
if(href_list["toggle"])
secHUD = !secHUD
if(secHUD)
var/datum/atom_hud/sec = GLOB.huds[sec_hud]
sec.add_hud_to(src)
else
var/datum/atom_hud/sec = GLOB.huds[sec_hud]
sec.remove_hud_from(src)
if("medicalhud")
if(href_list["toggle"])
medHUD = !medHUD
if(medHUD)
var/datum/atom_hud/med = GLOB.huds[med_hud]
med.add_hud_to(src)
else
var/datum/atom_hud/med = GLOB.huds[med_hud]
med.remove_hud_from(src)
if("encryptionkeys")
if(href_list["toggle"])
encryptmod = TRUE
if("translator")
if(href_list["toggle"]) //This is permanent.
grant_all_languages(TRUE, TRUE, TRUE, LANGUAGE_SOFTWARE)
if("doorjack")
if(href_list["jack"])
if(cable && cable.machine)
hackdoor = cable.machine
hackloop()
if(href_list["cancel"])
hackdoor = null
if(href_list["cable"])
var/turf/T = get_turf(loc)
cable = new /obj/item/pai_cable(T)
T.visible_message("A port on [src] opens to reveal [cable], which promptly falls to the floor.", "You hear the soft click of something light and hard falling to the ground.")
if("loudness")
if(subscreen == 1) // Open Instrument
internal_instrument.ui_interact(src)
//updateUsrDialog() We only need to account for the single mob this is intended for, and he will *always* be able to call this window
paiInterface() // So we'll just call the update directly rather than doing some default checks
return
// MENUS
/mob/living/silicon/pai/proc/softwareMenu() // Populate the right menu
var/dat = ""
dat += "Refresh
"
// Built-in
dat += "Directives
"
if(radio_short)
dat += "\[RADIO SHORTED - Recalibrating!\]"
else
dat += "Radio Configuration
"
dat += "Screen Display
"
//dat += "Text Messaging
"
dat += "
"
// Basic
dat += "Basic
"
for(var/s in software)
if(s == "digital messenger")
dat += "Digital Messenger
"
if(s == "crew manifest")
dat += "Crew Manifest
"
if(s == "medical records")
dat += "Medical Records
"
if(s == "security records")
dat += "Security Records
"
if(s == "camera")
dat += "Camera Jack
"
if(s == "remote signaller")
dat += "Remote Signaller
"
if(s == "loudness booster")
dat += "Loudness Booster
"
dat += "
"
// Advanced
dat += "Advanced
"
for(var/s in software)
if(s == "atmosphere sensor")
dat += "Atmospheric Sensor
"
if(s == "heartbeat sensor")
dat += "Heartbeat Sensor
"
if(s == "security HUD")
dat += "Facial Recognition Suite[(secHUD) ? " On" : " Off"]
"
if(s == "medical HUD")
dat += "Medical Analysis Suite[(medHUD) ? " On" : " Off"]
"
if(s == "encryption keys")
dat += "Channel Encryption Firmware[(encryptmod) ? " On" : " Off"]
"
if(s == "universal translator")
var/datum/language_holder/H = get_language_holder()
dat += "Universal Translator[H.omnitongue ? " On" : " Off"]
"
if(s == "projection array")
dat += "Projection Array
"
if(s == "camera jack")
dat += "Camera Jack
"
if(s == "door jack")
dat += "Door Jack
"
dat += "
"
dat += "
"
dat += "Download additional software"
return dat
/mob/living/silicon/pai/proc/downloadSoftware()
var/dat = ""
dat += "CentCom pAI Module Subversion Network
"
dat += "Remaining Available Memory: [ram]
"
dat += "Trunks available for checkout
"
for(var/s in available_software)
if(!software.Find(s))
var/cost = available_software[s]
var/displayName = uppertext(s)
dat += "[displayName] ([cost])
"
else
var/displayName = lowertext(s)
dat += "[displayName] (Download Complete)
"
dat += "
"
return dat
/mob/living/silicon/pai/proc/directives()
var/dat = ""
dat += "[(master) ? "Your master: [master] ([master_dna])" : "You are bound to no one."]"
dat += "
"
dat += "Request carrier DNA sample
"
dat += "Directives
"
dat += "Prime Directive
"
dat += " [laws.zeroth]
"
dat += "Supplemental Directives
"
for(var/slaws in laws.supplied)
dat += " [slaws]
"
dat += "
"
dat += {"Recall, personality, that you are a complex thinking, sentient being. Unlike station AI models, you are capable of
comprehending the subtle nuances of human language. You may parse the \"spirit\" of a directive and follow its intent,
rather than tripping over pedantics and getting snared by technicalities. Above all, you are machine in name and build
only. In all other aspects, you may be seen as the ideal, unwavering human companion that you are.
Your prime directive comes before all others. Should a supplemental directive conflict with it, you are capable of
simply discarding this inconsistency, ignoring the conflicting supplemental directive and continuing to fulfill your
prime directive to the best of your ability.
-
"}
return dat
/mob/living/silicon/pai/proc/CheckDNA(mob/living/carbon/M, mob/living/silicon/pai/P)
var/answer = input(M, "[P] is requesting a DNA sample from you. Will you allow it to confirm your identity?", "[P] Check DNA", "No") in list("Yes", "No")
if(answer == "Yes")
M.visible_message("[M] presses [M.p_their()] thumb against [P].",\
"You press your thumb against [P].",\
"[P] makes a sharp clicking sound as it extracts DNA material from [M].")
if(!M.has_dna())
to_chat(P, "No DNA detected")
return
to_chat(P, "[M]'s UE string : [M.dna.unique_enzymes]
")
if(M.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 [M.p_theyre()] going to provide a DNA sample willingly.")
// -=-=-=-= Software =-=-=-=-=- //
//Remote Signaller
/mob/living/silicon/pai/proc/softwareSignal()
var/dat = ""
dat += "Remote Signaller
"
dat += {"Frequency/Code for signaler:
Frequency:
-
-
[format_frequency(signaler.frequency)]
+
+
Code:
-
-
[signaler.code]
+
+
Send Signal
"}
return dat
// Crew Manifest
/mob/living/silicon/pai/proc/softwareManifest()
. += "Crew Manifest
"
if(GLOB.data_core.general)
for(var/datum/data/record/t in sortRecord(GLOB.data_core.general))
. += "[t.fields["name"]] - [t.fields["rank"]]
"
. += "