add sborka
This commit is contained in:
40
garrysmod/addons/tacrp/lua/autorun/sh_tacrp_load.lua
Normal file
40
garrysmod/addons/tacrp/lua/autorun/sh_tacrp_load.lua
Normal file
@@ -0,0 +1,40 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
TacRP = {}
|
||||
|
||||
local searchdir = "tacrp/"
|
||||
|
||||
local function includeFiles()
|
||||
|
||||
for _, v in pairs(file.Find(searchdir .. "shared/*", "LUA")) do
|
||||
include(searchdir .. "shared/" .. v)
|
||||
AddCSLuaFile(searchdir .. "shared/" .. v)
|
||||
end
|
||||
|
||||
for _, v in pairs(file.Find(searchdir .. "client/*", "LUA")) do
|
||||
AddCSLuaFile(searchdir .. "client/" .. v)
|
||||
if CLIENT then
|
||||
include(searchdir .. "client/" .. v)
|
||||
end
|
||||
end
|
||||
|
||||
for _, v in pairs(file.Find(searchdir .. "client/vgui/*", "LUA")) do
|
||||
AddCSLuaFile(searchdir .. "client/vgui/" .. v)
|
||||
if CLIENT then
|
||||
include(searchdir .. "client/vgui/" .. v)
|
||||
end
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
for _, v in pairs(file.Find(searchdir .. "server/*", "LUA")) do
|
||||
include(searchdir .. "server/" .. v)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
includeFiles()
|
||||
|
||||
searchdir = "tacrp_mod/"
|
||||
|
||||
includeFiles()
|
||||
4
garrysmod/addons/tacrp/lua/autorun/swwf_launchers.lua
Normal file
4
garrysmod/addons/tacrp/lua/autorun/swwf_launchers.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
if CLIENT then
|
||||
killicon.Add( "weapon_sw_fim92", "vgui/hud/weapon_sw_fim92", Color( 255, 255, 255, 255 ) )
|
||||
killicon.Add( "weapon_sw_9k38", "vgui/hud/weapon_sw_9k38", Color( 255, 255, 255, 255 ) )
|
||||
end
|
||||
75
garrysmod/addons/tacrp/lua/effects/tacrp_chargesmoke.lua
Normal file
75
garrysmod/addons/tacrp/lua/effects/tacrp_chargesmoke.lua
Normal file
@@ -0,0 +1,75 @@
|
||||
function EFFECT:Init(data)
|
||||
if CurTime() < 1 then self:Remove() return end
|
||||
|
||||
self.TrailEnt = data:GetEntity()
|
||||
if !IsValid(self.TrailEnt) then self:Remove() return end
|
||||
|
||||
local pos = data:GetOrigin() + Vector(0, 0, 4)
|
||||
local dir = data:GetNormal()
|
||||
|
||||
local emitter = ParticleEmitter(pos)
|
||||
local amt = 24
|
||||
|
||||
for i = 1, amt do
|
||||
local smoke = emitter:Add("particle/smokestack", pos)
|
||||
smoke:SetVelocity(dir * math.Rand(-300, -100) + VectorRand() * 256 + Vector(0, 0, math.Rand(100, 300)))
|
||||
smoke:SetGravity(Vector(0, 0, -300))
|
||||
smoke:SetStartAlpha(75)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(math.Rand(8, 12))
|
||||
smoke:SetEndSize(math.Rand(48, 64))
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-0.2, 0.2))
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetAirResistance(200)
|
||||
smoke:SetCollide(true)
|
||||
smoke:SetBounce(0.2)
|
||||
smoke:SetLighting(true)
|
||||
smoke:SetDieTime(math.Rand(0.9, 1.25))
|
||||
end
|
||||
end
|
||||
|
||||
function EFFECT:Think()
|
||||
if !IsValid(self.TrailEnt) or (self.TrailEnt:IsPlayer() and !self.TrailEnt:Alive()) or !self.TrailEnt:GetNWBool("TacRPChargeState") then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function EFFECT:Render()
|
||||
--if self.TrailEnt:IsOnGround() then
|
||||
local pos = self.TrailEnt:GetPos() + Vector(math.Rand(-8, 8), math.Rand(-8, 8), 4)
|
||||
|
||||
local emitter = ParticleEmitter(pos)
|
||||
|
||||
local smoke = emitter:Add("particle/smokestack", pos)
|
||||
if self.TrailEnt:IsOnGround() then
|
||||
smoke:SetVelocity(self.TrailEnt:GetVelocity() * 0.2 + VectorRand() * 32 + Vector(0, 0, math.Rand(32, 64)))
|
||||
smoke:SetGravity(Vector(0, 0, -128))
|
||||
|
||||
smoke:SetStartSize(math.Rand(8, 12))
|
||||
smoke:SetEndSize(math.Rand(48, 64))
|
||||
smoke:SetDieTime(math.Rand(0.8, 1))
|
||||
else
|
||||
smoke:SetPos(pos + Vector(0, 0, 16))
|
||||
smoke:SetVelocity(VectorRand() * 32)
|
||||
smoke:SetGravity(Vector(0, 0, -128))
|
||||
smoke:SetStartSize(16)
|
||||
smoke:SetEndSize(32)
|
||||
smoke:SetDieTime(math.Rand(0.4, 0.6))
|
||||
end
|
||||
|
||||
smoke:SetStartAlpha(25)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-0.2, 0.2))
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetAirResistance(25)
|
||||
smoke:SetCollide(true)
|
||||
smoke:SetBounce(0.2)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
emitter:Finish()
|
||||
--end
|
||||
end
|
||||
66
garrysmod/addons/tacrp/lua/effects/tacrp_confetti.lua
Normal file
66
garrysmod/addons/tacrp/lua/effects/tacrp_confetti.lua
Normal file
@@ -0,0 +1,66 @@
|
||||
function EFFECT:Init( data )
|
||||
|
||||
local vOffset = data:GetOrigin()
|
||||
local dir = data:GetAngles()
|
||||
local velocity = data:GetMagnitude()
|
||||
local spread = data:GetScale()
|
||||
|
||||
// sound.Play( "tacrp/kids_cheering.mp3", vOffset, 80, 100 )
|
||||
|
||||
local NumParticles = 100
|
||||
|
||||
local emitter = ParticleEmitter( vOffset, true )
|
||||
|
||||
local forward, up, right = dir:Forward(), dir:Up(), dir:Right()
|
||||
|
||||
for i = 0, NumParticles do
|
||||
|
||||
local oDir = Angle(dir)
|
||||
local a = math.Rand(0, 360)
|
||||
local angleRand = Angle(math.sin(a), math.cos(a), 0)
|
||||
angleRand:Mul(spread * math.Rand(0, 45) * 1.4142135623730)
|
||||
|
||||
oDir:RotateAroundAxis(right, angleRand.p)
|
||||
oDir:RotateAroundAxis(up, angleRand.y)
|
||||
oDir:RotateAroundAxis(forward, angleRand.r)
|
||||
|
||||
local particle = emitter:Add( "particles/balloon_bit", vOffset + VectorRand(spread) )
|
||||
if ( particle ) then
|
||||
|
||||
particle:SetVelocity( oDir:Forward() * math.Rand(0.5, 1) * velocity)
|
||||
|
||||
particle:SetLifeTime( 0 )
|
||||
particle:SetDieTime( 10 )
|
||||
|
||||
particle:SetStartAlpha( 255 )
|
||||
particle:SetEndAlpha( 255 )
|
||||
|
||||
local Size = math.Rand( 1.5, 3 )
|
||||
particle:SetStartSize( Size )
|
||||
particle:SetEndSize( 0 )
|
||||
|
||||
particle:SetRoll( math.Rand( 0, 360 ) )
|
||||
particle:SetRollDelta( math.Rand( -2, 2 ) )
|
||||
|
||||
particle:SetAirResistance( 50 )
|
||||
particle:SetGravity( Vector( 0, 0, -75 ) )
|
||||
|
||||
particle:SetColor( math.Rand(50, 255), math.Rand(50, 255), math.Rand(50, 255) )
|
||||
|
||||
particle:SetCollide( true )
|
||||
|
||||
particle:SetAngleVelocity( Angle( math.Rand( -160, 160 ), math.Rand( -160, 160 ), math.Rand( -160, 160 ) ) )
|
||||
|
||||
particle:SetBounce( 0.7 )
|
||||
particle:SetLighting( true )
|
||||
end
|
||||
end
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
function EFFECT:Think()
|
||||
return false
|
||||
end
|
||||
|
||||
function EFFECT:Render()
|
||||
end
|
||||
84
garrysmod/addons/tacrp/lua/effects/tacrp_dashsmoke.lua
Normal file
84
garrysmod/addons/tacrp/lua/effects/tacrp_dashsmoke.lua
Normal file
@@ -0,0 +1,84 @@
|
||||
function EFFECT:Init(data)
|
||||
if CurTime() < 1 then self:Remove() return end
|
||||
|
||||
local pos = data:GetOrigin()
|
||||
local dir = data:GetNormal()
|
||||
|
||||
self.EndTime = CurTime() + 0.25
|
||||
self.TrailEnt = data:GetEntity()
|
||||
if !IsValid(self.TrailEnt) then self:Remove() return end
|
||||
|
||||
local emitter = ParticleEmitter(pos)
|
||||
local amt = 16
|
||||
|
||||
if IsValid(self.TrailEnt) and self.TrailEnt:IsOnGround() then
|
||||
pos = pos + Vector(0, 0, 2)
|
||||
|
||||
for i = 1, amt do
|
||||
local smoke = emitter:Add("particle/smokestack", pos)
|
||||
smoke:SetVelocity(dir * -200 + VectorRand() * 128 + Vector(0, 0, math.Rand(50, 100)))
|
||||
smoke:SetStartAlpha(200)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(8)
|
||||
smoke:SetEndSize(24)
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-0.2, 0.2))
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetAirResistance(150)
|
||||
smoke:SetCollide(true)
|
||||
smoke:SetBounce(0.2)
|
||||
smoke:SetLighting(true)
|
||||
smoke:SetDieTime(0.5)
|
||||
end
|
||||
else
|
||||
for i = 1, amt do
|
||||
local _, a = LocalToWorld(Vector(), Angle((i / amt) * 360, 90, 0), pos, dir:Angle())
|
||||
local smoke = emitter:Add("particle/smokestack", pos)
|
||||
smoke:SetVelocity(dir * -50 + 150 * a:Up())
|
||||
smoke:SetStartAlpha(200)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(8)
|
||||
smoke:SetEndSize(24)
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-0.2, 0.2))
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetAirResistance(150)
|
||||
smoke:SetCollide(true)
|
||||
smoke:SetBounce(0.2)
|
||||
smoke:SetLighting(true)
|
||||
smoke:SetDieTime(0.5)
|
||||
end
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
function EFFECT:Think()
|
||||
if CurTime() > self.EndTime or !IsValid(self.TrailEnt) or (self.TrailEnt:IsPlayer() and !self.TrailEnt:Alive()) then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function EFFECT:Render()
|
||||
local pos = self.TrailEnt:GetPos() + Vector( 0, 0, 1 )
|
||||
local emitter = ParticleEmitter(pos)
|
||||
local d = math.Clamp((self.EndTime - CurTime()) / 0.15, 0, 1) ^ 2
|
||||
|
||||
local smoke = emitter:Add("particle/smokestack", pos)
|
||||
smoke:SetVelocity(VectorRand() * 4)
|
||||
smoke:SetStartAlpha(d * 150)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(4)
|
||||
smoke:SetEndSize(24)
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-0.2, 0.2))
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetAirResistance(15)
|
||||
smoke:SetCollide(false)
|
||||
smoke:SetBounce(0.2)
|
||||
smoke:SetLighting(true)
|
||||
smoke:SetDieTime(0.25)
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
78
garrysmod/addons/tacrp/lua/effects/tacrp_divesmoke.lua
Normal file
78
garrysmod/addons/tacrp/lua/effects/tacrp_divesmoke.lua
Normal file
@@ -0,0 +1,78 @@
|
||||
function EFFECT:Init(data)
|
||||
if CurTime() < 1 then self:Remove() return end
|
||||
|
||||
local pos = data:GetOrigin()
|
||||
local dir = data:GetNormal()
|
||||
|
||||
self.EndTime = CurTime() + 0.2
|
||||
self.TrailEnt = data:GetEntity()
|
||||
if !IsValid(self.TrailEnt) then self:Remove() return end
|
||||
|
||||
local emitter = ParticleEmitter(pos)
|
||||
|
||||
local tr = util.TraceLine({
|
||||
start = pos,
|
||||
endpos = pos - Vector(0, 0, 2048),
|
||||
mask = MASK_SOLID_BRUSHONLY
|
||||
})
|
||||
|
||||
pos = pos - dir * 32
|
||||
local amt = 12 + math.ceil(tr.Fraction / 20)
|
||||
|
||||
for i = 1, amt do
|
||||
local _, a = LocalToWorld(Vector(), Angle((i / amt) * 360, 90, 0), pos, dir:Angle())
|
||||
local smoke = emitter:Add("particle/smokestack", pos)
|
||||
smoke:SetVelocity(dir * -(150 + tr.Fraction * 100) + (300 - tr.Fraction * 100) * a:Up())
|
||||
smoke:SetStartAlpha(20 + tr.Fraction * 50)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(8)
|
||||
smoke:SetEndSize(24 + tr.Fraction * 16)
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-0.2, 0.2))
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetAirResistance(50)
|
||||
smoke:SetCollide(false)
|
||||
smoke:SetBounce(0.2)
|
||||
smoke:SetLighting(false)
|
||||
smoke:SetDieTime(0.15 + tr.Fraction * 0.6)
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
function EFFECT:Think()
|
||||
if CurTime() > self.EndTime or !IsValid(self.TrailEnt) or (self.TrailEnt:IsPlayer() and !self.TrailEnt:Alive()) then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function EFFECT:Render()
|
||||
if self.TrailEnt:IsOnGround() then
|
||||
local pos = self.TrailEnt:GetPos() + Vector(math.Rand(-8, 8), math.Rand(-8, 8), 4)
|
||||
local dir = self.TrailEnt:GetVelocity():GetNormalized()
|
||||
local vel = self.TrailEnt:GetVelocity():Length()
|
||||
|
||||
local emitter = ParticleEmitter(pos)
|
||||
|
||||
if engine.TickCount() % 2 == 0 then
|
||||
local smoke = emitter:Add("particle/smokestack", pos)
|
||||
smoke:SetVelocity(VectorRand() * (50 + math.min(vel, 500) * 0.25) + dir * math.min(vel, 500) + Vector(0, 0, 200 - math.min(vel, 200)))
|
||||
smoke:SetGravity(Vector(0, 0, -400))
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(4)
|
||||
smoke:SetEndSize(32)
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-0.2, 0.2))
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetAirResistance(25)
|
||||
smoke:SetCollide(true)
|
||||
smoke:SetBounce(0.2)
|
||||
smoke:SetLighting(true)
|
||||
smoke:SetDieTime(math.Rand(0.75, 1))
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
92
garrysmod/addons/tacrp/lua/effects/tacrp_flare_explode.lua
Normal file
92
garrysmod/addons/tacrp/lua/effects/tacrp_flare_explode.lua
Normal file
@@ -0,0 +1,92 @@
|
||||
EFFECT.Model = "models/Items/AR2_Grenade.mdl"
|
||||
|
||||
function EFFECT:Init(data)
|
||||
self:SetModel(self.Model)
|
||||
local emitter = ParticleEmitter(data:GetOrigin())
|
||||
if not IsValid(emitter) then return end
|
||||
for i = 1, 5 do
|
||||
local smoke = emitter:Add("particle/smokestack", data:GetOrigin())
|
||||
smoke:SetVelocity(VectorRand() * 100)
|
||||
smoke:SetGravity(Vector(math.Rand(-5, 5), math.Rand(-5, 5), 70))
|
||||
smoke:SetDieTime(math.Rand(5, 7))
|
||||
smoke:SetStartAlpha(40)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(math.Rand(20, 40))
|
||||
smoke:SetEndSize(60)
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-0.5, 0.5))
|
||||
smoke:SetColor(175, 175, 175)
|
||||
smoke:SetAirResistance(120)
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetLighting(false)
|
||||
smoke:SetBounce(0.5)
|
||||
smoke:SetCollide(true)
|
||||
end
|
||||
|
||||
for i = 1, 5 do
|
||||
local smoke = emitter:Add("particle/smokestack", data:GetOrigin())
|
||||
smoke:SetVelocity(VectorRand() * 800)
|
||||
smoke:SetGravity(Vector(math.Rand(-25, 25), math.Rand(-25, 25), -500))
|
||||
smoke:SetDieTime(math.Rand(0.6, 1))
|
||||
smoke:SetStartAlpha(100)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(80)
|
||||
smoke:SetEndSize(250)
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-0.5, 0.5))
|
||||
smoke:SetColor(100, 100, 100)
|
||||
smoke:SetAirResistance(300)
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetLighting(false)
|
||||
smoke:SetBounce(0.5)
|
||||
smoke:SetCollide(true)
|
||||
end
|
||||
|
||||
for i = 1, 5 do
|
||||
local fire = emitter:Add("effects/fire_cloud" .. math.random(1, 2), data:GetOrigin())
|
||||
fire:SetVelocity(VectorRand() * 1200 - Vector(0, 0, 100))
|
||||
fire:SetGravity(Vector(0, 0, 0))
|
||||
fire:SetDieTime(math.Rand(0.1, 0.25))
|
||||
fire:SetStartAlpha(150)
|
||||
fire:SetEndAlpha(0)
|
||||
fire:SetStartSize(math.Rand(15, 30))
|
||||
fire:SetEndSize(math.Rand(120, 160))
|
||||
fire:SetRoll(math.Rand(-180, 180))
|
||||
fire:SetRollDelta(math.Rand(-0.5, 0.5))
|
||||
fire:SetColor(200, 150, 50)
|
||||
fire:SetAirResistance(300)
|
||||
fire:SetPos(self:GetPos())
|
||||
fire:SetLighting(false)
|
||||
fire:SetBounce(0.5)
|
||||
fire:SetCollide(false)
|
||||
end
|
||||
|
||||
for i = 1, math.random(3, 5) do
|
||||
local fire = emitter:Add("sprites/glow04_noz", data:GetOrigin())
|
||||
fire:SetVelocity(VectorRand() * 100 + Vector(0, 0, math.Rand(100, 300)))
|
||||
fire:SetGravity(Vector(0, 0, -400))
|
||||
fire:SetDieTime(math.Rand(2, 3))
|
||||
fire:SetStartAlpha(200)
|
||||
fire:SetEndAlpha(0)
|
||||
fire:SetStartSize(math.Rand(3, 5))
|
||||
fire:SetEndSize(math.Rand(10, 20))
|
||||
fire:SetRoll(math.Rand(-180, 180))
|
||||
fire:SetRollDelta(math.Rand(-0.5, 0.5))
|
||||
fire:SetColor(255, 140, 80)
|
||||
fire:SetAirResistance(2)
|
||||
fire:SetPos(self:GetPos())
|
||||
fire:SetLighting(false)
|
||||
fire:SetBounce(0.2)
|
||||
fire:SetCollide(true)
|
||||
end
|
||||
emitter:Finish()
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function EFFECT:Think()
|
||||
return false
|
||||
end
|
||||
|
||||
function EFFECT:Render()
|
||||
return false
|
||||
end
|
||||
77
garrysmod/addons/tacrp/lua/effects/tacrp_flashexplosion.lua
Normal file
77
garrysmod/addons/tacrp/lua/effects/tacrp_flashexplosion.lua
Normal file
@@ -0,0 +1,77 @@
|
||||
local images_smoke = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
|
||||
local function TableRandomChoice(tbl)
|
||||
return tbl[math.random(#tbl)]
|
||||
end
|
||||
|
||||
function EFFECT:Init(data)
|
||||
self.Origin = data:GetOrigin()
|
||||
|
||||
util.Decal("FadingScorch", self.Origin, self.Origin - Vector(0, 0, 16))
|
||||
|
||||
local emitter = ParticleEmitter( self.Origin + Vector( 0, 0, 16 ) )
|
||||
|
||||
for i = 0, 5 do
|
||||
local particle = emitter:Add( TableRandomChoice(images_smoke) , self.Origin )
|
||||
local scol = math.Rand( 200, 225 )
|
||||
|
||||
particle:SetVelocity( 250 * VectorRand() )
|
||||
particle:SetDieTime( math.Rand(1.5, 5) )
|
||||
particle:SetStartAlpha( 50 )
|
||||
particle:SetEndAlpha( 0 )
|
||||
particle:SetStartSize( math.Rand(100,200) )
|
||||
particle:SetEndSize( math.Rand(300,400) )
|
||||
particle:SetRoll( math.Rand(0,360) )
|
||||
particle:SetRollDelta( math.Rand(-1,1) )
|
||||
particle:SetColor( scol,scol,scol )
|
||||
particle:SetAirResistance( 100 )
|
||||
particle:SetGravity( Vector( math.Rand(-30,30) ,math.Rand(-30,30),math.Rand(10,40)) )
|
||||
particle:SetLighting( true )
|
||||
particle:SetCollide( true )
|
||||
particle:SetBounce( 0.5 )
|
||||
end
|
||||
|
||||
local particle = emitter:Add( "sprites/heatwave", self.Origin )
|
||||
particle:SetAirResistance( 0 )
|
||||
particle:SetDieTime( 1.5 )
|
||||
particle:SetStartAlpha( 255 )
|
||||
particle:SetEndAlpha( 255 )
|
||||
particle:SetStartSize( 250 )
|
||||
particle:SetEndSize( 0 )
|
||||
particle:SetRoll( math.Rand(180,480) )
|
||||
particle:SetRollDelta( math.Rand(-5,5) )
|
||||
particle:SetColor( 255, 255, 255 )
|
||||
|
||||
local fire = emitter:Add( "particle/fire", self.Origin )
|
||||
fire:SetAirResistance( 0 )
|
||||
fire:SetDieTime( 0.1 )
|
||||
fire:SetStartAlpha( 255 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetEndSize( 0 )
|
||||
fire:SetStartSize( data:GetRadius() )
|
||||
fire:SetRoll( math.Rand(180,480) )
|
||||
fire:SetRollDelta( math.Rand(-1,1) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
|
||||
local light = DynamicLight(self:EntIndex())
|
||||
if (light) then
|
||||
light.Pos = self.Origin
|
||||
light.r = 255
|
||||
light.g = 255
|
||||
light.b = 255
|
||||
light.Brightness = 10 * data:GetScale()
|
||||
light.Decay = 2500
|
||||
light.Size = data:GetRadius()
|
||||
light.DieTime = CurTime() + 0.1
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
|
||||
end
|
||||
|
||||
function EFFECT:Think()
|
||||
return false
|
||||
end
|
||||
|
||||
function EFFECT:Render()
|
||||
end
|
||||
36
garrysmod/addons/tacrp/lua/effects/tacrp_jumpsmoke.lua
Normal file
36
garrysmod/addons/tacrp/lua/effects/tacrp_jumpsmoke.lua
Normal file
@@ -0,0 +1,36 @@
|
||||
function EFFECT:Init(data)
|
||||
local pos = data:GetOrigin()
|
||||
local dir = data:GetNormal()
|
||||
self.TrailEnt = data:GetEntity()
|
||||
if !IsValid(self.TrailEnt) then self:Remove() return end
|
||||
|
||||
local emitter = ParticleEmitter(pos)
|
||||
local amt = 16
|
||||
|
||||
for i = 1, amt do
|
||||
local _, a = LocalToWorld(Vector(0, 0, 2), Angle((i / amt) * 360, 90, 0), pos, dir:Angle())
|
||||
local smoke = emitter:Add("particle/smokestack", pos)
|
||||
smoke:SetVelocity(150 * a:Up())
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(8)
|
||||
smoke:SetEndSize(24)
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-0.2, 0.2))
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetAirResistance(150)
|
||||
smoke:SetCollide(true)
|
||||
smoke:SetBounce(0.2)
|
||||
smoke:SetLighting(true)
|
||||
smoke:SetDieTime(0.4)
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
function EFFECT:Think()
|
||||
return true
|
||||
end
|
||||
|
||||
function EFFECT:Render()
|
||||
end
|
||||
97
garrysmod/addons/tacrp/lua/effects/tacrp_leapsmoke.lua
Normal file
97
garrysmod/addons/tacrp/lua/effects/tacrp_leapsmoke.lua
Normal file
@@ -0,0 +1,97 @@
|
||||
function EFFECT:Init(data)
|
||||
local pos = data:GetOrigin()
|
||||
local dir = data:GetNormal()
|
||||
|
||||
local emitter = ParticleEmitter(pos)
|
||||
local amt = 24
|
||||
|
||||
if IsValid(data:GetEntity()) and data:GetEntity():IsOnGround() and data:GetEntity():Crouching() then
|
||||
pos = pos + Vector(0, 0, 4)
|
||||
for i = 1, amt / 2 do
|
||||
local _, a = LocalToWorld(Vector(), Angle((i / amt) * 360, 90, 0), pos, dir:Angle())
|
||||
local smoke = emitter:Add("particle/smokestack", pos)
|
||||
smoke:SetVelocity(dir * -50 + 300 * a:Up() + VectorRand() * 128)
|
||||
smoke:SetGravity(Vector(0, 0, -200))
|
||||
smoke:SetStartAlpha(200)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(8)
|
||||
smoke:SetEndSize(64)
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-0.2, 0.2))
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetAirResistance(150)
|
||||
smoke:SetCollide(true)
|
||||
smoke:SetBounce(0.2)
|
||||
smoke:SetLighting(true)
|
||||
smoke:SetDieTime(1)
|
||||
end
|
||||
|
||||
for i = 1, amt / 2 do
|
||||
local smoke = emitter:Add("particle/smokestack", pos)
|
||||
smoke:SetVelocity(dir * math.Rand(400, 800) + VectorRand() * 128)
|
||||
smoke:SetStartAlpha(200)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(8)
|
||||
smoke:SetEndSize(32)
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-0.2, 0.2))
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetAirResistance(150)
|
||||
smoke:SetCollide(true)
|
||||
smoke:SetBounce(0.2)
|
||||
smoke:SetLighting(true)
|
||||
smoke:SetDieTime(0.75)
|
||||
end
|
||||
elseif IsValid(data:GetEntity()) and data:GetEntity():IsOnGround() then
|
||||
pos = pos + Vector(0, 0, 2)
|
||||
|
||||
local dir2 = Vector(dir)
|
||||
dir2.z = 0
|
||||
dir2:Normalize()
|
||||
|
||||
for i = 1, amt do
|
||||
local smoke = emitter:Add("particle/smokestack", pos)
|
||||
smoke:SetVelocity(dir2 * math.Rand(-600, -200) + VectorRand() * 128 + Vector(0, 0, math.Rand(250, 400)))
|
||||
smoke:SetGravity(Vector(0, 0, -300))
|
||||
smoke:SetStartAlpha(150)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(8)
|
||||
smoke:SetEndSize(32)
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-0.2, 0.2))
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetAirResistance(200)
|
||||
smoke:SetCollide(true)
|
||||
smoke:SetBounce(0.2)
|
||||
smoke:SetLighting(true)
|
||||
smoke:SetDieTime(1)
|
||||
end
|
||||
else
|
||||
for i = 1, amt do
|
||||
local _, a = LocalToWorld(Vector(), Angle((i / amt) * 360, 90, 0), pos, dir:Angle())
|
||||
local smoke = emitter:Add("particle/smokestack", pos)
|
||||
smoke:SetVelocity(dir * -50 + 150 * a:Up() + VectorRand() * 8)
|
||||
smoke:SetStartAlpha(200)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(8)
|
||||
smoke:SetEndSize(24)
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-0.2, 0.2))
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetAirResistance(150)
|
||||
smoke:SetCollide(true)
|
||||
smoke:SetBounce(0.2)
|
||||
smoke:SetLighting(true)
|
||||
smoke:SetDieTime(0.75)
|
||||
end
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
function EFFECT:Think()
|
||||
return false
|
||||
end
|
||||
|
||||
function EFFECT:Render()
|
||||
end
|
||||
113
garrysmod/addons/tacrp/lua/effects/tacrp_m202_explode.lua
Normal file
113
garrysmod/addons/tacrp/lua/effects/tacrp_m202_explode.lua
Normal file
@@ -0,0 +1,113 @@
|
||||
EFFECT.Model = "models/Items/AR2_Grenade.mdl"
|
||||
|
||||
function EFFECT:Init(data)
|
||||
self:SetModel(self.Model)
|
||||
local emitter = ParticleEmitter(data:GetOrigin())
|
||||
if not IsValid(emitter) then return end
|
||||
for i = 1, 10 do
|
||||
local smoke = emitter:Add("particle/smokestack", data:GetOrigin())
|
||||
smoke:SetVelocity(VectorRand() * 100)
|
||||
smoke:SetGravity(Vector(math.Rand(-5, 5), math.Rand(-5, 5), 70))
|
||||
smoke:SetDieTime(math.Rand(5, 7))
|
||||
smoke:SetStartAlpha(80)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(math.Rand(20, 40))
|
||||
smoke:SetEndSize(80)
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-0.5, 0.5))
|
||||
smoke:SetColor(175, 175, 175)
|
||||
smoke:SetAirResistance(120)
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetLighting(false)
|
||||
smoke:SetBounce(0.5)
|
||||
smoke:SetCollide(true)
|
||||
end
|
||||
|
||||
for i = 1, 10 do
|
||||
local smoke = emitter:Add("particle/smokestack", data:GetOrigin())
|
||||
smoke:SetVelocity(VectorRand() * 800)
|
||||
smoke:SetGravity(Vector(math.Rand(-25, 25), math.Rand(-25, 25), -500))
|
||||
smoke:SetDieTime(math.Rand(0.6, 1))
|
||||
smoke:SetStartAlpha(120)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(80)
|
||||
smoke:SetEndSize(250)
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-0.5, 0.5))
|
||||
smoke:SetColor(100, 100, 100)
|
||||
smoke:SetAirResistance(300)
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetLighting(false)
|
||||
smoke:SetBounce(0.5)
|
||||
smoke:SetCollide(true)
|
||||
end
|
||||
|
||||
for i = 1, 10 do
|
||||
local fire = emitter:Add("effects/fire_cloud" .. math.random(1, 2), data:GetOrigin())
|
||||
fire:SetVelocity(VectorRand() * 1200 - Vector(0, 0, 100))
|
||||
fire:SetGravity(Vector(0, 0, 0))
|
||||
fire:SetDieTime(math.Rand(0.1, 0.25))
|
||||
fire:SetStartAlpha(255)
|
||||
fire:SetEndAlpha(0)
|
||||
fire:SetStartSize(math.Rand(15, 30))
|
||||
fire:SetEndSize(math.Rand(180, 200))
|
||||
fire:SetRoll(math.Rand(-180, 180))
|
||||
fire:SetRollDelta(math.Rand(-0.5, 0.5))
|
||||
fire:SetColor(200, 200, 200)
|
||||
fire:SetAirResistance(300)
|
||||
fire:SetPos(self:GetPos())
|
||||
fire:SetLighting(false)
|
||||
fire:SetBounce(0.5)
|
||||
fire:SetCollide(false)
|
||||
end
|
||||
|
||||
for i = 1, 20 do
|
||||
local fire = emitter:Add("effects/fire_embers" .. math.random(1, 3), data:GetOrigin())
|
||||
local v = VectorRand() * 1500
|
||||
v.z = v.z * 0.25
|
||||
fire:SetVelocity(v)
|
||||
fire:SetGravity(Vector(0, 0, -750))
|
||||
fire:SetDieTime(math.Rand(1.2, 3))
|
||||
fire:SetStartAlpha(200)
|
||||
fire:SetEndAlpha(0)
|
||||
fire:SetStartSize(math.Rand(30, 50))
|
||||
fire:SetEndSize(math.Rand(40, 70))
|
||||
fire:SetRoll(math.Rand(-180, 180))
|
||||
fire:SetRollDelta(math.Rand(-0.5, 0.5))
|
||||
fire:SetColor(200, 200, 200)
|
||||
fire:SetAirResistance(200)
|
||||
fire:SetPos(self:GetPos())
|
||||
fire:SetLighting(false)
|
||||
fire:SetBounce(0.5)
|
||||
fire:SetCollide(true)
|
||||
end
|
||||
|
||||
for i = 1, math.random(6, 9) do
|
||||
local fire = emitter:Add("sprites/glow04_noz", data:GetOrigin())
|
||||
fire:SetVelocity(VectorRand() * 100 + Vector(0, 0, math.Rand(300, 800)))
|
||||
fire:SetGravity(Vector(0, 0, -400))
|
||||
fire:SetDieTime(math.Rand(2, 3))
|
||||
fire:SetStartAlpha(200)
|
||||
fire:SetEndAlpha(0)
|
||||
fire:SetStartSize(math.Rand(3, 5))
|
||||
fire:SetEndSize(math.Rand(10, 20))
|
||||
fire:SetRoll(math.Rand(-180, 180))
|
||||
fire:SetRollDelta(math.Rand(-0.5, 0.5))
|
||||
fire:SetColor(255, 180, 100)
|
||||
fire:SetAirResistance(2)
|
||||
fire:SetPos(self:GetPos())
|
||||
fire:SetLighting(false)
|
||||
fire:SetBounce(0.2)
|
||||
fire:SetCollide(true)
|
||||
end
|
||||
emitter:Finish()
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function EFFECT:Think()
|
||||
return false
|
||||
end
|
||||
|
||||
function EFFECT:Render()
|
||||
return false
|
||||
end
|
||||
65
garrysmod/addons/tacrp/lua/effects/tacrp_muzzleeffect.lua
Normal file
65
garrysmod/addons/tacrp/lua/effects/tacrp_muzzleeffect.lua
Normal file
@@ -0,0 +1,65 @@
|
||||
function EFFECT:Init(data)
|
||||
local wpn = data:GetEntity()
|
||||
|
||||
if !IsValid(wpn) then self:Remove() return end
|
||||
|
||||
if wpn:GetOwner() == LocalPlayer() and wpn:GetValue("ScopeHideWeapon") and wpn:IsInScope() then
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
local muzzle = TacRP.MuzzleEffects[data:GetFlags() or 1] or "muzzleflash_pistol"
|
||||
if wpn.GetValue then
|
||||
muzzle = wpn:GetValue("MuzzleEffect")
|
||||
end
|
||||
|
||||
local att = data:GetAttachment() or 1
|
||||
|
||||
local wm = false
|
||||
|
||||
if (LocalPlayer():ShouldDrawLocalPlayer() or wpn.Owner != LocalPlayer()) then
|
||||
wm = true
|
||||
att = data:GetHitBox()
|
||||
end
|
||||
|
||||
local parent = wpn
|
||||
|
||||
if !wm then
|
||||
parent = LocalPlayer():GetViewModel()
|
||||
end
|
||||
|
||||
if wpn.GetMuzzleDevice then
|
||||
parent = wpn:GetMuzzleDevice(wm)
|
||||
else
|
||||
parent = self
|
||||
end
|
||||
|
||||
-- if !IsValid(parent) then return end
|
||||
|
||||
if muzzle then
|
||||
if !istable(muzzle) then
|
||||
muzzle = {muzzle}
|
||||
end
|
||||
|
||||
for _, muzzleeffect in ipairs(muzzle) do
|
||||
local pcf = CreateParticleSystem(muz or parent, muzzleeffect, PATTACH_POINT_FOLLOW, att)
|
||||
|
||||
if IsValid(pcf) then
|
||||
pcf:StartEmission()
|
||||
|
||||
if (muz or parent) != vm and !wm then
|
||||
pcf:SetShouldDraw(false)
|
||||
table.insert(wpn.MuzzPCFs, pcf)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function EFFECT:Think()
|
||||
return false
|
||||
end
|
||||
|
||||
function EFFECT:Render()
|
||||
return false
|
||||
end
|
||||
130
garrysmod/addons/tacrp/lua/effects/tacrp_nukeexplosion.lua
Normal file
130
garrysmod/addons/tacrp/lua/effects/tacrp_nukeexplosion.lua
Normal file
@@ -0,0 +1,130 @@
|
||||
local images_smoke = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
|
||||
local function TableRandomChoice(tbl)
|
||||
return tbl[math.random(#tbl)]
|
||||
end
|
||||
|
||||
local effecttime = 30
|
||||
|
||||
function EFFECT:Init(data)
|
||||
self.Origin = data:GetOrigin()
|
||||
|
||||
self.SpawnTime = CurTime()
|
||||
|
||||
util.Decal("FadingScorch", self.Origin, self.Origin - Vector(0, 0, 16))
|
||||
|
||||
local emitter = ParticleEmitter( self.Origin + Vector( 0, 0, 16 ) )
|
||||
|
||||
// smoke cloud
|
||||
|
||||
for i = 1,25 do
|
||||
local particle = emitter:Add( TableRandomChoice(images_smoke) , self.Origin )
|
||||
local scol = math.Rand( 200, 225 )
|
||||
|
||||
particle:SetVelocity( 250 * VectorRand() )
|
||||
particle:SetDieTime( math.Rand(0.9, 1.1) * effecttime )
|
||||
particle:SetStartAlpha( 255 )
|
||||
particle:SetEndAlpha( 0 )
|
||||
particle:SetStartSize( math.Rand(300,400) )
|
||||
particle:SetEndSize( math.Rand(2000,2500) )
|
||||
particle:SetRoll( math.Rand(0,360) )
|
||||
particle:SetRollDelta( math.Rand(-1,1) )
|
||||
particle:SetColor( scol,scol,scol )
|
||||
particle:SetAirResistance( 50 )
|
||||
particle:SetGravity( Vector( math.Rand(-250, 250), math.Rand(-250, 250), 500) )
|
||||
particle:SetLighting( false )
|
||||
end
|
||||
|
||||
// stack
|
||||
|
||||
for i = 1,25 do
|
||||
local particle = emitter:Add( TableRandomChoice(images_smoke) , self.Origin )
|
||||
local scol = math.Rand( 200, 225 )
|
||||
|
||||
particle:SetVelocity( 250 * VectorRand() )
|
||||
particle:SetDieTime( math.Rand(0.9, 1.1) * effecttime )
|
||||
particle:SetStartAlpha( 255 )
|
||||
particle:SetEndAlpha( 0 )
|
||||
particle:SetStartSize( math.Rand(300,400) )
|
||||
particle:SetEndSize( math.Rand(1000,1500) )
|
||||
particle:SetRoll( math.Rand(0,360) )
|
||||
particle:SetRollDelta( math.Rand(-1,1) )
|
||||
particle:SetColor( scol,scol,scol )
|
||||
particle:SetAirResistance( 50 )
|
||||
particle:SetGravity( Vector( math.Rand(-10, 10), math.Rand(-10, 10), math.Rand(0, 500)) )
|
||||
particle:SetLighting( false )
|
||||
end
|
||||
|
||||
// wave
|
||||
|
||||
local amt = 50
|
||||
|
||||
for i = 1, amt do
|
||||
local particle = emitter:Add( TableRandomChoice(images_smoke) , self.Origin )
|
||||
local scol = math.Rand( 200, 225 )
|
||||
|
||||
particle:SetVelocity( VectorRand() * 8 + (Angle(0, i * (360 / amt), 0):Forward() * 750) )
|
||||
particle:SetDieTime( math.Rand(0.9, 1.1) * effecttime )
|
||||
particle:SetStartAlpha( 255 )
|
||||
particle:SetEndAlpha( 0 )
|
||||
particle:SetStartSize( math.Rand(300,400) )
|
||||
particle:SetEndSize( math.Rand(1000,1500) )
|
||||
particle:SetRoll( math.Rand(0,360) )
|
||||
particle:SetRollDelta( math.Rand(-1,1) )
|
||||
particle:SetColor( scol,scol,scol )
|
||||
particle:SetAirResistance( 5 )
|
||||
particle:SetLighting( false )
|
||||
particle:SetCollide( false )
|
||||
end
|
||||
|
||||
local particle = emitter:Add( "sprites/heatwave", self.Origin )
|
||||
particle:SetAirResistance( 0 )
|
||||
particle:SetDieTime( effecttime )
|
||||
particle:SetStartAlpha( 255 )
|
||||
particle:SetEndAlpha( 255 )
|
||||
particle:SetStartSize( 5000 )
|
||||
particle:SetEndSize( 0 )
|
||||
particle:SetRoll( math.Rand(180,480) )
|
||||
particle:SetRollDelta( math.Rand(-5,5) )
|
||||
particle:SetColor( 255, 255, 255 )
|
||||
|
||||
emitter:Finish()
|
||||
|
||||
local light = DynamicLight(self:EntIndex())
|
||||
if (light) then
|
||||
light.Pos = self.Origin
|
||||
light.r = 255
|
||||
light.g = 255
|
||||
light.b = 255
|
||||
light.Brightness = 9
|
||||
light.Decay = 2500
|
||||
light.Size = 2048
|
||||
light.DieTime = CurTime() + 10
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function EFFECT:Think()
|
||||
if (self.SpawnTime + effecttime) < CurTime() then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local glaremat = Material("effects/ar2_altfire1b")
|
||||
|
||||
function EFFECT:Render()
|
||||
local d = (CurTime() - self.SpawnTime) / 15
|
||||
|
||||
d = 1 - d
|
||||
|
||||
d = math.Clamp(d, 0, 1)
|
||||
|
||||
cam.IgnoreZ(true)
|
||||
|
||||
render.SetMaterial(glaremat)
|
||||
render.DrawSprite(self.Origin, 15000 * d, 15000 * d, Color(255, 255, 255))
|
||||
|
||||
cam.IgnoreZ(false)
|
||||
end
|
||||
170
garrysmod/addons/tacrp/lua/effects/tacrp_shelleffect.lua
Normal file
170
garrysmod/addons/tacrp/lua/effects/tacrp_shelleffect.lua
Normal file
@@ -0,0 +1,170 @@
|
||||
EFFECT.Type = 1
|
||||
|
||||
EFFECT.Pitch = 100
|
||||
|
||||
EFFECT.Model = "models/shells/shell_57.mdl"
|
||||
|
||||
EFFECT.AlreadyPlayedSound = false
|
||||
EFFECT.ShellTime = 0.5
|
||||
EFFECT.SpawnTime = 0
|
||||
|
||||
EFFECT.VMContext = true
|
||||
|
||||
function EFFECT:Init(data)
|
||||
|
||||
local att = data:GetAttachment()
|
||||
local ent = data:GetEntity()
|
||||
|
||||
self.Type = data:GetFlags() or self.Type
|
||||
|
||||
local typetbl = TacRP.ShellTypes[self.Type]
|
||||
|
||||
if !IsValid(ent) then self:Remove() return end
|
||||
if !IsValid(ent:GetOwner()) then self:Remove() return end
|
||||
|
||||
local origin, ang, dir
|
||||
|
||||
if ent:GetOwner() == LocalPlayer() and ent:GetValue("ScopeHideWeapon") and ent:IsInScope() then
|
||||
origin = EyePos()
|
||||
+ EyeAngles():Right() * ent.PassivePos.x
|
||||
+ EyeAngles():Forward() * ent.PassivePos.y
|
||||
+ EyeAngles():Up() * ent.PassivePos.z
|
||||
ang = EyeAngles()
|
||||
dir = ang:Right() -- not exactly correct but we can't rely on weapon model here
|
||||
else
|
||||
if LocalPlayer():ShouldDrawLocalPlayer() or ent:GetOwner() != LocalPlayer() then
|
||||
mdl = ent
|
||||
att = data:GetHitBox()
|
||||
self.VMContext = false
|
||||
else
|
||||
mdl = LocalPlayer():GetViewModel()
|
||||
table.insert(ent.ActiveEffects, self)
|
||||
end
|
||||
|
||||
if !IsValid(ent) then self:Remove() return end
|
||||
if !mdl or !IsValid(mdl) then self:Remove() return end
|
||||
if !mdl:GetAttachment(att) then self:Remove() return end
|
||||
if !typetbl then return end
|
||||
|
||||
origin = mdl:GetAttachment(att).Pos
|
||||
ang = mdl:GetAttachment(att).Ang
|
||||
|
||||
-- ang:RotateAroundAxis(ang:Up(), -90)
|
||||
|
||||
-- ang:RotateAroundAxis(ang:Right(), (ent.ShellRotateAngle or Angle(0, 0, 0))[1])
|
||||
-- ang:RotateAroundAxis(ang:Up(), (ent.ShellRotateAngle or Angle(0, 0, 0))[2])
|
||||
-- ang:RotateAroundAxis(ang:Forward(), (ent.ShellRotateAngle or Angle(0, 0, 0))[3])
|
||||
|
||||
dir = ang:Forward()
|
||||
|
||||
ang:RotateAroundAxis(ang:Forward(), 0)
|
||||
ang:RotateAroundAxis(ang:Up(), 0)
|
||||
end
|
||||
|
||||
self:SetPos(origin)
|
||||
self:SetModel(typetbl.Model)
|
||||
self:SetModelScale(data:GetScale(), 0)
|
||||
self:DrawShadow(true)
|
||||
self:SetAngles(ang)
|
||||
|
||||
self:SetNoDraw(true)
|
||||
|
||||
self.Sounds = typetbl.Sounds
|
||||
|
||||
local pb_vert = 2
|
||||
local pb_hor = 0.25
|
||||
|
||||
local mag = 150
|
||||
|
||||
self:PhysicsInitBox(Vector(-pb_vert,-pb_hor,-pb_hor), Vector(pb_vert,pb_hor,pb_hor))
|
||||
|
||||
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
|
||||
local plyvel = Vector(0, 0, 0)
|
||||
|
||||
if IsValid(ent.Owner) then
|
||||
plyvel = ent.Owner:GetAbsVelocity()
|
||||
end
|
||||
|
||||
phys:Wake()
|
||||
phys:SetDamping(0, 0)
|
||||
phys:SetMass(1)
|
||||
phys:SetMaterial("gmod_silent")
|
||||
|
||||
phys:SetVelocity((dir * mag * math.Rand(1, 2)) + plyvel)
|
||||
|
||||
phys:AddAngleVelocity(VectorRand() * 100)
|
||||
phys:AddAngleVelocity(ang:Up() * -2500 * math.Rand(0.75, 1.25))
|
||||
|
||||
local smoke = true
|
||||
|
||||
if smoke and IsValid(mdl) then
|
||||
local pcf = CreateParticleSystem(mdl, "port_smoke", PATTACH_POINT_FOLLOW, att)
|
||||
|
||||
if IsValid(pcf) then
|
||||
pcf:StartEmission()
|
||||
end
|
||||
|
||||
local smkpcf = CreateParticleSystem(self, "shellsmoke", PATTACH_ABSORIGIN_FOLLOW, 0)
|
||||
|
||||
if IsValid(smkpcf) then
|
||||
smkpcf:StartEmission()
|
||||
end
|
||||
|
||||
if self.VMContext then
|
||||
table.insert(ent.PCFs, pcf)
|
||||
table.insert(ent.PCFs, smkpcf)
|
||||
|
||||
pcf:SetShouldDraw(false)
|
||||
smkpcf:SetShouldDraw(false)
|
||||
end
|
||||
end
|
||||
|
||||
self.SpawnTime = CurTime()
|
||||
end
|
||||
|
||||
function EFFECT:PhysicsCollide(colData)
|
||||
if self.AlreadyPlayedSound then return end
|
||||
local phys = self:GetPhysicsObject()
|
||||
phys:SetVelocityInstantaneous(colData.HitNormal * -150)
|
||||
|
||||
sound.Play(self.Sounds[math.random(#self.Sounds)], self:GetPos(), 65, 100, 1)
|
||||
self:StopSound("Default.ImpactHard")
|
||||
self.VMContext = false
|
||||
self:SetNoDraw(false)
|
||||
|
||||
self.AlreadyPlayedSound = true
|
||||
end
|
||||
|
||||
function EFFECT:Think()
|
||||
if self:GetVelocity():Length() > 0 then self.SpawnTime = CurTime() end
|
||||
self:StopSound("Default.ScrapeRough")
|
||||
|
||||
if (self.SpawnTime + self.ShellTime) <= CurTime() then
|
||||
if !IsValid(self) then return end
|
||||
self:SetRenderFX( kRenderFxFadeFast )
|
||||
if (self.SpawnTime + self.ShellTime + 0.25) <= CurTime() then
|
||||
if !IsValid(self:GetPhysicsObject()) then return end
|
||||
self:GetPhysicsObject():EnableMotion(false)
|
||||
if (self.SpawnTime + self.ShellTime + 0.5) <= CurTime() then
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function EFFECT:Render()
|
||||
if !IsValid(self) then return end
|
||||
|
||||
self:DrawModel()
|
||||
end
|
||||
|
||||
function EFFECT:DrawTranslucent()
|
||||
if !IsValid(self) then return end
|
||||
|
||||
self:DrawModel()
|
||||
end
|
||||
101
garrysmod/addons/tacrp/lua/effects/tacrp_tracer.lua
Normal file
101
garrysmod/addons/tacrp/lua/effects/tacrp_tracer.lua
Normal file
@@ -0,0 +1,101 @@
|
||||
EFFECT.StartPos = Vector(0, 0, 0)
|
||||
EFFECT.EndPos = Vector(0, 0, 0)
|
||||
EFFECT.StartTime = 0
|
||||
EFFECT.LifeTime = 0.15
|
||||
EFFECT.LifeTime2 = 0.15
|
||||
EFFECT.DieTime = 0
|
||||
EFFECT.Color = Color(255, 255, 255)
|
||||
EFFECT.Speed = 5000
|
||||
|
||||
local head = Material("particle/fire")
|
||||
local tracer = Material("tacrp/tracer")
|
||||
|
||||
function EFFECT:Init(data)
|
||||
|
||||
local hit = data:GetOrigin()
|
||||
local wep = data:GetEntity()
|
||||
|
||||
if !IsValid(wep) then return end
|
||||
local tacrp = wep.ArcticTacRP and wep.GetValue
|
||||
|
||||
local start = data:GetStart()
|
||||
if wep:GetOwner() == LocalPlayer() and tacrp and wep:GetValue("ScopeHideWeapon") and wep:IsInScope() then
|
||||
start = EyePos()
|
||||
+ EyeAngles():Right() * wep.PassivePos.x
|
||||
+ EyeAngles():Forward() * wep.PassivePos.y
|
||||
+ EyeAngles():Up() * wep.PassivePos.z
|
||||
elseif wep.GetTracerOrigin then
|
||||
start = wep:GetTracerOrigin()
|
||||
end
|
||||
|
||||
if !start then
|
||||
start = wep:GetPos() -- ???
|
||||
end
|
||||
|
||||
local diff = hit - start
|
||||
local dist = diff:Length()
|
||||
|
||||
if !tacrp then
|
||||
self.Speed = 15000
|
||||
elseif TacRP.ConVars["physbullet"]:GetBool() then
|
||||
self.Speed = math.max(wep:GetValue("MuzzleVelocity") or data:GetScale(), 5000)
|
||||
else
|
||||
self.Speed = math.max(wep:GetValue("MuzzleVelocity") or data:GetScale(), dist / 0.4)
|
||||
end
|
||||
|
||||
self.LifeTime = dist / self.Speed
|
||||
self.StartTime = UnPredictedCurTime()
|
||||
self.DieTime = UnPredictedCurTime() + math.max(self.LifeTime, self.LifeTime2)
|
||||
|
||||
self.StartPos = start
|
||||
self.EndPos = hit
|
||||
self.Dir = diff:GetNormalized()
|
||||
end
|
||||
|
||||
function EFFECT:Think()
|
||||
return self.DieTime > UnPredictedCurTime()
|
||||
end
|
||||
|
||||
function EFFECT:Render()
|
||||
|
||||
if !self.Dir then return end
|
||||
|
||||
local d = (UnPredictedCurTime() - self.StartTime) / self.LifeTime
|
||||
local startpos = self.StartPos + (d * 0.2 * (self.EndPos - self.StartPos))
|
||||
local endpos = self.StartPos + (d * (self.EndPos - self.StartPos))
|
||||
|
||||
--[[]
|
||||
local col = LerpColor(d, self.Color, Color(0, 0, 0, 0))
|
||||
local col2 = LerpColor(d2, Color(255, 255, 255, 255), Color(0, 0, 0, 0))
|
||||
|
||||
render.SetMaterial(head)
|
||||
render.DrawSprite(endpos, size * 3, size * 3, col)
|
||||
|
||||
render.SetMaterial(tracer)
|
||||
render.DrawBeam(endpos, startpos, size, 0, 1, col)
|
||||
]]
|
||||
|
||||
local size = math.Clamp(math.log(EyePos():DistToSqr(endpos) - math.pow(256, 2)), 0, math.huge)
|
||||
|
||||
local vel = self.Dir * self.Speed - LocalPlayer():GetVelocity()
|
||||
|
||||
local dot = math.abs(EyeAngles():Forward():Dot(vel:GetNormalized()))
|
||||
--dot = math.Clamp(((dot * dot) - 0.25) * 5, 0, 1)
|
||||
local headsize = size * dot * 2 -- * math.min(EyePos():DistToSqr(pos) / math.pow(2500, 2), 1)
|
||||
-- cam.Start3D()
|
||||
|
||||
local col = Color(255, 225, 200)
|
||||
-- local col = Color(255, 225, 200)
|
||||
|
||||
render.SetMaterial(head)
|
||||
render.DrawSprite(endpos, headsize, headsize, col)
|
||||
|
||||
-- local tailpos = startpos
|
||||
-- if (endpos - startpos):Length() > 512 then
|
||||
-- tailpos = endpos - self.Dir * 512
|
||||
-- end
|
||||
local tail = (self.Dir * math.min(self.Speed / 25, 512, (endpos - startpos):Length() - 64))
|
||||
|
||||
render.SetMaterial(tracer)
|
||||
render.DrawBeam(endpos, endpos - tail, size * 0.75, 0, 1, col)
|
||||
end
|
||||
173
garrysmod/addons/tacrp/lua/entities/tacrp_ammo.lua
Normal file
173
garrysmod/addons/tacrp/lua/entities/tacrp_ammo.lua
Normal file
@@ -0,0 +1,173 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Ammo Pickup"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/ammoboxes/ammo_bag-1.mdl"
|
||||
ENT.ModelOptions = nil
|
||||
|
||||
ENT.InfiniteUse = false
|
||||
ENT.OpeningAnim = false
|
||||
ENT.NextUse = 0
|
||||
ENT.Open = false
|
||||
ENT.MaxHealth = 0
|
||||
|
||||
function ENT:Initialize()
|
||||
local model = self.Model
|
||||
|
||||
if self.ModelOptions then
|
||||
model = table.Random(self.ModelOptions)
|
||||
end
|
||||
|
||||
self:SetModel(model)
|
||||
|
||||
if SERVER then
|
||||
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
self:SetUseType(CONTINUOUS_USE)
|
||||
self:PhysWake()
|
||||
|
||||
if self.MaxHealth > 0 then
|
||||
self:SetMaxHealth(self.MaxHealth)
|
||||
self:SetHealth(self.MaxHealth)
|
||||
end
|
||||
|
||||
self:SetTrigger(true) -- Enables Touch() to be called even when not colliding
|
||||
self:UseTriggerBounds(true, 24)
|
||||
end
|
||||
end
|
||||
|
||||
local function ClampedGiveAmmo(ply, ammo, amt, clamp)
|
||||
local count = ply:GetAmmoCount(ammo)
|
||||
|
||||
if count >= clamp then
|
||||
return false
|
||||
elseif count + amt > clamp then
|
||||
amt = math.max(clamp - count, 0)
|
||||
end
|
||||
|
||||
ply:GiveAmmo(amt, ammo)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:ApplyAmmo(ply)
|
||||
if self.NextUse > CurTime() then return end
|
||||
|
||||
local wpn = ply:GetActiveWeapon()
|
||||
|
||||
local ammotype = wpn:GetPrimaryAmmoType()
|
||||
local clipsize = wpn:GetMaxClip1()
|
||||
local supplyamount = clipsize * 1
|
||||
local max = clipsize * 6
|
||||
|
||||
local t2
|
||||
|
||||
if wpn.ArcticTacRP then
|
||||
ammotype = wpn:GetAmmoType()
|
||||
clipsize = wpn.ClipSize
|
||||
max = (wpn:GetValue("SupplyAmmoAmount") or (clipsize * 6)) * (wpn:GetValue("SupplyLimit") or 1)
|
||||
|
||||
if max <= 0 then
|
||||
max = 1
|
||||
end
|
||||
|
||||
if TacRP.ConVars["resupply_grenades"]:GetBool() then
|
||||
local nade = wpn:GetGrenade()
|
||||
|
||||
if nade.Ammo then
|
||||
if !nade.AdminOnly or ply:IsAdmin() then
|
||||
t2 = ClampedGiveAmmo(ply, nade.Ammo, 1, 3)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local t = ClampedGiveAmmo(ply, ammotype, supplyamount, max)
|
||||
|
||||
if t or t2 then
|
||||
if self.OpeningAnim and !self.Open then
|
||||
local seq = self:LookupSequence("open")
|
||||
self:ResetSequence(seq)
|
||||
self:EmitSound("items/ammocrate_open.wav")
|
||||
|
||||
self.Open = true
|
||||
end
|
||||
|
||||
self.NextUse = CurTime() + 1
|
||||
|
||||
if !self.InfiniteUse then
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ENT.CollisionSoundsHard = {
|
||||
"physics/cardboard/cardboard_box_impact_hard1.wav",
|
||||
"physics/cardboard/cardboard_box_impact_hard2.wav",
|
||||
"physics/cardboard/cardboard_box_impact_hard3.wav",
|
||||
"physics/cardboard/cardboard_box_impact_hard4.wav",
|
||||
"physics/cardboard/cardboard_box_impact_hard5.wav",
|
||||
"physics/cardboard/cardboard_box_impact_hard6.wav",
|
||||
"physics/cardboard/cardboard_box_impact_hard7.wav",
|
||||
}
|
||||
|
||||
ENT.CollisionSoundsSoft = {
|
||||
"physics/cardboard/cardboard_box_impact_soft1.wav",
|
||||
"physics/cardboard/cardboard_box_impact_soft2.wav",
|
||||
"physics/cardboard/cardboard_box_impact_soft3.wav",
|
||||
"physics/cardboard/cardboard_box_impact_soft4.wav",
|
||||
"physics/cardboard/cardboard_box_impact_soft5.wav",
|
||||
"physics/cardboard/cardboard_box_impact_soft6.wav",
|
||||
"physics/cardboard/cardboard_box_impact_soft7.wav",
|
||||
}
|
||||
|
||||
function ENT:PhysicsCollide(data)
|
||||
if data.DeltaTime < 0.1 then return end
|
||||
|
||||
if data.Speed > 25 then
|
||||
self:EmitSound(self.CollisionSoundsHard[math.random(#self.CollisionSoundsHard)])
|
||||
else
|
||||
self:EmitSound(self.CollisionSoundsSoft[math.random(#self.CollisionSoundsSoft)])
|
||||
end
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
|
||||
function ENT:Use(ply)
|
||||
if !ply:IsPlayer() then return end
|
||||
self:ApplyAmmo(ply)
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if self.Open and (self.NextUse + 0.1) < CurTime() then
|
||||
local seq = self:LookupSequence("close")
|
||||
self:ResetSequence(seq)
|
||||
self:EmitSound("items/ammocrate_close.wav")
|
||||
|
||||
self.Open = false
|
||||
end
|
||||
|
||||
self:NextThink(CurTime())
|
||||
return true
|
||||
end
|
||||
|
||||
elseif CLIENT then
|
||||
|
||||
function ENT:DrawTranslucent()
|
||||
self:Draw()
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
end
|
||||
|
||||
end
|
||||
15
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_c4.lua
Normal file
15
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_c4.lua
Normal file
@@ -0,0 +1,15 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_ammo_frag"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "C4 Charge (Ammo)"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.AdminOnly = false
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/c4_charge-1.mdl"
|
||||
|
||||
ENT.Ammo = "ti_c4"
|
||||
ENT.GrenadeProxy = "tacrp_c4_detonator"
|
||||
15
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_charge.lua
Normal file
15
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_charge.lua
Normal file
@@ -0,0 +1,15 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_ammo_frag"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Door Charge (Ammo)"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.AdminOnly = false
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/door_charge-1.mdl"
|
||||
|
||||
ENT.Ammo = "ti_charge"
|
||||
ENT.GrenadeProxy = "tacrp_nade_charge"
|
||||
28
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_crate.lua
Normal file
28
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_crate.lua
Normal file
@@ -0,0 +1,28 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_ammo"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Ammo Crate"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/ammoboxes/ammo_box-2b.mdl"
|
||||
|
||||
ENT.InfiniteUse = true
|
||||
ENT.OpeningAnim = true
|
||||
|
||||
ENT.AutomaticFrameAdvance = true
|
||||
|
||||
ENT.CollisionSoundsHard = {
|
||||
"physics/metal/metal_box_impact_hard1.wav",
|
||||
"physics/metal/metal_box_impact_hard2.wav",
|
||||
"physics/metal/metal_box_impact_hard3.wav",
|
||||
}
|
||||
|
||||
ENT.CollisionSoundsSoft = {
|
||||
"physics/metal/metal_box_impact_soft1.wav",
|
||||
"physics/metal/metal_box_impact_soft2.wav",
|
||||
"physics/metal/metal_box_impact_soft3.wav",
|
||||
}
|
||||
286
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_crate_ttt.lua
Normal file
286
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_crate_ttt.lua
Normal file
@@ -0,0 +1,286 @@
|
||||
if engine.ActiveGamemode() ~= "terrortown" then return end
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.RenderGroup = RENDERGROUP_BOTH
|
||||
|
||||
ENT.PrintName = "tacrp_ammocrate_name"
|
||||
|
||||
ENT.Model = "models/weapons/tacint/ammoboxes/ammo_box-2b.mdl"
|
||||
ENT.CanHavePrints = true
|
||||
ENT.CanUseKey = true
|
||||
ENT.MaxHealth = 250
|
||||
|
||||
ENT.MaxStored = 100
|
||||
ENT.RechargeRate = 1
|
||||
ENT.RechargeFreq = 2
|
||||
|
||||
ENT.AutomaticFrameAdvance = true
|
||||
|
||||
ENT.CollisionSoundsHard = {
|
||||
"physics/metal/metal_box_impact_hard1.wav",
|
||||
"physics/metal/metal_box_impact_hard2.wav",
|
||||
"physics/metal/metal_box_impact_hard3.wav",
|
||||
}
|
||||
|
||||
ENT.CollisionSoundsSoft = {
|
||||
"physics/metal/metal_box_impact_soft1.wav",
|
||||
"physics/metal/metal_box_impact_soft2.wav",
|
||||
"physics/metal/metal_box_impact_soft3.wav",
|
||||
}
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"^TacRP/weapons/grenade/frag_explode-1.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-2.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-3.wav",
|
||||
}
|
||||
|
||||
ENT.AmmoInfo = {
|
||||
-- ammo per use, max, cost per use
|
||||
["357"] = {10, nil, 12}, -- 2 to fill
|
||||
["smg1"] = {30, nil, 10}, -- 2 to fill
|
||||
["pistol"] = {20, nil, 5}, -- 3 to fill
|
||||
["alyxgun"] = {12, nil, 6}, -- 3 to fill
|
||||
["buckshot"] = {8, nil, 8}, -- 3 to fill
|
||||
|
||||
["smg1_grenade"] = {1, 3, 34},
|
||||
["rpg_round"] = {1, 2, 50},
|
||||
["ti_sniper"] = {5, 10, 50},
|
||||
}
|
||||
|
||||
if CLIENT then
|
||||
|
||||
ENT.Icon = "entities/tacrp_ammo_crate.png"
|
||||
|
||||
LANG.AddToLanguage("english", "tacrp_ammocrate_hint", "Press {usekey} to get ammo. Remaining charge: {num}")
|
||||
LANG.AddToLanguage("english", "tacrp_ammocrate_broken", "Your Ammo Crate has been destroyed!")
|
||||
LANG.AddToLanguage("english", "tacrp_ammocrate_subtitle", "Press {usekey} to receive ammo.")
|
||||
LANG.AddToLanguage("english", "tacrp_ammocrate_charge", "Remaining charge: {charge}.")
|
||||
LANG.AddToLanguage("english", "tacrp_ammocrate_empty", "No charge left")
|
||||
|
||||
LANG.AddToLanguage("english", "tacrp_ammocrate_short_desc", "The ammo crate recharges over time")
|
||||
|
||||
local TryT = LANG.TryTranslation
|
||||
local ParT = LANG.GetParamTranslation
|
||||
|
||||
ENT.TargetIDHint = {
|
||||
name = "tacrp_ammocrate_name",
|
||||
hint = "tacrp_ammocrate_hint",
|
||||
fmt = function(ent, txt)
|
||||
return ParT(txt, {
|
||||
usekey = Key("+use", "USE"),
|
||||
num = ent:GetStoredAmmo() or 0
|
||||
})
|
||||
end
|
||||
}
|
||||
|
||||
local key_params = {
|
||||
usekey = Key("+use", "USE")
|
||||
}
|
||||
|
||||
-- TTT2 does this
|
||||
hook.Add("TTTRenderEntityInfo", "tacrp_ammo_crate", function(tData)
|
||||
local client = LocalPlayer()
|
||||
local ent = tData:GetEntity()
|
||||
|
||||
if not IsValid(client) or not client:IsTerror() or not client:Alive()
|
||||
or not IsValid(ent) or tData:GetEntityDistance() > 100 or ent:GetClass() ~= "tacrp_ammo_crate_ttt" then
|
||||
return
|
||||
end
|
||||
|
||||
-- enable targetID rendering
|
||||
tData:EnableText()
|
||||
tData:EnableOutline()
|
||||
tData:SetOutlineColor(client:GetRoleColor())
|
||||
|
||||
tData:SetTitle(TryT(ent.PrintName))
|
||||
tData:SetSubtitle(ParT("tacrp_ammocrate_subtitle", key_params))
|
||||
tData:SetKeyBinding("+use")
|
||||
|
||||
local charge = ent:GetStoredAmmo() or 0
|
||||
|
||||
tData:AddDescriptionLine(TryT("tacrp_ammocrate_short_desc"))
|
||||
|
||||
tData:AddDescriptionLine(
|
||||
(charge > 0) and ParT("tacrp_ammocrate_charge", {charge = charge}) or TryT("tacrp_ammocrate_empty"),
|
||||
(charge > 0) and roles.DETECTIVE.ltcolor or COLOR_ORANGE
|
||||
)
|
||||
end)
|
||||
end
|
||||
|
||||
AccessorFuncDT(ENT, "StoredAmmo", "StoredAmmo")
|
||||
AccessorFunc(ENT, "Placer", "Placer")
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:DTVar("Int", 0, "StoredAmmo")
|
||||
end
|
||||
|
||||
function ENT:AddToStorage(amount)
|
||||
self:SetStoredAmmo(math.min(self.MaxStored, self:GetStoredAmmo() + amount))
|
||||
end
|
||||
|
||||
function ENT:TakeFromStorage(amount)
|
||||
amount = math.min(amount, self:GetStoredAmmo())
|
||||
self:SetStoredAmmo(math.max(0, self:GetStoredAmmo() - amount))
|
||||
return amount
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel(self.Model)
|
||||
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
self:SetUseType(CONTINUOUS_USE)
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if IsValid(phys) then
|
||||
phys:SetMass(150)
|
||||
phys:Wake()
|
||||
end
|
||||
|
||||
if self.MaxHealth > 0 then
|
||||
self:SetMaxHealth(self.MaxHealth)
|
||||
self:SetHealth(self.MaxHealth)
|
||||
end
|
||||
|
||||
self:SetStoredAmmo(self.MaxStored)
|
||||
|
||||
self:SetPlacer(nil)
|
||||
|
||||
self.fingerprints = {}
|
||||
end
|
||||
end
|
||||
|
||||
local function ClampedGiveAmmo(ply, ammo, amt, clamp)
|
||||
local count = ply:GetAmmoCount(ammo)
|
||||
|
||||
if count >= clamp then
|
||||
return 0
|
||||
elseif count + amt > clamp then
|
||||
amt = math.max(clamp - count, 0)
|
||||
end
|
||||
|
||||
return amt
|
||||
end
|
||||
|
||||
function ENT:ApplyAmmo(ply)
|
||||
if (self.NextUse or 0) > CurTime() then return end
|
||||
|
||||
local wpn = ply:GetActiveWeapon()
|
||||
|
||||
local ammotype = string.lower(game.GetAmmoName(wpn:GetPrimaryAmmoType()) or "")
|
||||
if !self.AmmoInfo[ammotype] then return end
|
||||
|
||||
local max = self.AmmoInfo[ammotype][2] or wpn.Primary.ClipMax
|
||||
local amt = self.AmmoInfo[ammotype][1]
|
||||
amt = ClampedGiveAmmo(ply, ammotype, amt, max) -- amount we need
|
||||
local cost = self.AmmoInfo[ammotype][3] * (amt / self.AmmoInfo[ammotype][1])
|
||||
local f = math.min(cost, self:GetStoredAmmo()) / cost -- fraction of cost we can afford
|
||||
|
||||
amt = math.floor(amt * f)
|
||||
|
||||
if amt > 0 then
|
||||
self:TakeFromStorage(cost * f)
|
||||
ply:GiveAmmo(amt, ammotype)
|
||||
|
||||
if !self.Open then
|
||||
local seq = self:LookupSequence("open")
|
||||
self:ResetSequence(seq)
|
||||
self:EmitSound("items/ammocrate_open.wav")
|
||||
|
||||
self.Open = true
|
||||
end
|
||||
|
||||
self.NextUse = CurTime() + 1
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:PhysicsCollide(data)
|
||||
if data.DeltaTime < 0.1 then return end
|
||||
|
||||
if data.Speed > 25 then
|
||||
self:EmitSound(self.CollisionSoundsHard[math.random(#self.CollisionSoundsHard)])
|
||||
else
|
||||
self:EmitSound(self.CollisionSoundsSoft[math.random(#self.CollisionSoundsSoft)])
|
||||
end
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
|
||||
function ENT:Use(ply)
|
||||
if !ply:IsPlayer() then return end
|
||||
self:ApplyAmmo(ply)
|
||||
end
|
||||
function ENT:Think()
|
||||
if self.Open and (self.NextUse + 0.1) < CurTime() then
|
||||
local seq = self:LookupSequence("close")
|
||||
self:ResetSequence(seq)
|
||||
self:EmitSound("items/ammocrate_close.wav")
|
||||
|
||||
self.Open = false
|
||||
end
|
||||
|
||||
if (self.NextCharge or 0) < CurTime() then
|
||||
self:AddToStorage(self.RechargeRate)
|
||||
self.NextCharge = CurTime() + self.RechargeFreq
|
||||
end
|
||||
|
||||
self:NextThink(CurTime())
|
||||
return true
|
||||
end
|
||||
|
||||
elseif CLIENT then
|
||||
|
||||
function ENT:DrawTranslucent()
|
||||
self:Draw()
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function ENT:OnTakeDamage(dmginfo)
|
||||
if self.BOOM then return end
|
||||
|
||||
self:TakePhysicsDamage(dmginfo)
|
||||
self:SetHealth(self:Health() - dmginfo:GetDamage())
|
||||
local att = dmginfo:GetAttacker()
|
||||
local placer = self:GetPlacer()
|
||||
|
||||
if IsPlayer(att) then
|
||||
DamageLog(Format("DMG: \t %s [%s] damaged ammo crate [%s] for %d dmg", att:Nick(), att:GetRoleString(), IsPlayer(placer) and placer:Nick() or "<disconnected>", dmginfo:GetDamage()))
|
||||
end
|
||||
|
||||
if self:Health() < 0 then
|
||||
self:Remove()
|
||||
util.EquipmentDestroyed(self:GetPos())
|
||||
|
||||
if IsValid(self:GetPlacer()) then
|
||||
LANG.Msg(self:GetPlacer(), "tacrp_ammocrate_broken")
|
||||
end
|
||||
|
||||
self.BOOM = true
|
||||
|
||||
local dmg = self:GetStoredAmmo() * 2.25 + 75
|
||||
|
||||
util.BlastDamage(self, dmginfo:GetAttacker(), self:GetPos(), 400, dmg)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 125, 90)
|
||||
end
|
||||
end
|
||||
16
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_fire.lua
Normal file
16
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_fire.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_ammo_frag"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Thermite Grenade (Ammo)"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.AdminOnly = false
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/smoke.mdl"
|
||||
|
||||
ENT.Ammo = "ti_thermite"
|
||||
ENT.Material = "models/tacint/weapons/w_models/smoke/thermite-1"
|
||||
ENT.GrenadeProxy = "tacrp_nade_thermite"
|
||||
15
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_flashbang.lua
Normal file
15
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_flashbang.lua
Normal file
@@ -0,0 +1,15 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_ammo_frag"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Flashbang (Ammo)"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.AdminOnly = false
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/flashbang.mdl"
|
||||
|
||||
ENT.Ammo = "ti_flashbang"
|
||||
ENT.GrenadeProxy = "tacrp_nade_flashbang"
|
||||
85
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_frag.lua
Normal file
85
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_frag.lua
Normal file
@@ -0,0 +1,85 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Frag Grenade (Ammo)"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.AdminOnly = false
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/frag.mdl"
|
||||
|
||||
ENT.Ammo = "grenade"
|
||||
ENT.GrenadeProxy = "tacrp_nade_frag"
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel(self.Model)
|
||||
|
||||
if SERVER then
|
||||
self:SetMaterial(self.Material or "")
|
||||
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
self:SetUseType(CONTINUOUS_USE)
|
||||
self:PhysWake()
|
||||
|
||||
self:SetTrigger(true) -- Enables Touch() to be called even when not colliding
|
||||
self:UseTriggerBounds(true, 24)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:ApplyAmmo(ply)
|
||||
if self.Used then return end
|
||||
|
||||
self.Used = true
|
||||
ply:GiveAmmo(1, self.Ammo)
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
ENT.CollisionSoundsHard = {
|
||||
"physics/metal/weapon_impact_hard1.wav",
|
||||
"physics/metal/weapon_impact_hard2.wav",
|
||||
"physics/metal/weapon_impact_hard3.wav",
|
||||
}
|
||||
|
||||
ENT.CollisionSoundsSoft = {
|
||||
"physics/metal/weapon_impact_soft1.wav",
|
||||
"physics/metal/weapon_impact_soft2.wav",
|
||||
"physics/metal/weapon_impact_soft3.wav",
|
||||
}
|
||||
|
||||
function ENT:PhysicsCollide(data)
|
||||
if data.DeltaTime < 0.1 then return end
|
||||
|
||||
if data.Speed > 25 then
|
||||
self:EmitSound(self.CollisionSoundsHard[math.random(#self.CollisionSoundsHard)])
|
||||
else
|
||||
self:EmitSound(self.CollisionSoundsSoft[math.random(#self.CollisionSoundsSoft)])
|
||||
end
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
|
||||
function ENT:Use(ply)
|
||||
if !ply:IsPlayer() then return end
|
||||
self:ApplyAmmo(ply)
|
||||
if self.GrenadeProxy then
|
||||
ply:Give(self.GrenadeProxy, true)
|
||||
end
|
||||
end
|
||||
|
||||
elseif CLIENT then
|
||||
|
||||
function ENT:DrawTranslucent()
|
||||
self:Draw()
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
end
|
||||
|
||||
end
|
||||
16
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_gas.lua
Normal file
16
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_gas.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_ammo_frag"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "CS Gas Grenade (Ammo)"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.AdminOnly = false
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/smoke.mdl"
|
||||
|
||||
ENT.Ammo = "ti_gas"
|
||||
ENT.Material = "models/tacint/weapons/w_models/smoke/gas-1"
|
||||
ENT.GrenadeProxy = "tacrp_nade_gas"
|
||||
16
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_heal.lua
Normal file
16
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_heal.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_ammo_frag"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Medi-Smoke Canister (Ammo)"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.AdminOnly = false
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/smoke.mdl"
|
||||
|
||||
ENT.Ammo = "ti_heal"
|
||||
ENT.Material = "models/tacint/weapons/w_models/smoke/heal-1"
|
||||
ENT.GrenadeProxy = "tacrp_nade_heal"
|
||||
28
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_nuke.lua
Normal file
28
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_nuke.lua
Normal file
@@ -0,0 +1,28 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_ammo_frag"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Nuclear Device (Ammo)"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.AdminOnly = true
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/props_misc/briefcase_bomb-1.mdl"
|
||||
|
||||
ENT.Ammo = "ti_nuke"
|
||||
|
||||
ENT.CollisionSoundsHard = {
|
||||
"physics/metal/metal_box_impact_hard1.wav",
|
||||
"physics/metal/metal_box_impact_hard2.wav",
|
||||
"physics/metal/metal_box_impact_hard3.wav",
|
||||
}
|
||||
|
||||
ENT.CollisionSoundsSoft = {
|
||||
"physics/metal/metal_box_impact_soft1.wav",
|
||||
"physics/metal/metal_box_impact_soft2.wav",
|
||||
"physics/metal/metal_box_impact_soft3.wav",
|
||||
}
|
||||
|
||||
ENT.GrenadeProxy = false
|
||||
15
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_smoke.lua
Normal file
15
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_smoke.lua
Normal file
@@ -0,0 +1,15 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_ammo_frag"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Smoke Grenade (Ammo)"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.AdminOnly = false
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/smoke.mdl"
|
||||
|
||||
ENT.Ammo = "ti_smoke"
|
||||
ENT.GrenadeProxy = "tacrp_nade_smoke"
|
||||
167
garrysmod/addons/tacrp/lua/entities/tacrp_att.lua
Normal file
167
garrysmod/addons/tacrp/lua/entities/tacrp_att.lua
Normal file
@@ -0,0 +1,167 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Attachment"
|
||||
ENT.Category = "Tactical Intervention - Attachments"
|
||||
|
||||
ENT.Spawnable = false
|
||||
ENT.Model = "models/tacint/props_containers/supply_case-2.mdl"
|
||||
ENT.AttToGive = nil
|
||||
|
||||
function ENT:Initialize()
|
||||
local model = self.Model
|
||||
|
||||
self:SetModel(model)
|
||||
|
||||
if SERVER then
|
||||
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
self:PhysWake()
|
||||
|
||||
self:SetTrigger(true) -- Enables Touch() to be called even when not colliding
|
||||
self:UseTriggerBounds(true, 24)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:GiveAtt(ply)
|
||||
if !self.AttToGive then return end
|
||||
|
||||
if TacRP.ConVars["free_atts"]:GetBool() then
|
||||
ply:PrintMessage(HUD_PRINTTALK, "All attachments are free! This is not necessary!")
|
||||
return
|
||||
end
|
||||
|
||||
if TacRP.ConVars["lock_atts"]:GetBool() and TacRP:PlayerGetAtts(ply, self.AttToGive) > 0 then
|
||||
ply:PrintMessage(HUD_PRINTTALK, "You already have this attachment!")
|
||||
return
|
||||
end
|
||||
|
||||
local given = TacRP:PlayerGiveAtt(ply, self.AttToGive, 1)
|
||||
if given then
|
||||
TacRP:PlayerSendAttInv(ply)
|
||||
self:EmitSound("TacRP/weapons/flashlight_on.wav")
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
|
||||
ENT.CollisionSoundsHard = {
|
||||
"physics/metal/metal_box_impact_hard1.wav",
|
||||
"physics/metal/metal_box_impact_hard2.wav",
|
||||
"physics/metal/metal_box_impact_hard3.wav",
|
||||
}
|
||||
|
||||
ENT.CollisionSoundsSoft = {
|
||||
"physics/metal/metal_box_impact_soft1.wav",
|
||||
"physics/metal/metal_box_impact_soft2.wav",
|
||||
"physics/metal/metal_box_impact_soft3.wav",
|
||||
}
|
||||
|
||||
function ENT:PhysicsCollide(data)
|
||||
if data.DeltaTime < 0.1 then return end
|
||||
|
||||
if data.Speed > 40 then
|
||||
self:EmitSound(self.CollisionSoundsHard[math.random(#self.CollisionSoundsHard)], 70, 100, data.Speed / 100)
|
||||
else
|
||||
self:EmitSound(self.CollisionSoundsSoft[math.random(#self.CollisionSoundsSoft)], 70, 100, data.Speed / 100)
|
||||
end
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
|
||||
function ENT:Use(ply)
|
||||
if !ply:IsPlayer() then return end
|
||||
self:GiveAtt(ply)
|
||||
end
|
||||
|
||||
elseif CLIENT then
|
||||
|
||||
function ENT:DrawTranslucent()
|
||||
self:Draw()
|
||||
end
|
||||
|
||||
local font = "TacRP_Myriad_Pro_48_Unscaled"
|
||||
local iw2 = 128
|
||||
|
||||
local drawit = function(self, p, a, alpha)
|
||||
cam.Start3D2D(p, a, 0.05)
|
||||
-- surface.SetFont("TacRP_LondonBetween_24_Unscaled")
|
||||
|
||||
if !self.PrintLines then
|
||||
self.PrintLines = TacRP.MultiLineText(TacRP:GetAttName(self.AttToGive), 328, font)
|
||||
end
|
||||
for j, text in ipairs(self.PrintLines or {}) do
|
||||
draw.SimpleTextOutlined(text, font, 0, -40 + j * 40, Color(255, 255, 255, alpha * 255), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 2, Color(0, 0, 0, alpha * 75))
|
||||
end
|
||||
|
||||
-- local w2 = surface.GetTextSize(self.PrintName)
|
||||
|
||||
-- surface.SetTextPos(-w2 / 2, 0)
|
||||
-- surface.SetTextColor(255, 255, 255, 255)
|
||||
-- surface.DrawText(self.PrintName)
|
||||
|
||||
surface.SetDrawColor(255, 255, 255, alpha * 255)
|
||||
surface.SetMaterial(self.Icon or defaulticon)
|
||||
surface.DrawTexturedRect(-iw2 / 2, -iw2 - 8, iw2, iw2)
|
||||
cam.End3D2D()
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
local distsqr = (EyePos() - self:WorldSpaceCenter()):LengthSqr()
|
||||
if distsqr <= 262144 then -- 512^2
|
||||
local a = math.Clamp(1 - (distsqr - 196608) / 65536, 0, 1)
|
||||
local ang = self:GetAngles()
|
||||
|
||||
ang:RotateAroundAxis(ang:Forward(), 180)
|
||||
ang:RotateAroundAxis(ang:Right(), 90)
|
||||
ang:RotateAroundAxis(ang:Up(), 90)
|
||||
|
||||
local pos = self:GetPos()
|
||||
|
||||
pos = pos + ang:Forward() * 0
|
||||
pos = pos + ang:Up() * 4.1
|
||||
pos = pos + ang:Right() * -8
|
||||
|
||||
drawit(self, pos, ang, a)
|
||||
|
||||
-- cam.Start3D2D(pos, ang, 0.1)
|
||||
-- surface.SetFont("TacRP_LondonBetween_24_Unscaled")
|
||||
|
||||
-- local w = surface.GetTextSize(self.PrintName)
|
||||
|
||||
-- surface.SetTextPos(-w / 2, 0)
|
||||
-- surface.SetTextColor(255, 255, 255, 255)
|
||||
-- surface.DrawText(self.PrintName)
|
||||
|
||||
-- surface.SetDrawColor(255, 255, 255)
|
||||
-- surface.SetMaterial(self.Icon or defaulticon)
|
||||
-- local iw = 64
|
||||
-- surface.DrawTexturedRect(-iw / 2, -iw - 8, iw, iw)
|
||||
-- cam.End3D2D()
|
||||
|
||||
local ang2 = self:GetAngles()
|
||||
|
||||
ang2:RotateAroundAxis(ang2:Forward(), 90)
|
||||
ang2:RotateAroundAxis(ang2:Right(), -90)
|
||||
ang2:RotateAroundAxis(ang2:Up(), 0)
|
||||
|
||||
local pos2 = self:GetPos()
|
||||
|
||||
pos2 = pos2 + ang2:Forward() * 0
|
||||
pos2 = pos2 + ang2:Up() * 4.1
|
||||
pos2 = pos2 + ang2:Right() * -8
|
||||
|
||||
drawit(self, pos2, ang2, a)
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
68
garrysmod/addons/tacrp/lua/entities/tacrp_bench.lua
Normal file
68
garrysmod/addons/tacrp/lua/entities/tacrp_bench.lua
Normal file
@@ -0,0 +1,68 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.RenderGroup = RENDERGROUP_BOTH
|
||||
|
||||
ENT.PrintName = "Customization Bench"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/props_canal/winch02.mdl"
|
||||
|
||||
function ENT:Initialize()
|
||||
local model = self.Model
|
||||
|
||||
self:SetModel(model)
|
||||
|
||||
if SERVER then
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
self:PhysWake()
|
||||
end
|
||||
|
||||
-- removal is handled when checking position
|
||||
table.insert(TacRP.Benches, self)
|
||||
end
|
||||
|
||||
local font = "TacRP_Myriad_Pro_24_Unscaled"
|
||||
|
||||
function ENT:DrawTranslucent()
|
||||
|
||||
local distsqr = (EyePos() - self:WorldSpaceCenter()):LengthSqr()
|
||||
if distsqr <= 262144 then -- 512^2
|
||||
local a = 1 --math.Clamp(1 - (distsqr - 196608) / 65536, 0, 1)
|
||||
local ang = self:GetAngles()
|
||||
|
||||
ang:RotateAroundAxis(ang:Forward(), 180)
|
||||
ang:RotateAroundAxis(ang:Right(), 90)
|
||||
ang:RotateAroundAxis(ang:Up(), 90)
|
||||
|
||||
local pos = self:GetPos()
|
||||
|
||||
pos = pos + ang:Forward() * 2.75
|
||||
pos = pos + ang:Up() * 9
|
||||
pos = pos + ang:Right() * -33
|
||||
|
||||
cam.Start3D2D(pos, ang, 0.075)
|
||||
surface.SetFont(font)
|
||||
local w = surface.GetTextSize(self.PrintName)
|
||||
surface.SetTextPos(-w / 2, 0)
|
||||
surface.SetTextColor(255, 255, 255)
|
||||
surface.DrawText(self.PrintName)
|
||||
if distsqr <= 16384 then
|
||||
local t2 = "READY"
|
||||
local w2 = surface.GetTextSize(t2)
|
||||
surface.SetTextPos(-w2 / 2, 30)
|
||||
surface.SetTextColor(100, 255, 100)
|
||||
surface.DrawText(t2)
|
||||
end
|
||||
cam.End3D2D()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
end
|
||||
143
garrysmod/addons/tacrp/lua/entities/tacrp_droppedmag.lua
Normal file
143
garrysmod/addons/tacrp/lua/entities/tacrp_droppedmag.lua
Normal file
@@ -0,0 +1,143 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Dropped Magazine"
|
||||
ENT.Category = ""
|
||||
|
||||
ENT.Spawnable = false
|
||||
ENT.Model = ""
|
||||
ENT.FadeTime = 5
|
||||
ENT.CanHavePrints = true -- TTT
|
||||
|
||||
ENT.ImpactSounds = {
|
||||
["pistol"] = {
|
||||
"TacRP/weapons/drop_magazine_pistol-1.wav",
|
||||
"TacRP/weapons/drop_magazine_pistol-2.wav",
|
||||
"TacRP/weapons/drop_magazine_pistol-3.wav",
|
||||
"TacRP/weapons/drop_magazine_pistol-4.wav",
|
||||
"TacRP/weapons/drop_magazine_pistol-5.wav",
|
||||
},
|
||||
["metal"] = {
|
||||
"TacRP/weapons/drop_magazine_metal-1.wav",
|
||||
"TacRP/weapons/drop_magazine_metal-2.wav",
|
||||
"TacRP/weapons/drop_magazine_metal-3.wav",
|
||||
"TacRP/weapons/drop_magazine_metal-4.wav",
|
||||
},
|
||||
["plastic"] = {
|
||||
"TacRP/weapons/drop_magazine_plastic-1.wav",
|
||||
"TacRP/weapons/drop_magazine_plastic-2.wav"
|
||||
},
|
||||
["bullet"] = {
|
||||
"player/pl_shell1.wav",
|
||||
"player/pl_shell2.wav",
|
||||
"player/pl_shell3.wav"
|
||||
},
|
||||
["shotgun"] = {
|
||||
"weapons/fx/tink/shotgun_shell1.wav",
|
||||
"weapons/fx/tink/shotgun_shell2.wav",
|
||||
"weapons/fx/tink/shotgun_shell3.wav",
|
||||
},
|
||||
["spoon"] = {
|
||||
"TacRP/weapons/grenade/spoon_bounce-1.wav",
|
||||
"TacRP/weapons/grenade/spoon_bounce-2.wav",
|
||||
"TacRP/weapons/grenade/spoon_bounce-3.wav",
|
||||
}
|
||||
}
|
||||
|
||||
ENT.ImpactType = "pistol"
|
||||
|
||||
ENT.AmmoType = nil
|
||||
ENT.AmmoCount = nil
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel(self.Model)
|
||||
|
||||
if SERVER then
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
|
||||
self:PhysWake()
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if !phys:IsValid() then
|
||||
self:PhysicsInitBox(Vector(-1, -1, -1), Vector(1, 1, 1))
|
||||
end
|
||||
end
|
||||
|
||||
self.SpawnTime = CurTime()
|
||||
if engine.ActiveGamemode() == "terrortown" and TacRP.ConVars["ttt_magazine_dna"]:GetBool() then
|
||||
self.FadeTime = 600
|
||||
if SERVER then
|
||||
self.fingerprints = {}
|
||||
table.insert(self.fingerprints, self:GetOwner())
|
||||
end
|
||||
end
|
||||
|
||||
if self.AmmoType and self.AmmoCount then
|
||||
self.FadeTime = math.max(self.FadeTime, 120)
|
||||
self:SetOwner(NULL) -- Owner can't +USE their own entities
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:PhysicsCollide(colData, collider)
|
||||
if colData.DeltaTime < 0.5 then return end
|
||||
|
||||
local tbl = self.ImpactSounds[self.ImpactType]
|
||||
|
||||
local snd = ""
|
||||
|
||||
if tbl then
|
||||
snd = table.Random(tbl)
|
||||
end
|
||||
|
||||
self:EmitSound(snd)
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if !self.SpawnTime then
|
||||
self.SpawnTime = CurTime()
|
||||
end
|
||||
|
||||
if SERVER and (self.SpawnTime + self.FadeTime) <= CurTime() then
|
||||
|
||||
self:SetRenderFX( kRenderFxFadeFast )
|
||||
|
||||
if (self.SpawnTime + self.FadeTime + 1) <= CurTime() then
|
||||
|
||||
if IsValid(self:GetPhysicsObject()) then
|
||||
self:GetPhysicsObject():EnableMotion(false)
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
if (self.SpawnTime + self.FadeTime + 1.5) <= CurTime() then
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Use(ply)
|
||||
if self.AmmoType and (self.AmmoCount or 0) > 0 and (self.SpawnTime + 0.5 <= CurTime()) then
|
||||
local given = ply:GiveAmmo(self.AmmoCount, self.AmmoType)
|
||||
self.AmmoCount = self.AmmoCount - given
|
||||
if self.AmmoCount <= 0 then
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:DrawTranslucent()
|
||||
self:Draw()
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
end
|
||||
309
garrysmod/addons/tacrp/lua/entities/tacrp_fire_cloud.lua
Normal file
309
garrysmod/addons/tacrp/lua/entities/tacrp_fire_cloud.lua
Normal file
@@ -0,0 +1,309 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Fire Particle"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
ENT.Model = "models/Items/AR2_Grenade.mdl"
|
||||
|
||||
ENT.FireTime = 8
|
||||
|
||||
ENT.Armed = false
|
||||
|
||||
ENT.NextDamageTick = 0
|
||||
|
||||
ENT.Ticks = 0
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
self.SpawnTime = CurTime()
|
||||
|
||||
if SERVER then
|
||||
self:SetModel( self.Model )
|
||||
self:SetMoveType( MOVETYPE_VPHYSICS )
|
||||
self:SetSolid( SOLID_VPHYSICS )
|
||||
local maxs = Vector(1, 1, 1)
|
||||
local mins = -maxs
|
||||
self:PhysicsInitBox(mins, maxs)
|
||||
self:DrawShadow( false )
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if phys:IsValid() then
|
||||
phys:Wake()
|
||||
phys:SetBuoyancyRatio(0)
|
||||
end
|
||||
|
||||
self:Detonate()
|
||||
|
||||
-- self.FireTime = self.FireTime * math.Rand(0.8, 1.2)
|
||||
-- self:SetNWFloat("FireTime", CurTime() + self.FireTime)
|
||||
|
||||
self:SetCollisionGroup(COLLISION_GROUP_PROJECTILE)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if CLIENT then
|
||||
local d = Lerp((self.SpawnTime + self.FireTime - CurTime()) / 8, 1, 0.000001) ^ 2
|
||||
|
||||
if !self.Light and TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
self.Light = DynamicLight(self:EntIndex())
|
||||
if (self.Light) then
|
||||
self.Light.Pos = self:GetPos()
|
||||
self.Light.r = 255
|
||||
self.Light.g = 135
|
||||
self.Light.b = 0
|
||||
self.Light.Brightness = 5
|
||||
self.Light.Size = math.Clamp(TacRP.ConVars["thermite_radius"]:GetFloat(), 128, 512) * 1.5
|
||||
self.Light.DieTime = CurTime() + self.FireTime
|
||||
end
|
||||
elseif self.Light then
|
||||
self.Light.Pos = self:GetPos()
|
||||
end
|
||||
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
if !self:IsValid() or self:WaterLevel() > 2 then return end
|
||||
if !IsValid(emitter) then return end
|
||||
|
||||
if self.Ticks % math.ceil(2 + d * 8) == 0 then
|
||||
local fire = emitter:Add("particles/smokey", self:GetPos() + Vector(math.Rand(-32, 32), math.Rand(-32, 32), 0))
|
||||
fire:SetVelocity( (VectorRand() * 500) + (self:GetAngles():Up() * 300) )
|
||||
fire:SetGravity( Vector(0, 0, 1500) )
|
||||
fire:SetDieTime( math.Rand(0.5, 1) )
|
||||
fire:SetStartAlpha( 100 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetStartSize( 10 )
|
||||
fire:SetEndSize( 150 )
|
||||
fire:SetRoll( math.Rand(-180, 180) )
|
||||
fire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
fire:SetAirResistance( 250 )
|
||||
fire:SetPos( self:GetPos() )
|
||||
fire:SetLighting( false )
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(0.75)
|
||||
fire:SetNextThink( CurTime() + FrameTime() )
|
||||
fire:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
local col1 = Color(255, 135, 0)
|
||||
local col2 = Color(255, 255, 255)
|
||||
|
||||
local col3 = col1
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
col3.r = Lerp(d, col1.r, col2.r)
|
||||
col3.g = Lerp(d, col1.g, col2.g)
|
||||
col3.b = Lerp(d, col1.b, col2.b)
|
||||
|
||||
pa:SetColor(col3.r, col3.g, col3.b)
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
end
|
||||
|
||||
if self.Ticks % math.ceil(1 + d * 6) == 0 then
|
||||
local fire = emitter:Add("effects/spark", self:GetPos() + Vector(math.Rand(-32, 32), math.Rand(-32, 32), 0))
|
||||
fire:SetVelocity( VectorRand() * 750 )
|
||||
fire:SetGravity( Vector(math.Rand(-5, 5), math.Rand(-5, 5), -2000) )
|
||||
fire:SetDieTime( math.Rand(0.5, 1) )
|
||||
fire:SetStartAlpha( 255 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetStartSize( 5 )
|
||||
fire:SetEndSize( 0 )
|
||||
fire:SetRoll( math.Rand(-180, 180) )
|
||||
fire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
fire:SetAirResistance( 50 )
|
||||
fire:SetPos( self:GetPos() )
|
||||
fire:SetLighting( false )
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(0.8)
|
||||
fire.Ticks = 0
|
||||
end
|
||||
|
||||
self.NextFlareTime = self.NextFlareTime or CurTime()
|
||||
|
||||
if self.NextFlareTime <= CurTime() then
|
||||
self.NextFlareTime = CurTime() + math.Rand(0.1, 0.5)
|
||||
local fire = emitter:Add("sprites/orangeflare1", self:GetPos())
|
||||
fire:SetVelocity( VectorRand() * 750 )
|
||||
fire:SetGravity( Vector(math.Rand(-5, 5), math.Rand(-5, 5), -2000) )
|
||||
fire:SetDieTime( math.Rand(1, 2) )
|
||||
fire:SetStartAlpha( 255 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetStartSize( 50 )
|
||||
fire:SetEndSize( 0 )
|
||||
fire:SetRoll( math.Rand(-180, 180) )
|
||||
fire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
fire:SetAirResistance( 50 )
|
||||
fire:SetPos( self:GetPos() )
|
||||
fire:SetLighting( false )
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(0.8)
|
||||
fire.Ticks = 0
|
||||
fire:SetNextThink( CurTime() + FrameTime() )
|
||||
fire:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
|
||||
local aemitter = ParticleEmitter(pa:GetPos())
|
||||
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
|
||||
if !IsValid(aemitter) then return end
|
||||
|
||||
if pa.Ticks % 5 == 0 then
|
||||
local afire = aemitter:Add("particles/smokey", pa:GetPos())
|
||||
afire:SetVelocity( VectorRand() * 5 )
|
||||
afire:SetGravity( Vector(0, 0, 1500) )
|
||||
afire:SetDieTime( math.Rand(0.25, 0.5) * d )
|
||||
afire:SetStartAlpha( 255 )
|
||||
afire:SetEndAlpha( 0 )
|
||||
afire:SetStartSize( 5 * d )
|
||||
afire:SetEndSize( 20 )
|
||||
afire:SetRoll( math.Rand(-180, 180) )
|
||||
afire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
afire:SetColor( 255, 255, 255 )
|
||||
afire:SetAirResistance( 150 )
|
||||
afire:SetPos( pa:GetPos() )
|
||||
afire:SetLighting( false )
|
||||
afire:SetCollide(true)
|
||||
afire:SetBounce(0.9)
|
||||
afire:SetNextThink( CurTime() + FrameTime() )
|
||||
afire:SetThinkFunction( function(apa)
|
||||
if !apa then return end
|
||||
local col1 = Color(255, 135, 0)
|
||||
local col2 = Color(255, 255, 255)
|
||||
|
||||
local col3 = col1
|
||||
local d2 = apa:GetLifeTime() / apa:GetDieTime()
|
||||
col3.r = Lerp(d2, col1.r, col2.r)
|
||||
col3.g = Lerp(d2, col1.g, col2.g)
|
||||
col3.b = Lerp(d2, col1.b, col2.b)
|
||||
|
||||
apa:SetColor(col3.r, col3.g, col3.b)
|
||||
apa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
end
|
||||
|
||||
aemitter:Finish()
|
||||
|
||||
pa.Ticks = pa.Ticks + 1
|
||||
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
|
||||
self.Ticks = self.Ticks + 1
|
||||
else
|
||||
|
||||
if !self:GetOwner():IsValid() then self:Remove() return end
|
||||
|
||||
if self:GetVelocity():LengthSqr() <= 32 then
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
end
|
||||
|
||||
if self.NextDamageTick > CurTime() then return end
|
||||
|
||||
if self:WaterLevel() > 2 then self:Remove() return end
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamageType(DMG_BURN)
|
||||
dmg:SetDamage(Lerp((self.SpawnTime + self.FireTime - CurTime()) / self.FireTime, TacRP.ConVars["thermite_damage_max"]:GetFloat(), TacRP.ConVars["thermite_damage_min"]:GetFloat()))
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetAttacker(self:GetOwner())
|
||||
util.BlastDamageInfo(dmg, IsValid(self:GetParent()) and self:GetParent():GetPos() or self:GetPos(), TacRP.ConVars["thermite_radius"]:GetFloat())
|
||||
|
||||
if self.SpawnTime + self.FireTime <= CurTime() then self:Remove() return end
|
||||
|
||||
self.NextDamageTick = CurTime() + 0.2
|
||||
self:NextThink(self.NextDamageTick)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if self.Light then
|
||||
self.Light.dietime = CurTime() + 0.5
|
||||
self.Light.decay = 2000
|
||||
end
|
||||
if !self.FireSound then return end
|
||||
self.FireSound:Stop()
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
if !self:IsValid() then return end
|
||||
|
||||
self.Armed = true
|
||||
|
||||
if self.Order and self.Order != 1 then return end
|
||||
|
||||
-- self.FireSound = CreateSound(self, "tacrp_extras/grenades/fire_loop_1.wav")
|
||||
self.FireSound = CreateSound(self, "ambient/gas/steam2.wav")
|
||||
self.FireSound:Play()
|
||||
self.FireSound:ChangePitch(120)
|
||||
|
||||
self.FireSound:ChangePitch(100, self.FireTime)
|
||||
|
||||
timer.Simple(self.FireTime - 1, function()
|
||||
if !IsValid(self) then return end
|
||||
|
||||
self.FireSound:ChangeVolume(0, 1)
|
||||
end)
|
||||
|
||||
timer.Simple(self.FireTime, function()
|
||||
if !IsValid(self) then return end
|
||||
|
||||
self:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
-- cam.Start3D() -- Start the 3D function so we can draw onto the screen.
|
||||
-- render.SetMaterial( GetFireParticle() ) -- Tell render what material we want, in this case the flash from the gravgun
|
||||
-- render.DrawSprite( self:GetPos(), math.random(200, 250), math.random(200, 250), Color(255, 255, 255) ) -- Draw the sprite in the middle of the map, at 16x16 in it's original colour with full alpha.
|
||||
-- cam.End3D()
|
||||
end
|
||||
|
||||
local directfiredamage = {
|
||||
["npc_zombie"] = true,
|
||||
["npc_zombie_torso"] = true,
|
||||
["npc_fastzombie"] = true,
|
||||
["npc_fastzombie_torso"] = true,
|
||||
["npc_poisonzombie"] = true,
|
||||
["npc_zombine"] = true,
|
||||
["npc_headcrab"] = true,
|
||||
["npc_headcrab_fast"] = true,
|
||||
["npc_headcrab_black"] = true,
|
||||
["npc_headcrab_poison"] = true,
|
||||
}
|
||||
|
||||
hook.Add("EntityTakeDamage", "tacrp_fire_cloud", function(ent, dmginfo)
|
||||
if IsValid(dmginfo:GetInflictor()) and dmginfo:GetInflictor():GetClass() == "tacrp_fire_cloud" and dmginfo:GetDamageType() == DMG_BURN then
|
||||
if ent:IsNPC() then
|
||||
if directfiredamage[ent:GetClass()] then
|
||||
dmginfo:SetDamageType(DMG_SLOWBURN) -- DMG_BURN does not hurt HL2 zombies and instead turns them black.
|
||||
elseif ent.Immune_Fire then
|
||||
dmginfo:SetDamageType(DMG_DIRECT) -- Bitch
|
||||
end
|
||||
elseif !ent:IsNextBot() and !ent:IsPlayer() then
|
||||
if ent:GetClass() == "prop_physics" then
|
||||
dmginfo:SetDamageType(DMG_DIRECT) -- some props like to burn slowly against DMG_BURN or DMG_SLOWBURN. don't.
|
||||
elseif ent:GetClass() == "tacrp_proj_nade_thermite" then
|
||||
return true -- don't burn other thermite grenades
|
||||
end
|
||||
dmginfo:ScaleDamage(2) -- tremendous damage to props
|
||||
end
|
||||
dmginfo:SetDamageForce(Vector()) -- fire does not push things around. still applies to players, but that can't be helped.
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("PostEntityTakeDamage", "tacrp_fire_cloud", function(ent, dmginfo, took)
|
||||
if took and IsValid(dmginfo:GetInflictor()) and dmginfo:GetInflictor():GetClass() == "tacrp_fire_cloud" and !ent:IsPlayer() then
|
||||
ent:Ignite(math.Rand(3, 5))
|
||||
end
|
||||
end)
|
||||
219
garrysmod/addons/tacrp/lua/entities/tacrp_flare_cloud.lua
Normal file
219
garrysmod/addons/tacrp/lua/entities/tacrp_flare_cloud.lua
Normal file
@@ -0,0 +1,219 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Flare Particle"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
ENT.Model = "models/Items/AR2_Grenade.mdl"
|
||||
|
||||
ENT.FireTime = 15
|
||||
|
||||
ENT.Armed = false
|
||||
|
||||
ENT.NextDamageTick = 0
|
||||
|
||||
ENT.Ticks = 0
|
||||
|
||||
ENT.FlareLength = 1
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
self.SpawnTime = CurTime()
|
||||
|
||||
if SERVER then
|
||||
self:SetModel( self.Model )
|
||||
self:SetMoveType( MOVETYPE_VPHYSICS )
|
||||
self:SetSolid( SOLID_VPHYSICS )
|
||||
local maxs = Vector(2, 1, 1)
|
||||
local mins = -maxs
|
||||
self:PhysicsInitBox(mins, maxs)
|
||||
self:DrawShadow( false )
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if phys:IsValid() then
|
||||
phys:Wake()
|
||||
phys:SetBuoyancyRatio(0)
|
||||
phys:SetDragCoefficient(5)
|
||||
end
|
||||
|
||||
self:Detonate()
|
||||
|
||||
-- self.FireTime = self.FireTime * math.Rand(0.8, 1.2)
|
||||
-- self:SetNWFloat("FireTime", CurTime() + self.FireTime)
|
||||
else
|
||||
local tr = util.TraceHull({
|
||||
start = self:GetPos() + Vector(0, 0, 12),
|
||||
endpos = self:GetPos() + Vector(0, 0, 1024),
|
||||
mask = MASK_SOLID_BRUSHONLY,
|
||||
mins = Vector(-4, -4, -4),
|
||||
maxs = Vector(4, 4, 4),
|
||||
})
|
||||
self.FlareLength = math.Clamp(tr.Fraction ^ 2, 0.2, 1)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if CLIENT then
|
||||
local d = Lerp((self.SpawnTime + self.FireTime - CurTime()) / 12, 1, 0.000001) ^ 2
|
||||
|
||||
if !self.Light and TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
self.Light = DynamicLight(self:EntIndex())
|
||||
if (self.Light) then
|
||||
self.Light.Pos = self:GetPos()
|
||||
self.Light.r = 255
|
||||
self.Light.g = 75
|
||||
self.Light.b = 60
|
||||
self.Light.Brightness = 1.5
|
||||
self.Light.Size = 512
|
||||
self.Light.DieTime = CurTime() + self.FireTime
|
||||
end
|
||||
elseif self.Light then
|
||||
self.Light.Pos = self:GetPos()
|
||||
end
|
||||
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
if !self:IsValid() or self:WaterLevel() > 2 then return end
|
||||
if !IsValid(emitter) then return end
|
||||
|
||||
if self.Ticks % math.ceil(2 + d * 8) == 0 then
|
||||
local fire = emitter:Add("particles/smokey", self:GetPos() + Vector(math.Rand(-4, 4), math.Rand(-4, 4), 8))
|
||||
local wind = Vector(math.sin(CurTime() / 60), math.cos(CurTime() / 60), 0) * math.Rand(1000, 1400)
|
||||
fire:SetVelocity( VectorRand() * 75 + self:GetVelocity() )
|
||||
fire:SetGravity( wind + Vector(0, 0, 2500) )
|
||||
fire:SetDieTime( self.FlareLength * math.Rand(2, 3) )
|
||||
fire:SetStartAlpha( 100 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetStartSize( 10 )
|
||||
fire:SetEndSize( Lerp(self.FlareLength, 48, 128) )
|
||||
fire:SetRoll( math.Rand(-180, 180) )
|
||||
fire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
fire:SetAirResistance( 300 )
|
||||
fire:SetPos( self:GetPos() )
|
||||
fire:SetLighting( false )
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(1)
|
||||
fire:SetNextThink( CurTime() + FrameTime() )
|
||||
fire:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
local col1 = Color(255, 50, 25)
|
||||
local col2 = Color(255, 155, 155)
|
||||
|
||||
local col3 = col1
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
col3.r = Lerp(d, col1.r, col2.r)
|
||||
col3.g = Lerp(d, col1.g, col2.g)
|
||||
col3.b = Lerp(d, col1.b, col2.b)
|
||||
|
||||
pa:SetColor(col3.r, col3.g, col3.b)
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
end
|
||||
|
||||
if self.Ticks % math.ceil(6 + d * 10) == 0 then
|
||||
local fire = emitter:Add("effects/spark", self:GetPos() + Vector(math.Rand(-4, 4), math.Rand(-4, 4), 0))
|
||||
fire:SetVelocity( VectorRand() * 300 + Vector(0, 0, 300) )
|
||||
fire:SetGravity( Vector(math.Rand(-5, 5), math.Rand(-5, 5), -2000) )
|
||||
fire:SetDieTime( math.Rand(0.5, 1) )
|
||||
fire:SetStartAlpha( 255 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetStartSize( 5 )
|
||||
fire:SetEndSize( 0 )
|
||||
fire:SetRoll( math.Rand(-180, 180) )
|
||||
fire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
fire:SetAirResistance( 50 )
|
||||
fire:SetPos( self:GetPos() )
|
||||
fire:SetLighting( false )
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(0.8)
|
||||
fire.Ticks = 0
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
|
||||
self.Ticks = self.Ticks + 1
|
||||
else
|
||||
|
||||
if !self:GetOwner():IsValid() then self:Remove() return end
|
||||
|
||||
if self:GetVelocity():LengthSqr() <= 32 then
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
end
|
||||
|
||||
if self.NextDamageTick > CurTime() then return end
|
||||
|
||||
if self:WaterLevel() > 2 then self:Remove() return end
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamageType(DMG_BURN)
|
||||
dmg:SetDamage(15)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetAttacker(self:GetOwner())
|
||||
util.BlastDamageInfo(dmg, IsValid(self:GetParent()) and self:GetParent():GetPos() or self:GetPos(), 96)
|
||||
|
||||
if self.SpawnTime + self.FireTime <= CurTime() then self:Remove() return end
|
||||
|
||||
self.NextDamageTick = CurTime() + 0.2
|
||||
self:NextThink(self.NextDamageTick)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if self.Light then
|
||||
self.Light.dietime = CurTime() + 0.5
|
||||
self.Light.decay = 2000
|
||||
end
|
||||
if !self.FireSound then return end
|
||||
self.FireSound:Stop()
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
if !self:IsValid() then return end
|
||||
|
||||
self.Armed = true
|
||||
|
||||
if self.Order and self.Order != 1 then return end
|
||||
|
||||
-- self.FireSound = CreateSound(self, "tacrp_extras/grenades/fire_loop_1.wav")
|
||||
self.FireSound = CreateSound(self, "weapons/flaregun/burn.wav")
|
||||
self.FireSound:SetSoundLevel(70)
|
||||
self.FireSound:Play()
|
||||
self.FireSound:ChangePitch(105)
|
||||
|
||||
self.FireSound:ChangePitch(95, self.FireTime)
|
||||
|
||||
timer.Simple(self.FireTime - 1, function()
|
||||
if !IsValid(self) then return end
|
||||
|
||||
self.FireSound:ChangeVolume(0, 1)
|
||||
end)
|
||||
|
||||
timer.Simple(self.FireTime, function()
|
||||
if !IsValid(self) then return end
|
||||
|
||||
self:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
ENT.FlareColor = Color(255, 200, 200)
|
||||
ENT.FlareSizeMin = 48
|
||||
ENT.FlareSizeMax = 64
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
function ENT:Draw()
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos() + Vector(0, 0, 4), math.Rand(self.FlareSizeMin, self.FlareSizeMax), math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
|
||||
function ENT:UpdateTransmitState()
|
||||
if TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
return TRANSMIT_ALWAYS
|
||||
end
|
||||
return TRANSMIT_PVS
|
||||
end
|
||||
233
garrysmod/addons/tacrp/lua/entities/tacrp_flare_cloud_para.lua
Normal file
233
garrysmod/addons/tacrp/lua/entities/tacrp_flare_cloud_para.lua
Normal file
@@ -0,0 +1,233 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Flare Particle"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
ENT.Model = "models/Items/AR2_Grenade.mdl"
|
||||
|
||||
ENT.FireTime = 15
|
||||
|
||||
ENT.Armed = false
|
||||
|
||||
ENT.NextDamageTick = 0
|
||||
|
||||
ENT.Ticks = 0
|
||||
|
||||
ENT.FlareLength = 1
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
self.SpawnTime = CurTime()
|
||||
|
||||
if SERVER then
|
||||
self:SetModel( self.Model )
|
||||
self:SetMoveType( MOVETYPE_VPHYSICS )
|
||||
self:SetSolid( SOLID_VPHYSICS )
|
||||
local maxs = Vector(2, 2, 2)
|
||||
local mins = -maxs
|
||||
self:PhysicsInitBox(mins, maxs)
|
||||
self:DrawShadow( false )
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if phys:IsValid() then
|
||||
phys:Wake()
|
||||
phys:SetBuoyancyRatio(0)
|
||||
phys:SetDragCoefficient(4)
|
||||
end
|
||||
|
||||
self:Detonate()
|
||||
end
|
||||
end
|
||||
|
||||
ENT.LastTraceTime = 0
|
||||
ENT.LastTracePos = nil
|
||||
|
||||
function ENT:Think()
|
||||
if CLIENT then
|
||||
local d = Lerp((self.SpawnTime + self.FireTime - CurTime()) / 12, 1, 0.000001) ^ 2
|
||||
|
||||
if !self.Light and TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
self.Light = DynamicLight(self:EntIndex())
|
||||
if (self.Light) then
|
||||
self.Light.Pos = self:GetPos()
|
||||
self.Light.r = 255
|
||||
self.Light.g = 200
|
||||
self.Light.b = 140
|
||||
self.Light.Brightness = 1
|
||||
self.Light.Size = 1500
|
||||
self.Light.DieTime = CurTime() + self.FireTime
|
||||
end
|
||||
elseif self.Light then
|
||||
self.Light.Pos = self:GetPos()
|
||||
end
|
||||
|
||||
-- fucking expensive
|
||||
--[[]
|
||||
if !self.ProjectedTexture then
|
||||
self.ProjectedTexture = ProjectedTexture()
|
||||
self.ProjectedTexture:SetTexture("effects/flashlight001")
|
||||
self.ProjectedTexture:SetColor(Color(255, 200, 140))
|
||||
self.ProjectedTexture:SetNearZ(728)
|
||||
self.ProjectedTexture:SetFarZ(4096)
|
||||
self.ProjectedTexture:SetAngles(down)
|
||||
self.ProjectedTexture:SetFOV(170)
|
||||
self.ProjectedTexture:SetLightWorld(false)
|
||||
self.ProjectedTexture:SetBrightness(0.75)
|
||||
end
|
||||
self.ProjectedTexture:SetPos(self:GetPos())
|
||||
self.ProjectedTexture:Update()
|
||||
]]
|
||||
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
if !self:IsValid() or self:WaterLevel() > 2 then return end
|
||||
if !IsValid(emitter) then return end
|
||||
|
||||
if self.Ticks % math.ceil(4 + d * 8) == 0 then
|
||||
local fire = emitter:Add("particles/smokey", self:GetPos() + Vector(math.Rand(-4, 4), math.Rand(-4, 4), 8))
|
||||
fire:SetVelocity( VectorRand() * 8 )
|
||||
fire:SetGravity( Vector(0, 0, 100) )
|
||||
fire:SetDieTime( self.FlareLength * math.Rand(5, 6) )
|
||||
fire:SetStartAlpha( 20 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetStartSize( 12 )
|
||||
fire:SetEndSize( math.Rand(32, 48) )
|
||||
fire:SetRoll( math.Rand(-180, 180) )
|
||||
fire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
fire:SetAirResistance( 100 )
|
||||
fire:SetPos( self:GetPos() )
|
||||
fire:SetLighting( false )
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(1)
|
||||
fire:SetNextThink( CurTime() + FrameTime() )
|
||||
fire:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
local col1 = Color(255, 200, 150)
|
||||
local col2 = Color(255, 255, 225)
|
||||
|
||||
local col3 = col1
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
col3.r = Lerp(d, col1.r, col2.r)
|
||||
col3.g = Lerp(d, col1.g, col2.g)
|
||||
col3.b = Lerp(d, col1.b, col2.b)
|
||||
|
||||
pa:SetColor(col3.r, col3.g, col3.b)
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
end
|
||||
|
||||
if self.Ticks % math.ceil(4 + d * 10) == 0 then
|
||||
local fire = emitter:Add("effects/spark", self:GetPos())
|
||||
fire:SetVelocity( VectorRand() * 300 + Vector(0, 0, 300) )
|
||||
fire:SetGravity( Vector(math.Rand(-5, 5), math.Rand(-5, 5), -2000) )
|
||||
fire:SetDieTime( math.Rand(0.5, 1) )
|
||||
fire:SetStartAlpha( 255 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetStartSize( 5 )
|
||||
fire:SetEndSize( 0 )
|
||||
fire:SetRoll( math.Rand(-180, 180) )
|
||||
fire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
fire:SetAirResistance( 50 )
|
||||
fire:SetPos( self:GetPos() )
|
||||
fire:SetLighting( false )
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(0.8)
|
||||
fire.Ticks = 0
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
|
||||
self.Ticks = self.Ticks + 1
|
||||
else
|
||||
|
||||
if !self:GetOwner():IsValid() then self:Remove() return end
|
||||
|
||||
if self.NextDamageTick > CurTime() then return end
|
||||
|
||||
if self:WaterLevel() > 2 then self:Remove() return end
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamageType(DMG_BURN)
|
||||
dmg:SetDamage(15)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetAttacker(self:GetOwner())
|
||||
util.BlastDamageInfo(dmg, IsValid(self:GetParent()) and self:GetParent():GetPos() or self:GetPos(), 96)
|
||||
|
||||
if self.SpawnTime + self.FireTime <= CurTime() then self:Remove() return end
|
||||
|
||||
self.NextDamageTick = CurTime() + 0.2
|
||||
self:NextThink(self.NextDamageTick)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if self.Light then
|
||||
self.Light.dietime = CurTime() + 0.5
|
||||
self.Light.decay = 800
|
||||
end
|
||||
if IsValid(self.ProjectedTexture) then
|
||||
self.ProjectedTexture:Remove()
|
||||
end
|
||||
if !self.FireSound then return end
|
||||
self.FireSound:Stop()
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
if !self:IsValid() then return end
|
||||
|
||||
self.Armed = true
|
||||
|
||||
if self.Order and self.Order != 1 then return end
|
||||
|
||||
-- self.FireSound = CreateSound(self, "tacrp_extras/grenades/fire_loop_1.wav")
|
||||
self.FireSound = CreateSound(self, "weapons/flaregun/burn.wav")
|
||||
self.FireSound:SetSoundLevel(70)
|
||||
self.FireSound:Play()
|
||||
self.FireSound:ChangePitch(105)
|
||||
|
||||
self.FireSound:ChangePitch(95, self.FireTime)
|
||||
|
||||
timer.Simple(self.FireTime - 1, function()
|
||||
if !IsValid(self) then return end
|
||||
|
||||
self.FireSound:ChangeVolume(0, 1)
|
||||
end)
|
||||
|
||||
timer.Simple(self.FireTime, function()
|
||||
if !IsValid(self) then return end
|
||||
|
||||
self:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
ENT.FlareColor = Color(255, 240, 240)
|
||||
ENT.FlareSizeMin = 64
|
||||
ENT.FlareSizeMax = 96
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
function ENT:Draw()
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos() + Vector(0, 0, 4), math.Rand(self.FlareSizeMin, self.FlareSizeMax), math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
if phys:IsGravityEnabled() and self:WaterLevel() <= 2 then
|
||||
local v = phys:GetVelocity()
|
||||
v.z = math.max(v.z, -70)
|
||||
phys:SetVelocityInstantaneous(v)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:UpdateTransmitState()
|
||||
if TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
return TRANSMIT_ALWAYS
|
||||
end
|
||||
return TRANSMIT_PVS
|
||||
end
|
||||
219
garrysmod/addons/tacrp/lua/entities/tacrp_flare_cloud_signal.lua
Normal file
219
garrysmod/addons/tacrp/lua/entities/tacrp_flare_cloud_signal.lua
Normal file
@@ -0,0 +1,219 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Flare Particle"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
ENT.Model = "models/Items/AR2_Grenade.mdl"
|
||||
|
||||
ENT.FireTime = 60 -- Duration once landed
|
||||
|
||||
ENT.Armed = false
|
||||
|
||||
ENT.NextDamageTick = 0
|
||||
|
||||
ENT.Ticks = 0
|
||||
|
||||
ENT.FlareLength = 2
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
self.SpawnTime = CurTime()
|
||||
|
||||
if SERVER then
|
||||
self:SetModel( self.Model )
|
||||
self:SetMoveType( MOVETYPE_VPHYSICS )
|
||||
self:SetSolid( SOLID_VPHYSICS )
|
||||
local maxs = Vector(2, 1, 1)
|
||||
local mins = -maxs
|
||||
self:PhysicsInitBox(mins, maxs)
|
||||
self:DrawShadow( false )
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if phys:IsValid() then
|
||||
phys:Wake()
|
||||
phys:SetBuoyancyRatio(0)
|
||||
phys:SetDragCoefficient(5)
|
||||
end
|
||||
|
||||
self:Detonate()
|
||||
|
||||
-- self.FireTime = self.FireTime * math.Rand(0.8, 1.2)
|
||||
-- self:SetNWFloat("FireTime", CurTime() + self.FireTime)
|
||||
else
|
||||
local tr = util.TraceHull({
|
||||
start = self:GetPos() + Vector(0, 0, 12),
|
||||
endpos = self:GetPos() + Vector(0, 0, 1024),
|
||||
mask = MASK_SOLID_BRUSHONLY,
|
||||
mins = Vector(-4, -4, -4),
|
||||
maxs = Vector(4, 4, 4),
|
||||
})
|
||||
self.FlareLength = math.Clamp(tr.Fraction ^ 2, 0.2, 1)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if CLIENT then
|
||||
local d = Lerp((self.SpawnTime + self.FireTime - CurTime()) / 12, 1, 0.000001) ^ 2
|
||||
|
||||
if !self.Light and TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
self.Light = DynamicLight(self:EntIndex())
|
||||
if (self.Light) then
|
||||
self.Light.Pos = self:GetPos()
|
||||
self.Light.r = 255
|
||||
self.Light.g = 75
|
||||
self.Light.b = 60
|
||||
self.Light.Brightness = 1.5
|
||||
self.Light.Size = 512
|
||||
self.Light.DieTime = CurTime() + self.FireTime
|
||||
end
|
||||
elseif self.Light then
|
||||
self.Light.Pos = self:GetPos()
|
||||
end
|
||||
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
if !self:IsValid() or self:WaterLevel() > 2 then return end
|
||||
if !IsValid(emitter) then return end
|
||||
|
||||
if self.Ticks % math.ceil(2 + d * 8) == 0 then
|
||||
local fire = emitter:Add("particles/smokey", self:GetPos() + Vector(math.Rand(-4, 4), math.Rand(-4, 4), 8))
|
||||
local wind = Vector(math.sin(CurTime() / 60), math.cos(CurTime() / 60), 0) * math.Rand(1000, 1400)
|
||||
fire:SetVelocity( VectorRand() * 75 + self:GetVelocity() )
|
||||
fire:SetGravity( wind + Vector(0, 0, 2500) )
|
||||
fire:SetDieTime( self.FlareLength * math.Rand(8, 12) ) -- Flare Height
|
||||
fire:SetStartAlpha( 100 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetStartSize( 10 )
|
||||
fire:SetEndSize( Lerp(self.FlareLength, 96, 256) ) -- Particle Size
|
||||
fire:SetRoll( math.Rand(-180, 180) )
|
||||
fire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
fire:SetAirResistance( 300 )
|
||||
fire:SetPos( self:GetPos() )
|
||||
fire:SetLighting( false )
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(1)
|
||||
fire:SetNextThink( CurTime() + FrameTime() )
|
||||
fire:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
local col1 = Color(255, 50, 25)
|
||||
local col2 = Color(255, 155, 155)
|
||||
|
||||
local col3 = col1
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
col3.r = Lerp(d, col1.r, col2.r)
|
||||
col3.g = Lerp(d, col1.g, col2.g)
|
||||
col3.b = Lerp(d, col1.b, col2.b)
|
||||
|
||||
pa:SetColor(col3.r, col3.g, col3.b)
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
end
|
||||
|
||||
if self.Ticks % math.ceil(6 + d * 10) == 0 then
|
||||
local fire = emitter:Add("effects/spark", self:GetPos() + Vector(math.Rand(-4, 4), math.Rand(-4, 4), 0))
|
||||
fire:SetVelocity( VectorRand() * 300 + Vector(0, 0, 300) )
|
||||
fire:SetGravity( Vector(math.Rand(-5, 5), math.Rand(-5, 5), -2000) )
|
||||
fire:SetDieTime( math.Rand(0.5, 1) )
|
||||
fire:SetStartAlpha( 255 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetStartSize( 5 )
|
||||
fire:SetEndSize( 0 )
|
||||
fire:SetRoll( math.Rand(-180, 180) )
|
||||
fire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
fire:SetAirResistance( 50 )
|
||||
fire:SetPos( self:GetPos() )
|
||||
fire:SetLighting( false )
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(0.8)
|
||||
fire.Ticks = 0
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
|
||||
self.Ticks = self.Ticks + 1
|
||||
else
|
||||
|
||||
if !self:GetOwner():IsValid() then self:Remove() return end
|
||||
|
||||
if self:GetVelocity():LengthSqr() <= 32 then
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
end
|
||||
|
||||
if self.NextDamageTick > CurTime() then return end
|
||||
|
||||
if self:WaterLevel() > 2 then self:Remove() return end
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamageType(DMG_BURN)
|
||||
dmg:SetDamage(15)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetAttacker(self:GetOwner())
|
||||
util.BlastDamageInfo(dmg, IsValid(self:GetParent()) and self:GetParent():GetPos() or self:GetPos(), 96)
|
||||
|
||||
if self.SpawnTime + self.FireTime <= CurTime() then self:Remove() return end
|
||||
|
||||
self.NextDamageTick = CurTime() + 0.2
|
||||
self:NextThink(self.NextDamageTick)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if self.Light then
|
||||
self.Light.dietime = CurTime() + 0.5
|
||||
self.Light.decay = 2000
|
||||
end
|
||||
if !self.FireSound then return end
|
||||
self.FireSound:Stop()
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
if !self:IsValid() then return end
|
||||
|
||||
self.Armed = true
|
||||
|
||||
if self.Order and self.Order != 1 then return end
|
||||
|
||||
-- self.FireSound = CreateSound(self, "tacrp_extras/grenades/fire_loop_1.wav")
|
||||
self.FireSound = CreateSound(self, "weapons/flaregun/burn.wav")
|
||||
self.FireSound:SetSoundLevel(70)
|
||||
self.FireSound:Play()
|
||||
self.FireSound:ChangePitch(105)
|
||||
|
||||
self.FireSound:ChangePitch(95, self.FireTime)
|
||||
|
||||
timer.Simple(self.FireTime - 1, function()
|
||||
if !IsValid(self) then return end
|
||||
|
||||
self.FireSound:ChangeVolume(0, 1)
|
||||
end)
|
||||
|
||||
timer.Simple(self.FireTime, function()
|
||||
if !IsValid(self) then return end
|
||||
|
||||
self:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
ENT.FlareColor = Color(255, 200, 200)
|
||||
ENT.FlareSizeMin = 96
|
||||
ENT.FlareSizeMax = 128
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
function ENT:Draw()
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos() + Vector(0, 0, 4), math.Rand(self.FlareSizeMin, self.FlareSizeMax), math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
|
||||
function ENT:UpdateTransmitState()
|
||||
if TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
return TRANSMIT_ALWAYS
|
||||
end
|
||||
return TRANSMIT_PVS
|
||||
end
|
||||
244
garrysmod/addons/tacrp/lua/entities/tacrp_gas_cloud.lua
Normal file
244
garrysmod/addons/tacrp/lua/entities/tacrp_gas_cloud.lua
Normal file
@@ -0,0 +1,244 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Gas Cloud"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
ENT.Particles = nil
|
||||
ENT.SmokeRadius = 256
|
||||
ENT.SmokeColor = Color(125, 150, 50)
|
||||
ENT.BillowTime = 5
|
||||
ENT.Life = 15
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel( "models/weapons/w_eq_smokegrenade_thrown.mdl" )
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
self:SetSolid( SOLID_NONE )
|
||||
self:DrawShadow( false )
|
||||
|
||||
sound.EmitHint(SOUND_DANGER, self:GetPos(), 328, self.Life, self)
|
||||
else
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
self.Particles = {}
|
||||
|
||||
local amt = 20
|
||||
|
||||
for i = 1, amt do
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
smoke:SetVelocity( VectorRand() * 8 + (Angle(0, i * (360 / amt), 0):Forward() * 200) )
|
||||
smoke:SetStartAlpha( 0 )
|
||||
smoke:SetEndAlpha( 255 )
|
||||
smoke:SetStartSize( 0 )
|
||||
smoke:SetEndSize( self.SmokeRadius )
|
||||
smoke:SetRoll( math.Rand(-180, 180) )
|
||||
smoke:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
smoke:SetColor( self.SmokeColor.r, self.SmokeColor.g, self.SmokeColor.b )
|
||||
smoke:SetAirResistance( 75 )
|
||||
smoke:SetPos( self:GetPos() )
|
||||
smoke:SetCollide( true )
|
||||
smoke:SetBounce( 0.2 )
|
||||
smoke:SetLighting( false )
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke.bt = CurTime() + self.BillowTime
|
||||
smoke.dt = CurTime() + self.BillowTime + self.Life
|
||||
smoke.ft = CurTime() + self.BillowTime + self.Life + math.Rand(2.5, 5)
|
||||
smoke:SetDieTime(smoke.ft)
|
||||
smoke.life = self.Life
|
||||
smoke.billowed = false
|
||||
smoke.radius = self.SmokeRadius
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
|
||||
local prog = 1
|
||||
local alph = 0
|
||||
|
||||
if pa.ft < CurTime() then
|
||||
return
|
||||
elseif pa.dt < CurTime() then
|
||||
local d = (CurTime() - pa.dt) / (pa.ft - pa.dt)
|
||||
|
||||
alph = 1 - d
|
||||
elseif pa.bt < CurTime() then
|
||||
alph = 1
|
||||
else
|
||||
local d = math.Clamp(pa:GetLifeTime() / (pa.bt - CurTime()), 0, 1)
|
||||
|
||||
prog = (-d ^ 2) + (2 * d)
|
||||
|
||||
alph = d
|
||||
end
|
||||
|
||||
pa:SetEndSize( pa.radius * prog )
|
||||
pa:SetStartSize( pa.radius * prog )
|
||||
|
||||
alph = math.Clamp(alph, 0, 1)
|
||||
|
||||
pa:SetStartAlpha(50 * alph)
|
||||
pa:SetEndAlpha(50 * alph)
|
||||
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
table.insert(self.Particles, smoke)
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
self.dt = CurTime() + self.Life + self.BillowTime
|
||||
end
|
||||
|
||||
|
||||
function ENT:Think()
|
||||
|
||||
if SERVER then
|
||||
if !self:GetOwner():IsValid() then self:Remove() return end
|
||||
|
||||
local o = self:GetOwner()
|
||||
local origin = self:GetPos() + Vector(0, 0, 16)
|
||||
|
||||
local ttt = TacRP.GetBalanceMode() == TacRP.BALANCE_TTT
|
||||
local threshold = ttt and 50 or 25
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(self:GetOwner())
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamageType(DMG_NERVEGAS)
|
||||
dmg:SetDamageForce(Vector(0, 0, 0))
|
||||
dmg:SetDamagePosition(self:GetPos())
|
||||
dmg:SetDamageCustom(1024) -- immersive death
|
||||
for i, k in pairs(ents.FindInSphere(origin, 300)) do
|
||||
if k:IsPlayer() or k:IsNPC() or k:IsNextBot() then
|
||||
|
||||
if k:IsPlayer() then
|
||||
local wep = k:GetActiveWeapon()
|
||||
if IsValid(wep) and wep.ArcticTacRP and wep:GetValue("GasImmunity") then
|
||||
continue
|
||||
end
|
||||
end
|
||||
|
||||
local tr = util.TraceLine({
|
||||
start = origin,
|
||||
endpos = k:EyePos() or k:WorldSpaceCenter(),
|
||||
filter = self,
|
||||
mask = MASK_SOLID_BRUSHONLY
|
||||
})
|
||||
if tr.Fraction < 1 then continue end
|
||||
|
||||
dmg:SetDamage(math.Rand(3, 6))
|
||||
|
||||
if k:IsPlayer() and TacRP.ConVars["gas_affectplayers"]:GetBool() then
|
||||
k:TakeDamageInfo(dmg)
|
||||
|
||||
local timername = "tacrp_gas_" .. k:EntIndex()
|
||||
local reps = 6
|
||||
|
||||
if timer.Exists(timername) then
|
||||
reps = math.Clamp(timer.RepsLeft(timername) + 3, reps, 20)
|
||||
timer.Remove(timername)
|
||||
end
|
||||
timer.Create(timername, ttt and 5 or 1.5, reps, function()
|
||||
if !IsValid(k) or !k:Alive() or (engine.ActiveGamemode() == "terrortown" and (GetRoundState() == ROUND_PREP or GetRoundState() == ROUND_POST)) then
|
||||
timer.Remove(timername)
|
||||
return
|
||||
end
|
||||
k:ScreenFade( SCREENFADE.IN, Color(125, 150, 50, 3), 0.1, 0 )
|
||||
if k:Health() > threshold then
|
||||
local d = DamageInfo()
|
||||
d:SetDamageType(DMG_NERVEGAS)
|
||||
d:SetDamage(1)
|
||||
d:SetInflictor(IsValid(self) and self or o)
|
||||
d:SetAttacker(o)
|
||||
d:SetDamageForce(k:GetForward())
|
||||
d:SetDamagePosition(k:GetPos())
|
||||
d:SetDamageCustom(1024)
|
||||
k:TakeDamageInfo(d)
|
||||
else
|
||||
k:ViewPunch(Angle(math.Rand(-2, 2), 0, 0))
|
||||
end
|
||||
if ttt or math.random() <= 0.333 then
|
||||
k:EmitSound("ambient/voices/cough" .. math.random(1, 4) .. ".wav", 80, math.Rand(95, 105))
|
||||
end
|
||||
end)
|
||||
elseif k:IsNPC() and TacRP.ConVars["gas_affectnpcs"]:GetBool() and (k:GetHullType() == HULL_HUMAN or k:GetHullType() == HULL_WIDE_HUMAN) then
|
||||
k:SetCurrentWeaponProficiency(WEAPON_PROFICIENCY_POOR)
|
||||
local rng = math.random()
|
||||
if rng <= 0.3 then
|
||||
k:SetSchedule(SCHED_RUN_RANDOM)
|
||||
elseif rng <= 0.8 then
|
||||
k:SetSchedule(SCHED_COWER)
|
||||
end
|
||||
k:TakeDamageInfo(dmg)
|
||||
elseif !k:IsNPC() and !k:IsPlayer() then
|
||||
k:TakeDamageInfo(dmg)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:NextThink(CurTime() + 1)
|
||||
|
||||
if self.dt < CurTime() then
|
||||
SafeRemoveEntity(self)
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
return false
|
||||
end
|
||||
|
||||
-- cs gas strips armor and will try not deal lethal damage
|
||||
hook.Add("EntityTakeDamage", "tacrp_gas", function(ent, dmg)
|
||||
if dmg:GetDamageType() == DMG_NERVEGAS and bit.band(dmg:GetDamageCustom(), 1024) == 1024 then
|
||||
if ent:IsPlayer() then
|
||||
local threshold = TacRP.GetBalanceMode() == TacRP.BALANCE_TTT and 50 or 25
|
||||
local wep = ent:GetActiveWeapon()
|
||||
if IsValid(wep) and wep.ArcticTacRP and wep:GetValue("GasImmunity") then
|
||||
dmg:SetDamage(0)
|
||||
elseif ent:Health() - dmg:GetDamage() <= threshold then
|
||||
dmg:SetDamage(math.max(0, ent:Health() - threshold))
|
||||
end
|
||||
if dmg:GetDamage() <= 0 then
|
||||
ent.TacRPGassed = true
|
||||
end
|
||||
elseif ent:IsNPC() then
|
||||
if ent:Health() <= dmg:GetDamage() then
|
||||
ent:SetHealth(1)
|
||||
dmg:SetDamage(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("PostEntityTakeDamage", "tacrp_gas", function(ent, dmg, took)
|
||||
if ent:IsPlayer() and dmg:GetDamageType() == DMG_NERVEGAS and bit.band(dmg:GetDamageCustom(), 1024) == 1024 then
|
||||
ent:SetArmor(math.max(0, ent:Armor() - dmg:GetDamage()))
|
||||
if ent.TacRPGassed or (dmg:GetDamage() > 0 and IsValid(dmg:GetInflictor()) and (dmg:GetInflictor():GetClass() == "tacrp_gas_cloud" or dmg:GetInflictor():GetClass() == "tacrp_smoke_cloud_ninja")) then
|
||||
local distsqr = dmg:GetInflictor():GetPos():DistToSqr(ent:GetPos())
|
||||
if distsqr <= 350 * 350 then
|
||||
ent:SetNWFloat("TacRPGasEnd", CurTime() + 10)
|
||||
ent.TacRPGassed = nil
|
||||
ent:ScreenFade( SCREENFADE.IN, Color(125, 150, 50, 100), 0.5, 0 )
|
||||
ent:ViewPunch(Angle(math.Rand(-1, 1), math.Rand(-1, 1), math.Rand(-1, 1)))
|
||||
local ttt = TacRP.GetBalanceMode() == TacRP.BALANCE_TTT
|
||||
if ttt or math.random() <= 0.333 then
|
||||
ent:EmitSound("ambient/voices/cough" .. math.random(1, 4) .. ".wav", 80, math.Rand(95, 105))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
216
garrysmod/addons/tacrp/lua/entities/tacrp_heal_cloud.lua
Normal file
216
garrysmod/addons/tacrp/lua/entities/tacrp_heal_cloud.lua
Normal file
@@ -0,0 +1,216 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Healing Gas Cloud"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
local SmokeColor = Color(125, 25, 125)
|
||||
|
||||
ENT.Particles = nil
|
||||
ENT.SmokeRadius = 256
|
||||
ENT.SmokeColor = SmokeColor
|
||||
ENT.BillowTime = 2.5
|
||||
ENT.Life = 15
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel( "models/weapons/w_eq_smokegrenade_thrown.mdl" )
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
self:SetSolid( SOLID_NONE )
|
||||
self:DrawShadow( false )
|
||||
else
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
self.Particles = {}
|
||||
|
||||
local amt = 20
|
||||
|
||||
for i = 1, amt do
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
smoke:SetVelocity( VectorRand() * 8 + (Angle(0, i * (360 / amt), 0):Forward() * 200) )
|
||||
smoke:SetStartAlpha( 0 )
|
||||
smoke:SetEndAlpha( 255 )
|
||||
smoke:SetStartSize( 0 )
|
||||
smoke:SetEndSize( self.SmokeRadius )
|
||||
smoke:SetRoll( math.Rand(-180, 180) )
|
||||
smoke:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
smoke:SetColor( self.SmokeColor.r, self.SmokeColor.g, self.SmokeColor.b )
|
||||
smoke:SetAirResistance( 75 )
|
||||
smoke:SetPos( self:GetPos() )
|
||||
smoke:SetCollide( true )
|
||||
smoke:SetBounce( 0.2 )
|
||||
smoke:SetLighting( false )
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke.bt = CurTime() + self.BillowTime
|
||||
smoke.dt = CurTime() + self.BillowTime + self.Life
|
||||
smoke.ft = CurTime() + self.BillowTime + self.Life + math.Rand(2.5, 5)
|
||||
smoke:SetDieTime(smoke.ft)
|
||||
smoke.life = self.Life
|
||||
smoke.billowed = false
|
||||
smoke.radius = self.SmokeRadius / 2
|
||||
smoke.offset_r = math.Rand(0, 100)
|
||||
smoke.offset_g = math.Rand(0, 100)
|
||||
smoke.offset_b = math.Rand(0, 100)
|
||||
smoke.pulsate_time = math.Rand(0.9, 3)
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
if !self then return end
|
||||
|
||||
local prog = 1
|
||||
local alph = 0
|
||||
|
||||
if pa.ft < CurTime() then
|
||||
return
|
||||
elseif pa.dt < CurTime() then
|
||||
local d = (CurTime() - pa.dt) / (pa.ft - pa.dt)
|
||||
|
||||
alph = 1 - d
|
||||
elseif pa.bt < CurTime() then
|
||||
alph = 1
|
||||
else
|
||||
local d = math.Clamp(pa:GetLifeTime() / (pa.bt - CurTime()), 0, 1)
|
||||
|
||||
prog = (-d ^ 2) + (2 * d)
|
||||
|
||||
alph = d
|
||||
end
|
||||
|
||||
pa:SetColor(
|
||||
SmokeColor.r + math.sin((CurTime() * pa.pulsate_time) + pa.offset_r) * 20,
|
||||
SmokeColor.g + math.sin((CurTime() * pa.pulsate_time) + pa.offset_g) * 20,
|
||||
SmokeColor.b + math.sin((CurTime() * pa.pulsate_time) + pa.offset_b) * 20
|
||||
)
|
||||
|
||||
pa:SetEndSize( pa.radius * prog )
|
||||
pa:SetStartSize( pa.radius * prog )
|
||||
|
||||
alph = math.Clamp(alph, 0, 1)
|
||||
|
||||
pa:SetStartAlpha(35 * alph)
|
||||
pa:SetEndAlpha(35 * alph)
|
||||
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
table.insert(self.Particles, smoke)
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
self.dt = CurTime() + self.Life + self.BillowTime
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
|
||||
if SERVER then
|
||||
if !self:GetOwner():IsValid() then self:Remove() return end
|
||||
local origin = self:GetPos() + Vector(0, 0, 16)
|
||||
|
||||
for i, k in pairs(ents.FindInSphere(origin, self.SmokeRadius)) do
|
||||
if (k:IsPlayer() or k:IsNPC() or k:IsNextBot()) then
|
||||
local tr = util.TraceLine({
|
||||
start = origin,
|
||||
endpos = k:EyePos() or k:WorldSpaceCenter(),
|
||||
filter = self,
|
||||
mask = MASK_SOLID_BRUSHONLY
|
||||
})
|
||||
if tr.Fraction < 1 then continue end
|
||||
if k:IsPlayer() and (k.TacRPNextCanHealthGasTime or 0) <= CurTime() then
|
||||
local ply = k
|
||||
if ply:Health() < ply:GetMaxHealth() then
|
||||
local amt = TacRP.ConVars["healnade_heal"]:GetInt()
|
||||
local ret = {amt}
|
||||
hook.Run("TacRP_MedkitHeal", self, self:GetOwner(), ply, ret)
|
||||
amt = ret and ret[1] or amt
|
||||
ply:SetHealth(math.min(ply:Health() + amt, ply:GetMaxHealth()))
|
||||
elseif ply:Armor() > 0 and ply:Armor() <= ply:GetMaxArmor() and TacRP.ConVars["healnade_armor"]:GetInt() > 0 then
|
||||
ply:SetArmor(math.min(ply:Armor() + TacRP.ConVars["healnade_armor"]:GetInt(), ply:GetMaxArmor()))
|
||||
end
|
||||
k.TacRPNextCanHealthGasTime = CurTime() + 0.19
|
||||
elseif !k:IsPlayer() and (k.TacRPNextCanHealthGasTime or 0) <= CurTime() then
|
||||
if TacRP.EntityIsNecrotic(k) then
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker(self:GetOwner() or self)
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamageType(DMG_NERVEGAS)
|
||||
dmginfo:SetDamage(TacRP.ConVars["healnade_damage"]:GetInt())
|
||||
k:TakeDamageInfo(dmginfo)
|
||||
elseif k:Health() < k:GetMaxHealth() then
|
||||
local amt = TacRP.ConVars["healnade_heal"]:GetInt()
|
||||
local ret = {amt}
|
||||
hook.Run("TacRP_MedkitHeal", self, self:GetOwner(), k, ret)
|
||||
amt = ret and ret[1] or amt
|
||||
k:SetHealth(math.min(k:Health() + amt, k:GetMaxHealth()))
|
||||
end
|
||||
k.TacRPNextCanHealthGasTime = CurTime() + 0.19
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:NextThink(CurTime() + 0.2)
|
||||
|
||||
if self.dt < CurTime() then
|
||||
SafeRemoveEntity(self)
|
||||
end
|
||||
else
|
||||
if (self.NextEmitTime or 0) > CurTime() then return end
|
||||
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add("effects/spark", self:GetPos())
|
||||
smoke:SetVelocity( Vector(math.Rand(-1, 1), math.Rand(-1, 1), math.Rand(0, 1)) * 300 )
|
||||
smoke:SetStartAlpha( 255 )
|
||||
smoke:SetEndAlpha( 0 )
|
||||
smoke:SetStartSize( 0 )
|
||||
smoke:SetEndSize( 0 )
|
||||
smoke:SetRoll( math.Rand(-180, 180) )
|
||||
smoke:SetRollDelta( math.Rand(-32, 32) )
|
||||
smoke:SetColor( 255, 255, 255 )
|
||||
smoke:SetAirResistance( 100 )
|
||||
smoke:SetPos( self:GetPos() )
|
||||
smoke:SetCollide( true )
|
||||
smoke:SetBounce( 1 )
|
||||
smoke:SetLighting( false )
|
||||
smoke:SetDieTime(2)
|
||||
smoke:SetGravity(Vector(0, 0, -100))
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke.hl2 = CurTime() + 1
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
|
||||
if pa.hl2 < CurTime() and !pa.alreadyhl then
|
||||
pa:SetStartSize(8)
|
||||
pa:SetEndSize(0)
|
||||
pa:SetLifeTime(0)
|
||||
pa:SetDieTime(math.Rand(0.25, 0.5))
|
||||
pa:SetVelocity(VectorRand() * 300)
|
||||
pa:SetGravity(Vector(0, 0, -200))
|
||||
pa:SetAirResistance( 200 )
|
||||
pa.alreadyhl = true
|
||||
else
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end
|
||||
end )
|
||||
|
||||
emitter:Finish()
|
||||
|
||||
self.NextEmitTime = CurTime() + 0.02
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
return false
|
||||
end
|
||||
218
garrysmod/addons/tacrp/lua/entities/tacrp_heal_cloud_p2a1.lua
Normal file
218
garrysmod/addons/tacrp/lua/entities/tacrp_heal_cloud_p2a1.lua
Normal file
@@ -0,0 +1,218 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Healing Gas Cloud"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
local SmokeColor = Color(125, 25, 125)
|
||||
|
||||
ENT.Particles = nil
|
||||
ENT.SmokeRadius = 128
|
||||
ENT.SmokeColor = SmokeColor
|
||||
ENT.BillowTime = 0.5
|
||||
ENT.Life = 5
|
||||
|
||||
ENT.TacRPSmoke = true
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel( "models/weapons/w_eq_smokegrenade_thrown.mdl" )
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
self:SetSolid( SOLID_NONE )
|
||||
self:DrawShadow( false )
|
||||
else
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
self.Particles = {}
|
||||
|
||||
local amt = 12
|
||||
|
||||
for i = 1, amt do
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
smoke:SetVelocity( VectorRand() * 8 + (Angle(0, i * (360 / amt), 0):Forward() * 120) )
|
||||
smoke:SetStartAlpha( 0 )
|
||||
smoke:SetEndAlpha( 255 )
|
||||
smoke:SetStartSize( 0 )
|
||||
smoke:SetEndSize( self.SmokeRadius )
|
||||
smoke:SetRoll( math.Rand(-180, 180) )
|
||||
smoke:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
smoke:SetColor( self.SmokeColor.r, self.SmokeColor.g, self.SmokeColor.b )
|
||||
smoke:SetAirResistance( 75 )
|
||||
smoke:SetPos( self:GetPos() )
|
||||
smoke:SetCollide( true )
|
||||
smoke:SetBounce( 0.2 )
|
||||
smoke:SetLighting( false )
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke.bt = CurTime() + self.BillowTime
|
||||
smoke.dt = CurTime() + self.BillowTime + self.Life
|
||||
smoke.ft = CurTime() + self.BillowTime + self.Life + math.Rand(2.5, 5)
|
||||
smoke:SetDieTime(smoke.ft)
|
||||
smoke.life = self.Life
|
||||
smoke.billowed = false
|
||||
smoke.radius = self.SmokeRadius / 2
|
||||
smoke.offset_r = math.Rand(0, 100)
|
||||
smoke.offset_g = math.Rand(0, 100)
|
||||
smoke.offset_b = math.Rand(0, 100)
|
||||
smoke.pulsate_time = math.Rand(0.9, 3)
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
if !self then return end
|
||||
|
||||
local prog = 1
|
||||
local alph = 0
|
||||
|
||||
if pa.ft < CurTime() then
|
||||
return
|
||||
elseif pa.dt < CurTime() then
|
||||
local d = (CurTime() - pa.dt) / (pa.ft - pa.dt)
|
||||
|
||||
alph = 1 - d
|
||||
elseif pa.bt < CurTime() then
|
||||
alph = 1
|
||||
else
|
||||
local d = math.Clamp(pa:GetLifeTime() / (pa.bt - CurTime()), 0, 1)
|
||||
|
||||
prog = (-d ^ 2) + (2 * d)
|
||||
|
||||
alph = d
|
||||
end
|
||||
|
||||
pa:SetColor(
|
||||
SmokeColor.r + math.sin((CurTime() * pa.pulsate_time) + pa.offset_r) * 20,
|
||||
SmokeColor.g + math.sin((CurTime() * pa.pulsate_time) + pa.offset_g) * 20,
|
||||
SmokeColor.b + math.sin((CurTime() * pa.pulsate_time) + pa.offset_b) * 20
|
||||
)
|
||||
|
||||
pa:SetEndSize( pa.radius * prog )
|
||||
pa:SetStartSize( pa.radius * prog )
|
||||
|
||||
alph = math.Clamp(alph, 0, 1)
|
||||
|
||||
pa:SetStartAlpha(35 * alph)
|
||||
pa:SetEndAlpha(35 * alph)
|
||||
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
table.insert(self.Particles, smoke)
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
self.dt = CurTime() + self.Life + self.BillowTime
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
|
||||
if SERVER then
|
||||
if !self:GetOwner():IsValid() then self:Remove() return end
|
||||
local origin = self:GetPos() + Vector(0, 0, 16)
|
||||
|
||||
for i, k in pairs(ents.FindInSphere(origin, self.SmokeRadius)) do
|
||||
if (k:IsPlayer() or k:IsNPC() or k:IsNextBot()) then
|
||||
local tr = util.TraceLine({
|
||||
start = origin,
|
||||
endpos = k:EyePos() or k:WorldSpaceCenter(),
|
||||
filter = self,
|
||||
mask = MASK_SOLID_BRUSHONLY
|
||||
})
|
||||
if tr.Fraction < 1 then continue end
|
||||
if k:IsPlayer() and (k.TacRPNextCanHealthGasTime or 0) <= CurTime() then
|
||||
local ply = k
|
||||
if ply:Health() < ply:GetMaxHealth() then
|
||||
local amt = TacRP.ConVars["healnade_heal"]:GetInt()
|
||||
local ret = {amt}
|
||||
hook.Run("TacRP_MedkitHeal", self, self:GetOwner(), ply, ret)
|
||||
amt = ret and ret[1] or amt
|
||||
ply:SetHealth(math.min(ply:Health() + amt, ply:GetMaxHealth()))
|
||||
elseif ply:Armor() > 0 and ply:Armor() <= ply:GetMaxArmor() and TacRP.ConVars["healnade_armor"]:GetInt() > 0 then
|
||||
ply:SetArmor(math.min(ply:Armor() + TacRP.ConVars["healnade_armor"]:GetInt(), ply:GetMaxArmor()))
|
||||
end
|
||||
k.TacRPNextCanHealthGasTime = CurTime() + 0.74
|
||||
elseif !k:IsPlayer() and (k.TacRPNextCanHealthGasTime or 0) <= CurTime() then
|
||||
if TacRP.EntityIsNecrotic(k) then
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker(self:GetOwner() or self)
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamageType(DMG_NERVEGAS)
|
||||
dmginfo:SetDamage(TacRP.ConVars["healnade_damage"]:GetInt())
|
||||
k:TakeDamageInfo(dmginfo)
|
||||
elseif k:Health() < k:GetMaxHealth() then
|
||||
local amt = TacRP.ConVars["healnade_heal"]:GetInt()
|
||||
local ret = {amt}
|
||||
hook.Run("TacRP_MedkitHeal", self, self:GetOwner(), k, ret)
|
||||
amt = ret and ret[1] or amt
|
||||
k:SetHealth(math.min(k:Health() + amt, k:GetMaxHealth()))
|
||||
end
|
||||
k.TacRPNextCanHealthGasTime = CurTime() + 0.74
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:NextThink(CurTime() + 0.75)
|
||||
|
||||
if self.dt < CurTime() then
|
||||
SafeRemoveEntity(self)
|
||||
end
|
||||
else
|
||||
if (self.NextEmitTime or 0) > CurTime() then return end
|
||||
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add("effects/spark", self:GetPos())
|
||||
smoke:SetVelocity( Vector(math.Rand(-1, 1), math.Rand(-1, 1), math.Rand(0, 1)) * self.SmokeRadius )
|
||||
smoke:SetStartAlpha( 255 )
|
||||
smoke:SetEndAlpha( 0 )
|
||||
smoke:SetStartSize( 0 )
|
||||
smoke:SetEndSize( 0 )
|
||||
smoke:SetRoll( math.Rand(-180, 180) )
|
||||
smoke:SetRollDelta( math.Rand(-32, 32) )
|
||||
smoke:SetColor( 255, 255, 255 )
|
||||
smoke:SetAirResistance( 100 )
|
||||
smoke:SetPos( self:GetPos() )
|
||||
smoke:SetCollide( true )
|
||||
smoke:SetBounce( 1 )
|
||||
smoke:SetLighting( false )
|
||||
smoke:SetDieTime(2)
|
||||
smoke:SetGravity(Vector(0, 0, -100))
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke.hl2 = CurTime() + self.BillowTime
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
|
||||
if pa.hl2 < CurTime() and !pa.alreadyhl then
|
||||
pa:SetStartSize(4)
|
||||
pa:SetEndSize(0)
|
||||
pa:SetLifeTime(0)
|
||||
pa:SetDieTime(math.Rand(0.25, 0.5))
|
||||
pa:SetVelocity(VectorRand() * 300)
|
||||
pa:SetGravity(Vector(0, 0, -200))
|
||||
pa:SetAirResistance( 200 )
|
||||
pa.alreadyhl = true
|
||||
else
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end
|
||||
end )
|
||||
|
||||
emitter:Finish()
|
||||
|
||||
self.NextEmitTime = CurTime() + 0.1
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
return false
|
||||
end
|
||||
83
garrysmod/addons/tacrp/lua/entities/tacrp_nuke_cloud.lua
Normal file
83
garrysmod/addons/tacrp/lua/entities/tacrp_nuke_cloud.lua
Normal file
@@ -0,0 +1,83 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Nuclear Radiation"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
ENT.Life = 10
|
||||
|
||||
ENT.MaxRadius = 7500
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel( "models/weapons/w_eq_smokegrenade_thrown.mdl" )
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
self:SetSolid( SOLID_NONE )
|
||||
self:DrawShadow( false )
|
||||
end
|
||||
|
||||
self.SpawnTime = CurTime()
|
||||
self.dt = CurTime() + self.Life
|
||||
|
||||
util.ScreenShake(self:GetPos(), 16, 30, self.Life, self.MaxRadius)
|
||||
|
||||
if CLIENT then return end
|
||||
|
||||
for i, k in pairs(ents.FindInSphere(self:GetPos(), self.MaxRadius)) do
|
||||
if k:GetClass() == "func_breakable_surf" then
|
||||
k:Fire("shatter", "", 0)
|
||||
elseif k:GetClass() == "func_breakable" then
|
||||
k:Fire("break", "", 0)
|
||||
end
|
||||
|
||||
local phys = k:GetPhysicsObject()
|
||||
|
||||
if IsValid(phys) then
|
||||
local vec = (k:GetPos() - self:GetPos()) * 500
|
||||
phys:ApplyForceCenter(vec)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:RadiationAttack()
|
||||
local d = (CurTime() - self.SpawnTime) / self.Life
|
||||
local radius = self.MaxRadius * d
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamage((1 - d) * 5000)
|
||||
dmg:SetDamageType(DMG_RADIATION)
|
||||
dmg:SetDamagePosition(self:GetPos())
|
||||
dmg:SetAttacker(self:GetOwner() or self.Attacker)
|
||||
dmg:SetInflictor(self)
|
||||
|
||||
for i, k in pairs(ents.FindInSphere(self:GetPos(), radius)) do
|
||||
if !IsValid(k) then continue end
|
||||
constraint.RemoveAll(k)
|
||||
k:TakeDamageInfo(dmg)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if SERVER then
|
||||
if !self:GetOwner():IsValid() then self:Remove() return end
|
||||
|
||||
self:RadiationAttack()
|
||||
|
||||
self:NextThink(CurTime() + 1)
|
||||
|
||||
if self.dt < CurTime() then
|
||||
SafeRemoveEntity(self)
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
return false
|
||||
end
|
||||
84
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_3gl.lua
Normal file
84
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_3gl.lua
Normal file
@@ -0,0 +1,84 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm 3GL"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"^TacRP/weapons/grenade/40mm_explode-1.wav",
|
||||
"^TacRP/weapons/grenade/40mm_explode-2.wav",
|
||||
"^TacRP/weapons/grenade/40mm_explode-3.wav",
|
||||
}
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat() * (self.NPCDamage and 0.5 or 1)
|
||||
local dmg = 55
|
||||
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 200, dmg * mult)
|
||||
self:ImpactTraceAttack(ent, dmg * mult, 50)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("helicoptermegabomb", fx)
|
||||
end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 100, math.Rand(103, 110))
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(10)
|
||||
smoke:SetEndSize(math.Rand(20, 40))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(-self:GetAngles():Forward() * 400 + (VectorRand() * 10))
|
||||
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.5, 1))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,76 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm Baton"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/flare.mdl"
|
||||
ENT.CollisionSphere = 1
|
||||
|
||||
ENT.IsRocket = false
|
||||
|
||||
ENT.InstantFuse = false
|
||||
ENT.RemoteFuse = false
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.ExplodeOnDamage = false
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
ENT.SmokeTrail = false
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Initialize()
|
||||
BaseClass.Initialize(self)
|
||||
if SERVER then
|
||||
self:GetPhysicsObject():SetDragCoefficient(0)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
if self.Impacted then return end
|
||||
self.Impacted = true
|
||||
|
||||
local tgt = data.HitEntity
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local d = data.OurOldVelocity:GetNormalized()
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetInflictor(IsValid(self.Inflictor) and self.Inflictor or self)
|
||||
dmg:SetDamage(500)
|
||||
dmg:SetDamageType(DMG_CLUB)
|
||||
dmg:SetDamagePosition(data.HitPos)
|
||||
dmg:SetDamageForce(d * 5000)
|
||||
|
||||
local atktr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = data.HitPos,
|
||||
filter = self
|
||||
})
|
||||
|
||||
-- TacRP.CancelBodyDamage(tgt, dmg, atktr.HitGroup)
|
||||
tgt:DispatchTraceAttack(dmg, atktr)
|
||||
|
||||
-- leave a bullet hole. Also may be able to hit things it can't collide with (like stuck C4)
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Damage = 0,
|
||||
Force = 1,
|
||||
Distance = 4,
|
||||
HullSize = 4,
|
||||
Tracer = 0,
|
||||
Dir = d,
|
||||
Src = data.HitPos - d,
|
||||
IgnoreEntity = self,
|
||||
Callback = function(atk, tr, dmginfo)
|
||||
dmginfo:SetInflictor(IsValid(self.Inflictor) and self.Inflictor or self)
|
||||
end
|
||||
})
|
||||
|
||||
self:Remove()
|
||||
return true
|
||||
end
|
||||
39
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_gas.lua
Normal file
39
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_gas.lua
Normal file
@@ -0,0 +1,39 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm CS Gas"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/smoke_explode-1.wav",
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
if self:WaterLevel() > 0 then self:Remove() return end
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 75)
|
||||
|
||||
local cloud = ents.Create( "TacRP_gas_cloud" )
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetOwner(attacker)
|
||||
cloud:Spawn()
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
48
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_he.lua
Normal file
48
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_he.lua
Normal file
@@ -0,0 +1,48 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm HE"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"^TacRP/weapons/grenade/frag_explode-1.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-2.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-3.wav",
|
||||
}
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat() * (self.NPCDamage and 0.25 or 1)
|
||||
local dmg = 150
|
||||
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 300, dmg * mult)
|
||||
self:ImpactTraceAttack(ent, dmg * mult, 100)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 125)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
50
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_heal.lua
Normal file
50
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_heal.lua
Normal file
@@ -0,0 +1,50 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm Medi-Smoke"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.BounceSounds = {
|
||||
"TacRP/weapons/grenade/smoke_bounce-1.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-2.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-3.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-4.wav",
|
||||
}
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/smoke_explode-1.wav",
|
||||
}
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
function ENT:Detonate()
|
||||
if self:WaterLevel() > 0 then self:Remove() return end
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 75)
|
||||
|
||||
local cloud = ents.Create( "TacRP_heal_cloud" )
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetOwner(attacker)
|
||||
cloud:Spawn()
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
54
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_heat.lua
Normal file
54
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_heat.lua
Normal file
@@ -0,0 +1,54 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm HEAT"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"^TacRP/weapons/grenade/frag_explode-1.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-2.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-3.wav",
|
||||
}
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
function ENT:Detonate()
|
||||
if self:WaterLevel() > 0 then self:Remove() return end
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 150, 25 * TacRP.ConVars["mult_damage_explosive"]:GetFloat())
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 75)
|
||||
|
||||
local cloud = ents.Create( "TacRP_fire_cloud" )
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
local ang = self:GetAngles()
|
||||
|
||||
ang:RotateAroundAxis(ang:Right(), 90)
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetAngles(ang)
|
||||
cloud:SetOwner(attacker)
|
||||
cloud:Spawn()
|
||||
|
||||
cloud:SetMoveType(MOVETYPE_NONE)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
@@ -0,0 +1,52 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm Beanbag"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.SmokeTrail = false
|
||||
ENT.BounceSounds = {
|
||||
"TacRP/weapons/grenade/flashbang_bounce-1.wav",
|
||||
"TacRP/weapons/grenade/flashbang_bounce-2.wav",
|
||||
"TacRP/weapons/grenade/flashbang_bounce-3.wav",
|
||||
}
|
||||
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
self:EmitSound("weapons/rpg/shotdown.wav", 90, 115)
|
||||
|
||||
if IsValid(data.HitEntity) then
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamage(Lerp((data.OurOldVelocity:Length() - 1000) / 4000, 0, 100))
|
||||
dmg:SetDamageType(DMG_CRUSH)
|
||||
dmg:SetDamageForce(data.OurOldVelocity:GetNormalized() * 5000)
|
||||
dmg:SetDamagePosition(data.HitPos)
|
||||
data.HitEntity:TakeDamageInfo(dmg)
|
||||
end
|
||||
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("ManhackSparks", fx)
|
||||
|
||||
SafeRemoveEntityDelayed(self, 3)
|
||||
return true
|
||||
end
|
||||
63
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_lvg.lua
Normal file
63
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_lvg.lua
Normal file
@@ -0,0 +1,63 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm LVG"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0.3
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"^TacRP/weapons/grenade/frag_explode-1.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-2.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-3.wav",
|
||||
}
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat() * (self.NPCDamage and 0.25 or 1)
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamageType(DMG_SONIC)
|
||||
dmg:SetDamagePosition(self:GetPos())
|
||||
dmg:SetDamage(100 * mult)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), 300)
|
||||
dmg:SetDamage(10)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), 512)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
fx:SetRadius(512)
|
||||
util.Effect("TacRP_flashexplosion", fx)
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
|
||||
TacRP.Flashbang(self, self:GetPos(), 1024, 2.5, 0.25, 1)
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 125, 110)
|
||||
self:EmitSound("TacRP/weapons/grenade/flashbang_explode-1.wav", 125, 90, 0.8)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:Impact()
|
||||
self:EmitSound("weapons/rpg/shotdown.wav", 90, 115)
|
||||
end
|
||||
120
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_ratshot.lua
Normal file
120
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_ratshot.lua
Normal file
@@ -0,0 +1,120 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm Ratshot"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.InstantFuse = false
|
||||
ENT.RemoteFuse = false
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"^TacRP/weapons/grenade/frag_explode-1.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-2.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-3.wav",
|
||||
}
|
||||
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Initialize()
|
||||
BaseClass.Initialize(self)
|
||||
if SERVER then
|
||||
self:SetTrigger(true)
|
||||
self:UseTriggerBounds(true, 96)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:StartTouch(ent)
|
||||
if SERVER and ent ~= self:GetOwner() and (ent:IsNPC() or ent:IsPlayer() or ent:IsNextBot()) then
|
||||
self:Detonate()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
local dir = self:GetForward()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local src = self:GetPos()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(src)
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
fx:SetMagnitude(4)
|
||||
fx:SetScale(1.5)
|
||||
fx:SetRadius(4)
|
||||
fx:SetNormal(dir)
|
||||
util.Effect("Sparks", fx)
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
|
||||
local mult = (self.NPCDamage and 0.25 or 1) * TacRP.ConVars["mult_damage_explosive"]:GetFloat()
|
||||
util.BlastDamage(self, attacker, src, 328, 90 * mult)
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 115, 105)
|
||||
self:EmitSound("physics/metal/metal_box_break1.wav", 100, 190, 0.5)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(10)
|
||||
smoke:SetEndSize(math.Rand(20, 40))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetVelocity(-self:GetAngles():Forward() * 400 + (VectorRand() * 10))
|
||||
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.5, 1))
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
|
||||
local spark = emitter:Add("effects/spark", self:GetPos())
|
||||
|
||||
spark:SetStartAlpha(255)
|
||||
spark:SetEndAlpha(255)
|
||||
|
||||
spark:SetStartSize(4)
|
||||
spark:SetEndSize(0)
|
||||
|
||||
spark:SetRoll(math.Rand(-180, 180))
|
||||
spark:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
spark:SetVelocity(-self:GetAngles():Forward() * 300 + (VectorRand() * 100))
|
||||
|
||||
spark:SetColor(255, 255, 255)
|
||||
spark:SetLighting(false)
|
||||
|
||||
spark:SetDieTime(math.Rand(0.1, 0.3))
|
||||
|
||||
spark:SetGravity(Vector(0, 0, 10))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,48 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm Smoke"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.BounceSounds = {
|
||||
"TacRP/weapons/grenade/smoke_bounce-1.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-2.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-3.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-4.wav",
|
||||
}
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/smoke_explode-1.wav",
|
||||
}
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
function ENT:Detonate()
|
||||
if self:WaterLevel() > 0 then self:Remove() return end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 75)
|
||||
|
||||
local cloud = ents.Create( "TacRP_smoke_cloud" )
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:Spawn()
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
132
garrysmod/addons/tacrp/lua/entities/tacrp_proj_ball.lua
Normal file
132
garrysmod/addons/tacrp/lua/entities/tacrp_proj_ball.lua
Normal file
@@ -0,0 +1,132 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Thrown Ball"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint_extras/w_baseball.mdl" --"models/weapons/w_models/w_baseball.mdl" -- TODO replace with hexed model
|
||||
|
||||
ENT.IsRocket = false
|
||||
|
||||
ENT.InstantFuse = false
|
||||
ENT.RemoteFuse = false
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.ExplodeOnDamage = false
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.SmokeTrail = false
|
||||
|
||||
ENT.Damage = 25
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Initialize()
|
||||
BaseClass.Initialize(self)
|
||||
if SERVER then
|
||||
self:GetPhysicsObject():SetDragCoefficient(0)
|
||||
self.StartPos = self:GetPos()
|
||||
self.Trail = util.SpriteTrail(self, 0, color_white, true, 4, 0, 0.1, 2, "trails/tube")
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:StartTouch(ent)
|
||||
if self.Impacted and (CurTime() - self.SpawnTime) > 0.05 and IsValid(ent) and ent:IsPlayer() and ent:GetNWFloat("TacRPScoutBall", 0) > CurTime() then
|
||||
ent:SetNWFloat("TacRPScoutBall", 0)
|
||||
SafeRemoveEntity(self)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:PhysicsCollide(data, collider)
|
||||
|
||||
if IsValid(data.HitEntity) and data.HitEntity:GetClass() == "func_breakable_surf" then
|
||||
self:FireBullets({
|
||||
Attacker = self:GetOwner(),
|
||||
Inflictor = self,
|
||||
Damage = 0,
|
||||
Distance = 32,
|
||||
Tracer = 0,
|
||||
Src = self:GetPos(),
|
||||
Dir = data.OurOldVelocity:GetNormalized(),
|
||||
})
|
||||
local pos, ang, vel = self:GetPos(), self:GetAngles(), data.OurOldVelocity
|
||||
self:SetAngles(ang)
|
||||
self:SetPos(pos)
|
||||
self:GetPhysicsObject():SetVelocityInstantaneous(vel * 0.5)
|
||||
return
|
||||
end
|
||||
|
||||
if self.Impacted then return end
|
||||
self.Impacted = true
|
||||
self:SetTrigger(true)
|
||||
self:UseTriggerBounds(true, 8)
|
||||
if IsValid(self.Trail) then
|
||||
self.Trail:Remove()
|
||||
end
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
if IsValid(data.HitEntity) then
|
||||
local d = data.OurOldVelocity:GetNormalized()
|
||||
|
||||
local tgtpos = data.HitPos
|
||||
local dist = (tgtpos - self.StartPos):Length()
|
||||
self.Damage = Lerp(math.Clamp(dist / 1500, 0, 1) ^ 1.5, 15, 50) * (data.HitEntity:IsPlayer() and 1 or 1.5)
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetInflictor(IsValid(self.Inflictor) and self.Inflictor or self)
|
||||
dmg:SetDamage(self.Damage)
|
||||
dmg:SetDamageType(DMG_SLASH)
|
||||
dmg:SetDamageForce(d * 10000)
|
||||
dmg:SetDamagePosition(data.HitPos)
|
||||
|
||||
if dist > 200 then
|
||||
data.HitEntity.TacRPBashSlow = true
|
||||
end
|
||||
|
||||
if data.HitEntity:IsPlayer() then
|
||||
local wep = data.HitEntity:GetActiveWeapon()
|
||||
if IsValid(wep) and wep.ArcticTacRP then
|
||||
wep:SetBreath(0)
|
||||
wep:SetOutOfBreath(true)
|
||||
end
|
||||
end
|
||||
|
||||
if data.HitEntity:IsPlayer() or data.HitEntity:IsNPC() or data.HitEntity:IsNextBot() then
|
||||
if dist >= 1500 then
|
||||
data.HitEntity:EmitSound("tacrp/sandman/pl_impact_stun_range.wav", 100)
|
||||
else
|
||||
data.HitEntity:EmitSound("tacrp/sandman/pl_impact_stun.wav", 90)
|
||||
end
|
||||
else
|
||||
data.HitEntity:EmitSound("tacrp/sandman/baseball_hitworld" .. math.random(1, 3) .. ".wav", 90)
|
||||
end
|
||||
|
||||
if data.HitEntity:IsNPC() or data.HitEntity:IsNextBot() then
|
||||
data.HitEntity:SetVelocity(Vector(0, 0, 200))
|
||||
if data.HitEntity:IsNPC() then
|
||||
data.HitEntity:SetSchedule(SCHED_FLINCH_PHYSICS)
|
||||
end
|
||||
end
|
||||
|
||||
local atktr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = tgtpos,
|
||||
filter = self
|
||||
})
|
||||
|
||||
TacRP.CancelBodyDamage(data.HitEntity, dmg, atktr.HitGroup)
|
||||
data.HitEntity:SetPhysicsAttacker(attacker, 3)
|
||||
data.HitEntity:DispatchTraceAttack(dmg, atktr)
|
||||
|
||||
self:SetOwner(nil)
|
||||
else
|
||||
data.HitEntity:EmitSound("tacrp/sandman/baseball_hitworld" .. math.random(1, 3) .. ".wav", 90)
|
||||
end
|
||||
|
||||
SafeRemoveEntityDelayed(self, 5)
|
||||
-- self:GetPhysicsObject():SetVelocity(-data.HitNormal * data.OurNewVelocity:Length())
|
||||
end
|
||||
618
garrysmod/addons/tacrp/lua/entities/tacrp_proj_base.lua
Normal file
618
garrysmod/addons/tacrp/lua/entities/tacrp_proj_base.lua
Normal file
@@ -0,0 +1,618 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Base Projectile"
|
||||
ENT.Category = ""
|
||||
|
||||
ENT.Spawnable = false
|
||||
ENT.Model = ""
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
ENT.Material = false // custom material
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.Sticky = false // projectile sticks on impact
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.TimeFuse = false // projectile will arm after this amount of time
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
ENT.StickyFuse = false // projectile becomes timed after sticking.
|
||||
|
||||
ENT.SafetyFuse = 0 // impact fuse hitting too early will not detonate
|
||||
|
||||
ENT.RemoveOnImpact = false
|
||||
ENT.ExplodeOnImpact = false
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false // projectile explodes when it enters water
|
||||
|
||||
ENT.Defusable = false // press E on the projectile to defuse it
|
||||
ENT.DefuseOnDamage = false
|
||||
|
||||
ENT.ImpactDamage = 50
|
||||
ENT.ImpactDamageType = DMG_CRUSH + DMG_CLUB
|
||||
|
||||
ENT.Delay = 0 // after being triggered and this amount of time has passed, the projectile will explode.
|
||||
|
||||
ENT.SoundHint = false // Emit a sound hint so NPCs can react
|
||||
ENT.SoundHintDelay = 0 // Delay after spawn
|
||||
ENT.SoundHintRadius = 328
|
||||
ENT.SoundHintDuration = 1
|
||||
|
||||
ENT.Armed = false
|
||||
|
||||
ENT.SmokeTrail = false // leaves trail of smoke
|
||||
ENT.FlareColor = nil
|
||||
ENT.FlareSizeMin = 200
|
||||
ENT.FlareSizeMax = 250
|
||||
|
||||
|
||||
// Guided projectile related
|
||||
ENT.SteerDelay = 0 // Delay before steering logic kicks in
|
||||
ENT.SteerSpeed = 60 // Turn rate in degrees per second
|
||||
ENT.SteerBrake = 0 // Amount of speed to slow down by when turning
|
||||
ENT.SeekerAngle = 180 // Angle difference (degrees) above which projectile loses target
|
||||
ENT.SeekerExplodeRange = 256 // Distance to the target below which the missile will immediately explode
|
||||
ENT.SeekerExplodeSnapPosition = true // When exploding on a seeked target, teleport to the entity's position for more damage
|
||||
ENT.SeekerExplodeAngle = 180 // Angle tolerance (degrees) below which detonation can happen
|
||||
|
||||
ENT.TopAttack = false // This missile will attack from the top
|
||||
ENT.TopAttackHeight = 512 // Distance above target to top attack
|
||||
ENT.TopAttackDistance = 128 // Distance from target to stop top attacking
|
||||
|
||||
ENT.RocketLifetime = 30 // Rocket will cut after this time
|
||||
|
||||
ENT.MinSpeed = 0
|
||||
ENT.MaxSpeed = 0
|
||||
ENT.Acceleration = 0
|
||||
|
||||
ENT.LeadTarget = false // account for target's velocity and distance
|
||||
ENT.SuperSteerTime = 0 // Amount of time where turn rate is boosted
|
||||
ENT.SuperSteerSpeed = 100 // Boosted turn rate in degrees per seconds
|
||||
|
||||
ENT.NoReacquire = true // If target is lost, it cannot be tracked anymore
|
||||
ENT.FlareRedirectChance = 0
|
||||
|
||||
ENT.LockOnEntity = NULL
|
||||
ENT.TargetPos = nil
|
||||
|
||||
ENT.AudioLoop = nil
|
||||
ENT.BounceSounds = nil
|
||||
ENT.CollisionSphere = nil
|
||||
ENT.GunshipWorkaround = true
|
||||
|
||||
// Tell LVS to not ricochet us
|
||||
ENT.DisableBallistics = true
|
||||
|
||||
ENT.TopAttacking = false
|
||||
ENT.StartSuperSteerTime = 0
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Entity", 0, "Weapon")
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel(self.Model)
|
||||
self:SetMaterial(self.Material or "")
|
||||
if self.CollisionSphere then
|
||||
self:PhysicsInitSphere(self.CollisionSphere)
|
||||
else
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
end
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
|
||||
self:SetCollisionGroup(COLLISION_GROUP_PROJECTILE)
|
||||
if self.Defusable then
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
end
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if !phys:IsValid() then
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
phys:EnableDrag(false)
|
||||
phys:SetDragCoefficient(0)
|
||||
phys:SetBuoyancyRatio(0)
|
||||
phys:Wake()
|
||||
|
||||
if self.IsRocket then
|
||||
phys:EnableGravity(false)
|
||||
end
|
||||
|
||||
if self.TopAttack then
|
||||
self.TopAttacking = true
|
||||
end
|
||||
|
||||
self:SwitchTarget(self.LockOnEntity)
|
||||
end
|
||||
|
||||
self.StartSuperSteerTime = CurTime()
|
||||
self.SpawnTime = CurTime()
|
||||
self.NextFlareRedirectTime = 0
|
||||
|
||||
self.NPCDamage = IsValid(self:GetOwner()) and self:GetOwner():IsNPC() and !TacRP.ConVars["npc_equality"]:GetBool()
|
||||
|
||||
if self.AudioLoop then
|
||||
self.LoopSound = CreateSound(self, self.AudioLoop)
|
||||
self.LoopSound:Play()
|
||||
end
|
||||
|
||||
if self.InstantFuse then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
|
||||
self:OnInitialize()
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if self.LoopSound then
|
||||
self.LoopSound:Stop()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnTakeDamage(dmg)
|
||||
if self.Detonated then return end
|
||||
|
||||
// self:TakePhysicsDamage(dmg)
|
||||
|
||||
if self.ExplodeOnDamage then
|
||||
if IsValid(self:GetOwner()) and IsValid(dmg:GetAttacker()) then self:SetOwner(dmg:GetAttacker())
|
||||
else self.Attacker = dmg:GetAttacker() or self.Attacker end
|
||||
self:PreDetonate()
|
||||
elseif self.DefuseOnDamage and dmg:GetDamageType() != DMG_BLAST then
|
||||
self:EmitSound("physics/plastic/plastic_box_break" .. math.random(1, 2) .. ".wav", 70, math.Rand(95, 105))
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
fx:SetNormal(self:GetAngles():Forward())
|
||||
fx:SetAngles(self:GetAngles())
|
||||
util.Effect("ManhackSparks", fx)
|
||||
self.Detonated = true
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:PhysicsCollide(data, collider)
|
||||
if IsValid(data.HitEntity) and data.HitEntity:GetClass() == "func_breakable_surf" then
|
||||
self:FireBullets({
|
||||
Attacker = self:GetOwner(),
|
||||
Inflictor = self,
|
||||
Damage = 0,
|
||||
Distance = 32,
|
||||
Tracer = 0,
|
||||
Src = self:GetPos(),
|
||||
Dir = data.OurOldVelocity:GetNormalized(),
|
||||
})
|
||||
local pos, ang, vel = self:GetPos(), self:GetAngles(), data.OurOldVelocity
|
||||
self:SetAngles(ang)
|
||||
self:SetPos(pos)
|
||||
self:GetPhysicsObject():SetVelocityInstantaneous(vel * 0.5)
|
||||
return
|
||||
end
|
||||
|
||||
if (self.SafetyFuse or 0) > 0 and self.SpawnTime + self.SafetyFuse > CurTime() then
|
||||
self:SafetyImpact(data, collider)
|
||||
self:Remove()
|
||||
return
|
||||
elseif self.ImpactFuse then
|
||||
if !self.Armed then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
|
||||
if self:Impact(data, collider) then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if self.Delay == 0 or self.ExplodeOnImpact then
|
||||
self:PreDetonate(data.HitEntity)
|
||||
end
|
||||
elseif self.ImpactDamage > 0 and (self.NextImpactDamage or 0) < CurTime() and data.Speed >= 10 and IsValid(data.HitEntity) and (engine.ActiveGamemode() != "terrortown" or !data.HitEntity:IsPlayer()) then
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(IsValid(self:GetOwner()) and self:GetOwner() or self.Attacker)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamage(self.ImpactDamage)
|
||||
dmg:SetDamageType(self.ImpactDamageType)
|
||||
dmg:SetDamageForce(data.OurOldVelocity)
|
||||
dmg:SetDamagePosition(data.HitPos)
|
||||
data.HitEntity:TakeDamageInfo(dmg)
|
||||
self.NextImpactDamage = CurTime() + 0.05
|
||||
elseif !self.ImpactFuse then
|
||||
self:Impact(data, collider)
|
||||
end
|
||||
|
||||
if self.Sticky then
|
||||
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
self:SetPos(data.HitPos)
|
||||
|
||||
self:SetAngles((-data.HitNormal):Angle())
|
||||
|
||||
if data.HitEntity:IsWorld() or data.HitEntity:GetSolid() == SOLID_BSP then
|
||||
self:SetMoveType(MOVETYPE_NONE)
|
||||
self:SetPos(data.HitPos)
|
||||
else
|
||||
self:SetPos(data.HitPos)
|
||||
self:SetParent(data.HitEntity)
|
||||
end
|
||||
|
||||
self:EmitSound("TacRP/weapons/plant_bomb.wav", 65)
|
||||
|
||||
self.Attacker = self:GetOwner()
|
||||
self:SetOwner(NULL)
|
||||
|
||||
if self.StickyFuse and !self.Armed then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
|
||||
self:Stuck()
|
||||
else
|
||||
if !self.Bounced then
|
||||
self.Bounced = true
|
||||
local dot = data.HitNormal:Dot(Vector(0, 0, 1))
|
||||
if dot < 0 then
|
||||
self:GetPhysicsObject():SetVelocityInstantaneous(data.OurNewVelocity * (1 + dot * 0.5))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if data.DeltaTime < 0.1 then return end
|
||||
if !self.BounceSounds then return end
|
||||
|
||||
local s = table.Random(self.BounceSounds)
|
||||
|
||||
self:EmitSound(s)
|
||||
end
|
||||
|
||||
function ENT:OnThink()
|
||||
end
|
||||
|
||||
function ENT:OnInitialize()
|
||||
end
|
||||
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(10)
|
||||
smoke:SetEndSize(math.Rand(50, 75))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(-self:GetAngles():Forward() * 400 + (VectorRand() * 10))
|
||||
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.75, 1.25))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
if self.SpawnTime + self.RocketLifetime < CurTime() then return end
|
||||
|
||||
if self.TargetPos and (self.SteerDelay + self.SpawnTime) <= CurTime() then
|
||||
local v = phys:GetVelocity()
|
||||
|
||||
local steer_amount = self.SteerSpeed * FrameTime()
|
||||
if self.SuperSteerTime + self.StartSuperSteerTime > CurTime() then
|
||||
steer_amount = self.SuperSteerSpeed * FrameTime()
|
||||
end
|
||||
|
||||
local dir = (self.TargetPos - self:GetPos()):GetNormalized()
|
||||
local diff = math.deg(math.acos(dir:Dot(self:GetForward())))
|
||||
local turn_deg = math.min(diff, steer_amount)
|
||||
|
||||
local newang = self:GetAngles()
|
||||
newang:RotateAroundAxis(dir:Cross(self:GetForward()), -turn_deg)
|
||||
|
||||
local brake = turn_deg / steer_amount * self.SteerBrake
|
||||
|
||||
self:SetAngles(Angle(newang.p, newang.y, 0))
|
||||
phys:SetVelocityInstantaneous(self:GetForward() * math.Clamp(v:Length() + (self.Acceleration - brake) * FrameTime(), self.MinSpeed, self.MaxSpeed))
|
||||
elseif self.Acceleration > 0 then
|
||||
phys:SetVelocityInstantaneous(self:GetForward() * math.Clamp(phys:GetVelocity():Length() + self.Acceleration * FrameTime(), self.MinSpeed, self.MaxSpeed))
|
||||
end
|
||||
end
|
||||
|
||||
local gunship = {["npc_combinegunship"] = true, ["npc_combinedropship"] = true, ["npc_helicopter"] = true}
|
||||
|
||||
function ENT:DoTracking()
|
||||
local target = self.LockOnEntity
|
||||
if IsValid(target) then
|
||||
if self.TopAttack and self.TopAttacking then
|
||||
local xyvector = (target:WorldSpaceCenter() - self:GetPos())
|
||||
xyvector.z = 0
|
||||
local dist = xyvector:Length()
|
||||
|
||||
self.TargetPos = target:WorldSpaceCenter() + Vector(0, 0, self.TopAttackHeight)
|
||||
if self.LeadTarget then
|
||||
local dist2 = (self.TargetPos - self:GetPos()):Length()
|
||||
|
||||
local time = dist2 / self:GetVelocity():Length()
|
||||
self.TargetPos = self.TargetPos + (target:GetVelocity() * time)
|
||||
end
|
||||
|
||||
if dist <= self.TopAttackDistance then
|
||||
self.TopAttacking = false
|
||||
self.StartSuperSteerTime = CurTime()
|
||||
end
|
||||
else
|
||||
local dir = (target:WorldSpaceCenter() - self:GetPos()):GetNormalized()
|
||||
local diff = math.deg(math.acos(dir:Dot(self:GetForward())))
|
||||
if diff <= self.SeekerAngle or self.SuperSteerTime + self.StartSuperSteerTime > CurTime() then
|
||||
self.TargetPos = target:WorldSpaceCenter()
|
||||
local dist = (self.TargetPos - self:GetPos()):Length()
|
||||
if self.LeadTarget then
|
||||
local time = dist / self:GetVelocity():Length()
|
||||
self.TargetPos = self.TargetPos + (target:GetVelocity() * time)
|
||||
end
|
||||
|
||||
if self.FlareRedirectChance > 0 and self.NextFlareRedirectTime <= CurTime() and !TacRP.FlareEntities[target:GetClass()] then
|
||||
local flares = ents.FindInSphere(self:GetPos(), 2048)
|
||||
for k, v in pairs(flares) do
|
||||
if (TacRP.FlareEntities[v:GetClass()] or v.IsTacRPFlare) and math.Rand(0, 1) <= self.FlareRedirectChance then
|
||||
self:SwitchTarget(v)
|
||||
break
|
||||
end
|
||||
end
|
||||
self.NextFlareRedirectTime = CurTime() + 0.5
|
||||
end
|
||||
|
||||
if self.SeekerExplodeRange > 0 and diff <= self.SeekerExplodeAngle
|
||||
and self.SteerDelay + self.SpawnTime <= CurTime()
|
||||
and dist < self.SeekerExplodeRange then
|
||||
local tr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = target:GetPos(),
|
||||
filter = self,
|
||||
mask = MASK_SOLID,
|
||||
})
|
||||
if self.SeekerExplodeSnapPosition then
|
||||
self:SetPos(tr.HitPos)
|
||||
end
|
||||
self:PreDetonate(target)
|
||||
end
|
||||
elseif self.NoReacquire then
|
||||
self.LockOnEntity = nil
|
||||
self.TargetPos = nil
|
||||
end
|
||||
end
|
||||
elseif (!IsValid(target) and self.NoReacquire) or target.UnTrackable then
|
||||
self.LockOnEntity = nil
|
||||
self.TargetPos = nil
|
||||
end
|
||||
|
||||
if self.GunshipWorkaround and (self.GunshipCheck or 0 < CurTime()) then
|
||||
self.GunshipCheck = CurTime() + 0.33
|
||||
local tr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = self:GetPos() + (self:GetVelocity() * 6 * engine.TickInterval()),
|
||||
filter = self,
|
||||
mask = MASK_SHOT
|
||||
})
|
||||
if IsValid(tr.Entity) and gunship[tr.Entity:GetClass()] then
|
||||
self:SetPos(tr.HitPos)
|
||||
self:PreDetonate(tr.Entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if !IsValid(self) or self:GetNoDraw() then return end
|
||||
|
||||
if !self.SpawnTime then
|
||||
self.SpawnTime = CurTime()
|
||||
end
|
||||
|
||||
if SERVER and self.SoundHint and CurTime() >= self.SpawnTime + self.SoundHintDelay then
|
||||
self.SoundHint = false // only once
|
||||
sound.EmitHint(SOUND_DANGER, self:GetPos(), self.SoundHintRadius, self.SoundHintDuration, self)
|
||||
end
|
||||
|
||||
if !self.Armed and isnumber(self.TimeFuse) and self.SpawnTime + self.TimeFuse < CurTime() then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
|
||||
if self.Armed and self.ArmTime + self.Delay < CurTime() then
|
||||
self:PreDetonate()
|
||||
end
|
||||
|
||||
if self.ExplodeUnderwater and self:WaterLevel() > 0 then
|
||||
self:PreDetonate()
|
||||
end
|
||||
|
||||
if SERVER and self.SpawnTime + self.RocketLifetime > CurTime() then
|
||||
self:DoTracking()
|
||||
end
|
||||
|
||||
self:DoSmokeTrail()
|
||||
|
||||
self:OnThink()
|
||||
|
||||
self:NextThink(CurTime())
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:Use(ply)
|
||||
if !self.Defusable then return end
|
||||
|
||||
self:EmitSound("TacRP/weapons/rifle_jingle-1.wav")
|
||||
|
||||
if self.PickupAmmo then
|
||||
ply:GiveAmmo(1, self.PickupAmmo, true)
|
||||
end
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:RemoteDetonate()
|
||||
self:EmitSound("TacRP/weapons/c4/relay_switch-1.wav")
|
||||
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
|
||||
function ENT:PreDetonate(ent)
|
||||
if CLIENT then return end
|
||||
|
||||
if !self.Detonated then
|
||||
self.Detonated = true
|
||||
|
||||
if !IsValid(self.Attacker) and !IsValid(self:GetOwner()) then self.Attacker = game.GetWorld() end
|
||||
|
||||
self:Detonate(ent)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
// fill this in :)
|
||||
end
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
end
|
||||
|
||||
function ENT:SafetyImpact(data, collider)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("ManhackSparks", fx)
|
||||
|
||||
if IsValid(data.HitEntity) then
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker(attacker)
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamageType(self.ImpactDamageType)
|
||||
dmginfo:SetDamage(self.ImpactDamage * (self.NPCDamage and 0.25 or 1))
|
||||
dmginfo:SetDamageForce(data.OurOldVelocity * 20)
|
||||
dmginfo:SetDamagePosition(data.HitPos)
|
||||
data.HitEntity:TakeDamageInfo(dmginfo)
|
||||
end
|
||||
|
||||
self:EmitSound("weapons/rpg/shotdown.wav", 80)
|
||||
|
||||
if self:GetModel() == "models/weapons/tacint/rocket_deployed.mdl" then
|
||||
for i = 1, 4 do
|
||||
local prop = ents.Create("prop_physics")
|
||||
prop:SetPos(self:GetPos())
|
||||
prop:SetAngles(self:GetAngles())
|
||||
prop:SetModel("models/weapons/tacint/rpg7_shrapnel_p" .. i .. ".mdl")
|
||||
prop:Spawn()
|
||||
prop:GetPhysicsObject():SetVelocityInstantaneous(data.OurNewVelocity * 0.5 + VectorRand() * 75)
|
||||
prop:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
SafeRemoveEntityDelayed(prop, 3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:ImpactTraceAttack(ent, damage, pen)
|
||||
if !IsValid(ent) then return end
|
||||
if ent.LVS then
|
||||
// LVS only does its penetration logic on FireBullets, so we must fire a bullet to trigger it
|
||||
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS) // The projectile blocks the penetration decal?!
|
||||
self:FireBullets({
|
||||
Attacker = self.Attacker or self:GetOwner(),
|
||||
Damage = damage,
|
||||
Tracer = 0,
|
||||
Src = self:GetPos(),
|
||||
Dir = self:GetForward(),
|
||||
HullSize = 16,
|
||||
Distance = 128,
|
||||
IgnoreEntity = self,
|
||||
Callback = function(atk, btr, dmginfo)
|
||||
dmginfo:SetDamageType(DMG_AIRBOAT + DMG_SNIPER) // LVS wants this
|
||||
dmginfo:SetDamageForce(self:GetForward() * pen) // penetration strength
|
||||
end,
|
||||
})
|
||||
else
|
||||
// This is way more consistent because the damage always lands
|
||||
local tr = util.TraceHull({
|
||||
start = self:GetPos(),
|
||||
endpos = self:GetPos() + self:GetForward() * 256,
|
||||
filter = ent,
|
||||
whitelist = true,
|
||||
ignoreworld = true,
|
||||
mask = MASK_ALL,
|
||||
mins = Vector( -8, -8, -8 ),
|
||||
maxs = Vector( 8, 8, 8 ),
|
||||
})
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker(self.Attacker or self:GetOwner())
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamagePosition(self:GetPos())
|
||||
dmginfo:SetDamageForce(self:GetForward() * pen)
|
||||
dmginfo:SetDamageType(DMG_AIRBOAT + DMG_SNIPER)
|
||||
dmginfo:SetDamage(damage)
|
||||
ent:DispatchTraceAttack(dmginfo, tr, self:GetForward())
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Stuck()
|
||||
end
|
||||
|
||||
function ENT:DrawTranslucent()
|
||||
self:Draw()
|
||||
end
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
|
||||
function ENT:Draw()
|
||||
if self:GetOwner() == LocalPlayer() and (self.SpawnTime + 0.05) > CurTime() then return end
|
||||
|
||||
self:DrawModel()
|
||||
|
||||
if self.FlareColor then
|
||||
local mult = self.SafetyFuse and math.Clamp((CurTime() - (self.SpawnTime + self.SafetyFuse)) / self.SafetyFuse, 0.1, 1) or 1
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos() + (self:GetAngles():Forward() * -16), mult * math.Rand(self.FlareSizeMin, self.FlareSizeMax), mult * math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:SwitchTarget(target)
|
||||
if IsValid(self.LockOnEntity) then
|
||||
if isfunction(self.LockOnEntity.OnLaserLock) then
|
||||
self.LockOnEntity:OnLaserLock(false)
|
||||
end
|
||||
end
|
||||
|
||||
self.LockOnEntity = target
|
||||
|
||||
if IsValid(self.LockOnEntity) then
|
||||
if isfunction(self.LockOnEntity.OnLaserLock) then
|
||||
self.LockOnEntity:OnLaserLock(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("EntityTakeDamage", "tacrp_proj_collision", function(ent, dmginfo)
|
||||
if IsValid(dmginfo:GetInflictor())
|
||||
and scripted_ents.IsBasedOn(dmginfo:GetInflictor():GetClass(), "tacrp_proj_base")
|
||||
and dmginfo:GetDamageType() == DMG_CRUSH then dmginfo:SetDamage(0) return true end
|
||||
end)
|
||||
@@ -0,0 +1,98 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Breaching Slug"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/flare.mdl"
|
||||
ENT.CollisionSphere = 1
|
||||
|
||||
ENT.IsRocket = false
|
||||
|
||||
ENT.InstantFuse = false
|
||||
ENT.RemoteFuse = false
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.ExplodeOnDamage = false
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
ENT.SmokeTrail = false
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Initialize()
|
||||
BaseClass.Initialize(self)
|
||||
if SERVER then
|
||||
self:GetPhysicsObject():SetDragCoefficient(5)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
if self.Impacted then return end
|
||||
self.Impacted = true
|
||||
|
||||
local tgt = data.HitEntity
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local d = data.OurOldVelocity:GetNormalized()
|
||||
if IsValid(tgt) and string.find(tgt:GetClass(), "door") then
|
||||
-- if slug spent too much time in the air, it can only open doors, not breach them
|
||||
local vel = d * math.max(0, (self.SpawnTime + 0.25 - CurTime()) / 0.25) ^ 0.75 * 3000
|
||||
for _, otherDoor in pairs(ents.FindInSphere(tgt:GetPos(), 72)) do
|
||||
if tgt != otherDoor and otherDoor:GetClass() == tgt:GetClass() then
|
||||
TacRP.DoorBust(otherDoor, vel, attacker)
|
||||
break
|
||||
end
|
||||
end
|
||||
TacRP.DoorBust(tgt, vel, attacker)
|
||||
elseif IsValid(tgt) and tgt:GetClass() == "func_button" then
|
||||
-- press buttons remotely :3
|
||||
tgt:Use(attacker, self)
|
||||
end
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetInflictor(IsValid(self.Inflictor) and self.Inflictor or self)
|
||||
dmg:SetDamage(50)
|
||||
dmg:SetDamageType(DMG_CLUB)
|
||||
dmg:SetDamagePosition(data.HitPos)
|
||||
dmg:SetDamageForce(d * 30000)
|
||||
|
||||
local atktr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = data.HitPos,
|
||||
filter = self
|
||||
})
|
||||
|
||||
-- TacRP.CancelBodyDamage(tgt, dmg, atktr.HitGroup)
|
||||
tgt:DispatchTraceAttack(dmg, atktr)
|
||||
|
||||
-- leave a bullet hole. Also may be able to hit things it can't collide with (like stuck C4)
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Damage = 0,
|
||||
Force = 1,
|
||||
Distance = 4,
|
||||
HullSize = 4,
|
||||
Tracer = 0,
|
||||
Dir = d,
|
||||
Src = data.HitPos - d,
|
||||
IgnoreEntity = self,
|
||||
Callback = function(atk, tr, dmginfo)
|
||||
dmginfo:SetInflictor(IsValid(self.Inflictor) and self.Inflictor or self)
|
||||
end
|
||||
})
|
||||
|
||||
self:Remove()
|
||||
return true
|
||||
end
|
||||
|
||||
hook.Add("PostEntityTakeDamage", "tacrp_proj_breach_slug", function(ent, dmg, took)
|
||||
if took and IsValid(dmg:GetInflictor()) and ent:IsPlayer()
|
||||
and dmg:GetInflictor():GetClass() == "tacrp_proj_breach_slug"
|
||||
and (!IsValid(ent:GetActiveWeapon()) or !ent:GetActiveWeapon().ArcticTacRP or !ent:GetActiveWeapon():GetValue("StunResist")) then
|
||||
ent:SetNWFloat("TacRPLastBashed", CurTime() + 3)
|
||||
end
|
||||
end)
|
||||
165
garrysmod/addons/tacrp/lua/entities/tacrp_proj_gyrojet.lua
Normal file
165
garrysmod/addons/tacrp/lua/entities/tacrp_proj_gyrojet.lua
Normal file
@@ -0,0 +1,165 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Gyrojet Round"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint_shark/projectiles/gyrojet_rocket.mdl"
|
||||
ENT.CollisionSphere = 2
|
||||
|
||||
ENT.IsRocket = true
|
||||
|
||||
ENT.InstantFuse = false
|
||||
ENT.RemoteFuse = false
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.ExplodeOnDamage = false
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.SafetyFuse = 0
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(255, 128, 0, 100)
|
||||
ENT.FlareLife = 0.5
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"^TacRP/weapons/grenade/40mm_explode-1.wav",
|
||||
"^TacRP/weapons/grenade/40mm_explode-2.wav",
|
||||
"^TacRP/weapons/grenade/40mm_explode-3.wav",
|
||||
}
|
||||
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
function ENT:MakeSmoke()
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(55)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(4)
|
||||
smoke:SetEndSize(math.Rand(16, 24))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(-self:GetAngles():Forward() * 200 + (VectorRand() * 5)
|
||||
+ self:GetAngles():Right() * math.sin(CurTime() * math.pi * 16) * 32
|
||||
+ self:GetAngles():Up() * math.cos(CurTime() * math.pi * 16) * 32)
|
||||
|
||||
smoke:SetColor(255, 255, 255)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.4, 0.6))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if !IsValid(self) or self:GetNoDraw() then return end
|
||||
|
||||
if CurTime() - self.SpawnTime >= self.FlareLife then
|
||||
self.FlareColor = false
|
||||
end
|
||||
|
||||
if !self.SpawnTime then
|
||||
self.SpawnTime = CurTime()
|
||||
end
|
||||
|
||||
if !self.Armed and isnumber(self.TimeFuse) and self.SpawnTime + self.TimeFuse < CurTime() then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
|
||||
if self.Armed and self.ArmTime + self.Delay < CurTime() then
|
||||
self:PreDetonate()
|
||||
end
|
||||
|
||||
if self.ExplodeUnderwater and self:WaterLevel() > 0 then
|
||||
self:PreDetonate()
|
||||
end
|
||||
|
||||
if CLIENT and self.SmokeTrail and CurTime() - self.SpawnTime >= 0.1 then
|
||||
self:MakeSmoke()
|
||||
end
|
||||
|
||||
self:OnThink()
|
||||
end
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("MetalSpark", fx)
|
||||
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local inflictor = attacker.GetWeapon and attacker:GetWeapon("tacrp_sd_gyrojet")
|
||||
local dmg = inflictor and inflictor.GetValue and inflictor:GetValue("Damage_Max") or 75
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Inflictor = inflictor or self,
|
||||
Force = 5,
|
||||
Num = 1,
|
||||
Tracer = 0,
|
||||
Dir = data.OurOldVelocity:GetNormalized(),
|
||||
Src = data.HitPos,
|
||||
Damage = dmg,
|
||||
HullSize = 2,
|
||||
Callback = function(att, btr, dmginfo)
|
||||
if IsValid(btr.Entity) then
|
||||
if IsValid(inflictor) and inflictor.GetValue then
|
||||
local range = (btr.HitPos - btr.StartPos):Length()
|
||||
inflictor:AfterShotFunction(btr, dmginfo, range, inflictor:GetValue("Penetration"), {})
|
||||
end
|
||||
else
|
||||
-- Even though bullet did not hit, projectile did; just apply damage
|
||||
if attacker:IsNPC() and !TacRP.ConVars["npc_equality"]:GetBool() then
|
||||
dmginfo:ScaleDamage(0.25)
|
||||
end
|
||||
data.HitEntity:TakeDamageInfo(dmginfo)
|
||||
end
|
||||
|
||||
end
|
||||
})
|
||||
|
||||
self:Remove()
|
||||
return false
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
local len = phys:GetVelocity():Length()
|
||||
local f = math.Clamp(len / 4000, 0, 1)
|
||||
phys:AddVelocity(self:GetForward() * Lerp(f, 10, 1))
|
||||
end
|
||||
|
||||
local mat = Material("sprites/light_glow02_add")
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
|
||||
if self.FlareColor then
|
||||
local s = Lerp(((CurTime() - self.SpawnTime) / self.FlareLife) ^ 0.5, 1, 0)
|
||||
local s1, s2 = 32 * s, 64 * s
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos() + (self:GetAngles():Forward() * -4), math.Rand(s1, s2), math.Rand(s1, s2), self.FlareColor)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,39 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_gyrojet"
|
||||
ENT.PrintName = "HE Gyrojet Round"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(255, 200, 128, 100)
|
||||
ENT.FlareLife = 0.5
|
||||
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
return false
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local inflictor = attacker.GetWeapon and attacker:GetWeapon("tacrp_sd_gyrojet")
|
||||
local dmg = inflictor and inflictor:GetValue("Damage_Max") or 50
|
||||
if attacker:IsNPC() and !TacRP.ConVars["npc_equality"]:GetBool() then
|
||||
dmg = dmg * 0.25
|
||||
end
|
||||
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 128, dmg)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
fx:SetNormal(self:GetForward())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 80, 110, 0.75)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
@@ -0,0 +1,41 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_gyrojet"
|
||||
ENT.PrintName = "LV Gyrojet Round"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(255, 255, 200, 100)
|
||||
ENT.FlareLife = 0.2
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
function ENT:MakeSmoke()
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(45)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(2)
|
||||
smoke:SetEndSize(math.Rand(8, 16))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(-self:GetAngles():Forward() * 150 + (VectorRand() * 5))
|
||||
|
||||
smoke:SetColor(255, 255, 255)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.2, 0.4))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
@@ -0,0 +1,86 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_gyrojet"
|
||||
ENT.PrintName = "Gyrojet Pipe Grenade"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/Items/AR2_Grenade.mdl"
|
||||
ENT.CollisionSphere = false
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(255, 200, 128, 100)
|
||||
ENT.FlareLife = 0.1
|
||||
|
||||
ENT.IsRocket = false
|
||||
ENT.InstantFuse = true
|
||||
ENT.ImpactFuse = false
|
||||
ENT.Delay = 1.5
|
||||
|
||||
ENT.AudioLoop = false
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
if IsValid(data.HitEntity) and (data.HitEntity:IsPlayer() or data.HitEntity:IsNPC() or data.HitEntity:IsNextBot()) then
|
||||
self:Detonate()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local inflictor = attacker.GetWeapon and attacker:GetWeapon("tacrp_sd_gyrojet")
|
||||
local dmg = inflictor and inflictor.GetValue and inflictor:GetValue("Damage_Max") or 75
|
||||
if attacker:IsNPC() and !TacRP.ConVars["npc_equality"]:GetBool() then
|
||||
dmg = dmg * 0.25
|
||||
end
|
||||
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 150, dmg)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
fx:SetNormal(self:GetForward())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 80, 110, 0.75)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
end
|
||||
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
function ENT:MakeSmoke()
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(2)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(4)
|
||||
smoke:SetEndSize(math.Rand(10, 12))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 25)
|
||||
|
||||
smoke:SetColor(255, 255, 255)
|
||||
smoke:SetLighting(false)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.6, 0.8))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 256))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
@@ -0,0 +1,56 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_gyrojet"
|
||||
ENT.PrintName = "Ratshot Gyrojet Round"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(155, 155, 255, 255)
|
||||
ENT.FlareLife = 0.4
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Initialize()
|
||||
BaseClass.Initialize(self)
|
||||
if SERVER then
|
||||
self:SetTrigger(true)
|
||||
self:UseTriggerBounds(true, 48)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:StartTouch(ent)
|
||||
if SERVER and ent ~= self:GetOwner() and (ent:IsNPC() or ent:IsPlayer() or ent:IsNextBot()) then
|
||||
self:Detonate()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
local dir = self:GetForward()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local inflictor = attacker.GetWeapon and attacker:GetWeapon("tacrp_sd_gyrojet")
|
||||
local damage = inflictor and inflictor:GetValue("Damage_Max") or 50
|
||||
if attacker:IsNPC() and !TacRP.ConVars["npc_equality"]:GetBool() then
|
||||
damage = damage * 0.25
|
||||
end
|
||||
local src = self:GetPos() -- + dir * 32
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(src)
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
fx:SetMagnitude(4)
|
||||
fx:SetScale(4)
|
||||
fx:SetRadius(8)
|
||||
fx:SetNormal(dir)
|
||||
util.Effect("Sparks", fx)
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
|
||||
util.BlastDamage(self, attacker, src, 200, damage)
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 90, 110, 0.75)
|
||||
self:EmitSound("physics/metal/metal_box_break1.wav", 90, 175)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
257
garrysmod/addons/tacrp/lua/entities/tacrp_proj_knife.lua
Normal file
257
garrysmod/addons/tacrp/lua/entities/tacrp_proj_knife.lua
Normal file
@@ -0,0 +1,257 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Thrown Knife"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/w_knife.mdl"
|
||||
|
||||
ENT.IsRocket = false
|
||||
|
||||
ENT.InstantFuse = false
|
||||
ENT.RemoteFuse = false
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.ExplodeOnDamage = false
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
ENT.SmokeTrail = false
|
||||
local path = "tacrp/weapons/knife/"
|
||||
ENT.Sound_MeleeHit = {
|
||||
path .. "/scrape_metal-1.wav",
|
||||
path .. "/scrape_metal-2.wav",
|
||||
path .. "/scrape_metal-3.wav",
|
||||
}
|
||||
ENT.Sound_MeleeHitBody = {
|
||||
path .. "/flesh_hit-1.wav",
|
||||
path .. "/flesh_hit-2.wav",
|
||||
path .. "/flesh_hit-3.wav",
|
||||
path .. "/flesh_hit-4.wav",
|
||||
path .. "/flesh_hit-5.wav",
|
||||
}
|
||||
|
||||
ENT.Damage = 35
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Initialize()
|
||||
BaseClass.Initialize(self)
|
||||
if SERVER then
|
||||
self:GetPhysicsObject():SetDragCoefficient(2)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
if self.Impacted then return end
|
||||
self.Impacted = true
|
||||
|
||||
local tgt = data.HitEntity
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
if IsValid(tgt) then
|
||||
local d = data.OurOldVelocity:GetNormalized()
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetInflictor(IsValid(self.Inflictor) and self.Inflictor or self)
|
||||
dmg:SetDamage(self.Damage)
|
||||
dmg:SetDamageType(self.DamageType or DMG_SLASH)
|
||||
dmg:SetDamageForce(d * 10000)
|
||||
dmg:SetDamagePosition(data.HitPos)
|
||||
|
||||
local tgtpos = data.HitPos
|
||||
if (tgt:IsPlayer() or tgt:IsNPC() or tgt:IsNextBot()) then
|
||||
if (tgt:GetNWFloat("TacRPLastBashed", 0) + 3 >= CurTime()
|
||||
or (tgt:GetNWFloat("TacRPStunStart", 0) + tgt:GetNWFloat("TacRPStunDur", 0) >= CurTime())) then
|
||||
dmg:ScaleDamage(1.5)
|
||||
tgt:EmitSound("weapons/crossbow/bolt_skewer1.wav", 80, 110)
|
||||
end
|
||||
|
||||
-- Check if the knife is a headshot
|
||||
-- Either the head is the closest bodygroup, or the direction is quite on point
|
||||
local headpos = nil
|
||||
local pos = data.HitPos + d * 8
|
||||
local hset = tgt:GetHitboxSet()
|
||||
local hdot, bhg, bdist, hdist = 0, 0, math.huge, math.huge
|
||||
for i = 0, tgt:GetHitBoxCount(hset) or 0 do
|
||||
|
||||
local bone = tgt:GetHitBoxBone(i, hset)
|
||||
local mtx = bone and tgt:GetBoneMatrix(bone)
|
||||
if !mtx then continue end
|
||||
local hpos = mtx:GetTranslation()
|
||||
local dot = (hpos - data.HitPos):GetNormalized():Dot(d)
|
||||
local dist = (hpos - pos):LengthSqr()
|
||||
|
||||
if tgt:GetHitBoxHitGroup(i, hset) == HITGROUP_HEAD then
|
||||
hdot = dot
|
||||
hdist = dist
|
||||
headpos = hpos
|
||||
end
|
||||
if dist < bdist then
|
||||
bdist = dist
|
||||
bhg = tgt:GetHitBoxHitGroup(i, hset)
|
||||
tgtpos = hpos
|
||||
end
|
||||
end
|
||||
|
||||
if bhg == HITGROUP_HEAD or (hdot >= 0.85 and hdist < 2500) then
|
||||
dmg:ScaleDamage(2)
|
||||
tgt:EmitSound("player/headshot" .. math.random(1, 2) .. ".wav", 80, 105)
|
||||
tgtpos = headpos
|
||||
end
|
||||
|
||||
self:EmitSound(istable(self.Sound_MeleeHitBody) and self.Sound_MeleeHitBody[math.random(1, #self.Sound_MeleeHitBody)] or self.Sound_MeleeHitBody, 80, 110, 1)
|
||||
-- self:EmitSound("tacrp/weapons/knife/flesh_hit-" .. math.random(1, 5) .. ".wav", 80, 110, 1)
|
||||
|
||||
-- local ang = data.OurOldVelocity:Angle()
|
||||
-- local fx = EffectData()
|
||||
-- fx:SetStart(data.HitPos - d * 4)
|
||||
-- fx:SetOrigin(data.HitPos)
|
||||
-- fx:SetNormal(d)
|
||||
-- fx:SetAngles(-ang)
|
||||
-- fx:SetEntity(tgt)
|
||||
-- fx:SetDamageType(DMG_SLASH)
|
||||
-- fx:SetSurfaceProp(data.TheirSurfaceProps)
|
||||
-- util.Effect("Impact", fx)
|
||||
|
||||
else
|
||||
dmg:SetDamageForce(d * 30000)
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("ManhackSparks", fx)
|
||||
if SERVER then
|
||||
self:EmitSound(istable(self.Sound_MeleeHit) and self.Sound_MeleeHit[math.random(1, #self.Sound_MeleeHit)] or self.Sound_MeleeHit, 80, 110, 1)
|
||||
end
|
||||
end
|
||||
|
||||
-- tgt:TakeDamageInfo(dmg)
|
||||
|
||||
local atktr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = tgtpos,
|
||||
filter = self
|
||||
})
|
||||
|
||||
TacRP.CancelBodyDamage(tgt, dmg, atktr.HitGroup)
|
||||
tgt:DispatchTraceAttack(dmg, atktr)
|
||||
else
|
||||
-- leave a bullet hole. Also may be able to hit things it can't collide with (like stuck C4)
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Damage = self.Damage,
|
||||
Force = 1,
|
||||
Distance = 4,
|
||||
HullSize = 4,
|
||||
Tracer = 0,
|
||||
Dir = ang:Forward(),
|
||||
Src = data.HitPos - ang:Forward(),
|
||||
IgnoreEntity = self,
|
||||
Callback = function(atk, tr, dmginfo)
|
||||
dmginfo:SetInflictor(IsValid(self.Inflictor) and self.Inflictor or self)
|
||||
if tr.HitSky then
|
||||
SafeRemoveEntity(self)
|
||||
else
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("ManhackSparks", fx)
|
||||
if SERVER then
|
||||
self:EmitSound(istable(self.Sound_MeleeHit) and self.Sound_MeleeHit[math.random(1, #self.Sound_MeleeHit)] or self.Sound_MeleeHit, 80, 110, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
-- self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
|
||||
if self.DamageType == DMG_SLASH and (tgt:IsWorld() or (IsValid(tgt) and tgt:GetPhysicsObject():IsValid())) then
|
||||
local angles = data.OurOldVelocity:Angle()
|
||||
angles:RotateAroundAxis(self:GetRight(), -90)
|
||||
self:GetPhysicsObject():Sleep()
|
||||
|
||||
timer.Simple(0.01, function()
|
||||
if IsValid(self) and tgt:IsWorld() or (IsValid(tgt) and (!(tgt:IsNPC() or tgt:IsPlayer()) or tgt:Health() > 0)) then
|
||||
if !tgt:IsWorld() then
|
||||
self:SetSolid(SOLID_NONE)
|
||||
end
|
||||
self:SetMoveType(MOVETYPE_NONE)
|
||||
|
||||
local f = {self, self:GetOwner()}
|
||||
table.Add(f, tgt:GetChildren())
|
||||
local tr = util.TraceLine({
|
||||
start = data.HitPos - data.OurOldVelocity,
|
||||
endpos = data.HitPos + data.OurOldVelocity,
|
||||
filter = f,
|
||||
mask = MASK_SOLID,
|
||||
ignoreworld = true,
|
||||
})
|
||||
|
||||
local bone = (tr.Entity == tgt) and tr.PhysicsBone == 0
|
||||
and tr.Entity:GetHitBoxBone(tr.HitBox, tr.Entity:GetHitboxSet())
|
||||
or tr.PhysicsBone or -1
|
||||
local matrix = tgt:GetBoneMatrix(bone)
|
||||
if tr.Entity == tgt and matrix then
|
||||
local bpos = matrix:GetTranslation()
|
||||
local bang = matrix:GetAngles()
|
||||
self:SetPos(data.HitPos)
|
||||
self:FollowBone(tgt, bone)
|
||||
local n_pos, n_ang = WorldToLocal(tr.HitPos + tr.HitNormal * self:GetModelRadius() * 0.5, angles, bpos, bang)
|
||||
self:SetLocalPos(n_pos)
|
||||
self:SetLocalAngles(n_ang)
|
||||
debugoverlay.Cross(pos, 8, 5, Color(255, 0, 255), true)
|
||||
else
|
||||
self:SetAngles(angles)
|
||||
self:SetPos(data.HitPos - data.OurOldVelocity:GetNormalized() * self:GetModelRadius() * 0.5)
|
||||
if !tgt:IsWorld() then
|
||||
self:SetParent(tgt)
|
||||
end
|
||||
end
|
||||
elseif IsValid(self) then
|
||||
self:GetPhysicsObject():SetVelocityInstantaneous(data.OurNewVelocity * 0.5)
|
||||
self:GetPhysicsObject():SetAngleVelocityInstantaneous(data.OurOldAngularVelocity * 0.5)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
timer.Simple(0.01, function()
|
||||
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
if self.HasAmmo then
|
||||
self:SetTrigger(true)
|
||||
self:SetOwner(NULL)
|
||||
end
|
||||
end)
|
||||
|
||||
timer.Simple(5, function()
|
||||
if IsValid(self) then
|
||||
self:SetRenderMode(RENDERMODE_TRANSALPHA)
|
||||
self:SetRenderFX(kRenderFxFadeFast)
|
||||
end
|
||||
end)
|
||||
SafeRemoveEntityDelayed(self, 7)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:Touch(ent)
|
||||
if self.HasAmmo and ent:IsPlayer() and (IsValid(self.Inflictor) and ent == self.Inflictor:GetOwner()) then
|
||||
self.HasAmmo = false
|
||||
ent:GiveAmmo(1, "xbowbolt")
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("PostEntityTakeDamage", "TacRP_KnifeProj", function(ent)
|
||||
if (ent:IsPlayer() or ent:IsNPC()) and ent:Health() < 0 then
|
||||
for _, proj in pairs(ent:GetChildren()) do
|
||||
if proj:GetClass() == "tacrp_proj_knife" then proj:Remove() end
|
||||
end
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,49 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "KS-23 Flashbang"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
ENT.ExplodeOnImpact = true
|
||||
|
||||
ENT.Delay = 0.2
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/flashbang_explode-1.wav",
|
||||
}
|
||||
|
||||
ENT.AudioLoop = ""
|
||||
|
||||
ENT.SmokeTrail = false
|
||||
|
||||
function ENT:Detonate()
|
||||
// util.BlastDamage(self, self:GetOwner(), self:GetPos(), 150, 25)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
self:Remove()
|
||||
return
|
||||
else
|
||||
fx:SetRadius(328)
|
||||
util.Effect("TacRP_flashexplosion", fx)
|
||||
end
|
||||
|
||||
TacRP.Flashbang(self, self:GetPos(), 328, 1, 0.1, 0.3)
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 125)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
85
garrysmod/addons/tacrp/lua/entities/tacrp_proj_m202.lua
Normal file
85
garrysmod/addons/tacrp/lua/entities/tacrp_proj_m202.lua
Normal file
@@ -0,0 +1,85 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "M202 Rocket"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.SafetyFuse = 0.05
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 200, 150)
|
||||
|
||||
ENT.Radius = 400
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat()
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamagePosition(self:GetPos())
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetAttacker(attacker)
|
||||
|
||||
// Apply a small instance of damage to ignite first, before doing the real damage
|
||||
// This will ensure if the target dies it is on fire first (so it can ignite its ragdolls etc.)
|
||||
dmg:SetDamageType(DMG_SLOWBURN)
|
||||
dmg:SetDamage(5)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), self.Radius)
|
||||
|
||||
dmg:SetDamageType(DMG_BLAST + DMG_BURN)
|
||||
dmg:SetDamage(250 * mult)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), self.Radius)
|
||||
|
||||
self:ImpactTraceAttack(ent, 100 * mult, 100)
|
||||
|
||||
local decaltr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = self:GetPos() + self:GetForward() * 128,
|
||||
filter = self,
|
||||
mask = MASK_SOLID,
|
||||
})
|
||||
util.Decal("Scorch", decaltr.StartPos, decaltr.HitPos - (decaltr.HitNormal * 16), self)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("tacrp_m202_explode", fx)
|
||||
self:EmitSound("^weapons/explode5.wav", 100, 110)
|
||||
self:EmitSound("^ambient/fire/ignite.wav", 110, 110)
|
||||
end
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
local burn = {
|
||||
tacrp_proj_m202 = 12,
|
||||
tacrp_proj_p2a1_flare = 4,
|
||||
tacrp_proj_p2a1_paraflare = 4,
|
||||
tacrp_proj_p2a1_incendiary = 8,
|
||||
}
|
||||
|
||||
hook.Add("PostEntityTakeDamage", "tacrp_pa_m202", function(ent, dmginfo, took)
|
||||
local infl = dmginfo:GetInflictor()
|
||||
if took and IsValid(infl) and burn[infl:GetClass()] and dmginfo:IsDamageType(DMG_SLOWBURN) then
|
||||
local fr = Lerp(1 - (ent:GetPos():Distance(infl:GetPos())) / infl.Radius, 0.25, 1)
|
||||
ent:Ignite(fr * burn[infl:GetClass()] * (ent:IsPlayer() and 1 or 2.5))
|
||||
end
|
||||
end)
|
||||
134
garrysmod/addons/tacrp/lua/entities/tacrp_proj_m202_apers.lua
Normal file
134
garrysmod/addons/tacrp/lua/entities/tacrp_proj_m202_apers.lua
Normal file
@@ -0,0 +1,134 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "M202 Rocket (APERS)"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.SafetyFuse = 0.05
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(200, 200, 255)
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/smoke_explode-1.wav",
|
||||
}
|
||||
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:PhysicsCollide(data, collider)
|
||||
if self:Impact(data, collider) then
|
||||
return
|
||||
end
|
||||
|
||||
BaseClass.PhysicsCollide(self, data, collider)
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if self.SpawnTime + self.SafetyFuse < CurTime() and (self.NextTraceTime or 0) < CurTime() then
|
||||
self.NextTraceTime = CurTime() + 0.1
|
||||
|
||||
local dir = self:GetVelocity():GetNormalized()
|
||||
local deg = 1 //math.Clamp(1.5 - dir:Cross(Vector(0, 0, -1)):Length(), 0.5, 1)
|
||||
|
||||
local tr = util.TraceHull({
|
||||
start = self:GetPos(),
|
||||
endpos = self:GetPos() + dir * (1024 * deg),
|
||||
filter = self,
|
||||
mins = Vector(-32, -32, -32),
|
||||
maxs = Vector(32, 32, 32)
|
||||
})
|
||||
if tr.Hit then
|
||||
self:PreDetonate()
|
||||
end
|
||||
end
|
||||
|
||||
BaseClass.Think(self)
|
||||
end
|
||||
|
||||
|
||||
function ENT:Detonate()
|
||||
local dir = self:GetForward()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local src = self:GetPos() - dir * 64
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(src)
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
fx:SetMagnitude(8)
|
||||
fx:SetScale(2)
|
||||
fx:SetRadius(8)
|
||||
fx:SetNormal(dir)
|
||||
util.Effect("Sparks", fx)
|
||||
|
||||
local tr = util.TraceHull({
|
||||
start = src,
|
||||
endpos = src + dir * 1024,
|
||||
filter = self,
|
||||
mins = Vector(-16, -16, -8),
|
||||
maxs = Vector(16, 16, 8)
|
||||
})
|
||||
fx:SetMagnitude(4)
|
||||
fx:SetScale(1)
|
||||
fx:SetRadius(2)
|
||||
fx:SetNormal(dir)
|
||||
for i = 1, math.floor(tr.Fraction * 6) do
|
||||
fx:SetOrigin(tr.StartPos + tr.Normal * (i / 6) * 1024)
|
||||
util.Effect("Sparks", fx)
|
||||
end
|
||||
end
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat()
|
||||
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Damage = 5,
|
||||
Force = 1,
|
||||
Distance = 1024,
|
||||
HullSize = 16,
|
||||
Num = 48,
|
||||
Tracer = 1,
|
||||
Src = src,
|
||||
Dir = dir,
|
||||
Spread = Vector(1, 1, 0),
|
||||
IgnoreEntity = self,
|
||||
})
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetDamageType(DMG_BULLET + DMG_BLAST)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamageForce(self:GetVelocity() * 100)
|
||||
dmg:SetDamagePosition(src)
|
||||
for _, ent in pairs(ents.FindInCone(src, dir, 1024, 0.707)) do
|
||||
local tr = util.QuickTrace(src, ent:GetPos() - src, {self, ent})
|
||||
if tr.Fraction == 1 then
|
||||
dmg:SetDamage(mult * 60 * math.Rand(0.75, 1) * Lerp((ent:GetPos():DistToSqr(src) / 1048576) ^ 0.5, 1, 0.25) * (self.NPCDamage and 0.5 or 1) * mult)
|
||||
if !ent:IsOnGround() then dmg:ScaleDamage(1.5) end
|
||||
ent:TakeDamageInfo(dmg)
|
||||
end
|
||||
end
|
||||
|
||||
util.BlastDamage(self, attacker, src, 256, 50 * mult)
|
||||
|
||||
self:EmitSound("TacRP/weapons/rpg7/explode.wav", 125, 100)
|
||||
self:EmitSound("physics/metal/metal_box_break1.wav", 100, 200)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
205
garrysmod/addons/tacrp/lua/entities/tacrp_proj_m202_harpoon.lua
Normal file
205
garrysmod/addons/tacrp/lua/entities/tacrp_proj_m202_harpoon.lua
Normal file
@@ -0,0 +1,205 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "M202 Harpoon"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/props_junk/harpoon002a.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.SmokeTrail = false
|
||||
|
||||
local path = "tacrp/weapons/knife/"
|
||||
ENT.Sound_MeleeHit = {
|
||||
path .. "/scrape_metal-1.wav",
|
||||
path .. "/scrape_metal-2.wav",
|
||||
path .. "/scrape_metal-3.wav",
|
||||
}
|
||||
ENT.Sound_MeleeHitBody = {
|
||||
path .. "/flesh_hit-1.wav",
|
||||
path .. "/flesh_hit-2.wav",
|
||||
path .. "/flesh_hit-3.wav",
|
||||
path .. "/flesh_hit-4.wav",
|
||||
path .. "/flesh_hit-5.wav",
|
||||
}
|
||||
|
||||
function ENT:OnInitialize()
|
||||
if SERVER then
|
||||
self:GetPhysicsObject():SetMass(25)
|
||||
self:GetPhysicsObject():SetDragCoefficient(10)
|
||||
self:Ignite(30)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
local tgt = data.HitEntity
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local d = data.OurOldVelocity:GetNormalized()
|
||||
local forward = data.OurOldVelocity:Dot(self:GetAngles():Forward())
|
||||
if forward <= 100 then return true end
|
||||
if IsValid(tgt) then
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("ManhackSparks", fx)
|
||||
|
||||
if IsValid(data.HitEntity) then
|
||||
data.HitEntity:Ignite(math.Rand(5, 10), 128)
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker(attacker)
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamageType(DMG_CLUB)
|
||||
dmginfo:SetDamage(self.NPCDamage and 25 or math.Clamp(forward / 70, 10, 200))
|
||||
dmginfo:SetDamageForce(data.OurOldVelocity)
|
||||
dmginfo:SetDamagePosition(data.HitPos)
|
||||
data.HitEntity:TakeDamageInfo(dmginfo)
|
||||
end
|
||||
else
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("ManhackSparks", fx)
|
||||
if SERVER then
|
||||
self:EmitSound(istable(self.Sound_MeleeHit) and self.Sound_MeleeHit[math.random(1, #self.Sound_MeleeHit)] or self.Sound_MeleeHit, 80, 110, 1)
|
||||
end
|
||||
|
||||
-- leave a bullet hole. Also may be able to hit things it can't collide with (like stuck C4)
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Damage = self.Damage,
|
||||
Force = 1,
|
||||
Distance = 4,
|
||||
HullSize = 4,
|
||||
Tracer = 0,
|
||||
Dir = ang:Forward(),
|
||||
Src = data.HitPos - ang:Forward(),
|
||||
IgnoreEntity = self,
|
||||
Callback = function(atk, tr, dmginfo)
|
||||
dmginfo:SetDamageType(DMG_SLASH)
|
||||
dmginfo:SetInflictor(attacker)
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
if tgt:IsWorld() or (IsValid(tgt) and tgt:GetPhysicsObject():IsValid()) then
|
||||
local angles = data.OurOldVelocity:Angle()
|
||||
self:GetPhysicsObject():Sleep()
|
||||
|
||||
timer.Simple(0, function()
|
||||
if tgt:IsWorld() or (IsValid(tgt) and (!(tgt:IsNPC() or tgt:IsPlayer()) or tgt:Health() > 0)) then
|
||||
self:SetSolid(SOLID_NONE)
|
||||
self:SetMoveType(MOVETYPE_NONE)
|
||||
|
||||
local f = {self, self:GetOwner()}
|
||||
table.Add(f, tgt:GetChildren())
|
||||
local tr = util.TraceLine({
|
||||
start = data.HitPos - data.OurOldVelocity,
|
||||
endpos = data.HitPos + data.OurOldVelocity,
|
||||
filter = f,
|
||||
mask = MASK_SOLID,
|
||||
ignoreworld = true,
|
||||
})
|
||||
|
||||
local bone = (tr.Entity == tgt) and tr.PhysicsBone == 0
|
||||
and tr.Entity:GetHitBoxBone(tr.HitBox, tr.Entity:GetHitboxSet())
|
||||
or tr.PhysicsBone or -1
|
||||
local matrix = tgt:GetBoneMatrix(bone)
|
||||
if tr.Entity == tgt and matrix then
|
||||
local bpos = matrix:GetTranslation()
|
||||
local bang = matrix:GetAngles()
|
||||
self:SetPos(data.HitPos)
|
||||
self:FollowBone(tgt, bone)
|
||||
local n_pos, n_ang = WorldToLocal(tr.HitPos + tr.HitNormal * self:GetModelRadius() * 0.5, angles, bpos, bang)
|
||||
self:SetLocalPos(n_pos)
|
||||
self:SetLocalAngles(n_ang)
|
||||
debugoverlay.Cross(pos, 8, 5, Color(255, 0, 255), true)
|
||||
else
|
||||
self:SetAngles(angles)
|
||||
self:SetPos(data.HitPos - data.OurOldVelocity:GetNormalized() * self:GetModelRadius() * 0.5)
|
||||
if !tgt:IsWorld() then
|
||||
self:SetParent(tgt)
|
||||
end
|
||||
end
|
||||
else
|
||||
self:GetPhysicsObject():SetVelocity(data.OurOldVelocity * 0.75)
|
||||
self:GetPhysicsObject():SetAngleVelocity(data.OurOldAngularVelocity)
|
||||
self.Armed = false
|
||||
end
|
||||
end)
|
||||
end
|
||||
timer.Simple(5, function()
|
||||
if IsValid(self) then
|
||||
self:SetRenderMode(RENDERMODE_TRANSALPHA)
|
||||
self:SetRenderFX(kRenderFxFadeFast)
|
||||
end
|
||||
end)
|
||||
SafeRemoveEntityDelayed(self, 7)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local g = Vector(0, 0, -9.81)
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
if !self.Armed and phys:IsGravityEnabled() and self:WaterLevel() <= 2 then
|
||||
local v = phys:GetVelocity()
|
||||
self:SetAngles(v:Angle())
|
||||
phys:SetVelocityInstantaneous(v * 0.985 + g)
|
||||
end
|
||||
|
||||
-- local v = phys:GetVelocity()
|
||||
-- self:SetAngles(v:Angle() + Angle(2, 0, 0))
|
||||
-- phys:SetVelocityInstantaneous(self:GetForward() * v:Length())
|
||||
end
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and self:GetVelocity():Length() >= 100 then
|
||||
local pos = self:GetPos() + self:GetUp() * 4
|
||||
local emitter = ParticleEmitter(pos)
|
||||
local smoke = emitter:Add(GetSmokeImage(), pos)
|
||||
|
||||
smoke:SetStartAlpha(100)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(2)
|
||||
smoke:SetEndSize(math.Rand(16, 24))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetVelocity(VectorRand() * 8 + self:GetUp() * 16)
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.5, 0.75))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 15))
|
||||
|
||||
local fire = emitter:Add("effects/fire_cloud" .. math.random(1, 2), pos)
|
||||
fire:SetStartAlpha(150)
|
||||
fire:SetEndAlpha(0)
|
||||
fire:SetStartSize(math.Rand(2, 4))
|
||||
fire:SetEndSize(math.Rand(8, 16))
|
||||
fire:SetRoll(math.Rand(-180, 180))
|
||||
fire:SetRollDelta(math.Rand(-1, 1))
|
||||
fire:SetVelocity(VectorRand() * 16 + self:GetUp() * 16)
|
||||
fire:SetLighting(false)
|
||||
fire:SetDieTime(math.Rand(0.1, 0.3))
|
||||
fire:SetGravity(Vector(0, 0, 50))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
47
garrysmod/addons/tacrp/lua/entities/tacrp_proj_m202_he.lua
Normal file
47
garrysmod/addons/tacrp/lua/entities/tacrp_proj_m202_he.lua
Normal file
@@ -0,0 +1,47 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "M202 Rocket (HE)"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.SafetyFuse = 0.05
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 255, 200)
|
||||
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat() * (self.NPCDamage and 0.25 or 1)
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 350, 150 * mult)
|
||||
self:ImpactTraceAttack(ent, 800 * mult, 13000)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
end
|
||||
|
||||
self:EmitSound("TacRP/weapons/rpg7/explode.wav", 125)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
@@ -0,0 +1,44 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "M202 Rocket (Smoke)"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.SafetyFuse = 0.05
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 255, 255)
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/smoke_explode-1.wav",
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
if self:WaterLevel() > 0 then self:Remove() return end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 75)
|
||||
|
||||
local cloud = ents.Create( "TacRP_smoke_cloud" )
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:Spawn()
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
91
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_c4.lua
Normal file
91
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_c4.lua
Normal file
@@ -0,0 +1,91 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "C4"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/c4_charge-1.mdl"
|
||||
|
||||
ENT.Sticky = true
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = true // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false
|
||||
|
||||
ENT.Defusable = true
|
||||
ENT.DefuseOnDamage = true
|
||||
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
ENT.Delay = 0.5
|
||||
|
||||
ENT.PickupAmmo = "ti_c4"
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/breaching_charge-1.wav"
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
local dmg = TacRP.ConVars["c4_damage"]:GetFloat()
|
||||
local rad = TacRP.ConVars["c4_radius"]:GetFloat()
|
||||
local p = self:GetPos() + self:GetForward() * 8
|
||||
|
||||
util.BlastDamage(self, attacker, p, rad / 2, dmg)
|
||||
util.BlastDamage(self, attacker, p, rad, dmg)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(p)
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
|
||||
if rad >= 400 then
|
||||
local count = 8
|
||||
for i = 1, count do
|
||||
local tr = util.TraceLine({
|
||||
start = p,
|
||||
endpos = p + Angle(0, i / count * 360, 0):Forward() * (rad - 200) * math.Rand(0.9, 1.1),
|
||||
mask = MASK_SHOT,
|
||||
filter = self,
|
||||
})
|
||||
fx:SetOrigin(tr.HitPos)
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 125)
|
||||
|
||||
self:SetParent(NULL)
|
||||
for _, door in pairs(ents.FindInSphere(self:GetPos(), 256)) do
|
||||
if IsValid(door) and string.find(door:GetClass(), "door") and !door.TacRP_DoorBusted then
|
||||
local vel = (door:GetPos() - self:GetPos()):GetNormalized() * 200000
|
||||
for _, otherDoor in pairs(ents.FindInSphere(door:GetPos(), 72)) do
|
||||
if door != otherDoor and otherDoor:GetClass() == door:GetClass() then
|
||||
TacRP.DoorBust(otherDoor, vel, attacker)
|
||||
break
|
||||
end
|
||||
end
|
||||
TacRP.DoorBust(door, vel, attacker)
|
||||
end
|
||||
end
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:Stuck()
|
||||
// you are already dead
|
||||
if IsValid(self:GetParent()) and self:GetParent():IsPlayer() and !IsValid(self:GetParent().nadescream) then
|
||||
self:GetParent().nadescream = self
|
||||
self:GetParent():EmitSound("vo/npc/male01/ohno.wav")
|
||||
end
|
||||
end
|
||||
149
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_charge.lua
Normal file
149
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_charge.lua
Normal file
@@ -0,0 +1,149 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "C4"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/door_charge-1.mdl"
|
||||
|
||||
ENT.Sticky = true
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
ENT.StickyFuse = true
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false
|
||||
|
||||
ENT.Defusable = false
|
||||
ENT.DefuseOnDamage = true
|
||||
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
ENT.Delay = 2
|
||||
|
||||
ENT.PickupAmmo = "ti_charge"
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/breaching_charge-1.wav"
|
||||
}
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Entity", 0, "Weapon")
|
||||
self:NetworkVar("Bool", 0, "Remote")
|
||||
self:NetworkVar("Float", 0, "ArmTime")
|
||||
end
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Initialize()
|
||||
if IsValid(self:GetOwner()) and self:GetOwner():IsPlayer() and IsValid(self:GetOwner():GetActiveWeapon()) and self:GetOwner():GetActiveWeapon():GetClass() == "tacrp_c4_detonator" then
|
||||
self.StickyFuse = false
|
||||
self.RemoteFuse = true
|
||||
self.Delay = 0.5
|
||||
self.Defusable = true
|
||||
self:SetRemote(true)
|
||||
end
|
||||
|
||||
BaseClass.Initialize(self)
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = IsValid(self.Attacker) and self.Attacker or self:GetOwner()
|
||||
|
||||
util.BlastDamage(self, attacker, self:GetPos(), TacRP.ConVars["charge_radius"]:GetFloat(), TacRP.ConVars["charge_damage"]:GetFloat())
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
fx:SetNormal(self:GetForward())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 110)
|
||||
|
||||
local door = self:GetParent()
|
||||
self:SetParent(NULL)
|
||||
|
||||
if IsValid(door) and string.find(door:GetClass(), "door") then
|
||||
local vel = self:GetForward() * -50000
|
||||
for _, otherDoor in pairs(ents.FindInSphere(door:GetPos(), 72)) do
|
||||
if door != otherDoor and otherDoor:GetClass() == door:GetClass() then
|
||||
TacRP.DoorBust(otherDoor, vel, attacker)
|
||||
break
|
||||
end
|
||||
end
|
||||
TacRP.DoorBust(door, vel, attacker)
|
||||
end
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:Stuck()
|
||||
|
||||
sound.EmitHint(SOUND_DANGER, self:GetPos(), 256, 2, self)
|
||||
|
||||
self:SetArmTime(CurTime())
|
||||
if !self:GetRemote() then
|
||||
local ttt = TacRP.GetBalanceMode() == TacRP.BALANCE_TTT
|
||||
self:EmitSound("weapons/c4/c4_beep1.wav", ttt and 60 or 80, 110)
|
||||
timer.Create("breachbeep_" .. self:EntIndex(), 0.25, 7, function()
|
||||
if !IsValid(self) then return end
|
||||
self:EmitSound("weapons/c4/c4_beep1.wav", ttt and 60 or 80, 110)
|
||||
end)
|
||||
end
|
||||
|
||||
// you are already dead
|
||||
if IsValid(self:GetParent()) and self:GetParent():IsPlayer() and !IsValid(self:GetParent().nadescream) then
|
||||
self:GetParent().nadescream = self
|
||||
if self:GetRemote() then
|
||||
self:GetParent():EmitSound("vo/npc/male01/ohno.wav")
|
||||
else
|
||||
self:GetParent():EmitSound("vo/npc/male01/no0" .. math.random(1, 2) .. ".wav")
|
||||
end
|
||||
end
|
||||
|
||||
if VJ then
|
||||
self.Zombies = {}
|
||||
for _, x in ipairs(ents.FindInSphere(self:GetPos(), 512)) do
|
||||
if x:IsNPC() and string.find(x:GetClass(),"npc_vj_l4d_com_") and x.Zombie_CanHearPipe == true and x.Zombie_NextPipBombT < CurTime() then
|
||||
x.Zombie_NextPipBombT = CurTime() + 3
|
||||
table.insert(x.VJ_AddCertainEntityAsEnemy,self)
|
||||
x:AddEntityRelationship(self, D_HT, 99)
|
||||
x.MyEnemy = self
|
||||
x:SetEnemy(self)
|
||||
table.insert(self.Zombies, x)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnThink()
|
||||
if VJ and self.Zombies then
|
||||
for _, v in ipairs(self.Zombies) do
|
||||
if IsValid(v) then
|
||||
v:SetLastPosition(self:GetPos())
|
||||
v:VJ_TASK_GOTO_LASTPOS()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local clr_timed = Color(255, 0, 0)
|
||||
local clr_remote = Color(0, 255, 0)
|
||||
|
||||
local mat = Material("sprites/light_glow02_add")
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
|
||||
if (self:GetRemote() or self:GetArmTime() > 0) and math.ceil((CurTime() - self:GetArmTime()) * (self:GetRemote() and 2 or 8)) % 2 == 1 then
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos() + self:GetAngles():Up() * 7.5 + self:GetAngles():Right() * -4.5 + self:GetAngles():Forward() * 2, 8, 8, self:GetRemote() and clr_remote or clr_timed)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,94 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Flash Grenade"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/flashbang.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false
|
||||
|
||||
ENT.ImpactDamage = 1
|
||||
|
||||
ENT.Delay = 1.5
|
||||
|
||||
ENT.SoundHint = true
|
||||
ENT.SoundHintDelay = 0.5
|
||||
ENT.SoundHintRadius = 728
|
||||
ENT.SoundHintDuration = 1
|
||||
|
||||
ENT.BounceSounds = {
|
||||
"TacRP/weapons/grenade/flashbang_bounce-1.wav",
|
||||
"TacRP/weapons/grenade/flashbang_bounce-2.wav",
|
||||
"TacRP/weapons/grenade/flashbang_bounce-3.wav",
|
||||
}
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/flashbang_explode-1.wav",
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamageType(engine.ActiveGamemode() == "terrortown" and DMG_DIRECT or DMG_SONIC)
|
||||
dmg:SetDamagePosition(self:GetPos())
|
||||
dmg:SetDamage(3)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), 728)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
self:Remove()
|
||||
return
|
||||
else
|
||||
fx:SetRadius(728)
|
||||
util.Effect("TacRP_flashexplosion", fx)
|
||||
end
|
||||
|
||||
TacRP.Flashbang(self, self:GetPos(), 728, 3, 0.25, 0.5)
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 125)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and (self.Tick or 0) % 5 == 0 then
|
||||
local pos = self:GetPos() + VectorRand() * 2
|
||||
local emitter = ParticleEmitter(pos)
|
||||
|
||||
local smoke = emitter:Add("effects/spark", pos)
|
||||
|
||||
smoke:SetVelocity( VectorRand() * 32 )
|
||||
smoke:SetStartAlpha( 255 )
|
||||
smoke:SetEndAlpha( 0 )
|
||||
smoke:SetStartSize( 2 )
|
||||
smoke:SetEndSize( 0 )
|
||||
smoke:SetRoll( math.Rand(-180, 180) )
|
||||
smoke:SetRollDelta( math.Rand(-32, 32) )
|
||||
smoke:SetColor( 255, 255, 255 )
|
||||
smoke:SetAirResistance( 125 )
|
||||
smoke:SetPos( pos )
|
||||
smoke:SetCollide( true )
|
||||
smoke:SetBounce( 1 )
|
||||
smoke:SetLighting( false )
|
||||
smoke:SetDieTime(math.Rand(2, 3))
|
||||
smoke:SetGravity(Vector(0, 0, 4))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
self.Tick = (self.Tick or 0) + 1
|
||||
end
|
||||
59
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_frag.lua
Normal file
59
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_frag.lua
Normal file
@@ -0,0 +1,59 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Frag Grenade"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/frag.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false
|
||||
|
||||
ENT.SoundHint = true
|
||||
ENT.SoundHintDelay = 1
|
||||
ENT.SoundHintRadius = 512
|
||||
ENT.SoundHintDuration = 1
|
||||
|
||||
ENT.ImpactDamage = 1
|
||||
|
||||
ENT.Delay = 2
|
||||
|
||||
ENT.BounceSounds = {
|
||||
"TacRP/weapons/grenade/frag_bounce-1.wav",
|
||||
"TacRP/weapons/grenade/frag_bounce-2.wav",
|
||||
"TacRP/weapons/grenade/frag_bounce-3.wav",
|
||||
}
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"^TacRP/weapons/grenade/frag_explode-1.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-2.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-3.wav",
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
local dmg = TacRP.ConVars["frag_damage"]:GetFloat()
|
||||
if self.ImpactFuse then dmg = dmg * 0.5 end
|
||||
|
||||
util.BlastDamage(self, attacker, self:GetPos(), TacRP.ConVars["frag_radius"]:GetFloat(), dmg)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 125)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
90
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_gas.lua
Normal file
90
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_gas.lua
Normal file
@@ -0,0 +1,90 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Gas Grenade"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/smoke.mdl"
|
||||
|
||||
ENT.Material = "models/tacint/weapons/w_models/smoke/gas-1"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false
|
||||
|
||||
ENT.SoundHint = true
|
||||
ENT.SoundHintDelay = 1
|
||||
ENT.SoundHintRadius = 512
|
||||
ENT.SoundHintDuration = 1
|
||||
|
||||
ENT.ImpactDamage = 1
|
||||
|
||||
ENT.Delay = 2
|
||||
|
||||
ENT.BounceSounds = {
|
||||
"TacRP/weapons/grenade/smoke_bounce-1.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-2.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-3.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-4.wav",
|
||||
}
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/smoke_explode-1.wav",
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
if self:WaterLevel() > 0 then self:Remove() return end
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
// util.BlastDamage(self, attacker, self:GetPos(), 300, 10)
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 75)
|
||||
|
||||
local cloud = ents.Create( "TacRP_gas_cloud" )
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetOwner(attacker)
|
||||
cloud:Spawn()
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail then
|
||||
local pos = self:GetPos() + self:GetUp() * 4
|
||||
local emitter = ParticleEmitter(pos)
|
||||
local smoke = emitter:Add(GetSmokeImage(), pos)
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(2)
|
||||
smoke:SetEndSize(math.Rand(16, 24))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetVelocity(VectorRand() * 8 + self:GetUp() * 16)
|
||||
smoke:SetColor(125, 150, 50)
|
||||
smoke:SetLighting(false)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.5, 0.75))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 15))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
88
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_heal.lua
Normal file
88
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_heal.lua
Normal file
@@ -0,0 +1,88 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Medi-Gas Canister"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/smoke.mdl"
|
||||
|
||||
ENT.Material = "models/tacint/weapons/w_models/smoke/heal-1"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false
|
||||
|
||||
ENT.ImpactDamage = 1
|
||||
|
||||
ENT.Delay = 5
|
||||
|
||||
ENT.BounceSounds = {
|
||||
"TacRP/weapons/grenade/smoke_bounce-1.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-2.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-3.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-4.wav",
|
||||
}
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/smoke_explode-1.wav",
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
if self:WaterLevel() > 0 then self:Remove() return end
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
// util.BlastDamage(self, attacker, self:GetPos(), 300, 10)
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 75)
|
||||
|
||||
local cloud = ents.Create( "TacRP_heal_cloud" )
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetOwner(attacker)
|
||||
cloud:Spawn()
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
ENT.NextSmokeTime = 0
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and self.NextSmokeTime < CurTime() then
|
||||
local pos = self:GetPos() + self:GetUp() * 4
|
||||
local emitter = ParticleEmitter(pos)
|
||||
local smoke = emitter:Add(GetSmokeImage(), pos)
|
||||
|
||||
smoke:SetStartAlpha(75)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(10)
|
||||
smoke:SetEndSize(math.Rand(16, 32))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetVelocity(VectorRand() * 8 + self:GetUp() * 42)
|
||||
|
||||
smoke:SetColor(125, 25, 125)
|
||||
smoke:SetLighting(false)
|
||||
|
||||
smoke:SetDieTime(math.Rand(1, 1.5))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 15))
|
||||
|
||||
emitter:Finish()
|
||||
|
||||
self.NextSmokeTime = CurTime() + 0.025
|
||||
end
|
||||
end
|
||||
55
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_nuke.lua
Normal file
55
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_nuke.lua
Normal file
@@ -0,0 +1,55 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Nuke"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/props_misc/briefcase_bomb-1.mdl"
|
||||
|
||||
ENT.Sticky = false
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = true // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false
|
||||
|
||||
ENT.Defusable = true
|
||||
ENT.PickupAmmo = "ti_nuke"
|
||||
|
||||
ENT.Delay = 0.5
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"ambient/explosions/explode_6.wav"
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
self:Remove()
|
||||
return
|
||||
else
|
||||
util.Effect("TacRP_nukeexplosion", fx)
|
||||
end
|
||||
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 1024, 100000)
|
||||
|
||||
local cloud = ents.Create( "TacRP_nuke_cloud" )
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetOwner(attacker)
|
||||
cloud:Spawn()
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 149)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
324
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_rock.lua
Normal file
324
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_rock.lua
Normal file
@@ -0,0 +1,324 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Rock"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/props_debris/concrete_chunk05g.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.AllowFunny = true
|
||||
|
||||
ENT.ExtraModels = {
|
||||
"models/props_junk/PopCan01a.mdl",
|
||||
"models/Gibs/HGIBS.mdl",
|
||||
"models/props_junk/garbage_glassbottle003a.mdl",
|
||||
"models/props_junk/garbage_glassbottle001a.mdl",
|
||||
"models/props_junk/garbage_glassbottle002a.mdl",
|
||||
"models/props_junk/garbage_metalcan001a.mdl",
|
||||
"models/props_junk/garbage_metalcan002a.mdl",
|
||||
"models/props_junk/GlassBottle01a.mdl",
|
||||
"models/props_junk/garbage_coffeemug001a.mdl",
|
||||
"models/props_junk/glassjug01.mdl",
|
||||
"models/props_lab/jar01b.mdl",
|
||||
"models/props_junk/watermelon01.mdl",
|
||||
"models/props_junk/CinderBlock01a.mdl",
|
||||
"models/props_junk/MetalBucket01a.mdl",
|
||||
"models/props_junk/metal_paintcan001a.mdl",
|
||||
"models/Gibs/Antlion_gib_Large_2.mdl",
|
||||
"models/props_junk/garbage_plasticbottle003a.mdl",
|
||||
"models/props_junk/garbage_plasticbottle002a.mdl",
|
||||
"models/props_junk/garbage_plasticbottle001a.mdl",
|
||||
"models/props_junk/terracotta01.mdl",
|
||||
"models/props_junk/Shoe001a.mdl",
|
||||
"models/props_lab/frame002a.mdl",
|
||||
"models/props_lab/reciever01c.mdl",
|
||||
"models/props_lab/box01a.mdl",
|
||||
"models/props_junk/garbage_milkcarton001a.mdl",
|
||||
"models/props_lab/cactus.mdl",
|
||||
"models/props_lab/desklamp01.mdl",
|
||||
"models/Gibs/HGIBS_spine.mdl",
|
||||
"models/Gibs/wood_gib01a.mdl",
|
||||
"models/Gibs/wood_gib01b.mdl",
|
||||
"models/Gibs/wood_gib01c.mdl",
|
||||
"models/Gibs/wood_gib01d.mdl",
|
||||
"models/Gibs/wood_gib01e.mdl",
|
||||
"models/props_c17/oildrum001_explosive.mdl", // won't actually explode :trolleg:
|
||||
"models/props_interiors/SinkKitchen01a.mdl",
|
||||
"models/props_borealis/door_wheel001a.mdl",
|
||||
"models/hunter/blocks/cube025x025x025.mdl",
|
||||
"models/food/burger.mdl",
|
||||
"models/food/hotdog.mdl",
|
||||
"models/lamps/torch.mdl",
|
||||
"models/player/items/humans/top_hat.mdl",
|
||||
"models/dav0r/camera.mdl",
|
||||
"models/dav0r/tnt/tnt.mdl",
|
||||
"models/maxofs2d/camera.mdl",
|
||||
"models/maxofs2d/companion_doll.mdl",
|
||||
"models/maxofs2d/cube_tool.mdl",
|
||||
"models/maxofs2d/light_tubular.mdl",
|
||||
"models/maxofs2d/lamp_flashlight.mdl",
|
||||
"models/mechanics/gears/gear12x12.mdl",
|
||||
"models/mechanics/various/211.mdl",
|
||||
"models/props_phx/games/chess/white_rook.mdl",
|
||||
"models/props_phx/games/chess/white_queen.mdl",
|
||||
"models/props_phx/games/chess/white_pawn.mdl",
|
||||
"models/props_phx/games/chess/white_knight.mdl",
|
||||
"models/props_phx/games/chess/white_king.mdl",
|
||||
"models/props_phx/games/chess/white_dama.mdl",
|
||||
"models/props_phx/games/chess/black_rook.mdl",
|
||||
"models/props_phx/games/chess/black_queen.mdl",
|
||||
"models/props_phx/games/chess/black_pawn.mdl",
|
||||
"models/props_phx/games/chess/black_knight.mdl",
|
||||
"models/props_phx/games/chess/black_king.mdl",
|
||||
"models/props_phx/games/chess/black_dama.mdl",
|
||||
"models/props_phx/games/chess/black_bishop.mdl",
|
||||
"models/props_phx/misc/egg.mdl",
|
||||
"models/props_phx/misc/potato.mdl",
|
||||
"models/props_phx/misc/potato_launcher_explosive.mdl",
|
||||
"models/props_phx/misc/smallcannonball.mdl",
|
||||
"models/props_phx/misc/soccerball.mdl",
|
||||
"models/props_phx/misc/fender.mdl",
|
||||
"models/props_combine/breenbust.mdl",
|
||||
"models/props_combine/breenglobe.mdl",
|
||||
"models/props_combine/combinebutton.mdl",
|
||||
"models/props_combine/breenclock.mdl",
|
||||
"models/props_interiors/pot01a.mdl",
|
||||
"models/props_junk/garbage_bag001a.mdl",
|
||||
"models/props_lab/harddrive02.mdl",
|
||||
"models/props_lab/monitor02.mdl", // HAAAAAAX
|
||||
"models/props_lab/clipboard.mdl",
|
||||
"models/props_lab/tpplug.mdl",
|
||||
"models/props_pipes/valvewheel002a.mdl",
|
||||
"models/props_pipes/valve003.mdl",
|
||||
"models/props_rooftop/sign_letter_m001.mdl",
|
||||
"models/props_rooftop/sign_letter_f001b.mdl",
|
||||
"models/props_rooftop/sign_letter_u001b.mdl",
|
||||
"models/props_wasteland/speakercluster01a.mdl",
|
||||
"models/props_wasteland/prison_toilet01.mdl",
|
||||
"models/props_c17/streetsign001c.mdl",
|
||||
"models/props_c17/streetsign002b.mdl",
|
||||
"models/props_c17/streetsign003b.mdl",
|
||||
"models/props_c17/streetsign004e.mdl",
|
||||
"models/props_c17/streetsign004f.mdl",
|
||||
"models/props_c17/streetsign005b.mdl",
|
||||
"models/props_c17/streetsign005c.mdl",
|
||||
"models/props_c17/streetsign005d.mdl",
|
||||
"models/props_c17/playgroundTick-tack-toe_block01a.mdl",
|
||||
"models/props_c17/doll01.mdl",
|
||||
"models/props_c17/BriefCase001a.mdl",
|
||||
"models/props_c17/metalPot001a.mdl",
|
||||
"models/props_c17/metalPot002a.mdl",
|
||||
"models/props_canal/mattpipe.mdl",
|
||||
"models/extras/info_speech.mdl",
|
||||
"models/items/grenadeammo.mdl", // not a live one
|
||||
"models/props_c17/light_cagelight02_on.mdl",
|
||||
"models/props_c17/suitcase_passenger_physics.mdl",
|
||||
"models/props_citizen_tech/guillotine001a_wheel01.mdl",
|
||||
"models/props_interiors/bathtub01a.mdl", // now this is just absurd
|
||||
"models/props_junk/garbage_takeoutcarton001a.mdl",
|
||||
"models/props_junk/garbage_newspaper001a.mdl",
|
||||
"models/props_junk/sawblade001a.mdl",
|
||||
"models/props_lab/bewaredog.mdl",
|
||||
"models/props_lab/huladoll.mdl",
|
||||
"models/props_lab/powerbox02d.mdl",
|
||||
"models/props_lab/powerbox02b.mdl",
|
||||
"models/props_lab/powerbox02a.mdl",
|
||||
"models/weapons/w_bugbait.mdl",
|
||||
"models/weapons/w_alyx_gun.mdl",
|
||||
"models/weapons/w_crowbar.mdl",
|
||||
"models/weapons/w_smg1.mdl",
|
||||
"models/weapons/w_shotgun.mdl",
|
||||
"models/weapons/w_rocket_launcher.mdl",
|
||||
"models/weapons/w_pistol.mdl",
|
||||
"models/weapons/w_physics.mdl",
|
||||
"models/weapons/w_irifle.mdl",
|
||||
"models/weapons/w_357.mdl",
|
||||
"models/weapons/w_package.mdl",
|
||||
"models/weapons/w_pist_deagle.mdl",
|
||||
"models/weapons/w_pist_elite_single.mdl",
|
||||
"models/weapons/w_pist_glock18.mdl",
|
||||
"models/weapons/w_rif_ak47.mdl",
|
||||
"models/weapons/w_rif_m4a1.mdl",
|
||||
"models/weapons/w_shot_m3super90.mdl",
|
||||
"models/weapons/w_smg_mp5.mdl",
|
||||
"models/weapons/w_snip_awp.mdl",
|
||||
"models/weapons/w_crossbow.mdl",
|
||||
"models/weapons/w_eq_defuser.mdl",
|
||||
"models/weapons/w_toolgun.mdl",
|
||||
"models/weapons/w_missile_closed.mdl",
|
||||
"models/weapons/w_stunbaton.mdl",
|
||||
"models/weapons/w_annabelle.mdl",
|
||||
"models/roller.mdl",
|
||||
"models/pigeon.mdl",
|
||||
"models/headcrabclassic.mdl",
|
||||
"models/headcrab.mdl",
|
||||
"models/headcrabblack.mdl",
|
||||
"models/crow.mdl",
|
||||
"models/seagull.mdl",
|
||||
"models/kleiner.mdl",
|
||||
"models/gman.mdl",
|
||||
"models/manhack.mdl",
|
||||
|
||||
// CSS
|
||||
"models/props/cs_militia/bottle01.mdl",
|
||||
"models/props/cs_office/coffee_mug.mdl",
|
||||
"models/props/cs_office/computer_keyboard.mdl",
|
||||
"models/props/cs_office/water_bottle.mdl",
|
||||
"models/props/cs_office/projector_remote.mdl",
|
||||
"models/props/cs_office/phone.mdl",
|
||||
"models/props/cs_italy/bananna_bunch.mdl",
|
||||
"models/props/cs_italy/bananna.mdl",
|
||||
"models/props/cs_italy/orange.mdl",
|
||||
"models/props/de_tides/vending_turtle.mdl",
|
||||
}
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
if util.IsValidModel(TacRP.ConVars["rock_funny"]:GetString()) then
|
||||
self:SetModel(TacRP.ConVars["rock_funny"]:GetString())
|
||||
elseif self.AllowFunny and math.random() <= TacRP.ConVars["rock_funny"]:GetFloat() then
|
||||
local i = math.min(TacRP.ConVars["rock_funny"]:GetFloat() > 1 and TacRP.ConVars["rock_funny"]:GetInt() - 1 or math.random(1, #self.ExtraModels), #self.ExtraModels)
|
||||
local mdl = self.ExtraModels[i]
|
||||
self:SetModel(util.IsValidModel(mdl) and mdl or self.Model)
|
||||
else
|
||||
self:SetModel(self.Model)
|
||||
end
|
||||
|
||||
self:SetSkin(math.random(1, self:SkinCount()))
|
||||
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_PROJECTILE)
|
||||
if self.Defusable then
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
end
|
||||
self:PhysWake()
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if !phys:IsValid() then
|
||||
self:Remove()
|
||||
else
|
||||
phys:SetDragCoefficient(0)
|
||||
phys:SetMass(2)
|
||||
end
|
||||
|
||||
if self.IsRocket then
|
||||
phys:EnableGravity(false)
|
||||
end
|
||||
end
|
||||
|
||||
self.SpawnTime = CurTime()
|
||||
|
||||
self.NPCDamage = IsValid(self:GetOwner()) and self:GetOwner():IsNPC() and !TacRP.ConVars["npc_equality"]:GetBool()
|
||||
|
||||
if self.AudioLoop then
|
||||
self.LoopSound = CreateSound(self, self.AudioLoop)
|
||||
self.LoopSound:Play()
|
||||
end
|
||||
|
||||
if self.InstantFuse then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
function ENT:PhysicsCollide(data, collider)
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
if IsValid(data.HitEntity) and data.HitEntity:GetClass() == "func_breakable_surf" then
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Inflictor = self,
|
||||
Damage = 0,
|
||||
Distance = 32,
|
||||
Tracer = 0,
|
||||
Src = self:GetPos(),
|
||||
Dir = data.OurOldVelocity:GetNormalized(),
|
||||
})
|
||||
local pos, ang, vel = self:GetPos(), self:GetAngles(), data.OurOldVelocity
|
||||
self:SetAngles(ang)
|
||||
self:SetPos(pos)
|
||||
self:GetPhysicsObject():SetVelocityInstantaneous(vel * 0.5)
|
||||
return
|
||||
end
|
||||
|
||||
local prop1 = util.GetSurfaceData(data.OurSurfaceProps)
|
||||
local prop2 = util.GetSurfaceData(data.TheirSurfaceProps)
|
||||
|
||||
|
||||
if IsValid(data.HitEntity) and (self.LastDamage or 0) + 0.25 < CurTime() then
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamage(Lerp((data.OurOldVelocity:Length() - 500) / 2500, 4, 35))
|
||||
if self:GetModel() != self.Model then
|
||||
dmg:ScaleDamage(2)
|
||||
end
|
||||
dmg:SetDamageType(DMG_CRUSH + DMG_CLUB)
|
||||
dmg:SetDamageForce(data.OurOldVelocity)
|
||||
dmg:SetDamagePosition(data.HitPos)
|
||||
data.HitEntity:TakeDamageInfo(dmg)
|
||||
self.LastDamage = CurTime()
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
elseif data.Speed >= 75 and (self.LastImpact or 0) + 0.1 < CurTime() then
|
||||
self.LastImpact = CurTime()
|
||||
self:EmitSound(self:GetModel() == self.Model and "physics/concrete/rock_impact_hard" .. math.random(1, 6) .. ".wav" or prop1.impactHardSound)
|
||||
elseif data.Speed >= 25 and (self.LastImpact or 0) + 0.1 < CurTime() then
|
||||
self.LastImpact = CurTime()
|
||||
self:EmitSound(self:GetModel() == self.Model and "physics/concrete/rock_impact_soft" .. math.random(1, 3) .. ".wav" or prop1.impactSoftSound)
|
||||
end
|
||||
|
||||
if !self.FirstHit then
|
||||
self.FirstHit = true
|
||||
self:EmitSound(prop2.bulletImpactSound)
|
||||
|
||||
if self:GetModel() == self.Model then
|
||||
self:EmitSound("physics/concrete/concrete_break" .. math.random(2, 3) .. ".wav", 75, math.Rand(105, 110), 0.5)
|
||||
SafeRemoveEntityDelayed(self, 3)
|
||||
else
|
||||
self:EmitSound(prop1.impactHardSound)
|
||||
if util.IsValidRagdoll(self:GetModel()) then
|
||||
local rag = ents.Create("prop_ragdoll")
|
||||
rag:SetModel(self:GetModel())
|
||||
rag:SetPos(self:GetPos())
|
||||
rag:SetAngles(self:GetAngles())
|
||||
rag:Spawn()
|
||||
rag:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
if IsValid(rag:GetPhysicsObject()) then
|
||||
rag:GetPhysicsObject():ApplyForceOffset(data.HitPos, data.OurOldVelocity)
|
||||
end
|
||||
|
||||
SafeRemoveEntityDelayed(rag, 5)
|
||||
self:Remove()
|
||||
else
|
||||
local gibs = self:PrecacheGibs()
|
||||
if gibs > 0 then
|
||||
self:GibBreakClient(data.OurNewVelocity * math.Rand(0.8, 1.2))
|
||||
// self:GibBreakServer( data.OurOldVelocity * 2 )
|
||||
self:Remove()
|
||||
else
|
||||
SafeRemoveEntityDelayed(self, 3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,79 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Smoke Grenade"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/smoke.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false
|
||||
|
||||
ENT.ImpactDamage = 1
|
||||
|
||||
ENT.Delay = 2
|
||||
|
||||
ENT.BounceSounds = {
|
||||
"TacRP/weapons/grenade/smoke_bounce-1.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-2.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-3.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-4.wav",
|
||||
}
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/smoke_explode-1.wav",
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
if self:WaterLevel() > 0 then self:Remove() return end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 75)
|
||||
|
||||
local cloud = ents.Create( "TacRP_smoke_cloud" )
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:Spawn()
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail then
|
||||
local pos = self:GetPos() + self:GetUp() * 4
|
||||
local emitter = ParticleEmitter(pos)
|
||||
|
||||
local smoke = emitter:Add(GetSmokeImage(), pos)
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(2)
|
||||
smoke:SetEndSize(math.Rand(16, 24))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetVelocity(VectorRand() * 8 + self:GetUp() * 16)
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(false)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.25, 0.5))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 25))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
113
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_thermite.lua
Normal file
113
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_thermite.lua
Normal file
@@ -0,0 +1,113 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Thermite Grenade"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/smoke.mdl"
|
||||
|
||||
ENT.Material = "models/tacint/weapons/w_models/smoke/thermite-1"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
ENT.DefuseOnDamage = true
|
||||
|
||||
ENT.ImpactDamage = 1
|
||||
|
||||
ENT.Delay = 3
|
||||
|
||||
|
||||
ENT.SoundHint = true
|
||||
ENT.SoundHintDelay = 1.5
|
||||
ENT.SoundHintRadius = 328
|
||||
ENT.SoundHintDuration = 1.5
|
||||
|
||||
ENT.Sticky = true
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"^TacRP/weapons/grenade/frag_explode-1.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-2.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-3.wav",
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
if self:WaterLevel() > 0 then self:Remove() return end
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
-- local dmg = 50
|
||||
-- if self.ImpactFuse then dmg = dmg * 0.5 end
|
||||
-- util.BlastDamage(self, attacker, self:GetPos(), 350, dmg)
|
||||
|
||||
self:EmitSound("ambient/fire/gascan_ignite1.wav", 80, 110)
|
||||
|
||||
local cloud = ents.Create( "TacRP_fire_cloud" )
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
local t = 8
|
||||
if self.ImpactFuse then t = t * 0.5 end
|
||||
|
||||
cloud.FireTime = t
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetAngles(self:GetAngles())
|
||||
cloud:SetOwner(attacker)
|
||||
cloud:Spawn()
|
||||
if IsValid(self:GetParent()) then
|
||||
cloud:SetParent(self:GetParent())
|
||||
elseif self:GetMoveType() == MOVETYPE_NONE then
|
||||
cloud:SetMoveType(MOVETYPE_NONE)
|
||||
end
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
ENT.NextDamageTick = 0
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail then
|
||||
local pos = self:GetPos() + self:GetUp() * 4
|
||||
local emitter = ParticleEmitter(pos)
|
||||
|
||||
local smoke = emitter:Add("particles/smokey", pos)
|
||||
|
||||
smoke:SetStartAlpha(30)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(2)
|
||||
smoke:SetEndSize(math.Rand(16, 24))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetVelocity(VectorRand() * 16 + Vector(0, 0, 64))
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(false)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.5, 1))
|
||||
smoke:SetGravity(Vector(0, 0, -100))
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
local col1 = Color(255, 135, 0)
|
||||
local col2 = Color(255, 255, 255)
|
||||
|
||||
local col3 = col1
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
col3.r = Lerp(d, col1.r, col2.r)
|
||||
col3.g = Lerp(d, col1.g, col2.g)
|
||||
col3.b = Lerp(d, col1.b, col2.b)
|
||||
|
||||
pa:SetColor(col3.r, col3.g, col3.b)
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
232
garrysmod/addons/tacrp/lua/entities/tacrp_proj_p2a1_flare.lua
Normal file
232
garrysmod/addons/tacrp/lua/entities/tacrp_proj_p2a1_flare.lua
Normal file
@@ -0,0 +1,232 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "P2A1 Signal Flare"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnImpact = true
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 8
|
||||
ENT.SafetyFuse = 0
|
||||
|
||||
ENT.ImpactDamage = 50
|
||||
ENT.ImpactDamageType = DMG_BURN + DMG_SLOWBURN
|
||||
|
||||
ENT.AudioLoop = false
|
||||
|
||||
ENT.Radius = 200
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(255, 200, 200)
|
||||
ENT.FlareSizeMin = 16
|
||||
ENT.FlareSizeMax = 32
|
||||
ENT.Gravity = Vector(0, 0, 9.81 * 0.333333)
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel(self.Model)
|
||||
self:PhysicsInitBox(-Vector(3, 3, 3), Vector(3, 3, 3) )
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_PROJECTILE)
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if !phys:IsValid() then
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
phys:EnableDrag(false)
|
||||
phys:SetDragCoefficient(0)
|
||||
phys:SetMass(1)
|
||||
phys:SetBuoyancyRatio(0)
|
||||
phys:Wake()
|
||||
end
|
||||
|
||||
self.SpawnTime = CurTime()
|
||||
self.NextFlareRedirectTime = 0
|
||||
|
||||
self.NPCDamage = IsValid(self:GetOwner()) and self:GetOwner():IsNPC() and !TacRP.ConVars["npc_equality"]:GetBool()
|
||||
|
||||
if self.AudioLoop then
|
||||
self.LoopSound = CreateSound(self, self.AudioLoop)
|
||||
self.LoopSound:Play()
|
||||
end
|
||||
|
||||
if self.InstantFuse then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
if phys:IsGravityEnabled() and self:WaterLevel() <= 2 then
|
||||
local v = phys:GetVelocity()
|
||||
phys:SetVelocityInstantaneous(v + self.Gravity)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat() * (self.NPCDamage and 0.25 or 1)
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamagePosition(self:GetPos())
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetAttacker(attacker)
|
||||
|
||||
// Apply a small instance of damage to ignite first, before doing the real damage
|
||||
// This will ensure if the target dies it is on fire first (so it can ignite its ragdolls etc.)
|
||||
dmg:SetDamageType(DMG_SLOWBURN)
|
||||
dmg:SetDamage(5)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), self.Radius)
|
||||
|
||||
dmg:SetDamageType(DMG_BURN)
|
||||
dmg:SetDamage(60 * mult)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), self.Radius)
|
||||
|
||||
// TacRP.Flashbang(self, self:GetPos(), 512, 0.5, 0.1, 0)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("tacrp_flare_explode", fx)
|
||||
self:EmitSound("^ambient/fire/ignite.wav", 80, 112)
|
||||
end
|
||||
|
||||
local cloud = ents.Create("tacrp_flare_cloud")
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetAngles(self:GetAngles())
|
||||
cloud:SetOwner(attacker)
|
||||
timer.Simple(0, function()
|
||||
cloud:Spawn()
|
||||
if IsValid(self:GetParent()) then
|
||||
cloud:SetParent(self:GetParent())
|
||||
elseif self:GetMoveType() == MOVETYPE_NONE then
|
||||
cloud:SetMoveType(MOVETYPE_NONE)
|
||||
else
|
||||
cloud:GetPhysicsObject():SetVelocityInstantaneous(self:GetVelocity() * 0.5)
|
||||
end
|
||||
self:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
function ENT:Draw()
|
||||
if !self.Light and TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
self.Light = DynamicLight(self:EntIndex() + 1)
|
||||
if (self.Light) then
|
||||
self.Light.Pos = self:GetPos()
|
||||
self.Light.r = 255
|
||||
self.Light.g = 75
|
||||
self.Light.b = 60
|
||||
self.Light.Brightness = 1
|
||||
self.Light.Size = 1024
|
||||
self.Light.DieTime = CurTime() + 8
|
||||
end
|
||||
elseif self.Light then
|
||||
self.Light.Pos = self:GetPos()
|
||||
end
|
||||
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos(), math.Rand(self.FlareSizeMin, self.FlareSizeMax), math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if self.Light then
|
||||
self.Light.Size = 1200
|
||||
self.Light.Brightness = 1.5
|
||||
self.Light.DieTime = CurTime() + 1
|
||||
self.Light.Decay = 2000
|
||||
end
|
||||
if !self.FireSound then return end
|
||||
self.FireSound:Stop()
|
||||
end
|
||||
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and !(self:GetOwner() == LocalPlayer() and (self.SpawnTime + 0.1) > CurTime()) then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add("particles/smokey", self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(30)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(4)
|
||||
smoke:SetEndSize(math.Rand(30, 40))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 4)
|
||||
|
||||
smoke:SetColor(255, 50, 25)
|
||||
smoke:SetLighting(false)
|
||||
smoke:SetDieTime(math.Rand(3.5, 4.5))
|
||||
smoke:SetGravity(Vector(0, 0, -7))
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
local col1 = Color(255, 50, 25)
|
||||
local col2 = Color(255, 155, 155)
|
||||
|
||||
local col3 = col1
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
col3.r = Lerp(d, col1.r, col2.r)
|
||||
col3.g = Lerp(d, col1.g, col2.g)
|
||||
col3.b = Lerp(d, col1.b, col2.b)
|
||||
|
||||
pa:SetColor(col3.r, col3.g, col3.b)
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function ENT:SafetyImpact(data, collider)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("StunstickImpact", fx)
|
||||
|
||||
if IsValid(data.HitEntity) then
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker(attacker)
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamageType(DMG_CRUSH + DMG_SLOWBURN)
|
||||
dmginfo:SetDamage(self.ImpactDamage * (self.NPCDamage and 0.25 or 1))
|
||||
dmginfo:SetDamageForce(data.OurOldVelocity * 20)
|
||||
dmginfo:SetDamagePosition(data.HitPos)
|
||||
data.HitEntity:TakeDamageInfo(dmginfo)
|
||||
end
|
||||
|
||||
self:EmitSound("physics/plastic/plastic_barrel_impact_hard2.wav", 70, 110)
|
||||
end
|
||||
|
||||
function ENT:UpdateTransmitState()
|
||||
if TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
return TRANSMIT_ALWAYS
|
||||
end
|
||||
return TRANSMIT_PVS
|
||||
end
|
||||
@@ -0,0 +1,232 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "P2A1 Signal Flare"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnImpact = true
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 10
|
||||
ENT.SafetyFuse = 0
|
||||
|
||||
ENT.ImpactDamage = 50
|
||||
ENT.ImpactDamageType = DMG_BURN + DMG_SLOWBURN
|
||||
|
||||
ENT.AudioLoop = false
|
||||
|
||||
ENT.Radius = 200
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(255, 200, 200)
|
||||
ENT.FlareSizeMin = 320
|
||||
ENT.FlareSizeMax = 640
|
||||
ENT.Gravity = Vector(0, 0, 9.81 * 0.333333)
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel(self.Model)
|
||||
self:PhysicsInitBox(-Vector(3, 3, 3), Vector(3, 3, 3) )
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_PROJECTILE)
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if !phys:IsValid() then
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
phys:EnableDrag(false)
|
||||
phys:SetDragCoefficient(0)
|
||||
phys:SetMass(1)
|
||||
phys:SetBuoyancyRatio(0)
|
||||
phys:Wake()
|
||||
end
|
||||
|
||||
self.SpawnTime = CurTime()
|
||||
self.NextFlareRedirectTime = 0
|
||||
|
||||
self.NPCDamage = IsValid(self:GetOwner()) and self:GetOwner():IsNPC() and !TacRP.ConVars["npc_equality"]:GetBool()
|
||||
|
||||
if self.AudioLoop then
|
||||
self.LoopSound = CreateSound(self, self.AudioLoop)
|
||||
self.LoopSound:Play()
|
||||
end
|
||||
|
||||
if self.InstantFuse then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
if phys:IsGravityEnabled() and self:WaterLevel() <= 2 then
|
||||
local v = phys:GetVelocity()
|
||||
phys:SetVelocityInstantaneous(v + self.Gravity)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat() * (self.NPCDamage and 0.25 or 1)
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamagePosition(self:GetPos())
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetAttacker(attacker)
|
||||
|
||||
// Apply a small instance of damage to ignite first, before doing the real damage
|
||||
// This will ensure if the target dies it is on fire first (so it can ignite its ragdolls etc.)
|
||||
dmg:SetDamageType(DMG_SLOWBURN)
|
||||
dmg:SetDamage(5)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), self.Radius)
|
||||
|
||||
dmg:SetDamageType(DMG_BURN)
|
||||
dmg:SetDamage(60 * mult)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), self.Radius)
|
||||
|
||||
// TacRP.Flashbang(self, self:GetPos(), 512, 0.5, 0.1, 0)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("tacrp_flare_explode", fx)
|
||||
self:EmitSound("^ambient/fire/ignite.wav", 80, 112)
|
||||
end
|
||||
|
||||
local cloud = ents.Create("tacrp_flare_cloud_signal")
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetAngles(self:GetAngles())
|
||||
cloud:SetOwner(attacker)
|
||||
timer.Simple(0, function()
|
||||
cloud:Spawn()
|
||||
if IsValid(self:GetParent()) then
|
||||
cloud:SetParent(self:GetParent())
|
||||
elseif self:GetMoveType() == MOVETYPE_NONE then
|
||||
cloud:SetMoveType(MOVETYPE_NONE)
|
||||
else
|
||||
cloud:GetPhysicsObject():SetVelocityInstantaneous(self:GetVelocity() * 0.5)
|
||||
end
|
||||
self:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
function ENT:Draw()
|
||||
if !self.Light and TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
self.Light = DynamicLight(self:EntIndex() + 1)
|
||||
if (self.Light) then
|
||||
self.Light.Pos = self:GetPos()
|
||||
self.Light.r = 255
|
||||
self.Light.g = 75
|
||||
self.Light.b = 60
|
||||
self.Light.Brightness = 1
|
||||
self.Light.Size = 1024
|
||||
self.Light.DieTime = CurTime() + 8
|
||||
end
|
||||
elseif self.Light then
|
||||
self.Light.Pos = self:GetPos()
|
||||
end
|
||||
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos(), math.Rand(self.FlareSizeMin, self.FlareSizeMax), math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if self.Light then
|
||||
self.Light.Size = 1200
|
||||
self.Light.Brightness = 1.5
|
||||
self.Light.DieTime = CurTime() + 1
|
||||
self.Light.Decay = 2000
|
||||
end
|
||||
if !self.FireSound then return end
|
||||
self.FireSound:Stop()
|
||||
end
|
||||
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and !(self:GetOwner() == LocalPlayer() and (self.SpawnTime + 0.1) > CurTime()) then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add("particles/smokey", self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(30)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(4)
|
||||
smoke:SetEndSize(math.Rand(30, 40))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 4)
|
||||
|
||||
smoke:SetColor(255, 50, 25)
|
||||
smoke:SetLighting(false)
|
||||
smoke:SetDieTime(math.Rand(3.5, 4.5))
|
||||
smoke:SetGravity(Vector(0, 0, -7))
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
local col1 = Color(255, 50, 25)
|
||||
local col2 = Color(255, 155, 155)
|
||||
|
||||
local col3 = col1
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
col3.r = Lerp(d, col1.r, col2.r)
|
||||
col3.g = Lerp(d, col1.g, col2.g)
|
||||
col3.b = Lerp(d, col1.b, col2.b)
|
||||
|
||||
pa:SetColor(col3.r, col3.g, col3.b)
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function ENT:SafetyImpact(data, collider)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("StunstickImpact", fx)
|
||||
|
||||
if IsValid(data.HitEntity) then
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker(attacker)
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamageType(DMG_CRUSH + DMG_SLOWBURN)
|
||||
dmginfo:SetDamage(self.ImpactDamage * (self.NPCDamage and 0.25 or 1))
|
||||
dmginfo:SetDamageForce(data.OurOldVelocity * 20)
|
||||
dmginfo:SetDamagePosition(data.HitPos)
|
||||
data.HitEntity:TakeDamageInfo(dmginfo)
|
||||
end
|
||||
|
||||
self:EmitSound("physics/plastic/plastic_barrel_impact_hard2.wav", 70, 110)
|
||||
end
|
||||
|
||||
function ENT:UpdateTransmitState()
|
||||
if TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
return TRANSMIT_ALWAYS
|
||||
end
|
||||
return TRANSMIT_PVS
|
||||
end
|
||||
58
garrysmod/addons/tacrp/lua/entities/tacrp_proj_p2a1_heal.lua
Normal file
58
garrysmod/addons/tacrp/lua/entities/tacrp_proj_p2a1_heal.lua
Normal file
@@ -0,0 +1,58 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_p2a1_flare"
|
||||
ENT.PrintName = "P2A1 Medi-Smoke Flare"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(100, 50, 255)
|
||||
ENT.FlareSizeMin = 16
|
||||
ENT.FlareSizeMax = 32
|
||||
ENT.Gravity = Vector(0, 0, 9.81 * 0.3333)
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
|
||||
self:EmitSound("TacRP/weapons/grenade/smoke_explode-1.wav", 80, 108)
|
||||
timer.Simple(0, function()
|
||||
local cloud = ents.Create( "tacrp_heal_cloud_p2a1" )
|
||||
if !IsValid(cloud) then return end
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetOwner(self:GetOwner())
|
||||
cloud:Spawn()
|
||||
self:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
function ENT:Draw()
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos(), math.Rand(self.FlareSizeMin, self.FlareSizeMax), math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and !(self:GetOwner() == LocalPlayer() and (self.SpawnTime + 0.1) > CurTime()) then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add("particles/smokey", self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(4)
|
||||
smoke:SetEndSize(math.Rand(25, 35))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 32)
|
||||
smoke:SetColor(125, 25, 255)
|
||||
smoke:SetLighting(false)
|
||||
smoke:SetDieTime(math.Rand(0.3, 0.5))
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,148 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_p2a1_flare"
|
||||
ENT.PrintName = "P2A1 Incendiary Flare"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Radius = 328
|
||||
|
||||
ENT.SafetyFuse = 0.3
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(255, 200, 100)
|
||||
ENT.FlareSizeMin = 16
|
||||
ENT.FlareSizeMax = 32
|
||||
ENT.Gravity = Vector(0, 0, 9.81 * 0.3)
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat() * (self.NPCDamage and 0.25 or 1)
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamagePosition(self:GetPos())
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetAttacker(attacker)
|
||||
|
||||
// Apply a small instance of damage to ignite first, before doing the real damage
|
||||
// This will ensure if the target dies it is on fire first (so it can ignite its ragdolls etc.)
|
||||
dmg:SetDamageType(DMG_SLOWBURN)
|
||||
dmg:SetDamage(5)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), self.Radius)
|
||||
|
||||
dmg:SetDamageType(DMG_BURN)
|
||||
dmg:SetDamage(60 * mult)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), self.Radius)
|
||||
|
||||
// TacRP.Flashbang(self, self:GetPos(), 512, 0.5, 0.1, 0)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("tacrp_m202_explode", fx)
|
||||
self:EmitSound("^ambient/fire/ignite.wav", 80, 108)
|
||||
self:EmitSound("^weapons/explode5.wav", 80, 115, 0.8)
|
||||
end
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
function ENT:Draw()
|
||||
if !self.Light and TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
self.Light = DynamicLight(self:EntIndex() + 1)
|
||||
if (self.Light) then
|
||||
self.Light.Pos = self:GetPos()
|
||||
self.Light.r = 255
|
||||
self.Light.g = 128
|
||||
self.Light.b = 50
|
||||
self.Light.Brightness = 1
|
||||
self.Light.Size = 328
|
||||
self.Light.DieTime = CurTime() + 30
|
||||
end
|
||||
elseif self.Light then
|
||||
self.Light.Pos = self:GetPos()
|
||||
end
|
||||
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos(), math.Rand(self.FlareSizeMin, self.FlareSizeMax), math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if self.Light then
|
||||
self.Light.Size = 728
|
||||
self.Light.Brightness = 1
|
||||
self.Light.DieTime = CurTime() + 4
|
||||
self.Light.Decay = 250
|
||||
end
|
||||
if !self.FireSound then return end
|
||||
self.FireSound:Stop()
|
||||
end
|
||||
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and !(self:GetOwner() == LocalPlayer() and (self.SpawnTime + 0.1) > CurTime()) then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add("particles/smokey", self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(4)
|
||||
smoke:SetEndSize(math.Rand(25, 35))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 32)
|
||||
|
||||
smoke:SetColor(255, 200, 25)
|
||||
smoke:SetLighting(false)
|
||||
smoke:SetDieTime(math.Rand(0.3, 0.5))
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
local col1 = Color(255, 128, 50)
|
||||
local col2 = Color(220, 200, 180)
|
||||
|
||||
local col3 = col1
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
col3.r = Lerp(d, col1.r, col2.r)
|
||||
col3.g = Lerp(d, col1.g, col2.g)
|
||||
col3.b = Lerp(d, col1.b, col2.b)
|
||||
|
||||
pa:SetColor(col3.r, col3.g, col3.b)
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function ENT:SafetyImpact(data, collider)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("StunstickImpact", fx)
|
||||
|
||||
if IsValid(data.HitEntity) then
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker(attacker)
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamageType(self.ImpactDamageType)
|
||||
dmginfo:SetDamage(self.ImpactDamage * (self.NPCDamage and 0.25 or 1))
|
||||
dmginfo:SetDamageForce(data.OurOldVelocity * 20)
|
||||
dmginfo:SetDamagePosition(data.HitPos)
|
||||
data.HitEntity:TakeDamageInfo(dmginfo)
|
||||
end
|
||||
|
||||
self:EmitSound("physics/plastic/plastic_barrel_impact_hard2.wav", 70, 110)
|
||||
end
|
||||
@@ -0,0 +1,113 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_p2a1_flare"
|
||||
ENT.PrintName = "P2A1 Parachute Flare"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.InstantFuse = true
|
||||
ENT.RemoteFuse = false
|
||||
ENT.ImpactFuse = false
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 2
|
||||
|
||||
ENT.Radius = 328
|
||||
|
||||
ENT.FlareColor = Color(255, 240, 240)
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
self:EmitSound("tacint_extras/p2a1/confetti.wav", 80, 80)
|
||||
end
|
||||
|
||||
local cloud = ents.Create("tacrp_flare_cloud_para")
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetAngles(self:GetAngles())
|
||||
cloud:SetOwner(attacker)
|
||||
timer.Simple(0, function()
|
||||
cloud:Spawn()
|
||||
if IsValid(self:GetParent()) then
|
||||
cloud:SetParent(self:GetParent())
|
||||
elseif self:GetMoveType() == MOVETYPE_NONE then
|
||||
cloud:SetMoveType(MOVETYPE_NONE)
|
||||
else
|
||||
cloud:GetPhysicsObject():SetVelocityInstantaneous(self:GetVelocity() * 1 + Vector(math.Rand(-64, 64), math.Rand(-64, 64), 256))
|
||||
end
|
||||
self:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
function ENT:Draw()
|
||||
if !self.Light and TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
self.Light = DynamicLight(self:EntIndex() + 1)
|
||||
if (self.Light) then
|
||||
self.Light.Pos = self:GetPos()
|
||||
self.Light.r = 255
|
||||
self.Light.g = 200
|
||||
self.Light.b = 100
|
||||
self.Light.Brightness = 0.5
|
||||
self.Light.Size = 728
|
||||
self.Light.DieTime = CurTime() + 2
|
||||
end
|
||||
elseif self.Light then
|
||||
self.Light.Pos = self:GetPos()
|
||||
end
|
||||
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos(), math.Rand(self.FlareSizeMin, self.FlareSizeMax), math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and !(self:GetOwner() == LocalPlayer() and (self.SpawnTime + 0.1) > CurTime()) then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add("particles/smokey", self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(30)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(4)
|
||||
smoke:SetEndSize(math.Rand(30, 40))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 4)
|
||||
|
||||
smoke:SetColor(255, 50, 25)
|
||||
smoke:SetLighting(false)
|
||||
smoke:SetDieTime(math.Rand(3.5, 4.5))
|
||||
smoke:SetGravity(Vector(0, 0, -7))
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
local col1 = Color(255, 200, 150)
|
||||
local col2 = Color(255, 255, 225)
|
||||
|
||||
local col3 = col1
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
col3.r = Lerp(d, col1.r, col2.r)
|
||||
col3.g = Lerp(d, col1.g, col2.g)
|
||||
col3.b = Lerp(d, col1.b, col2.b)
|
||||
|
||||
pa:SetColor(col3.r, col3.g, col3.b)
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,59 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_p2a1_flare"
|
||||
ENT.PrintName = "P2A1 Smoke Flare"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(255, 255, 255)
|
||||
ENT.FlareSizeMin = 16
|
||||
ENT.FlareSizeMax = 32
|
||||
ENT.Gravity = Vector(0, 0, 9.81 * 0.3333)
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
|
||||
self:EmitSound("TacRP/weapons/grenade/smoke_explode-1.wav", 80, 108)
|
||||
timer.Simple(0, function()
|
||||
local cloud = ents.Create( "tacrp_smoke_cloud_p2a1" )
|
||||
if !IsValid(cloud) then return end
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetOwner(self:GetOwner())
|
||||
cloud:Spawn()
|
||||
self:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
function ENT:Draw()
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos(), math.Rand(self.FlareSizeMin, self.FlareSizeMax), math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and !(self:GetOwner() == LocalPlayer() and (self.SpawnTime + 0.1) > CurTime()) then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add("particles/smokey", self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(4)
|
||||
smoke:SetEndSize(math.Rand(25, 35))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 32)
|
||||
|
||||
smoke:SetColor(255, 255, 255)
|
||||
smoke:SetLighting(false)
|
||||
smoke:SetDieTime(math.Rand(0.3, 0.5))
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
46
garrysmod/addons/tacrp/lua/entities/tacrp_proj_rpg7.lua
Normal file
46
garrysmod/addons/tacrp/lua/entities/tacrp_proj_rpg7.lua
Normal file
@@ -0,0 +1,46 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "RPG-7 Rocket"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.SafetyFuse = 0.075
|
||||
ENT.ImpactDamage = 150
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 255, 255)
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat() * (self.NPCDamage and 0.25 or 1)
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 350, 200 * mult)
|
||||
self:ImpactTraceAttack(ent, 1000 * mult, 15000)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
end
|
||||
|
||||
self:EmitSound("TacRP/weapons/rpg7/explode.wav", 125)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
155
garrysmod/addons/tacrp/lua/entities/tacrp_proj_rpg7_harpoon.lua
Normal file
155
garrysmod/addons/tacrp/lua/entities/tacrp_proj_rpg7_harpoon.lua
Normal file
@@ -0,0 +1,155 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "RPG7 Shovel" -- not actually a harpoon lol
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/props_junk/Shovel01a.mdl"
|
||||
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
ENT.InstantFuse = false
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.SmokeTrail = false
|
||||
|
||||
local path = "tacrp/weapons/knife/"
|
||||
ENT.Sound_MeleeHit = {
|
||||
"physics/metal/metal_box_impact_hard1.wav",
|
||||
"physics/metal/metal_box_impact_hard2.wav",
|
||||
"physics/metal/metal_box_impact_hard3.wav",
|
||||
}
|
||||
ENT.Sound_MeleeHitBody = {
|
||||
path .. "/flesh_hit-1.wav",
|
||||
path .. "/flesh_hit-2.wav",
|
||||
path .. "/flesh_hit-3.wav",
|
||||
path .. "/flesh_hit-4.wav",
|
||||
path .. "/flesh_hit-5.wav",
|
||||
}
|
||||
|
||||
function ENT:OnInitialize()
|
||||
if SERVER then
|
||||
self:GetPhysicsObject():SetMass(50)
|
||||
self:GetPhysicsObject():SetDragCoefficient(5)
|
||||
end
|
||||
self.Attacker = self.Attacker or self:GetOwner()
|
||||
end
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
local tgt = data.HitEntity
|
||||
local attacker = self.Attacker or (IsValid(self:GetOwner()) and self:GetOwner()) or self
|
||||
local d = data.OurOldVelocity:GetNormalized()
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
|
||||
local speed = data.Speed
|
||||
if speed <= 50 then return true end
|
||||
|
||||
local dmg = self.NPCDamage and 75 or math.Clamp(speed / 15, 50, 200)
|
||||
|
||||
if IsValid(tgt) then
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker(attacker)
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamageType(DMG_CLUB)
|
||||
dmginfo:SetDamage(dmg)
|
||||
dmginfo:SetDamageForce(data.OurOldVelocity)
|
||||
dmginfo:SetDamagePosition(data.HitPos)
|
||||
tgt:TakeDamageInfo(dmginfo)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("ManhackSparks", fx)
|
||||
else
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
|
||||
-- leave a bullet hole. Also may be able to hit things it can't collide with (like stuck C4)
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Damage = dmg,
|
||||
Force = 1,
|
||||
Distance = 4,
|
||||
HullSize = 4,
|
||||
Tracer = 0,
|
||||
Dir = ang:Forward(),
|
||||
Src = data.HitPos - ang:Forward(),
|
||||
IgnoreEntity = self,
|
||||
Callback = function(atk, tr, dmginfo)
|
||||
dmginfo:SetDamageType(DMG_CLUB)
|
||||
dmginfo:SetInflictor(attacker)
|
||||
if tr.HitSky then
|
||||
SafeRemoveEntity(self)
|
||||
else
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("ManhackSparks", fx)
|
||||
if SERVER then
|
||||
self:EmitSound(istable(self.Sound_MeleeHit) and self.Sound_MeleeHit[math.random(1, #self.Sound_MeleeHit)] or self.Sound_MeleeHit, 80, 110, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
self:GetPhysicsObject():SetVelocityInstantaneous(data.OurNewVelocity * 0.5)
|
||||
|
||||
timer.Simple(0.01, function()
|
||||
if IsValid(self) then
|
||||
self:SetOwner(NULL) -- lol
|
||||
self:SetCollisionGroup(COLLISION_GROUP_INTERACTIVE)
|
||||
end
|
||||
end)
|
||||
timer.Simple(5, function()
|
||||
if IsValid(self) then
|
||||
self:SetRenderMode(RENDERMODE_TRANSALPHA)
|
||||
self:SetRenderFX(kRenderFxFadeFast)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
end
|
||||
end)
|
||||
SafeRemoveEntityDelayed(self, 7)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local g = Vector(0, 0, -9.81)
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
if !self.Armed and phys:IsGravityEnabled() and self:WaterLevel() <= 2 then
|
||||
local v = phys:GetVelocity()
|
||||
local a = v:Angle()
|
||||
a.p = a.p - 90
|
||||
self:SetAngles(a)
|
||||
phys:SetVelocityInstantaneous(v * 0.985 + g)
|
||||
end
|
||||
end
|
||||
|
||||
ENT.SmokeTrail = false
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and self:GetVelocity():Length() >= 100 then
|
||||
local pos = self:GetPos()
|
||||
local emitter = ParticleEmitter(pos)
|
||||
local smoke = emitter:Add(GetSmokeImage(), pos)
|
||||
|
||||
smoke:SetStartAlpha(25)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(2)
|
||||
smoke:SetEndSize(math.Rand(16, 24))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetVelocity(VectorRand() * 8 + self:GetUp() * 16)
|
||||
smoke:SetColor(255, 255, 255)
|
||||
smoke:SetLighting(true)
|
||||
smoke:SetDieTime(math.Rand(0.5, 0.75))
|
||||
smoke:SetGravity(Vector(0, 0, 15))
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,253 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "RPG-7 Improvised Rocket"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.SafetyFuse = 0
|
||||
ENT.BoostTime = 5
|
||||
ENT.ImpactDamage = 150
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 255, 75)
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Bool", 0, "NoBooster")
|
||||
self:NetworkVar("Entity", 0, "Weapon")
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
BaseClass.Initialize(self)
|
||||
|
||||
if SERVER then
|
||||
local phys = self:GetPhysicsObject()
|
||||
local rng = math.random()
|
||||
if rng <= 0.01 then
|
||||
self:EmitSound("weapons/rpg/shotdown.wav", 80, 95)
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos() + self:GetForward() * 32)
|
||||
fx:SetStart(Vector(math.Rand(0, 255), math.Rand(0, 255), math.Rand(0, 255)))
|
||||
util.Effect("balloon_pop", fx)
|
||||
self:GetOwner():EmitSound("tacrp/kids_cheering.mp3", 100, 100, 1)
|
||||
SafeRemoveEntity(self)
|
||||
elseif rng <= 0.25 then
|
||||
self.BoostTime = math.Rand(0.5, 5)
|
||||
|
||||
self:EmitSound("weapons/rpg/shotdown.wav", 80, 95)
|
||||
|
||||
self:SetNoBooster(math.random() <= 0.2)
|
||||
phys:EnableGravity(true)
|
||||
|
||||
if self:GetNoBooster() then
|
||||
phys:SetVelocityInstantaneous(self:GetOwner():GetVelocity() + self:GetForward() * math.Rand(25, 75) + self:GetUp() * math.Rand(75, 150))
|
||||
else
|
||||
phys:SetVelocityInstantaneous(self:GetOwner():GetVelocity() + self:GetForward() * math.Rand(100, 500) + self:GetUp() * math.Rand(50, 200))
|
||||
end
|
||||
phys:AddAngleVelocity(VectorRand() * 180)
|
||||
else
|
||||
self.BoostTime = math.Rand(1, 3)
|
||||
phys:SetVelocityInstantaneous(self:GetForward() * math.Rand(3000, 6000))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
|
||||
if math.random() <= 0.05 then
|
||||
self:EmitSound("physics/metal/metal_barrel_impact_hard3.wav", 125, 115)
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
fx:SetMagnitude(4)
|
||||
fx:SetScale(4)
|
||||
fx:SetRadius(4)
|
||||
fx:SetNormal(self:GetVelocity():GetNormalized())
|
||||
util.Effect("Sparks", fx)
|
||||
|
||||
for i = 1, 4 do
|
||||
local prop = ents.Create("prop_physics")
|
||||
prop:SetPos(self:GetPos())
|
||||
prop:SetAngles(self:GetAngles())
|
||||
prop:SetModel("models/weapons/tacint/rpg7_shrapnel_p" .. i .. ".mdl")
|
||||
prop:Spawn()
|
||||
prop:GetPhysicsObject():SetVelocityInstantaneous(self:GetVelocity() * 0.5 + VectorRand() * 75)
|
||||
prop:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
|
||||
SafeRemoveEntityDelayed(prop, 3)
|
||||
end
|
||||
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat()
|
||||
if self.NPCDamage then
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 350, 100)
|
||||
else
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 350, math.Rand(150, 250) * mult)
|
||||
self:ImpactTraceAttack(ent, math.Rand(750, 1500) * mult, math.Rand(7500, 20000))
|
||||
end
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
end
|
||||
|
||||
self:EmitSound("TacRP/weapons/rpg7/explode.wav", 125)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
if self:GetNoBooster() then return end
|
||||
local len = phys:GetVelocity():Length()
|
||||
local f = math.Clamp(len / 5000, 0, 1)
|
||||
if phys:IsGravityEnabled() then
|
||||
phys:AddVelocity(self:GetForward() * math.Rand(0, Lerp(f, 100, 10)))
|
||||
phys:AddAngleVelocity(VectorRand() * Lerp(f, 8, 2))
|
||||
elseif self.SpawnTime < CurTime() and len < 500 then
|
||||
phys:EnableGravity(true)
|
||||
else
|
||||
phys:AddVelocity(VectorRand() * Lerp(f, 5, 50) + self:GetForward() * Lerp(f, 10, 0))
|
||||
end
|
||||
end
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if !IsValid(self) or self:GetNoDraw() then return end
|
||||
|
||||
if !self.SpawnTime then
|
||||
self.SpawnTime = CurTime()
|
||||
end
|
||||
|
||||
if !self.Armed and isnumber(self.TimeFuse) and self.SpawnTime + self.TimeFuse < CurTime() then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
|
||||
if self.Armed and self.ArmTime + self.Delay < CurTime() then
|
||||
self:PreDetonate()
|
||||
end
|
||||
|
||||
if SERVER and !self:GetNoBooster() and self.SpawnTime + self.BoostTime < CurTime() then
|
||||
self:SetNoBooster(true)
|
||||
self:GetPhysicsObject():EnableGravity(true)
|
||||
end
|
||||
|
||||
if self.LoopSound and self:GetNoBooster() then
|
||||
self.LoopSound:Stop()
|
||||
end
|
||||
|
||||
if self.ExplodeUnderwater and self:WaterLevel() > 0 then
|
||||
self:PreDetonate()
|
||||
end
|
||||
|
||||
if self.SmokeTrail and CLIENT then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
if !self:GetNoBooster() then
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(10)
|
||||
smoke:SetEndSize(math.Rand(50, 75))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(-self:GetAngles():Forward() * 400 + (VectorRand() * 10))
|
||||
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.75, 1.25))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
|
||||
elseif !self.LastNoBooster then
|
||||
|
||||
for i = 1, 10 do
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(25)
|
||||
smoke:SetEndSize(math.Rand(100, 150))
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 200)
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(true)
|
||||
smoke:SetDieTime(math.Rand(0.75, 1.75))
|
||||
smoke:SetGravity(Vector(0, 0, -200))
|
||||
end
|
||||
else
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(30)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(10)
|
||||
smoke:SetEndSize(math.Rand(25, 50))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 10)
|
||||
|
||||
smoke:SetColor(150, 150, 150)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.2, 0.3))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
end
|
||||
emitter:Finish()
|
||||
|
||||
self.LastNoBooster = self:GetNoBooster()
|
||||
|
||||
end
|
||||
|
||||
|
||||
self:OnThink()
|
||||
end
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
|
||||
if self.FlareColor and !self:GetNoBooster() then
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos() + (self:GetAngles():Forward() * -16), math.Rand(100, 150), math.Rand(100, 150), self.FlareColor)
|
||||
end
|
||||
end
|
||||
250
garrysmod/addons/tacrp/lua/entities/tacrp_proj_rpg7_mortar.lua
Normal file
250
garrysmod/addons/tacrp/lua/entities/tacrp_proj_rpg7_mortar.lua
Normal file
@@ -0,0 +1,250 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "RPG-7 Mortar Rocket"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true
|
||||
|
||||
ENT.InstantFuse = false
|
||||
ENT.RemoteFuse = false
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.SafetyFuse = 0.7
|
||||
ENT.BoostTime = 0.3
|
||||
ENT.ImpactDamage = 150
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 50, 0)
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Entity", 0, "Weapon")
|
||||
self:NetworkVar("Bool", 0, "NoBooster")
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
BaseClass.Initialize(self)
|
||||
|
||||
if SERVER then
|
||||
-- self:SetAngles(self:GetAngles() + Angle(-5, 0, 0))
|
||||
local phys = self:GetPhysicsObject()
|
||||
phys:SetMass(30)
|
||||
phys:SetDragCoefficient(1)
|
||||
phys:SetVelocity(self:GetForward() * 4000)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat()
|
||||
|
||||
if self.NPCDamage then
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 512, 150 * mult)
|
||||
else
|
||||
if self.SpawnTime + self.SafetyFuse >= CurTime() then
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 256, 100 * mult)
|
||||
else
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
end
|
||||
self:EmitSound("^ambient/explosions/explode_3.wav", 100, 90, 0.75, CHAN_AUTO)
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 128, 500 * mult)
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 328, 120 * mult)
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 768, 80 * mult)
|
||||
local count = 8
|
||||
for i = 1, count do
|
||||
local tr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = self:GetPos() + Angle(0, i / count * 360, 0):Forward() * 328 * math.Rand(0.75, 1),
|
||||
mask = MASK_SHOT,
|
||||
filter = self,
|
||||
})
|
||||
fx:SetOrigin(tr.HitPos)
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
end
|
||||
end
|
||||
self:EmitSound("TacRP/weapons/rpg7/explode.wav", 125, 95)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if !IsValid(self) or self:GetNoDraw() then return end
|
||||
|
||||
if !self.SpawnTime then
|
||||
self.SpawnTime = CurTime()
|
||||
end
|
||||
|
||||
if !self.Armed and isnumber(self.TimeFuse) and self.SpawnTime + self.TimeFuse < CurTime() then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
|
||||
if self.Armed and self.ArmTime + self.Delay < CurTime() then
|
||||
self:PreDetonate()
|
||||
end
|
||||
|
||||
if SERVER and !self:GetNoBooster() and self.SpawnTime + self.BoostTime < CurTime() then
|
||||
self:SetNoBooster(true)
|
||||
self:GetPhysicsObject():EnableGravity(true)
|
||||
self:GetPhysicsObject():SetVelocityInstantaneous(self:GetVelocity() * 0.5)
|
||||
end
|
||||
|
||||
if self.LoopSound and self:GetNoBooster() then
|
||||
self.LoopSound:Stop()
|
||||
end
|
||||
|
||||
if self.ExplodeUnderwater and self:WaterLevel() > 0 then
|
||||
self:PreDetonate()
|
||||
end
|
||||
|
||||
if self.SmokeTrail and CLIENT then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
if !self:GetNoBooster() then
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(10)
|
||||
smoke:SetEndSize(math.Rand(50, 75))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(-self:GetAngles():Forward() * 400 + (VectorRand() * 10))
|
||||
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.75, 1.25))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
|
||||
elseif !self.LastNoBooster then
|
||||
|
||||
for i = 1, 10 do
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(25)
|
||||
smoke:SetEndSize(math.Rand(100, 150))
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 200)
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(true)
|
||||
smoke:SetDieTime(math.Rand(0.75, 1.75))
|
||||
smoke:SetGravity(Vector(0, 0, -200))
|
||||
end
|
||||
else
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(30)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(10)
|
||||
smoke:SetEndSize(math.Rand(25, 50))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 10)
|
||||
|
||||
smoke:SetColor(150, 150, 150)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.2, 0.3))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
end
|
||||
|
||||
if CurTime() >= (self.SpawnTime + self.SafetyFuse) and !self.Sparked then
|
||||
self.Sparked = true
|
||||
for i = 1, 15 do
|
||||
local fire = emitter:Add("effects/spark", self:GetPos())
|
||||
fire:SetVelocity(VectorRand() * 512 + self:GetVelocity() * 0.25)
|
||||
fire:SetGravity(Vector(math.Rand(-5, 5), math.Rand(-5, 5), -1000))
|
||||
fire:SetDieTime(math.Rand(0.2, 0.4))
|
||||
fire:SetStartAlpha(255)
|
||||
fire:SetEndAlpha(0)
|
||||
fire:SetStartSize(8)
|
||||
fire:SetEndSize(0)
|
||||
fire:SetRoll(math.Rand(-180, 180))
|
||||
fire:SetRollDelta(math.Rand(-0.2, 0.2))
|
||||
fire:SetColor(255, 255, 255)
|
||||
fire:SetAirResistance(50)
|
||||
fire:SetLighting(false)
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(0.8)
|
||||
end
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
|
||||
self.LastNoBooster = self:GetNoBooster()
|
||||
end
|
||||
|
||||
self:OnThink()
|
||||
end
|
||||
|
||||
local g = Vector(0, 0, -9.81)
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
if phys:IsGravityEnabled() then
|
||||
local v = phys:GetVelocity()
|
||||
self:SetAngles(v:Angle())
|
||||
phys:SetVelocityInstantaneous(v + g)
|
||||
end
|
||||
|
||||
-- local v = phys:GetVelocity()
|
||||
-- self:SetAngles(v:Angle() + Angle(2, 0, 0))
|
||||
-- phys:SetVelocityInstantaneous(self:GetForward() * v:Length())
|
||||
end
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
|
||||
if self.FlareColor and !self:GetNoBooster() then
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos() + (self:GetAngles():Forward() * -16), math.Rand(100, 150), math.Rand(100, 150), self.FlareColor)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,98 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "RPG-7 Ratshot"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
ENT.TimeFuse = false
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0.3
|
||||
ENT.SafetyFuse = 0.3
|
||||
ENT.ImpactDamage = 150
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(75, 175, 255)
|
||||
|
||||
function ENT:Detonate()
|
||||
local dir = self:GetForward()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local src = self:GetPos() - dir * 64
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(src)
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
fx:SetMagnitude(8)
|
||||
fx:SetScale(2)
|
||||
fx:SetRadius(8)
|
||||
fx:SetNormal(dir)
|
||||
util.Effect("Sparks", fx)
|
||||
|
||||
local tr = util.TraceHull({
|
||||
start = src,
|
||||
endpos = src + dir * 2048,
|
||||
filter = self,
|
||||
mins = Vector(-16, -16, -8),
|
||||
maxs = Vector(16, 16, 8)
|
||||
})
|
||||
fx:SetMagnitude(4)
|
||||
fx:SetScale(1)
|
||||
fx:SetRadius(2)
|
||||
fx:SetNormal(dir)
|
||||
for i = 1, math.floor(tr.Fraction * 6) do
|
||||
fx:SetOrigin(tr.StartPos + tr.Normal * (i / 6) * 2048)
|
||||
util.Effect("Sparks", fx)
|
||||
end
|
||||
end
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat() * (self.NPCDamage and 0.25 or 1)
|
||||
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Damage = 5,
|
||||
Force = 1,
|
||||
Distance = 2048,
|
||||
HullSize = 16,
|
||||
Num = 48,
|
||||
Tracer = 1,
|
||||
Src = src,
|
||||
Dir = dir,
|
||||
Spread = Vector(1, 1, 0),
|
||||
IgnoreEntity = self,
|
||||
})
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetDamageType(DMG_BULLET + DMG_BLAST)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamageForce(self:GetVelocity() * 100)
|
||||
dmg:SetDamagePosition(src)
|
||||
for _, ent in pairs(ents.FindInCone(src, dir, 2048, 0.707)) do
|
||||
local tr = util.QuickTrace(src, ent:GetPos() - src, {self, ent})
|
||||
if tr.Fraction == 1 then
|
||||
dmg:SetDamage(130 * math.Rand(0.75, 1) * Lerp((ent:GetPos():DistToSqr(src) / 4194304) ^ 0.5, 1, 0.25) * mult)
|
||||
if !ent:IsOnGround() then dmg:ScaleDamage(1.5) end
|
||||
ent:TakeDamageInfo(dmg)
|
||||
end
|
||||
end
|
||||
|
||||
util.BlastDamage(self, attacker, src, 256, 50 * mult)
|
||||
|
||||
self:EmitSound("TacRP/weapons/rpg7/explode.wav", 125, 100)
|
||||
self:EmitSound("physics/metal/metal_box_break1.wav", 100, 200)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
73
garrysmod/addons/tacrp/lua/entities/tacrp_proj_stinger.lua
Normal file
73
garrysmod/addons/tacrp/lua/entities/tacrp_proj_stinger.lua
Normal file
@@ -0,0 +1,73 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "FIM-92 Missile"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.GunshipWorkaround = false
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.SafetyFuse = 0.1
|
||||
ENT.ImpactDamage = 150
|
||||
|
||||
ENT.SteerSpeed = 120
|
||||
ENT.SeekerAngle = 55
|
||||
|
||||
ENT.LeadTarget = true
|
||||
ENT.SuperSteerTime = 1
|
||||
ENT.SuperSteerSpeed = 240
|
||||
|
||||
ENT.MaxSpeed = 5000
|
||||
ENT.Acceleration = 4000
|
||||
|
||||
ENT.SteerDelay = 0.5
|
||||
ENT.FlareRedirectChance = 0.2
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 255, 255)
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
local dir = self:GetForward()
|
||||
local src = self:GetPos() - dir * 64
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat()
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetDamageType(DMG_BLAST + DMG_AIRBOAT)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamageForce(self:GetVelocity() * 100)
|
||||
dmg:SetDamagePosition(src)
|
||||
dmg:SetDamage(100 * mult)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), 256)
|
||||
self:ImpactTraceAttack(ent, 500 * mult, 100)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
end
|
||||
|
||||
self:EmitSound("TacRP/weapons/rpg7/explode.wav", 125)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
@@ -0,0 +1,71 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_stinger"
|
||||
ENT.PrintName = "FIM-92 Missile (4AAM)"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.GunshipWorkaround = false
|
||||
|
||||
ENT.FlareSizeMin = 150
|
||||
ENT.FlareSizeMax = 200
|
||||
|
||||
ENT.SafetyFuse = 0.1
|
||||
ENT.ImpactDamage = 150
|
||||
|
||||
ENT.SteerSpeed = 200
|
||||
ENT.SeekerAngle = 90
|
||||
|
||||
ENT.LeadTarget = true
|
||||
ENT.SuperSteerTime = 0.5
|
||||
ENT.SuperSteerSpeed = -90 // yes this is intentionally negative
|
||||
|
||||
ENT.MaxSpeed = 6000
|
||||
ENT.Acceleration = 2000
|
||||
|
||||
ENT.SteerDelay = 0
|
||||
ENT.FlareRedirectChance = 0.4
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 230, 200)
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
local dir = self:GetForward()
|
||||
local src = self:GetPos() - dir * 64
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat()
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetDamageType(DMG_BLAST + DMG_AIRBOAT)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamageForce(self:GetVelocity() * 100)
|
||||
dmg:SetDamagePosition(src)
|
||||
dmg:SetDamage(75 * mult)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), 200)
|
||||
self:ImpactTraceAttack(ent, 100 * mult, 100)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
|
||||
self:EmitSound("^tacrp/weapons/grenade/40mm_explode-" .. math.random(1, 3) .. ".wav", 115)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
123
garrysmod/addons/tacrp/lua/entities/tacrp_proj_stinger_apers.lua
Normal file
123
garrysmod/addons/tacrp/lua/entities/tacrp_proj_stinger_apers.lua
Normal file
@@ -0,0 +1,123 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_stinger"
|
||||
ENT.PrintName = "FIM-92 Missile (APERS)"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
ENT.TimeFuse = false
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.GunshipWorkaround = false
|
||||
|
||||
ENT.SafetyFuse = 0.1
|
||||
ENT.ImpactDamage = 150
|
||||
|
||||
ENT.SteerSpeed = 30
|
||||
ENT.SeekerAngle = 180
|
||||
ENT.SeekerExplodeRange = 728
|
||||
ENT.SeekerExplodeSnapPosition = false
|
||||
ENT.SeekerExplodeAngle = 20
|
||||
|
||||
ENT.LeadTarget = true
|
||||
ENT.SuperSteerTime = 1.5
|
||||
ENT.SuperSteerSpeed = 400
|
||||
|
||||
ENT.MaxSpeed = 2000
|
||||
ENT.Acceleration = 5000
|
||||
|
||||
ENT.SteerDelay = 0.5
|
||||
ENT.FlareRedirectChance = 0.5
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 255, 255)
|
||||
|
||||
function ENT:OnInitialize()
|
||||
if SERVER and IsValid(self.LockOnEntity) then
|
||||
local dist = self.LockOnEntity:WorldSpaceCenter():Distance(self:GetPos())
|
||||
self.SteerDelay = math.Clamp(dist / 2000, 0.75, 3)
|
||||
self.SuperSteerTime = self.SteerDelay + 0.5
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
local dir = self:GetForward()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local src = self:GetPos() - dir * 64
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(src)
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
fx:SetMagnitude(8)
|
||||
fx:SetScale(2)
|
||||
fx:SetRadius(8)
|
||||
fx:SetNormal(dir)
|
||||
util.Effect("Sparks", fx)
|
||||
|
||||
local tr = util.TraceHull({
|
||||
start = src,
|
||||
endpos = src + dir * 2048,
|
||||
filter = self,
|
||||
mins = Vector(-16, -16, -8),
|
||||
maxs = Vector(16, 16, 8)
|
||||
})
|
||||
fx:SetMagnitude(4)
|
||||
fx:SetScale(1)
|
||||
fx:SetRadius(2)
|
||||
fx:SetNormal(dir)
|
||||
for i = 1, math.floor(tr.Fraction * 6) do
|
||||
fx:SetOrigin(tr.StartPos + tr.Normal * (i / 6) * 2048)
|
||||
util.Effect("Sparks", fx)
|
||||
end
|
||||
end
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat()
|
||||
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Damage = 5,
|
||||
Force = 1,
|
||||
Distance = 1024,
|
||||
HullSize = 16,
|
||||
Num = 48,
|
||||
Tracer = 1,
|
||||
Src = src,
|
||||
Dir = dir,
|
||||
Spread = Vector(0.5, 0.5, 0),
|
||||
IgnoreEntity = self,
|
||||
})
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetDamageType(DMG_BUCKSHOT + DMG_BLAST)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamageForce(self:GetVelocity() * 100)
|
||||
dmg:SetDamagePosition(src)
|
||||
for _, ent in pairs(ents.FindInCone(src, dir, 1024, 0.707)) do
|
||||
local tr = util.QuickTrace(src, ent:GetPos() - src, {self, ent})
|
||||
if tr.Fraction == 1 then
|
||||
dmg:SetDamage(100 * math.Rand(0.75, 1) * Lerp((ent:GetPos():DistToSqr(src) / 1048576) ^ 0.5, 1, 0.25) * (self.NPCDamage and 0.5 or 1) * mult)
|
||||
if !ent:IsOnGround() then dmg:ScaleDamage(1.5) end
|
||||
ent:TakeDamageInfo(dmg)
|
||||
end
|
||||
end
|
||||
|
||||
util.BlastDamage(self, attacker, src, 256, 50 * mult)
|
||||
|
||||
self:EmitSound("TacRP/weapons/rpg7/explode.wav", 125, 100)
|
||||
self:EmitSound("physics/metal/metal_box_break1.wav", 100, 200)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
@@ -0,0 +1,40 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_stinger"
|
||||
ENT.PrintName = "FIM-92 Missile (QAAM)"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.GunshipWorkaround = false
|
||||
|
||||
ENT.SafetyFuse = 0.1
|
||||
ENT.ImpactDamage = 150
|
||||
|
||||
ENT.SteerSpeed = 30
|
||||
ENT.SeekerAngle = 75
|
||||
|
||||
ENT.LeadTarget = true
|
||||
ENT.SuperSteerTime = 3
|
||||
ENT.SuperSteerSpeed = 120
|
||||
|
||||
ENT.MaxSpeed = 8000
|
||||
ENT.Acceleration = 8000
|
||||
|
||||
ENT.SteerDelay = 0.3
|
||||
ENT.FlareRedirectChance = 0.35
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(175, 175, 255)
|
||||
@@ -0,0 +1,81 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_stinger"
|
||||
ENT.PrintName = "FIM-92 Missile (SAAM)"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.GunshipWorkaround = false
|
||||
|
||||
ENT.SafetyFuse = 0.1
|
||||
ENT.ImpactDamage = 150
|
||||
|
||||
ENT.SteerSpeed = 60
|
||||
ENT.SeekerAngle = 55
|
||||
|
||||
ENT.LeadTarget = true
|
||||
ENT.SuperSteerTime = 1
|
||||
ENT.SuperSteerSpeed = 150
|
||||
|
||||
ENT.MaxSpeed = 4500
|
||||
ENT.Acceleration = 2000
|
||||
|
||||
ENT.SteerDelay = 0.5
|
||||
ENT.FlareRedirectChance = 0.05
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 255, 255)
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
local dir = self:GetForward()
|
||||
local src = self:GetPos() - dir * 64
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat()
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetDamageType(DMG_BLAST + DMG_AIRBOAT)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamageForce(self:GetVelocity())
|
||||
dmg:SetDamagePosition(src)
|
||||
dmg:SetDamage(150 * mult)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), 256)
|
||||
self:ImpactTraceAttack(ent, 700 * mult, 100)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
end
|
||||
|
||||
self:EmitSound("TacRP/weapons/rpg7/explode.wav", 125)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:OnThink()
|
||||
if IsValid(self:GetOwner()) and IsValid(self:GetOwner():GetActiveWeapon())
|
||||
and self:GetOwner():GetActiveWeapon().ArcticTacRP then
|
||||
self.LockOnEntity = self:GetOwner():GetActiveWeapon():GetLockOnEntity()
|
||||
else
|
||||
self:SwitchTarget(nil)
|
||||
end
|
||||
end
|
||||
193
garrysmod/addons/tacrp/lua/entities/tacrp_smoke_cloud.lua
Normal file
193
garrysmod/addons/tacrp/lua/entities/tacrp_smoke_cloud.lua
Normal file
@@ -0,0 +1,193 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Smoke Cloud"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
ENT.TacRPSmoke = true
|
||||
ENT.Particles = nil
|
||||
ENT.SmokeRadius = 300
|
||||
ENT.SmokeColor = Color(150, 150, 150)
|
||||
ENT.BillowTime = 1
|
||||
ENT.Life = 20
|
||||
|
||||
-- Cheap maths
|
||||
ENT.SmokeRadiusSqr = ENT.SmokeRadius * ENT.SmokeRadius
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
local mins, maxs = Vector(-self.SmokeRadius / 2, -self.SmokeRadius / 2, -self.SmokeRadius / 2), Vector(self.SmokeRadius / 2, self.SmokeRadius / 2, self.SmokeRadius / 2)
|
||||
if SERVER then
|
||||
self:PhysicsInitSphere(self.SmokeRadius / 2)
|
||||
self:SetCollisionBounds(mins, maxs)
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
self:DrawShadow( false )
|
||||
else
|
||||
|
||||
table.insert(TacRP.ClientSmokeCache, self)
|
||||
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
self.Particles = {}
|
||||
|
||||
local amt = 20
|
||||
|
||||
for i = 1, amt do
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
smoke:SetVelocity( VectorRand() * 8 + (Angle(0, i * (360 / amt), 0):Forward() * 250) )
|
||||
smoke:SetStartAlpha( 0 )
|
||||
smoke:SetEndAlpha( 255 )
|
||||
smoke:SetStartSize( 0 )
|
||||
smoke:SetEndSize( self.SmokeRadius )
|
||||
smoke:SetRoll( math.Rand(-180, 180) )
|
||||
smoke:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
smoke:SetColor( self.SmokeColor.r, self.SmokeColor.g, self.SmokeColor.b )
|
||||
smoke:SetAirResistance( 75 )
|
||||
smoke:SetPos( self:GetPos() )
|
||||
smoke:SetCollide( true )
|
||||
smoke:SetBounce( 0.2 )
|
||||
smoke:SetLighting( false )
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke.bt = CurTime() + self.BillowTime
|
||||
smoke.dt = CurTime() + self.BillowTime + self.Life
|
||||
smoke.ft = CurTime() + self.BillowTime + self.Life + math.Rand(2.5, 5)
|
||||
smoke:SetDieTime(smoke.ft)
|
||||
smoke.life = self.Life
|
||||
smoke.billowed = false
|
||||
smoke.radius = self.SmokeRadius
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
|
||||
local prog = 1
|
||||
local alph = 0
|
||||
|
||||
if pa.ft < CurTime() then
|
||||
// pass
|
||||
elseif pa.dt < CurTime() then
|
||||
local d = (CurTime() - pa.dt) / (pa.ft - pa.dt)
|
||||
|
||||
alph = 1 - d
|
||||
elseif pa.bt < CurTime() then
|
||||
alph = 1
|
||||
else
|
||||
local d = math.Clamp(pa:GetLifeTime() / (pa.bt - CurTime()), 0, 1)
|
||||
|
||||
prog = (-d ^ 2) + (2 * d)
|
||||
|
||||
alph = d
|
||||
end
|
||||
|
||||
pa:SetEndSize( pa.radius * prog )
|
||||
pa:SetStartSize( pa.radius * prog )
|
||||
|
||||
pa:SetStartAlpha(255 * alph)
|
||||
pa:SetEndAlpha(255 * alph)
|
||||
|
||||
-- pa:SetLifeTime(pa:GetLifeTime() + FrameTime())
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
table.insert(self.Particles, smoke)
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
if TacRP.ConVars["smoke_affectnpcs"]:GetBool() then
|
||||
self:EnableCustomCollisions()
|
||||
self:SetCustomCollisionCheck(true)
|
||||
self:CollisionRulesChanged()
|
||||
else
|
||||
self:SetSolid(SOLID_NONE)
|
||||
end
|
||||
|
||||
self.dt = CurTime() + self.Life + self.BillowTime
|
||||
end
|
||||
|
||||
function ENT:TestCollision( startpos, delta, isbox, extents, mask )
|
||||
if (mask == MASK_BLOCKLOS or mask == MASK_BLOCKLOS_AND_NPCS) then
|
||||
local len = delta:Length()
|
||||
if len <= 200 then return false end -- NPCs can see very close
|
||||
|
||||
local rad = self.SmokeRadiusSqr
|
||||
local pos = self:GetPos()
|
||||
local dir = delta:GetNormalized()
|
||||
|
||||
-- Trace started within the smoke
|
||||
if startpos:DistToSqr(pos) <= rad then
|
||||
return {
|
||||
HitPos = startpos,
|
||||
Fraction = 0,
|
||||
Normal = -dir,
|
||||
}
|
||||
end
|
||||
|
||||
-- Find the closest point on the original trace to the smoke's origin point
|
||||
local t = (pos - startpos):Dot(dir)
|
||||
local p = startpos + t * dir
|
||||
|
||||
-- If the point is within smoke radius, the trace is intersecting the smoke
|
||||
if p:DistToSqr(pos) <= rad then
|
||||
return {
|
||||
HitPos = p,
|
||||
Fraction = math.Clamp(t / len, 0, 0.95),
|
||||
Normal = -dir,
|
||||
}
|
||||
end
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("ShouldCollide", "tacrp_smoke_cloud", function(ent1, ent2)
|
||||
if ent1.TacRPSmoke and !ent2:IsNPC() then return false end
|
||||
if ent2.TacRPSmoke and !ent1:IsNPC() then return false end
|
||||
end)
|
||||
|
||||
function ENT:Think()
|
||||
|
||||
if SERVER then
|
||||
if self.dt < CurTime() then
|
||||
SafeRemoveEntity(self)
|
||||
return
|
||||
end
|
||||
|
||||
--[[]
|
||||
if !TacRP.ConVars["smoke_affectnpcs"]:GetBool() then return end
|
||||
local targets = ents.FindInSphere(self:GetPos(), self.SmokeRadius)
|
||||
for _, k in pairs(targets) do
|
||||
if k:IsNPC() then
|
||||
local ret = hook.Run("TacRP_StunNPC", k, self)
|
||||
if ret then continue end
|
||||
k:SetSchedule(SCHED_STANDOFF)
|
||||
end
|
||||
end
|
||||
|
||||
self:NextThink(CurTime() + 0.5)
|
||||
]]
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if CLIENT then
|
||||
timer.Simple(0, function()
|
||||
if !IsValid(self) then
|
||||
table.RemoveByValue(TacRP.ClientSmokeCache, self)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
return false
|
||||
end
|
||||
207
garrysmod/addons/tacrp/lua/entities/tacrp_smoke_cloud_ninja.lua
Normal file
207
garrysmod/addons/tacrp/lua/entities/tacrp_smoke_cloud_ninja.lua
Normal file
@@ -0,0 +1,207 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Smoke Cloud"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
ENT.TacRPSmoke = true
|
||||
ENT.Particles = nil
|
||||
ENT.SmokeRadius = 256
|
||||
ENT.SmokeColor = Color(220, 220, 220)
|
||||
ENT.BillowTime = 0.5
|
||||
ENT.Life = 8
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel( "models/weapons/w_eq_smokegrenade_thrown.mdl" )
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
self:SetSolid( SOLID_NONE )
|
||||
self:DrawShadow( false )
|
||||
else
|
||||
|
||||
table.insert(TacRP.ClientSmokeCache, self)
|
||||
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
self.Particles = {}
|
||||
|
||||
local amt = 20
|
||||
|
||||
for i = 1, amt do
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
smoke:SetVelocity( VectorRand() * 8 + (Angle(0, i * (360 / amt), 0):Forward() * 220) )
|
||||
smoke:SetStartAlpha( 0 )
|
||||
smoke:SetEndAlpha( 255 )
|
||||
smoke:SetStartSize( 0 )
|
||||
smoke:SetEndSize( self.SmokeRadius )
|
||||
smoke:SetRoll( math.Rand(-180, 180) )
|
||||
smoke:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
smoke:SetColor( self.SmokeColor.r, self.SmokeColor.g, self.SmokeColor.b )
|
||||
smoke:SetAirResistance( 75 )
|
||||
smoke:SetPos( self:GetPos() )
|
||||
smoke:SetCollide( true )
|
||||
smoke:SetBounce( 0.2 )
|
||||
smoke:SetLighting( false )
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke.bt = CurTime() + self.BillowTime
|
||||
smoke.dt = CurTime() + self.BillowTime + self.Life
|
||||
smoke.ft = CurTime() + self.BillowTime + self.Life + math.Rand(1, 3)
|
||||
smoke:SetDieTime(smoke.ft)
|
||||
smoke.life = self.Life
|
||||
smoke.billowed = false
|
||||
smoke.radius = self.SmokeRadius
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
|
||||
local prog = 1
|
||||
local alph = 0
|
||||
|
||||
if pa.ft < CurTime() then
|
||||
// pass
|
||||
elseif pa.dt < CurTime() then
|
||||
local d = (CurTime() - pa.dt) / (pa.ft - pa.dt)
|
||||
|
||||
alph = 1 - d
|
||||
elseif pa.bt < CurTime() then
|
||||
alph = 1
|
||||
else
|
||||
local d = math.Clamp(pa:GetLifeTime() / (pa.bt - CurTime()), 0, 1)
|
||||
|
||||
prog = (-d ^ 2) + (2 * d)
|
||||
|
||||
alph = d
|
||||
end
|
||||
|
||||
pa:SetEndSize( pa.radius * prog )
|
||||
pa:SetStartSize( pa.radius * prog )
|
||||
|
||||
pa:SetStartAlpha(255 * alph)
|
||||
pa:SetEndAlpha(255 * alph)
|
||||
|
||||
-- pa:SetLifeTime(pa:GetLifeTime() + FrameTime())
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
table.insert(self.Particles, smoke)
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
self.dt = CurTime() + self.Life + self.BillowTime + 2
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
|
||||
|
||||
if SERVER then
|
||||
if !self:GetOwner():IsValid() then self:Remove() return end
|
||||
|
||||
-- local o = self:GetOwner()
|
||||
-- local origin = self:GetPos() + Vector(0, 0, 16)
|
||||
|
||||
-- local dmg = DamageInfo()
|
||||
-- dmg:SetAttacker(self:GetOwner())
|
||||
-- dmg:SetInflictor(self)
|
||||
-- dmg:SetDamageType(DMG_NERVEGAS)
|
||||
-- dmg:SetDamageForce(Vector(0, 0, 0))
|
||||
-- dmg:SetDamagePosition(self:GetPos())
|
||||
-- dmg:SetDamageCustom(1024) -- immersive death
|
||||
|
||||
-- util.BlastDamageInfo(dmg, self:GetPos(), 300)
|
||||
|
||||
-- for i, k in pairs(ents.FindInSphere(origin, 300)) do
|
||||
-- if k == self:GetOwner() then continue end
|
||||
|
||||
-- if k:IsPlayer() or k:IsNPC() or k:IsNextBot() then
|
||||
-- local tr = util.TraceLine({
|
||||
-- start = origin,
|
||||
-- endpos = k:EyePos() or k:WorldSpaceCenter(),
|
||||
-- filter = self,
|
||||
-- mask = MASK_SOLID_BRUSHONLY
|
||||
-- })
|
||||
-- if tr.Fraction < 1 then continue end
|
||||
-- local dist = (tr.HitPos - tr.StartPos):Length()
|
||||
-- local delta = dist / 320
|
||||
|
||||
-- dmg:SetDamage(k:IsPlayer() and math.Rand(1, 3) or math.Rand(5, 15))
|
||||
|
||||
-- k:TakeDamageInfo(dmg)
|
||||
|
||||
-- if k:IsPlayer() then
|
||||
-- k:ScreenFade( SCREENFADE.IN, Color(150, 150, 50, 100), 2 * delta, 0 )
|
||||
|
||||
-- local timername = "tacrp_ninja_gas_" .. k:EntIndex()
|
||||
-- local reps = 3
|
||||
|
||||
-- if timer.Exists(timername) then
|
||||
-- reps = math.Clamp(timer.RepsLeft(timername) + 3, reps, 10)
|
||||
-- timer.Remove(timername)
|
||||
-- end
|
||||
-- timer.Create(timername, 2, reps, function()
|
||||
-- if !IsValid(k) or !k:Alive() then
|
||||
-- timer.Remove(timername)
|
||||
-- return
|
||||
-- end
|
||||
-- k:ScreenFade( SCREENFADE.IN, Color(150, 150, 50, 5), 0.1, 0 )
|
||||
-- if k:Health() > 1 then
|
||||
-- local d = DamageInfo()
|
||||
-- d:SetDamageType(DMG_NERVEGAS)
|
||||
-- d:SetDamage(math.random(1, 2))
|
||||
-- d:SetInflictor(IsValid(self) and self or o)
|
||||
-- d:SetAttacker(o)
|
||||
-- d:SetDamageForce(k:GetForward())
|
||||
-- d:SetDamagePosition(k:GetPos())
|
||||
-- d:SetDamageCustom(1024)
|
||||
-- k:TakeDamageInfo(d)
|
||||
-- else
|
||||
-- k:ViewPunch(Angle(math.Rand(-2, 2), 0, 0))
|
||||
-- end
|
||||
-- if math.random() <= 0.3 then
|
||||
-- k:EmitSound("ambient/voices/cough" .. math.random(1, 4) .. ".wav", 80, math.Rand(95, 105))
|
||||
-- end
|
||||
-- end)
|
||||
|
||||
-- if math.random() <= 0.3 then
|
||||
-- k:EmitSound("ambient/voices/cough" .. math.random(1, 4) .. ".wav", 80, math.Rand(95, 105))
|
||||
-- end
|
||||
-- elseif k:IsNPC() then
|
||||
-- k:SetSchedule(SCHED_STANDOFF)
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- self:NextThink(CurTime() + 1)
|
||||
|
||||
if self.dt < CurTime() then
|
||||
SafeRemoveEntity(self)
|
||||
end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if CLIENT then
|
||||
timer.Simple(0, function()
|
||||
if !IsValid(self) then
|
||||
table.RemoveByValue(TacRP.ClientSmokeCache, self)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
return false
|
||||
end
|
||||
100
garrysmod/addons/tacrp/lua/entities/tacrp_smoke_cloud_p2a1.lua
Normal file
100
garrysmod/addons/tacrp/lua/entities/tacrp_smoke_cloud_p2a1.lua
Normal file
@@ -0,0 +1,100 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_smoke_cloud"
|
||||
ENT.PrintName = "Smoke Cloud"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
ENT.SmokeRadius = 150
|
||||
ENT.SmokeColor = Color(150, 150, 150)
|
||||
ENT.BillowTime = 1
|
||||
ENT.Life = 12
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel( "models/weapons/w_eq_smokegrenade_thrown.mdl" )
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
self:SetSolid( SOLID_NONE )
|
||||
self:DrawShadow( false )
|
||||
else
|
||||
|
||||
table.insert(TacRP.ClientSmokeCache, self)
|
||||
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
self.Particles = {}
|
||||
|
||||
local amt = 15
|
||||
|
||||
for i = 1, amt do
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
smoke:SetVelocity( VectorRand() * 8 + (Angle(0, i * (360 / amt), 0):Forward() * 100) )
|
||||
smoke:SetStartAlpha( 0 )
|
||||
smoke:SetEndAlpha( 255 )
|
||||
smoke:SetStartSize( 0 )
|
||||
smoke:SetEndSize( self.SmokeRadius )
|
||||
smoke:SetRoll( math.Rand(-180, 180) )
|
||||
smoke:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
smoke:SetColor( self.SmokeColor.r, self.SmokeColor.g, self.SmokeColor.b )
|
||||
smoke:SetAirResistance( 75 )
|
||||
smoke:SetPos( self:GetPos() )
|
||||
smoke:SetCollide( true )
|
||||
smoke:SetBounce( 0.2 )
|
||||
smoke:SetLighting( false )
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke.bt = CurTime() + self.BillowTime
|
||||
smoke.dt = CurTime() + self.BillowTime + self.Life
|
||||
smoke.ft = CurTime() + self.BillowTime + self.Life + math.Rand(2.5, 5)
|
||||
smoke:SetDieTime(smoke.ft)
|
||||
smoke.life = self.Life
|
||||
smoke.billowed = false
|
||||
smoke.radius = self.SmokeRadius
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
|
||||
local prog = 1
|
||||
local alph = 0
|
||||
|
||||
if pa.ft < CurTime() then
|
||||
// pass
|
||||
elseif pa.dt < CurTime() then
|
||||
local d = (CurTime() - pa.dt) / (pa.ft - pa.dt)
|
||||
|
||||
alph = 1 - d
|
||||
elseif pa.bt < CurTime() then
|
||||
alph = 1
|
||||
else
|
||||
local d = math.Clamp(pa:GetLifeTime() / (pa.bt - CurTime()), 0, 1)
|
||||
|
||||
prog = (-d ^ 2) + (2 * d)
|
||||
|
||||
alph = d
|
||||
end
|
||||
|
||||
pa:SetEndSize( pa.radius * prog )
|
||||
pa:SetStartSize( pa.radius * prog )
|
||||
|
||||
pa:SetStartAlpha(255 * alph)
|
||||
pa:SetEndAlpha(255 * alph)
|
||||
|
||||
-- pa:SetLifeTime(pa:GetLifeTime() + FrameTime())
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
table.insert(self.Particles, smoke)
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
self.dt = CurTime() + self.Life + self.BillowTime + 2
|
||||
end
|
||||
134
garrysmod/addons/tacrp/lua/tacrp/client/cl_bind.lua
Normal file
134
garrysmod/addons/tacrp/lua/tacrp/client/cl_bind.lua
Normal file
@@ -0,0 +1,134 @@
|
||||
hook.Add("PlayerBindPress", "TacRP_Binds", function(ply, bind, pressed, code)
|
||||
local wpn = ply:GetActiveWeapon()
|
||||
|
||||
if !wpn or !IsValid(wpn) or !wpn.ArcticTacRP then return end
|
||||
|
||||
-- if we don't block, TTT will do radio menu
|
||||
if engine.ActiveGamemode() == "terrortown" and bind == "+zoom" and !LocalPlayer():KeyDown(IN_USE) then
|
||||
ply.TacRPBlindFireDown = pressed
|
||||
return true
|
||||
end
|
||||
|
||||
if bind == "+showscores" then
|
||||
wpn.LastHintLife = CurTime() -- ping the hints
|
||||
end
|
||||
|
||||
if bind == "+menu_context" and !LocalPlayer():KeyDown(IN_USE) then
|
||||
TacRP.KeyPressed_Customize = pressed
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
if TacRP.ConVars["toggletactical"]:GetBool() and bind == "impulse 100" and wpn:GetValue("CanToggle") and (!GetConVar("mp_flashlight"):GetBool() or (TacRP.ConVars["flashlight_alt"]:GetBool() and ply:KeyDown(IN_WALK)) or (!TacRP.ConVars["flashlight_alt"]:GetBool() and !ply:KeyDown(IN_WALK))) then
|
||||
TacRP.KeyPressed_Tactical = pressed
|
||||
|
||||
return true
|
||||
end
|
||||
end)
|
||||
|
||||
function TacRP.GetBind(binding)
|
||||
local bind = input.LookupBinding(binding)
|
||||
|
||||
if !bind then
|
||||
if binding == "+grenade1" then
|
||||
return string.upper(input.GetKeyName(TacRP.GRENADE1_Backup))
|
||||
elseif binding == "+grenade2" then
|
||||
return string.upper(input.GetKeyName(TacRP.GRENADE2_Backup))
|
||||
end
|
||||
|
||||
return "!"
|
||||
end
|
||||
|
||||
return string.upper(bind)
|
||||
end
|
||||
|
||||
function TacRP.GetBindKey(bind)
|
||||
local key = input.LookupBinding(bind)
|
||||
if !key then
|
||||
if bind == "+grenade1" then
|
||||
return string.upper(input.GetKeyName(TacRP.GRENADE1_Backup))
|
||||
elseif bind == "+grenade2" then
|
||||
return string.upper(input.GetKeyName(TacRP.GRENADE2_Backup))
|
||||
end
|
||||
|
||||
return bind
|
||||
else
|
||||
return string.upper(key)
|
||||
end
|
||||
end
|
||||
|
||||
function TacRP.GetKeyIsBound(bind)
|
||||
local key = input.LookupBinding(bind)
|
||||
|
||||
if !key then
|
||||
if bind == "+grenade1" then
|
||||
return true
|
||||
elseif bind == "+grenade2" then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function TacRP.GetKey(bind)
|
||||
local key = input.LookupBinding(bind)
|
||||
|
||||
if !key then
|
||||
if bind == "+grenade1" then
|
||||
return TacRP.GRENADE1_Backup
|
||||
elseif bind == "+grenade2" then
|
||||
return TacRP.GRENADE2_Backup
|
||||
end
|
||||
|
||||
return false
|
||||
else
|
||||
return input.GetKeyCode(key)
|
||||
end
|
||||
end
|
||||
|
||||
TacRP.KeyPressed_Melee = false
|
||||
|
||||
concommand.Add("+tacrp_melee", function()
|
||||
TacRP.KeyPressed_Melee = true
|
||||
end)
|
||||
|
||||
concommand.Add("-tacrp_melee", function()
|
||||
TacRP.KeyPressed_Melee = false
|
||||
end)
|
||||
|
||||
TacRP.KeyPressed_Customize = false
|
||||
|
||||
concommand.Add("+tacrp_customize", function()
|
||||
TacRP.KeyPressed_Customize = true
|
||||
end)
|
||||
|
||||
concommand.Add("-tacrp_customize", function()
|
||||
TacRP.KeyPressed_Customize = false
|
||||
end)
|
||||
|
||||
TacRP.KeyPressed_Tactical = false
|
||||
|
||||
concommand.Add("+tacrp_tactical", function()
|
||||
TacRP.KeyPressed_Tactical = true
|
||||
end)
|
||||
|
||||
concommand.Add("-tacrp_tactical", function()
|
||||
TacRP.KeyPressed_Tactical = false
|
||||
end)
|
||||
|
||||
concommand.Add("tacrp_dev_listanims", function()
|
||||
local wep = LocalPlayer():GetActiveWeapon()
|
||||
if !wep then return end
|
||||
local vm = LocalPlayer():GetViewModel()
|
||||
if !vm then return end
|
||||
local alist = vm:GetSequenceList()
|
||||
|
||||
for i = 0, #alist do
|
||||
MsgC(clr_b, i, " --- ")
|
||||
MsgC(color_white, "\t", alist[i], "\n [")
|
||||
MsgC(clr_r, "\t", vm:SequenceDuration(i), "\n")
|
||||
end
|
||||
end)
|
||||
136
garrysmod/addons/tacrp/lua/tacrp/client/cl_darkrp.lua
Normal file
136
garrysmod/addons/tacrp/lua/tacrp/client/cl_darkrp.lua
Normal file
@@ -0,0 +1,136 @@
|
||||
local hold_tbl = {}
|
||||
net.Receive("tacrp_spawnedwepatts", function()
|
||||
local ent_index = net.ReadUInt(12)
|
||||
hold_tbl[ent_index] = {}
|
||||
local count = net.ReadUInt(4)
|
||||
for i = 1, count do
|
||||
hold_tbl[ent_index][net.ReadUInt(4)] = net.ReadUInt(TacRP.Attachments_Bits)
|
||||
end
|
||||
|
||||
if IsValid(Entity(ent_index)) then
|
||||
Entity(ent_index).Attachments = hold_tbl[ent_index]
|
||||
end
|
||||
end)
|
||||
|
||||
local function makeattmdl(self, atttbl, slottbl)
|
||||
local model = atttbl.Model
|
||||
|
||||
if atttbl.WorldModel then
|
||||
model = atttbl.WorldModel
|
||||
end
|
||||
|
||||
local csmodel = ClientsideModel(model)
|
||||
|
||||
if !IsValid(csmodel) then return end
|
||||
|
||||
local scale = Matrix()
|
||||
local vec = Vector(1, 1, 1) * (atttbl.Scale or 1) * (slottbl.WMScale or 1)
|
||||
scale:Scale(vec)
|
||||
csmodel:EnableMatrix("RenderMultiply", scale)
|
||||
csmodel:SetNoDraw(true)
|
||||
|
||||
local tbl = {
|
||||
Model = csmodel,
|
||||
Weapon = self
|
||||
}
|
||||
|
||||
table.insert(TacRP.CSModelPile, tbl)
|
||||
|
||||
return csmodel
|
||||
end
|
||||
|
||||
hook.Add("onDrawSpawnedWeapon", "TacRP", function(ent)
|
||||
local wep_tbl = weapons.Get(ent:GetWeaponClass())
|
||||
if !wep_tbl or !wep_tbl.ArcticTacRP then return end
|
||||
|
||||
ent:DrawModel()
|
||||
|
||||
if !ent.Attachments and hold_tbl[ent:EntIndex()] then
|
||||
ent.Attachments = table.Copy(hold_tbl[ent:EntIndex()])
|
||||
hold_tbl[ent:EntIndex()] = nil
|
||||
end
|
||||
|
||||
local count = table.Count(ent.Attachments or {})
|
||||
|
||||
if count > 0 then
|
||||
ent.TacRP_CSAttModels = ent.TacRP_CSAttModels or {}
|
||||
for k, v in pairs(ent.Attachments) do
|
||||
local atttbl = TacRP.Attachments[TacRP.Attachments_Index[v]]
|
||||
local slottbl = wep_tbl.Attachments[k]
|
||||
if !atttbl or !atttbl.Model then continue end
|
||||
if !IsValid(ent.TacRP_CSAttModels[k]) then
|
||||
ent.TacRP_CSAttModels[k] = makeattmdl(ent, atttbl, slottbl)
|
||||
end
|
||||
local model = ent.TacRP_CSAttModels[k]
|
||||
|
||||
local offset_pos = slottbl.Pos_WM
|
||||
local offset_ang = slottbl.Ang_WM
|
||||
local bone = slottbl.WMBone or "ValveBiped.Bip01_R_Hand"
|
||||
|
||||
if !bone then continue end
|
||||
|
||||
local boneindex = ent:LookupBone(bone)
|
||||
if !boneindex then continue end
|
||||
|
||||
local bonemat = ent:GetBoneMatrix(boneindex)
|
||||
if bonemat then
|
||||
bpos = bonemat:GetTranslation()
|
||||
bang = bonemat:GetAngles()
|
||||
end
|
||||
|
||||
local apos, aang
|
||||
|
||||
apos = bpos + bang:Forward() * offset_pos.x
|
||||
apos = apos + bang:Right() * offset_pos.y
|
||||
apos = apos + bang:Up() * offset_pos.z
|
||||
|
||||
aang = Angle()
|
||||
aang:Set(bang)
|
||||
|
||||
aang:RotateAroundAxis(aang:Right(), offset_ang.p)
|
||||
aang:RotateAroundAxis(aang:Up(), offset_ang.y)
|
||||
aang:RotateAroundAxis(aang:Forward(), offset_ang.r)
|
||||
|
||||
local moffset = (atttbl.ModelOffset or Vector(0, 0, 0)) * (slottbl.VMScale or 1)
|
||||
|
||||
apos = apos + aang:Forward() * moffset.x
|
||||
apos = apos + aang:Right() * moffset.y
|
||||
apos = apos + aang:Up() * moffset.z
|
||||
|
||||
model:SetPos(apos)
|
||||
model:SetAngles(aang)
|
||||
model:SetRenderOrigin(apos)
|
||||
model:SetRenderAngles(aang)
|
||||
|
||||
model:DrawModel()
|
||||
end
|
||||
end
|
||||
|
||||
-- if (EyePos() - ent:GetPos()):LengthSqr() <= 262144 then -- 512^2
|
||||
-- local ang = LocalPlayer():EyeAngles()
|
||||
|
||||
-- ang:RotateAroundAxis(ang:Forward(), 180)
|
||||
-- ang:RotateAroundAxis(ang:Right(), 90)
|
||||
-- ang:RotateAroundAxis(ang:Up(), 90)
|
||||
|
||||
-- cam.Start3D2D(ent:WorldSpaceCenter() + Vector(0, 0, (ent:OBBMaxs().z - ent:OBBMins().z) * 0.5 + 8) , ang, 0.1)
|
||||
-- -- surface.SetFont("TacRP_LondonBetween_32_Unscaled")
|
||||
-- surface.SetFont("TacRP_Myriad_Pro_32_Unscaled")
|
||||
|
||||
-- local name = wep_tbl.PrintName .. (ent:Getamount() > 1 and (" ×" .. ent:Getamount()) or "")
|
||||
-- local w = surface.GetTextSize(name)
|
||||
-- surface.SetTextPos(-w / 2, 0)
|
||||
-- surface.SetTextColor(255, 255, 255, 255)
|
||||
-- surface.DrawText(name)
|
||||
-- if count > 0 then
|
||||
-- local str = count .. " Attachments"
|
||||
-- local w2 = surface.GetTextSize(str)
|
||||
-- surface.SetTextPos(-w2 / 2, 32)
|
||||
-- surface.SetTextColor(255, 255, 255, 255)
|
||||
-- surface.DrawText(str)
|
||||
-- end
|
||||
-- cam.End3D2D()
|
||||
-- end
|
||||
|
||||
return true
|
||||
end)
|
||||
170
garrysmod/addons/tacrp/lua/tacrp/client/cl_font.lua
Normal file
170
garrysmod/addons/tacrp/lua/tacrp/client/cl_font.lua
Normal file
@@ -0,0 +1,170 @@
|
||||
local hudscale = TacRP.ConVars["hudscale"]
|
||||
function TacRP.SS(i)
|
||||
return ScrW() / 640 * i * hudscale:GetFloat()
|
||||
end
|
||||
TacRP.HoloSS = (ScreenScaleH(1) / ScreenScale(1)) or 1
|
||||
|
||||
local sizes_to_make = {
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
8,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
14,
|
||||
16,
|
||||
20,
|
||||
32
|
||||
}
|
||||
|
||||
local italic_sizes_to_make = {
|
||||
6,
|
||||
8,
|
||||
}
|
||||
|
||||
local unscaled_sizes_to_make = {
|
||||
24,
|
||||
32,
|
||||
48
|
||||
}
|
||||
|
||||
local fonts_to_make = {
|
||||
"Myriad Pro",
|
||||
"HD44780A00 5x8"
|
||||
}
|
||||
|
||||
-- TacRP_HD44780A00_5x8_32
|
||||
|
||||
local function generatefonts()
|
||||
|
||||
for ind, font in ipairs(fonts_to_make) do
|
||||
local fontname = string.Replace(font, " ", "_")
|
||||
|
||||
if GetConVar("tacrp_font" .. ind) and GetConVar("tacrp_font" .. ind):GetString() ~= "" then
|
||||
font = GetConVar("tacrp_font" .. ind):GetString()
|
||||
else
|
||||
font = TacRP:GetPhrase("font." .. ind) or font
|
||||
end
|
||||
|
||||
for _, i in pairs(sizes_to_make) do
|
||||
|
||||
surface.CreateFont( "TacRP_" .. fontname .. "_" .. tostring(i), {
|
||||
font = font,
|
||||
size = TacRP.SS(i),
|
||||
weight = 0,
|
||||
antialias = true,
|
||||
extended = true, -- Required for non-latin fonts
|
||||
} )
|
||||
|
||||
surface.CreateFont( "TacRP_" .. fontname .. "_" .. tostring(i) .. "_Glow", {
|
||||
font = font,
|
||||
size = TacRP.SS(i),
|
||||
weight = 0,
|
||||
antialias = true,
|
||||
blursize = 6,
|
||||
extended = true,
|
||||
} )
|
||||
end
|
||||
|
||||
for _, i in pairs(italic_sizes_to_make) do
|
||||
surface.CreateFont( "TacRP_" .. fontname .. "_" .. tostring(i) .. "_Italic", {
|
||||
font = font,
|
||||
size = TacRP.SS(i),
|
||||
weight = 0,
|
||||
antialias = true,
|
||||
extended = true,
|
||||
italic = true,
|
||||
} )
|
||||
end
|
||||
|
||||
for _, i in pairs(unscaled_sizes_to_make) do
|
||||
|
||||
surface.CreateFont( "TacRP_" .. fontname .. "_" .. tostring(i) .. "_Unscaled", {
|
||||
font = font,
|
||||
size = i,
|
||||
weight = 0,
|
||||
antialias = true,
|
||||
extended = true,
|
||||
} )
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
generatefonts()
|
||||
|
||||
function TacRP.Regen(full)
|
||||
TacRP.HoloSS = (ScreenScaleH(1) / ScreenScale(1)) -- a little bodge to make sights scale, i'm not adding an extra hook just for this
|
||||
if full then
|
||||
generatefonts()
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add( "OnScreenSizeChanged", "TacRP.Regen", function() TacRP.Regen(true) end)
|
||||
cvars.AddChangeCallback("tacrp_hudscale", function() TacRP.Regen(true) end, "tacrp_hudscale")
|
||||
|
||||
function TacRP.MultiLineText(text, maxw, font)
|
||||
local content = {}
|
||||
local tline = ""
|
||||
local x = 0
|
||||
surface.SetFont(font)
|
||||
|
||||
local ts = surface.GetTextSize(" ")
|
||||
|
||||
local newlined = string.Split(text, "\n")
|
||||
|
||||
for _, line in ipairs(newlined) do
|
||||
local words = string.Split(line, " ")
|
||||
|
||||
for _, word in ipairs(words) do
|
||||
local tx = surface.GetTextSize(word)
|
||||
|
||||
if x + tx > maxw then
|
||||
local dashi = string.find(word, "-")
|
||||
if dashi and surface.GetTextSize(utf8.sub(word, 0, dashi)) <= maxw - x then
|
||||
-- cut the word at the dash sign if possible
|
||||
table.insert(content, tline .. utf8.sub(word, 0, dashi))
|
||||
tline = ""
|
||||
x = 0
|
||||
word = utf8.sub(word, dashi + 1)
|
||||
tx = surface.GetTextSize(word)
|
||||
else
|
||||
-- move whole word to new line
|
||||
table.insert(content, tline)
|
||||
tline = ""
|
||||
x = 0
|
||||
|
||||
-- else
|
||||
-- -- cut the word down from the middle
|
||||
-- while x + tx > maxw do
|
||||
-- local cut = ""
|
||||
-- for i = 2, utf8.len(word) do
|
||||
-- cut = utf8.sub(word, 0, -i)
|
||||
-- tx = surface.GetTextSize(cut)
|
||||
-- if x + tx < maxw then
|
||||
-- table.insert(content, tline .. cut)
|
||||
-- tline = ""
|
||||
-- word = utf8.sub(word, utf8.len(word) - i + 2)
|
||||
-- x = 0
|
||||
-- tx = surface.GetTextSize(word)
|
||||
-- break
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
end
|
||||
end
|
||||
|
||||
tline = tline .. word .. " "
|
||||
|
||||
x = x + tx + ts
|
||||
end
|
||||
|
||||
table.insert(content, tline)
|
||||
tline = ""
|
||||
x = 0
|
||||
end
|
||||
|
||||
return content
|
||||
end
|
||||
60
garrysmod/addons/tacrp/lua/tacrp/client/cl_garbage.lua
Normal file
60
garrysmod/addons/tacrp/lua/tacrp/client/cl_garbage.lua
Normal file
@@ -0,0 +1,60 @@
|
||||
TacRP.CSModelPile = {} -- { {Model = NULL, Weapon = NULL} }
|
||||
TacRP.FlashlightPile = {}
|
||||
|
||||
function TacRP.CollectGarbage()
|
||||
local removed = 0
|
||||
|
||||
local newpile = {}
|
||||
|
||||
for _, k in pairs(TacRP.CSModelPile) do
|
||||
if IsValid(k.Weapon) then
|
||||
table.insert(newpile, k)
|
||||
|
||||
continue
|
||||
end
|
||||
|
||||
SafeRemoveEntity(k.Model)
|
||||
|
||||
removed = removed + 1
|
||||
end
|
||||
|
||||
TacRP.CSModelPile = newpile
|
||||
|
||||
if TacRP.Developer() and removed > 0 then
|
||||
print("Removed " .. tostring(removed) .. " CSModels")
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("PostCleanupMap", "TacRP.CleanGarbage", function()
|
||||
TacRP.CollectGarbage()
|
||||
end)
|
||||
|
||||
timer.Create("TacRP CSModel Garbage Collector", 5, 0, TacRP.CollectGarbage)
|
||||
|
||||
hook.Add("PostDrawEffects", "TacRP_CleanFlashlights", function()
|
||||
local newflashlightpile = {}
|
||||
|
||||
for _, k in pairs(TacRP.FlashlightPile) do
|
||||
if IsValid(k.Weapon) and k.Weapon == LocalPlayer():GetActiveWeapon() then
|
||||
table.insert(newflashlightpile, k)
|
||||
|
||||
continue
|
||||
end
|
||||
|
||||
if k.ProjectedTexture and k.ProjectedTexture:IsValid() then
|
||||
k.ProjectedTexture:Remove()
|
||||
end
|
||||
end
|
||||
|
||||
TacRP.FlashlightPile = newflashlightpile
|
||||
|
||||
local wpn = LocalPlayer():GetActiveWeapon()
|
||||
|
||||
if !wpn then return end
|
||||
if !IsValid(wpn) then return end
|
||||
if !wpn.ArcticTacRP then return end
|
||||
|
||||
if GetViewEntity() == LocalPlayer() then return end
|
||||
|
||||
wpn:KillFlashlightsVM()
|
||||
end)
|
||||
210
garrysmod/addons/tacrp/lua/tacrp/client/cl_hooks.lua
Normal file
210
garrysmod/addons/tacrp/lua/tacrp/client/cl_hooks.lua
Normal file
@@ -0,0 +1,210 @@
|
||||
hook.Add("PostPlayerDraw", "TacRP_Holster", function(ply, flags)
|
||||
if !ply.TacRP_Holster or bit.band(flags, STUDIO_RENDER) != STUDIO_RENDER then return end
|
||||
if ply == LocalPlayer() and !LocalPlayer():ShouldDrawLocalPlayer() then return end
|
||||
|
||||
if !TacRP.ConVars["drawholsters"]:GetBool() or !TacRP.ConVars["visibleholster"]:GetBool() then return end
|
||||
|
||||
ply.TacRP_HolsterModels = ply.TacRP_HolsterModels or {}
|
||||
for i, v in ipairs(TacRP.HolsterBones) do
|
||||
local wep = ply.TacRP_Holster[i]
|
||||
if !IsValid(wep) or wep:GetOwner() != ply or wep == ply:GetActiveWeapon() or !wep:GetValue("HolsterVisible") then
|
||||
SafeRemoveEntity(ply.TacRP_HolsterModels[i])
|
||||
ply.TacRP_HolsterModels[i] = nil
|
||||
ply.TacRP_Holster[i] = nil
|
||||
continue
|
||||
end
|
||||
|
||||
local bone = ply:LookupBone(v[1])
|
||||
local matrix = bone and ply:GetBoneMatrix(bone)
|
||||
if !bone or !matrix then return end
|
||||
|
||||
local fallback
|
||||
local holstermodel = wep:GetValue("HolsterModel") or wep.WorldModel
|
||||
if !util.IsValidModel(holstermodel) and v[3] then
|
||||
holstermodel = v[3][1]
|
||||
fallback = true
|
||||
end
|
||||
|
||||
if !ply.TacRP_HolsterModels[i] or !IsValid(ply.TacRP_HolsterModels[i])
|
||||
or ply.TacRP_HolsterModels[i]:GetModel() != holstermodel then
|
||||
SafeRemoveEntity(ply.TacRP_HolsterModels[i])
|
||||
ply.TacRP_HolsterModels[i] = ClientsideModel(holstermodel, RENDERGROUP_OPAQUE)
|
||||
ply.TacRP_HolsterModels[i]:SetNoDraw(true)
|
||||
end
|
||||
|
||||
local spos, sang = v[2], Angle()
|
||||
if istable(v[2]) then
|
||||
spos = v[2][1]
|
||||
sang = v[2][2]
|
||||
elseif v[2] == nil then
|
||||
spos = Vector()
|
||||
end
|
||||
|
||||
local hpos, hang = wep:GetValue("HolsterPos"), wep:GetValue("HolsterAng")
|
||||
if fallback then
|
||||
hpos = v[3][2]
|
||||
hang = v[3][3]
|
||||
end
|
||||
local off = spos + hpos
|
||||
local rot = hang + sang
|
||||
|
||||
local pos = matrix:GetTranslation()
|
||||
local ang = matrix:GetAngles()
|
||||
|
||||
pos = pos + ang:Right() * off.x + ang:Forward() * off.y + ang:Up() * off.z
|
||||
ang:RotateAroundAxis(ang:Forward(), rot.p)
|
||||
ang:RotateAroundAxis(ang:Up(), rot.y)
|
||||
ang:RotateAroundAxis(ang:Right(), rot.r)
|
||||
|
||||
debugoverlay.Axis(pos, ang, 8, FrameTime() * 2, true)
|
||||
|
||||
model = ply.TacRP_HolsterModels[i]
|
||||
model:SetPos(pos)
|
||||
model:SetAngles(ang)
|
||||
model:SetRenderOrigin(pos)
|
||||
model:SetRenderAngles(ang)
|
||||
model:DrawModel()
|
||||
model:SetRenderOrigin()
|
||||
model:SetRenderAngles()
|
||||
|
||||
if !wep:GetValue("HolsterModel") then
|
||||
wep:DoBodygroups(true, model)
|
||||
wep:DrawCustomModel(true, ply.TacRP_HolsterModels[i])
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
TacRP.ClientSmokeCache = {}
|
||||
|
||||
hook.Add( "HUDDrawTargetID", "TacRP_FlashlightGlint", function()
|
||||
local ply = LocalPlayer():GetEyeTrace().Entity
|
||||
if !IsValid(ply) then return end
|
||||
|
||||
-- Flashed
|
||||
if LocalPlayer():GetNWFloat("TacRPStunStart", 0) + LocalPlayer():GetNWFloat("TacRPStunDur", 0) > CurTime() then return false end
|
||||
|
||||
-- Flashlight glint
|
||||
if ply:IsPlayer() and TacRP.ConVars["flashlight_blind"]:GetBool() then
|
||||
local wep = ply:GetActiveWeapon()
|
||||
if IsValid(wep) and wep.ArcticTacRP and wep:GetValue("Flashlight") then
|
||||
|
||||
local src, dir = wep:GetTracerOrigin(), wep:GetShootDir()
|
||||
|
||||
local diff = EyePos() - src
|
||||
|
||||
local dot = -dir:Forward():Dot(EyeAngles():Forward())
|
||||
local dot2 = dir:Forward():Dot(diff:GetNormalized())
|
||||
dot = math.max(0, (dot + dot2) / 2) ^ 1.5
|
||||
if dot > 0.707 then
|
||||
local dist = 300
|
||||
local wep2 = LocalPlayer():GetActiveWeapon()
|
||||
if IsValid(wep2) and wep2.ArcticTacRP and wep2:IsInScope() and wep2:GetValue("ScopeOverlay") then
|
||||
dist = 3500
|
||||
end
|
||||
if wep:GetTracerOrigin():Distance(EyePos()) <= dist then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Smoke
|
||||
for i, ent in ipairs(TacRP.ClientSmokeCache) do
|
||||
if !IsValid(ent) or !ent.TacRPSmoke then table.remove(TacRP.ClientSmokeCache, i) continue end
|
||||
local pos = ent:GetPos()
|
||||
local rad = ent.SmokeRadius
|
||||
|
||||
-- target is in smoke
|
||||
if ply:WorldSpaceCenter():Distance(pos) <= rad then return false end
|
||||
|
||||
local s = ply:WorldSpaceCenter() - EyePos()
|
||||
local d = s:GetNormalized()
|
||||
local v = pos - EyePos()
|
||||
local t = v:Dot(d)
|
||||
local p = EyePos() + t * d
|
||||
|
||||
-- we are in smoke OR line of sight is intersecting smoke
|
||||
if t > -rad and t < s:Length() and p:Distance(pos) <= rad then return false end
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("CreateMove", "TacRP_CreateMove", function(cmd)
|
||||
local wpn = LocalPlayer():GetActiveWeapon()
|
||||
|
||||
-- In TTT ScreenClicker isn't disabled for some reason
|
||||
if TacRP.CursorEnabled and !LocalPlayer():Alive() then
|
||||
TacRP.CursorEnabled = false
|
||||
gui.EnableScreenClicker(false)
|
||||
end
|
||||
|
||||
if !IsValid(wpn) then return end
|
||||
if !wpn.ArcticTacRP then return end
|
||||
|
||||
if TacRP.ConVars["autoreload"]:GetBool() then
|
||||
if wpn:GetMaxClip1() > 0 and wpn:Clip1() == 0 and (wpn:Ammo1() > 0 or wpn:GetInfiniteAmmo())
|
||||
and wpn:GetNextPrimaryFire() + 0.5 < CurTime() and wpn:ShouldAutoReload() then
|
||||
local buttons = cmd:GetButtons()
|
||||
|
||||
buttons = buttons + IN_RELOAD
|
||||
|
||||
cmd:SetButtons(buttons)
|
||||
end
|
||||
end
|
||||
|
||||
local is_typing = LocalPlayer():IsTyping() or gui.IsConsoleVisible() or gui.IsGameUIVisible() or vgui.GetKeyboardFocus() != nil
|
||||
|
||||
local grenade1bind = input.LookupBinding("+grenade1")
|
||||
|
||||
if !grenade1bind then
|
||||
if input.IsKeyDown( KEY_G ) and !is_typing then
|
||||
cmd:AddKey(IN_GRENADE1)
|
||||
end
|
||||
end
|
||||
|
||||
local grenade2bind = input.LookupBinding("+grenade2")
|
||||
|
||||
if !grenade2bind then
|
||||
if input.IsKeyDown( KEY_H ) and !is_typing then
|
||||
cmd:AddKey(IN_GRENADE2)
|
||||
end
|
||||
end
|
||||
|
||||
if TacRP.KeyPressed_Melee then
|
||||
cmd:AddKey(TacRP.IN_MELEE)
|
||||
end
|
||||
|
||||
if TacRP.KeyPressed_Customize then
|
||||
cmd:AddKey(TacRP.IN_CUSTOMIZE)
|
||||
end
|
||||
|
||||
if TacRP.KeyPressed_Tactical then
|
||||
cmd:AddKey(TacRP.IN_TACTICAL)
|
||||
end
|
||||
|
||||
local mult = TacRP.CalculateMaxMoveSpeed(LocalPlayer())
|
||||
|
||||
local basemove = Vector(cmd:GetForwardMove(), cmd:GetUpMove(), cmd:GetSideMove())
|
||||
local maxspeed = basemove:Length()
|
||||
local movedir = basemove:GetNormalized()
|
||||
|
||||
local finalmovedir = movedir * maxspeed * mult
|
||||
|
||||
cmd:SetForwardMove(finalmovedir[1])
|
||||
cmd:SetUpMove(finalmovedir[2])
|
||||
cmd:SetSideMove(finalmovedir[3])
|
||||
end)
|
||||
|
||||
hook.Add("PreRender", "TACRP_PreRender", function()
|
||||
local wpn = LocalPlayer():GetActiveWeapon()
|
||||
|
||||
if !wpn.ArcticTacRP then return end
|
||||
|
||||
if wpn:GetValue("BlindFireCamera") then
|
||||
wpn:DoRT()
|
||||
end
|
||||
|
||||
if wpn:GetValue("ThermalCamera") then
|
||||
wpn:DoThermalRT()
|
||||
end
|
||||
end)
|
||||
149
garrysmod/addons/tacrp/lua/tacrp/client/cl_hud.lua
Normal file
149
garrysmod/addons/tacrp/lua/tacrp/client/cl_hud.lua
Normal file
@@ -0,0 +1,149 @@
|
||||
local mat_corner_ul = Material("TacRP/hud/800corner_nobg1.png", "mips smooth")
|
||||
local mat_corner_ur = Material("TacRP/hud/800corner_nobg2.png", "mips smooth")
|
||||
local mat_corner_br = Material("TacRP/hud/800corner_nobg3.png", "mips smooth")
|
||||
local mat_corner_bl = Material("TacRP/hud/800corner_nobg4.png", "mips smooth")
|
||||
|
||||
function TacRP.DrawCorneredBox(x, y, w, h, col)
|
||||
col = col or Color(255, 255, 255)
|
||||
|
||||
surface.DrawRect(x, y, w, h)
|
||||
|
||||
surface.SetDrawColor(col)
|
||||
|
||||
local s = 8
|
||||
|
||||
surface.SetMaterial(mat_corner_ul)
|
||||
surface.DrawTexturedRect(x, y, s, s)
|
||||
|
||||
surface.SetMaterial(mat_corner_ur)
|
||||
surface.DrawTexturedRect(x + w - s, y, s, s)
|
||||
|
||||
surface.SetMaterial(mat_corner_bl)
|
||||
surface.DrawTexturedRect(x, y + h - s, s, s)
|
||||
|
||||
surface.SetMaterial(mat_corner_br)
|
||||
surface.DrawTexturedRect(x + w - s, y + h - s, s, s)
|
||||
end
|
||||
|
||||
local hide = {
|
||||
["CHudHealth"] = true,
|
||||
["CHudBattery"] = true,
|
||||
["CHudAmmo"] = true,
|
||||
["CHudSecondaryAmmo"] = true,
|
||||
}
|
||||
|
||||
hook.Add("HUDShouldDraw", "TacRP_HideHUD", function(name)
|
||||
if !IsValid(LocalPlayer()) then return end
|
||||
local wpn = LocalPlayer():GetActiveWeapon()
|
||||
|
||||
if IsValid(wpn) and wpn.ArcticTacRP and
|
||||
((TacRP.ConVars["drawhud"]:GetBool() and TacRP.ConVars["hud"]:GetBool()) or wpn:GetCustomize()) and hide[name] then
|
||||
return false
|
||||
end
|
||||
end)
|
||||
|
||||
local names = {
|
||||
["357"] = "Magnum Ammo",
|
||||
["smg1"] = "Carbine Ammo",
|
||||
["ar2"] = "Rifle Ammo",
|
||||
}
|
||||
|
||||
hook.Add("PreGamemodeLoaded", "TacRP_AmmoName", function()
|
||||
if TacRP.ConVars["ammonames"]:GetBool() then
|
||||
for k, v in pairs(names) do
|
||||
language.Add(k .. "_ammo", TacRP:GetPhrase("ammo." .. k) or v)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local gaA = 0
|
||||
function TacRP.GetFOVAcc(spread)
|
||||
local raw = isnumber(spread)
|
||||
if !raw and spread:IsWeapon() then spread = spread:GetSpread() end
|
||||
cam.Start3D()
|
||||
local lool = ( EyePos() + ( EyeAngles():Forward() ) + ( spread * EyeAngles():Up() ) ):ToScreen()
|
||||
cam.End3D()
|
||||
|
||||
local gau = ( (ScrH() / 2) - lool.y )
|
||||
if raw then return gau end
|
||||
|
||||
gaA = math.Approach(gaA, gau, (ScrH() / 2) * FrameTime() * 2)
|
||||
|
||||
return gaA
|
||||
end
|
||||
|
||||
TacRP.PanelColors = {
|
||||
["bg"] = {
|
||||
Color(0, 0, 0, 150), -- normal
|
||||
Color(255, 255, 255, 255), -- hover
|
||||
Color(150, 150, 150, 150), -- sel
|
||||
Color(255, 255, 255, 255), -- sel, hover
|
||||
},
|
||||
["bg2"] = {
|
||||
Color(0, 0, 0, 200), -- normal
|
||||
Color(255, 255, 255, 255), -- hover
|
||||
Color(150, 150, 150, 200), -- sel
|
||||
Color(255, 255, 255, 255), -- sel, hover
|
||||
},
|
||||
["corner"] = {
|
||||
Color(255, 255, 255),
|
||||
Color(0, 0, 0),
|
||||
Color(50, 50, 255),
|
||||
Color(150, 150, 255),
|
||||
},
|
||||
["text"] = {
|
||||
Color(255, 255, 255),
|
||||
Color(0, 0, 0),
|
||||
Color(255, 255, 255),
|
||||
Color(0, 0, 0),
|
||||
},
|
||||
["text_glow"] = {
|
||||
Color(255, 255, 255, 100),
|
||||
Color(0, 0, 0, 100),
|
||||
Color(255, 255, 255, 100),
|
||||
Color(0, 0, 0, 100),
|
||||
},
|
||||
}
|
||||
|
||||
function TacRP.GetPanelColor(str, hvr, sel)
|
||||
local i = 1
|
||||
if isnumber(hvr) or hvr == nil then
|
||||
i = hvr or 1
|
||||
elseif sel then
|
||||
i = hvr and 4 or 3
|
||||
elseif hvr then
|
||||
i = 2
|
||||
end
|
||||
|
||||
return TacRP.PanelColors[str][i]
|
||||
end
|
||||
|
||||
function TacRP.GetPanelColors(hvr, sel)
|
||||
local i = 1
|
||||
if sel then
|
||||
i = hvr and 4 or 3
|
||||
elseif hvr then
|
||||
i = 2
|
||||
end
|
||||
return TacRP.PanelColors["bg2"][i], TacRP.PanelColors["corner"][i], TacRP.PanelColors["text"][i]
|
||||
end
|
||||
|
||||
hook.Add("RenderScreenspaceEffects", "TacRP_Gas", function()
|
||||
if LocalPlayer():GetNWFloat("TacRPGasEnd", 0) > CurTime() then
|
||||
local delta = math.Clamp((LocalPlayer():GetNWFloat("TacRPGasEnd", 0) - CurTime()) / 2, 0, 1) ^ 1.5
|
||||
|
||||
DrawMaterialOverlay("effects/water_warp01", delta * 0.1)
|
||||
DrawMotionBlur(0.5 * delta, 0.75 * delta, 0.01)
|
||||
DrawColorModify({
|
||||
[ "$pp_colour_addr" ] = 0.125 * delta,
|
||||
[ "$pp_colour_addg" ] = 0.2 * delta,
|
||||
[ "$pp_colour_addb" ] = 0.05 * delta,
|
||||
[ "$pp_colour_brightness" ] = -0.2 * delta,
|
||||
[ "$pp_colour_contrast" ] = 1 - delta * 0.1,
|
||||
[ "$pp_colour_colour" ] = 1 - delta * 0.75,
|
||||
[ "$pp_colour_mulr" ] = 0,
|
||||
[ "$pp_colour_mulg" ] = 0,
|
||||
[ "$pp_colour_mulb" ] = 0,
|
||||
})
|
||||
end
|
||||
end )
|
||||
71
garrysmod/addons/tacrp/lua/tacrp/client/cl_killicons.lua
Normal file
71
garrysmod/addons/tacrp/lua/tacrp/client/cl_killicons.lua
Normal file
@@ -0,0 +1,71 @@
|
||||
TacRPOldKilliconDraw = TacRPOldKilliconDraw or killicon.Draw
|
||||
local killicons_cachednames = {}
|
||||
local killicons_cachedicons = {}
|
||||
local killiconmat = Material("HUD/killicons/default")
|
||||
|
||||
TacRP.KillIconAlias = {
|
||||
["tacrp_proj_rpg7"] = "tacrp_rpg7",
|
||||
["tacrp_proj_rpg7_ratshot"] = "tacrp_rpg7",
|
||||
|
||||
["tacrp_proj_40mm_3gl"] = "tacrp_m320",
|
||||
["tacrp_proj_40mm_gas"] = "tacrp_m320",
|
||||
["tacrp_proj_40mm_he"] = "tacrp_m320",
|
||||
["tacrp_proj_40mm_heat"] = "tacrp_m320",
|
||||
["tacrp_proj_40mm_lvg"] = "tacrp_m320",
|
||||
["tacrp_proj_40mm_smoke"] = "tacrp_m320",
|
||||
|
||||
["tacrp_proj_ks23_flashbang"] = "tacrp_ks23",
|
||||
|
||||
["tacrp_proj_knife"] = "tacrp_knife",
|
||||
|
||||
["tacrp_gas_cloud"] = "tacrp_proj_nade_gas", -- also used by 40mm gas but whatever
|
||||
["tacrp_fire_cloud"] = "tacrp_proj_nade_thermite",
|
||||
["tacrp_nuke_cloud"] = "tacrp_proj_nade_nuke",
|
||||
}
|
||||
|
||||
TacRPNewKilliconDraw = function(x, y, name, alpha)
|
||||
name = TacRP.KillIconAlias[name] or name
|
||||
local wpn = weapons.Get(name)
|
||||
|
||||
if tobool(killicons_cachednames[name]) == true then
|
||||
local w, h
|
||||
|
||||
-- nade icons are smaller
|
||||
if killicons_cachednames[name] == 2 then
|
||||
w, h = 48, 48
|
||||
else
|
||||
w, h = 64, 64
|
||||
end
|
||||
|
||||
x = x - w * 0.5
|
||||
y = y - h * 0.3
|
||||
|
||||
cam.Start2D()
|
||||
|
||||
local selecticon = killicons_cachedicons[name]
|
||||
|
||||
if !selecticon then -- not cached
|
||||
local loadedmat = Material(wpn.IconOverride or "entities/" .. name .. ".png", "smooth mips")
|
||||
killicons_cachedicons[name] = loadedmat
|
||||
selecticon = loadedmat
|
||||
end
|
||||
|
||||
surface.SetDrawColor(255, 255, 255, alpha)
|
||||
surface.SetMaterial(selecticon or killiconmat)
|
||||
surface.DrawTexturedRect(x, y, w, h)
|
||||
cam.End2D()
|
||||
else
|
||||
if killicons_cachednames[name] == nil then -- not cached yet, checking for tacrp
|
||||
if TacRP.QuickNades_EntLookup[name] then
|
||||
killicons_cachednames[name] = 2
|
||||
killicons_cachedicons[name] = TacRP.QuickNades[TacRP.QuickNades_EntLookup[name]].Icon or killiconmat
|
||||
else
|
||||
killicons_cachednames[name] = (weapons.Get(name) and weapons.Get(name).ArcticTacRP) or false
|
||||
end -- weapons.get() will return nil for any hl2 base gun
|
||||
else -- we know it is totally not tacrp gun
|
||||
return TacRPOldKilliconDraw(x, y, name, alpha)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
killicon.Draw = TacRPNewKilliconDraw
|
||||
93
garrysmod/addons/tacrp/lua/tacrp/client/cl_net.lua
Normal file
93
garrysmod/addons/tacrp/lua/tacrp/client/cl_net.lua
Normal file
@@ -0,0 +1,93 @@
|
||||
net.Receive("tacrp_networkweapon", function(len)
|
||||
local wpn_index = net.ReadUInt(13)
|
||||
local wpn = Entity(wpn_index)
|
||||
|
||||
-- When the server immediately calls NetworkWeapon on a new weapon,
|
||||
-- the client entity may not be valid or correct instantly.
|
||||
-- (in SP, the entity will appear valid but the functions/variables will all be nil.)
|
||||
if !IsValid(wpn) or !wpn.ArcticTacRP then
|
||||
local tname = "wait" .. engine.TickCount() .. math.random(100, 999)
|
||||
|
||||
-- Read bits now (can't do it in a timer)
|
||||
-- WriteEntity always uses 13 bits, so we can derive amount of attachments
|
||||
local ids = {}
|
||||
for i = 1, (len - 13) / TacRP.Attachments_Bits do
|
||||
table.insert(ids, net.ReadUInt(TacRP.Attachments_Bits))
|
||||
end
|
||||
|
||||
-- Wait until entity properly exists to pass on attachment info.
|
||||
-- Usually won't take more than 1 tick but ping may cause issues
|
||||
timer.Create(tname, 0, 100, function()
|
||||
local wpn = Entity(wpn_index)
|
||||
if !IsValid(wpn) or !wpn.ArcticTacRP then return end
|
||||
|
||||
wpn:ReceiveWeapon(ids)
|
||||
wpn:UpdateHolster()
|
||||
|
||||
timer.Remove(tname)
|
||||
end)
|
||||
else
|
||||
wpn:ReceiveWeapon()
|
||||
wpn:UpdateHolster()
|
||||
end
|
||||
end)
|
||||
|
||||
net.Receive("TacRP_updateholster", function()
|
||||
local ply = net.ReadEntity()
|
||||
--local slot = net.ReadUInt(TacRP.HolsterNetBits)
|
||||
local item = net.ReadEntity()
|
||||
|
||||
if !IsValid(ply) or !IsValid(item) or !item.GetValue then return end
|
||||
|
||||
local visible = item:GetValue("HolsterVisible")
|
||||
local slot = item:GetValue("HolsterSlot")
|
||||
|
||||
if visible and slot then
|
||||
ply.TacRP_Holster = ply.TacRP_Holster or {}
|
||||
if !IsValid(item) then
|
||||
ply.TacRP_Holster[slot] = nil
|
||||
else
|
||||
ply.TacRP_Holster[slot] = item
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
net.Receive("tacrp_doorbust", function()
|
||||
local door = net.ReadEntity()
|
||||
if IsValid(door) then
|
||||
local mins, maxs = door:GetCollisionBounds()
|
||||
door:SetRenderBounds(mins, maxs, Vector(4, 4, 4))
|
||||
end
|
||||
end)
|
||||
|
||||
gameevent.Listen("player_spawn")
|
||||
hook.Add("player_connect", "TacRP_Holster", function(userid)
|
||||
local ply = Player(userid)
|
||||
ply.TacRP_Holster = {}
|
||||
end)
|
||||
|
||||
net.Receive("tacrp_flashbang", function()
|
||||
local time = net.ReadFloat()
|
||||
|
||||
if time > 0 then
|
||||
LocalPlayer():ScreenFade( SCREENFADE.IN, TacRP.ConVars["flash_dark"]:GetBool() and Color(0, 0, 0, 255) or Color(255, 255, 255, 255), math.min(time * 2, 2.5), time)
|
||||
end
|
||||
|
||||
if TacRP.ConVars["flash_dark"]:GetBool() then
|
||||
LocalPlayer():SetDSP(32, time == 0)
|
||||
else
|
||||
LocalPlayer():SetDSP(37, time == 0)
|
||||
end
|
||||
|
||||
end)
|
||||
net.Receive("tacrp_addshieldmodel", function(len, ply)
|
||||
local wpn = net.ReadEntity()
|
||||
local mdl = net.ReadEntity()
|
||||
mdl.mmRHAe = net.ReadFloat()
|
||||
mdl.TacRPShield = true
|
||||
|
||||
if !IsValid(wpn) or !wpn.ArcticTacRP then return end
|
||||
|
||||
wpn.Shields = wpn.Shields or {}
|
||||
table.insert(wpn.Shields, mdl)
|
||||
end)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user