feat: Enhance minigame effects and UI interactions

- Implemented LeaveMinigameQueueEffect to handle player removal from queues and runtime.
- Added OpenMinigameQueueUIEffect to manage the opening of the minigame queue UI.
- Introduced StartPlayerTimerEffect and StopPlayerTimerEffect for managing player timers and scoring.
- Enhanced PlaceBlocksEffect with options for filling volumes and hollow placements.
- Updated SpawnItemEffect to fix codec handling for item IDs.
- Added MountPlayerEffect and DismountPlayerEffect for player interactions with NPCs.
- Improved StartQueuedMinigameEffect to check player counts before starting games.
- Added localization entries for new effects and UI elements.
- Updated manifest to include HyUI as a dependency.
This commit is contained in:
2026-06-11 17:17:54 -07:00
parent 67e70a71bd
commit 49bbd2b871
58 changed files with 3664 additions and 37 deletions
@@ -0,0 +1,51 @@
# King of the Hill — Overview
In this tutorial you will build a **King of the Hill** minigame with three rounds. Each round has a dedicated capture point in a different part of the arena. Players earn one point per second while standing on the active hill. The player with the most points after all three rounds wins.
## What You Will Build
| Volume / File | Purpose |
|---|---|
| `King_Of_The_Hill.json` | Minigame definition — rounds, timing, HUD, PvP rules |
| Queue pad | Players step on it to join the waiting session |
| Start button | Game master trigger to launch the game and set phase to ACTIVE |
| Arena boundary | Map discovery tag — tells the runtime which map it is running on |
| Spawn zone | Where players enter to activate and start playing |
| Capture Zone A | Active during Round 1 — scores +1/second while standing inside |
| Capture Zone B | Active during Round 2 — scores +1/second while standing inside |
| Capture Zone C | Active during Round 3 — scores +1/second while standing inside |
| Round 2 / Round 3 signal volumes | Announce the new round when it starts |
| End-game timer volumes | Detect when Round 3 finishes and end the game |
## Game Flow
```
1. Players step on the queue pad.
2. Game master triggers the start button (or add auto-start logic).
3. Runtime starts → phase is set to ACTIVE.
4. Players enter the spawn zone → they become ACTIVE (HUD shown, items given).
5. Round 1 runs for 120 seconds. Capture Zone A scores.
6. Round 1 ends → Round 2 begins. Capture Zone B scores.
7. Round 2 ends → Round 3 begins. Capture Zone C scores.
8. Round 3 ends → game_end timer fires → EndMinigame.
9. Scores are tallied. Highest score wins. Arena resets.
```
## Prerequisites
- A Hytale server with core-minigames installed.
- A world with three distinct hilltop areas for your capture zones (A, B, C).
- A lobby or staging area where players queue before the game begins.
- Basic familiarity with placing trigger volumes and adding conditions/effects in the editor.
## Files in This Tutorial
| File | Contents |
|---|---|
| `02-minigame-definition.md` | JSON definition with all fields explained |
| `03-join-and-start.md` | Queue pad, start button, map boundary |
| `04-spawn-and-activation.md` | Spawn zone + player activation |
| `05-capture-zones.md` | The three scoring capture zones |
| `06-round-signals.md` | Round announcements and end-game timer |
| `07-end-and-reset.md` | Ending the game and resetting the arena |
| `08-full-example-files.md` | All complete configurations in one place |
@@ -0,0 +1,60 @@
# King of the Hill — Minigame Definition
Create the following file in your server's assets:
```
src/main/resources/Server/Minigames/King_Of_The_Hill.json
```
```json
{
"Id": "King_Of_The_Hill",
"Name": "King of the Hill",
"Enabled": true,
"MinPlayers": 2,
"MaxPlayers": 16,
"TeamMode": "SOLO",
"WinCondition": "HIGHEST_SCORE",
"RoundLengthSeconds": 120,
"TotalRounds": 3,
"CountdownSeconds": 10,
"AllowPvp": true,
"RequiredGameMode": "Adventure",
"ShowHud": true,
"ShowScore": true,
"ShowTime": true,
"ShowRound": true
}
```
## Field Breakdown
| Field | Value | Why |
|---|---|---|
| `Id` | `King_Of_The_Hill` | Must match the filename exactly and all `MinigameId` fields on every trigger volume in the world. |
| `MinPlayers` | `2` | Queue will not start a countdown until at least 2 players have joined. Set to `1` for solo testing. |
| `TeamMode` | `SOLO` | Each player competes individually with their own score. |
| `WinCondition` | `HIGHEST_SCORE` | The player with the most points when the game ends wins. |
| `RoundLengthSeconds` | `120` | Each hill is active for 2 minutes before the next round begins. |
| `TotalRounds` | `3` | Three rounds run in sequence. The runtime advances rounds automatically when each timer expires. |
| `CountdownSeconds` | `10` | After MinPlayers has joined the queue, a 10-second countdown begins before the game starts. |
| `AllowPvp` | `true` | Players can knock each other off the hill. Set to `false` for a passive score-race version. |
| `RequiredGameMode` | `Adventure` | Applied to each player when they activate. Prevents block breaking and placing. |
| `ShowHud` | `true` | Enables the in-game HUD. Without this, no HUD appears even if the other Show* fields are set. |
| `ShowScore` | `true` | Shows the player's current score on the HUD. |
| `ShowTime` | `true` | Shows time remaining in the current round on the HUD. Only renders when `RoundLengthSeconds > 0`. |
| `ShowRound` | `true` | Shows current round out of total rounds (e.g. `2 / 3`). Only renders when `TotalRounds > 1`. |
## How Rounds Work
You do not need to manually advance rounds. The runtime handles this automatically:
1. When the game starts, the `$round` timer begins counting down `RoundLengthSeconds` for round 1.
2. When the timer expires, round 2 starts and the timer resets.
3. When round 3's timer expires, `on_game_rounds_complete` is dispatched.
Your trigger volumes use the `CurrentRound` condition to check which round is active, so each capture zone automatically becomes active or inactive as rounds change.
## Testing With One Player
Change `MinPlayers` to `1` while setting up and testing your world. Change it back before going live.
@@ -0,0 +1,86 @@
# King of the Hill — Join Pad & Auto-Start
This step sets up the volumes that let players join the queue and auto-start the game once enough players are ready.
---
## 1. Arena Boundary Volume
This volume is not interactive — it exists purely so the runtime knows which map it is running on. Place it as a large box that encompasses the entire arena.
**Volume type:** Any (Enter trigger is fine, no effects needed)
**Tags:**
| Tag | Value |
|---|---|
| `MinigameId` | `King_Of_The_Hill` |
| `MapId` | `Hillside` *(replace with your map name)* |
| `MapRole` | `MainArena` |
No conditions. No effects.
> The `MapId` value is arbitrary — pick a name that describes your arena (e.g. `Hillside`, `Volcano`, `Castle`). Use the same value on every other volume in this world that belongs to this map.
---
## 2. Queue Pad
Place this volume at a lobby pad where players gather before the game. When stepped on, it adds the player to the queue and attempts to start the game. The start attempt is a no-op until `MinPlayers` (2) have joined, at which point the runtime is created automatically.
**Volume type:** Enter trigger
**Tags:**
| Tag | Value |
|---|---|
| `MinigameId` | `King_Of_The_Hill` |
**Effects:**
| Effect | Fields |
|---|---|
| `JoinMinigameQueue` | `MinigameId = King_Of_The_Hill` |
| `StartQueuedMinigame` | `MinigameId = King_Of_The_Hill` |
> **How the auto-start works:** `StartQueuedMinigame` checks that no runtime is already running and that the queue has at least `MinPlayers` players before doing anything. With `MinPlayers = 2`: Player 1 steps on the pad — `StartQueuedMinigame` sees only 1 queued player and skips. Player 2 steps on the pad — queue now has 2 players, `StartQueuedMinigame` creates the runtime (phase = `WAITING_FOR_PLAYERS`). The signal volume below immediately advances it to `ACTIVE`.
Players who step on this pad after the game has already started are queued for the next game — `StartQueuedMinigame` detects the active runtime and skips.
---
## 3. STARTING Phase Volume
The system runs the `CountdownSeconds` countdown automatically during `WAITING_FOR_PLAYERS`. Once the countdown finishes, the runtime advances to `STARTING` and fires `SignalPhaseStart=STARTING`. Your volume responds by setting the phase to `ACTIVE` to begin the game.
**Volume type:** Any (Tag Added trigger — fired by the runtime, not physically entered)
**Tags:**
| Tag | Value |
|---|---|
| `MinigameId` | `King_Of_The_Hill` |
| `MapId` | `Hillside` |
| `SignalPhaseStart` | `STARTING` |
**Effects:**
| Effect | Fields |
|---|---|
| `SetMinigamePhase` | `MinigameId = King_Of_The_Hill`, `Phase = ACTIVE` |
| `SetRound` | `Operation = Set`, `Amount = 1` |
(anything else you want to happen? Effects, sounds, Starting cinematic? Do before setting to active and starting the round)
> **Countdown**: with `CountdownSeconds = 10` in the definition, a "Starting in N..." message is sent to all players each second. If a player steps off the queue pad (`LeaveMinigameQueue`) or disconnects during the countdown and the player count drops below `MinPlayers`, the countdown cancels and players are returned to the queue automatically.
>
> **Skip the countdown**: set `CountdownSeconds = 0` in the definition to go from `STARTING` to `ACTIVE` immediately.
---
## Leave Queue (Optional)
If players want to leave before the game starts, add a separate pad with:
| Effect | Fields |
|---|---|
| `LeaveMinigameQueue` | `MinigameId = King_Of_The_Hill` |
@@ -0,0 +1,67 @@
# King of the Hill — Spawn Zone & Player Activation
Players are not automatically active when the game starts. They must enter the spawn zone, which triggers the activation lifecycle: inventory save, item giving, game mode change, and HUD display.
---
## What Activation Does
When `SetPlayerStatus ACTIVE` fires for a player, the runtime:
1. Saves their current inventory (if `SavePlayerInventory = true`, the default).
2. Gives them their start items or assigned loadout (if any defined in the definition).
3. Applies `RequiredGameMode` (`Adventure` in this tutorial).
4. Shows the HUD (since `ShowHud = true`).
This only happens once per player per game. If the same player re-enters the spawn zone it is harmless — the runtime ignores duplicate ACTIVE requests.
---
## Spawn Zone Volume
Place this volume at the area where players begin the round — typically a platform or small room at the edge of the arena that all players pass through when the game starts.
**Volume type:** Enter trigger
**Tags:**
| Tag | Value |
|---|---|
| `MinigameId` | `King_Of_The_Hill` |
| `MapId` | `Hillside` |
**Conditions:**
| Condition | Fields | Purpose |
|---|---|---|
| `PlayerInMinigame` | `MinigameId = King_Of_The_Hill` | Only fires for players who are actually in the runtime (not random passersby). |
| `MinigamePhase` | `MinigameId = King_Of_The_Hill`, `Phase = ACTIVE` | Prevents accidental activation while players are still in the lobby countdown. |
**Effects:**
| Effect | Fields |
|---|---|
| `SetPlayerStatus` | `MinigameId = King_Of_The_Hill`, `Status = ACTIVE` |
| `SetSpawnPoint` | `MinigameId = King_Of_The_Hill`, `DestinationId = 100,64,200` *(replace with your spawn coordinates)* |
> The `SetSpawnPoint` stores a respawn destination for each player. When a player dies during the game, the runtime automatically respawns them at their stored checkpoint. Replace `100,64,200` with the actual world coordinates of your spawn area center. You can also use the format `world_name,X,Y,Z` if the spawn is in a different world.
---
## How Players Get to the Spawn Zone
In a typical KOTH setup, players are somewhere in the arena or lobby when the game starts. You have two options:
**Option A — Players walk there.** The spawn zone is accessible from the lobby area. When the game starts and phase becomes `ACTIVE`, players walk through the spawn zone on their way into the arena. This is the simplest approach and works well when the lobby and arena are adjacent.
**Option B — Teleport on game start.** Add a `SignalPhaseStart=ACTIVE` signal volume (covered in `06-round-signals.md`) with a `RespawnPlayer` effect. This teleports all active players to their spawn on phase change.
For this tutorial, Option A is assumed. If using Option B, `RespawnPlayer` resolves the destination using the player's stored checkpoint from `SetSpawnPoint`, so the activation volume still needs to fire first. Consider placing the spawn zone between the lobby exit and the arena entrance so it is always traversed.
---
## Respawn on Death
Because `SetSpawnPoint` is called at activation, player deaths during the game automatically respawn at those coordinates. No additional setup is required for basic respawning.
If you want players to respawn with a delay or only when a specific condition is met, add a `RespawnPlayer` effect to a separate signal or death-event volume.
@@ -0,0 +1,147 @@
# King of the Hill : Capture Zones
Each round has one active capture zone. Players standing inside the correct zone for the current round earn +1 point per second. Zones outside the active round do nothing.
You will create three separate trigger volumes : one per hilltop.
---
## How Scoring Works
Each capture zone uses:
- A **TICK** volume type so it fires continuously while players are standing inside it.
- A `CurrentRound` condition that passes only when the correct round number is active.
- A `ModifyPlayerScore` effect that adds 1 point per trigger fire.
The tick rate on the volume controls how often points are awarded. Set it to **1 second** in the editor so players earn 1 point per second. If the tick fires every 0.5 seconds, players would earn 2 points per second : adjust the amount or tick rate to your preference.
leaving it at zero would be everytick its fired, Giving 30 points
---
## Capture Zone A : Round 1
Place this volume on Hilltop A, the first round's scoring area. Size it so that players must be clearly on top of the hill.
**Volume type:** TICK trigger (tick interval: 1 second)
**Tags:**
| Tag | Value |
|---|---|
| `MinigameId` | `King_Of_The_Hill` |
| `MapId` | `Hillside` |
**Conditions:**
| Condition | Fields | Purpose |
|---|---|---|
| `PlayerInMinigame` | `MinigameId = King_Of_The_Hill` | Only scores players in the runtime. |
| `CurrentRound` | `MinigameId = King_Of_The_Hill`, `Compare = EQUAL`, `Round = 1` | Only active during Round 1. |
**Effects:**
| Effect | Fields |
|---|---|
| `ModifyPlayerScore` | `MinigameId = King_Of_The_Hill`, `Operation = ADD`, `Amount = 1` |
---
## Capture Zone B : Round 2
Place this volume on Hilltop B. Same setup as Zone A with only the round number changed.
**Volume type:** TICK trigger (tick interval: 1 second)
**Tags:** Same as Zone A (`MinigameId`, `MapId`)
**Conditions:**
| Condition | Fields |
|---|---|
| `PlayerInMinigame` | `MinigameId = King_Of_The_Hill` |
| `CurrentRound` | `MinigameId = King_Of_The_Hill`, `Compare = EQUAL`, `Round = 2` |
**Effects:**
| Effect | Fields |
|---|---|
| `ModifyPlayerScore` | `MinigameId = King_Of_The_Hill`, `Operation = ADD`, `Amount = 1` |
---
## Capture Zone C : Round 3
Place this volume on Hilltop C.
**Volume type:** TICK trigger (tick interval: 1 second)
**Tags:** Same as above
**Conditions:**
| Condition | Fields |
|---|---|
| `PlayerInMinigame` | `MinigameId = King_Of_The_Hill` |
| `CurrentRound` | `MinigameId = King_Of_The_Hill`, `Compare = EQUAL`, `Round = 3` |
**Effects:**
| Effect | Fields |
|---|---|
| `ModifyPlayerScore` | `MinigameId = King_Of_The_Hill`, `Operation = ADD`, `Amount = 1` |
---
## Notes
**You may want to add further effects the zones** :
On Capture Zone 1 using `SignalRoundStart=1` volume tag (covered in `06-round-signals.md` and `tags.md`)
you can add the following to play a sound at the start of the round and have a VFX with a duration of the round set
On Tag Added trigger
| Effect | Fields |
|---|---|
| `PlaySound` | `Your choice of sound`|
| `Play VFX` | `Your choice of VFX` `Duration = round time`|
**Multiple players on the hill at once** : each player in the volume gets the `ModifyPlayerScore` effect independently. If two players stand on Hilltop A during Round 1, both earn +1/second. This is intentional for KOTH : fighting over the hill is part of the game.
**Zone size** : make your capture zones intentionally tight so there is real competition for the spot. A zone that is too large removes the "king of the hill" tension.
**Dymanic Zone Size**
Lets say you have rounds last 60 secounds. You want the Capture Zone for round 2 to get smaller half way.
Create two Capture Zones one the full size and one the half size
Add on the large Capture Zone 2 using `SignalRoundStart=2` volume tag (covered in `06-round-signals.md` and `tags.md`)
And another tag to each to later identify them
`Round2Capture=Large`
`Round2Capture=Small`
The larger Capture Zone
On Tag Added trigger
| Effect | Fields |
|---|---|
| `DisableVolume` | `MatchTagKey=Round2Capture` `MatchTagValue=Small`|
| `PlaySound` | `Your choice of sound`|
| `Play VFX` | `Your choice of VFX` `Duration = 30`|
| `EnableVolume` | `EffectDelay=30` `MatchTagKey=Round2Capture` `MatchTagValue=Small`|
| `ModifyTag` | `Operation=Set` `TagKey=SmallRound2Capture` `TagValue=Enabled` `MatchTagKey=Round2Capture` `MatchTagValue=Small`|
| `DisableVolume` | `MatchTagKey=Round2Capture` `MatchTagValue=Large`|
The Smaller Capture Zone
On Tag Added trigger
| Effect | Fields |
|---|---|
| `PlaySound` | `Your choice of sound`|
| `Play VFX` | `Your choice of VFX` `Duration = 30`|
| `EnableVolume` | `EffectDelay=30` `MatchTagKey=Round2Capture` `MatchTagValue=Large`|
| `ModifyTag` | `Operation=Remove` `TagKey=SmallRound2Capture` `TagValue=Enabled` `MatchTagKey=Round2Capture` `MatchTagValue=Small`|
| `DisableVolume` | `MatchTagKey=Round2Capture` `MatchTagValue=Large`|
There are a couple of ways to do this, but this is just one I felt like typing.
**Score display** : the HUD shows the current score in real time. Players can see how their score compares while standing on the hill. Round and time remaining are also shown because `ShowRound = true` and `ShowTime = true` are set in the definition.
@@ -0,0 +1,112 @@
# King of the Hill — Round Signals & Game End
This step wires up announcements for each new round and explains how the game ends automatically when the final round completes.
---
## How Signal Volumes Work
Signal volumes have special tags (`SignalRoundStart`, `SignalPhaseTick`, `SignalPhaseStart`, etc.) that the runtime writes to at the right moment. When the tag value changes, Hytale fires the volume's `TAG_ADDED` trigger, which runs the attached effects.
Every signal volume must also have `MinigameId` set so the runtime knows which game's signals to respond to.
---
## Round 2 Announcement
When Round 2 begins, fire a message to all players announcing the new hill location.
**Volume type:** Any (Tag Added trigger is conventional for signal volumes — the volume is never physically entered, it is fired by the runtime)
**Tags:**
| Tag | Value |
|---|---|
| `MinigameId` | `King_Of_The_Hill` |
| `MapId` | `Hillside` |
| `SignalRoundStart` | `2` |
**Effects:**
| Effect | Fields |
|---|---|
| `SendMinigameMessage` | `MinigameId = King_Of_The_Hill`, `MessageKey = round_2_start`, `Target = ALL` |
> `MessageKey` references a translation key in your server's language files. If you do not have a dedicated translations setup, you can skip `SendMinigameMessage` for now — the HUD already shows the updated round number automatically.
---
## Round 3 Announcement
Same structure, fires when Round 3 begins.
**Tags:**
| Tag | Value |
|---|---|
| `MinigameId` | `King_Of_The_Hill` |
| `MapId` | `Hillside` |
| `SignalRoundStart` | `3` |
**Effects:**
| Effect | Fields |
|---|---|
| `SendMinigameMessage` | `MinigameId = King_Of_The_Hill`, `MessageKey = round_3_start`, `Target = ALL` |
---
## How the Game Ends Automatically
When the Round 3 timer expires, the runtime calls `end()` automatically (because `TotalRounds = 3` and neither `OvertimeEnabled` nor `SuddenDeathEnabled` are set). No extra timer volume is needed.
The end sequence fires in this order:
1. `SignalPhaseStart=ENDING` fires — use this for a scoreboard display, player freeze, or end announcement.
2. HUDs are removed, inventories restored, rewards distributed.
3. `on_game_end` event fires (with `reason = "rounds_complete"`).
4. Runtime is removed from the active list.
5. `SignalPhaseStart=RESETTING` fires — use this to restore blocks, re-enable the queue pad, etc.
6. `on_arena_reset` event fires.
You do not need a `StartTimer`/`SignalOnTimerExpire` pair to end the game.
---
## ENDING Phase Volume (Optional)
To show a final message or freeze players briefly at game end, respond to `SignalPhaseStart=ENDING`:
**Tags:**
| Tag | Value |
|---|---|
| `MinigameId` | `King_Of_The_Hill` |
| `MapId` | `Hillside` |
| `SignalPhaseStart` | `ENDING` |
**Example effects:**
| Effect | Fields |
|---|---|
| `SendMinigameMessage` | `MinigameId = King_Of_The_Hill`, `MessageKey = game_over`, `Target = ALL` |
---
## Round 1 Announcement (Optional)
Round 1 begins immediately when the game goes ACTIVE (there is no `SignalRoundStart=1` in the current round implementation for the initial round). If you want a Round 1 announcement, fire it from the `SignalPhaseStart=ACTIVE` volume set up in step 03:
**Tags:**
| Tag | Value |
|---|---|
| `MinigameId` | `King_Of_The_Hill` |
| `MapId` | `Hillside` |
| `SignalPhaseStart` | `ACTIVE` |
**Effects:**
| Effect | Fields |
|---|---|
| `SendMinigameMessage` | `MinigameId = King_Of_The_Hill`, `MessageKey = round_1_start`, `Target = ALL` |
@@ -0,0 +1,87 @@
# King of the Hill — Ending & Resetting
This step covers what happens when the game ends, what signals fire and when, and how to use arena reset to prepare for the next game.
---
## What Happens When the Game Ends
When the final round timer expires (and no overtime/sudden death is configured), the runtime calls `end("rounds_complete")` automatically. The full sequence:
1. **HUDs removed** for all players in the runtime.
2. **Phase set to `ENDING`**`SignalPhaseStart=ENDING` fires.
3. **Active signal timers cancelled.**
4. **Temporary entities cleaned up** (spawned NPCs/items tracked by the runtime).
5. **Player inventories restored** (since `RestorePlayerInventory = true` is the default).
6. **Rewards distributed** (if any `Rewards` are defined in the definition).
7. **`on_game_end` event dispatched** with `reason = "rounds_complete"` and final scores.
8. **Runtime state cleared** — scores, player status, timers, counters all zeroed.
9. **Runtime removed** from the active list.
10. **Phase set to `RESETTING`**`SignalPhaseStart=RESETTING` fires.
11. **`on_arena_reset` event dispatched** (since `ResetOnEnd = true` is the default).
You do not need to manually reset scores or clear HUDs.
---
## ENDING Phase Volume (Optional)
Use `SignalPhaseStart=ENDING` to show a scoreboard, announce the winner, or freeze players briefly before cleanup. This fires while the runtime still holds final scores.
**Tags:**
| Tag | Value |
|---|---|
| `MinigameId` | `King_Of_The_Hill` |
| `MapId` | `Hillside` |
| `SignalPhaseStart` | `ENDING` |
**Example effects:**
| Effect | Fields |
|---|---|
| `SendMinigameMessage` | `MinigameId = King_Of_The_Hill`, `MessageKey = game_over`, `Target = ALL` |
---
## Arena Reset Volume
Use `SignalPhaseStart=RESETTING` to restore any world state changed during the game. This fires after the runtime has been cleaned up, so it is safe to re-enable the queue pad without risk of double-triggering.
> **Scope note:** `SignalPhaseStart=RESETTING` is scoped by `MinigameId` tag match, NOT by physical containment within the `MapRole=MainArena` boundary. Any volume anywhere in the world with a matching `MinigameId` tag will respond. The arena boundary volume is only used for map *discovery*, not for event routing.
For this King of the Hill setup there are no block placements or NPC spawns, so the arena reset volume is optional. Add it if you want to re-enable the queue pad, reset visual markers, or restore barriers changed mid-game.
**Tags:**
| Tag | Value |
|---|---|
| `MinigameId` | `King_Of_The_Hill` |
| `MapId` | `Hillside` |
| `SignalPhaseStart` | `RESETTING` |
**Example effects:**
| Effect | Fields | Purpose |
|---|---|---|
| `PlaceBlocks` | *(coordinates of any changed areas, original block id)* | Restore modified terrain. |
---
## Repeating the Game
After the runtime ends and `SignalPhaseStart=RESETTING` fires, the minigame is ready to start again. Players can step back onto the queue pad and a new runtime will be created when `StartQueuedMinigame` fires again.
No state from the previous game persists — scores, player status, timers, and counters are all cleared by the end flow.
---
## Manual Reset
If you need to reset the game mid-match (for testing or crash recovery), use the admin command:
```
/minigame reset King_Of_The_Hill
```
This calls `ResetMinigame` directly, which sets phase to `RESETTING`, fires `SignalPhaseStart=RESETTING`, clears runtime state, and dispatches `on_arena_reset` — without going through the normal end flow (no rewards, no inventory restore, no `ENDING` phase).
@@ -0,0 +1,135 @@
# King of the Hill — Complete Reference
All volumes and the definition file in one place. Use this as a checklist when setting up your world.
---
## Definition File
**Path:** `src/main/resources/Server/Minigames/King_Of_The_Hill.json`
```json
{
"Id": "King_Of_The_Hill",
"Name": "King of the Hill",
"Enabled": true,
"MinPlayers": 2,
"MaxPlayers": 16,
"TeamMode": "SOLO",
"WinCondition": "HIGHEST_SCORE",
"RoundLengthSeconds": 120,
"TotalRounds": 3,
"CountdownSeconds": 10,
"AllowPvp": true,
"RequiredGameMode": "Adventure",
"ShowHud": true,
"ShowScore": true,
"ShowTime": true,
"ShowRound": true
}
```
---
## Volume Checklist
| # | Volume Name | Type | Tags | Conditions | Effects |
|---|---|---|---|---|---|
| 1 | Arena Boundary | Enter | `MinigameId=King_Of_The_Hill` `MapId=Hillside` `MapRole=MainArena` | — | — |
| 2 | Queue Pad | Enter | `MinigameId=King_Of_The_Hill` | — | `JoinMinigameQueue``StartQueuedMinigame` |
| 3 | Starting Signal | Tag Added | `MinigameId=King_Of_The_Hill` `MapId=Hillside` `SignalPhaseStart=STARTING` | — | `SetMinigamePhase ACTIVE` |
| 4 | Spawn Zone | Enter | `MinigameId=King_Of_The_Hill` `MapId=Hillside` | `PlayerInMinigame` + `MinigamePhase=ACTIVE` | `SetPlayerStatus ACTIVE``SetSpawnPoint` |
| 5 | Capture Zone A | TICK (1s) | `MinigameId=King_Of_The_Hill` `MapId=Hillside` | `PlayerInMinigame` + `CurrentRound=EQUAL 1` | `ModifyPlayerScore ADD 1` |
| 6 | Capture Zone B | TICK (1s) | `MinigameId=King_Of_The_Hill` `MapId=Hillside` | `PlayerInMinigame` + `CurrentRound=EQUAL 2` | `ModifyPlayerScore ADD 1` |
| 7 | Capture Zone C | TICK (1s) | `MinigameId=King_Of_The_Hill` `MapId=Hillside` | `PlayerInMinigame` + `CurrentRound=EQUAL 3` | `ModifyPlayerScore ADD 1` |
| 8 | Round 2 Signal | Tag Added | `MinigameId=King_Of_The_Hill` `MapId=Hillside` `SignalRoundStart=2` | — | `SendMinigameMessage round_2_start ALL` |
| 9 | Round 3 Signal | Tag Added | `MinigameId=King_Of_The_Hill` `MapId=Hillside` `SignalRoundStart=3` | — | `SendMinigameMessage round_3_start ALL` |
| 10 | End Announcement | Tag Added | `MinigameId=King_Of_The_Hill` `MapId=Hillside` `SignalPhaseStart=ENDING` | — | `SendMinigameMessage game_over ALL` *(optional)* |
| 11 | Arena Reset | Tag Added | `MinigameId=King_Of_The_Hill` `MapId=Hillside` `SignalPhaseStart=RESETTING` | — | *(block restore effects)* *(optional)* |
The game ends automatically when Round 3's timer expires — no end-game timer volume is needed.
---
## Volume Detail — Queue Pad (Auto-Start)
```
Tags:
MinigameId = King_Of_The_Hill
Effects:
JoinMinigameQueue MinigameId=King_Of_The_Hill
StartQueuedMinigame MinigameId=King_Of_The_Hill
```
`StartQueuedMinigame` is a no-op until `MinPlayers` (2) are in the queue AND no runtime is already running.
---
## Volume Detail — Starting Signal
```
Tags:
MinigameId = King_Of_The_Hill
MapId = Hillside
SignalPhaseStart = STARTING
Effects:
SetMinigamePhase MinigameId=King_Of_The_Hill Phase=ACTIVE
```
Fires after the countdown completes. The system runs the `CountdownSeconds` countdown
automatically during `WAITING_FOR_PLAYERS` — no timer volume required.
---
## Volume Detail — Spawn Zone
```
Tags:
MinigameId = King_Of_The_Hill
MapId = Hillside
Conditions:
PlayerInMinigame MinigameId=King_Of_The_Hill
MinigamePhase MinigameId=King_Of_The_Hill Phase=ACTIVE
Effects:
SetPlayerStatus MinigameId=King_Of_The_Hill Status=ACTIVE
SetSpawnPoint MinigameId=King_Of_The_Hill DestinationId=<X,Y,Z>
```
Replace `<X,Y,Z>` with the world coordinates of your spawn area.
---
## Volume Detail — Capture Zone A (copy pattern for B and C)
```
Tags:
MinigameId = King_Of_The_Hill
MapId = Hillside
Conditions:
PlayerInMinigame MinigameId=King_Of_The_Hill
CurrentRound MinigameId=King_Of_The_Hill Compare=EQUAL Round=1
Effects:
ModifyPlayerScore MinigameId=King_Of_The_Hill Operation=ADD Amount=1
```
Change `Round=1` to `Round=2` and `Round=3` for Zones B and C.
---
## Common Mistakes
| Symptom | Likely Cause |
|---|---|
| HUD never appears | `SetPlayerStatus ACTIVE` is not firing — check that the spawn zone has both `PlayerInMinigame` and `MinigamePhase=ACTIVE` conditions. |
| Score never changes | Capture zone tick interval is not set, or the `CurrentRound` condition does not match the active round. Verify the `Round` value matches the round number (1, 2, or 3). |
| Game never starts | Queue pad must have both `JoinMinigameQueue` AND `StartQueuedMinigame`. The starting signal volume must have `SignalPhaseStart=STARTING` with `SetMinigamePhase ACTIVE` effect. |
| Game never ends | Rounds do not auto-end if `OvertimeEnabled` or `SuddenDeathEnabled` are set in the definition. Verify neither is enabled. |
| Volume conditions blocked | Wrong `MinigameId` value — ensure every volume and every condition/effect field uses exactly `King_Of_The_Hill` (case-sensitive, underscores not spaces). |
| Players not activating | Phase was never set to `ACTIVE` — verify the auto-start signal volume (`SignalPhaseStart=WAITING_FOR_PLAYERS`) is present and fires `SetMinigamePhase ACTIVE`. |
| Game starts with 1 player | `MinPlayers` in the definition is set to `1`. Change to `2` if you need two players. |
@@ -0,0 +1,50 @@
These are just examples of how tutorial files might be depending on their game and format.
solo-brawl/
01-overview.md
02-create-minigame-definition.md
03-create-start-pad.md
04-create-arena-and-spawns.md
05-activate-players.md
06-enable-pvp-and-damage.md
07-add-scoring.md
08-add-timer-and-win-condition.md
09-end-reset-and-cleanup.md
10-full-example-files.md
team-objective-game/
01-overview.md
02-create-minigame-definition.md
03-create-queue-and-start-flow.md
04-create-map-tags-and-arena.md
05-create-team-spawns.md
06-assign-and-balance-teams.md
07-activate-players.md
08-create-objectives.md
09-add-team-scoring.md
10-add-win-condition.md
11-end-reset-and-cleanup.md
12-full-example-files.md
parkour-checkpoints/
01-overview.md
02-create-minigame-definition.md
03-create-start-and-finish-volumes.md
04-create-checkpoints.md
05-track-player-progress.md
06-add-timer.md
07-handle-falls-and-respawns.md
08-finish-reset-and-cleanup.md
09-full-example-files.md
hot-potato/
01-overview.md
02-create-minigame-definition.md
03-create-queue-and-start-flow.md
04-create-arena-and-spawns.md
05-activate-players.md
06-spawn-the-potato-item.md
07-pass-the-potato.md
08-countdown-and-explosion.md
09-eliminate-or-score-players.md
10-end-reset-and-cleanup.md
11-full-example-files.md