mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
204 lines
6.8 KiB
Lua
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) |