add sborka

This commit is contained in:
2026-03-31 10:27:04 +03:00
commit f5e5f56c84
2345 changed files with 382127 additions and 0 deletions

View File

@@ -0,0 +1,949 @@
AddCSLuaFile()
local StartSnds = {}
StartSnds[1] = "sw/rocket/rocket_start_01.wav"
StartSnds[2] = "sw/rocket/rocket_start_02.wav"
StartSnds[3] = "sw/rocket/rocket_start_03.wav"
StartSnds[4] = "sw/rocket/rocket_start_04.wav"
local ImpSnds = {}
ImpSnds[1] = "sw/bomb/impact_1.wav"
ImpSnds[2] = "sw/bomb/impact_2.wav"
ImpSnds[3] = "sw/bomb/impact_3.wav"
local WtrImpSnds = {}
WtrImpSnds[1] = "sw/bomb/impact_wtr_1.wav"
WtrImpSnds[2] = "sw/bomb/impact_wtr_2.wav"
WtrImpSnds[3] = "sw/bomb/impact_wtr_3.wav"
local DbrSnds = {}
DbrSnds[1] = "sw/bomb/debris_1.wav"
DbrSnds[2] = "sw/bomb/debris_2.wav"
DbrSnds[3] = "sw/bomb/debris_3.wav"
DbrSnds[4] = "sw/bomb/debris_4.wav"
local ExpSnds = {}
ExpSnds[1] = "sw/explosion/exp_tny_1.wav"
ExpSnds[2] = "sw/explosion/exp_tny_2.wav"
ExpSnds[3] = "sw/explosion/exp_tny_3.wav"
local FarExpSnds = {}
FarExpSnds[1] = "sw/explosion/exp_sml_dst_1.wav"
FarExpSnds[2] = "sw/explosion/exp_sml_dst_2.wav"
FarExpSnds[3] = "sw/explosion/exp_sml_dst_3.wav"
FarExpSnds[4] = "sw/explosion/exp_sml_dst_4.wav"
FarExpSnds[5] = "sw/explosion/exp_sml_dst_5.wav"
FarExpSnds[6] = "sw/explosion/exp_sml_dst_6.wav"
FarExpSnds[7] = "sw/explosion/exp_sml_dst_7.wav"
FarExpSnds[8] = "sw/explosion/exp_sml_dst_8.wav"
local DstExpSnds = {}
DstExpSnds[1] = "sw/explosion/exp_sml_far_1.wav"
DstExpSnds[2] = "sw/explosion/exp_sml_far_2.wav"
DstExpSnds[3] = "sw/explosion/exp_sml_far_3.wav"
DstExpSnds[4] = "sw/explosion/exp_sml_far_4.wav"
DstExpSnds[5] = "sw/explosion/exp_sml_far_5.wav"
DstExpSnds[6] = "sw/explosion/exp_sml_far_6.wav"
DstExpSnds[7] = "sw/explosion/exp_sml_far_7.wav"
DstExpSnds[8] = "sw/explosion/exp_sml_far_8.wav"
local WtrExpSnds = {}
WtrExpSnds[1] = "sw/explosion/exp_trp_1.wav"
WtrExpSnds[2] = "sw/explosion/exp_trp_2.wav"
WtrExpSnds[3] = "sw/explosion/exp_trp_3.wav"
sound.Add( {
name = "SW_ROCKET_ENG_LOOP",
channel = CHAN_AUTO,
volume = 1.0,
level = 80,
sound = "sw/rocket/rocket_fly_loop.wav"
} )
--Main info
ENT.Type = "anim"
ENT.Spawnable = false
ENT.AdminSpawnable = false
ENT.AdminOnly = false
ENT.PrintName = "Rocket basescript V3"
ENT.Author = "Shermann Wolf"
ENT.Contact = "shermannwolf@gmail.com"
ENT.Category = "SW Bombs V3"
ENT.Editable = true
ENT.SWBombV3 = true
ENT.IsRocket = true
--Visual
ENT.Model = "models/sw/rus/rockets/s1of.mdl"
ENT.Effect = "ins_m203_explosion"
ENT.EffectAir = "ins_m203_explosion"
ENT.EffectWater = "ins_water_explosion"
ENT.Decal = "scorch_25kg"
ENT.AngEffect = true
ENT.RocketTrail = "Small_mis_thrust"
ENT.RocketBurnoutTrail = "Small_mis_burnout"
ENT.Tracer1Att = nil
ENT.Tracer2Att = nil
ENT.Engine1Att = nil
ENT.Engine2Att = nil
--Sounds
ENT.ArmSound = "sw/bomb/arm.wav"
ENT.ImpactSound = table.Random(ImpSnds)
ENT.WaterImpactSound = table.Random(WtrImpSnds)
ENT.DebrisSound = table.Random(DbrSnds)
ENT.WhistleSound = "sw/bomb/whistle.wav"
ENT.ExplosionSound = table.Random(ExpSnds)
ENT.FarExplosionSound = table.Random(FarExpSnds)
ENT.DistExplosionSound = table.Random(DstExpSnds)
ENT.WaterExplosionSound = table.Random(WtrExpSnds)
ENT.WaterFarExplosionSound = nil
ENT.StartSound = table.Random(StartSnds)
ENT.EngineSound = "SW_ROCKET_ENG_LOOP"
--Physics
ENT.TraceLength = 150
ENT.ImpactSpeed = 500
ENT.ImpactDepth = 0
ENT.Mass = 100
ENT.Durability = 100
ENT.DetonateHeight = 0
ENT.MaxVelocity = 100
ENT.FuelBurnoutTime = 1
ENT.RotationalForce = 1000
--Explosion
ENT.DamageType = DMG_BURN
ENT.ExplosionDamage = 1000
ENT.ExplosionRadius = 300
ENT.BlastRadius = 450
ENT.FragDamage = 25
ENT.FragRadius = 600
ENT.FragCount = 100
ENT.ArmorPenetration = 1000
ENT.PenetrationDamage = 1000
--Guidance
ENT.DiveHeight = 0
ENT.Agility = 100
ENT.HaveGuidance = false
ENT.GuidanceActive = false
ENT.LaserGuided = false
ENT.LaserCode = "view"
ENT.SpiralRate = -0.4
ENT.SpiralRadius = 0
ENT.IRunstable = false
ENT.IRradius = 0
function ENT:SetupDataTables()
self:NetworkVar("Bool",0,"AirDetonate", {KeyName = "airdetonate", Edit = { type = "Boolean", category = "Fuze"}})
self:NetworkVar("Int",1,"DetonateHeight", { KeyName = "detonateheight", Edit = { type = "Int", min = 0, max = 2000, category = "Fuze"} } )
self:NetworkVar("Int",2,"TracerScale")
self:NetworkVar("Bool",3,"RadioFuze", {KeyName = "radiofuze", Edit = { type = "Boolean", category = "Fuze"}})
self:NetworkVar("Int",4,"RadioFuzeRadius", { KeyName = "radiofuzeradius", Edit = { type = "Int", min = 0, max = 5000, category = "Fuze"} })
end
if SERVER then
local angle_reg = Angle(0,0,0)
local angle_dif = Angle(-90,0,0)
local Normal = Vector(1,1,0)
local Normal2 = Vector(0.1,1,1)
local trlength = Vector(0,0,9000)
local angle_zero = Angle()
local angle_1 = Angle(-90,0,0)
function ENT:SpawnFunction( ply, tr, ClassName )
if not tr.Hit then return end
local ent = ents.Create( ClassName )
ent:SetPos( tr.HitPos + tr.HitNormal )
ent:SetAngles( Angle(0, ply:EyeAngles().y, 0 ) )
ent:Spawn()
ent:Activate()
ent.StartSound = table.Random(StartSnds)
ent.ImpactSound = table.Random(ImpSnds)
ent.WaterImpactSoundSound = table.Random(WtrImpSnds)
ent.DebrisSound = table.Random(DbrSnds)
ent.ExplosionSound = table.Random(ExpSnds)
ent.FarExplosionSound = table.Random(FarExpSnds)
ent.DistExplosionSound = table.Random(DstExpSnds)
ent.WaterExplosionSound = table.Random(WtrExpSnds)
return ent
end
function ENT:Initialize()
self:SetModel(self.Model)
self:SetSolid(SOLID_VPHYSICS)
self:PhysicsInit(SOLID_VPHYSICS)
self:SetCollisionGroup( COLLISION_GROUP_NONE )
self:PhysWake()
local pObj = self:GetPhysicsObject()
pObj:SetMass( self.Mass )
pObj:EnableGravity( false )
pObj:EnableMotion( true )
pObj:EnableDrag( false )
self:StartMotionController()
self:PhysWake()
self.InGround = false
self.InEntity = false
self.Exploded = false
self.Armed = false
self.CurDurability = self.Durability
self.AirDetTicks = 0
self.MaxVelocityUnitsSquared = self.MaxVelocity and self:ConvertMetersToUnits(self.MaxVelocity^2) or nil
end
--Arming
function ENT:Use( activator, caller )
if !self.Exploded and !self.Armed then
self:EmitSound(self.ArmSound)
self.Armed = true
self:Launch()
end
end
function ENT:Launch()
if self.Exploded or self.Burnt or self.Fired then return end
self:SetCollisionGroup(COLLISION_GROUP_PROJECTILE)
local phys = self:GetPhysicsObject()
if !IsValid(phys) then return end
self.ImpactSpeed = 10
self.Fired = true
self:SetNWBool("Fired",true)
constraint.RemoveAll(self)
phys:Wake()
phys:EnableMotion(true)
self:InitLaunch(phys)
end
function ENT:InitLaunch(phys)
self:EmitSound(self.StartSound)
util.ScreenShake( self:GetPos(), 1, 10, 1, 150+self.ExplosionRadius, true, nil )
self:SetBodygroup(1,1)
phys:AddAngleVelocity(Vector(self.RotationalForce or 0,0,0))
if self.RocketTrail then
timer.Simple(0,function()
if !IsValid(self) then return end
if self.Engine1Att then
local ID = self:LookupAttachment( self.Engine1Att )
ParticleEffectAttach(self.RocketTrail,PATTACH_POINT_FOLLOW,self,ID)
end
if self.Engine2Att then
local ID = self:LookupAttachment( self.Engine2Att )
ParticleEffectAttach(self.RocketTrail,PATTACH_POINT_FOLLOW,self,ID)
end
if not self.Engine1Att and not self.Engine2Att then
ParticleEffectAttach(self.RocketTrail,PATTACH_ABSORIGIN_FOLLOW,self,1)
end
if self.Tracer1Att then
if self.TracerEffect then
local ID = self:LookupAttachment( self.Tracer1Att )
ParticleEffectAttach(self.TracerEffect,PATTACH_POINT_FOLLOW,self,ID)
end
end
if self.Tracer2Att then
if self.TracerEffect then
local ID = self:LookupAttachment( self.Tracer2Att )
ParticleEffectAttach(self.TracerEffect,PATTACH_POINT_FOLLOW,self,ID)
end
end
end)
end
if self.FuelBurnoutTime and self.FuelBurnoutTime != 0 then
timer.Simple(self.FuelBurnoutTime,function()
if !IsValid(self) then return end
self.Burnt = true
self:SetNWBool("Burnt",true)
self:StopParticles()
self:StopSound(self.EngineSound)
self:StopSound(self.StartSound)
if self.Engine1Att then
local ID = self:LookupAttachment( self.Engine1Att )
ParticleEffectAttach(self.RocketBurnoutTrail,PATTACH_POINT_FOLLOW,self,ID)
end
if self.Engine2Att then
local ID = self:LookupAttachment( self.Engine2Att )
ParticleEffectAttach(self.RocketBurnoutTrail,PATTACH_POINT_FOLLOW,self,ID)
end
if not self.Engine1Att and not self.Engine2Att then
ParticleEffectAttach(self.RocketBurnoutTrail,PATTACH_ABSORIGIN_FOLLOW,self,1)
end
if self.Tracer1Att then
if self.TracerEffect then
local ID = self:LookupAttachment( self.Tracer1Att )
ParticleEffectAttach(self.TracerEffect,PATTACH_POINT_FOLLOW,self,ID)
end
end
if self.Tracer2Att then
if self.TracerEffect then
local ID = self:LookupAttachment( self.Tracer2Att )
ParticleEffectAttach(self.TracerEffect,PATTACH_POINT_FOLLOW,self,ID)
end
end
end)
end
end
--Think
function ENT:ConvertMetersToUnits(Meters)
return Meters / 0.01905
end
function ENT:ConvertUnitsToMeters(Units)
return Units * 0.01905
end
function ENT:Think()
self:NextThink(CurTime())
if self:IsPlayerHolding() then
self:SetNWBool("IsPlayerHolding",true)
else
self:SetNWBool("IsPlayerHolding",false)
end
if self.Armed then
if self:GetAirDetonate() then
if IsValid(self) and (self:GetVelocity():Length() > self.ImpactSpeed) and not self:IsPlayerHolding() then
self.AirDetTicks = self.AirDetTicks + 1
if self.AirDetTicks >= 50 then
local tr = util.TraceLine({
start = self:LocalToWorld(self:OBBCenter()),
endpos = self:LocalToWorld(self:OBBCenter()) - Vector(0,0,self:GetDetonateHeight()),
filter = self,
})
if tr.Hit then
self.Exploded = true
self:Explode(self:GetPos())
end
end
end
end
if self.CruiseMode and self.GuidanceActive then
local ph = self:GetPhysicsObject()
local target = self.target:LocalToWorld(self.targetOffset)
local tr = util.TraceLine( {
start = self:GetPos(),
endpos = (self:GetPos() + (self:GetAngles():Forward()*7500) - (self:GetAngles():Up()*2500) ),
filter = {self}
} )
if tr.Hit then
local distance = self:GetPos():Distance(target)
if distance > 10000 then
ph:AddVelocity(self:GetAngles():Up()*500)
end
end
end
if self.GuidanceActive then
self:LaserGuidance()
self:Guidance(self:GetPhysicsObject())
if IsValid(self.target) then
if self.WithOffset then
self.TargetForwardOffset = self:GetPos():Distance(self.target:GetPos())/(self.OffsetMultiplier or 2)
self.targetOffset = self.target:WorldToLocal(self.target:GetPos()+(self.target:GetForward()*self.TargetForwardOffset))
end
end
if self.IRunstable == true then
for _, e in pairs(ents.FindInCone(self:GetPos(),self:GetForward(),1500,math.cos(math.rad(self.SeekerCone)))) do
if IsValid( e ) and e:GetClass() == "misc_flare" then
local tr = util.TraceLine( {
start = self:GetPos(),
endpos = e:GetPos(),
} )
if tr.Hit and tr.Entity == e then
self.LaserGuided = false
self.target = e
end
end
if IsValid( e ) and e:GetClass() == "sw_flr" then
local tr = util.TraceLine( {
start = self:GetPos(),
endpos = e:GetPos(),
} )
if tr.Hit and tr.Entity == e then
self.LaserGuided = false
self.target = e
end
end
if IsValid( e ) and e:GetClass() == "sw_flare_v3" then
local tr = util.TraceLine( {
start = self:GetPos(),
endpos = e:GetPos(),
} )
if tr.Hit and tr.Entity == e then
self.LaserGuided = false
self.target = e
end
end
end
end
end
if self:GetRadioFuze() then
for _, e in pairs(ents.FindInSphere(self:GetPos(), self:GetRadioFuzeRadius())) do
if IsValid( e ) and e != self.Launcher then
if self.LaserGuided == true then
if e.IsRocket == true and e.Launcher != self.Launcher then
self.Exploded = true
self:Explode()
end
if e.Fired == true and e.Launcher != self.Launcher then
self.Exploded = true
self:Explode()
end
if e.Armed == true and e.Launcher != self.Launcher then
self.Exploded = true
self:Explode()
end
if e.Burnt == true and e.Launcher != self.Launcher then
self.Exploded = true
self:Explode()
end
if ((e.LFS and e:GetEngineActive()) or ((e:GetClass() == "lvs_helicopter_engine" or e:GetClass() == "lvs_fighterplane_engine") and e:GetBase():GetEngineActive()) or (e.isWacAircraft and e.active)) then
self.Exploded = true
self:Explode()
end
else
if ((e.LFS and e:GetEngineActive()) or ((e:GetClass() == "lvs_helicopter_engine" or e:GetClass() == "lvs_fighterplane_engine") and e:GetBase():GetEngineActive()) or (e.isWacAircraft and e.active)) then
self.Exploded = true
self:Explode()
end
if e.IsRocket == true and e.Launcher != self.Launcher then
self.Exploded = true
self:Explode()
end
if e.Fired == true and e.Launcher != self.Launcher then
self.Exploded = true
self:Explode()
end
if e.Armed == true and e.Launcher != self.Launcher then
self.Exploded = true
self:Explode()
end
if e.Burnt == true and e.Launcher != self.Launcher then
self.Exploded = true
self:Explode()
end
end
end
end
end
if self:GetNWBool("Fired") == true then
if not self.Burnt then
local phys = self:GetPhysicsObject()
if IsValid(phys) then
if self.MaxVelocityUnitsSquared and phys:GetVelocity():LengthSqr() < self.MaxVelocityUnitsSquared then
phys:ApplyForceCenter(self:GetForward() * 500000)
end
end
end
end
end
if self.InGround or self.InEntity then
if self:IsPlayerHolding() then
self.InGround = false
self.InEntity = false
end
end
self:OnTick()
return true
end
function ENT:OnTick()
end
--Flight physics
function ENT:PhysicsSimulate( phys, deltatime )
if self.GuidanceActive or IsValid(self.target) then return end
phys:Wake()
local ForceLinear, ForceAngle = phys:CalculateForceOffset( physenv.GetGravity(), phys:LocalToWorld( phys:GetMassCenter() + Vector(10,0,0) ) )
ForceAngle = ForceAngle - phys:GetAngleVelocity() * 30
if self.RotationalForce and self.Fired then
phys:AddAngleVelocity(Vector(self.RotationalForce,0,0))
end
return ForceAngle, ForceLinear, SIM_GLOBAL_ACCELERATION
end
--Guidance
function ENT:LaserGuidance()
if self.Armed and not (self.InGround or self.InEntity) then
if self.LaserGuided then
if IsValid(self.Launcher) then
local Parent = self.Launcher
local phys = self:GetPhysicsObject()
local ID = Parent:LookupAttachment( self.LaserCode )
local Attachment = Parent:GetAttachment( ID )
if Parent:GetAttachment( ID ) then
local TargetDir = Attachment.Ang:Forward()
local tr = util.TraceLine( {
start = Attachment.Pos,
endpos = (Attachment.Pos + TargetDir * 999999),
filter = {self,Parent,Parent.wheel_C,Parent.wheel_R,Parent.wheel_L}
} )
self.target = tr.Entity
self.targetOffset = tr.Entity:WorldToLocal(tr.HitPos)
phys:SetVelocity( self:GetVelocity() + self:GetAngles():Forward() * 50 )
end
end
end
end
end
function ENT:Guidance(ph)
if self.target != NULL then
if IsValid(self.target) or self.target:GetClass() == "worldspawn" then
if not (self.InGround or self.Armed or self.InEntity) then return end
local pos = self:GetPos()
local vel = self:WorldToLocal(pos+ph:GetVelocity())*0.4
vel.x = 0
local target = self.target:LocalToWorld(self.targetOffset)
local v = self:WorldToLocal(target + Vector(0,0,math.Clamp((pos*Normal):Distance(target*Normal)/5 - 10,0,self.DiveHeight or 0))):GetNormal()
if isnumber(self.Agility) then
v.y = math.Clamp(v.y*10,-1,1)*self.Agility
v.z = math.Clamp(v.z*10,-1,1)*self.Agility
else
v.y = math.Clamp(v.y*10,-1,1)*10
v.z = math.Clamp(v.z*10,-1,1)*10
end
if self.Fired then
if self.SpiralRadius > 0 then
self.SpiralRadius = self.SpiralRadius - FrameTime()*(self.StabilisationTime or 50)
end
if self.SpiralRadius < 0 then
self.SpiralRadius = self.SpiralRadius + FrameTime()*(self.StabilisationTime or 50)
end
if self.SpiralRate > 0 then
self.SpiralRate = self.SpiralRate - FrameTime()
end
if self.SpiralRate < 0 then
self.SpiralRate = self.SpiralRate + FrameTime()
end
end
if self.SpiralRadnom then
ph:AddAngleVelocity(
ph:GetAngleVelocity()*self.SpiralRate
+ Vector(math.Rand(-self.SpiralRadius,self.SpiralRadius), math.Rand(-self.SpiralRadius,self.SpiralRadius), math.Rand(-self.SpiralRadius,self.SpiralRadius))
+ Vector(0,-vel.z,vel.y)
+ Vector(0,-v.z,v.y)
)
else
ph:AddAngleVelocity(
ph:GetAngleVelocity()*self.SpiralRate
+ Vector(self.SpiralRadius, self.SpiralRadius, self.SpiralRadius)
+ Vector(0,-vel.z,vel.y)
+ Vector(0,-v.z,v.y)
)
end
ph:AddVelocity(self:GetForward() - self:LocalToWorld(vel*Normal2) + pos)
end
end
end
--Taking damage
function ENT:OnTakeDamage(dmginfo)
if self.Exploded then return end
local inflictor = dmginfo:GetInflictor()
local attacker = dmginfo:GetAttacker()
if IsValid(inflictor) and (inflictor.IsGredBomb or inflictor.lvsProjectile or inflictor.SWBombV3 ) then return end
self:TakePhysicsDamage(dmginfo)
self.CurDurability = self.CurDurability - dmginfo:GetDamage()
if self.Armed then
if self.CurDurability <= 0 then
self.Exploded = true
self:Explode(self:GetPos())
end
else
if !self.Armed and !self.Fired then
self:EmitSound(self.ArmSound)
self.Armed = true
self:Launch()
end
end
end
--Explosion
function ENT:Explode(pos)
if !self.Exploded then return end
if !self.Armed then return end
pos = self:LocalToWorld(self:OBBCenter())
if(self:WaterLevel() >= 1) then
local tr = util.TraceLine({
start = pos,
endpos = pos + Vector(0,0,9000),
filter = self,
})
local tr2 = util.TraceLine({
start = tr.HitPos,
endpos = tr.HitPos - Vector(0,0,9000),
filter = self,
mask = MASK_WATER + CONTENTS_TRANSLUCENT,
})
if tr2.Hit then
ParticleEffect(self.EffectWater, tr2.HitPos,(self.AngEffect and angle_dif or angle_reg), nil)
end
else
local tr = util.TraceLine({
start = pos,
endpos = pos - Vector(0, 0, self.TraceLength),
filter = self,
})
if tr.HitWorld then
ParticleEffect(self.Effect,pos,(self.AngEffect and angle_dif or angle_reg),nil)
else
ParticleEffect(self.EffectAir,pos,(self.AngEffect and angle_dif or angle_reg),nil)
end
end
if self.HEAT then
local heat = {}
heat.Src = self:GetPos()
heat.Dir = self:GetAngles():Forward()
heat.Spread = Vector(0,0,0)
heat.Force = self.ArmorPenetration+math.Rand(-self.ArmorPenetration/10,self.ArmorPenetration/10)
heat.HullSize = self.HEATRadius or 0
heat.Damage = self.PenetrationDamage+math.Rand(-self.PenetrationDamage/5,self.PenetrationDamage/5)
heat.Velocity = 10000
heat.Attacker = self.Owner
LVS:FireBullet( heat )
--Blast wave
if self.ExplosionRadius > 0 then
util.BlastDamage( self, ((IsValid(self:GetCreator()) and self:GetCreator()) or self.Attacker or game.GetWorld()), pos, self.ExplosionRadius,self.ExplosionDamage )
self:BlastDoors(self, pos, 10)
end
--Frags
if self.FragCount > 0 then
self:Fragmentation(self,pos,10000,self.FragDamage,self.FragRadius,((IsValid(self:GetCreator()) and self:GetCreator()) or self.Attacker or game.GetWorld()))
end
debugoverlay.Text(pos+Vector(0,0,10),"Penetration: "..heat.Force,5)
debugoverlay.Text(pos-Vector(0,0,10),"Damage: "..heat.Damage,5)
debugoverlay.Sphere(pos,self.ExplosionRadius,5,Color(200,150,0,100),false)
debugoverlay.Sphere(pos,self.FragRadius,5,Color(200,200,0,100),false)
else
debugoverlay.Sphere(pos,self.ExplosionRadius,5,Color(255,0,0,100),false)
debugoverlay.Sphere(pos,self.BlastRadius,5,Color(200,150,0,100),false)
debugoverlay.Sphere(pos,self.FragRadius,5,Color(200,200,0,100),false)
--Deadly zone
if self.ExplosionRadius > 0 then
for k, v in pairs(ents.FindInSphere(pos,self.ExplosionRadius)) do
if v:IsValid() and not v.SWBombV3 then
local dmg = DamageInfo()
dmg:SetInflictor(self)
dmg:SetDamage(self.ExplosionDamage)
dmg:SetDamageType(self.DamageType)
dmg:SetAttacker((IsValid(self:GetCreator()) and self:GetCreator()) or self.Attacker or game.GetWorld())
v:TakeDamageInfo(dmg)
end
end
end
--Blast wave
if self.BlastRadius > 0 then
util.BlastDamage( self, ((IsValid(self:GetCreator()) and self:GetCreator()) or self.Attacker or game.GetWorld()), pos, self.BlastRadius,self.ExplosionDamage/2 )
self:BlastDoors(self, pos, 10)
end
--Frags
if self.FragCount > 0 then
self:Fragmentation(self,pos,10000,self.FragDamage,self.FragRadius,((IsValid(self:GetCreator()) and self:GetCreator()) or self.Attacker or game.GetWorld()))
end
end
swv3.CreateSound(pos,false,self.ExplosionSound,self.FarExplosionSound,self.DistExplosionSound)
timer.Simple(0,function()
if !IsValid(self) then return end
self:Remove()
end)
end
--Impact
function ENT:PhysicsCollide( data, physobj )
if self:GetVelocity():Length() >= self.ImpactSpeed then
if self.Armed then
self.Exploded = true
self:Explode(self:GetPos())
else
if !self.Armed and !self.Fired then
self:EmitSound(self.ArmSound)
self.Armed = true
self:Launch()
end
end
end
end
--Door blasting
function ENT:IsDoor(ent)
local Class = ent:GetClass()
return (Class == "prop_door") or (Class == "prop_door_rotating") or (Class == "func_door") or (Class == "func_door_rotating")
end
function ENT:BlastDoors(blaster, pos, power, range, ignoreVisChecks)
for k, door in pairs(ents.FindInSphere(pos, 40 * power * (range or 1))) do
if self:IsDoor(door) then
local proceed = ignoreVisChecks
if not proceed then
local tr = util.QuickTrace(pos, door:LocalToWorld(door:OBBCenter()) - pos, blaster)
proceed = IsValid(tr.Entity) and (tr.Entity == door)
end
if proceed then
self:BlastDoor(door, (door:LocalToWorld(door:OBBCenter()) - pos):GetNormalized() * 1000)
end
end
if door:GetClass() == "func_breakable_surf" then
door:Fire("Break")
end
end
end
function ENT:BlastDoor(ent, vel)
local Moddel, Pozishun, Ayngul, Muteeriul, Skin = ent:GetModel(), ent:GetPos(), ent:GetAngles(), ent:GetMaterial(), ent:GetSkin()
sound.Play("Wood_Crate.Break", Pozishun, 60, 100)
sound.Play("Wood_Furniture.Break", Pozishun, 60, 100)
ent:Fire("unlock", "", 0)
ent:Fire("open", "", 0)
ent:SetNoDraw(true)
ent:SetNotSolid(true)
if Moddel and Pozishun and Ayngul then
local Replacement = ents.Create("prop_physics")
Replacement:SetModel(Moddel)
Replacement:SetPos(Pozishun + Vector(0, 0, 1))
Replacement:SetAngles(Ayngul)
if Muteeriul then
Replacement:SetMaterial(Muteeriul)
end
if Skin then
Replacement:SetSkin(Skin)
end
Replacement:SetModelScale(.9, 0)
Replacement:Spawn()
Replacement:Activate()
if vel then
Replacement:GetPhysicsObject():SetVelocity(vel)
timer.Simple(0, function()
if IsValid(Replacement) then
Replacement:GetPhysicsObject():ApplyForceCenter(vel * 100)
end
end)
end
timer.Simple(3, function()
if IsValid(Replacement) then
Replacement:SetCollisionGroup(COLLISION_GROUP_WEAPON)
end
end)
timer.Simple(30, function()
if IsValid(ent) then
ent:SetNotSolid(false)
ent:SetNoDraw(false)
end
if IsValid(Replacement) then
Replacement:Remove()
end
end)
end
end
--Frags
function ENT:Fragmentation(shooter, origin, fragNum, fragDmg, fragMaxDist, attacker, direction, spread, zReduction)
shooter = shooter or game.GetWorld()
zReduction = zReduction or 2
local Spred = Vector(0, 0, 0)
local BulletsFired, MaxBullets, disperseTime = 0, self.FragCount, .5
if fragNum >= 12000 then
disperseTime = 2
elseif fragNum >= 6000 then
disperseTime = 1
end
for i = 1, fragNum do
timer.Simple((i / fragNum) * disperseTime, function()
local Dir
if direction and spread then
Dir = Vector(direction.x, direction.y, direction.z)
Dir = Dir + VectorRand() * math.Rand(0, spread)
Dir:Normalize()
else
Dir = VectorRand()
end
if zReduction then
Dir.z = Dir.z / zReduction
Dir:Normalize()
end
local Tr = util.QuickTrace(origin, Dir * fragMaxDist, shooter)
if Tr.Hit and not Tr.HitSky and not Tr.HitWorld and (BulletsFired < MaxBullets) then
local LowFrag = (Tr.Entity.IsVehicle and Tr.Entity:IsVehicle()) or Tr.Entity.LFS or Tr.Entity.LVS or Tr.Entity.EZlowFragPlease
if (not LowFrag) or (LowFrag and math.random(1, 4) == 2) then
local firer = (IsValid(shooter) and shooter) or game.GetWorld()
firer:FireBullets({
Attacker = attacker,
Damage = fragDmg,
Force = fragDmg / 8,
Num = 1,
Src = origin,
Tracer = 0,
Dir = Dir,
Spread = Spred,
AmmoType = "Buckshot"
})
BulletsFired = BulletsFired + 1
end
end
end)
end
end
end
if CLIENT then
function ENT:Initialize()
self.snd = CreateSound(self, self.WhistleSound)
self.snd:SetSoundLevel( 110 )
self.snd:PlayEx(0,150)
self.EngSND = CreateSound( self, self.EngineSound )
end
function ENT:CalcDoppler()
local Ent = LocalPlayer()
local ViewEnt = Ent:GetViewEntity()
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.Fired then
self.EngSND:Play()
end
if self:GetNWBool("Fired",false) and not self:GetNWBool("IsPlayerHolding",true) then
if self:GetTracerScale() then
if self.Tracer1Att and not self.TracerEffect then
self.Tracer = Material("sprites/animglow02")
self.Tracer:SetVector("$color", Vector(255,0,0))
if IsValid(self.Emitter) then
local particle
for i = 0,1 do
local ID = self:LookupAttachment( self.Tracer1Att )
local Attachment = self:GetAttachment( ID )
particle = self.Emitter:Add(self.Tracer,Attachment.Pos)
if particle then
particle:SetVelocity(self:GetVelocity())
particle:SetDieTime(0.015)
particle:SetAirResistance(0)
particle:SetStartAlpha(255)
particle:SetStartSize(self:GetTracerScale()*2)
particle:SetEndSize(self:GetTracerScale()*2)
particle:SetRoll(math.Rand(-1,1))
particle:SetGravity(Vector(0,0,0))
particle:SetCollide(false)
end
end
else
self.Emitter = ParticleEmitter(self:GetPos(),false)
end
end
if self.Tracer2Att and not self.TracerEffect then
self.Tracer = Material("sprites/animglow02")
self.Tracer:SetVector("$color", Vector(255,0,0))
if IsValid(self.Emitter) then
local particle
for i = 0,1 do
local ID = self:LookupAttachment( self.Tracer2Att )
local Attachment = self:GetAttachment( ID )
particle = self.Emitter:Add(self.Tracer,Attachment.Pos)
if particle then
particle:SetVelocity(self:GetVelocity())
particle:SetDieTime(0.015)
particle:SetAirResistance(0)
particle:SetStartAlpha(255)
particle:SetStartSize(self:GetTracerScale()*2)
particle:SetEndSize(self:GetTracerScale()*2)
particle:SetRoll(math.Rand(-1,1))
particle:SetGravity(Vector(0,0,0))
particle:SetCollide(false)
end
end
else
self.Emitter = ParticleEmitter(self:GetPos(),false)
end
end
if not self.Tracer1Att and not self.Tracer2Att then
self.Tracer = Material("sprites/animglow02")
self.Tracer:SetVector("$color", Vector(255,0,0))
if IsValid(self.Emitter) then
local particle
for i = 0,1 do
particle = self.Emitter:Add(self.Tracer,self:GetPos())
if particle then
particle:SetVelocity(self:GetVelocity())
particle:SetDieTime(0.015)
particle:SetAirResistance(0)
particle:SetStartAlpha(255)
particle:SetStartSize(self:GetTracerScale()*2)
particle:SetEndSize(self:GetTracerScale()*2)
particle:SetRoll(math.Rand(-1,1))
particle:SetGravity(Vector(0,0,0))
particle:SetCollide(false)
end
end
else
self.Emitter = ParticleEmitter(self:GetPos(),false)
end
end
end
end
end
function ENT:Draw()
self:DrawModel()
end
function ENT:SoundStop()
if self.snd then
self.snd:Stop()
end
end
function ENT:OnRemove()
self:SoundStop()
end
end