K@@*BCOg!uT$}7lmY#&`dt*_s3k#*CgLG1@M0~osxRin1PVOU
z>u3FfQtEfr?}AWA{}h_Xr0L_%h=
z^8zhF)VtNvY?fNTtA3XN){a^eba5j4AR6#Jh?z7R!0Pc1QNPssUG=+6u%tK=#U;U6
zBxpUsnIjk&N%cFwSZf@0WE?CBT7jVR5&b=MG4;V5r)>Q$P@#^0I+7_0g4l(IBNzfr
zQ$1V1vwrPg+#woB9hDg;U)ZQmq)&b3aqaxvBO
zKB$QgveFXt{C;tIoUE*ba4yggl=W;BP@F5R>xma!;1bzLT4>PyU6xV&y
zB-Li#HIwYE-yPORnOe~Io+n>OuvfoJD-)gaHKX5pBEN@VRX(c;_Ud;IP~OrZ5ES-y
z?Is9CZH?BbJN3JDbD-`L)cRb45F2s?d-c0R*j}`Qpeu4wg0XK-u6}dc*z-`8Cn>>o
z;XK)SYSyiP$FRL<2f<`uxvwU6yZ(csS0|d3Dl
z_}Bhb>Yw@Z5C0qO7pM)vY@k4J_IEGT?@}cD6CoIXZVW$-eRLi{sQi~BxYmfd`dzw9
zZXC-5!+)R|g3$*J5>&wnD8bS|fgoR>+cS;@A3S;|R>8v2C@#m)h>#(unJRm_Lu-B6
zF#HyxI60u(!AA(X$22?N3=4g5Z`V{M)OS
z?JqpJss5i6Ju~f3>pM9oh9DZKO;cUE!v4Ymg5Gj};0XHH&qRX#{e@Q|coGOMvwvrQ
zb6zNcz55Ggg3+tUnJ4H~96_{i##qJUazv5^ft~vcWrF+l8w8zwi$90==1f6wS@!HN
zlnL(Fi#~`(IdYyPXmDFNOeW~IZQ){c-L@4Mwxi>q)Wwt_6UDxGntU&;sSsgFFlszN
z(Av1yJV&GWNX`S}pnG>Sxt3A>R1(a8cNhQ~txE&@1Vhvw$hod=wW*2{j5lFaIF(Uc
zi+>gM$^^MoRS-n~f@LMBOuYgVJQ-Af&32
z;GAOEGc;zCU_+=!u&-xRl|-;5a4Er_UPx6U!Nf`SK^G$5Tr35M?sN3l4Y5w^mY<6tVu={418`TbyO;8h5QD_2|LGeKC3
zn)?V2`(Te?ZqvR?;O{^|@uPO$!3R6@LE%SPlmz3?o+vqOjDw@InTzx{Uzk7Yga32+
Z58c@ {
+ const { act, data } = useBackend(context);
+
+ const [tab, setTab] = useLocalState(context, 'tab', 1);
+
+ return (
+
+
+
+
+
+ {(data.integrity + 100) * 0.5}%
+ System Integrity
+
+
+
+
+ {data.location_name}
+
+ ({data.location_coords})
+
+
+
+
+ Current Uplink Location
+
+
+ {data.temperature}K
+ Current Uplink Temperature
+
+
+
+
+
+ {data.temperature}K
+ Utilized CPU Power
+
+
+ {data.temperature}K
+ Utilized RAM Capacity
+
+
+
+
+
+
+ setTab(1))}>
+ Available Projects
+
+ setTab(2))}>
+ Completed Projects
+
+ setTab(3))}>
+ Cloud Resources
+
+
+ {tab === 3 && (
+
+
+ {data.current_cpu ? data.current_cpu : 0}/{data.max_cpu} THz
+
+
+ {data.current_ram ? data.current_ram : 0 }/{data.max_ram} TB
+
+
+ )}
+
+
+
+
+ );
+};
diff --git a/yogstation.dme b/yogstation.dme
index 23119a259820..ef94e9084bfb 100644
--- a/yogstation.dme
+++ b/yogstation.dme
@@ -2314,7 +2314,9 @@
#include "code\modules\mob\living\silicon\ai\decentralized\decentralized_os.dm"
#include "code\modules\mob\living\silicon\ai\decentralized\expansion_card.dm"
#include "code\modules\mob\living\silicon\ai\decentralized\expansion_card_holder.dm"
+#include "code\modules\mob\living\silicon\ai\decentralized\management\ai_dashboard.dm"
#include "code\modules\mob\living\silicon\ai\decentralized\management\resource_distribution.dm"
+#include "code\modules\mob\living\silicon\ai\decentralized\projects\_ai_project.dm"
#include "code\modules\mob\living\silicon\ai\freelook\cameranet.dm"
#include "code\modules\mob\living\silicon\ai\freelook\chunk.dm"
#include "code\modules\mob\living\silicon\ai\freelook\eye.dm"
From 780777c27fbfad06f908b2b352753a3b982c367e Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Thu, 16 Sep 2021 20:09:49 +0200
Subject: [PATCH 08/46] Update ai_dashboard.dm
---
.../silicon/ai/decentralized/management/ai_dashboard.dm | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm b/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
index c63a725ffbf0..6ae593588e78 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
@@ -59,8 +59,8 @@
data["location_name"] = get_area(current_turf)
data["location_coords"] = "[current_turf.x], [current_turf.y], [current_turf.z]"
-
- data["temperature"] = current_turf?.air.return_temperature()
+ var/datum/gas_mixture/env = current_turf.return_air()
+ data["temperature"] = env.return_temperature()
for(var/datum/ai_project/AP as anything in available_projects)
data["available_projects"] += list(list("name" = AP.name, "description" = AP.description, "ram_required" = AP.ram_required, "available" = AP.available(), "research_requirements" = AP.research_requirements))
From 50fdce72058157cfdd220c6bfe200c192b20615a Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Thu, 23 Sep 2021 19:36:29 +0200
Subject: [PATCH 09/46] zonk
---
.../decentralized/management/ai_dashboard.dm | 39 ++++++++++++++++---
.../ai/decentralized/projects/_ai_project.dm | 12 +++++-
tgui/packages/tgui/interfaces/AiDashboard.js | 36 +++++++++++++----
3 files changed, 72 insertions(+), 15 deletions(-)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm b/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
index 6ae593588e78..c4bc7f35aad9 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
@@ -1,7 +1,10 @@
/datum/ai_dashboard
var/mob/living/silicon/ai/owner
- var/available_projects
+ var/available_projects
+
+ var/cpu_usage
+ var/ram_usage
var/completed_upgrades
@@ -11,8 +14,11 @@
if(!istype(new_owner))
qdel(src)
owner = new_owner
+ available_projects = list()
completed_upgrades = list()
running_upgrades = list()
+ cpu_usage = list()
+ ram_usage = list()
for(var/path in subtypesof(/datum/ai_project))
available_projects += new path()
@@ -44,15 +50,26 @@
return
var/list/data = list()
- data["current_cpu"] = GLOB.ai_os.cpu_assigned[owner]
- data["current_ram"] = GLOB.ai_os.ram_assigned[owner]
+ data["current_cpu"] = GLOB.ai_os.cpu_assigned[owner] ? GLOB.ai_os.cpu_assigned[owner] : 0
+ data["current_ram"] = GLOB.ai_os.ram_assigned[owner] ? GLOB.ai_os.ram_assigned[owner] : 0
+
+ var/total_cpu_used = 0
+ for(var/I in cpu_usage)
+ total_cpu_used += cpu_usage[I]
+
+ var/total_ram_used = 0
+ for(var/I in ram_usage)
+ total_ram_used += ram_usage[I]
+
+ data["used_cpu"] = total_cpu_used
+ data["used_ram"] = total_ram_used
data["max_cpu"] = GLOB.ai_os.total_cpu
data["max_ram"] = GLOB.ai_os.total_ram
data["available_projects"] = list()
- var/turf/current_turf = get_step(src, 0)
+ var/turf/current_turf = get_turf(owner)
data["integrity"] = owner.health
@@ -63,7 +80,8 @@
data["temperature"] = env.return_temperature()
for(var/datum/ai_project/AP as anything in available_projects)
- data["available_projects"] += list(list("name" = AP.name, "description" = AP.description, "ram_required" = AP.ram_required, "available" = AP.available(), "research_requirements" = AP.research_requirements))
+ data["available_projects"] += list(list("name" = AP.name, "description" = AP.description, "ram_required" = AP.ram_required, "available" = AP.available(), "research_cost" = AP.research_cost, "research_progress" = AP.research_progress,
+ "assigned_cpu" = cpu_usage[AP.name] ? cpu_usage[AP.name] : 0, "research_requirements" = AP.research_requirements))
data["completed_projects"] = list()
@@ -79,4 +97,13 @@
return
switch(action)
-
+ if("haha")
+ return
+
+
+
+/datum/ai_dashboard/proc/has_completed_projects(project_name)
+ for(var/datum/ai_project/P as anything in completed_upgrades)
+ if(P.name == project_name)
+ return TRUE
+ return FALSE
diff --git a/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm b/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm
index 19f2dbad6e60..d3a107853ccd 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm
@@ -4,9 +4,19 @@ GLOBAL_LIST_EMPTY(ai_projects)
/datum/ai_project
var/name = "DEBUG"
var/description = "DEBUG"
- var/research_requirements
+ var/research_progress = 0
+ var/research_cost = 0
var/ram_required = 0
var/running = FALSE
+ //Text for available()
+ var/research_requirements
/datum/ai_project/proc/available()
return TRUE
+
+/datum/ai_project/test_project
+ name = "Test Project"
+ description = "I'm a test! How quirky"
+ research_cost = 2
+ ram_required = 1
+ research_requirements = "None"
diff --git a/tgui/packages/tgui/interfaces/AiDashboard.js b/tgui/packages/tgui/interfaces/AiDashboard.js
index 206cd3e0232f..311ddfabeea8 100644
--- a/tgui/packages/tgui/interfaces/AiDashboard.js
+++ b/tgui/packages/tgui/interfaces/AiDashboard.js
@@ -1,6 +1,6 @@
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from '../backend';
-import { Box, Button, Tabs, ProgressBar, Section, Divider, LabeledControls } from '../components';
+import { Box, Button, Tabs, ProgressBar, Section, Divider, LabeledControls, NumberInput } from '../components';
import { Window } from '../layouts';
export const AiDashboard = (props, context) => {
@@ -24,12 +24,11 @@ export const AiDashboard = (props, context) => {
average: [25, 50],
bad: [0, 25]
}}
-
value={(data.integrity + 100) * 0.5}
maxValue={100}>{(data.integrity + 100) * 0.5}%
System Integrity
-
+
{data.location_name}
@@ -51,7 +50,7 @@ export const AiDashboard = (props, context) => {
value={data.temperature}
maxValue={750}>{data.temperature}K
- Current Uplink Temperature
+ Uplink Temperature
@@ -63,9 +62,9 @@ export const AiDashboard = (props, context) => {
average: [250, 750],
bad: [750, Infinity]
}}
- value={data.temperature}
+ value={data.current_cpu}
- maxValue={750}>{data.temperature}K
+ maxValue={data.max_cpu}>{data.current_cpu ? data.current_cpu : 0} THz
Utilized CPU Power
@@ -75,9 +74,9 @@ export const AiDashboard = (props, context) => {
average: [250, 750],
bad: [750, Infinity]
}}
- value={data.temperature}
+ value={data.current_ram}
- maxValue={750}>{data.temperature}K
+ maxValue={data.max_ram}>{data.current_ram ? data.current_ram : 0} TB
Utilized RAM Capacity
@@ -101,6 +100,27 @@ export const AiDashboard = (props, context) => {
Cloud Resources
+ {tab === 1 && (
+
+ {data.available_projects && data.available_projects.map(project => (
+
+ Assigned CPU:
+
+ THz
+
+ )}>
+ Research Cost: {project.research_cost} THz
+ RAM Requiremnt: {project.ram_required} TB
+ Research Requirements: {project.research_requirements}
+
+ {project.description}
+
+
+
+ ))}
+
+ )}
{tab === 3 && (
From 0f02b3ce4e1888db1b72dd5a8f83306da6472e99 Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Tue, 12 Oct 2021 16:16:56 +0200
Subject: [PATCH 10/46] project code
---
.../silicon/ai/decentralized/ai_data_core.dm | 2 +-
.../ai/decentralized/decentralized_os.dm | 1 +
.../decentralized/management/ai_dashboard.dm | 93 +++++++++++++++++--
.../ai/decentralized/projects/_ai_project.dm | 32 ++++++-
.../mob/living/silicon/ai/decentralized_ai.dm | 3 +-
code/modules/mob/living/silicon/ai/life.dm | 4 +-
6 files changed, 122 insertions(+), 13 deletions(-)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm b/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm
index 932c52c30937..c97805848c1c 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm
@@ -45,5 +45,5 @@ GLOBAL_VAR_INIT(primary_data_core, null)
/obj/machinery/ai/data_core/primary
name = "primary AI Data Core"
- desc = "A complicated computer system capable of emulating the neural functions of a human at near-instantanous speeds. This one has a scrawny note saying: 'Primary AI Data Core'"
+ desc = "A complicated computer system capable of emulating the neural functions of a human at near-instantanous speeds. This one has a scrawny and faded note saying: 'Primary AI Data Core'"
primary = TRUE
diff --git a/code/modules/mob/living/silicon/ai/decentralized/decentralized_os.dm b/code/modules/mob/living/silicon/ai/decentralized/decentralized_os.dm
index 2a9491c3e954..3e112cd5f467 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/decentralized_os.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/decentralized_os.dm
@@ -87,6 +87,7 @@ GLOBAL_DATUM_INIT(ai_os, /datum/ai_os, new)
for(var/A in affected_AIs)
to_chat(A, "You have been deducted processing capabilities. Please contact your network administrator if you believe this to be an error.")
+
/datum/ai_os/proc/add_cpu(mob/living/silicon/ai/AI, amount)
if(!AI || !amount)
return
diff --git a/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm b/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
index c4bc7f35aad9..b0724742965d 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
@@ -3,25 +3,27 @@
var/available_projects
+ //What we're currently using, not what we're being granted by the ai data core
var/cpu_usage
var/ram_usage
- var/completed_upgrades
+ var/completed_projects
- var/running_upgrades
+ var/running_projects
/datum/ai_dashboard/New(mob/living/silicon/ai/new_owner)
if(!istype(new_owner))
qdel(src)
owner = new_owner
available_projects = list()
- completed_upgrades = list()
- running_upgrades = list()
+ completed_projects = list()
+ running_projects = list()
cpu_usage = list()
ram_usage = list()
for(var/path in subtypesof(/datum/ai_project))
- available_projects += new path()
+ available_projects += new path(owner, src)
+
/datum/ai_dashboard/proc/is_interactable(mob/user)
if(user != owner || owner.incapacitated())
@@ -85,7 +87,7 @@
data["completed_projects"] = list()
- for(var/datum/ai_project/P as anything in completed_upgrades)
+ for(var/datum/ai_project/P as anything in completed_projects)
data["completed_projects"] += list(list("name" = P.name, "description" = P.description, "ram_required" = P.ram_required, "running" = P.running))
return data
@@ -97,13 +99,86 @@
return
switch(action)
- if("haha")
- return
+ if("add_project_cpu")
+ if(!add_project_cpu(params["project_name"]))
+ to_chat(owner, "Unable to add CPU to [params["project_name"]].")
+ . = TRUE
+ if("remove_project_cpu")
+ remove_project_cpu(params["project_name"]) // Can't fail (hopefully), so no failure check
+ . = TRUE
+ if("run_project")
+ if(!run_project(params["project_name"]))
+ to_chat(owner, "Unable to run the program '[params["project_name"]].'")
+ else
+ to_chat(owner, "Spinning up instance of [params["project_name"]]...")
+ . = TRUE
+ if("stop_project")
+ stop_project(params["project_name"]) // Can't fail (hopefully), so no failure check
+ to_chat(owner, "Instance of [params["project_name"]] succesfully ended.")
+ . = TRUE
+
+
+
+/datum/ai_dashboard/proc/add_project_cpu(datum/ai_project/project)
+ var/current_cpu = GLOB.ai_os.cpu_assigned[owner] ? GLOB.ai_os.cpu_assigned[owner] : 0
+ if(!project.canResearch())
+ return FALSE
+
+ if(current_cpu > 0)
+ cpu_usage[project.name]++
+ return TRUE
+
+/datum/ai_dashboard/proc/remove_project_cpu(datum/ai_project/project)
+ if(cpu_usage[project.name])
+ cpu_usage[project.name]--
+ return TRUE
+/datum/ai_dashboard/proc/run_project(datum/ai_project/project)
+ var/current_ram = GLOB.ai_os.ram_assigned[owner] ? GLOB.ai_os.ram_assigned[owner] : 0
+
+ var/total_ram_used = 0
+ for(var/I in ram_usage)
+ total_ram_used += ram_usage[I]
+
+ if(current_ram - total_ram_used > project.ram_required && project.canRun())
+ project.run_project()
+ ram_usage[project.name] += project.ram_required
+ return TRUE
+ return FALSE
+
+/datum/ai_dashboard/proc/stop_project(datum/ai_project/project)
+ project.stop()
+ if(ram_usage[project.name])
+ ram_usage[project.name] -= project.ram_required
+
+ return TRUE
/datum/ai_dashboard/proc/has_completed_projects(project_name)
- for(var/datum/ai_project/P as anything in completed_upgrades)
+ for(var/datum/ai_project/P as anything in completed_projects)
if(P.name == project_name)
return TRUE
return FALSE
+
+
+/datum/ai_dashboard/proc/finish_project(datum/ai_project/project, notify_user = TRUE)
+ available_projects -= project
+ completed_projects += project
+ cpu_usage[project.name] = 0
+ if(notify_user)
+ to_chat(owner, "[project] has been completed. User input required.")
+
+
+//Stuff is handled in here per tick :)
+/datum/ai_dashboard/proc/tick(seconds)
+ for(var/project_being_researched in cpu_usage)
+ if(!cpu_usage[project_being_researched])
+ continue
+ var/used_cpu = round(cpu_usage[project_being_researched] * seconds, 1)
+ var/datum/ai_project/project = locate(project_being_researched) in completed_projects
+ if(!project)
+ cpu_usage[project_being_researched] = 0
+ project.research_progress += used_cpu
+ if(project.research_progress > project.research_cost)
+ finish_project(project)
+
diff --git a/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm b/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm
index d3a107853ccd..d0bafda9eae0 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm
@@ -2,18 +2,48 @@ GLOBAL_LIST_EMPTY(ai_projects)
/datum/ai_project
+ ///Name of the project. This is used as an ID so please keep all names unique (Or refactor it to use an ID like you should)
var/name = "DEBUG"
var/description = "DEBUG"
var/research_progress = 0
+ ///Research cost of project in seconds of CPU time.
var/research_cost = 0
var/ram_required = 0
var/running = FALSE
- //Text for available()
+ //Text for canResearch()
var/research_requirements
+ var/mob/living/silicon/ai/ai
+ var/datum/ai_dashboard/dashboard
+
+/datum/ai_project/New(new_ai, new_dash)
+ ai = new_ai
+ dashboard = new_dash
+ if(!ai || !dashboard)
+ qdel(src)
+ ..()
+
+
+/datum/ai_project/proc/canResearch()
+ return TRUE
+
/datum/ai_project/proc/available()
return TRUE
+/datum/ai_project/proc/run_project(force_run = FALSE)
+ if(!force_run)
+ if(!canRun())
+ return FALSE
+ running = TRUE
+
+
+//Important! This isn't for checking processing requirements. That is checked on the AI for ease of references (See ai_dashboard.dm). This is just for special cases (Don't want the program to run while X runs or similar)
+/datum/ai_project/proc/canRun()
+ return !running
+
+/datum/ai_project/proc/stop()
+ return TRUE
+
/datum/ai_project/test_project
name = "Test Project"
description = "I'm a test! How quirky"
diff --git a/code/modules/mob/living/silicon/ai/decentralized_ai.dm b/code/modules/mob/living/silicon/ai/decentralized_ai.dm
index 68c301325424..a09c1deba3fd 100644
--- a/code/modules/mob/living/silicon/ai/decentralized_ai.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized_ai.dm
@@ -36,6 +36,7 @@
sleep(0.5 SECONDS)
to_chat(src, "System shutdown complete. Thank you for using NTOS.")
sleep(1.5 SECONDS)
- qdel(src)
+ adjustOxyLoss(200) //Die!!
+ QDEL_IN(src, 5 SECONDS)
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index 15a9a6f84649..ff02a8c6020f 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -3,7 +3,7 @@
#define POWER_RESTORATION_SEARCH_APC 2
#define POWER_RESTORATION_APC_FOUND 3
-/mob/living/silicon/ai/Life()
+/mob/living/silicon/ai/Life(seconds)
if (stat == DEAD)
return
else //I'm not removing that shitton of tabs, unneeded as they are. -- Urist
@@ -12,6 +12,8 @@
update_gravity(mob_has_gravity())
handle_status_effects()
+ if(dashboard)
+ dashboard.tick(seconds)
if(malfhack && malfhack.aidisabled)
deltimer(malfhacking)
From 4de4c64075c1a8266934b839763868768f68dc87 Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Tue, 12 Oct 2021 17:15:15 +0200
Subject: [PATCH 11/46] bug fixing for 30 minutes i love it
---
.../ai/decentralized/expansion_card_holder.dm | 8 +
.../management/resource_distribution.dm | 71 +++++++-
tgui/packages/tgui/interfaces/AiResources.js | 160 ++++++++++++------
3 files changed, 175 insertions(+), 64 deletions(-)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm b/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm
index a62c8aa57fb9..952ac12019d8 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm
@@ -15,6 +15,7 @@ GLOBAL_LIST_EMPTY(expansion_card_holders)
..()
installed_cards = list()
GLOB.expansion_card_holders += src
+ update_icon()
/obj/machinery/ai/expansion_card_holder/Destroy()
installed_cards = list()
@@ -26,6 +27,13 @@ GLOBAL_LIST_EMPTY(expansion_card_holders)
GLOB.ai_os.update_hardware()
..()
+/obj/machinery/ai/expansion_card_holder/update_icon()
+ cut_overlays()
+
+ if(!(stat & (BROKEN|NOPOWER|EMPED)))
+ var/mutable_appearance/on_overlay = mutable_appearance(icon, "[initial(icon_state)]_on")
+ add_overlay(on_overlay)
+
/obj/machinery/ai/expansion_card_holder/attackby(obj/item/W, mob/living/user, params)
if(istype(W, /obj/item/processing_card) || istype(W, /obj/item/memory_card))
if(installed_cards.len >= max_cards)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/management/resource_distribution.dm b/code/modules/mob/living/silicon/ai/decentralized/management/resource_distribution.dm
index 631d4029e1af..97044a4c0768 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/management/resource_distribution.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/management/resource_distribution.dm
@@ -1,7 +1,7 @@
/obj/machinery/computer/ai_resource_distribution
name = "\improper AI system resource distribution"
desc = "Used for distributing processing resources across the current artificial intelligences."
- req_access = list(ACCESS_CAPTAIN, ACCESS_ROBOTICS, ACCESS_HEADS)
+ req_access = list(ACCESS_ROBOTICS)
circuit = /obj/item/circuitboard/computer/aifixer
icon_keyboard = "tech_key"
icon_screen = "ai-fixer"
@@ -16,13 +16,51 @@
ui = new(user, src, "AiResources", name)
ui.open()
-/obj/machinery/computer/ai_resource_distribution/ui_data(mob/user)
+/obj/machinery/computer/ai_resource_distribution/ui_data(mob/living/carbon/human/user)
var/list/data = list()
- data["authenticated"] = authenticated;
+ data["authenticated"] = authenticated
+
+ if(issilicon(user))
+ var/mob/living/silicon/borg = user
+ data["username"] = borg.name
+ data["has_access"] = TRUE
+
+ if(IsAdminGhost(user))
+ data["username"] = user.client.holder.admin_signature
+ data["has_access"] = TRUE
+
+ if(ishuman(user))
+ var/username = user.get_authentification_name("Unknown")
+ data["username"] = user.get_authentification_name("Unknown")
+ if(username != "Unknown")
+ var/datum/data/record/record
+ for(var/RP in GLOB.data_core.general)
+ var/datum/data/record/R = RP
+
+ if(!istype(R))
+ continue
+ if(R.fields["name"] == username)
+ record = R
+ break
+ if(record)
+ if(istype(record.fields["photo_front"], /obj/item/photo))
+ var/obj/item/photo/P1 = record.fields["photo_front"]
+ var/icon/picture = icon(P1.picture.picture_image)
+ picture.Crop(10, 32, 22, 22)
+ var/md5 = md5(fcopy_rsc(picture))
+
+ if(!SSassets.cache["photo_[md5]_cropped.png"])
+ SSassets.transport.register_asset("photo_[md5]_cropped.png", picture)
+ SSassets.transport.send_assets(user, list("photo_[md5]_cropped.png" = picture))
+
+ data["user_image"] = SSassets.transport.get_asset_url("photo_[md5]_cropped.png")
+ data["has_access"] = check_access(user.get_idcard())
+
if(!authenticated)
return data
+
data["total_cpu"] = GLOB.ai_os.total_cpu
data["total_ram"] = GLOB.ai_os.total_ram
@@ -33,15 +71,11 @@
data["total_assigned_cpu"] = GLOB.ai_os.total_cpu_assigned()
data["total_assigned_ram"] = GLOB.ai_os.total_ram_assigned()
- for(var/AI in data["assigned_cpu"])
- data["assigned_cpu"][AI].name = REF(AI)
- for(var/AI in data["assigned_ram"])
- data["assigned_ram"][AI].name = REF(AI)
data["ais"] = list()
for(var/mob/living/silicon/ai/A in GLOB.ai_list)
- data["ais"] += list(list("name" = A.name, "ref" = REF(A)))
+ data["ais"] += list(list("name" = A.name, "ref" = REF(A), "assigned_cpu" = data["assigned_cpu"][A] ? data["assigned_cpu"][A] : 0, "assigned_ram" = data["assigned_ram"][A] ? data["assigned_ram"][A] : 0))
return data
@@ -50,9 +84,30 @@
return
if(!authenticated)
+ if(action == "log_in")
+ if(issilicon(usr))
+ authenticated = TRUE
+ return
+
+ if(IsAdminGhost(usr))
+ authenticated = TRUE
+
+
+
+
+ var/mob/living/carbon/human/H = usr
+ if(!istype(H))
+ return
+
+ if(check_access(H.get_idcard()))
+ authenticated = TRUE
return
switch(action)
+ if("log_out")
+ authenticated = FALSE
+ . = TRUE
+
if("clear_ai_resources")
var/mob/living/silicon/ai/target_ai = locate(params["targetAI"])
if(!istype(target_ai))
diff --git a/tgui/packages/tgui/interfaces/AiResources.js b/tgui/packages/tgui/interfaces/AiResources.js
index da165914ff95..c6982568e5bb 100644
--- a/tgui/packages/tgui/interfaces/AiResources.js
+++ b/tgui/packages/tgui/interfaces/AiResources.js
@@ -1,77 +1,125 @@
import { Fragment } from 'inferno';
import { useBackend, useSharedState } from '../backend';
-import { Box, Button, LabeledList, Slider, ProgressBar, Section, Flex } from '../components';
+import { Box, Button, LabeledList, Slider, ProgressBar, Section, Flex, Icon, NoticeBox } from '../components';
import { Window } from '../layouts';
export const AiResources = (props, context) => {
const { act, data } = useBackend(context);
+ const { username, has_access } = data
+
return (
-
-
-
+ act("log_out")}>Log Out
+ )}>
+ {data.total_assigned_cpu}/{data.total_cpu} THz
+
+
+ {data.total_assigned_cpu}/{data.total_cpu} THz
-
-
- {data.total_assigned_ram}/{data.total_ram} TB
-
-
-
+ value={data.total_assigned_ram}
+ maxValue={data.total_ram}>{data.total_assigned_ram}/{data.total_ram} TB
+
+
+
- {data.ais.map(ai => {
- return (
- act("clear_ai_resources", { targetAI: ai.ref })}>Clear AI Resources
- )}>
-
- CPU Capacity:
-
- {data.assigned_cpu[ai.ref] ? data.assigned_cpu[ai.ref] : 0} THz
-
-
-
+ {data.ais.map(ai => {
+ return (
+ act("clear_ai_resources", { targetAI: ai.ref })}>Clear AI Resources
+ )}>
+
+ CPU Capacity:
+
+ {ai.assigned_cpu} THz
+
+
+
-
-
- RAM Capacity:
-
- {data.assigned_ram[ai.ref] ? data.assigned_ram[ai.ref] : 0} TB
-
-
-
+
+
+ RAM Capacity:
+
+ {ai.assigned_ram} TB
+
+
+
-
-
- );
- })}
-
-
+