mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
417 lines
17 KiB
Lua
417 lines
17 KiB
Lua
--[[
|
|
| This file was obtained through the combined efforts
|
|
| of Madbluntz & Plymouth Antiquarian Society.
|
|
|
|
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
|
| Maloy, DrPepper10 @ RIP, Atle!
|
|
|
|
|
| Visit for more: https://plymouth.thetwilightzone.ru/
|
|
--]]
|
|
|
|
AddCSLuaFile("shared.lua")
|
|
include("shared.lua")
|
|
|
|
ENT.Model = {"models/gunship.mdl"}
|
|
ENT.StartHealth = 440
|
|
|
|
--ENT.CustomBlood_Particle = {"blood_impact_synth_01"}
|
|
ENT.BloodColor = "White"
|
|
|
|
ENT.HeliLights = false
|
|
ENT.Heli_CanCrash = false
|
|
ENT.Heli_CanBomb = false
|
|
ENT.CrashAlarmSound = "npc/combine_gunship/gunship_crashing1.wav"
|
|
ENT.HasRockets = false
|
|
|
|
ENT.RotorSound = "npc/combine_gunship/engine_rotor_loop1.wav"
|
|
ENT.ShootSound = "npc/combine_gunship/gunship_weapon_fire_loop6.wav"
|
|
|
|
ENT.SoundTbl_Idle = {"NPC_CombineGunship.PatrolPing"}
|
|
ENT.SoundTbl_Alert = {"NPC_CombineGunship.SeeEnemy"}
|
|
ENT.SoundTbl_CombatIdle = {"NPC_CombineGunship.SeeEnemy"}
|
|
ENT.SoundTbl_CallForHelp = {"NPC_CombineGunship.SeeEnemy"}
|
|
ENT.SoundTbl_Pain = {"NPC_CombineGunship.Pain"}
|
|
ENT.SoundTbl_Breath = {"NPC_CombineGunship.RotorBlastSound"}
|
|
ENT.SoundTbl_Investigate = {"NPC_CombineGunship.SearchPing"}
|
|
ENT.SoundTbl_LostEnemy = {"NPC_CombineGunship.SearchPing"}
|
|
ENT.SoundTbl_OnReceiveOrder = {"NPC_CombineGunship.SearchPing"}
|
|
|
|
ENT.BreathSoundLevel = 90
|
|
ENT.IdleSoundLevel = 130
|
|
ENT.CombatIdleSoundLevel = 130
|
|
ENT.OnReceiveOrderSoundLevel = 130
|
|
ENT.InvestigateSoundLevel = 130
|
|
ENT.LostEnemySoundLevel = 130
|
|
ENT.AlertSoundLevel = 130
|
|
ENT.CallForHelpSoundLevel = 130
|
|
ENT.PainSoundLevel = 130
|
|
|
|
ENT.DeathCorpseSkin = 1
|
|
ENT.HasDeathRagdoll = true -- If set to false, it will not spawn the regular ragdoll of the SNPC
|
|
|
|
ENT.GibOnDeathDamagesTable = {"UseDefault"}
|
|
ENT.HasGibOnDeathSounds = true
|
|
|
|
ENT.BulletSpread = 0.03
|
|
ENT.BulletsUntilReload = 30
|
|
|
|
ENT.AimYawPoseParam = "flex_horz"
|
|
ENT.AimPitchPoseParam = "flex_vert"
|
|
ENT.FlipAimPitchPoseParam = false
|
|
|
|
ENT.MaxBCannonDistFromEnemy = 250
|
|
ENT.BCannonCooldown = 4
|
|
|
|
ENT.CanShootDownRockets = false
|
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
function ENT:CustomHeliInit()
|
|
|
|
self.Bullseye = ents.Create("obj_vj_Bullseye")
|
|
self.Bullseye:SetModel("models/hunter/plates/plate.mdl")
|
|
self.Bullseye:SetParent(self,5)
|
|
self.Bullseye:SetPos(self:GetAttachment(5).Pos - Vector(0,0,30))
|
|
self.Bullseye:Spawn()
|
|
self.Bullseye:SetNoDraw(true)
|
|
self.Bullseye:DrawShadow(false)
|
|
self.Bullseye:SetSolid(SOLID_NONE)
|
|
self.Bullseye.VJ_NPC_Class = self.VJ_NPC_Class
|
|
|
|
self.RotorBlastSoundLoop = CreateSound(self, "npc/combine_gunship/gunship_engine_loop3.wav")
|
|
self.RotorBlastSoundLoop:SetSoundLevel(95)
|
|
self.RotorBlastSoundLoop:Play()
|
|
|
|
self.Antennas_NoiseSpeedOffset = math.Rand(0.9, 1.1)
|
|
self.Fins_NoiseSpeedOffset = math.Rand(0.9, 1.1)
|
|
|
|
self.Body_vert_NoiseSpeedOffset = math.Rand(0.9, 1.1)
|
|
self.Body_horz_NoiseSpeedOffset = math.Rand(0.9, 1.1)
|
|
|
|
self:SetCollisionBounds( Vector (185,185,95) , Vector (-185,-185,-30) )
|
|
|
|
self.NextBCannon = CurTime()
|
|
|
|
end
|
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
function ENT:DoGunAttack()
|
|
|
|
local bullet_source = self:GetAttachment(1).Pos
|
|
local fire_dir = (self.ShootPos - bullet_source):GetNormalized()
|
|
|
|
local expLight = ents.Create("light_dynamic")
|
|
expLight:SetKeyValue("brightness", "5")
|
|
expLight:SetKeyValue("distance", "250")
|
|
expLight:Fire("Color", "0 75 255")
|
|
expLight:SetPos(bullet_source)
|
|
expLight:Spawn()
|
|
expLight:SetParent(self,1)
|
|
expLight:Fire("TurnOn", "", 0)
|
|
timer.Simple(0.1,function() if IsValid(expLight) then expLight:Remove() end end)
|
|
self:DeleteOnRemove(expLight)
|
|
ParticleEffectAttach("vj_rifle_full_blue",PATTACH_POINT_FOLLOW,self,1)
|
|
|
|
self:FireBullets({
|
|
Src = bullet_source,
|
|
Dir = fire_dir,
|
|
Damage = 3,
|
|
Force = 25,
|
|
TracerName = "AirboatGunTracer",
|
|
Spread = Vector( self.BulletSpread,self.BulletSpread,self.BulletSpread ),
|
|
Num = 1,
|
|
Callback = function(attacker, tracer)
|
|
if math.random(1, 2) == 1 then
|
|
local effectdata = EffectData()
|
|
effectdata:SetOrigin(tracer.HitPos)
|
|
effectdata:SetNormal(tracer.HitNormal)
|
|
effectdata:SetRadius( 10 )
|
|
util.Effect( "cball_bounce", effectdata )
|
|
end
|
|
effects.BeamRingPoint( tracer.HitPos, 0.2, 0, 70, 12, 12, Color(255,255,175) )
|
|
util.VJ_SphereDamage(self,self,tracer.HitPos,20,3,DMG_SONIC,true,false,false,false)
|
|
end,
|
|
})
|
|
|
|
if IsValid(self.EnemyRocket) && self.ShootPos:Distance(self.EnemyRocket:GetPos()) < 50 then
|
|
local destroyed_rocket = ents.Create("obj_vj_destroyed_rocket_z")
|
|
destroyed_rocket:SetPos(self.EnemyRocket:GetPos())
|
|
destroyed_rocket:SetModel(self.EnemyRocket:GetModel())
|
|
destroyed_rocket:Spawn()
|
|
|
|
self.EnemyRocket:Fire("KillHierarchy")
|
|
end
|
|
|
|
self.BulletsFired = self.BulletsFired + 1
|
|
|
|
if self.BulletsFired >= self.BulletsUntilReload then
|
|
|
|
self:UnchargeGun()
|
|
|
|
self.GunHasCooledDown = false
|
|
timer.Simple(self.GunCooldownTime, function() if IsValid(self) then self.GunHasCooledDown = true end end)
|
|
|
|
if self.Diving then self.Diving = false end
|
|
self:ConsiderDive()
|
|
|
|
end
|
|
|
|
self.GunFiring = true
|
|
|
|
end
|
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
function ENT:AnimationThink()
|
|
|
|
local sin = math.sin
|
|
local time = CurTime()
|
|
|
|
|
|
local noise_speed_mult = 2
|
|
self.body_vert_noise = 13 + sin(time*self.Body_vert_NoiseSpeedOffset*noise_speed_mult)*13
|
|
self.body_horz_noise = sin(time*self.Body_horz_NoiseSpeedOffset*noise_speed_mult)*5
|
|
|
|
|
|
local fin_noise = 0.33 + sin(time*self.Fins_NoiseSpeedOffset*noise_speed_mult)*0.33
|
|
local antenna_noise = 0.5 + sin(time*self.Antennas_NoiseSpeedOffset*noise_speed_mult)*0.5
|
|
|
|
self:SetPoseParameter("fin_accel",fin_noise)
|
|
self:SetPoseParameter("antenna_accel",antenna_noise)
|
|
|
|
self:AddLayeredSequence(self:LookupSequence("prop_turn"),2)
|
|
|
|
end
|
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
function ENT:EnemyInBCannonDist()
|
|
|
|
local tr = util.TraceLine({
|
|
start = self:GetPos(),
|
|
endpos = self:GetPos() - Vector(0,0,10000),
|
|
mask = MASK_NPCWORLDSTATIC,
|
|
})
|
|
|
|
local BombSpot = tr.HitPos
|
|
|
|
if self:GetEnemy():GetPos():Distance(BombSpot) < self.MaxBCannonDistFromEnemy then
|
|
return true
|
|
end
|
|
|
|
end
|
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
function ENT:DoBCannon()
|
|
if self.DoingBCannon or self.NextBCannon > CurTime() then return end
|
|
self.DoingBCannon = true
|
|
self:SetNWBool("VJGunshipZDoingBCannon", true)
|
|
|
|
local time_until_fire = 1.15
|
|
|
|
local chargeLight = ents.Create("light_dynamic")
|
|
chargeLight:SetKeyValue("brightness", "5")
|
|
chargeLight:SetKeyValue("distance", "400")
|
|
chargeLight:Fire("Color", "0 75 255")
|
|
chargeLight:SetPos(self:GetAttachment(4).Pos)
|
|
chargeLight:Spawn()
|
|
chargeLight:SetParent(self,4)
|
|
chargeLight:Fire("TurnOn", "", 0)
|
|
self:DeleteOnRemove(chargeLight)
|
|
|
|
self:EmitSound( "NPC_Strider.Charge", 120, 100)
|
|
|
|
|
|
timer.Simple(time_until_fire, function() if IsValid(self) then
|
|
|
|
if IsValid(chargeLight) then chargeLight:Remove() end
|
|
|
|
local tr_bcannon = util.TraceLine({
|
|
start = self:GetPos(),
|
|
endpos = self:GetPos() - Vector(0,0,10000),
|
|
mask = MASK_NPCWORLDSTATIC,
|
|
})
|
|
|
|
local expLight = ents.Create("light_dynamic")
|
|
expLight:SetKeyValue("brightness", "7")
|
|
expLight:SetKeyValue("distance", "600")
|
|
expLight:Fire("Color", "0 75 255")
|
|
expLight:SetPos(self:GetAttachment(4).Pos)
|
|
expLight:Spawn()
|
|
expLight:SetParent(self,4)
|
|
expLight:Fire("TurnOn", "", 0)
|
|
timer.Simple(0.1,function() if IsValid(expLight) then expLight:Remove() end end)
|
|
self:DeleteOnRemove(expLight)
|
|
|
|
local expLight2 = ents.Create("light_dynamic")
|
|
expLight2:SetKeyValue("brightness", "8")
|
|
expLight2:SetKeyValue("distance", "700")
|
|
expLight2:Fire("Color", "0 75 255")
|
|
expLight2:SetPos(tr_bcannon.HitPos)
|
|
expLight2:Spawn()
|
|
expLight2:Fire("TurnOn", "", 0)
|
|
timer.Simple(0.1,function() if IsValid(expLight2) then expLight2:Remove() end end)
|
|
self:DeleteOnRemove(expLight2)
|
|
|
|
util.ScreenShake(tr_bcannon.HitPos, 16, 200, 1, 3000)
|
|
|
|
util.ParticleTracerEx("Weapon_Combine_Ion_Cannon_Beam",self:GetAttachment(4).Pos,tr_bcannon.HitPos,false,self:EntIndex(),4)
|
|
--ParticleEffect("grenade_explosion_01f", tr_bcannon.HitPos, Angle(0,0,0))
|
|
|
|
local effectdata = EffectData()
|
|
effectdata:SetOrigin(tr_bcannon.HitPos)
|
|
effectdata:SetNormal(tr_bcannon.HitNormal)
|
|
effectdata:SetRadius( 400 )
|
|
effectdata:SetScale( 200 )
|
|
util.Effect( "cball_bounce", effectdata )
|
|
util.Effect( "AR2Explosion", effectdata )
|
|
util.Effect( "ThumperDust", effectdata )
|
|
util.Effect( "ThumperDust", effectdata )
|
|
util.Effect( "ThumperDust", effectdata )
|
|
|
|
util.Decal( "Scorch", tr_bcannon.HitPos + tr_bcannon.HitNormal, tr_bcannon.HitPos - tr_bcannon.HitNormal)
|
|
|
|
local damage = 150
|
|
|
|
util.VJ_SphereDamage(self,self,tr_bcannon.HitPos,self.MaxBCannonDistFromEnemy*1.5,damage,bit.bor(DMG_DISSOLVE,DMG_SHOCK,DMG_BLAST),true,true,false,false)
|
|
|
|
self:EmitSound( "NPC_Strider.Shoot", 100, 120)
|
|
sound.Play( "Weapon_Mortar.Impact", tr_bcannon.HitPos, 120, 100, 1 )
|
|
|
|
self.DoingBCannon = false
|
|
self:SetNWBool("VJGunshipZDoingBCannon", false)
|
|
|
|
if self.Diving then
|
|
self.Diving = false
|
|
self.NextDiveTime = CurTime() + self.DiveCooldown
|
|
end
|
|
|
|
self.NextBCannon = CurTime() + self.BCannonCooldown
|
|
|
|
end end)
|
|
|
|
end
|
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
function ENT:DiveBehavior()
|
|
local enemy = self:GetEnemy()
|
|
if self.Diving && IsValid(enemy) && util.TraceLine({start = enemy:GetPos(), endpos = enemy:GetPos()-Vector(0,0,self.MaxBCannonDistFromEnemy), mask = MASK_NPCWORLDSTATIC}).Hit then
|
|
self.Heli_MinChaseDist = self.MaxBCannonDistFromEnemy
|
|
self.Heli_BackAwayFromEnemyDist = self.MaxBCannonDistFromEnemy
|
|
else
|
|
self.Heli_MinChaseDist = self.ShootDist
|
|
self.Heli_BackAwayFromEnemyDist = 1000
|
|
end
|
|
end
|
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
function ENT:CustomHeliThink()
|
|
|
|
self.Bullseye.VJ_NPC_Class = self.VJ_NPC_Class
|
|
|
|
self:AnimationThink()
|
|
|
|
if self.DoingBCannon then
|
|
ParticleEffectAttach("hunter_shield_impact", PATTACH_POINT_FOLLOW, self, 4)
|
|
-- local effectdata = EffectData()
|
|
-- effectdata:SetStart(self:GetAttachment(4).Pos)
|
|
-- util.Effect("cguard_suck", effectdata)
|
|
end
|
|
|
|
if IsValid(self:GetEnemy()) then
|
|
if self:EnemyInBCannonDist() then
|
|
self:DoBCannon()
|
|
end
|
|
end
|
|
end
|
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
function ENT:CustomOnRemove()
|
|
|
|
self.RotorSoundLoop:Stop()
|
|
self.ShootGunLoop:Stop()
|
|
self.RotorBlastSoundLoop:Stop()
|
|
|
|
if self.CrashAlarm && self.CrashSound then
|
|
self.CrashAlarm:Stop()
|
|
self.CrashSound:Stop()
|
|
end
|
|
|
|
end
|
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
function ENT:SetUpGibesOnDeath(dmginfo, hitgroup)
|
|
self:EmitSound("NPC_CombineGunship.Explode", 120, 100)
|
|
local effectdata = EffectData()
|
|
effectdata:SetOrigin(self:GetPos())
|
|
effectdata:SetScale( 500 )
|
|
util.Effect( "Explosion", effectdata )
|
|
self:EmitSound( "Explo.ww2bomb", 130, 100)
|
|
ParticleEffect("vj_explosion1", self:GetPos(), Angle(0,0,0), nil)
|
|
ParticleEffect( "striderbuster_explode_goop", self:GetPos(), self:GetAngles() )
|
|
|
|
self:CreateGibEntity("obj_vj_gib","models/gibs/gunship_gibs_sensorarray.mdl",{BloodType = "",Vel = self:GetVelocity()+VectorRand()*600, CollideSound = {"SolidMetal.ImpactSoft"}})
|
|
self:CreateGibEntity("obj_vj_gib","models/gibs/gunship_gibs_eye.mdl",{BloodType = "",Vel = self:GetVelocity()+VectorRand()*600, CollideSound = {"SolidMetal.ImpactSoft"}})
|
|
self:CreateGibEntity("obj_vj_gib","models/gibs/gunship_gibs_wing.mdl",{BloodType = "",Vel = self:GetVelocity()+VectorRand()*600, CollideSound = {"SolidMetal.ImpactSoft"}})
|
|
self:CreateGibEntity("obj_vj_gib","models/gibs/gunship_gibs_engine.mdl",{BloodType = "",Vel = self:GetVelocity()+VectorRand()*600, CollideSound = {"SolidMetal.ImpactSoft"}})
|
|
|
|
self:CreateGibEntity("obj_vj_gib","models/gibs/gunship_gibs_headsection.mdl",{Pos = self:LocalToWorld(Vector(150,0,0)), BloodType = "", Ang = self:GetAngles(), Vel = self:GetVelocity(), AngVel = VectorRand()*50, CollideSound = {"SolidMetal.ImpactSoft"}})
|
|
self:CreateGibEntity("obj_vj_gib","models/gibs/gunship_gibs_midsection.mdl",{BloodType = "", Ang = self:GetAngles(), Vel = self:GetVelocity(), AngVel = VectorRand()*50, CollideSound = {"SolidMetal.ImpactSoft"}})
|
|
self:CreateGibEntity("obj_vj_gib","models/gibs/gunship_gibs_tailsection.mdl",{Pos = self:LocalToWorld(Vector(-150,0,0)), BloodType = "", Ang = self:GetAngles(), Vel = self:GetVelocity(), AngVel = VectorRand()*50, CollideSound = {"SolidMetal.ImpactSoft"}})
|
|
self:CreateGibEntity("obj_vj_gib","models/gibs/gunship_gibs_nosegun.mdl",{Pos = self:LocalToWorld(Vector(250,0,0)), BloodType = "", Ang = self:GetAngles(), Vel = self:GetVelocity(), AngVel = VectorRand()*50, CollideSound = {"SolidMetal.ImpactSoft"}})
|
|
|
|
return true
|
|
|
|
end
|
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
function ENT:CustomOnDeath_AfterCorpseSpawned(dmginfo, hitgroup, corpseEnt)
|
|
|
|
corpseEnt:GetPhysicsObject():SetVelocity( self:GetVelocity() * 4 + Vector(0,0,250) )
|
|
|
|
corpseEnt:EmitSound("NPC_CombineGunship.Explode", 120, 100)
|
|
ParticleEffectAttach("env_fire_large_smoke", PATTACH_POINT_FOLLOW, corpseEnt, 5)
|
|
local effectdata = EffectData()
|
|
effectdata:SetOrigin(self:GetAttachment(5).Pos)
|
|
effectdata:SetScale( 500 )
|
|
util.Effect( "Explosion", effectdata )
|
|
self:EmitSound( "Explo.ww2bomb", 130, 100)
|
|
timer.Simple(16,function() if IsValid(corpseEnt) then
|
|
corpseEnt:StopParticles()
|
|
end end)
|
|
|
|
end
|
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
function ENT:CustomOnTakeDamage_BeforeDamage(dmginfo, hitgroup)
|
|
|
|
self.HasPainSounds = true -- If set to false, it won't play the pain sounds
|
|
self.Bleeds = false
|
|
|
|
local rotor_damage = dmginfo:GetDamagePosition():Distance(self:GetAttachment(5).Pos) < 75
|
|
|
|
if !dmginfo:IsExplosionDamage() && !rotor_damage && !comballdamage then
|
|
|
|
self.HasPainSounds = false -- If set to false, it won't play the pain sounds
|
|
dmginfo:SetDamage(dmginfo:GetDamage() * 0.1)
|
|
|
|
if math.random(1, 4) == 1 then
|
|
self.Bleeds = true
|
|
self:EmitSound("physics/metal/metal_sheet_impact_bullet1.wav", 92, math.random(70, 90))
|
|
local spark = ents.Create("env_spark")
|
|
spark:SetPos(dmginfo:GetDamagePosition())
|
|
spark:Spawn()
|
|
spark:Fire("StartSpark", "", 0)
|
|
spark:Fire("StopSpark", "", 0.001)
|
|
self:DeleteOnRemove(spark)
|
|
end
|
|
|
|
else
|
|
self.Bleeds = true
|
|
|
|
if rotor_damage then
|
|
if dmginfo:IsExplosionDamage() then
|
|
dmginfo:ScaleDamage(1.5)
|
|
else
|
|
dmginfo:ScaleDamage(0.33)
|
|
end
|
|
end
|
|
|
|
local spark = ents.Create("env_spark")
|
|
spark:SetPos(dmginfo:GetDamagePosition())
|
|
spark:SetKeyValue("Magnitude","2")
|
|
spark:SetKeyValue("Spark Trail Length","2")
|
|
spark:Spawn()
|
|
spark:Fire("StartSpark", "", 0)
|
|
spark:Fire("StopSpark", "", 0.001)
|
|
self:DeleteOnRemove(spark)
|
|
end
|
|
|
|
end
|
|
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |