AiDriver
An AI driver for the car it sits on. Put it on a car's chassis: a torqueCars `Car` (driven through `Car:setIntent`) or a builtin `VehicleController` (driven through its own `setIntent`, throttle -1..1). It only thinks on the peer that owns the car (`entity:isLocal()`), at the per…
AiDriver
An AI driver for the car it sits on. Put it on a car's chassis: a torqueCars Car (driven through Car:setIntent) or a builtin VehicleController (driven through its own setIntent, throttle -1..1). It only thinks on the peer that owns the car (entity:isLocal()), at the personality's rate (15-40 Hz), and keeps its inputs between ticks.
What it does each tick: finds where it is along its line (nearest point, searched in a window around the last one; a whole-path search only after a knock), steers by pure pursuit at a lookahead that grows with speed plus yaw-rate feedback (damps the weave and catches oversteer), takes a target speed from the curvature ahead (v = sqrt(latG * 9.81 / k), pulled down before corners by its braking deceleration), keeps a gap to the car ahead (a cone in front of it, against a car list shared by every driver and refreshed once a second), overtakes or goes round a stopped car, gets itself unstuck (under 1.5 m/s for 2 s, for any reason: 1.6 s reverse with the nose swinging toward the path, the other lock on each retry; still slow at 5 s, or 8 s without gaining 6 m along the path, 4 s when far off the road: respawned on its line at the nearest clear point ahead, no other car within 8 m, drift or tourist manoeuvre cancelled), resets upright when flipped for 2 s, and drives back to its line after being knocked off. It learns the car: the braking it plans for drops to what it measures, and the cornering g drops a little each time it runs wide.
Fields: personality (commuter, aggressive, racer, drifter, tourist), path (a roadPieces road, or an entity whose children are waypoints in order), loop, autoPath (follow the nearest roadPieces road when nothing else is given), roadWidth, laneOffset (-1 = the personality's lane), speedLimit (m/s, 0 = none), driving, seed, aimOffset (metres right of its own line to aim for, kept inside the road: a pickup to grab), pace (0.3 to 1.6, multiplier on the speed it plans, read every tick: rubber-banding).
vehiclesKit vehicles: on a vehiclesKit Vehicle (whose VehicleController is stepped from the Vehicle's own intent every physics step) the driver drives through Vehicle:setIntent, braking at a stop to reverse. When a person sits in the driver's seat it hands the controls back (setIntent(nil)) and waits until the seat is free again.
Methods: setPath(points, loop), clearPath(), setPersonality(name) (any name defined in aiDrivers.personalities), laps() → { count, last, best, times, current } (physics seconds, start-line crossing to crossing), state() (mode, index, offPath, speed, targetSpeed, pedals, drift phase, body slip, rearSlipAngle/rearSlipMean/rearSlipMax, tourist state, stuck/reset counts, slowTime/noProgressTime/reverseTries/lastRecovery, learned planGrip/planDecel), stats() → { avgTickMs, maxTickMs, ticks, rate, msPerSecond }, resetStats(), linePoints(), respawnOnPath() (nearest clear point on its line).
Values it publishes on the chassis: ai.hazard (stopped or lost; replicated), ai.lap.
local Assemble = require("torqueCars.assemble")
local car = Assemble.spawn({ kind = "coupe", position = vector.create(0, 0.3, 0), control = "script" })
local ai = car.component.add("AiDriver", { personality = "racer", roadWidth = 9 })
ai:setPath({ vector.create(0, 0, 0), vector.create(0, 0, -120), vector.create(60, 0, -150), vector.create(80, 0, -20) }, true)
Scoped to this part · feeds back into the world's score.