qb-scrapyard
qb-scrapyard posts a rotating list of wanted vehicle models. A player who delivers a matching
vehicle to the scrapyard receives crafting materials. The list regenerates every hour.
It produces the same material set as qb-recyclejob, through a different gameplay loop. Both feed crafting and repair systems.
The manifest at the commit linked above declares version 1.5.0.
Dependencies and start order
From the manifest: a shared_script block containing PolyZone client.lua, BoxZone.lua,
ComboZone.lua, config.lua, @qb-core/shared/locale.lua, and locales. client.lua on the
client, and @oxmysql/lib/MySQL.lua plus server.lua on the server.
Note that PolyZone is loaded through shared_script here rather than client_script, which is how
the upstream manifest is written at this commit.
From the implementation: qb-core and qb-inventory.
Start order: oxmysql, qb-core, qb-inventory, PolyZone, then qb-scrapyard.
Configuration
| Key | Default | Meaning |
|---|---|---|
Config.UseTarget | from the UseTarget convar | Set setr UseTarget true in server.cfg |
Config.Locations | one entry | main, deliver, and list zones |
Config.Items | seven entries | Material pool: metalscrap, plastic, copper, iron, aluminum, steel, glass |
Config.VehicleCount | 40 | Target size of the wanted list |
Config.CurrentVehicles | {} | Runtime list, do not edit |
Config.Vehicles | model list | Candidate models for the wanted list |
The reward quantities are not configurable. server.lua grants 2 to 4 material stacks of 25 to 45
units each, plus a one in eight chance of 10 to 20 rubber.
Config.VehicleCount is a target, not a guarantee. GenerateVehicleList draws
Config.VehicleCount random models and skips duplicates without retrying, so the actual list is
shorter than 40 whenever a duplicate is drawn.
Database
No table of its own and no SQL file. It reads player_vehicles:
SELECT `plate` FROM `player_vehicles` WHERE `plate` = ?The qb-scrapyard:checkOwnerVehicle callback returns true when the plate is not found, in
other words when the vehicle is not player owned. This is what stops players from scrapping each
other’s owned vehicles for materials.
Server surface
| Handler | Kind | Arguments |
|---|---|---|
qb-scrapyard:server:LoadVehicleList | net event | none, sends the current list to the caller |
qb-scrapyard:checkOwnerVehicle | callback | plate, returns true when the plate is not owned |
qb-scrapyard:server:ScrapVehicle | net event | listKey |
Reward validation
ScrapVehicle takes only a list index from the client and re-derives everything else on the server:
- Resolve the player from
source. - Read the ped, and the vehicle the ped is in, on the server.
- Require the ped to be in the driver seat,
GetPedInVehicleSeat(vehicle, -1). - Read the vehicle’s model hash on the server.
- Require
GetHashKey(Config.CurrentVehicles[listKey])to equal that model hash. - Remove the entry from the list and broadcast the new list.
Because the model is read from the actual entity the player occupies, a forged listKey only
succeeds if the player really is driving a vehicle of that model. The reward items and quantities
come from Config.Items and server-side math.random calls, never from the client.
What is not checked is distance to the delivery zone. The client-side zone is the only thing placing
the player at the scrapyard. If that matters, add a server-side distance check against
Config.Locations[1]['deliver'].coords, in the style of
qb-storerobbery.
Step 5 also means that duplicate models in the wanted list can be scrapped with any matching vehicle, so a player who owns one such model can scrap repeatedly as long as the ownership check passes on the plate used.
Note on the client event name
The server broadcasts to qb-scapyard:client:setNewVehicles, missing the r in “scrapyard”. The
client registers the same misspelled name, so the pair works. Use the exact misspelled string if you
write your own handler for it.
Troubleshooting
| Symptom | Likely cause |
|---|---|
Wanted list is shorter than Config.VehicleCount | Duplicate draws are skipped without retry |
| Delivering the right model does nothing | The player is not in the driver seat, or the plate belongs to a player_vehicles row |
| No materials granted | An entry in Config.Items is missing from your shared items |
| List never appears | The client listens on qb-scapyard:client:setNewVehicles, note the spelling |
| List does not refresh | GenerateVehicleList runs on a one hour loop. Restart the resource to force it |
Proposed manual smoke test
Not yet executed. On staging:
- Confirm every entry in
Config.Itemsplusrubberexists in your shared items. - Deliver a wanted model and confirm materials arrive.
- Attempt the same with a player-owned plate and confirm the refusal.
- Attempt it from the passenger seat and confirm the refusal.
- Restart the resource and confirm the wanted list changes.