Files
wnsrc/lua/stormfox2/framework/sh_maplight.lua
lifestorm 94063e4369 Upload
2024-08-04 22:55:00 +03:00

788 lines
25 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/
--]]
StormFox2.Setting.AddSV("maplight_min",0,mil, "Effects", 0, 100)
StormFox2.Setting.AddSV("maplight_max",80,nil, "Effects", 0, 100)
StormFox2.Setting.AddSV("maplight_smooth",true,nil, "Effects",0,1)
StormFox2.Setting.AddSV("maplight_auto", true, nil, "Effects")
StormFox2.Setting.AddSV("maplight_lightenv", false,nil, "Effects")
StormFox2.Setting.AddSV("maplight_colormod", false,nil, "Effects")
StormFox2.Setting.AddSV("maplight_dynamic", false,nil, "Effects")
StormFox2.Setting.AddSV("maplight_lightstyle", false,nil, "Effects")
--[[----------------------------------------------------------------]]--
StormFox2.Setting.AddSV("maplight_updaterate",game.SinglePlayer() and 6 or 3,nil, "Effects")
StormFox2.Setting.AddSV("overwrite_extra_darkness",-1,nil, "Effects", -1, 1)
StormFox2.Setting.SetType( "overwrite_extra_darkness", "special_float")
StormFox2.Setting.AddSV("allow_weather_lightchange",true,nil, "Weather")
if CLIENT then
StormFox2.Setting.AddCL("extra_darkness",render.SupportsPixelShaders_2_0(),nil,"Effects",0,1)
StormFox2.Setting.AddCL("extra_darkness_amount",0.75,nil, "Effects",0,1)
StormFox2.Setting.SetType( "extra_darkness_amount", "float" )
end
-- Converts a lightlvl to char
local function convertToBZ( nNum ) -- From b to z
local byte = math.Round(6 * nNum / 25 + 98)
return string.char(byte)
end
local function convertToAZ( nNum )
return string.char(97 + nNum / 4)
end
local SetLightStyle, SetLightEnv
if SERVER then
-- Sets the lightstyle
local function _SetLightStyle( char )
engine.LightStyle(0,char)
net.Start(StormFox2.Net.LightStyle)
net.WriteUInt(string.byte(char), 7)
net.Broadcast()
end
local var = 'm'
-- Making it a timer, gives other scripts time to overwrite it.
SetLightStyle = function( char )
if char == 'a' then char = 'b' end -- 'a' will break all light on the map
if char == var then return end
var = char
if timer.Exists("sf_lightstyleset") then return end
timer.Create( "sf_lightstyleset", 1, 1, function()
_SetLightStyle( var )
end)
end
local oldLight = 'm'
local has_faded = false
SetLightEnv = function( char)
if not StormFox2.Ent.light_environments then return end
if char == oldLight then return end
oldLight = char
for _,light in ipairs(StormFox2.Ent.light_environments) do -- Doesn't lag
if not IsValid(light) then continue end
if has_faded then
light:Fire("FadeToPattern", char ,0)
else
light:Fire("SetPattern", char ,0)
end
if char == "a" then
light:Fire("TurnOff","",0)
else
light:Fire("TurnOn","",0)
end
light:Activate()
end
has_faded = true
end
else
local last_sv
net.Receive(StormFox2.Net.LightStyle, function(len)
local c_var = net.ReadUInt(7)
if last_sv and last_sv == c_var then return end -- No need
last_sv = c_var
timer.Simple(1, function()
render.RedownloadAllLightmaps( true, true )
--MsgC(color_white,"Redownload ligthmap [" .. last_sv .. "]\n")
end)
end)
end
--[[ Diffrent types of maplight options.
available = Return true to indicate this option is available. No function = always.
on = When you switch it on
off = When you switch it off
change = When the lightvl changes. Secondary is when the smoothness ends.
]]
local mapLights = {}
local e_light_env = 0
local e_lightstyle = 1
local e_colormod = 2
local e_lightdynamic = 3
local lastSetting = {}
-- light_environment (SV) Fast, but not all maps have it
mapLights[e_light_env] = {}
mapLights[e_light_env]["available"] = function()
return StormFox2.Ent.light_environments and true or false
end
if SERVER then
mapLights[e_light_env]["on"] = function(lightLvl)
SetLightEnv( convertToAZ(lightLvl) )
end
mapLights[e_light_env]["off"] = function(lightLvl)
if lastSetting[e_lightdynamic] then
SetLightEnv('b')
else
SetLightEnv('m')
end
end
mapLights[e_light_env]["change"] = mapLights[e_light_env]["on"]
end
-- light_style (SV) Laggy on large maps
mapLights[e_lightstyle] = {}
if SERVER then
mapLights[e_lightstyle]["on"] = function(lightLvl)
SetLightStyle( convertToBZ(lightLvl) )
end
mapLights[e_lightstyle]["off"] = function(lightLvl)
SetLightStyle('m')
timer.Remove( "sf_lightstyle" )
end
local nextSet
mapLights[e_lightstyle]["change"] = function(lightLvl, full) -- We make this a 30sec timer, since lightstyle is so slow and laggy.
if not full then return end -- Ignore 'smoothness' light
if timer.Exists("sf_lightstyle") then
nextSet = convertToBZ(lightLvl)
else
SetLightStyle(convertToBZ(lightLvl))
timer.Create("sf_lightstyle", 5, 1, function()
if not nextSet then return end
SetLightStyle(nextSet)
nextSet = nil
end)
end
end
end
-- ColorMod (CL) A fast alternative
mapLights[e_colormod] = {}
local cmod_on
if CLIENT then
local fardetarget = 0
mapLights[e_colormod]["on"] = function(lightLvl)
cmod_on = (1 - (lightLvl / 80)) * 0.7
fardetarget = 0
end
mapLights[e_colormod]["off"] = function(lightLvl)
cmod_on = nil
end
mapLights[e_colormod]["change"] = function(lightLvl)
cmod_on = (1 - (lightLvl / 80)) * 0.7
end
local tab = {
[ "$pp_colour_addr" ] = -0.09,
[ "$pp_colour_addg" ] = -0.1,
[ "$pp_colour_addb" ] = -0.05,
[ "$pp_colour_brightness" ] = 0,
[ "$pp_colour_contrast" ] = 1,
[ "$pp_colour_colour" ] = 1,
[ "$pp_colour_mulr" ] = 0,
[ "$pp_colour_mulg" ] = 0,
[ "$pp_colour_mulb" ] = 0
}
hook.Add( "RenderScreenspaceEffects", "StormFox2.MapLightCMod", function()
if not cmod_on then return end
local darkness = cmod_on
local env = StormFox2.Environment.Get()
if not env.outside then
if not env.nearest_outside then
darkness = 0
else
local dis = 1 - ( env.nearest_outside:DistToSqr(StormFox2.util.RenderPos() or EyePos()) / 90000 )
dis = math.Clamp(dis, 0, 1)
darkness = darkness * 0.2 + darkness * 0.8 * dis
end
end
fardetarget = math.Approach(fardetarget, darkness, FrameTime() * 0.5)
local r_var = fardetarget
local tL = math.min(255,StormFox2.Thunder.GetLight() or 0) / 255
if tL > 0 then
r_var = r_var * (1 - tL)
end
tab[ "$pp_colour_addr" ] = -0.09 * r_var
tab[ "$pp_colour_addg" ] = -0.1 * r_var
tab[ "$pp_colour_addb" ] = -0.05 * r_var
tab[ "$pp_colour_brightness" ] = 0 -r_var * 0.15
tab[ "$pp_colour_colour" ] = 1 - r_var * 0.5 -- We're not good at seeing colors in the dark.
tab[ "$pp_colour_contrast" ] = 1 + r_var * 0.08 -- Lower the contrast, however; Bright things are still bright
DrawColorModify( tab )
end)
end
-- Dynamic Light
local dsize = 3000
local dlengh = 9000 - 30
mapLights[e_lightdynamic] = {}
local dLight = -1
local function tick()
if not SF_SUN_PROTEX then return end
local vis = dLight
-- While the best option is to delete the project-texture.
-- Sadly, doing so would allow another mod to override it, as they're limited.
if vis < 0 then return end
local sunang = StormFox2.Sun.GetAngle() -- Angle towards sun
local p = sunang.p % 360
local tL = math.min(255,StormFox2.Thunder.GetLight() or 0)
if tL > 0 then
p = 270
sunang.p = p
vis = tL / 2
else
if p > 350 then -- 15 before
SF_SUN_PROTEX:SetBrightness(0)
SF_SUN_PROTEX:Update()
return
elseif p > 345 then
vis = vis * math.Clamp(-p / 5 + 70, 0, 1)
elseif p <= 190 then
SF_SUN_PROTEX:SetBrightness(0)
SF_SUN_PROTEX:Update()
return
elseif p <= 195 then
vis = vis * math.Clamp(p / 5 - 38, 0, 1)
end
end
local sunnorm = sunang:Forward() -- Norm of sun
local viewpos = StormFox2.util.RenderPos() -- Point of render
local pos = viewpos + sunnorm * dlengh
pos.x = math.Round(pos.x / 50) * 50
pos.y = math.Round(pos.y / 50) * 50
SF_SUN_PROTEX:SetPos(pos)
if math.Round(sunang.p) == 0 then -- All source light gets a bit, glitchy at 0 or 180 pitch
SF_SUN_PROTEX:SetAngles(Angle(179,sunang.y,0))
else
SF_SUN_PROTEX:SetAngles(Angle(sunang.p + 180,sunang.y,0))
end
SF_SUN_PROTEX:SetBrightness(vis * 2)
SF_SUN_PROTEX:Update()
end
mapLights[e_lightdynamic]["on"] = function(lightLvl)
if SERVER then
SetLightStyle( 'b' )
SetLightEnv('b')
StormFox2.Shadows.SetDisabled( true )
else
RunConsoleCommand("r_flashlightdepthres", 8192)
dLight = lightLvl
if IsValid(SF_SUN_PROTEX) then
SF_SUN_PROTEX:Remove()
end
SF_SUN_PROTEX = ProjectedTexture()
SF_SUN_PROTEX:SetTexture("stormfox2/effects/dynamic_light")
SF_SUN_PROTEX:SetOrthographic( true , dsize, dsize, dsize, dsize)
SF_SUN_PROTEX:SetNearZ(0)
SF_SUN_PROTEX:SetFarZ( 12000 )
SF_SUN_PROTEX:SetQuadraticAttenuation( 0 )
SF_SUN_PROTEX:SetShadowDepthBias(0.000005)
SF_SUN_PROTEX:SetShadowFilter(0.05) -- Meed tp blur the shadows a bit.
SF_SUN_PROTEX:SetShadowSlopeScaleDepthBias(2)
SF_SUN_PROTEX:SetEnableShadows(true)
hook.Add("Think", "StormFox2.MapLightDynamic", tick)
end
end
mapLights[e_lightdynamic]["off"] = function(lightLvl)
if SERVER then
SetLightStyle( 'm' )
SetLightEnv('m')
StormFox2.Shadows.SetDisabled( false )
else
dLight = 0
if SF_SUN_PROTEX then
SF_SUN_PROTEX:Remove()
SF_SUN_PROTEX = nil
end
hook.Remove("Think", "StormFox2.MapLightDynamic")
end
end
if CLIENT then
mapLights[e_lightdynamic]["change"] = function(lightlvl)
dLight = lightlvl
end
end
-- MapLight functions
local function EnableMapLight(str, lightlvl)
if not mapLights[str] then
error("Unknown light")
end
if not mapLights[str]["on"] then return end
mapLights[str]["on"](lightlvl)
end
local function DisableMapLight(str, lightlvl)
if not mapLights[str] then
error("Unknown light")
end
if not mapLights[str]["off"] then return end
mapLights[str]["off"](lightlvl)
end
local function ChangeMapLight(str, lightlvl, full)
if not mapLights[str] then
error("Unknown light")
end
if not mapLights[str]["change"] then return end
mapLights[str]["change"](lightlvl, full)
end
-- Function that will remember and enable / disable a setting.
local function checkSetting(e_type, bool, lightlvl)
if bool and lastSetting[e_type] then return end
if not bool and not lastSetting[e_type] then return end
if bool then
EnableMapLight(e_type, lightlvl)
else
DisableMapLight(e_type, lightlvl)
end
lastSetting[e_type] = bool
end
-- Called when one of the settings change
local function SettingMapLight( lightlvl )
-- Stop all light-settings when SF gets turned off.
if not StormFox2.Setting.GetCache("enable", true) then
checkSetting(e_lightstyle, false, lightlvl)
checkSetting(e_colormod, false, lightlvl)
checkSetting(e_lightdynamic,false, lightlvl)
checkSetting(e_light_env, false, lightlvl)
return
end
-- Choose e_light_env or e_colormod
if StormFox2.Setting.Get("maplight_auto") then
checkSetting(e_lightdynamic,false, lightlvl)
checkSetting(e_lightstyle, false, lightlvl)
if StormFox2.Ent.light_environments then
checkSetting(e_colormod, false, lightlvl)
checkSetting(e_light_env, true, lightlvl)
else
checkSetting(e_light_env, false, lightlvl)
checkSetting(e_colormod, true, lightlvl)
end
else
-- Can be enabled for all
checkSetting(e_colormod, StormFox2.Setting.Get("maplight_colormod", false), lightlvl)
-- Choose dynamic or lightstyle
if StormFox2.Setting.Get("maplight_dynamic", false) then
checkSetting(e_lightstyle, false, lightlvl)
checkSetting(e_light_env, false, lightlvl)
checkSetting(e_lightdynamic,true, lightlvl)
else
checkSetting(e_lightdynamic,false, lightlvl)
checkSetting(e_lightstyle, StormFox2.Setting.Get("maplight_lightstyle", false),lightlvl)
checkSetting(e_light_env, StormFox2.Setting.Get("maplight_lightenv", false), lightlvl)
end
end
end
-- Called when lightlvl has changed
local function ChangedMapLight( lightlvl, isSmoothLight)
local LastUpdate = not isSmoothLight
if StormFox2.Setting.GetCache("maplight_auto", true) then
if StormFox2.Ent.light_environments then
ChangeMapLight(e_light_env, lightlvl, LastUpdate)
return true
else
ChangeMapLight(e_colormod, lightlvl, LastUpdate)
end
else
local a = false
if StormFox2.Setting.GetCache("maplight_dynamic", false) then
ChangeMapLight(e_lightdynamic, lightlvl, LastUpdate)
a = true
end
if StormFox2.Setting.GetCache("maplight_lightstyle", false) then
ChangeMapLight(e_lightstyle, lightlvl, LastUpdate)
a = true
end
if StormFox2.Setting.GetCache("maplight_lightenv", false) then
ChangeMapLight(e_light_env, lightlvl, LastUpdate)
a = true
end
if StormFox2.Setting.GetCache("maplight_colormod", false) then
ChangeMapLight(e_colormod, lightlvl, LastUpdate)
end
return a
end
end
-- Sets the detail-light
local SetDetailLight
if CLIENT then
-- Detail MapLight
-- Use default detail material (Just in case)
local detailstr = {["detail/detailsprites"] = true}
-- Find map detail from BSP
local mE = StormFox2.Map.Entities()[1]
if mE and mE["detailmaterial"] then
detailstr[mE["detailmaterial"]] = true
end
-- Add EP2 by default
local ep2m = Material("detail/detailsprites_ep2")
if ep2m and not ep2m:IsError() then
detailstr["detail/detailsprites_ep2"] = true
end
local detail = {}
for k,v in pairs(detailstr) do
table.insert(detail, (Material(k)))
end
SetDetailLight = function(lightAmount)
lightAmount = math.Clamp(lightAmount / 100, 0, 1)
local v = Vector(lightAmount,lightAmount,lightAmount)
for i, m in ipairs(detail) do
m:SetVector("$color",v)
end
end
end
-- Returns light-variables
local f_mapLight = StormFox2.Setting.GetCache("maplight_max",80)
local f_mapLightRaw = 100
local c_last_char = 'm'
---Returns the current light-amount.
---@return number
---@shared
function StormFox2.Map.GetLight()
return f_mapLight
end
---Returns the current raw light-amount. Ignores settings.
---@return number
---@shared
function StormFox2.Map.GetLightRaw()
return f_mapLightRaw
end
---Returns the current light-char. Source use letters to indecate light.
---@return string
---@shared
function StormFox2.Map.GetLightChar()
return c_last_char
end
local function getMaxLight(curLight)
if curLight <= 0 then return 0 end
local n = StormFox2.Setting.GetCache("maplight_max",80)
if n <= 0 then return 0 end
return math.Clamp(curLight / n, 0, 1) * 100
end
-- On launch. Setup light
local init = false
do
local chicken, egg = false, false
local function tryInit()
if not chicken or not egg then return end
SettingMapLight(f_mapLight)
hook.Run("StormFox2.lightsystem.new", f_mapLight, getMaxLight(f_mapLight))
if CLIENT then SetDetailLight(f_mapLight) end
init = true
end
hook.Add("StormFox2.PostEntityScan", "stormfox2.lightsystem.init", function()
chicken = true
tryInit()
end)
hook.Add("stormfox2.postinit", "stormfox2.lightsystem.init2", function()
egg = true
tryInit()
end)
end
-- On settings change
for _, conv in ipairs({"enable","maplight_auto", "maplight_lightenv", "maplight_colormod", "maplight_dynamic", "maplight_lightstyle"}) do
StormFox2.Setting.Callback(conv,function(var)
SettingMapLight(f_mapLight)
end, conv .. "MLCheck")
end
-- Allows us to use SetLight, without removing the lerp.
local lil = true
local function SetLightInternal(f, isSmoothLight)
if f < 0 then f = 0 elseif
f > 100 then f = 100 end
if f_mapLight == f and lil == isSmoothLight then return end -- Ignore
f_mapLight = f
lil = isSmoothLight
c_last_char = convertToAZ(f)
if not init then return end
-- 2D Skybox
if SERVER then
local str = StormFox2.Setting.GetCache("overwrite_2dskybox","")
local use_2d = StormFox2.Setting.GetCache("use_2dskybox",false)
if use_2d and str ~= "painted" then
StormFox2.Map.Set2DSkyBoxDarkness( f * 0.009 + 0.1, true )
end
end
-- SetMapLight
ChangedMapLight(f, isSmoothLight)
if CLIENT then SetDetailLight(f) end
-- Tell scripts to update
hook.Run("StormFox2.lightsystem.new", f, getMaxLight(f))
end
local t = {}
---Sets the maplight using a number between 0 - 100. last_update should be true, if we aren't lerping.
---Clients need to run this too for internal stuff, but won't change the maplight.
---@param int number
---@param last_update boolean
---@shared
function StormFox2.Map.SetLight( int, last_update )
t = {} -- Remove light lerping
SetLightInternal(int, last_update)
end
--[[ Lerp light
People complain if we use lightStyle too much (Even with settings), so I've removed lerp from maps without light_environment.
]]
---Lerps the light towards the goal. Make "isSmooth" false if you're calling it rapidly.
---@param int number
---@param nLerpTime number
---@param isSmooth boolean
---@shared
function StormFox2.Map.SetLightLerp(int, nLerpTime, isSmooth )
local smooth = StormFox2.Setting.GetCache("maplight_smooth",true)
local num = StormFox2.Setting.GetCache("maplight_updaterate", 3)
-- No lights to smooth and/or setting is off
local _5sec = 0.08 * StormFox2.Time.GetSpeed_RAW()
t = {}
if not smooth or nLerpTime <= _5sec or not f_mapLight or num <= 1 then
SetLightInternal( int )
return
end
-- Are we trying to lerp towards current value?
if f_mapLight and f_mapLight == int then
return
end
-- Start lerping ..
-- We make a time-list of said values.
local st = StormFox2.Time.Get() -- Start Time
local st_lerpt = nLerpTime / num -- Each "step"'s time
-- Too fast of a light change. Can bug out.
if st_lerpt < 5 then -- Set the each step to min 5 seconds.
st_lerpt = 5
num = math.floor(nLerpTime / 5)
if num <= 1 then -- Only change once.
SetLightInternal( int )
return
end
end
local st_lerp = math.abs(f_mapLight - int) / num -- Each "step"'s value
-- from: f_mapLight
-- to: f
for i = 0, num - 1 do
table.insert(t, {
(st + (i * st_lerpt)) % 1440, -- Time when applied
math.floor(math.Approach(f_mapLight, int, st_lerp * (i + 1))),-- The light value
i ~= num - 1 or isSmooth -- Isn't last
})
end
--print("From:",f_mapLight, "TO:", f, "step:",st_lerp, "nums:",num)
--StormFox2.Map.SetLight( math.Approach(f_mapLight, f, n), true )
end
timer.Create("StormFox2.lightupdate", 2, 0, function()
if #t <= 0 then return end
local n = t[1]
local time = StormFox2.Time.Get()
if n[1] > time or math.abs(time - n[1]) > 720 then return end -- Wait.
-- Trigger
local v = table.remove(t, 1)
SetLightInternal( v[2], v[3] ) -- Set the light, and lightsystel if last.
--print("SetLight", v[2], v[3])
end)
if SERVER then
-- Control light
hook.Add("StormFox2.weather.postchange", "StormFox2.weather.setlight", function( sName ,nPercentage, nDelta )
local night, day
if StormFox2.Setting.GetCache("allow_weather_lightchange") then
night,day = StormFox2.Data.GetFinal("mapNightLight", 0), StormFox2.Data.GetFinal("mapDayLight",100) -- Maplight
else
local c = StormFox2.Weather.Get("Clear")
night,day = c:Get("mapNightLight",0), c:Get("mapDayLight",80) -- Maplight
end
local minlight,maxlight = StormFox2.Setting.GetCache("maplight_min",0),StormFox2.Setting.GetCache("maplight_max",80) -- Settings
local smooth = StormFox2.Setting.GetCache("maplight_smooth",game.SinglePlayer())
-- Calc maplight
local isSmooth = false
local stamp, mapLight = StormFox2.Sky.GetLastStamp()
if stamp >= SF_SKY_CEVIL then
mapLight = night
elseif stamp <= SF_SKY_DAY then
mapLight = day
else
local delta = math.abs( SF_SKY_DAY - SF_SKY_CEVIL )
local f = StormFox2.Sky.GetLastStamp() / delta
if smooth then
mapLight = Lerp((f + 0.5) / 2, day, night)
isSmooth = true
elseif f <= 0.5 then
mapLight = day
else
mapLight = night
end
end
f_mapLightRaw = mapLight
-- Apply settings
local newLight = minlight + mapLight * (maxlight - minlight) / 100
local sec = 15 * StormFox2.Time.GetSpeed_RAW()
StormFox2.Map.SetLightLerp(newLight, math.min(sec, nDelta or sec), isSmooth )
end)
-- Min and maxlight hotupdate
local function hotUpdate()
local night, day
if StormFox2.Setting.GetCache("allow_weather_lightchange") then
night,day = StormFox2.Data.GetFinal("mapNightLight", 0), StormFox2.Data.GetFinal("mapDayLight",100) -- Maplight
else
local c = StormFox2.Weather.Get("Clear")
night,day = c:Get("mapNightLight",0), c:Get("mapDayLight",80) -- Maplight
end
local minlight,maxlight = StormFox2.Setting.GetCache("maplight_min",0),StormFox2.Setting.GetCache("maplight_max",80) -- Settings
local smooth = StormFox2.Setting.GetCache("maplight_smooth",game.SinglePlayer())
-- Calc maplight
local isSmooth = false
local stamp, mapLight = StormFox2.Sky.GetLastStamp()
if stamp >= SF_SKY_CEVIL then
mapLight = night
elseif stamp <= SF_SKY_DAY then
mapLight = day
else
local delta = math.abs( SF_SKY_DAY - SF_SKY_CEVIL )
local f = StormFox2.Sky.GetLastStamp() / delta
if smooth then
mapLight = Lerp((f + 0.5) / 2, day, night)
isSmooth = true
elseif f <= 0.5 then
mapLight = day
else
mapLight = night
end
end
f_mapLightRaw = mapLight
-- Apply settings
local newLight = minlight + mapLight * (maxlight - minlight) / 100
StormFox2.Map.SetLight( newLight )
end
StormFox2.Setting.Callback("maplight_min", hotUpdate)
StormFox2.Setting.Callback("maplight_max", hotUpdate)
else -- Fake darkness. Since some maps are bright
hook.Add("StormFox2.weather.postchange", "StormFox2.weather.setlight", function( sName ,nPercentage, nDelta )
if not StormFox2.Map or not StormFox2.Map.SetLightLerp then return end
local minlight,maxlight = StormFox2.Setting.GetCache("maplight_min",0),StormFox2.Setting.GetCache("maplight_max",80) -- Settings
local smooth = StormFox2.Setting.GetCache("maplight_smooth",game.SinglePlayer())
local night, day
if StormFox2.Setting.GetCache("allow_weather_lightchange") then
night,day = StormFox2.Data.GetFinal("mapNightLight", 0), StormFox2.Data.GetFinal("mapDayLight",100) -- Maplight
else
local c = StormFox2.Weather.Get("Clear")
night,day = c:Get("mapNightLight",0), c:Get("mapDayLight",80) -- Maplight
end
-- Calc maplight
local isSmooth = false
local stamp, mapLight = StormFox2.Sky.GetLastStamp()
if stamp >= SF_SKY_CEVIL then
mapLight = night
elseif stamp <= SF_SKY_DAY then
mapLight = day
else
local delta = math.abs( SF_SKY_DAY - SF_SKY_CEVIL )
local f = StormFox2.Sky.GetLastStamp() / delta
if smooth then
mapLight = Lerp((f + 0.5) / 2, day, night)
isSmooth = true
elseif f <= 0.5 then
mapLight = day
else
mapLight = night
end
end
f_mapLightRaw = mapLight
-- Apply settings
local newLight = minlight + mapLight * (maxlight - minlight) / 100
local sec = 15 * StormFox2.Time.GetSpeed_RAW()
StormFox2.Map.SetLightLerp(newLight, math.min(sec, nDelta or sec), isSmooth )
end)
local function exp(n)
return n * n
end
local mat_screen = Material( "stormfox2/shader/pp_dark" )
local mat_ColorMod = Material( "stormfox2/shader/color" )
mat_ColorMod:SetTexture( "$fbtexture", render.GetScreenEffectTexture() )
local texMM = GetRenderTargetEx( "_SF_DARK", -1, -1, RT_SIZE_FULL_FRAME_BUFFER, MATERIAL_RT_DEPTH_NONE, 0, 0, IMAGE_FORMAT_RGB888 )
-- Renders pp_dark
local function UpdateStencil( darkness )
if not render.SupportsPixelShaders_2_0() then return end -- How old is the GPU!?
render.UpdateScreenEffectTexture()
render.PushRenderTarget(texMM)
render.Clear( 255 * darkness, 255 * darkness, 255 * darkness, 255 * darkness )
render.ClearDepth()
render.OverrideBlend( true, BLEND_ONE_MINUS_SRC_COLOR, BLEND_ONE_MINUS_SRC_COLOR, 0, BLEND_ONE, BLEND_ZERO, BLENDFUNC_ADD )
render.SetMaterial(mat_ColorMod)
render.DrawScreenQuad()
render.OverrideBlend( false )
render.PopRenderTarget()
mat_screen:SetTexture( "$basetexture", texMM )
end
local fade = 0
hook.Add("RenderScreenspaceEffects","StormFox2.Light.MapMat",function()
if not StormFox2.Map.GetLightRaw then return end
if not StormFox2.Setting.SFEnabled() then return end
-- How old is the GPU!?
if not render.SupportsPixelShaders_2_0() then return end
local a = 1 - StormFox2.Map.GetLightRaw() / 100
if a <= 0 then -- Too bright
fade = 0
return
end
-- Check settings
local scale = StormFox2.Setting.GetCache("overwrite_extra_darkness",-1)
if scale == 0 then return end -- Force off.
if scale < 0 then
if not StormFox2.Setting.GetCache("extra_darkness",true) then return end
scale = StormFox2.Setting.GetCache("extra_darkness_amount",1)
end
if scale <= 0 then return end
-- Calc the "fade" between outside and inside
local t = StormFox2.Environment.Get()
if t.outside then
fade = math.min(2, fade + FrameTime())
elseif t.nearest_outside then
-- Calc dot
local view = StormFox2.util.GetCalcView()
if not view then return end
local d = view.pos:DistToSqr(t.nearest_outside)
if d < 15000 then
fade = math.min(2, fade + FrameTime())
elseif d > 40000 then -- Too far away
fade = math.max(0, fade - FrameTime())
else
local v1 = view.ang:Forward()
local v2 = (t.nearest_outside - view.pos):GetNormalized()
if v1:Dot(v2) < 0.6 then -- You're looking away
fade = math.max(0, fade - FrameTime())
else -- You're looking at it
fade = math.min(2, fade + FrameTime())
end
end
else
fade = math.max(0, fade - FrameTime())
end
if fade <= 0 then return end
-- Render
UpdateStencil(exp(a * scale * math.min(1, fade)))
render.SetMaterial(mat_screen)
local w,h = ScrW(),ScrH()
render.OverrideBlend( true, 0, BLEND_ONE_MINUS_SRC_COLOR, 2, BLEND_ONE, BLEND_ZERO, BLENDFUNC_ADD )
render.DrawScreenQuadEx(0,0,w,h)
render.OverrideBlend( false )
end)
end
--[[
TODO:
1) Add option to limit the angle of the shadows.
2) Shadow color to match skies?
]]