mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-28 06:27:26 +01:00
TGUI Medical: Sleeper
This commit is contained in:
@@ -135,17 +135,18 @@
|
||||
to_chat(user, "<span class='notice'>Close the maintenance panel first.</span>")
|
||||
return
|
||||
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/sleeper/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/sleeper/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, "sleeper.tmpl", "Sleeper", 550, 770)
|
||||
ui = new(user, src, ui_key, "Sleeper", "Sleeper", 550, 770)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
ui.set_autoupdate(TRUE)
|
||||
|
||||
/obj/machinery/sleeper/ui_data(mob/user, datum/topic_state/state)
|
||||
/obj/machinery/sleeper/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
data["amounts"] = amounts
|
||||
data["hasOccupant"] = occupant ? 1 : 0
|
||||
var/occupantData[0]
|
||||
var/crisis = 0
|
||||
@@ -210,9 +211,13 @@
|
||||
if(beaker)
|
||||
data["isBeakerLoaded"] = 1
|
||||
if(beaker.reagents)
|
||||
data["beakerMaxSpace"] = beaker.reagents.maximum_volume
|
||||
data["beakerFreeSpace"] = round(beaker.reagents.maximum_volume - beaker.reagents.total_volume)
|
||||
else
|
||||
data["beakerMaxSpace"] = 0
|
||||
data["beakerFreeSpace"] = 0
|
||||
else
|
||||
data["isBeakerLoaded"] = FALSE
|
||||
|
||||
var/chemicals[0]
|
||||
for(var/re in possible_chems)
|
||||
@@ -234,51 +239,50 @@
|
||||
if(temp.id in occupant.reagents.overdose_list())
|
||||
overdosing = 1
|
||||
|
||||
// Because I don't know how to do this on the nano side
|
||||
pretty_amount = round(reagent_amount, 0.05)
|
||||
|
||||
chemicals.Add(list(list("title" = temp.name, "id" = temp.id, "commands" = list("chemical" = temp.id), "occ_amount" = reagent_amount, "pretty_amount" = pretty_amount, "injectable" = injectable, "overdosing" = overdosing, "od_warning" = caution)))
|
||||
data["chemicals"] = chemicals
|
||||
return data
|
||||
|
||||
/obj/machinery/sleeper/Topic(href, href_list)
|
||||
if(!controls_inside && usr == occupant)
|
||||
return 0
|
||||
|
||||
/obj/machinery/sleeper/tgui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
return
|
||||
if(!controls_inside && usr == occupant)
|
||||
return
|
||||
if(panel_open)
|
||||
to_chat(usr, "<span class='notice'>Close the maintenance panel first.</span>")
|
||||
return 0
|
||||
return
|
||||
|
||||
if((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon/ai)))
|
||||
if(href_list["chemical"])
|
||||
if(occupant)
|
||||
if(occupant.stat == DEAD)
|
||||
to_chat(usr, "<span class='danger'>This person has no life for to preserve anymore. Take [occupant.p_them()] to a department capable of reanimating them.</span>")
|
||||
else if(occupant.health > min_health || (href_list["chemical"] in emergency_chems))
|
||||
inject_chemical(usr,href_list["chemical"],text2num(href_list["amount"]))
|
||||
else
|
||||
to_chat(usr, "<span class='danger'>This person is not in good enough condition for sleepers to be effective! Use another means of treatment, such as cryogenics!</span>")
|
||||
|
||||
if(href_list["removebeaker"])
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("chemical")
|
||||
if(!occupant)
|
||||
return
|
||||
if(occupant.stat == DEAD)
|
||||
to_chat(usr, "<span class='danger'>This person has no life to preserve anymore. Take [occupant.p_them()] to a department capable of reanimating them.</span>")
|
||||
return
|
||||
var/chemical = params["chemid"]
|
||||
var/amount = text2num(params["amount"])
|
||||
if(!length(chemical) || amount <= 0)
|
||||
return
|
||||
if(occupant.health > min_health || (chemical in emergency_chems))
|
||||
inject_chemical(usr, chemical, amount)
|
||||
else
|
||||
to_chat(usr, "<span class='danger'>This person is not in good enough condition for sleepers to be effective! Use another means of treatment, such as cryogenics!</span>")
|
||||
if("removebeaker")
|
||||
remove_beaker()
|
||||
|
||||
if(href_list["togglefilter"])
|
||||
if("togglefilter")
|
||||
toggle_filter()
|
||||
|
||||
if(href_list["ejectify"])
|
||||
if("ejectify")
|
||||
eject()
|
||||
|
||||
if(href_list["auto_eject_dead_on"])
|
||||
if("auto_eject_dead_on")
|
||||
auto_eject_dead = TRUE
|
||||
|
||||
if(href_list["auto_eject_dead_off"])
|
||||
if("auto_eject_dead_off")
|
||||
auto_eject_dead = FALSE
|
||||
|
||||
add_fingerprint(usr)
|
||||
return 1
|
||||
else
|
||||
return FALSE
|
||||
add_fingerprint(usr)
|
||||
|
||||
/obj/machinery/sleeper/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/reagent_containers/glass))
|
||||
@@ -290,6 +294,7 @@
|
||||
beaker = I
|
||||
I.forceMove(src)
|
||||
user.visible_message("[user] adds \a [I] to [src]!", "You add \a [I] to [src]!")
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
|
||||
else
|
||||
@@ -328,6 +333,7 @@
|
||||
to_chat(M, "<span class='boldnotice'>You feel cool air surround you. You go numb as your senses turn inward.</span>")
|
||||
add_fingerprint(user)
|
||||
qdel(G)
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
|
||||
return ..()
|
||||
@@ -374,9 +380,11 @@
|
||||
occupant = null
|
||||
updateUsrDialog()
|
||||
update_icon()
|
||||
SStgui.update_uis(src)
|
||||
if(A == beaker)
|
||||
beaker = null
|
||||
updateUsrDialog()
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/sleeper/emp_act(severity)
|
||||
if(filtering)
|
||||
@@ -394,7 +402,7 @@
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/sleeper/proc/toggle_filter()
|
||||
if(filtering)
|
||||
if(filtering || !beaker)
|
||||
filtering = 0
|
||||
else
|
||||
filtering = 1
|
||||
@@ -410,26 +418,25 @@
|
||||
// eject trash the occupant dropped
|
||||
for(var/atom/movable/A in contents - component_parts - list(beaker))
|
||||
A.forceMove(loc)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/machinery/sleeper/proc/inject_chemical(mob/living/user as mob, chemical, amount)
|
||||
/obj/machinery/sleeper/proc/inject_chemical(mob/living/user, chemical, amount)
|
||||
if(!(chemical in possible_chems))
|
||||
to_chat(user, "<span class='notice'>The sleeper does not offer that chemical!</span>")
|
||||
return
|
||||
if(!(amount in amounts))
|
||||
return
|
||||
|
||||
if(occupant)
|
||||
if(occupant.reagents)
|
||||
if(occupant.reagents.get_reagent_amount(chemical) + amount <= max_chem)
|
||||
occupant.reagents.add_reagent(chemical, amount)
|
||||
return
|
||||
else
|
||||
to_chat(user, "You can not inject any more of this chemical.")
|
||||
return
|
||||
else
|
||||
to_chat(user, "The patient rejects the chemicals!")
|
||||
return
|
||||
else
|
||||
to_chat(user, "There's no occupant in the sleeper!")
|
||||
return
|
||||
|
||||
/obj/machinery/sleeper/verb/eject()
|
||||
set name = "Eject Sleeper"
|
||||
@@ -456,6 +463,7 @@
|
||||
filtering = 0
|
||||
beaker.forceMove(usr.loc)
|
||||
beaker = null
|
||||
SStgui.update_uis(src)
|
||||
add_fingerprint(usr)
|
||||
return
|
||||
|
||||
@@ -508,6 +516,7 @@
|
||||
add_fingerprint(user)
|
||||
if(user.pulling == L)
|
||||
user.stop_pulling()
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
return
|
||||
|
||||
@@ -544,6 +553,7 @@
|
||||
for(var/obj/O in src)
|
||||
qdel(O)
|
||||
add_fingerprint(usr)
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
@@ -1,211 +0,0 @@
|
||||
<!--
|
||||
Title: Sleeper Status UI
|
||||
Used In File(s): \code\game\machinery\Sleeper.dm
|
||||
-->
|
||||
<h3>Sleeper Status</h3>
|
||||
|
||||
<div class="statusDisplay">
|
||||
{{if !data.hasOccupant}}
|
||||
<div class="line">Sleeper Unoccupied</div>
|
||||
{{else}}
|
||||
<div class="line">
|
||||
{{:data.occupant.name}} =>
|
||||
{{if data.occupant.stat == 0}}
|
||||
<span class="good">Conscious</span>
|
||||
{{else data.occupant.stat == 1}}
|
||||
<span class="average">Unconscious</span>
|
||||
{{else}}
|
||||
<span class="bad">DEAD</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="line">
|
||||
<div class="statusLabel">Health:</div>
|
||||
{{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}}
|
||||
<div class="statusValue">{{:helper.smoothRound(data.occupant.health)}}</div>
|
||||
</div>
|
||||
|
||||
<div class="line">
|
||||
<div class="statusLabel">=> Brute Damage:</div>
|
||||
{{:helper.displayBar(data.occupant.bruteLoss, 0, data.occupant.maxHealth, 'bad')}}
|
||||
<div class="statusValue">{{:helper.smoothRound(data.occupant.bruteLoss)}}</div>
|
||||
</div>
|
||||
|
||||
<div class="line">
|
||||
<div class="statusLabel">=> Resp. Damage:</div>
|
||||
{{:helper.displayBar(data.occupant.oxyLoss, 0, data.occupant.maxHealth, 'bad')}}
|
||||
<div class="statusValue">{{:helper.smoothRound(data.occupant.oxyLoss)}}</div>
|
||||
</div>
|
||||
|
||||
<div class="line">
|
||||
<div class="statusLabel">=> Toxin Damage:</div>
|
||||
{{:helper.displayBar(data.occupant.toxLoss, 0, data.occupant.maxHealth, 'bad')}}
|
||||
<div class="statusValue">{{:helper.smoothRound(data.occupant.toxLoss)}}</div>
|
||||
</div>
|
||||
|
||||
<div class="line">
|
||||
<div class="statusLabel">=> Burn Severity:</div>
|
||||
{{:helper.displayBar(data.occupant.fireLoss, 0, data.occupant.maxHealth, 'bad')}}
|
||||
<div class="statusValue">{{:helper.smoothRound(data.occupant.fireLoss)}}</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<div class="line">
|
||||
<!--
|
||||
<div class="statusLabel">Patient Temperature:</div>
|
||||
{{if data.occupant.temperatureSuitability == -3}}
|
||||
{{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'cold3')}}
|
||||
<div class="statusValue bad">{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F</div>
|
||||
{{else data.occupant.temperatureSuitability == -2}}
|
||||
{{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'cold2')}}
|
||||
<div class="statusValue bad">{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F</div>
|
||||
{{else data.occupant.temperatureSuitability == -1}}
|
||||
{{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'cold1')}}
|
||||
<div class="statusValue">{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F</div>
|
||||
{{else data.occupant.temperatureSuitability == 0}}
|
||||
{{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'good')}}
|
||||
<div class="statusValue">{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F</div>
|
||||
{{else data.occupant.temperatureSuitability == 1}}
|
||||
{{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'hot1')}}
|
||||
<div class="statusValue">{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F</div>
|
||||
{{else data.occupant.temperatureSuitability == 2}}
|
||||
{{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'hot2')}}
|
||||
<div class="statusValue bad">{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F</div>
|
||||
{{else data.occupant.temperatureSuitability == 3}}
|
||||
{{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'hot3')}}
|
||||
<div class="statusValue bad">{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F</div>
|
||||
{{/if}}
|
||||
If you can get the changing temperature bars to work right, congratulations
|
||||
-->
|
||||
<div class="statusLabel">Patient Temperature:</div>
|
||||
{{if data.occupant.temperatureSuitability == -3}}
|
||||
{{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'bad')}}
|
||||
<div class="statusValue bad">{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F</div>
|
||||
{{else data.occupant.temperatureSuitability == -2}}
|
||||
{{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'average')}}
|
||||
<div class="statusValue bad">{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F</div>
|
||||
{{else data.occupant.temperatureSuitability == -1}}
|
||||
{{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'average')}}
|
||||
<div class="statusValue">{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F</div>
|
||||
{{else data.occupant.temperatureSuitability == 0}}
|
||||
{{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'good')}}
|
||||
<div class="statusValue">{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F</div>
|
||||
{{else data.occupant.temperatureSuitability == 1}}
|
||||
{{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'average')}}
|
||||
<div class="statusValue">{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F</div>
|
||||
{{else data.occupant.temperatureSuitability == 2}}
|
||||
{{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'average')}}
|
||||
<div class="statusValue bad">{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F</div>
|
||||
{{else data.occupant.temperatureSuitability == 3}}
|
||||
{{:helper.displayBar(data.occupant.bodyTemperature, 0, data.occupant.maxTemp, 'bad')}}
|
||||
<div class="statusValue bad">{{:helper.smoothRound(data.occupant.btCelsius)}}°C, {{:helper.smoothRound(data.occupant.btFaren)}}°F</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
|
||||
{{if data.occupant.hasBlood}}
|
||||
|
||||
<br>
|
||||
<div class="line">
|
||||
<div class="statusLabel">Pulse:</div> <div class="statusValue">{{:data.occupant.pulse}} bpm</div>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="statusLabel">Blood Level:</div>
|
||||
{{if data.occupant.bloodPercent <= 60}}
|
||||
{{:helper.displayBar(data.occupant.bloodLevel, 0, data.occupant.bloodMax, 'bad')}}
|
||||
<div class="statusValue">
|
||||
{{:helper.smoothRound(data.occupant.bloodPercent)}}%, {{:helper.smoothRound(data.occupant.bloodLevel)}}cl
|
||||
</div>
|
||||
{{else data.occupant.bloodPercent <= 90}}
|
||||
{{:helper.displayBar(data.occupant.bloodLevel, 0, data.occupant.bloodMax, 'average')}}
|
||||
<div class="statusValue">
|
||||
{{:helper.smoothRound(data.occupant.bloodPercent)}}%, {{:helper.smoothRound(data.occupant.bloodLevel)}}cl
|
||||
</div>
|
||||
{{else}}
|
||||
{{:helper.displayBar(data.occupant.bloodLevel, 0, data.occupant.bloodMax, 'good')}}
|
||||
<div class="statusValue">
|
||||
{{:helper.smoothRound(data.occupant.bloodPercent)}}%, {{:helper.smoothRound(data.occupant.bloodLevel)}}cl
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<h3>Sleeper Operation</h3>
|
||||
<div class="item">
|
||||
<div class="itemLabel">
|
||||
Sleeper Status:
|
||||
</div>
|
||||
<div class="itemContent" style="width: 26%;">
|
||||
{{:helper.link('Eject Occupant', 'arrow-circle-o-down', {'ejectify' : 1}, data.hasOccupant ? null : 'disabled')}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item"> </div>
|
||||
<div class="item">
|
||||
<div class="itemLabel">
|
||||
Dialysis Beaker:
|
||||
</div>
|
||||
<div class="itemContent" style="width: 40%;">
|
||||
{{if data.isBeakerLoaded}}
|
||||
<span class="highlight">{{:helper.smoothRound(data.beakerFreeSpace)}} units of space remaining</span><br>
|
||||
{{else}}
|
||||
<span class="average"><i>No Dialysis Output Beaker Loaded</i></span>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="itemContent" style="width: 26%;">
|
||||
{{:helper.link('Eject Beaker', 'eject', {'removebeaker' : 1}, data.isBeakerLoaded ? null : 'disabled')}}
|
||||
{{if data.isBeakerLoaded}}
|
||||
<div class="line">
|
||||
<div class="itemContent">
|
||||
{{:helper.link('On', 'power-off', {'togglefilter' : 1}, data.occupant.hasBlood ? (data.dialysis ? 'selected' : null) : 'disabled')}}{{:helper.link('Off', 'close', {'togglefilter' : 1}, data.dialysis ? null : 'selected')}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="itemLabel">
|
||||
Chemicals:
|
||||
</div>
|
||||
|
||||
{{for data.chemicals}}
|
||||
<div class="line"><b>{{:value.title}}</b></div>
|
||||
<div class="line">
|
||||
{{if value.overdosing}}
|
||||
{{:helper.displayBar(value.occ_amount, 0, data.maxchem, 'bad')}}
|
||||
{{else value.od_warning}}
|
||||
{{:helper.displayBar(value.occ_amount, 0, data.maxchem, 'average')}}
|
||||
{{else}}
|
||||
{{:helper.displayBar(value.occ_amount, 0, data.maxchem, 'good')}}
|
||||
{{/if}}
|
||||
<div class="statusValue">{{:helper.smoothRound(value.pretty_amount)}}/{{:data.maxchem}}</div>
|
||||
<br>
|
||||
</div>
|
||||
<div class="line">
|
||||
<div class="itemContent">
|
||||
{{:helper.link('5', 'gear', {'chemical' : value.id, 'amount' : 5}, (!value.injectable || ((value.occ_amount + 5) > data.maxchem)) ? 'disabled' : null)}}
|
||||
{{:helper.link('10', 'gear', {'chemical' : value.id, 'amount' : 10}, (!value.injectable || ((value.occ_amount + 10) > data.maxchem)) ? 'disabled' : null)}}
|
||||
</div>
|
||||
</div>
|
||||
{{/for}}
|
||||
|
||||
<div class="item"> </div>
|
||||
<div class="item">
|
||||
<div class="itemLabel" style="width: 35%">
|
||||
Auto-eject dead patients:
|
||||
</div>
|
||||
<div class="itemContent" style="width: 30%">
|
||||
{{:helper.link('On', 'power-off', {'auto_eject_dead_on' : 1}, data.auto_eject_dead ? 'selected' : null)}}{{:helper.link('Off', 'close', {'auto_eject_dead_off' : 0}, data.auto_eject_dead ? null : 'selected')}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,315 @@
|
||||
import { round, toFixed } from 'common/math';
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend } from "../backend";
|
||||
import { Window } from "../layouts";
|
||||
import { AnimatedNumber, Box, Button, Flex, Icon, LabeledList, NumberInput, ProgressBar, Section } from "../components";
|
||||
import { BeakerContents } from '../interfaces/common/BeakerContents';
|
||||
|
||||
const stats = [
|
||||
['good', 'Alive'],
|
||||
['average', 'Critical'],
|
||||
['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 Sleeper = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
hasOccupant,
|
||||
} = data;
|
||||
const body = hasOccupant ? <SleeperMain /> : <SleeperEmpty />;
|
||||
return (
|
||||
<Window resizable>
|
||||
<Window.Content className="Layout__content--flexColumn">
|
||||
{body}
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
const SleeperMain = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
occupant,
|
||||
} = data;
|
||||
return (
|
||||
<Fragment>
|
||||
<SleeperOccupant />
|
||||
<SleeperDamage />
|
||||
<SleeperDialysis />
|
||||
<SleeperChemicals />
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const SleeperOccupant = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
occupant,
|
||||
auto_eject_dead,
|
||||
} = data;
|
||||
return (
|
||||
<Section
|
||||
title="Occupant"
|
||||
buttons={(
|
||||
<Fragment>
|
||||
<Box color="label" display="inline">
|
||||
Auto-eject if dead:
|
||||
</Box>
|
||||
<Button
|
||||
icon={auto_eject_dead ? "toggle-on" : "toggle-off"}
|
||||
selected={auto_eject_dead}
|
||||
content={auto_eject_dead ? 'On' : 'Off'}
|
||||
onClick={() =>
|
||||
act('auto_eject_dead_' + (auto_eject_dead ? 'off' : 'on'))}
|
||||
/>
|
||||
<Button
|
||||
icon="user-slash"
|
||||
content="Eject"
|
||||
onClick={() => act('ejectify')}
|
||||
/>
|
||||
</Fragment>
|
||||
)}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Name">
|
||||
{occupant.name}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Health">
|
||||
<ProgressBar
|
||||
min="0"
|
||||
max={occupant.maxHealth}
|
||||
value={occupant.health / occupant.maxHealth}
|
||||
ranges={{
|
||||
good: [0.5, Infinity],
|
||||
average: [0, 0.5],
|
||||
bad: [-Infinity, 0],
|
||||
}}>
|
||||
{round(occupant.health)}
|
||||
</ProgressBar>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Status" color={stats[occupant.stat][0]}>
|
||||
{stats[occupant.stat][1]}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Temperature">
|
||||
<ProgressBar
|
||||
min="0"
|
||||
max={occupant.maxTemp}
|
||||
value={occupant.bodyTemperature / occupant.maxTemp}
|
||||
color={tempColors[occupant.temperatureSuitability + 3]}>
|
||||
{round(occupant.btCelsius)}°C, {round(occupant.btFaren)}°F
|
||||
</ProgressBar>
|
||||
</LabeledList.Item>
|
||||
{!!occupant.hasBlood && (
|
||||
<Fragment>
|
||||
<LabeledList.Item label="Blood Level">
|
||||
<ProgressBar
|
||||
min="0"
|
||||
max={occupant.bloodMax}
|
||||
value={occupant.bloodLevel / occupant.bloodMax}
|
||||
ranges={{
|
||||
bad: [-Infinity, 0.6],
|
||||
average: [0.6, 0.9],
|
||||
good: [0.6, Infinity],
|
||||
}}>
|
||||
{occupant.bloodPercent}%, {occupant.bloodLevel}cl
|
||||
</ProgressBar>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Pulse" verticalAlign="middle">
|
||||
{occupant.pulse} BPM
|
||||
</LabeledList.Item>
|
||||
</Fragment>
|
||||
)}
|
||||
</LabeledList>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const SleeperDamage = (props, context) => {
|
||||
const { data } = useBackend(context);
|
||||
const {
|
||||
occupant,
|
||||
} = data;
|
||||
return (
|
||||
<Section
|
||||
title="Damage">
|
||||
<LabeledList>
|
||||
{damages.map((d, i) => (
|
||||
<LabeledList.Item key={i} label={d[0]}>
|
||||
<ProgressBar
|
||||
key={i}
|
||||
min="0"
|
||||
max="100"
|
||||
value={occupant[d[1]] / 100}
|
||||
ranges={damageRange}>
|
||||
{round(occupant[d[1]])}
|
||||
</ProgressBar>
|
||||
</LabeledList.Item>
|
||||
))}
|
||||
</LabeledList>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const SleeperDialysis = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
isBeakerLoaded,
|
||||
beakerMaxSpace,
|
||||
beakerFreeSpace,
|
||||
dialysis,
|
||||
} = data;
|
||||
const canDialysis = dialysis && beakerFreeSpace > 0;
|
||||
return (
|
||||
<Section
|
||||
title="Dialysis"
|
||||
buttons={
|
||||
<Fragment>
|
||||
<Button
|
||||
disabled={!isBeakerLoaded || beakerFreeSpace <= 0}
|
||||
selected={canDialysis}
|
||||
icon={canDialysis ? "toggle-on" : "toggle-off"}
|
||||
content={canDialysis ? "Active" : "Inactive"}
|
||||
onClick={() => act('togglefilter')}
|
||||
/>
|
||||
<Button
|
||||
disabled={!isBeakerLoaded}
|
||||
icon="eject"
|
||||
content="Eject"
|
||||
onClick={() => act('removebeaker')}
|
||||
/>
|
||||
</Fragment>
|
||||
}>
|
||||
{isBeakerLoaded ? (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Remaining Space">
|
||||
<ProgressBar
|
||||
min="0"
|
||||
max={beakerMaxSpace}
|
||||
value={beakerFreeSpace / beakerMaxSpace}
|
||||
ranges={{
|
||||
good: [0.5, Infinity],
|
||||
average: [0.25, 0.5],
|
||||
bad: [-Infinity, 0.25],
|
||||
}}>
|
||||
{beakerFreeSpace}u
|
||||
</ProgressBar>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
) : (
|
||||
<Box color="label">
|
||||
No beaker loaded.
|
||||
</Box>
|
||||
)}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const SleeperChemicals = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
occupant,
|
||||
chemicals,
|
||||
maxchem,
|
||||
amounts,
|
||||
} = data;
|
||||
return (
|
||||
<Section title="Chemicals" flexGrow="1">
|
||||
{chemicals.map((chem, i) => {
|
||||
let barColor = '';
|
||||
let odWarning;
|
||||
if (chem.overdosing) {
|
||||
barColor = 'bad';
|
||||
odWarning = (
|
||||
<Box color="bad">
|
||||
<Icon name="exclamation-circle" />
|
||||
Overdosing!
|
||||
</Box>
|
||||
);
|
||||
} else if (chem.od_warning) {
|
||||
barColor = 'average';
|
||||
odWarning = (
|
||||
<Box color="average">
|
||||
<Icon name="exclamation-triangle" />
|
||||
Close to overdosing
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Box key={i} backgroundColor="rgba(0, 0, 0, 0.33)" mb="0.5rem">
|
||||
<Section
|
||||
title={chem.title}
|
||||
level="3"
|
||||
mx="0"
|
||||
lineHeight="18px"
|
||||
buttons={odWarning}>
|
||||
<ProgressBar
|
||||
min="0"
|
||||
max={maxchem}
|
||||
value={chem.occ_amount / maxchem}
|
||||
color={barColor}
|
||||
mb="0.5rem">
|
||||
{chem.pretty_amount}/{maxchem}u
|
||||
</ProgressBar>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Inject">
|
||||
{amounts.map((a, i) => (
|
||||
<Button
|
||||
key={i}
|
||||
disabled={!chem.injectable
|
||||
|| ((chem.occ_amount + a) > maxchem)
|
||||
|| occupant.stat === 2}
|
||||
icon="syringe"
|
||||
content={a}
|
||||
onClick={() => act('chemical', {
|
||||
chemid: chem.id,
|
||||
amount: a,
|
||||
})}
|
||||
/>
|
||||
))}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const SleeperEmpty = (props, context) => {
|
||||
return (
|
||||
<Section textAlign="center" flexGrow="1">
|
||||
<Flex height="100%">
|
||||
<Flex.Item grow="1" align="center" color="label">
|
||||
<Icon
|
||||
name="user-slash"
|
||||
mb="0.5rem"
|
||||
size="5"
|
||||
/><br />
|
||||
No occupant detected.
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user