From 74983781a71f566ca5d5cf4fc85d56bdfba1289e Mon Sep 17 00:00:00 2001 From: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Date: Wed, 21 Jan 2026 22:09:15 -0600 Subject: [PATCH] Buffs mutagen hydroponics application, adds some plant traits to interact with it (#94783) ## About The Pull Request Unstable Mutagen 1. Now consistently adds 0.1 instability per unit per tick (the same as L4Z) 2. No longer applies toxin damage directly 3. RNG roll now scales strength based on volume - 10u of mutagen = 1x effect modifier. 4. RNG instability roll now grants 2(*modifier) instability (down from 5) 5. RNG instability roll now also adds 1.5(*modifier) toxins 6. RNG instability roll now applies even if the tray is set to auto-grow 7. RNG health penalty now deals 5(*modifier) damage (down from 10) Uranium 1. Now consistently adds 0.05 instability per unit per tick (half as powerful as L4Z) 2. Now adds `0.5 * volume * toxpower` toxins, rather than `volume / toxpower` 3. No longer damages plant health directly 4. Has the same changes as Unstable Mutagen wrt RNG rolls New genes - Adds `Toxin Resistance`, which grants the plant immunity to health damage from high toxins in the tray. - Available in Death Berries, for which it is now their graft gene. - Adds `Toxin Adaptation`, which not only grants the plant immunity to health damage - Not available naturally (yet?), must be mutated (or found in strange seeds) Other Cleaned up a smidge of botany code while working in the area ## Why It's Good For The Game Unstable Mutagen is... ok. It's perfectly usable, but it requires a lot of work for something that you don't have easy access to. Best case it's only slightly (1.25x) better than L4Z alone. Gurus will make a mixture of L4Z, mutagen, and cryoxadone or multiver for maximum mutation speed, which is cool, but a little cheesy. As a consequence, Mutagen is USUALLY only used 1. as a noob trap and 2. to get Kudzu or spiders This makes me sad considering how it used to have legendary status for botany. So I kinda wanted to bring it back. The flat scaling makes it worst case AS GOOD AS L4Z. You are rewarded for getting something besides vendor chems. The RNG roll changes give it a bit of a boost, so it becomes "L4Z+ but with a minor downside". It also removes the cheese aspect, which I admit is kinda sad. Green = Mutagen Purple = l4z p = probability of RNG instability v = volume y = instability x = ticks image 20u mutagen = 17 ticks for 100 instability + 25 toxins 20u l4z = 25ticks for 100 instability + 0 toxins Speed scales faster (1.25x faster at 10u, 1.5x faster at 20u, 1.75x faster at 30u) - but so does toxin accumulation TL;DR more mutagen = more mutation = more toxin Now you're wondering "Okay where does the gene changes come into play" Well I'm a big fan of fertilizers that require you use *botany* knowledge, not chem knowledge, *botany* knowledge to maximize their potential. For example, using Weed Adaptation for consequence-free Liquid Earthquake. I wanted do to that here, so I added these two genes that allow you to get no penalties for tray toxins, allowing "unchecked" use of mutagen (and such) for a clever botanist. ## Changelog :cl: Melbert balance: Rebalanced Unstable Mutagen's / Uranium's botany use. It now always increases instability (on par with L4Z), and occasionally increases instability even more at the costs of some toxins. It also scales with volume add: Adds "Toxin Resistance" gene to botany which makes the plant immune to toxin damage. Given (and graftable from) Death Berries. add: Adds "Toxin Adaptation" gene to botany which makes the plant heal from toxin damage. Only in strange seeds (for now). code: Cleaned up a smidge of botany code /:cl: --- code/modules/hydroponics/grown/berries.dm | 2 + code/modules/hydroponics/hydroponics.dm | 69 +++++++++++-------- .../hydroponics/hydroponics_chemreact.dm | 38 ++++++---- code/modules/hydroponics/plant_genes.dm | 14 +++- .../chemistry/reagents/medicine_reagents.dm | 2 +- .../chemistry/reagents/other_reagents.dm | 6 +- .../chemistry/reagents/toxin_reagents.dm | 4 +- 7 files changed, 85 insertions(+), 50 deletions(-) diff --git a/code/modules/hydroponics/grown/berries.dm b/code/modules/hydroponics/grown/berries.dm index 5f457d83d27..697c7eb41ee 100644 --- a/code/modules/hydroponics/grown/berries.dm +++ b/code/modules/hydroponics/grown/berries.dm @@ -68,8 +68,10 @@ lifespan = 30 potency = 50 mutatelist = null + genes = list(/datum/plant_gene/trait/repeated_harvest, /datum/plant_gene/trait/tox_resistance) reagents_add = list(/datum/reagent/toxin/coniine = 0.08, /datum/reagent/toxin/staminatoxin = 0.1, /datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/nutriment = 0.1) rarity = 30 + graft_gene = /datum/plant_gene/trait/tox_resistance /obj/item/food/grown/berries/death seed = /obj/item/seeds/berry/death diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index 104c4e4384c..8eda5c23fab 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -333,20 +333,26 @@ //Toxins///////////////////////////////////////////////////////////////// // Too much toxins cause harm, but when the plant drinks the contaiminated water, the toxins disappear slowly - if(toxic >= 40 && toxic < 80) - adjust_plant_health(-1 / rating) - adjust_toxic(-rating * 2) - else if(toxic >= 80) // I don't think it ever gets here tbh unless above is commented out - adjust_plant_health(-3) - adjust_toxic(-rating * 3) + if(toxic >= 10) + if(myseed.get_gene(/datum/plant_gene/trait/plant_type/toxin_adaptation)) + adjust_plant_health(round(toxic / rand(10, 16))) + myseed.adjust_potency(round(toxic / rand(20, 30))) + + else if(toxic >= 40 && !myseed.get_gene(/datum/plant_gene/trait/tox_resistance)) + if(toxic < 80) + adjust_plant_health(-1 / rating) + adjust_toxic(-rating * 2) + else + adjust_plant_health(-3) + adjust_toxic(-rating * 3) //Pests & Weeds////////////////////////////////////////////////////////// if(pestlevel >= 8) if(!myseed.get_gene(/datum/plant_gene/trait/carnivory)) if(myseed.potency >= 30) - myseed.adjust_potency(-rand(2,6)) //Pests eat leaves and nibble on fruit, lowering potency. - myseed.set_potency(min((myseed.potency), CARNIVORY_POTENCY_MIN, MAX_PLANT_POTENCY)) + // Pests eat leaves and nibble on fruit, lowering potency. + myseed.set_potency(min(myseed.potency - rand(2, 6), CARNIVORY_POTENCY_MIN)) else adjust_plant_health(2 / rating) adjust_pestlevel(-1 / rating) @@ -354,8 +360,7 @@ else if(pestlevel >= 4) if(!myseed.get_gene(/datum/plant_gene/trait/carnivory)) if(myseed.potency >= 30) - myseed.adjust_potency(-rand(1,4)) - myseed.set_potency(min((myseed.potency), CARNIVORY_POTENCY_MIN, MAX_PLANT_POTENCY)) + myseed.set_potency(min(myseed.potency - rand(1, 4) , CARNIVORY_POTENCY_MIN)) else adjust_plant_health(1 / rating) @@ -399,7 +404,7 @@ // If the plant is too old, lose health fast if(age > myseed.lifespan) - adjust_plant_health(-rand(1,5) / rating) + adjust_plant_health(-rand(1, 5) / rating) // Harvest code if(age > myseed.production && (age - lastproduce) > myseed.production && plant_status == HYDROTRAY_PLANT_GROWING) @@ -713,19 +718,21 @@ addtimer(CALLBACK(src, PROC_REF(after_mutation), message), 0.5 SECONDS) /obj/machinery/hydroponics/proc/mutateweed() // If the weeds gets the mutagent instead. Mind you, this pretty much destroys the old plant - if( weedlevel > 5 ) - set_seed(null) - var/newWeed = pick(/obj/item/seeds/liberty, /obj/item/seeds/angel, /obj/item/seeds/nettle/death, /obj/item/seeds/kudzu) - set_seed(new newWeed(src)) - hardmutate() - set_plant_health(myseed.endurance, update_icon = FALSE) - lastcycle = world.time - set_weedlevel(0, update_icon = FALSE) // Reset + if(weedlevel <= 5) + visible_message(span_warning("The few weeds in [src] seem to react, but only for a moment...")) + return + + set_seed(null) + var/newWeed = pick(/obj/item/seeds/liberty, /obj/item/seeds/angel, /obj/item/seeds/nettle/death, /obj/item/seeds/kudzu) + set_seed(new newWeed(src)) + hardmutate() + set_plant_health(myseed.endurance, update_icon = FALSE) + lastcycle = world.time + set_weedlevel(0, update_icon = FALSE) // Reset + + var/message = span_warning("The mutated weeds in [src] spawn some [myseed.plantname]!") + addtimer(CALLBACK(src, PROC_REF(after_mutation), message), 0.5 SECONDS) - var/message = span_warning("The mutated weeds in [src] spawn some [myseed.plantname]!") - addtimer(CALLBACK(src, PROC_REF(after_mutation), message), 0.5 SECONDS) - else - to_chat(usr, span_warning("The few weeds in [src] seem to react, but only for a moment...")) /** * Called after plant mutation, update the appearance of the tray content and send a visible_message() */ @@ -785,14 +792,18 @@ * 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) +/obj/machinery/hydroponics/proc/mutatepest() + if(pestlevel <= 5) + visible_message(span_warning("The pests seem to behave oddly in [src], but quickly settle down...")) + return + + var/mob/user = lastuser?.resolve() + if(!isnull(user)) message_admins("[ADMIN_LOOKUPFLW(user)] last altered a hydro tray's contents which spawned spiderlings.") user.log_message("last altered a hydro tray, which spiderlings spawned from.", LOG_GAME) - visible_message(span_warning("The pests seem to behave oddly...")) - spawn_atom_to_turf(/mob/living/basic/spider/growing/spiderling/hunter, src, 3, FALSE) - else if(myseed) - visible_message(span_warning("The pests seem to behave oddly in [myseed.name] tray, but quickly settle down...")) + + visible_message(span_warning("The pests seem to behave oddly...")) + spawn_atom_to_turf(/mob/living/basic/spider/growing/spiderling/hunter, src, 3, FALSE) /obj/machinery/hydroponics/wrench_act(mob/living/user, obj/item/tool) . = ..() diff --git a/code/modules/hydroponics/hydroponics_chemreact.dm b/code/modules/hydroponics/hydroponics_chemreact.dm index 0af7c258f8f..8e10cbb04dc 100644 --- a/code/modules/hydroponics/hydroponics_chemreact.dm +++ b/code/modules/hydroponics/hydroponics_chemreact.dm @@ -26,22 +26,32 @@ src.reagents.add_reagent(reagent.type, reagents[reagent]) update_appearance() -/obj/machinery/hydroponics/proc/mutation_roll(mob/user) - switch(rand(100)) - if(91 to 100) - adjust_plant_health(-10) +/// Called when a radioactive reagent is applied to the tray +/obj/machinery/hydroponics/proc/radioactive_exposure(modifier = 1) + if(isnull(myseed)) + return + + if(prob(min(75, 25 * modifier))) + myseed.adjust_instability(round(2 * modifier)) + adjust_toxic(round(1.5 * modifier)) // It is still toxic, mind you + return + + switch(rand(0, 50)) + if(41 to 50) + adjust_plant_health(round(-5 * modifier)) visible_message(span_warning("\The [myseed.plantname] starts to wilt and burn!")) - return - if(41 to 90) - if(myseed && !self_sustaining) //Stability - myseed.adjust_instability(5) - return + if(21 to 40) visible_message(span_notice("\The [myseed.plantname] appears unusually reactive...")) - return + if(11 to 20) - mutateweed() - return + if(modifier >= 0.5) + mutateweed() + else + adjust_weedlevel(max(1, round(modifier))) + if(0 to 10) - mutatepest(user) - return + if(modifier >= 0.5) + mutatepest() + else + adjust_pestlevel(max(1, round(modifier))) diff --git a/code/modules/hydroponics/plant_genes.dm b/code/modules/hydroponics/plant_genes.dm index 4437353b1d3..0844708b3ff 100644 --- a/code/modules/hydroponics/plant_genes.dm +++ b/code/modules/hydroponics/plant_genes.dm @@ -958,6 +958,13 @@ if(istype(grown_plant)) grown_plant.preserved_food = TRUE +/// Ignores tox damage +/datum/plant_gene/trait/tox_resistance + name = "Toxin Resistance" + description = "It is immune to the negative effects of a toxic environment." + icon = FA_ICON_SKULL_CROSSBONES + mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE + /datum/plant_gene/trait/carnivory name = "Obligate Carnivory" description = "Pests have positive effect on the plant health." @@ -981,6 +988,12 @@ description = "It is a mushroom that needs no water, less light and can't be overtaken by weeds." icon = FA_ICON_DROPLET_SLASH +/// A plant that thrives in toxic environments. +/datum/plant_gene/trait/plant_type/toxin_adaptation + name = "Toxin Adaptation" + description = "It is a toxic plant that thrives in poisonous environments." + icon = FA_ICON_SKULL_CROSSBONES + /// Currently unused and does nothing. Appears in strange seeds. /datum/plant_gene/trait/plant_type/alien_properties name ="?????" @@ -1002,4 +1015,3 @@ description = "A plant that needs the firm embrace of soil to develop properly, produces small irregular produce when grown hydroponically." icon = FA_ICON_MOUND mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE - diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 5354662a390..c5357772f04 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -60,7 +60,7 @@ if(33 to 65) mytray.mutateweed() if(1 to 32) - mytray.mutatepest(user) + mytray.mutatepest() else if(prob(20)) mytray.visible_message(span_warning("Nothing happens...")) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index e55e1b33b32..70685934419 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1205,9 +1205,9 @@ //Mutagenic chem side-effects. /datum/reagent/uranium/on_hydroponics_apply(obj/machinery/hydroponics/mytray, mob/user) - mytray.mutation_roll(user) - mytray.adjust_plant_health(-round(volume)) - mytray.adjust_toxic(round(volume / tox_damage)) // more damage = more + mytray.radioactive_exposure(modifier = volume * 0.1) + mytray.myseed?.adjust_instability(round(volume * 0.1)) + mytray.adjust_toxic(round(0.5 * volume * tox_damage)) /datum/reagent/uranium/radium name = "Radium" diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 0d6988abb69..944fcac731f 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -71,8 +71,8 @@ return UPDATE_MOB_HEALTH /datum/reagent/toxin/mutagen/on_hydroponics_apply(obj/machinery/hydroponics/mytray, mob/user) - mytray.mutation_roll(user) - mytray.adjust_toxic(3) //It is still toxic, mind you, but not to the same degree. + mytray.radioactive_exposure(modifier = volume * 0.1) + mytray.myseed?.adjust_instability(round(volume * 0.2)) /datum/reagent/toxin/mutagen/used_on_fish(obj/item/fish/fish) ADD_TRAIT(fish, TRAIT_FISH_MUTAGENIC, type)