AddCSLuaFile()

ENT.PrintName		= "Construction"
ENT.Type 			= "anim"
ENT.Base 			= "base_gmodentity"
ENT.Spawnable		= false
ENT.AdminOnly 		= true
ENT.DoNotDuplicate 	= false
ENT._Seen        = false
ENT._Lerp        = 0
ENT._Ler2 		= 0

function ENT:SetupDataTables()
    self:NetworkVar("Int", 0, "State")
    self:NetworkVar("Float", 0, "Progress")
    self:NetworkVar("String", 0, "Nick")
    self:NetworkVar("Entity", 0, "Owned")
    self:NetworkVar("Entity", 1, "Player") 
    
    if SERVER then
        self:NetworkVarNotify("Progress", function(self, name, old, new)
            if new >= 99.9 then
                if self:GetState() == 2 then return end
                self:SetState(2)
                
                if self.EntToBuild == "prop_physics" then
                    self.buildEnt = ents.Create("constructor_prop")
                    self.buildEnt:SetPos(self:GetPos() + vector_up*0.5)
                    self.buildEnt:SetAngles(self:GetAngles())
                    
                    if self.EntModel then
                        self.buildEnt:SetModel(self.EntModel)
                        self.buildEnt.Model = self.EntModel 
                    else
                        self.buildEnt:SetModel(self:GetModel())
                    end
                    
                    self.buildEnt.InitialHealth = self.EntHealth or 10000
                    self.buildEnt.PropName = self:GetNick() or "Constructor Prop"
                    
                    self.buildEnt:Spawn()
                    self.buildEnt:Activate()
                    self.buildEnt:SetNWEntity("SpikeOwner", self:GetPlayer())
                    self.buildEnt.BuilderCost = self.EntToBuildCost or 10
                    
                    local phys = self.buildEnt:GetPhysicsObject()
                    if IsValid(phys) then
                        phys:EnableMotion(false)
                    end

                    if self.EntToBuild == "sw_sania" then
                        timer.Simple(0, function()
                            if not IsValid(self.buildEnt) then return end

                            local nearest
                            local dist = 200

                            for _, veh in ipairs(ents.FindInSphere(self:GetPos(), 200)) do
                                if veh.LVS then
                                    local d = veh:GetPos():Distance(self:GetPos())
                                    if d < dist then
                                        dist = d
                                        nearest = veh
                                    end
                                end
                            end

                            if IsValid(nearest) then
                                local physTarget = nearest:GetBase() or nearest

                                self.buildEnt:SetPos(nearest:GetPos() + Vector(0,0,60))
                                self.buildEnt:SetAngles(nearest:GetAngles())

                                constraint.Weld(self.buildEnt, physTarget, 0, 0, 0, true)

                                print("[REB] РЭБ приварена к LVS:", nearest)
                            else
                                print("[REB] LVS техника не найдена рядом")
                            end
                        end)
                    end
                    
                    undo.ReplaceEntity(self, self.buildEnt)
                    cleanup.ReplaceEntity(self, self.buildEnt)
                    
                    sound.Play("weapons/building.wav", self:GetPos() + vector_up*16, 80, 120)
                    self:Remove()
                    return
                else
                    self.buildEnt = ents.Create(self.EntToBuild)
                    
                    if not IsValid(self.buildEnt) then
                        return
                    end
                    
                    self.buildEnt:SetPos(self:GetPos() + vector_up*0.5)
                    self.buildEnt:SetAngles(self:GetAngles())
                    
                    self.buildEnt:SetKeyValue("Modification", 1)
                    
                    if self:GetNick() == "Rebel Turret" then
                        self.buildEnt:SetKeyValue("spawnflags", 512)
                        self.buildEnt:SetSaveValue("m_bHackedByAlyx", true)
                    end
                    
                    self.buildEnt:SetSaveValue("m_bPlacedByPlayer", true)
                    self.buildEnt:SetSaveValue("m_Efficiency", 2)
                    self.buildEnt:SetSaveValue("m_CurrentWeaponProficiency", 100)
                    
                    self.buildEnt:Spawn()
                    self.buildEnt:Activate()
                    self.buildEnt.BuilderCost = self.EntToBuildCost or 10

                    
                    local owner = self:GetOwned() or self:GetOwner()
                    self.buildEnt:SetNWEntity("SpikeOwner", owner)
                    
                    if self.buildEnt:GetClass():find("sent_ranged_healer") then
                        self.buildEnt:SetHealEverything(false)
                        self.buildEnt:SetHealRadius(256)
                        self.buildEnt:SetHealTeam(1001)
                        if owner and owner:IsPlayer() then
                            self.buildEnt:SetPlayer(owner)
                        end
                        self.buildEnt:SetReplenishArmor(false)
                    elseif self.buildEnt:GetClass():find("barricade") then
                        local phys = self.buildEnt:GetPhysicsObject()
                        if IsValid(phys) then
                            phys:EnableMotion(false)
                        end
                        self.buildEnt:SetPos(self:GetPos() + vector_up*-5)
                    elseif self.buildEnt:GetClass():find("item_") then
                        self.buildEnt:PhysicsInit(SOLID_VPHYSICS)
                        if IsValid(self.MyWeldedEnt) then
                            constraint.Weld(self.buildEnt, self.MyWeldedEnt, 0, 0, 0, 0, true)
                        else
                            local phys = self.buildEnt:GetPhysicsObject()
                            if IsValid(phys) then
                                phys:EnableMotion(false)
                            end
                        end
                    elseif self.buildEnt:GetClass() == "bouncingmortar" or 
                           self.buildEnt:GetClass() == "ent_trappopeller_engine" then
                        local phys = self.buildEnt:GetPhysicsObject()
                        if IsValid(phys) then
                            phys:EnableMotion(false)
                        end
                        self.buildEnt:SetAngles(angle_zero)
                    elseif self.buildEnt:GetClass() == "npc_turret_floor" then
                        self.buildEnt:SetNWBool("RebSentri", true)
                        if self:GetNick() == "Rebel Turret" then
                            local v = self.buildEnt
                            v.FriendsWithAllPlayerAllies = true
                            v.PlayerFriendly = true
                            v.VJ_NPC_Class = {"CLASS_REBEL"}
                            v.DisableMakingSelfEnemyToNPCs = true
                            
                            if math.random() < 0.33 then
                                v:SetSubMaterial(0, "models/combine_turrets/floor_turret/floor_turret_citizen")
                                v:SetMaterial("models/combine_turrets/floor_turret/floor_turret_citizen")
                            elseif math.random() > 0.33 then
                                v:SetSubMaterial(0, "models/combine_turrets/floor_turret/floor_turret_citizen2")
                                v:SetMaterial("models/combine_turrets/floor_turret/floor_turret_citizen2")
                            else
                                v:SetSubMaterial(0, "models/combine_turrets/floor_turret/floor_turret_citizen4")
                                v:SetMaterial("models/combine_turrets/floor_turret/floor_turret_citizen4")
                            end
                        end
                    elseif self.buildEnt:GetClass() == "combine_mine" then
                        local v = self.buildEnt
                        if math.random() < 0.33 then
                            v:SetSubMaterial(0, "Models/Combine_Mine/combine_mine_citizen")
                            v:SetMaterial("Models/Combine_Mine/combine_mine_citizen")
                        elseif math.random() > 0.33 then
                            v:SetSubMaterial(0, "Models/Combine_Mine/combine_mine_citizen"..math.random(2,3))
                            v:SetMaterial("Models/Combine_Mine/combine_mine_citizen"..math.random(2,3))
                        end
                        timer.Simple(1, function()
                            if IsValid(v) then
                                v:StopSound("npc/roller/mine/combine_mine_active_loop1.wav")
                            end
                        end)
                    end
                    
                    undo.ReplaceEntity(self, self.buildEnt)
                    cleanup.ReplaceEntity(self, self.buildEnt)
                    
                    sound.Play("weapons/building.wav", self:GetPos() + vector_up*16, 80, 120)
                    self:Remove()
                    return
                end
            else
                self:SetColor(Color(255, 255, 255, math.Clamp(new/100*255, 32, 192)))
            end
        end)
        
        self:NetworkVarNotify("Owned", function(self, name, old, new)
            if old == new then return end
            self.Owner = new
            self:SetOwner(new)
            if NADMOD then 
                NADMOD.PlayerMakePropOwner(new, self) 
            end
        end)
        
        self:NetworkVarNotify("Player", function(self, name, old, new)
            if old == new then return end
            self._Player = new
        end)
    end
