diff --git a/koptilnya/engine/clutch.txt b/koptilnya/engine/clutch.txt index b46df16..5ff835b 100644 --- a/koptilnya/engine/clutch.txt +++ b/koptilnya/engine/clutch.txt @@ -1,16 +1,39 @@ Clutch = class("Clutch") function Clutch:initialize(options) - options = options or {} + options = options or {} - self.stiffness = options.Stiffness or 0 - self.capacity = options.Capacity or 0 - self.damping = options.Damping or 0 + self.stiffness = options.Stiffness or 0 + self.capacity = options.Capacity or 0 + self.damping = options.Damping or 0 + self.maxTorque = options.MaxTorque or 0 - self._engine = options.Engine - self._gearbox = options.Gearbox + self.press = 1 + self.slip = 0 + self.targetTorque = 0 + self.torque = 0 + + self._engine = nil + self._gearbox = nil end function Clutch:update() - -end \ No newline at end of file + local someConversionCoeff = 0.10472 + + local engRPM = self._engine and self._engine.rpm or 0 + local gboxRPM = self._gearbox and self._gearbox.rpm or 0 + local gboxRatio = self._gearbox and self._gearbox.ratio or 0 + local gboxRatioNotZero = gboxRatio ~= 0 and 1 or 0 + + self.slip = (engRPM * someConversionCoeff - gboxRPM * someConversionCoeff) * gboxRatioNotZero / 2 + self.targetTorque = math.clamp(self.slip * self.stiffness * (1 - self.press), -self.maxTorque, self.maxTorque) + self.torque = math.lerp(self.torque, self.targetTorque, self.damping) +end + +function Clutch:linkEngine(engine) + self._engine = engine +end + +function Clutch:linkGearbox(gbox) + self._gearbox = gbox +end diff --git a/koptilnya/engine/engine.txt b/koptilnya/engine/engine.txt index 91f453b..1bd20cb 100644 --- a/koptilnya/engine/engine.txt +++ b/koptilnya/engine/engine.txt @@ -1,20 +1,73 @@ +-- @include ../libs/constants.txt +require("../libs/constants.txt") + Engine = class("Engine") function Engine:initialize(options) - options = options or {} + options = options or {} - self.idleRPM = options.IdleRPM or 800 - self.maxRPM = options.MaxRPM or 8000 + self.idleRPM = options.IdleRPM or 800 + self.maxRPM = options.MaxRPM or 8000 - self.flywheelMass = options.FlywheelMass or 4 - self.flywheelRadius = options.FlywheelRadius or 0.3 + self.flywheelMass = options.FlywheelMass or 4 + self.flywheelRadius = options.FlywheelRadius or 0.3 - self.startFriction = options.StartFriction or -30 - self.frictionCoeff = options.FrictionCoeff or 0.02 + self.startFriction = options.StartFriction or -30 + self.frictionCoeff = options.FrictionCoeff or 0.02 - self.limiterDuration = options.LimiterDuration or 0.05 + self.limiterDuration = options.LimiterDuration or 0.05 - self.torqueMap = options.TorqueMap or {} + self.torqueMap = options.TorqueMap or {} - self.throttle = 0 -end \ No newline at end of file + self.throttle = 0 + + self.torque = 0 + self.rpmFrac = 0 + self.rpm = self.idleRPM + self.friction = 0 + + self._fwInertia = self.flywheelMass * self.flywheelRadius ^ 2 / 2 + self._limiterTime = 0 + + self._clutch = nil +end + +function Engine:setThrottle(throttle) + self.throttle = throttle +end + +function Engine:linkClutch(clutch) + self._clutch = clutch + clutch:linkEngine(self) +end + +function Engine:update() + self.rpmFrac = math.clamp((self.rpm - self.idleRPM) / (self.maxRPM - self.idleRPM), 0, 1) + self.friction = self.startFriction - self.rpm * self.frictionCoeff + + local tqIdx = math.clamp(math.floor(self.rpmFrac * #self.torqueMap), 1, #self.torqueMap) + local maxInitialTorque = self.torqueMap[tqIdx] - self.friction + + local idleFadeStart = math.clamp(math.remap(self.rpm, self.idleRPM - 300, self.idleRPM, 1, 0), 0, 1) + local idleFadeEnd = math.clamp(math.remap(self.rpm, self.idleRPM, self.idleRPM + 600, 1, 0), 0, 1) + + local additionalEnergySupply = idleFadeEnd * (-self.friction / maxInitialTorque) + idleFadeStart + + if self.rpm > self.maxRPM then + self.throttle = 0 + self._limiterTime = os.time() + else + self.throttle = os.time() >= self._limiterTime + self.limiterDuration and self.throttle or 0 + end + + local masterThrottle = math.clamp(additionalEnergySupply + self.throttle, 0, 1) + + local realInitialTorque = maxInitialTorque * masterThrottle + + local loadTorque = self._clutch and self._clutch.torque or 0 + + self.torque = realInitialTorque + self.friction + + self.rpm = self.rpm + (self.torque - loadTorque) / self._fwInertia * RAD_TO_RPM * TICK_INTERVAL + self.rpm = math.max(self.rpm, 0) +end diff --git a/koptilnya/engine/gearboxes/base.txt b/koptilnya/engine/gearboxes/base.txt index 7a2d4ff..d517f85 100644 --- a/koptilnya/engine/gearboxes/base.txt +++ b/koptilnya/engine/gearboxes/base.txt @@ -1,18 +1,20 @@ Gearbox = class("Gearbox") function Gearbox:initialize(options) - options = options or {} + options = options or {} - self.ratios = options.ratios - self.finalDrive = options.finalDrive + self.ratios = options.Ratios + self.finalDrive = options.FinalDrive + self.reverse = options.Reverse - self._linkedDiffs = {} + self.gear = 0 - self.gear = 0 + self._linkedDiffs = {} + self._clutch = nil end function Gearbox:linkDiff(diff) - table.insert(self._linkedDiffs, diff) + table.insert(self._linkedDiffs, diff) end function Gearbox:shift(dir) @@ -20,9 +22,16 @@ function Gearbox:shift(dir) end function Gearbox:setGear(gear) - self.gear = gear + if gear >= -1 and gear <= #self.ratios then + self.gear = gear + end +end + +function Gearbox:linkClutch(clutch) + self._clutch = clutch + clutch:linkGearbox(self) end function Gearbox:update() - -end \ No newline at end of file + +end diff --git a/koptilnya/engine/gearboxes/cvt.txt b/koptilnya/engine/gearboxes/cvt.txt index e370381..020d20b 100644 --- a/koptilnya/engine/gearboxes/cvt.txt +++ b/koptilnya/engine/gearboxes/cvt.txt @@ -1,4 +1,10 @@ -- @include ./base.txt require("./base.txt") -CVT = class("CVT") \ No newline at end of file +CVT = class("CVT") + +function CVT:initialize(options) + options = options or {} + + self.base = Gearbox:new(options) +end diff --git a/koptilnya/engine/gearboxes/manual.txt b/koptilnya/engine/gearboxes/manual.txt index 9257c4f..2f7da78 100644 --- a/koptilnya/engine/gearboxes/manual.txt +++ b/koptilnya/engine/gearboxes/manual.txt @@ -4,7 +4,14 @@ require("./base.txt") ManualGearbox = class("ManualGearbox") function ManualGearbox:initialize(options) - -- create base gearbox inside + options = options or {} + + -- might want to segregate construction options for base gearbox + self.base = Gearbox:new(options) end --- proxy the methods here \ No newline at end of file +function ManualGearbox:linkClutch(clutch) + return self.base:linkClutch(clutch) +end + +-- proxy the methods here diff --git a/koptilnya/engine/main.txt b/koptilnya/engine/main.txt index c3f0e1b..94685d9 100644 --- a/koptilnya/engine/main.txt +++ b/koptilnya/engine/main.txt @@ -1,9 +1,11 @@ -- @name Koptilnya Engine -- @author Koptilnya1337 --- @shared +-- @server -- -- @include ./engine.txt -- +-- @include ./clutch.txt +-- -- @include ./gearboxes/manual.txt -- @include ./gearboxes/cvt.txt -- @include ./gearboxes/auto.txt @@ -13,6 +15,8 @@ -- @include ./configs/audi_tt.txt require("./engine.txt") -- +require("./clutch.txt") +-- require("./gearboxes/manual.txt") require("./gearboxes/cvt.txt") require("./gearboxes/auto.txt") @@ -21,22 +25,54 @@ require("./differential.txt") -- require("./configs/audi_tt.txt") -if SERVER then - function adjustPorts() - wire.adjustPorts({ - Input = "table" - }, { - RPM = "number" - }) - end +ECU = class("ECU") - function setupHooks() +function ECU:initialize(options) + options = options or {} - end + self.engine = options.Engine + self.clutch = options.Clutch + self.gearbox = options.Gearbox + self.differentials = options.Differentials + self.input = {} - adjustPorts() - -- printTable(config) -else + self:adjustPorts() + hook.add('tick', 'ecu_update', function() + self:update() + end) end +function ECU:adjustPorts() + wire.adjustPorts({ + Input = "table" + }, { + RPM = "number", + Torque = "number" + }) +end + +function ECU:update() + wire.ports.RPM = self.engine.rpm + wire.ports.Torque = self.engine.torque + + self.input = wire.ports.Input + + self.engine:setThrottle(self.input.Throttle.Value) + self.engine:update() +end + +local clutch = Clutch:new(config.Clutch) + +local engine = Engine:new(config.Engine) +engine:linkClutch(clutch) + +local gearbox = ManualGearbox:new(config.Gearbox) +gearbox:linkClutch(clutch) + +local ecu = ECU:new({ + Engine = engine, + Clutch = clutch + -- Gearbox = gearbox +}) +-- printTable(config) diff --git a/koptilnya/libs/constants.txt b/koptilnya/libs/constants.txt index fee1b0f..b9e1c6f 100644 --- a/koptilnya/libs/constants.txt +++ b/koptilnya/libs/constants.txt @@ -1,3 +1,5 @@ NULL_ENTITY = entity(0) CURRENT_PLAYER = player() -OWNER = owner() \ No newline at end of file +OWNER = owner() +TICK_INTERVAL = game.getTickInterval() +RAD_TO_RPM = 9.5493 \ No newline at end of file