Biogenerator tweaks, leather makes more belts and clothing (#71175)

## About The Pull Request

### Revamped the biogenerator UI:


https://user-images.githubusercontent.com/3625094/200973283-b703f21b-c747-493e-98d9-043eef86d410.mp4

### Changed biogenerator icon to use layers and see the biomass level:


https://user-images.githubusercontent.com/3625094/201396065-caeaa412-6676-46f6-875e-efa2dca34985.mp4

### Biogenerator rebalance:

- Now you don't need the beaker to print solid products.
- Biogenerator now accepts all food, not just plants.
- Biogenerator now treats all nutriment subtypes as nutriments, so
vitamins and proteins also turn into biomass.
- Biomass now has the same units as other reagents (you get 5 biomass
from 5 nutrient with tier 1 parts).
- Doubled the cost of all items and reagents. (biomass generation
reduced by 10 and prices - by 5)
- Chemicals output amounts are now in units and you can select how much
you want to output exactly. It will not let you specify more than the
size of container or above 50 units with one button click.
- Reduced the amount of stored items and introduced a limit to the
biomass, both tied to the matter bin tier.

### Recipes changes:

Made biogenerator more dumb by moving the clothing out from the
biogenerator designs, and extending leather recipes instead.

The biogenerator is a grinder/recycler style machine so it doesn't make
sense that it outputs clothing.
Also you need to make leather to craft the toolbelt, while you can't do
the same to craft job-specific belts.
Now you can print leather in biogenerator and craft the leather clothing
by using the leather in-hand.
And the rice hat is now crafted from bamboo, instead of biogenerator.

Also added paper to the biogenerator recipes as it makes stuff from
cellulose and barely anyone knows that you can craft paper from 1 log
and 50 water. And paper is needed in large quantities to craft some
items, like paper frames.

And it doesn't output a pack of rolling paper. It's dumb now. It prints
the rolling paper sheets instead.

## Why It's Good For The Game

Biogenerator had terrible UX and backend logic. I didn't improve much on
BE though, but now it should be less frustrating to use.

Also I hate how biogenerator is superior to all other means of obtaining
its products. It doesn't make sense to grow and grind wheat, for
instance, when you can just throw shit into biogenerator and get the
flour fast. And the costs are ridiculous - you can get a couple of
bottles of fertilizers just from one medium potato.

It honestly begs for more nerfing, at least to make the nutriment -
chemicals exchange rate 1:1.

The reason for the biomass cap is because people use it as a sink for
veggies and generate infinite biomass. Maybe the limit will make them
care more about the part upgrade and offload some of the veggies to the
fridge for the Cook.

Also it was weird that biogenerator could tailor some things, while
others have to be crafted in-hand. Now you can print leather and craft
all types of belts and leather clothing.

## Changelog
🆑
refactor: biogenerator UI revamped
qol: biogenerator no longer requires beaker for materials, monkey cubes
and nori
balance: biogenerator accepts all food, not just plants
balance: biogenerator treats all nutriment subtypes as nutriments
(vitamins, protein, etc.)
balance: biogenerator product prices doubled
balance: biogenerator biomass storage is limited depending on the level
of matter bins
balance: cowboy boots recipe moved from crafting to leather recipes
balance: leather clothing & belt recipes moved from biogenerator to
leather recipes
balance: rice hat recipe moved from biogenerator to bamboo recipes
balance: biogenerator now outputs rolling paper sheets instead of a pack
add: biogenerator can now print paper
imageadd: biogenerator icons now use overlays, have emissive layer and
indicate the biomass volume
/🆑
This commit is contained in:
Andrew
2022-11-21 20:57:13 -08:00
committed by GitHub
parent 440a85177d
commit 590847bdf7
9 changed files with 523 additions and 515 deletions
@@ -183,9 +183,9 @@
#define RND_CATEGORY_LIMBS_OTHER "Other Limbs"
/// Biogenerator Categories
#define RND_CATEGORY_FOOD "Food"
#define RND_CATEGORY_BOTANY_CHEMICALS "Botany Chemicals"
#define RND_CATEGORY_ORGANIC_MATERIALS "Organic Materials"
#define RND_CATEGORY_BIO_FOOD "Food"
#define RND_CATEGORY_BIO_CHEMICALS "Chemicals"
#define RND_CATEGORY_BIO_MATERIALS "Materials"
// Meta categories
#define RND_CATEGORY_INITIAL "initial"
@@ -130,13 +130,6 @@
reqs = list(/obj/item/bedsheet = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/cowboyboots
name = "Cowboy Boots"
result = /obj/item/clothing/shoes/cowboy
reqs = list(/obj/item/stack/sheet/leather = 2)
time = 4.5 SECONDS
category = CAT_CLOTHING
/datum/crafting_recipe/lizardboots
name = "Lizard Skin Boots"
result = /obj/effect/spawner/random/clothing/lizardboots
@@ -188,22 +188,30 @@ GLOBAL_LIST_INIT(xeno_recipes, list ( \
GLOBAL_LIST_INIT(leather_recipes, list ( \
new/datum/stack_recipe("wallet", /obj/item/storage/wallet, 1), \
new/datum/stack_recipe("muzzle", /obj/item/clothing/mask/muzzle, 2), \
new/datum/stack_recipe("botany gloves", /obj/item/clothing/gloves/botanic_leather, 3), \
new/datum/stack_recipe("toolbelt", /obj/item/storage/belt/utility, 4), \
new/datum/stack_recipe("leather satchel", /obj/item/storage/backpack/satchel/leather, 5), \
new/datum/stack_recipe("bandolier", /obj/item/storage/belt/bandolier, 5), \
new/datum/stack_recipe("leather jacket", /obj/item/clothing/suit/jacket/leather, 7), \
new/datum/stack_recipe("leather shoes", /obj/item/clothing/shoes/laceup, 2), \
new/datum/stack_recipe("biker jacket", /obj/item/clothing/suit/jacket/leather/biker, 7), \
new/datum/stack_recipe("saddle", /obj/item/saddle, 5), \
new/datum/stack_recipe("leather shoes", /obj/item/clothing/shoes/laceup, 2), \
new/datum/stack_recipe("cowboy boots", /obj/item/clothing/shoes/cowboy, 2), \
new/datum/stack_recipe("botany gloves", /obj/item/clothing/gloves/botanic_leather, 3), \
new/datum/stack_recipe("leather satchel", /obj/item/storage/backpack/satchel/leather, 5), \
new/datum/stack_recipe("sheriff vest", /obj/item/clothing/accessory/vest_sheriff, 4), \
new/datum/stack_recipe("leather jacket", /obj/item/clothing/suit/jacket/leather, 7), \
new/datum/stack_recipe("biker jacket", /obj/item/clothing/suit/jacket/leather/biker, 7), \
new/datum/stack_recipe_list("belts", list( \
new/datum/stack_recipe("tool belt", /obj/item/storage/belt/utility, 4), \
new/datum/stack_recipe("botanical belt", /obj/item/storage/belt/plant, 2), \
new/datum/stack_recipe("janitorial belt", /obj/item/storage/belt/janitor, 2), \
new/datum/stack_recipe("medical belt", /obj/item/storage/belt/medical, 2), \
new/datum/stack_recipe("security belt", /obj/item/storage/belt/security, 2), \
new/datum/stack_recipe("shoulder holster", /obj/item/storage/belt/holster, 3), \
new/datum/stack_recipe("bandolier", /obj/item/storage/belt/bandolier, 5), \
)),
new/datum/stack_recipe_list("cowboy hats", list( \
new/datum/stack_recipe("sheriff hat", /obj/item/clothing/head/cowboy/brown, 2), \
new/datum/stack_recipe("desperado hat", /obj/item/clothing/head/cowboy/black, 2), \
new/datum/stack_recipe("ten-gallon hat", /obj/item/clothing/head/cowboy/white, 2), \
new/datum/stack_recipe("deputy hat", /obj/item/clothing/head/cowboy/red, 2), \
new/datum/stack_recipe("drifter hat", /obj/item/clothing/head/cowboy/grey, 2), \
)),
)),
))
/obj/item/stack/sheet/leather/get_main_recipes()
@@ -65,46 +65,46 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
)),
null, \
new/datum/stack_recipe("rack parts", /obj/item/rack_parts), \
new/datum/stack_recipe("closet", /obj/structure/closet, 2, time = 15, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("closet", /obj/structure/closet, 2, time = 1.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
null, \
new/datum/stack_recipe("unfinished canister frame", /obj/structure/canister_frame/machine/unfinished_canister_frame, 5, time = 8, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("unfinished canister frame", /obj/structure/canister_frame/machine/unfinished_canister_frame, 5, time = 0.8 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
null, \
new/datum/stack_recipe("floor tile", /obj/item/stack/tile/iron/base, 1, 4, 20), \
new/datum/stack_recipe("iron rod", /obj/item/stack/rods, 1, 2, 60), \
null, \
new/datum/stack_recipe("wall girders (anchored)", /obj/structure/girder, 2, time = 40, one_per_turf = TRUE, on_solid_ground = TRUE, trait_booster = TRAIT_QUICK_BUILD, trait_modifier = 0.75), \
new/datum/stack_recipe("wall girders (anchored)", /obj/structure/girder, 2, time = 4 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, trait_booster = TRAIT_QUICK_BUILD, trait_modifier = 0.75), \
null, \
new/datum/stack_recipe("tram wall girders (anchored)", /obj/structure/girder/tram, 2, time = 40, one_per_turf = TRUE, on_solid_ground = FALSE, on_tram = TRUE, trait_booster = TRAIT_QUICK_BUILD, trait_modifier = 0.75), \
new/datum/stack_recipe("tram wall girders (anchored)", /obj/structure/girder/tram, 2, time = 4 SECONDS, one_per_turf = TRUE, on_solid_ground = FALSE, on_tram = TRUE, trait_booster = TRAIT_QUICK_BUILD, trait_modifier = 0.75), \
null, \
new/datum/stack_recipe("computer frame", /obj/structure/frame/computer, 5, time = 25, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("modular console", /obj/machinery/modular_computer/console, 10, time = 25, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("machine frame", /obj/structure/frame/machine, 5, time = 25, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("computer frame", /obj/structure/frame/computer, 5, time = 2.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("modular console", /obj/machinery/modular_computer/console, 10, time = 2.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("machine frame", /obj/structure/frame/machine, 5, time = 2.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
null, \
new /datum/stack_recipe_list("airlock assemblies", list( \
new /datum/stack_recipe("standard airlock assembly", /obj/structure/door_assembly, 4, time = 50, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("public airlock assembly", /obj/structure/door_assembly/door_assembly_public, 4, time = 50, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("command airlock assembly", /obj/structure/door_assembly/door_assembly_com, 4, time = 50, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("security airlock assembly", /obj/structure/door_assembly/door_assembly_sec, 4, time = 50, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("engineering airlock assembly", /obj/structure/door_assembly/door_assembly_eng, 4, time = 50, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("mining airlock assembly", /obj/structure/door_assembly/door_assembly_min, 4, time = 50, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("atmospherics airlock assembly", /obj/structure/door_assembly/door_assembly_atmo, 4, time = 50, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("research airlock assembly", /obj/structure/door_assembly/door_assembly_research, 4, time = 50, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("freezer airlock assembly", /obj/structure/door_assembly/door_assembly_fre, 4, time = 50, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("science airlock assembly", /obj/structure/door_assembly/door_assembly_science, 4, time = 50, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("medical airlock assembly", /obj/structure/door_assembly/door_assembly_med, 4, time = 50, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("hydroponics airlock assembly", /obj/structure/door_assembly/door_assembly_hydro, 4, time = 50, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("virology airlock assembly", /obj/structure/door_assembly/door_assembly_viro, 4, time = 50, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("maintenance airlock assembly", /obj/structure/door_assembly/door_assembly_mai, 4, time = 50, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("external airlock assembly", /obj/structure/door_assembly/door_assembly_ext, 4, time = 50, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("external maintenance airlock assembly", /obj/structure/door_assembly/door_assembly_extmai, 4, time = 50, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("airtight hatch assembly", /obj/structure/door_assembly/door_assembly_hatch, 4, time = 50, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("maintenance hatch assembly", /obj/structure/door_assembly/door_assembly_mhatch, 4, time = 50, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("standard airlock assembly", /obj/structure/door_assembly, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("public airlock assembly", /obj/structure/door_assembly/door_assembly_public, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("command airlock assembly", /obj/structure/door_assembly/door_assembly_com, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("security airlock assembly", /obj/structure/door_assembly/door_assembly_sec, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("engineering airlock assembly", /obj/structure/door_assembly/door_assembly_eng, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("mining airlock assembly", /obj/structure/door_assembly/door_assembly_min, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("atmospherics airlock assembly", /obj/structure/door_assembly/door_assembly_atmo, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("research airlock assembly", /obj/structure/door_assembly/door_assembly_research, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("freezer airlock assembly", /obj/structure/door_assembly/door_assembly_fre, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("science airlock assembly", /obj/structure/door_assembly/door_assembly_science, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("medical airlock assembly", /obj/structure/door_assembly/door_assembly_med, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("hydroponics airlock assembly", /obj/structure/door_assembly/door_assembly_hydro, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("virology airlock assembly", /obj/structure/door_assembly/door_assembly_viro, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("maintenance airlock assembly", /obj/structure/door_assembly/door_assembly_mai, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("external airlock assembly", /obj/structure/door_assembly/door_assembly_ext, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("external maintenance airlock assembly", /obj/structure/door_assembly/door_assembly_extmai, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("airtight hatch assembly", /obj/structure/door_assembly/door_assembly_hatch, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1), \
new /datum/stack_recipe("maintenance hatch assembly", /obj/structure/door_assembly/door_assembly_mhatch, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1), \
)), \
null, \
new/datum/stack_recipe("firelock frame", /obj/structure/firelock_frame, 3, time = 50, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("turret frame", /obj/machinery/porta_turret_construct, 5, time = 25, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("meatspike frame", /obj/structure/kitchenspike_frame, 5, time = 25, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("reflector frame", /obj/structure/reflector, 5, time = 25, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("firelock frame", /obj/structure/firelock_frame, 3, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("turret frame", /obj/machinery/porta_turret_construct, 5, time = 2.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("meatspike frame", /obj/structure/kitchenspike_frame, 5, time = 2.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("reflector frame", /obj/structure/reflector, 5, time = 2.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
null, \
new/datum/stack_recipe("grenade casing", /obj/item/grenade/chem_grenade), \
new/datum/stack_recipe("light fixture frame", /obj/item/wallframe/light_fixture, 2), \
@@ -120,8 +120,8 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
new/datum/stack_recipe("filing cabinet", /obj/structure/filingcabinet, 2, time = 10 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("desk bell", /obj/structure/desk_bell, 2, time = 3 SECONDS), \
new/datum/stack_recipe("floodlight frame", /obj/structure/floodlight_frame, 5, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("voting box", /obj/structure/votebox, 15, time = 50), \
new/datum/stack_recipe("pestle", /obj/item/pestle, 1, time = 50), \
new/datum/stack_recipe("voting box", /obj/structure/votebox, 15, time = 5 SECONDS), \
new/datum/stack_recipe("pestle", /obj/item/pestle, 1, time = 5 SECONDS), \
new/datum/stack_recipe("hygienebot assembly", /obj/item/bot_assembly/hygienebot, 2, time = 5 SECONDS), \
new/datum/stack_recipe("shower frame", /obj/structure/showerframe, 2, time= 2 SECONDS)
))
@@ -240,13 +240,13 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
* Plasteel
*/
GLOBAL_LIST_INIT(plasteel_recipes, list ( \
new/datum/stack_recipe("AI core", /obj/structure/ai_core, 4, time = 50, one_per_turf = TRUE),
new/datum/stack_recipe("bomb assembly", /obj/machinery/syndicatebomb/empty, 10, time = 50),
new/datum/stack_recipe("AI core", /obj/structure/ai_core, 4, time = 5 SECONDS, one_per_turf = TRUE),
new/datum/stack_recipe("bomb assembly", /obj/machinery/syndicatebomb/empty, 10, time = 5 SECONDS),
new/datum/stack_recipe("Large Gas Tank", /obj/structure/tank_frame, 4, time=1 SECONDS, one_per_turf=TRUE),
null,
new /datum/stack_recipe_list("airlock assemblies", list( \
new/datum/stack_recipe("high security airlock assembly", /obj/structure/door_assembly/door_assembly_highsecurity, 4, time = 50, one_per_turf = 1, on_solid_ground = 1),
new/datum/stack_recipe("vault door assembly", /obj/structure/door_assembly/door_assembly_vault, 6, time = 50, one_per_turf = 1, on_solid_ground = 1),
new/datum/stack_recipe("high security airlock assembly", /obj/structure/door_assembly/door_assembly_highsecurity, 4, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1),
new/datum/stack_recipe("vault door assembly", /obj/structure/door_assembly/door_assembly_vault, 6, time = 5 SECONDS, one_per_turf = 1, on_solid_ground = 1),
)), \
))
@@ -285,36 +285,36 @@ GLOBAL_LIST_INIT(plasteel_recipes, list ( \
GLOBAL_LIST_INIT(wood_recipes, list ( \
new/datum/stack_recipe("wooden sandals", /obj/item/clothing/shoes/sandal, 1), \
new/datum/stack_recipe("wood floor tile", /obj/item/stack/tile/wood, 1, 4, 20), \
new/datum/stack_recipe("wood table frame", /obj/structure/table_frame/wood, 2, time = 10), \
new/datum/stack_recipe("rolling pin", /obj/item/kitchen/rollingpin, 2, time = 30), \
new/datum/stack_recipe("wooden chair", /obj/structure/chair/wood/, 3, time = 10, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("winged wooden chair", /obj/structure/chair/wood/wings, 3, time = 10, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("wooden barricade", /obj/structure/barricade/wooden, 5, time = 50, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("wooden door", /obj/structure/mineral_door/wood, 10, time = 20, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("wood table frame", /obj/structure/table_frame/wood, 2, time = 1 SECONDS), \
new/datum/stack_recipe("rolling pin", /obj/item/kitchen/rollingpin, 2, time = 3 SECONDS), \
new/datum/stack_recipe("wooden chair", /obj/structure/chair/wood/, 3, time = 1 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("winged wooden chair", /obj/structure/chair/wood/wings, 3, time = 1 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("wooden barricade", /obj/structure/barricade/wooden, 5, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("wooden door", /obj/structure/mineral_door/wood, 10, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("wooden stairs frame", /obj/structure/stairs_frame/wood, 10, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("coffin", /obj/structure/closet/crate/coffin, 5, time = 15, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("book case", /obj/structure/bookcase, 4, time = 15, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("drying rack", /obj/machinery/smartfridge/drying_rack, 10, time = 15, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("wooden barrel", /obj/structure/fermenting_barrel, 8, time = 50, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("dog bed", /obj/structure/bed/dogbed, 10, time = 10, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("dresser", /obj/structure/dresser, 10, time = 15, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("picture frame", /obj/item/wallframe/picture, 1, time = 10),\
new/datum/stack_recipe("painting frame", /obj/item/wallframe/painting, 1, time = 10),\
new/datum/stack_recipe("coffin", /obj/structure/closet/crate/coffin, 5, time = 1.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("book case", /obj/structure/bookcase, 4, time = 1.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("drying rack", /obj/machinery/smartfridge/drying_rack, 10, time = 1.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("wooden barrel", /obj/structure/fermenting_barrel, 8, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("dog bed", /obj/structure/bed/dogbed, 10, time = 1 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("dresser", /obj/structure/dresser, 10, time = 1.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("picture frame", /obj/item/wallframe/picture, 1, time = 1 SECONDS),\
new/datum/stack_recipe("painting frame", /obj/item/wallframe/painting, 1, time = 1 SECONDS),\
new/datum/stack_recipe("display case chassis", /obj/structure/displaycase_chassis, 5, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("wooden buckler", /obj/item/shield/riot/buckler, 20, time = 40), \
new/datum/stack_recipe("apiary", /obj/structure/beebox, 40, time = 50),\
new/datum/stack_recipe("wooden buckler", /obj/item/shield/riot/buckler, 20, time = 4 SECONDS), \
new/datum/stack_recipe("apiary", /obj/structure/beebox, 40, time = 5 SECONDS),\
new/datum/stack_recipe("tiki mask", /obj/item/clothing/mask/gas/tiki_mask, 2), \
new/datum/stack_recipe("honey frame", /obj/item/honey_frame, 5, time = 10),\
new/datum/stack_recipe("wooden bucket", /obj/item/reagent_containers/cup/bucket/wooden, 3, time = 10),\
new/datum/stack_recipe("rake", /obj/item/cultivator/rake, 5, time = 10),\
new/datum/stack_recipe("ore box", /obj/structure/ore_box, 4, time = 50, one_per_turf = TRUE, on_solid_ground = TRUE),\
new/datum/stack_recipe("wooden crate", /obj/structure/closet/crate/wooden, 6, time = 50, one_per_turf = TRUE, on_solid_ground = TRUE),\
new/datum/stack_recipe("baseball bat", /obj/item/melee/baseball_bat, 5, time = 15),\
new/datum/stack_recipe("loom", /obj/structure/loom, 10, time = 15, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("honey frame", /obj/item/honey_frame, 5, time = 1 SECONDS),\
new/datum/stack_recipe("wooden bucket", /obj/item/reagent_containers/cup/bucket/wooden, 3, time = 1 SECONDS),\
new/datum/stack_recipe("rake", /obj/item/cultivator/rake, 5, time = 1 SECONDS),\
new/datum/stack_recipe("ore box", /obj/structure/ore_box, 4, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE),\
new/datum/stack_recipe("wooden crate", /obj/structure/closet/crate/wooden, 6, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE),\
new/datum/stack_recipe("baseball bat", /obj/item/melee/baseball_bat, 5, time = 1.5 SECONDS),\
new/datum/stack_recipe("loom", /obj/structure/loom, 10, time = 1.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("mortar", /obj/item/reagent_containers/cup/mortar, 3), \
new/datum/stack_recipe("firebrand", /obj/item/match/firebrand, 2, time = 100), \
new/datum/stack_recipe("bonfire", /obj/structure/bonfire, 10, time = 60, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("easel", /obj/structure/easel, 5, time = 10, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("firebrand", /obj/item/match/firebrand, 2, time = 10 SECONDS), \
new/datum/stack_recipe("bonfire", /obj/structure/bonfire, 10, time = 6 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("easel", /obj/structure/easel, 5, time = 1 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
null, \
new/datum/stack_recipe_list("pews", list(
new /datum/stack_recipe("pew (middle)", /obj/structure/chair/pew, 3, one_per_turf = TRUE, on_solid_ground = TRUE),
@@ -354,18 +354,19 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
*/
GLOBAL_LIST_INIT(bamboo_recipes, list ( \
new/datum/stack_recipe("punji sticks trap", /obj/structure/punji_sticks, 5, time = 30, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("bamboo spear", /obj/item/spear/bamboospear, 25, time = 90), \
new/datum/stack_recipe("blow gun", /obj/item/gun/syringe/blowgun, 10, time = 70), \
new/datum/stack_recipe("crude syringe", /obj/item/reagent_containers/syringe/crude, 5, time = 10), \
new/datum/stack_recipe("punji sticks trap", /obj/structure/punji_sticks, 5, time = 3 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("bamboo spear", /obj/item/spear/bamboospear, 25, time = 9 SECONDS), \
new/datum/stack_recipe("blow gun", /obj/item/gun/syringe/blowgun, 10, time = 7 SECONDS), \
new/datum/stack_recipe("crude syringe", /obj/item/reagent_containers/syringe/crude, 5, time = 1 SECONDS), \
new/datum/stack_recipe("rice hat", /obj/item/clothing/head/costume/rice_hat, 10, time = 7 SECONDS), \
null, \
new/datum/stack_recipe("bamboo stool", /obj/structure/chair/stool/bamboo, 2, time = 10, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("bamboo stool", /obj/structure/chair/stool/bamboo, 2, time = 1 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("bamboo mat piece", /obj/item/stack/tile/bamboo, 1, 4, 20), \
null, \
new/datum/stack_recipe_list("bamboo benches", list(
new /datum/stack_recipe("bamboo bench (middle)", /obj/structure/chair/sofa/bamboo, 3, time = 10, one_per_turf = TRUE, on_solid_ground = TRUE),
new /datum/stack_recipe("bamboo bench (left)", /obj/structure/chair/sofa/bamboo/left, 3, time = 10, one_per_turf = TRUE, on_solid_ground = TRUE),
new /datum/stack_recipe("bamboo bench (right)", /obj/structure/chair/sofa/bamboo/right, 3, time = 10, one_per_turf = TRUE, on_solid_ground = TRUE)
new /datum/stack_recipe("bamboo bench (middle)", /obj/structure/chair/sofa/bamboo, 3, time = 1 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE),
new /datum/stack_recipe("bamboo bench (left)", /obj/structure/chair/sofa/bamboo/left, 3, time = 1 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE),
new /datum/stack_recipe("bamboo bench (right)", /obj/structure/chair/sofa/bamboo/right, 3, time = 1 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE)
)), \
))
@@ -458,10 +459,10 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \
amount = 5
GLOBAL_LIST_INIT(durathread_recipes, list ( \
new/datum/stack_recipe("durathread jumpsuit", /obj/item/clothing/under/misc/durathread, 4, time = 40),
new/datum/stack_recipe("durathread beret", /obj/item/clothing/head/beret/durathread, 2, time = 40), \
new/datum/stack_recipe("durathread beanie", /obj/item/clothing/head/beanie/durathread, 2, time = 40), \
new/datum/stack_recipe("durathread bandana", /obj/item/clothing/mask/bandana/durathread, 1, time = 25), \
new/datum/stack_recipe("durathread jumpsuit", /obj/item/clothing/under/misc/durathread, 4, time = 4 SECONDS),
new/datum/stack_recipe("durathread beret", /obj/item/clothing/head/beret/durathread, 2, time = 4 SECONDS), \
new/datum/stack_recipe("durathread beanie", /obj/item/clothing/head/beanie/durathread, 2, time = 4 SECONDS), \
new/datum/stack_recipe("durathread bandana", /obj/item/clothing/mask/bandana/durathread, 1, time = 2.5 SECONDS), \
))
/obj/item/stack/sheet/durathread
@@ -619,12 +620,12 @@ GLOBAL_LIST_INIT(cardboard_recipes, list ( \
*/
GLOBAL_LIST_INIT(bronze_recipes, list ( \
new/datum/stack_recipe("wall gear", /obj/structure/girder/bronze, 2, time = 20, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("wall gear", /obj/structure/girder/bronze, 2, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
null,
new/datum/stack_recipe("directional bronze window", /obj/structure/window/bronze/unanchored, time = 0, on_solid_ground = TRUE, window_checks = TRUE), \
new/datum/stack_recipe("fulltile bronze window", /obj/structure/window/bronze/fulltile/unanchored, 2, time = 0, on_solid_ground = TRUE, window_checks = TRUE), \
new/datum/stack_recipe("pinion airlock assembly", /obj/structure/door_assembly/door_assembly_bronze, 4, time = 50, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("bronze pinion airlock assembly", /obj/structure/door_assembly/door_assembly_bronze/seethru, 4, time = 50, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("pinion airlock assembly", /obj/structure/door_assembly/door_assembly_bronze, 4, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("bronze pinion airlock assembly", /obj/structure/door_assembly/door_assembly_bronze/seethru, 4, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE), \
new/datum/stack_recipe("bronze floor tile", /obj/item/stack/tile/bronze, 1, 4, 20), \
new/datum/stack_recipe("bronze hat", /obj/item/clothing/head/costume/bronze), \
new/datum/stack_recipe("bronze suit", /obj/item/clothing/suit/costume/bronze), \
@@ -715,7 +716,7 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \
GLOBAL_LIST_INIT(plastic_recipes, list(
new /datum/stack_recipe("plastic floor tile", /obj/item/stack/tile/plastic, 1, 4, 20), \
new /datum/stack_recipe("folding plastic chair", /obj/structure/chair/plastic, 2), \
new /datum/stack_recipe("plastic flaps", /obj/structure/plasticflaps, 5, one_per_turf = TRUE, on_solid_ground = TRUE, time = 40), \
new /datum/stack_recipe("plastic flaps", /obj/structure/plasticflaps, 5, one_per_turf = TRUE, on_solid_ground = TRUE, time = 4 SECONDS), \
new /datum/stack_recipe("water bottle", /obj/item/reagent_containers/cup/glass/waterbottle/empty), \
new /datum/stack_recipe("large water bottle", /obj/item/reagent_containers/cup/glass/waterbottle/large/empty, 3), \
new /datum/stack_recipe("colo cups", /obj/item/reagent_containers/cup/glass/colocup, 1), \
@@ -745,8 +746,8 @@ GLOBAL_LIST_INIT(plastic_recipes, list(
. += GLOB.plastic_recipes
GLOBAL_LIST_INIT(paperframe_recipes, list(
new /datum/stack_recipe("paper frame separator", /obj/structure/window/paperframe, 2, one_per_turf = TRUE, on_solid_ground = TRUE, time = 10), \
new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperframe, 3, one_per_turf = TRUE, on_solid_ground = TRUE, time = 10 )))
new /datum/stack_recipe("paper frame separator", /obj/structure/window/paperframe, 2, one_per_turf = TRUE, on_solid_ground = TRUE, time = 1 SECONDS), \
new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperframe, 3, one_per_turf = TRUE, on_solid_ground = TRUE, time = 1 SECONDS )))
/obj/item/stack/sheet/paperframes
name = "paper frames"
+105 -95
View File
@@ -2,26 +2,32 @@
name = "biogenerator"
desc = "Converts plants into biomass, which can be used to construct useful items."
icon = 'icons/obj/machines/biogenerator.dmi'
icon_state = "biogen-empty"
icon_state = "biogenerator"
density = TRUE
circuit = /obj/item/circuitboard/machine/biogenerator
light_power = 1
light_range = MINIMUM_USEFUL_LIGHT_RANGE
var/processing = FALSE
var/obj/item/reagent_containers/cup/beaker = null
var/points = 0
var/biomass = 0
var/efficiency = 0
var/productivity = 0
var/max_items = 40
var/max_items = 20
var/max_biomass = 500
var/max_output = 50
var/datum/techweb/stored_research
var/list/show_categories = list(RND_CATEGORY_FOOD, RND_CATEGORY_BOTANY_CHEMICALS, RND_CATEGORY_ORGANIC_MATERIALS)
/// Currently selected category in the UI
var/list/show_categories = list(RND_CATEGORY_BIO_FOOD, RND_CATEGORY_BIO_CHEMICALS, RND_CATEGORY_BIO_MATERIALS)
var/selected_cat
var/datum/looping_sound/generator/soundloop
/obj/machinery/biogenerator/Initialize(mapload)
. = ..()
stored_research = new /datum/techweb/specialized/autounlocking/biogenerator
soundloop = new(src, processing)
/obj/machinery/biogenerator/Destroy()
QDEL_NULL(beaker)
QDEL_NULL(soundloop)
return ..()
/obj/machinery/biogenerator/contents_explosion(severity, target)
@@ -47,43 +53,58 @@
. = ..()
var/E = 0
var/P = 0
var/max_storage = 40
var/I = 10
var/V = 0
for(var/obj/item/stock_parts/matter_bin/B in component_parts)
P += B.rating
max_storage = 40 * B.rating
I += 10 * B.rating
V += 500 * B.rating
for(var/obj/item/stock_parts/manipulator/M in component_parts)
P += M.rating
E += M.rating
efficiency = E
productivity = P
max_items = max_storage
max_items = I
max_biomass = V
update_appearance()
/obj/machinery/biogenerator/examine(mob/user)
. = ..()
if(in_range(user, src) || isobserver(user))
. += span_notice("The status display reads: Productivity at <b>[productivity*100]%</b>.<br>Matter consumption reduced by <b>[(efficiency*25)-25]</b>%.<br>Machine can hold up to <b>[max_items]</b> pieces of produce.")
. += span_notice("The status display reads: Productivity at <b>[productivity*100]%</b>.<br>Matter consumption reduced by <b>[(efficiency*25)-25]</b>%.<br>Machine can hold up to <b>[max_items]</b> pieces of produce.<br>And up to <b>[max_biomass]</b> units of biomass.")
/obj/machinery/biogenerator/update_icon_state()
/obj/machinery/biogenerator/update_appearance()
. = ..()
if((machine_stat & (NOPOWER|BROKEN)) || panel_open)
luminosity = 0
return
luminosity = 1 + ROUND_UP(2 * biomass / max_biomass) + (processing & 1)
/obj/machinery/biogenerator/update_overlays()
. = ..()
if(panel_open)
icon_state = "biogen-empty-o"
return ..()
if(!beaker)
icon_state = "biogen-empty"
return ..()
if(!processing)
icon_state = "biogen-stand"
return ..()
icon_state = "biogen-work"
return ..()
. += mutable_appearance(icon, "[icon_state]_o_panel", alpha = alpha)
if(beaker)
. += mutable_appearance(icon, "[icon_state]_o_container", alpha = alpha)
if(biomass > 0)
var/biomass_level = min(ROUND_UP(7 * biomass / max_biomass), 7)
. += mutable_appearance(icon, "[icon_state]_o_biomass_[biomass_level]", alpha = alpha)
. += emissive_appearance(icon, "[icon_state]_o_biomass_[biomass_level]", src, alpha = alpha)
if(machine_stat & (NOPOWER|BROKEN))
return
if(processing)
. += mutable_appearance(icon, "[icon_state]_o_process", alpha = alpha)
. += emissive_appearance(icon, "[icon_state]_o_process", src, alpha = alpha)
. += mutable_appearance(icon, "[icon_state]_o_screen", alpha = alpha)
. += emissive_appearance(icon, "[icon_state]_o_screen", src, alpha = alpha)
/obj/machinery/biogenerator/attackby(obj/item/O, mob/living/user, params)
if(user.combat_mode)
return ..()
if(processing)
to_chat(user, span_warning("The biogenerator is currently processing."))
return
if(default_deconstruction_screwdriver(user, "biogen-empty-o", "biogen-empty", O))
if(default_deconstruction_screwdriver(user, icon_state, icon_state, O))
if(processing)
processing = FALSE
soundloop.stop()
if(beaker)
var/obj/item/reagent_containers/cup/B = beaker
B.forceMove(drop_location())
@@ -91,7 +112,12 @@
update_appearance()
return
var/turf/drop_location = drop_location()
if(default_deconstruction_crowbar(O))
if(biomass > 0)
drop_location.visible_message(span_warning("The biomass spills!"))
playsound(drop_location, 'sound/effects/slosh.ogg', 25, vary = TRUE)
new /obj/effect/decal/cleanable/greenglow(drop_location)
return
if(istype(O, /obj/item/reagent_containers/cup))
@@ -99,33 +125,32 @@
to_chat(user, span_warning("Close the maintenance panel first."))
else
insert_beaker(user, O)
return TRUE
else if(istype(O, /obj/item/storage/bag/plants))
var/obj/item/storage/bag/plants/PB = O
else if(istype(O, /obj/item/storage/bag))
var/obj/item/storage/bag/bag = O
var/i = 0
for(var/obj/item/food/grown/G in contents)
for(var/obj/item/food/item in contents)
i++
if(i >= max_items)
to_chat(user, span_warning("The biogenerator is already full! Activate it."))
else
for(var/obj/item/food/grown/G in PB.contents)
for(var/obj/item/food/item in bag.contents)
if(i >= max_items)
break
if(PB.atom_storage.attempt_remove(G, src))
if(bag.atom_storage.attempt_remove(item, src))
i++
if(i<max_items)
to_chat(user, span_info("You empty the plant bag into the biogenerator."))
else if(PB.contents.len == 0)
to_chat(user, span_info("You empty the plant bag into the biogenerator, filling it to its capacity."))
if(bag.contents.len == 0)
to_chat(user, span_info("You empty the bag into the biogenerator."))
else if (i >= max_items)
to_chat(user, span_info("You fill the biogenerator from the bag to its capacity."))
else
to_chat(user, span_info("You fill the biogenerator to its capacity."))
to_chat(user, span_info("You fill the biogenerator from the bag."))
return TRUE //no afterattack
else if(istype(O, /obj/item/food/grown))
else if(istype(O, /obj/item/food))
var/i = 0
for(var/obj/item/food/grown/G in contents)
for(var/obj/item/food/item in contents)
i++
if(i >= max_items)
to_chat(user, span_warning("The biogenerator is full! Activate it."))
@@ -154,7 +179,7 @@
eject_beaker(user)
/**
* activate: Activates biomass processing and converts all inserted grown products into biomass
* activate: Activates biomass processing and converts all inserted food products into biomass
*
* Arguments:
* * user The mob starting the biomass processing
@@ -167,74 +192,55 @@
if(processing)
to_chat(user, span_warning("The biogenerator is in the process of working."))
return
var/processing_time = 0
for(var/obj/item/food/grown/I in contents)
processing_time += 5
if(I.reagents.get_reagent_amount(/datum/reagent/consumable/nutriment) < 0.1)
points += 1 * productivity
else
points += I.reagents.get_reagent_amount(/datum/reagent/consumable/nutriment) * 10 * productivity
qdel(I)
if(processing_time)
if(biomass >= max_biomass)
say("Warning: The biomass storage is full!")
return
if(locate(/obj/item/food) in contents)
processing = TRUE
soundloop.start()
update_appearance()
playsound(loc, 'sound/machines/blender.ogg', 50, TRUE)
use_power(processing_time * active_power_usage * 0.1) // .1 needed here to convert time (in deciseconds) to seconds such that watts * seconds = joules
sleep(processing_time + 15 / productivity)
for(var/obj/item/food/object in contents)
var/nutriments = 0
for(var/nutriment in typesof(/datum/reagent/consumable/nutriment))
nutriments += object.reagents.get_reagent_amount(nutriment)
qdel(object)
var/potential_biomass = max(1, nutriments) * productivity
while(processing && potential_biomass > 0)
use_power(active_power_usage * (1 SECONDS)) // Seconds needed here to convert time (in deciseconds) to seconds such that watts * seconds = joules
potential_biomass -= 1
biomass += 1
stoplag(2 / productivity)
update_appearance(UPDATE_ICON)
processing = FALSE
soundloop.stop()
update_appearance()
/obj/machinery/biogenerator/proc/check_cost(list/materials, multiplier = 1, remove_points = TRUE)
/obj/machinery/biogenerator/proc/use_biomass(list/materials, amount = 1, remove_biomass = TRUE)
if(materials.len != 1 || materials[1] != GET_MATERIAL_REF(/datum/material/biomass))
return FALSE
if (materials[GET_MATERIAL_REF(/datum/material/biomass)]*multiplier/efficiency > points)
if (ROUND_UP(materials[GET_MATERIAL_REF(/datum/material/biomass)]*amount/efficiency) > biomass)
return FALSE
else
if(remove_points)
points -= materials[GET_MATERIAL_REF(/datum/material/biomass)]*multiplier/efficiency
if(remove_biomass)
biomass -= ROUND_UP(materials[GET_MATERIAL_REF(/datum/material/biomass)]*amount/efficiency)
update_appearance()
return TRUE
/obj/machinery/biogenerator/proc/check_container_volume(list/reagents, multiplier = 1)
var/sum_reagents = 0
for(var/R in reagents)
sum_reagents += reagents[R]
sum_reagents *= multiplier
if(beaker.reagents.total_volume + sum_reagents > beaker.reagents.maximum_volume)
return FALSE
return TRUE
/obj/machinery/biogenerator/proc/create_product(datum/design/D, amount)
if(!beaker || !loc)
return FALSE
if(ispath(D.build_path, /obj/item/stack))
if(!check_container_volume(D.make_reagents, amount))
if(D.make_reagents.len > 0)
if(!beaker)
return FALSE
if(!check_cost(D.materials, amount))
if(beaker.reagents.maximum_volume - beaker.reagents.total_volume < amount)
say("Warning: Attached container does not have enough free capacity!")
return FALSE
if(!use_biomass(D.materials, amount))
return FALSE
beaker.reagents.add_reagent(D.make_reagents[1], amount)
if(D.build_path)
if(!use_biomass(D.materials, amount))
return FALSE
new D.build_path(drop_location(), amount)
for(var/R in D.make_reagents)
beaker.reagents.add_reagent(R, D.make_reagents[R]*amount)
else
var/i = amount
while(i > 0)
if(!check_container_volume(D.make_reagents))
say("Warning: Attached container does not have enough free capacity!")
return .
if(!check_cost(D.materials))
return .
if(D.build_path)
new D.build_path(loc)
for(var/R in D.make_reagents)
beaker.reagents.add_reagent(R, D.make_reagents[R])
. = 1
--i
update_appearance()
return .
return TRUE
/*
* Insert a new beaker into the biogenerator, replacing/swapping our current beaker if there is one.
@@ -301,9 +307,12 @@
/obj/machinery/biogenerator/ui_data(mob/user)
var/list/data = list()
data["beaker"] = beaker ? TRUE : FALSE
data["biomass"] = points
data["biomass"] = biomass
data["max_biomass"] = max_biomass
data["processing"] = processing
if(locate(/obj/item/food/grown) in contents)
data["max_output"] = max_output
data["efficiency"] = efficiency
if((locate(/obj/item/food) in contents) && biomass < max_biomass)
data["can_process"] = TRUE
else
data["can_process"] = FALSE
@@ -335,6 +344,7 @@
cat["items"] += list(list(
"id" = D.id,
"name" = D.name,
"is_reagent" = D.make_reagents.len > 0,
"cost" = D.materials[GET_MATERIAL_REF(/datum/material/biomass)]/efficiency,
))
data["categories"] += list(cat)
@@ -355,7 +365,6 @@
return TRUE
if("create")
var/amount = text2num(params["amount"])
amount = clamp(amount, 1, 10)
if(!amount)
return
var/id = params["id"]
@@ -363,6 +372,7 @@
stack_trace("ID did not map to a researched datum [id]")
return
var/datum/design/D = SSresearch.techweb_design_by_id(id)
amount = clamp(amount, 1, (D.make_reagents.len > 0 && beaker ? beaker.reagents.maximum_volume - beaker.reagents.total_volume : max_output))
if(D && !istype(D, /datum/design/error_design))
create_product(D, amount)
else
@@ -3,225 +3,185 @@
///////////////////////////////////
/datum/design/milk
name = "10u Milk"
name = "Milk"
id = "milk"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 20)
make_reagents = list(/datum/reagent/consumable/milk = 10)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_FOOD)
materials = list(/datum/material/biomass= 0.4)
make_reagents = list(/datum/reagent/consumable/milk = 1)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_FOOD)
/datum/design/soymilk
name = "10u Soy Milk"
name = "Soy Milk"
id = "soymilk"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 20)
make_reagents = list(/datum/reagent/consumable/soymilk = 10)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_FOOD)
materials = list(/datum/material/biomass= 0.4)
make_reagents = list(/datum/reagent/consumable/soymilk = 1)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_FOOD)
/datum/design/ethanol
name = "10u Ethanol"
name = "Ethanol"
id = "ethanol"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 30)
make_reagents = list(/datum/reagent/consumable/ethanol = 10)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_FOOD)
materials = list(/datum/material/biomass= 0.6)
make_reagents = list(/datum/reagent/consumable/ethanol = 1)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_FOOD)
/datum/design/cream
name = "10u Cream"
name = "Cream"
id = "cream"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 30)
make_reagents = list(/datum/reagent/consumable/cream = 10)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_FOOD)
materials = list(/datum/material/biomass= 0.6)
make_reagents = list(/datum/reagent/consumable/cream = 1)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_FOOD)
/datum/design/black_pepper
name = "10u Black Pepper"
name = "Black Pepper"
id = "black_pepper"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 25)
make_reagents = list(/datum/reagent/consumable/blackpepper = 10)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_FOOD)
materials = list(/datum/material/biomass= 0.6)
make_reagents = list(/datum/reagent/consumable/blackpepper = 1)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_FOOD)
/datum/design/enzyme
name = "10u Universal Enzyme"
name = "Universal Enzyme"
id = "enzyme"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 30)
make_reagents = list(/datum/reagent/consumable/enzyme = 10)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_FOOD)
materials = list(/datum/material/biomass= 0.6)
make_reagents = list(/datum/reagent/consumable/enzyme = 1)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_FOOD)
/datum/design/flour
name = "10u Flour"
name = "Flour"
id = "flour_sack"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 30)
make_reagents = list(/datum/reagent/consumable/flour = 10)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_FOOD)
materials = list(/datum/material/biomass= 0.6)
make_reagents = list(/datum/reagent/consumable/flour = 1)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_FOOD)
/datum/design/sugar
name = "10u Sugar"
name = "Sugar"
id = "sugar"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 30)
make_reagents = list(/datum/reagent/consumable/sugar = 10)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_FOOD)
materials = list(/datum/material/biomass= 0.6)
make_reagents = list(/datum/reagent/consumable/sugar = 1)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_FOOD)
/datum/design/monkey_cube
name = "Monkey Cube"
id = "mcube"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 250)
materials = list(/datum/material/biomass= 50)
build_path = /obj/item/food/monkeycube
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_FOOD)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_FOOD)
/datum/design/seaweed_sheet
name = "Seaweed sheet"
id = "seaweedsheet"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 30)
materials = list(/datum/material/biomass= 3)
build_path = /obj/item/food/seaweedsheet
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_FOOD)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_FOOD)
/datum/design/ez_nut //easy nut :)
name = "25u E-Z Nutrient"
name = "E-Z Nutrient"
id = "ez_nut"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 10)
make_reagents = list(/datum/reagent/plantnutriment/eznutriment = 25)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BOTANY_CHEMICALS)
materials = list(/datum/material/biomass= 0.1)
make_reagents = list(/datum/reagent/plantnutriment/eznutriment = 1)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_CHEMICALS)
/datum/design/l4z_nut
name = "25u Left 4 Zed"
name = "Left 4 Zed"
id = "l4z_nut"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 20)
make_reagents = list(/datum/reagent/plantnutriment/left4zednutriment = 25)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BOTANY_CHEMICALS)
materials = list(/datum/material/biomass= 0.1)
make_reagents = list(/datum/reagent/plantnutriment/left4zednutriment = 1)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_CHEMICALS)
/datum/design/rh_nut
name = "25u Robust Harvest"
name = "Robust Harvest"
id = "rh_nut"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 25)
make_reagents = list(/datum/reagent/plantnutriment/robustharvestnutriment = 25)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BOTANY_CHEMICALS)
materials = list(/datum/material/biomass= 0.2)
make_reagents = list(/datum/reagent/plantnutriment/robustharvestnutriment = 1)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_CHEMICALS)
/datum/design/end_gro
name = "25u Enduro Grow"
name = "Enduro Grow"
id = "end_gro"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 30)
make_reagents = list(/datum/reagent/plantnutriment/endurogrow = 25)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BOTANY_CHEMICALS)
materials = list(/datum/material/biomass= 0.3)
make_reagents = list(/datum/reagent/plantnutriment/endurogrow = 1)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_CHEMICALS)
/datum/design/liq_earth
name = "25u Liquid Earthquake"
name = "Liquid Earthquake"
id = "liq_earth"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 30)
make_reagents = list(/datum/reagent/plantnutriment/liquidearthquake = 25)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BOTANY_CHEMICALS)
materials = list(/datum/material/biomass= 0.3)
make_reagents = list(/datum/reagent/plantnutriment/liquidearthquake = 1)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_CHEMICALS)
/datum/design/weed_killer
name = "25u Weed Killer"
name = "Weed Killer"
id = "weed_killer"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 50)
make_reagents = list(/datum/reagent/toxin/plantbgone/weedkiller = 25)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BOTANY_CHEMICALS)
materials = list(/datum/material/biomass= 0.2)
make_reagents = list(/datum/reagent/toxin/plantbgone/weedkiller = 1)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_CHEMICALS)
/datum/design/pest_spray
name = "25u Pest Killer"
name = "Pest Killer"
id = "pest_spray"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 50)
make_reagents = list(/datum/reagent/toxin/pestkiller = 25)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BOTANY_CHEMICALS)
materials = list(/datum/material/biomass= 0.4)
make_reagents = list(/datum/reagent/toxin/pestkiller = 1)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_CHEMICALS)
/datum/design/org_pest_spray
name = "25u Organic Pest Killer"
name = "Organic Pest Killer"
id = "org_pest_spray"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 80)
make_reagents = list(/datum/reagent/toxin/pestkiller/organic = 25)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BOTANY_CHEMICALS)
/datum/design/cloth
name = "Roll of Cloth"
id = "cloth"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 50)
build_path = /obj/item/stack/sheet/cloth
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_ORGANIC_MATERIALS)
/datum/design/cardboard
name = "Sheet of Cardboard"
id = "cardboard"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 25)
build_path = /obj/item/stack/sheet/cardboard
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_ORGANIC_MATERIALS)
/datum/design/rolling_paper_pack
name = "Rolling Paper Pack"
id = "rolling_paper_pack"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 50)
build_path = /obj/item/storage/fancy/rollingpapers
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_ORGANIC_MATERIALS)
materials = list(/datum/material/biomass= 0.6)
make_reagents = list(/datum/reagent/toxin/pestkiller/organic = 1)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_CHEMICALS)
/datum/design/leather
name = "Sheet of Leather"
id = "leather"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 150)
materials = list(/datum/material/biomass= 30)
build_path = /obj/item/stack/sheet/leather
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_ORGANIC_MATERIALS)
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_MATERIALS)
/datum/design/secbelt
name = "Security Belt"
id = "secbelt"
/datum/design/cloth
name = "Sheet of Cloth"
id = "cloth"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 300)
build_path = /obj/item/storage/belt/security
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_ORGANIC_MATERIALS)
materials = list(/datum/material/biomass= 10)
build_path = /obj/item/stack/sheet/cloth
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_MATERIALS)
/datum/design/medbelt
name = "Medical Belt"
id = "medbel"
/datum/design/cardboard
name = "Sheet of Cardboard"
id = "cardboard"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 300)
build_path = /obj/item/storage/belt/medical
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_ORGANIC_MATERIALS)
materials = list(/datum/material/biomass= 5)
build_path = /obj/item/stack/sheet/cardboard
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_MATERIALS)
/datum/design/janibelt
name = "Janitorial Belt"
id = "janibelt"
/datum/design/paper
name = "Sheet of Paper"
id = "paper"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 300)
build_path = /obj/item/storage/belt/janitor
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_ORGANIC_MATERIALS)
materials = list(/datum/material/biomass= 2)
build_path = /obj/item/paper
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_MATERIALS)
/datum/design/plantbelt
name = "Botanical Belt"
id = "plantbelt"
/datum/design/rolling_paper
name = "Sheet of Rolling Paper"
id = "rollingpaper"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 300)
build_path = /obj/item/storage/belt/plant
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_ORGANIC_MATERIALS)
/datum/design/s_holster
name = "Shoulder Holster"
id = "s_holster"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 400)
build_path = /obj/item/storage/belt/holster
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_ORGANIC_MATERIALS)
/datum/design/rice_hat
name = "Rice Hat"
id = "rice_hat"
build_type = BIOGENERATOR
materials = list(/datum/material/biomass= 300)
build_path = /obj/item/clothing/head/costume/rice_hat
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_ORGANIC_MATERIALS)
materials = list(/datum/material/biomass= 1)
build_path = /obj/item/rollingpaper
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_BIO_MATERIALS)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

@@ -1,189 +0,0 @@
import { classes } from 'common/react';
import { createSearch } from 'common/string';
import { useBackend, useLocalState } from '../backend';
import { Box, Button, Dimmer, Divider, Flex, Icon, Input, NoticeBox, NumberInput, ProgressBar, Section, Table, Tabs } from '../components';
import { formatMoney } from '../format';
import { Window } from '../layouts';
const MAX_SEARCH_RESULTS = 25;
export const Biogenerator = (props, context) => {
const { data } = useBackend(context);
const { beaker, processing } = data;
return (
<Window width={550} height={420}>
{!!processing && (
<Dimmer fontSize="32px">
<Icon name="cog" spin={1} />
{' Processing...'}
</Dimmer>
)}
<Window.Content scrollable>
{!beaker && <NoticeBox>No Container</NoticeBox>}
{!!beaker && <BiogeneratorContent />}
</Window.Content>
</Window>
);
};
export const BiogeneratorContent = (props, context) => {
const { act, data } = useBackend(context);
const {
beakerCurrentVolume,
beakerMaxVolume,
biomass,
can_process,
categories = [],
reagent_color,
} = data;
const [searchText, setSearchText] = useLocalState(context, 'searchText', '');
const [selectedCategory, setSelectedCategory] = useLocalState(
context,
'category',
categories[0]?.name
);
const testSearch = createSearch(searchText, (item) => {
return item.name;
});
const items =
(searchText.length > 0 &&
// Flatten all categories and apply search to it
categories
.flatMap((category) => category.items || [])
.filter(testSearch)
.filter((item, i) => i < MAX_SEARCH_RESULTS)) ||
// Select a category and show all items in it
categories.find((category) => category.name === selectedCategory)?.items ||
// If none of that results in a list, return an empty list
[];
return (
<Section
title={
<Box inline color={biomass > 0 ? 'good' : 'bad'}>
{formatMoney(biomass)} Biomass
</Box>
}
buttons={
<>
Search
<Input
autoFocus
value={searchText}
onInput={(e, value) => setSearchText(value)}
mx={1}
/>
<Button icon="eject" content="Eject" onClick={() => act('eject')} />
<Button
icon="cog"
content="Activate"
disabled={!can_process}
onClick={() => act('activate')}
/>
</>
}>
<Flex>
{searchText.length === 0 && (
<Flex.Item>
<Tabs vertical>
{categories.map((category) => (
<Tabs.Tab
key={category.name}
selected={category.name === selectedCategory}
onClick={() => setSelectedCategory(category.name)}>
{category.name} ({category.items?.length || 0})
</Tabs.Tab>
))}
</Tabs>
<Divider />
<div>Container Contents:</div>
<ProgressBar
mt={1}
value={beakerCurrentVolume}
maxValue={beakerMaxVolume}
backgroundColor="black"
color={reagent_color}>
<div>{beakerCurrentVolume + '/' + beakerMaxVolume}</div>
</ProgressBar>
</Flex.Item>
)}
<Flex.Item grow={1} basis={0}>
{items.length === 0 && (
<NoticeBox>
{searchText.length === 0
? 'No items in this category.'
: 'No results found.'}
</NoticeBox>
)}
<Table>
<ItemList biomass={biomass} items={items} />
</Table>
</Flex.Item>
</Flex>
</Section>
);
};
const ItemList = (props, context) => {
const { act } = useBackend(context);
const [hoveredItem, setHoveredItem] = useLocalState(
context,
'hoveredItem',
{}
);
const hoveredCost = hoveredItem.cost || 0;
// Append extra hover data to items
const items = props.items.map((item) => {
const [amount, setAmount] = useLocalState(context, 'amount' + item.name, 1);
const notSameItem = hoveredItem.name !== item.name;
const notEnoughHovered =
props.biomass - hoveredCost * hoveredItem.amount < item.cost * amount;
const disabledDueToHovered = notSameItem && notEnoughHovered;
const disabled = props.biomass < item.cost * amount || disabledDueToHovered;
return {
...item,
disabled,
amount,
setAmount,
};
});
return items.map((item) => (
<Table.Row key={item.id}>
<Table.Cell>
<span
className={classes(['design32x32', item.id])}
style={{
'vertical-align': 'middle',
}}
/>{' '}
<b>{item.name}</b>
</Table.Cell>
<Table.Cell collapsing>
<NumberInput
value={Math.round(item.amount)}
width="35px"
minValue={1}
maxValue={10}
onChange={(e, value) => item.setAmount(value)}
/>
</Table.Cell>
<Table.Cell collapsing>
<Button
style={{
'text-align': 'right',
}}
fluid
content={item.cost * item.amount + ' ' + 'BIO'}
disabled={item.disabled}
onmouseover={() => setHoveredItem(item)}
onmouseout={() => setHoveredItem({})}
onClick={() =>
act('create', {
id: item.id,
amount: item.amount,
})
}
/>
</Table.Cell>
</Table.Row>
));
};
@@ -0,0 +1,225 @@
import { BooleanLike } from 'common/react';
import { classes } from 'common/react';
import { useBackend, useLocalState } from '../backend';
import { Window } from '../layouts';
import { Section, NumberInput, Table, Tabs, LabeledList, NoticeBox, Button, ProgressBar, Stack } from '../components';
type BiogeneratorData = {
processing: BooleanLike;
beaker: BooleanLike;
reagent_color: string;
biomass: number;
max_biomass: number;
can_process: BooleanLike;
beakerCurrentVolume: number;
beakerMaxVolume: number;
max_output: number;
efficiency: number;
categories: Category[];
};
type Category = {
name: string;
items: Design[];
};
type Design = {
id: number;
name: string;
is_reagent: BooleanLike;
disable: BooleanLike;
cost: number;
amount: number;
};
export const Biogenerator = (props, context) => {
const { act, data } = useBackend<BiogeneratorData>(context);
const {
processing,
beaker,
reagent_color,
biomass,
max_biomass,
can_process,
beakerCurrentVolume,
beakerMaxVolume,
max_output,
efficiency,
categories,
} = data;
const [selectedCategory, setSelectedCategory] = useLocalState<string>(
context,
'category',
data.categories[0]?.name
);
const items =
categories.find((category) => category.name === selectedCategory)?.items ||
[];
return (
<Window width={400} height={480}>
<Window.Content>
<Stack vertical fill>
<Stack.Item>
<LabeledList>
<LabeledList.Item
label="Biomass"
buttons={
<Button
width={7}
align="center"
icon="cog"
iconSpin={processing ? 1 : 0}
content="Generate"
disabled={!can_process || processing}
onClick={() => act('activate')}
/>
}>
<ProgressBar
value={biomass}
minValue={0}
maxValue={max_biomass}
color="good">
<span
style={{
'text-shadow': '1px 1px 0 black',
}}>
{`${biomass} of ${max_biomass} units`}
</span>
</ProgressBar>
</LabeledList.Item>
{!!beaker && (
<LabeledList.Item
label="Container"
buttons={
<Button
width={7}
align="center"
icon="eject"
content="Eject"
onClick={() => act('eject')}
/>
}>
<ProgressBar
value={beakerCurrentVolume}
minValue={0}
maxValue={beakerMaxVolume}
color={reagent_color}>
<span
style={{
'text-shadow': '1px 1px 0 black',
}}>
{`${beakerCurrentVolume} of ${beakerMaxVolume} units`}
</span>
</ProgressBar>
</LabeledList.Item>
)}
{!beaker && (
<LabeledList.Item label="Container">
<NoticeBox m={0} height="19px" fontSize="11px">
No liquid container
</NoticeBox>
</LabeledList.Item>
)}
</LabeledList>
</Stack.Item>
<Stack.Item>
<Tabs fluid>
{categories.map((category) => (
<Tabs.Tab
align="center"
key={category.name}
selected={category.name === selectedCategory}
onClick={() => setSelectedCategory(category.name)}>
{category.name}
</Tabs.Tab>
))}
</Tabs>
</Stack.Item>
<Stack.Item grow mt={'2px'}>
<Section fill scrollable>
<Table>
<ItemList
processing={processing}
biomass={biomass}
items={items}
beaker={beaker}
efficiency={efficiency}
max_output={max_output}
space={beaker ? beakerMaxVolume - beakerCurrentVolume : 1}
/>
</Table>
</Section>
</Stack.Item>
</Stack>
</Window.Content>
</Window>
);
};
const ItemList = (props, context) => {
const { act } = useBackend(context);
const items = props.items.map((item) => {
const [amount, setAmount] = useLocalState(
context,
'amount' + item.name,
item.is_reagent ? Math.min(Math.max(props.space, 1), 10) : 1
);
const disabled =
props.processing ||
(item.is_reagent && !props.beaker) ||
(item.is_reagent && props.space < amount) ||
props.biomass < Math.ceil((item.cost * amount) / props.efficiency);
const max_possible = Math.floor(
(props.efficiency * props.biomass) / item.cost
);
const max_capacity = item.is_reagent ? props.space : props.max_output;
const max_amount = Math.max(1, Math.min(max_capacity, max_possible));
return {
...item,
disabled,
max_amount,
amount,
setAmount,
};
});
return items.map((item) => (
<Table.Row key={item.id}>
<Table.Cell>
<span
className={classes(['design32x32', item.id])}
style={{
'vertical-align': 'middle',
}}
/>{' '}
<b>{item.name}</b>
</Table.Cell>
<Table.Cell collapsing>
<NumberInput
value={item.amount}
width="35px"
minValue={1}
maxValue={item.max_amount}
onChange={(e, value) => item.setAmount(value)}
/>
</Table.Cell>
<Table.Cell collapsing>
<Button
fluid
align="right"
content={
Math.ceil((item.cost * item.amount) / props.efficiency) +
' ' +
'BIO'
}
disabled={item.disabled}
onClick={() =>
act('create', {
id: item.id,
amount: item.amount,
})
}
/>
</Table.Cell>
</Table.Row>
));
};