add sborka
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
|
||||
resource.AddWorkshop("2922255746") -- LVS Helicopters
|
||||
@@ -0,0 +1,65 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminOnly = false
|
||||
ENT.DoNotDuplicate = true
|
||||
|
||||
ENT.AutomaticFrameAdvance = true
|
||||
|
||||
ENT._LVS = true
|
||||
|
||||
function ENT:PlayAnimation( animation, playbackrate )
|
||||
playbackrate = playbackrate or 1
|
||||
|
||||
local sequence = self:LookupSequence( animation )
|
||||
|
||||
self:ResetSequence( sequence )
|
||||
self:SetPlaybackRate( playbackrate )
|
||||
self:SetSequence( sequence )
|
||||
end
|
||||
|
||||
function ENT:GetAimVector()
|
||||
local Parent = self:GetParent()
|
||||
|
||||
if not IsValid( Parent ) or not Parent.GetAimVector then return -self:GetUp() end
|
||||
|
||||
local Muzzle = self:GetAttachment( self:LookupAttachment( "bellygun" ) )
|
||||
|
||||
if not Muzzle then return -self:GetUp() end
|
||||
|
||||
local AimAng = self:WorldToLocalAngles( (Parent:GetEyeTrace().HitPos - Muzzle.Pos):Angle() )
|
||||
|
||||
AimAng.p = math.Clamp( AimAng.p, 45, 90 )
|
||||
|
||||
return self:LocalToWorldAngles( AimAng ):Forward()
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
function ENT:Initialize()
|
||||
self:SetModel( "models/gunship.mdl" )
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
self:SetSolid( SOLID_NONE )
|
||||
self:SetNoDraw( true )
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
self:NextThink( CurTime() )
|
||||
|
||||
return true
|
||||
end
|
||||
else
|
||||
function ENT:Initialize()
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,109 @@
|
||||
include("shared.lua")
|
||||
|
||||
function ENT:DamageFX()
|
||||
self.nextDFX = self.nextDFX or 0
|
||||
|
||||
if self.nextDFX < CurTime() then
|
||||
self.nextDFX = CurTime() + 0.05
|
||||
|
||||
local HP = self:GetHP()
|
||||
local MaxHP = self:GetMaxHP()
|
||||
|
||||
if HP > MaxHP * 0.25 then return end
|
||||
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin( self:LocalToWorld( Vector(-10,25,-10) ) )
|
||||
effectdata:SetNormal( self:GetUp() )
|
||||
effectdata:SetMagnitude( math.Rand(0.5,1.5) )
|
||||
effectdata:SetEntity( self )
|
||||
util.Effect( "lvs_exhaust_fire", effectdata )
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnFrame()
|
||||
self:AnimRotor()
|
||||
self:AnimTail()
|
||||
self:DamageFX()
|
||||
end
|
||||
|
||||
function ENT:RemoveLight()
|
||||
if IsValid( self.projector ) then
|
||||
self.projector:Remove()
|
||||
self.projector = nil
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemoved()
|
||||
self:RemoveLight()
|
||||
end
|
||||
|
||||
function ENT:AnimTail()
|
||||
local Steer = self:GetSteer()
|
||||
|
||||
local TargetValue = -(Steer.x + Steer.z * 2) * 10
|
||||
|
||||
self.sm_pp_rudder = self.sm_pp_rudder and (self.sm_pp_rudder + (TargetValue - self.sm_pp_rudder) * RealFrameTime() * 5) or 0
|
||||
|
||||
self:SetPoseParameter("rudder", self.sm_pp_rudder)
|
||||
self:InvalidateBoneCache()
|
||||
end
|
||||
|
||||
function ENT:AnimRotor()
|
||||
local RPM = self:GetThrottle() * 2500
|
||||
|
||||
self.RPM = self.RPM and (self.RPM + RPM * RealFrameTime() * 0.5) or 0
|
||||
|
||||
local Rot1 = Angle( -self.RPM,0,0)
|
||||
Rot1:Normalize()
|
||||
|
||||
local Rot2 = Angle(0,0,self.RPM)
|
||||
Rot2:Normalize()
|
||||
|
||||
self:ManipulateBoneAngles( 2, Rot1 )
|
||||
self:ManipulateBoneAngles( 5, Rot2 )
|
||||
self:ManipulateBoneAngles( 3, Rot2 )
|
||||
end
|
||||
|
||||
|
||||
ENT.LightMaterial = Material( "effects/lvs/heli_spotlight" )
|
||||
ENT.GlowMaterial = Material( "sprites/light_glow02_add" )
|
||||
|
||||
function ENT:PreDrawTranslucent()
|
||||
if not self:GetLightsEnabled() then
|
||||
self:RemoveLight()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local SpotLight = self:GetAttachment( self:LookupAttachment( "SpotLight" ) )
|
||||
|
||||
if not SpotLight then return true end
|
||||
|
||||
if not IsValid( self.projector ) then
|
||||
local thelamp = ProjectedTexture()
|
||||
thelamp:SetBrightness( 5 )
|
||||
thelamp:SetTexture( "effects/flashlight/soft" )
|
||||
thelamp:SetColor( Color(255,255,255) )
|
||||
thelamp:SetEnableShadows( true )
|
||||
thelamp:SetFarZ( 2500 )
|
||||
thelamp:SetNearZ( 75 )
|
||||
thelamp:SetFOV( 60 )
|
||||
self.projector = thelamp
|
||||
end
|
||||
|
||||
local Dir = SpotLight.Ang:Forward()
|
||||
|
||||
render.SetMaterial( self.GlowMaterial )
|
||||
render.DrawSprite( SpotLight.Pos + Dir * 5, 32, 32, Color( 255, 255, 255, 255) )
|
||||
|
||||
render.SetMaterial( self.LightMaterial )
|
||||
render.DrawBeam( SpotLight.Pos, SpotLight.Pos + Dir * 100, 32, 0, 0.99, Color( 100, 100, 100, 255) )
|
||||
|
||||
if IsValid( self.projector ) then
|
||||
self.projector:SetPos( SpotLight.Pos )
|
||||
self.projector:SetAngles( SpotLight.Ang )
|
||||
self.projector:Update()
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
@@ -0,0 +1,124 @@
|
||||
AddCSLuaFile( "shared.lua" )
|
||||
AddCSLuaFile( "cl_init.lua" )
|
||||
include("shared.lua")
|
||||
|
||||
function ENT:OnSpawn( PObj )
|
||||
local DriverSeat = self:AddDriverSeat( Vector(120,0,-40), Angle(0,-90,0) )
|
||||
DriverSeat:SetCameraDistance( 0.2 )
|
||||
|
||||
self:AddEngineSound( Vector(0,0,0) )
|
||||
|
||||
--self:AddRotor( pos, angle, radius, turn_speed_and_direction )
|
||||
self.Rotor = self:AddRotor( Vector(0,0,65), Angle(15,0,0), 310, -4000 )
|
||||
self.Rotor:SetRotorEffects( true )
|
||||
self.Rotor:SetHP( 50 )
|
||||
function self.Rotor:OnDestroyed( base )
|
||||
local ID = base:LookupBone( "Chopper.Rotor_Blur" )
|
||||
base:ManipulateBoneScale( ID, Vector(0,0,0) )
|
||||
|
||||
base:DestroyEngine()
|
||||
|
||||
self:EmitSound( "physics/metal/metal_box_break2.wav" )
|
||||
end
|
||||
|
||||
self.TailRotor = self:AddRotor( Vector(-218,4,-1.8), Angle(0,0,90), 25, -6000 )
|
||||
self.TailRotor:SetHP( 100 )
|
||||
function self.TailRotor:OnDestroyed( base )
|
||||
base:DestroySteering( -2.5 )
|
||||
base:SnapTailRotor()
|
||||
|
||||
self:EmitSound( "physics/metal/metal_box_break2.wav" )
|
||||
end
|
||||
|
||||
self:AddDS( {
|
||||
pos = Vector(-218,4,-1.8),
|
||||
ang = Angle(0,0,0),
|
||||
mins = Vector(-45,-15,-40),
|
||||
maxs = Vector(75,15,60),
|
||||
Callback = function( tbl, ent, dmginfo )
|
||||
if dmginfo:GetDamage() <= 0 then return end
|
||||
|
||||
ent.TailRotor:TakeDamageInfo( dmginfo )
|
||||
end
|
||||
} )
|
||||
|
||||
local ID = self:LookupAttachment( "muzzle" )
|
||||
local Muzzle = self:GetAttachment( ID )
|
||||
self.weaponSND = self:AddSoundEmitter( self:WorldToLocal( Muzzle.Pos ), "npc/attack_helicopter/aheli_weapon_fire_loop3.wav", "npc/attack_helicopter/aheli_weapon_fire_loop3.wav" )
|
||||
self.weaponSND:SetSoundLevel( 110 )
|
||||
self.weaponSND:SetParent( self, ID )
|
||||
end
|
||||
|
||||
function ENT:SnapTailRotor()
|
||||
if self.TailDestroyed then return end
|
||||
|
||||
self.TailDestroyed = true
|
||||
|
||||
local ent = ents.Create( "prop_physics" )
|
||||
ent:SetModel( "models/gibs/helicopter_brokenpiece_05_tailfan.mdl" )
|
||||
ent:SetPos( self:LocalToWorld( Vector(-153.476349,1.618453,3.479492) ) )
|
||||
ent:SetAngles( self:GetAngles() )
|
||||
ent:Spawn()
|
||||
ent:Activate()
|
||||
ent:SetRenderMode( RENDERMODE_TRANSALPHA )
|
||||
ent:SetCollisionGroup( COLLISION_GROUP_WORLD )
|
||||
|
||||
self:DeleteOnRemove( ent )
|
||||
|
||||
local PhysObj = ent:GetPhysicsObject()
|
||||
|
||||
if not IsValid( PhysObj ) then return end
|
||||
|
||||
PhysObj:SetVelocityInstantaneous( self:GetVelocity() )
|
||||
PhysObj:AddAngleVelocity( VectorRand() * 500 )
|
||||
PhysObj:EnableDrag( false )
|
||||
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin( ent:GetPos() )
|
||||
effectdata:SetStart( PhysObj:GetMassCenter() )
|
||||
effectdata:SetEntity( ent )
|
||||
effectdata:SetScale( 0.25 )
|
||||
effectdata:SetMagnitude( 5 )
|
||||
util.Effect( "lvs_firetrail", effectdata )
|
||||
|
||||
local BonesToScale = {
|
||||
"Chopper.Tail",
|
||||
"Chopper.Blade_Tail",
|
||||
}
|
||||
|
||||
for _, name in pairs( BonesToScale ) do
|
||||
local ID = self:LookupBone( name )
|
||||
self:ManipulateBoneScale( ID, Vector(0,0,0) )
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:GetMissileOffset()
|
||||
return Vector(-60,0,0)
|
||||
end
|
||||
|
||||
function ENT:OnEngineActiveChanged( Active )
|
||||
if Active then
|
||||
self:EmitSound( "lvs/vehicles/helicopter/start.wav" )
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnCollision( data, physobj )
|
||||
if self:IsPlayerHolding() then return false end
|
||||
|
||||
if data.Speed > 60 and data.DeltaTime > 0.2 then
|
||||
local VelDif = data.OurOldVelocity:Length() - data.OurNewVelocity:Length()
|
||||
|
||||
if VelDif > 200 then
|
||||
local part = self:FindDS( data.HitPos - data.OurOldVelocity:GetNormalized() * 25 )
|
||||
|
||||
if part then
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetDamage( 200 )
|
||||
dmginfo:SetDamageType( DMG_CRUSH )
|
||||
part:Callback( self, dmginfo )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
@@ -0,0 +1,333 @@
|
||||
|
||||
ENT.Base = "lvs_base_helicopter"
|
||||
|
||||
ENT.PrintName = "Combine Helicopter"
|
||||
ENT.Author = "Luna"
|
||||
ENT.Information = "Combine Attack Helicopter from Half Life 2 + Episodes"
|
||||
ENT.Category = "[LVS] - Helicopters"
|
||||
|
||||
ENT.VehicleCategory = "Helicopters"
|
||||
ENT.VehicleSubCategory = "Combine"
|
||||
|
||||
ENT.Spawnable = true
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
ENT.DisableBallistics = true
|
||||
|
||||
ENT.MDL = "models/Combine_Helicopter.mdl"
|
||||
ENT.GibModels = {
|
||||
"models/gibs/helicopter_brokenpiece_01.mdl",
|
||||
"models/gibs/helicopter_brokenpiece_02.mdl",
|
||||
"models/gibs/helicopter_brokenpiece_03.mdl",
|
||||
"models/gibs/helicopter_brokenpiece_06_body.mdl",
|
||||
"models/gibs/helicopter_brokenpiece_04_cockpit.mdl",
|
||||
"models/gibs/helicopter_brokenpiece_05_tailfan.mdl",
|
||||
}
|
||||
|
||||
ENT.AITEAM = 1
|
||||
|
||||
ENT.MaxHealth = 1600
|
||||
|
||||
ENT.MaxVelocity = 2150
|
||||
|
||||
ENT.ThrustUp = 1
|
||||
ENT.ThrustDown = 0.8
|
||||
ENT.ThrustRate = 1
|
||||
|
||||
ENT.ThrottleRateUp = 0.2
|
||||
ENT.ThrottleRateDown = 0.2
|
||||
|
||||
ENT.TurnRatePitch = 1
|
||||
ENT.TurnRateYaw = 1
|
||||
ENT.TurnRateRoll = 1
|
||||
|
||||
ENT.GravityTurnRateYaw = 2
|
||||
|
||||
ENT.ForceLinearDampingMultiplier = 1.5
|
||||
|
||||
ENT.ForceAngleMultiplier = 1
|
||||
ENT.ForceAngleDampingMultiplier = 1
|
||||
|
||||
ENT.EngineSounds = {
|
||||
{
|
||||
sound = "^npc/attack_helicopter/aheli_rotor_loop1.wav",
|
||||
--sound_int = "lvs/vehicles/helicopter/loop_interior.wav",
|
||||
Pitch = 0,
|
||||
PitchMin = 0,
|
||||
PitchMax = 255,
|
||||
PitchMul = 100,
|
||||
Volume = 1,
|
||||
VolumeMin = 0,
|
||||
VolumeMax = 1,
|
||||
SoundLevel = 125,
|
||||
UseDoppler = true,
|
||||
},
|
||||
}
|
||||
|
||||
function ENT:OnSetupDataTables()
|
||||
self:AddDT( "Bool", "LightsEnabled" )
|
||||
end
|
||||
|
||||
function ENT:GetAimAngles()
|
||||
local Gun = self:GetAttachment( self:LookupAttachment( "gun" ) )
|
||||
|
||||
if not Gun then return end
|
||||
|
||||
local trace = self:GetEyeTrace()
|
||||
|
||||
local AimAngles = self:WorldToLocalAngles( (trace.HitPos - Gun.Pos):GetNormalized():Angle() )
|
||||
|
||||
return AimAngles
|
||||
end
|
||||
|
||||
function ENT:WeaponsInRange()
|
||||
local AimAngles = self:GetAimAngles()
|
||||
|
||||
return math.abs( AimAngles.y ) < 40 and AimAngles.p < 90 and AimAngles.p > -20
|
||||
end
|
||||
|
||||
function ENT:SetPoseParameterTurret()
|
||||
local AimAngles = self:GetAimAngles()
|
||||
|
||||
self:SetPoseParameter("weapon_yaw", AimAngles.y )
|
||||
self:SetPoseParameter("weapon_pitch", -AimAngles.p )
|
||||
end
|
||||
|
||||
function ENT:HandleShoot( FireInput, active )
|
||||
self.charge = self.charge or 0
|
||||
|
||||
if self.charging then
|
||||
self.charge = math.min( self.charge + FrameTime() * 60, 100 )
|
||||
|
||||
if self.charge >= 100 then
|
||||
self.charging = nil
|
||||
end
|
||||
else
|
||||
if FireInput and self.charge > 0 then
|
||||
self:ShootGun()
|
||||
else
|
||||
if FireInput then
|
||||
self:ChargeGun()
|
||||
else
|
||||
self.charge = math.max(self.charge - FrameTime() * 120,0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local Fire = FireInput and active and self.charge > 0 and not self.charging
|
||||
|
||||
if not IsValid( self.weaponSND ) then return end
|
||||
|
||||
if self._oldFire ~= Fire then
|
||||
self._oldFire = Fire
|
||||
|
||||
if Fire then
|
||||
if self.weaponSND.snd_chrg then
|
||||
self.weaponSND.snd_chrg:Stop()
|
||||
self.weaponSND.snd_chrg = nil
|
||||
end
|
||||
self.weaponSND:Play()
|
||||
else
|
||||
self.weaponSND:Stop()
|
||||
end
|
||||
end
|
||||
|
||||
if not active then return end
|
||||
|
||||
if Fire then
|
||||
self:SetHeat( 1 - self.charge / 100 )
|
||||
else
|
||||
self:SetHeat( math.Clamp(self.charge / 100,0,0.89) ) -- clamp to 0.89 so the ai doesnt detect it as overheating
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:ChargeGun()
|
||||
self._doAttack = true
|
||||
self.charging = true
|
||||
|
||||
if not IsValid( self.weaponSND ) then return end
|
||||
|
||||
self.weaponSND.snd_chrg = CreateSound( self, "NPC_AttackHelicopter.ChargeGun" )
|
||||
self.weaponSND.snd_chrg:Play()
|
||||
end
|
||||
|
||||
function ENT:FinishShoot()
|
||||
self._doAttack = nil
|
||||
self.charging = nil
|
||||
|
||||
if not IsValid( self.weaponSND ) then return end
|
||||
|
||||
self.weaponSND:Stop()
|
||||
|
||||
if self.weaponSND.snd_chrg then
|
||||
self.weaponSND.snd_chrg:Stop()
|
||||
self.weaponSND.snd_chrg = nil
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:ShootGun()
|
||||
local T = CurTime()
|
||||
|
||||
if (self.NextFire or 0) > T then return end
|
||||
|
||||
self.NextFire = T + 0.03
|
||||
|
||||
self.charge = self.charge - 0.9
|
||||
|
||||
local Muzzle = self:GetAttachment( self:LookupAttachment( "muzzle" ) )
|
||||
|
||||
if not Muzzle then return end
|
||||
|
||||
local trace = self:GetEyeTrace()
|
||||
|
||||
local bullet = {}
|
||||
bullet.Src = Muzzle.Pos
|
||||
bullet.Dir = (trace.HitPos - Muzzle.Pos):GetNormalized()
|
||||
bullet.Spread = Vector(0.06,0.06,0.06)
|
||||
bullet.TracerName = "lvs_pulserifle_tracer"
|
||||
bullet.Force = 1000
|
||||
bullet.HullSize = 6
|
||||
bullet.Damage = 6
|
||||
bullet.Velocity = 15000
|
||||
bullet.Attacker = self:GetDriver()
|
||||
bullet.Callback = function(att, tr, dmginfo)
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin( tr.HitPos )
|
||||
effectdata:SetNormal( tr.HitNormal )
|
||||
util.Effect( "AR2Impact", effectdata, true, true )
|
||||
end
|
||||
self:LVSFireBullet( bullet )
|
||||
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin( Muzzle.Pos )
|
||||
effectdata:SetNormal( Muzzle.Ang:Forward() )
|
||||
effectdata:SetEntity( ent )
|
||||
util.Effect( "lvs_pulserifle_muzzle", effectdata )
|
||||
end
|
||||
|
||||
function ENT:InitWeapons()
|
||||
local weapon = {}
|
||||
weapon.Icon = Material("lvs/weapons/mg.png")
|
||||
weapon.Ammo = -1
|
||||
weapon.Delay = 0
|
||||
weapon.HeatRateUp = 0
|
||||
weapon.HeatRateDown = 0
|
||||
weapon.StartAttack = function( ent )
|
||||
ent:ChargeGun()
|
||||
end
|
||||
weapon.FinishAttack = function( ent )
|
||||
ent:FinishShoot()
|
||||
end
|
||||
weapon.Attack = function( ent )
|
||||
end
|
||||
weapon.OnThink = function( ent, active )
|
||||
ent:SetPoseParameterTurret()
|
||||
ent:HandleShoot( ent._doAttack and active and ent:WeaponsInRange(), active )
|
||||
end
|
||||
weapon.OnSelect = function( ent ) ent:EmitSound("physics/metal/weapon_impact_soft3.wav") end
|
||||
self:AddWeapon( weapon )
|
||||
|
||||
|
||||
local weapon = {}
|
||||
weapon.Icon = Material("lvs/weapons/missile.png")
|
||||
weapon.Ammo = 60
|
||||
weapon.Delay = 0.25
|
||||
weapon.HeatRateUp = 0.25
|
||||
weapon.HeatRateDown = 0.25
|
||||
weapon.Attack = function( ent )
|
||||
|
||||
ent.FireLeft = not ent.FireLeft
|
||||
|
||||
local Driver = ent:GetDriver()
|
||||
local Target = ent:GetEyeTrace().HitPos
|
||||
|
||||
local projectile = ents.Create( "lvs_missile" )
|
||||
projectile:SetPos( ent:LocalToWorld( Vector(17.36,50.89 * (self.FireLeft and 1 or -1),-59.39) ) )
|
||||
projectile:SetAngles( ent:GetAngles() )
|
||||
projectile:SetParent( ent )
|
||||
projectile:Spawn()
|
||||
projectile:Activate()
|
||||
projectile.GetTarget = function( missile ) return missile end
|
||||
projectile.GetTargetPos = function( missile )
|
||||
if missile.HasReachedTarget then
|
||||
return missile:LocalToWorld( Vector(100,0,0) )
|
||||
end
|
||||
|
||||
if (missile:GetPos() - Target):Length() < 100 then
|
||||
missile.HasReachedTarget = true
|
||||
end
|
||||
return Target
|
||||
end
|
||||
projectile:SetAttacker( IsValid( Driver ) and Driver or self )
|
||||
projectile:SetEntityFilter( ent:GetCrosshairFilterEnts() )
|
||||
projectile:SetSpeed( ent:GetVelocity():Length() + 4000 )
|
||||
projectile:SetDamage( 400 )
|
||||
projectile:SetRadius( 150 )
|
||||
projectile:Enable()
|
||||
projectile:EmitSound("npc/waste_scanner/grenade_fire.wav")
|
||||
|
||||
ent:TakeAmmo()
|
||||
end
|
||||
weapon.OnSelect = function( ent )
|
||||
ent:EmitSound("weapons/shotgun/shotgun_cock.wav")
|
||||
end
|
||||
self:AddWeapon( weapon )
|
||||
|
||||
|
||||
local weapon = {}
|
||||
weapon.Icon = Material("lvs/weapons/bomb.png")
|
||||
weapon.UseableByAI = false
|
||||
weapon.Ammo = 128
|
||||
weapon.Delay = 0.25
|
||||
weapon.HeatRateUp = -0.4
|
||||
weapon.HeatRateDown = 0.4
|
||||
weapon.StartAttack = function( ent )
|
||||
local Driver = ent:GetDriver()
|
||||
|
||||
local projectile = ents.Create( "lvs_helicopter_combine_bomb" )
|
||||
projectile:SetPos( ent:LocalToWorld( Vector(-50,0,-25) ) )
|
||||
projectile:SetAngles( ent:GetAngles() )
|
||||
projectile:SetParent( ent )
|
||||
projectile:Spawn()
|
||||
projectile:Activate()
|
||||
projectile:SetAttacker( IsValid( Driver ) and Driver or ent )
|
||||
projectile:SetEntityFilter( ent:GetCrosshairFilterEnts() )
|
||||
projectile:SetSpeed( ent:GetVelocity() )
|
||||
projectile:SetDamage( 150 )
|
||||
projectile:SetRadius( 250 )
|
||||
|
||||
self._ProjectileEntity = projectile
|
||||
end
|
||||
weapon.FinishAttack = function( ent )
|
||||
if not IsValid( ent._ProjectileEntity ) then return end
|
||||
|
||||
ent._ProjectileEntity:Enable()
|
||||
ent._ProjectileEntity:EmitSound("npc/attack_helicopter/aheli_mine_drop1.wav")
|
||||
|
||||
ent:TakeAmmo()
|
||||
|
||||
ent:SetHeat( ent:GetHeat() + 0.2 )
|
||||
|
||||
if ent:GetHeat() >= 1 then
|
||||
ent:SetOverheated( true )
|
||||
end
|
||||
end
|
||||
self:AddWeapon( weapon )
|
||||
|
||||
local weapon = {}
|
||||
weapon.Icon = Material("lvs/weapons/light.png")
|
||||
weapon.UseableByAI = false
|
||||
weapon.Ammo = -1
|
||||
weapon.Delay = 0
|
||||
weapon.HeatRateUp = 0
|
||||
weapon.HeatRateDown = 1
|
||||
weapon.StartAttack = function( ent )
|
||||
if not ent.SetLightsEnabled then return end
|
||||
|
||||
if ent:GetAI() then return end
|
||||
|
||||
ent:SetLightsEnabled( not ent:GetLightsEnabled() )
|
||||
ent:EmitSound( "items/flashlight1.wav", 75, 105 )
|
||||
end
|
||||
self:AddWeapon( weapon )
|
||||
end
|
||||
@@ -0,0 +1,92 @@
|
||||
include("shared.lua")
|
||||
|
||||
function ENT:PreDraw()
|
||||
local Body = self:GetBody()
|
||||
|
||||
if not IsValid( Body ) then return false end
|
||||
|
||||
Body:DrawModel()
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function ENT:PreDrawTranslucent()
|
||||
return false
|
||||
end
|
||||
|
||||
function ENT:DamageFX()
|
||||
self.nextDFX = self.nextDFX or 0
|
||||
|
||||
if self.nextDFX < CurTime() then
|
||||
self.nextDFX = CurTime() + 0.05
|
||||
|
||||
local HP = self:GetHP()
|
||||
local MaxHP = self:GetMaxHP()
|
||||
|
||||
if HP > MaxHP * 0.25 then return end
|
||||
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin( self:LocalToWorld( Vector(-60,0,-10) ) )
|
||||
effectdata:SetNormal( self:GetUp() )
|
||||
effectdata:SetMagnitude( math.Rand(0.5,1.5) )
|
||||
effectdata:SetEntity( self )
|
||||
util.Effect( "lvs_exhaust_fire", effectdata )
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnFrame()
|
||||
self:AnimRotor()
|
||||
self:DamageFX()
|
||||
end
|
||||
|
||||
function ENT:AnimRotor()
|
||||
local RPM = self:GetThrottle() * 2500
|
||||
|
||||
self.RPM = self.RPM and (self.RPM + RPM * RealFrameTime() * 0.5) or 0
|
||||
|
||||
local Rot = Angle( -self.RPM,0,0)
|
||||
Rot:Normalize()
|
||||
|
||||
local Body = self:GetBody()
|
||||
|
||||
if not IsValid( Body ) then return end
|
||||
|
||||
Body:ManipulateBoneAngles( 19, Rot )
|
||||
end
|
||||
|
||||
function ENT:PaintCrosshairSquare( Pos2D, Col )
|
||||
local X = Pos2D.x + 1
|
||||
local Y = Pos2D.y + 1
|
||||
|
||||
local Size = 20
|
||||
|
||||
surface.SetDrawColor( 0, 0, 0, 80 )
|
||||
surface.DrawLine( X - Size, Y + Size, X - Size * 0.5, Y + Size )
|
||||
surface.DrawLine( X + Size, Y + Size, X + Size * 0.5, Y + Size )
|
||||
surface.DrawLine( X - Size, Y + Size, X - Size, Y + Size * 0.5 )
|
||||
surface.DrawLine( X - Size, Y - Size, X - Size, Y - Size * 0.5 )
|
||||
surface.DrawLine( X + Size, Y + Size, X + Size, Y + Size * 0.5 )
|
||||
surface.DrawLine( X + Size, Y - Size, X + Size, Y - Size * 0.5 )
|
||||
surface.DrawLine( X - Size, Y - Size, X - Size * 0.5, Y - Size )
|
||||
surface.DrawLine( X + Size, Y - Size, X + Size * 0.5, Y - Size )
|
||||
|
||||
if Col then
|
||||
surface.SetDrawColor( Col.r, Col.g, Col.b, Col.a )
|
||||
else
|
||||
surface.SetDrawColor( 255, 255, 255, 255 )
|
||||
end
|
||||
|
||||
X = Pos2D.x
|
||||
Y = Pos2D.y
|
||||
|
||||
surface.DrawLine( X - Size, Y + Size, X - Size * 0.5, Y + Size )
|
||||
surface.DrawLine( X + Size, Y + Size, X + Size * 0.5, Y + Size )
|
||||
surface.DrawLine( X - Size, Y + Size, X - Size, Y + Size * 0.5 )
|
||||
surface.DrawLine( X - Size, Y - Size, X - Size, Y - Size * 0.5 )
|
||||
surface.DrawLine( X + Size, Y + Size, X + Size, Y + Size * 0.5 )
|
||||
surface.DrawLine( X + Size, Y - Size, X + Size, Y - Size * 0.5 )
|
||||
surface.DrawLine( X - Size, Y - Size, X - Size * 0.5, Y - Size )
|
||||
surface.DrawLine( X + Size, Y - Size, X + Size * 0.5, Y - Size )
|
||||
|
||||
self:PaintCrosshairCenter( Pos2D, Col )
|
||||
end
|
||||
@@ -0,0 +1,160 @@
|
||||
AddCSLuaFile( "shared.lua" )
|
||||
AddCSLuaFile( "cl_init.lua" )
|
||||
include("shared.lua")
|
||||
|
||||
function ENT:OnSpawn( PObj )
|
||||
local DriverSeat = self:AddDriverSeat( Vector(200,0,0), Angle(0,-90,0) )
|
||||
DriverSeat:SetCameraDistance( 0.2 )
|
||||
DriverSeat.HidePlayer = true
|
||||
|
||||
self:AddEngineSound( Vector(-133,0,55) )
|
||||
|
||||
self:DrawShadow( false )
|
||||
|
||||
local Body = ents.Create( "lvs_gunship_body" )
|
||||
Body:SetPos( self:GetPos() )
|
||||
Body:SetAngles( self:GetAngles() )
|
||||
Body:Spawn()
|
||||
Body:Activate()
|
||||
Body:SetParent( self )
|
||||
Body:SetSkin( 1 )
|
||||
self:DeleteOnRemove( Body )
|
||||
self:TransferCPPI( Body )
|
||||
self:SetBody( Body )
|
||||
|
||||
local Rotor = self:AddRotor( Vector(-133,0,55), Angle(0,0,0), 0, 4000 )
|
||||
Rotor:SetRotorEffects( true )
|
||||
|
||||
local ID = Body:LookupAttachment( "muzzle" )
|
||||
local Muzzle = Body:GetAttachment( ID )
|
||||
self.weaponSND = self:AddSoundEmitter( Body:WorldToLocal( Muzzle.Pos ), "npc/combine_gunship/gunship_weapon_fire_loop6.wav", "npc/combine_gunship/gunship_fire_loop1.wav" )
|
||||
self.weaponSND:SetSoundLevel( 110 )
|
||||
self.weaponSND:SetParent( Body, ID )
|
||||
end
|
||||
|
||||
function ENT:SetRotor( PhysRot )
|
||||
local Body = self:GetBody()
|
||||
|
||||
if not IsValid( Body ) then return end
|
||||
|
||||
if self._oldPhysRot ~= PhysRot then
|
||||
self._oldPhysTor = PhysRot
|
||||
|
||||
if PhysRot then
|
||||
Body:SetSkin( 1 )
|
||||
else
|
||||
Body:SetSkin( 0 )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnTick()
|
||||
local PhysRot = self:GetThrottle() < 0.85
|
||||
|
||||
if not self:IsEngineDestroyed() then
|
||||
self:SetRotor( PhysRot )
|
||||
end
|
||||
|
||||
self:AnimBody()
|
||||
self:BodySounds()
|
||||
end
|
||||
|
||||
function ENT:BodySounds()
|
||||
local T = CurTime()
|
||||
|
||||
if (self._nextBodySND or 0) > T then return end
|
||||
|
||||
self._nextBodySND = T + 2
|
||||
|
||||
local HP = self:GetHP()
|
||||
|
||||
if self._oldHPsnd ~= HP then
|
||||
if isnumber( self._oldHPsnd ) then
|
||||
if self._oldHPsnd > HP and math.abs(self._oldHPsnd - HP) > 100 then
|
||||
self:EmitSound("NPC_CombineGunship.Pain")
|
||||
end
|
||||
end
|
||||
|
||||
self._oldHPsnd = HP
|
||||
end
|
||||
|
||||
local trace = self:GetEyeTrace()
|
||||
|
||||
local SeeEnemy = IsValid( trace.Entity ) and trace.Entity ~= self._oldEnemySND and trace.Entity.LVS and self:IsEnemy( trace.Entity )
|
||||
|
||||
if SeeEnemy then
|
||||
self._oldEnemySND = trace.Entity
|
||||
self:EmitSound("NPC_CombineGunship.SeeEnemy")
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:AnimBody()
|
||||
local PhysObj = self:GetPhysicsObject()
|
||||
|
||||
if not IsValid( PhysObj ) then return end
|
||||
|
||||
local Body = self:GetBody()
|
||||
|
||||
if not IsValid( Body ) then return end
|
||||
|
||||
local FT = FrameTime()
|
||||
|
||||
local LocalAngles = self:WorldToLocalAngles( self:GetAimVector():Angle() )
|
||||
|
||||
local VelL = self:WorldToLocal( self:GetPos() + self:GetVelocity() )
|
||||
local AngVel = PhysObj:GetAngleVelocity()
|
||||
local Steer = self:GetSteer()
|
||||
|
||||
self._smLocalAngles = self._smLocalAngles and self._smLocalAngles + (LocalAngles - self._smLocalAngles) * FT * 4 or LocalAngles
|
||||
self._smVelL = self._smVelL and self._smVelL + (VelL - self._smVelL) * FT * 10 or VelL
|
||||
self._smAngVel = self._smAngVel and self._smAngVel + (AngVel - self._smAngVel) * FT * 10 or AngVel
|
||||
self._smSteer = self._smSteer and self._smSteer + (Steer - self._smSteer) * FT * 0.2 or Steer
|
||||
|
||||
Body:SetPoseParameter("flex_vert", self._smSteer.y * 10 + self._smLocalAngles.p * 0.5 )
|
||||
Body:SetPoseParameter("flex_horz", self._smAngVel.z * 0.25 - self._smSteer.x * 10 + self._smLocalAngles.y * 0.5 )
|
||||
Body:SetPoseParameter("fin_accel", self._smVelL.x * 0.0015 + self._smSteer.y * 2 + self._smVelL.z * 0.008 )
|
||||
Body:SetPoseParameter("fin_sway", -self._smVelL.y * 0.007 - self._smSteer.x * 5 )
|
||||
Body:SetPoseParameter("antenna_accel", self._smVelL.x * 0.005 )
|
||||
Body:SetPoseParameter("antenna_sway", -self._smVelL.y * 0.005 )
|
||||
end
|
||||
|
||||
function ENT:FireBellyCannon()
|
||||
local base = self:GetBody()
|
||||
|
||||
if not IsValid( base ) then return end
|
||||
|
||||
local Muzzle = base:GetAttachment( base:LookupAttachment( "bellygun" ) )
|
||||
|
||||
if not Muzzle then return end
|
||||
|
||||
local traceTarget = util.TraceLine( {
|
||||
start = Muzzle.Pos,
|
||||
endpos = Muzzle.Pos + base:GetAimVector() * 50000,
|
||||
filter = self:GetCrosshairFilterEnts()
|
||||
} )
|
||||
|
||||
local traceBrush = util.TraceLine( {
|
||||
start = Muzzle.Pos,
|
||||
endpos = Muzzle.Pos + base:GetAimVector() * 50000,
|
||||
mask = MASK_SOLID_BRUSHONLY,
|
||||
} )
|
||||
|
||||
local Driver = self:GetDriver()
|
||||
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker( IsValid( Driver ) and Driver or self )
|
||||
dmginfo:SetInflictor( self )
|
||||
dmginfo:SetDamage( 500 )
|
||||
dmginfo:SetDamageType( DMG_DISSOLVE )
|
||||
dmginfo:SetDamagePosition( traceBrush.HitPos )
|
||||
|
||||
util.BlastDamageInfo( dmginfo, traceBrush.HitPos, 500 )
|
||||
|
||||
local HitEnt = traceTarget.Entity
|
||||
|
||||
if not IsValid( HitEnt ) then return end
|
||||
|
||||
dmginfo:SetDamage( 5000 )
|
||||
|
||||
HitEnt:TakeDamageInfo( dmginfo )
|
||||
end
|
||||
@@ -0,0 +1,247 @@
|
||||
|
||||
ENT.Base = "lvs_base_helicopter"
|
||||
|
||||
ENT.PrintName = "Combine Gunship"
|
||||
ENT.Author = "Luna"
|
||||
ENT.Information = "Combine Synth Gunship from Half Life 2 + Episodes"
|
||||
ENT.Category = "[LVS] - Helicopters"
|
||||
|
||||
ENT.VehicleCategory = "Helicopters"
|
||||
ENT.VehicleSubCategory = "Combine"
|
||||
|
||||
ENT.Spawnable = true
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
ENT.DisableBallistics = true
|
||||
|
||||
ENT.MDL = "models/blu/combine_gunship.mdl"
|
||||
ENT.GibModels = {
|
||||
"models/gibs/gunship_gibs_engine.mdl",
|
||||
"models/gibs/gunship_gibs_eye.mdl",
|
||||
"models/gibs/gunship_gibs_headsection.mdl",
|
||||
"models/gibs/gunship_gibs_midsection.mdl",
|
||||
"models/gibs/gunship_gibs_nosegun.mdl",
|
||||
"models/gibs/gunship_gibs_sensorarray.mdl",
|
||||
"models/gibs/gunship_gibs_tailsection.mdl",
|
||||
"models/gibs/gunship_gibs_wing.mdl",
|
||||
}
|
||||
|
||||
ENT.AITEAM = 1
|
||||
|
||||
ENT.MaxHealth = 1600
|
||||
|
||||
ENT.MaxVelocity = 2150
|
||||
|
||||
ENT.ThrustUp = 1
|
||||
ENT.ThrustDown = 0.8
|
||||
ENT.ThrustRate = 1
|
||||
|
||||
ENT.ThrottleRateUp = 0.2
|
||||
ENT.ThrottleRateDown = 0.2
|
||||
|
||||
ENT.TurnRatePitch = 1
|
||||
ENT.TurnRateYaw = 1
|
||||
ENT.TurnRateRoll = 1
|
||||
|
||||
ENT.GravityTurnRateYaw = 2
|
||||
|
||||
ENT.ForceLinearDampingMultiplier = 1.5
|
||||
|
||||
ENT.ForceAngleMultiplier = 1
|
||||
ENT.ForceAngleDampingMultiplier = 1
|
||||
|
||||
ENT.EngineSounds = {
|
||||
{
|
||||
sound = "^npc/combine_gunship/engine_whine_loop1.wav",
|
||||
--sound_int = "lvs/vehicles/helicopter/loop_interior.wav",
|
||||
Pitch = 0,
|
||||
PitchMin = 0,
|
||||
PitchMax = 255,
|
||||
PitchMul = 100,
|
||||
Volume = 1,
|
||||
VolumeMin = 0,
|
||||
VolumeMax = 1,
|
||||
SoundLevel = 125,
|
||||
UseDoppler = true,
|
||||
},
|
||||
{
|
||||
sound = "npc/combine_gunship/engine_rotor_loop1.wav",
|
||||
Pitch = 0,
|
||||
PitchMin = 0,
|
||||
PitchMax = 255,
|
||||
PitchMul = 100,
|
||||
Volume = 1,
|
||||
VolumeMin = 0,
|
||||
VolumeMax = 1,
|
||||
SoundLevel = 125,
|
||||
UseDoppler = true,
|
||||
},
|
||||
}
|
||||
|
||||
function ENT:OnSetupDataTables()
|
||||
self:AddDT( "Entity", "Body" )
|
||||
end
|
||||
|
||||
function ENT:GetAimAngles()
|
||||
local Muzzle = self:GetAttachment( self:LookupAttachment( "muzzle" ) )
|
||||
|
||||
if not Muzzle then return end
|
||||
|
||||
local trace = self:GetEyeTrace()
|
||||
|
||||
local AimAngles = self:WorldToLocalAngles( (trace.HitPos - Muzzle.Pos):GetNormalized():Angle() )
|
||||
|
||||
return AimAngles
|
||||
end
|
||||
|
||||
function ENT:WeaponsInRange()
|
||||
return self:AngleBetweenNormal( self:GetForward(), self:GetAimVector() ) < 75
|
||||
end
|
||||
|
||||
function ENT:BellyInRange()
|
||||
return self:AngleBetweenNormal( -self:GetUp(), self:GetAimVector() ) < 45
|
||||
end
|
||||
|
||||
function ENT:InitWeapons()
|
||||
local weapon = {}
|
||||
weapon.Icon = Material("lvs/weapons/mg.png")
|
||||
weapon.Ammo = 2000
|
||||
weapon.Delay = 0.1
|
||||
weapon.HeatRateUp = 0.2
|
||||
weapon.HeatRateDown = 0.25
|
||||
weapon.StartAttack = function( ent )
|
||||
if not IsValid( ent.weaponSND ) then return end
|
||||
|
||||
ent.weaponSND:EmitSound("NPC_CombineGunship.CannonStartSound")
|
||||
|
||||
self.ShouldPlaySND = true
|
||||
end
|
||||
weapon.FinishAttack = function( ent )
|
||||
if not IsValid( ent.weaponSND ) then return end
|
||||
|
||||
self.ShouldPlaySND = false
|
||||
|
||||
ent.weaponSND:Stop()
|
||||
ent.weaponSND:EmitSound("NPC_CombineGunship.CannonStopSound")
|
||||
end
|
||||
weapon.Attack = function( ent )
|
||||
if not ent:WeaponsInRange() then
|
||||
|
||||
ent.ShouldPlaySND = false
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
ent.ShouldPlaySND = true
|
||||
|
||||
local Body = ent:GetBody()
|
||||
|
||||
if not IsValid( Body ) then return end
|
||||
|
||||
local Muzzle = Body:GetAttachment( Body:LookupAttachment( "muzzle" ) )
|
||||
|
||||
if not Muzzle then return end
|
||||
|
||||
local trace = ent:GetEyeTrace()
|
||||
|
||||
local bullet = {}
|
||||
bullet.Src = Muzzle.Pos
|
||||
bullet.Dir = (trace.HitPos - Muzzle.Pos):GetNormalized()
|
||||
bullet.Spread = Vector(0.02,0.02,0.02)
|
||||
bullet.TracerName = "lvs_pulserifle_tracer_large"
|
||||
bullet.Force = 2000
|
||||
bullet.HullSize = 6
|
||||
bullet.Damage = 18
|
||||
bullet.Velocity = 12000
|
||||
bullet.Attacker = self:GetDriver()
|
||||
bullet.Callback = function(att, tr, dmginfo)
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin( tr.HitPos + tr.HitNormal )
|
||||
effectdata:SetNormal( tr.HitNormal * 2 )
|
||||
effectdata:SetRadius( 10 )
|
||||
util.Effect( "cball_bounce", effectdata, true, true )
|
||||
end
|
||||
self:LVSFireBullet( bullet )
|
||||
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin( Muzzle.Pos )
|
||||
effectdata:SetNormal( Muzzle.Ang:Forward() )
|
||||
effectdata:SetEntity( ent )
|
||||
util.Effect( "lvs_pulserifle_muzzle", effectdata )
|
||||
|
||||
ent:TakeAmmo()
|
||||
end
|
||||
weapon.OnThink = function( ent, active )
|
||||
if not IsValid( ent.weaponSND ) then return end
|
||||
|
||||
local ShouldPlay = ent.ShouldPlaySND and active
|
||||
|
||||
if ent._oldShouldPlaySND ~= ShouldPlay then
|
||||
ent._oldShouldPlaySND = ShouldPlay
|
||||
if ShouldPlay then
|
||||
ent.weaponSND:Play()
|
||||
else
|
||||
ent.weaponSND:Stop()
|
||||
end
|
||||
end
|
||||
end
|
||||
weapon.OnSelect = function( ent ) ent:EmitSound("physics/metal/weapon_impact_soft3.wav") end
|
||||
self:AddWeapon( weapon )
|
||||
|
||||
local color_red = Color(255,0,0,255)
|
||||
|
||||
local weapon = {}
|
||||
weapon.Icon = Material("lvs/weapons/warplaser.png")
|
||||
weapon.Ammo = -1
|
||||
weapon.Delay = 4
|
||||
weapon.HeatRateUp = 0
|
||||
weapon.HeatRateDown = 0.05
|
||||
weapon.Attack = function( ent )
|
||||
if ent:GetAI() and not ent:BellyInRange() then return true end
|
||||
|
||||
ent:SetHeat( 100 )
|
||||
ent:SetOverheated( true )
|
||||
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin( ent:GetPos() )
|
||||
effectdata:SetEntity( ent:GetBody() )
|
||||
util.Effect( "lvs_warpcannon_charge", effectdata )
|
||||
|
||||
timer.Simple( 2, function()
|
||||
if not IsValid( ent ) then return end
|
||||
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin( ent:GetPos() )
|
||||
effectdata:SetEntity( ent:GetBody() )
|
||||
util.Effect( "lvs_warpcannon_fire", effectdata )
|
||||
|
||||
timer.Simple( 0.2, function()
|
||||
if not IsValid( ent ) then return end
|
||||
|
||||
ent:FireBellyCannon()
|
||||
end )
|
||||
end )
|
||||
end
|
||||
weapon.OnSelect = function( ent ) ent:EmitSound("physics/metal/weapon_impact_soft3.wav") end
|
||||
weapon.HudPaint = function( ent, X, Y, ply )
|
||||
local base = ent:GetBody()
|
||||
|
||||
if not IsValid( base ) then return end
|
||||
|
||||
local Muzzle = base:GetAttachment( base:LookupAttachment( "bellygun" ) )
|
||||
|
||||
if not Muzzle then return end
|
||||
|
||||
local trace = util.TraceLine( {
|
||||
start = Muzzle.Pos,
|
||||
endpos = Muzzle.Pos + base:GetAimVector() * 50000,
|
||||
mask = MASK_SOLID_BRUSHONLY
|
||||
} )
|
||||
|
||||
local Pos2D = trace.HitPos:ToScreen()
|
||||
|
||||
ent:PaintCrosshairSquare( Pos2D, ent:BellyInRange() and color_white or color_red )
|
||||
ent:LVSPaintHitMarker( Pos2D )
|
||||
end
|
||||
self:AddWeapon( weapon )
|
||||
end
|
||||
@@ -0,0 +1,79 @@
|
||||
include("shared.lua")
|
||||
|
||||
function ENT:CalcViewPassenger( ply, pos, angles, fov, pod )
|
||||
if pod == self:GetGunnerSeat() then return LVS:CalcView( self, ply, pos, angles, fov, pod ) end
|
||||
|
||||
local view = {}
|
||||
view.origin = pos
|
||||
view.angles = angles
|
||||
view.fov = fov
|
||||
view.drawviewer = false
|
||||
|
||||
local Pod = ply:GetVehicle()
|
||||
|
||||
if not IsValid( Pod ) then return view end
|
||||
|
||||
if not Pod:GetThirdPersonMode() then
|
||||
Pod:SetThirdPersonMode( true )
|
||||
end
|
||||
|
||||
local radius = 800
|
||||
|
||||
local TargetOrigin = self:LocalToWorld( Vector(0,0,50) ) - view.angles:Forward() * radius + view.angles:Up() * radius * 0.2
|
||||
local WallOffset = 4
|
||||
|
||||
local tr = util.TraceHull( {
|
||||
start = view.origin,
|
||||
endpos = TargetOrigin,
|
||||
filter = function( e )
|
||||
local c = e:GetClass()
|
||||
local collide = not c:StartWith( "prop_physics" ) and not c:StartWith( "prop_dynamic" ) and not c:StartWith( "prop_ragdoll" ) and not e:IsVehicle() and not c:StartWith( "gmod_" ) and not c:StartWith( "player" ) and not e.LVS
|
||||
|
||||
return collide
|
||||
end,
|
||||
mins = Vector( -WallOffset, -WallOffset, -WallOffset ),
|
||||
maxs = Vector( WallOffset, WallOffset, WallOffset ),
|
||||
} )
|
||||
|
||||
view.origin = tr.HitPos
|
||||
|
||||
if tr.Hit and not tr.StartSolid then
|
||||
view.origin = view.origin + tr.HitNormal * WallOffset
|
||||
end
|
||||
|
||||
return view
|
||||
end
|
||||
|
||||
function ENT:DamageFX()
|
||||
self.nextDFX = self.nextDFX or 0
|
||||
|
||||
if self.nextDFX < CurTime() then
|
||||
self.nextDFX = CurTime() + 0.05
|
||||
|
||||
local HP = self:GetHP()
|
||||
local MaxHP = self:GetMaxHP()
|
||||
|
||||
if HP > MaxHP * 0.25 then return end
|
||||
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin( self:LocalToWorld( Vector(-10,0,80) ) )
|
||||
effectdata:SetNormal( self:GetUp() )
|
||||
effectdata:SetMagnitude( math.Rand(0.5,1.5) )
|
||||
effectdata:SetEntity( self )
|
||||
util.Effect( "lvs_exhaust_fire", effectdata )
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnFrame()
|
||||
self:AnimRotor()
|
||||
self:DamageFX()
|
||||
end
|
||||
|
||||
function ENT:AnimRotor()
|
||||
local RPM = self:GetThrottle() * 2500
|
||||
|
||||
self.RPM = self.RPM and (self.RPM + RPM * RealFrameTime() * 0.5) or 0
|
||||
|
||||
self:SetPoseParameter("rotor_spin", self.RPM )
|
||||
self:InvalidateBoneCache()
|
||||
end
|
||||
@@ -0,0 +1,102 @@
|
||||
AddCSLuaFile( "shared.lua" )
|
||||
AddCSLuaFile( "cl_init.lua" )
|
||||
include("shared.lua")
|
||||
|
||||
function ENT:OnSpawn( PObj )
|
||||
local DriverSeat = self:AddDriverSeat( Vector(85,-20,-7), Angle(0,-90,10) )
|
||||
DriverSeat:SetCameraDistance( 1 )
|
||||
|
||||
local PassengerSeats = {
|
||||
{
|
||||
pos = Vector(85,20,-7),
|
||||
ang = Angle(0,-90,10)
|
||||
},
|
||||
{
|
||||
pos = Vector(30,20,0),
|
||||
ang = Angle(0,-90,0)
|
||||
},
|
||||
{
|
||||
pos = Vector(30,-20,0),
|
||||
ang = Angle(0,-90,0)
|
||||
},
|
||||
{
|
||||
pos = Vector(-20,-20,0),
|
||||
ang = Angle(0,-90,0)
|
||||
},
|
||||
{
|
||||
pos = Vector(-20,20,0),
|
||||
ang = Angle(0,-90,0)
|
||||
},
|
||||
{
|
||||
pos = Vector(-70,-20,0),
|
||||
ang = Angle(0,-90,0)
|
||||
},
|
||||
{
|
||||
pos = Vector(-70,20,0),
|
||||
ang = Angle(0,-90,0)
|
||||
},
|
||||
{
|
||||
pos = Vector(-120,-20,0),
|
||||
ang = Angle(0,-90,0)
|
||||
},
|
||||
{
|
||||
pos = Vector(-120,20,0),
|
||||
ang = Angle(0,-90,0)
|
||||
},
|
||||
}
|
||||
for num, v in pairs( PassengerSeats ) do
|
||||
local Pod = self:AddPassengerSeat( v.pos, v.ang )
|
||||
|
||||
if num == 1 then
|
||||
self:SetGunnerSeat( Pod )
|
||||
end
|
||||
end
|
||||
|
||||
self:AddEngineSound( Vector(40,0,10) )
|
||||
|
||||
--self:AddRotor( pos, angle, radius, turn_speed_and_direction )
|
||||
self.Rotor = self:AddRotor( Vector(-65,0,100), Angle(2,0,0), 390, -4000 )
|
||||
self.Rotor:SetRotorEffects( true )
|
||||
self.Rotor:SetHP( 50 )
|
||||
function self.Rotor:OnDestroyed( base )
|
||||
base:SetBodygroup( 1, 2 )
|
||||
base:DestroyEngine()
|
||||
|
||||
self:EmitSound( "physics/metal/metal_box_break2.wav" )
|
||||
end
|
||||
|
||||
self.TailRotor = self:AddRotor( Vector(-575.360840,31.147699,105.635742), Angle(0,0,90), 80, -6000 )
|
||||
self.TailRotor:SetHP( 50 )
|
||||
function self.TailRotor:OnDestroyed( base )
|
||||
base:SetBodygroup( 2, 2 )
|
||||
base:DestroySteering( 2.5 )
|
||||
|
||||
self:EmitSound( "physics/metal/metal_box_break2.wav" )
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:SetRotor( PhysRot )
|
||||
self:SetBodygroup( 1, PhysRot and 0 or 1 )
|
||||
end
|
||||
|
||||
function ENT:SetTailRotor( PhysRot )
|
||||
self:SetBodygroup( 2, PhysRot and 0 or 1 )
|
||||
end
|
||||
|
||||
function ENT:OnTick()
|
||||
local PhysRot = self:GetThrottle() < 0.85
|
||||
|
||||
if not self:IsSteeringDestroyed() then
|
||||
self:SetTailRotor( PhysRot )
|
||||
end
|
||||
|
||||
if not self:IsEngineDestroyed() then
|
||||
self:SetRotor( PhysRot )
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnEngineActiveChanged( Active )
|
||||
if Active then
|
||||
self:EmitSound( "lvs/vehicles/helicopter/start.wav" )
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,82 @@
|
||||
|
||||
ENT.Base = "lvs_base_helicopter"
|
||||
|
||||
ENT.PrintName = "Rebel Helicopter"
|
||||
ENT.Author = "Luna"
|
||||
ENT.Information = "Transport Helicopter as seen in Half Life 2 Episode 2"
|
||||
ENT.Category = "[LVS] - Helicopters"
|
||||
|
||||
ENT.VehicleCategory = "Helicopters"
|
||||
ENT.VehicleSubCategory = "Resistance"
|
||||
|
||||
ENT.Spawnable = true
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
ENT.MDL = "models/blu/helicopter.mdl"
|
||||
ENT.GibModels = {
|
||||
"models/gibs/helicopter_brokenpiece_01.mdl",
|
||||
"models/gibs/helicopter_brokenpiece_02.mdl",
|
||||
"models/gibs/helicopter_brokenpiece_03.mdl",
|
||||
"models/combine_apc_destroyed_gib02.mdl",
|
||||
"models/combine_apc_destroyed_gib04.mdl",
|
||||
"models/combine_apc_destroyed_gib05.mdl",
|
||||
"models/props_c17/trappropeller_engine.mdl",
|
||||
"models/gibs/airboat_broken_engine.mdl",
|
||||
}
|
||||
|
||||
ENT.AITEAM = 2
|
||||
|
||||
ENT.MaxHealth = 3000
|
||||
|
||||
ENT.MaxVelocity = 1500
|
||||
|
||||
ENT.ThrustUp = 1
|
||||
ENT.ThrustDown = 0.8
|
||||
ENT.ThrustRate = 1
|
||||
|
||||
ENT.ThrottleRateUp = 0.2
|
||||
ENT.ThrottleRateDown = 0.2
|
||||
|
||||
ENT.TurnRatePitch = 0.75
|
||||
ENT.TurnRateYaw = 1
|
||||
ENT.TurnRateRoll = 0.75
|
||||
|
||||
ENT.GravityTurnRateYaw = 2
|
||||
|
||||
ENT.ForceLinearDampingMultiplier = 1.5
|
||||
|
||||
ENT.ForceAngleMultiplier = 1
|
||||
ENT.ForceAngleDampingMultiplier = 1
|
||||
|
||||
ENT.EngineSounds = {
|
||||
{
|
||||
sound = "^lvs/vehicles/helicopter/loop_near.wav",
|
||||
sound_int = "lvs/vehicles/helicopter/loop_interior.wav",
|
||||
Pitch = 0,
|
||||
PitchMin = 0,
|
||||
PitchMax = 255,
|
||||
PitchMul = 100,
|
||||
Volume = 1,
|
||||
VolumeMin = 0,
|
||||
VolumeMax = 1,
|
||||
SoundLevel = 125,
|
||||
UseDoppler = true,
|
||||
},
|
||||
{
|
||||
sound = "^lvs/vehicles/helicopter/loop_dist.wav",
|
||||
sound_int = "",
|
||||
Pitch = 0,
|
||||
PitchMin = 0,
|
||||
PitchMax = 255,
|
||||
PitchMul = 100,
|
||||
Volume = 1,
|
||||
VolumeMin = 0,
|
||||
VolumeMax = 1,
|
||||
SoundLevel = 125,
|
||||
UseDoppler = true,
|
||||
},
|
||||
}
|
||||
|
||||
function ENT:OnSetupDataTables()
|
||||
self:AddDT( "Entity", "GunnerSeat" )
|
||||
end
|
||||
Reference in New Issue
Block a user