diff --git a/code/modules/hydroponics/grafts.dm b/code/modules/hydroponics/grafts.dm
index db05ae80304..602bfc63886 100644
--- a/code/modules/hydroponics/grafts.dm
+++ b/code/modules/hydroponics/grafts.dm
@@ -12,8 +12,23 @@
var/datum/plant_gene/trait/stored_trait
///Determines the appearance of the graft. Rudimentary right now so it just picks randomly.
var/graft_appearance
- ///Seed type that the graft was taken from, used for applying parent stats.
+ ///Seed that the graft was taken from, used for applying parent stats. Can be unexpectedly nulled by the parent plant getting deleted.
var/obj/item/seeds/parent_seed = null
+ /// The name of the plant this was taken from.
+ var/parent_name = ""
+ ///The lifespan stat of the parent seed when the graft was taken.
+ var/lifespan
+ ///The endurance stat of the parent seed when the graft was taken.
+ var/endurance
+ ///The production stat of the parent seed when the graft was taken.
+ var/production
+ ///The weed_rate stat of the parent seed when the graft was taken.
+ var/weed_rate
+ ///The weed_chance stat of the parent seed when the graft was taken.
+ var/weed_chance
+ ///The yield stat of the parent seed when the graft was taken.
+ var/yield
+
/obj/item/graft/Initialize()
. = ..()
@@ -34,8 +49,8 @@
*/
/obj/item/graft/proc/get_graft_text()
var/text = "- Plant Graft -\n"
- if(parent_seed)
- text += "- Parent Plant: [parent_seed.plantname] -\n"
+ if(parent_name)
+ text += "- Parent Plant: [parent_name] -\n"
if(stored_trait)
text += "- Graftable Traits: [stored_trait.get_name()] -\n"
return text
diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm
index c05532ca8a9..e4663380ad2 100644
--- a/code/modules/hydroponics/hydroponics.dm
+++ b/code/modules/hydroponics/hydroponics.dm
@@ -607,8 +607,9 @@
//cause I don't want to feel like im juggling 15 tamagotchis and I can get to my real work of ripping flooring apart in hopes of validating my life choices of becoming a space-gardener
//This was originally in apply_chemicals, but due to apply_chemicals only holding nutrients, we handle it here now.
if(reagent_source.reagents.has_reagent(/datum/reagent/water, 1))
- H.adjustWater(round(reagent_source.reagents.get_reagent_amount(/datum/reagent/water)/(trays.len)))
- reagent_source.reagents.remove_reagent(/datum/reagent/water, reagent_source.reagents.get_reagent_amount(/datum/reagent/water)/(trays.len))
+ var/water_amt = reagent_source.reagents.get_reagent_amount(/datum/reagent/water) * split / reagent_source.reagents.total_volume
+ H.adjustWater(round(water_amt))
+ reagent_source.reagents.remove_reagent(/datum/reagent/water, water_amt)
reagent_source.reagents.trans_to(H.reagents, split, transfered_by = user)
if(istype(reagent_source, /obj/item/reagent_containers/food/snacks) || istype(reagent_source, /obj/item/reagent_containers/pill))
qdel(reagent_source)
@@ -687,13 +688,13 @@
return
else
user.visible_message("[user] grafts off a limb from [src].", "You carefully graft off a portion of [src].")
- var/obj/item/graft/snip = new /obj/item/graft(loc)
- if(myseed.graft_gene)
- snip.stored_trait = new myseed.graft_gene
- snip.parent_seed = myseed
+ var/obj/item/graft/snip = myseed.create_graft()
+ if(!snip)
+ return // The plant did not return a graft.
+
+ snip.forceMove(drop_location())
myseed.grafted = TRUE
adjustHealth(-5)
- snip.name += " ([snip.parent_seed.plantname])"
return
else if(istype(O, /obj/item/geneshears))
@@ -729,19 +730,12 @@
else if(istype(O, /obj/item/graft))
var/obj/item/graft/snip = O
- var/datum/plant_gene/trait/new_trait = snip.stored_trait
if(!myseed)
to_chat(user, "The tray is empty.")
return
- if(new_trait.can_add(myseed))
- myseed.genes += snip.stored_trait
- //Alright this one's a mess, but it's either 2/3rds of the difference of the two seed's respective stats, and the higher of the two is taken. Min 0, max 100.
- myseed.lifespan = round(clamp(max(myseed.lifespan,(myseed.lifespan+(2/3)*(snip.parent_seed.lifespan-myseed.lifespan))),0,100))
- myseed.endurance = round(clamp(max(myseed.endurance,(myseed.endurance+(2/3)*(snip.parent_seed.endurance-myseed.endurance))),0,100))
- myseed.production = round(clamp(max(myseed.production,(myseed.production+(2/3)*(snip.parent_seed.production-myseed.production))),0,100))
- myseed.weed_rate = round(clamp(max(myseed.weed_rate,(myseed.weed_rate+(2/3)*(snip.parent_seed.weed_rate-myseed.weed_rate))),0,100))
- myseed.weed_chance = round(clamp(max(myseed.weed_chance,(myseed.weed_chance+(2/3)*(snip.parent_seed.weed_chance-myseed.weed_chance))),0,100))
- myseed.yield = round(clamp(max(myseed.yield,(myseed.yield+(2/3)*(snip.parent_seed.yield-myseed.yield))),0,10))
+ if(!myseed.apply_graft(snip))
+ to_chat(user, "The [myseed.plantname] rejects the [snip]!")
+ return
qdel(snip)
to_chat(user, "You carefully integrate the grafted plant limb onto [myseed.plantname].")
return
diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm
index e4c7deff705..2eed0e8516d 100644
--- a/code/modules/hydroponics/seeds.dm
+++ b/code/modules/hydroponics/seeds.dm
@@ -551,3 +551,55 @@
for(var/i in 1 to amount_random_reagents)
var/datum/reagent/chemical = pick(reagents_add)
qdel(chemical)
+
+/**
+ * Creates a graft from this plant.
+ *
+ * Creates a new graft from this plant.
+ * Sets the grafts trait to this plants graftable trait.
+ * Gives the graft a reference to this plant.
+ * Copies all the relevant stats from this plant to the graft.
+ * Returns the created graft.
+ */
+/obj/item/seeds/proc/create_graft()
+ var/obj/item/graft/snip = new
+ if(graft_gene)
+ snip.stored_trait = graft_gene
+ snip.parent_seed = src
+ snip.parent_name = plantname
+ snip.name += "([plantname])"
+
+ // Copy over stats so the graft can outlive its parent.
+ snip.lifespan = lifespan
+ snip.endurance = endurance
+ snip.production = production
+ snip.weed_rate = weed_rate
+ snip.weed_chance = weed_chance
+ snip.yield = yield
+
+ return snip
+
+/**
+ * Applies a graft to this plant.
+ *
+ * Adds the graft trait to this plant if possible.
+ * Increases plant stats by 2/3 of the grafts stats to a maximum of 100 (10 for yield).
+ * Returns [TRUE]
+ *
+ * Arguments:
+ * - [snip][/obj/item/graft]: The graft being used applied to this plant.
+ */
+/obj/item/seeds/proc/apply_graft(obj/item/graft/snip)
+ var/datum/plant_gene/trait/new_trait = snip.stored_trait
+ if(new_trait?.can_add(src))
+ genes += new_trait
+
+ // Adjust stats based on graft stats.
+ src.lifespan = round(clamp(max(src.lifespan, (src.lifespan +(2/3)*(snip.lifespan -src.lifespan) )),0,100))
+ src.endurance = round(clamp(max(src.endurance, (src.endurance +(2/3)*(snip.endurance -src.endurance) )),0,100))
+ src.production = round(clamp(max(src.production, (src.production +(2/3)*(snip.production -src.production) )),0,100))
+ src.weed_rate = round(clamp(max(src.weed_rate, (src.weed_rate +(2/3)*(snip.weed_rate -src.weed_rate) )),0,100))
+ src.weed_chance = round(clamp(max(src.weed_chance, (src.weed_chance+(2/3)*(snip.weed_chance-src.weed_chance) )),0,100))
+ src.yield = round(clamp(max(src.yield, (src.yield +(2/3)*(snip.yield -src.yield) )),0,10 ))
+
+ return TRUE