add sborka

This commit is contained in:
2026-03-31 10:27:04 +03:00
commit f5e5f56c84
2345 changed files with 382127 additions and 0 deletions

View 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()

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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"

View 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"

View 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",
}

View 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

View 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"

View 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"

View 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

View 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"

View 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"

View 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

View 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"

View 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

View 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

View 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

View 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)

View 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

View 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

View 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

View 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)

View 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

View 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

View 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

View 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

View File

@@ -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

View 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

View 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

View 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

View 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

View File

@@ -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

View 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

View 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

View File

@@ -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

View 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

View 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)

View File

@@ -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)

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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)

View File

@@ -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

View 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)

View 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

View 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

View 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

View File

@@ -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

View 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

View 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

View File

@@ -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

View 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

View 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

View 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

View 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

View 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

View File

@@ -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

View 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

View 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

View 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 = 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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View 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

View File

@@ -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

View 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

View File

@@ -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

View 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

View File

@@ -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

View 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

View File

@@ -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)

View File

@@ -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

View 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

View 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

View 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

View 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)

View 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)

View 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

View 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)

View 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)

View 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 )

View 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

View 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