Roadfolks

Roadfolks gives the traffic in Euro Truck Simulator 2 drivers who talk. It reads the vehicles around you out of shared memory, keeps each one as a tracked person with a nationality, a personality and a memory of you, and lets them speak over the CB, the phone, the radio or the passenger seat.

In development. The engine is complete and tested offline, with 374 tests that need no game, no network and no API key. It has never run against the real game. Read Status before you expect it to work.
Runs onWindows, alongside Euro Truck Simulator 2
NeedsETS2LA with its game plugin, the SCS telemetry plugin, Python 3.11 or later
Dialogue byA language model, through a chain of five providers
Voice byWingman AI: microphone, speech recognition, text to speech
Player languagesEnglish, Slovenian, Croatian
LicenceMIT
374
Python tests, all offline
21
Worker tests
24
event types
66
written characters
239
conversation topics
37
countries with a native voice

Who talks to you, and how

Nine kinds of speaker, on five channels. Every one of them is a person the simulation decided exists, not a line picked from a list.

Other truck drivers

CB

Generated from the lorries actually around you. Nationality follows where you are driving: in Slovenia mostly Slovenians, then Austrians and Croatians, then the Polish and Lithuanian plates that run half the continent.

Written characters

CB

66 people written by hand, each with a route, a lorry, a reason to be on that road and a story that moves one beat per conversation. About one truck in six can be one, if their corridor covers the country you are in.

Car drivers

Horn

One burst out of a window and gone. They are never stored: a motorist who shouts once is not worth a database row.

Radio presenters

Radio

30 invented stations that change when you cross a border, each in the local language. Traffic bulletins are built only from incidents the simulation actually saw.

Traffic police

CB

Three speeding events inside fifteen minutes earns a stop, and the officer tells you which one. Speaks the language of the country you are in.

Border and customs staff

CB

Stop within 6 km of a crossing and somebody asks for your documents.

Roadside mechanics

CB

Called out when the truck is damaged enough to need them.

Hitchhikers

Cabin

They have a real destination on the map and they get out when you reach it. You can refuse the lift.

Your dispatcher

Phone

Knows the cargo, the deadline and the damage report before you say a word. When a written dispatcher fits your company, you get that person permanently.

The channels

ChannelWhat it isUsed by
CBTruck-to-truck radio. Short, clipped, and you cannot see who is speaking.Other truckers, written characters
HornA car driver cannot call you, so they shout out of the window alongside.Motorists
PhoneA call into the cab. You can answer it.Your dispatcher
CabinSomebody in the passenger seat.Hitchhikers
RadioA broadcast. You listen; you cannot reply.Radio presenters

How you reply

You press the push-to-talk key and speak. Wingman AI turns that into text and hands it to Roadfolks, which gives it to whoever is currently in range on that channel. You can also start a conversation rather than wait for one.

A car driver shouting through a window cannot hear an answer, and a radio broadcast is one-way. Everything else can be answered.

An example

Marko hr-HR, CB

Ej, pazi malo! Vidiš da sam tu?

You push to talk

Sorry mate, didn't see you.

Marko

Is okay. You go Koper too? Big queue today.

Marko opens in Croatian because his English is 0.42 and the simulation knows it. He switches when you answer in English, and the reply is short and missing an article because that is what a 0.42 speaker sounds like. A Croatian voice reads it, so the accent is in the audio rather than spelled out in the text.

Features

What is built and covered by tests today.

Reads the game, not a script

  • Up to 39 nearby vehicles, the parked lorries and the traffic lights, from three ETS2LA shared-memory blocks.
  • Your own position, job, cargo and clock from the SCS telemetry plugin.
  • Stable tracking through the dropouts ETS2 produces when it re-sorts the traffic array.
  • 24 event types decided by geometry alone: cut-in, tailgating, near miss, convoy, jam, border crossed and the rest.

People, not voice lines

  • Nationality, name, age, home town, personality, English level and voice, drawn from where you are.
  • Three tiers: a car driver is never stored, a trucker lasts the session, a written character is stored forever.
  • Relationships that decay: annoyance, trust and familiarity per driver.
  • Memory in SQLite, so a restart does not lose who you have met.

