Merge pull request #11681 from PersianXerxes/medicalTGUINext
TGUI Next in the Medbay
This commit is contained in:
@@ -207,11 +207,14 @@
|
||||
|
||||
/obj/machinery/sleeper/ui_data()
|
||||
var/list/data = list()
|
||||
var/chemical_list = list()
|
||||
var/blood_percent = 0
|
||||
|
||||
data["occupied"] = occupant ? 1 : 0
|
||||
data["open"] = state_open
|
||||
data["efficiency"] = efficiency
|
||||
data["current_vol"] = reagents.total_volume
|
||||
data["tot_capacity"] = reagents.maximum_volume
|
||||
data["blood_levels"] = blood_percent
|
||||
data["blood_status"] = "Patient either has no blood, or does not require it to function."
|
||||
data["chemical_list"] = chemical_list
|
||||
|
||||
data["chems"] = list()
|
||||
for(var/chem in available_chems)
|
||||
@@ -247,10 +250,13 @@
|
||||
data["occupant"]["fireLoss"] = mob_occupant.getFireLoss()
|
||||
data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss()
|
||||
data["occupant"]["brainLoss"] = mob_occupant.getOrganLoss(ORGAN_SLOT_BRAIN)
|
||||
data["occupant"]["reagents"] = list()
|
||||
if(mob_occupant.reagents && mob_occupant.reagents.reagent_list.len)
|
||||
|
||||
if(mob_occupant.reagents.reagent_list.len)
|
||||
for(var/datum/reagent/R in mob_occupant.reagents.reagent_list)
|
||||
data["occupant"]["reagents"] += list(list("name" = R.name, "volume" = R.volume))
|
||||
chemical_list += list(list("name" = R.name, "volume" = R.volume))
|
||||
else
|
||||
chemical_list = "Patient has no reagents."
|
||||
|
||||
data["occupant"]["failing_organs"] = list()
|
||||
var/mob/living/carbon/C = mob_occupant
|
||||
if(C)
|
||||
@@ -259,21 +265,25 @@
|
||||
continue
|
||||
data["occupant"]["failing_organs"] += list(list("name" = Or.name))
|
||||
|
||||
if(mob_occupant.has_dna()) // Blood-stuff is mostly a copy-paste from the healthscanner.
|
||||
var/blood_id = C.get_blood_id()
|
||||
if(blood_id)
|
||||
data["occupant"]["blood"] = list() // We can start populating this list.
|
||||
var/blood_type = C.dna.blood_type
|
||||
if(!(blood_id in GLOB.blood_reagent_types)) // special blood substance
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id]
|
||||
if(R)
|
||||
blood_type = R.name
|
||||
else
|
||||
blood_type = blood_id
|
||||
data["occupant"]["blood"]["maxBloodVolume"] = (BLOOD_VOLUME_NORMAL*C.blood_ratio)
|
||||
data["occupant"]["blood"]["currentBloodVolume"] = C.blood_volume
|
||||
data["occupant"]["blood"]["dangerBloodVolume"] = BLOOD_VOLUME_SAFE
|
||||
data["occupant"]["blood"]["bloodType"] = blood_type
|
||||
if(istype(C)) //Non-carbons shouldn't be able to enter sleepers, but this is to prevent runtimes if something ever breaks
|
||||
if(mob_occupant.has_dna()) // Blood-stuff is mostly a copy-paste from the healthscanner.
|
||||
blood_percent = round((C.blood_volume / BLOOD_VOLUME_NORMAL)*100)
|
||||
var/blood_id = C.get_blood_id()
|
||||
var/blood_warning = ""
|
||||
if(blood_percent < 80)
|
||||
blood_warning = "Patient has low blood levels."
|
||||
if(blood_percent < 60)
|
||||
blood_warning = "Patient has DANGEROUSLY low blood levels."
|
||||
if(blood_id)
|
||||
var/blood_type = C.dna.blood_type
|
||||
if(!(blood_id in GLOB.blood_reagent_types)) // special blood substance
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id]
|
||||
if(R)
|
||||
blood_type = R.name
|
||||
else
|
||||
blood_type = blood_id
|
||||
data["blood_status"] = "Patient has [blood_type] type blood. [blood_warning]"
|
||||
data["blood_levels"] = blood_percent
|
||||
return data
|
||||
|
||||
/obj/machinery/sleeper/ui_act(action, params)
|
||||
@@ -309,14 +319,14 @@
|
||||
if(allowed(usr))
|
||||
if(!is_operational())
|
||||
return
|
||||
reagents.remove_reagent(chem, 10)
|
||||
reagents.remove_reagent(chem, 1000)
|
||||
return
|
||||
if(chem in available_chems)
|
||||
if(!is_operational())
|
||||
return
|
||||
/*var/datum/reagent/R = reagents.has_reagent(chem) //For when purity effects are in
|
||||
if(R.purity < 0.8)*/
|
||||
reagents.remove_reagent(chem, 10)
|
||||
reagents.remove_reagent(chem, 1000)
|
||||
else
|
||||
visible_message("<span class='warning'>Access Denied.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
|
||||
@@ -189,96 +189,139 @@
|
||||
if(beaker)
|
||||
for(var/datum/reagent/R in beaker.reagents.reagent_list)
|
||||
beakerContents.Add(list(list("name" = R.name, "id" = ckey(R.name), "volume" = R.volume))) // list in a list because Byond merges the first list...
|
||||
data["beakerContents"] = beakerContents
|
||||
data["beakerContents"] = beakerContents
|
||||
|
||||
var/bufferContents[0]
|
||||
if(reagents.total_volume)
|
||||
for(var/datum/reagent/N in reagents.reagent_list)
|
||||
bufferContents.Add(list(list("name" = N.name, "id" = ckey(N.name), "volume" = N.volume))) // ^
|
||||
data["bufferContents"] = bufferContents
|
||||
data["bufferContents"] = bufferContents
|
||||
|
||||
//Calculated at init time as it never changes
|
||||
data["pillStyles"] = pillStyles
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/chem_master/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("eject")
|
||||
replace_beaker(usr)
|
||||
. = TRUE
|
||||
|
||||
if("ejectp")
|
||||
if("ejectPillBottle")
|
||||
replace_pillbottle(usr)
|
||||
. = TRUE
|
||||
|
||||
if("transferToBuffer")
|
||||
if(beaker)
|
||||
var/reagent = GLOB.name2reagent[params["id"]]
|
||||
var/amount = text2num(params["amount"])
|
||||
if (amount > 0)
|
||||
end_fermi_reaction()
|
||||
beaker.reagents.trans_id_to(src, reagent, amount)
|
||||
. = TRUE
|
||||
else if (amount == -1) // -1 means custom amount
|
||||
useramount = input("Enter the Amount you want to transfer:", name, useramount) as num|null
|
||||
if (useramount > 0)
|
||||
end_fermi_reaction()
|
||||
beaker.reagents.trans_id_to(src, reagent, useramount)
|
||||
. = TRUE
|
||||
|
||||
if("transferFromBuffer")
|
||||
if("transfer")
|
||||
if(!beaker)
|
||||
return FALSE
|
||||
var/reagent = GLOB.name2reagent[params["id"]]
|
||||
var/amount = text2num(params["amount"])
|
||||
if (amount > 0)
|
||||
if(mode)
|
||||
reagents.trans_id_to(beaker, reagent, amount)
|
||||
. = TRUE
|
||||
else
|
||||
reagents.remove_reagent(reagent, amount)
|
||||
. = TRUE
|
||||
else if (amount == -1) // -1 means custom amount
|
||||
useramount = input("Enter the Amount you want to transfer:", name, useramount) as num|null
|
||||
if (useramount > 0)
|
||||
end_fermi_reaction()
|
||||
reagents.trans_id_to(beaker, reagent, useramount)
|
||||
. = TRUE
|
||||
var/to_container = params["to"]
|
||||
// Custom amount
|
||||
if (amount == -1)
|
||||
amount = text2num(input(
|
||||
"Enter the amount you want to transfer:",
|
||||
name, ""))
|
||||
if (amount == null || amount <= 0)
|
||||
return FALSE
|
||||
if (to_container == "buffer")
|
||||
end_fermi_reaction()
|
||||
beaker.reagents.trans_id_to(src, reagent, amount)
|
||||
return TRUE
|
||||
if (to_container == "beaker" && mode)
|
||||
end_fermi_reaction()
|
||||
reagents.trans_id_to(beaker, reagent, amount)
|
||||
return TRUE
|
||||
if (to_container == "beaker" && !mode)
|
||||
end_fermi_reaction()
|
||||
reagents.remove_reagent(reagent, amount)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
if("toggleMode")
|
||||
mode = !mode
|
||||
. = TRUE
|
||||
|
||||
if("createPill")
|
||||
var/many = params["many"]
|
||||
if("pillStyle")
|
||||
var/id = text2num(params["id"])
|
||||
chosenPillStyle = id
|
||||
return TRUE
|
||||
|
||||
if("create")
|
||||
if(reagents.total_volume == 0)
|
||||
return
|
||||
if(!condi)
|
||||
var/amount = 1
|
||||
var/vol_each = min(reagents.total_volume, 50)
|
||||
if(text2num(many))
|
||||
amount = CLAMP(round(input(usr, "Max 10. Buffer content will be split evenly.", "How many pills?", amount) as num|null), 0, 10)
|
||||
if(!amount)
|
||||
return
|
||||
vol_each = min(reagents.total_volume / amount, 50)
|
||||
var/name = html_decode(stripped_input(usr,"Name:","Name your pill!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
return FALSE
|
||||
var/item_type = params["type"]
|
||||
// Get amount of items
|
||||
var/amount = text2num(params["amount"])
|
||||
if(amount == null)
|
||||
amount = text2num(input(usr,
|
||||
"Max 10. Buffer content will be split evenly.",
|
||||
"How many to make?", 1))
|
||||
amount = clamp(round(amount), 0, 10)
|
||||
if (amount <= 0)
|
||||
return FALSE
|
||||
// Get units per item
|
||||
var/vol_each = text2num(params["volume"])
|
||||
var/vol_each_text = params["volume"]
|
||||
var/vol_each_max = reagents.total_volume / amount
|
||||
if (item_type == "pill")
|
||||
vol_each_max = min(50, vol_each_max)
|
||||
else if (item_type == "patch")
|
||||
vol_each_max = min(40, vol_each_max)
|
||||
else if (item_type == "bottle")
|
||||
vol_each_max = min(30, vol_each_max)
|
||||
else if (item_type == "condimentPack")
|
||||
vol_each_max = min(10, vol_each_max)
|
||||
else if (item_type == "condimentBottle")
|
||||
vol_each_max = min(50, vol_each_max)
|
||||
else if (item_type == "hypoVial")
|
||||
vol_each_max = min(60, vol_each_max)
|
||||
else if (item_type == "smartDart")
|
||||
vol_each_max = min(20, vol_each_max)
|
||||
else
|
||||
return FALSE
|
||||
if(vol_each_text == "auto")
|
||||
vol_each = vol_each_max
|
||||
if(vol_each == null)
|
||||
vol_each = text2num(input(usr,
|
||||
"Maximum [vol_each_max] units per item.",
|
||||
"How many units to fill?",
|
||||
vol_each_max))
|
||||
vol_each = clamp(vol_each, 0, vol_each_max)
|
||||
if(vol_each <= 0)
|
||||
return FALSE
|
||||
// Get item name
|
||||
var/name = params["name"]
|
||||
var/name_has_units = item_type == "pill" || item_type == "patch"
|
||||
if(!name)
|
||||
var/name_default = reagents.get_master_reagent_name()
|
||||
if (name_has_units)
|
||||
name_default += " ([vol_each]u)"
|
||||
name = stripped_input(usr,
|
||||
"Name:",
|
||||
"Give it a name!",
|
||||
name_default,
|
||||
MAX_NAME_LEN)
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
|
||||
return FALSE
|
||||
// Start filling
|
||||
if(item_type == "pill")
|
||||
var/obj/item/reagent_containers/pill/P
|
||||
var/target_loc = drop_location()
|
||||
var/drop_threshold = INFINITY
|
||||
if(bottle)
|
||||
var/datum/component/storage/STRB = bottle.GetComponent(/datum/component/storage)
|
||||
var/datum/component/storage/STRB = bottle.GetComponent(
|
||||
/datum/component/storage)
|
||||
if(STRB)
|
||||
drop_threshold = STRB.max_items - bottle.contents.len
|
||||
target_loc = bottle
|
||||
|
||||
for(var/i in 1 to amount)
|
||||
if(i <= drop_threshold)
|
||||
P = new(target_loc)
|
||||
for(var/i = 0; i < amount; i++)
|
||||
if(i < drop_threshold)
|
||||
P = new/obj/item/reagent_containers/pill(target_loc)
|
||||
else
|
||||
P = new(drop_location())
|
||||
P = new/obj/item/reagent_containers/pill(drop_location())
|
||||
P.name = trim("[name] pill")
|
||||
if(chosenPillStyle == RANDOM_PILL_STYLE)
|
||||
P.icon_state ="pill[rand(1,21)]"
|
||||
@@ -287,171 +330,62 @@
|
||||
if(P.icon_state == "pill4")
|
||||
P.desc = "A tablet or capsule, but not just any, a red one, one taken by the ones not scared of knowledge, freedom, uncertainty and the brutal truths of reality."
|
||||
adjust_item_drop_location(P)
|
||||
reagents.trans_to(P,vol_each)
|
||||
else
|
||||
var/name = html_decode(stripped_input(usr, "Name:", "Name your pack!", reagents.get_master_reagent_name(), MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
var/obj/item/reagent_containers/food/condiment/pack/P = new/obj/item/reagent_containers/food/condiment/pack(drop_location())
|
||||
|
||||
P.originalname = name
|
||||
P.name = trim("[name] pack")
|
||||
P.desc = "A small condiment pack. The label says it contains [name]."
|
||||
reagents.trans_to(P,10)
|
||||
. = TRUE
|
||||
|
||||
if("pillStyle")
|
||||
var/id = text2num(params["id"])
|
||||
chosenPillStyle = id
|
||||
|
||||
if("createPatch")
|
||||
var/many = params["many"]
|
||||
if(reagents.total_volume == 0)
|
||||
return
|
||||
var/amount = 1
|
||||
var/vol_each = min(reagents.total_volume, 40)
|
||||
if(text2num(many))
|
||||
amount = CLAMP(round(input(usr, "Max 10. Buffer content will be split evenly.", "How many patches?", amount) as num|null), 0, 10)
|
||||
if(!amount)
|
||||
return
|
||||
vol_each = min(reagents.total_volume / amount, 40)
|
||||
var/name = html_decode(stripped_input(usr,"Name:","Name your patch!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
var/obj/item/reagent_containers/pill/P
|
||||
|
||||
for(var/i = 0; i < amount; i++)
|
||||
P = new/obj/item/reagent_containers/pill/patch(drop_location())
|
||||
P.name = trim("[name] patch")
|
||||
adjust_item_drop_location(P)
|
||||
reagents.trans_to(P,vol_each)
|
||||
. = TRUE
|
||||
|
||||
if("createBottle")
|
||||
var/many = params["many"]
|
||||
if(reagents.total_volume == 0)
|
||||
return
|
||||
|
||||
if(condi)
|
||||
var/name = html_decode(stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
var/obj/item/reagent_containers/food/condiment/P = new(drop_location())
|
||||
P.originalname = name
|
||||
P.name = trim("[name] bottle")
|
||||
reagents.trans_to(P, P.volume)
|
||||
else
|
||||
var/amount_full = 0
|
||||
var/vol_part = min(reagents.total_volume, 30)
|
||||
if(text2num(many))
|
||||
amount_full = round(reagents.total_volume / 30)
|
||||
vol_part = ((reagents.total_volume*1000) % 30000) / 1000 //% operator doesn't support decimals.
|
||||
var/name = html_decode(stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
|
||||
reagents.trans_to(P, vol_each)
|
||||
return TRUE
|
||||
if(item_type == "patch")
|
||||
var/obj/item/reagent_containers/pill/patch/P
|
||||
for(var/i = 0; i < amount; i++)
|
||||
P = new/obj/item/reagent_containers/pill/patch(drop_location())
|
||||
P.name = trim("[name] patch")
|
||||
adjust_item_drop_location(P)
|
||||
reagents.trans_to(P, vol_each)
|
||||
return TRUE
|
||||
if(item_type == "bottle")
|
||||
var/obj/item/reagent_containers/glass/bottle/P
|
||||
for(var/i = 0; i < amount_full; i++)
|
||||
for(var/i = 0; i < amount; i++)
|
||||
P = new/obj/item/reagent_containers/glass/bottle(drop_location())
|
||||
P.name = trim("[name] bottle")
|
||||
adjust_item_drop_location(P)
|
||||
reagents.trans_to(P, 30)
|
||||
|
||||
if(vol_part)
|
||||
P = new/obj/item/reagent_containers/glass/bottle(drop_location())
|
||||
reagents.trans_to(P, vol_each)
|
||||
return TRUE
|
||||
if(item_type == "condimentPack")
|
||||
var/obj/item/reagent_containers/food/condiment/pack/P
|
||||
for(var/i = 0; i < amount; i++)
|
||||
P = new/obj/item/reagent_containers/food/condiment/pack(drop_location())
|
||||
P.originalname = name
|
||||
P.name = trim("[name] pack")
|
||||
P.desc = "A small condiment pack. The label says it contains [name]."
|
||||
reagents.trans_to(P, vol_each)
|
||||
return TRUE
|
||||
if(item_type == "condimentBottle")
|
||||
var/obj/item/reagent_containers/food/condiment/P
|
||||
for(var/i = 0; i < amount; i++)
|
||||
P = new/obj/item/reagent_containers/food/condiment(drop_location())
|
||||
P.originalname = name
|
||||
P.name = trim("[name] bottle")
|
||||
reagents.trans_to(P, vol_each)
|
||||
return TRUE
|
||||
if(item_type == "hypoVial")
|
||||
var/obj/item/reagent_containers/glass/bottle/vial/small/P
|
||||
for(var/i = 0; i < amount; i++)
|
||||
P = new/obj/item/reagent_containers/glass/bottle/vial/small(drop_location())
|
||||
P.name = trim("[name] hypovial")
|
||||
adjust_item_drop_location(P)
|
||||
reagents.trans_to(P, vol_part)
|
||||
. = TRUE
|
||||
//CITADEL ADD Hypospray Vials
|
||||
if("createVial")
|
||||
var/many = params["many"]
|
||||
if(reagents.total_volume == 0)
|
||||
return
|
||||
reagents.trans_to(P, vol_each)
|
||||
return TRUE
|
||||
if(item_type == "smartDart")
|
||||
var/obj/item/reagent_containers/syringe/dart/P
|
||||
for(var/i = 0; i < amount; i++)
|
||||
P = new /obj/item/reagent_containers/syringe/dart(drop_location())
|
||||
P.name = trim("[name] SmartDart")
|
||||
adjust_item_drop_location(P)
|
||||
reagents.trans_to(P, vol_each)
|
||||
P.mode=!mode
|
||||
P.update_icon()
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
var/amount_full = 0
|
||||
var/vol_part = min(reagents.total_volume, 60)
|
||||
if(text2num(many))
|
||||
amount_full = round(reagents.total_volume / 60)
|
||||
vol_part = reagents.total_volume % 60
|
||||
var/name = html_decode(stripped_input(usr, "Name:","Name your hypovial!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
|
||||
var/obj/item/reagent_containers/glass/bottle/vial/small/P
|
||||
for(var/i = 0; i < amount_full; i++)
|
||||
P = new/obj/item/reagent_containers/glass/bottle/vial/small(drop_location())
|
||||
P.name = trim("[name] hypovial")
|
||||
adjust_item_drop_location(P)
|
||||
reagents.trans_to(P, 60)
|
||||
|
||||
if(vol_part)
|
||||
P = new/obj/item/reagent_containers/glass/bottle/vial/small(drop_location())
|
||||
P.name = trim("[name] hypovial")
|
||||
adjust_item_drop_location(P)
|
||||
reagents.trans_to(P, vol_part)
|
||||
. = TRUE
|
||||
|
||||
if("createDart")
|
||||
for(var/datum/reagent/R in reagents.reagent_list)
|
||||
if(!(istype(R, /datum/reagent/medicine)))
|
||||
visible_message("<b>The [src]</b> beeps, \"<span class='warning'>SmartDarts are insoluble with non-medicinal compounds.\"</span>")
|
||||
return
|
||||
|
||||
var/many = params["many"]
|
||||
if(reagents.total_volume == 0)
|
||||
return
|
||||
var/amount = 1
|
||||
var/vol_each = min(reagents.total_volume, 20)
|
||||
if(text2num(many))
|
||||
amount = CLAMP(round(input(usr, "Max 10. Buffer content will be split evenly.", "How many darts?", amount) as num|null), 0, 10)
|
||||
if(!amount)
|
||||
return
|
||||
vol_each = min(reagents.total_volume / amount, 20)
|
||||
|
||||
var/name = html_decode(stripped_input(usr,"Name:","Name your SmartDart!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
|
||||
var/obj/item/reagent_containers/syringe/dart/D
|
||||
for(var/i = 0; i < amount; i++)
|
||||
D = new /obj/item/reagent_containers/syringe/dart(drop_location())
|
||||
D.name = trim("[name] SmartDart")
|
||||
adjust_item_drop_location(D)
|
||||
reagents.trans_to(D, vol_each)
|
||||
D.mode=!mode
|
||||
D.update_icon()
|
||||
. = TRUE
|
||||
|
||||
//END CITADEL ADDITIONS
|
||||
if("analyzeBeak")
|
||||
var/datum/reagent/R = GLOB.name2reagent[params["id"]]
|
||||
if(R)
|
||||
var/state = "Unknown"
|
||||
if(initial(R.reagent_state) == 1)
|
||||
state = "Solid"
|
||||
else if(initial(R.reagent_state) == 2)
|
||||
state = "Liquid"
|
||||
else if(initial(R.reagent_state) == 3)
|
||||
state = "Gas"
|
||||
var/const/P = 3 //The number of seconds between life ticks
|
||||
var/T = initial(R.metabolization_rate) * (60 / P)
|
||||
var/datum/chemical_reaction/Rcr = get_chemical_reaction(R)
|
||||
if(Rcr && Rcr.FermiChem)
|
||||
fermianalyze = TRUE
|
||||
var/pHpeakCache = (Rcr.OptimalpHMin + Rcr.OptimalpHMax)/2
|
||||
var/datum/reagent/targetReagent = beaker.reagents.has_reagent(R)
|
||||
|
||||
if(!targetReagent)
|
||||
CRASH("Tried to find a reagent that doesn't exist in the chem_master!")
|
||||
analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold), "purityF" = targetReagent.purity, "inverseRatioF" = initial(R.inverse_chem_val), "purityE" = initial(Rcr.PurityMin), "minTemp" = initial(Rcr.OptimalTempMin), "maxTemp" = initial(Rcr.OptimalTempMax), "eTemp" = initial(Rcr.ExplodeTemp), "pHpeak" = pHpeakCache)
|
||||
else
|
||||
fermianalyze = FALSE
|
||||
analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold))
|
||||
screen = "analyze"
|
||||
return
|
||||
|
||||
if("analyzeBuff")
|
||||
if("analyze")
|
||||
var/datum/reagent/R = GLOB.name2reagent[params["id"]]
|
||||
if(R)
|
||||
var/state = "Unknown"
|
||||
@@ -476,7 +410,7 @@
|
||||
fermianalyze = FALSE
|
||||
analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold))
|
||||
screen = "analyze"
|
||||
return
|
||||
return TRUE
|
||||
|
||||
if("goScreen")
|
||||
screen = params["screen"]
|
||||
@@ -527,4 +461,4 @@
|
||||
condi = TRUE
|
||||
|
||||
#undef PILL_STYLE_COUNT
|
||||
#undef RANDOM_PILL_STYLE
|
||||
#undef RANDOM_PILL_STYLE
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
import { toFixed } from 'common/math';
|
||||
import { toTitleCase } from 'common/string';
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend } from '../backend';
|
||||
import { AnimatedNumber, Box, Button, Icon, LabeledList, ProgressBar, Section } from '../components';
|
||||
|
||||
export const ChemDispenser = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
const recording = !!data.recordingRecipe;
|
||||
// TODO: Change how this piece of shit is built on server side
|
||||
// It has to be a list, not a fucking OBJECT!
|
||||
const recipes = Object.keys(data.recipes)
|
||||
.map(name => ({
|
||||
name,
|
||||
contents: data.recipes[name],
|
||||
}));
|
||||
const beakerTransferAmounts = data.beakerTransferAmounts || [];
|
||||
const beakerContents = recording
|
||||
&& Object.keys(data.recordingRecipe)
|
||||
.map(id => ({
|
||||
id,
|
||||
name: toTitleCase(id.replace(/_/, ' ')),
|
||||
volume: data.recordingRecipe[id],
|
||||
}))
|
||||
|| data.beakerContents
|
||||
|| [];
|
||||
return (
|
||||
<Fragment>
|
||||
<Section
|
||||
title="Status"
|
||||
buttons={recording && (
|
||||
<Box inline mx={1} color="red">
|
||||
<Icon name="circle" mr={1} />
|
||||
Recording
|
||||
</Box>
|
||||
)}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Energy">
|
||||
<ProgressBar
|
||||
value={data.energy / data.maxEnergy}
|
||||
content={toFixed(data.energy) + ' units'} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section
|
||||
title="Recipes"
|
||||
buttons={(
|
||||
<Fragment>
|
||||
{!recording && (
|
||||
<Box inline mx={1}>
|
||||
<Button
|
||||
color="transparent"
|
||||
content="Clear recipes"
|
||||
onClick={() => act('clear_recipes')} />
|
||||
</Box>
|
||||
)}
|
||||
{!recording && (
|
||||
<Button
|
||||
icon="circle"
|
||||
disabled={!data.isBeakerLoaded}
|
||||
content="Record"
|
||||
onClick={() => act('record_recipe')} />
|
||||
)}
|
||||
{recording && (
|
||||
<Button
|
||||
icon="ban"
|
||||
color="transparent"
|
||||
content="Discard"
|
||||
onClick={() => act('cancel_recording')} />
|
||||
)}
|
||||
{recording && (
|
||||
<Button
|
||||
icon="save"
|
||||
color="green"
|
||||
content="Save"
|
||||
onClick={() => act('save_recording')} />
|
||||
)}
|
||||
</Fragment>
|
||||
)}>
|
||||
<Box mr={-1}>
|
||||
{recipes.map(recipe => (
|
||||
<Button key={recipe.name}
|
||||
icon="tint"
|
||||
width="129.5px"
|
||||
lineHeight="21px"
|
||||
content={recipe.name}
|
||||
onClick={() => act('dispense_recipe', {
|
||||
recipe: recipe.name,
|
||||
})} />
|
||||
))}
|
||||
{recipes.length === 0 && (
|
||||
<Box color="light-gray">
|
||||
No recipes.
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Section>
|
||||
<Section
|
||||
title="Dispense"
|
||||
buttons={(
|
||||
beakerTransferAmounts.map(amount => (
|
||||
<Button key={amount}
|
||||
icon="plus"
|
||||
selected={amount === data.amount}
|
||||
content={amount}
|
||||
onClick={() => act('amount', {
|
||||
target: amount,
|
||||
})} />
|
||||
))
|
||||
)}>
|
||||
<Box mr={-1}>
|
||||
{data.chemicals.map(chemical => (
|
||||
<Button key={chemical.id}
|
||||
icon="tint"
|
||||
width="129.5px"
|
||||
lineHeight="21px"
|
||||
content={chemical.title}
|
||||
onClick={() => act('dispense', {
|
||||
reagent: chemical.id,
|
||||
})} />
|
||||
))}
|
||||
</Box>
|
||||
</Section>
|
||||
<Section
|
||||
title="Beaker"
|
||||
buttons={(
|
||||
beakerTransferAmounts.map(amount => (
|
||||
<Button key={amount}
|
||||
icon="minus"
|
||||
disabled={recording}
|
||||
content={amount}
|
||||
onClick={() => act('remove', { amount })} />
|
||||
))
|
||||
)}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label="Beaker"
|
||||
buttons={!!data.isBeakerLoaded && (
|
||||
<Button
|
||||
icon="eject"
|
||||
content="Eject"
|
||||
disabled={!data.isBeakerLoaded}
|
||||
onClick={() => act('eject')} />
|
||||
)}>
|
||||
{recording
|
||||
&& 'Virtual beaker'
|
||||
|| data.isBeakerLoaded
|
||||
&& (
|
||||
<Fragment>
|
||||
<AnimatedNumber
|
||||
initial={0}
|
||||
value={data.beakerCurrentVolume} />
|
||||
/{data.beakerMaxVolume} units
|
||||
</Fragment>
|
||||
)
|
||||
|| 'No beaker'}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item
|
||||
label="Contents">
|
||||
<Box color="label">
|
||||
{(!data.isBeakerLoaded && !recording) && 'N/A'
|
||||
|| beakerContents.length === 0 && 'Nothing'}
|
||||
</Box>
|
||||
{beakerContents.map(chemical => (
|
||||
<Box
|
||||
key={chemical.name}
|
||||
color="label">
|
||||
<AnimatedNumber
|
||||
initial={0}
|
||||
value={chemical.volume} />
|
||||
{' '}
|
||||
units of {chemical.name}
|
||||
</Box>
|
||||
))}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
import { round, toFixed } from 'common/math';
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend } from '../backend';
|
||||
import { AnimatedNumber, Box, Button, LabeledList, NumberInput, Section } from '../components';
|
||||
import { BeakerContents } from './common/BeakerContents';
|
||||
|
||||
export const ChemHeater = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
const {
|
||||
targetTemp,
|
||||
isActive,
|
||||
isBeakerLoaded,
|
||||
currentTemp,
|
||||
beakerCurrentVolume,
|
||||
beakerMaxVolume,
|
||||
beakerContents = [],
|
||||
} = data;
|
||||
return (
|
||||
<Fragment>
|
||||
<Section
|
||||
title="Thermostat"
|
||||
buttons={(
|
||||
<Button
|
||||
icon={isActive ? 'power-off' : 'times'}
|
||||
selected={isActive}
|
||||
content={isActive ? 'On' : 'Off'}
|
||||
onClick={() => act('power')} />
|
||||
)}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Target">
|
||||
<NumberInput
|
||||
width="65px"
|
||||
unit="K"
|
||||
step={2}
|
||||
stepPixelSize={1}
|
||||
value={round(targetTemp)}
|
||||
minValue={0}
|
||||
maxValue={1000}
|
||||
onDrag={(e, value) => act('temperature', {
|
||||
target: value,
|
||||
})} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Reading">
|
||||
<Box
|
||||
width="60px"
|
||||
textAlign="right">
|
||||
{isBeakerLoaded && (
|
||||
<AnimatedNumber
|
||||
value={currentTemp}
|
||||
format={value => toFixed(value) + ' K'} />
|
||||
) || '—'}
|
||||
</Box>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section
|
||||
title="Beaker"
|
||||
buttons={!!isBeakerLoaded && (
|
||||
<Fragment>
|
||||
<Box inline color="label" mr={2}>
|
||||
{beakerCurrentVolume} / {beakerMaxVolume} units
|
||||
</Box>
|
||||
<Button
|
||||
icon="eject"
|
||||
content="Eject"
|
||||
onClick={() => act('eject')} />
|
||||
</Fragment>
|
||||
)}>
|
||||
<BeakerContents
|
||||
beakerLoaded={isBeakerLoaded}
|
||||
beakerContents={beakerContents} />
|
||||
</Section>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,448 @@
|
||||
import { Component, Fragment } from 'inferno';
|
||||
import { act } from '../byond';
|
||||
import { AnimatedNumber, Box, Button, ColorBox, LabeledList, NumberInput, Section, Table } from '../components';
|
||||
|
||||
export const ChemMaster = props => {
|
||||
const { state } = props;
|
||||
const { config, data } = state;
|
||||
const { ref } = config;
|
||||
const {
|
||||
screen,
|
||||
beakerContents = [],
|
||||
bufferContents = [],
|
||||
beakerCurrentVolume,
|
||||
beakerMaxVolume,
|
||||
isBeakerLoaded,
|
||||
isPillBottleLoaded,
|
||||
pillBottleCurrentAmount,
|
||||
pillBottleMaxAmount,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Section
|
||||
title="Beaker"
|
||||
buttons={!!data.isBeakerLoaded && (
|
||||
<Fragment>
|
||||
<Box inline color="label" mr={2}>
|
||||
<AnimatedNumber
|
||||
value={beakerCurrentVolume}
|
||||
initial={0} />
|
||||
{` / ${beakerMaxVolume} units`}
|
||||
</Box>
|
||||
<Button
|
||||
icon="eject"
|
||||
content="Eject"
|
||||
onClick={() => act(ref, 'eject')} />
|
||||
</Fragment>
|
||||
)}>
|
||||
{!isBeakerLoaded && (
|
||||
<Box color="label" mt="3px" mb="5px">
|
||||
No beaker loaded.
|
||||
</Box>
|
||||
)}
|
||||
{!!isBeakerLoaded && beakerContents.length === 0 && (
|
||||
<Box color="label" mt="3px" mb="5px">
|
||||
Beaker is empty.
|
||||
</Box>
|
||||
)}
|
||||
<ChemicalBuffer>
|
||||
{beakerContents.map(chemical => (
|
||||
<ChemicalBufferEntry
|
||||
key={chemical.id}
|
||||
state={state}
|
||||
chemical={chemical}
|
||||
transferTo="buffer" />
|
||||
))}
|
||||
</ChemicalBuffer>
|
||||
</Section>
|
||||
<Section
|
||||
title="Buffer"
|
||||
buttons={(
|
||||
<Fragment>
|
||||
<Box inline color="label" mr={1}>
|
||||
Mode:
|
||||
</Box>
|
||||
<Button
|
||||
color={data.mode ? 'good' : 'bad'}
|
||||
icon={data.mode ? 'exchange-alt' : 'times'}
|
||||
content={data.mode ? 'Transfer' : 'Destroy'}
|
||||
onClick={() => act(ref, 'toggleMode')} />
|
||||
</Fragment>
|
||||
)}>
|
||||
{bufferContents.length === 0 && (
|
||||
<Box color="label" mt="3px" mb="5px">
|
||||
Buffer is empty.
|
||||
</Box>
|
||||
)}
|
||||
<ChemicalBuffer>
|
||||
{bufferContents.map(chemical => (
|
||||
<ChemicalBufferEntry
|
||||
key={chemical.id}
|
||||
state={state}
|
||||
chemical={chemical}
|
||||
transferTo="beaker" />
|
||||
))}
|
||||
</ChemicalBuffer>
|
||||
</Section>
|
||||
<Section
|
||||
title="Packaging">
|
||||
<PackagingControls state={state} />
|
||||
</Section>
|
||||
{!!isPillBottleLoaded && (
|
||||
<Section
|
||||
title="Pill Bottle"
|
||||
buttons={(
|
||||
<Fragment>
|
||||
<Box inline color="label" mr={2}>
|
||||
{pillBottleCurrentAmount} / {pillBottleMaxAmount} pills
|
||||
</Box>
|
||||
<Button
|
||||
icon="eject"
|
||||
content="Eject"
|
||||
onClick={() => act(ref, 'ejectPillBottle')} />
|
||||
</Fragment>
|
||||
)} />
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const ChemicalBuffer = Table;
|
||||
|
||||
const ChemicalBufferEntry = props => {
|
||||
const { state, chemical, transferTo } = props;
|
||||
const { ref } = state.config;
|
||||
return (
|
||||
<Table.Row key={chemical.id}>
|
||||
<Table.Cell color="label">
|
||||
<AnimatedNumber
|
||||
value={chemical.volume}
|
||||
initial={0} />
|
||||
{` units of ${chemical.name}`}
|
||||
</Table.Cell>
|
||||
<Table.Cell collapsing>
|
||||
<Button
|
||||
content="1"
|
||||
onClick={() => act(ref, 'transfer', {
|
||||
id: chemical.id,
|
||||
amount: 1,
|
||||
to: transferTo,
|
||||
})} />
|
||||
<Button
|
||||
content="5"
|
||||
onClick={() => act(ref, 'transfer', {
|
||||
id: chemical.id,
|
||||
amount: 5,
|
||||
to: transferTo,
|
||||
})} />
|
||||
<Button
|
||||
content="10"
|
||||
onClick={() => act(ref, 'transfer', {
|
||||
id: chemical.id,
|
||||
amount: 10,
|
||||
to: transferTo,
|
||||
})} />
|
||||
<Button
|
||||
content="All"
|
||||
onClick={() => act(ref, 'transfer', {
|
||||
id: chemical.id,
|
||||
amount: 1000,
|
||||
to: transferTo,
|
||||
})} />
|
||||
<Button
|
||||
icon="ellipsis-h"
|
||||
title="Custom amount"
|
||||
onClick={() => act(ref, 'transfer', {
|
||||
id: chemical.id,
|
||||
amount: -1,
|
||||
to: transferTo,
|
||||
})} />
|
||||
<Button
|
||||
icon="question"
|
||||
title="Analyze"
|
||||
onClick={() => act(ref, 'analyze', {
|
||||
id: chemical.id,
|
||||
})} />
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
);
|
||||
};
|
||||
|
||||
const PackagingControlsItem = props => {
|
||||
const {
|
||||
label,
|
||||
amountUnit,
|
||||
amount,
|
||||
onChangeAmount,
|
||||
onCreate,
|
||||
sideNote,
|
||||
} = props;
|
||||
return (
|
||||
<LabeledList.Item label={label}>
|
||||
<NumberInput
|
||||
width={14}
|
||||
unit={amountUnit}
|
||||
step={1}
|
||||
stepPixelSize={15}
|
||||
value={amount}
|
||||
minValue={1}
|
||||
maxValue={10}
|
||||
onChange={onChangeAmount} />
|
||||
<Button ml={1}
|
||||
content="Create"
|
||||
onClick={onCreate} />
|
||||
<Box inline ml={1}
|
||||
color="label"
|
||||
content={sideNote} />
|
||||
</LabeledList.Item>
|
||||
);
|
||||
};
|
||||
|
||||
class PackagingControls extends Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
pillAmount: 1,
|
||||
patchAmount: 1,
|
||||
bottleAmount: 1,
|
||||
packAmount: 1,
|
||||
vialAmount: 1,
|
||||
dartAmount: 1,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { state, props } = this;
|
||||
const { ref } = props.state.config;
|
||||
const {
|
||||
pillAmount,
|
||||
patchAmount,
|
||||
bottleAmount,
|
||||
packAmount,
|
||||
vialAmount,
|
||||
dartAmount,
|
||||
} = this.state;
|
||||
const {
|
||||
condi,
|
||||
chosenPillStyle,
|
||||
pillStyles = [],
|
||||
} = props.state.data;
|
||||
return (
|
||||
<LabeledList>
|
||||
{!condi && (
|
||||
<LabeledList.Item label="Pill type">
|
||||
{pillStyles.map(pill => (
|
||||
<Button
|
||||
key={pill.id}
|
||||
width={5}
|
||||
selected={pill.id === chosenPillStyle}
|
||||
textAlign="center"
|
||||
color="transparent"
|
||||
onClick={() => act(ref, 'pillStyle', { id: pill.id })}>
|
||||
<Box mx={-1} className={pill.className} />
|
||||
</Button>
|
||||
))}
|
||||
</LabeledList.Item>
|
||||
)}
|
||||
{!condi && (
|
||||
<PackagingControlsItem
|
||||
label="Pills"
|
||||
amount={pillAmount}
|
||||
amountUnit="pills"
|
||||
sideNote="max 50u"
|
||||
onChangeAmount={(e, value) => this.setState({
|
||||
pillAmount: value,
|
||||
})}
|
||||
onCreate={() => act(ref, 'create', {
|
||||
type: 'pill',
|
||||
amount: pillAmount,
|
||||
volume: 'auto',
|
||||
})} />
|
||||
)}
|
||||
{!condi && (
|
||||
<PackagingControlsItem
|
||||
label="Patches"
|
||||
amount={patchAmount}
|
||||
amountUnit="patches"
|
||||
sideNote="max 40u"
|
||||
onChangeAmount={(e, value) => this.setState({
|
||||
patchAmount: value,
|
||||
})}
|
||||
onCreate={() => act(ref, 'create', {
|
||||
type: 'patch',
|
||||
amount: patchAmount,
|
||||
volume: 'auto',
|
||||
})} />
|
||||
)}
|
||||
{!condi && (
|
||||
<PackagingControlsItem
|
||||
label="Bottles"
|
||||
amount={bottleAmount}
|
||||
amountUnit="bottles"
|
||||
sideNote="max 30u"
|
||||
onChangeAmount={(e, value) => this.setState({
|
||||
bottleAmount: value,
|
||||
})}
|
||||
onCreate={() => act(ref, 'create', {
|
||||
type: 'bottle',
|
||||
amount: bottleAmount,
|
||||
volume: 'auto',
|
||||
})} />
|
||||
)}
|
||||
{!condi && (
|
||||
<PackagingControlsItem
|
||||
label="Hypovials"
|
||||
amount={vialAmount}
|
||||
amountUnit="vials"
|
||||
sideNote="max 60u"
|
||||
onChangeAmount={(e, value) => this.setState({
|
||||
vialAmount: value,
|
||||
})}
|
||||
onCreate={() => act(ref, 'create', {
|
||||
type: 'hypoVial',
|
||||
amount: vialAmount,
|
||||
volume: 'auto',
|
||||
})} />
|
||||
)}
|
||||
{!condi && (
|
||||
<PackagingControlsItem
|
||||
label="Smartdarts"
|
||||
amount={dartAmount}
|
||||
amountUnit="darts"
|
||||
sideNote="max 20u"
|
||||
onChangeAmount={(e, value) => this.setState({
|
||||
dartAmount: value,
|
||||
})}
|
||||
onCreate={() => act(ref, 'create', {
|
||||
type: 'smartDart',
|
||||
amount: dartAmount,
|
||||
volume: 'auto',
|
||||
})} />
|
||||
)}
|
||||
{!!condi && (
|
||||
<PackagingControlsItem
|
||||
label="Packs"
|
||||
amount={packAmount}
|
||||
amountUnit="packs"
|
||||
sideNote="max 10u"
|
||||
onChangeAmount={(e, value) => this.setState({
|
||||
packAmount: value,
|
||||
})}
|
||||
onCreate={() => act(ref, 'create', {
|
||||
type: 'condimentPack',
|
||||
amount: packAmount,
|
||||
volume: 'auto',
|
||||
})} />
|
||||
)}
|
||||
{!!condi && (
|
||||
<PackagingControlsItem
|
||||
label="Bottles"
|
||||
amount={bottleAmount}
|
||||
amountUnit="bottles"
|
||||
sideNote="max 50u"
|
||||
onChangeAmount={(e, value) => this.setState({
|
||||
bottleAmount: value,
|
||||
})}
|
||||
onCreate={() => act(ref, 'create', {
|
||||
type: 'condimentBottle',
|
||||
amount: bottleAmount,
|
||||
volume: 'auto',
|
||||
})} />
|
||||
)}
|
||||
</LabeledList>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const AnalysisResults = props => {
|
||||
const { state, fermianalyze } = props;
|
||||
const { ref } = state.config;
|
||||
const { analyzeVars } = state.data;
|
||||
return (
|
||||
<Section
|
||||
title="Analysis Results"
|
||||
buttons={(
|
||||
<Button
|
||||
icon="arrow-left"
|
||||
content="Back"
|
||||
onClick={() => act(ref, 'goScreen', {
|
||||
screen: 'home',
|
||||
})} />
|
||||
)}>
|
||||
{!fermianalyze && (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Name">
|
||||
{analyzeVars.name}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="State">
|
||||
{analyzeVars.state}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Color">
|
||||
<ColorBox color={analyzeVars.color} mr={1} />
|
||||
{analyzeVars.color}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Description">
|
||||
{analyzeVars.description}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Metabolization Rate">
|
||||
{analyzeVars.metaRate} u/minute
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Overdose Threshold">
|
||||
{analyzeVars.overD}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Addiction Threshold">
|
||||
{analyzeVars.addicD}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
)}
|
||||
{!!fermianalyze && (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Name">
|
||||
{analyzeVars.name}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="State">
|
||||
{analyzeVars.state}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Color">
|
||||
<ColorBox color={analyzeVars.color} mr={1} />
|
||||
{analyzeVars.color}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Description">
|
||||
{analyzeVars.description}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Metabolization Rate">
|
||||
{analyzeVars.metaRate} u/minute
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Overdose Threshold">
|
||||
{analyzeVars.overD}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Addiction Threshold">
|
||||
{analyzeVars.addicD}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Purity">
|
||||
{analyzeVars.purityF}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Inverse Ratio">
|
||||
{analyzeVars.inverseRatioF}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Purity E">
|
||||
{analyzeVars.purityE}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Lower Optimal Temperature">
|
||||
{analyzeVars.minTemp}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Upper Optimal Temperature">
|
||||
{analyzeVars.maxTemp}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Explosive Temperature">
|
||||
{analyzeVars.eTemp}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="pH Peak">
|
||||
{analyzeVars.pHpeak}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
)}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,181 @@
|
||||
import { useBackend } from '../backend';
|
||||
import { Box, Section, LabeledList, Button, ProgressBar, Flex, AnimatedNumber } from '../components';
|
||||
import { Fragment } from 'inferno';
|
||||
|
||||
export const Sleeper = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
|
||||
const {
|
||||
occupied,
|
||||
open,
|
||||
occupant = [],
|
||||
} = data;
|
||||
|
||||
const preSortChems = data.chems || [];
|
||||
const chems = preSortChems.sort((a, b) => {
|
||||
const descA = a.name.toLowerCase();
|
||||
const descB = b.name.toLowerCase();
|
||||
if (descA < descB) {
|
||||
return -1;
|
||||
}
|
||||
if (descA > descB) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
const preSortSynth = data.synthchems || [];
|
||||
const synthchems = preSortSynth.sort((a, b) => {
|
||||
const descA = a.name.toLowerCase();
|
||||
const descB = b.name.toLowerCase();
|
||||
if (descA < descB) {
|
||||
return -1;
|
||||
}
|
||||
if (descA > descB) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
const damageTypes = [
|
||||
{
|
||||
label: 'Brute',
|
||||
type: 'bruteLoss',
|
||||
},
|
||||
{
|
||||
label: 'Burn',
|
||||
type: 'fireLoss',
|
||||
},
|
||||
{
|
||||
label: 'Toxin',
|
||||
type: 'toxLoss',
|
||||
},
|
||||
{
|
||||
label: 'Oxygen',
|
||||
type: 'oxyLoss',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Section
|
||||
title={occupant.name ? occupant.name : 'No Occupant'}
|
||||
minHeight="210px"
|
||||
buttons={!!occupant.stat && (
|
||||
<Box
|
||||
inline
|
||||
bold
|
||||
color={occupant.statstate}>
|
||||
{occupant.stat}
|
||||
</Box>
|
||||
)}>
|
||||
{!!occupied && (
|
||||
<Fragment>
|
||||
<ProgressBar
|
||||
value={occupant.health}
|
||||
minValue={occupant.minHealth}
|
||||
maxValue={occupant.maxHealth}
|
||||
ranges={{
|
||||
good: [50, Infinity],
|
||||
average: [0, 50],
|
||||
bad: [-Infinity, 0],
|
||||
}} />
|
||||
<Box mt={1} />
|
||||
<LabeledList>
|
||||
{damageTypes.map(type => (
|
||||
<LabeledList.Item
|
||||
key={type.type}
|
||||
label={type.label}>
|
||||
<ProgressBar
|
||||
value={occupant[type.type]}
|
||||
minValue={0}
|
||||
maxValue={occupant.maxHealth}
|
||||
color="bad" />
|
||||
</LabeledList.Item>
|
||||
))}
|
||||
<LabeledList.Item
|
||||
label={'Blood'}>
|
||||
<ProgressBar
|
||||
value={data.blood_levels/100}
|
||||
color="bad">
|
||||
<AnimatedNumber value={data.blood_levels} />
|
||||
</ProgressBar>
|
||||
{data.blood_status}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item
|
||||
label="Cells"
|
||||
color={occupant.cloneLoss ? 'bad' : 'good'}>
|
||||
{occupant.cloneLoss ? 'Damaged' : 'Healthy'}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item
|
||||
label="Brain"
|
||||
color={occupant.brainLoss ? 'bad' : 'good'}>
|
||||
{occupant.brainLoss ? 'Abnormal' : 'Healthy'}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Fragment>
|
||||
)}
|
||||
</Section>
|
||||
<Section title="Chemical Analysis">
|
||||
<LabeledList.Item label="Chemical Contents">
|
||||
{data.chemical_list.map(specificChem => (
|
||||
<Box
|
||||
key={specificChem.id}
|
||||
color="good" >
|
||||
{specificChem.volume} units of {specificChem.name}
|
||||
</Box>
|
||||
),
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
</Section>
|
||||
<Section
|
||||
title="Inject Chemicals"
|
||||
minHeight="105px"
|
||||
buttons={(
|
||||
<Button
|
||||
icon={open ? 'door-open' : 'door-closed'}
|
||||
content={open ? 'Open' : 'Closed'}
|
||||
onClick={() => act('door')} />
|
||||
)}>
|
||||
{chems.map(chem => (
|
||||
<Button
|
||||
key={chem.name}
|
||||
icon="flask"
|
||||
content={chem.name}
|
||||
disabled={!(occupied && chem.allowed)}
|
||||
width="140px"
|
||||
onClick={() => act('inject', {
|
||||
chem: chem.id,
|
||||
})}
|
||||
/>
|
||||
))}
|
||||
</Section>
|
||||
<Section
|
||||
title="Synthesize Chemicals">
|
||||
{synthchems.map(chem => (
|
||||
<Button
|
||||
key={chem.name}
|
||||
content={chem.name}
|
||||
width="140px"
|
||||
onClick={() => act('synth', {
|
||||
chem: chem.id,
|
||||
})}
|
||||
/>
|
||||
))}
|
||||
</Section>
|
||||
<Section
|
||||
title="Purge Chemicals">
|
||||
{chems.map(chem => (
|
||||
<Button
|
||||
key={chem.name}
|
||||
content={chem.name}
|
||||
disabled={!(chem.allowed)}
|
||||
width="140px"
|
||||
onClick={() => act('purge', {
|
||||
chem: chem.id,
|
||||
})}
|
||||
/>
|
||||
))}
|
||||
</Section>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
@@ -19,7 +19,10 @@ import { CellularEmporium } from './interfaces/CellularEmporium';
|
||||
import { CentcomPodLauncher } from './interfaces/CentcomPodLauncher';
|
||||
import { ChemAcclimator } from './interfaces/ChemAcclimator';
|
||||
import { ChemDebugSynthesizer } from './interfaces/ChemDebugSynthesizer';
|
||||
import { ChemDispenser } from './interfaces/ChemDispenser';
|
||||
import { ChemFilter } from './interfaces/ChemFilter';
|
||||
import { ChemHeater } from './interfaces/ChemHeater';
|
||||
import { ChemMaster } from './interfaces/ChemMaster';
|
||||
import { ChemPress } from './interfaces/ChemPress';
|
||||
import { ChemReactionChamber } from './interfaces/ChemReactionChamber';
|
||||
import { ChemSplitter } from './interfaces/ChemSplitter';
|
||||
@@ -76,6 +79,7 @@ import { RapidPipeDispenser } from './interfaces/RapidPipeDispenser';
|
||||
import { SatelliteControl } from './interfaces/SatelliteControl';
|
||||
import { ScannerGate } from './interfaces/ScannerGate';
|
||||
import { ShuttleManipulator } from './interfaces/ShuttleManipulator';
|
||||
import { Sleeper } from './interfaces/Sleeper';
|
||||
import { SlimeBodySwapper } from './interfaces/SlimeBodySwapper';
|
||||
import { Signaler } from './interfaces/Signaler';
|
||||
import { SmartVend } from './interfaces/SmartVend';
|
||||
@@ -185,10 +189,22 @@ const ROUTES = {
|
||||
component: () => ChemAcclimator,
|
||||
scrollable: false,
|
||||
},
|
||||
chem_dispenser: {
|
||||
component: () => ChemDispenser,
|
||||
scrollable: true,
|
||||
},
|
||||
chemical_filter: {
|
||||
component: () => ChemFilter,
|
||||
scrollable: true,
|
||||
},
|
||||
chem_heater: {
|
||||
component: () => ChemHeater,
|
||||
scrollable: true,
|
||||
},
|
||||
chem_master: {
|
||||
component: () => ChemMaster,
|
||||
scrollable: true,
|
||||
},
|
||||
chem_press: {
|
||||
component: () => ChemPress,
|
||||
scrollable: false,
|
||||
@@ -441,6 +457,10 @@ const ROUTES = {
|
||||
component: () => ShuttleManipulator,
|
||||
scrollable: true,
|
||||
},
|
||||
sleeper: {
|
||||
component: () => Sleeper,
|
||||
scrollable: false,
|
||||
},
|
||||
slime_swap_body: {
|
||||
component: () => SlimeBodySwapper,
|
||||
scrollable: true,
|
||||
|
||||
Reference in New Issue
Block a user