end

function ENT:GetPlayer()
    if SERVER then
        return self._Player or self:GetVar("Player") or self:GetOwner()
    else
        return self:GetVar("Player") or self:GetOwner()
    end
end

function ENT:SetPlayer(ply)
    if not SERVER then return end
    self._Player = ply
    self:SetVar("Player", ply)
end

function ENT:Initialize()
    if CLIENT then return end

    if self.EntModel then
        self:SetModel(self.EntModel)
    else
        self:SetModel("models/props_junk/wood_crate001a.mdl")
    end

    self:PhysicsInit(SOLID_VPHYSICS)
    self:SetMoveType(MOVETYPE_VPHYSICS)
    self:SetSolid(SOLID_VPHYSICS)
    
    self:DrawShadow(false)
    self:SetCollisionGroup(COLLISION_GROUP_NONE)
    self:SetUseType(SIMPLE_USE)

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

    self:SetProgress(0)
    self:SetState(0)
    self:SetNick("")
end

function ENT:Use(ply)
	if ply:IsPlayer() then
		if self:IsPlayerHolding() then return end
		ply:PickupObject(self)
	end
end

function ENT:OnTakeDamage( damage )
	self:TakePhysicsDamage(damage)
end

function ENT:PhysicsCollide(data, phys)
	if data.DeltaTime > 0.2 then
		if data.Speed > 250 then
			self:EmitSound("physics/metal/metal_box_impact_hard" .. math.random(1, 3) .. ".wav", 75, math.random(90,110), 0.5)
		else
			self:EmitSound("physics/metal/metal_box_impact_soft" .. math.random(1, 3) .. ".wav", 75, math.random(90,110), 0.2)
		end
	end
