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