> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rollingquest.kramgames.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Unlockables — Secret Balls and Letters API Reference

> API reference for the Unlockables namespace in RollingQuest Lua scripting. Manage secret ball collections, secret letter collections, and generic unlockable items.

The `Unlockables` namespace provides access to the game's unlock system. It manages secret ball collections, secret letter collections, and other unlockable content. You access it via the global `Unlockables` variable during gameplay.

## Properties

| Property        | Type                       | Read-only | Description                                    |
| --------------- | -------------------------- | --------- | ---------------------------------------------- |
| `secretBalls`   | `SecretBallsUnlockables`   | ✅         | Access to the secret ball collection system.   |
| `secretLetters` | `SecretLettersUnlockables` | ✅         | Access to the secret letter collection system. |

## Methods

### isLocked

Checks whether a specific unlockable item is currently locked.

```lua theme={null}
--- @param type UnlockableType
--- @param key string
--- @return boolean
function Unlockables:isLocked(type, key)
```

### unlock

Unlocks a specific item. Optionally defers the unlock until the level is won.

```lua theme={null}
--- @param type UnlockableType
--- @param key string
function Unlockables:unlock(type, key)

--- @param type UnlockableType
--- @param key string
--- @param applyWhenLevelWon boolean
function Unlockables:unlock(type, key, applyWhenLevelWon)
```

### lock

Locks a specific item.

```lua theme={null}
--- @param type UnlockableType
--- @param key string
function Unlockables:lock(type, key)
```

## SecretBallsUnlockables

Accessed via `Unlockables.secretBalls`.

### Properties

| Property         | Type      | Read-only | Description                                     |
| ---------------- | --------- | --------- | ----------------------------------------------- |
| `isAllCollected` | `boolean` | ✅         | `true` if all secret balls have been collected. |

### Methods

```lua theme={null}
--- @param ballIndex integer
--- @return boolean
function SecretBallsUnlockables:isCollected(ballIndex)

--- @param ballIndex integer
function SecretBallsUnlockables:collect(ballIndex)

--- @param ballIndex integer
--- @param applyWhenLevelWon boolean
function SecretBallsUnlockables:collect(ballIndex, applyWhenLevelWon)

--- @param ballIndex integer
function SecretBallsUnlockables:unCollect(ballIndex)
```

## SecretLettersUnlockables

Accessed via `Unlockables.secretLetters`. Same interface as `SecretBallsUnlockables` but for secret letter collections.

### Properties

| Property         | Type      | Read-only | Description                                       |
| ---------------- | --------- | --------- | ------------------------------------------------- |
| `isAllCollected` | `boolean` | ✅         | `true` if all secret letters have been collected. |

### Methods

```lua theme={null}
--- @param letterIndex integer
--- @return boolean
function SecretLettersUnlockables:isCollected(letterIndex)

--- @param letterIndex integer
function SecretLettersUnlockables:collect(letterIndex)

--- @param letterIndex integer
--- @param applyWhenLevelWon boolean
function SecretLettersUnlockables:collect(letterIndex, applyWhenLevelWon)

--- @param letterIndex integer
function SecretLettersUnlockables:unCollect(letterIndex)
```

## Usage Example

Check if a secret ball has been collected and collect it when the player finds a hidden trigger:

```lua theme={null}
function OnBallRoll(self, rollIn, side, ball)
    if self.tag ~= "secret_ball_trigger" then return end

    if not Unlockables.secretBalls:isCollected(3) then
        Unlockables.secretBalls:collect(3, true)  -- collect, apply when level won
        Dialog.createTemporary("Secret ball found!", 3.0)
    end
end
```

Check if an unlockable theme is locked:

```lua theme={null}
function OnStart()
    if Unlockables:isLocked(UnlockableType.Theme, "ice_theme") then
        Logger.info("Ice theme is still locked")
    end
end
```
