mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-27 07:08:00 +01:00
tgui: AI system integrity restorer (#49828)
* AI fixer UI * Cleanup * Polish
This commit is contained in:
@@ -2,12 +2,16 @@
|
||||
name = "\improper AI system integrity restorer"
|
||||
desc = "Used with intelliCards containing nonfunctional AIs to restore them to working order."
|
||||
req_access = list(ACCESS_CAPTAIN, ACCESS_ROBOTICS, ACCESS_HEADS)
|
||||
var/mob/living/silicon/ai/occupier = null
|
||||
var/active = 0
|
||||
circuit = /obj/item/circuitboard/computer/aifixer
|
||||
icon_keyboard = "tech_key"
|
||||
icon_screen = "ai-fixer"
|
||||
light_color = LIGHT_COLOR_PINK
|
||||
ui_x = 370
|
||||
ui_y = 360
|
||||
/// Variable containing transferred AI
|
||||
var/mob/living/silicon/ai/occupier
|
||||
/// Variable dictating if we are in the process of restoring the occupier AI
|
||||
var/restoring = FALSE
|
||||
|
||||
/obj/machinery/computer/aifixer/screwdriver_act(mob/living/user, obj/item/I)
|
||||
if(occupier)
|
||||
@@ -18,60 +22,45 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/aifixer/ui_interact(mob/user)
|
||||
. = ..()
|
||||
/obj/machinery/computer/aifixer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "ai_restorer", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
var/dat = ""
|
||||
/obj/machinery/computer/aifixer/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
if (src.occupier)
|
||||
var/laws
|
||||
dat += "<h3>Stored AI: [src.occupier.name]</h3>"
|
||||
dat += "<b>System integrity:</b> [(src.occupier.health+100)/2]%<br>"
|
||||
data["ejectable"] = FALSE
|
||||
data["AI_present"] = FALSE
|
||||
data["error"] = null
|
||||
if(!occupier)
|
||||
data["error"] = "Please transfer an AI unit."
|
||||
else
|
||||
data["AI_present"] = TRUE
|
||||
data["name"] = occupier.name
|
||||
data["restoring"] = restoring
|
||||
data["health"] = (occupier.health + 100) / 2
|
||||
data["isDead"] = occupier.stat == DEAD
|
||||
data["laws"] = occupier.laws.get_law_list(include_zeroth = 1)
|
||||
|
||||
if (src.occupier.laws.zeroth)
|
||||
laws += "<b>0:</b> [src.occupier.laws.zeroth]<BR>"
|
||||
return data
|
||||
|
||||
for (var/index = 1, index <= src.occupier.laws.hacked.len, index++)
|
||||
var/law = src.occupier.laws.hacked[index]
|
||||
if (length(law) > 0)
|
||||
var/num = ionnum()
|
||||
laws += "<b>[num]:</b> [law]<BR>"
|
||||
/obj/machinery/computer/aifixer/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
if(!occupier)
|
||||
restoring = FALSE
|
||||
|
||||
for (var/index = 1, index <= src.occupier.laws.ion.len, index++)
|
||||
var/law = src.occupier.laws.ion[index]
|
||||
if (length(law) > 0)
|
||||
var/num = ionnum()
|
||||
laws += "<b>[num]:</b> [law]<BR>"
|
||||
|
||||
var/number = 1
|
||||
for (var/index = 1, index <= src.occupier.laws.inherent.len, index++)
|
||||
var/law = src.occupier.laws.inherent[index]
|
||||
if (length(law) > 0)
|
||||
laws += "<b>[number]:</b> [law]<BR>"
|
||||
number++
|
||||
|
||||
for (var/index = 1, index <= src.occupier.laws.supplied.len, index++)
|
||||
var/law = src.occupier.laws.supplied[index]
|
||||
if (length(law) > 0)
|
||||
laws += "<b>[number]:</b> [law]<BR>"
|
||||
number++
|
||||
|
||||
dat += "<b>Laws:</b><br>[laws]<br>"
|
||||
|
||||
if (src.occupier.stat == DEAD)
|
||||
dat += "<span class='bad'>AI non-functional</span>"
|
||||
else
|
||||
dat += "<span class='good'>AI functional</span>"
|
||||
if (!src.active)
|
||||
dat += {"<br><br><A href='byond://?src=[REF(src)];fix=1'>Begin Reconstruction</A>"}
|
||||
else
|
||||
dat += "<br><br>Reconstruction in process, please wait.<br>"
|
||||
dat += {"<br><A href='?src=[REF(user)];mach_close=computer'>Close</A>"}
|
||||
var/datum/browser/popup = new(user, "computer", "AI System Integrity Restorer", 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
switch(action)
|
||||
if("PRG_beginReconstruction")
|
||||
if(occupier?.health < 100)
|
||||
to_chat(usr, "<span class='notice'>Reconstruction in progress. This will take several minutes.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, FALSE)
|
||||
restoring = TRUE
|
||||
occupier.notify_ghost_cloning("Your core files are being restored!", source = src)
|
||||
. = TRUE
|
||||
|
||||
/obj/machinery/computer/aifixer/proc/Fix()
|
||||
use_power(1000)
|
||||
@@ -89,38 +78,24 @@
|
||||
|
||||
/obj/machinery/computer/aifixer/process()
|
||||
if(..())
|
||||
if(active)
|
||||
if(restoring)
|
||||
var/oldstat = occupier.stat
|
||||
active = Fix()
|
||||
restoring = Fix()
|
||||
if(oldstat != occupier.stat)
|
||||
update_icon()
|
||||
updateDialog()
|
||||
|
||||
/obj/machinery/computer/aifixer/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(href_list["fix"])
|
||||
to_chat(usr, "<span class='notice'>Reconstruction in progress. This will take several minutes.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, FALSE)
|
||||
active = TRUE
|
||||
if(occupier)
|
||||
var/mob/living/silicon/ai/A = occupier
|
||||
A.notify_ghost_cloning("Your core files are being restored!", source = src)
|
||||
add_fingerprint(usr)
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/computer/aifixer/update_overlays()
|
||||
. = ..()
|
||||
if(machine_stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if(active)
|
||||
if(restoring)
|
||||
. += "ai-fixer-on"
|
||||
if (occupier)
|
||||
switch (occupier.stat)
|
||||
if (0)
|
||||
if (CONSCIOUS)
|
||||
. += "ai-fixer-full"
|
||||
if (2)
|
||||
if (UNCONSCIOUS)
|
||||
. += "ai-fixer-404"
|
||||
else
|
||||
. += "ai-fixer-empty"
|
||||
@@ -143,14 +118,14 @@
|
||||
update_icon()
|
||||
|
||||
else //Uploading AI from terminal to card
|
||||
if(occupier && !active)
|
||||
if(occupier && !restoring)
|
||||
to_chat(occupier, "<span class='notice'>You have been downloaded to a mobile storage device. Still no remote access.</span>")
|
||||
to_chat(user, "<span class='notice'>Transfer successful</span>: [occupier.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory.")
|
||||
occupier.forceMove(card)
|
||||
card.AI = occupier
|
||||
occupier = null
|
||||
update_icon()
|
||||
else if (active)
|
||||
else if (restoring)
|
||||
to_chat(user, "<span class='alert'>ERROR: Reconstruction in progress.</span>")
|
||||
else if (!occupier)
|
||||
to_chat(user, "<span class='alert'>ERROR: Unable to locate artificial intelligence.</span>")
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
tgui_id = "ntos_ai_restorer"
|
||||
ui_x = 370
|
||||
ui_y = 400
|
||||
|
||||
/// Variable dictating if we are in the process of restoring the AI in the inserted intellicard
|
||||
var/restoring = FALSE
|
||||
|
||||
/datum/computer_file/program/aidiag/proc/get_ai(cardcheck)
|
||||
@@ -95,8 +95,10 @@
|
||||
|
||||
var/obj/item/aicard/aicard = get_ai(2)
|
||||
|
||||
data["ejectable"] = TRUE
|
||||
data["AI_present"] = FALSE
|
||||
data["error"] = null
|
||||
if(!aicard)
|
||||
data["nocard"] = TRUE
|
||||
data["error"] = "Please insert an intelliCard."
|
||||
else
|
||||
if(!AI)
|
||||
@@ -106,12 +108,12 @@
|
||||
if(cardhold.flush)
|
||||
data["error"] = "Flush in progress"
|
||||
else
|
||||
data["AI_present"] = TRUE
|
||||
data["name"] = AI.name
|
||||
data["restoring"] = restoring
|
||||
data["laws"] = AI.laws.get_law_list(include_zeroth = 1)
|
||||
data["health"] = (AI.health + 100) / 2
|
||||
data["isDead"] = AI.stat == DEAD
|
||||
data["ai_laws"] = AI.laws.get_law_list(include_zeroth = 1)
|
||||
data["laws"] = AI.laws.get_law_list(include_zeroth = 1)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend } from "../backend";
|
||||
import { Section, Box, Button, NoticeBox, ProgressBar, LabeledList } from "../components";
|
||||
|
||||
export const AiRestorer = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
const {
|
||||
AI_present,
|
||||
error,
|
||||
name,
|
||||
laws,
|
||||
isDead,
|
||||
restoring,
|
||||
health,
|
||||
ejectable,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{error && (
|
||||
<NoticeBox textAlign="center">
|
||||
{error}
|
||||
</NoticeBox>
|
||||
)}
|
||||
{!!ejectable && (
|
||||
<Button
|
||||
fluid
|
||||
icon="eject"
|
||||
content={AI_present ? name : "----------"}
|
||||
disabled={!AI_present}
|
||||
onClick={() => act('PRG_eject')}
|
||||
/>
|
||||
)}
|
||||
{!!AI_present && (
|
||||
<Section
|
||||
title={ejectable ? "System Status" : name}
|
||||
buttons={(
|
||||
<Box
|
||||
inline
|
||||
bold
|
||||
color={isDead ? 'bad' : 'good'}>
|
||||
{isDead ? "Nonfunctional" : "Functional"}
|
||||
</Box>
|
||||
)}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Integrity">
|
||||
<ProgressBar
|
||||
value={health}
|
||||
minValue={0}
|
||||
maxValue={100}
|
||||
ranges={{
|
||||
good: [70, Infinity],
|
||||
average: [50, 70],
|
||||
bad: [-Infinity, 50],
|
||||
}} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
{!!restoring && (
|
||||
<Box
|
||||
bold
|
||||
textAlign="center"
|
||||
fontSize="20px"
|
||||
color="good"
|
||||
mt={1}>
|
||||
RECONSTRUCTION IN PROGRESS
|
||||
</Box>
|
||||
)}
|
||||
<Button
|
||||
fluid
|
||||
icon="plus"
|
||||
content="Begin Reconstruction"
|
||||
disabled={restoring}
|
||||
mt={1}
|
||||
onClick={() => act('PRG_beginReconstruction')}
|
||||
/>
|
||||
<Section title="Laws" level={2}>
|
||||
{laws.map(law => (
|
||||
<Box key={law} className="candystripe">
|
||||
{law}
|
||||
</Box>
|
||||
))}
|
||||
</Section>
|
||||
</Section>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
@@ -1,87 +0,0 @@
|
||||
import { Section, Box, Button, NoticeBox, ProgressBar, LabeledList } from "../components";
|
||||
import { useBackend } from "../backend";
|
||||
import { Fragment } from "inferno";
|
||||
|
||||
export const NtosAiRestorer = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
|
||||
const {
|
||||
nocard,
|
||||
error,
|
||||
name,
|
||||
ai_laws,
|
||||
isDead,
|
||||
restoring,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{error && (
|
||||
<NoticeBox>
|
||||
{error}
|
||||
</NoticeBox>
|
||||
)}
|
||||
<Section>
|
||||
<Button
|
||||
fluid
|
||||
icon="eject"
|
||||
content={name || "----------"}
|
||||
disabled={!name}
|
||||
onClick={() => act('PRG_eject')}
|
||||
/>
|
||||
{!nocard && (
|
||||
<Section
|
||||
title="System Status"
|
||||
level={2}
|
||||
buttons={(
|
||||
<Box
|
||||
inline
|
||||
bold
|
||||
color={isDead ? 'bad' : 'good'}>
|
||||
{isDead ? "Nonfunctional" : "Functional"}
|
||||
</Box>
|
||||
)}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Integrity">
|
||||
<ProgressBar
|
||||
value={100}
|
||||
minValue={0}
|
||||
maxValue={100}
|
||||
ranges={{
|
||||
good: [70, Infinity],
|
||||
average: [50, 70],
|
||||
bad: [-Infinity, 50],
|
||||
}} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
{!!restoring && (
|
||||
<Box
|
||||
bold
|
||||
textAlign="center"
|
||||
fontSize="20px"
|
||||
color="good"
|
||||
mt={1}>
|
||||
RECONSTRUCTION IN PROGRESS
|
||||
</Box>
|
||||
)}
|
||||
<Button
|
||||
fluid
|
||||
icon="plus"
|
||||
content="Begin Reconstruction"
|
||||
disabled={restoring}
|
||||
mt={1}
|
||||
onClick={() => act('PRG_beginReconstruction')}
|
||||
/>
|
||||
<Section title="laws" level={3}>
|
||||
{ai_laws.map(law => (
|
||||
<Box key={law} className="candystripe">
|
||||
{law}
|
||||
</Box>
|
||||
))}
|
||||
</Section>
|
||||
</Section>
|
||||
)}
|
||||
</Section>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,7 @@
|
||||
import { Achievements } from './interfaces/Achievements';
|
||||
import { AiAirlock } from './interfaces/AiAirlock';
|
||||
import { AirAlarm } from './interfaces/AirAlarm';
|
||||
import { AiRestorer } from './interfaces/AiRestorer';
|
||||
import { AirlockElectronics } from './interfaces/AirlockElectronics';
|
||||
import { Apc } from './interfaces/Apc';
|
||||
import { AtmosAlertConsole } from './interfaces/AtmosAlertConsole';
|
||||
@@ -68,7 +69,6 @@ import { NaniteProgrammer } from './interfaces/NaniteProgrammer';
|
||||
import { NaniteRemote } from './interfaces/NaniteRemote';
|
||||
import { NotificationPreferences } from './interfaces/NotificationPreferences';
|
||||
import { NtnetRelay } from './interfaces/NtnetRelay';
|
||||
import { NtosAiRestorer } from './interfaces/NtosAiRestorer';
|
||||
import { NtosArcade } from './interfaces/NtosArcade';
|
||||
import { NtosCard } from './interfaces/NtosCard';
|
||||
import { NtosConfiguration } from './interfaces/NtosConfiguration';
|
||||
@@ -113,6 +113,7 @@ import { SpaceHeater } from './interfaces/SpaceHeater';
|
||||
import { SpawnersMenu } from './interfaces/SpawnersMenu';
|
||||
import { StationAlertConsole } from './interfaces/StationAlertConsole';
|
||||
import { SuitStorageUnit } from './interfaces/SuitStorageUnit';
|
||||
import { SyndContractor } from './interfaces/SyndContractor';
|
||||
import { Tank } from './interfaces/Tank';
|
||||
import { TankDispenser } from './interfaces/TankDispenser';
|
||||
import { Teleporter } from './interfaces/Teleporter';
|
||||
@@ -124,7 +125,6 @@ import { Uplink } from './interfaces/Uplink';
|
||||
import { VaultController } from './interfaces/VaultController';
|
||||
import { Vending } from './interfaces/Vending';
|
||||
import { Wires } from './interfaces/Wires';
|
||||
import { SyndContractor } from './interfaces/SyndContractor';
|
||||
|
||||
const ROUTES = {
|
||||
achievements: {
|
||||
@@ -139,6 +139,10 @@ const ROUTES = {
|
||||
component: () => AirAlarm,
|
||||
scrollable: true,
|
||||
},
|
||||
ai_restorer: {
|
||||
component: () => AiRestorer,
|
||||
scrollable: true,
|
||||
},
|
||||
airlock_electronics: {
|
||||
component: () => AirlockElectronics,
|
||||
scrollable: false,
|
||||
@@ -419,7 +423,7 @@ const ROUTES = {
|
||||
scrollable: false,
|
||||
},
|
||||
ntos_ai_restorer: {
|
||||
component: () => NtosAiRestorer,
|
||||
component: () => AiRestorer,
|
||||
wrapper: () => NtosWrapper,
|
||||
scrollable: true,
|
||||
theme: 'ntos',
|
||||
|
||||
Reference in New Issue
Block a user