206 lines
11 KiB
Markdown
206 lines
11 KiB
Markdown
# Minigame Definition Reference
|
|
|
|
Minigame definitions live in `src/main/resources/Server/Minigames/<Id>.json`. JSON keys use PascalCase. The filename should match the `Id` field.
|
|
|
|
## Identity
|
|
|
|
| Field | Type | Required | Default | Description |
|
|
|-------|------|----------|---------|-------------|
|
|
| `Id` | String | Yes | none | Unique asset ID. Use underscores instead of spaces. |
|
|
| `Name` | String | Yes | none | Display name shown in commands and UI. |
|
|
| `Description` | String | No | `""` | Short display description. |
|
|
| `Enabled` | Boolean | No | `true` | Whether the minigame can be started. |
|
|
| `Debug` | Boolean | No | `false` | Enables verbose minigame debug messages when supported by runtime logic. |
|
|
| `GameType` | Enum | No | `GENERIC` | `GENERIC`, `BATTLE`, `PUZZLE`, `RACE`, `CAPTURE`, or `SURVIVAL`. |
|
|
|
|
## World Binding
|
|
|
|
| Field | Type | Required | Default | Description |
|
|
|-------|------|----------|---------|-------------|
|
|
| `WorldId` | String | No | `""` | When set, the game may only be started in this world; starts from other worlds are refused with a message. |
|
|
| `RequiredGameMode` | Enum | No | `Adventure` | Game mode applied to each player when they become active. |
|
|
|
|
## Players
|
|
|
|
| Field | Type | Required | Default | Description |
|
|
|-------|------|----------|---------|-------------|
|
|
| `MinPlayers` | Integer | No | `1` | Minimum player count. |
|
|
| `MaxPlayers` | Integer | No | `16` | Maximum player count. |
|
|
| `DefaultPlayerLives` | Integer | No | `0` | Initial lives assigned to each player when a queued runtime starts. |
|
|
| `AllowJoinMidgame` | Boolean | No | `false` | When `true`, a player who disconnects mid-game is re-activated on reconnect. When `false`, reconnecting players get their saved inventory back and are dropped from the game. |
|
|
| `AllowSpectators` | Boolean | No | `true` | Whether `/minigame spectate` may join the game as a spectator. |
|
|
|
|
## Teams
|
|
|
|
| Field | Type | Required | Default | Description |
|
|
|-------|------|----------|---------|-------------|
|
|
| `TeamMode` | Enum | No | `SOLO` | `SOLO`, `TEAMS`, or `FREE_FOR_ALL`. With `TEAMS`, teams are auto-created and balanced when a queued game starts (using `TeamCount` / `PlayersPerTeam`). |
|
|
| `TeamCount` | Integer | No | `0` | Explicit number of teams when using `BalanceTeams`. `0` defers to `PlayersPerTeam`. |
|
|
| `PlayersPerTeam` | Integer | No | `0` | When `TeamCount` is `0`, `BalanceTeams` divides total players by this to determine team count. `0` means no automatic splitting. |
|
|
|
|
## Timing
|
|
|
|
| Field | Type | Required | Default | Description |
|
|
|-------|------|----------|---------|-------------|
|
|
| `RoundLengthSeconds` | Integer | No | `300` | Active round duration. |
|
|
| `TotalRounds` | Integer | No | `1` | Number of rounds to run. Values less than or equal to `0` allow open-ended round progression. |
|
|
| `CountdownSeconds` | Integer | No | `10` | Pre-game countdown duration. |
|
|
| `OvertimeEnabled` | Boolean | No | `false` | When the final round ends, enters `OVERTIME` for `OvertimeSeconds` and dispatches `on_overtime_start`. When the overtime timer expires the game either enters sudden death (if enabled) or ends. |
|
|
| `OvertimeSeconds` | Integer | No | `60` | Overtime duration. Must be positive when overtime is enabled. |
|
|
| `SuddenDeathEnabled` | Boolean | No | `false` | After the final round (and overtime, if enabled), enters `SUDDEN_DEATH` for `SuddenDeathSeconds` and dispatches `on_sudden_death_start`. The game ends when the timer expires. |
|
|
| `SuddenDeathSeconds` | Integer | No | `60` | Sudden-death duration. Must be positive when sudden death is enabled. |
|
|
|
|
## Win Condition
|
|
|
|
| Field | Type | Required | Default | Description |
|
|
|-------|------|----------|---------|-------------|
|
|
| `WinCondition` | Enum | No | `HIGHEST_SCORE` | How the winner is determined. Affects end-score display order and reward distribution. |
|
|
| `MapSelectionMode` | Enum | No | `VOTE` | How a waiting session chooses a discovered map: `VOTE` or `RANDOM`. |
|
|
| `FriendlyFireKillScoreMode` | Enum | No | `NO_POINTS` | How same-team player kills affect kill scoring: `OFF`, `LOSES_POINTS`, or `NO_POINTS`. |
|
|
|
|
Supported values:
|
|
|
|
| Value | Description |
|
|
|-------|-------------|
|
|
| `HIGHEST_SCORE` | Highest score at the end wins. Players ranked descending. |
|
|
| `LOWEST_SCORE` | Lowest score at the end wins. Players ranked ascending. |
|
|
| `FIRST_TO_SCORE` | First player or team to a target score wins. |
|
|
| `LAST_ALIVE` | Last active player or team wins. |
|
|
| `OBJECTIVE_COMPLETE` | Objective completion determines the winner. |
|
|
| `LOWEST_TIME` | Fastest completion time wins. Use `StartPlayerTimer` on the start pad and `StopPlayerTimer` on the finish line. Players who have not finished (score = 0) are ranked last. Times display as `M:SS.cc`. |
|
|
| `CUSTOM` | Trigger logic determines the winner. |
|
|
|
|
## World Rules
|
|
|
|
| Field | Type | Required | Default | Description |
|
|
|-------|------|----------|---------|-------------|
|
|
| `AllowPvp` | Boolean | No | `false` | Enforced: player-vs-player damage is cancelled for players in this game when `false` (applies when either the attacker or the victim is in a no-PvP game). |
|
|
| `AllowBlockBreaking` | Boolean | No | `false` | Enforced: block breaking by players in this game is cancelled when `false`. |
|
|
| `AllowBlockPlacing` | Boolean | No | `false` | Enforced: block placing by players in this game is cancelled when `false`. |
|
|
|
|
## Lifecycle
|
|
|
|
| Field | Type | Required | Default | Description |
|
|
|-------|------|----------|---------|-------------|
|
|
| `ResetOnEnd` | Boolean | No | `true` | After clearing runtime state at game end, dispatches `on_arena_reset` so trigger volumes can reset world state. |
|
|
| `SavePlayerInventory` | Boolean | No | `true` | Saves and then **clears** each player's inventory the first time they become `ACTIVE`. Items are only granted by volume effects (`SetPlayerLoadout`, `SpawnItem`) — nothing is given automatically. Restored on game end if `RestorePlayerInventory` is true, and when a player leaves or disconnects. |
|
|
| `RestorePlayerInventory` | Boolean | No | `true` | Restores each player's saved inventory when the game ends. |
|
|
|
|
## Items
|
|
|
|
| Field | Type | Required | Default | Description |
|
|
|-------|------|----------|---------|-------------|
|
|
| `StartItems` | `ItemStackConfig[]` | No | `[]` | Items given to each player when they become `ACTIVE`, if they have no assigned loadout. |
|
|
| `StartLoadouts` | `LoadoutConfig[]` | No | `[]` | Named item loadouts. A player's assigned loadout (set via `SetPlayerLoadout`) takes priority over `StartItems`. |
|
|
| `Rewards` | `RewardConfig[]` | No | `[]` | Rewards distributed at game end, before `on_game_end` fires. |
|
|
|
|
## HUD
|
|
|
|
| Field | Type | Required | Default | Description |
|
|
|-------|------|----------|---------|-------------|
|
|
| `ShowHud` | Boolean | No | `false` | Whether to show a HUD for each active player. Opt-in per game. |
|
|
| `ShowScore` | Boolean | No | `true` | Whether to show the player's current score on the HUD. |
|
|
| `ShowLives` | Boolean | No | `true` | Whether to show the player's remaining lives on the HUD. Only visible when `DefaultPlayerLives` is greater than `0`. |
|
|
| `ShowPosition` | Boolean | No | `false` | Whether to show the player's current race position (rank among active non-eliminated players). Useful for racing games using `LOWEST_SCORE`. |
|
|
| `ShowRound` | Boolean | No | `true` | Whether to show the current round out of total rounds (e.g. `2 / 3`). Only rendered when `TotalRounds` is greater than `1`. |
|
|
| `ShowTime` | Boolean | No | `true` | Whether to show the time remaining in the current round (e.g. `1:45`). Only rendered when `RoundLengthSeconds` is greater than `0`. Displays `0:00` once the round timer has expired. |
|
|
| `ShowScoreboard` | Boolean | No | `false` | Whether to show a ranked scoreboard panel on the HUD listing player names and scores in order. Capped at 10 rows or `MaxPlayers`, whichever is smaller. |
|
|
|
|
The HUD is shown when a player becomes `ACTIVE` and removed when the game ends. It refreshes approximately once per second. Position is ranked by current score respecting `WinCondition` (`LOWEST_SCORE` ranks lower scores ahead).
|
|
|
|
## Queue UI
|
|
|
|
| Field | Type | Required | Default | Description |
|
|
|-------|------|----------|---------|-------------|
|
|
| `UIQueueable` | Boolean | No | `false` | Whether this minigame appears in the global queue UI browser. Must be `true` for the game to show in `GLOBAL` mode. `SINGLE` and `LOCAL` modes work regardless of this flag — they are controlled by the `UIQueue=True` volume tag. |
|
|
|
|
When `UIQueueable=true`, the game will appear in the `OpenMinigameQueueUI` global browser alongside the queue count and a clickable join button, provided at least one `MainArena` volume has `UIQueue=True`.
|
|
|
|
## ItemStackConfig
|
|
|
|
```json
|
|
{
|
|
"ItemId": "event_fishing_rod",
|
|
"Amount": 1
|
|
}
|
|
```
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `ItemId` | String | Yes | Hytale item ID. |
|
|
| `Amount` | Integer | Yes | Stack amount. |
|
|
|
|
## LoadoutConfig
|
|
|
|
```json
|
|
{
|
|
"Id": "archer",
|
|
"DisplayName": "Archer",
|
|
"Items": [
|
|
{ "ItemId": "hunting_bow", "Amount": 1 },
|
|
{ "ItemId": "arrow", "Amount": 32 }
|
|
]
|
|
}
|
|
```
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `Id` | String | Yes | Loadout ID referenced by `SetPlayerLoadout`. |
|
|
| `DisplayName` | String | No | Player-facing name for UI display. |
|
|
| `Items` | `ItemStackConfig[]` | No | Items given when this loadout is applied. |
|
|
| `PlayerCustomizable` | Boolean | No | Reserved for a future loadout-selection UI. When `true`, item giving is skipped at activation. Defaults to `false`. |
|
|
|
|
Loadouts are selected by a `SetPlayerLoadout` effect before the player becomes `ACTIVE`. If no loadout is assigned, `StartItems` is used as a fallback.
|
|
|
|
## RewardConfig
|
|
|
|
```json
|
|
{
|
|
"Target": "winner",
|
|
"Items": [
|
|
{ "ItemId": "gold_coin", "Amount": 25 }
|
|
]
|
|
}
|
|
```
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `Target` | String | Yes | Who receives the reward. See target values below. |
|
|
| `Items` | `ItemStackConfig[]` | Yes | Items to grant. |
|
|
|
|
Reward target values:
|
|
|
|
| Value | Recipients |
|
|
|-------|------------|
|
|
| `all` | Every player in the runtime. |
|
|
| `winner` | The player ranked first (rank determined by `WinCondition`). |
|
|
| `top_N` | Top N players, e.g. `top_3`. |
|
|
|
|
## Minimal Example
|
|
|
|
```json
|
|
{
|
|
"Id": "Quick_Brawl",
|
|
"Name": "Quick Brawl",
|
|
"Enabled": true,
|
|
"MinPlayers": 2,
|
|
"MaxPlayers": 8,
|
|
"TeamMode": "SOLO",
|
|
"WinCondition": "LAST_ALIVE",
|
|
"RoundLengthSeconds": 120,
|
|
"AllowPvp": true
|
|
}
|
|
```
|
|
|
|
## Validation
|
|
|
|
Current validation is definition-focused:
|
|
|
|
- `Name` must not be blank.
|
|
- `MinPlayers` must be greater than or equal to 1.
|
|
- `MaxPlayers` must be greater than or equal to `MinPlayers`.
|
|
- `RoundLengthSeconds` must be greater than 0.
|
|
- `CountdownSeconds` must be greater than or equal to 0.
|
|
|
|
The old custom `MinigameAreaVolume` validation requirement no longer applies. Minigame areas are normal Hytale trigger volumes configured in the editor.
|