I was curious as to how exactly the worldgen settings for Poison Birchnut trees affected their spawn rate so I inspected the game's scripts and was surprised to find that the options clearly don't work as intended. I apologize for the long post, but sadly it doesn't seem that you can make code blocks collapsible like spoilers.
Short Version:
The values "never" (None) and "default" (Default) are the only two that function as one would expect, changing the first day upon which Poison Birches can spawn, as well as their spawn chance, while "rare" (Little), "often" (More), and "always" (Tons) only affect the minimum day and not the spawn rate, due to what is most likely a mistake with left over variable names.
Fix:
worldsettings_overrides.lua
DECID_MONSTER_SPAWN_CHANCE_BASE -> DECID_MONSTER_SPAWN_CHANCE_AUTUMN
DECID_MONSTER_SPAWN_CHANCE_LOW -> DECID_MONSTER_SPAWN_CHANCE_SPRING
DECID_MONSTER_SPAWN_CHANCE_MED -> DECID_MONSTER_SPAWN_CHANCE_SUMMER
Long Version:
In tuning.lua we can see the default values that the game uses for handling Posion Birchnut occurrences:
-- [ tuning.lua - 2496:2503 ] -- Birchnut monster chances have been reduced and tied to seasons instead of the number of days to balance things out for dedicated servers (which may be running for extremely long times) DECID_MONSTER_MIN_DAY = 3, -- No monsters during the first few days DECID_MONSTER_SPAWN_CHANCE_AUTUMN = .15, -- high chance of monsters in autumn to cancel out double birchnut and general easyness of autumn DECID_MONSTER_SPAWN_CHANCE_SPRING = .08, -- next highest in spring because everything attacks in spring DECID_MONSTER_SPAWN_CHANCE_SUMMER = .033, -- low chance in summer since summer is hard anyway DECID_MONSTER_SPAWN_CHANCE_WINTER = 0, -- can't make monsters in winter, they have to have leaves DECID_MONSTER_DAY_THRESHOLDS = { 20, 35, 70 }, -- Ramp monster spawns a bit over time DECID_MONSTER_SPAWN_CHANCE_MOD = { .2, .5, 1, 1.12 },
Then, in \prefabs\deciduoustrees.lua we can see how these values are used when the player chops a Birchnut tree:
-- [ deciduoustrees.lua - 509:536 ] local function chop_down_tree(inst, chopper) local days_survived = chopper.components.age ~= nil and chopper.components.age:GetAgeInDays() or TheWorld.state.cycles if not inst.monster and inst.leaf_state ~= "barren" and inst.components.growable ~= nil and inst.components.growable.stage == 3 and days_survived >= TUNING.DECID_MONSTER_MIN_DAY then --print("Chance of making a monster") --winter should always be 0 (because barren trees can't become monsters), but is included in tuning values for consistency local chance = (TheWorld.state.isautumn and TUNING.DECID_MONSTER_SPAWN_CHANCE_AUTUMN) or (TheWorld.state.isspring and TUNING.DECID_MONSTER_SPAWN_CHANCE_SPRING) or (TheWorld.state.issummer and TUNING.DECID_MONSTER_SPAWN_CHANCE_SUMMER) or (TheWorld.state.iswinter and TUNING.DECID_MONSTER_SPAWN_CHANCE_WINTER) or 0 local chance_mod = TUNING.DECID_MONSTER_SPAWN_CHANCE_MOD[1] for i, v in ipairs(TUNING.DECID_MONSTER_DAY_THRESHOLDS) do if days_survived < v then break end chance_mod = TUNING.DECID_MONSTER_SPAWN_CHANCE_MOD[i + 1] end if chopper:HasTag("beaver") then chance_mod = chance_mod * TUNING.BEAVER_DECID_MONSTER_CHANCE_MOD elseif chopper:HasTag("woodcutter") then chance_mod = chance_mod * TUNING.WOODCUTTER_DECID_MONSTER_CHANCE_MOD end --print("Chance is ", chance * chance_mod, TheWorld.state.season) if math.random() < chance * chance_mod then --print("Trying to spawn monster") -- ... (remainder of function)
In English, the game determines the days survived by the player (falling back on the world age) and ensures that the minimum days determined by DECID_MONSTER_MIN_DAY have passed. Then, it gets the spawn rate based on the current season using the conjunction and disjunction LUA operators, determines the chance modifier by getting a multiplier from within the DECID_MONSTER_SPAWN_CHANCE_MOD array based on days_survived (itself selected using the day thresholds in DECID_MONSTER_DAY_THRESHOLDS), and lastly alters that modifier further if the player is Woodie. Finally, the base chance is multiplied by the modifier to get the final true chance and RNG is used to "roll a die" and if the result is within the odds then a Posion Birchnut is spawned.
Note that these tuning values (as well as the two exceptions for Woodie) are the only ones that have bearing on their spawn rate.
Looking at the options for the Poison Birchnut spawn rate parameter, known as "deciduousmonster", we see it can have the following values in worldgenoverride.lua/leveldataoverride.lua:
- never (In-game: None)
- rare (In-game: Little)
- default (In-game: Default)
- often (In-game: More)
- always (In-game: Tons)
The game loads the static values from tuning.lua into a table (TUNING), which are then modified by worldsettings_overrides.lua according to the player's settings before actually being used. We can look there to see how these spawn rate parameters affect the above function. Note, I have omitted the function OverrideTuningVariables() at the top of the file, but just know that it's what actually handles swapping the custom values into the TUNING table:
-- [ worldsettings_overrides.lua - 166:203 ] deciduousmonster = function(difficulty) local tuning_vars = { never = { DECID_MONSTER_MIN_DAY = NEVER_TIME, DECID_MONSTER_SPAWN_CHANCE_AUTUMN = 0, DECID_MONSTER_SPAWN_CHANCE_SPRING = 0, DECID_MONSTER_SPAWN_CHANCE_SUMMER = 0, }, rare = { DECID_MONSTER_MIN_DAY = 5, DECID_MONSTER_SPAWN_CHANCE_BASE = 0.075, DECID_MONSTER_SPAWN_CHANCE_LOW = 0.04, DECID_MONSTER_SPAWN_CHANCE_MED = 0.0165, }, --[[ default = { DECID_MONSTER_MIN_DAY = 3, DECID_MONSTER_SPAWN_CHANCE_AUTUMN = 0.15, DECID_MONSTER_SPAWN_CHANCE_SPRING = 0.08, DECID_MONSTER_SPAWN_CHANCE_SUMMER = 0.033, }, --]] often = { DECID_MONSTER_MIN_DAY = 2, DECID_MONSTER_SPAWN_CHANCE_BASE = 0.3, DECID_MONSTER_SPAWN_CHANCE_LOW = 0.16, DECID_MONSTER_SPAWN_CHANCE_MED = 0.066, }, always = { DECID_MONSTER_MIN_DAY = 1, DECID_MONSTER_SPAWN_CHANCE_BASE = 0.6, DECID_MONSTER_SPAWN_CHANCE_LOW = 0.32, DECID_MONSTER_SPAWN_CHANCE_MED = 0.132, }, } OverrideTuningVariables(tuning_vars[difficulty]) end,
At first, looking at the value "never", things make sense. The minimum day is set to a macro that equates to day 9999999999 and the spawn chance for each season (except winter since its always zero) is set to zero. The same is true for the commented out default (which is just there as a reminder of the defaults and commented so that the values in tuning.lua are always used and Klei doesn't have to remember to update the defaults in two different places), but the moment we check any of the other values it immediately becomes apparent that something is wrong.
The use of the variables DECID_MONSTER_SPAWN_CHANCE_BASE, DECID_MONSTER_SPAWN_CHANCE_LOW, and DECID_MONSTER_SPAWN_CHANCE_MED is completely new here and these are not values present in the TUNING table (tuning.lua), and as we know from earlier these variables are not used at all within the Poison Birch spawning function (deciduoustrees.lua). In fact, with help of something like Notepad++'s handy "Find in Files" function one can easily see that these names are not referenced even once anywhere else in the entirety of the games scripts.
Essentially what this means is that only the minimum day portion of those values have any effect and the function is effectively:
deciduousmonster = function(difficulty) local tuning_vars = { never = { DECID_MONSTER_MIN_DAY = NEVER_TIME, DECID_MONSTER_SPAWN_CHANCE_AUTUMN = 0, DECID_MONSTER_SPAWN_CHANCE_SPRING = 0, DECID_MONSTER_SPAWN_CHANCE_SUMMER = 0, }, rare = { DECID_MONSTER_MIN_DAY = 5, }, --[[ default = { DECID_MONSTER_MIN_DAY = 3, DECID_MONSTER_SPAWN_CHANCE_AUTUMN = 0.15, DECID_MONSTER_SPAWN_CHANCE_SPRING = 0.08, DECID_MONSTER_SPAWN_CHANCE_SUMMER = 0.033, }, --]] often = { DECID_MONSTER_MIN_DAY = 2, }, always = { DECID_MONSTER_MIN_DAY = 1, }, } OverrideTuningVariables(tuning_vars[difficulty]) end,
where the default spawn rate values are used when "rare", "often", or "always" is selected.
I think it's reasonable to say that this wasn't intended and that the smoking gun is this comment in tuning.lua:
Quote-- Birchnut monster chances have been reduced and tied to seasons instead of the number of days to balance things out for dedicated servers (which may be running for extremely long times)
I think that for whatever reason when changing over to the new system/tuning values for spawning Poison Birchnut Trees, someone at Klei in their haste forgot to change the variables names for "rare", "often", and "always" from the old "BASE", "LOW" and "MED" implementation to the new season based one, resulting in those variables being dynamically added to the TUNING table (and left unused), instead of the intended "..._AUTMUM", "..._SPRING", and "..._SUMMER" variables being modified.
It's technically possible that these other values are referred to directly by the engine, but given the fact that the handling for a Birch tree being chopped is fully fleshed out in deciduoustrees.lua, this would be a bit spaghetti and is highly unlikely.
Additionally, if you look at the actual numbers used with the old variable names, it's clear that they are reasonable decreases/increases to the season based defaults. Therefore, with all the above being considered, I think the correct/originally intended function is:
deciduousmonster = function(difficulty) local tuning_vars = { never = { DECID_MONSTER_MIN_DAY = NEVER_TIME, DECID_MONSTER_SPAWN_CHANCE_AUTUMN = 0, DECID_MONSTER_SPAWN_CHANCE_SPRING = 0, DECID_MONSTER_SPAWN_CHANCE_SUMMER = 0, }, rare = { DECID_MONSTER_MIN_DAY = 5, DECID_MONSTER_SPAWN_CHANCE_AUTUMN = 0.075, -- Updated DECID_MONSTER_SPAWN_CHANCE_SPRING = 0.04, -- Updated DECID_MONSTER_SPAWN_CHANCE_SUMMER = 0.0165, -- Updated }, --[[ default = { DECID_MONSTER_MIN_DAY = 3, DECID_MONSTER_SPAWN_CHANCE_AUTUMN = 0.15, DECID_MONSTER_SPAWN_CHANCE_SPRING = 0.08, DECID_MONSTER_SPAWN_CHANCE_SUMMER = 0.033, }, --]] often = { DECID_MONSTER_MIN_DAY = 2, DECID_MONSTER_SPAWN_CHANCE_AUTUMN = 0.3, -- Updated DECID_MONSTER_SPAWN_CHANCE_SPRING = 0.16, -- Updated DECID_MONSTER_SPAWN_CHANCE_SUMMER = 0.066, -- Updated }, always = { DECID_MONSTER_MIN_DAY = 1, DECID_MONSTER_SPAWN_CHANCE_AUTUMN = 0.6, -- Updated DECID_MONSTER_SPAWN_CHANCE_SPRING = 0.32, -- Updated DECID_MONSTER_SPAWN_CHANCE_SUMMER = 0.132, -- Updated }, } OverrideTuningVariables(tuning_vars[difficulty]) end,
I know that this is a relatively minor issue compared to others, but I'd appreciate it if this could be corrected.
Read the above code review, or create a world with deciduousmonster set to "rare", "often", or "always" and notice that the Poison Birches don't seem to occur any more or less.
-
1
There are no comments to display.
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now