AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")

local LVS = LVS

ENT.Damage     = 0
ENT.Prime      = 0.03
ENT.Delay      = 30
ENT.HideDelay  = 0.0

function ENT:Initialize()
    if not self:GetModel() or self:GetModel() == "" or self:GetModel() == "models/error.mdl" then
        self:SetModel("models/weapons/fas2/world/explosives/rpg26/rocket.mdl")
    end

    if not self.Owner:IsPlayer() then
        self.Owner = NULL
    end

    self.burnout = CurTime() + 2

    self:PhysicsInit(SOLID_VPHYSICS)
    self:SetMoveType(MOVETYPE_VPHYSICS)
    self:SetSolid(SOLID_VPHYSICS)

    local phys = self:GetPhysicsObject()
    if IsValid(phys) then
        phys:Wake()
    end

    self:SetFriction(self.Delay)
    self.killtime = CurTime() + self.Delay
    self.StartTime = CurTime()

    self:EmitSound("TFA_INS2_RPG7.Loop")
    self:SetUseType(SIMPLE_USE)

    self.HasIdle = true
    self.HP = math.random(30, 60)

    timer.Simple(0.1, function()
        if IsValid(self) then
            self:SetOwner(self:GetOwner() or NULL)
        end
    end)

    self:SetNWFloat("HideTime", CurTime() + self.HideDelay)
end

function ENT:Think()
    local ct = CurTime()
    if self.killtime < ct then return false end

    local phys = self:GetPhysicsObject()
	if not IsValid(phys) then return end
    if phys:IsValid() then
        phys:ApplyForceCenter(Vector(0, 0, -9.80665 * 7) * phys:GetMass() * engine.TickInterval())
    end

    self:NextThink(ct)
    return true
end

function ENT:Explode()
    if self._Exploding then return end 
    self._Exploding = true

    if not IsValid(self.Owner) then
        self:Remove()
        return
    end

    local tr = util.TraceLine({
        start = pos,
        endpos = pos + self:GetAngles():Forward() * 200,
        filter = self
    })

    local hit = tr.Entity

    if IsValid(hit) and hit.LVS then
        local dmg = DamageInfo()
        dmg:SetDamage(250)
        dmg:SetDamageType(DMG_BLAST)
        dmg:SetAttacker(self.Owner or self)
        dmg:SetInflictor(self)
        hit:TakeDamageInfo(dmg)

        if hit.GetSubSystem then
            local subsys = hit:GetSubSystem(tr.HitPos)
            if subsys then
                subsys:TakeDamage(300)
            end
        end
    end

    local pos = self:GetPos()

    local effectdata = EffectData()
    effectdata:SetOrigin(pos)
    effectdata:SetScale(5)
    effectdata:SetMagnitude(5)

    util.Effect("HelicopterMegaBomb", effectdata)
    util.Effect("Explosion", effectdata)

    util.BlastDamage(self, self.Owner, pos, 100, 10)

    local shake = ents.Create("env_shake")
    shake:SetOwner(self.Owner)
    shake:SetPos(pos)
    shake:SetKeyValue("amplitude", "20")
    shake:SetKeyValue("radius", "768")
    shake:SetKeyValue("duration", tostring(self.Damage / 800))
    shake:SetKeyValue("frequency", "255")
    shake:SetKeyValue("spawnflags", "4")
    shake:Spawn()
    shake:Activate()
    shake:Fire("StartShake", "", 0)

    self:EmitSound("TFA_INS2_RPG7.2")

    LVS:FireBullet({
        Src      = pos,
        Dir      = self:GetAngles():Forward(),
        Spread   = vector_origin,
        Force    = 42000,
        HullSize = 0,
        Damage   = 12000,
        Velocity = 16000,
        Attacker = self.Owner
    })

    local tr = util.TraceHull({
        start = pos,
        endpos = pos,
        mins = Vector(-80, -80, -80),
        maxs = Vector(80, 80, 80),
        filter = self
    })

    local hit = tr.Entity

    if IsValid(hit) and hit.LVS then
        local dmg = DamageInfo()
        dmg:SetDamage(200)               
        dmg:SetDamageType(DMG_BLAST)
        dmg:SetAttacker(self.Owner or self)
        dmg:SetInflictor(self)
        hit:TakeDamageInfo(dmg)

        if hit.GetSubSystem then
            local subsys = hit:GetSubSystem(pos)

            if subsys then
                local name = subsys.Name:lower()

                if name:find("engine") then
                    subsys:SetHP(0)

                elseif name:find("ammo") then
                    subsys:SetHP(0)

                elseif name:find("fuel") then
                    subsys:SetHP(0)

                else
                    subsys:TakeDamage(250)
                end
            end
        end
    end
    self:Remove()
end

function ENT:PhysicsCollide(data, phys)
	if self._LastCollide and self._LastCollide > CurTime() - 0.05 then return end 
	self._LastCollide = CurTime()
    local ct = CurTime()

    if data.Speed > 60 and ct > self.StartTime + self.Prime then
        timer.Simple(0, function()
            if IsValid(self) then self:Explode() end
        end)
        return
    end

    self.Prime = math.huge

    if self.HasIdle then
        self:StopSound("TFA_INS2_RPG7.Loop")
        self.HasIdle = false
        self:SetNWFloat("HideTime", -1)
    end
end

function ENT:OnRemove()
    if self.HasIdle then
        self:StopSound("TFA_INS2_RPG7.Loop")
        self.HasIdle = false
    end
end

function ENT:Use(activator)
    if activator:IsPlayer() and self.WeaponClass then
        local wep = activator:GetWeapon(self.WeaponClass)
        if IsValid(wep) then
            activator:GiveAmmo(1, wep:GetPrimaryAmmoType(), false)
            self:Remove()
        end
    end
end

function ENT:OnTakeDamage(dmg)
    if dmg:GetInflictor() == self or dmg:GetAttacker() == self then return end
    if self.Exploded then return end

    local damage = dmg:GetDamage()
    self.HP = self.HP - damage

    if self.HP <= 0 then
        self.Exploded = true
        self:Explode()
        return
    end

    self:TakePhysicsDamage(dmg)
end
