diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm
index 21fddce64b7..f87c48b326f 100644
--- a/code/game/machinery/computer/Operating.dm
+++ b/code/game/machinery/computer/Operating.dm
@@ -40,8 +40,7 @@
add_fingerprint(user)
if(stat & (BROKEN|NOPOWER))
return
- ui_interact(user)
-
+ tgui_interact(user)
/obj/machinery/computer/operating/attack_hand(mob/user)
if(..(user))
@@ -52,16 +51,16 @@
add_fingerprint(user)
- ui_interact(user)
+ tgui_interact(user)
-/obj/machinery/computer/operating/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)//ui is mostly copy pasta from the sleeper ui
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
+/obj/machinery/computer/operating/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
+ ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
- ui = new(user, src, ui_key, "op_computer.tmpl", "Patient Monitor", 650, 455)
+ ui = new(user, src, ui_key, "OperatingComputer", "Patient Monitor", 650, 455, master_ui, state)
ui.open()
- ui.set_auto_update(1)
+ ui.set_autoupdate(TRUE)
-/obj/machinery/computer/operating/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
+/obj/machinery/computer/operating/tgui_data(mob/user)
var/data[0]
var/mob/living/carbon/human/occupant
if(table)
@@ -136,38 +135,40 @@
return data
-/obj/machinery/computer/operating/Topic(href, href_list)
+/obj/machinery/computer/operating/tgui_act(action, params)
if(..())
- return 1
+ return
if((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
usr.set_machine(src)
- if(href_list["verboseOn"])
- verbose=1
- if(href_list["verboseOff"])
- verbose=0
- if(href_list["healthOn"])
- healthAnnounce=1
- if(href_list["healthOff"])
- healthAnnounce=0
- if(href_list["critOn"])
- crit=1
- if(href_list["critOff"])
- crit=0
- if(href_list["oxyOn"])
- oxy=1
- if(href_list["oxyOff"])
- oxy=0
- if(href_list["oxy_adj"]!=0)
- oxyAlarm=oxyAlarm+text2num(href_list["oxy_adj"])
- if(href_list["choiceOn"])
- choice=1
- if(href_list["choiceOff"])
- choice=0
- if(href_list["health_adj"]!=0)
- healthAlarm=healthAlarm+text2num(href_list["health_adj"])
- return
-
+ . = TRUE
+ switch(action)
+ if("verboseOn")
+ verbose = TRUE
+ if("verboseOff")
+ verbose = FALSE
+ if("healthOn")
+ healthAnnounce = TRUE
+ if("healthOff")
+ healthAnnounce = FALSE
+ if("critOn")
+ crit = TRUE
+ if("critOff")
+ crit = FALSE
+ if("oxyOn")
+ oxy = TRUE
+ if("oxyOff")
+ oxy = FALSE
+ if("oxy_adj")
+ oxyAlarm = clamp(text2num(params["new"]), -100, 100)
+ if("choiceOn")
+ choice = TRUE
+ if("choiceOff")
+ choice = FALSE
+ if("health_adj")
+ healthAlarm = clamp(text2num(params["new"]), -100, 100)
+ else
+ return FALSE
/obj/machinery/computer/operating/process()
@@ -178,6 +179,7 @@
atom_say("New patient detected, loading stats")
victim = table.victim
atom_say("[victim.real_name], [victim.dna.blood_type] blood, [victim.stat ? "Non-Responsive" : "Awake"]")
+ SStgui.update_uis(src)
if(nextTick < world.time)
nextTick=world.time + OP_COMPUTER_COOLDOWN
if(crit && victim.health <= -50 )
diff --git a/nano/templates/op_computer.tmpl b/nano/templates/op_computer.tmpl
deleted file mode 100644
index 77894bcba16..00000000000
--- a/nano/templates/op_computer.tmpl
+++ /dev/null
@@ -1,215 +0,0 @@
-
-
- {{if data.choice==0}}
- {{if !data.hasOccupant}}
-
No Patient Detected
- {{else}}
-
- {{:data.occupant.name}} =>
- {{if data.occupant.stat == 0}}
- Conscious
- {{else data.occupant.stat == 1}}
- Unconscious
- {{else}}
- DEAD
- {{/if}}
-
-
-
-
Health:
- {{if data.occupant.health >= data.occupant.maxHealth}}
- {{:helper.displayBar(data.occupant.health, 0, data.occupant.maxHealth, 'good')}}
- {{else data.occupant.health > 0}}
- {{:helper.displayBar(data.occupant.health, 0, data.occupant.maxHealth, 'average')}}
- {{else data.occupant.health >= data.minhealth}}
- {{:helper.displayBar(data.occupant.health, 0, data.occupant.minHealth, 'average alignRight')}}
- {{else}}
- {{:helper.displayBar(data.occupant.health, 0, data.occupant.minHealth, 'bad alignRight')}}
- {{/if}}
-
{{:helper.smoothRound(data.occupant.health)}}
-
-
-
-
Brute Damage:
- {{:helper.displayBar(data.occupant.bruteLoss, 0, data.occupant.maxHealth, 'bad')}}
-
{{:helper.smoothRound(data.occupant.bruteLoss)}}
-
-
-
-
Resp. Damage:
- {{:helper.displayBar(data.occupant.oxyLoss, 0, data.occupant.maxHealth, 'bad')}}
-
{{:helper.smoothRound(data.occupant.oxyLoss)}}
-
-
-
-
Toxin Damage:
- {{:helper.displayBar(data.occupant.toxLoss, 0, data.occupant.maxHealth, 'bad')}}
-
{{:helper.smoothRound(data.occupant.toxLoss)}}
-
-
-
-
Burn Severity:
- {{:helper.displayBar(data.occupant.fireLoss, 0, data.occupant.maxHealth, 'bad')}}
-
{{:helper.smoothRound(data.occupant.fireLoss)}}
-
-
-
-
Patient Temperature:
- {{if data.occupant.temperatureSuitability == -3}}
- {{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'bad')}}
-
{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F
- {{else data.occupant.temperatureSuitability == -2}}
- {{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'average')}}
-
{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F
- {{else data.occupant.temperatureSuitability == -1}}
- {{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'average')}}
-
{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.helper.smoothRound(data.occupant.btFaren)}}°F
- {{else data.occupant.temperatureSuitability == 0}}
- {{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'good')}}
-
{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F
- {{else data.occupant.temperatureSuitability == 1}}
- {{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'average')}}
-
{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F
- {{else data.occupant.temperatureSuitability == 2}}
- {{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'average')}}
-
{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F
- {{else data.occupant.temperatureSuitability == 3}}
- {{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'bad')}}
-
{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F
- {{/if}}
-
- {{if data.occupant.hasBlood}}
-
-
-
Blood Level:
- {{if data.occupant.bloodPercent <= 60}}
- {{:helper.displayBar(data.occupant.bloodLevel, 0, data.occupant.bloodMax, 'bad')}}
-
- {{:helper.smoothRound(data.occupant.bloodPercent)}}%, {{:helper.smoothRound(data.occupant.bloodLevel)}}cl
-
- {{else data.occupant.bloodPercent <= 90}}
- {{:helper.displayBar(data.occupant.bloodLevel, 0, data.occupant.bloodMax, 'average')}}
-
- {{:helper.smoothRound(data.occupant.bloodPercent)}}%, {{:helper.smoothRound(data.occupant.bloodLevel)}}cl
-
- {{else}}
- {{:helper.displayBar(data.occupant.bloodLevel, 0, data.occupant.bloodMax, 'good')}}
-
- {{:helper.smoothRound(data.occupant.bloodPercent)}}%, {{:helper.smoothRound(data.occupant.bloodLevel)}}cl
-
- {{/if}}
-
-
Blood Type:
{{:data.occupant.bloodType}}
-
-
-
-
Pulse:
{{:data.occupant.pulse}} bpm
-
- {{/if}}
- {{if data.occupant.inSurgery}}
-
-
Initiated Surgery Procedure:
{{:data.occupant.surgeryName}}
-
-
Next Step:
{{:data.occupant.stepName}}
-
-
- {{/if}}
-
-
- {{/if}}
-
-
- {{:helper.link('Options', 'gear', {'choiceOn' : 1})}}
-
-
- {{else}}
-
-
- Loudspeaker:
-
-
- {{:helper.link('On', 'power-off', {'verboseOn' : 1}, data.verbose ? 'selected' : null)}}
- {{:helper.link('Off', 'close', {'verboseOff' : 1}, data.verbose ? null : 'selected')}}
-
-
-
-
-
- Health Announcer:
-
-
- {{:helper.link('On', 'power-off', {'healthOn' : 1}, data.health ? 'selected' : null)}}
- {{:helper.link('Off', 'close', {'healthOff' : 1}, data.health ? null : 'selected')}}
-
-
-
-
-
-
Health Announcer Threshold:
- {{:helper.link('-', null, {'health_adj' : -100}, (data.healthAlarm >= 0) ? null : 'disabled')}}
- {{:helper.link('-', null, {'health_adj' : -10}, (data.healthAlarm >= -90) ? null : 'disabled')}}
- {{:helper.link('-', null, {'health_adj' : -1}, (data.healthAlarm > -100) ? null : 'disabled')}}
-
- {{if data.healthAlarm >= 100}}
- {{:helper.displayBar(data.healthAlarm, 0, 100, 'good')}}
- {{else data.healthAlarm > 0}}
- {{:helper.displayBar(data.healthAlarm, 0, 100, 'average')}}
- {{else data.healthAlarm >= -100}}
- {{:helper.displayBar(data.healthAlarm, 0, -100, 'average alignRight')}}
- {{else}}
- {{:helper.displayBar(data.healthAlarm, 0, -100, 'bad alignRight')}}
- {{/if}}
-
- {{:helper.link('+', null, {'health_adj' : 1}, (data.healthAlarm < 100) ? null : 'disabled')}}
- {{:helper.link('+', null, {'health_adj' : 10}, (data.healthAlarm <= 90) ? null : 'disabled')}}
- {{:helper.link('+', null, {'health_adj' : 100}, (data.healthAlarm <= 0) ? null : 'disabled')}}
-
{{: data.healthAlarm }}
-
-
-
-
-
- Oxygen Alarm:
-
-
- {{:helper.link('On', 'power-off', {'oxyOn' : 1}, data.oxy ? 'selected' : null)}}
- {{:helper.link('Off', 'close', {'oxyOff' : 1}, data.oxy ? null : 'selected')}}
-
-
-
-
-
-
Oxygen Alert Threshold:
- {{:helper.link('-', null, {'oxy_adj' : -100}, (data.oxyAlarm >= 100) ? null : 'disabled')}}
- {{:helper.link('-', null, {'oxy_adj' : -10}, (data.oxyAlarm >= 10) ? null : 'disabled')}}
- {{:helper.link('-', null, {'oxy_adj' : -1}, (data.oxyAlarm >= 0) ? null : 'disabled')}}
- {{:helper.displayBar( data.oxyAlarm, 0, 200, 'good')}}
- {{:helper.link('+', null, {'oxy_adj' : 1}, (data.oxyAlarm < 200) ? null : 'disabled')}}
- {{:helper.link('+', null, {'oxy_adj' : 10}, (data.oxyAlarm <= 190) ? null : 'disabled')}}
- {{:helper.link('+', null, {'oxy_adj' : 100}, (data.oxyAlarm <= 100) ? null : 'disabled')}}
-
{{: data.oxyAlarm }}
-
-
-
-
-
- Critical Alert:
-
-
- {{:helper.link('On', 'power-off', {'critOn' : 1}, data.crit ? 'selected' : null)}}
- {{:helper.link('Off', 'close', {'critOff' : 1}, data.crit ? null : 'selected')}}
-
-
-
-
-
- {{:helper.link('Return', 'arrow-left', {'choiceOff' : 1})}}
-
-
- {{/if}}
-
diff --git a/tgui/packages/tgui/interfaces/OperatingComputer.js b/tgui/packages/tgui/interfaces/OperatingComputer.js
new file mode 100644
index 00000000000..65045510bb7
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/OperatingComputer.js
@@ -0,0 +1,251 @@
+import { round } from 'common/math';
+import { Fragment } from 'inferno';
+import { useBackend } from "../backend";
+import { Window } from "../layouts";
+import { Box, Button, Flex, Icon, Knob, LabeledList, Section, Tabs, ProgressBar } from "../components";
+
+const stats = [
+ ['good', 'Conscious'],
+ ['average', 'Unconscious'],
+ ['bad', 'DEAD'],
+];
+
+const damages = [
+ ['Resp.', 'oxyLoss'],
+ ['Toxin', 'toxLoss'],
+ ['Brute', 'bruteLoss'],
+ ['Burn', 'fireLoss'],
+];
+
+const damageRange = {
+ average: [0.25, 0.5],
+ bad: [0.5, Infinity],
+};
+
+const tempColors = [
+ 'bad',
+ 'average',
+ 'average',
+ 'good',
+ 'average',
+ 'average',
+ 'bad',
+];
+
+export const OperatingComputer = (props, context) => {
+ const { act, data } = useBackend(context);
+ const {
+ hasOccupant,
+ choice,
+ } = data;
+ let body;
+ if (!choice) {
+ body = hasOccupant
+ ?