Moved engine to koptilnya folder
This commit is contained in:
parent
5c854e183b
commit
191b13f6b4
3
koptilnya/engine_rework/constants.txt
Normal file
3
koptilnya/engine_rework/constants.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
NULL_ENTITY = entity(0)
|
||||||
|
CURRENT_PLAYER = player()
|
||||||
|
OWNER = owner()
|
||||||
132
koptilnya/engine_rework/controller.txt
Normal file
132
koptilnya/engine_rework/controller.txt
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
-- @name Engine
|
||||||
|
-- @author DarkSupah, Opti1337, .hemp
|
||||||
|
-- @shared
|
||||||
|
-- @include ./constants.txt
|
||||||
|
-- @include ./engine.txt
|
||||||
|
-- @include ./gearbox.txt
|
||||||
|
-- @include ./input.txt
|
||||||
|
require("./constants.txt")
|
||||||
|
require("./engine.txt")
|
||||||
|
require("./gearbox.txt")
|
||||||
|
require("./input.txt")
|
||||||
|
|
||||||
|
local configPath = "engine/"
|
||||||
|
|
||||||
|
local inputConfigPath = "input.json"
|
||||||
|
local engineConfigPath = "engine.json"
|
||||||
|
local gearboxConfigPath = "gearbox.json"
|
||||||
|
|
||||||
|
Controller = class("Controller")
|
||||||
|
|
||||||
|
function Controller:initialize(inputController, engine, gearbox, axles)
|
||||||
|
self.inputController = inputController
|
||||||
|
self.engine = engine
|
||||||
|
self.gearbox = gearbox
|
||||||
|
self.axles = axles
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
hook.add("PlayerEnteredVehicle", "enterHandler", function(ply, vehicle)
|
||||||
|
if (vehicle == wire.ports.Seat) then
|
||||||
|
self.inputController:setPlayer(ply)
|
||||||
|
hook.run("DriverChanged", ply)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
hook.add("PlayerLeaveVehicle", "exitHandler", function(ply, vehicle)
|
||||||
|
if (vehicle == wire.ports.Seat) then
|
||||||
|
self.inputController:setPlayer(NULL_ENTITY)
|
||||||
|
hook.run("DriverChanged", NULL_ENTITY)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
net.receive("serverConfigs", function()
|
||||||
|
local inputConfig = net.readTable()
|
||||||
|
local engineConfig = net.readTable()
|
||||||
|
local gearboxConfig = net.readTable()
|
||||||
|
|
||||||
|
self.inputController:setConfig(inputConfig)
|
||||||
|
self.engine:setConfig(engineConfig)
|
||||||
|
self.gearbox:setConfig(gearboxConfig)
|
||||||
|
|
||||||
|
net.start("clientConfigs")
|
||||||
|
net.writeTable(inputConfig)
|
||||||
|
net.writeTable(engineConfig)
|
||||||
|
net.writeTable(gearboxConfig)
|
||||||
|
net.send()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
if CLIENT then
|
||||||
|
net.receive("clientConfigs", function()
|
||||||
|
self.inputController:setConfig(net.readTable())
|
||||||
|
self.engine:setConfig(net.readTable())
|
||||||
|
self.gearbox:setConfig(net.readTable())
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function Controller:update()
|
||||||
|
self.inputController:update()
|
||||||
|
self.engine:update()
|
||||||
|
self.gearbox:update()
|
||||||
|
|
||||||
|
self.engine:setThrottle(self.inputController.throttle.value)
|
||||||
|
end
|
||||||
|
|
||||||
|
local inputController = InputController:new()
|
||||||
|
|
||||||
|
local engine = Engine:new()
|
||||||
|
local gearbox = Gearbox:new()
|
||||||
|
|
||||||
|
local controller = Controller:new(inputController, engine, gearbox)
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
wire.adjustPorts({
|
||||||
|
Seat = "entity"
|
||||||
|
}, {
|
||||||
|
Input = "table",
|
||||||
|
Engine = "table"
|
||||||
|
})
|
||||||
|
|
||||||
|
if wire.ports.Seat:isValid() then
|
||||||
|
local possibleDriver = wire.ports.Seat:getDriver()
|
||||||
|
|
||||||
|
if possibleDriver:isValid() then
|
||||||
|
controller.inputController:setPlayer(possibleDriver)
|
||||||
|
wire.ports.Driver = possibleDriver
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
hook.add("DriverChanged", "driverChangeHandler", function(ply)
|
||||||
|
wire.ports.Driver = ply
|
||||||
|
end)
|
||||||
|
|
||||||
|
hook.add("tick", "update", function()
|
||||||
|
controller:update()
|
||||||
|
|
||||||
|
wire.ports.Engine = controller.engine
|
||||||
|
wire.ports.Input = controller.inputController
|
||||||
|
|
||||||
|
end)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
if CLIENT then
|
||||||
|
if CURRENT_PLAYER == OWNER then
|
||||||
|
local inputConfigFile = file.read(configPath .. inputConfigPath)
|
||||||
|
local inputConfig = json.decode(inputConfigFile)
|
||||||
|
|
||||||
|
local engineConfigFile = file.read(configPath .. engineConfigPath)
|
||||||
|
local engineConfig = json.decode(engineConfigFile)
|
||||||
|
|
||||||
|
local gearboxConfigFile = file.read(configPath .. gearboxConfigPath)
|
||||||
|
local gearboxConfig = json.decode(gearboxConfigFile)
|
||||||
|
|
||||||
|
net.start("serverConfigs")
|
||||||
|
net.writeTable(inputConfig)
|
||||||
|
net.writeTable(engineConfig)
|
||||||
|
net.writeTable(gearboxConfig)
|
||||||
|
net.send()
|
||||||
|
end
|
||||||
|
end
|
||||||
121
koptilnya/engine_rework/engine.txt
Normal file
121
koptilnya/engine_rework/engine.txt
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
-- @include ./math.txt
|
||||||
|
require("./math.txt")
|
||||||
|
|
||||||
|
Engine = class("Engine")
|
||||||
|
|
||||||
|
function Engine:initialize()
|
||||||
|
self.config = {}
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
self.active = true
|
||||||
|
|
||||||
|
self.desiredRPM = 0
|
||||||
|
self.RPM = 0
|
||||||
|
|
||||||
|
self.throttle = 0
|
||||||
|
|
||||||
|
self.flywheelInertiaMoment = 0
|
||||||
|
self.volume = 0
|
||||||
|
self.peakTq = 0
|
||||||
|
self.torque = 0
|
||||||
|
self.power = 0
|
||||||
|
|
||||||
|
self.gearboxRPM = 0
|
||||||
|
|
||||||
|
self.torqueTable = {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
|
||||||
|
function Engine:setThrottle(throttle)
|
||||||
|
self.throttle = throttle
|
||||||
|
end
|
||||||
|
|
||||||
|
function Engine:update()
|
||||||
|
-- check if config table is not empty
|
||||||
|
if next(self.config) ~= nil then
|
||||||
|
local activeCoeff = self.active and 1 or 0
|
||||||
|
|
||||||
|
self.desiredRPM = self.throttle * self.config.maxRPM + self.config.idleRPM
|
||||||
|
|
||||||
|
local masterThrottle = activeCoeff * self.RPM > self.config.maxRPM and 0 or 1
|
||||||
|
|
||||||
|
self.RPM = math.lerp(1 / (self.flywheelInertiaMoment * 100), self.RPM, self.desiredRPM * masterThrottle)
|
||||||
|
|
||||||
|
self:calculateTorque()
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function Engine:updateStats()
|
||||||
|
local bore = self.config.bore
|
||||||
|
local stroke = self.config.stroke
|
||||||
|
local flywheelMass = self.config.flywheelMass
|
||||||
|
local cylinders = self.config.cylinders
|
||||||
|
local BMEP = self.config.BMEP
|
||||||
|
|
||||||
|
self.flywheelInertiaMoment = (stroke / 1000) * flywheelMass
|
||||||
|
|
||||||
|
self.volume = math.floor((bore / 2) ^ 2 * stroke * cylinders * math.pi / 1000)
|
||||||
|
|
||||||
|
self.peakTq = (stroke / bore) * self.volume * BMEP / 100
|
||||||
|
|
||||||
|
self.torqueTable = {}
|
||||||
|
|
||||||
|
for i = 1, #self.config.curve do
|
||||||
|
table.insert(self.torqueTable, self:getTorqueValue(i / #self.config.curve))
|
||||||
|
end
|
||||||
|
|
||||||
|
print("Peak Torque: " .. math.ceil(self.peakTq) .. "nm")
|
||||||
|
end
|
||||||
|
|
||||||
|
function Engine:calculateTorque()
|
||||||
|
local RPMfrac = math.min(1, self.RPM / self.config.maxRPM)
|
||||||
|
local tableCount = table.count(self.torqueTable)
|
||||||
|
|
||||||
|
local lerpTo = math.ceil(RPMfrac * tableCount)
|
||||||
|
local lerpFrom = math.floor(RPMfrac * tableCount)
|
||||||
|
|
||||||
|
local lerpToVal = self.torqueTable[lerpTo] or 0
|
||||||
|
local lerpFromVal = self.torqueTable[lerpFrom] or 0
|
||||||
|
|
||||||
|
local frac = (RPMfrac * tableCount) % 1
|
||||||
|
local minActiveThrottle = self.config.idleRPM / self.config.maxRPM
|
||||||
|
|
||||||
|
local value = math.max(minActiveThrottle, self.throttle) * math.lerp(frac, lerpFromVal, lerpToVal) * self.peakTq
|
||||||
|
|
||||||
|
local overdrive = math.clamp(1 - self.gearboxRPM / self.desiredRPM, -1, 0)
|
||||||
|
|
||||||
|
local idleRPM = self.config.idleRPM
|
||||||
|
local maxRPM = self.config.maxRPM
|
||||||
|
local brakeTorqueCoeff = self.config.brakeTorqueCoeff
|
||||||
|
|
||||||
|
local brakeTorque = -value * math.max(1 - self.throttle, idleRPM / maxRPM, -overdrive) *
|
||||||
|
(self.gearboxRPM / maxRPM) * brakeTorqueCoeff
|
||||||
|
|
||||||
|
local RPMLimiter = math.clamp(1 - self.throttle * (self.gearboxRPM / self.desiredRPM), self.throttle, 1)
|
||||||
|
local netTq = value * math.max(self.throttle, idleRPM / maxRPM) * RPMLimiter + brakeTorque
|
||||||
|
|
||||||
|
self.torque = netTq
|
||||||
|
end
|
||||||
|
|
||||||
|
function Engine:getTorqueValue(num)
|
||||||
|
local torque = 0
|
||||||
|
|
||||||
|
for key, segment in pairs(self.config.curve) do
|
||||||
|
torque = torque + segment * polinom(key, table.count(self.config.curve), num)
|
||||||
|
end
|
||||||
|
|
||||||
|
return torque
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function Engine:setConfig(config)
|
||||||
|
self.config = config
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
self:updateStats()
|
||||||
|
end
|
||||||
|
end
|
||||||
13
koptilnya/engine_rework/gearbox.txt
Normal file
13
koptilnya/engine_rework/gearbox.txt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
Gearbox = class("Gearbox")
|
||||||
|
|
||||||
|
function Gearbox:initialize()
|
||||||
|
self.config = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
function Gearbox:update()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function Gearbox:setConfig(config)
|
||||||
|
self.config = config
|
||||||
|
end
|
||||||
104
koptilnya/engine_rework/input.txt
Normal file
104
koptilnya/engine_rework/input.txt
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
-- @include ./constants.txt
|
||||||
|
require("./constants.txt")
|
||||||
|
|
||||||
|
InputController = class("InputController")
|
||||||
|
|
||||||
|
function InputController:initialize()
|
||||||
|
self.ply = NULL_ENTITY
|
||||||
|
|
||||||
|
self.config = {} -- keys and pedal speed config
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
self.throttle = {
|
||||||
|
target = 0,
|
||||||
|
value = 0
|
||||||
|
}
|
||||||
|
self.brake = {
|
||||||
|
target = 0,
|
||||||
|
value = 0
|
||||||
|
}
|
||||||
|
self.clutch = {
|
||||||
|
target = 0,
|
||||||
|
value = 0
|
||||||
|
}
|
||||||
|
self.start = {
|
||||||
|
target = 0,
|
||||||
|
value = 0,
|
||||||
|
type = "keyPress"
|
||||||
|
}
|
||||||
|
|
||||||
|
net.receive("input", function()
|
||||||
|
local inputName = net.readString()
|
||||||
|
local target = net.readBool()
|
||||||
|
|
||||||
|
if self[inputName] then
|
||||||
|
self[inputName].target = target and (self.config[inputName] and self.config[inputName].max or 1) or 0
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
if CLIENT then
|
||||||
|
function setTargetInput(pressedKey, target)
|
||||||
|
local key = string.upper(input.getKeyName(pressedKey))
|
||||||
|
|
||||||
|
if self.keyToInputName[key] then
|
||||||
|
net.start("input")
|
||||||
|
net.writeString(self.keyToInputName[key].inputName)
|
||||||
|
net.writeBool(target)
|
||||||
|
net.send()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
hook.add("inputPressed", "inputPress", function(key)
|
||||||
|
if (self.ply ~= NULL_ENTITY and self.ply == CURRENT_PLAYER) then
|
||||||
|
setTargetInput(key, true)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
hook.add("inputReleased", "inputRelease", function(key)
|
||||||
|
if (self.ply ~= NULL_ENTITY and self.ply == CURRENT_PLAYER) then
|
||||||
|
setTargetInput(key, false)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
net.receive("changePlayer", function()
|
||||||
|
self.ply = net.readEntity()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
function InputController:setPlayer(ply)
|
||||||
|
self.ply = ply
|
||||||
|
net.start("changePlayer")
|
||||||
|
net.writeEntity(ply or NULL_ENTITY)
|
||||||
|
net.send()
|
||||||
|
end
|
||||||
|
|
||||||
|
function InputController:update()
|
||||||
|
for key in pairs(self.config) do
|
||||||
|
if self[key] then
|
||||||
|
local pressSpeed = self.config[key].press or 1
|
||||||
|
local releaseSpeed = self.config[key].release or 1
|
||||||
|
|
||||||
|
self[key].value = math.lerp(self[key].target == 1 and pressSpeed or releaseSpeed, self[key].value,
|
||||||
|
self[key].target)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function InputController:setConfig(config)
|
||||||
|
self.config = table.copy(config)
|
||||||
|
|
||||||
|
local keyToInputName = {}
|
||||||
|
|
||||||
|
for key, value in pairs(config) do
|
||||||
|
keyToInputName[string.upper(value.key)] = {
|
||||||
|
inputName = key
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
self.keyToInputName = table.copy(keyToInputName)
|
||||||
|
end
|
||||||
13
koptilnya/engine_rework/math.txt
Normal file
13
koptilnya/engine_rework/math.txt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
function factorial(number)
|
||||||
|
local res = 1
|
||||||
|
|
||||||
|
for i = 1, number do
|
||||||
|
res = i * res
|
||||||
|
end
|
||||||
|
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
function polinom(i, n, t)
|
||||||
|
return factorial(n) / (factorial(i) * factorial(n - i)) * (t ^ i) * (1 - t) ^ (n - i)
|
||||||
|
end
|
||||||
Loading…
x
Reference in New Issue
Block a user