NOTICE - Cyborg lockdown lifted" : "ALERT - Cyborg lockdown detected"]: [R.name]
"
+
+ // Locks or unlocks the cyborg
+ else if (href_list["lockdown"])
+ var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["lockdown"])
+ if(!target || !istype(target))
+ return
+
+ if(isAI(user) && (target.connected_ai != user))
+ user << "Access Denied. This robot is not linked to you."
+ return
+
+ if(isrobot(user))
+ user << "Access Denied."
+ return
+
+ var/choice = input("Really [target.lockcharge ? "unlock" : "lockdown"] [target.name] ?") in list ("Yes", "No")
+ if(choice != "Yes")
+ return
+
+ if(!target || !istype(target))
+ return
+
+ message_admins("\blue [key_name_admin(usr)] [target.canmove ? "locked down" : "released"] [target.name]!")
+ log_game("[key_name(usr)] [target.canmove ? "locked down" : "released"] [target.name]!")
+ target.canmove = !target.canmove
+ if (target.lockcharge)
+ target.lockcharge = !target.lockcharge
+ target << "Your lockdown has been lifted!"
else
- usr << "Access Denied."
+ target.lockcharge = !target.lockcharge
+ target << "You have been locked down!"
- else if (href_list["magbot"])
- if(issilicon(usr) && is_special_character(usr))
- var/mob/living/silicon/robot/R = locate(href_list["magbot"])
- if(istype(R) && !R.emagged && R.connected_ai == usr && !R.scrambledcodes && can_control(usr, R))
- log_game("[key_name(usr)] emagged [R.name] using robotic console!")
- R.emagged = 1
- if(R.mind.special_role)
- R.verbs += /mob/living/silicon/robot/proc/ResetSecurityCodes
+ // Remotely hacks the cyborg. Only antag AIs can do this and only to linked cyborgs.
+ else if (href_list["hack"])
+ var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["hack"])
+ if(!target || !istype(target))
+ return
- src.updateUsrDialog()
- return
+ // Antag AI checks
+ if(!istype(user, /mob/living/silicon/ai) || !(user.mind.special_role && user.mind.original == user))
+ user << "Access Denied"
+ return
+
+ if(target.emagged)
+ user << "Robot is already hacked."
+ return
+
+ var/choice = input("Really hack [target.name]? This cannot be undone.") in list("Yes", "No")
+ if(choice != "Yes")
+ return
+
+ if(!target || !istype(target))
+ return
+
+ message_admins("\blue [key_name_admin(usr)] emagged [target.name] using robotic console!")
+ log_game("[key_name(usr)] emagged [target.name] using robotic console!")
+ target.emagged = 1
+ target << "Failsafe protocols overriden. New tools available."
+
+ // Arms the emergency self-destruct system
+ else if(href_list["arm"])
+ if(istype(user, /mob/living/silicon))
+ user << "Access Denied"
+ return
+
+ safety = !safety
+ user << "You [safety ? "disarm" : "arm"] the emergency self destruct"
+
+ // Destroys all accessible cyborgs if safety is disabled
+ else if(href_list["nuke"])
+ if(istype(user, /mob/living/silicon))
+ user << "Access Denied"
+ return
+ if(safety)
+ user << "Self-destruct aborted - safety active"
+ return
+
+ message_admins("\blue [key_name_admin(usr)] detonated all cyborgs!")
+ log_game("[key_name(usr)] detonated all cyborgs!")
+
+ for(var/mob/living/silicon/robot/R in mob_list)
+ if(istype(R, /mob/living/silicon/robot/drone))
+ continue
+ // Ignore antagonistic cyborgs
+ if(R.scrambledcodes)
+ continue
+ R << "Self-destruct command received."
+ spawn(10)
+ R.self_destruct()
+
+// Proc: get_cyborgs()
+// Parameters: 1 (operator - mob which is operating the console.)
+// Description: Returns NanoUI-friendly list of accessible cyborgs.
+/obj/machinery/computer/robotics/proc/get_cyborgs(var/mob/operator)
+ var/list/robots = list()
+
+ for(var/mob/living/silicon/robot/R in mob_list)
+ // Ignore drones
+ if(istype(R, /mob/living/silicon/robot/drone))
+ continue
+ // Ignore antagonistic cyborgs
+ if(R.scrambledcodes)
+ continue
+
+ var/list/robot = list()
+ robot["name"] = R.name
+ if(R.stat)
+ robot["status"] = "Not Responding"
+ else if (!R.canmove)
+ robot["status"] = "Lockdown"
+ else
+ robot["status"] = "Operational"
+
+ if(R.cell)
+ robot["cell"] = 1
+ robot["cell_capacity"] = R.cell.maxcharge
+ robot["cell_current"] = R.cell.charge
+ robot["cell_percentage"] = round(R.cell.percent())
+ else
+ robot["cell"] = 0
+
+ robot["module"] = R.module ? R.module.name : "None"
+ robot["master_ai"] = R.connected_ai ? R.connected_ai.name : "None"
+ robot["hackable"] = 0
+ // Antag AIs know whether linked cyborgs are hacked or not.
+ if(operator && istype(operator, /mob/living/silicon/ai) && (R.connected_ai == operator) && (operator.mind.special_role && operator.mind.original == operator))
+ robot["hacked"] = R.emagged ? 1 : 0
+ robot["hackable"] = R.emagged? 0 : 1
+ robots.Add(list(robot))
+ return robots
+
+// Proc: get_cyborg_by_name()
+// Parameters: 1 (name - Cyborg we are trying to find)
+// Description: Helper proc for finding cyborg by name
+/obj/machinery/computer/robotics/proc/get_cyborg_by_name(var/name)
+ if (!name)
+ return
+ for(var/mob/living/silicon/robot/R in mob_list)
+ if(R.name == name)
+ return R
\ No newline at end of file
diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm
index 8b309343c5f..558cb2cbfad 100644
--- a/code/modules/power/supermatter/supermatter.dm
+++ b/code/modules/power/supermatter/supermatter.dm
@@ -217,26 +217,60 @@
qdel(src)
return(gain)
-/obj/machinery/power/supermatter_shard/attack_robot(mob/user as mob)
+/obj/machinery/power/supermatter/attack_robot(mob/user as mob)
if(Adjacent(user))
return attack_hand(user)
else
- user << "You attempt to interface with the control circuits but find they are not connected to your network. Maybe in a future firmware update."
+ ui_interact(user)
return
/obj/machinery/power/supermatter_shard/attack_ai(mob/user as mob)
- user << "You attempt to interface with the control circuits but find they are not connected to your network. Maybe in a future firmware update."
+ ui_interact(user)
+
+/obj/machinery/power/supermatter_shard/attack_ghost(mob/user as mob)
+ ui_interact(user)
-/obj/machinery/power/supermatter_shard/attack_hand(mob/living/user as mob)
- if(!istype(user))
- return
- user.visible_message("\The [user] reaches out and touches \the [src], inducing a resonance... \his body starts to glow and bursts into flames before flashing into ash.",\
- "You reach out and touch \the [src]. Everything starts burning and all you can hear is ringing. Your last thought is \"That was not a wise decision.\"",\
- "You hear an unearthly noise as a wave of heat washes over you.")
-
- playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1)
+/obj/machinery/power/supermatter_shard/attack_hand(mob/user as mob)
+ user.visible_message("\The [user] reaches out and touches \the [src], inducing a resonance... \his body starts to glow and bursts into flames before flashing into ash.",\
+ "You reach out and touch \the [src]. Everything starts burning and all you can hear is ringing. Your last thought is \"That was not a wise decision.\"",\
+ "You hear an uneartly ringing, then what sounds like a shrilling kettle as you are washed with a wave of heat.")
+ playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1)
+
Consume(user)
+
+/obj/machinery/power/supermatter_shard/proc/get_integrity()
+ var/integrity = damage / explosion_point
+ integrity = round(100 - integrity * 100)
+ integrity = integrity < 0 ? 0 : integrity
+ return integrity
+
+// This is purely informational UI that may be accessed by AIs or robots
+/obj/machinery/power/supermatter_shard/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ var/data[0]
+
+ data["integrity_percentage"] = round(get_integrity())
+ var/datum/gas_mixture/env = null
+ if(!istype(src.loc, /turf/space))
+ env = src.loc.return_air()
+
+ if(!env)
+ data["ambient_temp"] = 0
+ data["ambient_pressure"] = 0
+ else
+ data["ambient_temp"] = round(env.temperature)
+ data["ambient_pressure"] = round(env.return_pressure())
+ if(damage > explosion_point)
+ data["detonating"] = 1
+ else
+ data["detonating"] = 0
+
+ ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
+ if (!ui)
+ ui = new(user, src, ui_key, "supermatter_crystal.tmpl", "Supermatter Crystal", 500, 300)
+ ui.set_initial_data(data)
+ ui.open()
+ ui.set_auto_update(1)
/obj/machinery/power/supermatter_shard/proc/transfer_energy()
for(var/obj/machinery/power/rad_collector/R in rad_collectors)
diff --git a/nano/templates/robot_control.tmpl b/nano/templates/robot_control.tmpl
new file mode 100644
index 00000000000..5bc18600181
--- /dev/null
+++ b/nano/templates/robot_control.tmpl
@@ -0,0 +1,89 @@
+{{if data.robots}}
+ {{if !data.is_ai}}
+
+
+ Emergency Self-Destruct:
+
+
+ {{if data.safety}}
+ {{:helper.link('ARM', 'unlocked', {'arm' : 1}, !data.allowed ? 'disabled' : null)}}
+ {{:helper.link('DETONATE', 'radiation', {'nuke' : 1}, 'disabled')}}
+ {{else}}
+ {{:helper.link('DISARM', 'locked', {'arm' : 1}, !data.allowed ? 'disabled' : null)}}
+ {{:helper.link('DETONATE', 'radiation', {'nuke' : 1}, !data.allowed ? 'disabled' : null, 'redButton')}}
+ {{/if}}
+
+
+
+ {{/if}}
+ {{for data.robots}}
+
+
+
{{:value.name}}
+ Information
+
+ Status:
+
+
+ {{:value.status}}
+
+
+ Master AI:
+
+
+ {{:value.master_ai}}
+
+
+ Module:
+
+
+ {{:value.module}}
+
+
+ {{if value.hackable}}
+
+ Safeties:
+
+
+ ENABLED
+
+ {{else value.hacked}}
+
+ Safeties:
+
+
+ DISABLED
+
+ {{/if}}
+ Power Cell
+ {{if value.cell}}
+
+ Rating :
+
+
+ {{:value.cell_capacity}}
+
+ {{:helper.displayBar(value.cell_percentage, 0, 100, (value.cell_percentage >= 50) ? 'good' : (value.cell_percentage >= 25) ? 'average' : 'bad')}}
+ {{:value.cell_percentage}} %
+ {{else}}
+ Not Installed
+ {{:helper.displayBar(100, 0, 100, 'bad')}}
+ N/A %
+ {{/if}}
+ Actions
+ {{if value.status == "Operational"}}
+ {{:helper.link('Lockdown', 'locked', {'lockdown' : value.name}, !data.allowed ? 'disabled' : null)}}
+ {{else}}
+ {{:helper.link('Unlock', 'unlocked', {'lockdown' : value.name}, !data.allowed ? 'disabled' : null)}}
+ {{/if}}
+ {{:helper.link('Self-Destruct', 'radiation', {'detonate' : value.name}, !data.allowed ? 'disabled' : null, 'redButton')}}
+ {{if value.hackable}}
+ {{:helper.link('Hack', 'calculator', {'hack' : value.name}, !data.allowed ? 'disabled' : null, 'redButton')}}
+ {{/if}}
+
+ {{/for}}
+{{else}}
+
+
No robots were found.
+
+{{/if}}
\ No newline at end of file
diff --git a/nano/templates/supermatter_crystal.tmpl b/nano/templates/supermatter_crystal.tmpl
new file mode 100644
index 00000000000..b06aaae7466
--- /dev/null
+++ b/nano/templates/supermatter_crystal.tmpl
@@ -0,0 +1,25 @@
+{{if data.detonating}}
+
+
CRYSTAL DELAMINATING
+
Evacuate area immediately
+
+
+{{else}}
+ Crystal Integrity
+ {{:helper.displayBar(data.integrity_percentage, 0, 100, (data.integrity_percentage >= 90) ? 'good' : (data.integrity_percentage >= 25) ? 'average' : 'bad')}}
+ {{:data.integrity_percentage}} %
+ Environment
+
+ Temperature:
+
+
+ {{:helper.displayBar(data.ambient_temp, 0, 10000, (data.ambient_temp >= 5000) ? 'bad' : (data.ambient_temp >= 4000) ? 'average' : 'good')}}
+ {{:data.ambient_temp}} K
+
+
+ Pressure:
+
+
+ {{:data.ambient_pressure}} kPa
+
+{{/if}}
\ No newline at end of file