From 0b71940310699488a99a5d58b68aba6f35964e83 Mon Sep 17 00:00:00 2001 From: Ivan Grachyov Date: Sat, 11 Dec 2021 17:36:34 +0500 Subject: [PATCH 1/7] Implementing better steering --- koptilnya/better_steering/config/sample.txt | 42 ++++ koptilnya/better_steering/slave.txt | 114 +++++++++++ koptilnya/better_steering/steering.txt | 79 ++++++++ koptilnya/data/models/bmw_m4_g82.txt | 45 +++++ koptilnya/engine_remastered/clutch.txt | 4 +- .../engine_remastered/configs/sx240_stock.txt | 2 +- koptilnya/engine_remastered/differential.txt | 4 +- koptilnya/engine_remastered/engine.txt | 4 +- .../engine_remastered/gearboxes/base.txt | 4 +- .../engine_remastered/novojiloff_diff.txt | 4 +- koptilnya/grip_steering/main.txt | 188 ------------------ koptilnya/grip_steering/slave.txt | 29 --- koptilnya/input_system/configs/sample.txt | 6 +- .../wire_component.txt | 0 14 files changed, 294 insertions(+), 231 deletions(-) create mode 100644 koptilnya/better_steering/config/sample.txt create mode 100644 koptilnya/better_steering/slave.txt create mode 100644 koptilnya/better_steering/steering.txt create mode 100644 koptilnya/data/models/bmw_m4_g82.txt delete mode 100644 koptilnya/grip_steering/main.txt delete mode 100644 koptilnya/grip_steering/slave.txt rename koptilnya/{engine_remastered => libs}/wire_component.txt (100%) diff --git a/koptilnya/better_steering/config/sample.txt b/koptilnya/better_steering/config/sample.txt new file mode 100644 index 0000000..0831ccc --- /dev/null +++ b/koptilnya/better_steering/config/sample.txt @@ -0,0 +1,42 @@ +-- @name Better steering sample config +-- @author Koptilnya1337 +-- @server +-- @include /koptilnya/better_steering/steering.txt +require('/koptilnya/better_steering/steering.txt') + +Steering:new({ + Sensitivity = 0.04, + Slaves = {{ + Lock = 30, + Camber = -2, + Caster = 5, + Ackermann = 15.43, + Toe = 0, + Offset = 180 + }, { + Lock = 30, + Camber = -2, + Caster = 5, + Ackermann = 15.43, + Toe = 0, + Offset = 180, + IsRight = true + }, { + Lock = 1, + Camber = -2, + Caster = 0, + Ackermann = 0, + Toe = 0, + Offset = 180, + Direction = -1 + }, { + Lock = 1, + Camber = -2, + Caster = 0, + Ackermann = 0, + Toe = 0, + Offset = 180, + IsRight = true, + Direction = -1 + }} +}) diff --git a/koptilnya/better_steering/slave.txt b/koptilnya/better_steering/slave.txt new file mode 100644 index 0000000..846ab17 --- /dev/null +++ b/koptilnya/better_steering/slave.txt @@ -0,0 +1,114 @@ +-- @include /koptilnya/libs/wire_component.txt +-- @include /koptilnya/libs/constants.txt +require('/koptilnya/libs/wire_component.txt') +require('/koptilnya/libs/constants.txt') + +Slave = class('Slave', WireComponent) + +function Slave:initialize(options) + options = options or {} + + self.lock = options.Lock or 0 + self.camber = options.Camber or 0 + self.caster = options.Caster or 0 + self.ackermann = options.Ackermann or 0 + self.toe = options.Toe or 0 + self.offset = options.Offset or 0 + self.isRight = options.IsRight or false + self.direction = options.Direction or 1 + + self.order = options.Order or 0 + + self.entity = nil + self.wheel = nil + self.base = options.Base or nil + + self.steer = 0 + self.steeringAngle = 0 + self.lateralVel = 0 + self.lateralForce = 0 + self.selfAligningTorque = 0 + self.correctingAngle = 0 +end + +function Slave:getInputs() + local inputs = {} + inputs['SL_' .. self.order] = 'entity' + inputs['W_' .. self.order] = 'entity' + + return inputs +end + +function Slave:getOutputs() + local outputs = {} + + outputs['SL_' .. self.order .. '_LateralForce'] = 'number' + outputs['SL_' .. self.order .. '_SelfAligningTq'] = 'number' + outputs['SL_' .. self.order .. '_CorrectingAngle'] = 'number' + outputs['W_' .. self.order .. '_LateralVel'] = 'number' + + return outputs +end + +function Slave:updateOutputs() + wire.ports['SL_' .. self.order .. '_LateralForce'] = self.lateralForce + wire.ports['SL_' .. self.order .. '_SelfAligningTq'] = self.selfAligningTorque + wire.ports['SL_' .. self.order .. '_CorrectingAngle'] = self.correctingAngle + wire.ports['W_' .. self.order .. '_LateralVel'] = self.lateralVel +end + +function Slave:update() + self.entity = wire.ports['SL_' .. self.order] + self.wheel = wire.ports['W_' .. self.order] + + if isValid(self.entity) and isValid(self.base) and isValid(self.wheel) then + local wheelMass = self.wheel:getMass() + local wheelInertia = self.wheel:getInertia():getLength() + local wheelRadius = self.wheel:getModelRadius() / UNITS_PER_METER + local wheelFriction = self.wheel:getFriction() + local lateralVel = self.wheel:worldToLocal(self.wheel:getVelocity() + self.wheel:getPos())[2] + + self.lateralVel = lateralVel + + if math.abs(self.steer) > 0 then + self.correctingAngle = 0 + else + self.lateralForce = wheelFriction * wheelMass * lateralVel / TICK_INTERVAL / + UNITS_PER_METER + self.selfAligningTorque = self.lateralForce * wheelRadius * 2 + self.correctingAngle = self.selfAligningTorque / wheelInertia * TICK_INTERVAL + end + + if self.isRight then + self.correctingAngle = self.correctingAngle * -1 + end + + self.correctingAngle = 0 + + if not self.entity:isFrozen() and not self.entity:isPlayerHolding() then + self.entity:setFrozen(1) + end + + local inc = self.steer * self.lock * self.direction + self.steeringAngle = math.clamp(self.steeringAngle + inc + self.correctingAngle, -self.lock, self.lock) + + local camber = self.isRight and -self.camber or self.camber + local steerRatio = self.lock ~= 0 and self.steeringAngle / self.lock or 0 + local caster = steerRatio * self.caster + local toe = self.isRight and self.toe or -self.toe + local ackermann = 0 + + if steerRatio > 0 then + ackermann = self.isRight and -steerRatio * self.ackermann or steerRatio * self.ackermann + elseif steerRatio < 0 then + ackermann = self.isRight and steerRatio * self.ackermann or -steerRatio * self.ackermann + end + + -- Dividing ackermann by 2 because ackermann angle is difference between wheels angle + -- So if we don't divide it by 2, the result angle will be 2 times more than expected + local angle = Angle(0, self.offset + self.steeringAngle + toe + ackermann / 2, camber - caster) + local localizedAngle = self.base:localToWorldAngles(angle) + + self.entity:setAngles(localizedAngle) + end +end diff --git a/koptilnya/better_steering/steering.txt b/koptilnya/better_steering/steering.txt new file mode 100644 index 0000000..112368f --- /dev/null +++ b/koptilnya/better_steering/steering.txt @@ -0,0 +1,79 @@ +-- @include /koptilnya/libs/wire_component.txt +-- @include ./slave.txt +-- @include /koptilnya/libs/table.txt +require('/koptilnya/libs/wire_component.txt') +require('./slave.txt') +require('/koptilnya/libs/table.txt') + +Steering = class('Steering', WireComponent) + +function Steering:initialize(options) + options = options or {} + self.slaves = {} + self.steer = 0 + self.sensitivity = options.Sensitivity or 1 + + for key, slave in ipairs(options.Slaves) do + slave.Order = key + slave.Base = wire.ports.Base + table.insert(self.slaves, Slave:new(slave)) + end + + self:_adjustPorts() + + hook.add('tick', 'update', function() + self:update() + end) +end + +function Steering:_adjustPorts() + local inputs = {} + local outputs = {} + + inputs = table.merge(inputs, self:getInputs()) + outputs = table.merge(outputs, self:getOutputs()) + + for _, slave in ipairs(self.slaves) do + inputs = table.merge(inputs, slave:getInputs()) + outputs = table.merge(outputs, slave:getOutputs()) + end + + wire.adjustPorts(inputs, outputs) +end + +function Steering:getInputs() + return { + TargetSteer = 'number', + Base = 'entity' + } +end + +function Steering:getOutputs() + return { + Steer = 'number' + } +end + +function Steering:updateOutputs() + local totalSteeringAngle = table.reduce(self.slaves, function(steer, slave) + return steer + slave.direction * slave.steeringAngle / (slave.lock ~= 0 and slave.lock or 1) + end, 0) + + local steerableSlaves = table.filter(self.slaves, function(slave) + return slave.lock ~= 0 + end) + + wire.ports.Steer = totalSteeringAngle / #steerableSlaves +end + +function Steering:update() + self.steer = wire.ports.TargetSteer * self.sensitivity + + self:updateOutputs() + + for _, slave in ipairs(self.slaves) do + slave.steer = self.steer + slave:update() + slave:updateOutputs() + end +end diff --git a/koptilnya/data/models/bmw_m4_g82.txt b/koptilnya/data/models/bmw_m4_g82.txt new file mode 100644 index 0000000..77834e1 --- /dev/null +++ b/koptilnya/data/models/bmw_m4_g82.txt @@ -0,0 +1,45 @@ +-- @shared +-- @name BMW M4 G82 Competition +-- @author Koptilnya1337 +-- @include /koptilnya/mesh_loader/builder.txt +require("/koptilnya/mesh_loader/builder.txt") + +DEBUG_MODE = true + +local LINK = "https://drive.google.com/u/0/uc?id=1yxjPtVhoMROwSB56tfL_dbBPrW1Yjr9h&export=download" +local SCALE = Vector(1) + +local Materials = +{ + Body = "phoenix_storms/fender_white", + Carbon = "sprops/textures/sprops_cfiber2" +} + +local Colors = +{ + Body = Color(115,218,201), + Carbon = Color(255,255,255) +} + +local builder = {} + +if SERVER then + builder = MeshBuilder:new(LINK) + + local this = chip() + + -- Body group + builder:build("Body", Vector(0), Angle(0), SCALE, Colors.Body, Materials.Body, this, this) + builder:build("LeftDoor", Vector(0), Angle(0), SCALE, Colors.Body, Materials.Body, this, this) + builder:build("RightDoor", Vector(0), Angle(0), SCALE, Colors.Body, Materials.Body, this, this) + builder:build("Bonnet", Vector(0), Angle(0), SCALE, Colors.Body, Materials.Body, this, this) + builder:build("Trunk", Vector(0), Angle(0), SCALE, Colors.Body, Materials.Body, this, this) + builder:build("Roof", Vector(0), Angle(0), SCALE, Colors.Carbon, Materials.Carbon, this, this) + + local result = builder:getResult() +else + PERMA.onPermissionsGained = function() + builder = MeshBuilder:new(LINK) + end + PERMA.build() +end diff --git a/koptilnya/engine_remastered/clutch.txt b/koptilnya/engine_remastered/clutch.txt index 9bb9ec4..561880b 100644 --- a/koptilnya/engine_remastered/clutch.txt +++ b/koptilnya/engine_remastered/clutch.txt @@ -1,8 +1,8 @@ --- @include ./wire_component.txt +-- @include /koptilnya/libs/wire_component.txt -- @include ./enums/gearbox.txt -- @include /koptilnya/libs/constants.txt require('/koptilnya/libs/constants.txt') -require('./wire_component.txt') +require('/koptilnya/libs/wire_component.txt') local gearboxTypes = require('./enums/gearbox.txt') Clutch = class('Clutch', WireComponent) diff --git a/koptilnya/engine_remastered/configs/sx240_stock.txt b/koptilnya/engine_remastered/configs/sx240_stock.txt index 09408e5..e2ff6c2 100644 --- a/koptilnya/engine_remastered/configs/sx240_stock.txt +++ b/koptilnya/engine_remastered/configs/sx240_stock.txt @@ -24,7 +24,7 @@ Vehicle:new({ } }, Clutch = {Stiffness = 20, Damping = 0.7, MaxTorque = 400}, - Gearbox = {Type = 'MANUAL', ShiftDuration = 0.2, ShiftSmoothness = 0.3, Ratios = {3.626, 2.200, 1.541, 1.213, 1.000, 0.767}, Reverse = 3.437}, + Gearbox = {Type = 'MANUAL', ShiftDuration = 0.2, ShiftSmoothness = 0.3, Ratios = {3.626, 2.200, 1.541, 1.213, 1.000, 0.767}, Reverse = 3.437}, Axles = {{Power = 0.96, Coast = 0.96, Preload = 10, UsePowerBias = 10, ViscousCoeff = 0.96, Axle = Vector(1, 0, 0), DistributionCoeff = 1, FinalDrive = 3.392}}, Systems = {{Type = 'LAUNCH', Limit = 3500}, {Type = 'TRACTION', Limit = 1.5}} }) diff --git a/koptilnya/engine_remastered/differential.txt b/koptilnya/engine_remastered/differential.txt index d92361f..6dbf61c 100644 --- a/koptilnya/engine_remastered/differential.txt +++ b/koptilnya/engine_remastered/differential.txt @@ -1,8 +1,8 @@ -- @server -- @include /koptilnya/libs/constants.txt --- @include ./wire_component.txt +-- @include /koptilnya/libs/wire_component.txt require('/koptilnya/libs/constants.txt') -require('./wire_component.txt') +require('/koptilnya/libs/wire_component.txt') Differential = class('Differential', WireComponent) diff --git a/koptilnya/engine_remastered/engine.txt b/koptilnya/engine_remastered/engine.txt index 134c919..5016026 100644 --- a/koptilnya/engine_remastered/engine.txt +++ b/koptilnya/engine_remastered/engine.txt @@ -1,6 +1,6 @@ --- @include ./wire_component.txt +-- @include /koptilnya/libs/wire_component.txt -- @include /koptilnya/libs/constants.txt -require('./wire_component.txt') +require('/koptilnya/libs/wire_component.txt') require('/koptilnya/libs/constants.txt') Engine = class('Engine', WireComponent) diff --git a/koptilnya/engine_remastered/gearboxes/base.txt b/koptilnya/engine_remastered/gearboxes/base.txt index cbb4e2c..c0aec4a 100644 --- a/koptilnya/engine_remastered/gearboxes/base.txt +++ b/koptilnya/engine_remastered/gearboxes/base.txt @@ -1,5 +1,5 @@ --- @include ../wire_component.txt -require('../wire_component.txt') +-- @include /koptilnya/libs/wire_component.txt +require('/koptilnya/libs/wire_component.txt') Gearbox = class('Gearbox', WireComponent) diff --git a/koptilnya/engine_remastered/novojiloff_diff.txt b/koptilnya/engine_remastered/novojiloff_diff.txt index 80c01c6..c947107 100644 --- a/koptilnya/engine_remastered/novojiloff_diff.txt +++ b/koptilnya/engine_remastered/novojiloff_diff.txt @@ -1,8 +1,8 @@ -- @server -- @include /koptilnya/libs/constants.txt --- @include ./wire_component.txt +-- @include /koptilnya/libs/wire_component.txt require('/koptilnya/libs/constants.txt') -require('./wire_component.txt') +require('/koptilnya/libs/wire_component.txt') Differential = class('Differential', WireComponent) diff --git a/koptilnya/grip_steering/main.txt b/koptilnya/grip_steering/main.txt deleted file mode 100644 index e2bddf2..0000000 --- a/koptilnya/grip_steering/main.txt +++ /dev/null @@ -1,188 +0,0 @@ --- @name Grip Steering --- @author DarkSupah --- @server --- @include ./slave.txt -Steering = class('Steering') - -require('./slave.txt') - -function inrange(val, min, max) - return val >= min and val <= max -end - -function isNaN(val) - return val ~= val -end - -function vectorIsNaN(vec) - return isNaN(vec[1]) or isNaN(vec[2]) or isNaN(vec[3]) -end - -function getLocalVelocity(ent) - return ent:worldToLocal((ent:getVelocity() + ent:getPos())) -end - -local options = { - Camber = -2, - Caster = 5, - Ackermann = 15, - Lock = 45, - - ZeroThreshold = 2, - - StartSpeedThreshold = 40, - EndSpeedThreshold = 150, - SpeedCoeff = 0.2, - - StartCorrectionThreshold = 5, - EndCorrectionThreshold = 40, - CorrectionOnCoeff = 0.6, - CorrectionOffCoeff = 1, - CorrectionOnLerp = 0.3, - CorrectionOffLerp = 0.6 -} - -function Steering:_adjustPorts() - local inputs = { - Axles = 'table', - Base = 'entity', - LeftSlave = 'entity', - RightSlave = 'entity' - } - - local outputs = { - SteerAngle = 'number', - TargetAngle = 'number', - CorrectionAngle = 'number' - } - - wire.adjustPorts(inputs, outputs) -end - -function Steering:_createSlaves() - local entities = {wire.ports.LeftSlave, wire.ports.RightSlave} - local slaves = {} - - for k, v in pairs(entities) do - local slave = Slave:new({ - Entity = v, - IsLeft = k % 2 == 1, - Offset = 180, - Base = wire.ports.Base, - Camber = self.slavesConfig.Camber, - Caster = self.slavesConfig.Caster, - Ackermann = self.slavesConfig.Ackermann - }) - - table.insert(self.slaves, slave) - end -end - -function Steering:_updateOutputs() - wire.ports.TargetAngle = self.targetAngle - wire.ports.SteerAngle = self.angle - wire.ports.CorrectionAngle = self.correction -end - -function Steering:_getCorrectionGradient(speed) - return math.clamp(math.remap(speed, self.startCorrectionThreshold, self.endCorrectionThreshold, 0, 1), 0, 1) -end - -function Steering:getBaseSpeed() - local MPH = self.base:getVelocity():getLength() * 3600 / 63360 - local KPH = MPH * 1.609 - - return KPH -end - -function Steering:_getSpeedCorrectionGradient(speed) - return math.clamp(math.remap(speed, self.startSpeedThreshold, self.endSpeedThreshold, 0, 1), 0, 1) -end - -function Steering:_getCorrectionAngle() - local localVel = getLocalVelocity(self.base) - local forwardVel = (localVel * Vector(1, 0, 0)):getNormalized() - local planarVec = (localVel * Vector(1, 1, 0)):getNormalized() - - forwardVel = vectorIsNaN(forwardVel) and Vector(0, 0, 0) or forwardVel - planarVec = vectorIsNaN(planarVec) and Vector(0, 0, 0) or planarVec - - local cross = forwardVel:cross(planarVec) - - return math.deg(math.acos(forwardVel:dot(planarVec))) * math.sign(localVel[2]) -end - -function Steering:initialize(options) - self:_adjustPorts() - - options = options or {} - - self.base = wire.ports.Base - - self.slavesConfig = { - Camber = options.Camber, - Caster = options.Caster, - Ackermann = options.Ackermann - } - - self.lock = options.Lock - - self.targetAngle = 0 - self.angle = 0 - - self.zeroThreshold = options.ZeroThreshold - - self.speedCoeff = options.SpeedCoeff - self.startSpeedThreshold = options.StartSpeedThreshold - self.endSpeedThreshold = options.EndSpeedThreshold - - self.startCorrectionThreshold = options.StartCorrectionThreshold - self.endCorrectionThreshold = options.EndCorrectionThreshold - self.correctionOnCoeff = options.CorrectionOnCoeff - self.correctionOffCoeff = options.CorrectionOffCoeff - - self.correctionOnLerp = options.CorrectionOnLerp - self.correctionOffLerp = options.CorrectionOffLerp - - self.correction = 0 - - self.slaves = {} - - self:_createSlaves() -end - -function Steering:update() - local horizontal = wire.ports.Axles.Horizontal.Value - local horizontalTarget = wire.ports.Axles.Horizontal.Target - - local baseSpeedKMH = self:getBaseSpeed() - local angleCorrection = self:_getCorrectionGradient(baseSpeedKMH) - local speedCorrection = self.angle * self:_getSpeedCorrectionGradient(baseSpeedKMH) * self.speedCoeff - - self.targetAngle = horizontal * self.lock - - local correctionCoeff = horizontalTarget ~= 0 and self.correctionOnCoeff or self.correctionOffCoeff - local correctionLerpCoeff = horizontalTarget ~= 0 and self.correctionOnLerp or self.correctionOffLerp - local correction = self:_getCorrectionAngle() * angleCorrection * correctionCoeff - self.correction = math.lerp(correctionLerpCoeff, self.correction, isNaN(correction) and 0 or correction) - - local possibleAngle = math.clamp(horizontal * self.lock + speedCorrection + self.correction, -self.lock, self.lock) - - if inrange(possibleAngle, -self.zeroThreshold, self.zeroThreshold) then - self.angle = 0 - else - self.angle = possibleAngle - end - - for k, v in pairs(self.slaves) do - v:rotate(self.angle) - end - - self:_updateOutputs() -end - -local steering = Steering:new(options) - -hook.add('think', 'SteeringUpdate', function() - steering:update() -end) diff --git a/koptilnya/grip_steering/slave.txt b/koptilnya/grip_steering/slave.txt deleted file mode 100644 index 6497fff..0000000 --- a/koptilnya/grip_steering/slave.txt +++ /dev/null @@ -1,29 +0,0 @@ -Slave = class('Slave') - -function Slave:initialize(options) - options = options or {} - - self.entity = options.Entity - self.base = options.Base - - self.camber = options.Camber - self.caster = options.Caster - self.ackermann = options.Ackermann - self.isLeft = options.IsLeft - self.offset = options.Offset -end - -function Slave:rotate(ang) - if self.entity:isFrozen() == false then - self.entity:setFrozen(1) - end - - local ackermann = math.sin(math.rad(ang)) ^ 2 * self.ackermann * (self.isLeft and -1 or 1) - local yaw = self.offset + ang + ackermann - local roll = (self.isLeft and 1 or -1) * self.camber - ang / 270 * self.caster - - local angle = Angle(0, yaw, roll) - local transformedAngle = self.base:localToWorldAngles(angle) - - self.entity:setAngles(transformedAngle) -end diff --git a/koptilnya/input_system/configs/sample.txt b/koptilnya/input_system/configs/sample.txt index 4dba483..c36a5da 100644 --- a/koptilnya/input_system/configs/sample.txt +++ b/koptilnya/input_system/configs/sample.txt @@ -2,8 +2,8 @@ Axles = { Horizontal = { Negative = KEY.D, Positive = KEY.A, - Gravity = 0.1, - Sensitivity = 0.2 + Gravity = 1, + Sensitivity = 1 }, Throttle = { Positive = KEY.W, @@ -20,5 +20,5 @@ Axles = { Negative = MOUSE.RIGHT, Gravity = 1, Sensitivity = 1 - }, + } } diff --git a/koptilnya/engine_remastered/wire_component.txt b/koptilnya/libs/wire_component.txt similarity index 100% rename from koptilnya/engine_remastered/wire_component.txt rename to koptilnya/libs/wire_component.txt From e2de173e25be2be471a6e6290b071979b682031a Mon Sep 17 00:00:00 2001 From: Ivan Grachyov Date: Mon, 24 Jan 2022 20:28:12 +0500 Subject: [PATCH 2/7] pushing some shit --- koptilnya/.idea/.gitignore | 5 ++ koptilnya/.idea/koptilnya.iml | 12 ++++ koptilnya/.idea/modules.xml | 8 +++ koptilnya/.idea/vcs.xml | 6 ++ koptilnya/better_steering/config/sample.txt | 30 +++----- koptilnya/better_steering/slave.txt | 69 ++++++++----------- koptilnya/better_steering/steering.txt | 42 +++++------ koptilnya/better_steering/steering_axle.txt | 69 +++++++++++++++++++ koptilnya/engine_remastered/configs/sx240.txt | 3 +- koptilnya/input_system/configs/sample.txt | 5 ++ 10 files changed, 166 insertions(+), 83 deletions(-) create mode 100644 koptilnya/.idea/.gitignore create mode 100644 koptilnya/.idea/koptilnya.iml create mode 100644 koptilnya/.idea/modules.xml create mode 100644 koptilnya/.idea/vcs.xml create mode 100644 koptilnya/better_steering/steering_axle.txt diff --git a/koptilnya/.idea/.gitignore b/koptilnya/.idea/.gitignore new file mode 100644 index 0000000..b58b603 --- /dev/null +++ b/koptilnya/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/koptilnya/.idea/koptilnya.iml b/koptilnya/.idea/koptilnya.iml new file mode 100644 index 0000000..0c8867d --- /dev/null +++ b/koptilnya/.idea/koptilnya.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/koptilnya/.idea/modules.xml b/koptilnya/.idea/modules.xml new file mode 100644 index 0000000..22e25db --- /dev/null +++ b/koptilnya/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/koptilnya/.idea/vcs.xml b/koptilnya/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/koptilnya/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/koptilnya/better_steering/config/sample.txt b/koptilnya/better_steering/config/sample.txt index 0831ccc..f88cba4 100644 --- a/koptilnya/better_steering/config/sample.txt +++ b/koptilnya/better_steering/config/sample.txt @@ -6,37 +6,23 @@ require('/koptilnya/better_steering/steering.txt') Steering:new({ Sensitivity = 0.04, - Slaves = {{ + PowerSteer = 0.5, + Axles = {{ Lock = 30, Camber = -2, - Caster = 5, + Caster = 8, Ackermann = 15.43, Toe = 0, - Offset = 180 + LeftOffset = 180, + RightOffset = 180 }, { - Lock = 30, - Camber = -2, - Caster = 5, - Ackermann = 15.43, - Toe = 0, - Offset = 180, - IsRight = true - }, { - Lock = 1, + Lock = 0, Camber = -2, Caster = 0, Ackermann = 0, Toe = 0, - Offset = 180, - Direction = -1 - }, { - Lock = 1, - Camber = -2, - Caster = 0, - Ackermann = 0, - Toe = 0, - Offset = 180, - IsRight = true, + LeftOffset = 180, + RightOffset = 180, Direction = -1 }} }) diff --git a/koptilnya/better_steering/slave.txt b/koptilnya/better_steering/slave.txt index 846ab17..f219ebc 100644 --- a/koptilnya/better_steering/slave.txt +++ b/koptilnya/better_steering/slave.txt @@ -1,7 +1,9 @@ -- @include /koptilnya/libs/wire_component.txt -- @include /koptilnya/libs/constants.txt +-- @include /koptilnya/libs/entity.txt require('/koptilnya/libs/wire_component.txt') require('/koptilnya/libs/constants.txt') +require('/koptilnya/libs/entity.txt') Slave = class('Slave', WireComponent) @@ -19,26 +21,19 @@ function Slave:initialize(options) self.order = options.Order or 0 - self.entity = nil - self.wheel = nil + self.entity = options.Slave + self.wheel = options.Wheel self.base = options.Base or nil self.steer = 0 self.steeringAngle = 0 self.lateralVel = 0 + self.baseLngVel = 0 self.lateralForce = 0 self.selfAligningTorque = 0 self.correctingAngle = 0 end -function Slave:getInputs() - local inputs = {} - inputs['SL_' .. self.order] = 'entity' - inputs['W_' .. self.order] = 'entity' - - return inputs -end - function Slave:getOutputs() local outputs = {} @@ -46,6 +41,8 @@ function Slave:getOutputs() outputs['SL_' .. self.order .. '_SelfAligningTq'] = 'number' outputs['SL_' .. self.order .. '_CorrectingAngle'] = 'number' outputs['W_' .. self.order .. '_LateralVel'] = 'number' + outputs['SL_' .. self.order .. '_SteeringAngle'] = 'number' + outputs['SL_' .. self.order .. '_BaseLngVel'] = 'number' return outputs end @@ -55,42 +52,24 @@ function Slave:updateOutputs() wire.ports['SL_' .. self.order .. '_SelfAligningTq'] = self.selfAligningTorque wire.ports['SL_' .. self.order .. '_CorrectingAngle'] = self.correctingAngle wire.ports['W_' .. self.order .. '_LateralVel'] = self.lateralVel + wire.ports['SL_' .. self.order .. '_SteeringAngle'] = self.steeringAngle + wire.ports['SL_' .. self.order .. '_BaseLngVel'] = self.baseLngVel end function Slave:update() - self.entity = wire.ports['SL_' .. self.order] - self.wheel = wire.ports['W_' .. self.order] - if isValid(self.entity) and isValid(self.base) and isValid(self.wheel) then - local wheelMass = self.wheel:getMass() - local wheelInertia = self.wheel:getInertia():getLength() - local wheelRadius = self.wheel:getModelRadius() / UNITS_PER_METER - local wheelFriction = self.wheel:getFriction() - local lateralVel = self.wheel:worldToLocal(self.wheel:getVelocity() + self.wheel:getPos())[2] - - self.lateralVel = lateralVel - - if math.abs(self.steer) > 0 then - self.correctingAngle = 0 - else - self.lateralForce = wheelFriction * wheelMass * lateralVel / TICK_INTERVAL / - UNITS_PER_METER - self.selfAligningTorque = self.lateralForce * wheelRadius * 2 - self.correctingAngle = self.selfAligningTorque / wheelInertia * TICK_INTERVAL - end - - if self.isRight then - self.correctingAngle = self.correctingAngle * -1 - end - - self.correctingAngle = 0 - if not self.entity:isFrozen() and not self.entity:isPlayerHolding() then self.entity:setFrozen(1) end - local inc = self.steer * self.lock * self.direction - self.steeringAngle = math.clamp(self.steeringAngle + inc + self.correctingAngle, -self.lock, self.lock) + local wheelMass = self.wheel:getMass() + local wheelInertia = self.wheel:getInertia():getLength() + local wheelRadius = self.wheel:getModelRadius() / UNITS_PER_METER + local wheelFriction = self.wheel:getFriction() + local wheelLocalVel = getLocalVelocity(self.wheel) + local baseLocalVel = getLocalVelocity(self.base) + local lateralVel = wheelLocalVel[2] + local baseLngVel = baseLocalVel[1] local camber = self.isRight and -self.camber or self.camber local steerRatio = self.lock ~= 0 and self.steeringAngle / self.lock or 0 @@ -104,11 +83,23 @@ function Slave:update() ackermann = self.isRight and steerRatio * self.ackermann or -steerRatio * self.ackermann end + self.lateralForce = wheelFriction * wheelMass * lateralVel / UNITS_PER_METER + self.selfAligningTorque = self.lateralForce * wheelRadius + + self.correctingAngle = self.selfAligningTorque / wheelInertia * math.sin(math.rad(math.abs(self.caster * 2))) * + math.sign(baseLngVel) * (self.isRight and -1 or 1) + + local inc = self.steer * self.lock * self.direction * math.cos(math.rad(math.abs(self.caster * 2))) + self.steeringAngle = math.clamp(self.steeringAngle + inc + self.correctingAngle, -self.lock, self.lock) + -- Dividing ackermann by 2 because ackermann angle is difference between wheels angle -- So if we don't divide it by 2, the result angle will be 2 times more than expected - local angle = Angle(0, self.offset + self.steeringAngle + toe + ackermann / 2, camber - caster) + local angle = Angle(0, self.offset + self.steeringAngle + toe + ackermann / 2, camber + caster) local localizedAngle = self.base:localToWorldAngles(angle) self.entity:setAngles(localizedAngle) + + self.lateralVel = lateralVel + self.baseLngVel = baseLngVel end end diff --git a/koptilnya/better_steering/steering.txt b/koptilnya/better_steering/steering.txt index 112368f..fd682d6 100644 --- a/koptilnya/better_steering/steering.txt +++ b/koptilnya/better_steering/steering.txt @@ -1,22 +1,22 @@ -- @include /koptilnya/libs/wire_component.txt --- @include ./slave.txt +-- @include ./steering_axle.txt -- @include /koptilnya/libs/table.txt require('/koptilnya/libs/wire_component.txt') -require('./slave.txt') +require('./steering_axle.txt') require('/koptilnya/libs/table.txt') Steering = class('Steering', WireComponent) function Steering:initialize(options) options = options or {} - self.slaves = {} + self.axles = {} self.steer = 0 self.sensitivity = options.Sensitivity or 1 - for key, slave in ipairs(options.Slaves) do - slave.Order = key - slave.Base = wire.ports.Base - table.insert(self.slaves, Slave:new(slave)) + for key, axle in ipairs(options.Axles) do + axle.Order = key + axle.Base = wire.ports.Base + table.insert(self.axles, SteeringAxle:new(axle)) end self:_adjustPorts() @@ -33,9 +33,9 @@ function Steering:_adjustPorts() inputs = table.merge(inputs, self:getInputs()) outputs = table.merge(outputs, self:getOutputs()) - for _, slave in ipairs(self.slaves) do - inputs = table.merge(inputs, slave:getInputs()) - outputs = table.merge(outputs, slave:getOutputs()) + for _, axle in ipairs(self.axles) do + inputs = table.merge(inputs, axle:getInputs()) + outputs = table.merge(outputs, axle:getOutputs()) end wire.adjustPorts(inputs, outputs) @@ -55,15 +55,15 @@ function Steering:getOutputs() end function Steering:updateOutputs() - local totalSteeringAngle = table.reduce(self.slaves, function(steer, slave) - return steer + slave.direction * slave.steeringAngle / (slave.lock ~= 0 and slave.lock or 1) - end, 0) + -- local totalSteeringAngle = table.reduce(self.slaves, function(steer, slave) + -- return steer + slave.direction * slave.steeringAngle / (slave.lock ~= 0 and slave.lock or 1) + -- end, 0) - local steerableSlaves = table.filter(self.slaves, function(slave) - return slave.lock ~= 0 - end) + -- local steerableSlaves = table.filter(self.slaves, function(slave) + -- return slave.lock ~= 0 + -- end) - wire.ports.Steer = totalSteeringAngle / #steerableSlaves + -- wire.ports.Steer = totalSteeringAngle / #steerableSlaves end function Steering:update() @@ -71,9 +71,9 @@ function Steering:update() self:updateOutputs() - for _, slave in ipairs(self.slaves) do - slave.steer = self.steer - slave:update() - slave:updateOutputs() + for _, axle in ipairs(self.axles) do + axle.steer = self.steer + axle:update() + axle:updateOutputs() end end diff --git a/koptilnya/better_steering/steering_axle.txt b/koptilnya/better_steering/steering_axle.txt new file mode 100644 index 0000000..7f43432 --- /dev/null +++ b/koptilnya/better_steering/steering_axle.txt @@ -0,0 +1,69 @@ +-- @include /koptilnya/libs/wire_component.txt +-- @include /koptilnya/libs/constants.txt +-- @include /koptilnya/libs/entity.txt +-- @include ./slave.txt +require('/koptilnya/libs/wire_component.txt') +require('/koptilnya/libs/constants.txt') +require('/koptilnya/libs/entity.txt') +require('./slave.txt') + +SteeringAxle = class('SteeringAxle', WireComponent) + +function SteeringAxle:createSlave(options, isRight) + local config = { + Lock = options.Lock, + Camber = options.Camber, + Caster = options.Caster, + Ackermann = options.Ackermann, + Toe = options.Toe, + Direction = options.Direction, + IsRight = isRight, + Slave = wire.ports[self._prefix .. (isRight and '_RightSlave' or '_LeftSlave')], + Wheel = wire.ports[self._prefix .. (isRight and '_RightWheel' or '_LeftWheel')], + Offset = isRight and options.RightOffset or options.LeftOffset, + Prefix = self._prefix .. (isRight and '_RightWheel' or '_LeftWheel'), + Base = wire.ports.Base + } + + return Slave:new(config) +end + +function SteeringAxle:initialize(options) + options = options or {} + + self.steer = 0 + self._prefix = 'Axle' .. options.Order + + self.leftSlave = self:createSlave(options, false) + self.rightSlave = self:createSlave(options, true) +end + +function SteeringAxle:getInputs() + local inputs = {} + + inputs[self._prefix .. '_LeftSlave'] = 'entity' + inputs[self._prefix .. '_RightSlave'] = 'entity' + inputs[self._prefix .. '_LeftWheel'] = 'entity' + inputs[self._prefix .. '_RightWheel'] = 'entity' + + return inputs +end + +function SteeringAxle:getOutputs() + local outputs = {} + + table.merge(outputs, self.leftSlave:getOutputs()) + table.merge(outputs, self.rightSlave:getOutputs()) + + return outputs +end + +function SteeringAxle:updateOutputs() + self.leftSlave:updateOutputs() + self.rightSlave:updateOutputs() +end + +function SteeringAxle:update() + self.leftSlave:update() + self.rightSlave:update() +end \ No newline at end of file diff --git a/koptilnya/engine_remastered/configs/sx240.txt b/koptilnya/engine_remastered/configs/sx240.txt index aaae9aa..1dbad92 100644 --- a/koptilnya/engine_remastered/configs/sx240.txt +++ b/koptilnya/engine_remastered/configs/sx240.txt @@ -26,7 +26,8 @@ Vehicle:new({ Clutch = {Stiffness = 20, Damping = 0.5, MaxTorque = 400}, Gearbox = {Type = 'MANUAL', ShiftDuration = 0.2, ShiftSmoothness = 0.3, Ratios = {3.321, 1.902, 1.308, 1, 0.838}, Reverse = 3.382}, Axles = { - {Power = 0.96, Coast = 0.96, Preload = 10, UsePowerBias = 10, ViscousCoeff = 0.96, Axle = Vector(1, 0, 0), DistributionCoeff = 1, FinalDrive = 3.9} + {Power = 0.96, Coast = 0.96, Preload = 10, UsePowerBias = 10, ViscousCoeff = 0.96, Axle = Vector(1, 0, 0), DistributionCoeff = 0.8, FinalDrive = 3.9}, + {Power = 0.96, Coast = 0.96, Preload = 10, UsePowerBias = 10, ViscousCoeff = 0.96, Axle = Vector(1, 0, 0), DistributionCoeff = 1.2, FinalDrive = 3.9}, }, Systems = {{Type = 'LAUNCH', Limit = 3500}, {Type = 'TRACTION', Limit = 1.5}} }) diff --git a/koptilnya/input_system/configs/sample.txt b/koptilnya/input_system/configs/sample.txt index c36a5da..8fc6217 100644 --- a/koptilnya/input_system/configs/sample.txt +++ b/koptilnya/input_system/configs/sample.txt @@ -15,6 +15,11 @@ Axles = { Gravity = 0.15, Sensitivity = 0.25 }, + Brakes = { + Positive = KEY.S, + Gravity = 0.15, + Sensitivity = 0.25 + }, Shifter = { Positive = MOUSE.LEFT, Negative = MOUSE.RIGHT, From c8a817277a29ce9a4d6fd7a581ffd7a322674582 Mon Sep 17 00:00:00 2001 From: Ivan Grachyov Date: Sat, 23 Jul 2022 23:16:03 +0300 Subject: [PATCH 3/7] Implemented basic functionality for applyforce suspension. Works fine? --- koptilnya/suspension/main.txt | 99 +++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 koptilnya/suspension/main.txt diff --git a/koptilnya/suspension/main.txt b/koptilnya/suspension/main.txt new file mode 100644 index 0000000..e113dd3 --- /dev/null +++ b/koptilnya/suspension/main.txt @@ -0,0 +1,99 @@ +--@name apply force suspension +--@author Koptilnya1337 +--@shared + + local _restLength = 26.0 + local _springTravel = 20.0 + local _springStiffness = 35000 + local _compressionDamper = 140000 -- 45000 + local _reboundDamper = 35000 -- 196000 + local _maxForce = 500000 + + local _minLength = 0 + local _maxLength = 0 + local _lastLength = 0 + local _springLength = 0 + local _springVelocity = 0 + local _springForce = 0 + local _damperForce = 0 + +if SERVER then + wire.adjustInputs( + { + 'Wheel1', + 'Wheel2', + 'Wheel3', + 'Wheel4', + 'Strut1', + 'Strut2', + 'Strut3', + 'Strut4', + 'Base' + }, + { + 'entity', + 'entity', + 'entity', + 'entity', + 'entity', + 'entity', + 'entity', + 'entity', + 'entity' + } + ) + + local wheel1 = wire.ports.Wheel1 + local wheel2 = wire.ports.Wheel2 + local wheel3 = wire.ports.Wheel3 + local wheel4 = wire.ports.Wheel4 + + local strut1 = wire.ports.Strut1 + local strut2 = wire.ports.Strut2 + local strut3 = wire.ports.Strut3 + local strut4 = wire.ports.Strut4 + + local wheels = { wheel1, wheel2, wheel3, wheel4 } + local struts = { strut1, strut2, strut3, strut4 } + + local base = wire.ports.Base + + function handleWheel(base, wheel, strut) + local lastLength = 0 + + return function () + if not base:isValid() then return end + if not wheel:isValid() then return end + if not strut:isValid() then return end + + local distance = strut:getPos():getDistance(wheel:getPos()) - _restLength + local strutToWheelDirection = (strut:getPos() - wheel:getPos()):setX(0):setY(0):getNormalized() + local springVelocity = (distance - lastLength) + + local usedDamper = springVelocity > 0 and _compressionDamper or _reboundDamper + local spring = distance * _springStiffness + local dampener = springVelocity * usedDamper + + local force = math.clamp((spring + dampener) * game.getTickInterval(), -_maxForce, _maxForce) + local direction = (strut:getPos() - wheel:getPos()):getNormalized() --base:getUp() + + lastLength = distance + + base:applyForceOffset(-force * direction, wheel:getPos()) + wheel:applyForceCenter(force * direction * strutToWheelDirection) + end + end + + local wheelHandlers = {} + + for idx, wheel in ipairs(wheels) do + table.insert(wheelHandlers, handleWheel(base, wheel, struts[idx])) + end + + hook.add('tick', 'runtime', function() + for _, handler in ipairs(wheelHandlers) do + handler() + end + end) + +end \ No newline at end of file From 22fad8994e90ed3fb247137861b536bc7cee8bed Mon Sep 17 00:00:00 2001 From: Ivan Grachyov Date: Wed, 27 Jul 2022 23:38:51 +0300 Subject: [PATCH 4/7] Added model for golf mk7.5 --- koptilnya/data/models/vw_golf_mk7_5.txt | 151 ++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 koptilnya/data/models/vw_golf_mk7_5.txt diff --git a/koptilnya/data/models/vw_golf_mk7_5.txt b/koptilnya/data/models/vw_golf_mk7_5.txt new file mode 100644 index 0000000..5da5e2a --- /dev/null +++ b/koptilnya/data/models/vw_golf_mk7_5.txt @@ -0,0 +1,151 @@ +-- @shared +-- @name VW Golf Mk 7.5 +-- @author Koptilnya1337 +-- @include /koptilnya/mesh_loader/builder.txt +require("/koptilnya/mesh_loader/builder.txt") + +DEBUG_MODE = true + +local LINK = "https://drive.google.com/u/0/uc?id=1FNn5_6PMmurvraVqlJNNV3WXTMnozMJM&export=download" +local SCALE = Vector(1) + +local Materials = { + { + Match = "Shadow", + Material = "", + Color = Color(20,20,20) + }, + { + Match = "BumpersVents", + Material = "models/debug/debugwhite", + Color = Color(20,20,20) + }, + { + Match = { "Body", ".*Body*" }, + Material = "phoenix_storms/fender_white", + Color = Color(230,229,231) + }, + { + Match = "Badges", + Material = "debug/env_cubemap_model", + Color = Color(255,255,255) + }, + { + Match = ".*Lights_Glass*", + Material = "phoenix_storms/mrref2", + Color = Color(255,255,255,120) + }, + { + Match = { ".*Lights_Base*", "RearLights_Chrome" }, + Material = "models/debug/debugwhite", + Color = Color(20,20,20) + }, + { + Match = { "WindowsRubber", "WindshieldOutline" }, + Material = "phoenix_storms/mrref2", + Color = Color(25,25,25) + }, + { + Match = ".*Seat.*", + Material = "models/debug/debugwhite", + Color = Color(60,60,60) + }, + { + Match = "Interior_DoorMaps", + Material = "models/debug/debugwhite", + Color = Color(40,40,40) + }, + { + Match = "Interior_Plastic", + Material = "models/debug/debugwhite", + Color = Color(50,50,50) + } +} + +local Bodyparts = { + "Body", + "Bonnet_Body", + "DoorHandles", + "BumpersVents", + "ExhaustPipes", + "ExhaustPipes", + "FrontBumper_Body", + "FrontLeftDoor_Body", + "FrontQuaterpanels_Body", + "FrontRightDoor_Body", + "FrontRightDoor_Body", + "Mirrors_Plastic", + "RearBumper_Body", + "RearLeftDoor_Body", + "RearRightDoor_Body", + "RearRightDoor_Body", + "Shadow", + "Sidepanels_Body", + "Sideskirts_Body", + "Trunk_Body", +} + +local Details = { + "Badges", +} + +local FrontLights = { + "FrontLights_Base", + -- "FrontLights_Glass", +} + +local RearLights = { + "RearLights", + "RearLights_Base", + "RearLights_Chrome", + -- "RearLights_Glass", +} + +local Windows = { + "WindowsRubber", + "WindshieldOutline", +} + +local Interior = { + "FrontLeftSeat", + "FrontRightSeat", + "RearSeats", + -- "Interior_Decals", + "Interior_DoorMaps", + "Interior_Plastic", + "SoundDynamics", + "SteeringWheel", + "SteeringWheel_Badge", + -- "SteeringWheel_Decals", + "SteeringWheel_Plastic", +} + +local Meshes = {} + +table.add(Meshes, Bodyparts) +table.add(Meshes, Details) +table.add(Meshes, FrontLights) +table.add(Meshes, RearLights) +table.add(Meshes, Windows) +table.add(Meshes, Interior) + +local builder = {} + +if SERVER then + local this = chip() + + builder = MeshBuilder:new(LINK) + :useGlobalScale(SCALE) + :useGlobalParent(this) + :useGlobalRelative(this) + + builder:buildAll(Meshes) + builder:getResult() + +else + PERMA.onPermissionsGained = function() + builder = MeshBuilder:new(LINK) + builder:useMaterialPipeline(Materials) + end + PERMA.build() +end From 98fe60a7656e0737cd53c5a7c301d504a923cb84 Mon Sep 17 00:00:00 2001 From: Ivan Grachyov Date: Thu, 28 Jul 2022 00:18:35 +0300 Subject: [PATCH 5/7] Fixed suspension breaking when car was flipped --- koptilnya/suspension/main.txt | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/koptilnya/suspension/main.txt b/koptilnya/suspension/main.txt index e113dd3..e7fde2f 100644 --- a/koptilnya/suspension/main.txt +++ b/koptilnya/suspension/main.txt @@ -4,10 +4,10 @@ local _restLength = 26.0 local _springTravel = 20.0 - local _springStiffness = 35000 - local _compressionDamper = 140000 -- 45000 - local _reboundDamper = 35000 -- 196000 - local _maxForce = 500000 + local _springStiffness = 45000 + local _compressionDamper = 250000 -- 45000 + local _reboundDamper = 150000 -- 196000 + local _maxForce = 800000 local _minLength = 0 local _maxLength = 0 @@ -70,17 +70,18 @@ if SERVER then local strutToWheelDirection = (strut:getPos() - wheel:getPos()):setX(0):setY(0):getNormalized() local springVelocity = (distance - lastLength) - local usedDamper = springVelocity > 0 and _compressionDamper or _reboundDamper + local usedDamper = springVelocity > 0 and _reboundDamper or _compressionDamper local spring = distance * _springStiffness local dampener = springVelocity * usedDamper local force = math.clamp((spring + dampener) * game.getTickInterval(), -_maxForce, _maxForce) - local direction = (strut:getPos() - wheel:getPos()):getNormalized() --base:getUp() + local direction = (strut:getPos() - wheel:getPos()):getNormalized() + local baseDirection = direction * Vector(0, 0, math.clamp(base:getUp().z, 0, 1)) lastLength = distance - base:applyForceOffset(-force * direction, wheel:getPos()) - wheel:applyForceCenter(force * direction * strutToWheelDirection) + base:applyForceOffset(-force * baseDirection, wheel:getPos()) + wheel:applyForceCenter(force * direction) end end From b884b06d44d1ab76c91793d392f72bfbf2422916 Mon Sep 17 00:00:00 2001 From: Ivan Grachyov Date: Thu, 28 Jul 2022 00:31:16 +0300 Subject: [PATCH 6/7] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8c207c7..7d65d7a 100644 --- a/README.md +++ b/README.md @@ -1 +1,2 @@ Не забудьте установить форматтер ```koihik.vscode-lua-format``` +Для WebStorm нужно поставить EmmyLua From c7933b47ace8d771509b1c1377b47abc80b04e87 Mon Sep 17 00:00:00 2001 From: Ivan Grachyov Date: Thu, 28 Jul 2022 00:31:49 +0300 Subject: [PATCH 7/7] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7d65d7a..1119fc4 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ Не забудьте установить форматтер ```koihik.vscode-lua-format``` -Для WebStorm нужно поставить EmmyLua +
+Для WebStorm нужно поставить ```EmmyLua```