Jump to content

Lunar hail updating issues (networking and visuals)


hoxi
  • Fixed

The more severe issue is that when lunar hail is the current precipitation type, StopPrecipitation will get called on the server on every tick, unless permanent rain is enabled. This is really bad for network performance, because:

local StopPrecipitation = _ismastersim and function()
	_moisture:set(_moisturefloor:value()) -- won't sync due to the value being the same unless an external event modified moisture
	_moistureceil:set(RandomizeMoistureCeil()) -- will ALWAYS sync because the value is constantly getting randomized

	if _preciptype:value() ~= PRECIP_TYPES.lunarhail then
		_preciptype:set(PRECIP_TYPES.none)
	end
end or nil

Thinking of it, didn't some people report unusual lag or performance issues with lunar hail? This issue was probably the cause, and if not, it definitely didn't help.

 

So regarding how to fix it, I could just leave it at that, but I do have to point out that there's two possible ways to go about it, mainly because they have to do with how lunar hail works (where it takes over precipitation completely, or simply interrupts it and prevents it from starting again, but otherwise lets moisture increase during the hail).

function self:OnUpdate(dt)
	--Update noise
	SetWithPeriodicSync(_noisetime, _noisetime:value() + dt, NOISE_SYNC_PERIOD, _ismastersim)

	local preciprate = CalculatePrecipitationRate()
	local lunarhailrate = CalculateLunarHailRate()

	--Update moisture and toggle precipitation
	if _preciptype:value() ~= PRECIP_TYPES.lunarhail then -- OPTION 1
		if _precipmode:value() == PRECIP_MODES.always then
			if _ismastersim and _preciptype:value() == PRECIP_TYPES.none then
				StartPrecipitation(_temperature)
			end
		elseif _precipmode:value() == PRECIP_MODES.never then
			if _ismastersim and _preciptype:value() ~= PRECIP_TYPES.none and _preciptype:value() ~= PRECIP_TYPES.lunarhail then -- OPTION 2
				StopPrecipitation()
			end
		elseif _preciptype:value() ~= PRECIP_TYPES.none and _preciptype:value() ~= PRECIP_TYPES.lunarhail then -- OPTION 2
			--Dissipate moisture
			local moisture = math.max(_moisture:value() - preciprate * dt * PRECIP_RATE_SCALE, 0)
			if moisture <= _moisturefloor:value() then
				if _ismastersim then
					StopPrecipitation()
				else
					_moisture:set_local(math.min(_moisturefloor:value() + .001, _moisture:value()))
				end
			else
				SetWithPeriodicSync(_moisture, moisture, MOISTURE_SYNC_PERIOD, _ismastersim)
			end
		elseif _moistureceil:value() > 0 then
			--Accumulate moisture
			local moisture = _moisture:value() + _moisturerate:value() * dt
			if moisture >= _moistureceil:value() then
				if _ismastersim then
					if _preciptype:value() ~= PRECIP_TYPES.lunarhail then -- OPTION 2 (though kinda unneeded here because StartPrecipitation checks for this)
						StartPrecipitation(_temperature)
					end
				else
					_moisture:set_local(math.max(_moistureceil:value() - .001, _moisture:value()))
				end
			else
				SetWithPeriodicSync(_moisture, moisture, MOISTURE_SYNC_PERIOD, _ismastersim)
			end
		end
	end

OPTION 1: encase the whole thing in a "precip type isn't lunar hail" check to not process moisture increasing or decreasing, and precipitation start/stop events. One problem is that external sources can still modify moisture despite this, so those would need to be addressed too (namely, OnForcePrecipitation and OnDeltaMoisture), since currently, moisture will be set to the floor again anyway, meaning it should probably stay that way, just without destroying the network performance.

This is probably the more fitting one with the current way lunar hail works, because feels like it just takes over rain/snow entirely and does its thing, especially given that it literally stops precipitation and sets atmosphere moisture to the floor value.

