Mechanic
Roadside assistance: the customer calls, mechanics bid a price, and the customer picks one.
The app is called Mechanic. A stranded driver calls from it, mechanics answer from it — same app, different screen depending on the player's job.
There is nothing to create here. Unlike restaurants, one job code in the config is the whole setup:
Config.Mechanic = {
Enabled = true,
JobCode = "mechanic", -- your job, exactly as the framework knows it
RequireDuty = true, -- only clocked-in mechanics receive calls
}Whoever holds that job opens Mechanic and lands on the Service calls list. Everyone else gets the call form.
More than one shop
Bennys, a tuner shop and your main garage can share the same call pool:
AlternativeJobs = { "bennys", "tuner" },Both shapes work — a plain list as above, or { ["bennys"] = true } if you prefer the style the rest of the config uses. Setting one to false switches it off.
How a call runs
The driver calls
They open Mechanic, pick Repair, Fuel or Tow, and send it.
The phone fills in the rest by itself: the street they are on, and the car they are in or standing next to — model, plate, and how bad the engine and body are. A note is optional.
If nobody is on duty the call is refused on the spot with No mechanic is available right now, rather than sitting in a queue nobody will read.
Mechanics bid
Every on-duty mechanic gets a notification and the call in their Service calls list, with the vehicle's engine and body condition on the card.
They type a price and Send offer. Any number of them can bid on the same call, and a second offer replaces their first.
Rival prices are hidden on purpose — a mechanic only sees how many others have bid, not what they asked. Nobody has driven anywhere yet, so bidding costs nothing.
The driver picks
Offers arrive on the driver's phone cheapest first, each with the mechanic's name and phone number, so they can ring and ask before choosing.
Accept picks one. That mechanic gets a waypoint to where the driver is now, and everyone who bid and lost is told.
The mechanic finishes
Once they are within CompleteDistance of the driver, Complete ends the job: the bill is raised for the agreed price, and the service is applied to the car.
Too far away and it refuses — nobody gets billed for a mechanic who never arrived.
Either side can back out. The driver's Cancel request costs them a cooldown; the mechanic's Drop job withdraws their own offer and hands the call back to the pool, so the driver can just pick somebody else instead of starting over.
Calls are not stored in the database — restarting the resource clears the open ones.
The three services
What each one actually does is the action field:
| Type | action | What happens on Complete |
|---|---|---|
| Repair | repair | The car is fixed — engine, body, deformation, engine back on |
| Fuel | fuel | The tank is set to FuelAmount litres. 100 fills it |
| Tow | none | Nothing automatic. The mechanic roleplays it |
Add, remove or rename them in Types:
Types = {
{ id = "repair", label = "MECHANICAPP.TYPE_REPAIR", icon = "wrench", action = "repair" },
{ id = "fuel", label = "MECHANICAPP.TYPE_FUEL", icon = "drop", action = "fuel", FuelAmount = 100.0 },
{ id = "tow", label = "MECHANICAPP.TYPE_TOW", icon = "car_fill", action = "none" },
},label is a locale key, so a new type is named in locales/*.json. action only understands those three values — anything else behaves like none.
The service is applied to the car the job was quoted on: the plate has to still match. A driver who wandered over to another car gets nothing repaired, rather than the wrong car fixed on someone else's bill.
Prices
Mechanics name their own price, within a range you set:
Quote = { Min = 0, Max = 25000 },Checked on the server, so an edited phone cannot send a price outside it. The bill goes through Config.BillingCommissions like every other invoice.
Settings
Config.Mechanic = {
Enabled = true,
JobCode = "mechanic",
AlternativeJobs = {}, -- extra jobs sharing the same call pool
RequireDuty = true, -- only clocked-in mechanics receive calls
Quote = { Min = 0, Max = 25000 },
CompleteDistance = 20.0, -- metres the mechanic must get within
RequestTimeout = 600, -- seconds before an unanswered call expires
CancelCooldown = 120, -- seconds before the driver may call again
BillingDescription = "Mechanic service", -- uses Config.BillingCommissions
Blip = { enabled = true, blip = 402, colour = 5, scale = 0.8, text = "Mechanic Request" },
}When something is not working
"No mechanic is available right now." Nobody is on shift. With RequireDuty = true they have to be clocked on, not merely on the job.
A mechanic sees the call form instead of the job list. Their job does not match JobCode or any entry in AlternativeJobs. Case and spelling have to be exact.
Fuel does not stick. The tank is set both ways — the native and the fuel statebag most fuel resources read. A resource that uses neither needs its own line in applyService.

