mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
1429 lines
38 KiB
Lua
1429 lines
38 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" )
|
|
AddCSLuaFile( "cl_init.lua" )
|
|
AddCSLuaFile( "cl_tiresounds.lua" )
|
|
include("shared.lua")
|
|
include("spawn.lua")
|
|
include("simfunc.lua")
|
|
include("numpads.lua")
|
|
include("damage.lua")
|
|
|
|
function ENT:AlignView( ply )
|
|
if not IsValid( ply ) then return end
|
|
|
|
timer.Simple( 0, function()
|
|
if not IsValid( ply ) or not IsValid( self ) then return end
|
|
|
|
local Ang = Angle(0,90,0)
|
|
|
|
local pod = ply:GetVehicle()
|
|
local MouseAim = ply:lvsMouseAim() and self:GetDriver() == ply
|
|
|
|
if MouseAim and IsValid( pod ) then
|
|
Ang = pod:LocalToWorldAngles( Angle(0,90,0) )
|
|
Ang.r = 0
|
|
end
|
|
|
|
ply:SetEyeAngles( Ang )
|
|
end)
|
|
end
|
|
|
|
function ENT:TakeCollisionDamage( damage, attacker )
|
|
end
|
|
|
|
local function EntityLookup(CreatedEntities)
|
|
return function(id, default)
|
|
if id == nil then return default end
|
|
if id == 0 then return game.GetWorld() end
|
|
local ent = CreatedEntities[id] or (isnumber(id) and ents.GetByIndex(id))
|
|
if IsValid(ent) then return ent else return default end
|
|
end
|
|
end
|
|
|
|
function ENT:ApplyDupeInfo(ply, ent, info, GetEntByID)
|
|
if istable( WireLib ) then
|
|
WireLib.ApplyDupeInfo(ply, ent, info, GetEntByID)
|
|
end
|
|
end
|
|
|
|
function ENT:PreEntityCopy()
|
|
if istable( WireLib ) then
|
|
duplicator.StoreEntityModifier( self, "WireDupeInfo", WireLib.BuildDupeInfo(self) )
|
|
end
|
|
end
|
|
|
|
function ENT:PostEntityPaste(Player,Ent,CreatedEntities)
|
|
if istable( WireLib ) then
|
|
if Ent.EntityMods and Ent.EntityMods.WireDupeInfo then
|
|
WireLib.ApplyDupeInfo(Player, Ent, Ent.EntityMods.WireDupeInfo, EntityLookup(CreatedEntities))
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:OnSpawn()
|
|
end
|
|
|
|
function ENT:OnTick()
|
|
end
|
|
|
|
function ENT:OnDelete()
|
|
end
|
|
|
|
function ENT:OnDestroyed()
|
|
end
|
|
|
|
function ENT:OnRepaired()
|
|
end
|
|
|
|
function ENT:Think()
|
|
local Time = CurTime()
|
|
|
|
self:PhysicsThink()
|
|
self:OnTick()
|
|
|
|
hook.Run( "simfphysOnTick", self, Time )
|
|
|
|
self.NextTick = self.NextTick or 0
|
|
if self.NextTick < Time then
|
|
self.NextTick = Time + 0.025
|
|
|
|
if IsValid( self.DriverSeat ) then
|
|
local Driver = self.DriverSeat:GetDriver()
|
|
Driver = IsValid( self.RemoteDriver ) and self.RemoteDriver or Driver
|
|
|
|
local OldDriver = self:GetDriver()
|
|
if OldDriver ~= Driver then
|
|
if self:GetlvsLockedStatus() then
|
|
self:UnLock()
|
|
end
|
|
|
|
self:SetDriver( Driver )
|
|
|
|
local HadDriver = IsValid( OldDriver )
|
|
local HasDriver = IsValid( Driver )
|
|
|
|
if HasDriver then
|
|
self:SetActive( true )
|
|
self:SetupControls( Driver )
|
|
|
|
if Driver:GetInfoNum( "cl_simfphys_autostart", 1 ) > 0 then
|
|
self:StartEngine()
|
|
end
|
|
|
|
else
|
|
if self.ems then
|
|
self.ems:Stop()
|
|
end
|
|
|
|
if self.horn then
|
|
self.horn:Stop()
|
|
end
|
|
|
|
if self.PressedKeys then
|
|
for k,v in pairs( self.PressedKeys ) do
|
|
if isbool( v ) then
|
|
self.PressedKeys[k] = false
|
|
end
|
|
end
|
|
end
|
|
|
|
if self.keys then
|
|
for i = 1, table.Count( self.keys ) do
|
|
numpad.Remove( self.keys[i] )
|
|
end
|
|
end
|
|
|
|
if HadDriver then
|
|
if OldDriver:GetInfoNum( "cl_simfphys_autostart", 1 ) > 0 then
|
|
self:StopEngine()
|
|
self:SetActive( false )
|
|
else
|
|
self:ResetJoystick()
|
|
|
|
if not self:EngineActive() then
|
|
self:SetActive( false )
|
|
end
|
|
end
|
|
else
|
|
self:SetActive( false )
|
|
self:StopEngine()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if self:IsInitialized() then
|
|
self:SetColors()
|
|
self:SimulateVehicle( Time )
|
|
self:ControlLighting( Time )
|
|
self:ControlHorn()
|
|
|
|
if istable( WireLib ) then
|
|
self:UpdateWireOutputs()
|
|
end
|
|
|
|
self.NextWaterCheck = self.NextWaterCheck or 0
|
|
if self.NextWaterCheck < Time then
|
|
self.NextWaterCheck = Time + 0.2
|
|
self:WaterPhysics()
|
|
end
|
|
|
|
if self:GetActive() then
|
|
self:SetPhysics( ((math.abs(self.ForwardSpeed) < 50) and (self.Brake > 0 or self.HandBrake > 0)) )
|
|
else
|
|
self:SetPhysics( true )
|
|
end
|
|
end
|
|
end
|
|
|
|
self:NextThink( Time )
|
|
|
|
return true
|
|
end
|
|
|
|
function ENT:ControlHorn()
|
|
local HornVol = self.HornKeyIsDown and 1 or 0
|
|
self.HornVolume = self.HornVolume and self.HornVolume + math.Clamp(HornVol - self.HornVolume,-0.45,0.8) or 0
|
|
|
|
if self.horn then
|
|
if self.HornVolume <= 0 then
|
|
if self.horn then
|
|
self.horn:Stop()
|
|
self.horn = nil
|
|
end
|
|
else
|
|
self.horn:ChangeVolume( self.HornVolume ^ 2 )
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:createWireIO()
|
|
self.Inputs = WireLib.CreateInputs( self,{"Eject Driver","Eject Passengers","Lock","Engine Start","Engine Stop","Engine Toggle","Steer","Throttle","Gear Up","Gear Down","Set Gear","Clutch","Handbrake","Brake/Reverse"} )
|
|
--self.Inputs = WireLib.CreateSpecialInputs(self, { "blah" }, { "NORMAL" })
|
|
|
|
self.Outputs = WireLib.CreateSpecialOutputs( self,
|
|
{ "Active","Health","RPM","Torque","DriverSeat","PassengerSeats","Driver","Gear","Ratio","Lights Enabled","Highbeams Enabled","Foglights Enabled","Sirens Enabled","Turn Signals Enabled","Remaining Fuel" },
|
|
{ "NORMAL","NORMAL","NORMAL","NORMAL","ENTITY","ARRAY","ENTITY","NORMAL","NORMAL","NORMAL","NORMAL","NORMAL","NORMAL","NORMAL","NORMAL" }
|
|
)
|
|
end
|
|
|
|
function ENT:TriggerInput( name, value )
|
|
if name == "Engine Start" then
|
|
if value >= 1 then
|
|
self:SetActive( true )
|
|
self:StartEngine()
|
|
end
|
|
end
|
|
|
|
if name == "Engine Stop" then
|
|
if value >= 1 then
|
|
self:SetActive( false )
|
|
self:StopEngine()
|
|
end
|
|
end
|
|
|
|
if name == "Engine Toggle" then
|
|
if value >= 1 then
|
|
if self:GetActive() then
|
|
if not self:EngineActive() then
|
|
self:StartEngine()
|
|
else
|
|
self:StopEngine()
|
|
self:SetActive( false )
|
|
end
|
|
else
|
|
self:SetActive( true )
|
|
self:StartEngine()
|
|
end
|
|
end
|
|
end
|
|
|
|
if name == "Lock" then
|
|
if value >= 1 then
|
|
self:Lock()
|
|
else
|
|
self:UnLock()
|
|
end
|
|
end
|
|
|
|
if name == "Eject Driver" then
|
|
local Driver = self:GetDriver()
|
|
if IsValid( Driver ) then
|
|
Driver:ExitVehicle()
|
|
end
|
|
end
|
|
|
|
if name == "Eject Passengers" then
|
|
if istable( self.pSeat ) then
|
|
for i = 1, table.Count( self.pSeat ) do
|
|
if IsValid( self.pSeat[i] ) then
|
|
|
|
local Driver = self.pSeat[i]:GetDriver()
|
|
|
|
if IsValid( Driver ) then
|
|
Driver:ExitVehicle()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if name == "Steer" then
|
|
self:SteerVehicle( math.Clamp( value, -1 , 1) * self.VehicleData["steerangle"] )
|
|
for i = 1, table.Count(self.Wheels) do
|
|
local Wheel = self.Wheels[i]
|
|
if IsValid( Wheel ) then
|
|
Wheel:PhysWake()
|
|
end
|
|
end
|
|
end
|
|
|
|
if name == "Throttle" then
|
|
self.PressedKeys["joystick_throttle"] = math.Clamp( value, 0, 1 )
|
|
end
|
|
|
|
if name == "Brake/Reverse" then
|
|
self.PressedKeys["joystick_brake"] = math.Clamp( value, 0, 1 )
|
|
end
|
|
|
|
if name == "Gear Up" then
|
|
if value >= 1 then
|
|
self.CurrentGear = math.Clamp(self.CurrentGear + 1,1,table.Count( self.Gears ) )
|
|
self:SetGear( self.CurrentGear )
|
|
end
|
|
end
|
|
|
|
if name == "Gear Down" then
|
|
if value >= 1 then
|
|
self.CurrentGear = math.Clamp(self.CurrentGear - 1,1,table.Count( self.Gears ) )
|
|
self:SetGear( self.CurrentGear )
|
|
end
|
|
end
|
|
|
|
if name == "Set Gear" then
|
|
self:ForceGear( math.Round( value, 0 ) )
|
|
end
|
|
|
|
if name == "Clutch" then
|
|
self.PressedKeys["joystick_clutch"] = math.Clamp( value, 0, 1 )
|
|
end
|
|
|
|
if name == "Handbrake" then
|
|
self.PressedKeys["joystick_handbrake"] = (value > 0) and 1 or 0
|
|
end
|
|
end
|
|
|
|
function ENT:ForceGear( desGear )
|
|
self.CurrentGear = math.Clamp( math.Round( desGear, 0 ),1,table.Count( self.Gears ) )
|
|
self:SetGear( self.CurrentGear )
|
|
end
|
|
|
|
function ENT:UpdateWireOutputs()
|
|
WireLib.TriggerOutput(self, "Active", self:EngineActive() and 1 or 0 )
|
|
WireLib.TriggerOutput(self, "Health", self:GetCurHealth() )
|
|
|
|
WireLib.TriggerOutput(self, "Driver", self:GetDriver() )
|
|
WireLib.TriggerOutput(self, "Torque", self.Torque )
|
|
WireLib.TriggerOutput(self, "RPM", self:GetEngineRPM() )
|
|
|
|
WireLib.TriggerOutput(self, "Gear", self:GetGear() )
|
|
WireLib.TriggerOutput(self, "Ratio",self:GetGear() == 2 and 0 or (self.GearRatio or 0) )
|
|
|
|
WireLib.TriggerOutput(self, "Lights Enabled", self:GetLightsEnabled() and 1 or 0 )
|
|
WireLib.TriggerOutput(self, "Highbeams Enabled", self:GetLampsEnabled() and 1 or 0 )
|
|
WireLib.TriggerOutput(self, "Foglights Enabled", self:GetFogLightsEnabled() and 1 or 0 )
|
|
WireLib.TriggerOutput(self, "Sirens Enabled", self:GetEMSEnabled() and 1 or 0 )
|
|
WireLib.TriggerOutput(self, "Turn Signals Enabled", self:GetTSEnabled())
|
|
WireLib.TriggerOutput(self, "Remaining Fuel", self:GetFuel())
|
|
end
|
|
|
|
function ENT:OnActiveChanged( name, old, new)
|
|
if new == old then return end
|
|
|
|
if not self:IsInitialized() then return end
|
|
|
|
local TurboCharged = self:GetTurboCharged()
|
|
local SuperCharged = self:GetSuperCharged()
|
|
|
|
if new == true then
|
|
|
|
self.HandBrakePower = self:GetMaxTraction() + 20 - self:GetTractionBias() * self:GetMaxTraction()
|
|
|
|
if self:GetEMSEnabled() then
|
|
if self.ems then
|
|
self.ems:Play()
|
|
end
|
|
end
|
|
|
|
if TurboCharged then
|
|
self.Turbo = CreateSound(self, self.snd_spool or "simulated_vehicles/turbo_spin.wav")
|
|
self.Turbo:PlayEx(0,0)
|
|
end
|
|
|
|
if SuperCharged then
|
|
self.Blower = CreateSound(self, self.snd_bloweroff or "simulated_vehicles/blower_spin.wav")
|
|
self.BlowerWhine = CreateSound(self, self.snd_bloweron or "simulated_vehicles/blower_gearwhine.wav")
|
|
|
|
self.Blower:PlayEx(0,0)
|
|
self.BlowerWhine:PlayEx(0,0)
|
|
end
|
|
else
|
|
self:StopEngine()
|
|
|
|
if TurboCharged then
|
|
self.Turbo:Stop()
|
|
end
|
|
|
|
if SuperCharged then
|
|
self.Blower:Stop()
|
|
self.BlowerWhine:Stop()
|
|
end
|
|
|
|
self:SetIsBraking( false )
|
|
end
|
|
|
|
if istable( self.Wheels ) then
|
|
for i = 1, table.Count( self.Wheels ) do
|
|
local Wheel = self.Wheels[ i ]
|
|
if IsValid(Wheel) then
|
|
Wheel:SetOnGround( 0 )
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:OnHealthChanged( name, OldHealth, NewHealth)
|
|
if NewHealth == OldHealth or NewHealth < OldHealth then return end
|
|
|
|
local MaxHealth = self:GetMaxHealth()
|
|
|
|
if NewHealth > (MaxHealth * 0.6) then
|
|
self:SetOnFire( false )
|
|
self:SetOnSmoke( false )
|
|
end
|
|
|
|
if NewHealth > (MaxHealth * 0.3) then
|
|
self:SetOnFire( false )
|
|
if NewHealth <= (MaxHealth * 0.6) then
|
|
self:SetOnSmoke( true )
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:OnThrottleChanged( name, old, new)
|
|
if new == old then return end
|
|
|
|
local Health = self:GetCurHealth()
|
|
local MaxHealth = self:GetMaxHealth()
|
|
local Active = self:EngineActive()
|
|
|
|
if new == 1 then
|
|
if Health < MaxHealth * 0.6 then
|
|
if Active then
|
|
if math.Round(math.random(0,4),0) == 1 then
|
|
self:DamagedStall()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if new == 0 then
|
|
if self:GetTurboCharged() then
|
|
if (self.SmoothTurbo > 350) then
|
|
local Volume = math.Clamp( ((self.SmoothTurbo - 300) / 150) ,0, 1) * 0.5
|
|
self.SmoothTurbo = 0
|
|
self.BlowOff:Stop()
|
|
self.BlowOff = CreateSound(self, self.snd_blowoff or "simulated_vehicles/turbo_blowoff.ogg")
|
|
self.BlowOff:PlayEx(Volume,100)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:WaterPhysics()
|
|
if self:WaterLevel() <= 1 then self.IsInWater = false return end
|
|
|
|
if self:GetDoNotStall() then
|
|
|
|
self:SetOnFire( false )
|
|
self:SetOnSmoke( false )
|
|
|
|
return
|
|
end
|
|
|
|
if not self.IsInWater then
|
|
if self:EngineActive() then
|
|
self:EmitSound( "vehicles/jetski/jetski_off.wav" )
|
|
end
|
|
|
|
self.IsInWater = true
|
|
self.EngineIsOn = 0
|
|
self.EngineRPM = 0
|
|
self:SetFlyWheelRPM( 0 )
|
|
|
|
self:SetOnFire( false )
|
|
self:SetOnSmoke( false )
|
|
end
|
|
|
|
local phys = self:GetPhysicsObject()
|
|
phys:ApplyForceCenter( -self:GetVelocity() * 0.5 * phys:GetMass() )
|
|
end
|
|
|
|
function ENT:SetColors()
|
|
if self.ColorableProps then
|
|
|
|
local Color = self:GetColor()
|
|
local dot = Color.r * Color.g * Color.b * Color.a
|
|
|
|
if dot ~= self.OldColor then
|
|
|
|
for i, prop in pairs( self.ColorableProps ) do
|
|
if IsValid(prop) then
|
|
prop:SetColor( Color )
|
|
prop:SetRenderMode( self:GetRenderMode() )
|
|
end
|
|
end
|
|
|
|
self.OldColor = dot
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:ControlLighting( curtime )
|
|
if (self.NextLightCheck or 0) < curtime then
|
|
|
|
if self.LightsActivated ~= self.DoCheck then
|
|
self.DoCheck = self.LightsActivated
|
|
|
|
if self.LightsActivated then
|
|
self:SetLightsEnabled(true)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:SetTSInternal(mode)
|
|
self.TSMode = mode
|
|
end
|
|
|
|
function ENT:GetTSEnabled()
|
|
if self.TSMode != nil then return self.TSMode else return 0 end
|
|
end
|
|
|
|
function ENT:GetEngineData()
|
|
local LimitRPM = math.max(self:GetLimitRPM(),4)
|
|
local Powerbandend = math.Clamp(self:GetPowerBandEnd(),3,LimitRPM - 1)
|
|
local Powerbandstart = math.Clamp(self:GetPowerBandStart(),2,Powerbandend - 1)
|
|
local IdleRPM = math.Clamp(self:GetIdleRPM(),1,Powerbandstart - 1)
|
|
local Data = {
|
|
IdleRPM = IdleRPM,
|
|
Powerbandstart = Powerbandstart,
|
|
Powerbandend = Powerbandend,
|
|
LimitRPM = LimitRPM,
|
|
}
|
|
return Data
|
|
end
|
|
|
|
function ENT:SimulateVehicle( curtime )
|
|
local Active = self:GetActive()
|
|
|
|
local EngineData = self:GetEngineData()
|
|
|
|
local LimitRPM = EngineData.LimitRPM
|
|
local Powerbandend = EngineData.Powerbandend
|
|
local Powerbandstart = EngineData.Powerbandstart
|
|
local IdleRPM = EngineData.IdleRPM
|
|
|
|
self.Forward = self:LocalToWorldAngles( self.VehicleData.LocalAngForward ):Forward()
|
|
self.Right = self:LocalToWorldAngles( self.VehicleData.LocalAngRight ):Forward()
|
|
self.Up = self:GetUp()
|
|
|
|
self.Vel = self:GetVelocity()
|
|
self.VelNorm = self.Vel:GetNormalized()
|
|
|
|
self.MoveDir = math.acos( math.Clamp( self.Forward:Dot(self.VelNorm) ,-1,1) ) * (180 / math.pi)
|
|
self.ForwardSpeed = math.cos(self.MoveDir * (math.pi / 180)) * self.Vel:Length()
|
|
|
|
if self.poseon then
|
|
self.cpose = self.cpose or self.LightsPP.min
|
|
local anglestep = math.abs(math.max(self.LightsPP.max or self.LightsPP.min)) / 3
|
|
self.cpose = self.cpose + math.Clamp(self.poseon - self.cpose,-anglestep,anglestep)
|
|
self:SetPoseParameter(self.LightsPP.name, self.cpose)
|
|
end
|
|
|
|
self:SetPoseParameter("vehicle_guage", (math.abs(self.ForwardSpeed) * 0.0568182 * 0.75) / (self.SpeedoMax or 120))
|
|
|
|
if self.RPMGaugePP then
|
|
local flywheelrpm = self:GetFlyWheelRPM()
|
|
local rpm
|
|
if self:GetRevlimiter() then
|
|
local throttle = self:GetThrottle()
|
|
local maxrpm = self:GetLimitRPM()
|
|
local revlimiter = (maxrpm > 2500) and (throttle > 0)
|
|
rpm = math.Round(((flywheelrpm >= maxrpm - 200) and revlimiter) and math.Round(flywheelrpm - 200 + math.sin(curtime * 50) * 600,0) or flywheelrpm,0)
|
|
else
|
|
rpm = flywheelrpm
|
|
end
|
|
|
|
self:SetPoseParameter(self.RPMGaugePP, rpm / self.RPMGaugeMax)
|
|
end
|
|
|
|
|
|
if Active then
|
|
local ply = self:GetDriver()
|
|
local IsValidDriver = IsValid( ply )
|
|
|
|
local GearUp = self.PressedKeys["M1"] and 1 or self.PressedKeys["joystick_gearup"]
|
|
local GearDown = self.PressedKeys["M2"] and 1 or self.PressedKeys["joystick_geardown"]
|
|
|
|
local W = self.PressedKeys["W"] and 1 or 0
|
|
local A = self.PressedKeys["A"] and 1 or self.PressedKeys["joystick_steer_left"]
|
|
local S = self.PressedKeys["S"] and 1 or 0
|
|
local D = self.PressedKeys["D"] and 1 or self.PressedKeys["joystick_steer_right"]
|
|
|
|
if IsValidDriver then self:PlayerSteerVehicle( ply, A, D ) end
|
|
|
|
local aW = self.PressedKeys["aW"] and 1 or self.PressedKeys["joystick_air_w"]
|
|
local aA = self.PressedKeys["aA"] and 1 or self.PressedKeys["joystick_air_a"]
|
|
local aS = self.PressedKeys["aS"] and 1 or self.PressedKeys["joystick_air_s"]
|
|
local aD = self.PressedKeys["aD"] and 1 or self.PressedKeys["joystick_air_d"]
|
|
|
|
local cruise = self:GetIsCruiseModeOn()
|
|
|
|
local k_sanic = IsValidDriver and ply:GetInfoNum( "cl_simfphys_sanic", 0 ) or 1
|
|
local sanicmode = isnumber( k_sanic ) and k_sanic or 0
|
|
local k_Shift = self.PressedKeys["Shift"]
|
|
local Shift = (sanicmode == 1) and (k_Shift and 0 or 1) or (k_Shift and 1 or 0)
|
|
|
|
local sportsmode = IsValidDriver and ply:GetInfoNum( "cl_simfphys_sport", 0 ) or 1
|
|
local k_auto = IsValidDriver and ply:GetInfoNum( "cl_simfphys_auto", 0 ) or 1
|
|
local transmode = (k_auto == 1)
|
|
|
|
local Alt = self.PressedKeys["Alt"] and 1 or 0
|
|
local Space = self.PressedKeys["Space"] and 1 or self.PressedKeys["joystick_handbrake"]
|
|
|
|
if cruise then
|
|
if (self.PressedKeys["joystick_gearup"] + self.PressedKeys["joystick_geardown"] + self.PressedKeys["joystick_handbrake"] + self.PressedKeys["joystick_throttle"] + self.PressedKeys["joystick_clutch"] + self.PressedKeys["joystick_brake"]) > 0 then
|
|
self:SetIsCruiseModeOn( false )
|
|
end
|
|
|
|
if k_Shift then
|
|
self.cc_speed = math.Round(self:GetVelocity():Length(),0) + 70
|
|
end
|
|
if Alt == 1 then
|
|
self.cc_speed = math.Round(self:GetVelocity():Length(),0) - 25
|
|
end
|
|
end
|
|
|
|
self:SimulateTransmission(W,S,Shift,Alt,Space,GearUp,GearDown,transmode,IdleRPM,Powerbandstart,Powerbandend,sportsmode,cruise,curtime)
|
|
|
|
self:SimulateEngine( IdleRPM, LimitRPM, Powerbandstart, Powerbandend, curtime )
|
|
self:SimulateWheels( math.max(Space,Alt), LimitRPM )
|
|
self:SimulateAirControls( aW, aS, aA, aD )
|
|
|
|
if self.WheelOnGroundDelay < curtime then
|
|
self:WheelOnGround()
|
|
self.WheelOnGroundDelay = curtime + 0.15
|
|
end
|
|
else
|
|
self:SetWheelVelocity( 0 )
|
|
|
|
for i = 1, table.Count( self.Wheels ) do
|
|
local Wheel = self.Wheels[i]
|
|
|
|
if not IsValid( Wheel ) or Wheel:GetRPM() == 0 then continue end
|
|
|
|
Wheel:SetRPM( 0 )
|
|
end
|
|
end
|
|
|
|
if self.CustomWheels then
|
|
self:PhysicalSteer()
|
|
end
|
|
end
|
|
|
|
function ENT:SetupControls( ply )
|
|
self:ResetJoystick()
|
|
|
|
if self.keys then
|
|
for i = 1, table.Count( self.keys ) do
|
|
numpad.Remove( self.keys[i] )
|
|
end
|
|
end
|
|
|
|
if IsValid(ply) then
|
|
self.cl_SteerSettings = {
|
|
Overwrite = (ply:GetInfoNum( "cl_simfphys_overwrite", 0 ) >= 1),
|
|
TurnSpeed = ply:GetInfoNum( "cl_simfphys_steerspeed", 8 ),
|
|
fadespeed = ply:GetInfoNum( "cl_simfphys_fadespeed", 535 ),
|
|
fastspeedangle = ply:GetInfoNum( "cl_simfphys_steerangfast", 10 ),
|
|
smoothsteer = (ply:GetInfoNum( "cl_simfphys_smoothsteer", 0 ) >= 1),
|
|
}
|
|
|
|
local W = ply:GetInfoNum( "cl_simfphys_keyforward", 0 )
|
|
local A = ply:GetInfoNum( "cl_simfphys_keyleft", 0 )
|
|
local S = ply:GetInfoNum( "cl_simfphys_keyreverse", 0 )
|
|
local D = ply:GetInfoNum( "cl_simfphys_keyright", 0 )
|
|
|
|
local aW = ply:GetInfoNum( "cl_simfphys_key_air_forward", 0 )
|
|
local aA = ply:GetInfoNum( "cl_simfphys_key_air_left", 0 )
|
|
local aS = ply:GetInfoNum( "cl_simfphys_key_air_reverse", 0 )
|
|
local aD = ply:GetInfoNum( "cl_simfphys_key_air_right", 0 )
|
|
|
|
local GearUp = ply:GetInfoNum( "cl_simfphys_keygearup", 0 )
|
|
local GearDown = ply:GetInfoNum( "cl_simfphys_keygeardown", 0 )
|
|
|
|
local R = ply:GetInfoNum( "cl_simfphys_cruisecontrol", 0 )
|
|
|
|
local F = ply:GetInfoNum( "cl_simfphys_lights", 0 )
|
|
|
|
local V = ply:GetInfoNum( "cl_simfphys_foglights", 0 )
|
|
|
|
local H = ply:GetInfoNum( "cl_simfphys_keyhorn", 0 )
|
|
|
|
local I = ply:GetInfoNum( "cl_simfphys_keyengine", 0 )
|
|
|
|
local Shift = ply:GetInfoNum( "cl_simfphys_keywot", 0 )
|
|
|
|
local Alt = ply:GetInfoNum( "cl_simfphys_keyclutch", 0 )
|
|
local Space = ply:GetInfoNum( "cl_simfphys_keyhandbrake", 0 )
|
|
|
|
local lock = ply:GetInfoNum( "cl_simfphys_key_lock", 0 )
|
|
|
|
local w_dn = numpad.OnDown( ply, W, "k_forward",self, true )
|
|
local w_up = numpad.OnUp( ply, W, "k_forward",self, false )
|
|
local s_dn = numpad.OnDown( ply, S, "k_reverse",self, true )
|
|
local s_up = numpad.OnUp( ply, S, "k_reverse",self, false )
|
|
local a_dn = numpad.OnDown( ply, A, "k_left",self, true )
|
|
local a_up = numpad.OnUp( ply, A, "k_left",self, false )
|
|
local d_dn = numpad.OnDown( ply, D, "k_right",self, true )
|
|
local d_up = numpad.OnUp( ply, D, "k_right",self, false )
|
|
|
|
local aw_dn = numpad.OnDown( ply, aW, "k_a_forward",self, true )
|
|
local aw_up = numpad.OnUp( ply, aW, "k_a_forward",self, false )
|
|
local as_dn = numpad.OnDown( ply, aS, "k_a_reverse",self, true )
|
|
local as_up = numpad.OnUp( ply, aS, "k_a_reverse",self, false )
|
|
local aa_dn = numpad.OnDown( ply, aA, "k_a_left",self, true )
|
|
local aa_up = numpad.OnUp( ply, aA, "k_a_left",self, false )
|
|
local ad_dn = numpad.OnDown( ply, aD, "k_a_right",self, true )
|
|
local ad_up = numpad.OnUp( ply, aD, "k_a_right",self, false )
|
|
|
|
local gup_dn = numpad.OnDown( ply, GearUp, "k_gup",self, true )
|
|
local gup_up = numpad.OnUp( ply, GearUp, "k_gup",self, false )
|
|
|
|
local gdn_dn = numpad.OnDown( ply, GearDown, "k_gdn",self, true )
|
|
local gdn_up = numpad.OnUp( ply, GearDown, "k_gdn",self, false )
|
|
|
|
local shift_dn = numpad.OnDown( ply, Shift, "k_wot",self, true )
|
|
local shift_up = numpad.OnUp( ply, Shift, "k_wot",self, false )
|
|
|
|
local alt_dn = numpad.OnDown( ply, Alt, "k_clutch",self, true )
|
|
local alt_up = numpad.OnUp( ply, Alt, "k_clutch",self, false )
|
|
|
|
local space_dn = numpad.OnDown( ply, Space, "k_hbrk",self, true )
|
|
local space_up = numpad.OnUp( ply, Space, "k_hbrk",self, false )
|
|
|
|
local k_cruise = numpad.OnDown( ply, R, "k_ccon",self, true )
|
|
|
|
local k_lights_dn = numpad.OnDown( ply, F, "k_lgts",self, true )
|
|
local k_lights_up = numpad.OnUp( ply, F, "k_lgts",self, false )
|
|
|
|
local k_flights_dn = numpad.OnDown( ply, V, "k_flgts",self, true )
|
|
local k_flights_up = numpad.OnUp( ply, V, "k_flgts",self, false )
|
|
|
|
local k_horn_dn = numpad.OnDown( ply, H, "k_hrn",self, true )
|
|
local k_horn_up = numpad.OnUp( ply, H, "k_hrn",self, false )
|
|
|
|
local k_engine_dn = numpad.OnDown( ply, I, "k_eng",self, true )
|
|
local k_engine_up = numpad.OnUp( ply, I, "k_eng",self, false )
|
|
|
|
self.keys = {
|
|
w_dn,w_up,
|
|
s_dn,s_up,
|
|
a_dn,a_up,
|
|
d_dn,d_up,
|
|
aw_dn,aw_up,
|
|
as_dn,as_up,
|
|
aa_dn,aa_up,
|
|
ad_dn,ad_up,
|
|
gup_dn,gup_up,
|
|
gdn_dn,gdn_up,
|
|
shift_dn,shift_up,
|
|
alt_dn,alt_up,
|
|
space_dn,space_up,
|
|
k_cruise,
|
|
k_lights_dn,k_lights_up,
|
|
k_horn_dn,k_horn_up,
|
|
k_flights_dn,k_flights_up,
|
|
k_engine_dn,k_engine_up,
|
|
}
|
|
end
|
|
end
|
|
|
|
function ENT:PhysicalSteer()
|
|
|
|
if IsValid(self.SteerMaster) then
|
|
local physobj = self.SteerMaster:GetPhysicsObject()
|
|
if not IsValid(physobj) then return end
|
|
|
|
if physobj:IsMotionEnabled() then
|
|
physobj:EnableMotion(false)
|
|
end
|
|
|
|
self.SteerMaster:SetAngles( self:LocalToWorldAngles( Angle(0,math.Clamp(-self.VehicleData[ "Steer" ],-self.CustomSteerAngle,self.CustomSteerAngle),0) ) )
|
|
end
|
|
|
|
if IsValid(self.SteerMaster2) then
|
|
local physobj = self.SteerMaster2:GetPhysicsObject()
|
|
if not IsValid(physobj) then return end
|
|
|
|
if physobj:IsMotionEnabled() then
|
|
physobj:EnableMotion(false)
|
|
end
|
|
|
|
self.SteerMaster2:SetAngles( self:LocalToWorldAngles( Angle(0,math.Clamp(self.VehicleData[ "Steer" ],-self.CustomSteerAngle,self.CustomSteerAngle),0) ) )
|
|
end
|
|
end
|
|
|
|
function ENT:EngineActive()
|
|
return (self.EngineIsOn == 1)
|
|
end
|
|
|
|
function ENT:IsDriveWheelsOnGround()
|
|
return (self.DriveWheelsOnGround == 1)
|
|
end
|
|
|
|
function ENT:GetRPM()
|
|
local RPM = self.EngineRPM and self.EngineRPM or 0
|
|
return RPM
|
|
end
|
|
|
|
function ENT:GetEngineRPM()
|
|
local flywheelrpm = self:GetRPM()
|
|
local rpm
|
|
if self:GetRevlimiter() then
|
|
local throttle = self:GetThrottle()
|
|
local maxrpm = self:GetLimitRPM()
|
|
local revlimiter = (maxrpm > 2500) and (throttle > 0)
|
|
rpm = math.Round(((flywheelrpm >= maxrpm - 200) and revlimiter) and math.Round(flywheelrpm - 200 + math.sin(CurTime()* 50) * 600,0) or flywheelrpm,0)
|
|
else
|
|
rpm = flywheelrpm
|
|
end
|
|
|
|
return rpm
|
|
end
|
|
|
|
function ENT:GetDiffGear()
|
|
return math.max(self:GetDifferentialGear(),0.01)
|
|
end
|
|
|
|
function ENT:DamagedStall()
|
|
if not self:GetActive() then return end
|
|
|
|
local rtimer = 0.8
|
|
|
|
timer.Simple( rtimer, function()
|
|
if not IsValid( self ) then return end
|
|
net.Start( "simfphys_backfire" )
|
|
net.WriteEntity( self )
|
|
net.Broadcast()
|
|
end)
|
|
|
|
self:StallAndRestart( rtimer, true )
|
|
end
|
|
|
|
function ENT:StopEngine()
|
|
if self:EngineActive() then
|
|
|
|
if hook.Run( "simfphysOnEngine", self, false, bIgnoreSettings ) then return end
|
|
|
|
self:EmitSound( "vehicles/jetski/jetski_off.wav" )
|
|
|
|
self.EngineRPM = 0
|
|
self.EngineIsOn = 0
|
|
|
|
self:SetFlyWheelRPM( 0 )
|
|
self:SetIsCruiseModeOn( false )
|
|
end
|
|
end
|
|
|
|
function ENT:CanStart()
|
|
local FuelSystemOK = true
|
|
|
|
if simfphys.Fuel then
|
|
FuelSystemOK = self:GetFuel() > 0
|
|
end
|
|
|
|
local canstart = self:GetCurHealth() > (self:GetMaxHealth() * 0.1) and FuelSystemOK
|
|
|
|
return canstart
|
|
end
|
|
|
|
function ENT:StartEngine( bIgnoreSettings )
|
|
if not self:CanStart() then return end
|
|
|
|
if not self:EngineActive() then
|
|
|
|
if hook.Run( "simfphysOnEngine", self, true, bIgnoreSettings ) then return end
|
|
|
|
if not bIgnoreSettings then
|
|
self.CurrentGear = 2
|
|
end
|
|
|
|
if not self.IsInWater then
|
|
self.EngineRPM = self:GetEngineData().IdleRPM
|
|
self.EngineIsOn = 1
|
|
else
|
|
if self:GetDoNotStall() then
|
|
self.EngineRPM = self:GetEngineData().IdleRPM
|
|
self.EngineIsOn = 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:StallAndRestart( nTimer, bIgnoreSettings )
|
|
nTimer = nTimer or 1
|
|
|
|
self:StopEngine()
|
|
|
|
local ply = self:GetDriver()
|
|
if IsValid(ply) and not bIgnoreSettings then
|
|
if ply:GetInfoNum( "cl_simfphys_autostart", 1 ) <= 0 then return end
|
|
end
|
|
|
|
timer.Simple( nTimer, function()
|
|
if not IsValid(self) then return end
|
|
self:StartEngine( bIgnoreSettings )
|
|
end)
|
|
end
|
|
|
|
function ENT:PlayerSteerVehicle( ply, left, right )
|
|
if IsValid( ply ) then
|
|
local CounterSteeringEnabled = (ply:GetInfoNum( "cl_simfphys_ctenable", 0 ) or 1) == 1
|
|
local CounterSteeringMul = math.Clamp(ply:GetInfoNum( "cl_simfphys_ctmul", 0 ) or 0.7,0.1,2)
|
|
local MaxHelpAngle = math.Clamp(ply:GetInfoNum( "cl_simfphys_ctang", 0 ) or 15,1,90)
|
|
|
|
local Ang = self.MoveDir
|
|
|
|
local TurnSpeed
|
|
local fadespeed
|
|
local fastspeedangle
|
|
local extrasmooth = false
|
|
|
|
if istable(self.cl_SteerSettings) and self.cl_SteerSettings.Overwrite then
|
|
TurnSpeed = self.cl_SteerSettings.TurnSpeed
|
|
fadespeed = self.cl_SteerSettings.fadespeed
|
|
fastspeedangle = self.cl_SteerSettings.fastspeedangle
|
|
extrasmooth = self.cl_SteerSettings.smoothsteer
|
|
else
|
|
TurnSpeed = self:GetSteerSpeed()
|
|
fadespeed = self:GetFastSteerConeFadeSpeed()
|
|
fastspeedangle = self:GetFastSteerAngle() * self.VehicleData["steerangle"]
|
|
end
|
|
|
|
local SlowSteeringRate = (Ang > 20) and ((math.Clamp((self.ForwardSpeed - 150) / 25,0,1) == 1) and 60 or self.VehicleData["steerangle"]) or self.VehicleData["steerangle"]
|
|
local FastSteeringAngle = math.Clamp(fastspeedangle,1,SlowSteeringRate)
|
|
|
|
local FastSteeringRate = FastSteeringAngle + ((Ang > (FastSteeringAngle-1)) and 1 or 0) * math.min(Ang,90 - FastSteeringAngle)
|
|
|
|
local Ratio = 1 - math.Clamp((math.abs(self.ForwardSpeed) - fadespeed) / 25,0,1)
|
|
|
|
local SteerRate = FastSteeringRate + (SlowSteeringRate - FastSteeringRate) * Ratio
|
|
local Steer = ((left + right) > 0 and (right - left) or self:GetMouseSteer()) * SteerRate
|
|
|
|
local LocalDrift = math.acos( math.Clamp( self.Right:Dot(self.VelNorm) ,-1,1) ) * (180 / math.pi) - 90
|
|
|
|
local CounterSteer = CounterSteeringEnabled and (math.Clamp(LocalDrift * CounterSteeringMul * (((left + right) == 0) and 1 or 0),-MaxHelpAngle,MaxHelpAngle) * ((self.ForwardSpeed > 50) and 1 or 0)) or 0
|
|
|
|
local Rate = extrasmooth and math.max( (math.abs(self.SmoothAng) / self.VehicleData["steerangle"]) ^ 1.5 * TurnSpeed, math.max(1 - self.ForwardSpeed / 2000,0.05) ) or TurnSpeed
|
|
|
|
self.SmoothAng = self.SmoothAng + math.Clamp((Steer - CounterSteer) - self.SmoothAng,-Rate,Rate)
|
|
|
|
self:SteerVehicle( self.SmoothAng )
|
|
end
|
|
end
|
|
|
|
function ENT:SteerVehicle( steer )
|
|
self.VehicleData[ "Steer" ] = steer
|
|
self:SetVehicleSteer( steer / self.VehicleData["steerangle"] )
|
|
end
|
|
|
|
function ENT:ForceLightsOff()
|
|
local vehiclelist = list.Get( "simfphys_lights" )[self.LightsTable] or false
|
|
if not vehiclelist then return end
|
|
|
|
if vehiclelist.Animation then
|
|
if self.LightsActivated then
|
|
self.LightsActivated = false
|
|
self.LampsActivated = false
|
|
|
|
self:SetLightsEnabled(false)
|
|
self:SetLampsEnabled(false)
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:EnteringSequence( ply )
|
|
local LinkedDoorAnims = istable(self.ModelInfo) and istable(self.ModelInfo.LinkDoorAnims)
|
|
if not istable(self.Enterpoints) and not LinkedDoorAnims then return end
|
|
|
|
local sequence
|
|
local pos
|
|
local dist
|
|
|
|
if LinkedDoorAnims then
|
|
for i,_ in pairs( self.ModelInfo.LinkDoorAnims ) do
|
|
local seq_ = self.ModelInfo.LinkDoorAnims[ i ].enter
|
|
|
|
local a_pos = self:GetAttachment( self:LookupAttachment( i ) ).Pos
|
|
local a_dist = (ply:GetPos() - a_pos):Length()
|
|
|
|
if not sequence then
|
|
sequence = seq_
|
|
pos = a_pos
|
|
dist = a_dist
|
|
else
|
|
if a_dist < dist then
|
|
sequence = seq_
|
|
pos = a_pos
|
|
dist = a_dist
|
|
end
|
|
end
|
|
end
|
|
else
|
|
for i = 1, table.Count( self.Enterpoints ) do
|
|
local a_ = self.Enterpoints[ i ]
|
|
|
|
local a_pos = self:GetAttachment( self:LookupAttachment( a_ ) ).Pos
|
|
local a_dist = (ply:GetPos() - a_pos):Length()
|
|
|
|
if i == 1 then
|
|
sequence = a_
|
|
pos = a_pos
|
|
dist = a_dist
|
|
else
|
|
if (a_dist < dist) then
|
|
sequence = a_
|
|
pos = a_pos
|
|
dist = a_dist
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
self:PlayAnimation( sequence )
|
|
self:ForceLightsOff()
|
|
end
|
|
|
|
function ENT:GetMouseSteer()
|
|
local Driver = self:GetDriver()
|
|
|
|
if not IsValid( Driver ) or not Driver.lvsMouseAim or not Driver:lvsMouseAim() then return 0 end
|
|
|
|
local TargetAngle = Driver:EyeAngles()
|
|
|
|
local pod = self:GetDriverSeat()
|
|
|
|
if not IsValid( pod ) then return end
|
|
|
|
local ang = self:GetAngles()
|
|
ang.y = pod:GetAngles().y + 90
|
|
|
|
local Forward = ang:Right()
|
|
local View = pod:WorldToLocalAngles( TargetAngle ):Forward()
|
|
|
|
local Reversed = false
|
|
if self:AngleBetweenNormal( View, ang:Forward() ) < 90 then
|
|
Reversed = self:GetGear() == 1
|
|
end
|
|
|
|
local LocalAngSteer = (self:AngleBetweenNormal( View, ang:Right() ) - 90) / self.MouseSteerAngle
|
|
|
|
local Steer = (math.min( math.abs( LocalAngSteer ), 1 ) ^ self.MouseSteerExponent * self:Sign( LocalAngSteer ))
|
|
|
|
return -Steer
|
|
end
|
|
|
|
function ENT:SetPhysics( enable )
|
|
if enable then
|
|
if not self.PhysicsEnabled then
|
|
for i = 1, table.Count( self.Wheels ) do
|
|
local Wheel = self.Wheels[i]
|
|
if IsValid(Wheel) then
|
|
Wheel:GetPhysicsObject():SetMaterial("jeeptire")
|
|
end
|
|
end
|
|
self.PhysicsEnabled = true
|
|
end
|
|
else
|
|
if self.PhysicsEnabled ~= false then
|
|
for i = 1, table.Count( self.Wheels ) do
|
|
local Wheel = self.Wheels[i]
|
|
if IsValid(Wheel) then
|
|
Wheel:GetPhysicsObject():SetMaterial("friction_00")
|
|
if Wheel:GetPhysicsObject():GetMaterial() ~= "friction_00" then
|
|
print("(SIMFPHYS) ERROR! MISSING ''friction_00'' PHYSPROP-MATERIAL!!! THIS SHOULD NEVER HAPPEN!! CLEAN YOUR GMOD!! DON'T USE CONTENT OF GAMES YOU DON'T OWN!! DON'T EVEN BOTHER REPORTING THIS ISSUE, BECAUSE ONLY YOU CAN FIX THIS AS THIS IS AN ISSUE WITH YOUR GAME!!!!")
|
|
sound.Play( "common/bugreporter_failed.wav", self:GetPos() )
|
|
self:Remove()
|
|
|
|
break
|
|
end
|
|
end
|
|
end
|
|
self.PhysicsEnabled = false
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:SetSuspension( index , bIsDamaged )
|
|
local bIsDamaged = bIsDamaged or false
|
|
|
|
local h_mod = index <= 2 and self:GetFrontSuspensionHeight() or self:GetRearSuspensionHeight()
|
|
|
|
local heights = {
|
|
[1] = self.FrontHeight + self.VehicleData.suspensiontravel_fl * -h_mod,
|
|
[2] = self.FrontHeight + self.VehicleData.suspensiontravel_fr * -h_mod,
|
|
[3] = self.RearHeight + self.VehicleData.suspensiontravel_rl * -h_mod,
|
|
[4] = self.RearHeight + self.VehicleData.suspensiontravel_rr * -h_mod,
|
|
[5] = self.RearHeight + self.VehicleData.suspensiontravel_rl * -h_mod,
|
|
[6] = self.RearHeight + self.VehicleData.suspensiontravel_rr * -h_mod
|
|
}
|
|
local Wheel = self.Wheels[index]
|
|
if not IsValid(Wheel) then return end
|
|
|
|
local subRadius = bIsDamaged and Wheel.dRadius or 0
|
|
|
|
local newheight = heights[index] + subRadius
|
|
|
|
local Elastic = self.Elastics[index]
|
|
if IsValid(Elastic) then
|
|
Elastic:Fire( "SetSpringLength", newheight )
|
|
end
|
|
|
|
if self.StrengthenSuspension == true then
|
|
local Elastic2 = self.Elastics[index * 10]
|
|
if IsValid(Elastic2) then
|
|
Elastic2:Fire( "SetSpringLength", newheight )
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:OnFrontSuspensionHeightChanged( name, old, new )
|
|
if old == new then return end
|
|
if not self.CustomWheels and new > 0 then new = 0 end
|
|
if not self:IsInitialized() then return end
|
|
|
|
if IsValid(self.Wheels[1]) then
|
|
local Elastic = self.Elastics[1]
|
|
if IsValid(Elastic) then
|
|
Elastic:Fire( "SetSpringLength", self.FrontHeight + self.VehicleData.suspensiontravel_fl * -new )
|
|
end
|
|
|
|
if self.StrengthenSuspension == true then
|
|
|
|
local Elastic2 = self.Elastics[10]
|
|
|
|
if IsValid(Elastic2) then
|
|
Elastic2:Fire( "SetSpringLength", self.FrontHeight + self.VehicleData.suspensiontravel_fl * -new )
|
|
end
|
|
end
|
|
end
|
|
|
|
if IsValid(self.Wheels[2]) then
|
|
local Elastic = self.Elastics[2]
|
|
if IsValid(Elastic) then
|
|
Elastic:Fire( "SetSpringLength", self.FrontHeight + self.VehicleData.suspensiontravel_fr * -new )
|
|
end
|
|
|
|
if self.StrengthenSuspension == true then
|
|
|
|
local Elastic2 = self.Elastics[20]
|
|
|
|
if (IsValid(Elastic2)) then
|
|
Elastic2:Fire( "SetSpringLength", self.FrontHeight + self.VehicleData.suspensiontravel_fr * -new )
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:OnRearSuspensionHeightChanged( name, old, new )
|
|
if old == new then return end
|
|
if not self.CustomWheels and new > 0 then new = 0 end
|
|
if not self:IsInitialized() then return end
|
|
|
|
if IsValid(self.Wheels[3]) then
|
|
local Elastic = self.Elastics[3]
|
|
if IsValid(Elastic) then
|
|
Elastic:Fire( "SetSpringLength", self.RearHeight + self.VehicleData.suspensiontravel_rl * -new )
|
|
end
|
|
|
|
if self.StrengthenSuspension == true then
|
|
|
|
local Elastic2 = self.Elastics[30]
|
|
|
|
if IsValid(Elastic2) then
|
|
Elastic2:Fire( "SetSpringLength", self.RearHeight + self.VehicleData.suspensiontravel_rl * -new )
|
|
end
|
|
end
|
|
end
|
|
|
|
if IsValid(self.Wheels[4]) then
|
|
local Elastic = self.Elastics[4]
|
|
if IsValid(Elastic) then
|
|
Elastic:Fire( "SetSpringLength", self.RearHeight + self.VehicleData.suspensiontravel_rr * -new )
|
|
end
|
|
|
|
if self.StrengthenSuspension == true then
|
|
|
|
local Elastic2 = self.Elastics[40]
|
|
|
|
if IsValid(Elastic2) then
|
|
Elastic2:Fire( "SetSpringLength", self.RearHeight + self.VehicleData.suspensiontravel_rr * -new )
|
|
end
|
|
end
|
|
end
|
|
|
|
if IsValid(self.Wheels[5]) then
|
|
local Elastic = self.Elastics[5]
|
|
if IsValid(Elastic) then
|
|
Elastic:Fire( "SetSpringLength", self.RearHeight + self.VehicleData.suspensiontravel_rl * -new )
|
|
end
|
|
|
|
if self.StrengthenSuspension == true then
|
|
|
|
local Elastic2 = self.Elastics[50]
|
|
|
|
if IsValid(Elastic2) then
|
|
Elastic2:Fire( "SetSpringLength", self.RearHeight + self.VehicleData.suspensiontravel_rl * -new )
|
|
end
|
|
end
|
|
end
|
|
|
|
if IsValid(self.Wheels[6]) then
|
|
local Elastic = self.Elastics[6]
|
|
if IsValid(Elastic) then
|
|
Elastic:Fire( "SetSpringLength", self.RearHeight + self.VehicleData.suspensiontravel_rr * -new )
|
|
end
|
|
|
|
if self.StrengthenSuspension == true then
|
|
|
|
local Elastic2 = self.Elastics[60]
|
|
|
|
if IsValid(Elastic2) then
|
|
Elastic2:Fire( "SetSpringLength", self.RearHeight + self.VehicleData.suspensiontravel_rr * -new )
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:OnTurboCharged( name, old, new )
|
|
if old == new then return end
|
|
local Active = self:GetActive()
|
|
|
|
if new == true and Active then
|
|
self.Turbo:Stop()
|
|
self.Turbo = CreateSound(self, self.snd_spool or "simulated_vehicles/turbo_spin.wav")
|
|
self.Turbo:PlayEx(0,0)
|
|
|
|
elseif new == false then
|
|
if self.Turbo then
|
|
self.Turbo:Stop()
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:OnSuperCharged( name, old, new )
|
|
if old == new then return end
|
|
local Active = self:GetActive()
|
|
|
|
if new == true and Active then
|
|
self.Blower:Stop()
|
|
self.BlowerWhine:Stop()
|
|
|
|
self.Blower = CreateSound(self, self.snd_bloweroff or "simulated_vehicles/blower_spin.wav")
|
|
self.BlowerWhine = CreateSound(self, self.snd_bloweron or "simulated_vehicles/blower_gearwhine.wav")
|
|
|
|
self.Blower:PlayEx(0,0)
|
|
self.BlowerWhine:PlayEx(0,0)
|
|
elseif new == false then
|
|
if self.Blower then
|
|
self.Blower:Stop()
|
|
end
|
|
if self.BlowerWhine then
|
|
self.BlowerWhine:Stop()
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:OnRemove()
|
|
if self.Wheels then
|
|
for i = 1, table.Count( self.Wheels ) do
|
|
local Ent = self.Wheels[ i ]
|
|
if IsValid(Ent) then
|
|
Ent:Remove()
|
|
end
|
|
end
|
|
end
|
|
if self.keys then
|
|
for i = 1, table.Count( self.keys ) do
|
|
numpad.Remove( self.keys[i] )
|
|
end
|
|
end
|
|
if self.Turbo then
|
|
self.Turbo:Stop()
|
|
end
|
|
if self.Blower then
|
|
self.Blower:Stop()
|
|
end
|
|
if self.BlowerWhine then
|
|
self.BlowerWhine:Stop()
|
|
end
|
|
if self.horn then
|
|
self.horn:Stop()
|
|
end
|
|
if self.ems then
|
|
self.ems:Stop()
|
|
end
|
|
|
|
self:OnDelete()
|
|
hook.Run( "simfphysOnDelete", self )
|
|
end
|
|
|
|
function ENT:PlayPP( On )
|
|
self.poseon = On and self.LightsPP.max or self.LightsPP.min
|
|
end
|
|
|
|
function ENT:SetOnFire( bOn )
|
|
if bOn == self:OnFire() then return end
|
|
|
|
if hook.Run( "simfphysOnFire", self, bOn ) then return end
|
|
self:SetNWBool( "OnFire", bOn )
|
|
|
|
if bOn then
|
|
self:DamagedStall()
|
|
end
|
|
end
|
|
|
|
function ENT:SetOnSmoke( bOn )
|
|
if bOn == self:OnSmoke() then return end
|
|
|
|
if hook.Run( "simfphysOnSmoke", self, bOn ) then return end
|
|
self:SetNWBool( "OnSmoke", bOn )
|
|
|
|
if bOn then
|
|
self:DamagedStall()
|
|
end
|
|
end
|
|
|
|
function ENT:SetMaxHP( nHealth )
|
|
self:SetMaxHealth( nHealth )
|
|
end
|
|
|
|
function ENT:SetMaxHealth( nHealth )
|
|
self:SetNWFloat( "MaxHealth", nHealth )
|
|
end
|
|
|
|
function ENT:SetMaxFuel( nFuel )
|
|
self:SetNWFloat( "MaxFuel", nFuel )
|
|
end
|
|
|
|
function ENT:SetFuel( nFuel )
|
|
self:SetNWFloat( "Fuel", math.Clamp( nFuel,0,self:GetMaxFuel() ) )
|
|
end
|
|
|
|
function ENT:SetFuelUse( nFuel )
|
|
self:SetNWFloat( "FuelUse", nFuel )
|
|
end
|
|
|
|
function ENT:SetFuelType( fueltype )
|
|
self:SetNWInt( "FuelType", fueltype )
|
|
end
|
|
|
|
function ENT:SetFuelPos( vPos )
|
|
self:SetFuelPortPosition( vPos )
|
|
end
|
|
|
|
function ENT:OnMaintenance()
|
|
net.Start( "simfphys_lightsfixall" )
|
|
net.WriteEntity( self )
|
|
net.Broadcast()
|
|
|
|
self:OnRepaired()
|
|
|
|
local Fuel = self:GetFuel()
|
|
local MaxFuel = self:GetMaxFuel()
|
|
|
|
if Fuel ~= MaxFuel then
|
|
self:SetFuel( MaxFuel )
|
|
self:OnRefueled()
|
|
end
|
|
|
|
if istable(self.Wheels) then
|
|
for i = 1, table.Count( self.Wheels ) do
|
|
local Wheel = self.Wheels[ i ]
|
|
if IsValid(Wheel) then
|
|
Wheel:SetDamaged( false )
|
|
end
|
|
end
|
|
end
|
|
|
|
hook.Run( "simfphysOnRepaired", self )
|
|
end
|
|
|
|
function ENT:AddFuelTank( fueltype )
|
|
if IsValid( self:GetFuelTank() ) then return end
|
|
|
|
local FuelTank = ents.Create( "gmod_sent_vehicle_fphysics_fueltank" )
|
|
|
|
if not IsValid( FuelTank ) then
|
|
self:Remove()
|
|
|
|
print("LVS: Failed to create fueltank entity. Vehicle terminated.")
|
|
|
|
return
|
|
end
|
|
|
|
FuelTank:SetPos( self:GetPos() )
|
|
FuelTank:SetAngles( self:GetAngles() )
|
|
FuelTank:Spawn()
|
|
FuelTank:Activate()
|
|
FuelTank:SetParent( self )
|
|
FuelTank:SetBase( self )
|
|
|
|
self:SetFuelTank( FuelTank )
|
|
|
|
self:DeleteOnRemove( FuelTank )
|
|
|
|
self:TransferCPPI( FuelTank )
|
|
end
|
|
|
|
function ENT:OnRefueled()
|
|
local FuelTank = self:GetFuelTank()
|
|
|
|
if not IsValid( FuelTank ) then return end
|
|
|
|
FuelTank:EmitSound( "vehicles/jetski/jetski_no_gas_start.wav" )
|
|
end
|
|
|
|
function ENT:SetRoadkillAttacker( ply )
|
|
local T = CurTime()
|
|
|
|
if (self._nextSetAttacker or 0) > T then return end
|
|
|
|
self._nextSetAttacker = T + 1
|
|
|
|
self:SetPhysicsAttacker( ply, 1.1 )
|
|
end
|
|
|
|
|