The Marketplace tab on the dashboard is a VICE storefront for heist-prep items. The flow is checkout → pickup banner → drive to the door → knock → items, with a server-side time window in the middle.Documentation Index
Fetch the complete documentation index at: https://docs.cc-scripts.com/llms.txt
Use this file to discover all available pages before exploring further.
Item catalog
Defined inshared/marketplace_config.lua. Categories of items, each with an id (must match your inventory item name), a display name, and a VICE price.
The server strips the catalog of any non-serializable fields before sending it to the dashboard, so you can reference Lua-only values (functions, vectors) inside the config — they just won’t reach the NUI.
Checkout flow
Player builds a cart
Multiple items, each with a quantity. Total VICE cost is computed and shown live in the cart panel.
Click checkout
Dashboard fires
marketplaceCheckout → cc_heistcontracts:marketplaceCheckout net event with the cart array.Server validates and debits
Each item is looked up; an unknown id rejects the whole cart. Total is summed against the player’s VICE balance. On success, VICE is debited atomically (one ledger entry: “Marketplace checkout”).
Server rolls (or merges into) a pickup
First active checkout for the player → uniformly random pickup location from
marketplace_config.locations, with that location’s window (seconds) deadline. Subsequent checkouts while a pickup is active merge into the existing pickup — items combine, deadline does not extend.Pickup banner appears
Server pushes a
pickup action with { pickupId, location, expiresAt, total, items }. Client spawns an ox_target sphere zone at the door coords, label “Knock”, radius from config.Player drives there and knocks
Interacting with the zone plays the door-knock animation (
timetable@jimmy@doorknock@), then fires cc_heistcontracts:marketplaceClaim with the pickup id.Pickup payload
pickupSetGps callback — SetNewWaypoint(coords.x, coords.y) runs locally; nothing is round-tripped through the server.
Failure modes
Marketplace.Checkout returns one of these error codes when it returns false:
| Code | Cause |
|---|---|
empty_cart | The cart array is empty or not a table. |
unknown_item | At least one cart line has an id not in any category. The third return is the offending id. |
no_profile | Server couldn’t resolve the player’s profile. |
insufficient_vice | Cart total exceeds the player’s VICE balance. |
no_locations | The locations table is empty. Configuration error — fix marketplace_config.lua. |
Marketplace.Claim:
| Code | Cause |
|---|---|
unknown_pickup | Pickup id was already cleared (delivered, expired, or never existed). |
not_owner | A different player tried to claim. |
already_delivered | Race condition — first claim already won. |
expired | Player ran out the time window. The pickup is dropped at the same time. |
error toasts with the literal error code in the message, so a player seeing Pickup failed: expired knows exactly what happened.
Auto-cleanup
- A
SetTimeout(window * 1000)per pickup drops it from the in-memory map when its window elapses. - A successful claim removes the pickup from the map immediately.
- Pickups currently don’t survive a server restart — they live only in
pendingPickupsin memory. If the server restarts mid-pickup, the player’s VICE was already debited and the items are lost. Worth being aware of if you do rolling restarts.
Inventory dependency
Item delivery callscc_lib.Inventory.AddItem(src, line.id, line.qty). If cc_lib doesn’t have an Inventory module wired up to your core, the claim will fail with Pickup failed: no inventory module. The VICE was already debited at checkout — a manual refund or a re-roll of the pickup is the recovery, not a known automatic path.