Conversation

  • Answers in your language if you used it, then in a shared second language, then in English if their English is good enough.
  • Accent comes from a native text-to-speech voice. Dialogue is never spelled phonetically, and a test enforces it.
  • Four profanity levels. The default is moderate and it gets stronger when the character is provoked.
  • English, Slovenian and Croatian are the player languages out of the box.

Silence by default

  • A global cooldown, a per-driver cooldown, a personality roll and a ceiling of 6 unprompted lines per 10 minutes.
  • Under 15 lines an hour on a busy motorway. A test fails the build above that number.
  • Red lights are read from the game, including the seconds left, so nobody starts something the light will cut off. One line per junction.
  • In a lay-by, the engine waits 20 seconds after you stop before anybody speaks.

Content

  • 109 places with local detail, on 30 real freight corridors.
  • 239 conversation topics, filtered by country, weather, time of day and how well you know the speaker.
  • 105 easter eggs pinned to map coordinates, with real-world radii.
  • 273 story beats across 66 written characters in 31 countries.

Operations

  • Five model providers tried in order, with a canned line rather than an exception if all five are out.
  • A provider is parked by why it failed: quota, refused key, or error.
  • roadfolks doctor checks every part and prints one instruction per failure.
  • roadfolks probe --record saves a drive as JSONL for offline work, and roadfolks diagnose finds the shared-memory layout by physics if ETS2LA changes it.

Live demo

Eight of the written characters, in the browser. Dialogue only: no game, no voice, and nothing is remembered between visits.

The replies come from a model on Cloudflare Workers AI, using the same character sheets the mod uses. The demo is rate limited to six messages a minute per visitor and a fixed number a day for everybody together, so the free allowance survives.

Runs containers between Koper and Munich. Twenty-two years on the road. Loathes the Karawanken queue and says so every time.

Checking whether the demo is on.

Bojan answers in Slovenian and Marko in Croatian if you write to them in those languages.

How it works

The simulation decides the facts. The model only writes the words.

A model asked to invent an interesting trucker produces a different disposable person every time. Roadfolks never asks it to invent anything. It hands over a driver who already exists, an event that already happened and a grudge from last Tuesday, and asks for one line:

vehicle 1834, 12 m behind, followed you 4 min,
passed aggressively on the left, driver Marko,
Croatian, impatient, English 0.45, met once
before near Maribor

The pipeline

ETS2LA pluginTraffic, parked vehicles and traffic lights, from three shared-memory blocks.
SCS telemetry pluginYour position, job, cargo and the in-game clock.
TrackerKeeps one vehicle as one track across the dropouts.
Event detector24 event types from geometry. No randomness, no model calls.
World engineWho exists, what they remember, and whether anybody speaks at all.
Model routerOne line, from the first of five providers that answers.
Wingman AIMicrophone, speech recognition, voice and playback.

Why the layouts are the fragile part

Two modules know the binary shared-memory layouts, and nothing else does. They are transcribed from ETS2LA's own C# readers: bare arrays of fixed records, with no header, no magic number and no write counter. The record arithmetic is a test. A wrong layout produces plausible-looking floats rather than an exception, so every vehicle is checked against NaNs and physical limits before it reaches the simulation.

When ETS2LA changes the layout, the fix is a new entry in the layout table and a config change. roadfolks diagnose scores every known layout against the real buffer, and roadfolks diagnose --search finds the vehicle array with no layout knowledge at all, by looking for a repeating record that holds a position, a bounding box and a speed, then confirming the positions move between two samples a second apart.

Where the state lives

Story beats, relationships and memories are rows in SQLite, not context in a prompt. A restart does not lose them, and a player who talks constantly cannot rush somebody through a whole story in one afternoon.

Requirements

Both game plugins are required. Neither one alone is enough.

ComponentNeededWhy
Euro Truck Simulator 2 Required American Truck Simulator is planned but the name pools and places are Europe-only today.
ETS2LA, with its game plugin Required Writes the three traffic blocks. No block holds your own position.
SCS telemetry plugin Required The only source of your own position. Without it the engine refuses to start.
Python 3.11 or later Required Windows. 3.11, 3.12 and 3.13 are tested in CI.
One model API key Required for dialogue Cloudflare Workers AI is the default. Without a key the lines are canned.
Wingman AI Required for voice Without it, Roadfolks still runs and the lines arrive over HTTP as text.

