mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 21:53:46 +03:00
Upload
This commit is contained in:
535
lua/stormfox2/framework/sh_thunder.lua
Normal file
535
lua/stormfox2/framework/sh_thunder.lua
Normal file
@@ -0,0 +1,535 @@
|
||||
--[[
|
||||
| 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.Thunder = {}
|
||||
|
||||
---Returns true if it is thundering.
|
||||
---@return boolean
|
||||
---@shared
|
||||
function StormFox2.Thunder.IsThundering()
|
||||
return StormFox2.Data.Get("nThunder", 0) > 0
|
||||
end
|
||||
|
||||
---Returns the amount of posible strikes pr minute.
|
||||
---@return number
|
||||
---@shared
|
||||
function StormFox2.Thunder.GetActivity()
|
||||
return StormFox2.Data.Get("nThunder", 0)
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
local THUNDER_MAKE_SKYBOX = 0
|
||||
local THUNDER_TRACE_ERROR = 1
|
||||
local THUNDER_SUCCESS = 2
|
||||
|
||||
local function ETHull(pos,pos2,size,mask)
|
||||
local t = util.TraceHull( {
|
||||
start = pos,
|
||||
endpos = pos2,
|
||||
maxs = Vector(size,size,4),
|
||||
mins = Vector(-size,-size,0),
|
||||
mask = mask
|
||||
} )
|
||||
t.HitPos = t.HitPos or pos + pos2
|
||||
return t
|
||||
end
|
||||
-- Damages an entity
|
||||
local function StrikeDamageEnt( ent )
|
||||
if not ent or not IsValid(ent) then return end
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin( ent:GetPos() )
|
||||
effectdata:SetEntity(ent)
|
||||
effectdata:SetMagnitude(2)
|
||||
effectdata:SetScale(3)
|
||||
for i = 1,100 do
|
||||
util.Effect( "TeslaHitboxes", effectdata, true, true )
|
||||
end
|
||||
local ctd = DamageInfo()
|
||||
ctd:IsDamageType(DMG_SHOCK)
|
||||
ctd:SetDamage(math.Rand(90,200))
|
||||
local vr = VectorRand()
|
||||
vr.z = math.abs(vr.z)
|
||||
ctd:SetDamageForce(vr * 1000)
|
||||
ctd:SetInflictor(game.GetWorld())
|
||||
ctd:SetAttacker(game.GetWorld())
|
||||
ent:TakeDamageInfo(ctd)
|
||||
end
|
||||
-- Damanges an area
|
||||
local function StrikeDamagePos( vPos )
|
||||
local b_InWater = bit.band( util.PointContents( vPos ), CONTENTS_WATER ) == CONTENTS_WATER
|
||||
local t = {}
|
||||
for _,ent in ipairs(ents.FindInSphere(vPos,750)) do
|
||||
-- It hit in water, and you're nearby
|
||||
if b_InWater and ent:WaterLevel() > 0 then
|
||||
StrikeDamageEnt(ent)
|
||||
table.insert(t, ent)
|
||||
elseif ent:GetPos():Distance( vPos ) < 150 then
|
||||
StrikeDamageEnt(ent)
|
||||
table.insert(t, ent)
|
||||
end
|
||||
end
|
||||
hook.Run("StormFox2.Thunder.OnStrike", vPos, t)
|
||||
end
|
||||
-- Make STrike
|
||||
local Sway = 100
|
||||
|
||||
-- Traces a lightningstrike from sky to ground.
|
||||
|
||||
local BrushZ = math.max(1, ( StormFox2.Map.MaxSize().z - StormFox2.Map.MinSize().z ) / 20000)
|
||||
|
||||
local function MakeStrikeDown( vPos, nTraceSize )
|
||||
if not nTraceSize then nTraceSize = 512 end
|
||||
-- Find the sky position at the area
|
||||
local SkyPos = StormFox2.DownFall.FindSky( vPos, vector_up, 8 )
|
||||
if not SkyPos then -- Unable to find sky above. Get the higest point
|
||||
SkyPos = Vector(vPos.x, vPos.y, StormFox2.Map.MaxSize().z)
|
||||
SkyPos = StormFox2.DownFall.FindSky( SkyPos, vector_up, 1 ) or SkyPos
|
||||
end
|
||||
--debugoverlay.Box(SkyPos, Vector(1,1,1) * -20, Vector(1,1,1) * 20, 15, Color(255,0,0))
|
||||
-- Find the strike distance (Some maps are suuuper tall)
|
||||
local tr = ETHull(SkyPos - vector_up * 10, Vector( vPos.x, vPos.y, StormFox2.Map.MinSize().z), 256, MASK_SOLID_BRUSHONLY )
|
||||
if tr.AllSolid or tr.Fraction == 0 then -- This is inside solid and should instead be done in the skybox.
|
||||
return THUNDER_MAKE_SKYBOX, SkyPos
|
||||
end
|
||||
SkyPos.z = math.min( SkyPos.z, tr.HitPos.z + 8000 )
|
||||
local line = {}
|
||||
table.insert(line,pos)
|
||||
-- Create a line down
|
||||
local olddir = Vector(0,0,-1)
|
||||
local m_dis = math.max(1, ( SkyPos.z - StormFox2.Map.MinSize().z ) / 20000)
|
||||
local pos = SkyPos - vector_up * 5
|
||||
local _n = nTraceSize / 40
|
||||
for i = 20, 1, -1 do
|
||||
-- Random sway
|
||||
local randir = Angle(math.Rand(-Sway,Sway) + 90,math.random(360),math.Rand(-Sway,Sway)):Forward() + olddir
|
||||
randir:Normalize()
|
||||
randir.z = -math.abs(randir.z)
|
||||
olddir = randir
|
||||
local pos2 = pos + randir * math.Rand(800, 1000) * m_dis
|
||||
local m_dis = math.max(1, ( StormFox2.Map.MaxSize().z - StormFox2.Map.MinSize().z ) / 20000)
|
||||
local tr = ETHull(pos, pos2, nTraceSize - i * _n )
|
||||
--debugoverlay.Line(pos, pos2, 10)
|
||||
if not tr.Hit then
|
||||
table.insert(line, pos2)
|
||||
pos = pos2
|
||||
else
|
||||
if tr.HitSky then -- We hit the side of the skybox. Go to other way
|
||||
olddir = -olddir
|
||||
else
|
||||
table.insert(line, tr.HitPos)
|
||||
return THUNDER_SUCCESS, line, tr
|
||||
end
|
||||
end
|
||||
end
|
||||
return line, tr
|
||||
end
|
||||
|
||||
-- Creates a lightniingstrike up ( Useful when forcing a lightning strike to hit something )
|
||||
local function MakeStrikeUp( vPos )
|
||||
local SkyPos = StormFox2.DownFall.FindSky( vPos, vector_up, 8 )
|
||||
if not SkyPos then -- Unable to find sky above. Get the higest point
|
||||
SkyPos = Vector(vPos.x, vPos.y, StormFox2.Map.MaxSize().z)
|
||||
SkyPos = StormFox2.DownFall.FindSky( SkyPos, vector_up, 1 ) or SkyPos
|
||||
end
|
||||
local olddir = Vector(0,0,-1)
|
||||
local pos = vPos
|
||||
local m_dis = math.max(1, ( StormFox2.Map.MaxSize().z - StormFox2.Map.MinSize().z ) / 20000)
|
||||
local list = {pos}
|
||||
for i = 1, 20 do
|
||||
local randir = Angle(math.Rand(-Sway,Sway) + 90,math.random(360),math.Rand(-Sway,Sway)):Forward() + olddir
|
||||
randir:Normalize()
|
||||
randir.z = -math.abs(randir.z)
|
||||
olddir = randir
|
||||
local pos2 = pos + -randir * math.Rand(800, 1000) * m_dis
|
||||
if pos2.z >= SkyPos.z then
|
||||
table.insert(list, Vector(pos2.x, pos2.y, SkyPos.z))
|
||||
break
|
||||
else
|
||||
pos = pos2
|
||||
table.insert(list, pos)
|
||||
end
|
||||
end
|
||||
return table.Reverse(list)
|
||||
end
|
||||
|
||||
local function LightFluff(tList, b_InSkybox )
|
||||
local n_Length = math.Rand(.4,0.7)
|
||||
local n_Light = math.random(200, 250)
|
||||
|
||||
net.Start(StormFox2.Net.Thunder)
|
||||
net.WriteBool( true )
|
||||
net.WriteUInt(#tList, 5)
|
||||
for i = 1, #tList do
|
||||
net.WriteVector(tList[i])
|
||||
end
|
||||
net.WriteBool( b_InSkybox )
|
||||
net.WriteFloat(n_Length)
|
||||
net.WriteUInt(n_Light,8)
|
||||
net.Broadcast()
|
||||
end
|
||||
|
||||
---Creates a lightningstrike at a given position. Will return a hit entity as a second argument.
|
||||
---@param pos Vector
|
||||
---@return boolean success
|
||||
---@return Entity
|
||||
---@server
|
||||
function StormFox2.Thunder.CreateAt( pos )
|
||||
local t_Var, tList, tr
|
||||
local b_InSkybox = false
|
||||
local vMapMin = StormFox2.Map.MinSize()
|
||||
local vMapMax = StormFox2.Map.MaxSize()
|
||||
if not pos then
|
||||
pos = Vector( math.Rand(vMapMin.x, vMapMax.x), math.Rand(vMapMin.y, vMapMax.y), math.Rand(vMapMax.z, vMapMin.z / 2) )
|
||||
end
|
||||
local bInside = pos.x >= vMapMin.x and pos.x <= vMapMax.x and vMapMin.y and pos.y <= vMapMax.y
|
||||
if bInside then
|
||||
t_Var, tList, tr = MakeStrikeDown( pos )
|
||||
if t_Var == THUNDER_MAKE_SKYBOX then
|
||||
bInside = false
|
||||
end
|
||||
end
|
||||
if not bInside then -- Outside the map
|
||||
tList = MakeStrikeUp( Vector(pos.x, pos.y, StormFox2.Map.MinSize().z) )
|
||||
b_InSkybox = true
|
||||
end
|
||||
if not tList then return false end -- Unable to create lightning strike here.
|
||||
local hPos = tr and tr.HitPos or tList[#tList]
|
||||
if not hPos then return end
|
||||
if tr and IsValid( tr.Entity ) then
|
||||
table.insert(tList, tr.Entity:GetPos() + tr.Entity:OBBCenter())
|
||||
hPos = tr.Entity:GetPos() + tr.Entity:OBBCenter()
|
||||
end
|
||||
StrikeDamagePos( hPos )
|
||||
LightFluff(tList, b_InSkybox )
|
||||
return true, tr and IsValid( tr.Entity ) and tr.Entity
|
||||
end
|
||||
|
||||
---Creates a lightning strike to hit the given position / entity.
|
||||
---@param zPosOrEnt Vector|Entity
|
||||
---@param bRangeDamage number
|
||||
---@return boolean success
|
||||
---@server
|
||||
function StormFox2.Thunder.Strike( zPosOrEnt, bRangeDamage )
|
||||
-- Strike the entity
|
||||
if not bRangeDamage and zPosOrEnt.Health then
|
||||
local ent = zPosOrEnt
|
||||
timer.Simple(0.4, function()
|
||||
StrikeDamageEnt( ent )
|
||||
end)
|
||||
end
|
||||
if zPosOrEnt.GetPos then
|
||||
if zPosOrEnt.OBBCenter then
|
||||
zPosOrEnt = zPosOrEnt:GetPos() + zPosOrEnt:OBBCenter()
|
||||
else
|
||||
zPosOrEnt = zPosOrEnt:GetPos()
|
||||
end
|
||||
end
|
||||
if bRangeDamage then
|
||||
timer.Simple(0.4, function() StrikeDamagePos( zPosOrEnt ) end)
|
||||
end
|
||||
local b_InSkybox = not StormFox2.Map.IsInside( zPosOrEnt )
|
||||
--if b_InSkybox then
|
||||
-- zPosOrEnt = StormFox2.Map.WorldtoSkybox( zPosOrEnt )
|
||||
--end
|
||||
|
||||
local tList = MakeStrikeUp( zPosOrEnt )
|
||||
LightFluff(tList, false )
|
||||
return true
|
||||
end
|
||||
|
||||
---Creates a rumble.
|
||||
---@param pos Vector
|
||||
---@param bLight boolean
|
||||
---@server
|
||||
function StormFox2.Thunder.Rumble( pos, bLight )
|
||||
if not pos then
|
||||
local vMapMin = StormFox2.Map.MinSize()
|
||||
local vMapMax = StormFox2.Map.MaxSize()
|
||||
pos = Vector( math.Rand(vMapMin.x, vMapMax.x), math.Rand(vMapMin.y, vMapMax.y), math.Rand(vMapMax.z, vMapMin.z / 2) )
|
||||
end
|
||||
local n_Length = bLight and math.Rand(.4,0.7) or 0
|
||||
local n_Light = bLight and math.random(150, 250) or 0
|
||||
net.Start( StormFox2.Net.Thunder )
|
||||
net.WriteBool( false )
|
||||
net.WriteVector( pos )
|
||||
net.WriteFloat(n_Length)
|
||||
net.WriteUInt(n_Light,8)
|
||||
net.Broadcast()
|
||||
end
|
||||
|
||||
-- Enables thunder and makes them spawn at random, until set off or another weather gets selected
|
||||
local b = false
|
||||
local n = math.max(StormFox2.Map.MaxSize().x, StormFox2.Map.MaxSize().y, -StormFox2.Map.MinSize().x,-StormFox2.Map.MinSize().y)
|
||||
if StormFox2.Map.Has3DSkybox() then
|
||||
n = n * 1.5
|
||||
end
|
||||
|
||||
do
|
||||
local n = 0
|
||||
---Enables / Disables thunder.
|
||||
---@param bEnable boolean
|
||||
---@param nActivityPrMinute? number
|
||||
---@param nTimeAmount? number
|
||||
---@server
|
||||
function StormFox2.Thunder.SetEnabled( bEnable, nActivityPrMinute, nTimeAmount )
|
||||
n = 0
|
||||
if bEnable then
|
||||
StormFox2.Network.Set("nThunder", nActivityPrMinute)
|
||||
if nTimeAmount then
|
||||
StormFox2.Network.Set("nThunder", 0, nTimeAmount)
|
||||
end
|
||||
else
|
||||
StormFox2.Network.Set("nThunder", 0)
|
||||
end
|
||||
end
|
||||
hook.Add("Think", "StormFox2.thunder.activity", function()
|
||||
if not StormFox2.Thunder.IsThundering() then return end
|
||||
if n >= CurTime() then return end
|
||||
local a = StormFox2.Thunder.GetActivity()
|
||||
n = CurTime() + math.random(50, 60) / a
|
||||
-- Strike or rumble
|
||||
if math.random(1,3) < 3 then
|
||||
StormFox2.Thunder.CreateAt()
|
||||
else
|
||||
StormFox2.Thunder.Rumble( nil, math.random(10) > 1 )
|
||||
end
|
||||
end)
|
||||
end
|
||||
else
|
||||
lightningStrikes = lightningStrikes or {}
|
||||
local _Light, _Stop, _Length = 0,0,0
|
||||
|
||||
---Returns light created by thunder.
|
||||
---@return number
|
||||
---@client
|
||||
function StormFox2.Thunder.GetLight()
|
||||
if _Light <= 0 then return 0 end
|
||||
if _Stop < CurTime() then
|
||||
_Light = 0
|
||||
return 0
|
||||
end
|
||||
local t = (_Stop - CurTime()) / _Length
|
||||
local c = math.abs(math.sin( t * math.pi ))
|
||||
local l = _Light * c
|
||||
return math.random(l, l * 0.5) -- Flicker a bit
|
||||
end
|
||||
|
||||
-- 0 - 2000
|
||||
local CloseStrikes = {"sound/stormfox2/amb/thunder_strike.ogg"}
|
||||
-- 2000 - 20000
|
||||
local MediumStrikes = {"sound/stormfox2/amb/thunder_strike.ogg", "sound/stormfox2/amb/thunder_strike2.ogg"}
|
||||
-- 20000 +
|
||||
local FarStrikes = {}
|
||||
|
||||
if IsMounted("csgo") or IsMounted("left4dead2") then
|
||||
table.insert(FarStrikes, "ambient/weather/thunderstorm/lightning_strike_1.wav")
|
||||
table.insert(FarStrikes, "ambient/weather/thunderstorm/lightning_strike_4.wav")
|
||||
end
|
||||
if #FarStrikes < 1 then
|
||||
table.insert(FarStrikes, "sound/stormfox2/amb/thunder_strike2.ogg")
|
||||
end
|
||||
|
||||
local snd_buffer = {}
|
||||
local function StrikeEffect( pos, n_Length )
|
||||
local dlight = DynamicLight( 1 )
|
||||
if ( dlight ) then
|
||||
dlight.pos = pos
|
||||
dlight.r = 255
|
||||
dlight.g = 255
|
||||
dlight.b = 255
|
||||
dlight.brightness = 6
|
||||
dlight.Decay = 3000 / n_Length
|
||||
dlight.Size = 256 * 8
|
||||
dlight.DieTime = CurTime() + n_Length
|
||||
end
|
||||
local effectdata = EffectData()
|
||||
local s = math.random(5, 8)
|
||||
effectdata:SetOrigin( pos + vector_up * 4 )
|
||||
effectdata:SetMagnitude( s / 2 )
|
||||
effectdata:SetNormal(vector_up)
|
||||
effectdata:SetRadius( 8 )
|
||||
util.Effect( "Sparks", effectdata, true, true )
|
||||
end
|
||||
|
||||
local function PlayStrike( vPos, nViewDis, viewPos )
|
||||
local snd = ""
|
||||
if nViewDis <= 2000 then
|
||||
snd = table.Random(CloseStrikes)
|
||||
elseif nViewDis <= 15000 then
|
||||
snd = table.Random(MediumStrikes)
|
||||
else
|
||||
snd = table.Random(FarStrikes)
|
||||
end
|
||||
if string.sub(snd, 0, 6 ) == "sound/" or string.sub(snd,-4) == ".ogg" then
|
||||
sound.PlayFile( snd, "3dnoplay", function( station, errCode, errStr )
|
||||
if ( IsValid( station ) ) then
|
||||
station:Set3DFadeDistance( 0, 10 )
|
||||
station:SetVolume( 1)
|
||||
station:SetPos(vPos)
|
||||
station:Play()
|
||||
end
|
||||
end)
|
||||
else
|
||||
surface.PlaySound( snd )
|
||||
end
|
||||
end
|
||||
--[[
|
||||
Sound moves about 343 meters pr second
|
||||
52.49 hU = 1 meter ~ 18.004 hU pr second
|
||||
]]
|
||||
local b = true
|
||||
local function SndThink()
|
||||
if #snd_buffer < 1 then
|
||||
hook.Remove("Think","StormFox2.Thunder.SndDis")
|
||||
b = false
|
||||
return
|
||||
end
|
||||
local r = {}
|
||||
local view = StormFox2.util.ViewEntity():GetPos()
|
||||
local c = CurTime() - 0.2
|
||||
for k,v in ipairs( snd_buffer ) do
|
||||
local travel = (c - v[2]) * 18004
|
||||
local vDis = view:Distance( v[1] )
|
||||
if vDis - travel < 0 then
|
||||
table.insert(r, k)
|
||||
PlayStrike( v[1], vDis, view )
|
||||
end
|
||||
end
|
||||
for i = #r, 1, -1 do
|
||||
table.remove(snd_buffer, r[i])
|
||||
end
|
||||
end
|
||||
hook.Add("Think","StormFox2.Thunder.SndDis", SndThink)
|
||||
|
||||
local function Strike( tList, b_InSkybox, n_Length, n_Light )
|
||||
table.insert(lightningStrikes, {CurTime() + n_Length, n_Length, b_InSkybox, tList, true})
|
||||
local pos = tList[#tList][1]
|
||||
sound.Play("ambient/energy/weld" .. math.random(1,2) .. ".wav", pos)
|
||||
if not b then
|
||||
hook.Add("Think","StormFox2.Thunder.SndDis", SndThink)
|
||||
end
|
||||
table.insert(snd_buffer, {pos, CurTime()})
|
||||
local c = CurTime()
|
||||
_Light = 255
|
||||
_Length = .7
|
||||
_Stop = math.max(c + _Length, _Stop)
|
||||
end
|
||||
|
||||
local function Rumble( vPos, n_Length, n_Light )
|
||||
-- Thunder is at 120dB
|
||||
local c = CurTime()
|
||||
_Light = n_Light
|
||||
_Length = n_Length
|
||||
_Stop = math.max(c + n_Length, _Stop)
|
||||
sound.Play("ambient/atmosphere/thunder" .. math.random(3,4) .. ".wav", StormFox2.util.ViewEntity():GetPos(), 150)
|
||||
|
||||
end
|
||||
local Sway = 120
|
||||
net.Receive( StormFox2.Net.Thunder, function(len)
|
||||
local b_Strike = net.ReadBool()
|
||||
if b_Strike then
|
||||
local tList = {}
|
||||
local old
|
||||
local n = net.ReadUInt(5)
|
||||
for i = 1, n do
|
||||
local randir = Angle(math.Rand(-Sway,Sway) + 90,math.random(360),math.Rand(-Sway,Sway))
|
||||
local new = net.ReadVector()
|
||||
if old then
|
||||
randir = randir:Forward() + (new - old):Angle():Forward() * 2
|
||||
else
|
||||
randir = randir:Forward()
|
||||
end
|
||||
old = new
|
||||
tList[i] = {new,math.Rand(1.2,1.5),randir,math.random(0,1)}
|
||||
--debugoverlay.Sphere(new, 15, 15, Color(255,255,255), true)
|
||||
end
|
||||
local b_InSkybox = net.ReadBool()
|
||||
Strike(tList, b_InSkybox, net.ReadFloat(), net.ReadUInt(8))
|
||||
else
|
||||
local vPos = net.ReadVector()
|
||||
Rumble(vPos, net.ReadFloat(), net.ReadUInt(8) )
|
||||
end
|
||||
end)
|
||||
|
||||
-- Render Strikes
|
||||
local tex = {(Material("stormfox2/effects/lightning"))}
|
||||
local texend = {(Material("stormfox2/effects/lightning_end")),(Material("stormfox2/effects/lightning_end2"))}
|
||||
for k, v in ipairs( texend ) do
|
||||
v:SetFloat("$nofog",1)
|
||||
end
|
||||
local t = 0
|
||||
hook.Add("PostDrawOpaqueRenderables","StormFox2.Render.Lightning",function(a,sky)
|
||||
if a or #lightningStrikes < 1 then return end
|
||||
if sky then return end -- Doesn't work yet
|
||||
local r = {}
|
||||
local c = CurTime()
|
||||
local col = Color( 255, 255, 255, 255)
|
||||
for k, v in ipairs( lightningStrikes ) do
|
||||
-- Render world or skybox
|
||||
--if v[3] ~= sky then continue end
|
||||
-- Remove if dead
|
||||
if v[1] < c then
|
||||
table.insert(r, k)
|
||||
continue
|
||||
end
|
||||
|
||||
local life = 1 - ( v[1] - c ) / v[2] -- 0 - 1
|
||||
if life < 0.6 then
|
||||
col.a = 425 * life
|
||||
else
|
||||
col.a = 637.5 * (1 - life)
|
||||
end
|
||||
local fuzzy = life < 0.6
|
||||
local i = 0.6 / #v[4]
|
||||
if v[5] and not fuzzy then
|
||||
StrikeEffect( v[4][#v[4]][1] , life )
|
||||
lightningStrikes[k][5] = false
|
||||
end
|
||||
-- Render beams
|
||||
render.SetMaterial(tex[1])
|
||||
render.StartBeam(#v[4])
|
||||
local l = math.Rand(0.4, 0.8)
|
||||
for k2, v2 in ipairs( v[4] ) do
|
||||
if life < k2 * i then break end
|
||||
local tp = 0.1
|
||||
render.AddBeam( v2[1], 400, (l * (k2 - 1)) % 1, col )
|
||||
end
|
||||
render.EndBeam()
|
||||
|
||||
-- Render strikes
|
||||
if fuzzy then
|
||||
for k2, v2 in ipairs( v[4] ) do
|
||||
if life < k2 * i or k2 + 3 >= #v[4] then break end
|
||||
local n2 = life * 2- k2 * 0.04
|
||||
local vec = v2[1]
|
||||
local tp = 1 / #v[4] * k2
|
||||
local n = k2 % #texend + 1
|
||||
render.SetMaterial(texend[n])
|
||||
local w,h = texend[n]:Width() * n2,texend[n]:Height() * n2
|
||||
render.DrawBeam( vec, vec + v2[3] * h * v2[2], w * v2[2], 1 - n2, 1, col )
|
||||
end
|
||||
else
|
||||
local v1 = v[4][1][1]
|
||||
local v2 = v[4][#v[4]][1]
|
||||
local vc = (v1 + v2) / 2
|
||||
vc.z = v2.z
|
||||
local vc2 = Vector(vc.x,vc.y,v1.z)
|
||||
local a = math.max(0, 1 - life - 0.2)
|
||||
col.a = a * 1275
|
||||
render.SetMaterial(Material("stormfox2/effects/lightning_light"))
|
||||
render.DrawBeam(vc, vc2, 24400, 0.3 , 0.7, col)
|
||||
end
|
||||
end
|
||||
for i = #r, 1, -1 do
|
||||
table.remove(lightningStrikes, r[i])
|
||||
end
|
||||
end)
|
||||
end
|
||||
Reference in New Issue
Block a user