end

hook.Add( "GetPreferredCarryAngles", "BuilderCarryAngs", function( ent )
	if ent:GetNWBool("RebSentri") then
		return Angle( -10, 0, 0 )
	end
end)

if SERVER then return end

function ENT:OnRemove()
	if self:GetState() > 0 then
		local ed = EffectData()
		ed:SetOrigin(self:GetPos())
		ed:SetEntity(self)
		util.Effect( "entity_remove", ed, true, true )
	end
end

function ENT:Think()
	if self._Seen != self:BeingLookedAtByLocalPlayer() then
		self._Seen = self:BeingLookedAtByLocalPlayer()  self._Lerp = SysTime() +0.2
	end
	self._Ler2 = Lerp( 0.1, self._Ler2, self:GetProgress() )
end

local glow = Material( "models/wireframe" ) 
local Mat = Material( "particle/particle_ring_wave_addnofog" )

function ENT:Draw()
	self:DrawModel( )
	
	render.CullMode(MATERIAL_CULLMODE_CW)
		self.DrawModel( self )
	render.CullMode(MATERIAL_CULLMODE_CCW)

	if self:GetState() == 0 then
        render.SuppressEngineLighting( true )
        render.SetBlend( 0.25 ) render.MaterialOverride( glow )
        render.SetColorModulation( 1, 1, 0 )
        self:DrawModel()
        render.SetBlend( 1 ) render.MaterialOverride()
        render.SetColorModulation( 1, 1, 1 )
        render.SuppressEngineLighting( false )
	else
		local pro = math.Clamp( 1 -self:GetProgress()/100, 0, 1 )
        render.SuppressEngineLighting( true )
        render.SetBlend( pro/4 ) render.MaterialOverride( glow )
        render.SetColorModulation( 1, 1, 1 )
        self:DrawModel()
        render.SetBlend( 1 ) render.MaterialOverride()
        render.SetColorModulation( 1, 1, 1 )
        render.SuppressEngineLighting( false )
	end
	if self._Seen or self._Lerp > SysTime() then
		local ler = math.Clamp( ( self._Lerp -SysTime() )/0.2, 0, 1 )
		if self._Seen then ler = 1-ler end
		cam.Start2D()
		local pos = self:WorldSpaceCenter():ToScreen()
		local x, y, radius, seg, per = math.Round( pos.x ), math.Round( pos.y ), ler*40, 360, self._Ler2/100
		for i=1, 6 do surface.DrawCircle( x, y, radius -7 +i, Color( 0, 0, 0, 192*ler ) ) end
		per = isnumber( per ) and per or 1
		local cir = {}
		table.insert( cir, { x = x, y = y, u = 0.5, v = 0.5 } )
		for i = 0, seg do
			if i > math.ceil( seg*per ) then break end
			local a = math.rad( ( i/seg )*-360 +180 )
			table.insert( cir, { x = x +math.sin( a )*radius, y = y +math.cos( a )*radius, u = math.sin( a )/2 +0.5, v = math.cos( a )/2 +0.5 } )
		end
		local a = math.rad( 0 )
		surface.SetMaterial( Mat ) surface.SetDrawColor( 255, 200, 25, 255*ler )
		surface.DrawPoly( cir )
		draw.TextShadow( {
			text = math.Clamp( math.Round( self._Ler2 ), 0, 100 ).."%",
			pos = { x, y },
			font = "ScrapFont2",
			xalign = TEXT_ALIGN_CENTER,
			yalign = TEXT_ALIGN_CENTER,
			color = Color( 255, 200, 25, ler*255 )
		}, 1, ler*255 )
		draw.TextShadow( {
			text = self:GetNick(),
			pos = { x, y -ler*52 },
			font = "TargetID",
			xalign = TEXT_ALIGN_CENTER,
			yalign = TEXT_ALIGN_CENTER,
			color = Color( 255, 200, 25, ler*255 )
		}, 1, ler*255 )
		if IsValid( self:GetOwned() ) then
			draw.TextShadow( {
				text = "("..self:GetOwned():Nick()..")",
				pos = { x, y +ler*52 },
				font = "TargetIDSmall",
				xalign = TEXT_ALIGN_CENTER,
				yalign = TEXT_ALIGN_CENTER,
				color = Color( 255, 200, 25, ler*255 )
			}, 1, ler*255 )
		end
		cam.End2D()
	end
end
