Files
VnUtest/garrysmod/addons/molotok/lua/entities/sent_construction.lua
2026-03-31 10:27:04 +03:00

374 lines
14 KiB
Lua

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