Either, the component needs to be refactored to simply not use season duration when season mood is active, and simply listen to the season changing to change this, or, keep what I think might've been intended here (similar to other features), which is to have things during endless seasons use a length of 20 days as reference, as a way to not be too repetitive and allow some cycles, but address some of its behavior.
For starters, the component doesn't save its self.seasonmood variable. This means that even when season mood does end in an endless mood season, it'll simply reenable itself the moment you restart the server.
function Mood:OnSave() local multiplier = self.isinmood and self.worldsettingsmultiplier_inmood or self.worldsettingsmultiplier_outmood return {inmood = self.isinmood, daysleft = self.daystomoodchange ~= 0 and self.daystomoodchange / multiplier or 0, moodseasons = self.moodseasons, version = 2} end function Mood:OnLoad(data) self.moodseasons = data.moodseasons or self.moodseasons self.isinmood = not data.inmood local active = false local season = TheWorld.state.season if self.moodseasons then for i, s in pairs(self.moodseasons) do if season and s == season then active = true break end end end self:SetIsInMood(data.inmood, active) if not data.version then local max = self.isinmood and self.worldsettingsmultiplier_inmood or self.worldsettingsmultiplier_outmood self.daystomoodchange = math.min(data.daysleft, max) elseif data.version == 2 then local multiplier = self.isinmood and self.worldsettingsmultiplier_inmood or self.worldsettingsmultiplier_outmood self.daystomoodchange = RoundBiasedUp(data.daysleft * multiplier) end end
Honestly, I'm not even sure why self.moodseasons is saved, given that it's set on the prefab constructor, and changing it on the fly could only lead to issues as it's not dynamically checked until a restart, season change, or manual function call is made, so it doesn't seem like something you'd need or want to save. But you would want to save self.seasonmood and use it there for the SetIsInMood call.
Another very important bit is that the daysleft save data value needs to outright save the amount of days without the multiplier division if self.seasonmood is true, otherwise you could end up shortening seasonal mood if settings (for Beefalo Heat frequency) are changed between server restarts, both in endless seasons and in normal seasons.
At the bottom of the report, there is an edited version of the save and load functions with the things pointed out here and some stuff pointed out below, as well as more.
There's also these bits:
function Mood:CheckForMoodChange() if self.daystomoodchange <= 0 then --self:SetIsInMood(not self:IsInMood() or self.forcemood) self:SetIsInMood(not self:IsInMood() or self.forcemood, self.seasonmood) end end function Mood:ResetMood() if self.seasonmood then local wasinmood = self.isinmood self.seasonmood = false self.isinmood = false self.daystomoodchange = self.moodtimeindays.wait --if self.onleavemood then if wasinmood and self.onleavemood then -- don't call onleavemood if mood wasn't active self.onleavemood(self.inst) end end end
CheckForMoodChange currently overrides if season mood is active, which is relevant for endless mood seasons. This gets in the way of allowing an endless mood season to allow cycling back and forth between being in heat or not (which again, I think that was the original intention).
The ResetMood bit is just a small change to be cleaner.
Lastly for the component, this function does need some changes:
function Mood:SetIsInMood(inmood, entireseason) if inmood and not (self.enabled and self.worldsettingsenabled) then return end if self.isinmood ~= inmood or entireseason then self.isinmood = inmood if self.isinmood then if entireseason then self.seasonmood = true self.daystomoodchange = GetSeasonLength() or self.moodtimeindays.length else self.seasonmood = false self.daystomoodchange = self.moodtimeindays.length end if self.onentermood then self.onentermood(self.inst) end else if not entireseason then self.seasonmood = false self.daystomoodchange = self.moodtimeindays.wait end if self.onleavemood then self.onleavemood(self.inst) end end end end
To something like this maybe:
function Mood:SetIsInMood(inmood, entireseason) if inmood and not (self.enabled and self.worldsettingsenabled) then return end -- you can do this more properly, just doing it like this for reference -- you should set self.seasonmood = false in the component constructor as well entireseason = entireseason or false inmood = inmood or false if self.isinmood ~= inmood or self.seasonmood ~= entireseason then local mood_updated = self.isinmood ~= inmood self.isinmood = inmood self.seasonmood = entireseason if self.isinmood then self.daystomoodchange = self.seasonmood and GetSeasonLength() or self.moodtimeindays.length if mood_updated and self.onentermood then self.onentermood(self.inst) end else self.daystomoodchange = self.seasonmood and GetSeasonLength() or self.moodtimeindays.wait if mood_updated and self.onleavemood then self.onleavemood(self.inst) end end end end
The general idea is to prevent the entireseason parameter from always going through and producing changes, including calling the onentermood and onleavemood functions, as well as allowing a seasonal wait time to be set as well, for endless mood seasons.
Lastly for all this, there's one last thing to tackle outside of the mood component, in prefabs/beefaloherd.lua:
local function OnInit(inst) inst.components.mood:ValidateMood() end -- in "beefaloherd" prefab constructor inst:DoTaskInTime(0, OnInit)
This is a problem because it can override loaded save data, both currently, and it still would with the changes I suggested here. This has no actual effects outside of an endless season, but it can still end up overriding things, and during an endless mood season, it straight up resets the whole process, where mood gets forced enabled and duration is set to 20 days.
You might want to make this task get scheduled through the component instead (it doesn't make much sense for it to be done externally when it seems like something that would be relevant for anything using the mood component, instead of specifically the beefalo herd), and cancel it when the component loads save data.
After all, if it's there specifically for this reason:
-- Use this to set the mood correctly (used for making sure the beefalo are mating when the start season is spring)
It shouldn't be going through when loading in.
You could do something as simple as this to get the same result:
-- in component constructor local Mood = Class(function(self, inst) -- rest of the function self.startingseasontask = self.inst:DoTaskInTime(0, function(inst) self.startingseasontask = nil local mood = inst.components.mood if mood ~= nil then mood:ValidateMood() end end) end
And cancel it through the OnLoad function.
Below is how the modified save and load functions look like with all the corrections and changes mentioned through the report:
function Mood:OnSave() local multiplier = self.isinmood and self.worldsettingsmultiplier_inmood or self.worldsettingsmultiplier_outmood local data = { inmood = self.isinmood, --moodseasons = self.moodseasons, -- don't want to save this seasonmood = self.seasonmood, daysleft = self.seasonmood and self.daystomoodchange or self.daystomoodchange ~= 0 and self.daystomoodchange / multiplier or 0, version = 2, } return data end function Mood:OnLoad(data) -- we don't want to run the init task after loading save data or we'll override most of it if self.startingseasontask ~= nil then self.startingseasontask:Cancel() self.startingseasontask = nil end --self.moodseasons = data.moodseasons or self.moodseasons self.isinmood = not data.inmood self.seasonmood = not data.seasonmood self:SetIsInMood(not not data.inmood, not not data.seasonmood) if not data.version then local max = self.isinmood and self.worldsettingsmultiplier_inmood or self.worldsettingsmultiplier_outmood self.daystomoodchange = math.min(data.daysleft, max) elseif data.version == 2 then -- don't apply a multiplier for season mood if self.seasonmood then self.daystomoodchange = data.daysleft else local multiplier = self.isinmood and self.worldsettingsmultiplier_inmood or self.worldsettingsmultiplier_outmood self.daystomoodchange = RoundBiasedUp(data.daysleft * multiplier) end end end
I'll update the report if I find more issues, but this should be enough to make this work more consistently in endless seasons.
I have verified that all of this works with all of the changes. Cycles are saved properly during endless mood seasons, and otherwise the usual gameplay.
- Start a world with endless spring.
- Find a Beefalo herd.
- Skip/wait until spring starts.
- Then skip/wait a few days.
- Print how many days are left for the Beefalo herd to change mood.
- Now restart the server, and print that again (can always use the GetDebugString function).
- Notice how the day counter has reset.
- Now skip enough days for mood to change, then print the same value again, and keep in mind that seasonal mood should now be disabled.
- Restart the server.
- Notice how seasonal mood is enabled again and the duration has reset.
-
1
-
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