mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 13:53:45 +03:00
Upload
This commit is contained in:
570
lua/stormfox2/lib/sh_wind.lua
Normal file
570
lua/stormfox2/lib/sh_wind.lua
Normal file
@@ -0,0 +1,570 @@
|
||||
--[[
|
||||
| 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.Wind = StormFox2.Wind or {}
|
||||
local min,max,sqrt,abs = math.min,math.max,math.sqrt,math.abs
|
||||
local function ET(pos,pos2,mask,filter)
|
||||
local t = util.TraceLine( {
|
||||
start = pos,
|
||||
endpos = pos + pos2,
|
||||
mask = mask,
|
||||
filter = filter
|
||||
} )
|
||||
t.HitPos = t.HitPos or (pos + pos2)
|
||||
return t,t.HitSky
|
||||
end
|
||||
|
||||
-- Settings
|
||||
hook.Add("stormfox2.postlib", "stormfox2.windSettings",function()
|
||||
StormFox2.Setting.AddSV("windmove_players",true,nil,"Weather")
|
||||
StormFox2.Setting.AddSV("windmove_foliate",true,nil,"Weather")
|
||||
StormFox2.Setting.AddSV("windmove_props",false,nil,"Weather")
|
||||
StormFox2.Setting.AddSV("windmove_props_break",true,nil,"Weather")
|
||||
StormFox2.Setting.AddSV("windmove_props_unweld",true,nil,"Weather")
|
||||
StormFox2.Setting.AddSV("windmove_props_unfreeze",true,nil,"Weather")
|
||||
StormFox2.Setting.AddSV("windmove_props_max",100,nil,"Weather")
|
||||
StormFox2.Setting.AddSV("windmove_props_makedebris",true,nil,"Weather")
|
||||
hook.Remove("stormfox2.postlib", "stormfox2.windSettings")
|
||||
end)
|
||||
|
||||
|
||||
if SERVER then
|
||||
hook.Add("stormfox2.postlib", "stormfox2.svWindInit",function()
|
||||
if not StormFox2.Ent.env_winds then return end
|
||||
for _,ent in ipairs( StormFox2.Ent.env_winds ) do
|
||||
ent:SetKeyValue('windradius',-1) -- Make global
|
||||
ent:SetKeyValue('maxgustdelay', 20)
|
||||
ent:SetKeyValue('mingustdelay', 10)
|
||||
ent:SetKeyValue('gustduration', 5)
|
||||
end
|
||||
hook.Remove("stormfox2.postlib", "stormfox2.svWindInit")
|
||||
end)
|
||||
---Sets the wind force. Second argument is the lerp-time.
|
||||
---@param nForce number
|
||||
---@param nLerpTime? number
|
||||
---@server
|
||||
function StormFox2.Wind.SetForce( nForce, nLerpTime )
|
||||
StormFox2.Network.Set( "Wind", nForce, nLerpTime )
|
||||
end
|
||||
|
||||
---Sets the wind yaw. Second argument is the lerp-time.
|
||||
---@param nYaw number
|
||||
---@param nLerpTime? number
|
||||
---@server
|
||||
function StormFox2.Wind.SetYaw( nYaw, nLerpTime )
|
||||
StormFox2.Network.Set( "WindAngle", nYaw, nLerpTime )
|
||||
end
|
||||
end
|
||||
|
||||
---Returns the wind yaw-direction
|
||||
---@return number
|
||||
---@shared
|
||||
function StormFox2.Wind.GetYaw()
|
||||
return StormFox2.Data.Get( "WindAngle", 0 )
|
||||
end
|
||||
|
||||
---Returns the wind force.
|
||||
---@return number
|
||||
---@shared
|
||||
function StormFox2.Wind.GetForce()
|
||||
return StormFox2.Data.Get( "Wind", 0 )
|
||||
end
|
||||
|
||||
-- Beaufort scale and Saffir–Simpson hurricane scale
|
||||
local bfs = {}
|
||||
bfs[0] = "sf_winddescription.calm"
|
||||
bfs[0.3] = "sf_winddescription.light_air"
|
||||
bfs[1.6] = "sf_winddescription.light_breeze"
|
||||
bfs[3.4] = "sf_winddescription.gentle_breeze"
|
||||
bfs[5.5] = "sf_winddescription.moderate_breeze"
|
||||
bfs[8] = "sf_winddescription.fresh_breeze"
|
||||
bfs[10.8] = "sf_winddescription.strong_breeze"
|
||||
bfs[13.9] = "sf_winddescription.near_gale"
|
||||
bfs[17.2] = "sf_winddescription.gale"
|
||||
bfs[20.8] = "sf_winddescription.strong_gale"
|
||||
bfs[24.5] = "sf_winddescription.storm"
|
||||
bfs[28.5] = "sf_winddescription.violent_storm"
|
||||
bfs[32.7] = "sf_winddescription.hurricane" -- Also known as cat 1
|
||||
bfs[43] = "sf_winddescription.cat2"
|
||||
bfs[50] = "sf_winddescription.cat3"
|
||||
bfs[58] = "sf_winddescription.cat4"
|
||||
bfs[70] = "sf_winddescription.cat5"
|
||||
local bfkey = table.GetKeys(bfs)
|
||||
table.sort(bfkey,function(a,b) return a < b end)
|
||||
|
||||
---Returns the current (or given wind in m/s), in a beaufort-scale and description.
|
||||
---@param ms? number
|
||||
---@return number
|
||||
---@return string
|
||||
---@shared
|
||||
function StormFox2.Wind.GetBeaufort(ms)
|
||||
local n = ms or StormFox2.Wind.GetForce()
|
||||
local Beaufort, Description = 0, "sf_winddescription.calm"
|
||||
for k,kms in ipairs( bfkey ) do
|
||||
if kms <= n then
|
||||
Beaufort, Description = k - 1, bfs[ kms ]
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
return Beaufort, Description
|
||||
end
|
||||
-- Spawning env_wind won't work. Therefor we need to use the cl_tree_sway_dir on the client if it's not on the map.
|
||||
if CLIENT then
|
||||
local function updateWind()
|
||||
if StormFox2.Map.HadClass( "env_wind" ) then return end
|
||||
local nw = math.min(StormFox2.Wind.GetForce() * 0.6, 21)
|
||||
local ra = math.rad( StormFox2.Data.Get( "WindAngle", 0 ) )
|
||||
local wx,wy = math.cos(ra) * nw,math.sin(ra) * nw
|
||||
RunConsoleCommand("cl_tree_sway_dir",wx,wy)
|
||||
end
|
||||
hook.Add("StormFox2.Wind.Change","StormFox2.Wind.CLFix",function(windNorm, wind)
|
||||
if not StormFox2.Setting.GetCache("windmove_foliate", true) then return end
|
||||
updateWind()
|
||||
end)
|
||||
StormFox2.Setting.Callback("windmove_foliate", function(b)
|
||||
if b then
|
||||
updateWind()
|
||||
else
|
||||
RunConsoleCommand("cl_tree_sway_dir",0,0)
|
||||
end
|
||||
end)
|
||||
else
|
||||
local function updateWind(nw, ang)
|
||||
if not StormFox2.Ent.env_winds then return end
|
||||
local min = nw * .6
|
||||
local max = nw * .8
|
||||
local gust = math.min(nw, 5.5)
|
||||
for _,ent in ipairs( StormFox2.Ent.env_winds ) do
|
||||
if not IsValid(ent) then continue end
|
||||
--print(ent, max, min ,gust)
|
||||
if ang then ent:Fire('SetWindDir', ang) end
|
||||
ent:SetKeyValue('minwind', min)
|
||||
ent:SetKeyValue('maxwind', max)
|
||||
ent:SetKeyValue('gustdirchange', math.max(0, 21 - nw))
|
||||
ent:SetKeyValue('maxgust', gust)
|
||||
ent:SetKeyValue('mingust', gust * .8)
|
||||
end
|
||||
end
|
||||
hook.Add("StormFox2.Wind.Change","StormFox2.Wind.SVFix",function(windNorm, wind)
|
||||
local nw = StormFox2.Wind.GetForce() * 2
|
||||
local ang = StormFox2.Data.Get( "WindAngle", 0 )
|
||||
updateWind(nw, ang)
|
||||
end)
|
||||
StormFox2.Setting.Callback("windmove_foliate", function(b)
|
||||
if not StormFox2.Ent.env_winds then return end
|
||||
local ang = StormFox2.Data.Get( "WindAngle", 0 )
|
||||
if not b then
|
||||
updateWind(0, ang)
|
||||
return
|
||||
end
|
||||
local nw = StormFox2.Wind.GetForce() * 2
|
||||
updateWind(nw, ang)
|
||||
end)
|
||||
end
|
||||
--[[-------------------------------------------------------------------------
|
||||
Calculate and update the wind direction
|
||||
---------------------------------------------------------------------------]]
|
||||
local windNorm = Vector(0,0,-1)
|
||||
local windVec = Vector(0,0,0)
|
||||
local wind,windAng = 0,-1
|
||||
local function calcfunc()
|
||||
local owind = StormFox2.Data.Get("Wind",0)
|
||||
local nwind = owind * 0.2
|
||||
local nang = StormFox2.Data.Get("WindAngle",0)
|
||||
if nwind == wind and nang == windAng then return end -- Nothing changed
|
||||
wind = nwind
|
||||
windAng = nang
|
||||
windNorm = Angle( 90 - sqrt(wind) * 10 ,windAng,0):Forward()
|
||||
windVec = windNorm * wind
|
||||
windNorm:Normalize()
|
||||
--[[<Shared>-----------------------------------------------------------------
|
||||
Gets called when the wind changes.
|
||||
---------------------------------------------------------------------------]]
|
||||
hook.Run("StormFox2.Wind.Change", windNorm, owind)
|
||||
end
|
||||
|
||||
-- If the wind-data changes, is changing or is done changing. Reclaculate the wind.
|
||||
timer.Create("StormFox2.Wind.Update", 1, 0, function()
|
||||
if not StormFox2.Data.IsLerping("Wind") and not StormFox2.Data.IsLerping("WindAngle") then return end
|
||||
calcfunc()
|
||||
end)
|
||||
local function dataCheck(sKey,sVar)
|
||||
if sKey ~= "Wind" and sKey ~= "WindAngle" then return end
|
||||
calcfunc()
|
||||
end
|
||||
hook.Add("StormFox2.data.change","StormFox2.Wind.Calc",dataCheck)
|
||||
hook.Add("StormFox2.data.lerpend", "StormFox2.Wind.Calcfinish", dataCheck)
|
||||
|
||||
---Returns the wind norm.
|
||||
---@return Vector
|
||||
---@shared
|
||||
function StormFox2.Wind.GetNorm()
|
||||
return windNorm
|
||||
end
|
||||
|
||||
---Returns the wind vector.
|
||||
---@return Vector
|
||||
---@shared
|
||||
function StormFox2.Wind.GetVector()
|
||||
return windVec
|
||||
end
|
||||
--[[-------------------------------------------------------------------------
|
||||
Checks if an entity is out in the wind (or rain). Caches the result for 1 second.
|
||||
---------------------------------------------------------------------------]]
|
||||
local function IsMaterialEmpty( t )
|
||||
return t.HitTexture == "TOOLS/TOOLSINVISIBLE" or t.HitTexture == "**empty**" or t.HitTexture == "TOOLS/TOOLSNODRAW"
|
||||
end
|
||||
local function ET_II(pos, vec, mask, filter) -- Ignore invisble brushes 'n stuff'
|
||||
local lastT
|
||||
for i = 1, 5 do
|
||||
local t, a = ET(pos, vec, mask, filter)
|
||||
if not IsMaterialEmpty(t) and t.Hit then return t, a end
|
||||
lastT = lastT or t
|
||||
pos = t.HitPos
|
||||
end
|
||||
lastT.HitSky = true
|
||||
return lastT
|
||||
end
|
||||
local max_dis = 32400
|
||||
|
||||
---Checks to see if the entity is in the wind.
|
||||
---@param eEnt userdata
|
||||
---@param bDont_cache? boolean
|
||||
---@return boolean IsInWind
|
||||
---@return Vector WindNorm
|
||||
---@shared
|
||||
function StormFox2.Wind.IsEntityInWind(eEnt,bDont_cache)
|
||||
if not IsValid(eEnt) then return end
|
||||
if not bDont_cache then
|
||||
if eEnt.sf_wind_var and (eEnt.sf_wind_var[2] or 0) > CurTime() then
|
||||
return eEnt.sf_wind_var[1],windNorm
|
||||
else
|
||||
eEnt.sf_wind_var = {}
|
||||
end
|
||||
end
|
||||
local pos = eEnt:OBBCenter() + eEnt:GetPos()
|
||||
local tr = ET_II(pos, windNorm * -640000, MASK_SHOT, eEnt)
|
||||
local hitSky = tr.HitSky
|
||||
local dis = tr.HitPos:DistToSqr( pos )
|
||||
if not hitSky and dis >= max_dis then -- So far away. The wind would had gone around. Check if we're outside.
|
||||
local tr = ET(pos,Vector(0,0,640000),MASK_SHOT,eEnt)
|
||||
hitSky = tr.HitSky
|
||||
end
|
||||
if not bDont_cache then
|
||||
eEnt.sf_wind_var[1] = hitSky
|
||||
eEnt.sf_wind_var[2] = CurTime() + 1
|
||||
end
|
||||
return hitSky,windNorm
|
||||
end
|
||||
|
||||
-- Wind sounds
|
||||
if CLIENT then
|
||||
local windSnd = -1 -- -1 = none, 0 = outside, 0+ Distance to outside
|
||||
local windGusts = {}
|
||||
local maxVol = 1.5
|
||||
local function AddGuest( snd, vol, duration )
|
||||
if windGusts[snd] then return end
|
||||
if not duration then duration = SoundDuration( snd ) end
|
||||
windGusts[snd] = {vol * 0.4, CurTime() + duration - 1}
|
||||
end
|
||||
|
||||
timer.Create("StormFox2.Wind.Snd", 1, 0, function()
|
||||
windSnd = -1
|
||||
if StormFox2.Wind.GetForce() <= 0 then return end
|
||||
local env = StormFox2.Environment.Get()
|
||||
if not env or (not env.outside and not env.nearest_outside) then return end
|
||||
if not env.outside and env.nearest_outside then
|
||||
local view = StormFox2.util.RenderPos()
|
||||
windSnd = StormFox2.util.RenderPos():Distance(env.nearest_outside)
|
||||
else
|
||||
windSnd = 0
|
||||
end
|
||||
-- Guests
|
||||
local vM = (400 - windSnd) / 400
|
||||
if vM <= 0 then return end
|
||||
local wForce = StormFox2.Wind.GetForce()
|
||||
if math.random(50) > 40 then
|
||||
if wForce > 17 and math.random(1,2) > 1 then
|
||||
AddGuest("ambient/wind/windgust.wav",math.Rand(0.8, 1) * vM)
|
||||
elseif wForce > 14 and wForce < 30 then
|
||||
AddGuest("ambient/wind/wind_med" .. math.random(1,2) .. ".wav", math.min(maxVol, wForce / 30) * vM)
|
||||
end
|
||||
end
|
||||
if wForce > 27 and math.random(50) > 30 then
|
||||
AddGuest("ambient/wind/windgust_strong.wav",math.min(maxVol, wForce / 30) * vM)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Cold "empty" wind: ambience/wind1.wav
|
||||
-- ambient/wind/wind1.wav
|
||||
-- ambient/wind/wind_rooftop1.wav
|
||||
-- ambient/wind/wind1.wav
|
||||
-- StormFox2.Ambience.ForcePlay
|
||||
hook.Add("StormFox2.Ambiences.OnSound", "StormFox2.Ambiences.Wind", function()
|
||||
if windSnd < 0 then return end -- No wind
|
||||
local wForce = StormFox2.Wind.GetForce() * 0.25
|
||||
local vM = (400 - windSnd) / 400
|
||||
if vM <= 0 then return end
|
||||
-- Main loop
|
||||
StormFox2.Ambience.ForcePlay( "ambient/wind/wind_rooftop1.wav", math.min((wForce - 1) / 35, maxVol) * vM * 0.8, math.min(1.2, 0.9 + wForce / 100) )
|
||||
-- Wind gusts
|
||||
for snd,data in pairs(windGusts) do
|
||||
if data[2] <= CurTime() then
|
||||
windGusts[snd] = nil
|
||||
else
|
||||
StormFox2.Ambience.ForcePlay( snd, 0.2 * data[1] + math.Rand(0, 0.1) )
|
||||
end
|
||||
end
|
||||
end)
|
||||
else
|
||||
-- Flag models
|
||||
local flags = {}
|
||||
local flag_models = {}
|
||||
flag_models["models/props_fairgrounds/fairgrounds_flagpole01.mdl"] = 90
|
||||
flag_models["models/props_street/flagpole_american.mdl"] = 90
|
||||
flag_models["models/props_street/flagpole_american_tattered.mdl"] = 90
|
||||
flag_models["models/props_street/flagpole.mdl"] = 90
|
||||
flag_models["models/mapmodels/flags.mdl"] = 0
|
||||
flag_models["models/props/de_cbble/cobble_flagpole.mdl"] = 180
|
||||
flag_models["models/props/de_cbble/cobble_flagpole_2.mdl"] = 225
|
||||
flag_models["models/props/props_gameplay/capture_flag.mdl"] = 270
|
||||
flag_models["models/props_medieval/pendant_flag/pendant_flag.mdl"] = 0
|
||||
flag_models["models/props_moon/parts/moon_flag.mdl"] = 0
|
||||
local function FlagInit()
|
||||
-- Check if there are any flags on the map
|
||||
for _,ent in pairs(ents.GetAll()) do
|
||||
if not ent:CreatedByMap() then continue end
|
||||
-- Check the angle
|
||||
if math.abs(ent:GetAngles():Forward():Dot(Vector(0,0,1))) > 5 then continue end
|
||||
if not flag_models[ent:GetModel()] then continue end
|
||||
table.insert(flags,ent)
|
||||
end
|
||||
if #flags > 0 then -- Only add the hook if there are flags on the map.
|
||||
hook.Add("StormFox2.data.change","StormFox2.flagcontroller",function(key,var)
|
||||
if key == "WindAngle" then
|
||||
--print("Windang", var)
|
||||
for _,ent in ipairs(flags) do
|
||||
if not IsValid(ent) then continue end
|
||||
local y = flag_models[ent:GetModel()] or 0
|
||||
ent:SetAngles(Angle(0,var + y,0))
|
||||
end
|
||||
elseif key == "Wind" then
|
||||
--print("Wind", var)
|
||||
for _,ent in ipairs(flags) do
|
||||
if not IsValid(ent) then continue end
|
||||
ent:SetPlaybackRate(math.Clamp(var / 7,0.5,10))
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
hook.Add("StormFox2.PostEntityScan", "StormFox2.Wind.FlagInit", FlagInit)
|
||||
end
|
||||
|
||||
if CLIENT then return end
|
||||
-- Wind movment
|
||||
local function windMove(ply, mv, cmd )
|
||||
if not StormFox2.Setting.GetCache("windmove_players") then return end
|
||||
if( ply:GetMoveType() != MOVETYPE_WALK ) then return end
|
||||
local wF = (StormFox2.Wind.GetForce() - 15) / 11
|
||||
if wF <= 0 then return end
|
||||
if not StormFox2.Wind.IsEntityInWind(ply) then return end -- Not in wind
|
||||
-- Calc windforce
|
||||
local r = math.rad( StormFox2.Wind.GetYaw() - ply:GetAngles().y )
|
||||
local fS = math.cos( r ) * wF
|
||||
local sS = math.sin( r ) * wF
|
||||
|
||||
if mv:GetForwardSpeed() == 0 and mv:GetSideSpeed() == 0 then -- Not moving
|
||||
--mv:SetSideSpeed( - sS / 10) Annoying
|
||||
--mv:SetForwardSpeed( - fS / 10)
|
||||
else
|
||||
-- GetForwardMove() returns 10000y. We need to figure out the speed first.
|
||||
local running, walking = mv:KeyDown( IN_SPEED ), mv:KeyDown( IN_WALK )
|
||||
local speed = running and ply:GetRunSpeed() or walking and ply:GetSlowWalkSpeed() or ply:GetWalkSpeed()
|
||||
|
||||
local forward = math.Clamp(mv:GetForwardSpeed(), -speed, speed)
|
||||
local side = math.Clamp(mv:GetSideSpeed(), -speed, speed)
|
||||
if forward~=0 and side~=0 then
|
||||
forward = forward * .7
|
||||
side = side * .7
|
||||
end
|
||||
-- Now we modify them. We don't want to move back.
|
||||
if forward > 0 and fS < 0 then
|
||||
forward = math.max(0, forward / -fS)
|
||||
elseif forward < 0 and fS > 0 then
|
||||
forward = math.min(0, forward / fS)
|
||||
end
|
||||
if side > 0 and sS > 0 then
|
||||
side = math.max(0, side / sS)
|
||||
forward = forward + fS * 20
|
||||
elseif side < 0 and sS < 0 then
|
||||
side = math.min(0, side / -sS)
|
||||
forward = forward + fS * 20
|
||||
end
|
||||
-- Apply the new speed
|
||||
mv:SetForwardSpeed( forward )
|
||||
cmd:SetForwardMove( forward )
|
||||
mv:SetSideSpeed( side )
|
||||
cmd:SetSideMove( side )
|
||||
end
|
||||
end
|
||||
hook.Add("SetupMove", "windtest", windMove)
|
||||
|
||||
-- Wind proppush
|
||||
local move_list = {
|
||||
["rpg_missile"] = true,
|
||||
["npc_grenade_frag"] = true,
|
||||
["npc_grenade_bugbait"] = true, -- Doesn't work
|
||||
["gmod_hands"] = false,
|
||||
["gmod_tool"] = false
|
||||
}
|
||||
local function CanMoveClass( ent )
|
||||
if( IsValid( ent:GetParent()) ) then return end
|
||||
local class = ent:GetClass()
|
||||
if( move_list[class] == false ) then return false end
|
||||
return string.match(class,"^prop_") or string.match(class,"^gmod_") or move_list[class]
|
||||
end
|
||||
|
||||
local function ApplyWindEffect( ent, wind, windnorm )
|
||||
if ent:GetPersistent() then return end
|
||||
if(wind < 5) then return end
|
||||
-- Make a toggle
|
||||
local vol
|
||||
local phys = ent:GetPhysicsObject()
|
||||
if(not phys or not IsValid(phys)) then -- No physics
|
||||
return
|
||||
end
|
||||
vol = phys:GetVolume() or 15
|
||||
-- Check Move
|
||||
local windPush = windnorm * 1.37 * vol * .66
|
||||
--windnorm * 5.92 * (vol / 50)
|
||||
local windRequ = phys:GetInertia()
|
||||
windRequ = max(windRequ.x,windRequ.y)
|
||||
if max(abs(windPush.x),abs(windPush.y)) < windRequ then -- Can't move
|
||||
return
|
||||
end
|
||||
local class = ent:GetClass()
|
||||
if( class != "npc_grenade_frag") then
|
||||
windPush.x = math.Clamp(windPush.x, -5500, 5500)
|
||||
windPush.y = math.Clamp(windPush.y, -5500, 5500)
|
||||
end
|
||||
-- Unfreeze
|
||||
if(wind > 20) then
|
||||
if( StormFox2.Setting.GetCache("windmove_props_unfreeze", true) ) then
|
||||
if not phys:IsMoveable() then
|
||||
phys:EnableMotion(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Unweld
|
||||
if(wind > 30) then
|
||||
if( StormFox2.Setting.GetCache("windmove_props_unweld", true) ) then
|
||||
if constraint.FindConstraint( ent, "Weld" ) and math.random(1, 15) < 2 then
|
||||
ent:EmitSound("physics/wood/wood_box_break" .. math.random(1,2) .. ".wav")
|
||||
constraint.RemoveConstraints( ent, "Weld" )
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Move
|
||||
phys:Wake()
|
||||
phys:ApplyForceCenter(Vector(windPush.x, windPush.y, math.max(phys:GetVelocity().z, 0)))
|
||||
-- Break
|
||||
if(wind > 40) then
|
||||
if( StormFox2.Setting.GetCache("windmove_props_break", true) ) then
|
||||
if not ent:IsVehicle() and (ent._sfnext_dmg or 0) <= CurTime() and ent:GetClass() != "npc_grenade_frag" then
|
||||
ent._sfnext_dmg = CurTime() + 0.5
|
||||
ent:TakeDamage(ent:Health() / 10 + 2,game.GetWorld(),game.GetWorld())
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local move_tab = {}
|
||||
local current_prop = 0
|
||||
local function AddEntity( ent )
|
||||
if( ent._sfwindcan or 0 ) > CurTime() then return end
|
||||
if( StormFox2.Setting.GetCache("windmove_props_max", 50) <= table.Count(move_tab) ) then return end -- Too many props moving atm
|
||||
move_tab[ ent ] = CurTime()
|
||||
--ApplyWindEffect( ent, StormFox2.Wind.GetForce(), StormFox2.Wind.GetNorm() )
|
||||
end
|
||||
|
||||
hook.Add("OnEntityCreated","StormFox.Wind.PropMove",function(ent)
|
||||
if( not StormFox2.Setting.GetCache("windmove_props", false) ) then return end
|
||||
if( not IsValid(ent) ) then return end
|
||||
if( not CanMoveClass( ent ) ) then return end
|
||||
AddEntity( ent )
|
||||
end)
|
||||
|
||||
local scanID = 0
|
||||
local function ScanProps()
|
||||
local t = ents.GetAll()
|
||||
if( #t < scanID) then
|
||||
scanID = 0
|
||||
end
|
||||
for i = scanID, math.min(#t, scanID + 30) do
|
||||
local ent = t[i]
|
||||
if(not IsValid( ent )) then break end
|
||||
if ent:GetPersistent() then continue end
|
||||
if not CanMoveClass( ent ) then continue end
|
||||
if move_tab[ ent ] then continue end -- Already added
|
||||
if not StormFox2.Wind.IsEntityInWind( ent ) then continue end -- Not in wind
|
||||
AddEntity( ent )
|
||||
end
|
||||
scanID = scanID + 30
|
||||
end
|
||||
|
||||
local next_loop = 0 -- We shouldn't run this on think if there arae too few props
|
||||
hook.Add("Think","StormFox.Wind.EffectProps",function()
|
||||
if( not StormFox2.Setting.GetCache("windmove_props", false) ) then return end
|
||||
if( next_loop > CurTime() ) then return end
|
||||
next_loop = CurTime() + (game.SinglePlayer() and 0.1 or 0.2)
|
||||
-- Scan on all entities. This would be slow. But we're only looking at 30 entities at a time.
|
||||
ScanProps()
|
||||
|
||||
local t = table.GetKeys( move_tab )
|
||||
if(#t < 1) then return end
|
||||
local wind = StormFox2.Wind.GetForce()
|
||||
-- Check if there is wind
|
||||
if( wind < 10) then
|
||||
table.Empty( move_tab )
|
||||
return
|
||||
end
|
||||
if( current_prop > #t) then
|
||||
current_prop = 1
|
||||
end
|
||||
local wind, c_windnorm = StormFox2.Wind.GetForce(), StormFox2.Wind.GetNorm()
|
||||
local windnorm = Vector(c_windnorm.x, c_windnorm.y, 0)
|
||||
local c = CurTime()
|
||||
for i = current_prop, math.min(#t, current_prop + 30) do
|
||||
local ent = t[i]
|
||||
if(not ent) then
|
||||
break
|
||||
end
|
||||
-- Check if valid
|
||||
if(not IsValid( ent ) or not StormFox2.Wind.IsEntityInWind( ent )) then
|
||||
move_tab[ent] = nil
|
||||
continue
|
||||
end
|
||||
-- Check if presistence
|
||||
if ent:GetPersistent() then continue end
|
||||
-- If the entity has been in the wind for over 10 seconds, try and move on and see if we can pick up something else
|
||||
if(move_tab[ ent ] < c - 10) then
|
||||
ent._sfwindcan = c + math.random(20, 30)
|
||||
if(StormFox2.Setting.GetCache("windmove_props_makedebris", true)) then
|
||||
ent:SetCollisionGroup( COLLISION_GROUP_DEBRIS )
|
||||
end
|
||||
move_tab[ent] = nil
|
||||
continue
|
||||
end
|
||||
ApplyWindEffect( ent, wind, windnorm )
|
||||
end
|
||||
current_prop = current_prop + 30
|
||||
end)
|
||||
Reference in New Issue
Block a user