Merge pull request #16410 from ShadowLarkens/medical

Medical UI fixes and tweaks
This commit is contained in:
Heroman3003
2024-10-04 06:47:05 +10:00
committed by GitHub
26 changed files with 403 additions and 322 deletions
+131 -116
View File
@@ -17,7 +17,9 @@
var/list/temp = null
var/menu = MENU_MAIN //Which menu screen to display
var/datum/transhuman/body_record/active_br = null
var/can_grow_active = FALSE
var/datum/transhuman/mind_record/active_mr = null
var/can_sleeve_active = FALSE
var/organic_capable = 1
var/synthetic_capable = 1
var/obj/item/disk/transcore/disk
@@ -25,6 +27,7 @@
var/obj/machinery/transhuman/synthprinter/selected_printer
var/obj/machinery/transhuman/resleever/selected_sleever
// Resleeving database this machine interacts with. Blank for default database
// Needs a matching /datum/transcore_db with key defined in code
var/db_key
@@ -103,7 +106,7 @@
active_br = new /datum/transhuman/body_record(brDisk.stored) // Loads a COPY!
to_chat(user, "<span class='notice'>\The [src] loads the body record from \the [W] before ejecting it.</span>")
attack_hand(user)
view_b_rec("view_b_rec", list("ref" = "\ref[active_br]"))
view_b_rec(REF(active_br))
else
..()
return
@@ -140,121 +143,111 @@
var/data[0]
data["menu"] = menu
var/list/temppods[0]
var/list/clonepods = list()
for(var/obj/machinery/clonepod/transhuman/pod in pods)
var/status = "idle"
if(pod.mess)
status = "mess"
else if(pod.occupant && !(pod.stat & NOPOWER))
status = "cloning"
temppods.Add(list(list(
"pod" = "\ref[pod]",
clonepods += list(list(
"pod" = REF(pod),
"name" = sanitize(capitalize(pod.name)),
"biomass" = pod.get_biomass(),
"status" = status,
"progress" = (pod.occupant && pod.occupant.stat != DEAD) ? pod.get_completion() : 0
)))
data["pods"] = temppods.Copy()
temppods.Cut()
))
data["pods"] = clonepods
var/list/synthpods = list()
for(var/obj/machinery/transhuman/synthprinter/spod in spods)
temppods.Add(list(list(
"spod" = "\ref[spod]",
synthpods += list(list(
"spod" = REF(spod),
"name" = sanitize(capitalize(spod.name)),
"busy" = spod.busy,
"steel" = spod.stored_material[MAT_STEEL],
"glass" = spod.stored_material[MAT_GLASS]
)))
data["spods"] = temppods.Copy()
temppods.Cut()
))
data["spods"] = synthpods
var/list/resleevers = list()
for(var/obj/machinery/transhuman/resleever/resleever in sleevers)
temppods.Add(list(list(
"sleever" = "\ref[resleever]",
resleevers += list(list(
"sleever" = REF(resleever),
"name" = sanitize(capitalize(resleever.name)),
"occupied" = !!resleever.occupant,
"occupant" = resleever.occupant ? resleever.occupant.real_name : "None"
)))
data["sleevers"] = temppods.Copy()
temppods.Cut()
))
data["sleevers"] = resleevers
data["coredumped"] = our_db.core_dumped
data["emergency"] = disk
data["temp"] = temp
data["selected_pod"] = "\ref[selected_pod]"
data["selected_printer"] = "\ref[selected_printer]"
data["selected_sleever"] = "\ref[selected_sleever]"
data["selected_pod"] = REF(selected_pod)
data["selected_printer"] = REF(selected_printer)
data["selected_sleever"] = REF(selected_sleever)
var/bodyrecords_list_ui[0]
var/list/bodyrecords_list_ui = list()
for(var/N in our_db.body_scans)
var/datum/transhuman/body_record/BR = our_db.body_scans[N]
bodyrecords_list_ui[++bodyrecords_list_ui.len] = list("name" = N, "recref" = "\ref[BR]")
bodyrecords_list_ui += list(list(
"name" = N,
"recref" = REF(BR)
))
data["bodyrecords"] = bodyrecords_list_ui
var/mindrecords_list_ui[0]
var/list/mindrecords_list_ui = list()
for(var/N in our_db.backed_up)
var/datum/transhuman/mind_record/MR = our_db.backed_up[N]
mindrecords_list_ui[++mindrecords_list_ui.len] = list("name" = N, "recref" = "\ref[MR]")
mindrecords_list_ui += list(list(
"name" = N,
"recref" = REF(MR)
))
data["mindrecords"] = mindrecords_list_ui
data["modal"] = tgui_modal_data(src)
data["active_b_rec"] = null
if(active_br)
data["active_b_rec"] = list(
activerecord = REF(active_br),
realname = sanitize(active_br.mydna.name),
species = active_br.speciesname ? active_br.speciesname : active_br.mydna.dna.species,
sex = active_br.bodygender,
mind_compat = active_br.locked ? "Low" : "High",
synthetic = active_br.synthetic,
oocnotes = active_br.body_oocnotes ? active_br.body_oocnotes : "None",
can_grow_active = can_grow_active,
)
data["active_m_rec"] = null
if(active_mr)
data["active_m_rec"] = list(
activerecord = REF(active_mr),
realname = sanitize(active_mr.mindname),
obviously_dead = active_mr.dead_state == MR_DEAD ? "Past-due" : "Current",
oocnotes = active_mr.mind_oocnotes ? active_mr.mind_oocnotes : "None.",
can_sleeve_active = can_sleeve_active,
)
return data
/obj/machinery/computer/transhuman/resleeving/tgui_act(action, params)
if(..())
return TRUE
. = TRUE
switch(tgui_modal_act(src, action, params))
if(TGUI_MODAL_ANSWER)
// if(params["id"] == "del_rec" && active_record)
// var/obj/item/card/id/C = usr.get_active_hand()
// if(!istype(C) && !istype(C, /obj/item/pda))
// set_temp("ID not in hand.", "danger")
// return
// if(check_access(C))
// records.Remove(active_record)
// qdel(active_record)
// set_temp("Record deleted.", "success")
// menu = MENU_RECORDS
// else
// set_temp("Access denied.", "danger")
return
. = ..()
if(.)
return
switch(action)
if("view_b_rec")
view_b_rec(action, params)
view_b_rec(params["ref"])
. = TRUE
if("clear_b_rec")
active_br = null
. = TRUE
if("view_m_rec")
var/ref = params["ref"]
if(!length(ref))
return
active_mr = locate(ref)
if(istype(active_mr))
if(isnull(active_mr.ckey))
qdel(active_mr)
set_temp("Error: Record corrupt.", "danger")
else
var/can_sleeve_active = 1
if(!LAZYLEN(sleevers))
can_sleeve_active = 0
set_temp("Error: Cannot sleeve due to no sleevers.", "danger")
if(!selected_sleever)
can_sleeve_active = 0
set_temp("Error: Cannot sleeve due to no selected sleever.", "danger")
if(selected_sleever && !selected_sleever.occupant)
can_sleeve_active = 0
set_temp("Error: Cannot sleeve due to lack of sleever occupant.", "danger")
var/list/payload = list(
activerecord = "\ref[active_mr]",
realname = sanitize(active_mr.mindname),
obviously_dead = active_mr.dead_state == MR_DEAD ? "Past-due" : "Current",
oocnotes = active_mr.mind_oocnotes ? active_mr.mind_oocnotes : "None.",
can_sleeve_active = can_sleeve_active,
)
tgui_modal_message(src, action, "", null, payload)
else
active_mr = null
set_temp("Error: Record missing.", "danger")
view_m_rec(params["ref"])
. = TRUE
if("clear_m_rec")
active_mr = null
. = TRUE
if("coredump")
if(disk)
our_db.core_dump(disk)
@@ -262,11 +255,13 @@
visible_message("<span class='warning'>\The [src] spits out \the [disk].</span>")
disk.forceMove(get_turf(src))
disk = null
. = TRUE
if("ejectdisk")
disk.forceMove(get_turf(src))
disk = null
. = TRUE
if("create")
. = TRUE
if(istype(active_br))
//Tried to grow a synth but no synth pods.
if(active_br.synthetic && !spods.len)
@@ -281,32 +276,39 @@
var/obj/machinery/transhuman/synthprinter/spod = selected_printer
if(!istype(spod))
set_temp("Error: No SynthFab selected.", "danger")
active_br = null
return
//Already doing someone.
if(spod.busy)
set_temp("Error: SynthFab is currently busy.", "danger")
active_br = null
return
//Not enough steel or glass
else if(spod.stored_material[MAT_STEEL] < spod.body_cost)
set_temp("Error: Not enough [MAT_STEEL] in SynthFab.", "danger")
active_br = null
return
else if(spod.stored_material["glass"] < spod.body_cost)
set_temp("Error: Not enough glass in SynthFab.", "danger")
active_br = null
return
//Gross pod (broke mid-cloning or something).
else if(spod.broken)
set_temp("Error: SynthFab malfunction.", "danger")
active_br = null
return
//Do the cloning!
else if(spod.print(active_br))
set_temp("Initiating printing cycle...", "success")
active_br = null
menu = 1
else
set_temp("Initiating printing cycle... Error: Post-initialisation failed. Printing cycle aborted.", "danger")
active_br = null
return
//We're cloning an organic.
@@ -314,59 +316,58 @@
var/obj/machinery/clonepod/transhuman/pod = selected_pod
if(!istype(pod))
set_temp("Error: No clonepod selected.", "danger")
tgui_modal_clear(src)
active_br = null
return
//Already doing someone.
if(pod.occupant)
set_temp("Error: Growpod is currently occupied.", "danger")
tgui_modal_clear(src)
active_br = null
return
//Not enough materials.
else if(pod.get_biomass() < CLONE_BIOMASS)
set_temp("Error: Not enough biomass.", "danger")
tgui_modal_clear(src)
active_br = null
return
//Gross pod (broke mid-cloning or something).
else if(pod.mess)
set_temp("Error: Growpod malfunction.", "danger")
tgui_modal_clear(src)
active_br = null
return
//Disabled in config.
else if(!config.revival_cloning)
set_temp("Error: Unable to initiate growing cycle.", "danger")
tgui_modal_clear(src)
active_br = null
return
//Do the cloning!
else if(pod.growclone(active_br))
set_temp("Initiating growing cycle...", "success")
tgui_modal_clear(src)
active_br = null
else
set_temp("Initiating growing cycle... Error: Post-initialisation failed. Growing cycle aborted.", "danger")
tgui_modal_clear(src)
active_br = null
return
//The body record is broken somehow.
else
set_temp("Error: Data corruption.", "danger")
tgui_modal_clear(src)
return
active_br = null
if("sleeve")
if(istype(active_mr))
. = TRUE
if(!sleevers.len)
set_temp("Error: No sleevers detected.", "danger")
active_mr = null
else
var/mode = text2num(params["mode"])
var/override
var/obj/machinery/transhuman/resleever/sleever = selected_sleever
if(!istype(sleever))
set_temp("Error: No resleeving pod selected.", "danger")
tgui_modal_clear(src)
active_mr = null
return
switch(mode)
@@ -374,13 +375,13 @@
//No body to sleeve into.
if(!sleever.occupant)
set_temp("Error: Resleeving pod is not occupied.", "danger")
tgui_modal_clear(src)
active_mr = null
return
//OOC body lock thing.
if(sleever.occupant.resleeve_lock && active_mr.ckey != sleever.occupant.resleeve_lock)
set_temp("Error: Mind incompatible with body.", "danger")
tgui_modal_clear(src)
active_mr = null
return
var/list/subtargets = list()
@@ -393,13 +394,13 @@
override = tgui_input_list(usr,"Multiple bodies detected. Select target for resleeving of [active_mr.mindname] manually. Sleeving of primary body is unsafe with sub-contents, and is not listed.", "Resleeving Target", subtargets)
if(!override || oc_sanity != sleever.occupant || !(override in sleever.occupant))
set_temp("Error: Target selection aborted.", "danger")
tgui_modal_clear(src)
active_mr = null
return
if(2) //Card resleeving
if(sleever.sleevecards <= 0)
set_temp("Error: No available cards in resleever.", "danger")
tgui_modal_clear(src)
active_mr = null
return
//Body to sleeve into, but mind is in another living body.
@@ -409,16 +410,14 @@
//They declined to be moved.
if(answer != "Yes")
set_temp("Initiating resleeving... Error: Post-initialisation failed. Resleeving cycle aborted.", "danger")
tgui_modal_clear(src)
active_mr = null
return TRUE
//They were dead, or otherwise available.
sleever.putmind(active_mr,mode,override,db_key = db_key)
set_temp("Initiating resleeving...")
tgui_modal_clear(src)
active_mr = null
if("refresh")
SStgui.update_uis(src)
if("selectpod")
var/ref = params["ref"]
if(!length(ref))
@@ -426,6 +425,7 @@
var/obj/machinery/clonepod/selected = locate(ref)
if(istype(selected) && (selected in pods))
selected_pod = selected
. = TRUE
if("selectprinter")
var/ref = params["ref"]
if(!length(ref))
@@ -433,6 +433,7 @@
var/obj/machinery/transhuman/synthprinter/selected = locate(ref)
if(istype(selected) && (selected in spods))
selected_printer = selected
. = TRUE
if("selectsleever")
var/ref = params["ref"]
if(!length(ref))
@@ -440,12 +441,13 @@
var/obj/machinery/transhuman/resleever/selected = locate(ref)
if(istype(selected) && (selected in sleevers))
selected_sleever = selected
. = TRUE
if("menu")
menu = clamp(text2num(params["num"]), MENU_MAIN, MENU_MIND)
. = TRUE
if("cleartemp")
temp = null
else
return FALSE
. = TRUE
// In here because only relevant to computer
/obj/item/cmo_disk_holder
@@ -489,40 +491,53 @@
if(update_now)
SStgui.update_uis(src)
/obj/machinery/computer/transhuman/resleeving/proc/view_b_rec(action, params)
var/ref = params["ref"]
/obj/machinery/computer/transhuman/resleeving/proc/view_b_rec(ref)
if(!length(ref))
return
active_br = locate(ref)
if(istype(active_br))
var/can_grow_active = 1
can_grow_active = TRUE
if(!synthetic_capable && active_br.synthetic) //Disqualified due to being synthetic in an organic only.
can_grow_active = 0
can_grow_active = FALSE
set_temp("Error: Cannot grow [active_br.mydna.name] due to lack of synthfabs.", "danger")
else if(!organic_capable && !active_br.synthetic) //Disqualified for the opposite.
can_grow_active = 0
can_grow_active = FALSE
set_temp("Error: Cannot grow [active_br.mydna.name] due to lack of cloners.", "danger")
else if(!synthetic_capable && !organic_capable) //What have you done??
can_grow_active = 0
can_grow_active = FALSE
set_temp("Error: Cannot grow [active_br.mydna.name] due to lack of synthfabs and cloners.", "danger")
else if(active_br.toocomplex)
can_grow_active = 0
can_grow_active = FALSE
set_temp("Error: Cannot grow [active_br.mydna.name] due to species complexity.", "danger")
var/list/payload = list(
activerecord = "\ref[active_br]",
realname = sanitize(active_br.mydna.name),
species = active_br.speciesname ? active_br.speciesname : active_br.mydna.dna.species,
sex = active_br.bodygender,
mind_compat = active_br.locked ? "Low" : "High",
synthetic = active_br.synthetic,
oocnotes = active_br.body_oocnotes ? active_br.body_oocnotes : "None",
can_grow_active = can_grow_active,
)
tgui_modal_message(src, action, "", null, payload)
else
active_br = null
set_temp("Error: Record missing.", "danger")
/obj/machinery/computer/transhuman/resleeving/proc/view_m_rec(ref)
if(!length(ref))
return
active_mr = locate(ref)
if(istype(active_mr))
if(isnull(active_mr.ckey))
qdel(active_mr)
set_temp("Error: Record corrupt.", "danger")
else
can_sleeve_active = TRUE
if(!LAZYLEN(sleevers))
can_sleeve_active = FALSE
set_temp("Error: Cannot sleeve due to no sleevers.", "danger")
if(!selected_sleever)
can_sleeve_active = FALSE
set_temp("Error: Cannot sleeve due to no selected sleever.", "danger")
if(selected_sleever && !selected_sleever.occupant)
can_sleeve_active = FALSE
set_temp("Error: Cannot sleeve due to lack of sleever occupant.", "danger")
else
active_mr = null
set_temp("Error: Record missing.", "danger")
#undef MENU_MAIN
#undef MENU_BODY
#undef MENU_MIND
@@ -62,7 +62,7 @@ export const BodyScannerMainOccupant = (props: { occupant: occupant }) => {
value={occupant.blood.volume}
format={(value) => toFixed(value)}
/>
units&nbsp;(
u&nbsp;(
<AnimatedNumber
value={occupant.blood.percent}
format={(value) => toFixed(value)}
@@ -70,10 +70,8 @@ export const BodyScannerMainOccupant = (props: { occupant: occupant }) => {
%)
</LabeledList.Item>
<LabeledList.Item label="Weight">
{toFixed(occupant.weight) +
'lbs, ' +
toFixed(occupant.weight / 2.20463) +
'kgs'}
{toFixed(occupant.weight / 2.20463, 1) + 'kg, '}
{toFixed(occupant.weight) + 'lbs'}
</LabeledList.Item>
</LabeledList>
</Section>
@@ -51,18 +51,17 @@ export const BodyScannerMainOrgansExternal = (props: {
inline
>
{!!o.bruteLoss && (
<Box inline position="relative">
<Icon name="bone" />
<Tooltip content="Brute damage" position="top">
<Icon name="band-aid" />
{toFixed(o.bruteLoss)}&nbsp;
<Tooltip position="top" content="Brute damage" />
</Box>
</Tooltip>
)}
{!!o.fireLoss && (
<Box inline position="relative">
<Tooltip content="Burn damage" position="top">
<Icon name="fire" />
{toFixed(o.fireLoss)}
<Tooltip position="top" content="Burn damage" />
</Box>
</Tooltip>
)}
</Box>
<Box inline>{toFixed(o.totalLoss)}</Box>
@@ -1,5 +1,6 @@
import { useBackend } from '../../backend';
import { Box, Button, Input } from '../../components';
import { useBackend } from 'tgui/backend';
import { Box, Button, Input } from 'tgui-core/components';
import { Data } from './types';
export const MedicalRecordsList = (props) => {
@@ -1,5 +1,6 @@
import { useBackend } from '../../backend';
import { Box, Collapsible, LabeledList } from '../../components';
import { useBackend } from 'tgui/backend';
import { Box, Collapsible, LabeledList } from 'tgui-core/components';
import { Data } from './types';
export const MedicalRecordsMedbots = (props) => {
@@ -1,5 +1,6 @@
import { useBackend } from '../../backend';
import { Button, Icon, Section, Tabs } from '../../components';
import { useBackend } from 'tgui/backend';
import { Button, Section, Tabs } from 'tgui-core/components';
import { MedicalRecordsViewGeneral } from './MedicalRecordsViewGeneral';
import { MedicalRecordsViewMedical } from './MedicalRecordsViewMedical';
import { Data } from './types';
@@ -73,29 +74,29 @@ export const MedicalRecordsNavigation = (props) => {
<Tabs.Tab
selected={screen === 2}
onClick={() => act('screen', { screen: 2 })}
icon="list"
>
<Icon name="list" />
List Records
</Tabs.Tab>
<Tabs.Tab
selected={screen === 5}
onClick={() => act('screen', { screen: 5 })}
icon="database"
>
<Icon name="database" />
Virus Database
</Tabs.Tab>
<Tabs.Tab
selected={screen === 6}
onClick={() => act('screen', { screen: 6 })}
icon="plus-square"
>
<Icon name="plus-square" />
Medbot Tracking
</Tabs.Tab>
<Tabs.Tab
selected={screen === 3}
onClick={() => act('screen', { screen: 3 })}
icon="wrench"
>
<Icon name="wrench" />
Record Maintenance
</Tabs.Tab>
</Tabs>
@@ -1,5 +1,6 @@
import { useBackend } from '../../backend';
import { Box, Button, Image, LabeledList } from '../../components';
import { useBackend } from 'tgui/backend';
import { Box, Button, Image, LabeledList, Stack } from 'tgui-core/components';
import { doEdit } from '../GeneralRecords/functions';
import { Data } from './types';
@@ -10,13 +11,8 @@ export const MedicalRecordsViewGeneral = (props) => {
return <Box color="bad">General records lost!</Box>;
}
return (
<>
<Box
width="50%"
style={{
float: 'left',
}}
>
<Stack>
<Stack.Item grow>
<LabeledList>
{general.fields.map((field, i) => (
<LabeledList.Item key={i} label={field.field}>
@@ -33,14 +29,8 @@ export const MedicalRecordsViewGeneral = (props) => {
</LabeledList.Item>
))}
</LabeledList>
</Box>
<Box
width="50%"
style={{
float: 'right',
}}
textAlign="right"
>
</Stack.Item>
<Stack.Item>
{!!general.has_photos &&
general.photos!.map((p, i) => (
<Box key={i} inline textAlign="center" color="label">
@@ -55,7 +45,7 @@ export const MedicalRecordsViewGeneral = (props) => {
Photo #{i + 1}
</Box>
))}
</Box>
</>
</Stack.Item>
</Stack>
);
};
@@ -1,6 +1,7 @@
import { useBackend } from '../../backend';
import { Box, Button, LabeledList, Section } from '../../components';
import { modalOpen } from '../../interfaces/common/ComplexModal';
import { useBackend } from 'tgui/backend';
import { Box, Button, LabeledList, Section } from 'tgui-core/components';
import { modalOpen } from '../common/ComplexModal';
import { doEdit } from '../GeneralRecords/functions';
import { Data } from './types';
@@ -1,26 +1,29 @@
import { Fragment } from 'react';
import { useBackend } from '../../backend';
import { Button } from '../../components';
import { Button, NoticeBox } from '../../components';
import { Data } from './types';
export const MedicalRecordsViruses = (props) => {
const { act, data } = useBackend<Data>();
const { virus } = data;
virus && virus.sort((a, b) => (a.name > b.name ? 1 : -1));
return (
virus &&
virus.map((vir, i) => (
<Fragment key={i}>
<Button
icon="flask"
mb="0.5rem"
onClick={() => act('vir', { vir: vir.D })}
>
{vir.name}
</Button>
<br />
</Fragment>
))
);
if (!virus?.length) {
return <NoticeBox>No viruses in database.</NoticeBox>;
}
virus.sort((a, b) => (a.name > b.name ? 1 : -1));
return virus.map((vir, i) => (
<Fragment key={i}>
<Button
icon="flask"
mb="0.5rem"
onClick={() => act('vir', { vir: vir.D })}
>
{vir.name}
</Button>
<br />
</Fragment>
));
};
@@ -1,10 +1,11 @@
import { useBackend } from '../../backend';
import { Section } from '../../components';
import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import { Section, Stack } from 'tgui-core/components';
import {
ComplexModal,
modalRegisterBodyOverride,
} from '../../interfaces/common/ComplexModal';
import { Window } from '../../layouts';
} from '../common/ComplexModal';
import { LoginInfo } from '../common/LoginInfo';
import { LoginScreen } from '../common/LoginScreen';
import { TemporaryNotice } from '../common/TemporaryNotice';
@@ -46,14 +47,26 @@ export const MedicalRecords = (props) => {
return (
<Window width={800} height={380}>
<ComplexModal maxHeight="100%" maxWidth="80%" />
<Window.Content className="Layout__content--flexColumn" scrollable>
<LoginInfo />
<TemporaryNotice />
<MedicalRecordsNavigation />
<Section height="calc(100% - 5rem)" flexGrow>
{(screen && body[screen]) || ''}
</Section>
<Window.Content>
<ComplexModal maxHeight="100%" maxWidth="80%" />
<Stack fill vertical>
<Stack.Item>
<LoginInfo />
</Stack.Item>
{!!data.temp && (
<Stack.Item>
<TemporaryNotice />
</Stack.Item>
)}
<Stack.Item>
<MedicalRecordsNavigation />
</Stack.Item>
<Stack.Item grow>
<Section fill scrollable>
{(screen && body[screen]) || ''}
</Section>
</Stack.Item>
</Stack>
</Window.Content>
</Window>
);
@@ -58,6 +58,7 @@ export const OperatingComputerOptions = (props) => {
value={oxyAlarm}
stepPixelSize={5}
ml="0"
format={(val) => val + '%'}
onChange={(e, val: number) =>
act('oxy_adj', {
new: val,
@@ -74,7 +74,7 @@ export const OperatingComputerPatient = (props: { occupant: occupant }) => {
</LabeledList>
</Section>
<Section title="Current Procedure">
{occupant.surgery && occupant.surgery.length ? (
{occupant.surgery?.length ? (
<LabeledList>
{occupant.surgery.map((limb) => (
<LabeledList.Item key={limb.name} label={limb.name}>
@@ -1,3 +1,5 @@
import { Stack } from 'tgui-core/components';
import { useBackend } from '../../backend';
import { Section, Tabs } from '../../components';
import { Window } from '../../layouts';
@@ -22,23 +24,31 @@ export const OperatingComputer = (props) => {
return (
<Window width={650} height={455}>
<Window.Content>
<Tabs>
<Tabs.Tab
selected={!choice}
icon="user"
onClick={() => act('choiceOff')}
>
Patient
</Tabs.Tab>
<Tabs.Tab
selected={!!choice}
icon="cog"
onClick={() => act('choiceOn')}
>
Options
</Tabs.Tab>
</Tabs>
<Section flexGrow>{body}</Section>
<Stack fill vertical>
<Stack.Item>
<Tabs>
<Tabs.Tab
selected={!choice}
icon="user"
onClick={() => act('choiceOff')}
>
Patient
</Tabs.Tab>
<Tabs.Tab
selected={!!choice}
icon="cog"
onClick={() => act('choiceOn')}
>
Options
</Tabs.Tab>
</Tabs>
</Stack.Item>
<Stack.Item grow>
<Section fill scrollable>
{body}
</Section>
</Stack.Item>
</Stack>
</Window.Content>
</Window>
);
@@ -1,8 +1,9 @@
import { useBackend } from '../../backend';
import { Button, LabeledList, Section } from '../../components';
import { modalBBodyData } from './types';
import { Box, Button, LabeledList, Section } from 'tgui-core/components';
export const viewBodyRecordModalBodyOverride = (modal: modalBBodyData) => {
import { useBackend } from '../../backend';
import { ActiveBodyRecordData } from './types';
export const BodyRecordModal = (props: { data: ActiveBodyRecordData }) => {
const { act } = useBackend();
const {
activerecord,
@@ -13,32 +14,26 @@ export const viewBodyRecordModalBodyOverride = (modal: modalBBodyData) => {
synthetic,
oocnotes,
can_grow_active,
} = modal.args;
} = props.data;
return (
<Section
m="-1rem"
pb="1rem"
backgroundColor="#252525"
m={2}
title={'Body Record (' + realname + ')'}
buttons={
<Button icon="times" color="red" onClick={() => act('modal_close')} />
<Button icon="times" color="red" onClick={() => act('clear_b_rec')} />
}
>
<LabeledList>
<LabeledList.Item label="Name">{realname}</LabeledList.Item>
<LabeledList.Item label="Species">{species}</LabeledList.Item>
<LabeledList.Item label="Bio. Sex">{sex}</LabeledList.Item>
<LabeledList.Item label="Bio. Sex">
<Box style={{ textTransform: 'capitalize' }}>{sex}</Box>
</LabeledList.Item>
<LabeledList.Item label="Mind Compat">{mind_compat}</LabeledList.Item>
<LabeledList.Item label="Synthetic">
{synthetic ? 'Yes' : 'No'}
</LabeledList.Item>
<LabeledList.Item label="OOC Notes">
<Section
style={{ wordBreak: 'break-all', height: '100px' }}
scrollable
>
{oocnotes}
</Section>
</LabeledList.Item>
<LabeledList.Item label="Actions">
<Button
disabled={!can_grow_active}
@@ -52,6 +47,19 @@ export const viewBodyRecordModalBodyOverride = (modal: modalBBodyData) => {
{synthetic ? 'Build' : 'Grow'}
</Button>
</LabeledList.Item>
<LabeledList.Item label="OOC Notes" verticalAlign="top">
<Box height={10} mt={1} ml={1} mr={1}>
<Section
style={{ wordBreak: 'break-word', borderRadius: '5px' }}
scrollable
fill
backgroundColor="black"
preserveWhitespace
>
{oocnotes}
</Section>
</Box>
</LabeledList.Item>
</LabeledList>
</Section>
);
@@ -1,8 +1,9 @@
import { useBackend } from '../../backend';
import { Button, LabeledList, Section } from '../../components';
import { modalMindData } from './types';
import { useBackend } from 'tgui/backend';
import { Box, Button, LabeledList, Section } from 'tgui-core/components';
export const viewMindRecordModalBodyOverride = (modal: modalMindData) => {
import { modalMindData as ActiveMindRecordData } from './types';
export const MindRecordModal = (props: { data: ActiveMindRecordData }) => {
const { act } = useBackend();
const {
activerecord,
@@ -10,14 +11,14 @@ export const viewMindRecordModalBodyOverride = (modal: modalMindData) => {
obviously_dead,
oocnotes,
can_sleeve_active,
} = modal.args;
} = props.data;
return (
<Section
m="-1rem"
pb="1rem"
backgroundColor="#252525"
m={2}
title={'Mind Record (' + realname + ')'}
buttons={
<Button icon="times" color="red" onClick={() => act('modal_close')} />
<Button icon="times" color="red" onClick={() => act('clear_m_rec')} />
}
>
<LabeledList>
@@ -48,13 +49,18 @@ export const viewMindRecordModalBodyOverride = (modal: modalMindData) => {
Card
</Button>
</LabeledList.Item>
<LabeledList.Item label="OOC Notes">
<Section
style={{ wordBreak: 'break-all', height: '100px' }}
scrollable
>
{oocnotes}
</Section>
<LabeledList.Item label="OOC Notes" verticalAlign="top">
<Box height={10} mt={1} ml={1} mr={1}>
<Section
style={{ wordBreak: 'break-word', borderRadius: '5px' }}
scrollable
fill
backgroundColor="black"
preserveWhitespace
>
{oocnotes}
</Section>
</Box>
</LabeledList.Item>
</LabeledList>
</Section>
@@ -1,5 +1,5 @@
import { useBackend } from '../../backend';
import { Box, Button, Dimmer, Flex, Icon } from '../../components';
import { useBackend } from 'tgui/backend';
import { Box, Button, Dimmer, Flex, Icon } from 'tgui-core/components';
export const ResleevingConsoleCoreDump = (props) => {
return (
@@ -26,6 +26,7 @@ export const ResleevingConsoleDiskPrep = (props) => {
<Box color="bad">
<h2>!!WARNING!!</h2>
</Box>
<PulsingWarningTriangle />
<Box color="bad">
This will transfer all minds to the dump disk, and the TransCore will be
made unusable until post-shift maintenance! This should only be used in
@@ -50,3 +51,14 @@ export const ResleevingConsoleDiskPrep = (props) => {
</Dimmer>
);
};
export const PulsingWarningTriangle = (props) => {
return (
<Icon
color="bad"
size={4}
name="exclamation-triangle"
className="ResleevingConsole__WarningTriangle"
/>
);
};
@@ -1,5 +1,7 @@
import { useBackend } from '../../backend';
import { Box, Button, NoticeBox, Section, Tabs } from '../../components';
import { useBackend } from 'tgui/backend';
import { Stack } from 'tgui-core/components';
import { Box, Button, NoticeBox, Section, Tabs } from 'tgui-core/components';
import { MENU_BODY, MENU_MAIN, MENU_MIND } from './constants';
import { ResleevingConsolePodGrowers } from './ResleevingConsolePodGrowers';
import { ResleevingConsolePodSleevers } from './ResleevingConsolePodSleevers';
@@ -84,22 +86,24 @@ export const ResleevingConsoleTemp = (props) => {
const tempProp = { [temp.style]: true };
return (
<NoticeBox {...tempProp}>
<Box inline verticalAlign="middle">
{temp.text}
</Box>
<Button
icon="times-circle"
style={{
float: 'right',
}}
onClick={() => act('cleartemp')}
/>
<Box
style={{
clear: 'both',
}}
/>
</NoticeBox>
<Stack.Item>
<NoticeBox {...tempProp}>
<Box inline verticalAlign="middle">
{temp.text}
</Box>
<Button
icon="times-circle"
style={{
float: 'right',
}}
onClick={() => act('cleartemp')}
/>
<Box
style={{
clear: 'both',
}}
/>
</NoticeBox>
</Stack.Item>
);
};
@@ -1,8 +1,8 @@
import { toFixed } from 'common/math';
import { resolveAsset } from 'tgui/assets';
import { useBackend } from 'tgui/backend';
import { Box, Button, Icon, Image, ProgressBar } from 'tgui-core/components';
import { resolveAsset } from '../../assets';
import { useBackend } from '../../backend';
import { Box, Button, Icon, Image, ProgressBar } from '../../components';
import { Data } from './types';
export const ResleevingConsolePodGrowers = (props) => {
@@ -1,6 +1,7 @@
import { resolveAsset } from '../../assets';
import { useBackend } from '../../backend';
import { Box, Button, Image } from '../../components';
import { resolveAsset } from 'tgui/assets';
import { useBackend } from 'tgui/backend';
import { Box, Button, Image } from 'tgui-core/components';
import { Data } from './types';
export const ResleevingConsolePodSleevers = (props) => {
@@ -1,8 +1,8 @@
import { toFixed } from 'common/math';
import { resolveAsset } from 'tgui/assets';
import { useBackend } from 'tgui/backend';
import { Box, Button, Icon, Image, ProgressBar } from 'tgui-core/components';
import { resolveAsset } from '../../assets';
import { useBackend } from '../../backend';
import { Box, Button, Icon, Image, ProgressBar } from '../../components';
import { Data } from './types';
export const ResleevingConsolePodSpods = (props) => {
@@ -1,5 +1,6 @@
import { useBackend } from '../../backend';
import { Box, Button, Flex, Icon } from '../../components';
import { useBackend } from 'tgui/backend';
import { Box, Button, Flex, Icon } from 'tgui-core/components';
import { record } from './types';
export const ResleevingConsoleRecords = (props: {
@@ -1,5 +1,6 @@
import { useBackend } from '../../backend';
import { Box, LabeledList, Section } from '../../components';
import { useBackend } from 'tgui/backend';
import { Box, LabeledList, Section } from 'tgui-core/components';
import { Data } from './types';
export const ResleevingConsoleStatus = (props) => {
@@ -1,36 +1,39 @@
import { useBackend } from '../../backend';
import { Section } from '../../components';
import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import { Dimmer, Section, Stack } from 'tgui-core/components';
import { BodyRecordModal } from './BodyRecordModal';
import { MindRecordModal } from './MindRecordModal';
import {
ComplexModal,
modalRegisterBodyOverride,
} from '../../interfaces/common/ComplexModal';
import { Window } from '../../layouts';
ResleevingConsoleCoreDump,
ResleevingConsoleDiskPrep,
} from './ResleevingConsoleCoreDump';
import {
ResleevingConsoleBody,
ResleevingConsoleNavigation,
ResleevingConsoleTemp,
} from './ResleevingConsoleElements';
import { ResleevingConsoleStatus } from './ResleevingConsoleStatus';
import {
ResleevingConsoleCoreDump,
ResleevingConsoleDiskPrep,
} from './ResleevingConsoleTexts';
import { Data } from './types';
import { viewBodyRecordModalBodyOverride } from './viewBodyRecordModalBodyOverride';
import { viewMindRecordModalBodyOverride } from './viewMindRecordModalBodyOverride';
export const ResleevingConsole = (props) => {
const { data } = useBackend<Data>();
const { coredumped, emergency } = data;
let body: React.JSX.Element = (
<>
<Stack fill vertical>
<ResleevingConsoleTemp />
<ResleevingConsoleStatus />
<ResleevingConsoleNavigation />
<Section noTopPadding flexGrow>
<ResleevingConsoleBody />
</Section>
</>
<Stack.Item>
<ResleevingConsoleStatus />
</Stack.Item>
<Stack.Item>
<ResleevingConsoleNavigation />
</Stack.Item>
<Stack.Item grow>
<Section fill>
<ResleevingConsoleBody />
</Section>
</Stack.Item>
</Stack>
);
if (coredumped) {
body = <ResleevingConsoleCoreDump />;
@@ -38,14 +41,19 @@ export const ResleevingConsole = (props) => {
if (emergency) {
body = <ResleevingConsoleDiskPrep />;
}
modalRegisterBodyOverride('view_b_rec', viewBodyRecordModalBodyOverride);
modalRegisterBodyOverride('view_m_rec', viewMindRecordModalBodyOverride);
return (
<Window width={640} height={520}>
<ComplexModal maxWidth="75%" maxHeight="75%" />
<Window.Content className="Layout__content--flexColumn">
{body}
</Window.Content>
{data.active_b_rec && (
<Dimmer>
<BodyRecordModal data={data.active_b_rec} />
</Dimmer>
)}
{data.active_m_rec && (
<Dimmer>
<MindRecordModal data={data.active_m_rec} />
</Dimmer>
)}
<Window.Content>{body}</Window.Content>
</Window>
);
};
@@ -26,7 +26,8 @@ export type Data = {
selected_sleever: string;
bodyrecords: record[];
mindrecords: record[];
modal: Partial<modalBBodyData & modalMindData>;
active_b_rec: ActiveBodyRecordData | null;
active_m_rec: modalMindData | null;
};
type pod = {
@@ -37,33 +38,23 @@ type pod = {
progress: number;
};
export type modalBBodyData = {
id: string;
text: string;
args: {
activerecord: string;
realname: string;
species: string;
sex: string;
mind_compat: string;
synthetic: BooleanLike;
oocnotes: string;
can_grow_active: BooleanLike;
};
modal_type: string;
export type ActiveBodyRecordData = {
activerecord: string;
realname: string;
species: string;
sex: string;
mind_compat: string;
synthetic: BooleanLike;
oocnotes: string;
can_grow_active: BooleanLike;
};
export type modalMindData = {
id: string;
text: string;
args: {
activerecord: string;
realname: string;
obviously_dead: string;
oocnotes: string;
can_sleeve_active: BooleanLike;
};
modal_type: string;
activerecord: string;
realname: string;
obviously_dead: string;
oocnotes: string;
can_sleeve_active: BooleanLike;
};
export type record = { name: string; recref: string };
@@ -0,0 +1,15 @@
.ResleevingConsole__WarningTriangle {
animation: pulse 1s ease infinite;
}
@keyframes pulse {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
+1
View File
@@ -56,6 +56,7 @@
@include meta.load-css('./interfaces/NuclearBomb.scss');
@include meta.load-css('./interfaces/Paper.scss');
@include meta.load-css('./interfaces/Pda.scss');
@include meta.load-css('./interfaces/ResleevingConsole.scss');
@include meta.load-css('./interfaces/Roulette.scss');
@include meta.load-css('./interfaces/Safe.scss');
@include meta.load-css('./interfaces/TachyonArray.scss');