Skip to Content
Resourcesqb-towjob Reference

qb-towjob

qb-towjob gives the tow job a flatbed, NPC vehicles to collect, and a payout at the end of a shift. The flatbed requires a deposit that is refunded on return.

The /tow command is also usable by the mechanic job, which makes this resource a soft dependency of a mechanic workflow. See qb-mechanicjob.

Before deploying it, read Payout. The shift payout scales with a drop count sent by the client.

The manifest at the commit linked above declares version 1.2.0.

Dependencies and start order

From the manifest: @qb-core/shared/locale.lua, config.lua and locales as shared scripts, the PolyZone client files client.lua, BoxZone.lua, ComboZone.lua, plus client/main.lua and server/main.lua.

From the implementation: qb-core for the full core object, and qb-inventory for the crypto stick reward.

Start order: qb-core, qb-inventory, PolyZone, then qb-towjob.

Note that server/main.lua calls exports['qb-core']:GetCoreObject() with no filter, so it holds a reference to the whole core table including QBCore.Shared.Items.

Configuration

KeyDefaultMeaning
Config.UseTargetfrom the UseTarget convarSet setr UseTarget true in server.cfg
Config.BailPrice250Flatbed deposit
Config.Vehicles{ flatbed = 'Flatbed' }Job vehicles
Config.Locationstablemain headquarters, vehicle spawn, dropoff

The per-drop pay and the tax rate are not in the config. PaymentTax = 15 is a local in server/main.lua, and the per-drop price is math.random(150, 170) in the same file.

Commands

CommandRegistered withWho can use it
/npcQBCore.Commands.AddEveryone, toggles the NPC display
/towQBCore.Commands.AddHandler checks job.name is tow or mechanic

Both use the default user permission, so the job check inside the handler is the real gate.

Server surface

HandlerKindArguments
qb-tow:server:DoBailnet eventbool, vehInfo
qb-tow:server:nanonet eventvehNetID
qb-tow:server:11101110net eventdrops

Deposit

DoBail with bool = true charges Config.BailPrice from cash, or from the bank if cash is short, records the amount per citizenid, and spawns the vehicle. With bool = false it refunds the recorded amount to the bank. The record lives in memory, so a restart between taking and returning the flatbed loses the refund.

Note the refund always goes to the bank even when the charge came from cash.

Crypto stick find

qb-tow:server:nano takes a network ID, resolves the entity on the server, and requires:

  • the caller’s job.name to be tow
  • the distance between the caller’s vehicle and the target vehicle to be 11.0 or less

Failure results in DropPlayer. On success there is a roughly 25 percent chance of a cryptostick. Note it resolves the entity from a network ID rather than trusting coordinates, which is the correct way to reference an entity across the client and server boundary. See OneSync and networked entities for why.

Payout

qb-tow:server:11101110 is the shift payout. It checks the caller’s job is tow and that the caller is within 6.0 units of Config.Locations['main'].coords, both read server side, then computes:

local DropPrice = math.random(150, 170) local price = (DropPrice * drops) + bonus local taxAmount = math.ceil((price / 100) * PaymentTax) Player.Functions.AddMoney('bank', price - taxAmount, 'tow-salary')

drops arrives from the client and is only passed through tonumber. It is not compared against anything the server recorded, so the payout scales linearly with a value the client chooses. That is the one thing to fix before running this on a public server. Track completed drops per source on the server, as qb-garbagejob does with its route table, and ignore the client’s number.

The bonus tiers are also worth reading before tuning them:

if drops > 5 then bonus = ... elseif drops > 10 then bonus = ... elseif drops > 15 then bonus = ... elseif drops > 20 then bonus = ... end

Because the chain is ordered ascending, any value above 5 matches the first branch and the three later branches are unreachable. Reverse the order if you want the higher tiers to apply.

Troubleshooting

SymptomLikely cause
Deposit not refunded after a restartThe deposit table is in memory only
Refund arrives in the bank after a cash paymentThe refund branch always targets the bank
Player dropped on the crypto stick rollJob is not tow, or the vehicles are more than 11 units apart
No payoutNot within 6.0 units of the headquarters coordinates, or the job is not tow
Bonus tiers never changeThe elseif ordering, see above
/tow does nothingThe job is neither tow nor mechanic

Proposed manual smoke test

Not yet executed. On staging:

  1. Take the flatbed, confirm the charge, return it, confirm the refund and which account it lands in.
  2. Restart the server between those steps and confirm the refund is lost.
  3. Complete one drop and confirm the payout after tax.
  4. Fire the payout event from outside 6 units and confirm the drop.
  5. After adding server-side drop tracking, confirm a forged count no longer changes the payout.

Sources