From 0e32b0c19f28ee58d215cdb2b6aaeb291fe55534 Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 27 Jun 2024 23:11:16 +0300 Subject: [PATCH] New Microscope UI (#84298) ## About The Pull Request Continuing the QoL things for Cytology, updated Microscope UI to be more user-friendly. ![image](https://github.com/tgstation/tgstation/assets/3625094/c1740cd9-1371-4e15-b658-4dd468e45b7a) Before: ![image](https://github.com/tgstation/tgstation/assets/3625094/e67f147a-07b9-45b6-b4ad-886227bc8132) Plus some maintenance in micro organism code and QOL things for microscope (removing sample with right click, dish swapping, balloon alerts). ## Why It's Good For The Game The UX for cytology got better. ## Changelog :cl: qol: Updated Microscope UI qol: Microscope is easier to use - you can remove dish with right click and swap dishes /:cl: --------- Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com> --- .../xenobiology/vatgrowing/microscope.dm | 86 +++++--- .../vatgrowing/samples/_micro_organism.dm | 31 +-- .../vatgrowing/samples/cell_lines/common.dm | 71 +++---- tgui/packages/tgui/interfaces/Microscope.jsx | 91 --------- tgui/packages/tgui/interfaces/Microscope.tsx | 184 ++++++++++++++++++ 5 files changed, 301 insertions(+), 162 deletions(-) delete mode 100644 tgui/packages/tgui/interfaces/Microscope.jsx create mode 100644 tgui/packages/tgui/interfaces/Microscope.tsx diff --git a/code/modules/research/xenobiology/vatgrowing/microscope.dm b/code/modules/research/xenobiology/vatgrowing/microscope.dm index 2e70d20faf0..df065698436 100644 --- a/code/modules/research/xenobiology/vatgrowing/microscope.dm +++ b/code/modules/research/xenobiology/vatgrowing/microscope.dm @@ -3,17 +3,28 @@ desc = "A simple microscope, allowing you to examine micro-organisms." icon = 'icons/obj/science/vatgrowing.dmi' icon_state = "microscope" + ///Analyzed dish var/obj/item/petri_dish/current_dish -/obj/structure/microscope/attacked_by(obj/item/I, mob/living/user) - if(!istype(I, /obj/item/petri_dish)) - return ..() +/obj/structure/microscope/Initialize(mapload) + . = ..() + var/static/list/hovering_item_typechecks = list( + /obj/item/petri_dish = list( + SCREENTIP_CONTEXT_LMB = "Add petri dish", + ), + ) + AddElement(/datum/element/contextual_screentip_item_typechecks, hovering_item_typechecks) + AddElement(/datum/element/contextual_screentip_bare_hands, rmb_text = "Remove petri dish") + +/obj/structure/microscope/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + . = ..() + if(istype(tool, /obj/item/petri_dish)) + return add_dish(user, tool) + +/obj/structure/microscope/attack_hand_secondary(mob/user, list/modifiers) + . = ..() if(current_dish) - to_chat(user, span_warning("There is already a petridish in \the [src].")) - return - to_chat(user, span_notice("You put [I] into \the [src].")) - current_dish = I - current_dish.forceMove(src) + return remove_dish(user) /obj/structure/microscope/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) @@ -21,27 +32,30 @@ ui = new(user, src, "Microscope", name) ui.open() -/obj/structure/microscope/ui_data(mob/user) +/obj/structure/microscope/ui_static_data(mob/user) var/list/data = list() data["has_dish"] = current_dish ? TRUE : FALSE data["cell_lines"] = list() - data["viruses"] = list() if(!current_dish) return data if(!current_dish.sample) return data - for(var/organism in current_dish.sample.micro_organisms) //All the microorganisms in the dish + for(var/organism in current_dish.sample.micro_organisms) if(istype(organism, /datum/micro_organism/cell_line)) var/datum/micro_organism/cell_line/cell_line = organism + var/atom/resulting_atom = cell_line.resulting_atom var/list/organism_data = list( type = "cell line", name = cell_line.name, desc = cell_line.desc, - growth_rate = cell_line.growth_rate, - suspectibility = cell_line.virus_suspectibility, + icon = resulting_atom ? initial(resulting_atom.icon) : "", + icon_state = resulting_atom ? initial(resulting_atom.icon_state) : "", + consumption_rate = cell_line.consumption_rate * SSMACHINES_DT, + growth_rate = cell_line.growth_rate * SSMACHINES_DT, + suspectibility = cell_line.virus_suspectibility * SSMACHINES_DT, requireds = get_reagent_list(cell_line.required_reagents), supplementaries = get_reagent_list(cell_line.supplementary_reagents), suppressives = get_reagent_list(cell_line.suppressive_reagents) @@ -55,7 +69,7 @@ name = virus.name, desc = virus.desc ) - data["viruses"] += list(virus_data) + data["cell_lines"] += list(virus_data) return data @@ -63,23 +77,49 @@ var/list/reagent_list = list() for(var/i in reagents) //Convert from assoc to normal. Yeah very shit. var/datum/reagent/reagent = i - reagent_list += initial(reagent.name) - return reagent_list.Join(", ") + reagent_list["[initial(reagent.name)]"] = reagents[i] * SSMACHINES_DT + return reagent_list - -/obj/structure/microscope/ui_act(action, params) +/obj/structure/microscope/ui_act(action, params, datum/tgui/ui) . = ..() if(.) return switch(action) if("eject_petridish") - if(!current_dish) - return FALSE - current_dish.forceMove(get_turf(src)) - current_dish = null - . = TRUE + if(current_dish) + remove_dish(ui.user) + . = TRUE update_appearance() +///Insert a new dish, swapping the inserted one +/obj/structure/microscope/proc/add_dish(mob/living/user, obj/item/petri_dish/new_dish) + var/obj/item/petri_dish/old_dish + if(current_dish) + old_dish = current_dish + if(!user.transferItemToLoc(new_dish, src)) + balloon_alert(user, "couldn't add!") + return ITEM_INTERACT_FAILURE + current_dish = new_dish + update_static_data_for_all_viewers() + if(old_dish) + if(!user.put_in_hands(old_dish)) + old_dish.forceMove(get_turf(src)) + balloon_alert(user, "dish swapped") + else + balloon_alert(user, "dish added") + return ITEM_INTERACT_SUCCESS + +///Take the inserted dish, or drop it on the floor +/obj/structure/microscope/proc/remove_dish(mob/living/user) + if(!current_dish) + return SECONDARY_ATTACK_CONTINUE_CHAIN + if(!user.put_in_hands(current_dish)) + current_dish.forceMove(get_turf(src)) + current_dish = null + update_static_data_for_all_viewers() + balloon_alert(user, "dish removed") + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + /datum/crafting_recipe/microscope name = "Microscope" result = /obj/structure/microscope diff --git a/code/modules/research/xenobiology/vatgrowing/samples/_micro_organism.dm b/code/modules/research/xenobiology/vatgrowing/samples/_micro_organism.dm index edeeaad05c6..b8af4dd062c 100644 --- a/code/modules/research/xenobiology/vatgrowing/samples/_micro_organism.dm +++ b/code/modules/research/xenobiology/vatgrowing/samples/_micro_organism.dm @@ -23,8 +23,12 @@ var/virus_suspectibility = 1 ///This var defines how much % the organism grows per process(), without modifiers, if you have all required reagents var/growth_rate = 4 - ///Resulting atoms from growing this cell line. List is assoc atom type || amount - var/list/resulting_atoms = list() + ///This var defines how many units of every reagent is consumed during growth per process() + var/consumption_rate = REAGENTS_METABOLISM + ///Resulting atom from growing this cell line + var/atom/resulting_atom + ///The number of resulting atoms + var/resulting_atom_count = 1 ///Handles growth of the micro_organism. This only runs if the micro organism is in the growing vat. Reagents is the growing vats reagents /datum/micro_organism/cell_line/proc/handle_growth(obj/machinery/plumbing/growing_vat/vat) @@ -41,7 +45,7 @@ if(!reagents.has_reagent(i)) return FALSE for(var/i in required_reagents) //Delete the required reagents if used - reagents.remove_reagent(i, REAGENTS_METABOLISM) + reagents.remove_reagent(i, consumption_rate) return TRUE ///Apply modifiers on growth_rate based on supplementary and supressive reagents. Reagents is the growing vats reagents @@ -50,22 +54,22 @@ //Handle growth based on supplementary reagents here. for(var/i in supplementary_reagents) - if(!reagents.has_reagent(i, REAGENTS_METABOLISM)) + if(!reagents.has_reagent(i, consumption_rate)) continue . += supplementary_reagents[i] - reagents.remove_reagent(i, REAGENTS_METABOLISM) + reagents.remove_reagent(i, consumption_rate) //Handle degrowth based on supressive reagents here. for(var/i in suppressive_reagents) - if(!reagents.has_reagent(i, REAGENTS_METABOLISM)) + if(!reagents.has_reagent(i, consumption_rate)) continue . += suppressive_reagents[i] - reagents.remove_reagent(i, REAGENTS_METABOLISM) + reagents.remove_reagent(i, consumption_rate) //Handle debuffing growth based on viruses here. for(var/datum/micro_organism/virus/active_virus in biological_sample.micro_organisms) - if(reagents.has_reagent(/datum/reagent/medicine/spaceacillin, REAGENTS_METABOLISM)) - reagents.remove_reagent(/datum/reagent/medicine/spaceacillin, REAGENTS_METABOLISM) + if(reagents.has_reagent(/datum/reagent/medicine/spaceacillin, consumption_rate)) + reagents.remove_reagent(/datum/reagent/medicine/spaceacillin, consumption_rate) continue //This virus is stopped, We have antiviral stuff . -= virus_suspectibility @@ -98,11 +102,10 @@ var/datum/effect_system/fluid_spread/smoke/smoke = new smoke.set_up(0, holder = vat, location = vat.loc) smoke.start() - for(var/created_thing in resulting_atoms) - for(var/x in 1 to resulting_atoms[created_thing]) - var/atom/thing = new created_thing(get_turf(vat)) - ADD_TRAIT(thing, TRAIT_VATGROWN, "vatgrowing") - vat.visible_message(span_nicegreen("[thing] pops out of [vat]!")) + for(var/x in 1 to resulting_atom_count) + var/atom/thing = new resulting_atom(get_turf(vat)) + ADD_TRAIT(thing, TRAIT_VATGROWN, "vatgrowing") + vat.visible_message(span_nicegreen("[thing] pops out of [vat]!")) if(SEND_SIGNAL(vat.biological_sample, COMSIG_SAMPLE_GROWTH_COMPLETED) & SPARE_SAMPLE) return QDEL_NULL(vat.biological_sample) diff --git a/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/common.dm b/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/common.dm index b170cb19fd7..8dd4594d47d 100644 --- a/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/common.dm +++ b/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/common.dm @@ -25,7 +25,8 @@ virus_suspectibility = 2 growth_rate = VAT_GROWTH_RATE - resulting_atoms = list(/mob/living/basic/mouse = 2) + resulting_atom = /mob/living/basic/mouse + resulting_atom_count = 2 /datum/micro_organism/cell_line/chicken //basic cell line designed as a good source of protein and eggyolk. desc = "Galliform skin cells." @@ -43,7 +44,7 @@ virus_suspectibility = 1 growth_rate = VAT_GROWTH_RATE - resulting_atoms = list(/mob/living/basic/chicken = 1) + resulting_atom = /mob/living/basic/chicken /datum/micro_organism/cell_line/cow desc = "Bovine stem cells" @@ -62,7 +63,7 @@ /datum/reagent/toxin/carpotoxin = -5) virus_suspectibility = 1 - resulting_atoms = list(/mob/living/basic/cow = 1) + resulting_atom = /mob/living/basic/cow /datum/micro_organism/cell_line/moonicorn desc = "Fairyland Bovine stem cells" @@ -87,7 +88,7 @@ ) virus_suspectibility = 1 - resulting_atoms = list(/mob/living/basic/cow/moonicorn = 1) + resulting_atom = /mob/living/basic/cow/moonicorn /datum/micro_organism/cell_line/cat desc = "Feliform cells" @@ -108,7 +109,7 @@ /datum/reagent/consumable/milk/chocolate_milk = -1) virus_suspectibility = 1.5 - resulting_atoms = list(/mob/living/basic/pet/cat = 1) + resulting_atom = /mob/living/basic/pet/cat /datum/micro_organism/cell_line/corgi desc = "Canid cells" @@ -127,7 +128,7 @@ /datum/reagent/consumable/coco = -2) virus_suspectibility = 1 - resulting_atoms = list(/mob/living/basic/pet/dog/corgi = 1) + resulting_atom = /mob/living/basic/pet/dog/corgi /datum/micro_organism/cell_line/pug desc = "Squat canid cells" @@ -145,7 +146,7 @@ /datum/reagent/consumable/coco = -2) virus_suspectibility = 3 - resulting_atoms = list(/mob/living/basic/pet/dog/pug = 1) + resulting_atom = /mob/living/basic/pet/dog/pug /datum/micro_organism/cell_line/bear //bears can't really compete directly with more powerful creatures, so i made it possible to grow them real fast. desc = "Ursine cells" @@ -166,7 +167,7 @@ /datum/reagent/medicine/insulin = -2) //depletes hunny. virus_suspectibility = 2 - resulting_atoms = list(/mob/living/basic/bear = 1) + resulting_atom = /mob/living/basic/bear /datum/micro_organism/cell_line/carp desc = "Cyprinid cells" @@ -185,7 +186,7 @@ /datum/reagent/oxygen = -3) virus_suspectibility = 2 - resulting_atoms = list(/mob/living/basic/carp = 1) + resulting_atom = /mob/living/basic/carp /datum/micro_organism/cell_line/megacarp desc = "Cartilaginous cyprinid cells" @@ -205,7 +206,7 @@ /datum/reagent/oxygen = -3) virus_suspectibility = 1 - resulting_atoms = list(/mob/living/basic/carp/mega = 1) + resulting_atom = /mob/living/basic/carp/mega /datum/micro_organism/cell_line/snake desc = "Ophidic cells" @@ -223,7 +224,7 @@ /datum/reagent/consumable/corn_syrup = -6, /datum/reagent/sulfur = -3) //sulfur repels snakes according to professor google. - resulting_atoms = list(/mob/living/basic/snake = 1) + resulting_atom = /mob/living/basic/snake /////////////////////////////////////////// @@ -246,7 +247,7 @@ /datum/reagent/consumable/ice = -2) //Brrr! virus_suspectibility = 0 - resulting_atoms = list(/mob/living/basic/slime = 1) + resulting_atom = /mob/living/basic/slime /datum/micro_organism/cell_line/blob_spore //nuisance cell line desc = "Immature blob spores" @@ -263,7 +264,8 @@ /datum/reagent/medicine/psicodine = -2) //Blob zombies likely wouldn't appreciate psicodine so why this is here virus_suspectibility = 0 - resulting_atoms = list(/mob/living/basic/blob_minion/spore = 2) //These are useless so we might as well spawn 2. + resulting_atom = /mob/living/basic/blob_minion/spore + resulting_atom_count = 2 /datum/micro_organism/cell_line/blobbernaut desc = "Blobular myocytes" @@ -282,7 +284,7 @@ suppressive_reagents = list(/datum/reagent/consumable/tinlux = -6) virus_suspectibility = 0 - resulting_atoms = list(/mob/living/basic/blob_minion/blobbernaut = 1) + resulting_atom = /mob/living/basic/blob_minion/blobbernaut /datum/micro_organism/cell_line/gelatinous_cube desc = "Cubic ooze particles" @@ -307,7 +309,7 @@ /datum/reagent/consumable/ice = -1) virus_suspectibility = 0 - resulting_atoms = list(/mob/living/simple_animal/hostile/ooze/gelatinous = 1) + resulting_atom = /mob/living/simple_animal/hostile/ooze/gelatinous /datum/micro_organism/cell_line/sholean_grapes desc = "Globular ooze particles" @@ -334,7 +336,7 @@ /datum/reagent/consumable/ice = -1) virus_suspectibility = 0 - resulting_atoms = list(/mob/living/simple_animal/hostile/ooze/grapes = 1) + resulting_atom = /mob/living/simple_animal/hostile/ooze/grapes //////////////////// //// MISC //// @@ -355,7 +357,8 @@ /datum/reagent/consumable/ethanol/bug_spray = -4) virus_suspectibility = 0 - resulting_atoms = list(/mob/living/basic/cockroach = 5) + resulting_atom = /mob/living/basic/cockroach + resulting_atom_count = 5 /datum/micro_organism/cell_line/glockroach desc = "Gattodeoid anthropod cells" @@ -376,7 +379,8 @@ /datum/reagent/consumable/ethanol/bug_spray = -4) virus_suspectibility = 0 - resulting_atoms = list(/mob/living/basic/cockroach/glockroach = 2) + resulting_atom = /mob/living/basic/cockroach/glockroach + resulting_atom_count = 2 /datum/micro_organism/cell_line/hauberoach desc = "Hattodeoid anthropod cells" @@ -397,7 +401,8 @@ /datum/reagent/consumable/ethanol/cognac = -4) virus_suspectibility = 0 - resulting_atoms = list(/mob/living/basic/cockroach/hauberoach = 2) + resulting_atom = /mob/living/basic/cockroach/hauberoach + resulting_atom_count = 2 /datum/micro_organism/cell_line/pine desc = "Coniferous plant cells" @@ -418,7 +423,7 @@ suppressive_reagents = list(/datum/reagent/toxin/plantbgone = -8) virus_suspectibility = 1 - resulting_atoms = list(/mob/living/basic/tree = 1) + resulting_atom = /mob/living/basic/tree /datum/micro_organism/cell_line/vat_beast desc = "Hypergenic xenocytes" @@ -443,7 +448,7 @@ /datum/reagent/medicine/c2/syriniver = -2) virus_suspectibility = 0.5 - resulting_atoms = list(/mob/living/simple_animal/hostile/vatbeast = 1) + resulting_atom = /mob/living/simple_animal/hostile/vatbeast /datum/micro_organism/cell_line/vat_beast/succeed_growing(obj/machinery/plumbing/growing_vat/vat) . = ..() @@ -470,12 +475,9 @@ /datum/reagent/consumable/liquidgibs = -2) virus_suspectibility = 0 - resulting_atoms = list() /datum/micro_organism/cell_line/netherworld/succeed_growing(obj/machinery/plumbing/growing_vat/vat) - var/random_result = pick(/mob/living/basic/creature, /mob/living/basic/migo, /mob/living/basic/blankbody) //i looked myself, pretty much all of them are reasonably strong and somewhat on the same level. except migo is the jackpot and the blank body is whiff. - resulting_atoms = list() - resulting_atoms[random_result] = 1 + resulting_atom = pick(/mob/living/basic/creature, /mob/living/basic/migo, /mob/living/basic/blankbody) //i looked myself, pretty much all of them are reasonably strong and somewhat on the same level. except migo is the jackpot and the blank body is whiff. return ..() /datum/micro_organism/cell_line/clown/fuck_up_growing(obj/machinery/plumbing/growing_vat/vat) @@ -509,7 +511,7 @@ /datum/reagent/consumable/nothing = -2, /datum/reagent/fuel/oil = -1) - resulting_atoms = list(/mob/living/basic/clown/banana = 1) + resulting_atom = /mob/living/basic/clown/banana /datum/micro_organism/cell_line/clown/glutton desc = "hyperadipogenic clown stem cells" @@ -535,7 +537,7 @@ /datum/reagent/consumable/nothing = -2, /datum/reagent/toxin/bad_food = -1) - resulting_atoms = list(/mob/living/basic/clown/mutant/glutton = 1) + resulting_atom = /mob/living/basic/clown/mutant/glutton /datum/micro_organism/cell_line/clown/longclown desc = "long clown bits" @@ -558,7 +560,7 @@ /datum/reagent/consumable/nothing = -2, /datum/reagent/sulfur = -1) - resulting_atoms = list(/mob/living/basic/clown/longface = 1) + resulting_atom = /mob/living/basic/clown/longface /datum/micro_organism/cell_line/frog desc = "anura amphibian cells" @@ -579,7 +581,7 @@ /datum/reagent/toxin = -1) virus_suspectibility = 0.5 - resulting_atoms = list(/mob/living/basic/frog = 1) + resulting_atom = /mob/living/basic/frog /datum/micro_organism/cell_line/axolotl desc = "caudata amphibian cells" @@ -602,7 +604,7 @@ /datum/reagent/toxin = -1) virus_suspectibility = 0.5 - resulting_atoms = list(/mob/living/basic/axolotl = 1) + resulting_atom = /mob/living/basic/axolotl /datum/micro_organism/cell_line/walking_mushroom desc = "motile fungal hyphae" @@ -627,7 +629,7 @@ /datum/reagent/copper = -1) virus_suspectibility = 0 - resulting_atoms = list(/mob/living/basic/mushroom = 1) + resulting_atom = /mob/living/basic/mushroom /datum/micro_organism/cell_line/queen_bee desc = "aphid cells" @@ -652,7 +654,7 @@ /datum/reagent/drug/nicotine = -1) virus_suspectibility = 0 - resulting_atoms = list(/obj/item/queen_bee/bought = 1) + resulting_atom = /obj/item/queen_bee/bought /datum/micro_organism/cell_line/queen_bee/fuck_up_growing(obj/machinery/plumbing/growing_vat/vat) //we love job hazards vat.visible_message(span_warning("You hear angry buzzing coming from the inside of the vat!")) @@ -682,7 +684,8 @@ ) virus_suspectibility = 0 - resulting_atoms = list(/mob/living/basic/butterfly = 3) + resulting_atom = /mob/living/basic/butterfly + resulting_atom_count = 3 /datum/micro_organism/cell_line/mega_arachnid desc = "pseudoarachnoid cells" @@ -708,6 +711,6 @@ /datum/reagent/drug/nicotine = -1, /datum/reagent/toxin/pestkiller = -1) - resulting_atoms = list(/mob/living/basic/mega_arachnid = 1) + resulting_atom = /mob/living/basic/mega_arachnid #undef VAT_GROWTH_RATE diff --git a/tgui/packages/tgui/interfaces/Microscope.jsx b/tgui/packages/tgui/interfaces/Microscope.jsx deleted file mode 100644 index 74591fce7d3..00000000000 --- a/tgui/packages/tgui/interfaces/Microscope.jsx +++ /dev/null @@ -1,91 +0,0 @@ -import { useBackend, useSharedState } from '../backend'; -import { Button, LabeledList, NoticeBox, Section, Tabs } from '../components'; -import { Window } from '../layouts'; - -export const Microscope = (props) => { - const { act, data } = useBackend(); - const [tab, setTab] = useSharedState('tab', 1); - const { has_dish, cell_lines = [], viruses = [] } = data; - - return ( - - -
- - -
- - setTab(1)} - > - Micro-Organisms ({cell_lines.length}) - - setTab(2)} - > - Viruses ({viruses.length}) - - - {tab === 1 && } - {tab === 2 && } -
-
- ); -}; - -const Organisms = (props) => { - const { cell_lines } = props; - const { act, data } = useBackend(); - if (!cell_lines.length) { - return No micro-organisms found; - } - - return cell_lines.map((cell_line) => { - return ( -
- - - {cell_line.growth_rate} - - - {cell_line.suspectibility} - - - {cell_line.requireds} - - - {cell_line.supplementaries} - - - {cell_line.suppressives} - - -
- ); - }); -}; - -const Viruses = (props) => { - const { viruses } = props; - const { act } = useBackend(); - if (!viruses.length) { - return No viruses found; - } - return viruses.map((virus) => { - return
; - }); -}; diff --git a/tgui/packages/tgui/interfaces/Microscope.tsx b/tgui/packages/tgui/interfaces/Microscope.tsx new file mode 100644 index 00000000000..44aa7d2b660 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Microscope.tsx @@ -0,0 +1,184 @@ +import { BooleanLike } from 'common/react'; + +import { useBackend } from '../backend'; +import { + Box, + Button, + Divider, + DmIcon, + Icon, + NoticeBox, + Section, + Stack, +} from '../components'; +import { Window } from '../layouts'; + +type Data = { + has_dish: BooleanLike; + cell_lines: CellLine[]; +}; + +type CellLine = { + type: string; + name: string; + desc: string; + icon: string; + icon_state: string; + consumption_rate: number; + growth_rate: number; + suspectibility: number; + requireds: Record; + supplementaries: Record; + suppressives: Record; +}; + +export const Microscope = (props) => { + const { act, data } = useBackend(); + const { has_dish, cell_lines = [] } = data; + + return ( + + +
act('eject_petridish')} + > + Take Dish + + ) + } + > + +
+
+
+ ); +}; + +const CellList = (props) => { + const { cell_lines } = props; + const fallback = ( + + ); + if (!cell_lines.length) { + return No micro-organisms found; + } + + return cell_lines.map((cell_line) => { + return cell_line.type !== 'virus' ? ( + + + + + +
+ } + > + + Consume {cell_line.consumption_rate} units of every nutrient per + second to grow by {cell_line.growth_rate}%. + + {cell_line.suspectibility > 0 && ( + + Reduced by {cell_line.suspectibility}% when infected with + viruses. + + )} + + + + {Object.keys(cell_line.requireds).map((reagent) => ( + + ))} + + + + {Object.keys(cell_line.supplementaries).map((reagent) => ( + + ))} + + + + {Object.keys(cell_line.suppressives).map((reagent) => ( + + ))} + + +
+
+
+ ) : ( + + + + + +
+ + Reduces growth of other cell lines when not suppressed by + Spaceacillin. + +
+
+
+ ); + }); +}; + +const GroupTitle = (props) => { + const { title } = props; + return ( + + + + + + {title} + + + + + + ) as any; +};