From 3df567630488de219ad79c21de28a725eb2359e1 Mon Sep 17 00:00:00 2001 From: Jules Date: Thu, 9 May 2024 18:01:36 -0700 Subject: [PATCH] Fixed permanent skills not triggering when locked/unlocked --- .../java/net/Indyuce/mmocore/MMOCore.java | 2 - .../mmocore/api/player/PlayerData.java | 36 ++++++++++++----- .../mmocore/api/player/stats/PlayerStats.java | 5 +-- .../api/quest/trigger/UnlockSkillTrigger.java | 6 +-- .../api/quest/trigger/UnlockSlotTrigger.java | 13 +++---- .../rpg/admin/SkillCommandTreeNode.java | 12 +++--- .../rpg/admin/SlotCommandTreeNode.java | 16 ++++---- .../net/Indyuce/mmocore/skill/ClassSkill.java | 39 ++++++++++++------- .../mmocore/skill/binding/BoundSkillInfo.java | 4 +- .../skill/cast/SkillCastingInstance.java | 27 +++++++++++-- .../mmocore/skill/cast/handler/KeyCombos.java | 2 +- .../mmocore/skill/cast/handler/SkillBar.java | 33 ++++++++++------ .../skill/cast/handler/SkillScroller.java | 10 ++--- 13 files changed, 128 insertions(+), 77 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java index cf5e0ad6..ed3983b2 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java @@ -207,8 +207,6 @@ public class MMOCore extends MMOPlugin { if (Bukkit.getPluginManager().getPlugin("MMOMana") != null) { getLogger().log(Level.SEVERE, ChatColor.DARK_RED + "MMOCore is not meant to be used with MMOItems ManaAndStamina"); getLogger().log(Level.SEVERE, ChatColor.DARK_RED + "Please read the installation guide!"); - Bukkit.broadcastMessage(ChatColor.DARK_RED + "[MMOCore] MMOCore is not meant to be used with MMOItems ManaAndStamina"); - Bukkit.broadcastMessage(ChatColor.DARK_RED + "[MMOCore] Please read the installation guide!"); return; } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index 4c4c3f4c..e24e5bf2 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -393,11 +393,11 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD */ public boolean unlock(Unlockable unlockable) { Validate.isTrue(!unlockable.isUnlockedByDefault(), "Cannot unlock an item unlocked by default"); - unlockable.whenUnlocked(this); final boolean wasLocked = unlockedItems.add(unlockable.getUnlockNamespacedKey()); - // Call the event synchronously - if (wasLocked) + if (wasLocked) { + unlockable.whenUnlocked(this); Bukkit.getScheduler().runTask(MythicLib.plugin, () -> Bukkit.getPluginManager().callEvent(new ItemUnlockedEvent(this, unlockable.getUnlockNamespacedKey()))); + } return wasLocked; } @@ -409,11 +409,11 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD */ public boolean lock(Unlockable unlockable) { Validate.isTrue(!unlockable.isUnlockedByDefault(), "Cannot lock an item unlocked by default"); - unlockable.whenLocked(this); boolean wasUnlocked = unlockedItems.remove(unlockable.getUnlockNamespacedKey()); - if (wasUnlocked) - //Calls the event synchronously + if (wasUnlocked) { + unlockable.whenLocked(this); Bukkit.getScheduler().runTask(MythicLib.plugin, () -> Bukkit.getPluginManager().callEvent(new ItemLockedEvent(this, unlockable.getUnlockNamespacedKey()))); + } return wasUnlocked; } @@ -1224,19 +1224,37 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD Validate.notNull(skill, "Skill cannot be null"); if (slot <= 0) return; + // Friendly error in case server owner makes a skill permanent while players have already bound it + if (skill.isPermanent()) { + MMOCore.plugin.getLogger().log(Level.WARNING, "Attempted to bind permanent skill " + skill.getSkill().getName() + " to player " + getUniqueId()); + return; + } + // Unbinds the previous skill (important for passive skills) unbindSkill(slot); final SkillSlot skillSlot = getProfess().getSkillSlot(slot); boundSkills.put(slot, new BoundSkillInfo(skillSlot, skill, this)); } - public void unbindSkill(int slot) { + @Nullable + public BoundSkillInfo unbindSkill(int slot) { final @Nullable BoundSkillInfo boundSkillInfo = boundSkills.remove(slot); if (boundSkillInfo != null) boundSkillInfo.close(); + return boundSkillInfo; } - public List getBoundSkills() { - return boundSkills.values().stream().map(BoundSkillInfo::getClassSkill).collect(Collectors.toList()); + @NotNull + public Map getBoundSkills() { + return boundSkills; + } + + /** + * @return If the player has at least one active skill bound + */ + public boolean hasActiveSkillBound() { + for (BoundSkillInfo bound : boundSkills.values()) + if (!bound.isPassive()) return true; + return false; } @NotNull diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java index 96bccd90..a34811cd 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java @@ -103,10 +103,9 @@ public class PlayerStats { // Updates the player's unbindable CLASS passive skills final PassiveSkillMap skillMap = data.getMMOPlayerData().getPassiveSkillMap(); - skillMap.removeModifiers("MMOCorePassiveSkillNotBound"); + skillMap.removeModifiers("MMOCorePermanentSkill"); for (ClassSkill skill : data.getProfess().getSkills()) - if (!skill.needsBound() - && skill.getSkill().getTrigger().isPassive() + if (skill.isPermanent() && skill.getSkill().getTrigger() != TriggerType.LOGIN && data.hasUnlocked(skill) && data.hasUnlockedLevel(skill)) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSkillTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSkillTrigger.java index 23d784a1..22f24b37 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSkillTrigger.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSkillTrigger.java @@ -23,14 +23,12 @@ public class UnlockSkillTrigger extends Trigger implements Removable { @Override public void apply(PlayerData playerData) { final @Nullable ClassSkill found = playerData.getProfess().getSkill(skill); - if (found != null) - playerData.unlock(found); + if (found != null) playerData.unlock(found); } @Override public void remove(PlayerData playerData) { final @Nullable ClassSkill found = playerData.getProfess().getSkill(skill); - if (found != null) - playerData.lock(found); + if (found != null) playerData.lock(found); } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSlotTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSlotTrigger.java index 7c96878d..1f923ada 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSlotTrigger.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSlotTrigger.java @@ -13,26 +13,23 @@ public class UnlockSlotTrigger extends Trigger implements Removable { public UnlockSlotTrigger(MMOLineConfig config) { super(config); + config.validateKeys("slot"); try { slot = Integer.parseInt(config.getString("slot")); - }catch(NumberFormatException e){ - throw new IllegalArgumentException("The slot should be a number"); + } catch (NumberFormatException exception) { + throw new IllegalArgumentException("Slot should be a number"); } Validate.isTrue(slot > 0, "Slot number must be positive"); } @Override public void apply(PlayerData player) { - final SkillSlot skillSlot = player.getProfess().getSkillSlot(slot); - if (!player.hasUnlocked(skillSlot)) - player.unlock(skillSlot); + player.unlock(player.getProfess().getSkillSlot(slot)); } @Override public void remove(PlayerData player) { - final SkillSlot skillSlot = player.getProfess().getSkillSlot(slot); - if (player.hasUnlocked(skillSlot)) - player.lock(skillSlot); + player.lock(player.getProfess().getSkillSlot(slot)); } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SkillCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SkillCommandTreeNode.java index f72221be..bf1464d0 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SkillCommandTreeNode.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SkillCommandTreeNode.java @@ -77,7 +77,7 @@ public class SkillCommandTreeNode extends CommandTreeNode { } int value = change.apply(playerData.getSkillLevel(skill), amount); playerData.setSkillLevel(skill, value); - CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.GOLD + player.getName() + ChatColor.YELLOW + CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.YELLOW + player.getName() + ChatColor.YELLOW + " is now level " + ChatColor.GOLD + value + ChatColor.YELLOW + " for " + skill.getName() + "."); return CommandResult.SUCCESS; } @@ -100,31 +100,31 @@ public class SkillCommandTreeNode extends CommandTreeNode { return CommandResult.THROW_USAGE; Player player = Bukkit.getPlayer(args[3]); if (player == null) { - sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + "."); + sender.sendMessage(ChatColor.RED + "Could not find player called " + args[3] + "."); return CommandResult.FAILURE; } PlayerData playerData = PlayerData.get(player); ClassSkill skill = playerData.getProfess().getSkill(args[4]); if (skill == null) { - sender.sendMessage(ChatColor.RED + "The player's class doesn't have a skill called " + args[4] + "."); + sender.sendMessage(ChatColor.RED + "Class doesn't have a skill called " + args[4] + "."); return CommandResult.FAILURE; } if (lock) { if (!playerData.hasUnlocked(skill)) { - CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.RED + "The skill " + skill.getSkill().getName() + " is already locked" + " for " + player.getName()); + CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.RED + "Skill " + skill.getSkill().getName() + " already locked for " + player.getName()); return CommandResult.SUCCESS; } playerData.lock(skill); } else { if (playerData.hasUnlocked(skill)) { - CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.RED + "The skill " + skill.getSkill().getName() + " is already unlocked" + " for " + player.getName()); + CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.RED + "Skill " + skill.getSkill().getName() + " already unlocked for " + player.getName()); return CommandResult.SUCCESS; } playerData.unlock(skill); } - CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.GOLD + "The skill " + skill.getSkill().getName() + " is now " + (lock ? "locked" : "unlocked" + " for " + player.getName())); + CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.YELLOW + "Skill " + ChatColor.GOLD + skill.getSkill().getName() + ChatColor.YELLOW + " now " + (lock ? "locked" : "unlocked") + " for " + ChatColor.GOLD + player.getName()); return CommandResult.SUCCESS; } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SlotCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SlotCommandTreeNode.java index 05e294bb..66f2c706 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SlotCommandTreeNode.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SlotCommandTreeNode.java @@ -4,6 +4,7 @@ import io.lumine.mythic.lib.command.api.CommandTreeNode; import io.lumine.mythic.lib.command.api.Parameter; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.skill.binding.BoundSkillInfo; import net.Indyuce.mmocore.skill.binding.SkillSlot; import net.Indyuce.mmocore.command.api.CommandVerbose; import net.Indyuce.mmocore.skill.ClassSkill; @@ -54,7 +55,7 @@ public class SlotCommandTreeNode extends CommandTreeNode { return CommandResult.FAILURE; } SkillSlot skillSlot = playerData.getProfess().getSkillSlot(slot); - if(skillSlot.isUnlockedByDefault()){ + if (skillSlot.isUnlockedByDefault()) { sender.sendMessage(ChatColor.RED + "You can't lock a skill that is unlocked by default."); return CommandResult.FAILURE; } @@ -72,7 +73,7 @@ public class SlotCommandTreeNode extends CommandTreeNode { } playerData.unlock(skillSlot); } - CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.GOLD + "The skill slot " + skillSlot.getName() + " is now " + (lock ? "locked" : "unlocked" + " for " + player.getName())); + CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.YELLOW + "The skill slot " + skillSlot.getName() + " is now " + (lock ? "locked" : "unlocked" + " for " + player.getName())); return CommandResult.SUCCESS; } } @@ -113,7 +114,7 @@ public class SlotCommandTreeNode extends CommandTreeNode { } playerData.bindSkill(slot, skill); - CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.GOLD + "The skill " + skill.getSkill().getHandler().getId() + " is now bound to the slot " + slot); + CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.YELLOW + "Skill " + ChatColor.GOLD + skill.getSkill().getHandler().getId() + ChatColor.YELLOW + " now bound to slot " + ChatColor.GOLD + slot); return CommandResult.SUCCESS; } } @@ -143,11 +144,10 @@ public class SlotCommandTreeNode extends CommandTreeNode { sender.sendMessage(ChatColor.RED + args[4] + " is not a valid number."); return CommandResult.FAILURE; } - String skill = playerData.hasSkillBound(slot) ? playerData.getBoundSkill(slot).getSkill().getHandler().getId() : "none"; - if (playerData.hasSkillBound(slot)) - playerData.unbindSkill(slot); - - CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.GOLD + "The skill " + skill + " has been unbounded from the slot " + slot); + final BoundSkillInfo found = playerData.unbindSkill(slot); + CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.YELLOW + (found != null ? + "Skill " + ChatColor.GOLD + found.getClassSkill().getSkill().getName() + ChatColor.YELLOW + " was taken off the slot " + ChatColor.GOLD + slot : + "Could not find skill at slot " + ChatColor.GOLD + slot)); return CommandResult.SUCCESS; } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java index 1e5dd779..8d6264fe 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java @@ -19,7 +19,7 @@ import java.util.*; public class ClassSkill implements CooldownObject, Unlockable { private final RegisteredSkill skill; private final int unlockLevel, maxSkillLevel; - private final boolean unlockedByDefault, needsBinding, upgradable; + private final boolean unlockedByDefault, permanent, upgradable; private final Map parameters = new HashMap<>(); public ClassSkill(RegisteredSkill skill, int unlockLevel, int maxSkillLevel) { @@ -48,7 +48,7 @@ public class ClassSkill implements CooldownObject, Unlockable { this.unlockLevel = unlockLevel; this.maxSkillLevel = maxSkillLevel; this.unlockedByDefault = unlockedByDefault; - this.needsBinding = needsBinding; + this.permanent = !needsBinding && skill.getTrigger().isPassive(); this.upgradable = upgradable; for (String param : skill.getHandler().getParameters()) this.parameters.put(param, skill.getParameterInfo(param)); @@ -59,7 +59,7 @@ public class ClassSkill implements CooldownObject, Unlockable { unlockLevel = config.getInt("level"); maxSkillLevel = config.getInt("max-level"); unlockedByDefault = config.getBoolean("unlocked-by-default", true); - needsBinding = config.getBoolean("needs-bound", MMOCore.plugin.configManager.passiveSkillsNeedBinding); + permanent = !config.getBoolean("needs-bound", MMOCore.plugin.configManager.passiveSkillsNeedBinding) && skill.getTrigger().isPassive(); upgradable = config.getBoolean("upgradable", true); for (String param : skill.getHandler().getParameters()) { LinearValue defaultValue = skill.getParameterInfo(param); @@ -93,8 +93,18 @@ public class ClassSkill implements CooldownObject, Unlockable { return unlockedByDefault; } + @Deprecated public boolean needsBound() { - return needsBinding; + return !isPermanent(); + } + + /** + * @return Permanent skills are passive skills which do + * not have to be bound in order to apply their effects. + * Permanent skills can only be passive skills. + */ + public boolean isPermanent() { + return permanent; } @Override @@ -104,20 +114,22 @@ public class ClassSkill implements CooldownObject, Unlockable { @Override public void whenLocked(PlayerData playerData) { - playerData.mapBoundSkills().forEach((slot, skill) -> { - if (skill.equalsIgnoreCase(getUnlockNamespacedKey().split(":")[1])) + + // Unbind the skill if necessary + new HashMap<>(playerData.getBoundSkills()).forEach((slot, bound) -> { + if (this.equals(bound.getClassSkill())) playerData.unbindSkill(slot); }); - // Update the stats to remove the passive skill if it is locked - if (!needsBinding && getSkill().getTrigger().isPassive()) - playerData.getStats().updateStats(); + // Update stats to flush permanent skill + if (isPermanent()) playerData.getStats().updateStats(); } @Override public void whenUnlocked(PlayerData playerData) { - if (!needsBinding && getSkill().getTrigger().isPassive()) - playerData.getStats().updateStats(); + + // Update stats to register permanent skill + if (isPermanent()) playerData.getStats().updateStats(); } @@ -138,7 +150,6 @@ public class ClassSkill implements CooldownObject, Unlockable { parameters.put(parameter, linear); } - /** * Skill modifiers are now called parameters. */ @@ -190,10 +201,10 @@ public class ClassSkill implements CooldownObject, Unlockable { * is called. It needs to be saved somewhere when trying to * unregister the passive skill from the skill map later on. */ + @NotNull public PassiveSkill toPassive(PlayerData caster) { Validate.isTrue(skill.getTrigger().isPassive(), "Skill is active"); - //MMOCorePassiveSkillNotBound to identify passive skills that don't need to be bound - return new PassiveSkill("MMOCorePassiveSkill" + (!needsBinding ? "NotBound" : ""), toCastable(caster), EquipmentSlot.OTHER, ModifierSource.OTHER); + return new PassiveSkill("MMOCore" + (permanent ? "Permanent" : "Passive") + "Skill", toCastable(caster), EquipmentSlot.OTHER, ModifierSource.OTHER); } @Override diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java index fc7d70b5..8e0448e5 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java @@ -33,7 +33,7 @@ public class BoundSkillInfo implements Closeable { if (skillModifierTrigger.getTargetSkills().contains(classSkill.getSkill().getHandler())) skillModifierTrigger.apply(playerData, classSkill.getSkill().getHandler()); - if (classSkill.getSkill().getTrigger().isPassive() && classSkill.needsBound()) { + if (classSkill.getSkill().getTrigger().isPassive() && !classSkill.isPermanent()) { registered = classSkill.toPassive(playerData); registered.register(playerData.getMMOPlayerData()); } else registered = null; @@ -64,7 +64,7 @@ public class BoundSkillInfo implements Closeable { open = false; // Unregister skill if passive - if (isPassive()&& classSkill.needsBound()) registered.unregister(playerData.getMMOPlayerData()); + if (registered != null) registered.unregister(playerData.getMMOPlayerData()); // Remove skill buffs associated to the slot skillSlot.getSkillModifierTriggers().forEach(skillBuffTrigger -> skillBuffTrigger.remove(playerData, classSkill.getSkill().getHandler())); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingInstance.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingInstance.java index 1ca66abb..d4938ab8 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingInstance.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/SkillCastingInstance.java @@ -1,7 +1,9 @@ package net.Indyuce.mmocore.skill.cast; +import io.lumine.mythic.lib.UtilityMethods; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.skill.binding.BoundSkillInfo; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.event.HandlerList; @@ -9,11 +11,20 @@ import org.bukkit.event.Listener; import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.NotNull; +import java.util.List; +import java.util.stream.Collectors; + public abstract class SkillCastingInstance extends BukkitRunnable implements Listener { private final PlayerData caster; private final SkillCastingHandler handler; - private final int runnablePeriod = 10; // Hard coded + private static final int RUNNABLE_PERIOD = 10; + + /** + * This variable temporarily stores the active skills that the player + * can try to cast. + */ + private List activeSkills; private boolean open = true; private int j, sinceLastActivity; @@ -45,11 +56,18 @@ public abstract class SkillCastingInstance extends BukkitRunnable implements Lis sinceLastActivity = 0; } + @NotNull + public List getActiveSkills() { + if (activeSkills == null) + activeSkills = caster.getBoundSkills().values().stream().filter(bound -> !bound.isPassive()).collect(Collectors.toList()); + return activeSkills; + } + private static final int PARTICLES_PER_TICK = 2; @Override public void run() { - if (!caster.isOnline() || caster.getPlayer().isDead() || caster.getBoundSkills().isEmpty()) { + if (UtilityMethods.isInvalidated(caster.getMMOPlayerData()) || !caster.hasActiveSkillBound()) { caster.leaveSkillCasting(true); return; } @@ -67,7 +85,10 @@ public abstract class SkillCastingInstance extends BukkitRunnable implements Lis } // Apply casting mode-specific effects - if (j++ % runnablePeriod == 0) onTick(); + if (j++ % RUNNABLE_PERIOD == 0) { + activeSkills = null; + onTick(); + } } public abstract void onTick(); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/KeyCombos.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/KeyCombos.java index 68d5b4d5..3f53bfc6 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/KeyCombos.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/KeyCombos.java @@ -74,7 +74,7 @@ public class KeyCombos extends SkillCastingHandler { if (player.getGameMode() == GameMode.CREATIVE && !MMOCore.plugin.configManager.canCreativeCast) return; // Don't start combos if no skills are bound - if (playerData.getBoundSkills().isEmpty()) return; + if (!playerData.hasActiveSkillBound()) return; // Start combo when there is an initializer key if (!event.getData().isCasting() && initializerKey != null) { diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/SkillBar.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/SkillBar.java index c2238b75..7195076e 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/SkillBar.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/SkillBar.java @@ -10,6 +10,7 @@ import net.Indyuce.mmocore.api.SoundEvent; import net.Indyuce.mmocore.api.event.PlayerKeyPressEvent; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.skill.ClassSkill; +import net.Indyuce.mmocore.skill.binding.BoundSkillInfo; import net.Indyuce.mmocore.skill.cast.PlayerKey; import net.Indyuce.mmocore.skill.cast.SkillCastingHandler; import net.Indyuce.mmocore.skill.cast.SkillCastingInstance; @@ -57,7 +58,10 @@ public class SkillBar extends SkillCastingHandler { // Enter spell casting final PlayerData playerData = event.getData(); - if (player.getGameMode() != GameMode.SPECTATOR && (MMOCore.plugin.configManager.canCreativeCast || player.getGameMode() != GameMode.CREATIVE) && !playerData.isCasting() && !playerData.getBoundSkills().isEmpty()) + if (player.getGameMode() != GameMode.SPECTATOR + && (MMOCore.plugin.configManager.canCreativeCast || player.getGameMode() != GameMode.CREATIVE) + && !playerData.isCasting() + && playerData.hasActiveSkillBound()) if (playerData.setSkillCasting()) MMOCore.plugin.soundManager.getSound(SoundEvent.SPELL_CAST_BEGIN).playTo(player); } @@ -92,16 +96,17 @@ public class SkillBar extends SkillCastingHandler { event.setCancelled(true); refreshTimeOut(); - final int slot = event.getNewSlot() + 1 + (event.getNewSlot() >= player.getInventory().getHeldItemSlot() ? -1 : 0); + final int activeSlot = event.getNewSlot() + (event.getNewSlot() >= player.getInventory().getHeldItemSlot() ? -1 : 0); /* * The event is called again soon after the first since when * cancelling the first one, the player held item slot must go back * to the previous one. */ - if (slot >= 1 && getCaster().hasSkillBound(slot)) { + if (activeSlot < getActiveSkills().size()) { + final ClassSkill classSkill = getActiveSkills().get(activeSlot).getClassSkill(); final PlayerMetadata caster = getCaster().getMMOPlayerData().getStatMap().cache(EquipmentSlot.MAIN_HAND); - getCaster().getBoundSkill(slot).toCastable(getCaster()).cast(new TriggerMetadata(caster, null, null)); + classSkill.toCastable(getCaster()).cast(new TriggerMetadata(caster, null, null)); } } @@ -121,18 +126,22 @@ public class SkillBar extends SkillCastingHandler { } } + @NotNull private String getFormat(PlayerData data) { final StringBuilder str = new StringBuilder(); if (!data.isOnline()) return str.toString(); - for (int slot : data.mapBoundSkills().keySet()) { - final ClassSkill skill = data.getBoundSkill(slot); - if (skill.getSkill().getTrigger().isPassive()) continue; - str.append(str.isEmpty() ? "" : split).append((onCooldown(data, skill) ? onCooldown.replace("{cooldown}", - String.valueOf(data.getCooldownMap().getInfo(skill).getRemaining() / 1000)) : noMana(data, skill) ? noMana : (noStamina( - data, skill) ? noStamina : ready)).replace("{index}", - String.valueOf(slot + (data.getPlayer().getInventory().getHeldItemSlot() < slot ? 1 : 0))) - .replace("{skill}", data.getBoundSkill(slot).getSkill().getName())); + int slot = 1; + for (BoundSkillInfo active : getActiveSkills()) { + final ClassSkill skill = active.getClassSkill(); + + str.append(str.isEmpty() ? "" : split).append( + (onCooldown(data, skill) ? onCooldown.replace("{cooldown}", + String.valueOf(data.getCooldownMap().getInfo(skill).getRemaining() / 1000)) : + noMana(data, skill) ? noMana : (noStamina(data, skill) ? noStamina : ready)) + .replace("{index}", String.valueOf(slot + (data.getPlayer().getInventory().getHeldItemSlot() < slot ? 1 : 0))) + .replace("{skill}", skill.getSkill().getName())); + slot++; } return MMOCore.plugin.placeholderParser.parse(data.getPlayer(), str.toString()); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/SkillScroller.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/SkillScroller.java index f589629e..d194fb8a 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/SkillScroller.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/handler/SkillScroller.java @@ -83,7 +83,7 @@ public class SkillScroller extends SkillCastingHandler { } // Check if there are skills bound - if (playerData.getBoundSkills().isEmpty()) return; + if (!playerData.hasActiveSkillBound()) return; // Cancel event if necessary if (event.getPressed().shouldCancelEvent()) event.setCancelled(true); @@ -120,7 +120,7 @@ public class SkillScroller extends SkillCastingHandler { } public ClassSkill getSelected() { - return getCaster().getBoundSkill(index + 1); + return getActiveSkills().get(index).getClassSkill(); } @EventHandler @@ -128,7 +128,7 @@ public class SkillScroller extends SkillCastingHandler { if (!event.getPlayer().equals(getCaster().getPlayer())) return; PlayerData playerData = PlayerData.get(event.getPlayer()); - if (playerData.getBoundSkills().isEmpty()) { + if (!playerData.hasActiveSkillBound()) { playerData.leaveSkillCasting(true); return; } @@ -139,9 +139,9 @@ public class SkillScroller extends SkillCastingHandler { final int dist1 = 9 + current - previous, dist2 = current - previous, dist3 = current - previous - 9; final int change = Math.abs(dist1) < Math.abs(dist2) ? (Math.abs(dist1) < Math.abs(dist3) ? dist1 : dist3) : (Math.abs(dist3) < Math.abs(dist2) ? dist3 : dist2); - // Scroll trough items + // Scroll through items final CustomSkillCastingInstance casting = (CustomSkillCastingInstance) playerData.getSkillCasting(); - casting.index = mod(casting.index + change, playerData.getBoundSkills().size()); + casting.index = mod(casting.index + change, getActiveSkills().size()); casting.onTick(); casting.refreshTimeOut();