OPTION 2: only allow moisture increasing during lunar hail (but don't let precipitation start of course), as well as allow external events to modify it. A bit different from option 1, where moisture will go down to the floor value on starting hail, then proceed to go up again as usual, and precipitation will be blocked from starting until hail ends.

 

----------------------------------------------------------------------------------------------------------------------------------

 

Now, onto a less severe issues, but still a noticeable one, is weather lighting (not lightning), when lunar hail is active, and when it's about to be active. Currently, there's very noticeable snaps in lighting depending on current moisture, or if rain is set to lots/always.

Here's an example with code and comments:

local LUNAR_HAIL_NEAR_START_THRESHOLD = LUNAR_HAIL_CEIL * 0.95

local function CalculateLight()
	if _preciptype:value() == PRECIP_TYPES.lunarhail then
		-- HERE, match the permanent rain lighting, because it'll immediately go back to that anyway
		-- otherwise it'll look like the skies are clearing and then instantly get darker because of the big difference
		if _precipmode:value() == PRECIP_MODES.always then
			local snowlight = _temperature < _startsnowthreshold
			local dynrange = snowlight and (_daylight and SEASON_DYNRANGE_DAY["winter"] or SEASON_DYNRANGE_NIGHT["winter"])
								or (_daylight and SEASON_DYNRANGE_DAY[_season] or SEASON_DYNRANGE_NIGHT[_season])

			return 1 - dynrange
		end

		local dynrange = _daylight and SEASON_DYNRANGE_DAY[_season] or SEASON_DYNRANGE_NIGHT[_season]
		local p = 1 - CalculateLunarHailRate()
		p = easing.inQuad(p, 0, 1, 1)

		return p * dynrange + 1 - dynrange
	end

	if _precipmode:value() == PRECIP_MODES.never then
		return 1
	end

	local season = _season
	local snowlight = _preciptype:value() == PRECIP_TYPES.snow
	local dynrange = snowlight and (_daylight and SEASON_DYNRANGE_DAY["winter"] or SEASON_DYNRANGE_NIGHT["winter"])
								or (_daylight and SEASON_DYNRANGE_DAY[season] or SEASON_DYNRANGE_NIGHT[season])

	if _precipmode:value() == PRECIP_MODES.always then
		return 1 - dynrange
	end

	-- HERE, use something like a LUNAR_HAIL_NEAR_START_THRESHOLD (value is up to you)
	-- to directly modify the dynrange value (or p instead, up to you) and smoothly clear the skies a bit before lunar hail starts, otherwise it'll be very sudden and snappy
	-- didn't think too hard about this one, just tried to get results and give an example, you'd probably know a better way to do/handle this
	if _world.components.riftspawner ~= nil
		and _world.components.riftspawner:IsLunarPortalActive()
		and _lunarhaillevel:value() >= LUNAR_HAIL_NEAR_START_THRESHOLD
	then
		dynrange = dynrange * (1 - math.clamp((_lunarhaillevel:value() - LUNAR_HAIL_NEAR_START_THRESHOLD) / (LUNAR_HAIL_CEIL - LUNAR_HAIL_NEAR_START_THRESHOLD), 0, 1))
	end

	local p = 1 - math.min(math.max((_moisture:value() - _moisturefloor:value()) / (_moistureceil:value() - _moisturefloor:value()), 0), 1)
	if _preciptype:value() ~= PRECIP_TYPES.none then
		p = easing.inQuad(p, 0, 1, 1)
	end
	return p * dynrange + 1 - dynrange
end

The only issue with the second bit is that it might look weird if the skies are clearing, but there's still potential heavy rain happening, so you might have to add something like that too to the precipitation rate to limit it.

 

Lastly, should this account for lunar hail?

local function CalculatePOP()
	return (_preciptype:value() ~= PRECIP_TYPES.none and 1)
		or ((_moistureceil:value() <= 0 or _moisture:value() <= _moisturefloor:value()) and 0)
		or (_moisture:value() < _moistureceil:value() and (_moisture:value() - _moisturefloor:value()) / (_moistureceil:value() - _moisturefloor:value()))
		or 1
end

Since lunar hail isn't based on moisture and it gets rid of moisture. Or should it maybe do something similar to the bit above, with the lunar hail start threshold? Like with a value from 0 to 1 before lunar hail starts, but still clamped up if the pop value from moisture would be higher.


Steps to Reproduce

For the network variable issue:

  1. Start a world with rain not set to lots/always.
  2. Have TheWorld.net debug-selected (as host or client doesn't matter, but host will show how quickly it changes).
  3. Start lunar hail.
  4. Notice how the moisture ceiling value will constantly change, which also means it's syncing every one of those values.

For the lighting issues:

  1. Start a world with rain not set to none/never.
  2. While it just started raining (or at any point with permanent rain), have hail start.
  3. Notice how the skies will clear and things will become brighter in an instant.
  4. (if permanent rain is active) Wait until lunar hail is about to be done, and notice how things will do the opposite from step 3, going from bright to darker instantly.



User Feedback


A developer has marked this issue as fixed. This means that the issue has been addressed in the current development build and will likely be in the next update.


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 account

Sign in

Already have an account? Sign in here.

Sign In Now

×
  • Create New...