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