GKSHOP
GKSPHONE V2Configuration

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.lua
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:

config.lua
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:

TypeactionWhat happens on Complete
RepairrepairThe car is fixed — engine, body, deformation, engine back on
FuelfuelThe tank is set to FuelAmount litres. 100 fills it
TownoneNothing automatic. The mechanic roleplays it

Add, remove or rename them in Types:

config.lua
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:

config.lua
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.lua
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.

On this page