mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-29 08:08:49 +01:00
Plant Analyzer UX Revamp (#92667)
## About The Pull Request <img width="1300" height="706" alt="image" src="https://github.com/user-attachments/assets/c7971eab-6af3-4fea-94f5-b76104696b73" /> 1. Chems are no longer hidden in an icon's tooltip. There is a separate tab for chems. Right clicking to do a chem scan will pull up the chem tab, but you can also just use the two buttons at the top - Closes #91172 2. You no longer need to repeatedly scan a tray to update the UI. Standing adjacent to a scanned tray will update it regularly. 3. Units have been redefined from pure seconds to minutes/seconds where applicable. 4. The report has been swapped around, with tray on top and plant on bottom. 5. The nutrient bar is now colored based on contents of the tray. It no longer has a tooltip listing the tray's contents, that's now in the chemicals tab. 6. Auto-grow, pollinating, and yield modifier icons have been brought center below the tray, instead of in the top right section. They now change color to make it more apparent at a glance. 7. Traits have been moved from icons to a collapsible list at the bottom of the UI, and are now printed entirely. They still have tooltips explaining what they do. 8. Grafted gene was moved center below the plant, and is now printed entirely. 9. Mutations have been moved to a collapsible list center below the plant. 10. Plants now indicate if they are dead in the UI. 11. Scanning produce now lists all the chemicals inside it on top of all the chemicals it produces. - Closes #89443, Closes #90793 12. Restores lost behavior of seed unique data - Closes #90706 Also 13. Added Hydroponics to Runtime station 14. Added screentip for dumping reagents from hydro-trays ## Why It's Good For The Game While I was initially supportive of the move to a plant analyzer UI it was undeniable it was a huge UX stepdown from printing results to chat. This PR aims to bring back some of those lost UX features by making more information visible at a glance (instead of requiring memorization of mystery meat icons or hovering over many elements to find information hidden in tooltips) I know it's a little bit of a mess with the colors and layout, I planned on doing a whole custom css and layout and such but I kinda just wanted to get it out. ## Changelog 🆑 Melbert qol: Plant analyzer: Scanning a tray will regularly update the UI with the tray's information while you stand adjacent to it, no longer requiring you re-scan the tray to update it. qol: Plant analyzer: UI is now split between chems and stats - RMB will open directly to the chem tab. qol: Plant analyzer: UI received several UX changes - listing out more information at a glance, rather than behind tooltips or icons fix: Plant analyzer: Chem scanning plants now shows the plant's current chemical contents once again (on top of their genes) fix: Plant analyzer: Unique seed data (kudzu mutation, replica pod dna) is shown again qol: Added hydroponics to runtime station qol: Added screentip to hydroponic trays for clearing reagents /🆑
This commit is contained in:
@@ -1222,6 +1222,11 @@
|
||||
"kS" = (
|
||||
/turf/closed/wall/r_wall,
|
||||
/area/station/medical/chemistry)
|
||||
"kY" = (
|
||||
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
|
||||
/obj/structure/cable,
|
||||
/turf/open/floor/iron,
|
||||
/area/station/service/hydroponics)
|
||||
"lc" = (
|
||||
/turf/open/floor/engine,
|
||||
/area/station/hallway/secondary/entry)
|
||||
@@ -1444,6 +1449,13 @@
|
||||
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
|
||||
/turf/open/floor/plating,
|
||||
/area/station/engineering/main)
|
||||
"tj" = (
|
||||
/obj/structure/cable,
|
||||
/obj/machinery/light/directional/east,
|
||||
/obj/item/gun/energy/floragun,
|
||||
/obj/item/geneshears,
|
||||
/turf/open/floor/iron,
|
||||
/area/station/service/hydroponics)
|
||||
"tn" = (
|
||||
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
|
||||
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
|
||||
@@ -1559,6 +1571,12 @@
|
||||
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
|
||||
/turf/open/floor/iron/white/corner,
|
||||
/area/station/medical/medbay)
|
||||
"vK" = (
|
||||
/obj/machinery/door/airlock,
|
||||
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
|
||||
/obj/structure/cable,
|
||||
/turf/open/floor/iron,
|
||||
/area/station/service/hydroponics)
|
||||
"vQ" = (
|
||||
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
|
||||
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
|
||||
@@ -1638,6 +1656,12 @@
|
||||
/obj/structure/transit_tube/station/dispenser/reverse/flipped,
|
||||
/turf/open/floor/iron,
|
||||
/area/station/engineering/gravity_generator)
|
||||
"xv" = (
|
||||
/obj/machinery/vending/hydroseeds{
|
||||
all_products_free = 1
|
||||
},
|
||||
/turf/open/floor/iron,
|
||||
/area/station/service/hydroponics)
|
||||
"xD" = (
|
||||
/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4,
|
||||
/obj/effect/turf_decal/tile/blue/half/contrasted,
|
||||
@@ -1728,6 +1752,10 @@
|
||||
/obj/machinery/airalarm/directional/north,
|
||||
/turf/open/floor/iron,
|
||||
/area/station/science)
|
||||
"zU" = (
|
||||
/obj/machinery/hydroponics/constructable/fullupgrade,
|
||||
/turf/open/floor/iron,
|
||||
/area/station/service/hydroponics)
|
||||
"zY" = (
|
||||
/obj/effect/turf_decal/stripes/line,
|
||||
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
|
||||
@@ -1736,6 +1764,7 @@
|
||||
/area/station/commons/storage/primary)
|
||||
"Aj" = (
|
||||
/obj/structure/cable,
|
||||
/obj/machinery/light/directional/east,
|
||||
/turf/open/floor/iron,
|
||||
/area/station/cargo/bitrunning/den)
|
||||
"An" = (
|
||||
@@ -1792,6 +1821,11 @@
|
||||
/obj/item/gun/ballistic/automatic/pistol,
|
||||
/turf/open/floor/iron,
|
||||
/area/station/command/bridge)
|
||||
"BK" = (
|
||||
/obj/item/wrench,
|
||||
/obj/item/plant_analyzer,
|
||||
/turf/open/floor/iron,
|
||||
/area/station/service/hydroponics)
|
||||
"BM" = (
|
||||
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
|
||||
/turf/open/floor/iron,
|
||||
@@ -1841,6 +1875,17 @@
|
||||
/obj/machinery/component_printer,
|
||||
/turf/open/floor/iron/dark,
|
||||
/area/station/science/explab)
|
||||
"Dd" = (
|
||||
/obj/item/shovel/spade{
|
||||
pixel_y = 4;
|
||||
pixel_x = 3
|
||||
},
|
||||
/obj/item/secateurs,
|
||||
/obj/item/cultivator{
|
||||
pixel_x = -6
|
||||
},
|
||||
/turf/open/floor/iron,
|
||||
/area/station/service/hydroponics)
|
||||
"Df" = (
|
||||
/obj/machinery/light/directional/east,
|
||||
/obj/item/integrated_circuit/loaded/hello_world,
|
||||
@@ -1984,7 +2029,7 @@
|
||||
/area/station/engineering/atmos)
|
||||
"GN" = (
|
||||
/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{
|
||||
dir = 4
|
||||
dir = 1
|
||||
},
|
||||
/obj/machinery/light/directional/south,
|
||||
/turf/open/floor/iron,
|
||||
@@ -2098,6 +2143,9 @@
|
||||
/obj/effect/turf_decal/tile/neutral/fourcorners,
|
||||
/turf/open/floor/iron/dark,
|
||||
/area/station/engineering/gravity_generator)
|
||||
"Ju" = (
|
||||
/turf/closed/wall/r_wall,
|
||||
/area/station/service/hydroponics)
|
||||
"JJ" = (
|
||||
/obj/machinery/navbeacon{
|
||||
codes_txt = "patrol;next_patrol=4-Southeast";
|
||||
@@ -2133,6 +2181,12 @@
|
||||
/obj/machinery/light/directional/south,
|
||||
/turf/open/floor/plating,
|
||||
/area/station/engineering/atmos)
|
||||
"KW" = (
|
||||
/obj/structure/sink/directional/south,
|
||||
/obj/item/storage/bag/plants,
|
||||
/obj/item/reagent_containers/cup/watering_can/advanced,
|
||||
/turf/open/floor/iron,
|
||||
/area/station/service/hydroponics)
|
||||
"Lb" = (
|
||||
/obj/effect/turf_decal/stripes/line{
|
||||
dir = 1
|
||||
@@ -2193,11 +2247,6 @@
|
||||
/obj/structure/cable,
|
||||
/turf/open/floor/iron,
|
||||
/area/station/hallway/primary/central)
|
||||
"Ml" = (
|
||||
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
|
||||
/obj/machinery/light/directional/south,
|
||||
/turf/open/floor/iron,
|
||||
/area/station/hallway/secondary/entry)
|
||||
"My" = (
|
||||
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
|
||||
/obj/structure/cable,
|
||||
@@ -2210,6 +2259,12 @@
|
||||
},
|
||||
/turf/open/floor/iron,
|
||||
/area/station/cargo/miningoffice)
|
||||
"MH" = (
|
||||
/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/floor/iron,
|
||||
/area/station/service/hydroponics)
|
||||
"MM" = (
|
||||
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
|
||||
/obj/effect/turf_decal/stripes/line{
|
||||
@@ -2222,6 +2277,12 @@
|
||||
/obj/effect/turf_decal/tile/neutral/fourcorners,
|
||||
/turf/open/floor/iron/dark,
|
||||
/area/station/engineering/gravity_generator)
|
||||
"MT" = (
|
||||
/obj/machinery/vending/hydronutrients{
|
||||
all_products_free = 1
|
||||
},
|
||||
/turf/open/floor/iron,
|
||||
/area/station/service/hydroponics)
|
||||
"Nb" = (
|
||||
/obj/machinery/bci_implanter,
|
||||
/turf/open/floor/iron/dark,
|
||||
@@ -2275,6 +2336,10 @@
|
||||
/obj/item/stock_parts/power_store/cell/bluespace,
|
||||
/turf/open/floor/iron/dark,
|
||||
/area/station/science/explab)
|
||||
"Oy" = (
|
||||
/obj/machinery/seed_extractor,
|
||||
/turf/open/floor/iron,
|
||||
/area/station/service/hydroponics)
|
||||
"OF" = (
|
||||
/obj/structure/cable,
|
||||
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
|
||||
@@ -2483,7 +2548,6 @@
|
||||
/area/station/medical/medbay)
|
||||
"SC" = (
|
||||
/obj/structure/table/reinforced,
|
||||
/obj/machinery/light/directional/south,
|
||||
/obj/item/bitrunning_debug,
|
||||
/turf/open/floor/iron,
|
||||
/area/station/cargo/bitrunning/den)
|
||||
@@ -2573,6 +2637,13 @@
|
||||
/obj/structure/cable,
|
||||
/turf/open/floor/iron,
|
||||
/area/station/engineering/main)
|
||||
"VF" = (
|
||||
/obj/machinery/hydroponics/constructable/fullupgrade,
|
||||
/obj/machinery/power/apc/auto_name/directional/south,
|
||||
/obj/structure/cable,
|
||||
/obj/machinery/airalarm/directional/east,
|
||||
/turf/open/floor/iron,
|
||||
/area/station/service/hydroponics)
|
||||
"We" = (
|
||||
/obj/machinery/newscaster/directional/west,
|
||||
/turf/open/floor/iron,
|
||||
@@ -2672,6 +2743,10 @@
|
||||
"Yd" = (
|
||||
/turf/open/floor/iron,
|
||||
/area/station/cargo/bitrunning/den)
|
||||
"Yg" = (
|
||||
/obj/machinery/smartfridge/food,
|
||||
/turf/open/floor/plating,
|
||||
/area/station/service/hydroponics)
|
||||
"Ym" = (
|
||||
/obj/structure/table,
|
||||
/obj/item/storage/toolbox/electrical,
|
||||
@@ -3356,12 +3431,12 @@ aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
Ju
|
||||
Ju
|
||||
Ju
|
||||
Ju
|
||||
Ju
|
||||
Ju
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
@@ -3448,12 +3523,12 @@ aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
Ju
|
||||
MT
|
||||
xv
|
||||
BK
|
||||
zU
|
||||
Ju
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
@@ -3540,12 +3615,12 @@ aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
Ju
|
||||
KW
|
||||
MH
|
||||
Dd
|
||||
zU
|
||||
Ju
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
@@ -3632,12 +3707,12 @@ aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
Ju
|
||||
Oy
|
||||
kY
|
||||
tj
|
||||
VF
|
||||
Ju
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
@@ -3724,12 +3799,12 @@ Tj
|
||||
Tj
|
||||
Tj
|
||||
Tj
|
||||
dY
|
||||
en
|
||||
dY
|
||||
dY
|
||||
aa
|
||||
aa
|
||||
Ju
|
||||
Yg
|
||||
vK
|
||||
Ju
|
||||
Ju
|
||||
Ju
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
@@ -3818,7 +3893,7 @@ lc
|
||||
lc
|
||||
wB
|
||||
eh
|
||||
eh
|
||||
ax
|
||||
dY
|
||||
aa
|
||||
aa
|
||||
@@ -3910,7 +3985,7 @@ lc
|
||||
lc
|
||||
wB
|
||||
eh
|
||||
eh
|
||||
ax
|
||||
en
|
||||
aa
|
||||
aa
|
||||
@@ -4002,7 +4077,7 @@ lc
|
||||
lc
|
||||
wB
|
||||
eh
|
||||
eh
|
||||
ax
|
||||
en
|
||||
aa
|
||||
aa
|
||||
@@ -4094,7 +4169,7 @@ lc
|
||||
lc
|
||||
wB
|
||||
eh
|
||||
eh
|
||||
ax
|
||||
dY
|
||||
aa
|
||||
aa
|
||||
@@ -4186,7 +4261,7 @@ lc
|
||||
lc
|
||||
wB
|
||||
eh
|
||||
eh
|
||||
ax
|
||||
en
|
||||
aa
|
||||
aa
|
||||
@@ -4278,7 +4353,7 @@ lc
|
||||
lc
|
||||
wB
|
||||
eh
|
||||
eh
|
||||
ax
|
||||
en
|
||||
aa
|
||||
aa
|
||||
@@ -4369,8 +4444,8 @@ lc
|
||||
lc
|
||||
lc
|
||||
wB
|
||||
eh
|
||||
eh
|
||||
ax
|
||||
ax
|
||||
en
|
||||
aa
|
||||
aa
|
||||
@@ -4461,7 +4536,7 @@ lc
|
||||
lc
|
||||
lc
|
||||
wB
|
||||
eh
|
||||
ax
|
||||
eh
|
||||
dY
|
||||
aa
|
||||
@@ -4553,7 +4628,7 @@ lc
|
||||
lc
|
||||
lc
|
||||
wB
|
||||
eh
|
||||
ax
|
||||
eh
|
||||
en
|
||||
aa
|
||||
@@ -4645,7 +4720,7 @@ lc
|
||||
lc
|
||||
lc
|
||||
wB
|
||||
eh
|
||||
ax
|
||||
eh
|
||||
en
|
||||
aa
|
||||
@@ -4737,7 +4812,7 @@ lc
|
||||
lc
|
||||
lc
|
||||
wB
|
||||
eh
|
||||
ax
|
||||
gv
|
||||
dY
|
||||
aa
|
||||
@@ -4829,7 +4904,7 @@ lc
|
||||
lc
|
||||
lc
|
||||
wB
|
||||
eh
|
||||
ax
|
||||
eh
|
||||
en
|
||||
aa
|
||||
@@ -4921,7 +4996,7 @@ lc
|
||||
lc
|
||||
lc
|
||||
wB
|
||||
eh
|
||||
ax
|
||||
gF
|
||||
fj
|
||||
aa
|
||||
@@ -5013,7 +5088,7 @@ lc
|
||||
lc
|
||||
lc
|
||||
wB
|
||||
eh
|
||||
ax
|
||||
eh
|
||||
en
|
||||
aa
|
||||
@@ -5105,7 +5180,7 @@ lc
|
||||
lc
|
||||
lc
|
||||
wB
|
||||
eh
|
||||
ax
|
||||
GN
|
||||
dY
|
||||
aa
|
||||
@@ -5197,8 +5272,8 @@ lc
|
||||
lc
|
||||
lc
|
||||
wB
|
||||
ax
|
||||
eh
|
||||
BM
|
||||
en
|
||||
aa
|
||||
aa
|
||||
@@ -5289,8 +5364,8 @@ lc
|
||||
lc
|
||||
lc
|
||||
wB
|
||||
ax
|
||||
eh
|
||||
BM
|
||||
en
|
||||
aa
|
||||
aa
|
||||
@@ -5381,8 +5456,8 @@ lc
|
||||
lc
|
||||
lc
|
||||
wB
|
||||
ax
|
||||
eh
|
||||
BM
|
||||
en
|
||||
aa
|
||||
aa
|
||||
@@ -5473,8 +5548,8 @@ lc
|
||||
lc
|
||||
lc
|
||||
wB
|
||||
eh
|
||||
Ml
|
||||
ax
|
||||
gv
|
||||
dY
|
||||
aa
|
||||
aa
|
||||
@@ -5565,8 +5640,8 @@ lc
|
||||
lc
|
||||
lc
|
||||
wB
|
||||
ax
|
||||
eh
|
||||
BM
|
||||
en
|
||||
aa
|
||||
aa
|
||||
@@ -5657,8 +5732,8 @@ en
|
||||
en
|
||||
dY
|
||||
wB
|
||||
ax
|
||||
eh
|
||||
BM
|
||||
dY
|
||||
dY
|
||||
fn
|
||||
@@ -5749,8 +5824,8 @@ eh
|
||||
eh
|
||||
eV
|
||||
eh
|
||||
ax
|
||||
eh
|
||||
BM
|
||||
eh
|
||||
eV
|
||||
eh
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#define PLANT_ANALYZER_STAT_TAB 1
|
||||
#define PLANT_ANALYZER_CHEM_TAB 2
|
||||
|
||||
/obj/item/plant_analyzer
|
||||
name = "plant analyzer"
|
||||
desc = "A scanner used to evaluate a plant's various areas of growth, genetic traits and chemicals."
|
||||
@@ -12,13 +15,21 @@
|
||||
custom_materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT*0.3, /datum/material/glass =SMALL_MATERIAL_AMOUNT*0.2)
|
||||
/// Cached data from ui_interact
|
||||
var/list/last_scan_data
|
||||
/// Weakref to the last thing we scanned
|
||||
var/datum/weakref/last_tray_scanned
|
||||
/// Cached data for the product grinder results
|
||||
var/static/list/product_grinder_results = list()
|
||||
/// If TRUE the UI opens to the second tab / the chem tab
|
||||
var/shown_tab = PLANT_ANALYZER_STAT_TAB
|
||||
|
||||
/obj/item/plant_analyzer/Initialize(mapload)
|
||||
. = ..()
|
||||
register_item_context()
|
||||
|
||||
/obj/item/plant_analyzer/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/item/plant_analyzer/add_item_context(
|
||||
obj/item/source,
|
||||
list/context,
|
||||
@@ -63,6 +74,7 @@
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
shown_tab = PLANT_ANALYZER_STAT_TAB
|
||||
return analyze(user, interacting_with)
|
||||
|
||||
/// Same as above, but with right click. Right-clicking scans for chemicals.
|
||||
@@ -86,6 +98,7 @@
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
shown_tab = PLANT_ANALYZER_CHEM_TAB
|
||||
return analyze(user, scan_target)
|
||||
|
||||
/*
|
||||
@@ -123,8 +136,22 @@
|
||||
ui = new(user, src, "PlantAnalyzer", "Plant Analyzer")
|
||||
ui.open()
|
||||
|
||||
/obj/item/plant_analyzer/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
switch(action)
|
||||
if("setTab")
|
||||
var/tab = params["tab"]
|
||||
if(tab == PLANT_ANALYZER_STAT_TAB || tab == PLANT_ANALYZER_CHEM_TAB)
|
||||
shown_tab = tab
|
||||
return TRUE
|
||||
|
||||
/obj/item/plant_analyzer/ui_data(mob/user)
|
||||
return last_scan_data
|
||||
var/list/data = list()
|
||||
data["active_tab"] = shown_tab
|
||||
data += last_scan_data
|
||||
return data
|
||||
|
||||
/obj/item/plant_analyzer/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
@@ -140,13 +167,22 @@
|
||||
data["trait_db"] += trait_data
|
||||
return data
|
||||
|
||||
/obj/item/plant_analyzer/process(seconds_per_tick)
|
||||
var/atom/real_last_tray_scanned = last_tray_scanned?.resolve()
|
||||
if(QDELETED(real_last_tray_scanned))
|
||||
return PROCESS_KILL
|
||||
|
||||
if(loc.Adjacent(real_last_tray_scanned))
|
||||
analyze(null, real_last_tray_scanned)
|
||||
|
||||
/// Called when our analyzer is used on something
|
||||
/obj/item/plant_analyzer/proc/analyze(mob/user, atom/target)
|
||||
var/obj/item/graft/graft
|
||||
var/obj/item/seeds/seed
|
||||
var/obj/machinery/hydroponics/tray
|
||||
|
||||
playsound(src, SFX_INDUSTRIAL_SCAN, 20, TRUE, -2, TRUE, FALSE)
|
||||
if(user)
|
||||
playsound(src, SFX_INDUSTRIAL_SCAN, 20, TRUE, -2, TRUE, FALSE)
|
||||
|
||||
if (istype(target, /obj/machinery/hydroponics))
|
||||
tray = target
|
||||
@@ -166,12 +202,16 @@
|
||||
if (!seed && !tray && !graft)
|
||||
return NONE
|
||||
|
||||
if(!user.can_read(src))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(user)
|
||||
if(!user.can_read(src))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
START_PROCESSING(SSobj, src)
|
||||
last_tray_scanned = WEAKREF(tray) // sets it to null if no tray
|
||||
|
||||
last_scan_data = list(
|
||||
"tray_data" = null,
|
||||
"seed_data" = null,
|
||||
"plant_data" = null,
|
||||
"graft_data" = null,
|
||||
)
|
||||
|
||||
@@ -179,6 +219,7 @@
|
||||
last_scan_data["tray_data"] = list(
|
||||
"plant_health" = tray.plant_health,
|
||||
"plant_age" = tray.age,
|
||||
"is_dead" = tray.plant_status == HYDROTRAY_PLANT_DEAD,
|
||||
"name" = tray.name,
|
||||
"icon" = tray.icon,
|
||||
"icon_state" = tray.icon_state,
|
||||
@@ -198,15 +239,27 @@
|
||||
"toxins_max" = MAX_TRAY_TOXINS,
|
||||
"reagents" = list(),
|
||||
)
|
||||
for(var/datum/reagent/reagent in tray.reagents.reagent_list)
|
||||
for(var/datum/reagent/reagent as anything in tray.reagents.reagent_list)
|
||||
last_scan_data["tray_data"]["reagents"] += list(list(
|
||||
"name" = reagent.name,
|
||||
"volume" = reagent.volume
|
||||
"volume" = round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL),
|
||||
"color" = reagent.color,
|
||||
))
|
||||
|
||||
if(seed)
|
||||
last_scan_data["seed_data"] = make_seed_data(seed)
|
||||
|
||||
if(isitem(target) && target.reagents)
|
||||
last_scan_data["plant_data"] = list(
|
||||
"reagents" = list(),
|
||||
)
|
||||
for(var/datum/reagent/reagent as anything in target.reagents.reagent_list)
|
||||
last_scan_data["plant_data"]["reagents"] += list(list(
|
||||
"name" = reagent.name,
|
||||
"volume" = round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL),
|
||||
"color" = reagent.color,
|
||||
))
|
||||
|
||||
if(graft)
|
||||
last_scan_data["graft_data"] = list(
|
||||
"name" = graft.parent_name,
|
||||
@@ -218,10 +271,11 @@
|
||||
"endurance" = graft.endurance,
|
||||
"weed_rate" = graft.weed_rate,
|
||||
"weed_chance" = graft.weed_chance,
|
||||
"graft_gene" = graft.stored_trait.type
|
||||
"graft_gene" = graft.stored_trait.type,
|
||||
)
|
||||
|
||||
ui_interact(user)
|
||||
if(user)
|
||||
ui_interact(user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
|
||||
@@ -280,4 +334,15 @@
|
||||
seed_data["juice_name"] = product_grinder_results[seed.product]["juice_name"]
|
||||
seed_data["grind_results"] = product_grinder_results[seed.product]["grind_results"]
|
||||
|
||||
seed_data["unique_labels"] = list()
|
||||
seed_data["unique_collapsibles"] = list()
|
||||
var/list/unique_data = seed.get_unique_analyzer_data()
|
||||
for(var/label in unique_data)
|
||||
seed_data[islist(unique_data[label]) ? "unique_collapsibles" : "unique_labels"] += list(list(
|
||||
"label" = label,
|
||||
"data" = unique_data[label],
|
||||
))
|
||||
return seed_data
|
||||
|
||||
#undef PLANT_ANALYZER_STAT_TAB
|
||||
#undef PLANT_ANALYZER_CHEM_TAB
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/datum/spacevine_mutation
|
||||
/// Displayed name of mutation
|
||||
var/name = ""
|
||||
/// Description of mutation, shown in the plant analyzer
|
||||
var/description = ""
|
||||
/// Severity of mutation in terms of gameplay, affects appearance chance and how many mutations can be on the same vine
|
||||
var/severity = 1
|
||||
/// The mutation's contribution to a given vine's color
|
||||
@@ -64,6 +66,7 @@
|
||||
|
||||
/datum/spacevine_mutation/light
|
||||
name = "Light"
|
||||
description = "Emits light."
|
||||
hue = "#B2EA70"
|
||||
quality = POSITIVE
|
||||
severity = SEVERITY_TRIVIAL
|
||||
@@ -74,6 +77,7 @@
|
||||
|
||||
/datum/spacevine_mutation/toxicity
|
||||
name = "Toxic"
|
||||
description = "Releases toxins when touched or eaten."
|
||||
hue = "#9B3675"
|
||||
severity = SEVERITY_AVERAGE
|
||||
quality = NEGATIVE
|
||||
@@ -91,6 +95,7 @@
|
||||
|
||||
/datum/spacevine_mutation/explosive // JC IT'S A BOMB
|
||||
name = "Explosive"
|
||||
description = "Causes an explosion when destroyed."
|
||||
hue = "#D83A56"
|
||||
quality = NEGATIVE
|
||||
severity = SEVERITY_MAJOR
|
||||
@@ -108,6 +113,7 @@
|
||||
|
||||
/datum/spacevine_mutation/fire_proof
|
||||
name = "Fire proof"
|
||||
description = "Provides immunity to heat and burn damage."
|
||||
hue = "#FF616D"
|
||||
quality = MINOR_NEGATIVE
|
||||
severity = SEVERITY_ABOVE_AVERAGE
|
||||
@@ -123,6 +129,7 @@
|
||||
|
||||
/datum/spacevine_mutation/cold_proof
|
||||
name = "Cold proof"
|
||||
description = "Provides immunity to cold damage."
|
||||
hue = "#0BD5D9"
|
||||
quality = MINOR_NEGATIVE
|
||||
severity = SEVERITY_AVERAGE
|
||||
@@ -133,6 +140,7 @@
|
||||
|
||||
/datum/spacevine_mutation/temp_stabilisation
|
||||
name = "Temperature stabilisation"
|
||||
description = "Stabilizes the temperature of the surrounding area."
|
||||
hue = "#B09856"
|
||||
quality = POSITIVE
|
||||
severity = SEVERITY_MINOR
|
||||
@@ -156,6 +164,7 @@
|
||||
|
||||
/datum/spacevine_mutation/vine_eating
|
||||
name = "Vine eating"
|
||||
description = "Destroys other Kudzu vines on spread."
|
||||
hue = "#F4A442"
|
||||
quality = MINOR_NEGATIVE
|
||||
severity = SEVERITY_MINOR
|
||||
@@ -167,6 +176,7 @@
|
||||
|
||||
/datum/spacevine_mutation/aggressive_spread //very OP, but im out of other ideas currently
|
||||
name = "Aggressive spreading"
|
||||
description = "Heavily wounds mobs when spreading or tangling them."
|
||||
hue = "#316b2f"
|
||||
severity = SEVERITY_MAJOR
|
||||
quality = NEGATIVE
|
||||
@@ -222,6 +232,7 @@
|
||||
|
||||
/datum/spacevine_mutation/transparency
|
||||
name = "transparent"
|
||||
description = "Allows light to pass through."
|
||||
hue = ""
|
||||
quality = POSITIVE
|
||||
severity = SEVERITY_TRIVIAL
|
||||
@@ -232,6 +243,7 @@
|
||||
|
||||
/datum/spacevine_mutation/oxy_eater
|
||||
name = "Oxygen consuming"
|
||||
description = "Consumes Oxygen from the surrounding area."
|
||||
hue = "#28B5B5"
|
||||
severity = SEVERITY_AVERAGE
|
||||
quality = NEGATIVE
|
||||
@@ -247,6 +259,7 @@
|
||||
|
||||
/datum/spacevine_mutation/nitro_eater
|
||||
name = "Nitrogen consuming"
|
||||
description = "Consumes Nitrogen from the surrounding area."
|
||||
hue = "#FF7B54"
|
||||
severity = SEVERITY_AVERAGE
|
||||
quality = NEGATIVE
|
||||
@@ -262,6 +275,7 @@
|
||||
|
||||
/datum/spacevine_mutation/carbondioxide_eater
|
||||
name = "CO2 consuming"
|
||||
description = "Consumes Carbon Dioxide from the surrounding area."
|
||||
hue = "#798777"
|
||||
severity = SEVERITY_MINOR
|
||||
quality = POSITIVE
|
||||
@@ -277,6 +291,7 @@
|
||||
|
||||
/datum/spacevine_mutation/plasma_eater
|
||||
name = "Plasma consuming"
|
||||
description = "Consumes Plasma from the surrounding area."
|
||||
hue = "#9074b6"
|
||||
severity = SEVERITY_AVERAGE
|
||||
quality = POSITIVE
|
||||
@@ -292,6 +307,7 @@
|
||||
|
||||
/datum/spacevine_mutation/thorns
|
||||
name = "Thorny"
|
||||
description = "Causes damage when hitting or passing through the vines."
|
||||
hue = "#9ECCA4"
|
||||
severity = SEVERITY_AVERAGE
|
||||
quality = NEGATIVE
|
||||
@@ -324,6 +340,7 @@
|
||||
|
||||
/datum/spacevine_mutation/hardened
|
||||
name = "Hardened"
|
||||
description = "Provides resistance to cutting attacks, makes vines hardier, and prevents light from passing through."
|
||||
hue = "#997700"
|
||||
quality = NEGATIVE
|
||||
severity = SEVERITY_ABOVE_AVERAGE
|
||||
@@ -340,6 +357,7 @@
|
||||
|
||||
/datum/spacevine_mutation/timid
|
||||
name = "Timid"
|
||||
description = "Hides the vines under structures and prevents them from tangling mobs."
|
||||
hue = "#a4a9ac"
|
||||
quality = POSITIVE
|
||||
severity = SEVERITY_MINOR
|
||||
@@ -354,6 +372,7 @@
|
||||
|
||||
/datum/spacevine_mutation/flowering
|
||||
name = "Flowering"
|
||||
description = "Causes the vine to grow flower buds which spawns man eating plants when fully grown."
|
||||
hue = "#66DE93"
|
||||
quality = NEGATIVE
|
||||
severity = SEVERITY_MAJOR
|
||||
|
||||
@@ -106,11 +106,10 @@
|
||||
sampleDNA = null
|
||||
contains_sample = FALSE
|
||||
|
||||
/obj/item/seeds/replicapod/get_unique_analyzer_text()
|
||||
/obj/item/seeds/replicapod/get_unique_analyzer_data()
|
||||
if(contains_sample)
|
||||
return "It contains a blood sample with blood DNA (UE) \"[sampleDNA]\"." //blood DNA (UE) shows in medical records and is readable by forensics scanners
|
||||
else
|
||||
return null
|
||||
return list("Blood DNA" = sampleDNA)
|
||||
return null
|
||||
|
||||
/obj/item/seeds/replicapod/harvest(mob/user) //now that one is fun -- Urist
|
||||
var/obj/machinery/hydroponics/parent = loc
|
||||
|
||||
@@ -50,13 +50,12 @@
|
||||
plant(user)
|
||||
to_chat(user, span_notice("You plant the kudzu. You monster."))
|
||||
|
||||
/obj/item/seeds/kudzu/get_unique_analyzer_text()
|
||||
var/kudzu_mutations = ""
|
||||
var/output_message = ""
|
||||
for(var/datum/spacevine_mutation/SM in mutations)
|
||||
kudzu_mutations += "[(kudzu_mutations == "") ? "" : ", "][SM.name]"
|
||||
output_message += "Plant Mutations: [(kudzu_mutations == "") ? "None." : "[kudzu_mutations]."]"
|
||||
return output_message
|
||||
/obj/item/seeds/kudzu/get_unique_analyzer_data()
|
||||
var/list/all_mutations = list()
|
||||
for(var/datum/spacevine_mutation/vine_trait in mutations)
|
||||
all_mutations[vine_trait.name] = vine_trait.description
|
||||
|
||||
return list("Kudzu Traits" = all_mutations)
|
||||
|
||||
/obj/item/seeds/kudzu/on_chem_reaction(datum/reagents/reagents)
|
||||
var/list/temp_mut_list = list()
|
||||
|
||||
@@ -111,16 +111,16 @@
|
||||
if(HAS_SILICON_ACCESS(user))
|
||||
return NONE
|
||||
|
||||
context[SCREENTIP_CONTEXT_RMB] = "Empty nutrients"
|
||||
|
||||
switch(plant_status)
|
||||
if(HYDROTRAY_PLANT_DEAD)
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Remove dead plant"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
if(HYDROTRAY_PLANT_HARVESTABLE)
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Harvest plant"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
return NONE
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
// If the plant is harvestable, we can graft it with secateurs or harvest it with a plant bag.
|
||||
if(plant_status == HYDROTRAY_PLANT_HARVESTABLE)
|
||||
|
||||
@@ -452,9 +452,11 @@
|
||||
|
||||
/**
|
||||
* Override for seeds with unique text for their analyzer. (No newlines at the start or end of unique text!)
|
||||
* Returns null if no unique text, or a string of text if there is.
|
||||
* Returns null if no unique data
|
||||
* Return an assoc list (label = text) to add a new line to the analyzer
|
||||
* Return an assoc list (label = list(text = tooltip, text = tooltip)) to add a new collapsible section to the analyzer
|
||||
*/
|
||||
/obj/item/seeds/proc/get_unique_analyzer_text()
|
||||
/obj/item/seeds/proc/get_unique_analyzer_data()
|
||||
return null
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,6 +16,11 @@ export function PlantAnalyzerGraft(props) {
|
||||
const { data } = useBackend<PlantAnalyzerData>();
|
||||
const { graft_data } = data;
|
||||
|
||||
if (!graft_data) {
|
||||
// This shouldn't be rendered if graft_data is null
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Section
|
||||
title={`Graft: ${capitalizeFirst(graft_data.name)}`}
|
||||
|
||||
@@ -1,48 +1,107 @@
|
||||
import {
|
||||
Blink,
|
||||
Box,
|
||||
Button,
|
||||
Collapsible,
|
||||
DmIcon,
|
||||
Icon,
|
||||
LabeledList,
|
||||
NoticeBox,
|
||||
ProgressBar,
|
||||
Section,
|
||||
Stack,
|
||||
Table,
|
||||
Tooltip,
|
||||
} from 'tgui-core/components';
|
||||
import { capitalizeFirst } from 'tgui-core/string';
|
||||
|
||||
import { useBackend } from '../../backend';
|
||||
import { ReagentTooltip } from '../SeedExtractor';
|
||||
import { TraitTooltip } from '../SeedExtractor';
|
||||
import { Fallback } from './Fallback';
|
||||
import type { PlantAnalyzerData } from './types';
|
||||
import type { PlantAnalyzerData, ReagentData, SeedData } from './types';
|
||||
|
||||
export function PlantAnalyzerSeed(props) {
|
||||
export function PlantAnalyzerSeedStats(props) {
|
||||
const { data } = useBackend<PlantAnalyzerData>();
|
||||
const { seed_data, tray_data } = data;
|
||||
const { seed_data, tray_data, cycle_seconds, trait_db } = data;
|
||||
|
||||
if (!seed_data) {
|
||||
// This shouldn't be rendered if seed data is null
|
||||
return null;
|
||||
}
|
||||
|
||||
const all_traits = [
|
||||
...(seed_data.core_traits || []),
|
||||
...(seed_data.removable_traits || []),
|
||||
];
|
||||
|
||||
return (
|
||||
<Section
|
||||
title={capitalizeFirst(seed_data.name)}
|
||||
buttons={<SeedExtraData />}
|
||||
>
|
||||
<Section title={capitalizeFirst(seed_data.name)}>
|
||||
<Stack>
|
||||
<Stack.Item mx={2}>
|
||||
<DmIcon
|
||||
fallback={Fallback}
|
||||
icon={seed_data.icon}
|
||||
icon_state={seed_data.icon_state}
|
||||
height="64px"
|
||||
width="64px"
|
||||
/>
|
||||
{seed_data.product_icon && seed_data.product_icon_state && (
|
||||
<DmIcon
|
||||
mt={2}
|
||||
fallback={Fallback}
|
||||
icon={seed_data.product_icon}
|
||||
icon_state={seed_data.product_icon_state}
|
||||
height="64px"
|
||||
width="64px"
|
||||
/>
|
||||
)}
|
||||
<Stack.Item mx={1}>
|
||||
<Stack vertical align="center" width="150px">
|
||||
<Stack.Item>
|
||||
<DmIcon
|
||||
fallback={Fallback}
|
||||
icon={seed_data.icon}
|
||||
icon_state={seed_data.icon_state}
|
||||
height="64px"
|
||||
width="64px"
|
||||
/>
|
||||
</Stack.Item>
|
||||
{seed_data.product_icon && seed_data.product_icon_state && (
|
||||
<Stack.Item>
|
||||
<DmIcon
|
||||
mt={2}
|
||||
fallback={Fallback}
|
||||
icon={seed_data.product_icon}
|
||||
icon_state={seed_data.product_icon_state}
|
||||
height="64px"
|
||||
width="64px"
|
||||
/>
|
||||
</Stack.Item>
|
||||
)}
|
||||
<Stack.Item width="100%">
|
||||
<Button
|
||||
fluid
|
||||
icon="scissors"
|
||||
disabled={1}
|
||||
color="teal"
|
||||
ellipsis
|
||||
tooltip={
|
||||
'Using secateurs on the plant will produce a graft \
|
||||
containing the listed gene.'
|
||||
}
|
||||
>
|
||||
{getTraitInfo(seed_data.graft_gene, trait_db)?.name ||
|
||||
'No graft gene'}
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
{seed_data.mutatelist.length > 0 && (
|
||||
<Stack.Item width="100%">
|
||||
<Collapsible title="Mutations:" color="olive" textColor="black">
|
||||
<Stack vertical>
|
||||
{seed_data.mutatelist.map((mutation) => (
|
||||
<Stack.Item key={`preview_${mutation}`} width="100%">
|
||||
<Button
|
||||
fluid
|
||||
ellipsis
|
||||
icon="dna"
|
||||
disabled={1}
|
||||
color="olive"
|
||||
textColor="black"
|
||||
tooltip={
|
||||
'Once sufficiently unstable the plant may mutate \
|
||||
into the listed plant.'
|
||||
}
|
||||
>
|
||||
{mutation}
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
))}
|
||||
</Stack>
|
||||
</Collapsible>
|
||||
</Stack.Item>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
<Stack.Item width="100%">
|
||||
<LabeledList>
|
||||
@@ -79,18 +138,25 @@ export function PlantAnalyzerSeed(props) {
|
||||
|
||||
{tray_data && (
|
||||
<LabeledList.Item label="Age">
|
||||
<ProgressBar
|
||||
value={tray_data.plant_age}
|
||||
maxValue={seed_data.lifespan}
|
||||
ranges={{
|
||||
average: [0, seed_data.maturation],
|
||||
good: [seed_data.maturation, seed_data.lifespan],
|
||||
bad: [seed_data.lifespan, Infinity],
|
||||
}}
|
||||
>
|
||||
{tray_data.plant_age * data.cycle_seconds} /{' '}
|
||||
{seed_data.lifespan * data.cycle_seconds} seconds
|
||||
</ProgressBar>
|
||||
{tray_data.is_dead ? (
|
||||
<NoticeBox color="red" align="center">
|
||||
<Icon name="skull" mr={1} />
|
||||
Dead
|
||||
</NoticeBox>
|
||||
) : (
|
||||
<ProgressBar
|
||||
value={tray_data.plant_age}
|
||||
maxValue={seed_data.lifespan}
|
||||
ranges={{
|
||||
average: [0, seed_data.maturation],
|
||||
good: [seed_data.maturation, seed_data.lifespan],
|
||||
bad: [seed_data.lifespan, Infinity],
|
||||
}}
|
||||
>
|
||||
{tray_data.plant_age * cycle_seconds} /{' '}
|
||||
{formatPerSecond(seed_data.lifespan, cycle_seconds, false)}
|
||||
</ProgressBar>
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
)}
|
||||
|
||||
@@ -98,30 +164,21 @@ export function PlantAnalyzerSeed(props) {
|
||||
label="Maturation"
|
||||
tooltip="The age at which the plant starts growing products."
|
||||
>
|
||||
{seed_data.maturation * data.cycle_seconds} seconds
|
||||
{formatPerSecond(seed_data.maturation, cycle_seconds)}
|
||||
</LabeledList.Item>
|
||||
|
||||
<LabeledList.Item
|
||||
label="Production"
|
||||
tooltip="The time needed for a mature plant to (re)grow a product."
|
||||
>
|
||||
{seed_data.production * data.cycle_seconds} seconds
|
||||
{formatPerSecond(seed_data.production, cycle_seconds)}
|
||||
</LabeledList.Item>
|
||||
|
||||
<LabeledList.Item
|
||||
label="Lifespan"
|
||||
tooltip={`The age at which the plant starts withering, in ${data.cycle_seconds} second long cycles. Improves quality of resulting food & drinks.`}
|
||||
tooltip={`The age at which the plant starts withering. Improves quality of resulting food & drinks.`}
|
||||
>
|
||||
<ProgressBar
|
||||
value={seed_data.lifespan / 100}
|
||||
ranges={{
|
||||
good: [0.7, Infinity],
|
||||
average: [0.3, 0.7],
|
||||
bad: [0, 0.3],
|
||||
}}
|
||||
>
|
||||
{seed_data.lifespan} / 100
|
||||
</ProgressBar>
|
||||
{formatPerSecond(seed_data.lifespan, cycle_seconds)}
|
||||
</LabeledList.Item>
|
||||
|
||||
<LabeledList.Item
|
||||
@@ -173,70 +230,298 @@ export function PlantAnalyzerSeed(props) {
|
||||
</ProgressBar>
|
||||
</LabeledList.Item>
|
||||
|
||||
<LabeledList.Item label="Tray weeds">
|
||||
{seed_data.weed_chance && seed_data.weed_rate
|
||||
? seed_data.weed_chance +
|
||||
'% chance to grow by ' +
|
||||
seed_data.weed_rate
|
||||
: 'No weed growth'}
|
||||
<LabeledList.Item label="Weeds">
|
||||
{`${seed_data.weed_chance}% chance to grow by
|
||||
${seed_data.weed_rate} every ${cycle_seconds} seconds`}
|
||||
</LabeledList.Item>
|
||||
{seed_data.unique_labels.map((label) => (
|
||||
<LabeledList.Item key={label.label} label={label.label}>
|
||||
{label.data}
|
||||
</LabeledList.Item>
|
||||
))}
|
||||
</LabeledList>
|
||||
<Collapsible title="Traits:" open color="brown" width="100%" mt={1}>
|
||||
<Stack vertical>
|
||||
{all_traits.map((trait) => {
|
||||
const traitInfo = getTraitInfo(trait, trait_db);
|
||||
return (
|
||||
<Stack.Item key={`${trait}_removable`} width="100%">
|
||||
<Button
|
||||
ellipsis
|
||||
fluid
|
||||
color={
|
||||
seed_data.core_traits.includes(trait)
|
||||
? 'transparent'
|
||||
: 'blue'
|
||||
}
|
||||
disabled={1}
|
||||
tooltip={traitInfo?.description}
|
||||
icon={traitInfo?.icon}
|
||||
>
|
||||
{traitInfo?.name || 'Unknown Trait'}
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
);
|
||||
})}
|
||||
</Stack>
|
||||
</Collapsible>
|
||||
{seed_data.unique_collapsibles.map((collapsible) => (
|
||||
<Collapsible
|
||||
key={collapsible.label}
|
||||
title={collapsible.label}
|
||||
color="brown"
|
||||
width="100%"
|
||||
mt={1}
|
||||
>
|
||||
<Stack vertical>
|
||||
{Object.entries(collapsible.data).map(
|
||||
([dataText, dataTooltip]) => (
|
||||
<Stack.Item key={dataText} width="100%">
|
||||
<Button
|
||||
ellipsis
|
||||
fluid
|
||||
color="transparent"
|
||||
disabled={1}
|
||||
tooltip={dataTooltip}
|
||||
>
|
||||
{dataText}
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
),
|
||||
)}
|
||||
</Stack>
|
||||
</Collapsible>
|
||||
))}
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
function SeedExtraData(props) {
|
||||
export function PlantAnalyzerSeedChems(props) {
|
||||
const { data } = useBackend<PlantAnalyzerData>();
|
||||
const { seed_data } = data;
|
||||
|
||||
return (
|
||||
<>
|
||||
{!!seed_data.graft_gene && (
|
||||
<TraitTooltip
|
||||
path={seed_data.graft_gene}
|
||||
trait_db={data.trait_db}
|
||||
grafting
|
||||
/>
|
||||
)}
|
||||
if (!seed_data) {
|
||||
// This shouldn't be rendered if seed data is null
|
||||
return null;
|
||||
}
|
||||
|
||||
{seed_data.removable_traits?.map((trait) => (
|
||||
<TraitTooltip key="" path={trait} trait_db={data.trait_db} removable />
|
||||
))}
|
||||
{seed_data.core_traits?.map((trait) => (
|
||||
<TraitTooltip key="" path={trait} trait_db={data.trait_db} />
|
||||
))}
|
||||
{!!seed_data.mutatelist.length && (
|
||||
<Tooltip content={`Mutates into: ${seed_data.mutatelist.join(', ')}`}>
|
||||
<Icon name="dna" m={0.5} />
|
||||
</Tooltip>
|
||||
)}
|
||||
{!!seed_data.juice_name && (
|
||||
<Tooltip content={`Juicing result: ${seed_data.juice_name}`}>
|
||||
<Icon name="glass-water" m={0.5} />
|
||||
</Tooltip>
|
||||
)}
|
||||
{!!seed_data.distill_reagent && (
|
||||
<Tooltip content={`Ferments into: ${seed_data.distill_reagent}`}>
|
||||
<Icon name="wine-bottle" m={0.5} />
|
||||
</Tooltip>
|
||||
)}
|
||||
{seed_data.reagents.length > 0 && (
|
||||
<Tooltip
|
||||
content={
|
||||
<ReagentTooltip
|
||||
reagents={seed_data.reagents}
|
||||
grind_results={seed_data.grind_results}
|
||||
potency={seed_data.potency}
|
||||
volume_mod={seed_data.volume_mod}
|
||||
volume_units={seed_data.volume_units}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Icon name="blender" m={0.5} />
|
||||
</Tooltip>
|
||||
)}
|
||||
</>
|
||||
const totalPercentage = seed_data.reagents.reduce(
|
||||
(sum, reagent) => sum + reagent.rate * 100,
|
||||
0,
|
||||
);
|
||||
|
||||
const totalVolume =
|
||||
seed_data.reagents.reduce(
|
||||
(sum, reagent) => sum + expectedReagentVolume(reagent, seed_data),
|
||||
0,
|
||||
) || 0;
|
||||
|
||||
return (
|
||||
<Section title={capitalizeFirst(`${seed_data.name} Genes`)}>
|
||||
<Stack>
|
||||
<Stack.Item width="100%">
|
||||
{seed_data.reagents.length === 0 ? (
|
||||
<NoticeBox color="green" align="center">
|
||||
No reagent genes
|
||||
</NoticeBox>
|
||||
) : (
|
||||
<Table>
|
||||
<Table.Row header>
|
||||
<Table.Cell>Reagent</Table.Cell>
|
||||
<Table.Cell>Percentage</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Tooltip
|
||||
content={
|
||||
'Assuming the plant does not exceed its maximum capacity, \
|
||||
this is what you can expect to obtain from consuming \
|
||||
or grinding the product of the seed.'
|
||||
}
|
||||
>
|
||||
<Box
|
||||
inline
|
||||
style={{
|
||||
borderBottom: '2px dotted rgba(255, 255, 255, 0.8)',
|
||||
}}
|
||||
>
|
||||
Expected Volume
|
||||
</Box>
|
||||
</Tooltip>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
{seed_data.reagents.map((reagent) => (
|
||||
<Table.Row key={reagent.name} className="candystripe">
|
||||
<Table.Cell py={0.2} pl={1}>
|
||||
{reagent.name}
|
||||
</Table.Cell>
|
||||
<Table.Cell>{reagent.rate * 100}%</Table.Cell>
|
||||
<Table.Cell>
|
||||
~{expectedReagentVolume(reagent, seed_data)}u
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
))}
|
||||
<Table.Row
|
||||
className="candystripe"
|
||||
style={{ borderTop: '2px dotted gray' }}
|
||||
>
|
||||
<Table.Cell py={1} pl={1}>
|
||||
Total
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{totalPercentage}%
|
||||
{totalPercentage > 100 && (
|
||||
<Blink>
|
||||
<Button
|
||||
icon="exclamation-triangle"
|
||||
ml={1}
|
||||
disabled={1}
|
||||
color="transparent"
|
||||
tooltip="Exceeds 100% - each reagent
|
||||
will be proportionally reduced in the product."
|
||||
/>
|
||||
</Blink>
|
||||
)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>~{totalVolume}u</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row
|
||||
className="candystripe"
|
||||
style={{ borderTop: '2px dotted gray' }}
|
||||
>
|
||||
<Table.Cell py={1} pl={1}>
|
||||
Cap
|
||||
</Table.Cell>
|
||||
<Table.Cell>100%</Table.Cell>
|
||||
<Table.Cell>
|
||||
~{seed_data.volume_mod * seed_data.volume_units}u
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
{seed_data.grind_results.length > 0 && (
|
||||
<Table.Row
|
||||
className="candystripe"
|
||||
style={{ borderTop: '2px dotted gray' }}
|
||||
>
|
||||
<Table.Cell py={0.5} pl={1} colSpan={2}>
|
||||
<i>Grinds nutriments into:</i>
|
||||
</Table.Cell>
|
||||
<Table.Cell>{seed_data.grind_results.join(', ')}</Table.Cell>
|
||||
</Table.Row>
|
||||
)}
|
||||
{seed_data.juice_name && (
|
||||
<Table.Row
|
||||
className="candystripe"
|
||||
style={{ borderTop: '2px dotted gray' }}
|
||||
>
|
||||
<Table.Cell py={0.5} pl={1} colSpan={2}>
|
||||
<i>Juices into:</i>
|
||||
</Table.Cell>
|
||||
<Table.Cell>{seed_data.juice_name}</Table.Cell>
|
||||
</Table.Row>
|
||||
)}
|
||||
{seed_data.distill_reagent && (
|
||||
<Table.Row
|
||||
className="candystripe"
|
||||
style={{ borderTop: '2px dotted gray' }}
|
||||
>
|
||||
<Table.Cell py={0.5} pl={1} colSpan={2}>
|
||||
<i>Distills into:</i>
|
||||
</Table.Cell>
|
||||
<Table.Cell>{seed_data.distill_reagent}</Table.Cell>
|
||||
</Table.Row>
|
||||
)}
|
||||
</Table>
|
||||
)}
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
export function PlantAnalyzerPlantChems(props) {
|
||||
const { data } = useBackend<PlantAnalyzerData>();
|
||||
const { seed_data, plant_data } = data;
|
||||
|
||||
if (!seed_data || !plant_data) {
|
||||
// This shouldn't be rendered if seed or plant data is null
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Section title={capitalizeFirst(`${seed_data.name} Contents`)}>
|
||||
<Stack>
|
||||
<Stack.Item width="100%">
|
||||
{plant_data.reagents.length === 0 ? (
|
||||
<NoticeBox color="green" align="center">
|
||||
No reagent genes
|
||||
</NoticeBox>
|
||||
) : (
|
||||
<Table>
|
||||
<Table.Row header>
|
||||
<Table.Cell colSpan={2}>Reagent</Table.Cell>
|
||||
<Table.Cell>Volume</Table.Cell>
|
||||
</Table.Row>
|
||||
{plant_data.reagents.map((reagent) => (
|
||||
<Table.Row key={reagent.name} className="candystripe">
|
||||
<Table.Cell py={0.2} pl={1} colSpan={2}>
|
||||
{reagent.name}
|
||||
</Table.Cell>
|
||||
<Table.Cell>{reagent.volume}</Table.Cell>
|
||||
</Table.Row>
|
||||
))}
|
||||
<Table.Row
|
||||
className="candystripe"
|
||||
style={{ borderTop: '2px dotted gray' }}
|
||||
>
|
||||
<Table.Cell py={1} pl={1} colSpan={2}>
|
||||
Total
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{plant_data.reagents.reduce(
|
||||
(sum, reagent) => sum + reagent.volume,
|
||||
0,
|
||||
)}
|
||||
u
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table>
|
||||
)}
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
function expectedReagentVolume(
|
||||
reagent: ReagentData,
|
||||
seed_data: SeedData,
|
||||
): number {
|
||||
const baseVolume = seed_data.volume_units * seed_data.volume_mod;
|
||||
return Math.round(reagent.rate * baseVolume * (seed_data.potency / 100)) || 0;
|
||||
}
|
||||
|
||||
function formatPerSecond(
|
||||
value: number,
|
||||
cycle_seconds: number,
|
||||
simplify: boolean = true,
|
||||
) {
|
||||
if (!simplify) {
|
||||
return `${value * cycle_seconds} second${value * cycle_seconds > 1 ? 's' : ''}`;
|
||||
}
|
||||
const seconds = Math.round(value * cycle_seconds);
|
||||
if (seconds < 60) {
|
||||
return `${seconds} second${seconds > 1 ? 's' : ''}`;
|
||||
}
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
const remainingSeconds = seconds % 60;
|
||||
return `${minutes} minute${minutes > 1 ? 's' : ''}${
|
||||
remainingSeconds > 0
|
||||
? `, ${remainingSeconds} second${remainingSeconds > 1 ? 's' : ''}`
|
||||
: ''
|
||||
}`;
|
||||
}
|
||||
|
||||
function getTraitInfo(trait: string, trait_db: PlantAnalyzerData['trait_db']) {
|
||||
const traitData = trait_db.find((t) => t.path === trait);
|
||||
return traitData;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
DmIcon,
|
||||
Icon,
|
||||
LabeledList,
|
||||
NoticeBox,
|
||||
ProgressBar,
|
||||
Section,
|
||||
Stack,
|
||||
Table,
|
||||
Tooltip,
|
||||
} from 'tgui-core/components';
|
||||
import { capitalizeFirst } from 'tgui-core/string';
|
||||
|
||||
@@ -14,42 +15,70 @@ import { useBackend } from '../../backend';
|
||||
import { Fallback } from './Fallback';
|
||||
import type { PlantAnalyzerData } from './types';
|
||||
|
||||
export function PlantAnalyzerTray(props) {
|
||||
export function PlantAnalyzerTrayStats(props) {
|
||||
const { data } = useBackend<PlantAnalyzerData>();
|
||||
const { tray_data } = data;
|
||||
|
||||
if (!tray_data) {
|
||||
// This shouldn't be rendered if tray_data is null
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Section
|
||||
title={capitalizeFirst(tray_data.name)}
|
||||
buttons={
|
||||
<>
|
||||
{!!tray_data.self_sustaining && (
|
||||
<Tooltip content="Self sustaining active, providing light, reclaiming water and reducing weed and pest levels.">
|
||||
<Icon name="hand-holding-droplet" m={0.5} />
|
||||
</Tooltip>
|
||||
)}
|
||||
{!!tray_data.being_pollinated && (
|
||||
<Tooltip content="Cross pollinating nearby plants, potentially sharing plant reagents.">
|
||||
<Icon name="wind" m={0.5} />
|
||||
</Tooltip>
|
||||
)}
|
||||
{tray_data.yield_mod > 1 && (
|
||||
<Tooltip content="Pollinated by bees, doubling the yield.">
|
||||
<Icon name="sun" m={0.5} />
|
||||
</Tooltip>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Section title={capitalizeFirst(tray_data.name)}>
|
||||
<Stack>
|
||||
<Stack.Item mx={2}>
|
||||
<DmIcon
|
||||
fallback={Fallback}
|
||||
icon={tray_data.icon}
|
||||
icon_state={tray_data.icon_state}
|
||||
height="64px"
|
||||
width="64px"
|
||||
/>
|
||||
<Stack vertical align="center" width="100px">
|
||||
<Stack.Item>
|
||||
<DmIcon
|
||||
fallback={Fallback}
|
||||
icon={tray_data.icon}
|
||||
icon_state={tray_data.icon_state}
|
||||
height="64px"
|
||||
width="64px"
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Stack>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
icon="hand-holding-droplet"
|
||||
color={tray_data.self_sustaining ? 'yellow' : 'transparent'}
|
||||
tooltip={
|
||||
tray_data.self_sustaining
|
||||
? 'Autogrow active - providing light, reclaiming water and reducing weed and pest levels.'
|
||||
: 'Autogrow inactive'
|
||||
}
|
||||
disabled={1}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
icon="wind"
|
||||
color={tray_data.being_pollinated ? 'teal' : 'transparent'}
|
||||
tooltip={
|
||||
tray_data.being_pollinated
|
||||
? 'Cross pollinating nearby plants - potentially sharing plant reagents.'
|
||||
: 'Not cross pollinating'
|
||||
}
|
||||
disabled={1}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
icon="sun"
|
||||
color={tray_data.yield_mod > 1 ? 'olive' : 'transparent'}
|
||||
tooltip={
|
||||
tray_data.yield_mod > 1
|
||||
? 'Pollinated by bees - doubling yield.'
|
||||
: 'No yield modifier'
|
||||
}
|
||||
disabled={1}
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
<Stack.Item width="100%">
|
||||
<LabeledList>
|
||||
@@ -73,15 +102,32 @@ export function PlantAnalyzerTray(props) {
|
||||
label="Nutrients"
|
||||
tooltip="The plant starts withering without nutrients, unless it is a weed. Nutrients may affect plant and tray stats."
|
||||
>
|
||||
<Tooltip
|
||||
content={
|
||||
tray_data.reagents.length > 0 ? (
|
||||
<ReagentList reagents={tray_data.reagents} />
|
||||
) : (
|
||||
'No reagents detected.'
|
||||
)
|
||||
}
|
||||
>
|
||||
{tray_data.reagents.length > 0 ? (
|
||||
<Box>
|
||||
<ProgressBar
|
||||
width="234px" // why won't you scale??
|
||||
position="absolute"
|
||||
value={0}
|
||||
color="transparent"
|
||||
style={{
|
||||
zIndex: 3,
|
||||
border: `1px solid ${nutriToColor(tray_data.nutri, tray_data.nutri_max)}`,
|
||||
}}
|
||||
>
|
||||
{tray_data.nutri} / {tray_data.nutri_max}
|
||||
</ProgressBar>
|
||||
{tray_data.reagents.map((reagent, i) => (
|
||||
<ProgressBar
|
||||
key={`${i}-${reagent.name}`}
|
||||
mb={-0.5}
|
||||
width={`${(reagent.volume / tray_data.nutri_max) * 234}px`}
|
||||
value={1}
|
||||
color={reagent.color}
|
||||
empty
|
||||
/>
|
||||
))}
|
||||
</Box>
|
||||
) : (
|
||||
<ProgressBar
|
||||
value={tray_data.nutri / tray_data.nutri_max}
|
||||
ranges={{
|
||||
@@ -92,7 +138,7 @@ export function PlantAnalyzerTray(props) {
|
||||
>
|
||||
{tray_data.nutri} / {tray_data.nutri_max}
|
||||
</ProgressBar>
|
||||
</Tooltip>
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
|
||||
<LabeledList.Item
|
||||
@@ -169,22 +215,43 @@ export function PlantAnalyzerTray(props) {
|
||||
);
|
||||
}
|
||||
|
||||
function ReagentList(props) {
|
||||
const { reagents = [] } = props;
|
||||
export function PlantAnalyzerTrayChems(props) {
|
||||
const { data } = useBackend<PlantAnalyzerData>();
|
||||
const { tray_data } = data;
|
||||
|
||||
if (!tray_data) {
|
||||
// This shouldn't be rendered if tray_data is null
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Table>
|
||||
<Table.Row header>
|
||||
<Table.Cell colSpan={2}>Reagents:</Table.Cell>
|
||||
</Table.Row>
|
||||
{reagents.map((reagent, i) => (
|
||||
<Table.Row key={i}>
|
||||
<Table.Cell>{reagent.name}</Table.Cell>
|
||||
<Table.Cell py={0.5} pl={2} textAlign="right">
|
||||
{reagent.volume}u
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
))}
|
||||
</Table>
|
||||
<Section title={capitalizeFirst(`${tray_data.name} Nutrients`)}>
|
||||
{tray_data.reagents.length === 0 ? (
|
||||
<NoticeBox color="red" align="center">
|
||||
No reagents detected
|
||||
</NoticeBox>
|
||||
) : (
|
||||
<Table>
|
||||
<Table.Row header>
|
||||
<Table.Cell>Reagent</Table.Cell>
|
||||
<Table.Cell>Volume</Table.Cell>
|
||||
</Table.Row>
|
||||
{tray_data.reagents.map((reagent, i) => (
|
||||
<Table.Row key={i} className="candystripe">
|
||||
<Table.Cell py={0.5} pl={1}>
|
||||
{reagent.name}
|
||||
</Table.Cell>
|
||||
<Table.Cell>{reagent.volume}u</Table.Cell>
|
||||
</Table.Row>
|
||||
))}
|
||||
</Table>
|
||||
)}
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
function nutriToColor(nutri: number, maxNutri: number) {
|
||||
if (nutri < maxNutri * 0.3) return 'red';
|
||||
if (nutri < maxNutri * 0.7) return 'yellow';
|
||||
return 'green';
|
||||
}
|
||||
|
||||
@@ -1,20 +1,64 @@
|
||||
import { Button, Section, Stack } from 'tgui-core/components';
|
||||
import { useBackend } from '../../backend';
|
||||
import { Window } from '../../layouts';
|
||||
import { PlantAnalyzerGraft } from './Graft';
|
||||
import { PlantAnalyzerSeed } from './Seed';
|
||||
import { PlantAnalyzerTray } from './Tray';
|
||||
import {
|
||||
PlantAnalyzerPlantChems,
|
||||
PlantAnalyzerSeedChems,
|
||||
PlantAnalyzerSeedStats,
|
||||
} from './Seed';
|
||||
import { PlantAnalyzerTrayChems, PlantAnalyzerTrayStats } from './Tray';
|
||||
import type { PlantAnalyzerData } from './types';
|
||||
import { PlantAnalyzerTabs } from './types';
|
||||
|
||||
export function PlantAnalyzer(props) {
|
||||
const { data } = useBackend<PlantAnalyzerData>();
|
||||
const { graft_data, seed_data, tray_data } = data;
|
||||
const { act, data } = useBackend<PlantAnalyzerData>();
|
||||
const { graft_data, seed_data, tray_data, plant_data, active_tab } = data;
|
||||
|
||||
return (
|
||||
<Window width={480} height={520}>
|
||||
<Window width={475} height={625}>
|
||||
<Window.Content scrollable>
|
||||
{graft_data && <PlantAnalyzerGraft />}
|
||||
{seed_data && <PlantAnalyzerSeed />}
|
||||
{tray_data && <PlantAnalyzerTray />}
|
||||
<Section>
|
||||
<Stack>
|
||||
<Stack.Item grow>
|
||||
<Button
|
||||
fluid
|
||||
align="center"
|
||||
onClick={() => act('setTab', { tab: PlantAnalyzerTabs.STATS })}
|
||||
selected={
|
||||
active_tab === PlantAnalyzerTabs.STATS || !!graft_data
|
||||
}
|
||||
>
|
||||
Stats
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Button
|
||||
align="center"
|
||||
fluid
|
||||
onClick={() => act('setTab', { tab: PlantAnalyzerTabs.CHEM })}
|
||||
selected={active_tab === PlantAnalyzerTabs.CHEM && !graft_data}
|
||||
disabled={!!graft_data}
|
||||
>
|
||||
Chemicals
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Section>
|
||||
{active_tab === PlantAnalyzerTabs.STATS || graft_data ? (
|
||||
<>
|
||||
{graft_data && <PlantAnalyzerGraft />}
|
||||
{tray_data && <PlantAnalyzerTrayStats />}
|
||||
{seed_data && <PlantAnalyzerSeedStats />}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{/* grafts don't have any chems */}
|
||||
{tray_data && <PlantAnalyzerTrayChems />}
|
||||
{seed_data && <PlantAnalyzerSeedChems />}
|
||||
{plant_data && <PlantAnalyzerPlantChems />}
|
||||
</>
|
||||
)}
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
|
||||
@@ -1,36 +1,46 @@
|
||||
import type { BooleanLike } from 'tgui-core/react';
|
||||
|
||||
export enum PlantAnalyzerTabs {
|
||||
STATS = 1,
|
||||
CHEM = 2,
|
||||
}
|
||||
|
||||
export type PlantAnalyzerData = {
|
||||
graft_data: GraftData;
|
||||
seed_data: SeedData;
|
||||
tray_data: TrayData;
|
||||
graft_data: GraftData | null;
|
||||
seed_data: SeedData | null;
|
||||
plant_data: PlantData | null;
|
||||
tray_data: TrayData | null;
|
||||
// Static
|
||||
cycle_seconds: number;
|
||||
trait_db: TraitData[];
|
||||
active_tab: PlantAnalyzerTabs;
|
||||
};
|
||||
|
||||
type TrayData = {
|
||||
being_pollinated: boolean;
|
||||
icon_state: string;
|
||||
being_pollinated: BooleanLike;
|
||||
icon: string;
|
||||
icon_state: string;
|
||||
is_dead: BooleanLike;
|
||||
light_level: number;
|
||||
name: string;
|
||||
nutri_max: number;
|
||||
nutri: number;
|
||||
pests_max: number;
|
||||
nutri_max: number;
|
||||
pests: number;
|
||||
pests_max: number;
|
||||
plant_age: number;
|
||||
plant_health: number;
|
||||
reagents: ReagentVolume[];
|
||||
self_sustaining: boolean;
|
||||
toxins_max: number;
|
||||
self_sustaining: BooleanLike;
|
||||
toxins: number;
|
||||
water_max: number;
|
||||
toxins_max: number;
|
||||
water: number;
|
||||
weeds_max: number;
|
||||
water_max: number;
|
||||
weeds: number;
|
||||
weeds_max: number;
|
||||
yield_mod: number;
|
||||
};
|
||||
|
||||
type SeedData = {
|
||||
export type SeedData = {
|
||||
core_traits: string[];
|
||||
distill_reagent: string;
|
||||
endurance: number;
|
||||
@@ -56,6 +66,23 @@ type SeedData = {
|
||||
weed_chance: number;
|
||||
weed_rate: number;
|
||||
yield: number;
|
||||
unique_labels: UniqueSeedLabel[];
|
||||
unique_collapsibles: UniqueSeedCollapsible[];
|
||||
};
|
||||
|
||||
type UniqueSeedLabel = {
|
||||
label: string;
|
||||
data: string;
|
||||
};
|
||||
|
||||
type UniqueSeedCollapsible = {
|
||||
label: string;
|
||||
// key is shown text, value is tooltip text
|
||||
data: Record<string, string>;
|
||||
};
|
||||
|
||||
export type PlantData = {
|
||||
reagents: ReagentVolume[];
|
||||
};
|
||||
|
||||
type GraftData = {
|
||||
@@ -73,10 +100,11 @@ type GraftData = {
|
||||
|
||||
type ReagentVolume = {
|
||||
name: string;
|
||||
volume: string;
|
||||
volume: number;
|
||||
color: string;
|
||||
};
|
||||
|
||||
type ReagentData = {
|
||||
export type ReagentData = {
|
||||
name: string;
|
||||
rate: number;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user