add curse of panic

This commit is contained in:
2024-10-28 17:07:07 +01:00
parent 3752a9e31a
commit f96a164575
5 changed files with 298 additions and 8 deletions
@@ -26,6 +26,9 @@ public final class Enchantio extends JavaPlugin {
if (EnchantioConfig.ENCHANTS.containsKey(SmeltingEnchant.KEY)) {
getServer().getPluginManager().registerEvents(new SmeltingListener(), this);
}
if (EnchantioConfig.ENCHANTS.containsKey(PanicEnchant.KEY)) {
getServer().getPluginManager().registerEvents(new PanicListener(), this);
}
}
@Override
@@ -79,15 +79,15 @@ public class EnchantioConfig {
}
TelepathyEnchant telepathyEnchant = new TelepathyEnchant(
getInt(telepathySection,"anvilCost", 1),
getInt(telepathySection,"weight", 5),
getInt(telepathySection, "anvilCost", 1),
getInt(telepathySection, "weight", 5),
EnchantmentRegistryEntry.EnchantmentCost.of(
getInt(telepathySection,"minimumCost.base", 15),
getInt(telepathySection,"minimumCost.additionalPerLevel", 1)
getInt(telepathySection, "minimumCost.base", 15),
getInt(telepathySection, "minimumCost.additionalPerLevel", 1)
),
EnchantmentRegistryEntry.EnchantmentCost.of(
getInt(telepathySection,"maximumCost.base", 65),
getInt(telepathySection,"maximumCost.additionalPerLevel", 1)
getInt(telepathySection, "maximumCost.base", 65),
getInt(telepathySection, "maximumCost.additionalPerLevel", 1)
),
getBoolean(telepathySection, "canGetFromEnchantingTable", true),
getTagsFromList(getStringList(
@@ -147,7 +147,7 @@ public class EnchantioConfig {
),
EnchantmentRegistryEntry.EnchantmentCost.of(
getInt(executionerSection, "maximumCost.base", 65),
getInt(executionerSection,"maximumCost.additionalPerLevel", 1)
getInt(executionerSection, "maximumCost.additionalPerLevel", 1)
),
getBoolean(executionerSection, "canGetFromEnchantingTable", true),
getTagsFromList(getStringList(
@@ -157,7 +157,7 @@ public class EnchantioConfig {
"#minecraft:enchantable/weapon"
)
)),
getInt(executionerSection,"maxLevel", 5),
getInt(executionerSection, "maxLevel", 5),
getDouble(executionerSection, "damageMultiplierPerLevel", 0.05),
getDouble(executionerSection, "maxDamageHpThreshold", 0.25)
);
@@ -228,6 +228,43 @@ public class EnchantioConfig {
ENCHANTS.put(SmeltingEnchant.KEY, smeltingEnchant);
}
ConfigurationSection cursesSection = configuration.getConfigurationSection("curses");
if (cursesSection == null) {
cursesSection = configuration.createSection("curses");
}
ConfigurationSection panicSection = cursesSection.getConfigurationSection("panic");
if (panicSection == null) {
panicSection = cursesSection.createSection("panic");
}
PanicEnchant panicEnchant = new PanicEnchant(
getInt(panicSection, "anvilCost", 1),
getInt(panicSection, "weight", 2),
EnchantmentRegistryEntry.EnchantmentCost.of(
getInt(panicSection, "minimumCost.base", 0),
getInt(panicSection, "minimumCost.additionalPerLevel", 3)
),
EnchantmentRegistryEntry.EnchantmentCost.of(
getInt(panicSection, "maximumCost.base", 20),
getInt(panicSection, "maximumCost.additionalPerLevel", 1)
),
getBoolean(panicSection, "canGetFromEnchantingTable", true),
getTagsFromList(getStringList(
panicSection,
"supportedItemTags",
List.of(
"#minecraft:enchantable/armor"
)
)),
getInt(panicSection, "maxLevel", 1),
getDouble(panicSection, "panicChancePerLevel", 0.025)
);
if (getBoolean(panicSection, "enabled", true)) {
ENCHANTS.put(PanicEnchant.KEY, panicEnchant);
}
configuration.save(configFile);
}
@@ -0,0 +1,106 @@
package me.youhavetrouble.enchantio.enchants;
import io.papermc.paper.registry.data.EnchantmentRegistryEntry;
import io.papermc.paper.registry.keys.tags.EnchantmentTagKeys;
import io.papermc.paper.registry.tag.TagKey;
import io.papermc.paper.tag.TagEntry;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.text.Component;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.EquipmentSlotGroup;
import org.bukkit.inventory.ItemType;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@SuppressWarnings("UnstableApiUsage")
public class PanicEnchant implements EnchantioEnchant {
public static final Key KEY = Key.key("enchantio:panic_curse");
private final int anvilCost, weight, maxLevel;
private final EnchantmentRegistryEntry.EnchantmentCost minimumCost;
private final EnchantmentRegistryEntry.EnchantmentCost maximumCost;
private final double panicChancePerLevel;
private final Set<TagEntry<ItemType>> supportedItemTags;
private final Set<TagKey<Enchantment>> enchantTagKeys = new HashSet<>();
public PanicEnchant(
int anvilCost,
int weight,
EnchantmentRegistryEntry.EnchantmentCost minimumCost,
EnchantmentRegistryEntry.EnchantmentCost maximumCost,
boolean canGetFromEnchantingTable,
Set<TagEntry<ItemType>> supportedItemTags,
int maxLevel,
double panicChancePerLevel
) {
this.anvilCost = anvilCost;
this.weight = weight;
this.maxLevel = maxLevel;
this.minimumCost = minimumCost;
this.maximumCost = maximumCost;
this.supportedItemTags = supportedItemTags;
this.panicChancePerLevel = panicChancePerLevel;
if (canGetFromEnchantingTable) {
enchantTagKeys.add(EnchantmentTagKeys.IN_ENCHANTING_TABLE);
}
enchantTagKeys.add(EnchantmentTagKeys.CURSE);
}
@Override
public Key getKey() {
return KEY;
}
@Override
public Component getDescription() {
return Component.translatable("enchantio.enchant.panic_curse", "Curse of Panic");
}
@Override
public int getAnvilCost() {
return anvilCost;
}
@Override
public int getMaxLevel() {
return maxLevel;
}
@Override
public int getWeight() {
return weight;
}
@Override
public EnchantmentRegistryEntry.EnchantmentCost getMinimumCost() {
return minimumCost;
}
@Override
public EnchantmentRegistryEntry.EnchantmentCost getMaximumCost() {
return maximumCost;
}
@Override
public Iterable<EquipmentSlotGroup> getActiveSlots() {
return Set.of(EquipmentSlotGroup.ARMOR);
}
@Override
public Set<TagEntry<ItemType>> getSupportedItems() {
return supportedItemTags;
}
@Override
public Set<TagKey<Enchantment>> getEnchantTagKeys() {
return Collections.unmodifiableSet(enchantTagKeys);
}
public double getPanicChancePerLevel() {
return panicChancePerLevel;
}
}
@@ -0,0 +1,68 @@
package me.youhavetrouble.enchantio.events;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
/**
* Called when a player with the Panic enchantment takes damage and their hotbar is scrambled.
*/
public class PlayerPanicEvent extends PlayerEvent implements Cancellable {
private static final HandlerList HANDLERS = new HandlerList();
private boolean cancelled = false;
private final List<ItemStack> scrambledItems;
public PlayerPanicEvent(@NotNull Player player, @NotNull List<ItemStack> scrambledItems) {
super(player);
this.scrambledItems = scrambledItems;
}
/**
* Get the hotbar items that will be set for the player. List order will be preserved.
* @return The unmodifiable list of hotbar items
*/
public List<ItemStack> getScrambledItems() {
return Collections.unmodifiableList(scrambledItems);
}
/**
* Set the new player hotbar items. List order will be preserved. List must have a size of 9.
* @param scrambledItems The new hotbar items
*/
public void setScrambledItems(@NotNull List<ItemStack> scrambledItems) {
if (scrambledItems.size() != 9) {
throw new IllegalArgumentException("Scrambled items must have a size of 9");
}
this.scrambledItems.clear();
this.scrambledItems.addAll(scrambledItems);
}
@Override
public @NotNull HandlerList getHandlers() {
return HANDLERS;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
@NotNull
public static HandlerList getHandlerList() {
return HANDLERS;
}
}
@@ -0,0 +1,76 @@
package me.youhavetrouble.enchantio.listeners;
import io.papermc.paper.registry.RegistryAccess;
import io.papermc.paper.registry.RegistryKey;
import me.youhavetrouble.enchantio.EnchantioConfig;
import me.youhavetrouble.enchantio.enchants.BeheadingEnchant;
import me.youhavetrouble.enchantio.enchants.EnchantioEnchant;
import me.youhavetrouble.enchantio.enchants.PanicEnchant;
import me.youhavetrouble.enchantio.events.PlayerPanicEvent;
import org.bukkit.Bukkit;
import org.bukkit.Registry;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.EquipmentSlotGroup;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
public class PanicListener implements Listener {
private final Registry<Enchantment> registry = RegistryAccess.registryAccess().getRegistry(RegistryKey.ENCHANTMENT);
private final Enchantment panic = registry.get(PanicEnchant.KEY);
@EventHandler(ignoreCancelled = true, priority = EventPriority.NORMAL)
public void onPlayerPanic(EntityDamageEvent event) {
if (panic == null) return;
if (!(event.getEntity() instanceof Player player)) return;
EnchantioEnchant enchant = EnchantioConfig.ENCHANTS.get(PanicEnchant.KEY);
if (!(enchant instanceof PanicEnchant panicEnchant)) return;
PlayerInventory inventory = player.getInventory();
ItemStack highestPanicEnchantItem = null;
for (ItemStack item : inventory.getArmorContents()) {
if (item == null) continue;
if (item.containsEnchantment(panic)) {
if (highestPanicEnchantItem == null) {
highestPanicEnchantItem = item;
} else if (item.getEnchantmentLevel(panic) > highestPanicEnchantItem.getEnchantmentLevel(panic)) {
highestPanicEnchantItem = item;
}
}
}
if (highestPanicEnchantItem == null) return;
double chance = highestPanicEnchantItem.getEnchantmentLevel(panic) * panicEnchant.getPanicChancePerLevel();
if (ThreadLocalRandom.current().nextDouble() > chance) return;
List<ItemStack> hotbarItems = new ArrayList<>(Arrays.stream(inventory.getContents()).toList().subList(0, 9));
Collections.shuffle(hotbarItems, ThreadLocalRandom.current());
PlayerPanicEvent playerPanicEvent = new PlayerPanicEvent(player, hotbarItems);
Bukkit.getPluginManager().callEvent(playerPanicEvent);
if (playerPanicEvent.isCancelled()) return;
for (int i = 0; i < 9; i++) {
inventory.setItem(i, playerPanicEvent.getScrambledItems().get(i));
}
}
}