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

204 lines
6.8 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/
--]]
-- Breath Efect
do
local threshold = 2 -- IRL it is 7.2C, but i think the community would like to tie it closer to snow.
StormFox2.Setting.AddCL("enable_breath", true)
local m_mats = {(Material("particle/smokesprites_0001")),(Material("particle/smokesprites_0002")),(Material("particle/smokesprites_0003"))}
local function GetMouth( ply )
local att = ply:LookupAttachment("mouth")
if att <= 0 then return end -- No mouth?
return ply:GetAttachment(att)
end
local function DoEffect(ply, size)
if not _STORMFOX_PEM then return end -- Just in case
local pos, ang
local e = 1
if ply ~= StormFox2.util.ViewEntity() then -- "Someone else"
local att = GetMouth( ply )
if not att then return end
pos = att.Pos
ang = att.Ang
else -- Our viewpoint
-- Check the view
local view = StormFox2.util.GetCalcView()
if view.drawviewer then -- Third person
local att = GetMouth( ply )
if not att then return end
pos = att.Pos
ang = att.Ang
else
e = 2
ang = Angle(-view.ang.p,view.ang.y,0)
pos = view.pos + ang:Forward() * 3 + ang:Up() * -2
end
end
local l = StormFox2.Map.GetLight() / 100
local p = _STORMFOX_PEM["2D"]:Add(table.Random(m_mats),pos)
p:SetStartSize(1)
p:SetEndSize(size)
p:SetStartAlpha(math.min(255, 15 + math.random(55,135) * l * e))
p:SetEndAlpha(0)
p:SetLifeTime(0)
p:SetGravity(Vector(0,0,4))
p:SetDieTime(1)
p:SetLighting(false)
p:SetRoll(math.random(360))
p:SetRollDelta(math.Rand(-0.5,0.5))
p:SetVelocity(ang:Forward() * 2 + ply:GetVelocity() / 5)
end
-- Runs the effect on the player and returns next time it should be called.
local function CheckEffect(ply)
if not IsValid( ply) then return end
if not ply:Alive() then return end
if ply:WaterLevel() >= 3 then return end
if ply:InVehicle() then
local e = ply:GetVehicle()
if not IsValid( e ) then return end
if e:GetClass() ~= "prop_vehicle_jeep" then return end -- An open vehicle
end
if not StormFox2.Wind.IsEntityInWind(ply) then return end
local len = ply:GetVelocity():Length()
local t = math.Clamp(1.5 - (len / 100),0.2,1.5)
DoEffect(ply,5 + (len / 100))
return math.Rand(t,t * 2)
end
-- The most optiomal way is to check within the renderhook.
local function RunEffect(ply)
if not StormFox2.Setting.GetCache("enable_breath") then return end
if not StormFox2.Setting.SFEnabled() then return end
if StormFox2.Temperature.Get() > threshold then return end -- Breaht is visible at 7.2C or below
if (ply._sfbreath or 0) >= CurTime() then return end
local cE = CheckEffect( ply )
if not cE then
ply._sfbreath = CurTime() + 1
return
end
ply._sfbreath = CurTime() + cE
end
hook.Add("PostPlayerDraw", "StormFox2.Effect.Breath", RunEffect)
-- We also need to check when the player is in first person.
timer.Create("StormFox2.Effect.BreathT", 1, 0, function()
local LP = LocalPlayer( )
if not IsValid( LP ) then return end
RunEffect( LP )
end)
end
-- Depth Filter
local W,H = ScrW(), ScrH()
local depth_r = GetRenderTarget("SF_DepthFilter", W,H, true)
local depthLayer = Material( "stormfox2/shader/depth_layer" )
local a = 0
local l
-- Patch: Some people out there don't update the resources when updating the mod.
if depthLayer:GetKeyValues()["$detail"] then
StormFox2.Warning("stormfox2/shader/depth_layer.vmt is outdated! Hotpatching, but be sure to update the resources!")
depthLayer:SetUndefined("$detail")
depthLayer:SetUndefined("$detailtexturetransform")
depthLayer:SetUndefined("$detailblendmode")
depthLayer:SetUndefined("$detailscale")
depthLayer:SetUndefined("$additive")
end
hook.Add("StormFox2.weather.postchange", "StormFox2.DepthFilter.Reset", function(b)
if l and l == b then return end
l = b
a = 0
end)
local depthLayer = Material( "stormfox2/shader/depth_layer" )
local function updateDepthTexture(fFunc, a)
render.PushRenderTarget(depth_r)
cam.Start2D()
render.Clear(0,0,0,0,true, false)
fFunc(W,H, a)
cam.End2D()
render.PopRenderTarget()
depthLayer:SetTexture("$basetexture", depth_r)
return depthLayer
end
local invis_col = Color(255,0,0,0)
local function RenderDepthFilter()
-- Reset everything to known good fpr stencils
render.SetStencilWriteMask( 0xFF )
render.SetStencilTestMask( 0xFF )
render.SetStencilReferenceValue( 0 )
render.SetStencilCompareFunction( STENCIL_ALWAYS )
render.SetStencilPassOperation( STENCIL_REPLACE )
render.SetStencilFailOperation( STENCIL_ZERO )
render.SetStencilZFailOperation( STENCIL_ZERO )
render.ClearStencil()
-- Enable stencil
render.SetStencilEnable( true )
render.SetStencilReferenceValue( 1 )
render.SetStencilCompareFunction( STENCIL_ALWAYS )
-- Render Mask
local eA = EyeAngles()
cam.Start3D( EyePos(), eA )
render.SetColorMaterial()
local f_D = StormFox2.Fog.GetEnd()
if f_D > 2000 then
render.DrawSphere(EyePos(), -2000, 30, 30, invis_col)
else
--[[
Stencils look bad for heavy effects, since there is a clear pixel-line.
I've tried smoothing it, but it would require rendering the world twice within an RT.
So instead we make it a plain with the fog-distance.
Its bad in some cases, yes, but only solution I know for now.
]]
render.DrawQuadEasy(EyePos() + eA:Forward() * f_D, -eA:Forward(), ScrW() * 5, ScrH() * 5, invis_col, 0)
end
cam.End3D()
-- Now, only draw things that have their pixels set to 1. This is the hidden parts of the stencil tests.
render.SetStencilCompareFunction( STENCIL_EQUAL )
-- Render Depth-filter
cam.Start2D()
render.SetMaterial(depthLayer)
render.DrawScreenQuad()
cam.End2D()
-- Let everything render normally again
render.SetStencilEnable( false )
--render.PopRenderTarget()
end
hook.Add("RenderScreenspaceEffects", "StormFox2.Downfall.DepthRender", function()
if render.GetDXLevel() < 95 then return end
if not render.SupportsPixelShaders_2_0() then return end
if LocalPlayer():WaterLevel() >= 3 then return end -- Don't render SF effects under wanter.
local obj = StormFox2.Setting.GetObject("depthfilter")
if not obj then return end
if not obj:GetValue() then return end
-- Check if weather has depth. If not reset alpha
local dFr = StormFox2.Weather.GetCurrent().DepthFilter
if not dFr then a = 0 return end
-- Calc alpha
if StormFox2.Environment.Get().outside then
a = math.Approach(a, 1, FrameTime() * .8)
else
a = math.Approach(a, 0, FrameTime() * 5) -- Quick fadeaway
end
if a <= 0 then return end -- If alpha is 0 or below, don't render.
-- Update RT
updateDepthTexture(dFr, a)
-- Update screenspace effect
render.UpdateScreenEffectTexture()
render.UpdateFullScreenDepthTexture()
-- Render the depthfilter
RenderDepthFilter()
end)