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