Skip to main content

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.

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.

Item catalog

Defined in shared/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

1

Player builds a cart

Multiple items, each with a quantity. Total VICE cost is computed and shown live in the cart panel.
2

Click checkout

Dashboard fires marketplaceCheckoutcc_heistcontracts:marketplaceCheckout net event with the cart array.
3

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”).
4

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.
5

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.
6

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

Server hands items over

Validates ownership, expiry, and not-already-delivered. Calls cc_lib.Inventory.AddItem for each line. Pushes a pickupCleared action so the dashboard banner disappears, plus a success toast.

Pickup payload

{
  "pickupId": "p_3",
  "location": {
    "name": "El Burro Heights",
    "coords": { "x": 1128.21, "y": -2034.86, "z": 32.07 },
    "radius": 0.6
  },
  "expiresAt": 1730000600,    // os.time() + window
  "total": 5300,              // total VICE paid
  "items": [
    { "id": "c4",       "name": "C4",        "price": 2500, "qty": 1 },
    { "id": "thermite", "name": "Thermite", "price": 1800, "qty": 1 },
    { "id": "lockpick", "name": "Lockpick", "price": 250,  "qty": 4 }
  ]
}
The dashboard’s “Set GPS” button on the pickup banner uses the client-side 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:
CodeCause
empty_cartThe cart array is empty or not a table.
unknown_itemAt least one cart line has an id not in any category. The third return is the offending id.
no_profileServer couldn’t resolve the player’s profile.
insufficient_viceCart total exceeds the player’s VICE balance.
no_locationsThe locations table is empty. Configuration error — fix marketplace_config.lua.
Marketplace.Claim:
CodeCause
unknown_pickupPickup id was already cleared (delivered, expired, or never existed).
not_ownerA different player tried to claim.
already_deliveredRace condition — first claim already won.
expiredPlayer ran out the time window. The pickup is dropped at the same time.
The dashboard surfaces these as 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 pendingPickups in 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 calls cc_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.