Add LobbyItemManager; PDC support; misc fixes
Introduce LobbyItemManager to provide interactive lobby hotbar items (kits & perks) tagged via PersistentDataContainer and open the appropriate GUIs. Wire the manager into SpeedHG (field, init, event registration) and clear lobby items at game start in GameManager. Add ItemBuilder.pdc helper and necessary imports for setting PDC. Fix potion duration calculation to use invincibilityTime*20. Change AnchorKit icon/trigger material to ANVIL. Update config (border start/end/shrink and disable anti-runner) and update en_US language entries (lobby item names, leaderboard format, kit lore/formatting and small text fixes).
This commit is contained in:
@@ -16,6 +16,7 @@ import club.mcscrims.speedhg.disaster.DisasterManager
|
|||||||
import club.mcscrims.speedhg.game.GameManager
|
import club.mcscrims.speedhg.game.GameManager
|
||||||
import club.mcscrims.speedhg.game.PodiumManager
|
import club.mcscrims.speedhg.game.PodiumManager
|
||||||
import club.mcscrims.speedhg.game.modules.AntiRunningManager
|
import club.mcscrims.speedhg.game.modules.AntiRunningManager
|
||||||
|
import club.mcscrims.speedhg.game.modules.LobbyItemManager
|
||||||
import club.mcscrims.speedhg.gui.listener.MenuListener
|
import club.mcscrims.speedhg.gui.listener.MenuListener
|
||||||
import club.mcscrims.speedhg.kit.KitManager
|
import club.mcscrims.speedhg.kit.KitManager
|
||||||
import club.mcscrims.speedhg.kit.impl.*
|
import club.mcscrims.speedhg.kit.impl.*
|
||||||
@@ -110,6 +111,9 @@ class SpeedHG : JavaPlugin() {
|
|||||||
lateinit var lunarClientManager: LunarClientManager
|
lateinit var lunarClientManager: LunarClientManager
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
lateinit var lobbyItemManager: LobbyItemManager
|
||||||
|
private set
|
||||||
|
|
||||||
override fun onLoad()
|
override fun onLoad()
|
||||||
{
|
{
|
||||||
instance = this
|
instance = this
|
||||||
@@ -164,6 +168,7 @@ class SpeedHG : JavaPlugin() {
|
|||||||
kitManager = KitManager( this )
|
kitManager = KitManager( this )
|
||||||
discordWebhookManager = DiscordWebhookManager( this )
|
discordWebhookManager = DiscordWebhookManager( this )
|
||||||
lunarClientManager = LunarClientManager( this )
|
lunarClientManager = LunarClientManager( this )
|
||||||
|
lobbyItemManager = LobbyItemManager( this )
|
||||||
|
|
||||||
perkManager = PerkManager( this )
|
perkManager = PerkManager( this )
|
||||||
perkManager.initialize()
|
perkManager.initialize()
|
||||||
@@ -271,6 +276,7 @@ class SpeedHG : JavaPlugin() {
|
|||||||
pm.registerEvents( MenuListener(), this )
|
pm.registerEvents( MenuListener(), this )
|
||||||
pm.registerEvents(PerkEventDispatcher( this, perkManager ), this )
|
pm.registerEvents(PerkEventDispatcher( this, perkManager ), this )
|
||||||
pm.registerEvents( TeamListener(), this )
|
pm.registerEvents( TeamListener(), this )
|
||||||
|
pm.registerEvents( lobbyItemManager, this )
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerRecipes()
|
private fun registerRecipes()
|
||||||
|
|||||||
@@ -154,6 +154,8 @@ class GameManager(
|
|||||||
feastManager.reset()
|
feastManager.reset()
|
||||||
pitManager.reset()
|
pitManager.reset()
|
||||||
|
|
||||||
|
plugin.lobbyItemManager.clearAll()
|
||||||
|
|
||||||
setGameState( GameState.INVINCIBILITY )
|
setGameState( GameState.INVINCIBILITY )
|
||||||
timer = invincibilityTime
|
timer = invincibilityTime
|
||||||
|
|
||||||
@@ -170,7 +172,7 @@ class GameManager(
|
|||||||
|
|
||||||
val speedEffect = PotionEffect(
|
val speedEffect = PotionEffect(
|
||||||
PotionEffectType.SPEED,
|
PotionEffectType.SPEED,
|
||||||
timer,
|
invincibilityTime * 20,
|
||||||
0,
|
0,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
@@ -179,7 +181,7 @@ class GameManager(
|
|||||||
|
|
||||||
val hasteEffect = PotionEffect(
|
val hasteEffect = PotionEffect(
|
||||||
PotionEffectType.HASTE,
|
PotionEffectType.HASTE,
|
||||||
timer,
|
invincibilityTime * 20,
|
||||||
0,
|
0,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
|||||||
@@ -0,0 +1,230 @@
|
|||||||
|
package club.mcscrims.speedhg.game.modules
|
||||||
|
|
||||||
|
import club.mcscrims.speedhg.SpeedHG
|
||||||
|
import club.mcscrims.speedhg.game.GameState
|
||||||
|
import club.mcscrims.speedhg.game.modules.LobbyItemManager.Companion.TAG_KITS
|
||||||
|
import club.mcscrims.speedhg.game.modules.LobbyItemManager.Companion.TAG_PERKS
|
||||||
|
import club.mcscrims.speedhg.gui.menu.KitSelectorMenu
|
||||||
|
import club.mcscrims.speedhg.gui.menu.PerkSelectorMenu
|
||||||
|
import club.mcscrims.speedhg.util.ItemBuilder
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.NamespacedKey
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.EventPriority
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.block.Action
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent
|
||||||
|
import org.bukkit.event.player.PlayerDropItemEvent
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent
|
||||||
|
import org.bukkit.inventory.EquipmentSlot
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.persistence.PersistentDataType
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages interactive lobby hotbar items for the LOBBY and STARTING phases.
|
||||||
|
*
|
||||||
|
* ## Items
|
||||||
|
* - Slot 0: Kit selector (CHEST)
|
||||||
|
* - Slot 1: Perk selector (ENDER_CHEST)
|
||||||
|
*
|
||||||
|
* ## PDC tagging
|
||||||
|
* Each item is tagged with [KEY_LOBBY_ITEM] → a String value identifying which
|
||||||
|
* menu to open ([TAG_KITS] or [TAG_PERKS]). This avoids brittle display-name
|
||||||
|
* comparisons and survives MiniMessage colour changes cleanly.
|
||||||
|
*
|
||||||
|
* ## Lifecycle
|
||||||
|
* Call [giveItems] on join (handled internally via [onJoin]).
|
||||||
|
* Call [clearAll] when transitioning to INVINCIBILITY — see [SpeedHG.startGame].
|
||||||
|
*/
|
||||||
|
class LobbyItemManager(
|
||||||
|
private val plugin: SpeedHG
|
||||||
|
) : Listener {
|
||||||
|
|
||||||
|
// ── PDC keys ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/** Key stored on every lobby item; value identifies the target menu. */
|
||||||
|
val key: NamespacedKey = NamespacedKey( plugin, "lobby_item" )
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TAG_KITS = "kits"
|
||||||
|
const val TAG_PERKS = "perks"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Item definitions ──────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a fresh kit-selector item.
|
||||||
|
* Always call this factory rather than caching a singleton, because
|
||||||
|
* [ItemStack] is mutable and Paper may modify the stack object in-place.
|
||||||
|
*/
|
||||||
|
fun buildKitItem(
|
||||||
|
player: Player
|
||||||
|
): ItemStack
|
||||||
|
{
|
||||||
|
return ItemBuilder( Material.CHEST )
|
||||||
|
.name(plugin.languageManager.getComponent( player, "game.lobby-items.kits.name", mapOf() ))
|
||||||
|
.pdc( key, PersistentDataType.STRING, TAG_KITS )
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a fresh perk-selector item.
|
||||||
|
*/
|
||||||
|
fun buildPerkItem(
|
||||||
|
player: Player
|
||||||
|
): ItemStack
|
||||||
|
{
|
||||||
|
return ItemBuilder( Material.ENDER_CHEST )
|
||||||
|
.name(plugin.languageManager.getComponent( player, "game.lobby-items.perks.name", mapOf() ))
|
||||||
|
.pdc( key, PersistentDataType.STRING, TAG_PERKS )
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Public API ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the player's inventory and places the two lobby items into
|
||||||
|
* hotbar slots 0 and 1.
|
||||||
|
*
|
||||||
|
* Only call this during [GameState.LOBBY] or [GameState.STARTING].
|
||||||
|
*/
|
||||||
|
fun giveItems(
|
||||||
|
player: Player
|
||||||
|
) {
|
||||||
|
player.inventory.clear()
|
||||||
|
player.inventory.setItem( 0, buildKitItem( player ))
|
||||||
|
player.inventory.setItem( 1, buildPerkItem( player ))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes lobby items from every online player.
|
||||||
|
*
|
||||||
|
* Call this at the start of [GameState.INVINCIBILITY] (inside
|
||||||
|
* [GameManager.startGame], just before kit items are distributed):
|
||||||
|
*
|
||||||
|
* ```kotlin
|
||||||
|
* // Inside startGame(), before applyKit() loop:
|
||||||
|
* plugin.lobbyItemManager.clearAll()
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
fun clearAll()
|
||||||
|
{
|
||||||
|
plugin.server.onlinePlayers.forEach {
|
||||||
|
removeFromPlayer( it )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Helpers ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the PDC tag value ([TAG_KITS] / [TAG_PERKS]) if the given
|
||||||
|
* [ItemStack] is a lobby item, or `null` otherwise.
|
||||||
|
*/
|
||||||
|
private fun ItemStack?.lobbyTag(): String?
|
||||||
|
{
|
||||||
|
this ?: return null
|
||||||
|
if ( type.isAir ) return null
|
||||||
|
return itemMeta?.persistentDataContainer?.get( key, PersistentDataType.STRING )
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Removes only the lobby-tagged items from the player's inventory. */
|
||||||
|
private fun removeFromPlayer(
|
||||||
|
player: Player
|
||||||
|
) {
|
||||||
|
player.inventory.forEachIndexed { index, stack ->
|
||||||
|
if ( stack.lobbyTag() != null ) player.inventory.setItem( index, null )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isLobbyPhase(): Boolean = when( plugin.gameManager.currentState )
|
||||||
|
{
|
||||||
|
GameState.LOBBY, GameState.STARTING -> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Event handlers ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Give items to players who join while the server is in the lobby phase.
|
||||||
|
*/
|
||||||
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
|
fun onJoin(
|
||||||
|
event: PlayerJoinEvent
|
||||||
|
) {
|
||||||
|
if ( !isLobbyPhase() ) return
|
||||||
|
// Defer by one tick so ConnectListener's join logic (kick check etc.)
|
||||||
|
// completes first and we don't give items to a player about to be kicked.
|
||||||
|
plugin.server.scheduler.runTask( plugin ) { ->
|
||||||
|
if ( event.player.isOnline && isLobbyPhase() )
|
||||||
|
{
|
||||||
|
giveItems( event.player )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Right-click handler — opens the appropriate GUI.
|
||||||
|
*
|
||||||
|
* Priority HIGH so we run before other interact listeners and can cancel
|
||||||
|
* early without them seeing the event at all.
|
||||||
|
*/
|
||||||
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = false)
|
||||||
|
fun onInteract(
|
||||||
|
event: PlayerInteractEvent
|
||||||
|
) {
|
||||||
|
// Fast-exit: only main-hand right-clicks
|
||||||
|
if ( event.hand != EquipmentSlot.HAND ) return
|
||||||
|
if ( event.action != Action.RIGHT_CLICK_AIR &&
|
||||||
|
event.action != Action.RIGHT_CLICK_BLOCK ) return
|
||||||
|
if ( !isLobbyPhase() ) return
|
||||||
|
|
||||||
|
val tag = event.player.inventory.itemInMainHand.lobbyTag() ?: return
|
||||||
|
|
||||||
|
// Cancel unconditionally — prevents chest placement, block interaction, etc.
|
||||||
|
event.isCancelled = true
|
||||||
|
|
||||||
|
when( tag )
|
||||||
|
{
|
||||||
|
TAG_KITS -> KitSelectorMenu( event.player ).open( event.player )
|
||||||
|
TAG_PERKS -> PerkSelectorMenu( event.player ).open( event.player )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevents lobby items from being dropped.
|
||||||
|
*/
|
||||||
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = false)
|
||||||
|
fun onDrop(
|
||||||
|
event: PlayerDropItemEvent
|
||||||
|
) {
|
||||||
|
if ( !isLobbyPhase() ) return
|
||||||
|
if ( event.itemDrop.itemStack.lobbyTag() != null ) event.isCancelled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevents lobby items from being moved within the inventory.
|
||||||
|
*
|
||||||
|
* We only listen on the player's own inventory to avoid interfering
|
||||||
|
* with chest/crafting interactions — the cursor item and the clicked
|
||||||
|
* item are both checked.
|
||||||
|
*/
|
||||||
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = false)
|
||||||
|
fun onInventoryClick(
|
||||||
|
event: InventoryClickEvent
|
||||||
|
) {
|
||||||
|
if ( !isLobbyPhase() ) return
|
||||||
|
val player = event.whoClicked as? Player ?: return
|
||||||
|
|
||||||
|
// Only guard the player's own inventory (bottom section or hotbar)
|
||||||
|
val isOwnInventory = event.clickedInventory == player.inventory
|
||||||
|
if ( !isOwnInventory ) return
|
||||||
|
|
||||||
|
val clickedIsLobby = event.currentItem.lobbyTag() != null
|
||||||
|
val cursorIsLobby = event.cursor.lobbyTag() != null
|
||||||
|
|
||||||
|
if ( clickedIsLobby || cursorIsLobby ) event.isCancelled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -64,7 +64,7 @@ class AnchorKit : Kit() {
|
|||||||
get() = plugin.languageManager.getDefaultComponent("kits.anchor.name", mapOf())
|
get() = plugin.languageManager.getDefaultComponent("kits.anchor.name", mapOf())
|
||||||
override val lore: List<String>
|
override val lore: List<String>
|
||||||
get() = plugin.languageManager.getDefaultRawMessageList("kits.anchor.lore")
|
get() = plugin.languageManager.getDefaultRawMessageList("kits.anchor.lore")
|
||||||
override val icon = Material.CHAIN
|
override val icon = Material.ANVIL
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val PARTIAL_RESISTANCE = 0.4 // 40 % – immer aktiv
|
const val PARTIAL_RESISTANCE = 0.4 // 40 % – immer aktiv
|
||||||
@@ -141,7 +141,7 @@ class AnchorKit : Kit() {
|
|||||||
override val description: String
|
override val description: String
|
||||||
get() = plugin.languageManager.getDefaultRawMessage("kits.anchor.items.chain.description")
|
get() = plugin.languageManager.getDefaultRawMessage("kits.anchor.items.chain.description")
|
||||||
override val hardcodedHitsRequired = 15
|
override val hardcodedHitsRequired = 15
|
||||||
override val triggerMaterial = Material.CHAIN
|
override val triggerMaterial = Material.ANVIL
|
||||||
|
|
||||||
override fun execute(player: Player): AbilityResult {
|
override fun execute(player: Player): AbilityResult {
|
||||||
// Alten Anker entfernen (kein Todesklang – Spieler beschwört neuen)
|
// Alten Anker entfernen (kein Todesklang – Spieler beschwört neuen)
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ import net.kyori.adventure.text.format.TextDecoration
|
|||||||
import net.kyori.adventure.text.minimessage.MiniMessage
|
import net.kyori.adventure.text.minimessage.MiniMessage
|
||||||
import org.bukkit.ChatColor
|
import org.bukkit.ChatColor
|
||||||
import org.bukkit.Material
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.NamespacedKey
|
||||||
import org.bukkit.enchantments.Enchantment
|
import org.bukkit.enchantments.Enchantment
|
||||||
import org.bukkit.inventory.ItemFlag
|
import org.bukkit.inventory.ItemFlag
|
||||||
import org.bukkit.inventory.ItemStack
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.persistence.PersistentDataType
|
||||||
|
|
||||||
class ItemBuilder(
|
class ItemBuilder(
|
||||||
private val itemStack: ItemStack
|
private val itemStack: ItemStack
|
||||||
@@ -76,6 +78,18 @@ class ItemBuilder(
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T, Z> pdc(
|
||||||
|
key: NamespacedKey,
|
||||||
|
dataType: PersistentDataType<T, Z>,
|
||||||
|
value: Z
|
||||||
|
): ItemBuilder
|
||||||
|
{
|
||||||
|
itemStack.editMeta {
|
||||||
|
it.persistentDataContainer.set( key, dataType, value!! )
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
fun enchant(
|
fun enchant(
|
||||||
ench: Enchantment
|
ench: Enchantment
|
||||||
): ItemBuilder
|
): ItemBuilder
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ game:
|
|||||||
min-players: 2
|
min-players: 2
|
||||||
lobby-time: 60
|
lobby-time: 60
|
||||||
invincibility-time: 60
|
invincibility-time: 60
|
||||||
border-start: 300.0
|
border-start: 600.0
|
||||||
border-end: 20.0
|
border-end: 100.0
|
||||||
border-shrink-time: 600 # 10 Minuten
|
border-shrink-time: 900 # 10 Minuten
|
||||||
ranked: false
|
ranked: false
|
||||||
|
|
||||||
anti-runner:
|
anti-runner:
|
||||||
enabled: true
|
enabled: false
|
||||||
check-radius: 20.0
|
check-radius: 20.0
|
||||||
warn-time: 15
|
warn-time: 15
|
||||||
punish-time: 25
|
punish-time: 25
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ game:
|
|||||||
death-killed: '<prefix><yellow><player> has died whilst fighting <killer>! There are <left> players left.</yellow>'
|
death-killed: '<prefix><yellow><player> has died whilst fighting <killer>! There are <left> players left.</yellow>'
|
||||||
death-pve: '<prefix><yellow><player> has died! There are <left> players left.</yellow>'
|
death-pve: '<prefix><yellow><player> has died! There are <left> players left.</yellow>'
|
||||||
win-chat: '<prefix><green><winner> has won the game! Thanks for playing!</green>'
|
win-chat: '<prefix><green><winner> has won the game! Thanks for playing!</green>'
|
||||||
|
lobby-items:
|
||||||
|
kits:
|
||||||
|
name: '<gold><bold>Kits</bold></gold> <gray>(right-click)</gray>'
|
||||||
|
perks:
|
||||||
|
name: '<light_purple><bold>Perks</bold></light_purple> <gray>(right-click)</gray>'
|
||||||
|
|
||||||
ranking:
|
ranking:
|
||||||
placement_progress: '<prefix><gray>Placement <aqua><current>/<total></aqua> — Placed <aqua>#<placement></aqua> · <aqua><kills></aqua> Kill(s)</gray>'
|
placement_progress: '<prefix><gray>Placement <aqua><current>/<total></aqua> — Placed <aqua>#<placement></aqua> · <aqua><kills></aqua> Kill(s)</gray>'
|
||||||
@@ -139,7 +144,7 @@ commands:
|
|||||||
leaderboard:
|
leaderboard:
|
||||||
header: '<gray>====== <gold>Leaderboard</gold> ======</gray>'
|
header: '<gray>====== <gold>Leaderboard</gold> ======</gray>'
|
||||||
empty: '<red>There are currently no stats</red>'
|
empty: '<red>There are currently no stats</red>'
|
||||||
line: '#<rank> - <green><name></green> - <aqua><score></aqua>'
|
line: '#<rank> - <green><name></green> <dark_gray>[<white><playerrank></white>]</dark_gray> - <aqua><score></aqua>'
|
||||||
footer: '<gray>====== <gold>Leaderboard</gold> ======</gray>'
|
footer: '<gray>====== <gold>Leaderboard</gold> ======</gray>'
|
||||||
timer:
|
timer:
|
||||||
usage: '<red>Usage: /timer <seconds></red>'
|
usage: '<red>Usage: /timer <seconds></red>'
|
||||||
@@ -311,11 +316,8 @@ kits:
|
|||||||
name: '<gradient:dark_green:gray><bold>Goblin</bold></gradient>'
|
name: '<gradient:dark_green:gray><bold>Goblin</bold></gradient>'
|
||||||
lore:
|
lore:
|
||||||
- ' '
|
- ' '
|
||||||
- 'AGGRESSIVE:'
|
- 'AGGRESSIVE: Copy your enemies kit'
|
||||||
- 'Copy your enemies kit'
|
- 'DEFENSIVE: Summon a bunker for protection'
|
||||||
- ' '
|
|
||||||
- 'DEFENSIVE:'
|
|
||||||
- 'Summon a bunker for protection'
|
|
||||||
items:
|
items:
|
||||||
steal:
|
steal:
|
||||||
name: '§cSteal Kit'
|
name: '§cSteal Kit'
|
||||||
@@ -331,11 +333,8 @@ kits:
|
|||||||
name: '<gradient:dark_aqua:aqua><bold>IceMage</bold></gradient>'
|
name: '<gradient:dark_aqua:aqua><bold>IceMage</bold></gradient>'
|
||||||
lore:
|
lore:
|
||||||
- ' '
|
- ' '
|
||||||
- 'AGGRESSIVE:'
|
- 'AGGRESSIVE: Gain speed in ice biomes and give slowness'
|
||||||
- 'Gain speed in ice biomes and give slowness'
|
- 'DEFENSIVE: Summon snowballs and freeze enemies'
|
||||||
- ' '
|
|
||||||
- 'DEFENSIVE:'
|
|
||||||
- 'Summon snowballs and freeze enemies'
|
|
||||||
items:
|
items:
|
||||||
snowball:
|
snowball:
|
||||||
name: '§bFreeze'
|
name: '§bFreeze'
|
||||||
@@ -350,11 +349,8 @@ kits:
|
|||||||
name: '<gradient:dark_red:red><bold>Venom</bold></gradient>'
|
name: '<gradient:dark_red:red><bold>Venom</bold></gradient>'
|
||||||
lore:
|
lore:
|
||||||
- ' '
|
- ' '
|
||||||
- 'AGGRESSIVE:'
|
- 'AGGRESSIVE: Summon a deafening beam'
|
||||||
- 'Summon a deafening beam'
|
- 'DEFENSIVE: Create a shield for protection'
|
||||||
- ' '
|
|
||||||
- 'DEFENSIVE:'
|
|
||||||
- 'Create a shield for protection'
|
|
||||||
items:
|
items:
|
||||||
wither:
|
wither:
|
||||||
name: '§8Deafening Beam'
|
name: '§8Deafening Beam'
|
||||||
@@ -371,7 +367,7 @@ kits:
|
|||||||
shield_break: '<red>Your shield of darkness has broken!</red>'
|
shield_break: '<red>Your shield of darkness has broken!</red>'
|
||||||
ability_charged: '<yellow>Your ability has been recharged</yellow>'
|
ability_charged: '<yellow>Your ability has been recharged</yellow>'
|
||||||
rattlesnake:
|
rattlesnake:
|
||||||
name: '<gradient:green:lime><bold>Rattlesnake</bold></gradient>'
|
name: '<gradient:green:dark_green><bold>Rattlesnake</bold></gradient>'
|
||||||
lore:
|
lore:
|
||||||
- ' '
|
- ' '
|
||||||
- 'AGGRESSIVE: Sneak-charged pounce'
|
- 'AGGRESSIVE: Sneak-charged pounce'
|
||||||
@@ -508,10 +504,10 @@ kits:
|
|||||||
- 'DEFENSIVE: Blindness + Slowness III (4 s)'
|
- 'DEFENSIVE: Blindness + Slowness III (4 s)'
|
||||||
items:
|
items:
|
||||||
drain:
|
drain:
|
||||||
name: '<dark_purple>Life Drain'
|
name: '<dark_purple>Life Drain</dark_purple>'
|
||||||
description: 'Drain life from nearby enemies. Sneak to cancel.'
|
description: 'Drain life from nearby enemies. Sneak to cancel.'
|
||||||
fear:
|
fear:
|
||||||
name: '<dark_purple>Puppeteer''s Fear'
|
name: '<dark_purple>Puppeteer''s Fear</dark_purple>'
|
||||||
description: 'Apply Blindness + Slowness to nearby enemies'
|
description: 'Apply Blindness + Slowness to nearby enemies'
|
||||||
messages:
|
messages:
|
||||||
drain_start: '<dark_purple>Draining life...'
|
drain_start: '<dark_purple>Draining life...'
|
||||||
|
|||||||
Reference in New Issue
Block a user