# Minigame Definition Reference Minigame definitions live in `src/main/resources/Server/Minigames/.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 | `""` | Optional world identifier. | | `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` | Whether players can join after the game starts. | | `AllowSpectators` | Boolean | No | `true` | Whether spectators are allowed. | ## Teams | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `TeamMode` | Enum | No | `SOLO` | `SOLO`, `TEAMS`, or `FREE_FOR_ALL`. | | `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, sets the phase to `OVERTIME` and dispatches `on_overtime_start` before `on_game_rounds_complete`. | | `SuddenDeathEnabled` | Boolean | No | `false` | When the final round ends (after overtime if also enabled), sets the phase to `SUDDEN_DEATH` and dispatches `on_sudden_death_start`. | ## 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. | | `CUSTOM` | Trigger logic determines the winner. | ## World Rules | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `AllowPvp` | Boolean | No | `false` | Whether players can damage each other. | | `AllowBlockBreaking` | Boolean | No | `false` | Whether blocks can be broken. Readable via definition; enforcement relies on `RequiredGameMode` (`Adventure` blocks both break and place by default). | | `AllowBlockPlacing` | Boolean | No | `false` | Whether blocks can be placed. Same enforcement note as above. | ## 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 each player's inventory the first time they become `ACTIVE`. Restored on game end if `RestorePlayerInventory` is true. | | `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. | ## 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.