Last active
March 27, 2023 21:30
-
-
Save CheezusChrust/114f3281fb324f14212c684fd71b3208 to your computer and use it in GitHub Desktop.
A Starfall-based SetAng steering chip with decent counter-steering abilities
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--@name Car Steering v3.4 | |
--@author Cheezus | |
--@shared | |
--@model models/sprops/rectangles_thin/size_2/rect_12x12x1_5.mdl | |
local showAxes = true | |
local frontWheelPos = Vector(50, 0, 0) -- Between your front wheels | |
local rightAxis = Vector(0, -1, 0) -- The RIGHT facing direction of your car | |
local upAxis = Vector(0, 0, 1) -- The UP facing direction of your car | |
local fwdAxis = rightAxis:cross(-upAxis) | |
rightAxis:normalize() | |
upAxis:normalize() | |
if SERVER then | |
local maxAngle = 45 -- Maximum steering angle, in degrees | |
local steeringForce = 120 -- Maximum steering force, affects steering rate and how much your inputs overpower the countersteer | |
local casterAngle = 0 -- Caster angle, in degrees | |
local slipCounterForce = 1 -- Stops you from slipping sideways | |
local gyroCounterForce = 1 -- Stops you from rotating, tries to maintain current angle | |
local counterMax = 180 -- Maximum counter force, can be completely overpowered by manual inputs if lower than steeringForce | |
local antiWobbleAngle = 1.5 -- Lower than this angle, multiply the current steering angle by the value below every tick | |
local antiWobbleMul = 0.25 -- This helps cars that have a tendency to wobble while driving straight at high speeds | |
local addRateMul = 0 -- Increases manual steering power based on velocity, 0 to disable, increase in increments of 1-2 | |
local interval = 2 -- Run every X ticks | |
wire.adjustPorts({ | |
Base = "entity", | |
A = "number", | |
D = "number", | |
Active = "number" | |
}, { | |
SteeringAngle = "number", | |
Slip = "number", | |
VelL = "vector", | |
Understeer = "number", | |
Oversteer = "number" | |
}) | |
local clamp = math.clamp | |
local abs = math.abs | |
local chip = chip() | |
local dt = game.getTickInterval() * interval | |
net.receive("requestBase", function(_, ply) | |
if not wire.ports.Base:isValid() then return end | |
net.start("sendBase") | |
net.writeEntity(wire.ports.Base) | |
net.send(ply) | |
end) | |
chip:setCollisionGroup(COLLISION_GROUP.WORLD) | |
local steeringAngle = 0 | |
local tickCount = 0 | |
hook.add("tick", "interval", function() | |
local active = wire.ports.Active > 0 | |
tickCount = tickCount + 1 | |
if tickCount % (active and interval or 10) ~= 0 then | |
return | |
else | |
tickCount = 0 | |
end | |
local base = wire.ports.Base | |
if not base:isValid() then return end | |
local localUpAxis = base:localToWorldVector(upAxis) | |
if active then | |
local a = wire.ports.A | |
local d = wire.ports.D | |
local fwpos = base:localToWorld(frontWheelPos) | |
local velL = base:worldToLocal(base:getPhysicsObject():getVelocityAtPoint(fwpos) + base:getPos()) * dt | |
local slip = velL:rotateAroundAxis(localUpAxis, -steeringAngle):dot(rightAxis) | |
wire.ports.Understeer = slip / velL:getLength() | |
wire.ports.Slip = slip | |
wire.ports.VelL = velL | |
slip = slip * slipCounterForce | |
local rearPos = -frontWheelPos * -upAxis | |
local rearVel = base:worldToLocal(base:getPhysicsObject():getVelocityAtPoint(rearPos) + base:getPos()) | |
wire.ports.Oversteer = rearVel:dot(rightAxis) / rearVel:getLength() | |
local yawDamping = base:getAngleVelocity():dot(localUpAxis) * dt | |
--yawDamping = yawDamping * upAxis.z | |
yawDamping = yawDamping * gyroCounterForce | |
local addRate = velL:getLength() * addRateMul | |
local turn = (a - d) * (steeringForce + addRate) * dt | |
local counter = clamp(slip + yawDamping, -counterMax, counterMax) | |
steeringAngle = clamp(steeringAngle + turn - counter, -maxAngle, maxAngle) | |
if (abs(steeringAngle) < antiWobbleAngle) and (a == 0 and d == 0) then | |
steeringAngle = steeringAngle * antiWobbleMul | |
end | |
else | |
steeringAngle = 0 | |
end | |
local casterAxis = base:localToWorldVector(fwdAxis):rotateAroundAxis(localUpAxis, steeringAngle) | |
local casterRotation = steeringAngle / maxAngle * casterAngle | |
local finalAngle = base:getAngles():rotateAroundAxis(localUpAxis, steeringAngle):rotateAroundAxis(casterAxis, -casterRotation) | |
chip:setAngles(finalAngle) | |
wire.ports.SteeringAngle = steeringAngle | |
end) | |
timer.create("freezer", 0.5, 0, function() | |
if not chip:isPlayerHolding() and not chip:isFrozen() then | |
chip:setFrozen(true) | |
end | |
end) | |
elseif player() == owner() then | |
if not showAxes then return end | |
local base | |
timer.create("requestBase", 0.5, 0, function() | |
net.start("requestBase") | |
net.send() | |
end) | |
net.receive("sendBase", function() | |
base = net.readEntity() | |
timer.stop("requestBase") | |
end) | |
enableHud(owner(), true) | |
local font = render.createFont("Trebuchet24", 24, nil, false, nil, nil, true) | |
hook.add("drawHud", "hud", function() | |
if not base or not base:isValid() then return end | |
local basePos = base:localToWorld(frontWheelPos) | |
local right = base:localToWorld(frontWheelPos + rightAxis * 50) | |
local up = base:localToWorld(frontWheelPos + upAxis * 50) | |
local fwd = base:localToWorld(frontWheelPos + fwdAxis * 50) | |
local alpha = math.max(300 - owner():getPos():getDistanceSqr(basePos) / 1000, 0) | |
if alpha > 0 then | |
render.pushViewMatrix({ | |
type = "3D" | |
}) | |
render.setColor(Color(255, 0, 0)) | |
render.draw3DLine(basePos, right) | |
render.setColor(Color(0, 255, 0)) | |
render.draw3DLine(basePos, up) | |
render.setColor(Color(0, 0, 255)) | |
render.draw3DLine(basePos, fwd) | |
render.popViewMatrix() | |
local rightScr = right:toScreen() | |
local upScr = up:toScreen() | |
local fwdScr = fwd:toScreen() | |
render.setFont(font) | |
render.setColor(Color(255, 0, 0, alpha)) | |
render.drawSimpleText(rightScr.x, rightScr.y, "Right", 1, 1) | |
render.setColor(Color(0, 255, 0, alpha)) | |
render.drawSimpleText(upScr.x, upScr.y, "Up", 1, 1) | |
render.setColor(Color(0, 0, 255, alpha)) | |
render.drawSimpleText(fwdScr.x, fwdScr.y, "Forward", 1, 1) | |
end | |
end) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment