Moved engine to koptilnya folder

This commit is contained in:
Иван Грачёв 2021-03-28 18:30:08 +05:00
parent 5c854e183b
commit 191b13f6b4
6 changed files with 386 additions and 0 deletions

View File

@ -0,0 +1,3 @@
NULL_ENTITY = entity(0)
CURRENT_PLAYER = player()
OWNER = owner()

View 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

View 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

View 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

View 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

View 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