From a7c63e4a06f8654fa6ac929edbac488127ce7e7e Mon Sep 17 00:00:00 2001 From: FalseIncarnate Date: Sun, 23 Nov 2014 03:14:21 -0500 Subject: [PATCH] Botany Mutation Rework Reworked the mutation system for Botany to use a "tier system", adjusting mutation chances and the potential type of mutation based on the amount of the reagent(s) added. Updated handling for Floral Somatoray to work properly with new Botany Mutation Rework. Adjusted Floral Somatoray's Yield setting to adjust the yield stat of the plant instead of yield_mod stat of the tray. Also added additional information to the Plant Analyzer when scanning trays. Will now include information such as age, yield modifier, and toxicity in the report. This will not be shown when scanning harvested goods or seeds. Fixed some typos and missing words in podmen.dm in preparation of planned attempt to reintegrate pod-cloning functionality. Fixed hydroponics trays setting "waterlevel = maxwater" and "nutrilevel = 3" whenever RefreshParts() is called, and fixed sanity check for water and nutrients above previous max levels. Unreported change from my previous commit (this is for the sake of documentation): End of round score will factor Hydroponics harvests into the calculations. --- code/game/machinery/hydroponics.dm | 187 ++++++++++++++++++------ code/game/machinery/podmen.dm | 3 +- code/modules/hydroponics/hydro_tools.dm | 37 +++++ 3 files changed, 178 insertions(+), 49 deletions(-) diff --git a/code/game/machinery/hydroponics.dm b/code/game/machinery/hydroponics.dm index a4fced9bc6b..fab497eeeeb 100644 --- a/code/game/machinery/hydroponics.dm +++ b/code/game/machinery/hydroponics.dm @@ -41,7 +41,7 @@ // Construction var/unwrenchable = 1 - + // Reagent information for process(), consider moving this to a controller along // with cycle information under 'mechanical concerns' at some point. var/global/list/toxic_reagents = list( @@ -116,23 +116,26 @@ "left4zed" = list( 0, 0, 0.2 ) ) - // Mutagen list specifies minimum value for the mutation to take place, rather - // than a bound as the lists above specify. + //--FalseIncarnate + // Mutagen list specifies reagent_min_value and reagent_step + // Reagent_min_value (value 1) is the minimum number of units needed to begin mutations + // Reagent_step (value 2) is the number of units between each mutation threshold var/global/list/mutagenic_reagents = list( - "radium" = list(8,3), - "mutagen" = list(3,8) + "radium" = list(10,10), + "mutagen" = list(1,5) ) + //--FalseIncarnate /obj/machinery/portable_atmospherics/hydroponics/New() ..() - + component_parts = list() component_parts += new /obj/item/weapon/circuitboard/hydroponics(src) component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) component_parts += new /obj/item/weapon/stock_parts/console_screen(src) RefreshParts() - + create_reagents(200) connect() update_icon() @@ -145,22 +148,24 @@ tmp_capacity += M.rating maxwater = tmp_capacity * 50 // Up to 300 maxnutri = tmp_capacity * 5 // Up to 30 - waterlevel = maxwater - nutrilevel = 3 - + //waterlevel = maxwater + //nutrilevel = 3 + /obj/machinery/portable_atmospherics/hydroponics/bullet_act(var/obj/item/projectile/Proj) //Don't act on seeds like dionaea that shouldn't change. if(seed && seed.immutable > 0) return - //Override for somatoray projectiles. - if(istype(Proj ,/obj/item/projectile/energy/floramut) && prob(20)) - mutate(1) + //--FalseIncarnate + //Override for somatoray projectiles, updated to work with new mutation rework + if(istype(Proj ,/obj/item/projectile/energy/floramut)) + mutate("F1") return - else if(istype(Proj ,/obj/item/projectile/energy/florayield) && prob(20)) - yield_mod = min(10,yield_mod+rand(1,2)) + else if(istype(Proj ,/obj/item/projectile/energy/florayield)) + mutate("F2") return + //--FalseIncarnate ..() @@ -358,15 +363,27 @@ mutation_mod += beneficial_reagents[R.id][3] * reagent_total // Mutagen is distinct from the previous types and mostly has a chance of proccing a mutation. + + //--FalseIncarnate + // Mutation rework, will now use "thresholds" for proccing types of mutations and their respective chances. + // This should make it easier to avoid species shifts when trying to only affect stats like potency. + // Additionally, the chance of mutations will vary depending on the amount of mutagenic reagents added. if(mutagenic_reagents[R.id]) - var/reagent_min_value = mutagenic_reagents[R.id][1] - var/reagent_value = mutagenic_reagents[R.id][2]+mutation_mod + var/reagent_min_value = mutagenic_reagents[R.id][1] //10 for radium, 1 for unstable mutagen + var/reagent_step = mutagenic_reagents[R.id][2] //10 for radium, 5 for unstable mutagen - if(reagent_total >= reagent_min_value) - if(prob(min(reagent_total*reagent_value,100))) - mutate(reagent_total > 10 ? 2 : 1) + if(reagent_total >= reagent_min_value + (3 * reagent_step)) //31+ for radium, 16+ for unstable mutagen + mutate(4) + else if(reagent_total >= reagent_min_value + (2 * reagent_step)) //21-30 for radium, 11-15 for unstable mutagen + mutate(3) + else if(reagent_total >= reagent_min_value + reagent_step) //11-20 for radium, 6-10 for unstable mutagen + mutate(2) + else if(reagent_total >= reagent_min_value) //1-10 for radium, 1-5 for unstable mutagen + mutate(1) - // Handle nutrient refilling. + //--FalseIncarnate + + // Handle nutrient refilling if(nutrient_reagents[R.id]) nutrilevel += nutrient_reagents[R.id] * reagent_total @@ -506,26 +523,6 @@ return -/obj/machinery/portable_atmospherics/hydroponics/proc/mutate(var/severity) - - // No seed, no mutations. - if(!seed) - return - - // Check if we should even bother working on the current seed datum. - if(seed.mutants. && seed.mutants.len && severity > 1 && prob(10+mutation_mod)) - mutate_species() - return - - // We need to make sure we're not modifying one of the global seed datums. - // If it's not in the global list, then no products of the line have been - // harvested yet and it's safe to assume it's restricted to this tray. - if(!isnull(seed_types[seed.name])) - seed = seed.diverge() - seed.mutate(severity,get_turf(src)) - - return - /obj/machinery/portable_atmospherics/hydroponics/proc/check_level_sanity() //Make sure various values are sane. if(seed) @@ -534,14 +531,108 @@ health = 0 dead = 0 - nutrilevel = max(nutrilevel, 0) - nutrilevel = min(nutrilevel, maxnutri) - waterlevel = max(waterlevel, 0) - waterlevel = min(waterlevel, maxwater) + nutrilevel = max(0,min(nutrilevel,maxnutri)) + waterlevel = max(0,min(waterlevel,maxwater)) pestlevel = max(0,min(pestlevel,10)) weedlevel = max(0,min(weedlevel,10)) toxins = max(0,min(toxins,10)) +/obj/machinery/portable_atmospherics/hydroponics/proc/mutate(var/severity) + + // No seed, no mutations. + if(!seed) + return + + /* + --FalseIncarnate + New mutation system, now uses "Mutation Tiers" to adjust the chances of mutations + Tier 1 has a low chance of causing a stat mutation + Tier 2 has a higher chance of causing a stat mutation + Tier 3 has a low chance of causing a species shift (if possible), and will ALWAYS cause a stat mutation if it does not shift species + Tier 4 has a higher chance of causing a species shift (if possible), and will ALWAYS cause a stat mutation if it does not shift species + Tier 4 also has a low chance to cause a SECOND stat mutation when it does not shift species + All mutation chances are increased by the mutation_mod value. Mutation_mod is not transferred into seeds/harvests, and is reset when the plant dies + + */ + + switch(severity) + //Reagent Tiers + if(1) //Tier 1 + if(prob(20+mutation_mod)) //Low chance of stat mutation + if(!isnull(seed_types[seed.name])) + seed = seed.diverge() + seed.mutate(1,get_turf(src)) + return + if(2) //Tier 2 + if(prob(60+mutation_mod)) //Higher chance of stat mutation + if(!isnull(seed_types[seed.name])) + seed = seed.diverge() + seed.mutate(1,get_turf(src)) + return + if(3) //Tier 3 + if(prob(20+mutation_mod)) //Low chance of species shift mutation + if(seed.mutants. && seed.mutants.len) //Check if current seed/plant has mutant species + mutate_species() + else //No mutant species, mutate stats instead + if(!isnull(seed_types[seed.name])) + seed = seed.diverge() + seed.mutate(1,get_turf(src)) + return + else //Failed to shift, mutate stats instead + if(!isnull(seed_types[seed.name])) + seed = seed.diverge() + seed.mutate(1,get_turf(src)) + return + if(4) //Tier 4 + if(prob(60+mutation_mod)) //Higher chance of species shift mutation + if(seed.mutants. && seed.mutants.len) //Check if current seed/plant has mutant species + mutate_species() + else //No mutant species, mutate stats instead + if(!isnull(seed_types[seed.name])) + seed = seed.diverge() + seed.mutate(1,get_turf(src)) + if(prob(20+mutation_mod)) //Low chance for second stat mutation + if(!isnull(seed_types[seed.name])) + seed = seed.diverge() + seed.mutate(1,get_turf(src)) + return + else //Failed to shift, mutate stats instead + if(!isnull(seed_types[seed.name])) + seed = seed.diverge() + seed.mutate(1,get_turf(src)) + if(prob(20+mutation_mod)) //Low chance for second stat mutation + if(!isnull(seed_types[seed.name])) + seed = seed.diverge() + seed.mutate(1,get_turf(src)) + return + //Floral Somatoray Tiers + if("F1") //Random Stat Tier + if(prob(80+mutation_mod)) //EVEN Higher chance of stat mutation + if(!isnull(seed_types[seed.name])) + seed = seed.diverge() + seed.mutate(1,get_turf(src)) + return + if("F2") //Yield Tier + if(prob(40+mutation_mod)) //Medium chance of Yield stat mutation + if(!isnull(seed_types[seed.name])) + seed = seed.diverge() + if(seed.immutable <= 0 && seed.yield != -1) //Check if the plant can be mutated and has a yield to mutate + seed.yield = seed.yield + rand(-2, 2) //Randomly adjust yield + if(seed.yield < 0) //If yield would drop below 0 after adjustment, set to 0 to allow further attempts + seed.yield = 0 + return + + /* code references + // We need to make sure we're not modifying one of the global seed datums. + // If it's not in the global list, then no products of the line have been + // harvested yet and it's safe to assume it's restricted to this tray. + if(!isnull(seed_types[seed.name])) + seed = seed.diverge() + seed.mutate(severity,get_turf(src)) + */ + + //--FalseIncarnate + /obj/machinery/portable_atmospherics/hydroponics/proc/mutate_species() var/previous_plant = seed.display_name @@ -552,7 +643,7 @@ return dead = 0 - mutate(1) + //mutate(1) age = 0 health = seed.endurance lastcycle = world.time @@ -573,7 +664,7 @@ user << "Unscrew the hoses first!" return default_deconstruction_crowbar(O, 1) - + //--FalseIncarnate //Check if held item is an open container if (O.is_open_container()) @@ -643,7 +734,7 @@ update_icon() else user << "There's nothing in [src] to spray!" - + else if(istype(O, /obj/item/weapon/wrench) && unwrenchable) if(anchored == 2) user << "Unscrew the hoses first!" diff --git a/code/game/machinery/podmen.dm b/code/game/machinery/podmen.dm index d99c9e3548a..4a698e2a4e2 100644 --- a/code/game/machinery/podmen.dm +++ b/code/game/machinery/podmen.dm @@ -47,11 +47,12 @@ Growing it to term with nothing injected will grab a ghost from the observers. * for(var/mob/O in respawnable_list) if(O.mind == source.mind && config.revival_pod_plants) message_admins("Found mind, asking for respawn") - switch(alert(O,"Your corpse has been placed into a pod plant. Do you want to be resurrected/cloned? Please not if you select 'No', you will be able to be cloned or borged again this round.","Pod Alert","Yes","No")) + switch(alert(O,"Your corpse has been placed into a pod plant. Do you want to be resurrected/cloned? Please note if you select 'No', you will still be able to be cloned or borged again this round.","Pod Alert","Yes","No")) if("Yes") source.key = O.key return if("No") + user << "The seeds seem to reject the blood, returning to their original size as they stop quivering." return else user << "Nothing happens." diff --git a/code/modules/hydroponics/hydro_tools.dm b/code/modules/hydroponics/hydro_tools.dm index 9764b3a9041..be2158fee39 100644 --- a/code/modules/hydroponics/hydro_tools.dm +++ b/code/modules/hydroponics/hydro_tools.dm @@ -18,6 +18,17 @@ var/datum/seed/grown_seed var/datum/reagents/grown_reagents + + //--FalseIncarnate + var/IS_TRAY = 0 //used to track if the target is a hydroponics tray or soil. 1 if true, otherwise 0 + var/tray_age //age of the plant in the tray + var/tray_weed_level //weed level of tray + var/tray_pest_level //pest level of tray + var/tray_toxins //toxicity of the tray + var/tray_yield_mod //yield modifier of the tray + var/tray_mutation_mod //mutation modifier of the tray + //--FalseIncarnate + if(istype(target,/obj/item/weapon/reagent_containers/food/snacks/grown)) var/obj/item/weapon/reagent_containers/food/snacks/grown/G = target @@ -38,6 +49,19 @@ else if(istype(target,/obj/machinery/portable_atmospherics/hydroponics)) var/obj/machinery/portable_atmospherics/hydroponics/H = target + + //--FalseIncarnate + //Flag the target as a tray for showing tray-specific stats + IS_TRAY = 1 + //Save tray data to matching variables + tray_age = H.age + tray_weed_level = H.weedlevel + tray_pest_level = H.pestlevel + tray_toxins = H.toxins + tray_yield_mod = H.yield_mod + tray_mutation_mod = H.mutation_mod + //--FalseIncarnate + grown_seed = H.seed grown_reagents = H.reagents @@ -57,6 +81,19 @@ dat += "Maturation time[grown_seed.maturation]" dat += "Production time[grown_seed.production]" dat += "Potency[grown_seed.potency]" + + //--FalseIncarnate + //Tray-specific stats like Age and Mutation Modifier, not shown if target was not a hydroponics tray or soil + if(IS_TRAY == 1) + dat += "" + dat += "Age[tray_age]" + dat += "Weed Level[tray_weed_level]" + dat += "Pest Level[tray_pest_level]" + dat += "Toxins[tray_toxins]" + dat += "Yield Modifier[tray_yield_mod]" + dat += "Mutation Modifier[tray_mutation_mod]" + //--FalseIncarnate + dat += "" if(grown_reagents && grown_reagents.reagent_list && grown_reagents.reagent_list.len)