Files
tpf3-overtake/docs/research/overtake-feasibility.md
2026-10-04 21:58:04 +02:00

4.7 KiB

Can TpF3 scripting make cars overtake?

Issue #2 (part of map #1). Researched 2026-10-04.

Verdict: not feasible with the documented API. Scripts can observe vehicles and scale a vehicle's top speed, but nothing documented lets a script change a road vehicle's lane, path position or per-tick movement. Overtaking would need engine support that the docs do not show.

Sources

Findings

  1. The "modifiers/filters" page is about resource loading, not runtime behaviour. addModifier(category, fn) edits resource data (fileName, data) as it loads, and addFileFilter toggles resource visibility. Vehicle-related categories are only loadModule, loadMultipleUnit, plus the model/vehicle and model/car filters. They cannot touch live vehicle movement. The page says it "is not yet adapted for Transport Fever 3", so it may be outdated.
  2. BaseConfig has no road-vehicle or traffic-behaviour fields. The vehicle-related ones are trainAccelerationFactor, trainBrakeDeceleration, simulateCargoWeight, loadspeedPenaltyForTrainOverlength and maxVehicleCloneAmount. All are global and train-oriented. This runs once in preRunFn.
  3. Game script phases. gamescript.html defines update, postUpdate and handleEvent, which run on the engine state with mutable script state, and guiUpdate and guiHandleEvent for the GUI. "Mutable" here means the script's own state, not engine entities. api.engine is documented as "for reading the game engine state". So per-tick script code can read the world but only change it through api.cmd commands.
  4. Read access to vehicles exists but is thin. api.engine.system.landVehicleMoveSystem exposes getVehicleInfo(vehicleEntity), whose LandVehicleMoveInfo return type is not expanded in the docs. It also has getBlockedTrains, isTrainWaitingForFreePath and forEach (train oriented). Components include Engine.Component.MovePath (path, dyn.pathPos, dyn.speed, dyn.accel, blocked, occupiedFrontIndex, occupiedBackIndex) and Engine.Component.LandVehicle (isTram, dyn.brakingTimer, turnLeft, turnRight). BaseEdge carries laneConfig and BaseNodeConfig.laneConnections.
  5. Write access is limited to commands. The relevant api.cmd entries are makeVehicleSetModifiersCmd(vehicle, TransportVehicle.Modifiers), makeVehicleSetStoppedByUserCmd, makeVehicleSendToDepotCmd, makeVehicleReverseCmd, makeVehicleSetLineCmd and makeVehicleTryToDepartCmd. There is no command to set a MovePath, speed, lane or position on a land vehicle. makeComponentExchangeCmd is marked debug and its doc says it accepts only EmissionEmitter or ModelInstanceList. makeCustomVehicleCreateOrUpdateCmd takes a Carrier and an optional movePathAircraft, so it is aimed at aircraft or custom vehicles rather than road traffic.
  6. No overtaking concept appears anywhere. A text search of api.engine, api.engine.system and api.cmd found no "overtake" or "passing" terms.

Candidate mechanisms

Mechanism What it gives Overtaking?
makeVehicleSetModifiersCmd with topSpeedScale Per-vehicle top speed scaling No. A faster car still queues behind a slower one.
BaseConfig in preRunFn Global acceleration or braking (trains only) No
Lane config (BaseEdge.laneConfig, laneConnections) via construction or street definitions Static lane layout, for example an extra lane built into the road Only as static road design. Whether the engine's car AI uses a spare lane to pass is undocumented.
landVehicleMoveSystem / MovePath reads Observe speed, position and blockage per tick Detection only
Custom entities / custom vehicles (makeCustomEntity*, makeCustomVehicleCreateOrUpdateCmd) Script-driven fake visuals Theoretically a script could despawn a real car and animate a fake one past the blocker. This is a heavy hack with unproven viability for road vehicles.

Open questions (not answered by the docs)

  • The fields of LandVehicleMoveInfo.
  • Whether the engine already supports passing on multi-lane or bus-lane roads, outside of script control.
  • Whether anything outside the published script-doc (native mod interfaces) exists. Testing in-game would be the next step.