Files
2026-03-31 10:27:04 +03:00

349 lines
7.3 KiB
Lua

AddCSLuaFile()
ENT.Type = "anim"
ENT.ExplosionEffect = "lvs_explosion_bomb"
ENT.lvsProjectile = true
ENT.VJ_ID_Danger = true
function ENT:SetupDataTables()
self:NetworkVar( "Bool", 0, "Active" )
self:NetworkVar( "Bool", 1, "MaskSolid" )
self:NetworkVar( "Vector", 0, "Speed" )
end
if SERVER then
util.AddNetworkString( "lvs_bomb_hud" )
function ENT:SetEntityFilter( filter )
if not istable( filter ) then return end
self._FilterEnts = {}
for _, ent in pairs( filter ) do
self._FilterEnts[ ent ] = true
end
end
function ENT:GetEntityFilter()
return self._FilterEnts or {}
end
function ENT:SetDamage( num ) self._dmg = num end
function ENT:SetForce( num ) self._force = num end
function ENT:SetThrust( num ) self._thrust = num end
function ENT:SetRadius( num ) self._radius = num end
function ENT:SetAttacker( ent )
self._attacker = ent
if not IsValid( ent ) or not ent:IsPlayer() then return end
net.Start( "lvs_bomb_hud", true )
net.WriteEntity( self )
net.Send( ent )
end
function ENT:GetAttacker() return self._attacker or NULL end
function ENT:GetDamage() return (self._dmg or 2000) end
function ENT:GetForce() return (self._force or 8000) end
function ENT:GetRadius() return (self._radius or 400) end
function ENT:Initialize()
self:SetModel( "models/props_phx/ww2bomb.mdl" )
self:SetMoveType( MOVETYPE_NONE )
end
function ENT:OnTakeDamage( dmginfo )
end
function ENT:Enable()
if self.IsEnabled then return end
local Parent = self:GetParent()
if IsValid( Parent ) then
self:SetOwner( Parent )
self:SetParent( NULL )
end
self:PhysicsInit( SOLID_VPHYSICS )
self:SetMoveType( MOVETYPE_VPHYSICS )
self:SetSolid( SOLID_VPHYSICS )
self:SetCollisionGroup( COLLISION_GROUP_WORLD )
self:PhysWake()
timer.Simple(1, function()
if not IsValid( self ) then return end
self:SetCollisionGroup( COLLISION_GROUP_NONE )
end )
self.IsEnabled = true
local pObj = self:GetPhysicsObject()
if not IsValid( pObj ) then
self:Remove()
print("LVS: missing model. Missile terminated.")
return
end
pObj:SetMass( 500 )
pObj:EnableGravity( false )
pObj:EnableMotion( true )
pObj:EnableDrag( false )
pObj:SetVelocityInstantaneous( self:GetSpeed() )
self:SetTrigger( true )
self:StartMotionController()
self:PhysWake()
self.SpawnTime = CurTime()
self:SetActive( true )
end
function ENT:PhysicsSimulate( phys, deltatime )
phys:Wake()
local ForceLinear = physenv.GetGravity()
local Pos = self:GetPos()
local TargetPos = Pos + self:GetVelocity()
local AngForce = -self:WorldToLocalAngles( (TargetPos - Pos):Angle() )
local ForceAngle = (Vector(AngForce.r,-AngForce.p,-AngForce.y) * 10 - phys:GetAngleVelocity() * 5 ) * 250 * deltatime
return ForceAngle, ForceLinear, SIM_GLOBAL_ACCELERATION
end
function ENT:Think()
local T = CurTime()
self:NextThink( T )
self:UpdateTrajectory()
if not self.SpawnTime then return true end
if (self.SpawnTime + 12) < T then
self:Detonate()
end
return true
end
function ENT:UpdateTrajectory()
local base = self:GetParent()
if not IsValid( base ) then return end
self:SetSpeed( base:GetVelocity() )
end
ENT.IgnoreCollisionGroup = {
[COLLISION_GROUP_NONE] = true,
[COLLISION_GROUP_WORLD] = true,
[COLLISION_GROUP_IN_VEHICLE] = true
}
function ENT:StartTouch( entity )
if entity == self:GetAttacker() then return end
if istable( self._FilterEnts ) and self._FilterEnts[ entity ] then return end
if entity.GetCollisionGroup and self.IgnoreCollisionGroup[ entity:GetCollisionGroup() ] then return end
if entity.lvsProjectile then return end
self:Detonate( entity )
end
function ENT:EndTouch( entity )
end
function ENT:Touch( entity )
end
function ENT:PhysicsCollide( data )
if istable( self._FilterEnts ) and self._FilterEnts[ data.HitEntity ] then return end
self:Detonate( data.HitEntity )
end
function ENT:OnTakeDamage( dmginfo )
end
function ENT:Detonate( target )
if not self.IsEnabled or self.IsDetonated then return end
self.IsDetonated = true
local Pos = self:GetPos()
local effectdata = EffectData()
effectdata:SetOrigin( Pos )
util.Effect( self.ExplosionEffect, effectdata, true, true )
local attacker = self:GetAttacker()
LVS:BlastDamage( Pos, self:GetForward(), IsValid( attacker ) and attacker or game.GetWorld(), self, self:GetDamage(), DMG_BLAST, self:GetRadius(), self:GetForce() )
SafeRemoveEntityDelayed( self, FrameTime() )
end
return
end
function ENT:Enable()
if self.IsEnabled then return end
self.IsEnabled = true
self.snd = CreateSound(self, "lvs/weapons/bomb_whistle_loop.wav")
self.snd:SetSoundLevel( 110 )
self.snd:PlayEx(0,150)
end
function ENT:CalcDoppler()
local Ent = LocalPlayer()
local ViewEnt = Ent:GetViewEntity()
if Ent:lvsGetVehicle() == self then
if ViewEnt == Ent then
Ent = self
else
Ent = ViewEnt
end
else
Ent = ViewEnt
end
local sVel = self:GetVelocity()
local oVel = Ent:GetVelocity()
local SubVel = oVel - sVel
local SubPos = self:GetPos() - Ent:GetPos()
local DirPos = SubPos:GetNormalized()
local DirVel = SubVel:GetNormalized()
local A = math.acos( math.Clamp( DirVel:Dot( DirPos ) ,-1,1) )
return (1 + math.cos( A ) * SubVel:Length() / 13503.9)
end
function ENT:Think()
if self.snd then
self.snd:ChangePitch( 100 * self:CalcDoppler(), 1 )
self.snd:ChangeVolume(math.Clamp(-(self:GetVelocity().z + 1000) / 3000,0,1), 2)
end
if self.IsEnabled then return end
if self:GetActive() then
self:Enable()
end
end
function ENT:Draw()
local T = CurTime()
if not self:GetActive() then
self._PreventDrawTime = T + 0.1
return
end
if (self._PreventDrawTime or 0) > T then return end
self:DrawModel()
end
function ENT:SoundStop()
if self.snd then
self.snd:Stop()
end
end
function ENT:OnRemove()
self:SoundStop()
end
local color_red = Color(255,0,0,255)
local color_red_blocked = Color(100,0,0,255)
local HudTargets = {}
hook.Add( "HUDPaint", "!!!!lvs_bomb_hud", function()
for ID, _ in pairs( HudTargets ) do
local Missile = Entity( ID )
if not IsValid( Missile ) or Missile:GetActive() then
HudTargets[ ID ] = nil
continue
end
local Grav = physenv.GetGravity()
local FT = 0.05
local MissilePos = Missile:GetPos()
local Pos = MissilePos
local Vel = Missile:GetSpeed()
local LastColor = color_red
local Mask = Missile.GetMaskSolid and (Missile:GetMaskSolid() and MASK_SOLID or MASK_SOLID_BRUSHONLY) or MASK_SOLID_BRUSHONLY
cam.Start3D()
local Iteration = 0
while Iteration < 1000 do
Iteration = Iteration + 1
Vel = Vel + Grav * FT
local StartPos = Pos
local EndPos = Pos + Vel * FT
local trace = util.TraceLine( {
start = StartPos,
endpos = EndPos,
mask = Mask,
} )
local traceVisible = util.TraceLine( {
start = MissilePos,
endpos = StartPos,
mask = Mask,
} )
LastColor = traceVisible.Hit and color_red_blocked or color_red
render.DrawLine( StartPos, EndPos, LastColor )
Pos = EndPos
if trace.Hit then
break
end
end
cam.End3D()
local TargetPos = Pos:ToScreen()
if not TargetPos.visible then continue end
surface.DrawCircle( TargetPos.x, TargetPos.y, 20, LastColor )
end
end )
net.Receive( "lvs_bomb_hud", function( len )
local ent = net.ReadEntity()
if not IsValid( ent ) then return end
HudTargets[ ent:EntIndex() ] = true
end )