mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 21:53:46 +03:00
Upload
This commit is contained in:
447
lua/stormfox2/framework/sh_weather_handle.lua
Normal file
447
lua/stormfox2/framework/sh_weather_handle.lua
Normal file
@@ -0,0 +1,447 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
-- Updates the weather for given players
|
||||
|
||||
local lastSet = 0
|
||||
local CurrentWeather
|
||||
local CurrentPercent = 1
|
||||
|
||||
local function isColor(t)
|
||||
return t.r and t.g and t.b and true or false
|
||||
end
|
||||
local function Blender(nFraction, vFrom, vTo) -- Will it blend?
|
||||
-- Nils should be false, if one of them is a boolean
|
||||
if type(vFrom) == "nil" and type(vTo) == "boolean" then
|
||||
vFrom = false
|
||||
end
|
||||
if type(vTo) == "nil" and type(vFrom) == "boolean" then
|
||||
vTo = false
|
||||
end
|
||||
-- If the same value, then return it
|
||||
if vTo == vFrom then return vTo end
|
||||
-- In case of two diffrent variables.
|
||||
if type(vFrom) ~= type(vTo) then
|
||||
StormFox2.Warning("Mixer called with values of two different types[" .. type(vFrom) .. "," .. type(vTo) .. "]")
|
||||
debug.Trace()
|
||||
return vFrom
|
||||
elseif type(vTo) == "string" or type(vTo) == "IMaterial" or type(vTo) == "boolean" then -- String, material or bool. Return vTo.
|
||||
return vTo
|
||||
elseif type(vTo) == "number" then -- Number
|
||||
return Lerp(nFraction, vFrom, vTo)
|
||||
elseif type(vTo) == "table" and isColor(vTo) then -- Color
|
||||
local r = Lerp( nFraction, vFrom.r or 255, vTo.r )
|
||||
local g = Lerp( nFraction, vFrom.g or 255, vTo.g )
|
||||
local b = Lerp( nFraction, vFrom.b or 255, vTo.b )
|
||||
local a = Lerp( nFraction, vFrom.a or 255, vTo.a )
|
||||
return Color( r, g, b, a )
|
||||
end
|
||||
--StormFox2.Warning("ERROR: Unsupported mix value type[" .. type(vTo) .. "]. Returning original value")
|
||||
--debug.Trace()
|
||||
return vFrom
|
||||
end
|
||||
|
||||
local function IsSame(sName, nPercentage, nDelta)
|
||||
if CurrentPercent ~= nPercentage then return false end
|
||||
if not CurrentWeather then return false end
|
||||
return CurrentWeather.Name == sName
|
||||
end
|
||||
|
||||
local function ApplyWeather(sName, nPercentage, nDelta)
|
||||
hook.Run("StormFox2.weather.prechange", sName ,nPercentage )
|
||||
if nDelta and nDelta <= 0 then
|
||||
nDelta = nil
|
||||
elseif nDelta then
|
||||
local sp = StormFox2.Time.GetSpeed_RAW()
|
||||
if sp > 0 then
|
||||
nDelta = nDelta / sp
|
||||
end
|
||||
end
|
||||
local bSameWeather = sName == (CurrentWeather and CurrentWeather.Name or "Clear")
|
||||
if CurrentWeather and CurrentWeather.OnChange then
|
||||
CurrentWeather:OnChange( sName, nPercentage, nDelta )
|
||||
end
|
||||
if CurrentWeather and CurrentWeather.OnRemove and not bSameWeather then
|
||||
CurrentWeather:OnRemove( sName, nPercentage, nDelta )
|
||||
end
|
||||
local clear = StormFox2.Weather.Get( "Clear" )
|
||||
CurrentWeather = StormFox2.Weather.Get( sName )
|
||||
CurrentPercent = nPercentage
|
||||
local stamp = StormFox2.Sky.GetLastStamp()
|
||||
|
||||
if sName == "Clear" then
|
||||
nPercentage = 1
|
||||
end
|
||||
if nPercentage >= 1 then
|
||||
for _,key in ipairs( StormFox2.Weather.GetKeys() ) do
|
||||
local v = CurrentWeather:Get( key, stamp )
|
||||
if type(v) == "table" and not (v.r and v.g and v.b) then
|
||||
StormFox2.Data.Set(key, v)
|
||||
else
|
||||
StormFox2.Data.Set(key, v, nDelta)
|
||||
end
|
||||
end
|
||||
elseif nPercentage <= 0 then
|
||||
for _,key in ipairs( StormFox2.Weather.GetKeys() ) do
|
||||
StormFox2.Data.Set(key, clear:Get( key, stamp ), nDelta)
|
||||
end
|
||||
else -- Mixing bin
|
||||
for _,key in ipairs( StormFox2.Weather.GetKeys() ) do
|
||||
local var2,b_nomix = CurrentWeather:Get( key, stamp )
|
||||
local d = nDelta
|
||||
if type(var2) == "table" and not (var2.r and var2.g and var2.b) then
|
||||
d = nil
|
||||
end
|
||||
if b_nomix then
|
||||
StormFox2.Data.Set(key, var2, d)
|
||||
else
|
||||
local var1 = clear:Get( key, stamp )
|
||||
if var2 and not var1 then -- This is not a default variable
|
||||
if type(var2) == "number" then
|
||||
var1 = 0
|
||||
end
|
||||
end
|
||||
if not var1 and var2 then -- THis is not a default varable
|
||||
StormFox2.Data.Set(key, var2, d)
|
||||
elseif var1 and var2 then
|
||||
StormFox2.Data.Set(key, Blender(nPercentage, var1, var2), d)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if CurrentWeather.Init and not bSameWeather then
|
||||
CurrentWeather.Init()
|
||||
end
|
||||
if CurrentWeather.Tick10 then
|
||||
CurrentWeather.Tick10()
|
||||
end
|
||||
hook.Run("StormFox2.weather.postchange", sName ,nPercentage, nDelta )
|
||||
end
|
||||
|
||||
hook.Add("StormFox2.Sky.StampChange","StormFox2.Weather.Stamp",function(_,nLerpTime)
|
||||
ApplyWeather(CurrentWeather and CurrentWeather.Name or "Clear", CurrentPercent, nLerpTime)
|
||||
end)
|
||||
|
||||
---Returns the current weather-type.
|
||||
---@return Weather
|
||||
function StormFox2.Weather.GetCurrent()
|
||||
return CurrentWeather or StormFox2.Weather.Get( "Clear" )
|
||||
end
|
||||
|
||||
---Returns the current weather percent.
|
||||
---@return number Percent
|
||||
function StormFox2.Weather.GetPercent()
|
||||
return StormFox2.Data.Get("w_Percentage",CurrentPercent)
|
||||
end
|
||||
|
||||
---Returns the weather percent we're lerping to.
|
||||
---@return number
|
||||
function StormFox2.Weather.GetFinishPercent()
|
||||
return CurrentPercent
|
||||
end
|
||||
|
||||
---Returns the current weather description. Like 'Snow', 'Storm' .. ect.
|
||||
---Second argument isn't translated.
|
||||
---@return string Description
|
||||
---@return string Description_Untranslated
|
||||
function StormFox2.Weather.GetDescription()
|
||||
local c = StormFox2.Weather.GetCurrent()
|
||||
if not c.GetName then
|
||||
return c.Name
|
||||
end
|
||||
local a,b = c:GetName(StormFox2.Time.Get(), StormFox2.Temperature.Get(), StormFox2.Wind.GetForce(), StormFox2.Thunder.IsThundering(), StormFox2.Weather.GetPercent())
|
||||
return a,b or a
|
||||
end
|
||||
|
||||
local errM = Material("error")
|
||||
|
||||
---Returns the current weather-icon.
|
||||
---@return userdata Material
|
||||
function StormFox2.Weather.GetIcon()
|
||||
local c = StormFox2.Weather.GetCurrent()
|
||||
if not c.GetIcon then
|
||||
return errM
|
||||
end
|
||||
return c.GetIcon(StormFox2.Time.Get(), StormFox2.Temperature.Get(), StormFox2.Wind.GetForce(), StormFox2.Thunder.IsThundering(), StormFox2.Weather.GetPercent())
|
||||
end
|
||||
|
||||
local SF_UPDATE_WEATHER = 0
|
||||
local SF_INIT_WEATHER = 1
|
||||
|
||||
if SERVER then
|
||||
local l_data
|
||||
|
||||
---Sets the weather.
|
||||
---@server
|
||||
---@param sName string
|
||||
---@param nPercentage number
|
||||
---@param nDelta? number
|
||||
---@return boolean success
|
||||
function StormFox2.Weather.Set( sName, nPercentage, nDelta )
|
||||
if not StormFox2.Setting.GetCache("enable", true) then return end -- Just in case
|
||||
if nDelta and l_data and nDelta == l_data then
|
||||
if IsSame(sName, nPercentage) then return false end
|
||||
end
|
||||
l_data = nDelta
|
||||
-- Default vals
|
||||
if not nDelta then
|
||||
nDelta = 4
|
||||
end
|
||||
if not nPercentage then
|
||||
nPercentage = 1
|
||||
end
|
||||
-- Unknown weathers gets replaced with 'Clear'
|
||||
if not StormFox2.Weather.Get( sName ) then
|
||||
StormFox2.Warning("Unknown weather: " .. tostring(sName))
|
||||
sName = "Clear"
|
||||
end
|
||||
-- In case we set the weather to clear, change it so it is the current weather at 0 instead
|
||||
if sName == "Clear" and CurrentWeather and nDelta > 0 then
|
||||
nPercentage = 0
|
||||
sName = CurrentWeather.Name
|
||||
elseif sName == "Clear" then
|
||||
nPercentage = 1
|
||||
end
|
||||
lastSet = CurTime()
|
||||
net.Start( StormFox2.Net.Weather )
|
||||
net.WriteBit(SF_UPDATE_WEATHER)
|
||||
net.WriteUInt( math.max(0, StormFox2.Data.GetLerpEnd( "w_Percentage" )), 32)
|
||||
net.WriteFloat(nPercentage)
|
||||
net.WriteString(sName)
|
||||
net.WriteFloat(CurTime() + nDelta)
|
||||
net.Broadcast()
|
||||
ApplyWeather(sName, nPercentage, nDelta)
|
||||
if sName == "Clear" then
|
||||
nPercentage = 0
|
||||
end
|
||||
StormFox2.Data.Set("w_Percentage",nPercentage,nDelta)
|
||||
return true
|
||||
end
|
||||
net.Receive( StormFox2.Net.Weather, function(len, ply) -- OI, what weather?
|
||||
local lerpEnd = StormFox2.Data.GetLerpEnd( "w_Percentage" )
|
||||
net.Start( StormFox2.Net.Weather )
|
||||
net.WriteBit(SF_INIT_WEATHER)
|
||||
net.WriteUInt( math.max(0, StormFox2.Data.GetLerpEnd( "w_Percentage" )), 32)
|
||||
net.WriteFloat( CurrentPercent )
|
||||
net.WriteString( StormFox2.Weather.GetCurrent().Name )
|
||||
net.WriteFloat( StormFox2.Data.Get("w_Percentage",CurrentPercent) )
|
||||
net.Send(ply)
|
||||
end)
|
||||
-- Handles the terrain logic
|
||||
timer.Create("StormFox2.terrain.updater", 4, 0, function()
|
||||
local cW = StormFox2.Weather.GetCurrent()
|
||||
local cT = StormFox2.Terrain.GetCurrent()
|
||||
|
||||
if not cW then return end -- No weather!?
|
||||
local terrain = cW:Get("Terrain")
|
||||
if not cT and not terrain then return end -- No terrain detected
|
||||
if cT and terrain and cT == terrain then return end -- Same terrain detected
|
||||
if terrain then -- Switch terraintype out. This can't be the same as the other
|
||||
StormFox2.Terrain.Set(terrain.Name)
|
||||
elseif not terrain and not cT.lock then -- This terrain doesn't have a lock. Reset terrain
|
||||
StormFox2.Terrain.Reset()
|
||||
elseif not terrain and cT.lock then -- Check the lock of cT and see if we can reset
|
||||
if cT:lock() then -- Lock tells us we can reset the terrain
|
||||
StormFox2.Terrain.Reset()
|
||||
end
|
||||
end
|
||||
end)
|
||||
local tS = CurTime()
|
||||
-- In case no weather was set
|
||||
timer.Simple(8, function()
|
||||
-- Clear up weather when it reaches 0
|
||||
timer.Create("StormFox2.weather.clear",1,0,function()
|
||||
if not CurrentWeather then return end
|
||||
if CurrentWeather.Name == "Clear" then return end
|
||||
local p = StormFox2.Weather.GetPercent()
|
||||
if p <= 0 then
|
||||
StormFox2.Weather.Set("Clear", 1, 0)
|
||||
end
|
||||
end)
|
||||
if CurrentWeather then return end
|
||||
StormFox2.Weather.Set("Clear", 1, 0)
|
||||
end)
|
||||
else
|
||||
local hasLocalWeather = false
|
||||
local svWeather
|
||||
local function SetW( sName, nPercentage, nDelta )
|
||||
-- Block same weather
|
||||
if IsSame(sName, nPercentage) then return false end
|
||||
ApplyWeather(sName, nPercentage, nDelta)
|
||||
if sName == "Clear" then
|
||||
nPercentage = 0
|
||||
end
|
||||
StormFox2.Data.Set("w_Percentage",nPercentage,nDelta)
|
||||
end
|
||||
|
||||
---Sets the weather on the client. Server-side stuff won't be set.
|
||||
---@client
|
||||
---@param sName? string
|
||||
---@param nPercentage? number
|
||||
---@param nDelta? number
|
||||
---@param nTemperature? number
|
||||
function StormFox2.Weather.SetLocal( sName, nPercentage, nDelta, nTemperature)
|
||||
-- If nil then remove the local weather
|
||||
if not sName then
|
||||
return StormFox2.Weather.RemoveLocal()
|
||||
end
|
||||
-- Unknown weathers gets replaced with 'Clear'
|
||||
if not StormFox2.Weather.Get( sName ) then
|
||||
StormFox2.Warning("Unknown weather: " .. tostring(sName))
|
||||
sName = "Clear"
|
||||
end
|
||||
if not hasLocalWeather then
|
||||
svWeather = {StormFox2.Weather.GetCurrent().Name, StormFox2.Weather.GetFinishPercent(), StormFox2.Temperature.Get()}
|
||||
end
|
||||
StormFox2.Temperature.SetLocal(nTemperature)
|
||||
-- Block same weather
|
||||
SetW(sName, nPercentage or 1, nDelta)
|
||||
hasLocalWeather = true
|
||||
end
|
||||
|
||||
---Removes the local weather.
|
||||
---@client
|
||||
function StormFox2.Weather.RemoveLocal()
|
||||
if not hasLocalWeather then return end
|
||||
SetW(svWeather[1], svWeather[2], 4)
|
||||
StormFox2.Temperature.SetLocal(nil)
|
||||
svWeather = nil
|
||||
hasLocalWeather = false
|
||||
end
|
||||
net.Receive( StormFox2.Net.Weather, function(len)
|
||||
local flag = net.ReadBit() == SF_UPDATE_WEATHER
|
||||
local wTarget = net.ReadUInt(32)
|
||||
local nPercentage = net.ReadFloat()
|
||||
local sName = net.ReadString()
|
||||
if flag then
|
||||
local nDelta = net.ReadFloat() - CurTime()
|
||||
-- Calculate the time since server set this
|
||||
if not hasLocalWeather then
|
||||
SetW(sName, nPercentage, nDelta)
|
||||
else
|
||||
svWeather[1] = sName
|
||||
svWeather[2] = nPercentage
|
||||
end
|
||||
else
|
||||
local current = net.ReadFloat()
|
||||
if not hasLocalWeather then
|
||||
local secondsLeft = wTarget - CurTime()
|
||||
if secondsLeft <= 0 then
|
||||
SetW(sName, nPercentage, 0)
|
||||
else
|
||||
SetW(sName, current, 0)
|
||||
SetW(sName, nPercentage, secondsLeft)
|
||||
end
|
||||
else
|
||||
svWeather[1] = sName
|
||||
svWeather[2] = nPercentage
|
||||
end
|
||||
end
|
||||
end)
|
||||
-- Ask the server what weather we have
|
||||
hook.Add("StormFox2.InitPostEntity", "StormFox2.terrain", function()
|
||||
net.Start( StormFox2.Net.Weather )
|
||||
net.SendToServer()
|
||||
end)
|
||||
end
|
||||
|
||||
hook.Add("Think", "StormFox2.Weather.Think", function()
|
||||
if not CurrentWeather then return end
|
||||
if not CurrentWeather.Think then return end
|
||||
if not StormFox2.Setting.SFEnabled() then return end
|
||||
CurrentWeather:Think()
|
||||
end)
|
||||
|
||||
timer.Create("StormFox2.Weather.tickslow", 1, 0, function()
|
||||
if not CurrentWeather then return end
|
||||
if not CurrentWeather.TickSlow then return end
|
||||
CurrentWeather.TickSlow()
|
||||
end)
|
||||
|
||||
hook.Add("StormFox2.weather.postchange", "StormFox2.weather.slowtickinit", function()
|
||||
if not CurrentWeather then return end
|
||||
if not CurrentWeather.TickSlow then return end
|
||||
CurrentWeather.TickSlow()
|
||||
end)
|
||||
|
||||
if CLIENT then
|
||||
local c_tab = {"PostDrawTranslucentRenderables", "PreDrawTranslucentRenderables", "HUDPaint"}
|
||||
for i,v in ipairs(c_tab) do
|
||||
hook.Add(v, "StormFox2.Weather." .. v, function(...)
|
||||
if not CurrentWeather then return end
|
||||
if not CurrentWeather[v] then return end
|
||||
CurrentWeather[v](...)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
-- Some functions to make it easier.
|
||||
|
||||
---Returns true if it is raining, or if current weather is child of rain.
|
||||
---@return boolean
|
||||
---@shared
|
||||
function StormFox2.Weather.IsRaining()
|
||||
local wT = StormFox2.Weather.GetCurrent()
|
||||
if wT.Inherit == "Rain" then return true end
|
||||
if wT.Name ~= "Rain" then return false end
|
||||
return StormFox2.Temperature.Get() > -2 or false
|
||||
end
|
||||
|
||||
---Returns true if it is snowing.
|
||||
---@return boolean
|
||||
---@shared
|
||||
function StormFox2.Weather.IsSnowing()
|
||||
local wT = StormFox2.Weather.GetCurrent()
|
||||
if wT.Name ~= "Rain" then return false end
|
||||
return StormFox2.Temperature.Get() <= -2 or false
|
||||
end
|
||||
|
||||
---Returns the rain / snow amount. Between 0 - 1.
|
||||
---@return number
|
||||
---@shared
|
||||
function StormFox2.Weather.GetRainAmount()
|
||||
if not StormFox2.Weather.IsRaining() then return 0 end
|
||||
return StormFox2.Weather.GetPercent()
|
||||
end
|
||||
|
||||
---Returns true if the current weather is raining, snowing or inherit from rain.
|
||||
---@return boolean
|
||||
---@shared
|
||||
function StormFox2.Weather.HasDownfall()
|
||||
local wT = StormFox2.Weather.GetCurrent()
|
||||
if wT.Inherit == "Rain" then return true end
|
||||
return wT.Name == "Rain"
|
||||
end
|
||||
|
||||
-- Downfall
|
||||
|
||||
---Returns true if the entity is hit by rain or any downfall.
|
||||
---@param eEnt Entity
|
||||
---@param bDont_cache boolean
|
||||
---@return boolean
|
||||
---@shared
|
||||
function StormFox2.DownFall.IsEntityHit(eEnt, bDont_cache)
|
||||
if not StormFox2.Weather.HasDownfall() then return false end
|
||||
return (StormFox2.Wind.IsEntityInWind(eEnt,bDont_cache))
|
||||
end
|
||||
|
||||
---Checks to see if the given point is hit by rain.
|
||||
---@param vPos Vector
|
||||
---@return boolean
|
||||
---@shared
|
||||
function StormFox2.DownFall.IsPointHit(vPos)
|
||||
if not StormFox2.Weather.HasDownfall() then return false end
|
||||
local t = util.TraceLine( {
|
||||
start = vPos,
|
||||
endpos = vPos + -StormFox2.Wind.GetNorm() * 262144,
|
||||
mask = StormFox2.DownFall.Mask
|
||||
} )
|
||||
return t.HitSky
|
||||
end
|
||||
Reference in New Issue
Block a user