mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
288 lines
8.9 KiB
Lua
288 lines
8.9 KiB
Lua
--[[
|
|
| 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/
|
|
--]]
|
|
|
|
--[[-------------------------------------------------------------------------
|
|
Use the map-data to set a minimum and maximum fogdistance
|
|
---------------------------------------------------------------------------]]
|
|
StormFox2.Setting.AddSV("enable_svfog",true,nil, "Effects")
|
|
if CLIENT then StormFox2.Setting.AddCL("enable_fog",true, "sf_enable_fog") end
|
|
StormFox2.Setting.AddSV("enable_fogz",false,nil, "Effects")
|
|
StormFox2.Setting.AddSV("overwrite_fogdistance",-1,nil, "Effects", -1, 800000)
|
|
StormFox2.Setting.SetType("overwrite_fogdistance","special_float")
|
|
StormFox2.Setting.AddSV("allow_fog_change",engine.ActiveGamemode() == "sandbox",nil, "Effects")
|
|
|
|
StormFox2.Fog = {}
|
|
-- Local functions
|
|
local function fogEnabledCheck()
|
|
if not StormFox2.Setting.SFEnabled() then return false end
|
|
if not StormFox2.Setting.GetCache("enable_svfog", true) then return false end
|
|
if not StormFox2.Setting.GetCache("allow_fog_change", false) then return true end
|
|
return StormFox2.Setting.GetCache("enable_fog", true)
|
|
end
|
|
local _fS, _fE, _fD = 0,400000,1
|
|
local function fogStart( f )
|
|
_fS = f
|
|
end
|
|
local function fogEnd( f )
|
|
_fE = f
|
|
end
|
|
local function fogDensity( f )
|
|
_fD = f
|
|
end
|
|
local function getFogFill()
|
|
if _fS >= 0 then return 0 end
|
|
return -_fS / (_fE - _fS) * _fD * 0.1
|
|
end
|
|
-- Makes it so fog isn't linear
|
|
local e = 2.71828
|
|
local function fogCalc(b, a, p)
|
|
if a == b then return a end
|
|
p = e^(-8.40871*p)
|
|
local d = b - a
|
|
return a + d * p
|
|
end
|
|
|
|
---Returns the start of the fog.
|
|
---@return number
|
|
---@shared
|
|
function StormFox2.Fog.GetStart()
|
|
return math.max(0, _fS)
|
|
end
|
|
|
|
---Returns the end of fog.
|
|
---@return number
|
|
---@shared
|
|
function StormFox2.Fog.GetEnd()
|
|
return _fE
|
|
end
|
|
-- Locate / Calculate the default fog-data
|
|
local map_distance, map_farZ = -1, -1
|
|
local tab = StormFox2.Map.FindClass("env_fog_controller")
|
|
if #tab < 1 then
|
|
map_distance = 400000
|
|
else
|
|
-- Set a minimum
|
|
map_distance = 6000
|
|
for _, data in ipairs(tab) do
|
|
map_farZ = math.max(map_farZ, data.farz)
|
|
-- Calculate fog-brightness. We can use this to scale the map-distance up to match the fog.
|
|
local col_brightness = 1
|
|
local density = (tonumber( data.fogmaxdensity or "" ) or 1)
|
|
if data.fogcolor then
|
|
local fcol = string.Explode(" ", data.fogcolor)
|
|
col_brightness = (0.2126 * fcol[1] + 0.7152 * fcol[2] + 0.0722 * fcol[3]) / 255
|
|
end
|
|
density = density * col_brightness
|
|
map_distance = math.max(((data.fogend or 6000) / density), map_distance)
|
|
end
|
|
-- It is important we don't overshoot farZ
|
|
if map_farZ > 0 then
|
|
map_distance = math.min(map_distance, map_farZ)
|
|
end
|
|
end
|
|
|
|
---Returns the fog-amount. 0 - 1
|
|
---@return number
|
|
---@shared
|
|
function StormFox2.Fog.GetAmount()
|
|
return 1 - _fE / map_distance
|
|
end
|
|
|
|
---Returns the fog-distance ( Same as StormFox2.Fog.GetEnd(), but uses the map as a fallback )
|
|
---@return number
|
|
---@shared
|
|
function StormFox2.Fog.GetDistance()
|
|
return _fE or map_distance
|
|
end
|
|
|
|
-- Returns the default fog-distance for clear weather.
|
|
local function getDefaultDistance()
|
|
local ov = StormFox2.Setting.GetCache("overwrite_fogdistance",-1)
|
|
if ov > -1 then
|
|
return ov
|
|
end
|
|
return map_distance
|
|
end
|
|
-- Returns the fog-distance.
|
|
local function getAimDistance(bFinal)
|
|
local cW = StormFox2.Weather.GetCurrent()
|
|
local ov = getDefaultDistance()
|
|
if cW.Name == "Clear" then return ov end
|
|
local perc = bFinal and StormFox2.Weather.GetFinishPercent() or StormFox2.Weather.GetPercent()
|
|
local a = math.min(cW:Get('fogDistance'), ov)
|
|
if a == ov then return ov end -- This weathertype doesn't change the fog .. or is higer than default
|
|
if not a or perc <= 0 then return ov end -- If weather percent is 0 or under. Return the "clear" distance.
|
|
if perc >= 1 then return a end -- If weather is higer or equal to 1, return the base value.
|
|
return fogCalc(ov, a, perc)
|
|
end
|
|
|
|
if SERVER then
|
|
local loaded, data, f_FogZ = true
|
|
|
|
---Sets the fogZ distance. Seems buggy atm, use at own rist.
|
|
---@param num number
|
|
---@param nTimer number
|
|
---@server
|
|
function StormFox2.Fog.SetZ(num, nTimer)
|
|
timer.Remove( "sf_fog_timer" )
|
|
if nTimer then
|
|
timer.Create("sf_fog_timer", nTimer, 1, function()
|
|
StormFox2.Fog.SetZ(num)
|
|
end)
|
|
return
|
|
end
|
|
f_FogZ = num
|
|
if not loaded then
|
|
data = num
|
|
return
|
|
end
|
|
if not num then num = map_farZ end
|
|
for k,v in ipairs( StormFox2.Ent.env_fog_controllers or {} ) do
|
|
if not IsValid(v) then continue end
|
|
v:SetKeyValue("farz", num)
|
|
end
|
|
end
|
|
|
|
---Returns the fogz distance.
|
|
---@return number
|
|
---@server
|
|
function StormFox2.Fog.GetZ()
|
|
if not StormFox2.Setting.Get("enable_fogz", false) then return map_farZ end
|
|
return f_FogZ or (StormFox2.Fog.GetDistance() + 100)
|
|
end
|
|
hook.Add("StormFox2.PostEntityScan", "StormFox2.Fog.Initz", function()
|
|
loaded = true
|
|
if data then
|
|
StormFox2.Fog.SetZ(data)
|
|
data = nil
|
|
end
|
|
end)
|
|
hook.Add("StormFox2.weather.postchange", "StormFox2.Fog.Updater", function( sName ,nPercentage, nDelta )
|
|
local old_fE = _fE or map_distance
|
|
_fE = getAimDistance(true)
|
|
if _fE > 3000 then
|
|
_fS = 0
|
|
else
|
|
_fS = _fE - 3000
|
|
end
|
|
-- Check fogZ distance
|
|
if not StormFox2.Setting.Get("enable_fogz", false) then return end
|
|
if old_fE > _fE then -- The fog shriks
|
|
StormFox2.Fog.SetZ(_fE * 2 + 100, nDelta)
|
|
elseif old_fE < _fE then -- The fog grows
|
|
StormFox2.Fog.SetZ(_fE * 2 + 100)
|
|
end
|
|
end)
|
|
timer.Create("StormFox2.Fog.SVUpdate", 2, 0, function()
|
|
local cWD = StormFox2.Weather.GetCurrent().Dynamic or {}
|
|
if cWD.fogDistance then return end
|
|
_fE = getAimDistance(true)
|
|
end)
|
|
|
|
---Returns the fog-color.
|
|
---@return Color
|
|
---@server
|
|
function StormFox2.Fog.GetColor()
|
|
return StormFox2.Mixer.Get("fogColor", StormFox2.Mixer.Get("bottomColor",color_white) ) or color_white
|
|
end
|
|
return
|
|
end
|
|
----- Fog render and clientside -----
|
|
-- Fog logic and default render
|
|
-- Returns the "distance" to outside
|
|
local f_outside = 0
|
|
local f_indoor = -1
|
|
local f_lastDist = map_distance
|
|
|
|
local function outSideVar()
|
|
local env = StormFox2.Environment.Get()
|
|
if env.outside then
|
|
return f_outside
|
|
end
|
|
if not env.nearest_outside then
|
|
return f_indoor
|
|
end
|
|
local dis = StormFox2.util.RenderPos():Distance(env.nearest_outside) / 300
|
|
if dis > 1 then
|
|
return f_indoor
|
|
end
|
|
return dis
|
|
end
|
|
hook.Add("Think", "StormFox2.Fog.Updater", function()
|
|
-- Figure out the fogdistance we should have
|
|
local f_envfar = outSideVar()
|
|
local fog_dis = getAimDistance()
|
|
local fog_indoor = StormFox2.Mixer.Get("fogIndoorDistance",3000)
|
|
if f_envfar == f_indoor then -- Indoors
|
|
fog_dis = math.max(fog_dis, fog_indoor)
|
|
elseif f_envfar ~= f_outside then
|
|
fog_dis = Lerp(f_envfar + 0.1, fog_dis, fog_indoor)
|
|
end
|
|
_fE = math.Approach(_fE, fog_dis, math.max(10, _fE) * FrameTime())
|
|
if _fE > 3000 then
|
|
_fS = 0
|
|
else
|
|
_fS = _fE - 3000
|
|
end
|
|
end)
|
|
|
|
local f_Col = color_white
|
|
local SkyFog = function(scale)
|
|
if _fD <= 0 then return end
|
|
if not scale then scale = 1 end
|
|
if not fogEnabledCheck() then return end
|
|
f_Col = StormFox2.Mixer.Get("fogColor", StormFox2.Mixer.Get("bottomColor") ) or color_white
|
|
-- Apply fog
|
|
local tD = StormFox2.Thunder.GetLight() / 2055
|
|
render.FogMode( 1 )
|
|
render.FogStart( StormFox2.Fog.GetStart() * scale )
|
|
render.FogEnd( StormFox2.Fog.GetEnd() * scale )
|
|
render.FogMaxDensity( (_fD - tD) * 0.999 )
|
|
render.FogColor( f_Col.r,f_Col.g,f_Col.b )
|
|
return true
|
|
end
|
|
hook.Add("SetupSkyboxFog","StormFox2.Sky.Fog",SkyFog)
|
|
hook.Add("SetupWorldFog","StormFox2.Sky.WorldFog",SkyFog)
|
|
-- Returns the fog-color.
|
|
function StormFox2.Fog.GetColor()
|
|
return f_Col or color_white
|
|
end
|
|
|
|
-- Additional Fog render
|
|
local m_fog = Material('stormfox2/effects/fog_sphere')
|
|
local l_fogz = 0
|
|
hook.Add("StormFox2.2DSkybox.FogLayer", "StormFox2.Fog.RSky", function( viewPos )
|
|
if not fogEnabledCheck() then return end
|
|
local v = Vector(math.cos( viewPos.y ), math.sin( viewPos.y ), 0)
|
|
m_fog:SetVector("$color", Vector(f_Col.r,f_Col.g,f_Col.b) / 255)
|
|
m_fog:SetFloat("$alpha", math.Clamp(5000 / _fE, 0, 1))
|
|
render.SetMaterial( m_fog )
|
|
local tH = math.min(StormFox2.Environment.GetZHeight(), 2100)
|
|
if tH ~= l_fogz then
|
|
local delta = math.abs(l_fogz, tH) / 2
|
|
l_fogz = math.Approach( l_fogz, tH, math.max(delta, 10) * 5 * FrameTime() )
|
|
end
|
|
local h = 2000 + 6000 * StormFox2.Fog.GetAmount()
|
|
render.DrawSphere( Vector(0,0,h - l_fogz * 4) , -30000, 30, 30, color_white)
|
|
end)
|
|
|
|
local mat = Material("color")
|
|
local v1 = Vector(1,1,1)
|
|
hook.Add("PostDrawOpaqueRenderables", "StormFox2.Sky.FogPDE", function()
|
|
if _fS >= 0 or _fD <= 0 then return end
|
|
if not fogEnabledCheck() then return end
|
|
local a = getFogFill()
|
|
mat:SetVector("$color",Vector(f_Col.r / 255,f_Col.g / 255,f_Col.b / 255))
|
|
mat:SetFloat("$alpha",a)
|
|
render.SetMaterial(mat)
|
|
render.DrawScreenQuad()
|
|
mat:SetVector("$color",v1)
|
|
mat:SetFloat("$alpha",1)
|
|
end) |