The ETS2LA blocks contain traffic, parked vehicles and traffic lights. None of them contains your own position, which is why the SCS telemetry plugin is not optional. Without it the engine would have to measure every distance from the map origin, so it refuses to start instead.

Install

About fifteen minutes on a Windows game PC.

1. Install the game plugins

Put the ETS2LA game plugin and the SCS telemetry plugin in bin\win_x64\plugins inside the Euro Truck Simulator 2 folder. Create the folder if it is not there. Start the game once and leave it running in a job.

2. Install Roadfolks

git clone https://github.com/DavidKolsek/roadfolks-ets2 roadfolks
cd roadfolks
py -m venv .venv
.venv\Scripts\activate
pip install -e .

Use pip install -e ".[dev]" instead if you intend to run the test suite.

3. Add one model API key

setx CLOUDFLARE_ACCOUNT_ID "your-account-id"
setx CLOUDFLARE_API_TOKEN "your-token"

setx keeps the variable after a restart, but it does not affect the terminal you typed it in. Open a new terminal before the next step. Other providers are in docs/PROVIDERS.md.

4. Check what is missing

roadfolks doctor

One line per part: Python, the content library, the config, the database, the API keys, all four shared-memory blocks and the voice skill. Every part that is not ready prints one instruction. NOT READY stops the mod; MISSING costs a feature. The game has to be running or the three game items fail.

5. Start the service

roadfolks serve

The world engine listens on port 8731 over HTTP and WebSocket.

6. Add the voice skill

Copy wingman-skill\roadfolks into the Wingman AI skills folder and turn the skill on. Wingman owns the microphone, speech recognition, the voices and playback; Roadfolks does not reimplement any of that.

Without a game

roadfolks demo

Runs a whole encounter, with real dialogue, and prints each line beside the facts that produced it. Without an API key the lines are canned, which still proves the pipeline. The full first run on a game PC, with a check after every step, is in docs/GAME_PC.md.

Model providers

About half a cent per hour of play, and usually nothing.

Each line is a small request: under 2,500 tokens in and usually under 80 out. Speech recognition runs on your own PC through Wingman. The voices use Edge TTS, which is free.

ProviderDefault modelRole
Cloudflare Workers AI@cf/zhipu/glm-4.7-flashPrimary. Free allowance.
Groqopenai/gpt-oss-20bLow latency.
Google Geminigemini-3.1-flash-liteFree tier.
OpenRouteropenrouter/freeZero cost.
OpenAIgpt-5-nanoPaid fallback.

The five are tried in order. A provider that hits its quota sits out for as long as it asks, or for a cooldown that doubles each time up to an hour. A refused key sits out for six hours and the log names the environment variable to fix. One success clears the record.

If every provider is out, the driver says something short and fixed rather than nothing. Silence caused by a fault would look exactly like silence by design, and nobody can debug that from inside the game.

Not verified. No model ID in the table has been called with a real key. Run roadfolks selftest before trusting them, and roadfolks bakeoff to compare Slovenian and Croatian output.

Status

What is done, and what has not met the real game yet.

PartStateNote
Traffic tracking and event detection Done Tested offline against synthetic scenarios and recordings.
Characters, nationality, personality, memory Done
Silence budget and channel rules Done
Language policy and profanity levels Done
Content library Done 66 characters, 273 beats, 239 topics, 105 easter eggs, 109 places.
Radio, police, customs, hitchhikers, dispatcher Done
Provider fallback and quota handling Done No model ID has been called with a real key.
Shared-memory layouts Done Transcribed from ETS2LA's own C# readers, not guessed.
Shared memory against a running game Not verified Never run. First attempt is planned for 2026-09-20.
Event thresholds on real traffic Not verified Tuned on synthetic data only.
Heading calibration Not verified Decides whether “ahead” means ahead. Needs one drive.
Speech in and out through Wingman Not verified Never run against a live Wingman.
Live demo on Cloudflare Not verified Built and dry-run validated. Not deployed.

The full to-do list is in the repository.