diff --git a/aurorastation.dme b/aurorastation.dme
index f13e009a9b7..d1e1b228126 100644
--- a/aurorastation.dme
+++ b/aurorastation.dme
@@ -1689,6 +1689,7 @@
#include "code\modules\hydroponics\beekeeping\smoker.dm"
#include "code\modules\hydroponics\beekeeping\wax.dm"
#include "code\modules\hydroponics\seed_datums\adhomai.dm"
+#include "code\modules\hydroponics\seed_datums\aquaculture.dm"
#include "code\modules\hydroponics\seed_datums\flowers.dm"
#include "code\modules\hydroponics\seed_datums\fruits.dm"
#include "code\modules\hydroponics\seed_datums\grains.dm"
diff --git a/code/__defines/hydroponics.dm b/code/__defines/hydroponics.dm
index 5edafb92f6f..f6b89f81c77 100644
--- a/code/__defines/hydroponics.dm
+++ b/code/__defines/hydroponics.dm
@@ -1,6 +1,14 @@
//Misc
#define DEAD_PLANT_COLOUR "#C2A180"
+// Seed noun datums
+#define SEED_NOUN_SPORES "spores"
+#define SEED_NOUN_PITS "pits"
+#define SEED_NOUN_NODES "nodes"
+#define SEED_NOUN_CUTTINGS "cuttings"
+#define SEED_NOUN_SEEDS "seeds"
+#define SEED_NOUN_EGGS "eggs"
+
// Definitions for genes (trait groupings)
#define GENE_BIOCHEMISTRY "biochemistry"
#define GENE_HARDINESS "hardiness"
diff --git a/code/game/machinery/vending_items.dm b/code/game/machinery/vending_items.dm
index ab888d3b5d2..4539de56a2f 100644
--- a/code/game/machinery/vending_items.dm
+++ b/code/game/machinery/vending_items.dm
@@ -90,7 +90,7 @@
/obj/item/vending_refill/seeds
name = "resupply canister"
- vend_id = "seeds"
+ vend_id = SEED_NOUN_SEEDS
charges = 175
/obj/item/vending_refill/cutlery
diff --git a/code/game/machinery/vending_types.dm b/code/game/machinery/vending_types.dm
index 762719a8ee2..60bc612c156 100644
--- a/code/game/machinery/vending_types.dm
+++ b/code/game/machinery/vending_types.dm
@@ -584,8 +584,8 @@
desc = "When you need seeds fast!"
product_slogans = "THIS'S WHERE TH' SEEDS LIVE! GIT YOU SOME!;Hands down the best seed selection on the station!;Also certain mushroom varieties available, more for experts! Get certified today!"
product_ads = "We like plants!;Grow some crops!;Grow, baby, growww!;Aw h'yeah son!"
- icon_state = "seeds"
- vend_id = "seeds"
+ icon_state = SEED_NOUN_SEEDS
+ vend_id = SEED_NOUN_SEEDS
products = list(
/obj/item/seeds/ambrosiavulgarisseed = 3,
/obj/item/seeds/appleseed = 3,
diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm
index 9c7a6eb2f35..8ac23996a45 100644
--- a/code/modules/hydroponics/grown.dm
+++ b/code/modules/hydroponics/grown.dm
@@ -119,7 +119,7 @@
descriptors -= chosen
desc += "[(descriptor_count>1 && descriptor_count!=descriptor_num) ? "," : "" ] [chosen]"
descriptor_num--
- if(seed.seed_noun == "spores")
+ if(seed.seed_noun == SEED_NOUN_SPORES)
desc += " mushroom"
else
desc += " fruit"
diff --git a/code/modules/hydroponics/seed.dm b/code/modules/hydroponics/seed.dm
index af30676d8bc..65f035c37bc 100644
--- a/code/modules/hydroponics/seed.dm
+++ b/code/modules/hydroponics/seed.dm
@@ -7,7 +7,7 @@
var/uid // Unique identifier.
var/name // Index for global list.
var/seed_name // Plant name for seed packet.
- var/seed_noun = "seeds" // Descriptor for packet.
+ var/seed_noun = SEED_NOUN_SEEDS // Descriptor for packet.
var/display_name // Prettier name.
var/roundstart // If set, seed will not display variety number.
var/mysterious // Only used for the random seed packets.
@@ -21,8 +21,9 @@
var/kitchen_tag // Used by the reagent grinder.
var/trash_type // Garbage item produced when eaten.
var/splat_type = /obj/effect/decal/cleanable/fruit_smudge // Graffiti decal.
- var/has_mob_product
+ var/product_type = /obj/item/reagent_containers/food/snacks/grown
var/force_layer
+ var/hydrotray_only
/datum/seed/proc/setup_traits()
@@ -328,14 +329,50 @@
return impact
+/datum/seed/proc/generate_name()
+ var/prefix = ""
+ var/name = ""
+ if(prob(50)) //start with a prefix.
+ //These are various plant/mushroom genuses.
+ //I realize these might not be entirely accurate, but it could facilitate RP.
+ var/list/possible_prefixes
+ if(seed_noun == SEED_NOUN_CUTTINGS || seed_noun == SEED_NOUN_SEEDS || (seed_noun == SEED_NOUN_NODES && prob(50)))
+ possible_prefixes = list("amelanchier", "saskatoon",
+ "magnolia", "angiosperma", "osmunda", "scabiosa", "spigelia", "psydrax", "chastetree",
+ "strychnos", "treebine", "caper", "justica", "ragwortus", "everlasting", "combretum",
+ "loganiaceae", "gelsemium", "logania", "sabadilla", "neuburgia", "canthium", "rytigynia",
+ "chaste", "vitex", "cissus", "capparis", "senecio", "curry", "cycad", "liverwort", "charophyta",
+ "glaucophyte", "pinidae", "vascular", "embryophyte", "lillopsida")
+ else
+ possible_prefixes = list("bisporus", "bitorquis", "campestris", "crocodilinus", "agaricus",
+ "armillaria", "matsutake", "mellea", "ponderosa", "auricularia", "auricala",
+ "polytricha", "boletus", "badius", "edulis", "mirabilis", "zelleri",
+ "calvatia", "gigantea", "clitopilis", "prumulus", "entoloma", "abortivum",
+ "suillus", "tuber", "aestivum", "volvacea", "delica", "russula", "rozites")
+ possible_prefixes |= list("butter", "shad", "sugar", "june", "wild", "rigus", "curry", "hard", "soft", "dark", "brick", "stone", "red", "brown",
+ "black", "white", "paper", "slippery", "honey", "bitter")
+ prefix = pick(possible_prefixes)
+ var/num = rand(2,5)
+ var/list/possible_name = list("rhon", "cus", "quam", "met", "eget", "was", "reg", "zor", "fra", "rat", "sho", "ghen", "pa",
+ "eir", "lip", "sum", "lor", "em", "tem", "por", "invi", "dunt", "ut", "la", "bore", "mag", "na",
+ "al", "i", "qu", "yam", "er", "at", "sed", "di", "am", "vol", "up", "tua", "at", "ve", "ro", "eos",
+ "et", "ac", "cus")
+ for(var/i in 1 to num)
+ var/syl = pick(possible_name)
+ possible_name -= syl
+ name += syl
+ if(prefix)
+ name = "[prefix] [name]"
+ seed_name = name
+ display_name = name
+ display_name = "[name] plant"
+
//Creates a random seed. MAKE SURE THE LINE HAS DIVERGED BEFORE THIS IS CALLED.
/datum/seed/proc/randomize()
+ roundstart = FALSE
+ mysterious = TRUE
- roundstart = 0
- seed_name = "strange plant" // TODO: name generator.
- display_name = "strange plants" // TODO: name generator.
- mysterious = 1
- seed_noun = pick("spores","nodes","cuttings","seeds")
+ seed_noun = pick(SEED_NOUN_SEEDS, SEED_NOUN_PITS, SEED_NOUN_NODES, SEED_NOUN_CUTTINGS)
set_trait(TRAIT_POTENCY,rand(5,30),200,0)
set_trait(TRAIT_PRODUCT_ICON,pick(SSplants.plant_product_sprites))
@@ -486,6 +523,8 @@
set_trait(TRAIT_MATURATION,rand(5,15))
set_trait(TRAIT_PRODUCTION,get_trait(TRAIT_MATURATION)+rand(2,5))
+ generate_name()
+
//Returns a key corresponding to an entry in the global seed list.
/datum/seed/proc/get_mutant_variant()
if(!mutants || !mutants.len || get_trait(TRAIT_IMMUTABLE) > 0) return 0
@@ -609,8 +648,8 @@
consume_gasses |= new_gasses
gene.values["[TRAIT_CONSUME_GASSES]"] = null
if(GENE_METABOLISM)
- has_mob_product = gene.values["mob_product"]
- gene.values["mob_product"] = null
+ product_type = gene.values["product_type"]
+ gene.values["product_type"] = null
for(var/trait in gene.values)
set_trait(trait,gene.values["[trait]"])
@@ -639,7 +678,7 @@
if(GENE_HARDINESS)
traits_to_copy = list(TRAIT_TOXINS_TOLERANCE,TRAIT_PEST_TOLERANCE,TRAIT_WEED_TOLERANCE,TRAIT_ENDURANCE)
if(GENE_METABOLISM)
- P.values["mob_product"] = has_mob_product
+ P.values["product_type"] = product_type
traits_to_copy = list(TRAIT_REQUIRES_NUTRIENTS,TRAIT_REQUIRES_WATER,TRAIT_ALTER_TEMP)
if(GENE_VIGOUR)
traits_to_copy = list(TRAIT_PRODUCTION,TRAIT_MATURATION,TRAIT_YIELD,TRAIT_SPREAD)
@@ -700,17 +739,12 @@
spawn_seed(get_turf(user))
/datum/seed/proc/spawn_seed(var/turf/spawning_loc)
- var/obj/item/product
- if(has_mob_product)
- product = new has_mob_product(spawning_loc,name)
- else
- product = new /obj/item/reagent_containers/food/snacks/grown(spawning_loc,name)
+ var/obj/item/product = new product_type(spawning_loc, name)
if(get_trait(TRAIT_PRODUCT_COLOUR))
- if(!istype(product, /mob))
- product.color = get_trait(TRAIT_PRODUCT_COLOUR)
- if(istype(product,/obj/item/reagent_containers/food))
- var/obj/item/reagent_containers/food/food = product
- food.filling_color = get_trait(TRAIT_PRODUCT_COLOUR)
+ if(istype(product, /obj/item/reagent_containers/food))
+ var/obj/item/reagent_containers/food/food = product
+ food.color = get_trait(TRAIT_PRODUCT_COLOUR)
+ food.filling_color = get_trait(TRAIT_PRODUCT_COLOUR)
if(mysterious)
product.name += "?"
@@ -750,7 +784,7 @@
new_seed.can_self_harvest = can_self_harvest
new_seed.kitchen_tag = kitchen_tag
new_seed.trash_type = trash_type
- new_seed.has_mob_product = has_mob_product
+ new_seed.product_type = product_type
//Copy over everything else.
if(mutants) new_seed.mutants = mutants.Copy()
if(chems) new_seed.chems = chems.Copy()
diff --git a/code/modules/hydroponics/seed_datums/adhomai.dm b/code/modules/hydroponics/seed_datums/adhomai.dm
index 04125ff8d4a..df8141c1903 100644
--- a/code/modules/hydroponics/seed_datums/adhomai.dm
+++ b/code/modules/hydroponics/seed_datums/adhomai.dm
@@ -99,7 +99,7 @@
/datum/seed/mushroom/nfrihi
name = "nfrihi"
seed_name = "blizzard ears"
- seed_noun = "nodes"
+ seed_noun = SEED_NOUN_NODES
display_name = "blizzard ear stalks"
mutants = null
chems = list(/datum/reagent/nutriment/flour/nfrihi = list(10, 10))
@@ -127,7 +127,7 @@
name = "nmshaan"
seed_name = "sugar tree"
display_name = "sugar trees"
- seed_noun = "seeds"
+ seed_noun = SEED_NOUN_SEEDS
mutants = null
chems = list(/datum/reagent/sugar = list(2, 10))
kitchen_tag = "nmshaan"
diff --git a/code/modules/hydroponics/seed_datums/aquaculture.dm b/code/modules/hydroponics/seed_datums/aquaculture.dm
new file mode 100644
index 00000000000..7fae2199f68
--- /dev/null
+++ b/code/modules/hydroponics/seed_datums/aquaculture.dm
@@ -0,0 +1,52 @@
+/datum/seed/mollusc
+ name = "mollusc"
+ seed_name = "mollusc"
+ display_name = "mollusc bed"
+ product_type = /obj/item/mollusc
+ seed_noun = SEED_NOUN_EGGS
+ mutants = null
+
+/datum/seed/mollusc/New()
+ ..()
+ set_trait(TRAIT_MATURATION, 10)
+ set_trait(TRAIT_PRODUCTION, 1)
+ set_trait(TRAIT_YIELD, 3)
+ set_trait(TRAIT_POTENCY, 1)
+ set_trait(TRAIT_PRODUCT_ICON, "mollusc")
+ set_trait(TRAIT_PLANT_ICON, "mollusc")
+ set_trait(TRAIT_WATER_CONSUMPTION, 6)
+ set_trait(TRAIT_IDEAL_HEAT, 288)
+ set_trait(TRAIT_LIGHT_TOLERANCE, 6)
+ set_trait(TRAIT_PRODUCT_COLOUR, "#aaabba")
+ set_trait(TRAIT_PLANT_COLOUR, "#aaabba")
+
+/obj/item/seeds/mollusc
+ seed_type = "mollusc"
+
+/datum/seed/mollusc/clam
+ name = "clam"
+ seed_name = "clam"
+ display_name = "clam bed"
+ product_type = /obj/item/mollusc/clam
+
+/datum/seed/mollusc/clam/New()
+ ..()
+ set_trait(TRAIT_PRODUCT_COLOUR, "#9aaca6")
+ set_trait(TRAIT_PLANT_COLOUR, "#9aaca6")
+
+/obj/item/seeds/clam
+ seed_type = "clam"
+
+/datum/seed/mollusc/barnacle
+ name = "barnacle"
+ seed_name = "barnacle"
+ display_name = "barnacle bed"
+ product_type = /obj/item/mollusc/barnacle
+
+/datum/seed/mollusc/barnacle/New()
+ ..()
+ set_trait(TRAIT_PRODUCT_COLOUR, "#c1c0b6")
+ set_trait(TRAIT_PLANT_COLOUR, "#c1c0b6")
+
+/obj/item/seeds/barnacle
+ seed_type = "barnacle"
\ No newline at end of file
diff --git a/code/modules/hydroponics/seed_datums/fruits.dm b/code/modules/hydroponics/seed_datums/fruits.dm
index 409dac0e74f..045e8257b2d 100644
--- a/code/modules/hydroponics/seed_datums/fruits.dm
+++ b/code/modules/hydroponics/seed_datums/fruits.dm
@@ -306,7 +306,7 @@
/datum/seed/cherries
name = "cherry"
seed_name = "cherry"
- seed_noun = "pits"
+ seed_noun = SEED_NOUN_PITS
display_name = "cherry tree"
chems = list(/datum/reagent/nutriment = list(1,15), /datum/reagent/sugar = list(1,15), /datum/reagent/nutriment/cherryjelly = list(10,15))
kitchen_tag = "cherries"
diff --git a/code/modules/hydroponics/seed_datums/misc.dm b/code/modules/hydroponics/seed_datums/misc.dm
index 42e9ed4af80..93a4a14fb75 100644
--- a/code/modules/hydroponics/seed_datums/misc.dm
+++ b/code/modules/hydroponics/seed_datums/misc.dm
@@ -126,7 +126,7 @@
seed_noun = "node"
display_name = "diona pod"
can_self_harvest = 1
- has_mob_product = /mob/living/carbon/alien/diona
+ product_type = /mob/living/carbon/alien/diona
/datum/seed/diona/setup_traits()
..()
diff --git a/code/modules/hydroponics/seed_datums/mushrooms.dm b/code/modules/hydroponics/seed_datums/mushrooms.dm
index 6829e9c5e0b..195874489e1 100644
--- a/code/modules/hydroponics/seed_datums/mushrooms.dm
+++ b/code/modules/hydroponics/seed_datums/mushrooms.dm
@@ -4,7 +4,7 @@
/datum/seed/mushroom
name = "mushrooms"
seed_name = "chanterelle"
- seed_noun = "spores"
+ seed_noun = SEED_NOUN_SPORES
display_name = "chanterelle mushrooms"
mutants = list("reishi","amanita","plumphelmet")
chems = list(/datum/reagent/nutriment = list(1,25))
@@ -31,7 +31,7 @@
/datum/seed/koisspore
name = "koisspore"
seed_name = "kois"
- seed_noun = "spores"
+ seed_noun = SEED_NOUN_SPORES
display_name = "k'ois spores"
chems = list(
/datum/reagent/kois = list(4),
@@ -130,7 +130,7 @@
display_name = "walking mushrooms"
mutants = null
can_self_harvest = 1
- has_mob_product = /mob/living/simple_animal/mushroom
+ product_type = /mob/living/simple_animal/mushroom
/datum/seed/mushroom/plump/walking/setup_traits()
..()
diff --git a/code/modules/hydroponics/seed_datums/tomato.dm b/code/modules/hydroponics/seed_datums/tomato.dm
index 8e3d85009ec..894d6119fd3 100644
--- a/code/modules/hydroponics/seed_datums/tomato.dm
+++ b/code/modules/hydroponics/seed_datums/tomato.dm
@@ -5,7 +5,7 @@
name = "tomato"
seed_name = "tomato"
display_name = "tomato plant"
- mutants = list("bluetomato","bloodtomato") // no killer :(
+ mutants = list("bluetomato","bloodtomato") // no killer :[
chems = list(/datum/reagent/nutriment = list(1,10), /datum/reagent/drink/tomatojuice = list(10,10))
kitchen_tag = "tomato"
@@ -49,7 +49,7 @@
display_name = "killer tomato plant"
mutants = null
can_self_harvest = 1
- has_mob_product = /mob/living/simple_animal/tomato
+ product_type = /mob/living/simple_animal/tomato
/datum/seed/tomato/killer/setup_traits()
..()
diff --git a/code/modules/hydroponics/seed_packets.dm b/code/modules/hydroponics/seed_packets.dm
index ab3aa4ac008..bc347c37c51 100644
--- a/code/modules/hydroponics/seed_packets.dm
+++ b/code/modules/hydroponics/seed_packets.dm
@@ -23,13 +23,14 @@ var/global/list/plant_seed_sprites = list()
//Updates strings and icon appropriately based on seed datum.
/obj/item/seeds/proc/update_appearance()
- if(!seed) return
+ if(!seed)
+ return
// Update icon.
cut_overlays()
- var/is_seeds = ((seed.seed_noun in list("seeds","pits","nodes")) ? 1 : 0)
+ var/is_seeds = ((seed.seed_noun in list(SEED_NOUN_SEEDS, SEED_NOUN_PITS, SEED_NOUN_NODES)) ? 1 : 0)
var/image/seed_mask
- var/seed_base_key = "base-[is_seeds ? seed.get_trait(TRAIT_PLANT_COLOUR) : "spores"]"
+ var/seed_base_key = "base-[is_seeds ? seed.get_trait(TRAIT_PLANT_COLOUR) : SEED_NOUN_SPORES]"
if(plant_seed_sprites[seed_base_key])
seed_mask = plant_seed_sprites[seed_base_key]
else
@@ -52,10 +53,10 @@ var/global/list/plant_seed_sprites = list()
if(is_seeds)
src.name = "packet of [seed.seed_name] [seed.seed_noun]"
- src.desc = "It has a picture of [seed.display_name] on the front."
+ src.desc = "It has a picture of \a [seed.display_name] on the front."
else
src.name = "sample of [seed.seed_name] [seed.seed_noun]"
- src.desc = "It's labelled as coming from [seed.display_name]."
+ src.desc = "It's labelled as coming from \a [seed.display_name]."
/obj/item/seeds/examine(mob/user)
..(user)
@@ -63,7 +64,7 @@ var/global/list/plant_seed_sprites = list()
to_chat(user, "It's tagged as variety #[seed.uid].")
/obj/item/seeds/cutting
- name = "cuttings"
+ name = SEED_NOUN_CUTTINGS
desc = "Some plant cuttings."
/obj/item/seeds/cutting/update_appearance()
diff --git a/code/modules/hydroponics/seed_storage.dm b/code/modules/hydroponics/seed_storage.dm
index ecf9a57994d..160d9d5b888 100644
--- a/code/modules/hydroponics/seed_storage.dm
+++ b/code/modules/hydroponics/seed_storage.dm
@@ -21,7 +21,7 @@
name = "Seed storage"
desc = "It stores, sorts, and dispenses seeds."
icon = 'icons/obj/vending.dmi'
- icon_state = "seeds"
+ icon_state = SEED_NOUN_SEEDS
density = 1
anchored = 1
use_power = 1
@@ -91,7 +91,10 @@
/obj/item/seeds/wheatseed = 3,
/obj/item/seeds/whitebeetseed = 3,
/obj/item/seeds/wulumunushaseed = 2,
- /obj/item/seeds/ylpha = 2
+ /obj/item/seeds/ylpha = 2,
+ /obj/item/seeds/clam = 15,
+ /obj/item/seeds/barnacle = 15,
+ /obj/item/seeds/mollusc = 15
)
/obj/machinery/seed_storage/xenobotany
diff --git a/code/modules/hydroponics/spreading/spreading.dm b/code/modules/hydroponics/spreading/spreading.dm
index 539f0c7b6f1..50ebccbd04e 100644
--- a/code/modules/hydroponics/spreading/spreading.dm
+++ b/code/modules/hydroponics/spreading/spreading.dm
@@ -106,8 +106,8 @@
growth_type = 2 // Vines by default.
if(seed.get_trait(TRAIT_CARNIVOROUS) == 2)
growth_type = 1 // WOOOORMS.
- else if(!(seed.seed_noun in list("seeds","pits")))
- if(seed.seed_noun == "nodes")
+ else if(!(seed.seed_noun in list(SEED_NOUN_SEEDS,SEED_NOUN_PITS)))
+ if(seed.seed_noun == SEED_NOUN_NODES)
growth_type = 3 // Biomass
else
growth_type = 4 // Mold
diff --git a/code/modules/hydroponics/trays/tray.dm b/code/modules/hydroponics/trays/tray.dm
index 959664a907d..d9ef3522256 100644
--- a/code/modules/hydroponics/trays/tray.dm
+++ b/code/modules/hydroponics/trays/tray.dm
@@ -1,5 +1,6 @@
/obj/machinery/portable_atmospherics/hydroponics
name = "hydroponics tray"
+ desc = "A mechanical basin designed to nurture plants and other aquatic life. It has various useful sensors."
icon = 'icons/obj/hydroponics_machines.dmi'
icon_state = "hydrotray3"
density = 1
@@ -151,8 +152,7 @@
return ..()
/obj/machinery/portable_atmospherics/hydroponics/attack_ghost(var/mob/abstract/observer/user)
-
- if(!(harvest && seed && seed.has_mob_product))
+ if(!(harvest && seed && ispath(seed.product_type, /mob)))
return
var/datum/ghosttrap/plant/G = get_ghost_trap("living plant")
@@ -328,7 +328,8 @@
//Clears out a dead plant.
/obj/machinery/portable_atmospherics/hydroponics/proc/remove_dead(var/mob/user)
- if(!user || !dead) return
+ if(!user || !dead || !seed)
+ return
if(closed_system)
to_chat(user, "You can't remove the dead plant while the lid is shut.")
@@ -522,6 +523,10 @@
qdel(O)
return
+ if(S.seed.hydrotray_only && !mechanical)
+ to_chat(user, SPAN_WARNING("This packet can only be planted in a hydroponics tray."))
+ return
+
to_chat(user, "You plant the [S.seed.seed_name] [S.seed.seed_noun].")
lastproduce = 0
seed = S.seed //Grab the seed datum.
diff --git a/code/modules/hydroponics/trays/tray_soil.dm b/code/modules/hydroponics/trays/tray_soil.dm
index 01790ba055b..802691bc385 100644
--- a/code/modules/hydroponics/trays/tray_soil.dm
+++ b/code/modules/hydroponics/trays/tray_soil.dm
@@ -1,5 +1,6 @@
/obj/machinery/portable_atmospherics/hydroponics/soil
name = "soil"
+ desc = "A mound of earth. You could plant some seeds here."
icon_state = "soil"
density = 0
use_power = 0
@@ -47,6 +48,7 @@
// Hence using a blank icon.
/obj/machinery/portable_atmospherics/hydroponics/soil/invisible
name = "plant"
+ desc = null
icon = 'icons/obj/seeds.dmi'
icon_state = "blank"
diff --git a/code/modules/random_map/drop/drop_types.dm b/code/modules/random_map/drop/drop_types.dm
index 9c9a5e9f293..c7d06804da5 100644
--- a/code/modules/random_map/drop/drop_types.dm
+++ b/code/modules/random_map/drop/drop_types.dm
@@ -61,7 +61,7 @@ var/global/list/datum/supply_drop_loot/supply_drop
/obj/item/gun/projectile/automatic/rifle/z8)
/datum/supply_drop_loot/seeds
- name = "Seeds"
+ name = SEED_NOUN_SEEDS
container = /obj/structure/closet/crate
/datum/supply_drop_loot/seeds/New()
..()
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm
index 5be98eef7c2..91ecc43e541 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm
@@ -229,6 +229,11 @@
color = "#f5f4e9"
taste_description = "fish"
+/datum/reagent/nutriment/protein/seafood/mollusc
+ name = "Mollusc Protein"
+ taste_description = "cold, bitter slime"
+ hydration_factor = 6
+
/datum/reagent/nutriment/protein/egg // Also bad for skrell.
name = "Egg Yolk"
color = "#FFFFAA"
diff --git a/code/modules/reagents/reagent_containers/food/snacks/fish.dm b/code/modules/reagents/reagent_containers/food/snacks/fish.dm
index ad83a24a84d..c5e28f42e1d 100644
--- a/code/modules/reagents/reagent_containers/food/snacks/fish.dm
+++ b/code/modules/reagents/reagent_containers/food/snacks/fish.dm
@@ -22,3 +22,82 @@
/obj/item/reagent_containers/food/snacks/fish/fishfillet
name = "fish fillet"
desc = "A fillet of fish."
+
+/obj/item/reagent_containers/food/snacks/fish/mollusc
+ name = "slimy meat"
+ desc = "Some slimy meat from clams or molluscs."
+ fish_type = "mollusc"
+ reagents_to_add = list(/datum/reagent/nutriment/protein/seafood/mollusc = 3)
+
+/obj/item/reagent_containers/food/snacks/fish/mollusc/clam
+ fish_type = "clam"
+
+/obj/item/reagent_containers/food/snacks/fish/mollusc/barnacle
+ fish_type = "barnacle"
+
+// Molluscs!
+/obj/item/trash/mollusc_shell
+ name = "mollusc shell"
+ icon = 'icons/obj/molluscs.dmi'
+ icon_state = "mollusc_shell"
+ desc = "The cracked shell of an unfortunate mollusc."
+
+/obj/item/trash/mollusc_shell/clam
+ name = "clamshell"
+ icon_state = "clam_shell"
+
+/obj/item/trash/mollusc_shell/barnacle
+ name = "barnacle shell"
+ icon_state = "barnacle_shell"
+
+/obj/item/mollusc
+ name = "mollusc"
+ w_class = ITEMSIZE_TINY
+ desc = "A small slimy mollusc. Fresh!"
+ desc_info = "You will need a sharp or edged implement to pry it open. You can also try opening it in your hand if you're strong enough."
+ icon = 'icons/obj/molluscs.dmi'
+ icon_state = "mollusc"
+ var/meat_type = /obj/item/reagent_containers/food/snacks/fish/mollusc
+ var/shell_type = /obj/item/trash/mollusc_shell
+
+/obj/item/mollusc/barnacle
+ name = "barnacle"
+ desc = "A hull barnacle, probably freshly scraped off a spaceship."
+ icon_state = "barnacle"
+ meat_type = /obj/item/reagent_containers/food/snacks/fish/mollusc/barnacle
+ shell_type = /obj/item/trash/mollusc_shell/barnacle
+
+/obj/item/mollusc/clam
+ name = "clam"
+ desc = "A free-ranging space clam."
+ icon_state = "clam"
+ meat_type = /obj/item/reagent_containers/food/snacks/fish/mollusc/clam
+ shell_type = /obj/item/trash/mollusc_shell/clam
+
+/obj/item/mollusc/proc/crack_shell(var/mob/user)
+ playsound(loc, /decl/sound_category/pickaxe_sound, 40, TRUE)
+ if(user && loc == user)
+ user.drop_from_inventory(src)
+ if(meat_type)
+ var/obj/item/meat = new meat_type(get_turf(src))
+ if(user)
+ user.put_in_hands(meat)
+ if(shell_type)
+ var/obj/item/shell = new shell_type(get_turf(src))
+ if(user)
+ user.put_in_hands(shell)
+ qdel(src)
+
+/obj/item/mollusc/attack_self(mob/user)
+ if(isvaurca(user) || isipc(user) || isunathi(user))
+ user.visible_message("[user] cracks open \the [src] with their hands.", SPAN_NOTICE("You crack open \the [src] with your hands."))
+ crack_shell(user)
+ return
+ return ..()
+
+/obj/item/mollusc/attackby(var/obj/item/thing, var/mob/user)
+ if(thing.sharp || thing.edge)
+ user.visible_message("[user] cracks open \the [src] with \the [thing].", SPAN_NOTICE("You crack open \the [src] with \the [thing]."))
+ crack_shell(user)
+ return
+ return ..()
diff --git a/html/changelogs/geeves-aquaponics.yml b/html/changelogs/geeves-aquaponics.yml
new file mode 100644
index 00000000000..45251521679
--- /dev/null
+++ b/html/changelogs/geeves-aquaponics.yml
@@ -0,0 +1,7 @@
+author: Geeves
+
+delete-after: True
+
+changes:
+ - rscadd: "Ported Aquaponics and Molluscs from Nebula."
+ - rscadd: "Ported randomized strange plant names."
diff --git a/icons/obj/hydroponics_growing.dmi b/icons/obj/hydroponics_growing.dmi
index 192119a44f3..e6970fe1f14 100644
Binary files a/icons/obj/hydroponics_growing.dmi and b/icons/obj/hydroponics_growing.dmi differ
diff --git a/icons/obj/hydroponics_products.dmi b/icons/obj/hydroponics_products.dmi
index d7926cf9c8b..78fb1064a88 100644
Binary files a/icons/obj/hydroponics_products.dmi and b/icons/obj/hydroponics_products.dmi differ
diff --git a/icons/obj/molluscs.dmi b/icons/obj/molluscs.dmi
new file mode 100644
index 00000000000..6c9cfea125e
Binary files /dev/null and b/icons/obj/molluscs.dmi differ
diff --git a/icons/obj/seeds.dmi b/icons/obj/seeds.dmi
index fd33de118ef..09be91ba7a7 100644
Binary files a/icons/obj/seeds.dmi and b/icons/obj/seeds.dmi differ