mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-29 08:08:49 +01:00
[MIRROR] Refactored ghetto chem separator (#27958)
* Refactored ghetto chem separator (#83275) ## About The Pull Request This completely reworks how ghetto chem separator works & brings more depth & immersion to it. To understand the new system let's compare it with the current one **Old System** 1. You insert a beaker containing the reagents you want to separate. 2. You use a lighter/whatever to light a flame, Flame has _magic & unrealistic_ properties such as - It will never heat the beaker above 100k - It doesn't burn oxygen or use fuel source to sustain it - Distillation rate is a constant 5u/s. It doesn't increase as the solution boils hotter 3. The apparatus sorts the reagents alphabetically? & transfers the 1st reagent from sorted list to the target beaker. It does not care if each individual reagent has their boiling points & how to separate them based on that etc. It's just bland overall **New System** 1. You insert a beaker containing the reagents you want to separate, just lke the old system 2. You use a lighter/whatever to light a flame just like the old system, however flame behaves in a more realistic fashion as follows - It will heat the beaker all the way to 1000k if you let it run long enough - It now burns oxygen & uses a fuel source(a secondary beaker which you must insert containing flamable reagents like oil, welding fuel etc). When oxygen is the fuel source no O2 gas is required - Distillation rate starts at 2u/s & increases with rising temps - Intensity of the flame depends on the quality of reagents used as fuel, Oil has best flammable quality & will heat the beaker faster, other reagents mixed in various proportions can produce better quality flames which you can understand by examining the aparatus - The flame intensity can be adjusted via the burner knob setting 3. Each reagent now has their _boiling computed_ computed from their mass allowing for realistic interactions, like having to control the temp's just right to separate your required reagent 4. Temps automatically cooldown and you can install a condenser to Facilitate faster cooling Here's the demo video explaining everything https://github.com/tgstation/tgstation/assets/110812394/ba591859-3fff-4d06-90f8-024c7266f830 ## Changelog 🆑 refactor: ghetto chem separator has been reworked from scratch. See PR 83275 for details qol: adds examines & screentips for ghetto chem separator /🆑 * Refactored ghetto chem separator --------- Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
This commit is contained in:
@@ -120,6 +120,20 @@
|
||||
)
|
||||
category = CAT_CHEMISTRY
|
||||
|
||||
|
||||
/datum/crafting_recipe/chem_separator
|
||||
name = "chemical separator"
|
||||
result = /obj/structure/chem_separator
|
||||
tool_behaviors = list(TOOL_WELDER)
|
||||
time = 5 SECONDS
|
||||
reqs = list(
|
||||
/obj/item/stack/sheet/mineral/wood = 1,
|
||||
/obj/item/stack/sheet/glass = 1,
|
||||
/obj/item/burner = 1,
|
||||
/obj/item/thermometer = 1,
|
||||
)
|
||||
category = CAT_CHEMISTRY
|
||||
|
||||
/datum/crafting_recipe/improvised_chem_heater
|
||||
name = "Improvised chem heater"
|
||||
result = /obj/machinery/space_heater/improvised_chem_heater
|
||||
|
||||
@@ -19,3 +19,19 @@
|
||||
mixcolor = BlendRGB(R.color, mixcolor, vol_temp/vol_counter)
|
||||
|
||||
return mixcolor
|
||||
|
||||
/proc/reagent_threshold_overlay(datum/reagents/reagents, fill_icon, fill_prefix, list/fill_icon_thresholds)
|
||||
RETURN_TYPE(/mutable_appearance)
|
||||
|
||||
var/threshold = null
|
||||
for(var/i in 1 to fill_icon_thresholds.len)
|
||||
if(ROUND_UP(100 * reagents.total_volume / reagents.maximum_volume) >= fill_icon_thresholds[i])
|
||||
threshold = i
|
||||
|
||||
if(threshold)
|
||||
var/fill_name = "[fill_prefix][fill_icon_thresholds[threshold]]"
|
||||
var/mutable_appearance/filling = mutable_appearance(fill_icon, fill_name)
|
||||
filling.color = mix_color_from_reagents(reagents.reagent_list)
|
||||
return filling
|
||||
|
||||
return null
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
|
||||
/obj/machinery/chem_master/update_appearance(updates)
|
||||
. = ..()
|
||||
if(panel_open || (machine_stat & (NOPOWER|BROKEN)))
|
||||
if(panel_open || !is_operational)
|
||||
set_light(0)
|
||||
else
|
||||
set_light(1, 1, "#fffb00")
|
||||
@@ -112,7 +112,7 @@
|
||||
. += mutable_appearance(icon, base_icon_state + "_overlay_extruder")
|
||||
|
||||
// Screen overlay
|
||||
if(!panel_open && !(machine_stat & (NOPOWER | BROKEN)))
|
||||
if(!panel_open && is_operational)
|
||||
var/screen_overlay = base_icon_state + "_overlay_screen"
|
||||
if(is_printing)
|
||||
screen_overlay += "_active"
|
||||
@@ -123,15 +123,9 @@
|
||||
|
||||
// Buffer reagents overlay
|
||||
if(reagents.total_volume)
|
||||
var/threshold = null
|
||||
var/static/list/fill_icon_thresholds = list(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
|
||||
for(var/i in 1 to fill_icon_thresholds.len)
|
||||
if(ROUND_UP(100 * (reagents.total_volume / reagents.maximum_volume)) >= fill_icon_thresholds[i])
|
||||
threshold = i
|
||||
if(threshold)
|
||||
var/fill_name = "chemmaster[fill_icon_thresholds[threshold]]"
|
||||
var/mutable_appearance/filling = mutable_appearance('icons/obj/medical/reagent_fillings.dmi', fill_name)
|
||||
filling.color = mix_color_from_reagents(reagents.reagent_list)
|
||||
var/mutable_appearance/filling = reagent_threshold_overlay(reagents, 'icons/obj/medical/reagent_fillings.dmi', "chemmaster", fill_icon_thresholds)
|
||||
if(!isnull(filling))
|
||||
. += filling
|
||||
|
||||
|
||||
|
||||
@@ -1,245 +1,439 @@
|
||||
///The maximum number of settings on a burner knob
|
||||
#define MAX_BURNER_KNOB_SETTINGS 10
|
||||
|
||||
/obj/structure/chem_separator
|
||||
name = "distillation apparatus"
|
||||
desc = "A device that performs chemical separation by distillation."
|
||||
icon = 'icons/obj/medical/chemical.dmi'
|
||||
icon_state = "separator"
|
||||
light_power = 1
|
||||
var/fill_icon = 'icons/obj/medical/reagent_fillings.dmi'
|
||||
var/fill_icon_state = "separator"
|
||||
/// Icons for different percentages of beaker/separator reagent volumes
|
||||
var/list/fill_icon_thresholds = list(1,30,80)
|
||||
/// The temperature thresholds used for thermometer icon update, in Celsius
|
||||
var/list/temperature_icon_thresholds = list(0,50,100)
|
||||
/// Whether the burner is currently on and the mixture is heating up
|
||||
var/burning = FALSE
|
||||
/// Whether the mixture is above the required temperature and the separation is in process
|
||||
|
||||
///Is the mixture currently boiling
|
||||
var/boiling = FALSE
|
||||
/// Has the sound loop animation started
|
||||
var/loop_started = FALSE
|
||||
/// Sound during separation
|
||||
var/datum/looping_sound/boiling/soundloop
|
||||
/// Minimal mixture temperature for separation
|
||||
var/required_temp = T0C + 100
|
||||
/// Mixture heating speed in degrees per second for full container
|
||||
var/heating_rate = 5
|
||||
/// Separation speed in units per second
|
||||
var/distillation_rate = 5
|
||||
/// Reagent container for the vapor of the separating reagent
|
||||
var/datum/reagents/condenser
|
||||
/// The reagent chosen for separation
|
||||
var/datum/reagent/separating_reagent
|
||||
/// Reagent container for condensate or separator filling
|
||||
var/obj/item/reagent_containers/beaker
|
||||
/// The container for transferring distilled reagents into
|
||||
var/obj/item/reagent_containers/distilled_container
|
||||
/// The container for holding the fuel source for the bunset burner
|
||||
var/obj/item/reagent_containers/fuel_container
|
||||
/// Is the bunset burner currenrly switched on/off
|
||||
var/burner_on = FALSE
|
||||
/// Do we have a condenser installed for forced cooling
|
||||
var/condenser_installed = FALSE
|
||||
/// Is the condenser on
|
||||
var/condenser_on = FALSE
|
||||
/// Knob setting on the burner
|
||||
var/burner_knob = 1
|
||||
|
||||
/obj/structure/chem_separator/Initialize(mapload)
|
||||
. = ..()
|
||||
create_reagents(300, TRANSPARENT | INJECTABLE)
|
||||
condenser = new()
|
||||
soundloop = new(src, boiling)
|
||||
create_reagents(100, TRANSPARENT | INJECTABLE)
|
||||
soundloop = new(src)
|
||||
register_context()
|
||||
|
||||
/obj/structure/chem_separator/Destroy()
|
||||
if(burning)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
if(beaker)
|
||||
QDEL_NULL(beaker)
|
||||
QDEL_NULL(distilled_container)
|
||||
QDEL_NULL(fuel_container)
|
||||
QDEL_NULL(soundloop)
|
||||
return ..()
|
||||
|
||||
/obj/structure/chem_separator/atom_deconstruct(disassembled)
|
||||
var/atom/drop = drop_location()
|
||||
|
||||
new /obj/item/stack/sheet/mineral/wood(drop, 1)
|
||||
|
||||
new /obj/item/thermometer(drop)
|
||||
|
||||
new /obj/item/burner(drop)
|
||||
|
||||
if(condenser_installed)
|
||||
new /obj/item/assembly/igniter/condenser(drop)
|
||||
|
||||
if(!QDELETED(distilled_container))
|
||||
distilled_container.forceMove(drop)
|
||||
|
||||
if(!QDELETED(fuel_container))
|
||||
fuel_container.forceMove(drop)
|
||||
|
||||
/obj/structure/chem_separator/Exited(atom/movable/gone, direction)
|
||||
. = ..()
|
||||
if(gone == beaker)
|
||||
beaker = null
|
||||
update_appearance(UPDATE_ICON)
|
||||
if(distilled_container == gone)
|
||||
distilled_container = null
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
if(fuel_container == gone)
|
||||
toggle_burner(FALSE)
|
||||
fuel_container = null
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
|
||||
/obj/structure/chem_separator/add_context(atom/source, list/context, obj/item/held_item, mob/user)
|
||||
. = NONE
|
||||
if(isnull(held_item))
|
||||
if(!QDELETED(distilled_container))
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Remove beaker"
|
||||
. = CONTEXTUAL_SCREENTIP_SET
|
||||
if(!QDELETED(fuel_container))
|
||||
context[SCREENTIP_CONTEXT_RMB] = "Remove fuel"
|
||||
. = CONTEXTUAL_SCREENTIP_SET
|
||||
if(burner_on)
|
||||
context[SCREENTIP_CONTEXT_ALT_LMB] = "Off burner"
|
||||
. = CONTEXTUAL_SCREENTIP_SET
|
||||
return
|
||||
|
||||
if(!condenser_installed && istype(held_item, /obj/item/assembly/igniter/condenser))
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Installer cooler"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
if(is_reagent_container(held_item) && held_item.is_open_container())
|
||||
if(QDELETED(distilled_container))
|
||||
context[SCREENTIP_CONTEXT_LMB] = "[QDELETED(distilled_container) ? "Insert" : "Replace"] beaker"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
if(QDELETED(fuel_container))
|
||||
context[SCREENTIP_CONTEXT_RMB] = "[QDELETED(fuel_container) ? "Insert" : "Replace"] fuel"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
if(held_item.tool_behaviour == TOOL_CROWBAR)
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Deconstruct"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
/obj/structure/chem_separator/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
if(reagents.total_volume)
|
||||
. += span_notice("The distilation flask reads <b>[reagents.total_volume]/[reagents.maximum_volume]u</b>.")
|
||||
if(!QDELETED(distilled_container))
|
||||
. += span_notice("The distilation beaker reads <b>[distilled_container.reagents.total_volume]/[distilled_container.reagents.maximum_volume]u</b>.")
|
||||
. += span_notice("Remove beaker with [EXAMINE_HINT("LMB")].")
|
||||
else
|
||||
. += span_warning("Its missing a distilation container, insert with [EXAMINE_HINT("LMB")]")
|
||||
if(!QDELETED(fuel_container))
|
||||
. += span_notice("The burner fuel container reads <b>[fuel_container.reagents.total_volume]/[fuel_container.reagents.maximum_volume]u</b>.")
|
||||
. += span_notice("Remove fuel with [EXAMINE_HINT("RMB")].")
|
||||
else
|
||||
. += span_warning("Its missing a beaker containing fuel for the burner, insert with [EXAMINE_HINT("RMB")]")
|
||||
if(burner_on)
|
||||
. += span_notice("Off burner with [EXAMINE_HINT("ALT LMB")].")
|
||||
else
|
||||
. += span_notice("You can start a flame with an combustible device.")
|
||||
|
||||
if(condenser_installed)
|
||||
. += span_notice("The in-built condenser can facilitate faster cooling but consumes fuel.")
|
||||
else
|
||||
. += span_notice("You could install a [EXAMINE_HINT("condenser")] for fater cooling.")
|
||||
|
||||
. += span_notice("You can [EXAMINE_HINT("examine more")] to see reagent boiling points & fuel properties.")
|
||||
. += span_notice("The whole aparatus can be [EXAMINE_HINT("pried")] apart.")
|
||||
|
||||
/obj/structure/chem_separator/examine_more(mob/user)
|
||||
. = ..()
|
||||
|
||||
. += span_notice("For burner fuel Plasma > Oil > Welding Fuel = Oxygen > Ethanol > Monkey Energy")
|
||||
|
||||
. += span_notice("Upon cross examining the flasks reagents contents with its chart you see the boiling points of each reagent present.")
|
||||
for(var/datum/reagent/reg as anything in reagents.reagent_list)
|
||||
. += span_notice("[reg.name] [get_boiling_point(reg)]K")
|
||||
|
||||
/obj/structure/chem_separator/update_overlays()
|
||||
. = ..()
|
||||
set_light(burning ? light_power : 0)
|
||||
// Burner overlay
|
||||
if(burning)
|
||||
. += mutable_appearance(icon, "[icon_state]_burn")
|
||||
. += emissive_appearance(icon, "[icon_state]_burn", src)
|
||||
// Separator reagents overlay
|
||||
|
||||
//burner overlays
|
||||
if(burner_on)
|
||||
. += mutable_appearance('icons/obj/medical/chemical.dmi', "separator_burn")
|
||||
. += emissive_appearance('icons/obj/medical/chemical.dmi', "separator_burn", src)
|
||||
|
||||
var/static/list/fill_icon_thresholds = list(1, 30, 80)
|
||||
|
||||
//distilation flask overlays
|
||||
if(reagents.total_volume)
|
||||
var/threshold = null
|
||||
for(var/i in 1 to fill_icon_thresholds.len)
|
||||
if(ROUND_UP(100 * reagents.total_volume / reagents.maximum_volume) >= fill_icon_thresholds[i])
|
||||
threshold = i
|
||||
if(threshold)
|
||||
var/fill_name = "[fill_icon_state]_m_[fill_icon_thresholds[threshold]]"
|
||||
var/mutable_appearance/filling = mutable_appearance(fill_icon, fill_name)
|
||||
filling.color = mix_color_from_reagents(reagents.reagent_list)
|
||||
. += filling
|
||||
// Beaker overlay
|
||||
if(beaker)
|
||||
. += "[icon_state]_beaker"
|
||||
// Beaker reagents overlay
|
||||
if(beaker.reagents.total_volume)
|
||||
var/threshold = null
|
||||
for(var/i in 1 to fill_icon_thresholds.len)
|
||||
if(ROUND_UP(100 * beaker.reagents.total_volume / beaker.reagents.maximum_volume) >= fill_icon_thresholds[i])
|
||||
threshold = i
|
||||
if(threshold)
|
||||
var/fill_name = "[fill_icon_state]_b_[fill_icon_thresholds[threshold]]"
|
||||
var/mutable_appearance/filling = mutable_appearance(fill_icon, fill_name)
|
||||
filling.color = mix_color_from_reagents(beaker.reagents.reagent_list)
|
||||
. += filling
|
||||
// Dripping overlay
|
||||
if(boiling)
|
||||
var/mutable_appearance/filling = mutable_appearance(fill_icon, "separator_dripping")
|
||||
filling.color = separating_reagent.color
|
||||
. += filling
|
||||
// Thermometer overlay
|
||||
var/mutable_appearance/overlay = reagent_threshold_overlay(reagents, 'icons/obj/medical/reagent_fillings.dmi', "separator_m_", fill_icon_thresholds)
|
||||
if(!isnull(overlay))
|
||||
. += overlay
|
||||
|
||||
//dripping overlay
|
||||
if(boiling)
|
||||
var/mutable_appearance/filling = mutable_appearance('icons/obj/medical/reagent_fillings.dmi', "separator_dripping")
|
||||
filling.color = mix_color_from_reagents(reagents.reagent_list)
|
||||
. += filling
|
||||
|
||||
//distilation beaker overlays
|
||||
if(!QDELETED(distilled_container))
|
||||
. += "separator_beaker"
|
||||
var/mutable_appearance/overlay = reagent_threshold_overlay(distilled_container.reagents, 'icons/obj/medical/reagent_fillings.dmi', "separator_b_", fill_icon_thresholds)
|
||||
if(!isnull(overlay))
|
||||
. += overlay
|
||||
|
||||
//thermometer overlay
|
||||
var/static/list/temperature_icon_thresholds = list(0, 50, 100)
|
||||
var/threshold = null
|
||||
for(var/i in 1 to temperature_icon_thresholds.len)
|
||||
if(ROUND_UP(reagents.chem_temp - T0C) >= temperature_icon_thresholds[i])
|
||||
threshold = i
|
||||
if(threshold)
|
||||
var/fill_name = "[icon_state]_temp_[temperature_icon_thresholds[threshold]]"
|
||||
var/mutable_appearance/filling = mutable_appearance(icon_state, fill_name)
|
||||
var/fill_name = "separator_temp_[temperature_icon_thresholds[threshold]]"
|
||||
var/mutable_appearance/filling = mutable_appearance('icons/obj/medical/chemical.dmi', fill_name)
|
||||
. += filling
|
||||
|
||||
/// Checks whether the item can ignite the separator
|
||||
/obj/structure/chem_separator/proc/ignite_with(obj/item/object, mob/living/user)
|
||||
var/ignition_message = object.ignition_effect(src, user)
|
||||
if(!ignition_message)
|
||||
return FALSE
|
||||
user.visible_message(ignition_message)
|
||||
fire_act(object.get_temperature())
|
||||
return TRUE
|
||||
/**
|
||||
* Computes the boiling point of the reagent based on its mass. heaiver reagents obviously needs higher temps
|
||||
* Arguments
|
||||
*
|
||||
* * datum/reagent/reg - the reagent whos boiling point we are trying to compute
|
||||
*/
|
||||
/obj/structure/chem_separator/proc/get_boiling_point(datum/reagent/reg)
|
||||
PRIVATE_PROC(TRUE)
|
||||
|
||||
/obj/structure/chem_separator/attackby(obj/item/item, mob/user, params)
|
||||
if(ignite_with(item, user))
|
||||
return TRUE // no afterattack
|
||||
if(is_reagent_container(item) && !(item.item_flags & ABSTRACT) && item.is_open_container())
|
||||
var/obj/item/reagent_containers/new_beaker = item
|
||||
if(!user.transferItemToLoc(new_beaker, src))
|
||||
return FALSE
|
||||
replace_beaker(user, new_beaker)
|
||||
balloon_alert(user, "added beaker")
|
||||
update_appearance(UPDATE_ICON)
|
||||
return TRUE // no afterattack
|
||||
return ..()
|
||||
//use the constant mass set on init
|
||||
reg = GLOB.chemical_reagents_list[reg.type]
|
||||
|
||||
/// Insert, replace or eject the container depending on the state and parameters
|
||||
/obj/structure/chem_separator/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
|
||||
if(!user)
|
||||
CRASH("[user] ([user?.type]) is not a living, but is trying to replace beaker")
|
||||
if(beaker)
|
||||
if(burning)
|
||||
stop()
|
||||
if(!issilicon(user) && in_range(src, user))
|
||||
user.put_in_hands(beaker)
|
||||
playsound(src, 'sound/items/handling/drinkglass_pickup.ogg', PICKUP_SOUND_VOLUME, ignore_walls = FALSE)
|
||||
else
|
||||
beaker.forceMove(drop_location())
|
||||
beaker = null
|
||||
if(new_beaker)
|
||||
beaker = new_beaker
|
||||
playsound(src, 'sound/items/handling/drinkglass_drop.ogg', DROP_SOUND_VOLUME, ignore_walls = FALSE)
|
||||
update_appearance(UPDATE_ICON)
|
||||
return TRUE
|
||||
//reagents masses can vary between 10->800
|
||||
var/normalized_coord = (reg.mass - 10) / 790
|
||||
|
||||
//return a boiling point anywhere between 400->900 k. Change if you want more varity
|
||||
return 400 + (500 * normalized_coord)
|
||||
|
||||
/**
|
||||
* Computes the coefficient of burning(the ability of the reagent mixture to burn) of the burner fuel container
|
||||
* reagents can affect the intensity of the flame in different ways. A -ve value the mixture can not combust
|
||||
* whereas a +ve value(<= 1) means the flame can burn at maximum efficiency
|
||||
*/
|
||||
/obj/structure/chem_separator/proc/get_ignition_coefficient()
|
||||
PRIVATE_PROC(TRUE)
|
||||
|
||||
if(QDELETED(fuel_container))
|
||||
return 0
|
||||
|
||||
//map of reagents & how much burning potential they all have
|
||||
var/static/list/reagent_coefficients = list(
|
||||
/datum/reagent/toxin/plasma = 1,
|
||||
/datum/reagent/fuel/oil = 0.9,
|
||||
/datum/reagent/fuel = 0.8,
|
||||
/datum/reagent/oxygen = 0.8,
|
||||
/datum/reagent/consumable/ethanol = 0.7,
|
||||
/datum/reagent/consumable/monkey_energy = 0.6,
|
||||
/datum/reagent/water = - 0.7
|
||||
)
|
||||
|
||||
var/total_coefficient = 0
|
||||
for(var/datum/reagent/reg as anything in fuel_container.reagents.reagent_list)
|
||||
var/coefficient = -1 //any fuel that is not on the list acts as an inhibitor
|
||||
for(var/datum/reagent/fuel as anything in reagent_coefficients)
|
||||
if(istype(reg, fuel))
|
||||
coefficient = reagent_coefficients[fuel]
|
||||
break
|
||||
total_coefficient += coefficient
|
||||
|
||||
return clamp(total_coefficient, 0, 1)
|
||||
|
||||
/**
|
||||
* Toggles the burner on(only for a good fuel composition) or off
|
||||
* Arguments
|
||||
*
|
||||
* * state - on or off
|
||||
*/
|
||||
/obj/structure/chem_separator/proc/toggle_burner(state)
|
||||
PRIVATE_PROC(TRUE)
|
||||
|
||||
if(!state)
|
||||
burner_on = FALSE
|
||||
set_light(0)
|
||||
else
|
||||
if(!get_ignition_coefficient()) //no proper fuel
|
||||
return
|
||||
if(!reagents.total_volume) //no reagents to distill
|
||||
return
|
||||
if(QDELETED(distilled_container)) //no beaker to receive distilled reagents
|
||||
return
|
||||
burner_on = TRUE
|
||||
set_light(ROUND_UP(2 * (burner_knob / 5)))
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
|
||||
/obj/structure/chem_separator/fire_act(exposed_temperature, exposed_volume)
|
||||
if(burning)
|
||||
return ..()
|
||||
start()
|
||||
toggle_burner(TRUE)
|
||||
|
||||
/obj/structure/chem_separator/extinguish()
|
||||
. = ..()
|
||||
if(burning)
|
||||
stop()
|
||||
toggle_burner(FALSE)
|
||||
|
||||
/// Ignite the burner to start the separation process
|
||||
/obj/structure/chem_separator/proc/start()
|
||||
if(!beaker)
|
||||
return
|
||||
if(beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
|
||||
return
|
||||
if(!reagents.total_volume)
|
||||
return
|
||||
var/list/reagents_sorted = reagents.reagent_list.Copy()
|
||||
reagents_sorted = sort_list(reagents_sorted, GLOBAL_PROC_REF(cmp_reagents_asc))
|
||||
separating_reagent = reagents_sorted[1]
|
||||
burning = TRUE
|
||||
update_appearance(UPDATE_ICON)
|
||||
START_PROCESSING(SSobj, src)
|
||||
/obj/structure/chem_separator/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
|
||||
. = NONE
|
||||
if(user.combat_mode || tool.item_flags & ABSTRACT || tool.flags_1 & HOLOGRAM_1 || !user.can_perform_action(src, ALLOW_SILICON_REACH))
|
||||
return ITEM_INTERACT_SKIP_TO_ATTACK
|
||||
|
||||
/// Extinguish the burner to stop the separation process
|
||||
/obj/structure/chem_separator/proc/stop()
|
||||
separating_reagent = null
|
||||
burning = FALSE
|
||||
if(boiling)
|
||||
boiling = FALSE
|
||||
condenser.trans_to(reagents, condenser.total_volume)
|
||||
soundloop.stop()
|
||||
update_appearance(UPDATE_ICON)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
///Add the distilation flask
|
||||
if(is_reagent_container(tool) && tool.is_open_container())
|
||||
//transfer old container
|
||||
if(!QDELETED(distilled_container))
|
||||
user.put_in_hands(distilled_container)
|
||||
|
||||
/// Fill internal storage with reagents from the container
|
||||
/obj/structure/chem_separator/proc/load()
|
||||
if(burning)
|
||||
return
|
||||
if(!beaker?.reagents.total_volume)
|
||||
return
|
||||
if(reagents.total_volume >= reagents.maximum_volume)
|
||||
return
|
||||
beaker.reagents.trans_to(reagents, beaker.reagents.total_volume)
|
||||
update_appearance(UPDATE_ICON)
|
||||
//add new container
|
||||
if(!user.transferItemToLoc(tool, src))
|
||||
to_chat(user, span_warning("[tool] is stuck in your hand."))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
distilled_container = tool
|
||||
|
||||
/// Drain internal reagents into the container
|
||||
/obj/structure/chem_separator/proc/unload()
|
||||
if(burning)
|
||||
return
|
||||
if(!reagents.total_volume)
|
||||
return
|
||||
if(!beaker)
|
||||
return
|
||||
if(beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
|
||||
return
|
||||
reagents.trans_to(beaker.reagents, reagents.total_volume)
|
||||
update_appearance(UPDATE_ICON)
|
||||
START_PROCESSING(SSobj, src)
|
||||
balloon_alert(user, "distillation container added.")
|
||||
|
||||
/// Check whether the separation can process
|
||||
/obj/structure/chem_separator/proc/can_process(datum/gas_mixture/air)
|
||||
if(!burning)
|
||||
return FALSE
|
||||
if(!air || !air.has_gas(/datum/gas/oxygen, 1))
|
||||
return FALSE
|
||||
if(air.temperature > required_temp) // Too hot to condense
|
||||
return FALSE
|
||||
if(!beaker)
|
||||
return FALSE
|
||||
if(beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
|
||||
return FALSE
|
||||
if(!reagents.get_reagent_amount(separating_reagent.type))
|
||||
return FALSE
|
||||
return TRUE
|
||||
ui_interact(user)
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
else if(istype(tool, /obj/item/assembly/igniter/condenser))
|
||||
if(!user.temporarilyRemoveItemFromInventory(tool))
|
||||
to_chat(user, span_warning("[tool] is stuck in your hand."))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
condenser_installed = TRUE
|
||||
update_static_data_for_all_viewers()
|
||||
qdel(tool)
|
||||
balloon_alert(user, "condenser installed.")
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
///Try & ignite the bunset burner with this item
|
||||
var/ignition_message = tool.ignition_effect(src, user)
|
||||
if(!ignition_message)
|
||||
return NONE
|
||||
user.visible_message(ignition_message)
|
||||
toggle_burner(TRUE)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/structure/chem_separator/crowbar_act(mob/living/user, obj/item/tool)
|
||||
deconstruct(TRUE)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/structure/chem_separator/attack_hand(mob/living/user, list/modifiers)
|
||||
if(!QDELETED(distilled_container))
|
||||
if(!SStgui.get_open_ui(user, src)) //for convinience open ui first then interact with beakers if you still want to
|
||||
ui_interact(user)
|
||||
return TRUE
|
||||
|
||||
if(user.put_in_hands(distilled_container))
|
||||
to_chat(user, span_notice("you take out the output flask."))
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
return TRUE
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/structure/chem_separator/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers)
|
||||
. = NONE
|
||||
if(user.combat_mode || tool.item_flags & ABSTRACT || tool.flags_1 & HOLOGRAM_1 || !user.can_perform_action(src, ALLOW_SILICON_REACH))
|
||||
return ITEM_INTERACT_SKIP_TO_ATTACK
|
||||
|
||||
if(is_reagent_container(tool) && tool.is_open_container())
|
||||
//transfer old container
|
||||
if(!QDELETED(fuel_container))
|
||||
user.put_in_hands(fuel_container)
|
||||
|
||||
//add new container
|
||||
if(!user.transferItemToLoc(tool, src))
|
||||
to_chat(user, span_warning("[tool] is stuck in your hand."))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
fuel_container = tool
|
||||
balloon_alert(user, "fuel container added.")
|
||||
|
||||
ui_interact(user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/structure/chem_separator/attack_hand_secondary(mob/user, list/modifiers)
|
||||
if(!QDELETED(fuel_container))
|
||||
if(!SStgui.get_open_ui(user, src)) //for convinience open ui first then interact with beakers if you still want to
|
||||
ui_interact(user)
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
|
||||
if(user.put_in_hands(fuel_container))
|
||||
to_chat(user, span_notice("you take out the burner fuel container"))
|
||||
toggle_burner(FALSE)
|
||||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
||||
|
||||
return ..()
|
||||
|
||||
///Returns the coefficient of cooling of reagents, taking into consideration the condenser
|
||||
/obj/structure/chem_separator/proc/get_cool_coefficient()
|
||||
PRIVATE_PROC(TRUE)
|
||||
|
||||
var/coefficient = 0.2
|
||||
|
||||
var/fuel_coefficient = get_ignition_coefficient()
|
||||
if(condenser_installed && condenser_on && fuel_coefficient > 0)
|
||||
var/datum/reagents/fuel = fuel_container.reagents
|
||||
if(fuel.remove_all(0.15))
|
||||
coefficient += fuel_coefficient
|
||||
else
|
||||
condenser_on = FALSE
|
||||
|
||||
return coefficient
|
||||
|
||||
/obj/structure/chem_separator/process(seconds_per_tick)
|
||||
var/datum/gas_mixture/air = return_air()
|
||||
if(!can_process(air))
|
||||
return stop()
|
||||
if(isturf(loc))
|
||||
var/turf/location = loc
|
||||
location.hotspot_expose(exposed_temperature = 700, exposed_volume = 5)
|
||||
if(reagents.chem_temp < required_temp)
|
||||
reagents.adjust_thermal_energy(heating_rate * seconds_per_tick * SPECIFIC_HEAT_DEFAULT * reagents.maximum_volume)
|
||||
reagents.chem_temp = min(reagents.chem_temp, required_temp)
|
||||
update_appearance(UPDATE_ICON)
|
||||
return
|
||||
if(reagents.chem_temp >= required_temp)
|
||||
if(!boiling)
|
||||
if(!reagents.total_volume)
|
||||
if(QDELETED(distilled_container) || !distilled_container.reagents.total_volume)
|
||||
boiling = FALSE
|
||||
soundloop.stop()
|
||||
toggle_burner(FALSE)
|
||||
return PROCESS_KILL
|
||||
|
||||
//if burner in on attempt to heat the reagents
|
||||
if(burner_on)
|
||||
var/can_process = TRUE
|
||||
|
||||
//do we have good quality fuel to burn
|
||||
var/fuel_coefficient = get_ignition_coefficient()
|
||||
if(!fuel_coefficient)
|
||||
can_process = FALSE
|
||||
toggle_burner(FALSE)
|
||||
|
||||
var/knob_ratio = burner_knob / MAX_BURNER_KNOB_SETTINGS
|
||||
var/datum/reagents/fuel = fuel_container.reagents
|
||||
|
||||
//consume some air after we have validated we have some good fuel. Only if we don't already use O2 as a fuel
|
||||
if(can_process && !fuel.has_reagent(/datum/reagent/oxygen))
|
||||
var/datum/gas_mixture/air = return_air()
|
||||
if(!air.remove_specific(/datum/gas/oxygen, 0.01 + (0.04 * knob_ratio))) //can burn anywhere between 0.01 & 0.05 moles of air based on the knob settings
|
||||
can_process = FALSE
|
||||
toggle_burner(FALSE)
|
||||
|
||||
//burn some fuel if we combusted some air
|
||||
if(can_process)
|
||||
if(!fuel.remove_all(0.01 + (0.19 * knob_ratio))) //can burn anywhere between 0.01 & 0.2 units of fuel based on the knob settings
|
||||
can_process = FALSE
|
||||
toggle_burner(FALSE)
|
||||
|
||||
//finally heat the mixture
|
||||
if(can_process)
|
||||
reagents.adjust_thermal_energy((1000 - reagents.chem_temp) * seconds_per_tick * SPECIFIC_HEAT_DEFAULT * (0.05 + (0.45 * knob_ratio)) * fuel_coefficient)
|
||||
reagents.handle_reactions()
|
||||
else if(reagents.chem_temp > DEFAULT_REAGENT_TEMPERATURE) //the container cools down if there is no flame heating it till it reaches room temps
|
||||
reagents.adjust_thermal_energy((DEFAULT_REAGENT_TEMPERATURE - reagents.chem_temp) * seconds_per_tick * SPECIFIC_HEAT_DEFAULT * get_cool_coefficient())
|
||||
reagents.handle_reactions()
|
||||
|
||||
//the target distilation beaker also cools down
|
||||
if(!QDELETED(distilled_container) && distilled_container.reagents.chem_temp > DEFAULT_REAGENT_TEMPERATURE)
|
||||
var/datum/reagents/distiled_reagents = distilled_container.reagents
|
||||
distiled_reagents.adjust_thermal_energy((DEFAULT_REAGENT_TEMPERATURE - distiled_reagents.chem_temp) * seconds_per_tick * SPECIFIC_HEAT_DEFAULT * get_cool_coefficient())
|
||||
distiled_reagents.handle_reactions()
|
||||
|
||||
//the distilation process checks the individual boiling point of each reagent based on their mass for seperation
|
||||
boiling = FALSE
|
||||
for(var/datum/reagent/reg in reagents.reagent_list)
|
||||
var/bp = get_boiling_point(reg)
|
||||
//we can now distil this
|
||||
if(reagents.chem_temp > bp)
|
||||
//distilation rate increases as temps go up peaking at 12 units per tick(at 200k above boiling point)
|
||||
var/amount = 2 + ((reagents.chem_temp - bp) / 200) * 10
|
||||
if(!QDELETED(distilled_container))
|
||||
reagents.trans_to(distilled_container.reagents, amount, target_id = reg.type)
|
||||
else //no target container means reagents vanish into thin air i.e leak out
|
||||
reagents.remove_reagent(reg.type, amount)
|
||||
boiling = TRUE
|
||||
|
||||
//boiling sound effect
|
||||
if(boiling)
|
||||
if(!loop_started)
|
||||
soundloop.start()
|
||||
var/vapor_amount = distillation_rate * seconds_per_tick
|
||||
// Vapor to condenser
|
||||
reagents.trans_to(condenser, vapor_amount, target_id = separating_reagent.type)
|
||||
// Cool the vapor down
|
||||
condenser.set_temperature(air.temperature)
|
||||
// Condense into container
|
||||
condenser.trans_to(beaker.reagents, condenser.total_volume)
|
||||
else if (boiling)
|
||||
boiling = FALSE
|
||||
loop_started = TRUE
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
else
|
||||
soundloop.stop()
|
||||
update_appearance(UPDATE_ICON)
|
||||
loop_started = FALSE
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
|
||||
/obj/structure/chem_separator/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
@@ -247,46 +441,102 @@
|
||||
ui = new(user, src, "ChemSeparator", name)
|
||||
ui.open()
|
||||
|
||||
/obj/structure/chem_separator/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["is_burning"] = burning
|
||||
data["temperature"] = reagents.chem_temp - T0C // Thermometer is in Celsius
|
||||
data["own_total_volume"] = reagents.total_volume
|
||||
data["own_maximum_volume"] = reagents.maximum_volume
|
||||
data["own_reagent_color"] = mix_color_from_reagents(reagents.reagent_list)
|
||||
data["beaker"] = !!beaker
|
||||
if(beaker)
|
||||
data["beaker_total_volume"] = beaker.reagents.total_volume
|
||||
data["beaker_maximum_volume"] = beaker.reagents.maximum_volume
|
||||
data["beaker_reagent_color"] = mix_color_from_reagents(beaker.reagents.reagent_list)
|
||||
return data
|
||||
|
||||
/obj/structure/chem_separator/ui_act(action, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
switch(action)
|
||||
if("load")
|
||||
load()
|
||||
if("unload")
|
||||
unload()
|
||||
if("start")
|
||||
playsound(usr, 'sound/effects/pop.ogg', 30, ignore_walls = FALSE)
|
||||
start()
|
||||
if("stop")
|
||||
stop()
|
||||
if("eject")
|
||||
replace_beaker(usr)
|
||||
return TRUE
|
||||
|
||||
/datum/crafting_recipe/chem_separator
|
||||
name = "chemical separator"
|
||||
result = /obj/structure/chem_separator
|
||||
tool_behaviors = list(TOOL_WELDER)
|
||||
time = 5 SECONDS
|
||||
reqs = list(
|
||||
/obj/item/stack/sheet/mineral/wood = 1,
|
||||
/obj/item/stack/sheet/glass = 1,
|
||||
/obj/item/burner = 1,
|
||||
/obj/item/thermometer = 1,
|
||||
/obj/structure/chem_separator/ui_static_data(mob/user)
|
||||
return list(
|
||||
"condenser_installed" = condenser_installed,
|
||||
"max_burner_knob_settings" = MAX_BURNER_KNOB_SETTINGS,
|
||||
)
|
||||
category = CAT_CHEMISTRY
|
||||
|
||||
/obj/structure/chem_separator/ui_data(mob/user)
|
||||
. = list()
|
||||
|
||||
//distilation flask data
|
||||
var/list/flask_data = list()
|
||||
flask_data["total_volume"] = reagents.total_volume
|
||||
flask_data["maximum_volume"] = reagents.maximum_volume
|
||||
flask_data["temp"] = reagents.chem_temp
|
||||
flask_data["color"] = mix_color_from_reagents(reagents.reagent_list)
|
||||
.["flask"] = flask_data
|
||||
|
||||
//distilled beaker data
|
||||
var/list/distilled_data = null
|
||||
if(!QDELETED(distilled_container))
|
||||
var/datum/reagents/distilled_reagents = distilled_container.reagents
|
||||
|
||||
distilled_data = list()
|
||||
distilled_data["total_volume"] = distilled_reagents.total_volume
|
||||
distilled_data["maximum_volume"] = distilled_reagents.maximum_volume
|
||||
distilled_data["temp"] = distilled_reagents.chem_temp
|
||||
distilled_data["color"] = mix_color_from_reagents(distilled_reagents.reagent_list)
|
||||
.["beaker"] = distilled_data
|
||||
|
||||
//burner fuel data
|
||||
var/list/fuel_data = null
|
||||
if(!QDELETED(fuel_container))
|
||||
var/datum/reagents/fuel_reagents = fuel_container.reagents
|
||||
|
||||
fuel_data = list()
|
||||
fuel_data["total_volume"] = fuel_reagents.total_volume
|
||||
fuel_data["maximum_volume"] = fuel_reagents.maximum_volume
|
||||
fuel_data["temp"] = fuel_reagents.chem_temp
|
||||
fuel_data["color"] = mix_color_from_reagents(fuel_reagents.reagent_list)
|
||||
.["fuel"] = fuel_data
|
||||
|
||||
//Knob setting
|
||||
.["burner_on"] = burner_on
|
||||
.["knob"] = burner_knob
|
||||
|
||||
//Condenser setting
|
||||
.["condenser_on"] = condenser_on
|
||||
|
||||
/obj/structure/chem_separator/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("drain")
|
||||
if(QDELETED(distilled_container) || !reagents.total_volume)
|
||||
return FALSE
|
||||
|
||||
if(reagents.trans_to(distilled_container.reagents, reagents.maximum_volume))
|
||||
toggle_burner(FALSE)
|
||||
return TRUE
|
||||
|
||||
if("filter")
|
||||
if(QDELETED(distilled_container) || !distilled_container.reagents.total_volume)
|
||||
return FALSE
|
||||
|
||||
if(distilled_container.reagents.trans_to(reagents, reagents.maximum_volume))
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
return TRUE
|
||||
|
||||
if("knob")
|
||||
var/setting = params["amount"]
|
||||
if(isnull(setting))
|
||||
return FALSE
|
||||
|
||||
setting = text2num(setting)
|
||||
if(!setting)
|
||||
return FALSE
|
||||
|
||||
burner_knob = clamp(setting, 1, MAX_BURNER_KNOB_SETTINGS)
|
||||
if(burner_on)
|
||||
set_light(ROUND_UP(2 * (burner_knob / MAX_BURNER_KNOB_SETTINGS)))
|
||||
return TRUE
|
||||
|
||||
if("cool")
|
||||
if(!condenser_installed)
|
||||
return FALSE
|
||||
|
||||
condenser_on = !condenser_on
|
||||
return TRUE
|
||||
|
||||
/obj/structure/chem_separator/click_alt(mob/user)
|
||||
if(!burner_on)
|
||||
return CLICK_ACTION_BLOCKING
|
||||
|
||||
toggle_burner(FALSE)
|
||||
return CLICK_ACTION_SUCCESS
|
||||
|
||||
#undef MAX_BURNER_KNOB_SETTINGS
|
||||
|
||||
@@ -4,136 +4,69 @@ import { useBackend } from '../backend';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Knob,
|
||||
LabeledList,
|
||||
NoticeBox,
|
||||
ProgressBar,
|
||||
Section,
|
||||
Stack,
|
||||
} from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
type RegHolderData = {
|
||||
total_volume: number;
|
||||
maximum_volume: number;
|
||||
temp: number;
|
||||
color: string;
|
||||
};
|
||||
|
||||
type Data = {
|
||||
is_burning: BooleanLike;
|
||||
temperature: number;
|
||||
own_total_volume: number;
|
||||
own_maximum_volume: number;
|
||||
own_reagent_color: string;
|
||||
beaker: BooleanLike;
|
||||
beaker_total_volume: number;
|
||||
beaker_maximum_volume: number;
|
||||
beaker_reagent_color: string;
|
||||
flask: RegHolderData;
|
||||
beaker: RegHolderData;
|
||||
fuel: RegHolderData;
|
||||
burner_on: BooleanLike;
|
||||
knob: number;
|
||||
condenser_installed: BooleanLike;
|
||||
condenser_on: BooleanLike;
|
||||
max_burner_knob_settings: number;
|
||||
};
|
||||
|
||||
export const ChemSeparator = (props) => {
|
||||
const { act, data } = useBackend<Data>();
|
||||
const {
|
||||
flask,
|
||||
beaker,
|
||||
fuel,
|
||||
burner_on,
|
||||
knob,
|
||||
condenser_installed,
|
||||
condenser_on,
|
||||
max_burner_knob_settings,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<Window width={470} height={130}>
|
||||
<Window width={370} height={215}>
|
||||
<Window.Content>
|
||||
<Section fill>
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label="Separator"
|
||||
buttons={
|
||||
<Box my={1}>
|
||||
<Button
|
||||
mr={2}
|
||||
width={6}
|
||||
lineHeight={2}
|
||||
align="center"
|
||||
content="Drain"
|
||||
icon="arrow-down"
|
||||
disabled={
|
||||
data.is_burning ||
|
||||
!data.own_total_volume ||
|
||||
!data.beaker ||
|
||||
data.beaker_total_volume >= data.beaker_maximum_volume
|
||||
}
|
||||
onClick={() => act('unload')}
|
||||
/>
|
||||
{!data.is_burning ? (
|
||||
<Button
|
||||
width={6}
|
||||
lineHeight={2}
|
||||
align="center"
|
||||
content="Start"
|
||||
icon="filter"
|
||||
color="good"
|
||||
disabled={
|
||||
!data.own_total_volume ||
|
||||
!data.beaker ||
|
||||
data.beaker_total_volume >= data.beaker_maximum_volume
|
||||
}
|
||||
onClick={() => act('start')}
|
||||
/>
|
||||
) : (
|
||||
<Button
|
||||
width={6}
|
||||
lineHeight={2}
|
||||
align="center"
|
||||
content="Stop"
|
||||
icon="ban"
|
||||
color="bad"
|
||||
onClick={() => act('stop')}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<ProgressBar
|
||||
height={2}
|
||||
value={data.own_total_volume}
|
||||
minValue={0}
|
||||
maxValue={data.own_maximum_volume}
|
||||
color={data.own_reagent_color}
|
||||
>
|
||||
<Box
|
||||
lineHeight={1.9}
|
||||
style={{
|
||||
textShadow: '1px 1px 0 black',
|
||||
}}
|
||||
>
|
||||
{`${Math.ceil(data.own_total_volume)} of ${
|
||||
data.own_maximum_volume
|
||||
} units at ${Math.ceil(data.temperature)}°C`}
|
||||
</Box>
|
||||
</ProgressBar>
|
||||
</LabeledList.Item>
|
||||
{data.beaker ? (
|
||||
<LabeledList.Item
|
||||
label="Container"
|
||||
buttons={
|
||||
<Box my={1}>
|
||||
<Button
|
||||
mr={2}
|
||||
width={6}
|
||||
lineHeight={2}
|
||||
align="center"
|
||||
content="Fill"
|
||||
icon="arrow-up"
|
||||
disabled={
|
||||
data.is_burning ||
|
||||
!data.beaker_total_volume ||
|
||||
data.own_total_volume >= data.own_maximum_volume
|
||||
}
|
||||
onClick={() => act('load')}
|
||||
/>
|
||||
<Button
|
||||
width={6}
|
||||
lineHeight={2}
|
||||
align="center"
|
||||
icon="eject"
|
||||
content="Eject"
|
||||
disabled={data.is_burning}
|
||||
onClick={() => act('eject')}
|
||||
/>
|
||||
</Box>
|
||||
}
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label={
|
||||
<Box
|
||||
style={{
|
||||
transform: 'translate(20%, -50%)',
|
||||
width: '57px',
|
||||
}}
|
||||
>
|
||||
Flask:
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<Stack fill>
|
||||
<Stack.Item ml="27px">
|
||||
<ProgressBar
|
||||
height={2}
|
||||
value={data.beaker_total_volume}
|
||||
minValue={0}
|
||||
maxValue={data.beaker_maximum_volume}
|
||||
color={data.beaker_reagent_color}
|
||||
maxValue={flask.maximum_volume}
|
||||
value={flask.total_volume}
|
||||
color={flask.color}
|
||||
width="170px"
|
||||
>
|
||||
<Box
|
||||
lineHeight={1.9}
|
||||
@@ -141,19 +74,168 @@ export const ChemSeparator = (props) => {
|
||||
textShadow: '1px 1px 0 black',
|
||||
}}
|
||||
>
|
||||
{`${Math.ceil(data.beaker_total_volume)} of ${
|
||||
data.beaker_maximum_volume
|
||||
} units`}
|
||||
{`${Math.ceil(flask.total_volume)} of ${
|
||||
flask.maximum_volume
|
||||
} units at ${Math.ceil(flask.temp)}K`}
|
||||
</Box>
|
||||
</ProgressBar>
|
||||
</LabeledList.Item>
|
||||
) : (
|
||||
<LabeledList.Item label="Container">
|
||||
<NoticeBox my={0.7}>No container inserted.</NoticeBox>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
mr={2}
|
||||
width={6}
|
||||
lineHeight={2}
|
||||
align="center"
|
||||
icon="arrow-down"
|
||||
disabled={flask.total_volume <= 0 || !beaker}
|
||||
onClick={() => act('drain')}
|
||||
>
|
||||
Drain
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</LabeledList.Item>
|
||||
{beaker && (
|
||||
<LabeledList.Item
|
||||
label={
|
||||
<Box
|
||||
style={{
|
||||
transform: 'translate(20%, -50%)',
|
||||
width: '57px',
|
||||
}}
|
||||
>
|
||||
Beaker:
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<Stack fill>
|
||||
<Stack.Item ml="27px">
|
||||
<ProgressBar
|
||||
height={2}
|
||||
minValue={0}
|
||||
maxValue={beaker.maximum_volume}
|
||||
value={beaker.total_volume}
|
||||
color={beaker.color}
|
||||
width="170px"
|
||||
>
|
||||
<Box
|
||||
lineHeight={1.9}
|
||||
style={{
|
||||
textShadow: '1px 1px 0 black',
|
||||
}}
|
||||
>
|
||||
{`${Math.ceil(beaker.total_volume)} of ${
|
||||
beaker.maximum_volume
|
||||
} units at ${Math.ceil(beaker.temp)}K`}
|
||||
</Box>
|
||||
</ProgressBar>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
mr={2}
|
||||
width={6}
|
||||
lineHeight={2}
|
||||
align="center"
|
||||
icon="filter"
|
||||
disabled={beaker.total_volume <= 0}
|
||||
onClick={() => act('filter')}
|
||||
>
|
||||
Filter
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</LabeledList.Item>
|
||||
)}
|
||||
<LabeledList.Item
|
||||
label={
|
||||
<Box
|
||||
style={{
|
||||
transform: 'translate(20%, -50%)',
|
||||
width: '57px',
|
||||
}}
|
||||
>
|
||||
Burner Knob:
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<Knob
|
||||
ml="30px"
|
||||
size={1.3}
|
||||
minValue={1}
|
||||
maxValue={max_burner_knob_settings}
|
||||
step={1}
|
||||
stepPixelSize={10}
|
||||
value={knob}
|
||||
onDrag={(_e, value) =>
|
||||
act('knob', {
|
||||
amount: value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
{fuel && (
|
||||
<LabeledList.Item
|
||||
label={
|
||||
<Box
|
||||
style={{
|
||||
transform: 'translate(20%, -20%)',
|
||||
width: '57px',
|
||||
}}
|
||||
>
|
||||
Fuel Source:
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<ProgressBar
|
||||
height={2}
|
||||
minValue={0}
|
||||
maxValue={fuel.maximum_volume}
|
||||
value={fuel.total_volume}
|
||||
color={fuel.color}
|
||||
maxWidth="170px"
|
||||
ml="25px"
|
||||
>
|
||||
<Box
|
||||
lineHeight={1.9}
|
||||
style={{
|
||||
textShadow: '1px 1px 0 black',
|
||||
}}
|
||||
>
|
||||
{`${Math.ceil(fuel.total_volume)} of ${
|
||||
fuel.maximum_volume
|
||||
} units at ${Math.ceil(fuel.temp)}K`}
|
||||
</Box>
|
||||
</ProgressBar>
|
||||
</LabeledList.Item>
|
||||
)}
|
||||
{!!condenser_installed &&
|
||||
(flask.total_volume > 0 || beaker?.total_volume > 0) &&
|
||||
fuel?.total_volume > 0 && (
|
||||
<LabeledList.Item
|
||||
label={
|
||||
<Box
|
||||
style={{
|
||||
transform: 'translate(20%, -20%)',
|
||||
width: '57px',
|
||||
}}
|
||||
>
|
||||
Cooling:
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<Button
|
||||
icon="thermometer-full"
|
||||
disabled={burner_on}
|
||||
selected={condenser_on}
|
||||
fontSize="15px"
|
||||
ml="25px"
|
||||
onClick={() => act('cool')}
|
||||
>
|
||||
Start
|
||||
</Button>
|
||||
</LabeledList.Item>
|
||||
)}
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</LabeledList>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user