diff --git a/code/modules/modular_computers/computers/item/pda.dm b/code/modules/modular_computers/computers/item/pda.dm index c375fe9a5c1..1fea772b85e 100644 --- a/code/modules/modular_computers/computers/item/pda.dm +++ b/code/modules/modular_computers/computers/item/pda.dm @@ -328,7 +328,6 @@ starting_programs = list( /datum/computer_file/program/filemanager, /datum/computer_file/program/robotact, - /datum/computer_file/program/borg_monitor, /datum/computer_file/program/atmosscan, /datum/computer_file/program/crew_manifest, ) diff --git a/code/modules/modular_computers/file_system/programs/robotact.dm b/code/modules/modular_computers/file_system/programs/robotact.dm index c213790b80a..927e09c044a 100644 --- a/code/modules/modular_computers/file_system/programs/robotact.dm +++ b/code/modules/modular_computers/file_system/programs/robotact.dm @@ -23,6 +23,20 @@ program_open_overlay = "command-syndicate" return TRUE return FALSE +/** + * Checks if we should see a specific cyborg on our "network". Arguments are our borg, and another borg + * + * Intended to allow borgs with the same AI to see eachother, syndicate borgs (scrambledcodes) with no AI to see eachother + * and not-syndicate borgs with no AI to see no one. Syndicate borgs connected to an AI will no longer see other syndicate + * borgs except ones also slaved to the same AI. + */ +/datum/computer_file/program/robotact/proc/evaluate_borg(mob/living/silicon/robot/this_borg, mob/living/silicon/robot/other_borg) + if(this_borg.connected_ai != other_borg.connected_ai) + return FALSE + if(this_borg.scrambledcodes && other_borg.scrambledcodes) + return TRUE + if(this_borg.connected_ai) + return TRUE /datum/computer_file/program/robotact/ui_data(mob/user) var/list/data = list() @@ -34,9 +48,11 @@ var/mob/living/silicon/robot/cyborg = tablet.silicon_owner - data["name"] = cyborg.name + data["borgName"] = cyborg.name data["designation"] = cyborg.model - data["masterAI"] = cyborg.connected_ai //Master AI + data["masterAI"] = cyborg.connected_ai + data["MasterAI_connected"] = !!cyborg.connected_ai //Need a bool for this on the other side + data["masterAI_online"] = (cyborg.connected_ai?.stat == CONSCIOUS) var/charge = 0 var/maxcharge = 1 @@ -56,6 +72,34 @@ data["thrustersStatus"] = "[cyborg.ionpulse_on?"ACTIVE":"DISABLED"]" //Feedback for thruster status data["selfDestructAble"] = (cyborg.emagged || istype(cyborg, /mob/living/silicon/robot/model/syndicate)) + data["cyborg_groups"] = list() + if(data["masterAI_online"] || (!data["MasterAI_connected"] && cyborg.scrambledcodes)) //If a borg isn't connected, we can just skip this all + var/list/borggroup = list() //temporary list for holding groups of borgs + for(var/mob/living/silicon/robot/other_borg in GLOB.silicon_mobs) + if(!evaluate_borg(cyborg,other_borg)) + continue + + var/shell = FALSE + if(other_borg.shell && !other_borg.ckey) + shell = TRUE + + var/list/cyborg_data = list( + "otherBorgName" = other_borg.name, + "integ" = round((other_borg.health + 100) / 2), //mob heath is -100 to 100, we want to scale that to 0 - 100 + "locked_down" = other_borg.lockcharge, + "status" = other_borg.stat, + "shell_discon" = shell, + "charge" = other_borg.cell ? round(other_borg.cell.percent()) : null, + "module" = other_borg.model ? "[other_borg.model.name]" : "None", + "ref" = REF(other_borg) + ) + borggroup += list(cyborg_data) + if(length(borggroup) == 4) //grouping borgs in packs of four, since I can't do it later in js + data["cyborg_groups"] += list(borggroup) + borggroup = list() + if(length(borggroup)) //and any remainders + data["cyborg_groups"] += list(borggroup) + //Cover, TRUE for locked data["cover"] = "[cyborg.locked? "LOCKED":"UNLOCKED"]" //Ability to move. FAULT if lockdown wire is cut, DISABLED if borg locked, ENABLED otherwise diff --git a/tgui/packages/tgui/interfaces/NtosRobotact.jsx b/tgui/packages/tgui/interfaces/NtosRobotact.jsx index 71afb4db1ba..ecf27b3cf76 100644 --- a/tgui/packages/tgui/interfaces/NtosRobotact.jsx +++ b/tgui/packages/tgui/interfaces/NtosRobotact.jsx @@ -5,11 +5,15 @@ import { AnimatedNumber, Box, Button, + Divider, Flex, LabeledList, + NoticeBox, ProgressBar, Section, Slider, + Stack, + StackDivider, Tabs, } from '../components'; import { formatEnergy } from '../format'; @@ -49,8 +53,11 @@ export const NtosRobotactContent = (props) => { thrustersInstalled, thrustersStatus, selfDestructAble, + cyborg_groups = [], + masterAI_online, + MasterAI_connected, } = data; - const borgName = data.name || []; + const borgName = data.borgName || []; const borgType = data.designation || []; const masterAI = data.masterAI || []; const laws = data.Laws || []; @@ -77,6 +84,14 @@ export const NtosRobotactContent = (props) => { > Logs + setTab_main(3)} + > + Network + {tab_main === 1 && ( @@ -332,6 +347,111 @@ export const NtosRobotactContent = (props) => { )} + {tab_main === 3 && ( + +
+ + + + {!MasterAI_connected + ? 'No Conection' + : masterAI_online + ? 'Online' + : 'Unresponsive'} + + + +
+ + + {cyborg_groups.map((borggroup) => ( + + + {borggroup.map((cyborg) => ( + +
+ + + + {cyborg.status + ? 'Not Responding' + : cyborg.locked_down + ? 'Locked Down' + : cyborg.shell_discon + ? 'Nominal/Disconnected' + : 'Nominal'} + + + + + {cyborg.integ === 0 + ? 'Hard Fault' + : cyborg.integ <= 25 + ? 'Functionality Disrupted' + : cyborg.integ <= 75 + ? 'Functionality Impaired' + : 'Operational'} + + + + + {typeof cyborg.charge === 'number' + ? cyborg.charge + '%' + : 'No Cell'} + + + + {cyborg.module} + + +
+
+ ))} +
+ +
+ ))} +
+ + {!!!cyborg_groups.length && ( + + + CONNECTION UNAVAILABLE -- NETWORK STATUS UNKNOWN + + + )} +
+ )} ); };