cleanup, icon_stuff, tutorial, sound, balance tweaks

This commit is contained in:
Darlantan
2022-09-27 02:20:10 -04:00
parent 28ca297677
commit a84d9c68e3
6 changed files with 213 additions and 217 deletions

View File

@@ -73256,6 +73256,7 @@
/turf/simulated/floor/tiled/white, /turf/simulated/floor/tiled/white,
/area/medical/medbay) /area/medical/medbay)
"tpy" = ( "tpy" = (
/obj/machinery/chemical_synthesizer,
/obj/machinery/hologram/holopad, /obj/machinery/hologram/holopad,
/obj/machinery/atmospherics/pipe/simple/hidden/supply{ /obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 10 dir = 10

View File

@@ -4,27 +4,7 @@
#define RECIPE_MAX_STRING 160 #define RECIPE_MAX_STRING 160
#define RECIPE_MAX_STEPS 16 #define RECIPE_MAX_STEPS 16
// Recipes are stored as a list which alternates between chemical id's and volumes to add. // Recipes are stored as a list which alternates between chemical id's and volumes to add, e.g. 1 = 'Carbon', 2 = 20, 3 = 'Silicon', 4 = 20
// TODO:
// Design UI
// DONE TGUI procs
// DONE Create procs to take synthesis steps as an input and stores as a 1 click synthesis button. Needs name, expected output volume.
// DONE Create procs to actually perform the reagent transfer/etc. for a synthesis, reading the stored synthesis steps.
// DONE Implement a step-mode where the player manually clicks on each step and an expert mode where players input a comma-delineated list.
// DONE Add process() code which makes the machine actually work. Perhaps tie a boolean and single start proc into process().
// DONE Give the machine queue-behavior which allows players to queue up multiple recipes, even when the machine is busy. Reference protolathe code.
// DONE Give the machine a way to stop a synthesis and purge/bottle the reaction vessel.
// DONE Perhaps use recipes as a "ID" "num" "ID" "num" list to avoid using multiple lists.
// DONE Panel open button.
// DONE Code for power usage.
// Update_icon() overrides.
// Underlay code for the reaction vessel.
// DONE Add an eject catalyst bottle button.
// DONE Make sure recipes can only be removed when the machine is idle. Adding should be fine.
// May need yet another list which is just strings which match recipe ID's.
// For user recipes, make clicking on the recipe give a prompt with "add to queue," "export recipe," and "delete recipe."
/obj/machinery/chemical_synthesizer /obj/machinery/chemical_synthesizer
name = "chemical synthesizer" name = "chemical synthesizer"
desc = "A programmable machine capable of automatically synthesizing medicine." desc = "A programmable machine capable of automatically synthesizing medicine."
@@ -43,11 +23,9 @@
var/busy = FALSE var/busy = FALSE
var/production_mode = FALSE // Toggle between click-step input and comma-delineated text input for creating recipes. var/production_mode = FALSE // Toggle between click-step input and comma-delineated text input for creating recipes.
var/use_catalyst = TRUE // Determines whether or not the catalyst will be added to reagents while processing a recipe. var/use_catalyst = TRUE // Determines whether or not the catalyst will be added to reagents while processing a recipe.
var/delay_modifier = 3 // This is multiplied by the volume of a step to determine how long each step takes. Bigger volume = slower. var/delay_modifier = 4 // This is multiplied by the volume of a step to determine how long each step takes. Bigger volume = slower.
var/obj/item/weapon/reagent_containers/glass/catalyst = null // This is where the user adds catalyst. Usually phoron. var/obj/item/weapon/reagent_containers/glass/catalyst = null // This is where the user adds catalyst. Usually phoron.
var/list/debug_data // DELETE THIS ONCE DONE TESTNG
var/list/recipes = list() // This holds chemical recipes up to a maximum determined by SYNTHESIZER_MAX_RECIPES. Two-dimensional. var/list/recipes = list() // This holds chemical recipes up to a maximum determined by SYNTHESIZER_MAX_RECIPES. Two-dimensional.
var/list/queue = list() // This holds the recipe id's for queued up recipes. var/list/queue = list() // This holds the recipe id's for queued up recipes.
var/list/catalyst_ids = list() // This keeps track of the chemicals in the catalyst to remove before bottling. var/list/catalyst_ids = list() // This keeps track of the chemicals in the catalyst to remove before bottling.
@@ -98,11 +76,72 @@
add_cartridge(new type(src)) add_cartridge(new type(src))
panel_open = FALSE panel_open = FALSE
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(get_turf(src))
P.name = "Synthesizer Instructions"
P.desc = "A photocopy of a handwritten note."
P.info = {"Hello there! This device is a new NanoTrasen product currently being shipped to select facilities \
for internal testing! We haven't finished the instruction manual yet so each unit shipped with this pamphlet \
(I really hope you can read my handwriting). This machine is a programmable chemical synthesizer which, if used \
correctly, will allow you to queue up some recipes and go work on something else while the medicine manufactures. \
It's slower than doing things by hand but it also keeps your hands free! And yes, it bottles automatically. \
<BR><BR>To get started, you need to program some recipes. The machine has two modes for this: tutorial and production. \
Tutorial is intended to teach you how recipes work, or to create recipes for later use with production mode. This one \
should be self-explanatory, just follow the prompts. Production mode allows you to rapidly import recipes in CSV format. \
If I've lost you, just keep reading; once you give it a name and tell the machine how many steps are in the recipe, just \
input the recipe as a comma-separated string of chemical names and volumes to be added, like "Chem1,10,Chem2,20,... \
<BR><BR>If that still doesn't make sense, I've included an example for Dylovene at the bottom. Also, don't include \
catalyst reagents in the recipe, read below for that part. Also also, remember that chemical names are case sensitive and \
cartridge names are usually Capitalized Like These Words (AND FOR THE LOVE OF GOD KEVIN, STOP CHANGING THE NAMES ON THE \
LABELS WHEN THE CHEMISTS AREN'T LOOKING IT ISN'T FUNNY ANYMORE). \
<BR><BR>Next important concept is the catalyst, intended for catalyst reagents (usually phoron). When the catalyst option is \
enabled, whatever is in the catalyst bottle gets added to the reaction chamber before synthesis begins. When the \
recipe is done, it extracts the catalyst, bottles whatever you made, then adds the catalyst back before starting \
the next recipe in the queue. It's up to you to make sure no unwanted side reactions happen, and yes, this means \
you cannot queue up catalyst recipes with recipes ruined by the catalyst. Maybe add "NO CAT" or something to the \
name for recipes like that? \
<BR><BR>And that's the really important stuff. Remember you can export recipes for later shifts, just copy the \
output into your PDA or something. Oh, and stalling. Say you're missing a cartridge or the vessel is full (the \
capacity is [src.reagents.maximum_volume]) or you press the emergency stop button. The machine will stall, \
clearing the temporary memory. To get it started again, you just need to empty the vessel. Anyway, here's \
example recipe. \
<BR><BR> Name: Dylovene (60u) \
<BR> Number of steps: 3 \
<BR> Recipe string: Silicon,20,Nitrogen,20,Potassium,20"}
/obj/machinery/chemical_synthesizer/examine(mob/user) /obj/machinery/chemical_synthesizer/examine(mob/user)
. = ..() . = ..()
if(panel_open) if(panel_open)
. += "It has [cartridges.len] cartridges installed, and has space for [SYNTHESIZER_MAX_CARTRIDGES - cartridges.len] more." . += "It has [cartridges.len] cartridges installed, and has space for [SYNTHESIZER_MAX_CARTRIDGES - cartridges.len] more."
/obj/machinery/chemical_synthesizer/power_change()
. = ..()
update_icon()
/obj/machinery/chemical_synthesizer/update_icon()
underlays.Cut()
if(stat & BROKEN)
icon_state = "synth_broken"
return
if(stat & NOPOWER)
icon_state = "synth_off"
return
if(!busy)
if(catalyst)
icon_state = "synth_idle_bottle"
else
icon_state = "synth_idle"
else
icon_state = "synth_working"
if(catalyst) // All underlay icon_states requires the catalyst bottle to be present, so this works as a check.
if(catalyst.reagents.reagent_list.len)
var/image/cat_filling = image(icon, src, "synth_catalyst", -1)
cat_filling.color = catalyst.reagents.get_color()
underlays += cat_filling
if(src.reagents.reagent_list.len)
var/image/ves_filling = image(icon, src, "synth_vessel", -2)
ves_filling.color = src.reagents.get_color()
underlays += ves_filling
/obj/machinery/chemical_synthesizer/proc/add_cartridge(obj/item/weapon/reagent_containers/chem_disp_cartridge/C, mob/user) /obj/machinery/chemical_synthesizer/proc/add_cartridge(obj/item/weapon/reagent_containers/chem_disp_cartridge/C, mob/user)
if(!panel_open) if(!panel_open)
if(user) if(user)
@@ -169,6 +208,9 @@
if(catalyst) if(catalyst)
to_chat(user, "<span class='warning'>There is already \a [catalyst] in \the [src] catalyst slot!</span>") to_chat(user, "<span class='warning'>There is already \a [catalyst] in \the [src] catalyst slot!</span>")
return return
if(stat & (BROKEN|NOPOWER))
to_chat(user, "<span class='warning'>The clamp will not secure the catalyst while the machine is down!</span>")
return
var/obj/item/weapon/reagent_containers/RC = W var/obj/item/weapon/reagent_containers/RC = W
@@ -223,7 +265,6 @@
data["panel_open"] = panel_open data["panel_open"] = panel_open
data["use_catalyst"] = use_catalyst data["use_catalyst"] = use_catalyst
// Queue and recipe lists might not be formatted correctly here. Delete this once you've confirmed.
var/list/tmp_queue = list() var/list/tmp_queue = list()
for(var/i = 1, i <= queue.len, i++) for(var/i = 1, i <= queue.len, i++)
tmp_queue.Add(list(list("name" = queue[i], "index" = i))) // Thanks byond tmp_queue.Add(list(list("name" = queue[i], "index" = i))) // Thanks byond
@@ -263,7 +304,6 @@
chemicals.Add(list(list("title" = label, "id" = label, "amount" = C.reagents.total_volume))) // list in a list because Byond merges the first list chemicals.Add(list(list("title" = label, "id" = label, "amount" = C.reagents.total_volume))) // list in a list because Byond merges the first list
data["chemicals"] = chemicals data["chemicals"] = chemicals
debug_data = data
return data return data
/obj/machinery/chemical_synthesizer/tgui_act(action, params) /obj/machinery/chemical_synthesizer/tgui_act(action, params)
@@ -297,6 +337,7 @@
if(!busy && catalyst) if(!busy && catalyst)
catalyst.forceMove(get_turf(src)) catalyst.forceMove(get_turf(src))
catalyst = null catalyst = null
update_icon()
if("toggle_catalyst") if("toggle_catalyst")
// Decides if the machine uses the catalyst. // Decides if the machine uses the catalyst.
if(!busy) if(!busy)
@@ -471,6 +512,7 @@
catalyst.reagents.trans_to_holder(src.reagents, catalyst.reagents.total_volume) catalyst.reagents.trans_to_holder(src.reagents, catalyst.reagents.total_volume)
// Start the first recipe in the queue, starting with step 1. // Start the first recipe in the queue, starting with step 1.
update_icon()
follow_recipe(queue[1], 1) follow_recipe(queue[1], 1)
@@ -480,7 +522,6 @@
stall() stall()
return return
icon_state = "synth_working"
if(!step) if(!step)
step = 1 step = 1
@@ -519,13 +560,13 @@
// After all this mess of code, we reach the line where the magic happens. // After all this mess of code, we reach the line where the magic happens.
C.reagents.trans_to_holder(src.reagents, quantity) C.reagents.trans_to_holder(src.reagents, quantity)
// playsound(src, 'sound/machinery/HPLC_binary_pump.ogg', 25, 1) update_icon() // Update underlays.
playsound(src, 'modular_chomp/sound/machines/HPLC_binary_pump.ogg', 15, 1)
// Advance to the next step in the recipe. If this is outside of the recipe's index, we're finished. Otherwise, proceed to next step. // Advance to the next step in the recipe. If this is outside of the recipe's index, we're finished. Otherwise, proceed to next step.
step += 2 step += 2
var/list/tmp = recipes[r_id] var/list/tmp = recipes[r_id]
if(step > tmp.len) if(step > tmp.len)
icon_state = "synth_finished"
// First extract the catalyst(s), if any remain. // First extract the catalyst(s), if any remain.
if(use_catalyst) if(use_catalyst)
@@ -536,6 +577,8 @@
// Add a delay of 1 tick per unit of reagent. Clear the catalyst_ids. // Add a delay of 1 tick per unit of reagent. Clear the catalyst_ids.
catalyst_ids = list() catalyst_ids = list()
var/delay = reagents.total_volume var/delay = reagents.total_volume
update_icon() // Update the icon first to remove underlays, then switch to the new icon_state.
icon_state = "synth_finished"
addtimer(CALLBACK(src, .proc/bottle_product, r_id), delay) addtimer(CALLBACK(src, .proc/bottle_product, r_id), delay)
else else
@@ -569,6 +612,7 @@
for(var/datum/reagent/chem in catalyst.reagents.reagent_list) for(var/datum/reagent/chem in catalyst.reagents.reagent_list)
catalyst_ids += chem.id catalyst_ids += chem.id
catalyst.reagents.trans_to_holder(src.reagents, catalyst.reagents.total_volume) catalyst.reagents.trans_to_holder(src.reagents, catalyst.reagents.total_volume)
update_icon()
follow_recipe(queue[1], 1) follow_recipe(queue[1], 1)
else else

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

View File

@@ -1,19 +1,15 @@
import { Fragment } from 'inferno'; import { Fragment } from 'inferno';
import { useBackend } from "../backend"; import { useBackend } from '../backend';
import { Box, Button, Flex, LabeledList, Section } from "../components"; import { Box, Button, Flex, LabeledList, Section } from '../components';
import { Window } from "../layouts"; import { Window } from '../layouts';
import { BeakerContents } from './common/BeakerContents'; import { BeakerContents } from './common/BeakerContents';
export const ChemSynthesizer = (props, context) => { export const ChemSynthesizer = (props, context) => {
return ( return (
<Window <Window width={1100} height={640} resizable>
width={1100}
height={640}
resizable>
<Window.Content> <Window.Content>
<Flex <Flex height="100%">
height="100%"> <Flex.Item grow={1} maxWidth="33%">
<Flex.Item grow={1} maxWidth="33%" >
<ChemSynthesizerQueueRecipes /> <ChemSynthesizerQueueRecipes />
</Flex.Item> </Flex.Item>
<Flex.Item grow={1}> <Flex.Item grow={1}>
@@ -30,23 +26,11 @@ export const ChemSynthesizer = (props, context) => {
const ChemSynthesizerQueueRecipes = (props, context) => { const ChemSynthesizerQueueRecipes = (props, context) => {
const { act, data } = useBackend(context); const { act, data } = useBackend(context);
const { const { busy, use_catalyst, queue = [], recipes = [], production_mode } = data;
busy,
use_catalyst,
queue = [],
recipes = [],
production_mode,
} = data;
return ( return (
<Flex <Flex height="100%" width="100%" direction="column">
height="100%" <Flex.Item maxHeight="50%" grow={1} basis={0}>
width="100%"
direction="column">
<Flex.Item
maxHeight="50%"
grow={1}
basis={0}>
<Section <Section
height="100%" height="100%"
title="Queue" title="Queue"
@@ -55,65 +39,58 @@ const ChemSynthesizerQueueRecipes = (props, context) => {
<Fragment> <Fragment>
<Button <Button
disabled={!!busy} disabled={!!busy}
color={use_catalyst ? "green" : "bad"} color={use_catalyst ? 'green' : 'bad'}
icon="wrench" icon="wrench"
tooltip="Enable/Disable the catalyst BEFORE starting the queue." tooltip="Enable/Disable the catalyst BEFORE starting the queue."
content={use_catalyst ? "Catalyst Active" : "Catalyst Disabled"} content={use_catalyst ? 'Catalyst Active' : 'Catalyst Disabled'}
onClick={() => act("toggle_catalyst")} /> onClick={() => act('toggle_catalyst')}
/>
<Button.Confirm <Button.Confirm
disabled={!queue.length} disabled={!queue.length}
color="bad" color="bad"
icon="minus-circle" icon="minus-circle"
tooltip="Clear Queue" tooltip="Clear Queue"
onClick={() => act("clear_queue")} /> onClick={() => act('clear_queue')}
{(!busy && ( />
<Button {!busy && (
disabled={!queue.length} <Button disabled={!queue.length} icon="play" tooltip="Start Queue" onClick={() => act('start_queue')} />
icon="play" )}
tooltip="Start Queue"
onClick={() => act("start_queue")} />
))}
</Fragment> </Fragment>
}> }>
<LabeledList> <LabeledList>
{(queue.length && queue.map((item) => { {(queue.length &&
if ((item.index === 1) && !!busy) { queue.map((item) => {
return ( if (item.index === 1 && !!busy) {
<LabeledList.Item label={item.name} labelColor="bad"> return (
{ <LabeledList.Item label={item.name} labelColor="bad">
<Box> {
<Button <Box>
disabled icon="trash"> <Button disabled icon="trash">
Delete Delete
</Button> </Button>
</Box> </Box>
} }
</LabeledList.Item> </LabeledList.Item>
); );
} }
return ( return (
<LabeledList.Item label={item.name}> <LabeledList.Item label={item.name}>
<Button <Button
icon="trash" icon="trash"
onClick={() => act("rem_queue", { onClick={() =>
q_index: item.index, act('rem_queue', {
})}> q_index: item.index,
Delete })
</Button> }>
</LabeledList.Item> Delete
); </Button>
})) || ( </LabeledList.Item>
<Box m={1}> );
Queue Empty. })) || <Box m={1}>Queue Empty.</Box>}
</Box>
)}
</LabeledList> </LabeledList>
</Section> </Section>
</Flex.Item> </Flex.Item>
<Flex.Item <Flex.Item maxHeight="50%" grow={1} basis={0}>
maxHeight="50%"
grow={1}
basis={0}>
<Section <Section
height="100%" height="100%"
title="Recipes" title="Recipes"
@@ -121,40 +98,47 @@ const ChemSynthesizerQueueRecipes = (props, context) => {
buttons={ buttons={
<Button <Button
icon="plus" icon="plus"
tooltip={production_mode ? "Import Recipe" : "Generate Recipe"} tooltip={production_mode ? 'Import Recipe' : 'Generate Recipe'}
onClick={() => act("add_recipe")} /> onClick={() => act('add_recipe')}
/>
}> }>
<LabeledList> <LabeledList>
{(recipes.length && recipes.map((item) => { {(recipes.length &&
return ( recipes.map((item) => {
<LabeledList.Item label={item.name}> return (
<Button <LabeledList.Item label={item.name}>
icon="plus" <Button
tooltip="Add to Queue" icon="plus"
onClick={() => act("add_queue", { tooltip="Add to Queue"
qa_index: item.name, onClick={() =>
})} /> act('add_queue', {
<Button qa_index: item.name,
icon="inbox" })
tooltip="Export Recipe" }
onClick={() => act("exp_recipe", { />
exp_index: item.name, <Button
})} /> icon="inbox"
<Button tooltip="Export Recipe"
color="bad" onClick={() =>
icon="minus-circle" act('exp_recipe', {
tooltip="Delete Recipe" exp_index: item.name,
disabled={!!busy} })
onClick={() => act("rem_recipe", { }
rm_index: item.name, />
})} /> <Button
</LabeledList.Item> color="bad"
); icon="minus-circle"
})) || ( tooltip="Delete Recipe"
<Box m={1}> disabled={!!busy}
No recipes found. onClick={() =>
</Box> act('rem_recipe', {
)} rm_index: item.name,
})
}
/>
</LabeledList.Item>
);
})) || <Box m={1}>No recipes found.</Box>}
</LabeledList> </LabeledList>
</Section> </Section>
</Flex.Item> </Flex.Item>
@@ -179,71 +163,48 @@ const ChemSynthesizerChemicals = (props, context) => {
flexFillers.push(true); flexFillers.push(true);
} }
return ( return (
<Flex <Flex direction="column">
direction="column"> <Section title="Cartridge Reagents" flexGrow="1">
<Section <Flex direction="row" wrap="wrap" height="100%" align="flex-start">
title="Cartridge Reagents"
flexGrow="1">
<Flex
direction="row"
wrap="wrap"
height="100%"
align="flex-start">
{chemicals.map((c, i) => ( {chemicals.map((c, i) => (
<Flex.Item key={i} grow="1" m={0.2} basis="40%" height="20px"> <Flex.Item key={i} grow="1" m={0.2} basis="40%" height="20px">
<Button <Button
icon="arrow-circle-down" icon="arrow-circle-down"
width="100%" width="100%"
height="100%" height="100%"
align="flex-start" align="flex-start"
disabled={1} disabled={1}
content={c.title + ' (' + c.amount + ')'} content={c.title + ' (' + c.amount + ')'}
/> />
</Flex.Item> </Flex.Item>
))} ))}
{flexFillers.map((_, i) => ( {flexFillers.map((_, i) => (
<Flex.Item key={i} grow="1" basis="25%" height="20px" /> <Flex.Item key={i} grow="1" basis="25%" height="20px" />
))} ))}
</Flex> </Flex>
</Section> </Section>
<Section <Section title="Reaction Vessel">
title="Reaction Vessel"> {rxn_vessel.length > 0 ? (
{(rxn_vessel.length > 0) <BeakerContents beakerLoaded beakerContents={rxn_vessel} />
? ( ) : (
<BeakerContents <Box color="label">Vessel is empty.</Box>
beakerLoaded )}
beakerContents={rxn_vessel}
/>
)
: (
<Box color="label">
Vessel is empty.
</Box>
)}
</Section> </Section>
<Section <Section
title="Catalyst" title="Catalyst"
flex="content" flex="content"
minHeight="25%" minHeight="25%"
buttons={( buttons={
<Box> <Box>
{!!catalyst && ( {!!catalyst && (
<Box inline color="label" mr={2}> <Box inline color="label" mr={2}>
{catalystCurrentVolume} / {catalystMaxVolume} units {catalystCurrentVolume} / {catalystMaxVolume} units
</Box> </Box>
)} )}
<Button <Button icon="eject" content="Eject" disabled={!catalyst || !!busy} onClick={() => act('eject_catalyst')} />
icon="eject"
content="Eject"
disabled={!catalyst || !!busy}
onClick={() => act("eject_catalyst")}
/>
</Box> </Box>
)}> }>
<BeakerContents <BeakerContents beakerLoaded={catalyst} beakerContents={catalyst_reagents} />
beakerLoaded={catalyst}
beakerContents={catalyst_reagents}
/>
</Section> </Section>
</Flex> </Flex>
); );
@@ -251,62 +212,52 @@ const ChemSynthesizerChemicals = (props, context) => {
const ChemSynthesizerSettings = (props, context) => { const ChemSynthesizerSettings = (props, context) => {
const { act, data } = useBackend(context); const { act, data } = useBackend(context);
const { const { busy, production_mode, panel_open, rxn_vessel } = data;
busy,
production_mode,
panel_open,
rxn_vessel,
} = data;
return ( return (
<Flex <Flex height="100%" width="100%" direction="column">
height="100%" <Flex.Item height={0} grow={1}>
width="100%" <Section height="100%" title="Settings" overflowY="auto">
direction="column"> <Flex direction="column">
<Flex.Item <Flex.Item>
height={0}
grow={1}>
<Section
height="100%"
title="Settings"
overflowY="auto">
<Flex
direction="column">
<Flex.Item>
<Button <Button
color={production_mode ? "green" : "bad"} color={production_mode ? 'green' : 'bad'}
icon="wrench" icon="wrench"
content={production_mode ? "Recipe mode: Import" : "Recipe mode: Tutorial"} content={production_mode ? 'Recipe mode: Import' : 'Recipe mode: Tutorial'}
onClick={() => act("mode_toggle")} /> onClick={() => act('mode_toggle')}
</Flex.Item> />
<Flex.Item> </Flex.Item>
<Flex.Item>
<Button <Button
disabled={!!busy} disabled={!!busy}
color={panel_open ? "bad" : "green"} color={panel_open ? 'bad' : 'green'}
icon="wrench" icon="wrench"
content={panel_open ? "Panel Open" : "Panel Closed"} content={panel_open ? 'Panel Open' : 'Panel Closed'}
onClick={() => act("panel_toggle")} /> onClick={() => act('panel_toggle')}
</Flex.Item> />
<Flex.Item> </Flex.Item>
{(!busy && ( <Flex.Item>
{!busy && (
<Button <Button
disabled={!rxn_vessel.length} disabled={!rxn_vessel.length}
color="bad" color="bad"
icon="flask" icon="flask"
tooltip="For emptying the reaction vessel if the machine stalls." tooltip="For emptying the reaction vessel if the machine stalls."
content="Bottle Manually" content="Bottle Manually"
onClick={() => act("bottle_product")} /> onClick={() => act('bottle_product')}
))} />
</Flex.Item> )}
<Flex.Item> </Flex.Item>
<Flex.Item>
<Button <Button
disabled={!busy} disabled={!busy}
color="bad" color="bad"
icon="minus-circle" icon="minus-circle"
content="EMERGENCY STOP" content="EMERGENCY STOP"
onClick={() => act("emergency_stop")} /> onClick={() => act('emergency_stop')}
</Flex.Item> />
</Flex> </Flex.Item>
</Flex>
</Section> </Section>
</Flex.Item> </Flex.Item>
</Flex> </Flex>

File diff suppressed because one or more lines are too long