diff --git a/README.md b/README.md index 8c207c7..1119fc4 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ Не забудьте установить форматтер ```koihik.vscode-lua-format``` +
+Для WebStorm нужно поставить ```EmmyLua``` 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 new file mode 100644 index 0000000..f88cba4 --- /dev/null +++ b/koptilnya/better_steering/config/sample.txt @@ -0,0 +1,28 @@ +-- @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, + PowerSteer = 0.5, + Axles = {{ + Lock = 30, + Camber = -2, + Caster = 8, + Ackermann = 15.43, + Toe = 0, + LeftOffset = 180, + RightOffset = 180 + }, { + Lock = 0, + Camber = -2, + Caster = 0, + Ackermann = 0, + Toe = 0, + LeftOffset = 180, + RightOffset = 180, + Direction = -1 + }} +}) diff --git a/koptilnya/better_steering/slave.txt b/koptilnya/better_steering/slave.txt new file mode 100644 index 0000000..f219ebc --- /dev/null +++ b/koptilnya/better_steering/slave.txt @@ -0,0 +1,105 @@ +-- @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) + +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 = 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: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' + outputs['SL_' .. self.order .. '_SteeringAngle'] = 'number' + outputs['SL_' .. self.order .. '_BaseLngVel'] = '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 + wire.ports['SL_' .. self.order .. '_SteeringAngle'] = self.steeringAngle + wire.ports['SL_' .. self.order .. '_BaseLngVel'] = self.baseLngVel +end + +function Slave:update() + if isValid(self.entity) and isValid(self.base) and isValid(self.wheel) then + if not self.entity:isFrozen() and not self.entity:isPlayerHolding() then + self.entity:setFrozen(1) + end + + 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 + 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 + + 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 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 new file mode 100644 index 0000000..fd682d6 --- /dev/null +++ b/koptilnya/better_steering/steering.txt @@ -0,0 +1,79 @@ +-- @include /koptilnya/libs/wire_component.txt +-- @include ./steering_axle.txt +-- @include /koptilnya/libs/table.txt +require('/koptilnya/libs/wire_component.txt') +require('./steering_axle.txt') +require('/koptilnya/libs/table.txt') + +Steering = class('Steering', WireComponent) + +function Steering:initialize(options) + options = options or {} + self.axles = {} + self.steer = 0 + self.sensitivity = options.Sensitivity or 1 + + 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() + + 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 _, axle in ipairs(self.axles) do + inputs = table.merge(inputs, axle:getInputs()) + outputs = table.merge(outputs, axle: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 _, 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/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/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 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/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/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..8fc6217 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, @@ -15,10 +15,15 @@ Axles = { Gravity = 0.15, Sensitivity = 0.25 }, + Brakes = { + Positive = KEY.S, + Gravity = 0.15, + Sensitivity = 0.25 + }, Shifter = { Positive = MOUSE.LEFT, 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 diff --git a/koptilnya/suspension/main.txt b/koptilnya/suspension/main.txt new file mode 100644 index 0000000..e7fde2f --- /dev/null +++ b/koptilnya/suspension/main.txt @@ -0,0 +1,100 @@ +--@name apply force suspension +--@author Koptilnya1337 +--@shared + + local _restLength = 26.0 + local _springTravel = 20.0 + local _springStiffness = 45000 + local _compressionDamper = 250000 -- 45000 + local _reboundDamper = 150000 -- 196000 + local _maxForce = 800000 + + 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 _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() + local baseDirection = direction * Vector(0, 0, math.clamp(base:getUp().z, 0, 1)) + + lastLength = distance + + base:applyForceOffset(-force * baseDirection, wheel:getPos()) + wheel:applyForceCenter(force * direction) + 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