The time to regrow for a replanted Berry Bush is supposed to increases, to a maximum of 7 days, when the Berry Bush has been harvested multiple times since it was last fertilized. This is according to the wiki but also the lines of codes in berrybush.lua
However, there are two major bugs in the current implementation
1. Bug in getregentimefn in berrybush.lua
The function that calculates the regrowth time in berrybush.lua is
local function getregentimefn(inst) if inst.components.pickable then local num_cycles_passed = math.min(inst.components.pickable.max_cycles - inst.components.pickable.cycles_left, 0) return TUNING.BERRY_REGROW_TIME + TUNING.BERRY_REGROW_INCREASE*num_cycles_passed+ math.random()*TUNING.BERRY_REGROW_VARIANCE else return TUNING.BERRY_REGROW_TIME end end
but num_cycles_passed is always zero, because max_cycles-cycles_left is always positive and the math.min will always pick up the zero
This bug can be fixed by replacing math.min with math.max. See also the correct DST version below:
local function getregentimefn_normal(inst) if not inst.components.pickable then return TUNING.BERRY_REGROW_TIME end --V2C: nil cycles_left means unlimited picks, so use max value for math local max_cycles = inst.components.pickable.max_cycles local cycles_left = inst.components.pickable.cycles_left or max_cycles local num_cycles_passed = math.max(0, max_cycles - cycles_left) return TUNING.BERRY_REGROW_TIME + TUNING.BERRY_REGROW_INCREASE * num_cycles_passed + TUNING.BERRY_REGROW_VARIANCE * math.random() end
2. Bug in Pickable:Pick in pickable.lua
The getregentimefn function is only called when a whitered berrybush is fertilized, not when it is picked. This means that even fixing the above bug in getregentimefn, the regrowth time won't actually increase as the bush is harvested. See the Pickable:Pick function below, which calculates the next regrowth time after a berrybush is picked:
function Pickable:Pick(picker) if self.canbepicked and self.caninteractwith then if self.transplanted then if self.cycles_left ~= nil then self.cycles_left = self.cycles_left - 1 end end if self.protected_cycles ~= nil then self.protected_cycles = self.protected_cycles - 1 if self.protected_cycles <= 0 then if not self:IsWithered() then self:MakeWitherable() end end end local loot = nil if picker and picker.components.inventory and self.product then loot = SpawnPrefab(self.product) if loot then if self.numtoharvest > 1 and loot.components.stackable then loot.components.stackable:SetStackSize(self.numtoharvest) end self.inst:ApplyInheritedMoisture(loot) picker:PushEvent("picksomething", {object = self.inst, loot= loot}) picker.components.inventory:GiveItem(loot, nil, Vector3(TheSim:GetScreenPos(self.inst.Transform:GetWorldPosition()))) end end if self.onpickedfn then self.onpickedfn(self.inst, picker, loot) end self.canbepicked = false self.hasbeenpicked = true if not self.paused and not self.withered and self.baseregentime and (self.cycles_left == nil or self.cycles_left > 0) and self.inst:IsValid() then self.regentime = self.baseregentime * self:GetGrowthMod() self.task = self.inst:DoTaskInTime(self.regentime, OnRegen, "regen") self.targettime = GetTime() + self.regentime end self.inst:PushEvent("picked", {picker = picker, loot = loot, plant = self.inst}) end end
This can be fixed by adding the option to use self.getregentimefn if it exist, just like the DST code does. Here how I fixed it in my Miscellaneous Tweaks mod:
-- Pickable:Pick bugfix for vanilla and DLCs local function PickablePickBugFix(inst) function inst:Pick(picker) if self.canbepicked and self.caninteractwith then if self.transplanted and self.cycles_left ~= nil then self.cycles_left = math.max(0, self.cycles_left - 1) end if enabledAnyDLC then if self.protected_cycles ~= nil then self.protected_cycles = self.protected_cycles - 1 if self.protected_cycles <= 0 then if not self:IsWithered() then self:MakeWitherable() end end end end local loot = nil if picker and picker.components.inventory and self.product then loot = GLOBAL.SpawnPrefab(self.product) if loot then if self.numtoharvest > 1 and loot.components.stackable then loot.components.stackable:SetStackSize(self.numtoharvest) end -- Moisture handling, ROG if enabledROG then local targetMoisture = 0 if self.inst.components.moisturelistener then targetMoisture = self.inst.components.moisturelistener:GetMoisture() elseif self.inst.components.moisture then targetMoisture = self.inst.components.moisture:GetMoisture() else targetMoisture = GLOBAL.GetWorld().components.moisturemanager:GetWorldMoisture() end loot.targetMoisture = targetMoisture loot:DoTaskInTime(2*GLOBAL.FRAMES, function() if loot.components.moisturelistener then loot.components.moisturelistener.moisture = loot.targetMoisture loot.targetMoisture = nil loot.components.moisturelistener:DoUpdate() end end) -- Moisture handling, SHIP and PORKLAND elseif enabledSHIP or enabledPORK then self.inst:ApplyInheritedMoisture(loot) end picker:PushEvent("picksomething", {object = self.inst, loot= loot}) picker.components.inventory:GiveItem(loot, nil, GLOBAL.Vector3(GLOBAL.TheSim:GetScreenPos(self.inst.Transform:GetWorldPosition()))) end end if self.onpickedfn then self.onpickedfn(self.inst, picker, loot) end self.canbepicked = false if enabledAnyDLC then self.hasbeenpicked = true end local can_regen = not self.paused and (self.cycles_left == nil or self.cycles_left > 0) -- Vanilla: check on regentime only if vanilla then can_regen = can_regen and self.regentime -- DLCs: also check withered and baseregentime elseif enabledAnyDLC then can_regen = can_regen and not self.withered and self.baseregentime -- PORK: also check inst:IsValid() if enabledPORK then can_regen = can_regen and self.inst:IsValid() end end if can_regen then -- Vanilla: use regentime if getregentimefn not exists if vanilla then self.regentime = self.getregentimefn and self.getregentimefn(self.inst) or self.regentime -- ROG: use baseregentime if getregentimefn not exists, unless IsSpring elseif enabledROG and GLOBAL.GetSeasonManager():IsSpring() then local time = self.getregentimefn and self.getregentimefn(self.inst) or self.baseregentime self.regentime = time * TUNING.SPRING_GROWTH_MODIFIER -- SHIP and PORK: use baseregentime if getregentimefn not exists and GetGrowthMod elseif enabledSHIP or enabledPORK then local time = self.getregentimefn and self.getregentimefn(self.inst) or self.baseregentime self.regentime = time * self:GetGrowthMod() end self.task = self.inst:DoTaskInTime(self.regentime, function(inst) if inst.components.pickable then inst.components.pickable:Regen() end end, "regen") self.targettime = GLOBAL.GetTime() + self.regentime end local pickeddata = { picker = picker, loot = loot } if enabledAnyDLC then pickeddata.plant = self.inst end self.inst:PushEvent("picked", pickeddata) end end end
The function handles correctly all the various DLC branches, as there are 4 different versions of Pickable:Pick depending on the DLC enabled. For the fix available as a mod, see Miscellaneous Tweaks on the Steam workshop
Just look at the original code in berrybush.lua and pickable.lua. The bug can be reproduced by removing the variance and printing the regrowth time with the following mod snippet:
TUNING.BERRY_REGROW_VARIANCE = 0 local function PickableInit(inst) local orig_getregentimefn = inst.components.pickable.getregentimefn inst.components.pickable.getregentimefn = function(inst) print("/ original getregentimefn " .. tostring(orig_getregentimefn(inst))) return orig_getregentimefn(inst) end end AddPrefabPostInit("berrybush", PickableInit) AddPrefabPostInit("berrybush2", PickableInit)
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