Files
wnsrc/lua/simfphys_weapons/tankweapons_leopard.lua
lifestorm 9c918c46e5 Upload
2024-08-04 23:12:27 +03:00

540 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/
--]]
local leopard_susdata = {}
for i = 1,7 do
leopard_susdata[i] = {
attachment = "sus_left_attach_"..i,
poseparameter = "suspension_left_"..i,
}
local ir = i + 7
leopard_susdata[ir] = {
attachment = "sus_right_attach_"..i,
poseparameter = "suspension_right_"..i,
}
end
local function hmg_fire(ply,vehicle,shootOrigin,shootDirection)
vehicle:EmitSound("leopard_fire_mg")
local projectile = {}
projectile.filter = vehicle.VehicleData["filter"]
projectile.shootOrigin = shootOrigin
projectile.shootDirection = shootDirection
projectile.attacker = ply
projectile.Tracer = 1
projectile.HullSize = 6
projectile.attackingent = vehicle
projectile.Spread = Vector(0.01,0.01,0.01)
projectile.Damage = 25
projectile.Force = 12
simfphys.FireHitScan( projectile )
end
local function mg_fire(ply,vehicle,shootOrigin,shootDirection)
vehicle:EmitSound("tiger_fire_mg_new")
local projectile = {}
projectile.filter = vehicle.VehicleData["filter"]
projectile.shootOrigin = shootOrigin
projectile.shootDirection = shootDirection
projectile.attacker = ply
projectile.Tracer = 1
projectile.HullSize = 5
projectile.attackingent = vehicle
projectile.Spread = Vector(0.008,0.008,0.008)
projectile.Damage = 20
projectile.Force = 12
simfphys.FireHitScan( projectile )
end
local function cannon_fire(ply,vehicle,shootOrigin,shootDirection)
vehicle:EmitSound("leopard_fire")
vehicle:EmitSound("sherman_reload")
timer.Simple( 4, function()
if IsValid( vehicle ) then
vehicle:EmitSound("simulated_vehicles/weapons/leopard_ready.wav")
end
end)
local effectdata = EffectData()
effectdata:SetEntity( vehicle )
util.Effect( "simfphys_leopard_muzzle", effectdata )
vehicle:GetPhysicsObject():ApplyForceOffset( -shootDirection * 500000, shootOrigin )
local projectile = {}
projectile.filter = vehicle.VehicleData["filter"]
projectile.shootOrigin = shootOrigin
projectile.shootDirection = shootDirection
projectile.attacker = ply
projectile.attackingent = vehicle
projectile.Damage = 3500
projectile.Force = 8000
projectile.Size = 15
projectile.DeflectAng = 20
projectile.BlastRadius = 300
projectile.BlastDamage = 1000
projectile.BlastEffect = "simfphys_tankweapon_explosion"
simfphys.FirePhysProjectile( projectile )
end
function simfphys.weapon:ValidClasses()
return { "sim_fphys_tank3" }
end
function simfphys.weapon:Initialize( vehicle )
vehicle:SetNWBool( "SpecialCam_Loader", true )
vehicle:SetNWFloat( "SpecialCam_LoaderTime", 4.5 )
simfphys.RegisterCrosshair( vehicle:GetDriverSeat(), { Attachment = "cannon_muzzle", Type = 4 } )
simfphys.RegisterCamera( vehicle:GetDriverSeat(), Vector(-30,-20,-12), Vector(-25,50,110), true, "cannon_mg_muzzle" )
if not istable( vehicle.PassengerSeats ) or not istable( vehicle.pSeat ) then return end
simfphys.RegisterCrosshair( vehicle.pSeat[1] , { Attachment = "mg_muzzle", Type = 5 } )
simfphys.RegisterCamera( vehicle.pSeat[1], Vector(-80,-15,0), Vector(0,0,60), true, "mg_muzzle" )
simfphys.RegisterCamera( vehicle.pSeat[2], Vector(0,0,25), Vector(0,0,25), false )
simfphys.RegisterCamera( vehicle.pSeat[3], Vector(0,0,25), Vector(0,0,25), false )
timer.Simple( 1, function()
if not IsValid( vehicle ) then return end
if not vehicle.VehicleData["filter"] then print("[simfphys Armed Vehicle Pack] ERROR:TRACE FILTER IS INVALID. PLEASE UPDATE SIMFPHYS BASE") return end
vehicle.WheelOnGround = function( ent )
ent.FrontWheelPowered = ent:GetPowerDistribution() ~= 1
ent.RearWheelPowered = ent:GetPowerDistribution() ~= -1
for i = 1, table.Count( ent.Wheels ) do
local Wheel = ent.Wheels[i]
if IsValid( Wheel ) then
local dmgMul = Wheel:GetDamaged() and 0.5 or 1
local surfacemul = simfphys.TractionData[Wheel:GetSurfaceMaterial():lower()]
ent.VehicleData[ "SurfaceMul_" .. i ] = (surfacemul and math.max(surfacemul,0.001) or 1) * dmgMul
local WheelPos = ent:LogicWheelPos( i )
local WheelRadius = WheelPos.IsFrontWheel and ent.FrontWheelRadius or ent.RearWheelRadius
local startpos = Wheel:GetPos()
local dir = -ent.Up
local len = WheelRadius + math.Clamp(-ent.Vel.z / 50,2.5,6)
local HullSize = Vector(WheelRadius,WheelRadius,0)
local tr = util.TraceHull( {
start = startpos,
endpos = startpos + dir * len,
maxs = HullSize,
mins = -HullSize,
filter = ent.VehicleData["filter"]
} )
local onground = self:IsOnGround( vehicle ) and 1 or 0
Wheel:SetOnGround( onground )
ent.VehicleData[ "onGround_" .. i ] = onground
if tr.Hit then
Wheel:SetSpeed( Wheel.FX )
Wheel:SetSkidSound( Wheel.skid )
Wheel:SetSurfaceMaterial( util.GetSurfacePropName( tr.SurfaceProps ) )
end
end
end
local FrontOnGround = math.max(ent.VehicleData[ "onGround_1" ],ent.VehicleData[ "onGround_2" ])
local RearOnGround = math.max(ent.VehicleData[ "onGround_3" ],ent.VehicleData[ "onGround_4" ])
ent.DriveWheelsOnGround = math.max(ent.FrontWheelPowered and FrontOnGround or 0,ent.RearWheelPowered and RearOnGround or 0)
end
end)
end
function simfphys.weapon:GetForwardSpeed( vehicle )
return vehicle.ForwardSpeed
end
function simfphys.weapon:IsOnGround( vehicle )
return (vehicle.susOnGround == true)
end
function simfphys.weapon:AimMachinegun( ply, vehicle, pod )
if not IsValid( pod ) then return end
local Aimang = pod:WorldToLocalAngles( ply:EyeAngles() )
local AimRate = 250
local Angles = vehicle:WorldToLocalAngles( Aimang )
vehicle.sm_ppmg_yaw = vehicle.sm_ppmg_yaw and math.ApproachAngle( vehicle.sm_ppmg_yaw, Angles.y, AimRate * FrameTime() ) or 90
vehicle.sm_ppmg_pitch = vehicle.sm_ppmg_pitch and math.ApproachAngle( vehicle.sm_ppmg_pitch, Angles.p, AimRate * FrameTime() ) or 0
local TargetAng = Angle(vehicle.sm_ppmg_pitch,vehicle.sm_ppmg_yaw,0)
TargetAng:Normalize()
vehicle.sm_pp_yaw = vehicle.sm_pp_yaw or 90
vehicle:SetPoseParameter("mg_aim_yaw", TargetAng.y - vehicle.sm_pp_yaw )
vehicle:SetPoseParameter("mg_aim_pitch", -TargetAng.p )
end
function simfphys.weapon:AimCannon( ply, vehicle, pod, Attachment )
if not IsValid( pod ) then return end
local Aimang = pod:WorldToLocalAngles( ply:EyeAngles() )
Aimang:Normalize()
local AimRate = 60
local Angles = vehicle:WorldToLocalAngles( Aimang )
vehicle.sm_pp_yaw = vehicle.sm_pp_yaw and math.ApproachAngle( vehicle.sm_pp_yaw, Angles.y, AimRate * FrameTime() ) or 90
vehicle.sm_pp_pitch = vehicle.sm_pp_pitch and math.ApproachAngle( vehicle.sm_pp_pitch, Angles.p, AimRate * FrameTime() ) or 0
local TargetAng = Angle(vehicle.sm_pp_pitch,vehicle.sm_pp_yaw,0)
TargetAng:Normalize()
vehicle:SetPoseParameter("cannon_aim_yaw", TargetAng.y - 90 )
local pclamp = math.Clamp( (math.cos( math.rad(TargetAng.y + 90) ) - 0.7) * 6,0,1) ^ 2 * 15
vehicle:SetPoseParameter("cannon_aim_pitch", math.Clamp(-TargetAng.p,-15 + pclamp,20) )
end
function simfphys.weapon:ControlTurret( vehicle, deltapos )
if not istable( vehicle.PassengerSeats ) or not istable( vehicle.pSeat ) then return end
local pod = vehicle:GetDriverSeat()
if not IsValid( pod ) then return end
local ply = pod:GetDriver()
if not IsValid( ply ) then return end
local safemode = ply:KeyDown( IN_WALK )
if vehicle.ButtonSafeMode ~= safemode then
vehicle.ButtonSafeMode = safemode
if safemode then
vehicle:SetNWBool( "TurretSafeMode", not vehicle:GetNWBool( "TurretSafeMode", true ) )
if vehicle:GetNWBool( "TurretSafeMode" ) then
vehicle:EmitSound( "vehicles/tank_turret_stop1.wav")
else
vehicle:EmitSound( "vehicles/tank_readyfire1.wav")
end
end
end
if vehicle:GetNWBool( "TurretSafeMode", true ) then return end
local ID = vehicle:LookupAttachment( "cannon_muzzle" )
local Attachment = vehicle:GetAttachment( ID )
self:AimCannon( ply, vehicle, pod, Attachment )
local DeltaP = deltapos * engine.TickInterval()
local fire = ply:KeyDown( IN_ATTACK )
local fire2 = ply:KeyDown( IN_ATTACK2 )
if fire then
self:PrimaryAttack( vehicle, ply, Attachment.Pos + DeltaP, Attachment )
end
local Rate = FrameTime() / 5
vehicle.smTmpHMG = vehicle.smTmpHMG and vehicle.smTmpHMG + math.Clamp((fire2 and 1 or 0) - vehicle.smTmpHMG,-Rate * 6,Rate) or 0
if fire2 then
self:SecondaryAttack( vehicle, ply, DeltaP, Attachment.Pos, Attachment.Ang )
end
end
function simfphys.weapon:ControlMachinegun( vehicle, deltapos )
if not istable( vehicle.PassengerSeats ) or not istable( vehicle.pSeat ) then return end
local pod = vehicle.pSeat[1]
if not IsValid( pod ) then return end
local ply = pod:GetDriver()
if not IsValid( ply ) then return end
self:AimMachinegun( ply, vehicle, pod )
local ID = vehicle:LookupAttachment( "mg_muzzle" )
local Attachment = vehicle:GetAttachment( ID )
local shootOrigin = Attachment.Pos + deltapos * engine.TickInterval()
local fire = ply:KeyDown( IN_ATTACK )
local Rate = FrameTime() / 5
vehicle.smTmpMG = vehicle.smTmpMG and vehicle.smTmpMG + math.Clamp((fire and 1 or 0) - vehicle.smTmpMG,-Rate * 6,Rate) or 0
if fire then
self:Attack( vehicle, ply, shootOrigin, Attachment, ID )
end
end
function simfphys.weapon:Attack( vehicle, ply, shootOrigin, Attachment, ID )
if not self:CanAttack( vehicle ) then return end
local shootDirection = Attachment.Ang:Forward()
hmg_fire( ply, vehicle, shootOrigin, shootDirection )
self:SetNextFire( vehicle, CurTime() + 0.1 + (vehicle.smTmpMG ^ 5) * 0.05 )
end
function simfphys.weapon:CanAttack( vehicle )
vehicle.NextShoot3 = vehicle.NextShoot3 or 0
return vehicle.NextShoot3 < CurTime()
end
function simfphys.weapon:SetNextFire( vehicle, time )
vehicle.NextShoot3 = time
end
function simfphys.weapon:PrimaryAttack( vehicle, ply, shootOrigin, Attachment )
if not self:CanPrimaryAttack( vehicle ) then return end
local shootDirection = Attachment.Ang:Forward()
vehicle:PlayAnimation( "fire" )
cannon_fire( ply, vehicle, shootOrigin + shootDirection * 80, shootDirection )
self:SetNextPrimaryFire( vehicle, CurTime() + 4.5 )
end
function simfphys.weapon:CanPrimaryAttack( vehicle )
vehicle.NextShoot = vehicle.NextShoot or 0
return vehicle.NextShoot < CurTime()
end
function simfphys.weapon:SetNextPrimaryFire( vehicle, time )
vehicle.NextShoot = time
vehicle:SetNWFloat( "SpecialCam_LoaderNext", time )
end
function simfphys.weapon:SecondaryAttack( vehicle, ply, deltapos, cPos, cAng )
if not self:CanSecondaryAttack( vehicle ) then return end
local ID = vehicle:LookupAttachment( "cannon_mg_muzzle" )
local Attachment = vehicle:GetAttachment( ID )
local trace = util.TraceLine( {
start = cPos,
endpos = cPos + cAng:Forward() * 50000,
filter = vehicle.VehicleData["filter"]
} )
mg_fire( ply, vehicle, Attachment.Pos, (trace.HitPos - Attachment.Pos):GetNormalized() )
self:SetNextSecondaryFire( vehicle, CurTime() + 0.07 + (vehicle.smTmpHMG ^ 5) * 0.08 )
end
function simfphys.weapon:CanSecondaryAttack( vehicle )
vehicle.NextShoot2 = vehicle.NextShoot2 or 0
return vehicle.NextShoot2 < CurTime()
end
function simfphys.weapon:SetNextSecondaryFire( vehicle, time )
vehicle.NextShoot2 = time
end
function simfphys.weapon:ModPhysics( vehicle, wheelslocked )
if wheelslocked and self:IsOnGround( vehicle ) then
local phys = vehicle:GetPhysicsObject()
phys:ApplyForceCenter( -vehicle:GetVelocity() * phys:GetMass() * 0.04 )
end
end
function simfphys.weapon:ControlTrackSounds( vehicle, wheelslocked )
local speed = math.abs( self:GetForwardSpeed( vehicle ) )
local fastenuf = speed > 20 and not wheelslocked and self:IsOnGround( vehicle )
if fastenuf ~= vehicle.fastenuf then
vehicle.fastenuf = fastenuf
if fastenuf then
vehicle.track_snd = CreateSound( vehicle, "simulated_vehicles/leopard/tracks.wav" )
vehicle.track_snd:PlayEx(0,0)
vehicle:CallOnRemove( "stopmesounds", function( vehicle )
if vehicle.track_snd then
vehicle.track_snd:Stop()
end
end)
else
if vehicle.track_snd then
vehicle.track_snd:Stop()
vehicle.track_snd = nil
end
end
end
if vehicle.track_snd then
vehicle.track_snd:ChangePitch( math.Clamp(70 + speed / 40,0,150) )
vehicle.track_snd:ChangeVolume( math.min( math.max(speed - 20,0) / 200,1) )
end
end
function simfphys.weapon:ControlPassengerSeats( vehicle )
if not vehicle.pSeat then return end
vehicle.sm_pp_yaw = vehicle.sm_pp_yaw and vehicle.sm_pp_yaw or 90
vehicle.sm_pp_pitch = vehicle.sm_pp_pitch and vehicle.sm_pp_pitch or 0
do
local Commander = vehicle.pSeat[2]
if IsValid( Commander ) then
local ply = Commander:GetDriver()
local Toggle = false
if IsValid( ply ) then
Toggle = ply:KeyDown( IN_JUMP )
end
if Toggle ~= vehicle.OldToggleC then
vehicle.OldToggleC = Toggle
if Toggle then
vehicle.tg_c_z = not vehicle.tg_c_z
if vehicle.tg_c_z then
vehicle:EmitSound( "vehicles/atv_ammo_open.wav" )
simfphys.RegisterCamera( Commander, Vector(0,0,0), Vector(0,0,0), false )
else
vehicle:EmitSound( "vehicles/atv_ammo_close.wav" )
simfphys.RegisterCamera( Commander, Vector(0,0,25), Vector(0,0,25), false )
end
end
end
local X = math.sin( math.rad( -vehicle.sm_pp_yaw - 25 ) ) * 27
local Y = math.cos( math.rad( -vehicle.sm_pp_yaw - 25 ) ) * 27
Commander:SetLocalPos( Vector(X,Y,50 + (vehicle.tg_c_z and 25 or 0)) )
Commander:SetLocalAngles( Angle(0,vehicle.sm_pp_yaw - 90,0) )
end
end
do
local Loader = vehicle.pSeat[3]
if IsValid( Loader ) then
local ply = Loader:GetDriver()
local Toggle = false
if IsValid( ply ) then
Toggle = ply:KeyDown( IN_JUMP )
end
if Toggle ~= vehicle.OldToggleL then
vehicle.OldToggleL = Toggle
if Toggle then
vehicle.tg_l_z = not vehicle.tg_l_z
if vehicle.tg_l_z then
vehicle:EmitSound( "vehicles/atv_ammo_open.wav" )
simfphys.RegisterCamera( Loader, Vector(0,0,0), Vector(0,0,0), false )
else
vehicle:EmitSound( "vehicles/atv_ammo_close.wav" )
simfphys.RegisterCamera( Loader, Vector(0,0,25), Vector(0,0,25), false )
end
end
end
local X = math.sin( math.rad( -vehicle.sm_pp_yaw - 160 ) ) * 27
local Y = math.cos( math.rad( -vehicle.sm_pp_yaw - 160 ) ) * 27
Loader:SetLocalPos( Vector(X,Y,50 + (vehicle.tg_l_z and 25 or 0)) )
Loader:SetLocalAngles( Angle(0,vehicle.sm_pp_yaw - 90,0) )
end
end
end
function simfphys.weapon:Think( vehicle )
if not IsValid( vehicle ) or not vehicle:IsInitialized() then return end
vehicle.wOldPos = vehicle.wOldPos or Vector(0,0,0)
local deltapos = vehicle:GetPos() - vehicle.wOldPos
vehicle.wOldPos = vehicle:GetPos()
local handbrake = vehicle:GetHandBrakeEnabled()
self:ControlPassengerSeats( vehicle )
self:UpdateSuspension( vehicle )
self:DoWheelSpin( vehicle )
self:ControlTurret( vehicle, deltapos )
self:ControlMachinegun( vehicle, deltapos )
self:ControlTrackSounds( vehicle, handbrake )
self:ModPhysics( vehicle, handbrake )
end
function simfphys.weapon:UpdateSuspension( vehicle )
if not vehicle.filterEntities then
vehicle.filterEntities = player.GetAll()
table.insert(vehicle.filterEntities, vehicle)
for i, wheel in pairs( ents.FindByClass( "gmod_sent_vehicle_fphysics_wheel" ) ) do
table.insert(vehicle.filterEntities, wheel)
end
end
vehicle.oldDist = istable( vehicle.oldDist ) and vehicle.oldDist or {}
vehicle.susOnGround = false
local Up = vehicle:GetUp()
for i, v in pairs( leopard_susdata ) do
local pos = vehicle:GetAttachment( vehicle:LookupAttachment( leopard_susdata[i].attachment ) ).Pos + Up * 10
local trace = util.TraceHull( {
start = pos,
endpos = pos + Up * - 100,
maxs = Vector(10,10,0),
mins = -Vector(10,10,0),
filter = vehicle.filterEntities,
} )
local Dist = (pos - trace.HitPos):Length() - 38
if trace.Hit then
vehicle.susOnGround = true
end
vehicle.oldDist[i] = vehicle.oldDist[i] and (vehicle.oldDist[i] + math.Clamp(Dist - vehicle.oldDist[i],-5,1)) or 0
vehicle:SetPoseParameter(leopard_susdata[i].poseparameter, vehicle.oldDist[i] )
end
end
function simfphys.weapon:DoWheelSpin( vehicle )
local spin_r = (vehicle.VehicleData[ "spin_4" ] + vehicle.VehicleData[ "spin_6" ]) * 1.75
local spin_l = (vehicle.VehicleData[ "spin_3" ] + vehicle.VehicleData[ "spin_5" ]) * 1.75
net.Start( "simfphys_update_tracks", true )
net.WriteEntity( vehicle )
net.WriteFloat( spin_r )
net.WriteFloat( spin_l )
net.Broadcast()
vehicle:SetPoseParameter("spin_wheels_right", spin_r)
vehicle:SetPoseParameter("spin_wheels_left", spin_l )
end