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 dashboard is the player’s window into everything in cc_heistcontracts. It opens with F6 (configurable via config.openKey) or the /heist command, and blocks until the player closes it — SetNuiFocus(true, true) is held while it’s up.

How it boots

1

Player presses F6 / runs /heist

client/main.lua flips isOpen, sends a { action = 'open' } NUI message, takes NUI focus, and fires cc_heistcontracts:requestSync to the server.
2

Server replies with a bootstrap payload

Includes currency config, slot count, the player’s profile, the active rotation, the marketplace catalog, the player’s crew (if any), and the training catalog. Sent on cc_heistcontracts:sync with action bootstrap.
3

Dashboard requests an alias on first open

A new profile has alias = NULL. The dashboard refuses to render the rest of the UI until the player picks one. Server-side validation: 3–16 chars, must start with a letter, alphanumerics + underscore, case-insensitively unique across all profiles.
4

Dashboard renders

Tabs: Contracts, Slots, Marketplace, Training, Crew, Ledger.
The server adds src to a viewers set on bootstrap and removes it on close. Rotation broadcasts only target current viewers — a player whose dashboard is closed won’t receive rotation updates until they reopen.

Sync protocol

All server → client traffic flows over a single net event, cc_heistcontracts:sync, with a string action discriminator and a data payload.
ActionPayloadMeaning
bootstrapfull stateSent once when the dashboard opens.
profileprofile onlySent after any mutation (purchase, discard, transfer, training unlock, alias change, XP grant).
rotationrotation snapshotBroadcast to viewers when the rotation re-rolls.
crewcrew snapshot or nilWhen the player joins, leaves, or their crew is disbanded.
transferInviteinviteA different player offered to transfer a contract slot.
crewInviteinviteA different player invited the player to a crew.
pickuppickup payloadMarketplace checkout completed; the dashboard switches to the pickup banner.
pickupCleared{ pickupId }Pickup was claimed (or cleared by another path).
toast{ kind, message }Inline toast shown by the dashboard. kind is success, error, or info.

Profile payload shape

What the dashboard receives on every profile push:
{
  "citizenid": "ABC12345",
  "alias": "ghost_42",
  "characterName": "John Doe",
  "level": 7,
  "xp": 5400,
  "xpInLevel": 1000,    // XP accumulated within the current level
  "xpForLevel": 3600,   // XP span needed to finish the current level
  "viceBalance": 12500,
  "slots": [
    { "contractId": "fleeca_heist", "acquiredAt": 1730000000 },
    null,
    null
  ],
  "stats": {
    "completed": 14,
    "failed": 2,
    "totalViceEarned": 21000,
    "byContract": { "fleeca_heist": { "completed": 10, "failed": 1 } },
    "firstHeistAt": 1729800000,
    "favoriteContract": "fleeca_heist"
  },
  "ledger": [ /* last 50 VICE entries */ ],
  "trainingUnlocked": true,
  "trainingMinigames": { "drill": true, "circuit": true }
}
xpInLevel and xpForLevel are computed server-side via Profile.LevelProgress, so the dashboard’s level ring stays in sync with the configured curve without duplicating the math client-side.

Client → server actions

Every interactive control on the dashboard triggers a NUI callback that bridges to a net event. They’re all in client/main.lua:
NUI callbackServer net eventEffect
close(none)Clears NUI focus.
setAliascc_heistcontracts:setAliasFirst-open alias picker. Server validates and pushes a profile on success.
buyContractcc_heistcontracts:buyContractPurchase a rotation contract into a slot.
startContractcc_heistcontracts:startContractStart a slot — invokes the registered entry_point. Closes the dashboard automatically.
discardContractcc_heistcontracts:discardContractEmpty a slot. No refund.
transferContractcc_heistcontracts:transferContractSend a contract slot to another player. The recipient gets a transferInvite.
transferResponsecc_heistcontracts:transferResponseAccept/decline an inbound transfer.
marketplaceCheckoutcc_heistcontracts:marketplaceCheckoutPay VICE, get back a pickup payload.
pickupSetGps(none, client-only)SetNewWaypoint to the active pickup’s door.
crewInvite / crewInviteResponse / crewLeavematching cc_heistcontracts:crew*Wraps cc_lib.Groups.
trainingUnlock / trainingUnlockMinigame / trainingStartmatching cc_heistcontracts:training*Training sandbox.
nearbyPlayers(client-only)Returns server ids + names within 50 m. Used by the transfer / crew invite target picker.

Alias rules

function validateAliasFormat(alias)
    -- length 3..16, must match ^[A-Za-z][A-Za-z0-9_]+$
end
Error codeMeaning
invalidNot a string, or other malformed input.
lengthOutside 3–16 chars.
charsetDoesn’t match the regex (must start with a letter; only letters, digits, underscore).
takenCase-insensitively in use by another profile.
no_profileServer couldn’t load the player’s profile (citizenid lookup failed).
dbUPDATE didn’t affect any rows (extremely rare, usually a transient DB error).
The error code is returned to the client via the cc_heistcontracts:aliasResult net event so the dashboard can show an inline message.

Cleanup

  • Player drops — server clears them from viewers, removes them from any crew (disbanding if leader), flushes their profile, evicts from cache.
  • Resource stops — client clears NUI focus; server flushes every cached profile.