-- @include ./wire_component.txt -- @include /koptilnya/libs/constants.txt require('./wire_component.txt') require('/koptilnya/libs/constants.txt') Engine = class('Engine', WireComponent) function Engine:initialize(config, clutch) self.idleRPM = config.IdleRPM self.maxRPM = config.MaxRPM self.flywheelMass = config.FlywheelMass self.flywheelRadius = config.FlywheelRadius self.startFriction = config.StartFriction self.frictionCoeff = config.FrictionCoeff self.torque = 0 self.rpmFrac = 0 self.rpm = self.idleRPM self.friction = 0 self.limiterDuration = config.LimiterDuration self.torqueMap = config.TorqueMap or {} self._fwInertia = self.flywheelMass * self.flywheelRadius ^ 2 / 2 self._limiterTime = 0 self._clutch = clutch end function Engine:getInputs() return { Throttle = 'number' } end function Engine:getOutputs() return { RPM = 'number', Torque = 'number' } end function Engine:updateOutputs() wire.ports.RPM = self.rpm wire.ports.Torque = self.torque end function Engine:getThrottle() return wire.ports.Throttle end function Engine:update() local throttle = self:getThrottle() 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 throttle = 0 self._limiterTime = timer.systime() else throttle = timer.systime() >= self._limiterTime + self.limiterDuration and throttle or 0 end local masterThrottle = math.clamp(additionalEnergySupply + 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