> For the complete documentation index, see [llms.txt](https://trident-cas.sabn.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://trident-cas.sabn.xyz/games/battles.md).

# Battles

[Related cases api documentation is available here](/api/cases.md)

#### Events

**Client -> Server**

**`battles:create`**

Creates a new battle lobby.

* **Payload**:

  ```json
  {
      "gamemode": "1v1", // "1v1", "1v1v1", "1v1v1v1", "2v2", "2v2v2", "3v3"
      "cases": ["case-id-1", "case-id-2"],
      "isBot": false, // true to fill empty spots with bots
      "isPrivate": false,
      "isReversed": false, // If true, lowest total wins
      "battleMode": "normal", // "normal", "share", "pointRush", "jackpot"
      "isLastChance": false, // True to enable Last Chance modifier
      "fundingOptions": { // Optional funding restrictions
          "percentage": 50,
          "onlyAffiliates": true,
          "minDeposit": 1000
      }
  }
  ```
* **Response (Emits Back)**: `battles:create` event emitted directly back to the creator's socket with `{ status: true, gameID: "uuid-string" }`, and the user is joined to that socket room with roomId as the gameId.

**`battles:join`**

Joins an existing battle lobby. Also used by the creator to "Call Bot", filling a specific empty spot with a bot.

* **Payload**:

  ```json
  {
      "gameID": "uuid-string",
      "spot": 1, // Optional: specific spot index (0-based, e.g., 1 for Player 2). Required if addingBot is true.
      "addingBot": false // Optional: set to true if the creator is calling a bot to fill the 'spot'
  }
  ```
* **Response (Emits Back)**: `battles:join` event emitted directly back to the socket with `{ status: true }` or `{ status: false, message: "..." }`. Note: If calling a bot fills the final spot, the game will automatically start after a 5-second delay.

**`battles:games`**

Requests the list of active, public battles. Supports optional pagination.

* **Payload**:
  * Legacy/Unpaginated: None (returns a raw array)
  * Paginated:

    ```json
    {
        "page": 1, // Optional: page index (starts at 1)
        "limit": 12 // Optional: number of items (default: 12, max: 100). For live-updating infinite scroll, poll page 1 with an increasing limit.
    }
    ```
* **Response (Emits Back)**: `battles:games` event with an array of active game objects (if unpaginated), or a paginated object containing `{ games, hasMore, total, page }`. Filters out private games, finished games, and games with incompatible balance types.

**`battles:details`**

Joins the socket room for a specific battle and requests its current details.

* **Payload**:

  ```json
  {
      "gameID": "uuid-string"
  }
  ```
* **Response (Emits Back)**: `battles:details` event with the public data of the requested game.

**`battles:sponsor`**

Allows the creator of a game to pay for (sponsor) a specific spot, allowing another player to join that spot for free.

* **Payload**:

  ```json
  {
      "gameID": "uuid-string",
      "spot": 1 // Required: the spot index to sponsor
  }
  ```
* **Response (Emits Back)**: `battles:sponsor` event with `{ status: true }` or `{ status: false, message: "..." }`. Also broadcasts `battles:details` to all users in the related game room.

**Server -> Client**

**`battles:games`**

Emitted in response to a client's `battles:games` request.

* **Payload**:
  * If unpaginated request:

    ```json
    [
        {
            "id": "uuid-string",
            "status": "waiting",
            "gamemode": "1v1"
            // ... public game data
        }
    ]
    ```
  * If paginated request:

    ```json
    {
        "games": [
            {
                "id": "uuid-string",
                "status": "waiting",
                "gamemode": "1v1"
                // ... public game data
            }
        ],
        "hasMore": true,
        "total": 45,
        "page": 1
    }
    ```

**`battles:details`**

Emitted to the entire room (or directly to a user) whenever a game lobby updates state. This happens when a player joins, a bot is added, details are explicitly requested, or a spot is sponsored.

* **Payload**:

  ```json
  {
      "id": "uuid-string",
      "status": "waiting",
      "participants": ["steamid", null],
      "sponsor": [0, 1]
      // ... public game data
  }
  ```

**`battles:pf`**

Emitted when the game starts, sharing Provably Fair data.

* **Payload**:

  ```json
  {
      "serverSeedCommitment": "sha256-hash",
      "publicSeed": "block-id",
      "round": 1,
      "gameID": "uuid-string"
  }
  ```

**`battles:spin`**

Emitted for every round of opening cases.

* **Payload**:

  ```json
  {
    "id": "game-id",
    "round": 2,
    "itemPools": [[...], [...]], // Visual items for the spinner
    "forces": [[...], [...]],    // The index where the spinner stops
    "items": [[...], [...]],     // The actual winning items for this round
    "status": "in-game",
    // ... other game state data
  }
  ```

***

#### Game Logic details

1. **Creation**: Validates cases, costs, and user balance.
2. **Bots**:
   * If `isBot` is true on creation, the game automatically fills with bots and starts.
   * Creators can also "Call Bot" to fill specific empty spots after creation using `battles:join` with `addingBot: true`. If adding a bot fills the final spot, the game automatically starts.
3. **Provably Fair**:
   * Generates a `serverSeed`.
   * Uses a `publicSeed`
   * Calculates `ticket` for each slot to determine the item.
4. **Spinning**:
   * The server calculates the result for a round.
   * Emits `battles:spin` with the target item (via `forces` index) and the visual pool.
   * Waits for client animation (approx 4.3s) before processing the next round.
5. **Result**:
   * Once all rounds are done, the server calculates the earnings.
   * Determines winner based on gamemode (Standard vs Reversed, Team 2v2).
   * Distributes winnings.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://trident-cas.sabn.xyz/games/battles.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
