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
