696 lines
21 KiB
Lua
696 lines
21 KiB
Lua
AddCSLuaFile( "shared.lua" )
|
|
AddCSLuaFile( "cl_init.lua" )
|
|
|
|
include('shared.lua')
|
|
|
|
function ENT:Initialize()
|
|
|
|
self.Throttle = 0
|
|
self.Active = false
|
|
self.IsMaster = true
|
|
self.GearLink = {}
|
|
self.GearRope = {}
|
|
|
|
self.LastCheck = 0
|
|
self.LastThink = 0
|
|
self.Mass = 0
|
|
self.PhysMass = 0
|
|
self.MassRatio = 1
|
|
self.Legal = true
|
|
self.CanUpdate = true
|
|
|
|
--####################
|
|
self.TqAdd = 0
|
|
self.MaxRpmAdd = 0
|
|
self.LimitRpmAdd = 0
|
|
self.FlywheelMass = 0
|
|
self.WeightKg = 0
|
|
self.idle = 0
|
|
self.DisableCut = 0
|
|
self.CutMode = 0
|
|
self.CutValue = 0
|
|
self.CutRpm = 0
|
|
--####################
|
|
|
|
self.Inputs = Wire_CreateInputs( self, { "Active", "Throttle", "TqAdd", "MaxRpmAdd", "LimitRpmAdd", "FlywheelMass", "Idle", "DisableCut"} )
|
|
self.Outputs = WireLib.CreateSpecialOutputs( self, { "RPM", "Torque", "Power", "Entity" , "Mass" , "Physical Mass" }, { "NORMAL" ,"NORMAL" ,"NORMAL" , "ENTITY" , "NORMAL" , "NORMAL" } )
|
|
Wire_TriggerOutput(self, "Entity", self)
|
|
self.WireDebugName = "ACF Engine4"
|
|
|
|
end
|
|
|
|
function MakeACF_Engine4(Owner, Pos, Angle, Id, Data1, Data2, Data3, Data4, Data5, Data6)
|
|
|
|
if not Owner:CheckLimit("_acf_misc") then return false end
|
|
|
|
local Engine4 = ents.Create("ACF_Engine4")
|
|
local List = list.Get("ACFEnts")
|
|
local Classes = list.Get("ACFClasses")
|
|
if not Engine4:IsValid() then return false end
|
|
Engine4:SetAngles(Angle)
|
|
Engine4:SetPos(Pos)
|
|
Engine4:Spawn()
|
|
|
|
Engine4:SetPlayer(Owner)
|
|
Engine4.Owner = Owner
|
|
Engine4.Id = Id
|
|
Engine4.Model = List["Mobility2"][Id]["model"]
|
|
Engine4.SoundPath = List["Mobility2"][Id]["sound"]
|
|
Engine4.Weight = List["Mobility2"][Id]["weight"]
|
|
--##################################################################################
|
|
Engine4.iselec = List["Mobility2"][Id]["iselec"]
|
|
Engine4.elecpower = List["Mobility2"][Id]["elecpower"]
|
|
Engine4.FlywheelOverride = List["Mobility2"][Id]["flywheeloverride"]
|
|
|
|
Engine4.ModTable = List["Mobility2"][Id]["modtable"]
|
|
Engine4.ModTable[1] = Data1
|
|
Engine4.ModTable[2] = Data2
|
|
Engine4.ModTable[3] = Data3
|
|
Engine4.ModTable[4] = Data4
|
|
Engine4.ModTable[5] = Data5
|
|
Engine4.ModTable[6] = Data6
|
|
|
|
Engine4.PeakTorque = Data1
|
|
Engine4.IdleRPM = Data2
|
|
Engine4.PeakMinRPM = Data3
|
|
Engine4.LimitRPM = Data5
|
|
if(Data4 <= Data5 ) then
|
|
Engine4.PeakMaxRPM = Data4
|
|
elseif(Data4 > Data5 ) then
|
|
Engine4.PeakMaxRPM = Data5
|
|
end
|
|
Engine4.FlywheelMass2 = Data6
|
|
Engine4.CutValue = Engine4.LimitRPM / 40
|
|
Engine4.CutRpm = Engine4.LimitRPM - 100
|
|
|
|
Engine4.PeakTorque2 = Data1
|
|
Engine4.PeakTorque3 = Data1
|
|
Engine4.Idling = Data2
|
|
Engine4.PeakMaxRPM2 = Data4
|
|
Engine4.LimitRPM2 = Data5
|
|
Engine4.FlywheelMass3 = Data6
|
|
|
|
Engine4.Inertia = Engine4.FlywheelMass2*(3.1416)^2
|
|
--##################################################################################
|
|
|
|
Engine4.FlyRPM = 0
|
|
Engine4:SetModel( Engine4.Model )
|
|
Engine4.Sound = nil
|
|
Engine4.SoundPitch = 1
|
|
Engine4.RPM = {}
|
|
|
|
Engine4:PhysicsInit( SOLID_VPHYSICS )
|
|
Engine4:SetMoveType( MOVETYPE_VPHYSICS )
|
|
Engine4:SetSolid( SOLID_VPHYSICS )
|
|
|
|
Engine4.Out = Engine4:WorldToLocal(Engine4:GetAttachment(Engine4:LookupAttachment( "driveshaft" )).Pos)
|
|
|
|
local phys = Engine4:GetPhysicsObject()
|
|
if (phys:IsValid()) then
|
|
phys:SetMass( Engine4.Weight )
|
|
end
|
|
|
|
Engine4:SetNetworkedBeamString("Type",List["Mobility2"][Id]["name"])
|
|
Engine4:SetNetworkedBeamInt("Torque",Engine4.PeakTorque)
|
|
-- add in the variable to check if its an electric motor
|
|
if (Engine4.iselec == true )then
|
|
Engine4:SetNetworkedBeamInt("Power",Engine4.elecpower) -- add in the value from the elecpower
|
|
else
|
|
Engine4:SetNetworkedBeamInt("Power",math.floor(Engine4.PeakTorque * Engine4.PeakMaxRPM / 9548.8))
|
|
end
|
|
Engine4:SetNetworkedBeamInt("MinRPM",Engine4.PeakMinRPM)
|
|
Engine4:SetNetworkedBeamInt("MaxRPM",Engine4.PeakMaxRPM)
|
|
Engine4:SetNetworkedBeamInt("LimitRPM",Engine4.LimitRPM)
|
|
--####################################################
|
|
Engine4:SetNetworkedBeamInt("FlywheelMass2",Engine4.FlywheelMass3*1000)
|
|
Engine4:SetNetworkedBeamInt("Idle",Engine4.IdleRPM)
|
|
Engine4:SetNetworkedBeamInt("Weight",Engine4.Weight)
|
|
Engine4:SetNetworkedBeamInt("Rpm",Engine4.FlyRPM)
|
|
--####################################################
|
|
|
|
Owner:AddCount("_acf_engine4", Engine4)
|
|
Owner:AddCleanup( "acfmenu", Engine4 )
|
|
|
|
return Engine4
|
|
end
|
|
list.Set( "ACFCvars", "acf_engine4" , {"id", "data1", "data2", "data3", "data4", "data5", "data6"} )
|
|
duplicator.RegisterEntityClass("acf_engine4", MakeACF_Engine4, "Pos", "Angle", "Id", "PeakTorque", "IdleRPM", "PeakMinRPM", "PeakMaxRPM", "LimitRPM", "FlywheelMass2", "FlywheelMass3")
|
|
|
|
function ENT:Update( ArgsTable ) --That table is the player data, as sorted in the ACFCvars above, with player who shot, and pos and angle of the tool trace inserted at the start
|
|
|
|
local Feedback = "Engine updated"
|
|
if self.Active then
|
|
Feedback = "Please turn off the engine before updating it"
|
|
return Feedback end
|
|
if ( ArgsTable[1] != self.Owner ) then --Argtable[1] is the player that shot the tool
|
|
Feedback = "You don't own that engine !"
|
|
return Feedback end
|
|
|
|
local Id = ArgsTable[4] --Argtable[4] is the engine ID
|
|
local List = list.Get("ACFEnts")
|
|
|
|
if ( List["Mobility2"][Id]["model"] != self.Model ) then --Make sure the models are the sames before doing a changeover
|
|
Feedback = "The new engine needs to have the same model as the old one !"
|
|
return Feedback end
|
|
|
|
if self.Id != Id then
|
|
self.Id = Id
|
|
self.SoundPath = List["Mobility2"][Id]["sound"]
|
|
self.Weight = List["Mobility2"][Id]["weight"]
|
|
self.iselec = List["Mobility2"][Id]["iselec"] -- is the engine electric?
|
|
self.elecpower = List["Mobility2"][Id]["elecpower"] -- how much power does it output
|
|
self.FlywheelOverride = List["Mobility2"][Id]["flywheeloverride"] -- how much power does it output
|
|
end
|
|
|
|
self.ModTable[1] = ArgsTable[5]
|
|
self.ModTable[2] = ArgsTable[6]
|
|
self.ModTable[3] = ArgsTable[7]
|
|
self.ModTable[4] = ArgsTable[8]
|
|
self.ModTable[5] = ArgsTable[9]
|
|
self.ModTable[6] = ArgsTable[10]
|
|
|
|
self.PeakTorque = ArgsTable[5]
|
|
self.IdleRPM = ArgsTable[6]
|
|
self.PeakMaxRPM = ArgsTable[8]
|
|
if(ArgsTable[7] <= ArgsTable[8] ) then
|
|
self.PeakMinRPM = ArgsTable[7]
|
|
elseif(ArgsTable[7] > ArgsTable[8] ) then
|
|
self.PeakMinRPM = ArgsTable[8]
|
|
end
|
|
self.LimitRPM = ArgsTable[9]
|
|
self.FlywheelMass2 = ArgsTable[10]
|
|
self.CutValue = self.LimitRPM / 40
|
|
self.CutRpm = self.LimitRPM - 100
|
|
|
|
self.PeakTorque2 = ArgsTable[5]
|
|
self.PeakTorque3 = ArgsTable[5]
|
|
self.Idling = ArgsTable[6]
|
|
self.PeakMaxRPM2 = ArgsTable[8]
|
|
self.LimitRPM2 = ArgsTable[9]
|
|
self.FlywheelMass3 = ArgsTable[10]
|
|
|
|
self.Inertia = self.FlywheelMass2*(3.1416)^2
|
|
--##################################################################################
|
|
|
|
self:SetModel( self.Model )
|
|
self:SetSolid( SOLID_VPHYSICS )
|
|
self.Out = self:WorldToLocal(self:GetAttachment(self:LookupAttachment( "driveshaft" )).Pos)
|
|
|
|
local phys = self:GetPhysicsObject()
|
|
if (phys:IsValid()) then
|
|
phys:SetMass( self.Weight )
|
|
end
|
|
|
|
self:SetNetworkedBeamString("Type",List["Mobility2"][Id]["name"])
|
|
self:SetNetworkedBeamInt("Torque",self.PeakTorque)
|
|
-- add in the variable to check if its an electric motor
|
|
if (self.iselec == true) then
|
|
self:SetNetworkedBeamInt("Power",self.elecpower) -- add in the value from the elecpower
|
|
else
|
|
self:SetNetworkedBeamInt("Power",math.floor(self.PeakTorque * self.PeakMaxRPM / 9548.8))
|
|
end
|
|
|
|
self:SetNetworkedBeamInt("MinRPM",self.PeakMinRPM)
|
|
self:SetNetworkedBeamInt("MaxRPM",self.PeakMaxRPM)
|
|
self:SetNetworkedBeamInt("LimitRPM",self.LimitRPM)
|
|
--################################################
|
|
self:SetNetworkedBeamInt("FlywheelMass2",self.FlywheelMass3*1000)
|
|
self:SetNetworkedBeamInt("Idle",self.IdleRPM)
|
|
self:SetNetworkedBeamInt("Weight",self.Weight)
|
|
self:SetNetworkedBeamInt("Rpm",self.FlyRPM)
|
|
--################################################
|
|
|
|
|
|
return Feedback
|
|
end
|
|
|
|
function ENT:TriggerInput( iname , value )
|
|
|
|
if (iname == "Throttle") then
|
|
self.Throttle = math.Clamp(value,0,100)/100
|
|
elseif (iname == "Active") then
|
|
if (value > 0 and not self.Active) then
|
|
self.RPM = {}
|
|
self.RPM[1] = self.IdleRPM
|
|
self.Active = true
|
|
self.Active2 = true
|
|
self.Sound = CreateSound(self, self.SoundPath)
|
|
self.Sound:PlayEx(0.5,100)
|
|
self:ACFInit()
|
|
elseif (value <= 0 and self.Active) then
|
|
self.Active = false
|
|
Wire_TriggerOutput( self, "RPM", 0 )
|
|
Wire_TriggerOutput( self, "Torque", 0 )
|
|
Wire_TriggerOutput( self, "Power", 0 )
|
|
end
|
|
--##################################################
|
|
elseif (iname == "TqAdd") then
|
|
if (value ~= 0 ) then
|
|
self.TqAdd = true
|
|
self.PeakTorque = self.PeakTorque2+value
|
|
--self.PeakTorque3 = self.PeakTorque2+value
|
|
self:SetNetworkedBeamInt("Torque",self.PeakTorque)
|
|
self:SetNetworkedBeamInt("Power", math.floor(self.PeakTorque * self.PeakMaxRPM / 9548.8))
|
|
elseif (value == 0 ) then
|
|
self.TqAdd = false
|
|
self.PeakTorque = self.PeakTorque2
|
|
--self.PeakTorque3 = self.PeakTorque2
|
|
self:SetNetworkedBeamInt("Torque",self.PeakTorque)
|
|
self:SetNetworkedBeamInt("Power", math.floor(self.PeakTorque * self.PeakMaxRPM / 9548.8))
|
|
end
|
|
elseif (iname == "MaxRpmAdd") then
|
|
if (value ~= 0 ) then
|
|
self.MaxRpmAdd = true
|
|
--self.PeakMaxRPM = self.PeakMaxRPM2+value
|
|
if( self.PeakMaxRPM2+value <= self.LimitRPM ) then
|
|
self.PeakMaxRPM = self.PeakMaxRPM2+value
|
|
elseif( self.PeakMaxRPM2+value > self.LimitRPM ) then
|
|
self.PeakMaxRPM = self.LimitRPM
|
|
end
|
|
self:SetNetworkedBeamInt("MaxRPM",self.PeakMaxRPM)
|
|
self:SetNetworkedBeamInt("Power", math.floor(self.PeakTorque * self.PeakMaxRPM / 9548.8))
|
|
elseif (value == 0 ) then
|
|
self.MaxRpmAdd = false
|
|
self.PeakMaxRPM = self.PeakMaxRPM2
|
|
self:SetNetworkedBeamInt("MaxRPM",self.PeakMaxRPM)
|
|
self:SetNetworkedBeamInt("Power", math.floor(self.PeakTorque * self.PeakMaxRPM / 9548.8))
|
|
end
|
|
elseif (iname == "LimitRpmAdd") then
|
|
if (value ~= 0 ) then
|
|
self.LimitRpmAdd = true
|
|
self.LimitRPM = self.LimitRPM2+value
|
|
self:SetNetworkedBeamInt("LimitRPM",self.LimitRPM)
|
|
self.CutValue = self.LimitRPM / 40
|
|
self.CutRpm = self.LimitRPM - 100
|
|
elseif (value == 0 ) then
|
|
self.LimitRpmAdd = false
|
|
self.LimitRPM = self.LimitRPM2
|
|
self:SetNetworkedBeamInt("LimitRPM",self.LimitRPM)
|
|
self.CutValue = self.LimitRPM / 40
|
|
self.CutRpm = self.LimitRPM - 100
|
|
end
|
|
elseif (iname == "FlywheelMass") then
|
|
if (value > 0 ) then
|
|
self.FlywheelMass = true
|
|
self.Inertia = value*(3.1416)^2
|
|
self:SetNetworkedBeamInt("FlywheelMass2",value*1000)
|
|
elseif (value <= 0 ) then
|
|
self.FlywheelMass = false
|
|
self.Inertia = self.FlywheelMass3*(3.1416)^2
|
|
self:SetNetworkedBeamInt("FlywheelMass2",self.FlywheelMass3*1000)
|
|
end
|
|
elseif (iname == "Idle") then
|
|
if (value > 0 ) then
|
|
self.Idle = true
|
|
self.IdleRPM = value
|
|
self:SetNetworkedBeamInt("Idle",self.IdleRPM)
|
|
elseif (value <= 0 ) then
|
|
self.Idle = false
|
|
self.IdleRPM = self.Idling
|
|
self:SetNetworkedBeamInt("Idle",self.IdleRPM)
|
|
end
|
|
elseif (iname == "DisableCut") then
|
|
if (value > 0 ) then
|
|
self.DisableCut = 1
|
|
elseif (value <= 0 ) then
|
|
self.DisableCut = 0
|
|
end
|
|
end
|
|
|
|
end
|
|
--######################################################
|
|
|
|
function ENT:Think()
|
|
|
|
local Time = CurTime()
|
|
|
|
if self.Active2 then
|
|
if self.Legal then
|
|
self:CalcRPM()
|
|
end
|
|
|
|
if self.LastCheck < CurTime() then
|
|
self:CheckRopes()
|
|
if self:GetPhysicsObject():GetMass() < self.Weight or self:GetParent():IsValid() then
|
|
self.Legal = false
|
|
else
|
|
self.Legal = true
|
|
end
|
|
|
|
self.LastCheck = Time + math.Rand(5, 10)
|
|
end
|
|
|
|
end
|
|
|
|
self.LastThink = Time
|
|
self:NextThink( Time )
|
|
return true
|
|
|
|
end
|
|
|
|
function ENT:ACFInit()
|
|
|
|
local Constrained = constraint.GetAllConstrainedEntities(self)
|
|
self.Mass = 0
|
|
self.PhysMass = 0
|
|
|
|
for _,Ent in pairs(Constrained) do
|
|
|
|
if IsValid(Ent) then
|
|
local Phys = Ent:GetPhysicsObject()
|
|
|
|
if Phys and Phys:IsValid() then
|
|
self.Mass = self.Mass + Phys:GetMass()
|
|
local Parent = Ent:GetParent()
|
|
|
|
if IsValid(Parent) then
|
|
|
|
local Constraints = {}
|
|
table.Add(Constraints,constraint.FindConstraints(Ent, "Weld"))
|
|
table.Add(Constraints,constraint.FindConstraints(Ent, "Axis"))
|
|
table.Add(Constraints,constraint.FindConstraints(Ent, "Ballsocket"))
|
|
table.Add(Constraints,constraint.FindConstraints(Ent, "AdvBallsocket"))
|
|
|
|
if Constraints then
|
|
|
|
for Key,Const in pairs(Constraints) do
|
|
|
|
if Const.Ent1 == Parent or Const.Ent2 == Parent then
|
|
self.PhysMass = self.PhysMass + Phys:GetMass()
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
self.PhysMass = self.PhysMass + Phys:GetMass()
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
self.MassRatio = self.PhysMass/self.Mass
|
|
|
|
Wire_TriggerOutput(self, "Mass", math.floor(self.Mass))
|
|
Wire_TriggerOutput(self, "Physical Mass", math.floor(self.PhysMass))
|
|
|
|
self.LastThink = CurTime()
|
|
self.Torque = self.PeakTorque
|
|
self.FlyRPM = self.IdleRPM*1.5
|
|
|
|
end
|
|
|
|
function ENT:CalcRPM()
|
|
|
|
local DeltaTime = CurTime() - self.LastThink
|
|
-- local AutoClutch = math.min(math.max(self.FlyRPM-self.IdleRPM,0)/(self.IdleRPM+self.LimitRPM/10),1)
|
|
|
|
//local ClutchRatio = math.min(Clutch/math.max(TorqueDiff,0.05),1)
|
|
|
|
-- Calculate the current torque from flywheel RPM
|
|
--#################
|
|
local Drag
|
|
local TorqueDiff
|
|
if self.Active then
|
|
if( self.CutMode == 0 ) then
|
|
self.Torque = self.Throttle * math.max( self.PeakTorque * math.min( self.FlyRPM / self.PeakMinRPM , (self.LimitRPM - self.FlyRPM) / (self.LimitRPM - self.PeakMaxRPM), 1 ), 0 )
|
|
if self.iselec == true then
|
|
Drag = self.PeakTorque * (math.max( self.FlyRPM - self.IdleRPM, 0) / self.FlywheelOverride) * (1 - self.Throttle) / self.Inertia
|
|
else
|
|
Drag = self.PeakTorque * (math.max( self.FlyRPM - self.IdleRPM, 0) / self.PeakMaxRPM) * ( 1 - self.Throttle) / self.Inertia
|
|
end
|
|
|
|
elseif( self.CutMode == 1 ) then
|
|
self.Torque = 0 * math.max( self.PeakTorque * math.min( self.FlyRPM / self.PeakMinRPM , (self.LimitRPM - self.FlyRPM) / (self.LimitRPM - self.PeakMaxRPM), 1 ), 0 )
|
|
if self.iselec == true then
|
|
Drag = self.PeakTorque * (math.max( self.FlyRPM - self.IdleRPM, 0) / self.FlywheelOverride) * (1 - 0) / self.Inertia
|
|
else
|
|
Drag = self.PeakTorque * (math.max( self.FlyRPM - self.IdleRPM, 0) / self.PeakMaxRPM) * ( 1 - 0) / self.Inertia
|
|
end
|
|
|
|
end
|
|
|
|
-- Let's accelerate the flywheel based on that torque
|
|
self.FlyRPM = math.max( self.FlyRPM + self.Torque / self.Inertia - Drag, 1 )
|
|
-- This is the presently avaliable torque from the engine
|
|
TorqueDiff = math.max( self.FlyRPM - self.IdleRPM, 0 ) * self.Inertia
|
|
|
|
end
|
|
|
|
if( self.Active == false ) then
|
|
self.Torque = 0 * math.max( self.PeakTorque * math.min( self.FlyRPM / self.PeakMinRPM , (self.LimitRPM - self.FlyRPM) / (self.LimitRPM - self.PeakMaxRPM), 1 ), 0 )
|
|
if self.iselec == true then
|
|
Drag = self.PeakTorque * (math.max( self.FlyRPM - 0, 0) / self.FlywheelOverride) * (1 - 0) / self.Inertia
|
|
else
|
|
Drag = self.PeakTorque * (math.max( self.FlyRPM - 0, 0) / self.PeakMaxRPM) * ( 1 - 0) / self.Inertia
|
|
end
|
|
|
|
-- Let's accelerate the flywheel based on that torque
|
|
self.FlyRPM = math.max( self.FlyRPM + self.Torque / self.Inertia - Drag, 1 )
|
|
-- This is the presently avaliable torque from the engine
|
|
TorqueDiff = math.max( self.FlyRPM - 0, 0 ) * self.Inertia
|
|
|
|
end
|
|
--##############
|
|
|
|
-- The gearboxes don't think on their own, it's the engine that calls them, to ensure consistent execution order
|
|
local Boxes = table.Count( self.GearLink )
|
|
|
|
local MaxTqTable = {}
|
|
local MaxTq = 0
|
|
for Key, Gearbox in pairs(self.GearLink) do
|
|
-- Get the requirements for torque for the gearboxes (Max clutch rating minus any wheels currently spinning faster than the Flywheel)
|
|
MaxTqTable[Key] = Gearbox:Calc( self.FlyRPM, self.Inertia )
|
|
MaxTq = MaxTq + MaxTqTable[Key]
|
|
end
|
|
|
|
-- Calculate the ratio of total requested torque versus what's avaliable
|
|
local AvailTq = math.min( TorqueDiff / MaxTq / Boxes, 1 )
|
|
|
|
for Key, Gearbox in pairs(self.GearLink) do
|
|
-- Split the torque fairly between the gearboxes who need it
|
|
Gearbox:Act( MaxTqTable[Key] * AvailTq * self.MassRatio, DeltaTime )
|
|
end
|
|
|
|
self.FlyRPM = self.FlyRPM - (math.min(TorqueDiff,MaxTq)/self.Inertia)
|
|
|
|
--#######################################
|
|
--if( self.CutOn == 1 ) then
|
|
if( self.DisableCut == 0 ) then
|
|
if( self.FlyRPM >= self.CutRpm and self.CutMode == 0 ) then
|
|
self.CutMode = 1
|
|
if self.Sound then
|
|
self.Sound:Stop()
|
|
end
|
|
self.Sound = nil
|
|
self.Sound2 = CreateSound(self, "acf_other/penetratingshots/00000293.wav")
|
|
self.Sound2:PlayEx(0.5,100)
|
|
end
|
|
if( self.FlyRPM <= self.CutRpm - self.CutValue and self.CutMode == 1 ) then
|
|
self.CutMode = 0
|
|
self.Sound = CreateSound(self, self.SoundPath)
|
|
self.Sound:PlayEx(0.5,100)
|
|
if self.Sound2 then
|
|
self.Sound2:Stop()
|
|
end
|
|
end
|
|
--elseif( self.CutOn == 0 ) then
|
|
elseif( self.DisableCut == 1 ) then
|
|
self.CutMode = 0
|
|
end
|
|
if( self.FlyRPM <= 50 and self.Active == false ) then
|
|
self.Active2 = false
|
|
self.FlyRPM = 0
|
|
if self.Sound then
|
|
self.Sound:Stop()
|
|
end
|
|
self.Sound = nil
|
|
end
|
|
--#######################################
|
|
|
|
-- Then we calc a smoothed RPM value for the sound effects
|
|
table.remove( self.RPM, 10 )
|
|
table.insert( self.RPM, 1, self.FlyRPM )
|
|
local SmoothRPM = 0
|
|
for Key, RPM in pairs( self.RPM ) do
|
|
SmoothRPM = SmoothRPM + (RPM or 0)
|
|
end
|
|
SmoothRPM = SmoothRPM / 10
|
|
|
|
local Power = self.Torque * SmoothRPM / 9548.8
|
|
Wire_TriggerOutput(self, "Torque", math.floor(self.Torque))
|
|
Wire_TriggerOutput(self, "Power", math.floor(Power))
|
|
Wire_TriggerOutput(self, "RPM", self.FlyRPM)
|
|
--##############################################################################################
|
|
self:SetNetworkedBeamInt("Rpm",self.FlyRPM)
|
|
--##############################################################################################
|
|
|
|
if self.Sound then
|
|
self.Sound:ChangePitch( math.min( 20 + (SmoothRPM * self.SoundPitch) / 50, 255 ), 0 )
|
|
self.Sound:ChangeVolume( 0.25 + self.Throttle / 1.5, 0 )
|
|
end
|
|
|
|
return RPM
|
|
end
|
|
|
|
function ENT:CheckRopes()
|
|
|
|
for GearboxKey,Ent in pairs(self.GearLink) do
|
|
local Constraints = constraint.FindConstraints(Ent, "Rope")
|
|
if Constraints then
|
|
|
|
local Clean = false
|
|
for Key,Rope in pairs(Constraints) do
|
|
if Rope.Ent1 == self or Rope.Ent2 == self then
|
|
if Rope.length + Rope.addlength < self.GearRope[GearboxKey]*1.5 then
|
|
Clean = true
|
|
end
|
|
end
|
|
end
|
|
|
|
if not Clean then
|
|
self:Unlink( Ent )
|
|
end
|
|
|
|
else
|
|
self:Unlink( Ent )
|
|
end
|
|
|
|
local DrvAngle = (self:LocalToWorld(self.Out) - Ent:LocalToWorld(Ent.In)):GetNormalized():DotProduct( self:GetForward() )
|
|
if ( DrvAngle < 0.7 ) then
|
|
self:Unlink( Ent )
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
function ENT:Link( Target )
|
|
|
|
--##################################################
|
|
if ( !Target or Target:GetClass() != "acf_gearbox" and Target:GetClass() != "acf_gearbox2" and Target:GetClass() != "acf_gearbox3" ) then return ("Can only link to Gearboxes") end
|
|
--##################################################
|
|
|
|
local Duplicate = false
|
|
for Key,Value in pairs(self.GearLink) do
|
|
if Value == Target then
|
|
Duplicate = true
|
|
end
|
|
end
|
|
|
|
if not Duplicate then
|
|
|
|
local InPos = Target:LocalToWorld(Target.In)
|
|
local OutPos = self:LocalToWorld(self.Out)
|
|
local DrvAngle = (OutPos - InPos):GetNormalized():DotProduct((self:GetForward()))
|
|
if ( DrvAngle < 0.7 ) then
|
|
return 'ERROR : Excessive driveshaft angle'
|
|
end
|
|
|
|
table.insert(self.GearLink,Target)
|
|
table.insert(Target.Master,self)
|
|
local RopeL = (OutPos-InPos):Length()
|
|
constraint.Rope( self, Target, 0, 0, self.Out, Target.In, RopeL, RopeL*0.2, 0, 1, "cable/cable2", false )
|
|
table.insert(self.GearRope,RopeL)
|
|
|
|
return false
|
|
else
|
|
return ('ERROR : Gearbox already linked to this Engine')
|
|
end
|
|
|
|
|
|
end
|
|
|
|
function ENT:Unlink( Target )
|
|
|
|
local Success = false
|
|
for Key,Value in pairs(self.GearLink) do
|
|
if Value == Target then
|
|
|
|
local Constraints = constraint.FindConstraints(Value, "Rope")
|
|
if Constraints then
|
|
for Key,Rope in pairs(Constraints) do
|
|
if Rope.Ent1 == self or Rope.Ent2 == self then
|
|
Rope.Constraint:Remove()
|
|
end
|
|
end
|
|
end
|
|
|
|
table.remove(self.GearLink,Key)
|
|
table.remove(self.GearRope,Key)
|
|
Success = true
|
|
end
|
|
end
|
|
|
|
if Success then
|
|
return false
|
|
else
|
|
return ('ERROR : Did not find the Gearbox to unlink')
|
|
end
|
|
|
|
end
|
|
|
|
function ENT:PreEntityCopy()
|
|
|
|
//Link Saving
|
|
local info = {}
|
|
local entids = {}
|
|
for Key, Value in pairs(self.GearLink) do --First clean the table of any invalid entities
|
|
if not Value:IsValid() then
|
|
table.remove(self.GearLink, Value)
|
|
end
|
|
end
|
|
for Key, Value in pairs(self.GearLink) do --Then save it
|
|
table.insert(entids, Value:EntIndex())
|
|
end
|
|
|
|
info.entities = entids
|
|
if info.entities then
|
|
duplicator.StoreEntityModifier( self, "GearLink", info )
|
|
end
|
|
|
|
//Wire dupe info
|
|
local DupeInfo = WireLib.BuildDupeInfo( self )
|
|
if DupeInfo then
|
|
duplicator.StoreEntityModifier( self, "WireDupeInfo", DupeInfo )
|
|
end
|
|
|
|
end
|
|
|
|
function ENT:PostEntityPaste( Player, Ent, CreatedEntities )
|
|
|
|
//Link Pasting
|
|
if (Ent.EntityMods) and (Ent.EntityMods.GearLink) and (Ent.EntityMods.GearLink.entities) then
|
|
local GearLink = Ent.EntityMods.GearLink
|
|
if GearLink.entities and table.Count(GearLink.entities) > 0 then
|
|
for _,ID in pairs(GearLink.entities) do
|
|
local Linked = CreatedEntities[ ID ]
|
|
if Linked and Linked:IsValid() then
|
|
self:Link( Linked )
|
|
end
|
|
end
|
|
end
|
|
Ent.EntityMods.GearLink = nil
|
|
end
|
|
|
|
//Wire dupe info
|
|
if(Ent.EntityMods and Ent.EntityMods.WireDupeInfo) then
|
|
WireLib.ApplyDupeInfo(Player, Ent, Ent.EntityMods.WireDupeInfo, function(id) return CreatedEntities[id] end)
|
|
end
|
|
|
|
end
|
|
|
|
function ENT:OnRemove()
|
|
if self.Sound then
|
|
self.Sound:Stop()
|
|
end
|
|
Wire_Remove( self )
|
|
end
|
|
|
|
function ENT:OnRestore()
|
|
Wire_Restored( self )
|
|
end |