Files
GameModes-SpeedHG/README.md
2026-04-14 05:07:56 +02:00

323 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SpeedHG
> **A Spigot / Paper plugin for the *SpeedHG* Hunger-Games variant by McScrims Network.**
> Built with Kotlin · Paper API 1.21 · Version `1.0.0`
---
## Table of Contents
- [Overview](#overview)
- [Dependencies](#dependencies)
- [Game Flow](#game-flow)
- [Configuration](#configuration)
- [Kits](#kits)
- [Perks](#perks)
- [Commands](#commands)
- [Permissions](#permissions)
- [Architecture](#architecture)
- [Adding a New Kit](#adding-a-new-kit)
- [Adding a New Perk](#adding-a-new-perk)
- [Runtime Configuration via `SPEEDHG_CUSTOM_SETTINGS`](#runtime-configuration-via-speedhg_custom_settings)
---
## Overview
SpeedHG is a competitive Hunger-Games game-mode where every player selects a **Kit** (with an Aggressive or Defensive playstyle) and up to **2 passive Perks** before the round starts. The world border steadily shrinks, disasters trigger, and a feast spawns mid-game to force confrontation.
Key features at a glance:
- 17 fully-implemented Kits, each with 2 Playstyles (Aggressive / Defensive)
- 14 passive Perks with persistent DB-backed selection
- Hit-charge system for active abilities (configurable hits-to-charge per kit)
- Dynamic WorldBorder shrink, Feast, and Pit events
- Anti-runner detection, soup-based healing, team support
- Lunar Client integration (waypoints, scoreboard)
- Discord webhook for game results
- MySQL-backed stats, ranking, and leaderboard
- Fully i18n-able via `en_US.yml` (MiniMessage format)
---
## Dependencies
| Dependency | Role |
|-----------------|-------------------------------------|
| `WorldEdit` | Arena construction for GladiatorKit |
| `Apollo-Bukkit` | Lunar Client integration |
| `Kup` | Internal rank/permission bridge |
All three must be present on the server; the plugin will not load without them.
---
## Game Flow
```
LOBBY → STARTING → INVINCIBILITY → INGAME → ENDING
```
| Phase | Description |
|-----------------|------------------------------------------------------------------------------------------|
| `LOBBY` | Waiting for `min-players`. Every 15 s an idle message is broadcast. |
| `STARTING` | Countdown (`lobby-time` seconds). Aborts if player count drops. |
| `INVINCIBILITY` | Players are teleported, kits & perks applied, Speed I + Haste I active. No damage dealt. |
| `INGAME` | Combat enabled, WorldBorder shrinks, timer counts up, Feast & Pit events fire. |
| `ENDING` | Winner announced, server shuts down after a short delay. |
Default timing values (overridable in `config.yml`):
| Setting | Default |
|--------------------|------------|
| Min players | 8 |
| Lobby time | 120 s |
| Invincibility time | 120 s |
| Border start | 600 blocks |
| Border end | 150 blocks |
| Border shrink time | 900 s |
---
## Configuration
### `config.yml`
```yaml
game:
beta: true
min-players: 2
lobby-time: 60
invincibility-time: 120
border-start: 600.0
border-end: 100.0
border-shrink-time: 900 # seconds
max-radius-teleport: 50.0
ranked: false
teams:
enabled: false
preset-count: 10
max-size: 2
anti-runner:
enabled: false
discord:
enabled: false
webhook-url: "YOUR_WEBHOOK_URL"
database:
host: "localhost"
port: 3306
name: "speedhg"
username: "speedhg_user"
password: "your_password"
use-ssl: false
pool:
max-size: 10
min-idle: 2
```
### `SPEEDHG_CUSTOM_SETTINGS` Environment Variable
For production overrides without touching `config.yml`, pass a JSON blob via environment variable (see [Runtime Configuration](#runtime-configuration-via-speedhg_custom_settings)).
---
## Kits
Players select a kit in the lobby and choose a **Playstyle** (Aggressive `[AGG]` / Defensive `[DEF]`).
Active abilities are triggered by right-clicking the kit item. Most abilities require a configurable number of hits to charge first (`global_hits_required`, default: 15).
| Kit | Aggressive Active | Defensive Active | Passive (AGG) | Passive (DEF) |
|------------------|----------------------------------------------------------------|---------------------------------------------------------|----------------------------------------------|-------------------------------------------------|
| **Anchor** | Summon Iron Golem anchor — no-knock + bonus damage in radius | ← same | Partial knockback resistance | Partial knockback resistance |
| **Armorer** | — | — | Strength I on kill | Protection I on armor |
| **Backup** | — | — | — | — |
| **BlackPanther** | Wakanda Leap — leap forward, hit enemies on land | ← same | — | — |
| **Blitzcrank** | Rocket Grab — pull nearest enemy to you | ← same | — | — |
| **Gladiator** | Sky arena 1v1 duel (glass cage, Wither IV after 180 s) | ← same | — | — |
| **Goblin** | Steal enemy kit for 60 s | Spawn a bunker for cover | — | — |
| **IceMage** | Ice Spike Burst — cone of freezing projectiles | Freeze Burst — 16 snowballs in circle | Speed in cold biomes, slowness chance on hit | 33 % slowness proc on being hit |
| **Ninja** | Vanish + backstab: teleport behind last-hit enemy | Shadow Step: teleport to nearest enemy | Last-hit tracking | — |
| **Puppet** | Puppet Trap — summon entity traps | ← similar | — | — |
| **Rattlesnake** | Pounce — sneak-charge then leap, applies Poison II | — | Poison II on pounce hit | 25 % reflect Poison II on being hit |
| **Spielo** | — | — | — | — |
| **Tesla** | Lightning strike AoE | ← same | — | Knock-back + ignite reflect on being hit |
| **TheWorld** | Shockwave + 3× Blink forward | Shockwave + Freeze nearby enemies (10 s, 5-hit cap) | — | Frozen enemies have a 5-hit break cap |
| **Trident** | Dive — launch up, lightning on landing (charge-based) | — | — | Parry — chance to bounce + Slowness on attacker |
| **Venom** | Venom Blast — Blindness I + Wither I + 2 hearts instant damage | Barrier — absorbs up to 15 damage, reflects projectiles | — | — |
| **Voodoo** | Curse — apply Glowing + delayed damage to nearby enemies | ← similar | 20 % Wither proc on hit | Speed + Regen while cursed enemies are nearby |
### Kit Item
Each kit provides its signature item in the player's inventory at game start. Items are tracked in `cachedItems` (UUID → `List<ItemStack>`) and cleaned up on `onRemove`.
---
## Perks
Players may equip **up to 2 Perks** before the round starts. Selections are persisted to the database per-player UUID.
| Perk | Effect |
|-------------------|-------------------------------------------------------------------------------------|
| **Adrenaline** | Dropping below 3 hearts → Speed II for 5 s (30 s cooldown) |
| **Berserker** | Below 4 hearts → deal 15 % more melee damage |
| **Bloodlust** | On kill: Speed I + Regen I for 5 s |
| **Enderblood** | Ender Pearl landings deal no fall damage |
| **Evasion** | 15 % chance to dodge incoming projectiles |
| **Featherweight** | Full immunity to fall damage |
| **Ghost** | Invisible to compass tracking and the Oracle perk |
| **Gourmet** | Consuming soup → Regen I + Speed I for 2 s |
| **Last Stand** | Taking damage below 3 hearts → Resistance II + Absorption I for 4 s (60 s cooldown) |
| **Momentum** | Sprint for 4 s without combat → Speed I |
| **Oracle** | Shows kit + distance to the nearest enemy on sneak / compass |
| **Pyromaniac** | Immune to fire, lava, magma blocks, and burn ticks |
| **Scavenger** | Every kill drops an extra Golden Apple at the corpse |
| **Vampire** | 10 % chance on melee hit to heal ½ heart |
---
## Commands
| Command | Alias | Permission | Description |
|--------------------------------------------|------------------|-------------------------|-----------------------------------|
| `/kit <name> <playstyle>` | — | — | Select a kit via command |
| `/kitinfo <id>` | `/perkinfo <id>` | — | Show name + lore of a kit or perk |
| `/perks` | — | — | Open the Perk Selector GUI |
| `/leaderboard` | — | — | View the top 10 players |
| `/timer <time>` | — | `speedhg.admin.timer` | Change the current game timer |
| `/ranking <toggle\|status\|rank [player]>` | — | `speedhg.admin.ranking` | Manage the ranking system |
| `/help` | — | — | Show the help screen |
---
## Permissions
| Node | Default | Description |
|-------------------------|---------|--------------------------------|
| `speedhg.bypass` | `false` | Join while the game is running |
| `speedhg.admin.timer` | `op` | Change the game timer |
| `speedhg.admin.ranking` | `op` | Manage ranking |
| `speedhg.admin.staff` | `false` | Staff flag for Lunar Client |
---
## Architecture
```
SpeedHG (main class)
├── GameManager state machine, game loop, compass, win check
├── KitManager kit registry, player selections, hit-charge state
├── PerkManager perk registry, player selections, DB persistence
├── KitEventDispatcher single Listener delegating all kit events
├── PerkEventDispatcher single Listener delegating all perk events
├── ScoreboardManager sidebar scoreboard
├── TablistManager tab list (Lunar Client / Volcano rank)
├── AntiRunningManager cave-aware anti-runner detection
├── DisasterManager periodic in-game disasters
├── FeastManager mid-game feast event
├── PitManager pit event
├── RankingManager ELO / rank logic
├── StatsManager kill/death/win tracking (MySQL)
├── DatabaseManager HikariCP connection pool
├── LanguageManager MiniMessage i18n
├── LunarClientManager Lunar Client waypoints, scoreboard
├── DiscordWebhookManager post-game Discord messages
├── WorldManager map archive extraction & world loading
├── DataPackManager biome overrides via datapack
└── CustomGameManager SPEEDHG_CUSTOM_SETTINGS JSON parsing
```
### Thread Safety
All per-player state maps use `ConcurrentHashMap`. `BukkitTask` references are canceled and removed in every `onRemove` / `onDeactivate` hook.
### Kit Charge System
When a player's kit is applied, a `PlayerChargeData` object is stored in `KitManager`. Each confirmed melee hit (≥ 90 % attack strength) increments the charge counter. When it reaches `hitsRequired`, the state transitions to `READY` and the player receives an ActionBar notification. Hitting right-click with the ability item triggers `ActiveAbility.execute()` and resets the charge.
`hitsRequired` priority: **kit-specific override** > **global_hits_required** > **hardcoded default**.
Kits that use an internal cooldown instead (e.g. TridentKit Dive) set `hardcodedHitsRequired = 0`.
---
## Adding a New Kit
1. Create `src/main/kotlin/.../kit/impl/YourKit.kt` extending `Kit()`.
2. Implement all abstract members (`id`, `displayName`, `lore`, `icon`, `cachedItems`, `giveItems`, `getActiveAbility`, `getPassiveAbility`).
3. Create `private inner class` for each ability (Active & Passive, for each Playstyle).
4. Put magic numbers in a `companion object` with `UPPER_SNAKE_CASE` constants.
5. Wire configurable values through `override().getLong("key") ?: DEFAULT_*`.
6. Add language keys under `kits.<id>.*` in `src/main/resources/languages/en_US.yml`.
7. Register in `SpeedHG.registerKits()`:
```kotlin
kitManager.registerKit( YourKit() )
```
---
## Adding a New Perk
1. Create `src/main/kotlin/.../perk/impl/YourPerk.kt` extending `Perk()`.
2. Implement `id`, `displayName`, `lore`, `icon`.
3. Override only the event hooks you need (`onActivate`, `onDeactivate`, `onHitEnemy`, etc.).
4. Clean up all state in `onDeactivate`.
5. Add language keys under `perks.<id>.*` in `en_US.yml`.
6. Register in `SpeedHG.registerPerks()`:
```kotlin
perkManager.registerPerk( YourPerk() )
```
---
## Runtime Configuration via `SPEEDHG_CUSTOM_SETTINGS`
Pass a JSON blob as an environment variable to override game and kit settings without redeploying:
```json
{
"game": {
"min_players": 4,
"lobby_time": 45,
"invincibility_time": 60,
"border_start": 500.0,
"border_end": 50.0,
"border_shrink_time": 720
},
"kits": {
"global_hits_required": 12,
"kits": {
"ninja": {
"hits_required": 10,
"extras": {
"cooldown_ms": 8000,
"backstab_damage": 6.0
}
},
"gladiator": {
"arena_radius": 11,
"arena_height": 7,
"wither_after_seconds": 180
},
"trident": {
"extras": {
"max_dive_charges": 3,
"sequence_cooldown_ms": 12000,
"lightning_radius": 4.0,
"lightning_damage": 4.0,
"parry_chance": 0.35,
"parry_slowness_ticks": 60
}
}
}
}
}
```
Kit-level `extras` keys are free-form strings resolved at runtime via `KitOverride.getLong()`, `.getInt()`, and `.getDouble()` with the kit's own hardcoded defaults as fallback.
---
*McScrims Network · play.mcscrims.club*