From a6c89e2f21904e60fe16a65b9ea13e60d56d6b8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=B8=D1=82=D0=B0=20=D0=9A=D1=80=D1=83?= =?UTF-8?q?=D0=B3=D0=BB=D0=B8=D1=86=D0=BA=D0=B8=D0=B9?= Date: Sun, 11 May 2025 08:18:33 +0600 Subject: [PATCH] update --- .../engine_remastered/configs/new_sx240.txt | 6 +- .../engine_remastered/powertrain/clutch.txt | 4 + .../powertrain/differential.txt | 4 + .../engine_remastered/powertrain/engine.txt | 18 +++- .../powertrain/gearboxes/base.txt | 4 + .../powertrain/gearboxes/manual.txt | 2 + .../powertrain/powertrain_component.txt | 27 ++++++ .../engine_remastered/powertrain/wheel.txt | 68 ++++++++------ koptilnya/engine_remastered/vehicle.txt | 41 +++++---- .../engine_remastered/wire_component.txt | 2 + koptilnya/engine_sound.txt | 4 +- koptilnya/engine_sound_2.txt | 89 +++++++++++++++++++ koptilnya/libs/utils.txt | 11 +++ 13 files changed, 229 insertions(+), 51 deletions(-) create mode 100644 koptilnya/engine_sound_2.txt diff --git a/koptilnya/engine_remastered/configs/new_sx240.txt b/koptilnya/engine_remastered/configs/new_sx240.txt index f3f417b..bf1384e 100644 --- a/koptilnya/engine_remastered/configs/new_sx240.txt +++ b/koptilnya/engine_remastered/configs/new_sx240.txt @@ -1,6 +1,5 @@ --@name SX 240 --@author Koptilnya ---@server --@include /koptilnya/engine_remastered/vehicle.txt --@include /koptilnya/engine_remastered/powertrain/differential.txt @@ -8,8 +7,9 @@ local Vehicle, POWERTRAIN_COMPONENT = unpack(require('/koptilnya/engine_remaster local Differential = require('/koptilnya/engine_remastered/powertrain/differential.txt') local WheelConfig = { + DEBUG = true, BrakePower = 1200, - CustomWheel = { Mass = 80 }, + CustomWheel = { Mass = 80 }, Model = 'models/sprops/trans/wheel_a/wheel25.mdl' } local FrontWheelsConfig = table.merge(table.copy(WheelConfig), { SteerLock = 33, CustomWheel = { CasterAngle = 3 } }) @@ -25,7 +25,7 @@ Vehicle:new({ Inertia = 0.151, StartFriction = -10, FrictionCoeff = 0.01, - LimiterDuration = 0.08, + LimiterDuration = 0.06, TorqueMap = { 118.89918444138, 122.0751393736, 125.25109430583, 128.42704923806, 131.60300417029, 134.77895910251, 137.95491403474, 141.13086896697, 144.3068238992, 147.48277883143, 150.65873376365, 153.83468869588, 157.01064362811, 160.18659856034, 163.36255349256, 166.53850842479, 169.71446335702, 172.89041828925, 176.06637322148, 179.2423281537, 182.41828308593, 185.59423801816, 188.77019295039, 191.94614788261, 195.12210281484, 198.29805774707, 201.4740126793, 204.64996761153, 207.82592254375, 211.00187747598, diff --git a/koptilnya/engine_remastered/powertrain/clutch.txt b/koptilnya/engine_remastered/powertrain/clutch.txt index 8cebf49..4e456f2 100644 --- a/koptilnya/engine_remastered/powertrain/clutch.txt +++ b/koptilnya/engine_remastered/powertrain/clutch.txt @@ -10,6 +10,8 @@ local Clutch = class('Clutch', PowertrainComponent) function Clutch:initialize(vehicle, name, config) PowertrainComponent.initialize(self, vehicle, name, config) + if CLIENT then return end + self.wireInputs = { Clutch = 'number' } @@ -22,6 +24,8 @@ function Clutch:initialize(vehicle, name, config) end function Clutch:updateWireOutputs() + PowertrainComponent.updateWireOutputs(self) + wire.ports.Clutch_Torque = self.torque end diff --git a/koptilnya/engine_remastered/powertrain/differential.txt b/koptilnya/engine_remastered/powertrain/differential.txt index 271e8f6..0a17f81 100644 --- a/koptilnya/engine_remastered/powertrain/differential.txt +++ b/koptilnya/engine_remastered/powertrain/differential.txt @@ -15,6 +15,8 @@ end function Differential:initialize(vehicle, name, config) PowertrainComponent.initialize(self, vehicle, name, config) + if CLIENT then return end + self.wireOutputs = { Diff_Torque = 'number' } @@ -48,6 +50,8 @@ function Differential:linkComponent(component) end function Differential:updateWireOutputs() + PowertrainComponent.updateWireOutputs(self) + wire.ports.Diff_Torque = self.torque if self.outputA ~= nil then diff --git a/koptilnya/engine_remastered/powertrain/engine.txt b/koptilnya/engine_remastered/powertrain/engine.txt index 3552d96..339809a 100644 --- a/koptilnya/engine_remastered/powertrain/engine.txt +++ b/koptilnya/engine_remastered/powertrain/engine.txt @@ -3,6 +3,8 @@ local PowertrainComponent = require('./powertrain_component.txt') + + require('/koptilnya/libs/constants.txt') local Engine = class('Engine', PowertrainComponent) @@ -38,9 +40,18 @@ function Engine:initialize(vehicle, name, config) self.reactTorque = 0 self.returnedTorque = 0 + + if CLIENT then + --@include /koptilnya/engine_sound_2.txt + local Sound = require('/koptilnya/engine_sound_2.txt') + + Sound(config.MaxRPM or 7000, chip()) + end end function Engine:updateWireOutputs() + PowertrainComponent.updateWireOutputs(self) + wire.ports.Engine_RPM = self:getRPM() wire.ports.Engine_Torque = self.torque wire.ports.Engine_MasterThrottle = self.masterThrottle @@ -97,7 +108,7 @@ function Engine:forwardStep() local generatedTorque = self:_generateTorque() local reactTorque = (targetW - self.angularVelocity) * self.inertia / TICK_INTERVAL - local returnedTorque = self.output:forwardStep(generatedTorque - reactTorque, 0) -- ??? 0 -> self.inertia + local returnedTorque = self.output:forwardStep(generatedTorque - reactTorque, self.inertia) -- ??? 0 -> self.inertia self.reactTorque = reactTorque self.returnedTorque = returnedTorque @@ -108,6 +119,11 @@ function Engine:forwardStep() self.angularVelocity = self.angularVelocity + finalTorque / inertiaSum * TICK_INTERVAL self.angularVelocity = math.max(self.angularVelocity, 0) + + net.start("ENGINE_FULLRPM") + net.writeUInt(self:getRPM(), 16) + net.writeFloat(self.masterThrottle) + net.send(nil, true) end return Engine diff --git a/koptilnya/engine_remastered/powertrain/gearboxes/base.txt b/koptilnya/engine_remastered/powertrain/gearboxes/base.txt index 4b77170..e2e782e 100644 --- a/koptilnya/engine_remastered/powertrain/gearboxes/base.txt +++ b/koptilnya/engine_remastered/powertrain/gearboxes/base.txt @@ -7,6 +7,8 @@ local Gearbox = class('Gearbox', PowertrainComponent) function Gearbox:initialize(vehicle, name, config) PowertrainComponent.initialize(self, vehicle, name, config) + if CLIENT then return end + self.wireInputs = { Upshift = 'number', Downshift = 'number' @@ -24,6 +26,8 @@ function Gearbox:initialize(vehicle, name, config) end function Gearbox:updateWireOutputs() + PowertrainComponent.updateWireOutputs(self) + wire.ports.Gearbox_RPM = self:getRPM() wire.ports.Gearbox_Torque = self.torque wire.ports.Gearbox_Ratio = self.ratio diff --git a/koptilnya/engine_remastered/powertrain/gearboxes/manual.txt b/koptilnya/engine_remastered/powertrain/gearboxes/manual.txt index 97d5961..9e08aed 100644 --- a/koptilnya/engine_remastered/powertrain/gearboxes/manual.txt +++ b/koptilnya/engine_remastered/powertrain/gearboxes/manual.txt @@ -10,6 +10,8 @@ local ManualGearbox = class('ManualGearbox', BaseGearbox) function ManualGearbox:initialize(vehicle, name, config) BaseGearbox.initialize(self, vehicle, name, config) + if CLIENT then return end + table.merge(self.wireOutputs, { Gearbox_Gear = 'number' }) diff --git a/koptilnya/engine_remastered/powertrain/powertrain_component.txt b/koptilnya/engine_remastered/powertrain/powertrain_component.txt index 27f0b6f..f9343df 100644 --- a/koptilnya/engine_remastered/powertrain/powertrain_component.txt +++ b/koptilnya/engine_remastered/powertrain/powertrain_component.txt @@ -1,9 +1,11 @@ --@include /koptilnya/libs/constants.txt +--@include /koptilnya/libs/utils.txt --@include ../wire_component.txt local WireComponent = require('../wire_component.txt') require('/koptilnya/libs/constants.txt') +require('/koptilnya/libs/utils.txt') local PowertrainComponent = class('PowertrainComponent', WireComponent) @@ -15,12 +17,29 @@ function PowertrainComponent:initialize(vehicle, name, config) self.vehicle = vehicle self.name = name or 'PowertrainComponent' self.CONFIG = config + self.DEBUG = config.DEBUG or false self.input = nil self.output = nil self.inertia = 0.02 self.angularVelocity = 0 self.torque = 0 + + self.DEBUG_DATA = {} + + if self.DEBUG then + if CLIENT then + net.receive('DEBUG_' .. self.name, function() + self.DEBUG_DATA = net.readTable() + end) + end + + self.DEBUG_SEND_DATA_DEBOUNCED = debounce(function() + net.start("DEBUG_" .. self.name) + net.writeTable(self.DEBUG_DATA) + net.send(nil, true) + end, TICK_INTERVAL * 20) + end end function PowertrainComponent:start() @@ -67,4 +86,12 @@ function PowertrainComponent:forwardStep(torque, inertia) return self.output:forwardStep(self.torque, self.inertia + inertia) end +function PowertrainComponent:updateWireOutputs() + WireComponent.updateWireOutputs(self) + + if self.DEBUG then + self.DEBUG_SEND_DATA_DEBOUNCED() + end +end + return PowertrainComponent diff --git a/koptilnya/engine_remastered/powertrain/wheel.txt b/koptilnya/engine_remastered/powertrain/wheel.txt index 90c0543..c0ee60f 100644 --- a/koptilnya/engine_remastered/powertrain/wheel.txt +++ b/koptilnya/engine_remastered/powertrain/wheel.txt @@ -16,12 +16,40 @@ local DEBUG = false function Wheel:initialize(vehicle, name, config) PowertrainComponent.initialize(self, vehicle, name, config) + if CLIENT and self.DEBUG then + local scale = 0.1 + local font = render.createFont("Roboto", 256, 400, true) + local mat = render.createMaterial('models/debug/debugwhite') + + + hook.add("PostDrawTranslucentRenderables", "DEBUG_RENDER_" .. self.name, function() + if next(self.DEBUG_DATA) == nil then return end + if not isValid(self.DEBUG_DATA.entity) then return end + + local pos = self.DEBUG_DATA.entity:getPos() + + render.setMaterial(mat) + render.setColor(Color(255, 0, 0, 200)) + render.draw3DBeam(pos, pos + (16 * self.DEBUG_DATA.forward), 1, 0, 0) + + render.setColor(Color(0, 255, 0, 255)) + render.draw3DBeam(pos, pos + (16 * self.DEBUG_DATA.right), 1, 0, 0) + + render.setColor(Color(0, 0, 255, 200)) + render.draw3DBeam(pos, pos + (16 * self.DEBUG_DATA.up), 1, 0, 0) + end) + + if player() == owner() then + enableHud(nil, true) + end + + return + end + self.steerLock = config.SteerLock or 0 self.brakePower = config.BrakePower or 0 self.handbrakePower = config.HandbrakePower or 0 - self.rotationAxle = config.RotationAxle or Angle(0, 0, 1) - self.wireInputs = { [self.name] = 'entity' } @@ -50,14 +78,8 @@ function Wheel:initialize(vehicle, name, config) self.holo = self:createHolo(self.entity) - if DEBUG then - self.debugHoloF:setPos(self.entity:getPos()) - self.debugHoloR:setPos(self.entity:getPos()) - self.debugHoloU:setPos(self.entity:getPos()) - - self.debugHoloF:setParent(self.entity) - self.debugHoloR:setParent(self.entity) - self.debugHoloU:setParent(self.entity) + if self.DEBUG then + self.DEBUG_DATA.entity = self.entity end if not config.Radius then @@ -66,20 +88,6 @@ function Wheel:initialize(vehicle, name, config) end end) - if DEBUG then - self.debugHoloF = holograms.create(Vector(), Angle(), 'models/sprops/rectangles_thin/size_0/rect_1_5x48x1_5.mdl') - self.debugHoloR = holograms.create(Vector(), Angle(), 'models/sprops/rectangles_thin/size_0/rect_1_5x48x1_5.mdl') - self.debugHoloU = holograms.create(Vector(), Angle(), 'models/sprops/rectangles_thin/size_0/rect_1_5x48x1_5.mdl') - - self.debugHoloF:setMaterial('models/debug/debugwhite') - self.debugHoloR:setMaterial('models/debug/debugwhite') - self.debugHoloU:setMaterial('models/debug/debugwhite') - - self.debugHoloF:setColor(Color(255, 0, 0)) - self.debugHoloR:setColor(Color(0, 255, 0)) - self.debugHoloU:setColor(Color(0, 0, 255)) - end - self.steerVelocity = 0 end @@ -110,6 +118,8 @@ function Wheel:createHolo(entity) end function Wheel:updateWireOutputs() + PowertrainComponent.updateWireOutputs(self) + wire.ports[string.format('%s_RPM', self.name)] = self.customWheel:getRPM() wire.ports[string.format('%s_Mz', self.name)] = self.customWheel.mz wire.ports[string.format('%s_Fz', self.name)] = self.customWheel.load @@ -145,11 +155,11 @@ function Wheel:forwardStep(torque, inertia) end if isValid(self.holo) then - if DEBUG then - self.debugHoloF:setAngles(self.customWheel.forward:getAngle()) - self.debugHoloR:setAngles(self.customWheel.right:getAngle()) - self.debugHoloU:setAngles(self.customWheel.up:getAngle()) - end + if self.DEBUG then + self.DEBUG_DATA.forward = self.customWheel.forward + self.DEBUG_DATA.right = self.customWheel.right + self.DEBUG_DATA.up = self.customWheel.up + end local entityAngles = self.entity:getAngles() diff --git a/koptilnya/engine_remastered/vehicle.txt b/koptilnya/engine_remastered/vehicle.txt index ec926c5..f867b99 100644 --- a/koptilnya/engine_remastered/vehicle.txt +++ b/koptilnya/engine_remastered/vehicle.txt @@ -1,8 +1,9 @@ ---@server --@include ./enums/powertrain_component.txt --@include ./factories/powertrain_component.txt --@include /koptilnya/libs/table.txt --@include /koptilnya/libs/constants.txt +--@include /libs/task.txt +local Task = require('/libs/task.txt') local PowertrainComponentFactory = require('./factories/powertrain_component.txt') local CustomWheel = require('./wheel/wheel.txt') @@ -25,16 +26,22 @@ function Vehicle:initialize(config) self:createComponents() self:linkComponents() - self:createIO() + + if SERVER then + self:createIO() + end self.rootComponent = self:getRootComponent() - self.steer = 0 - self.brake = 0 - self.handbrake = 0 - hook.add('input', 'vehicle_wire_input', function(name, value) - self:handleWireInput(name, value) - end) + if SERVER then + self.steer = 0 + self.brake = 0 + self.handbrake = + + hook.add('input', 'vehicle_wire_input', function(name, value) + self:handleWireInput(name, value) + end) + end hook.add('tick', 'vehicle_update', function() self:update() @@ -112,16 +119,18 @@ function Vehicle:handleWireInput(name, value) end function Vehicle:update() - local base = wire.ports.Base + if SERVER then + local base = wire.ports.Base - self.rootComponent:forwardStep() + self.rootComponent:forwardStep() - for _, component in pairs(self.independentComponents) do - component:forwardStep(0, component:queryInertia()) - end + for _, component in pairs(self.independentComponents) do + component:forwardStep(0, component:queryInertia()) + end - for _, component in pairs(self.components) do - component:updateWireOutputs() + for _, component in pairs(self.components) do + component:updateWireOutputs() + end end --if isValid(base) and (self.clutch:getPress() == 1 or self.gearbox.ratio == 0) then @@ -135,4 +144,4 @@ end return { Vehicle, POWERTRAIN_COMPONENT -} +} \ No newline at end of file diff --git a/koptilnya/engine_remastered/wire_component.txt b/koptilnya/engine_remastered/wire_component.txt index 0ee3eef..7d62341 100644 --- a/koptilnya/engine_remastered/wire_component.txt +++ b/koptilnya/engine_remastered/wire_component.txt @@ -1,6 +1,8 @@ local WireComponent = class('WireComponent') function WireComponent:initialize() + if CLIENT then return end + self.wireInputs = {} self.wireOutputs = {} end diff --git a/koptilnya/engine_sound.txt b/koptilnya/engine_sound.txt index fa99ae9..dc6a519 100644 --- a/koptilnya/engine_sound.txt +++ b/koptilnya/engine_sound.txt @@ -1,5 +1,5 @@ --- @include libs/utils.txt --- @client +--@include libs/utils.txt +--@client require("/koptilnya/libs/utils.txt") EngineSound = class("EngineSound") diff --git a/koptilnya/engine_sound_2.txt b/koptilnya/engine_sound_2.txt new file mode 100644 index 0000000..bf6f54b --- /dev/null +++ b/koptilnya/engine_sound_2.txt @@ -0,0 +1,89 @@ +--@client +--@include /libs/task.txt +local Task = require('/libs/task.txt') + +local Sound = class("Sound") + +local function map(x, a, b, c, d) + return (x - a) / (b - a) * (d - c) + c +end + +local function fade(n, min, mid, max) + if n < min or n > max then + return 0 + end + + if n > mid then + min = mid - (max - mid) + end + + return math.cos((1 - ((n - min) / (mid - min))) * (math.pi / 2)) +end + +function Sound:initialize(redline, parent, sounds) + local sounds = sounds or { + [900] = "https://raw.githubusercontent.com/koptilnya/gmod-data/main/engine_sounds/bmw_s54/ext_e30s54_idle.ogg", + [2500] = "https://raw.githubusercontent.com/koptilnya/gmod-data/main/engine_sounds/bmw_s54/ext_e30s54_on_2500.ogg", + [4000] = "https://raw.githubusercontent.com/koptilnya/gmod-data/main/engine_sounds/bmw_s54/ext_e30s54_on_4000.ogg", + [6750] = "https://raw.githubusercontent.com/koptilnya/gmod-data/main/engine_sounds/bmw_s54/ext_e30s54_on_6750.ogg", + [8500] = "https://raw.githubusercontent.com/koptilnya/gmod-data/main/engine_sounds/bmw_s54/ext_e30s54_on_8500.ogg" + } + local redline = redline or 7000 + self.active = true + local soundObjects = {} + local soundRpms = {} + local maxValue = 0 + local throttle = 0 + local engineRpm = 0 + local smoothRpm = 0 + local smoothThrottle = 0 + + Task.run(function() + for soundRpm, soundPath in pairs(sounds) do + local sound = await* soundLoad(soundPath, "3d noblock noplay") + soundObjects[soundRpm] = sound + table.insert(soundRpms,soundRpm) + if maxValue < soundRpm then + maxValue = soundRpm + end + end + + table.sort(soundRpms) + + hook.add("think", table.address({}), function() + if not self.active then + return + end + + smoothRpm = smoothRpm * (1 - 0.2) + engineRpm * 0.2 + smoothThrottle = smoothThrottle * (1 - 0.1) + throttle * 0.1 + + for n, rpm in ipairs(soundRpms) do + if not soundObjects[rpm] then + goto CONTINUE + end + local min = n == 1 and -100000 or soundRpms[n - 1] + local max = n == #soundRpms and 100000 or soundRpms[n + 1] + local c = fade(smoothRpm, min - 10, rpm, max + 10) + local vol = c * map(smoothThrottle, 0, 1, 0.5, 1) + local soundObject = soundObjects[rpm].Bass + soundObject:setVolume(vol) + soundObject:setPitch(smoothRpm / rpm) + soundObject:setPos(parent:getPos()) + soundObject:pause() + soundObject:play() + ::CONTINUE:: + end + end) + end) + + net.receive("ENGINE_FULLRPM", function() + local rpm = net.readUInt(16) + engineRpm = rpm * (maxValue / redline) + throttle = math.max(net.readFloat(), 0) + end) +end + +return Sound + + diff --git a/koptilnya/libs/utils.txt b/koptilnya/libs/utils.txt index 65881a5..151b974 100644 --- a/koptilnya/libs/utils.txt +++ b/koptilnya/libs/utils.txt @@ -72,4 +72,15 @@ function isURL(str) local _1, _2, prefix = str:find("^(%w-):") return prefix == "http" or prefix == "https" or prefix == "data" +end + +function debounce(func, delay) + local lastCall = 0 + return function(...) + local now = timer.systime() + if now - lastCall >= delay then + lastCall = now + return func(...) + end + end end \ No newline at end of file