diff --git a/code/modules/hydroponics/grafts.dm b/code/modules/hydroponics/grafts.dm
index 105cd40ec29..b3cfbb825c8 100644
--- a/code/modules/hydroponics/grafts.dm
+++ b/code/modules/hydroponics/grafts.dm
@@ -1,6 +1,6 @@
-/*
-A new subsystem for hydroponics, as a way to share specific traits into plants, as a way to phase out the DNA manipulator.
-*/
+/**
+ *A new subsystem for hydroponics, as a way to share specific traits into plants, as a way to phase out the DNA manipulator.
+ */
/obj/item/graft
name = "plant graft"
desc = "A carefully cut graft off of a freshly grown plant. Can be grafted onto a plant in order to share unique plant traits onto a plant."
@@ -29,9 +29,9 @@ A new subsystem for hydroponics, as a way to share specific traits into plants,
to_chat(user, get_graft_text())
return ..()
-/*
-Adds text to the plant analyzer which describes the graft's parent plant and any stored trait it has, if any.
-*/
+/**
+ *Adds text to the plant analyzer which describes the graft's parent plant and any stored trait it has, if any.
+ */
/obj/item/graft/proc/get_graft_text()
var/text = "- Plant Graft -\n"
if(parent_seed)
diff --git a/code/modules/hydroponics/hydroitemdefines.dm b/code/modules/hydroponics/hydroitemdefines.dm
index 7c063500f6a..59a3769cfe6 100644
--- a/code/modules/hydroponics/hydroitemdefines.dm
+++ b/code/modules/hydroponics/hydroitemdefines.dm
@@ -185,6 +185,25 @@
attack_verb = list("slashed", "sliced", "cut", "clawed")
hitsound = 'sound/weapons/bladeslice.ogg'
+/obj/item/geneshears
+ name = "Botanogenetic Plant Shears"
+ desc = "A high tech, high fidelity pair of plant shears, capable of cutting genetic traits out of a plant."
+ icon = 'icons/obj/hydroponics/equipment.dmi'
+ icon_state = "genesheers"
+ item_state = "secateurs"
+ lefthand_file = 'icons/mob/inhands/equipment/hydroponics_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/hydroponics_righthand.dmi'
+ flags_1 = CONDUCT_1
+ force = 10
+ throwforce = 8
+ w_class = WEIGHT_CLASS_SMALL
+ slot_flags = ITEM_SLOT_BELT
+ material_flags = MATERIAL_NO_EFFECTS
+ custom_materials = list(/datum/material/iron=4000, /datum/material/uranium=1500, /datum/material/gold=500)
+ attack_verb = list("slashed", "sliced", "cut")
+ hitsound = 'sound/weapons/bladeslice.ogg'
+
+
// *************************************
// Nutrient defines for hydroponics
// *************************************
diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm
index d50fcc6d38d..a1c23480c67 100644
--- a/code/modules/hydroponics/hydroponics.dm
+++ b/code/modules/hydroponics/hydroponics.dm
@@ -1,6 +1,7 @@
#define TRAY_NAME_UPDATE name = myseed ? "[initial(name)] ([myseed.plantname])" : initial(name)
#define YIELD_WEED_MINIMUM 3
#define YIELD_WEED_MAXIMUM 10
+#define STATIC_NUTRIENT_CAPACITY 10
/obj/machinery/hydroponics
@@ -62,7 +63,7 @@
/obj/machinery/hydroponics/Initialize()
//ALRIGHT YOU DEGENERATES. YOU HAD REAGENT HOLDERS FOR AT LEAST 4 YEARS AND NONE OF YOU MADE HYDROPONICS TRAYS HOLD NUTRIENT CHEMS INSTEAD OF USING "Points".
//SO HERE LIES THE "nutrilevel" VAR. IT'S DEAD AND I PUT IT OUT OF IT'S MISERY. USE "reagents" INSTEAD. ~ArcaneMusic, accept no substitutes.
- create_reagents(10)
+ create_reagents(20)
. = ..()
@@ -78,7 +79,7 @@
for (var/obj/item/stock_parts/manipulator/M in component_parts)
rating = M.rating
maxwater = tmp_capacity * 50 // Up to 300
- maxnutri = tmp_capacity * 5 // Up to 30
+ maxnutri = (tmp_capacity * 5) + STATIC_NUTRIENT_CAPACITY // Up to 50 Maximum
reagents.maximum_volume = maxnutri
nutridrain = 1/rating
@@ -150,7 +151,6 @@
update_icon()
else if(self_sustaining)
- nutridrain = min(0.5, nutridrain) //By just upgrading your trays you will outpace your trays sustainability.
adjustWater(rand(1,2))
adjustWeeds(-1)
adjustPests(-1)
@@ -169,7 +169,10 @@
//Nutrients//////////////////////////////////////////////////////////////
// Nutrients deplete at a constant rate, since new nutrients can boost stats far easier.
apply_chemicals(lastuser)
- reagents.remove_any(nutridrain)
+ if(self_sustaining)
+ reagents.remove_any(min(0.5, nutridrain))
+ else
+ reagents.remove_any(nutridrain)
// Lack of nutrients hurts non-weeds
if(reagents.total_volume <= 0 && !myseed.get_gene(/datum/plant_gene/trait/plant_type/weed_hardy))
@@ -252,10 +255,9 @@
//This is where stability mutations exist now.
switch(myseed.instability)
- if(80 to 100)
- if(prob(20))
- mutate(0, 0, 0, 0, 0, 0, 0, 10, 0) //Exceedingly low odds of gaining a trait.
- if(60 to 79)
+ if(100 to 80)
+ mutate(0, 0, 0, 0, 0, 0, 0, 2, 0) //Exceedingly low odds of gaining a trait.
+ if(79 to 60)
if(prob((myseed.instability)/2) && !self_sustaining)
mutatespecie()
myseed.instability = myseed.instability/2
@@ -382,11 +384,10 @@
else
. += "It's empty."
- if(!self_sustaining)
- . += "Water: [waterlevel]/[maxwater].\n"+\
- "Nutrient: [reagents.total_volume]/[maxnutri]."
- else
- . += "It doesn't require any water or nutrients."
+ . += "Water: [waterlevel]/[maxwater].\n"+\
+ "Nutrient: [reagents.total_volume]/[maxnutri]."
+ if(self_sustaining)
+ . += "The tray's autogrow is active, protecting it from species mutations, weeds, and pests."
if(weedlevel >= 5)
to_chat(user, "It's filled with weeds!")
@@ -394,8 +395,11 @@
to_chat(user, "It's filled with tiny worms!")
to_chat(user, "" )
-
-/obj/machinery/hydroponics/proc/weedinvasion() // If a weed growth is sufficient, this happens.
+/**
+ * What happens when a tray's weeds grow too large.
+ * Plants a new weed in an empty tray, then resets the tray.
+ */
+/obj/machinery/hydroponics/proc/weedinvasion()
dead = FALSE
var/oldPlantName
if(myseed) // In case there's nothing in the tray beforehand
@@ -487,8 +491,11 @@
else
to_chat(usr, "The few weeds in [src] seem to react, but only for a moment...")
-
-/obj/machinery/hydroponics/proc/plantdies() // OH NOES!!!!! I put this all in one function to make things easier
+/**
+ * Plant Death Proc.
+ * Cleans up various stats for the plant upon death, including pests, harvestability, and plant health.
+ */
+/obj/machinery/hydroponics/proc/plantdies()
plant_health = 0
harvest = FALSE
pestlevel = 0 // Pests die
@@ -497,6 +504,12 @@
update_icon()
dead = TRUE
+/**
+ * Plant Cross-Pollination.
+ * Checks all plants in the tray's oview range, then averages out the seed's potency, instability, and yield values.
+ * If the seed's instability is >= 20, the seed donates one of it's reagents to that nearby plant.
+ * * Range - The Oview range of trays to which to look for plants to donate reagents.
+ */
/obj/machinery/hydroponics/proc/pollinate(var/range = 1)
for(var/obj/machinery/hydroponics/T in oview(src, range))
if(T.myseed && !T.dead)
@@ -509,9 +522,13 @@
if(reagent_gene.can_add(myseed))
myseed.genes += reagent_gene
myseed.reagents_from_genes()
- return
-
+ continue
+/**
+ * Pest Mutation Proc.
+ * When a tray is mutated with high pest values, it will spawn spiders.
+ * * User - Person who last added chemicals to the tray for logging purposes.
+ */
/obj/machinery/hydroponics/proc/mutatepest(mob/user)
if(pestlevel > 5)
message_admins("[ADMIN_LOOKUPFLW(user)] last altered a hydro tray's contents which spawned spiderlings")
@@ -536,6 +553,10 @@
to_chat(user, "[reagent_source] is empty!")
return 1
+ if(reagents.total_volume >= reagents.maximum_volume)
+ to_chat(user, "[src] is full.")
+ return
+
var/list/trays = list(src)//makes the list just this in cases of syringes and compost etc
var/target = myseed ? myseed.plantname : src
var/visi_msg = ""
@@ -619,7 +640,6 @@
var/list/text_string = myseed.get_analyzer_text()
if(text_string)
to_chat(user, text_string)
- return
else
to_chat(user, "No plant found.")
to_chat(user, "- Weed level: [weedlevel] / 10")
@@ -660,6 +680,37 @@
adjustHealth(-5)
return
+ else if(istype(O, /obj/item/geneshears))
+ if(!myseed)
+ to_chat(user, "The tray is empty.")
+ return
+ if(plant_health <= 15)
+ to_chat(user, "This plant looks too unhealty to be sheared right now.")
+ return
+
+ var/list/current_traits = list()
+ for(var/datum/plant_gene/gene in myseed.genes)
+ if(istype(gene, /datum/plant_gene/core) || (istype(gene,/datum/plant_gene/trait/plant_type)) || islist(gene))
+ continue
+ if(!(gene.mutability_flags & PLANT_GENE_REMOVABLE) || !(gene.mutability_flags & PLANT_GENE_EXTRACTABLE))
+ continue //No bypassing unextractable or essential genes.
+ current_traits[gene.name] = gene
+ var/removed_trait = (input(user, "Select a trait to remove from the [myseed.plantname].", "Plant Trait Removal") as null|anything in sortList(current_traits))
+ if(removed_trait == null)
+ return
+ if(!user.canUseTopic(src, BE_CLOSE))
+ return
+ for(var/datum/plant_gene/gene in myseed.genes)
+ if(gene.name == removed_trait)
+ if(myseed.genes.Remove(gene))
+ qdel(gene)
+ break
+ myseed.reagents_from_genes()
+ adjustHealth(-15)
+ to_chat(user, "You carefully shear the genes off of the [myseed.plantname], but leaving the plant looking a bit weak.")
+ update_icon()
+ return
+
else if(istype(O, /obj/item/graft))
var/obj/item/graft/snip = O
var/datum/plant_gene/trait/new_trait = snip.stored_trait
@@ -765,6 +816,8 @@
if(!powered())
to_chat(user, "[name] has no power.")
return
+ if(!anchored)
+ return
self_sustaining = !self_sustaining
idle_power_usage = self_sustaining ? 5000 : 0
to_chat(user, "You [self_sustaining ? "activate" : "deactivated"] [src]'s autogrow function[self_sustaining ? ", maintaining the tray's health while using high amounts of power" : ""].")
@@ -777,6 +830,13 @@
reagents.clear_reagents()
to_chat(user, "You empty [src]'s nutrient tank.")
+/**
+ * Update Tray Proc
+ * Handles plant harvesting on the tray side, by clearing the sead, names, description, and dead stat.
+ * Shuts off autogrow if enabled.
+ * Sends messages to the cleaer about plants harvested, or if nothing was harvested at all.
+ * * User - The mob who clears the tray.
+ */
/obj/machinery/hydroponics/proc/update_tray(mob/user)
harvest = FALSE
lastproduce = age
@@ -798,37 +858,61 @@
self_sustaining = FALSE
update_icon()
-/// Tray Setters - The following procs adjust the tray or plants variables, and make sure that the stat doesn't go out of bounds.///
+/// Tray Setters - The following procs adjust the tray or plants variables, and make sure that the stat doesn't go out of bounds.
+/**
+ * Adjust water.
+ * Raises or lowers tray water values by a set value. Adding water will dillute toxicity from the tray.
+ * * adjustamt - determines how much water the tray will be adjusted upwards or downwards.
+ */
/obj/machinery/hydroponics/proc/adjustWater(adjustamt)
waterlevel = clamp(waterlevel + adjustamt, 0, maxwater)
if(adjustamt>0)
adjustToxic(-round(adjustamt/4))//Toxicity dilutation code. The more water you put in, the lesser the toxin concentration.
+/**
+ * Adjust Health.
+ * Raises the tray's plant_health stat by a given amount, with total health determined by the seed's endurance.
+ * * adjustamt - Determines how much the plant_health will be adjusted upwards or downwards.
+ */
/obj/machinery/hydroponics/proc/adjustHealth(adjustamt)
if(myseed && !dead)
plant_health = clamp(plant_health + adjustamt, 0, myseed.endurance)
+/**
+ * Adjust Health.
+ * Raises the plant's plant_health stat by a given amount, with total health determined by the seed's endurance.
+ * * adjustamt - Determines how much the plant_health will be adjusted upwards or downwards.
+ */
/obj/machinery/hydroponics/proc/adjustToxic(adjustamt)
toxic = clamp(toxic + adjustamt, 0, 100)
+/**
+ * Adjust Pests.
+ * Raises the tray's pest level stat by a given amount.
+ * * adjustamt - Determines how much the pest level will be adjusted upwards or downwards.
+ */
/obj/machinery/hydroponics/proc/adjustPests(adjustamt)
pestlevel = clamp(pestlevel + adjustamt, 0, 10)
+/**
+ * Adjust Weeds.
+ * Raises the plant's weed level stat by a given amount.
+ * * adjustamt - Determines how much the weed level will be adjusted upwards or downwards.
+ */
/obj/machinery/hydroponics/proc/adjustWeeds(adjustamt)
weedlevel = clamp(weedlevel + adjustamt, 0, 10)
+/**
+ * Spawn Plant.
+ * Upon using strange reagent on a tray, it will spawn a killer tomato or killer tree at random.
+ */
/obj/machinery/hydroponics/proc/spawnplant() // why would you put strange reagent in a hydro tray you monster I bet you also feed them blood
var/list/livingplants = list(/mob/living/simple_animal/hostile/tree, /mob/living/simple_animal/hostile/killertomato)
var/chosen = pick(livingplants)
var/mob/living/simple_animal/hostile/C = new chosen
C.faction = list("plants")
-/obj/machinery/hydroponics/proc/become_self_sufficient() // Ambrosia Gaia effect
- visible_message("[src] begins to glow with a beautiful light!")
- self_sustaining = TRUE
- update_icon()
-
//////////////////////////////////////////////////////////////////////////////////
/obj/machinery/hydroponics/irrigated //Pre-Irrigated trays! Maybe map a couple on each map, just so they get used?
using_irrigation = TRUE
diff --git a/code/modules/hydroponics/hydroponics_chemreact.dm b/code/modules/hydroponics/hydroponics_chemreact.dm
index 4f460458c43..a4ef78a21fe 100644
--- a/code/modules/hydroponics/hydroponics_chemreact.dm
+++ b/code/modules/hydroponics/hydroponics_chemreact.dm
@@ -6,11 +6,11 @@
///Contains the reagents within the tray.
if(myseed)
myseed.on_chem_reaction(reagents) //In case seeds have some special interactions with special chems, currently only used by vines
- //FINE WE'LL DO IT THIS WAY.
for(var/c in reagents.reagent_list)
var/datum/reagent/chem = c
chem.on_hydroponics_apply(myseed, reagents, src, user)
+
/obj/machinery/hydroponics/proc/mutation_roll(mob/user)
switch(rand(100))
if(91 to 100)
diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm
index 75cb45bd121..f3e9e434af8 100644
--- a/code/modules/hydroponics/seeds.dm
+++ b/code/modules/hydroponics/seeds.dm
@@ -536,13 +536,3 @@
for(var/i in 1 to amount_random_reagents)
var/datum/reagent/chemical = pick(reagents_add)
qdel(chemical)
-
-/obj/item/seeds/proc/remove_random_traits(lower = 0, upper = 2)
- var/list/genepool = list()
- var/amount_random_traits = rand(lower, upper)
- for(var/datum/plant_gene/trait in genes)
- genepool += trait
-
- for(var/i in 1 to amount_random_traits)
- var/datum/plant_gene/planted_gene = pick(genepool)
- qdel(planted_gene)
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index 761ae035b11..c0c466e68d9 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -972,41 +972,3 @@
to_chat(M, "Ah, what was that? You thought you heard something...")
M.confused += 5
return ..()
-
-/datum/reagent/toxin/plantthinner
- name = "Plant Thinner"
- description = "Contains a chemical that can help in weeding out unwanted chemical traits in plants."
- color = "#3b7269" // rgb: 127, 132, 0
- toxpwr = 0.6
- taste_description = "burnt grass"
-
-/datum/reagent/plantthinner/on_mob_life(mob/living/carbon/M)
- M.adjustOrganLoss(ORGAN_SLOT_LUNGS, 0.3)
- M.confused += 1
- return ..()
-
-//It's paint thinner, for plants!
-/datum/reagent/plantthinner/on_hydroponics_apply(obj/item/seeds/myseed, datum/reagents/chems, obj/machinery/hydroponics/mytray, mob/user)
- . = ..()
- if(prob(40))
- myseed.remove_random_reagents(1,1)
- mytray.adjustToxic(3)
-
-/datum/reagent/toxin/plantthinner/trait
- name = "Trait Thinner"
- description = "Contains a stronger variant of plant thinner, capable of genetically stunting certain traits out of plants."
- color = "#31100a" // rgb: 127, 132, 0
- toxpwr = 1.5
- taste_description = "burnt hair"
-
-/datum/reagent/plantthinner/trait/on_mob_life(mob/living/carbon/M)
- M.adjustOrganLoss(ORGAN_SLOT_LUNGS, 1.1)
- M.confused += 3
- return ..()
-
-//It's paint thinner, for plants!
-/datum/reagent/plantthinner/trait/on_hydroponics_apply(obj/item/seeds/myseed, datum/reagents/chems, obj/machinery/hydroponics/mytray, mob/user)
- . = ..()
- if(prob(40))
- myseed.remove_random_traits(1,1)
- mytray.adjustToxic(6)
diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm
index 285e057d338..af6bfb29029 100644
--- a/code/modules/reagents/chemistry/recipes/others.dm
+++ b/code/modules/reagents/chemistry/recipes/others.dm
@@ -49,6 +49,15 @@
for(var/i = 1, i <= created_volume, i++)
new /obj/item/stack/sheet/mineral/gold(location)
+/datum/chemical_reaction/uraniumsolidification
+ required_reagents = list(/datum/reagent/consumable/frostoil = 5, /datum/reagent/uranium = 20, /datum/reagent/potassium = 1)
+ mob_react = FALSE
+
+/datum/chemical_reaction/uraniumsolidification/on_reaction(datum/reagents/holder, created_volume)
+ var/location = get_turf(holder.my_atom)
+ for(var/i = 1, i <= created_volume, i++)
+ new /obj/item/stack/sheet/mineral/uranium(location)
+
/datum/chemical_reaction/capsaicincondensation
results = list(/datum/reagent/consumable/condensedcapsaicin = 5)
required_reagents = list(/datum/reagent/consumable/capsaicin = 1, /datum/reagent/consumable/ethanol = 5)
diff --git a/code/modules/research/designs/tool_designs.dm b/code/modules/research/designs/tool_designs.dm
index bb48b7676fc..3eb106ce1ef 100644
--- a/code/modules/research/designs/tool_designs.dm
+++ b/code/modules/research/designs/tool_designs.dm
@@ -93,6 +93,16 @@
category = list("Tool Designs")
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_CARGO
+/datum/design/geneshears
+ name = "Botanogenetic Plant Shears"
+ desc = "A high tech, high fidelity pair of plant shears, capable of cutting genetic traits out of a plant."
+ id = "gene_shears"
+ build_path = /obj/item/geneshears
+ build_type = PROTOLATHE
+ materials = list(/datum/material/iron=4000, /datum/material/uranium=1500, /datum/material/silver=500)
+ category = list("Tool Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_SERVICE
+
/////////////////////////////////////////
//////////////Alien Tools////////////////
/////////////////////////////////////////
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index b48997565ab..437db42f585 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -563,7 +563,7 @@
id = "exp_tools"
display_name = "Experimental Tools"
description = "Highly advanced tools."
- design_ids = list("exwelder", "jawsoflife", "handdrill", "laserscalpel", "mechanicalpinches", "searingtool")
+ design_ids = list("exwelder", "jawsoflife", "handdrill", "laserscalpel", "mechanicalpinches", "searingtool", "gene_shears")
prereq_ids = list("adv_engi")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
diff --git a/icons/obj/hydroponics/equipment.dmi b/icons/obj/hydroponics/equipment.dmi
index e7c45f27ceb..343c88a0dff 100644
Binary files a/icons/obj/hydroponics/equipment.dmi and b/icons/obj/hydroponics/equipment.dmi differ