Introduce three new kits (Anchor, Puppet, Tesla) and multiple perks, plus related plumbing and behavior changes. Key changes: - Added kit implementations: AnchorKit (summon iron-golem anchor, knockback resistance/radius effects), PuppetKit (life-drain / fear abilities), TeslaKit (lightning active + passive knockback/fire aura). - Register new kits and register new perks in SpeedHG startup. - Added new perks: AdrenalinePerk (post-damage speed proc with cooldown), EnderbluePerk (ender-pearl fall damage handling), Ghost, Pyromaniac, Scavenger (and updated OraclePerk/PerkEventDispatcher usage). - Extended Perk API (Perk.kt) with onEnderPearlDamage and onPostDamage hooks to support specialized damage handling and post-damage checks. - PerkManager.isGhost added for checking Ghost perk selection and used to exclude ghost players from targeting/compass logic. - GameManager.updateCompass now excludes ghost-perk players when computing compass targets. - Updated PerkEventDispatcher and OraclePerk to integrate new hooks and behaviors. - Minor language additions in en_US.yml to support new kits/perks. These changes add new gameplay mechanics and ensure correct event dispatching for pearl/fall/post-damage cases and ghost invisibility to game tracking.
85 lines
3.5 KiB
Kotlin
85 lines
3.5 KiB
Kotlin
package club.mcscrims.speedhg.perk
|
|
|
|
import net.kyori.adventure.text.Component
|
|
import org.bukkit.Material
|
|
import org.bukkit.entity.Player
|
|
import org.bukkit.event.entity.EntityDamageByEntityEvent
|
|
import org.bukkit.event.entity.EntityDamageEvent
|
|
|
|
/**
|
|
* Basisklasse für alle passiven Perks in SpeedHG.
|
|
*
|
|
* Perks sind passive Boni, die Spieler neben ihrem Kit ausrüsten.
|
|
* Ein Spieler darf maximal [PerkManager.MAX_PERKS] Perks gleichzeitig aktiv haben.
|
|
*
|
|
* ## Neuen Perk erstellen
|
|
* 1. Diese Klasse erweitern.
|
|
* 2. Alle abstrakten Member implementieren.
|
|
* 3. Nur die Hooks überschreiben, die tatsächlich gebraucht werden — alle Defaults sind No-Ops.
|
|
* 4. Via `plugin.perkManager.registerPerk(DeinPerk())` in [SpeedHG.onEnable] registrieren.
|
|
*/
|
|
abstract class Perk {
|
|
|
|
/** Eindeutiger snake_case Bezeichner. Muss dem Sprachschlüssel-Prefix `perks.<id>.*` entsprechen. */
|
|
abstract val id: String
|
|
|
|
/** Angezeigter Name im GUI, aus der Sprachdatei geladen. */
|
|
abstract val displayName: Component
|
|
|
|
/** Kurze Lore-Zeilen als MiniMessage-Strings aus der Sprachdatei. */
|
|
abstract val lore: List<String>
|
|
|
|
/** Icon-Material im Perk-Selector-GUI. */
|
|
abstract val icon: Material
|
|
|
|
// ── Lifecycle ─────────────────────────────────────────────────────────────
|
|
|
|
/** Einmalig aufgerufen wenn das Spiel startet und dieser Perk für [player] aktiv ist. */
|
|
open fun onActivate(player: Player) {}
|
|
|
|
/** Aufgerufen wenn die Runde endet oder der Perk entfernt wird. Tasks hier abbrechen. */
|
|
open fun onDeactivate(player: Player) {}
|
|
|
|
// ── Combat Hooks (dispatched by PerkEventDispatcher) ──────────────────────
|
|
|
|
/** [attacker] (dieser Spieler) hat gerade [victim] per Nahkampf getroffen. */
|
|
open fun onHitEnemy(attacker: Player, victim: Player, event: EntityDamageByEntityEvent) {}
|
|
|
|
/** Dieser Spieler hat gerade einen Nahkampfhit von [attacker] erhalten. */
|
|
open fun onHitByEnemy(victim: Player, attacker: Player, event: EntityDamageByEntityEvent) {}
|
|
|
|
/** Dieser Spieler hat einen anderen Spieler getötet. */
|
|
open fun onKillEnemy(killer: Player, victim: Player) {}
|
|
|
|
/**
|
|
* Aufgerufen bei Umgebungsschaden (Fall, Feuer, etc.) — KEIN Nahkampf.
|
|
* Wird vom Dispatcher mit HIGH-Priority verarbeitet, damit Featherweight canceln kann.
|
|
*/
|
|
open fun onEnvironmentalDamage(player: Player, event: EntityDamageEvent) {}
|
|
|
|
/**
|
|
* Aufgerufen wenn dieser Spieler via Enderperle teleportiert wurde und
|
|
* direkt danach Fallschaden erhalten würde (Cause: FALL, nach ENDER_PEARL-Teleport).
|
|
*
|
|
* Der [PerkEventDispatcher] unterscheidet diesen Fall vom normalen Fallschaden
|
|
* über ein internes Tracking-Set und ruft diesen Hook **statt** [onEnvironmentalDamage] auf.
|
|
*
|
|
* → Überschreiben um den Schaden zu canceln ([event.isCancelled = true]).
|
|
*/
|
|
open fun onEnderPearlDamage(player: Player, event: EntityDamageEvent) {}
|
|
|
|
/**
|
|
* Aufgerufen **nach** vollständiger Schadensberechnung (MONITOR-Priority),
|
|
* wenn `event.finalDamage` den endgültigen Abzug nach Rüstung/Modifiern enthält.
|
|
* `player.health` ist hier noch der Vor-Schaden-Wert.
|
|
*
|
|
* Geeignet für Prüfungen der Form: `player.health - event.finalDamage < X`
|
|
*
|
|
* Gilt für **jeden** Schadenstyp (Nahkampf UND Umgebung).
|
|
* Wird nicht aufgerufen wenn das Event bereits gecancelt ist.
|
|
*
|
|
* → Primär für [AdrenalinePerk].
|
|
*/
|
|
open fun onPostDamage(player: Player, event: EntityDamageEvent) {}
|
|
|
|
} |