diff --git a/code/game/machinery/computer/HolodeckControl.dm b/code/game/machinery/computer/HolodeckControl.dm
index e4c6e621fee..431bb10cc4c 100644
--- a/code/game/machinery/computer/HolodeckControl.dm
+++ b/code/game/machinery/computer/HolodeckControl.dm
@@ -32,11 +32,11 @@
dat += "(Begin Wildlife Simulation)
"
dat += "Ensure the holodeck is empty before testing.
"
dat += "
"
- if(issilicon(user))
+ if(isaiorborg(user))
dat += "(Re-Enable Safety Protocols?)
"
dat += "Safety Protocols are DISABLED
"
else
- if(issilicon(user))
+ if(isaiorborg(user))
dat += "(Override Safety Protocols?)
"
dat += "
"
dat += "Safety Protocols are ENABLED
"
diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm
index 449bc3b3074..5331562c2ea 100644
--- a/code/game/machinery/computer/arcade.dm
+++ b/code/game/machinery/computer/arcade.dm
@@ -222,6 +222,9 @@
src.temp = "You have been drained! GAME OVER"
if(emagged)
feedback_inc("arcade_loss_mana_emagged")
+ if(ispAI(usr))
+ var/mob/living/silicon/pai/pai = usr
+ pai.card.explode()
usr.gib()
else
feedback_inc("arcade_loss_mana_normal")
@@ -241,6 +244,9 @@
src.temp = "You have been crushed! GAME OVER"
if(emagged)
feedback_inc("arcade_loss_hp_emagged")
+ if(ispAI(usr))
+ var/mob/living/silicon/pai/pai = usr
+ pai.card.explode()
usr.gib()
else
feedback_inc("arcade_loss_hp_normal")
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index 0d29218a025..5e8f7770730 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -35,6 +35,12 @@
if(..())
return
+ if(ispAI(usr))
+ if(paired != usr)
+ user.reset_view()
+ user.unset_machine()
+ return
+
var/list/L = list()
for (var/obj/machinery/camera/C in cameranet.cameras)
L.Add(C)
@@ -56,33 +62,41 @@
var/t = input(user, "Which camera should you change to?") as null|anything in D
if(!t)
+ if(!isAI(user))
+ user.reset_view()
user.unset_machine()
return 0
var/obj/machinery/camera/C = D[t]
if(t == "Cancel")
+ if(!isAI(user))
+ user.reset_view()
user.unset_machine()
return 0
if(C)
- if ((get_dist(user, src) > 1 || user.machine != src || user.blinded || !( C.can_use() )) && (!istype(user, /mob/living/silicon/ai)))
- if(!C.can_use() && !isAI(user))
- src.current = null
+ if(isAI(user))
+ var/mob/living/silicon/ai/A = user
+ A.eyeobj.setLoc(get_turf(C))
+ A.client.eye = A.eyeobj
+ if(ispAI(user))
+ var/mob/living/silicon/pai/A = user
+ A.switchCamera(C)
+ else if ((get_dist(user, src) > 1) || (user.machine != src)|| user.blinded || !( C.can_use() ))
+ src.current = null
return 0
else
- if(isAI(user))
- var/mob/living/silicon/ai/A = user
- A.eyeobj.setLoc(get_turf(C))
- A.client.eye = A.eyeobj
- else
- src.current = C
- use_power(50)
-
- spawn(5)
- attack_hand(user)
+ src.current = C
+ use_power(50)
+ spawn(5)
+ attack_hand(user)
+ return
+ else
+ if(!isAI(user))
+ user.reset_view()
+ user.unset_machine()
return
-
/obj/machinery/computer/security/telescreen
@@ -93,6 +107,7 @@
network = list("thunder")
density = 0
circuit = null
+ paiallowed = 0 //2retro
/obj/machinery/computer/security/telescreen/update_icon()
icon_state = initial(icon_state)
@@ -114,6 +129,7 @@
name = "security camera monitor"
desc = "An old TV hooked into the stations camera network."
icon_state = "security_det"
+ paiallowed = 0 //2retro
/obj/machinery/computer/security/mining
diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm
index d387102becf..f3299e61f20 100644
--- a/code/game/machinery/computer/computer.dm
+++ b/code/game/machinery/computer/computer.dm
@@ -8,6 +8,7 @@
active_power_usage = 300
var/obj/item/weapon/circuitboard/circuit = null //if circuit==null, computer can't disassembly
var/processing = 0
+ paiallowed = 1
/obj/machinery/computer/New()
..()
@@ -88,6 +89,8 @@
/obj/machinery/computer/proc/set_broken()
if(circuit) //no circuit, no breaking
+ if(paired)
+ paired.unpair(0)
stat |= BROKEN
update_icon()
return
@@ -112,6 +115,17 @@
A.state = 4
A.icon_state = "4"
qdel(src)
+ if(istype(I, /obj/item/device/paicard))
+ var/obj/item/device/paicard/C = I
+ if(C.pai && (C.pai.stat != DEAD) && C.pai.pairing)
+ if(allowed(user))
+ if(paiallowed)
+ C.pai.pair(src)
+ else
+ C.pai << "\[ERROR\] Remote device does not accept remote control connections."
+ else
+ user << "Access denied."
+ C.pai << "\[ERROR\] Handshake failed. User not authorised to connect remote devices."
return
/obj/machinery/computer/attack_hand(user)
@@ -140,4 +154,4 @@
return
user.visible_message("[user.name] smashes against the [src.name] with its claws.",\
"You smash against the [src.name] with your claws.",\
- "You hear a clicking sound.")
+ "You hear a clicking sound.")
\ No newline at end of file
diff --git a/code/game/machinery/computer/law.dm b/code/game/machinery/computer/law.dm
index 58991352c91..959bbc67b45 100644
--- a/code/game/machinery/computer/law.dm
+++ b/code/game/machinery/computer/law.dm
@@ -3,6 +3,7 @@
/obj/machinery/computer/upload
var/mob/living/silicon/current = null //The target of future law uploads
icon_state = null //To make sure mappers understand THIS ISN'T A VALID TYPE
+ paiallowed = 0
/obj/machinery/computer/upload/attackby(obj/item/O as obj, mob/user as mob)
if(istype(O, /obj/item/weapon/aiModule))
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
index b2a5436ef66..e1eed34cc29 100644
--- a/code/game/machinery/computer/medical.dm
+++ b/code/game/machinery/computer/medical.dm
@@ -133,12 +133,18 @@
src.active1 = null
src.active2 = null
else if (href_list["login"])
- if (istype(usr, /mob/living/silicon))
- src.active1 = null
- src.active2 = null
- src.authenticated = 1
- src.rank = "AI"
- src.screen = 1
+ if (isaiorborg(usr))
+ active1 = null
+ active2 = null
+ authenticated = 1
+ rank = "AI"
+ screen = 1
+ else if (ispAI(usr))
+ active1 = null
+ active2 = null
+ authenticated = usr.name
+ rank = "pAI"
+ screen = 1
else if (istype(src.scan, /obj/item/weapon/card/id))
src.active1 = null
src.active2 = null
@@ -453,3 +459,4 @@
name = "medical laptop"
desc = "A cheap Nanotrasen medical laptop, it functions as a medical records computer. It's bolted to the table."
icon_state = "medlaptop"
+ paiallowed = 0 //Go use a real computer
diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm
index 5b93f9e6d53..a412954abfc 100644
--- a/code/game/machinery/computer/pod.dm
+++ b/code/game/machinery/computer/pod.dm
@@ -123,6 +123,7 @@
icon_state = "old"
name = "\improper DoorMex control console"
title = "Door Controls"
+ paiallowed = 0 //2retro
/obj/machinery/computer/pod/old/syndicate
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index 5034a19f459..e9fabd91fb5 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -230,12 +230,18 @@ What a mess.*/
active2 = null
if("Log In")
- if (istype(usr, /mob/living/silicon))
+ if (isaiorborg(usr))
active1 = null
active2 = null
authenticated = 1
rank = "AI"
screen = 1
+ else if (ispAI(usr))
+ active1 = null
+ active2 = null
+ authenticated = usr.name
+ rank = "pAI"
+ screen = 1
else if (istype(scan, /obj/item/weapon/card/id))
active1 = null
active2 = null
@@ -556,3 +562,4 @@ What a mess.*/
/obj/machinery/computer/secure_data/detective_computer
icon = 'icons/obj/computer.dmi'
icon_state = "messyfiles"
+ paiallowed = 0 //2retro
diff --git a/code/game/machinery/computer/shuttle.dm b/code/game/machinery/computer/shuttle.dm
index d43833b955f..ee7ea2b1d81 100644
--- a/code/game/machinery/computer/shuttle.dm
+++ b/code/game/machinery/computer/shuttle.dm
@@ -4,6 +4,7 @@
icon_state = "shuttle"
var/auth_need = 3.0
var/list/authorized = list( )
+ paiallowed = 0
attackby(var/obj/item/weapon/card/W as obj, var/mob/user as mob)
diff --git a/code/game/machinery/computer/telecrystalconsoles.dm b/code/game/machinery/computer/telecrystalconsoles.dm
index 9f9c32260d2..682b79adcb5 100644
--- a/code/game/machinery/computer/telecrystalconsoles.dm
+++ b/code/game/machinery/computer/telecrystalconsoles.dm
@@ -1,221 +1,222 @@
-#define NUKESCALINGMODIFIER 0.5
-
-var/list/possible_uplinker_IDs = list("Alfa","Bravo","Charlie","Delta","Echo","Foxtrot","Zero", "Niner")
-
-
-/obj/machinery/computer/telecrystals
- name = "\improper Telecrystal assignment station"
- desc = "A device used to manage telecrystals during group operations. You shouldn't be looking at this particular one..."
- icon_state = "tcstation"
-
-/////////////////////////////////////////////
-/obj/machinery/computer/telecrystals/uplinker
- name = "\improper Telecrystal upload/recieve station"
- desc = "A device used to manage telecrystals during group operations. To use, simply insert your uplink. With your uplink installed \
- you can upload your telecrystals to the group's pool using the console, or be assigned additional telecrystals by your lieutenant."
- icon_state = "tcstation"
- var/obj/item/uplinkholder = null
- var/obj/machinery/computer/telecrystals/boss/linkedboss = null
-
-/obj/machinery/computer/telecrystals/uplinker/New()
- ..()
-
- var/ID
- if(possible_uplinker_IDs.len)
- ID = pick(possible_uplinker_IDs)
- possible_uplinker_IDs -= ID
- name = "[name] [ID]"
- else
- name = "[name] [rand(1,999)]"
-
-
-/obj/machinery/computer/telecrystals/uplinker/attackby(var/obj/item/O as obj, var/mob/user as mob)
- if(istype(O, /obj/item))
-
- if(uplinkholder)
- user << "The [src] already has an uplink in it."
- return
-
- if(O.hidden_uplink)
- var/obj/item/P = user.get_active_hand()
- user.drop_item()
- uplinkholder = P
- P.loc = src
- P.add_fingerprint(user)
- update_icon()
- updateUsrDialog()
- else
- user << "The [O] doesn't appear to be an uplink..."
-
-
-
-/obj/machinery/computer/telecrystals/uplinker/update_icon()
- overlays.Cut()
- if(uplinkholder)
- overlays += "[initial(icon_state)]-closed"
-
-
-/obj/machinery/computer/telecrystals/uplinker/proc/ejectuplink()
- if(uplinkholder)
- uplinkholder.loc = get_turf(src.loc)
- uplinkholder = null
- update_icon()
-
-/obj/machinery/computer/telecrystals/uplinker/proc/donateTC(var/amt, var/addLog = 1)
- if(uplinkholder && linkedboss)
- if(amt <= uplinkholder.hidden_uplink.uses)
- uplinkholder.hidden_uplink.uses -= amt
- linkedboss.storedcrystals += amt
- if(addLog)
- linkedboss.logTransfer("[src] donated [amt] telecrystals to [linkedboss].")
-
-/obj/machinery/computer/telecrystals/uplinker/proc/giveTC(var/amt, var/addLog = 1)
- if(uplinkholder && linkedboss)
- if(amt <= linkedboss.storedcrystals)
- uplinkholder.hidden_uplink.uses += amt
- linkedboss.storedcrystals -= amt
- if(addLog)
- linkedboss.logTransfer("[src] recieved [amt] telecrystals from [linkedboss].")
-
-///////
-
-/obj/machinery/computer/telecrystals/uplinker/attack_hand(mob/user as mob)
- if(..())
- return
- src.add_fingerprint(user)
- user.set_machine(src)
-
- var/dat = ""
- if(linkedboss)
- dat += "[linkedboss] has [linkedboss.storedcrystals] telecrystals available for distribution.
"
- else
- dat += "No linked management consoles detected. Scan for uplink stations using the management console.
"
-
- if(uplinkholder)
- dat += "[uplinkholder.hidden_uplink.uses] telecrystals remain in this uplink.
"
- if(linkedboss)
- dat += "Donate TC: 1 | 5"
- dat += "
Eject Uplink"
-
-
- var/datum/browser/popup = new(user, "computer", "Telecrystal Upload/Recieve Station", 700, 500)
- popup.set_content(dat)
- popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
- popup.open()
- return
-
-/obj/machinery/computer/telecrystals/uplinker/Topic(href, href_list)
- if(..())
- return
-
- if(href_list["donate1"])
- donateTC(1)
-
- if(href_list["donate5"])
- donateTC(5)
-
- if(href_list["eject"])
- ejectuplink()
-
- src.updateUsrDialog()
-
-
-/////////////////////////////////////////
-/obj/machinery/computer/telecrystals/boss
- name = "team Telecrystal management console"
- desc = "A device used to manage telecrystals during group operations. To use, simply initialize the machine by scanning for nearby uplink stations. \
- Once the consoles are linked up, you can assign any telecrystals amongst your operatives; be they donated by your agents or rationed to the squad \
- based on the danger rating of the mission."
- icon_state = "tcboss"
- var/virgin = 1
- var/scanrange = 10
- var/storedcrystals = 0
- var/list/TCstations = list()
- var/list/transferlog = list()
-
-/obj/machinery/computer/telecrystals/boss/proc/logTransfer(var/logmessage)
- transferlog += ("[worldtime2text()] [logmessage]")
-
-/obj/machinery/computer/telecrystals/boss/proc/scanUplinkers()
- for(var/obj/machinery/computer/telecrystals/uplinker/A in range(scanrange, src.loc))
- if(!A.linkedboss)
- TCstations += A
- A.linkedboss = src
- if(virgin)
- getDangerous()
- virgin = 0
-
-/obj/machinery/computer/telecrystals/boss/proc/getDangerous()//This scales the TC assigned with the round population.
- ..()
- var/danger
- danger = player_list.len
- while(!IsMultiple(++danger,10))//Just round up to the nearest multiple of ten.
- scaleTC(danger)
-
-/obj/machinery/computer/telecrystals/boss/proc/scaleTC(var/amt)//Its own proc, since it'll probably need a lot of tweaks for balance, use a fancier algorhithm, etc.
- storedcrystals += amt * NUKESCALINGMODIFIER
-
-/////////
-
-/obj/machinery/computer/telecrystals/boss/attack_hand(var/mob/user as mob)
- if(..())
- return
- src.add_fingerprint(user)
- user.set_machine(src)
-
-
- var/dat = ""
- dat += "Scan for TC stations.
"
- dat += "This [src] has [storedcrystals] telecrystals available for distribution.
"
- dat += "
"
-
-
- for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations)
- dat += "[A.name] | "
- if(A.uplinkholder)
- dat += "[A.uplinkholder.hidden_uplink.uses] telecrystals."
- if(storedcrystals)
- dat+= "
Add TC: 1 | 5"
- dat += "
"
-
- if(TCstations.len)
- dat += "
Evenly distribute remaining TC.
"
-
-
- for(var/entry in transferlog)
- dat += "[entry]
"
-
-
- var/datum/browser/popup = new(user, "computer", "Team Telecrystal Management Console", 700, 500)
- popup.set_content(dat)
- popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
- popup.open()
- return
-
-/obj/machinery/computer/telecrystals/boss/Topic(href, href_list)
- if(..())
- return
-
- if(href_list["scan"])
- scanUplinkers()
-
- if(href_list["give1"])
- var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["give1"])
- A.giveTC(1)
-
- if(href_list["give5"])
- var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["give5"])
- A.giveTC(5)
-
- if(href_list["distrib"])
- var/sanity = 0
- while(storedcrystals && sanity < 100)
- for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations)
- A.giveTC(1,0)
- sanity++
- logTransfer("[src] evenly distributed telecrystals.")
-
- src.updateUsrDialog()
- return
-
+#define NUKESCALINGMODIFIER 0.5
+
+var/list/possible_uplinker_IDs = list("Alfa","Bravo","Charlie","Delta","Echo","Foxtrot","Zero", "Niner")
+
+
+/obj/machinery/computer/telecrystals
+ name = "\improper Telecrystal assignment station"
+ desc = "A device used to manage telecrystals during group operations. You shouldn't be looking at this particular one..."
+ icon_state = "tcstation"
+ paiallowed = 0
+
+/////////////////////////////////////////////
+/obj/machinery/computer/telecrystals/uplinker
+ name = "\improper Telecrystal upload/recieve station"
+ desc = "A device used to manage telecrystals during group operations. To use, simply insert your uplink. With your uplink installed \
+ you can upload your telecrystals to the group's pool using the console, or be assigned additional telecrystals by your lieutenant."
+ icon_state = "tcstation"
+ var/obj/item/uplinkholder = null
+ var/obj/machinery/computer/telecrystals/boss/linkedboss = null
+
+/obj/machinery/computer/telecrystals/uplinker/New()
+ ..()
+
+ var/ID
+ if(possible_uplinker_IDs.len)
+ ID = pick(possible_uplinker_IDs)
+ possible_uplinker_IDs -= ID
+ name = "[name] [ID]"
+ else
+ name = "[name] [rand(1,999)]"
+
+
+/obj/machinery/computer/telecrystals/uplinker/attackby(var/obj/item/O as obj, var/mob/user as mob)
+ if(istype(O, /obj/item))
+
+ if(uplinkholder)
+ user << "The [src] already has an uplink in it."
+ return
+
+ if(O.hidden_uplink)
+ var/obj/item/P = user.get_active_hand()
+ user.drop_item()
+ uplinkholder = P
+ P.loc = src
+ P.add_fingerprint(user)
+ update_icon()
+ updateUsrDialog()
+ else
+ user << "The [O] doesn't appear to be an uplink..."
+
+
+
+/obj/machinery/computer/telecrystals/uplinker/update_icon()
+ overlays.Cut()
+ if(uplinkholder)
+ overlays += "[initial(icon_state)]-closed"
+
+
+/obj/machinery/computer/telecrystals/uplinker/proc/ejectuplink()
+ if(uplinkholder)
+ uplinkholder.loc = get_turf(src.loc)
+ uplinkholder = null
+ update_icon()
+
+/obj/machinery/computer/telecrystals/uplinker/proc/donateTC(var/amt, var/addLog = 1)
+ if(uplinkholder && linkedboss)
+ if(amt <= uplinkholder.hidden_uplink.uses)
+ uplinkholder.hidden_uplink.uses -= amt
+ linkedboss.storedcrystals += amt
+ if(addLog)
+ linkedboss.logTransfer("[src] donated [amt] telecrystals to [linkedboss].")
+
+/obj/machinery/computer/telecrystals/uplinker/proc/giveTC(var/amt, var/addLog = 1)
+ if(uplinkholder && linkedboss)
+ if(amt <= linkedboss.storedcrystals)
+ uplinkholder.hidden_uplink.uses += amt
+ linkedboss.storedcrystals -= amt
+ if(addLog)
+ linkedboss.logTransfer("[src] recieved [amt] telecrystals from [linkedboss].")
+
+///////
+
+/obj/machinery/computer/telecrystals/uplinker/attack_hand(mob/user as mob)
+ if(..())
+ return
+ src.add_fingerprint(user)
+ user.set_machine(src)
+
+ var/dat = ""
+ if(linkedboss)
+ dat += "[linkedboss] has [linkedboss.storedcrystals] telecrystals available for distribution.
"
+ else
+ dat += "No linked management consoles detected. Scan for uplink stations using the management console.
"
+
+ if(uplinkholder)
+ dat += "[uplinkholder.hidden_uplink.uses] telecrystals remain in this uplink.
"
+ if(linkedboss)
+ dat += "Donate TC: 1 | 5"
+ dat += "
Eject Uplink"
+
+
+ var/datum/browser/popup = new(user, "computer", "Telecrystal Upload/Recieve Station", 700, 500)
+ popup.set_content(dat)
+ popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
+ popup.open()
+ return
+
+/obj/machinery/computer/telecrystals/uplinker/Topic(href, href_list)
+ if(..())
+ return
+
+ if(href_list["donate1"])
+ donateTC(1)
+
+ if(href_list["donate5"])
+ donateTC(5)
+
+ if(href_list["eject"])
+ ejectuplink()
+
+ src.updateUsrDialog()
+
+
+/////////////////////////////////////////
+/obj/machinery/computer/telecrystals/boss
+ name = "team Telecrystal management console"
+ desc = "A device used to manage telecrystals during group operations. To use, simply initialize the machine by scanning for nearby uplink stations. \
+ Once the consoles are linked up, you can assign any telecrystals amongst your operatives; be they donated by your agents or rationed to the squad \
+ based on the danger rating of the mission."
+ icon_state = "tcboss"
+ var/virgin = 1
+ var/scanrange = 10
+ var/storedcrystals = 0
+ var/list/TCstations = list()
+ var/list/transferlog = list()
+
+/obj/machinery/computer/telecrystals/boss/proc/logTransfer(var/logmessage)
+ transferlog += ("[worldtime2text()] [logmessage]")
+
+/obj/machinery/computer/telecrystals/boss/proc/scanUplinkers()
+ for(var/obj/machinery/computer/telecrystals/uplinker/A in range(scanrange, src.loc))
+ if(!A.linkedboss)
+ TCstations += A
+ A.linkedboss = src
+ if(virgin)
+ getDangerous()
+ virgin = 0
+
+/obj/machinery/computer/telecrystals/boss/proc/getDangerous()//This scales the TC assigned with the round population.
+ ..()
+ var/danger
+ danger = player_list.len
+ while(!IsMultiple(++danger,10))//Just round up to the nearest multiple of ten.
+ scaleTC(danger)
+
+/obj/machinery/computer/telecrystals/boss/proc/scaleTC(var/amt)//Its own proc, since it'll probably need a lot of tweaks for balance, use a fancier algorhithm, etc.
+ storedcrystals += amt * NUKESCALINGMODIFIER
+
+/////////
+
+/obj/machinery/computer/telecrystals/boss/attack_hand(var/mob/user as mob)
+ if(..())
+ return
+ src.add_fingerprint(user)
+ user.set_machine(src)
+
+
+ var/dat = ""
+ dat += "Scan for TC stations.
"
+ dat += "This [src] has [storedcrystals] telecrystals available for distribution.
"
+ dat += "
"
+
+
+ for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations)
+ dat += "[A.name] | "
+ if(A.uplinkholder)
+ dat += "[A.uplinkholder.hidden_uplink.uses] telecrystals."
+ if(storedcrystals)
+ dat+= "
Add TC: 1 | 5"
+ dat += "
"
+
+ if(TCstations.len)
+ dat += "
Evenly distribute remaining TC.
"
+
+
+ for(var/entry in transferlog)
+ dat += "[entry]
"
+
+
+ var/datum/browser/popup = new(user, "computer", "Team Telecrystal Management Console", 700, 500)
+ popup.set_content(dat)
+ popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
+ popup.open()
+ return
+
+/obj/machinery/computer/telecrystals/boss/Topic(href, href_list)
+ if(..())
+ return
+
+ if(href_list["scan"])
+ scanUplinkers()
+
+ if(href_list["give1"])
+ var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["give1"])
+ A.giveTC(1)
+
+ if(href_list["give5"])
+ var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["give5"])
+ A.giveTC(5)
+
+ if(href_list["distrib"])
+ var/sanity = 0
+ while(storedcrystals && sanity < 100)
+ for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations)
+ A.giveTC(1,0)
+ sanity++
+ logTransfer("[src] evenly distributed telecrystals.")
+
+ src.updateUsrDialog()
+ return
+
#undef NUKESCALINGMODIFIER
\ No newline at end of file
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index db84ff75a83..662bea6800d 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -109,12 +109,16 @@ Class Procs:
var/mob/living/occupant = null
var/unsecuring_tool = /obj/item/weapon/wrench
var/interact_offline = 0 // Can the machine be interacted with while de-powered.
+ var/mob/living/silicon/pai/paired
+ var/paiallowed = 0
/obj/machinery/New()
..()
machines += src
/obj/machinery/Destroy()
+ if(paired)
+ paired.unpair(0)
machines.Remove(src)
..()
@@ -208,6 +212,10 @@ Class Procs:
usr << "You don't have the dexterity to do this!"
return 1
+ if(ispAI(usr))
+ if(paired != usr)
+ return 1
+
var/norange = 0
if(istype(usr, /mob/living/carbon/human))
var/mob/living/carbon/human/H = usr
diff --git a/code/game/machinery/telecomms/traffic_control.dm b/code/game/machinery/telecomms/traffic_control.dm
index 9a6f87c8d17..1fc91644fea 100644
--- a/code/game/machinery/telecomms/traffic_control.dm
+++ b/code/game/machinery/telecomms/traffic_control.dm
@@ -142,8 +142,10 @@
/obj/machinery/computer/telecomms/traffic/proc/create_log(var/entry, var/mob/user)
var/id = null
- if(issilicon(user))
+ if(isaiorborg(user))
id = "System Administrator"
+ else if(ispAI(user))
+ id = "[user.name] (pAI)"
else
if(auth)
id = "[auth.registered_name] ([auth.assignment])"
diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm
index 3fa8f1593f8..f4acf51399d 100644
--- a/code/game/objects/items/devices/paicard.dm
+++ b/code/game/objects/items/devices/paicard.dm
@@ -134,3 +134,22 @@
pai.emp_act(severity)
..()
+/obj/item/device/paicard/proc/explode()
+ var/turf/T = get_turf(src.loc)
+
+ if (ismob(loc))
+ var/mob/M = loc
+ M.show_message("\red Your [src] explodes!", 1)
+ else if(istype(loc, /obj/item/device/pda))
+ var/obj/item/device/pda/P = loc
+ if(P.detonate)
+ P.explode()
+ qdel(src)
+ return
+ if(T)
+ T.hotspot_expose(700,125)
+
+ explosion(T, -1, -1, 2, 3)
+
+ qdel(src)
+ return
\ No newline at end of file
diff --git a/code/modules/awaymissions/bluespaceartillery.dm b/code/modules/awaymissions/bluespaceartillery.dm
index 32fadf2eef7..da6add53782 100644
--- a/code/modules/awaymissions/bluespaceartillery.dm
+++ b/code/modules/awaymissions/bluespaceartillery.dm
@@ -6,6 +6,7 @@
icon = 'icons/obj/machines/particle_accelerator.dmi'
density = 1
anchored = 1
+ paiallowed = 1
/obj/machinery/artillerycontrol/process()
if(src.reload<180)
@@ -20,6 +21,12 @@
/obj/structure/artilleryplaceholder/decorative
density = 0
+/obj/machinery/artillerycontrol/attackby(I as obj, user as mob)
+ if(istype(I, /obj/item/device/paicard))
+ var/obj/item/device/paicard/C = I
+ if(C.pai && (C.pai.stat != DEAD) && C.pai.pairing)
+ C.pai.pair(src)
+
/obj/machinery/artillerycontrol/attack_hand(mob/user as mob)
user.set_machine(src)
var/dat = "Bluespace Artillery Control:
"
diff --git a/code/modules/mob/living/silicon/pai/death.dm b/code/modules/mob/living/silicon/pai/death.dm
index 75e30dda3f9..8d30f3b20d3 100644
--- a/code/modules/mob/living/silicon/pai/death.dm
+++ b/code/modules/mob/living/silicon/pai/death.dm
@@ -1,5 +1,6 @@
/mob/living/silicon/pai/death(gibbed)
if(stat == DEAD) return
+ unpair(1)
stat = DEAD
canmove = 0
if(blind) blind.layer = 0
diff --git a/code/modules/mob/living/silicon/pai/life.dm b/code/modules/mob/living/silicon/pai/life.dm
index 385c0ae6760..9166e7ba855 100644
--- a/code/modules/mob/living/silicon/pai/life.dm
+++ b/code/modules/mob/living/silicon/pai/life.dm
@@ -29,5 +29,7 @@
/mob/living/silicon/pai/proc/follow_pai()
while(card)
loc = get_turf(card)
+ if(paired && (loc.z != paired.z))
+ unpair(0) //Limit remote control to same z-level
sleep(5)
qdel(src) //if there's no pAI we shouldn't exist
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index 89fb455c19d..160c0bebbda 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -52,6 +52,9 @@
var/obj/item/radio/integrated/signal/sradio // AI's signaller
+ var/obj/machinery/paired
+ var/pairing = 0
+
/mob/living/silicon/pai/New(var/obj/item/device/paicard)
canmove = 0
@@ -191,6 +194,40 @@
/mob/living/silicon/pai/UnarmedAttack(var/atom/A)//Stops runtimes due to attack_animal being the default
return
+/mob/living/silicon/pai/proc/unpair(var/silent = 0)
+ if(!paired)
+ return
+ if(!(paired.paired == src))
+ return
+ src.unset_machine()
+ paired.overlays -= image('icons/obj/computer.dmi', "paipaired")
+ paired.paired = null
+ paired = null
+ if(!silent)
+ src << "\[ERROR\] Network timeout. Remote control connection severed."
+ return
+
+/mob/living/silicon/pai/proc/pair(var/obj/machinery/P)
+ if(!pairing)
+ return
+ if(!P)
+ return
+ if(P.stat & (BROKEN|NOPOWER))
+ src << "\[ERROR\] Remote device not responding to remote control handshake. Cannot establish connection."
+ return
+ if(!P.paiallowed)
+ src << "\[ERROR\] Remote device does not accept remote control connections."
+ return
+ pairing = 0
+ unpair(1)
+ if(P.paired && (P.paired != src))
+ P.paired.unpair(0)
+ P.paired = src
+ paired = P
+ paired.overlays += image('icons/obj/computer.dmi', "paipaired")
+ src << "Handshake complete. Remote control connection established."
+ return
+
//Addition by Mord_Sith to define AI's network change ability
/*
/mob/living/silicon/pai/proc/pai_network_change()
diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm
index cd797cb9ab3..aba8ab06ab1 100644
--- a/code/modules/mob/living/silicon/pai/software.dm
+++ b/code/modules/mob/living/silicon/pai/software.dm
@@ -13,6 +13,7 @@
"security records" = 15,
//"camera jack" = 10,
"door jack" = 30,
+ "remote control" = 60,
"atmosphere sensor" = 5,
//"heartbeat sensor" = 10,
"security HUD" = 20,
@@ -60,6 +61,8 @@
left_part = src.facialRecognition()
if("medicalhud")
left_part = src.medicalAnalysis()
+ if("remote")
+ left_part = src.remoteControl()
if("doorjack")
left_part = src.softwareDoor()
if("camerajack")
@@ -243,6 +246,19 @@
if("translator")
if(href_list["toggle"])
src.universal_speak = !src.universal_speak
+ if("remote")
+ if(href_list["pair"])
+ if(!paired)
+ pairing = 1
+ if(href_list["abort"])
+ if(!paired)
+ pairing = 0
+ if(href_list["control"])
+ if(paired && (paired.paired == src))
+ paired.attack_hand(src)
+ if(href_list["disconnect"])
+ unpair(1)
+ pairing = 0
if("doorjack")
if(href_list["jack"])
if(src.cable && src.cable.machine)
@@ -306,6 +322,8 @@
dat += "Projection Array
"
if(s == "camera jack")
dat += "Camera Jack
"
+ if(s == "remote control")
+ dat += "Remote Control
"
if(s == "door jack")
dat += "Door Jack
"
dat += "
"
@@ -561,6 +579,26 @@
src << "DERP"
return dat
+// Computer remote control
+/mob/living/silicon/pai/proc/remoteControl()
+ var/dat = "