diff --git a/code/datums/action.dm b/code/datums/action.dm
index 04d9c706ed..602dd2c37a 100644
--- a/code/datums/action.dm
+++ b/code/datums/action.dm
@@ -301,10 +301,7 @@
/datum/action/item_action/synthswitch/Trigger()
if(istype(target, /obj/item/instrument/piano_synth))
var/obj/item/instrument/piano_synth/synth = target
- var/chosen = input("Choose the type of instrument you want to use", "Instrument Selection", "piano") as null|anything in synth.insTypes
- if(!synth.insTypes[chosen])
- return
- return synth.changeInstrument(chosen)
+ return synth.selectInstrument()
return ..()
/datum/action/item_action/vortex_recall
@@ -827,4 +824,4 @@
for(var/datum/action/A in M.actions)
if(istype(A, action_type))
return A
- return
\ No newline at end of file
+ return
diff --git a/code/game/machinery/announcement_system.dm b/code/game/machinery/announcement_system.dm
index 5a597f7280..84e5910731 100644
--- a/code/game/machinery/announcement_system.dm
+++ b/code/game/machinery/announcement_system.dm
@@ -29,7 +29,7 @@ GLOBAL_LIST_EMPTY(announcement_systems)
/obj/machinery/announcement_system/Initialize()
. = ..()
GLOB.announcement_systems += src
- radio = new /obj/item/radio/headset/ai(src)
+ radio = new /obj/item/radio/headset/silicon/ai(src)
update_icon()
/obj/machinery/announcement_system/update_icon()
diff --git a/code/game/objects/items/devices/instruments.dm b/code/game/objects/items/devices/instruments.dm
index dd7c5b15d9..4c46d064c4 100644
--- a/code/game/objects/items/devices/instruments.dm
+++ b/code/game/objects/items/devices/instruments.dm
@@ -108,6 +108,12 @@
song.instrumentDir = name
song.instrumentExt = insTypes[name]
+/obj/item/instrument/piano_synth/proc/selectInstrument() // Moved here so it can be used by the action and PAI software panel without copypasta
+ var/chosen = input("Choose the type of instrument you want to use", "Instrument Selection", song.instrumentDir) as null|anything in insTypes
+ if(!insTypes[chosen])
+ return
+ return changeInstrument(chosen)
+
/obj/item/instrument/banjo
name = "banjo"
desc = "A 'Mura' brand banjo. It's pretty much just a drum with a neck and strings."
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index e04501144e..1b9cea37f3 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -254,12 +254,17 @@ GLOBAL_LIST_INIT(channel_tokens, list(
keyslot = null
bowman = TRUE
-/obj/item/radio/headset/ai
+/obj/item/radio/headset/silicon/pai
+ name = "\proper mini Integrated Subspace Transceiver "
+ subspace_transmission = FALSE
+
+
+/obj/item/radio/headset/silicon/ai
name = "\proper Integrated Subspace Transceiver "
keyslot2 = new /obj/item/encryptionkey/ai
command = TRUE
-/obj/item/radio/headset/ai/can_receive(freq, level)
+/obj/item/radio/headset/silicon/can_receive(freq, level)
return ..(freq, level, TRUE)
/obj/item/radio/headset/attackby(obj/item/W, mob/user, params)
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index ed0d0d02e8..3b15c47bcb 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -146,7 +146,7 @@
aiPDA.name = name + " (" + aiPDA.ownjob + ")"
aiMulti = new(src)
- radio = new /obj/item/radio/headset/ai(src)
+ radio = new /obj/item/radio/headset/silicon/ai(src)
aicamera = new/obj/item/camera/siliconcam/ai_camera(src)
deploy_action.Grant(src)
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index daaf9afbe2..074e637120 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -10,6 +10,7 @@
health = 500
maxHealth = 500
layer = BELOW_MOB_LAYER
+ var/obj/item/instrument/piano_synth/internal_instrument
silicon_privileges = PRIVILEDGES_PAI
var/datum/element/mob_holder/current_mob_holder //because only a few of their chassis can be actually held.
@@ -27,6 +28,7 @@
var/speakDoubleExclamation = "alarms"
var/speakQuery = "queries"
+ var/obj/item/radio/headset // The pAI's headset
var/obj/item/pai_cable/cable // The cable we produce and use when door or camera jacking
var/master // Name of the one who commands us
@@ -54,6 +56,7 @@
var/obj/item/integrated_signaler/signaler // AI's signaller
+ var/encryptmod = FALSE
var/holoform = FALSE
var/canholo = TRUE
var/obj/item/card/id/access_card = null
@@ -84,6 +87,7 @@
var/icon/custom_holoform_icon
/mob/living/silicon/pai/Destroy()
+ QDEL_NULL(internal_instrument)
if (loc != card)
card.forceMove(drop_location())
card.pai = null
@@ -106,7 +110,7 @@
card = P
signaler = new(src)
if(!radio)
- radio = new /obj/item/radio(src)
+ radio = new /obj/item/radio/headset/silicon/pai(src)
//PDA
pda = new(src)
@@ -296,6 +300,17 @@
/mob/living/silicon/pai/process()
emitterhealth = CLAMP((emitterhealth + emitterregen), -50, emittermaxhealth)
+/obj/item/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))
+ pai.radio.attackby(W, user, params)
+ else
+ to_chat(user, "Encryption Key ports not configured.")
+
/mob/living/silicon/pai/proc/short_radio()
if(radio_short_timerid)
deltimer(radio_short_timerid)
diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm
index 55f4bdd65d..7751632813 100644
--- a/code/modules/mob/living/silicon/pai/software.dm
+++ b/code/modules/mob/living/silicon/pai/software.dm
@@ -20,6 +20,8 @@
"universal translator" = 35,
//"projection array" = 15
"remote signaller" = 5,
+ "loudness booster" = 25,
+ "encryption keys" = 20
)
/mob/living/silicon/pai/proc/paiInterface()
@@ -50,6 +52,8 @@
left_part = softwareMedicalRecord()
if("securityrecord")
left_part = softwareSecurityRecord()
+ if("encryptionkeys")
+ left_part = softwareEncryptionKeys()
if("translator")
left_part = softwareTranslator()
if("atmosensor")
@@ -64,6 +68,8 @@
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
@@ -256,6 +262,9 @@
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"])
grant_all_languages(TRUE)
@@ -271,6 +280,12 @@
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.interact(src)
+ if(subscreen == 2) // Change Instrument type
+ internal_instrument.selectInstrument()
+
//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
@@ -306,6 +321,8 @@
dat += "Camera Jack
"
if(s == "remote signaller")
dat += "Remote Signaller
"
+ if(s == "loudness booster")
+ dat += "Loudness Booster
"
dat += "
"
// Advanced
@@ -319,6 +336,8 @@
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"]
"
@@ -469,6 +488,14 @@
. += "
Requested security record not found,