UPDATE
This commit is contained in:
68
koptilnya/engine_remastered/powertrain/clutch.txt
Normal file
68
koptilnya/engine_remastered/powertrain/clutch.txt
Normal file
@@ -0,0 +1,68 @@
|
||||
--@include ./powertrain_component.txt
|
||||
--@include /koptilnya/libs/constants.txt
|
||||
|
||||
local PowertrainComponent = require('./powertrain_component.txt')
|
||||
|
||||
require('/koptilnya/libs/constants.txt')
|
||||
|
||||
local Clutch = class('Clutch', PowertrainComponent)
|
||||
|
||||
function Clutch:initialize(vehicle, name, config)
|
||||
PowertrainComponent.initialize(self, vehicle, name, config)
|
||||
|
||||
self.wireInputs = {
|
||||
Clutch = 'number'
|
||||
}
|
||||
self.wireOutputs = {
|
||||
Clutch_Torque = 'number'
|
||||
}
|
||||
|
||||
self.inertia = config.Inertia or 0.1
|
||||
self.slipTorque = config.SlipTorque or 1000
|
||||
end
|
||||
|
||||
function Clutch:updateWireOutputs()
|
||||
wire.ports.Clutch_Torque = self.torque
|
||||
end
|
||||
|
||||
function Clutch:getPress()
|
||||
return 1 - wire.ports.Clutch
|
||||
end
|
||||
|
||||
function Clutch:queryInertia()
|
||||
if self.output == nil then
|
||||
return self.inertia
|
||||
end
|
||||
|
||||
return self.inertia + self.output:queryInertia() * self:getPress()
|
||||
end
|
||||
|
||||
function Clutch:queryAngularVelocity(angularVelocity)
|
||||
self.angularVelocity = angularVelocity
|
||||
|
||||
if self.output == nil then
|
||||
return angularVelocity
|
||||
end
|
||||
|
||||
local outputW = self.output:queryAngularVelocity(angularVelocity) * self:getPress()
|
||||
local inputW = angularVelocity * (1 - self:getPress())
|
||||
|
||||
return outputW + inputW
|
||||
end
|
||||
|
||||
function Clutch:forwardStep(torque, inertia)
|
||||
if self.output == nil then
|
||||
return torque
|
||||
end
|
||||
|
||||
local press = self:getPress()
|
||||
|
||||
self.torque = math.clamp(torque, -self.slipTorque, self.slipTorque)
|
||||
self.torque = self.torque * (1 - (1 - math.pow(press, 0.3)))
|
||||
|
||||
local returnTorque = self.output:forwardStep(self.torque, inertia * press + self.inertia) * press
|
||||
|
||||
return math.clamp(returnTorque, -self.slipTorque, self.slipTorque)
|
||||
end
|
||||
|
||||
return Clutch
|
||||
159
koptilnya/engine_remastered/powertrain/differential.txt
Normal file
159
koptilnya/engine_remastered/powertrain/differential.txt
Normal file
@@ -0,0 +1,159 @@
|
||||
--@include /koptilnya/libs/constants.txt
|
||||
--@include ./powertrain_component.txt
|
||||
|
||||
|
||||
local PowertrainComponent = require('./powertrain_component.txt')
|
||||
local WheelComponent = require('./wheel.txt')
|
||||
|
||||
require('/koptilnya/libs/constants.txt')
|
||||
|
||||
local Differential = class('Differential', PowertrainComponent)
|
||||
|
||||
function Differential:initialize(vehicle, name, config)
|
||||
PowertrainComponent.initialize(self, vehicle, name, config)
|
||||
|
||||
self.wireOutputs = {
|
||||
Diff_Torque = 'number'
|
||||
}
|
||||
|
||||
self.finalDrive = config.FinalDrive or 4
|
||||
self.inertia = config.Inertia or 0.2
|
||||
self.biasAB = config.Bias or 0.5
|
||||
self.coastRamp = config.CoastRamp or 0.5
|
||||
self.powerRamp = config.PowerRamp or 1
|
||||
self.preload = config.Preload or 10
|
||||
self.stiffness = config.Stiffness or 0.1
|
||||
self.slipTorque = config.SlipTorque or 1000
|
||||
end
|
||||
|
||||
function Differential:linkComponent(component)
|
||||
if not component:isInstanceOf(PowertrainComponent) then
|
||||
return
|
||||
end
|
||||
|
||||
if self.outputA == nil then
|
||||
self.outputA = component
|
||||
component.input = self
|
||||
elseif self.outputB == nil then
|
||||
self.outputB = component
|
||||
component.input = self
|
||||
end
|
||||
end
|
||||
|
||||
function Differential:updateWireOutputs()
|
||||
wire.ports.Diff_Torque = self.torque
|
||||
|
||||
if self.outputA ~= nil then
|
||||
self.outputA:updateWireOutputs()
|
||||
end
|
||||
|
||||
if self.outputB ~= nil then
|
||||
self.outputB:updateWireOutputs()
|
||||
end
|
||||
end
|
||||
|
||||
function Differential:queryInertia()
|
||||
if self.outputA == nil or self.outputB == nil then
|
||||
return self.inertia
|
||||
end
|
||||
|
||||
return self.inertia + (self.outputA:queryInertia() + self.outputB:queryInertia()) / math.pow(self.finalDrive, 2)
|
||||
end
|
||||
|
||||
function Differential:queryAngularVelocity(angularVelocity)
|
||||
self.angularVelocity = angularVelocity
|
||||
|
||||
if self.outputA == nil or self.outputB == nil then
|
||||
return angularVelocity
|
||||
end
|
||||
|
||||
local aW = self.outputA:queryAngularVelocity(angularVelocity)
|
||||
local bW = self.outputB:queryAngularVelocity(angularVelocity)
|
||||
|
||||
return (aW + bW) * self.finalDrive * 0.5
|
||||
end
|
||||
|
||||
function Differential:forwardStep(torque, inertia)
|
||||
if self.outputA == nil or self.outputB == nil then
|
||||
return torque
|
||||
end
|
||||
|
||||
local aW = self.outputA:queryAngularVelocity(self.angularVelocity)
|
||||
local bW = self.outputB:queryAngularVelocity(self.angularVelocity)
|
||||
local aI = self.outputA:queryInertia()
|
||||
local bI = self.outputB:queryInertia()
|
||||
|
||||
self.torque = torque * self.finalDrive
|
||||
|
||||
local tqA, tqB = self:_openDiffTorqueSplit(
|
||||
self.torque,
|
||||
aW,
|
||||
bW,
|
||||
aI,
|
||||
bI,
|
||||
self.biasAB,
|
||||
self.preload,
|
||||
self.stiffness,
|
||||
self.powerRamp,
|
||||
self.coastRamp,
|
||||
self.slipTorque
|
||||
)
|
||||
|
||||
tqA = self.outputA:forwardStep(tqA, inertia * 0.5 * math.pow(self.finalDrive, 2) + aI) / self.finalDrive
|
||||
tqB = self.outputB:forwardStep(tqB, inertia * 0.5 * math.pow(self.finalDrive, 2) + bI) / self.finalDrive
|
||||
|
||||
return (tqA + tqB) / self.finalDrive
|
||||
end
|
||||
|
||||
function Differential:_openDiffTorqueSplit(tq, aW, bW, aI, bI, biasAB, preload, stiffness, powerRamp, coastRamp, slipTorque)
|
||||
return tq * (1 - biasAB), tq * biasAB;
|
||||
end
|
||||
|
||||
function Differential:_lockingDiffTorqueSplit(tq, aW, bW, aI, bI, biasAB, preload, stiffness, powerRamp, coastRamp, slipTorque)
|
||||
local sumI = aI + bI
|
||||
local w = aI / sumI * aW + bI / sumI * bW
|
||||
local aTqCorr = (w - aW) * aI -- / dt
|
||||
aTqCorr = aTqCorr * stiffness
|
||||
|
||||
local bTqCorr = (w - bW) * bI -- / dt
|
||||
bTqCorr = bTqCorr * stiffness
|
||||
|
||||
local biasA = math.clamp(0.5 + (bW - aW) * 0.1 * stiffness, 0, 1)
|
||||
|
||||
return tq * biasA + aTqCorr, tq * (1 - biasA) * bTqCorr
|
||||
end
|
||||
|
||||
function Differential:_VLSDTorqueSplit(tq, aW, bW, aI, bI, biasAB, preload, stiffness, powerRamp, coastRamp, slipTorque)
|
||||
if aW < 0 or bW < 0 then
|
||||
return tq * (1 - biasAB), tq * biasAB
|
||||
end
|
||||
|
||||
local c = tq > 0 and powerRamp or coastRamp
|
||||
local totalW = math.abs(aW) + math.abs(bW)
|
||||
local slip = 0
|
||||
if aW > 0 or bW > 0 then
|
||||
slip = (aW - bW) / totalW
|
||||
end
|
||||
local dTq = slip * stiffness * c * slipTorque
|
||||
|
||||
return tq * (1 - biasAB) - dTq, tq * biasAB + dTq
|
||||
end
|
||||
|
||||
function Differential:_HLSDTorqueSplit(tq, aW, bW, aI, bI, biasAB, preload, stiffness, powerRamp, coastRamp, slipTorque)
|
||||
if aW < 0 or bW < 0 then
|
||||
return tq * (1 - biasAB), tq * biasAB
|
||||
end
|
||||
|
||||
local c = tq > 0 and powerRamp or coastRamp
|
||||
local tqFactor = math.clamp(math.abs(tq) / slipTorque, -1, 1)
|
||||
local totalW = math.abs(aW) + math.abs(bW)
|
||||
local slip = 0
|
||||
if aW > 0 or bW > 0 then
|
||||
slip = (aW - bW) / totalW
|
||||
end
|
||||
local dTq = slip * stiffness * c * slipTorque * tqFactor
|
||||
|
||||
return tq * (1 - biasAB) - dTq, tq * biasAB + dTq
|
||||
end
|
||||
|
||||
return Differential
|
||||
113
koptilnya/engine_remastered/powertrain/engine.txt
Normal file
113
koptilnya/engine_remastered/powertrain/engine.txt
Normal file
@@ -0,0 +1,113 @@
|
||||
--@include ./powertrain_component.txt
|
||||
--@include /koptilnya/libs/constants.txt
|
||||
|
||||
local PowertrainComponent = require('./powertrain_component.txt')
|
||||
|
||||
require('/koptilnya/libs/constants.txt')
|
||||
|
||||
local Engine = class('Engine', PowertrainComponent)
|
||||
|
||||
function Engine:initialize(vehicle, name, config)
|
||||
PowertrainComponent.initialize(self, vehicle, name, config)
|
||||
|
||||
self.wireInputs = {
|
||||
Throttle = 'number'
|
||||
}
|
||||
self.wireOutputs = {
|
||||
Engine_RPM = 'number',
|
||||
Engine_Torque = 'number',
|
||||
Engine_MasterThrottle = 'number',
|
||||
Engine_ReactTorque = 'number',
|
||||
Engine_ReturnedTorque = 'number',
|
||||
Engine_FinalTorque = 'number'
|
||||
}
|
||||
|
||||
self.idleRPM = config.IdleRPM or 900
|
||||
self.maxRPM = config.MaxRPM or 7000
|
||||
self.inertia = config.Inertia or 0.4
|
||||
self.startFriction = config.StartFriction or -50
|
||||
self.frictionCoeff = config.FrictionCoeff or 0.02
|
||||
self.limiterDuration = config.LimiterDuration or 0.05
|
||||
self.torqueMap = config.TorqueMap or {}
|
||||
|
||||
self.rpmFrac = 0
|
||||
self.friction = 0
|
||||
self.masterThrottle = 0
|
||||
|
||||
self.limiterTimer = 0
|
||||
|
||||
self.reactTorque = 0
|
||||
self.returnedTorque = 0
|
||||
end
|
||||
|
||||
function Engine:updateWireOutputs()
|
||||
wire.ports.Engine_RPM = self:getRPM()
|
||||
wire.ports.Engine_Torque = self.torque
|
||||
wire.ports.Engine_MasterThrottle = self.masterThrottle
|
||||
wire.ports.Engine_ReactTorque = self.reactTorque
|
||||
wire.ports.Engine_ReturnedTorque = self.returnedTorque
|
||||
wire.ports.Engine_FinalTorque = self.finalTorque
|
||||
end
|
||||
|
||||
function Engine:getThrottle()
|
||||
return wire.ports.Throttle
|
||||
end
|
||||
|
||||
function Engine:_generateTorque()
|
||||
local throttle = self:getThrottle()
|
||||
local rpm = self:getRPM()
|
||||
|
||||
local rpmFrac = math.clamp((rpm - self.idleRPM) / (self.maxRPM - self.idleRPM), 0, 1)
|
||||
self.friction = self.startFriction - self:getRPM() * self.frictionCoeff
|
||||
|
||||
local tqIdx = math.clamp(math.floor(rpmFrac * #self.torqueMap), 1, #self.torqueMap)
|
||||
local maxInitialTorque = self.torqueMap[tqIdx] - self.friction
|
||||
local idleFadeStart = math.clamp(math.remap(rpm, self.idleRPM - 300, self.idleRPM, 1, 0), 0, 1)
|
||||
local idleFadeEnd = math.clamp(math.remap(rpm, self.idleRPM, self.idleRPM + 600, 1, 0), 0, 1)
|
||||
local additionalEnergySupply = idleFadeEnd * (-self.friction / maxInitialTorque) + idleFadeStart
|
||||
|
||||
if rpm > self.maxRPM then
|
||||
throttle = 0
|
||||
self.limiterTimer = timer.systime()
|
||||
else
|
||||
throttle = timer.systime() >= self.limiterTimer + self.limiterDuration and throttle or 0
|
||||
end
|
||||
|
||||
self.masterThrottle = math.clamp(additionalEnergySupply + throttle, 0, 1)
|
||||
|
||||
local realInitialTorque = maxInitialTorque * self.masterThrottle
|
||||
|
||||
self.torque = realInitialTorque + self.friction
|
||||
|
||||
return self.torque
|
||||
end
|
||||
|
||||
function Engine:forwardStep()
|
||||
if self.output == nil then
|
||||
local generatedTorque = self:_generateTorque()
|
||||
|
||||
self.angularVelocity = self.angularVelocity + generatedTorque / self.inertia * TICK_INTERVAL
|
||||
self.angularVelocity = math.max(self.angularVelocity, 0)
|
||||
end
|
||||
|
||||
local outputInertia = self.output:queryInertia()
|
||||
local inertiaSum = self.inertia + outputInertia
|
||||
local outputW = self.output:queryAngularVelocity(self.angularVelocity)
|
||||
local targetW = self.inertia / inertiaSum * self.angularVelocity + outputInertia / inertiaSum * outputW
|
||||
|
||||
local generatedTorque = self:_generateTorque()
|
||||
local reactTorque = (targetW - self.angularVelocity) * self.inertia / TICK_INTERVAL
|
||||
local returnedTorque = self.output:forwardStep(generatedTorque - reactTorque, 0) -- ??? 0 -> self.inertia
|
||||
|
||||
self.reactTorque = reactTorque
|
||||
self.returnedTorque = returnedTorque
|
||||
|
||||
local finalTorque = generatedTorque + reactTorque + returnedTorque
|
||||
|
||||
self.finalTorque = finalTorque
|
||||
|
||||
self.angularVelocity = self.angularVelocity + finalTorque / inertiaSum * TICK_INTERVAL
|
||||
self.angularVelocity = math.max(self.angularVelocity, 0)
|
||||
end
|
||||
|
||||
return Engine
|
||||
66
koptilnya/engine_remastered/powertrain/gearboxes/base.txt
Normal file
66
koptilnya/engine_remastered/powertrain/gearboxes/base.txt
Normal file
@@ -0,0 +1,66 @@
|
||||
--@include ../powertrain_component.txt
|
||||
|
||||
local PowertrainComponent = require('../powertrain_component.txt')
|
||||
|
||||
local Gearbox = class('Gearbox', PowertrainComponent)
|
||||
|
||||
function Gearbox:initialize(vehicle, name, config)
|
||||
PowertrainComponent.initialize(self, vehicle, name, config)
|
||||
|
||||
self.wireInputs = {
|
||||
Upshift = 'number',
|
||||
Downshift = 'number'
|
||||
}
|
||||
self.wireOutputs = {
|
||||
Gearbox_RPM = 'number',
|
||||
Gearbox_Torque = 'number',
|
||||
Gearbox_Ratio = 'number'
|
||||
}
|
||||
|
||||
self.type = config.Type or 'MANUAL'
|
||||
self.inertia = config.Inertia or 1000
|
||||
|
||||
self.ratio = 0
|
||||
end
|
||||
|
||||
function Gearbox:updateWireOutputs()
|
||||
wire.ports.Gearbox_RPM = self:getRPM()
|
||||
wire.ports.Gearbox_Torque = self.torque
|
||||
wire.ports.Gearbox_Ratio = self.ratio
|
||||
end
|
||||
|
||||
function Gearbox:queryInertia()
|
||||
if self.output == nil or self.ratio == 0 then
|
||||
return self.inertia
|
||||
end
|
||||
|
||||
return self.inertia + self.output:queryInertia() / math.pow(self.ratio, 2)
|
||||
end
|
||||
|
||||
function Gearbox:queryAngularVelocity(angularVelocity)
|
||||
self.angularVelocity = angularVelocity
|
||||
|
||||
if self.output == nil or self.ratio == 0 then
|
||||
return angularVelocity
|
||||
end
|
||||
|
||||
return self.output:queryAngularVelocity(angularVelocity) * self.ratio
|
||||
end
|
||||
|
||||
function Gearbox:forwardStep(torque, inertia)
|
||||
if self.output == nil then
|
||||
return torque
|
||||
end
|
||||
|
||||
if self.ratio == 0 then
|
||||
self.output:forwardStep(0, self.inertia)
|
||||
|
||||
return torque
|
||||
end
|
||||
|
||||
self.torque = torque * self.ratio
|
||||
|
||||
return self.output:forwardStep(self.torque, (inertia + self.inertia) * math.pow(self.ratio, 2)) / self.ratio
|
||||
end
|
||||
|
||||
return Gearbox
|
||||
73
koptilnya/engine_remastered/powertrain/gearboxes/manual.txt
Normal file
73
koptilnya/engine_remastered/powertrain/gearboxes/manual.txt
Normal file
@@ -0,0 +1,73 @@
|
||||
--@include /koptilnya/libs/watcher.txt
|
||||
--@include ./base.txt
|
||||
|
||||
local BaseGearbox = require('./base.txt')
|
||||
|
||||
require('/koptilnya/libs/watcher.txt')
|
||||
|
||||
local ManualGearbox = class('ManualGearbox', BaseGearbox)
|
||||
|
||||
function ManualGearbox:initialize(vehicle, name, config)
|
||||
BaseGearbox.initialize(self, vehicle, name, config)
|
||||
|
||||
table.merge(self.wireOutputs, {
|
||||
Gearbox_Gear = 'number'
|
||||
})
|
||||
|
||||
self.ratios = config.Ratios or { 3.6, 2.2, 1.5, 1.2, 1.0, 0.8}
|
||||
self.reverse = config.Reverse or 3.4
|
||||
|
||||
self.gear = 0
|
||||
|
||||
function shiftFunc()
|
||||
local upshift = wire.ports.Upshift or 0
|
||||
local downshift = wire.ports.Downshift or 0
|
||||
|
||||
return upshift - downshift
|
||||
end
|
||||
|
||||
self.shiftWatcher = watcher(shiftFunc, function(val)
|
||||
if val ~= 0 then
|
||||
self:shift(val)
|
||||
end
|
||||
end)
|
||||
|
||||
self:recalcRatio()
|
||||
end
|
||||
|
||||
function ManualGearbox:updateWireOutputs()
|
||||
BaseGearbox.updateWireOutputs(self)
|
||||
|
||||
wire.ports.Gearbox_Gear = self.gear
|
||||
end
|
||||
|
||||
function ManualGearbox:setGear(gear)
|
||||
if gear >= -1 and gear <= #self.ratios then
|
||||
self.gear = gear
|
||||
self:recalcRatio()
|
||||
end
|
||||
end
|
||||
|
||||
function ManualGearbox:recalcRatio()
|
||||
if self.gear == -1 then
|
||||
self.ratio = -self.reverse
|
||||
elseif self.gear == 0 then
|
||||
self.ratio = 0
|
||||
else
|
||||
self.ratio = self.ratios[self.gear]
|
||||
end
|
||||
end
|
||||
|
||||
function ManualGearbox:shift(dir)
|
||||
self:setGear(self.gear + dir)
|
||||
end
|
||||
|
||||
function ManualGearbox:forwardStep(torque, inertia)
|
||||
local result = BaseGearbox.forwardStep(self, torque, inertia)
|
||||
|
||||
self.shiftWatcher()
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
return ManualGearbox
|
||||
@@ -0,0 +1,70 @@
|
||||
--@include /koptilnya/libs/constants.txt
|
||||
--@include ../wire_component.txt
|
||||
|
||||
local WireComponent = require('../wire_component.txt')
|
||||
|
||||
require('/koptilnya/libs/constants.txt')
|
||||
|
||||
local PowertrainComponent = class('PowertrainComponent', WireComponent)
|
||||
|
||||
function PowertrainComponent:initialize(vehicle, name, config)
|
||||
config = config or {}
|
||||
|
||||
WireComponent.initialize(self)
|
||||
|
||||
self.vehicle = vehicle
|
||||
self.name = name or 'PowertrainComponent'
|
||||
self.CONFIG = config
|
||||
self.input = nil
|
||||
self.output = nil
|
||||
|
||||
self.inertia = 0.02
|
||||
self.angularVelocity = 0
|
||||
self.torque = 0
|
||||
end
|
||||
|
||||
function PowertrainComponent:start()
|
||||
end
|
||||
|
||||
function PowertrainComponent:linkComponent(component)
|
||||
if not component:isInstanceOf(PowertrainComponent) then
|
||||
return
|
||||
end
|
||||
|
||||
if self.output == nil then
|
||||
self.output = component
|
||||
component.input = self
|
||||
end
|
||||
end
|
||||
|
||||
function PowertrainComponent:getRPM()
|
||||
return self.angularVelocity * RAD_TO_RPM
|
||||
end
|
||||
|
||||
function PowertrainComponent:queryInertia()
|
||||
if self.output == nil then
|
||||
return self.inertia
|
||||
end
|
||||
|
||||
return self.inertia + self.output:queryInertia()
|
||||
end
|
||||
|
||||
function PowertrainComponent:queryAngularVelocity(angularVelocity)
|
||||
self.angularVelocity = angularVelocity
|
||||
|
||||
if self.output == nil then
|
||||
return 0
|
||||
end
|
||||
|
||||
return self.output:queryAngularVelocity(angularVelocity)
|
||||
end
|
||||
|
||||
function PowertrainComponent:forwardStep(torque, inertia)
|
||||
if self.output == nil then
|
||||
return self.torque
|
||||
end
|
||||
|
||||
return self.output:forwardStep(self.torque, self.inertia + inertia)
|
||||
end
|
||||
|
||||
return PowertrainComponent
|
||||
122
koptilnya/engine_remastered/powertrain/wheel.txt
Normal file
122
koptilnya/engine_remastered/powertrain/wheel.txt
Normal file
@@ -0,0 +1,122 @@
|
||||
--@include ./powertrain_component.txt
|
||||
--@include ../wheel/wheel.txt
|
||||
--@include /koptilnya/libs/constants.txt
|
||||
--@include /koptilnya/libs/entity.txt
|
||||
|
||||
local PowertrainComponent = require('./powertrain_component.txt')
|
||||
local CustomWheel = require('../wheel/wheel.txt')
|
||||
|
||||
require('/koptilnya/libs/constants.txt')
|
||||
require('/koptilnya/libs/entity.txt')
|
||||
|
||||
local Wheel = class('Wheel', PowertrainComponent)
|
||||
|
||||
function Wheel:initialize(vehicle, name, config)
|
||||
PowertrainComponent.initialize(self, vehicle, name, config)
|
||||
|
||||
self.steerLock = config.SteerLock or 0
|
||||
self.brakePower = config.BrakePower or 0
|
||||
self.handbrakePower = config.HandbrakePower or 0
|
||||
|
||||
self.wireInputs = {
|
||||
[self.name] = 'entity'
|
||||
}
|
||||
self.wireOutputs = {
|
||||
[string.format('%s_RPM', self.name)] = 'number',
|
||||
[string.format('%s_Mz', self.name)] = 'number',
|
||||
[string.format('%s_Fz', self.name)] = 'number'
|
||||
}
|
||||
|
||||
self.entity = config.Entity or NULL_ENTITY
|
||||
self.holo = self:createHolo(self.entity)
|
||||
|
||||
self.customWheel = CustomWheel:new(config.CustomWheel)
|
||||
|
||||
hook.add('input', 'vehicle_wheel_update' .. self.name, function(name, value)
|
||||
if name == self.name then
|
||||
self.entity = value
|
||||
self.customWheel:setEntity(value)
|
||||
|
||||
if isValid(self.holo) then
|
||||
self.holo:remove()
|
||||
end
|
||||
|
||||
self.holo = self:createHolo(self.entity)
|
||||
|
||||
if not config.Radius then
|
||||
self.customWheel.radius = self:getEntityRadius()
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function Wheel:getEntityRadius()
|
||||
if not isValid(self.entity) then
|
||||
return 0
|
||||
end
|
||||
|
||||
return self.entity:getModelRadius() * UNITS_TO_METERS
|
||||
end
|
||||
|
||||
function Wheel:createHolo(entity)
|
||||
if not isValid(entity) then
|
||||
return NULL_ENTITY
|
||||
end
|
||||
|
||||
local holo = holograms.create(entity:getPos(), entity:getAngles(), 'models/props_c17/pulleywheels_small01.mdl')
|
||||
holo:setParent(entity)
|
||||
|
||||
return holo
|
||||
end
|
||||
|
||||
function Wheel:updateWireOutputs()
|
||||
wire.ports[string.format('%s_RPM', self.name)] = self.customWheel:getRPM()
|
||||
wire.ports[string.format('%s_Mz', self.name)] = self.customWheel.mz
|
||||
wire.ports[string.format('%s_Fz', self.name)] = self.customWheel.load
|
||||
end
|
||||
|
||||
function Wheel:queryInertia()
|
||||
return self.customWheel.inertia
|
||||
end
|
||||
|
||||
function Wheel:queryAngularVelocity()
|
||||
return self.angularVelocity
|
||||
end
|
||||
|
||||
function Wheel:forwardStep(torque, inertia)
|
||||
if not isValid(self.customWheel) then
|
||||
return 0
|
||||
end
|
||||
|
||||
self.customWheel.steerAngle = self.vehicle.steer * self.steerLock
|
||||
--self.customWheel.inertia = inertia
|
||||
--self.customWheel:setInertia(inertia)
|
||||
self.customWheel.motorTorque = torque
|
||||
self.customWheel.brakeTorque = math.max(self.brakePower * self.vehicle.brake, self.handbrakePower * self.vehicle.handbrake)
|
||||
|
||||
self.customWheel:update()
|
||||
|
||||
self.angularVelocity = self.customWheel.angularVelocity
|
||||
|
||||
if self.customWheel.hasHit and isValid(self.vehicle.basePhysObject) then
|
||||
local surfaceForceVector = self.customWheel.right * self.customWheel.sideFriction.force + self.customWheel.forward * self.customWheel.forwardFriction.force
|
||||
|
||||
self.vehicle.basePhysObject:applyForceOffset(surfaceForceVector, self.entity:getPos() - Vector(0, 0, self.customWheel.radius))
|
||||
end
|
||||
|
||||
if isValid(self.holo) then
|
||||
local angles = self.holo:getAngles()
|
||||
--local rot = angles:rotateAroundAxis(self.entity:getForward(), nil, 1)
|
||||
local rot = angles:rotateAroundAxis(self.entity:getRight(), nil, -self.angularVelocity * TICK_INTERVAL)
|
||||
--local steer = Angle():rotateAroundAxis(self.entity:getUp(), self.customWheel.steerAngle)
|
||||
--local rot = self.entity:getRight():getQuaternionFromAxis(-self.angularVelocity * TICK_INTERVAL)
|
||||
--local steer = self.entity:getUp():getQuaternionFromAxis(self.steerAngle)
|
||||
|
||||
--self.holo:setAngles(self.entity:localToWorldAngles(Angle(0, 90 - self.customWheel.steerAngle, 0)))
|
||||
self.holo:setAngles(rot)
|
||||
end
|
||||
|
||||
return self.customWheel.counterTorque
|
||||
end
|
||||
|
||||
return Wheel
|
||||
Reference in New Issue
Block a user