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

🆑
qol: Updated Microscope UI
qol: Microscope is easier to use - you can remove dish with right click
and swap dishes
/🆑

---------

Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
This commit is contained in:
Andrew
2024-06-27 13:11:16 -07:00
committed by GitHub
co-authored by MrMelbert
parent bfc70e2596
commit 0e32b0c19f
5 changed files with 301 additions and 162 deletions
@@ -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
@@ -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)
@@ -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
@@ -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 (
<Window>
<Window.Content scrollable>
<Section>
<LabeledList>
<LabeledList.Item label="Dish Sample">
<Button
icon="eject"
content="Eject"
disabled={!has_dish}
onClick={() => act('eject_petridish')}
/>
</LabeledList.Item>
</LabeledList>
</Section>
<Tabs>
<Tabs.Tab
icon="microscope"
lineHeight="23px"
selected={tab === 1}
onClick={() => setTab(1)}
>
Micro-Organisms ({cell_lines.length})
</Tabs.Tab>
<Tabs.Tab
icon="microscope"
lineHeight="23px"
selected={tab === 2}
onClick={() => setTab(2)}
>
Viruses ({viruses.length})
</Tabs.Tab>
</Tabs>
{tab === 1 && <Organisms cell_lines={cell_lines} />}
{tab === 2 && <Viruses viruses={viruses} />}
</Window.Content>
</Window>
);
};
const Organisms = (props) => {
const { cell_lines } = props;
const { act, data } = useBackend();
if (!cell_lines.length) {
return <NoticeBox>No micro-organisms found</NoticeBox>;
}
return cell_lines.map((cell_line) => {
return (
<Section key={cell_line.desc} title={cell_line.desc}>
<LabeledList>
<LabeledList.Item label="Growth Rate">
{cell_line.growth_rate}
</LabeledList.Item>
<LabeledList.Item label="Virus Suspectibility">
{cell_line.suspectibility}
</LabeledList.Item>
<LabeledList.Item label="Required Reagents">
{cell_line.requireds}
</LabeledList.Item>
<LabeledList.Item label="Supplementary Reagents">
{cell_line.supplementaries}
</LabeledList.Item>
<LabeledList.Item label="Suppresive reagents">
{cell_line.suppressives}
</LabeledList.Item>
</LabeledList>
</Section>
);
});
};
const Viruses = (props) => {
const { viruses } = props;
const { act } = useBackend();
if (!viruses.length) {
return <NoticeBox>No viruses found</NoticeBox>;
}
return viruses.map((virus) => {
return <Section key={virus.desc} title={virus.desc} />;
});
};
@@ -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<string, number>;
supplementaries: Record<string, number>;
suppressives: Record<string, number>;
};
export const Microscope = (props) => {
const { act, data } = useBackend<Data>();
const { has_dish, cell_lines = [] } = data;
return (
<Window width={620} height={620}>
<Window.Content scrollable>
<Section
title={has_dish ? 'Petri Dish Sample' : 'No Petri Dish'}
buttons={
!!has_dish && (
<Button
icon="eject"
disabled={!has_dish}
onClick={() => act('eject_petridish')}
>
Take Dish
</Button>
)
}
>
<CellList cell_lines={cell_lines} />
</Section>
</Window.Content>
</Window>
);
};
const CellList = (props) => {
const { cell_lines } = props;
const fallback = (
<Icon name="spinner" size={5} height="64px" width="64px" spin />
);
if (!cell_lines.length) {
return <NoticeBox>No micro-organisms found</NoticeBox>;
}
return cell_lines.map((cell_line) => {
return cell_line.type !== 'virus' ? (
<Stack key={cell_line.desc} mt={2}>
<Stack.Item>
<DmIcon
fallback={fallback}
icon={cell_line.icon}
icon_state={cell_line.icon_state}
height="64px"
width="64px"
/>
</Stack.Item>
<Stack.Item grow pl={1}>
<Section
title={cell_line.desc}
buttons={
<Button
color="transparent"
icon="circle-question"
tooltip="Put the sample into a Growing Vat and pour the required reagents."
/>
}
>
<Box my={1}>
Consume {cell_line.consumption_rate} units of every nutrient per
second to grow by {cell_line.growth_rate}%.
</Box>
{cell_line.suspectibility > 0 && (
<Box my={1}>
Reduced by {cell_line.suspectibility}% when infected with
viruses.
</Box>
)}
<Stack fill>
<Stack.Item grow>
<GroupTitle title="Required Reagents" />
{Object.keys(cell_line.requireds).map((reagent) => (
<Button fluid key={reagent}>
{reagent}
</Button>
))}
</Stack.Item>
<Stack.Item grow>
<GroupTitle title="Supplements" />
{Object.keys(cell_line.supplementaries).map((reagent) => (
<Button
fluid
color="good"
key={reagent}
tooltip={
'+' + cell_line.supplementaries[reagent] + '% growth/sec.'
}
>
{reagent}
</Button>
))}
</Stack.Item>
<Stack.Item grow>
<GroupTitle title="Supressives" />
{Object.keys(cell_line.suppressives).map((reagent) => (
<Button
fluid
color="bad"
key={reagent}
tooltip={cell_line.suppressives[reagent] + '% growth/sec.'}
>
{reagent}
</Button>
))}
</Stack.Item>
</Stack>
</Section>
</Stack.Item>
</Stack>
) : (
<Stack key={cell_line.desc} mt={2}>
<Stack.Item>
<Icon name="viruses" color="bad" size={4} mr={1} />
</Stack.Item>
<Stack.Item grow pl={1}>
<Section title={cell_line.desc}>
<Box my={1}>
Reduces growth of other cell lines when not suppressed by
Spaceacillin.
</Box>
</Section>
</Stack.Item>
</Stack>
);
});
};
const GroupTitle = (props) => {
const { title } = props;
return (
<Stack my={1}>
<Stack.Item grow>
<Divider />
</Stack.Item>
<Stack.Item
style={{
textTransform: 'capitalize',
}}
color={'gray'}
>
{title}
</Stack.Item>
<Stack.Item grow>
<Divider />
</Stack.Item>
</Stack>
) as any;
};