diff --git a/code/__DEFINES/botany.dm b/code/__DEFINES/botany.dm
index 15b63ee34d0..170f944e15f 100644
--- a/code/__DEFINES/botany.dm
+++ b/code/__DEFINES/botany.dm
@@ -11,6 +11,9 @@
/// MINS:
#define MIN_PLANT_ENDURANCE 10
+/// Default reagent volume for grown plants
+#define PLANT_REAGENT_VOLUME 100
+
/// -- Some botany trait value defines. --
/// Weed Hardy can only reduce plants to 3 yield.
#define WEED_HARDY_YIELD_MIN 3
@@ -73,6 +76,9 @@
// obj/machinery/hydroponics/var/plant_status defines
+/// How long to wait between plant age ticks, by default. See [/obj/machinery/hydroponics/var/cycledelay]
+#define HYDROTRAY_CYCLE_DELAY 20 SECONDS
+
#define HYDROTRAY_NO_PLANT "missing"
#define HYDROTRAY_PLANT_DEAD "dead"
#define HYDROTRAY_PLANT_GROWING "growing"
diff --git a/code/modules/asset_cache/assets/seeds.dm b/code/modules/asset_cache/assets/seeds.dm
new file mode 100644
index 00000000000..f3041408ac1
--- /dev/null
+++ b/code/modules/asset_cache/assets/seeds.dm
@@ -0,0 +1,12 @@
+/datum/asset/spritesheet/seeds
+ name = "seeds"
+
+/datum/asset/spritesheet/seeds/create_spritesheets()
+ for (var/path in subtypesof(/obj/item/seeds))
+ var/obj/item/seeds/seed_type = path
+ var/icon = initial(seed_type.icon)
+ var/icon_state = initial(seed_type.icon_state)
+ var/id = sanitize_css_class_name("[icon][icon_state]")
+ if(sprites[id]) //no dupes
+ continue
+ Insert(id, icon, icon_state)
diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm
index 521c41103a5..387cd19c542 100644
--- a/code/modules/hydroponics/grown.dm
+++ b/code/modules/hydroponics/grown.dm
@@ -14,7 +14,7 @@
icon = 'icons/obj/hydroponics/harvest.dmi'
worn_icon = 'icons/mob/clothing/head/hydroponics.dmi'
name = "fresh produce" // so recipe text doesn't say 'snack'
- max_volume = 100
+ max_volume = PLANT_REAGENT_VOLUME
w_class = WEIGHT_CLASS_SMALL
resistance_flags = FLAMMABLE
/// type path, gets converted to item on New(). It's safe to assume it's always a seed item.
diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm
index b8c1fc700bb..930b2dd588b 100644
--- a/code/modules/hydroponics/hydroponics.dm
+++ b/code/modules/hydroponics/hydroponics.dm
@@ -38,7 +38,7 @@
///Used for timing of cycles.
var/lastcycle = 0
///About 10 seconds / cycle
- var/cycledelay = 200
+ var/cycledelay = HYDROTRAY_CYCLE_DELAY
///The currently planted seed
var/obj/item/seeds/myseed
///Obtained from the quality of the parts used in the tray, determines nutrient drain rate.
diff --git a/code/modules/hydroponics/plant_genes.dm b/code/modules/hydroponics/plant_genes.dm
index 1c92687ee95..b7b404be770 100644
--- a/code/modules/hydroponics/plant_genes.dm
+++ b/code/modules/hydroponics/plant_genes.dm
@@ -2,6 +2,8 @@
/datum/plant_gene
/// The name of the gene.
var/name
+ /// The font awesome icon name representing the gene in the seed extractor UI
+ var/icon = "dna"
/// Flags that determine if a gene can be modified.
var/mutability_flags
@@ -115,7 +117,7 @@
/// The rate at which this trait affects something. This can be anything really - why? I dunno.
var/rate = 0.05
/// Bonus lines displayed on examine.
- var/examine_line = ""
+ var/description = ""
/// Flag - Traits that share an ID cannot be placed on the same plant.
var/trait_ids
/// Flag - Modifications made to the final product.
@@ -175,21 +177,21 @@
return FALSE
// Add on any bonus lines on examine
- if(examine_line)
+ if(description)
RegisterSignal(our_plant, COMSIG_PARENT_EXAMINE, PROC_REF(examine))
-
return TRUE
/// Add on any unique examine text to the plant's examine text.
/datum/plant_gene/trait/proc/examine(obj/item/our_plant, mob/examiner, list/examine_list)
SIGNAL_HANDLER
- examine_list += examine_line
+ examine_list += span_info("[description]")
/// Allows the plant to be squashed when thrown or slipped on, leaving a colored mess and trash type item behind.
/datum/plant_gene/trait/squash
name = "Liquid Contents"
- examine_line = "It has a lot of liquid contents inside."
+ icon = "droplet"
+ description = "It may burst open from the internal pressure on impact."
trait_ids = THROW_IMPACT_ID | REAGENT_TRANSFER_ID | ATTACK_SELF_ID
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
@@ -243,8 +245,9 @@
*/
/datum/plant_gene/trait/slip
name = "Slippery Skin"
+ description = "Watch your step around this."
+ icon = "person-falling"
rate = 1.6
- examine_line = "It has a very slippery skin."
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
/datum/plant_gene/trait/slip/on_new_plant(obj/item/our_plant, newloc)
@@ -276,6 +279,8 @@
*/
/datum/plant_gene/trait/cell_charge
name = "Electrical Activity"
+ description = "It can electrocute on interaction or recharge batteries when eaten."
+ icon = "bolt"
rate = 0.2
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
@@ -343,8 +348,9 @@
*/
/datum/plant_gene/trait/glow
name = "Bioluminescence"
+ icon = "lightbulb"
rate = 0.03
- examine_line = "It emits a soft glow."
+ description = "It emits a soft glow."
trait_ids = GLOW_ID
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
/// The color of our bioluminesence.
@@ -371,6 +377,7 @@
*/
/datum/plant_gene/trait/glow/shadow
name = "Shadow Emission"
+ icon = "lightbulb-o"
rate = 0.04
glow_color = "#AAD84B"
@@ -420,6 +427,8 @@
*/
/datum/plant_gene/trait/teleport
name = "Bluespace Activity"
+ description = "It causes people to teleport on interaction."
+ icon = "right-left"
rate = 0.1
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
@@ -483,6 +492,8 @@
*/
/datum/plant_gene/trait/maxchem
name = "Densified Chemicals"
+ description = "The reagent volume is doubled, halving the plant yield instead."
+ icon = "flask-vial"
rate = 2
trait_flags = TRAIT_HALVES_YIELD
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
@@ -503,6 +514,8 @@
/// Allows a plant to be harvested multiple times.
/datum/plant_gene/trait/repeated_harvest
name = "Perennial Growth"
+ description = "It may be harvested multiple times from the same plant."
+ icon = "cubes-stacked"
/// Don't allow replica pods to be multi harvested, please.
seed_blacklist = list(/obj/item/seeds/replicapod)
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
@@ -514,6 +527,8 @@
*/
/datum/plant_gene/trait/battery
name = "Capacitive Cell Production"
+ description = "It can work like a power cell when wired properly."
+ icon = "car-battery"
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
/// The number of cables needed to make a battery.
var/cables_needed_per_battery = 5
@@ -593,7 +608,8 @@
*/
/datum/plant_gene/trait/stinging
name = "Hypodermic Prickles"
- examine_line = "It's quite prickley."
+ description = "It stings, passing some reagents in the process."
+ icon = "syringe"
trait_ids = REAGENT_TRANSFER_ID
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
@@ -629,6 +645,8 @@
/// Explodes into reagent-filled smoke when squashed.
/datum/plant_gene/trait/smoke
name = "Gaseous Decomposition"
+ description = "It can be smashed to turn its Liquid Contents into smoke."
+ icon = "cloud"
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
/datum/plant_gene/trait/smoke/on_new_plant(obj/item/our_plant, newloc)
@@ -660,6 +678,8 @@
/// Makes the plant and its seeds fireproof. From lavaland plants.
/datum/plant_gene/trait/fire_resistance
name = "Fire Resistance"
+ description = "Makes the seeds, plant and produce fireproof."
+ icon = "fire"
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
/datum/plant_gene/trait/fire_resistance/on_new_seed(obj/item/seeds/new_seed)
@@ -681,6 +701,8 @@
/// Invasive spreading lets the plant jump to other trays, and the spreading plant won't replace plants of the same type.
/datum/plant_gene/trait/invasive
name = "Invasive Spreading"
+ description = "It attempts to spread around if not contained."
+ icon = "virus"
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
/datum/plant_gene/trait/invasive/on_new_seed(obj/item/seeds/new_seed)
@@ -745,6 +767,8 @@
*/
/datum/plant_gene/trait/brewing
name = "Auto-Distilling Composition"
+ description = "Its nutriments undergo fermentation."
+ icon = "wine-glass"
trait_ids = CONTENTS_CHANGE_ID
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
@@ -755,6 +779,8 @@
*/
/datum/plant_gene/trait/juicing
name = "Auto-Juicing Composition"
+ description = "Its nutriments turn into juice."
+ icon = "glass-water"
trait_ids = CONTENTS_CHANGE_ID
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
@@ -765,6 +791,8 @@
*/
/datum/plant_gene/trait/plant_laughter
name = "Hallucinatory Feedback"
+ description = "Makes sounds when people slip on it."
+ icon = "face-laugh-squint"
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
/// Sounds that play when this trait triggers
var/list/sounds = list('sound/items/SitcomLaugh1.ogg', 'sound/items/SitcomLaugh2.ogg', 'sound/items/SitcomLaugh3.ogg')
@@ -799,6 +827,8 @@
*/
/datum/plant_gene/trait/eyes
name = "Oculary Mimicry"
+ description = "It will watch after you."
+ icon = "eye"
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
/// Our googly eyes appearance.
var/mutable_appearance/googly
@@ -815,7 +845,8 @@
/// Makes the plant embed on thrown impact.
/datum/plant_gene/trait/sticky
name = "Prickly Adhesion"
- examine_line = "It's quite sticky."
+ description = "It sticks to people when thrown, also passing reagents if stingy."
+ icon = "bandage"
trait_ids = THROW_IMPACT_ID
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
@@ -838,6 +869,8 @@
*/
/datum/plant_gene/trait/chem_heating
name = "Exothermic Activity"
+ description = "It consumes nutriments to heat up other reagents, halving the yield."
+ icon = "temperatyre-arrow-up"
trait_ids = TEMP_CHANGE_ID
trait_flags = TRAIT_HALVES_YIELD
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
@@ -848,6 +881,8 @@
*/
/datum/plant_gene/trait/chem_cooling
name = "Endothermic Activity"
+ description = "It consumes nutriments to cool down other reagents, halving the yield."
+ icon = "temperature-arrow-down"
trait_ids = TEMP_CHANGE_ID
trait_flags = TRAIT_HALVES_YIELD
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
@@ -855,16 +890,20 @@
/// Prevents species mutation, while still allowing wild mutation harvest and Floral Somatoray species mutation. Trait acts as a tag for hydroponics.dm to recognise.
/datum/plant_gene/trait/never_mutate
name = "Prosophobic Inclination"
+ description = "The plant does not mutate normally, but may give a mutated produce."
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
/// Prevents stat mutation caused by instability. Trait acts as a tag for hydroponics.dm to recognise.
/datum/plant_gene/trait/stable_stats
name = "Symbiotic Resilience"
+ description = "High instability does not affect the plant stats."
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
/// Traits for flowers, makes plants not decompose.
/datum/plant_gene/trait/preserved
name = "Natural Insecticide"
+ description = "It does not attract ants or decompose."
+ icon = "bug-slash"
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
/datum/plant_gene/trait/preserved/on_new_plant(obj/item/our_plant, newloc)
@@ -878,6 +917,8 @@
/datum/plant_gene/trait/carnivory
name = "Obligate Carnivory"
+ description = "Pests have positive effect on the plant health."
+ icon = "spider"
/// Plant type traits. Incompatible with one another.
/datum/plant_gene/trait/plant_type
@@ -888,11 +929,16 @@
/// Weeds don't get annoyed by weeds in their tray.
/datum/plant_gene/trait/plant_type/weed_hardy
name = "Weed Adaptation"
+ description = "It is a weed that needs no nutrients and doesn't suffer from other weeds."
+ icon = "seedling"
/// Mushrooms need less light and have a minimum yield.
/datum/plant_gene/trait/plant_type/fungal_metabolism
name = "Fungal Vitality"
+ description = "It is a mushroom that needs no water, less light and can't be overtaken by weeds."
+ icon = "droplet-slash"
/// Currently unused and does nothing. Appears in strange seeds.
/datum/plant_gene/trait/plant_type/alien_properties
name ="?????"
+ icon = "reddit-alien"
diff --git a/code/modules/hydroponics/seed_extractor.dm b/code/modules/hydroponics/seed_extractor.dm
index 95e239349f2..1d418e30e67 100644
--- a/code/modules/hydroponics/seed_extractor.dm
+++ b/code/modules/hydroponics/seed_extractor.dm
@@ -166,9 +166,9 @@
* Arguments:
* * O - seed to generate the string from
*/
-/obj/machinery/seed_extractor/proc/generate_seed_string(obj/item/seeds/O)
- return "name=[O.name];lifespan=[O.lifespan];endurance=[O.endurance];maturation=[O.maturation];production=[O.production];yield=[O.yield];potency=[O.potency];instability=[O.instability]"
-
+/obj/machinery/seed_extractor/proc/generate_seed_hash(obj/item/seeds/O)
+ var/genes = list2params(O.genes)
+ return md5("[O.name][O.lifespan][O.endurance][O.maturation][O.production][O.yield][O.potency][O.instability][genes]");
/** Add Seeds Proc.
*
@@ -188,12 +188,32 @@
else if(!taking_from.atom_storage?.attempt_remove(to_add, src, silent = TRUE))
return FALSE
- var/seed_string = generate_seed_string(to_add)
- if(piles[seed_string])
- piles[seed_string] += WEAKREF(to_add)
+ var/seed_id = generate_seed_hash(to_add)
+ if(piles[seed_id])
+ piles[seed_id]["refs"] += WEAKREF(to_add)
else
- piles[seed_string] = list(WEAKREF(to_add))
-
+ var/list/seed_data = list()
+ seed_data["icon"] = sanitize_css_class_name("[initial(to_add.icon)][initial(to_add.icon_state)]")
+ seed_data["name"] = capitalize(replacetext(to_add.name,"pack of ", ""));
+ seed_data["lifespan"] = to_add.lifespan
+ seed_data["endurance"] = to_add.endurance
+ seed_data["maturation"] = to_add.maturation
+ seed_data["production"] = to_add.production
+ seed_data["yield"] = to_add.yield
+ seed_data["potency"] = to_add.potency
+ seed_data["instability"] = to_add.instability
+ seed_data["refs"] = list(WEAKREF(to_add))
+ seed_data["traits"] = list()
+ for(var/datum/plant_gene/trait/trait in to_add.genes)
+ seed_data["traits"] += trait.type
+ seed_data["reagents"] = list()
+ for(var/datum/plant_gene/reagent/reagent in to_add.genes)
+ seed_data["reagents"] += list(list(
+ "name" = reagent.name,
+ "rate" = reagent.rate
+ ))
+ seed_data["volume_mod"] = (locate(/datum/plant_gene/trait/maxchem) in to_add.genes) ? 2 : 1
+ piles[seed_id] = seed_data
return TRUE
/obj/machinery/seed_extractor/ui_state(mob/user)
@@ -206,15 +226,34 @@
ui.open()
/obj/machinery/seed_extractor/ui_data()
- var/list/V = list()
- for(var/key in piles)
- if(piles[key])
- var/len = length(piles[key])
- if(len)
- V[key] = len
-
+ var/list/seeds = list()
+ for(var/seed_id in piles)
+ if (!length(piles[seed_id]["refs"]))
+ piles.Remove(seed_id) // This shouldn't happen but still
+ continue
+ var/list/seed_data = piles[seed_id]
+ seed_data = seed_data.Copy()
+ seed_data["key"] = seed_id
+ seed_data["amount"] = length(seed_data["refs"])
+ seed_data.Remove("refs")
+ seeds += list(seed_data)
. = list()
- .["seeds"] = V
+ .["seeds"] = seeds
+
+/obj/machinery/seed_extractor/ui_static_data(mob/user)
+ var/list/data = list()
+ data["cycle_seconds"] = HYDROTRAY_CYCLE_DELAY / 10
+ data["trait_db"] = list()
+ for(var/trait_path in subtypesof(/datum/plant_gene/trait))
+ var/datum/plant_gene/trait/trait = new trait_path
+ var/trait_data = list(list(
+ "path" = trait.type,
+ "name" = trait.name,
+ "icon" = trait.icon,
+ "description" = trait.description
+ ))
+ data["trait_db"] += trait_data
+ return data
/obj/machinery/seed_extractor/ui_act(action, params)
. = ..()
@@ -222,15 +261,20 @@
return
switch(action)
- if("select")
+ if("scrap")
+ var/item = params["item"]
+ if(piles[item])
+ piles.Remove(item)
+ . = TRUE
+ if("take")
var/item = params["item"]
if(piles[item] && length(piles[item]) > 0)
- var/datum/weakref/found_seed_weakref = piles[item][1]
+ var/datum/weakref/found_seed_weakref = piles[item]["refs"][1]
var/obj/item/seeds/found_seed = found_seed_weakref.resolve()
if(!found_seed)
return
- piles[item] -= found_seed_weakref
+ piles[item]["refs"] -= found_seed_weakref
if(usr)
var/mob/user = usr
if(user.put_in_hands(found_seed))
@@ -241,3 +285,8 @@
found_seed.forceMove(drop_location())
visible_message(span_notice("[found_seed] falls onto the floor."), null, span_hear("You hear a soft clatter."), COMBAT_MESSAGE_RANGE)
. = TRUE
+
+/obj/machinery/seed_extractor/ui_assets(mob/user)
+ return list(
+ get_asset_datum(/datum/asset/spritesheet/seeds)
+ )
diff --git a/code/modules/hydroponics/unique_plant_genes.dm b/code/modules/hydroponics/unique_plant_genes.dm
index 0825350092f..c94dd08b315 100644
--- a/code/modules/hydroponics/unique_plant_genes.dm
+++ b/code/modules/hydroponics/unique_plant_genes.dm
@@ -5,6 +5,8 @@
/// Holymelon's anti-magic trait. Charges based on potency.
/datum/plant_gene/trait/anti_magic
name = "Anti-Magic Vacuoles"
+ description = "You can hide behind it from a fireball!"
+ icon = "hand-sparkles"
/// The amount of anti-magic blocking uses we have.
var/shield_uses = 1
@@ -36,6 +38,8 @@
/// Traits that turn a plant into a weapon, giving them force and effects on attack.
/datum/plant_gene/trait/attack
name = "On Attack Trait"
+ description = "It is a very dangerous weapon."
+ icon = "hand-fist"
/// The multiplier we apply to the potency to calculate force. Set to 0 to not affect the force.
var/force_multiplier = 0
/// If TRUE, our plant will degrade in force every hit until diappearing.
@@ -114,6 +118,7 @@
/// Novaflower's attack effects (sets people on fire) + degradation on attack
/datum/plant_gene/trait/attack/novaflower_attack
name = "Heated Petals"
+ description = "Hitting with it may cause things to combust."
force_multiplier = 0.2
degrades_after_hit = TRUE
degradation_noun = "petals"
@@ -134,6 +139,7 @@
/// Sunflower's attack effect (shows cute text)
/datum/plant_gene/trait/attack/sunflower_attack
name = "Bright Petals"
+ description = "Makes others feel the power on hit."
/datum/plant_gene/trait/attack/sunflower_attack/after_attack_effect(obj/item/our_plant, atom/target, mob/user, proximity_flag, click_parameters)
if(ismob(target))
@@ -159,6 +165,8 @@
/// Traits for plants with backfire effects. These are negative effects that occur when a plant is handled without gloves/unsafely.
/datum/plant_gene/trait/backfire
name = "Backfire Trait"
+ icon = "mitten"
+ description = "Be careful when holding it without protection."
/// Whether our actions are cancelled when the backfire triggers.
var/cancel_action_on_backfire = FALSE
/// A list of extra traits to check to be considered safe.
@@ -190,6 +198,7 @@
/// Rose's prick on backfire
/datum/plant_gene/trait/backfire/rose_thorns
name = "Rose Thorns"
+ description = "The stem has a lot of thorns."
traits_to_check = list(TRAIT_PIERCEIMMUNE)
/datum/plant_gene/trait/backfire/rose_thorns/backfire_effect(obj/item/our_plant, mob/living/carbon/user)
@@ -206,6 +215,7 @@
/// Novaflower's hand burn on backfire
/datum/plant_gene/trait/backfire/novaflower_heat
name = "Burning Stem"
+ description = "The stem may burn your hand."
cancel_action_on_backfire = TRUE
/datum/plant_gene/trait/backfire/novaflower_heat/backfire_effect(obj/item/our_plant, mob/living/carbon/user)
@@ -217,6 +227,7 @@
/// Normal Nettle hannd burn on backfire
/datum/plant_gene/trait/backfire/nettle_burn
name = "Stinging Stem"
+ description = "The stem may sting your hand."
/datum/plant_gene/trait/backfire/nettle_burn/backfire_effect(obj/item/our_plant, mob/living/carbon/user)
to_chat(user, span_danger("[our_plant] burns your bare hand!"))
@@ -240,6 +251,7 @@
/// Ghost-Chili heating up on backfire
/datum/plant_gene/trait/backfire/chili_heat
name = "Active Capsicum Glands"
+ description = "You may survive a cold winter with this in hand."
genes_to_check = list(/datum/plant_gene/trait/chem_heating)
/// The mob currently holding the chili.
var/datum/weakref/held_mob
@@ -295,6 +307,7 @@
/// Bluespace Tomato squashing on the user on backfire
/datum/plant_gene/trait/backfire/bluespace
name = "Bluespace Volatility"
+ description = "You may be spaced out if you hold this unprotected."
cancel_action_on_backfire = TRUE
genes_to_check = list(/datum/plant_gene/trait/squash)
@@ -311,6 +324,8 @@
/// Traits for plants that can be activated to turn into a mob.
/datum/plant_gene/trait/mob_transformation
name = "Dormant Ferocity"
+ description = "It comes to life when shaken in hand."
+ icon = "heart-pulse"
trait_ids = ATTACK_SELF_ID
/// Whether mobs spawned by this trait are dangerous or not.
var/dangerous = FALSE
@@ -443,6 +458,8 @@
/// Traiit for plants eaten in 1 bite.
/datum/plant_gene/trait/one_bite
name = "Large Bites"
+ description = "You can't hold off from eating this in one bite!"
+ icon = "drumstick-bite"
/datum/plant_gene/trait/one_bite/on_new_plant(obj/item/our_plant, newloc)
. = ..()
@@ -456,6 +473,8 @@
/// Traits for plants with a different base max_volume.
/datum/plant_gene/trait/modified_volume
name = "Deep Vesicles"
+ description = "It has more reagents than usual."
+ icon = "vials"
/// The new number we set the plant's max_volume to.
var/new_capcity = 100
@@ -481,6 +500,8 @@
/// Plants that explode when used (based on their reagent contents)
/datum/plant_gene/trait/bomb_plant
name = "Explosive Contents"
+ description = "Don't shake it, the contents may explode."
+ icon = "bomb"
trait_ids = ATTACK_SELF_ID
/datum/plant_gene/trait/bomb_plant/on_new_plant(obj/item/our_plant, newloc)
@@ -587,6 +608,8 @@
/// Can be generalized in the future to spawn any gas, but I don't think that's necessarily a good idea.
/datum/plant_gene/trait/gas_production
name = "Miasma Gas Production"
+ description = "This plant stinks when grown."
+ icon = "wind"
/// The location of our tray, if we have one.
var/datum/weakref/home_tray
/// The seed emitting gas.
diff --git a/code/modules/unit_tests/hydroponics_extractor_storage.dm b/code/modules/unit_tests/hydroponics_extractor_storage.dm
index 1145c408f02..ea2fc36c9e7 100644
--- a/code/modules/unit_tests/hydroponics_extractor_storage.dm
+++ b/code/modules/unit_tests/hydroponics_extractor_storage.dm
@@ -37,11 +37,11 @@
TEST_ASSERT_NOTNULL(apple_now_stored, "The apple seed was removed from the dummy's hands, but is not in the plant seed extractor's contents.")
// The apple seed's key should be in the extractor's "piles" list
- var/apple_seed_key = extractor.generate_seed_string(apple_now_stored)
+ var/apple_seed_key = extractor.generate_seed_hash(apple_now_stored)
TEST_ASSERT(apple_seed_key in extractor.piles, "The apple seed was added to the plant seed extractor's contents correctly, but did not register in the piles list, and is unaccessible.")
// And it should be tracked in the piles list as a weakref
- TEST_ASSERT_EQUAL(length(extractor.piles[apple_seed_key]), 1, "While 1 apple seed was added to the plant seed extractor, its weakref was not added to the piles list correctly.")
+ TEST_ASSERT_EQUAL(length(extractor.piles[apple_seed_key]["refs"]), 1, "While 1 apple seed was added to the plant seed extractor, its weakref was not added to the piles list correctly.")
// Let's test the plant bag now.
// If they fail to pick up the bag, we have an issue.
@@ -63,8 +63,8 @@
TEST_ASSERT_NOTNULL(seed_now_stored, "The plant bag transferred its [initial(seed_type.name)] somewhere, but they were not found in the plant seed extractor.")
// All keys shold be independently in the piles list
- var/stored_seed_key = extractor.generate_seed_string(seed_now_stored)
+ var/stored_seed_key = extractor.generate_seed_hash(seed_now_stored)
TEST_ASSERT(stored_seed_key in extractor.piles, "The [initial(seed_type.name)] was added to the plant seed extractor's contents correctly, but did not register in the piles list, and is unaccessible.")
// And all seeds should be tracked as weakrefs
- TEST_ASSERT_EQUAL(length(extractor.piles[stored_seed_key]), num_seeds_to_make_of_each, "While [num_seeds_to_make_of_each] [initial(seed_type.name)]s were added to the plant seed extractor, not all weakrefs were added to the piles list correctly.")
+ TEST_ASSERT_EQUAL(length(extractor.piles[stored_seed_key]["refs"]), num_seeds_to_make_of_each, "While [num_seeds_to_make_of_each] [initial(seed_type.name)]s were added to the plant seed extractor, not all weakrefs were added to the piles list correctly.")
diff --git a/tgstation.dme b/tgstation.dme
index 7c285058228..d52584019b4 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -2508,6 +2508,7 @@
#include "code\modules\asset_cache\assets\radar.dm"
#include "code\modules\asset_cache\assets\research_designs.dm"
#include "code\modules\asset_cache\assets\safe.dm"
+#include "code\modules\asset_cache\assets\seeds.dm"
#include "code\modules\asset_cache\assets\sheetmaterials.dm"
#include "code\modules\asset_cache\assets\supplypods.dm"
#include "code\modules\asset_cache\assets\tgfont.dm"
diff --git a/tgui/packages/tgui/interfaces/SeedExtractor.js b/tgui/packages/tgui/interfaces/SeedExtractor.js
deleted file mode 100644
index 0da80af8dc9..00000000000
--- a/tgui/packages/tgui/interfaces/SeedExtractor.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import { sortBy } from 'common/collections';
-import { flow } from 'common/fp';
-import { toTitleCase } from 'common/string';
-import { useBackend } from '../backend';
-import { Button, Section, Table } from '../components';
-import { Window } from '../layouts';
-
-/**
- * This method takes a seed string and splits the values
- * into an object
- */
-const splitSeedString = (text) => {
- const re = /([^;=]+)=([^;]+)/g;
- const ret = {};
- let m;
- do {
- m = re.exec(text);
- if (m) {
- ret[m[1]] = m[2] + '';
- }
- } while (m);
- return ret;
-};
-
-/**
- * This method splits up the string "name" we get for the seeds
- * and creates an object from it include the value that is the
- * ammount
- *
- * @returns {any[]}
- */
-const createSeeds = (seedStrings) => {
- const objs = Object.keys(seedStrings).map((key) => {
- const obj = splitSeedString(key);
- obj.amount = seedStrings[key];
- obj.key = key;
- obj.name = toTitleCase(obj.name.replace('pack of ', ''));
- return obj;
- });
- return flow([sortBy((item) => item.name)])(objs);
-};
-
-export const SeedExtractor = (props, context) => {
- const { act, data } = useBackend(context);
- const seeds = createSeeds(data.seeds);
- return (
-
-
-
-