Merge branch 'casting-events-enter-exit' into 'master'

Casting Enter/Exit Events!

Closes #857 and #860

See merge request phoenix-dvpmt/mmocore!27
This commit is contained in:
Guillaume 2023-06-25 08:24:00 +00:00
commit 6a1fb8473d
27 changed files with 304 additions and 153 deletions

View File

@ -0,0 +1,36 @@
package net.Indyuce.mmocore.api.event;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class PlayerEnterCastingModeEvent extends PlayerDataEvent implements Cancellable {
private static final HandlerList handlerList = new HandlerList();
private boolean cancelled = false;
public PlayerEnterCastingModeEvent(@NotNull Player who) {
super(PlayerData.get(who.getUniqueId()));
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
@NotNull
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
public static HandlerList getHandlerList(){
return handlerList;
}
}

View File

@ -0,0 +1,38 @@
package net.Indyuce.mmocore.api.event;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class PlayerExitCastingModeEvent extends PlayerDataEvent implements Cancellable {
private static final HandlerList handlerList = new HandlerList();
private boolean cancelled = false;
public PlayerExitCastingModeEvent(@NotNull Player who) {
super(PlayerData.get(who.getUniqueId()));
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
@NotNull
@Override
public HandlerList getHandlers() {
return handlerList;
}
public static HandlerList getHandlerList() {
return handlerList;
}
}

View File

@ -35,7 +35,7 @@ public class DefaultMMOLoader extends MMOLoader {
if (config.getKey().equals("levelup_skill")) if (config.getKey().equals("levelup_skill"))
return new LevelUpSkillTrigger(config); return new LevelUpSkillTrigger(config);
if (config.getKey().equals("skill_buff")) if (config.getKey().equals("skill_buff")||config.getKey().equals("skill_modifier"))
return new SkillModifierTrigger(config); return new SkillModifierTrigger(config);
if (config.getKey().equals("message")) if (config.getKey().equals("message"))

View File

@ -9,9 +9,7 @@ import io.lumine.mythic.lib.player.cooldown.CooldownMap;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigMessage; import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.api.SoundEvent; import net.Indyuce.mmocore.api.SoundEvent;
import net.Indyuce.mmocore.api.event.PlayerExperienceGainEvent; import net.Indyuce.mmocore.api.event.*;
import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent;
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
import net.Indyuce.mmocore.api.event.unlocking.ItemLockedEvent; import net.Indyuce.mmocore.api.event.unlocking.ItemLockedEvent;
import net.Indyuce.mmocore.api.event.unlocking.ItemUnlockedEvent; import net.Indyuce.mmocore.api.event.unlocking.ItemUnlockedEvent;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute; import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
@ -48,7 +46,7 @@ import net.Indyuce.mmocore.skill.binding.BoundSkillInfo;
import net.Indyuce.mmocore.skill.binding.SkillSlot; import net.Indyuce.mmocore.skill.binding.SkillSlot;
import net.Indyuce.mmocore.skill.cast.SkillCastingInstance; import net.Indyuce.mmocore.skill.cast.SkillCastingInstance;
import net.Indyuce.mmocore.skill.cast.SkillCastingMode; import net.Indyuce.mmocore.skill.cast.SkillCastingMode;
import net.Indyuce.mmocore.skilltree.NodeStatus; import net.Indyuce.mmocore.skilltree.SkillTreeStatus;
import net.Indyuce.mmocore.skilltree.SkillTreeNode; import net.Indyuce.mmocore.skilltree.SkillTreeNode;
import net.Indyuce.mmocore.skilltree.tree.SkillTree; import net.Indyuce.mmocore.skilltree.tree.SkillTree;
import net.Indyuce.mmocore.waypoint.Waypoint; import net.Indyuce.mmocore.waypoint.Waypoint;
@ -112,7 +110,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
/** /**
* Cached for easier access. Current status of each skill tree node. * Cached for easier access. Current status of each skill tree node.
*/ */
private final Map<SkillTreeNode, NodeStatus> nodeStates = new HashMap<>(); private final Map<SkillTreeNode, SkillTreeStatus> nodeStates = new HashMap<>();
private final Map<SkillTreeNode, Integer> nodeLevels = new HashMap<>(); private final Map<SkillTreeNode, Integer> nodeLevels = new HashMap<>();
private final Map<String, Integer> skillTreePoints = new HashMap<>(); private final Map<String, Integer> skillTreePoints = new HashMap<>();
@ -190,7 +188,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
// Stat triggers setup // Stat triggers setup
for (SkillTree skillTree : MMOCore.plugin.skillTreeManager.getAll()) for (SkillTree skillTree : MMOCore.plugin.skillTreeManager.getAll())
for (SkillTreeNode node : skillTree.getNodes()) for (SkillTreeNode node : skillTree.getNodes())
node.getExperienceTable().claimStatTriggers(this, node); node.getExperienceTable().claimRemovableTrigger(this, node);
} }
public int getPointSpent(SkillTree skillTree) { public int getPointSpent(SkillTree skillTree) {
@ -264,9 +262,9 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
} }
public boolean canIncrementNodeLevel(SkillTreeNode node) { public boolean canIncrementNodeLevel(SkillTreeNode node) {
NodeStatus nodeStatus = nodeStates.get(node); SkillTreeStatus skillTreeStatus = nodeStates.get(node);
//Check the State of the node //Check the State of the node
if (nodeStatus != NodeStatus.UNLOCKED && nodeStatus != NodeStatus.UNLOCKABLE) return false; if (skillTreeStatus != SkillTreeStatus.UNLOCKED && skillTreeStatus != SkillTreeStatus.UNLOCKABLE) return false;
return node.hasPermissionRequirement(this) && getNodeLevel(node) < node.getMaxLevel() && (skillTreePoints.getOrDefault(node.getTree().getId(), 0) + skillTreePoints.getOrDefault("global", 0) >= node.getSkillTreePointsConsumed()); return node.hasPermissionRequirement(this) && getNodeLevel(node) < node.getMaxLevel() && (skillTreePoints.getOrDefault(node.getTree().getId(), 0) + skillTreePoints.getOrDefault("global", 0) >= node.getSkillTreePointsConsumed());
} }
@ -280,7 +278,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
// Claims the nodes experience table. // Claims the nodes experience table.
node.getExperienceTable().claim(this, getNodeLevel(node), node); node.getExperienceTable().claim(this, getNodeLevel(node), node);
if (nodeStates.get(node) == NodeStatus.UNLOCKABLE) setNodeState(node, NodeStatus.UNLOCKED); if (nodeStates.get(node) == SkillTreeStatus.UNLOCKABLE) setNodeState(node, SkillTreeStatus.UNLOCKED);
int pointToWithdraw = node.getSkillTreePointsConsumed(); int pointToWithdraw = node.getSkillTreePointsConsumed();
if (skillTreePoints.get(node.getTree().getId()) > 0) { if (skillTreePoints.get(node.getTree().getId()) > 0) {
int pointWithdrawn = Math.min(pointToWithdraw, skillTreePoints.get(node.getTree().getId())); int pointWithdrawn = Math.min(pointToWithdraw, skillTreePoints.get(node.getTree().getId()));
@ -303,11 +301,11 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
skillTreePoints.put(treeId, skillTreePoints.get(treeId) - withdraw); skillTreePoints.put(treeId, skillTreePoints.get(treeId) - withdraw);
} }
public void setNodeState(SkillTreeNode node, NodeStatus nodeStatus) { public void setNodeState(SkillTreeNode node, SkillTreeStatus skillTreeStatus) {
nodeStates.put(node, nodeStatus); nodeStates.put(node, skillTreeStatus);
} }
public NodeStatus getNodeStatus(SkillTreeNode node) { public SkillTreeStatus getNodeStatus(SkillTreeNode node) {
return nodeStates.get(node); return nodeStates.get(node);
} }
@ -334,7 +332,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
skillTree.setupNodeStates(this); skillTree.setupNodeStates(this);
} }
public Map<SkillTreeNode, NodeStatus> getNodeStates() { public Map<SkillTreeNode, SkillTreeStatus> getNodeStates() {
return new HashMap<>(nodeStates); return new HashMap<>(nodeStates);
} }
@ -1005,9 +1003,21 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
return skillCasting != null; return skillCasting != null;
} }
public void setSkillCasting(@NotNull SkillCastingInstance skillCasting) { /**
* @return true if the PlayerEnterCastingModeEvent successfully put the player into casting mode, otherwise if the event is cancelled, returns false.
* @apiNote Changed to a boolean to reflect the cancellation state of the event being fired
*/
public boolean setSkillCasting(@NotNull SkillCastingInstance skillCasting) {
Validate.isTrue(!isCasting(), "Player already in casting mode"); Validate.isTrue(!isCasting(), "Player already in casting mode");
PlayerEnterCastingModeEvent event = new PlayerEnterCastingModeEvent(getPlayer());
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()){
skillCasting.close();
return false;
}
this.skillCasting = skillCasting; this.skillCasting = skillCasting;
return true;
} }
/** /**
@ -1023,11 +1033,33 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
return Objects.requireNonNull(skillCasting, "Player not in casting mode"); return Objects.requireNonNull(skillCasting, "Player not in casting mode");
} }
public void leaveSkillCasting() { /**
* API Method to leave casting mode and fire the PlayerExitCastingModeEvent
* @return true if the skill casting mode was left, or false if the event was cancelled, keeping the player in casting mode.
*/
public boolean leaveSkillCasting(){
return this.leaveSkillCasting(false);
}
/**
* @param skipEvent Skip Firing the PlayerExitCastingModeEvent
* @return true if the PlayerExitCastingModeEvent is not cancelled, or if the event is skipped.
*
*/
public boolean leaveSkillCasting(boolean skipEvent) {
Validate.isTrue(isCasting(), "Player not in casting mode"); Validate.isTrue(isCasting(), "Player not in casting mode");
if (!skipEvent) {
PlayerExitCastingModeEvent event = new PlayerExitCastingModeEvent(getPlayer());
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return false;
}
}
skillCasting.close(); skillCasting.close();
this.skillCasting = null; this.skillCasting = null;
setLastActivity(PlayerActivity.ACTION_BAR_MESSAGE, 0); // Reset action bar setLastActivity(PlayerActivity.ACTION_BAR_MESSAGE, 0); // Reset action bar
return true;
} }
public void displayActionBar(String message) { public void displayActionBar(String message) {

View File

@ -345,8 +345,8 @@ public class SavedClassInformation implements ClassDataContainer {
// We claim back the stats triggers for all the skill tree nodes of the new class. // We claim back the stats triggers for all the skill tree nodes of the new class.
for (SkillTree skillTree : profess.getSkillTrees()) for (SkillTree skillTree : profess.getSkillTrees())
for (SkillTreeNode node : skillTree.getNodes()) for (SkillTreeNode node : skillTree.getNodes())
node.getExperienceTable().claimStatTriggers(player, node); node.getExperienceTable().claimRemovableTrigger(player, node);
profess.getExperienceTable().claimStatTriggers(player, profess); profess.getExperienceTable().claimRemovableTrigger(player, profess);
// Unload current class information // Unload current class information
player.unloadClassInfo(profess); player.unloadClassInfo(profess);

View File

@ -103,14 +103,11 @@ public class PlayerStats {
*/ */
final PassiveSkillMap skillMap = data.getMMOPlayerData().getPassiveSkillMap(); final PassiveSkillMap skillMap = data.getMMOPlayerData().getPassiveSkillMap();
if (!MMOCore.plugin.configManager.passiveSkillNeedBound) { skillMap.removeModifiers("MMOCorePassiveSkillNotBound");
skillMap.removeModifiers("MMOCorePassiveSkill"); data.getProfess().getSkills()
data.getProfess().getSkills() .stream()
.stream() .filter((classSkill) -> !classSkill.needsBound()&&classSkill.getSkill().getTrigger().isPassive() && data.hasUnlocked(classSkill) && data.hasUnlockedLevel(classSkill))
.filter((classSkill) -> classSkill.getSkill().getTrigger().isPassive() && data.hasUnlocked(classSkill) && data.hasUnlockedLevel(classSkill)) .forEach(classSkill -> skillMap.addModifier(classSkill.toPassive(data)));
.forEach(classSkill -> skillMap.addModifier(classSkill.toPassive(data)));
}
// This updates the player's class SCRIPTS // This updates the player's class SCRIPTS
skillMap.removeModifiers("MMOCoreClassScript"); skillMap.removeModifiers("MMOCoreClassScript");

View File

@ -52,7 +52,7 @@ public class SkillModifierTrigger extends Trigger implements Removable {
} }
/** /**
* Used by skill slots to apply a skillBuff * Used by skill slots to apply a skill modifier.
* to a dynamically chosen skill handler. * to a dynamically chosen skill handler.
*/ */
public void apply(PlayerData playerData, SkillHandler<?> skill) { public void apply(PlayerData playerData, SkillHandler<?> skill) {

View File

@ -103,10 +103,10 @@ public class PlayerProfessions {
for (Profession profession : MMOCore.plugin.professionManager.getAll()) { for (Profession profession : MMOCore.plugin.professionManager.getAll()) {
if (profession.hasExperienceTable()) if (profession.hasExperienceTable())
profession.getExperienceTable().claimStatTriggers(playerData, profession); profession.getExperienceTable().claimRemovableTrigger(playerData, profession);
} }
if (playerData.getProfess().hasExperienceTable()) if (playerData.getProfess().hasExperienceTable())
playerData.getProfess().getExperienceTable().claimStatTriggers(playerData, playerData.getProfess()); playerData.getProfess().getExperienceTable().claimRemovableTrigger(playerData, playerData.getProfess());
} }

View File

@ -96,7 +96,7 @@ public class ExperienceItem {
* @param professionLevel The profession level the player just reached * @param professionLevel The profession level the player just reached
* @param timesCollected Amount of times the exp item has already been claimed by the player * @param timesCollected Amount of times the exp item has already been claimed by the player
* @return If the item should be claimed right now taking into * @return If the item should be claimed right now taking into
* account the randomness factor from the 'chance' parameter * account the randomness factor from the 'chance' parameter
*/ */
public boolean roll(int professionLevel, int timesCollected) { public boolean roll(int professionLevel, int timesCollected) {
@ -136,8 +136,8 @@ public class ExperienceItem {
* *
* @param playerData * @param playerData
*/ */
public void applyStatTriggers(PlayerData playerData) { public void applyRemovableTrigger(PlayerData playerData) {
for (Trigger trigger : triggers) for (Trigger trigger : triggers)
if (trigger instanceof StatTrigger statTrigger) statTrigger.apply(playerData); if (trigger instanceof Removable) trigger.apply(playerData);
} }
} }

View File

@ -80,16 +80,16 @@ public class ExperienceTable {
/** /**
* Called when a player joins and all the statTriggers are all triggered back * Called when a player joins and all the removable triggers get claimed back.
* *
* @param data PlayerData * @param data PlayerData
* @param object Either profession, skillTreeNode or class leveling up * @param object Either profession, skillTreeNode or class leveling up
*/ */
public void claimStatTriggers(PlayerData data, ExperienceObject object) { public void claimRemovableTrigger(PlayerData data, ExperienceObject object) {
for (ExperienceItem item : items) { for (ExperienceItem item : items) {
int timesClaimed = data.getClaims(object, this, item); int timesClaimed = data.getClaims(object, this, item);
for (int i = 0; i < timesClaimed; i++) for (int i = 0; i < timesClaimed; i++)
item.applyStatTriggers(data); item.applyRemovableTrigger(data);
} }
} }

View File

@ -1,7 +1,9 @@
package net.Indyuce.mmocore.gui.skilltree; package net.Indyuce.mmocore.gui.skilltree;
import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.UtilityMethods;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import java.util.logging.Level;
import net.Indyuce.mmocore.api.SoundEvent; import net.Indyuce.mmocore.api.SoundEvent;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.MMOCoreUtils; import net.Indyuce.mmocore.api.util.MMOCoreUtils;
@ -15,7 +17,6 @@ import net.Indyuce.mmocore.gui.skilltree.display.*;
import net.Indyuce.mmocore.skilltree.*; import net.Indyuce.mmocore.skilltree.*;
import net.Indyuce.mmocore.skilltree.tree.SkillTree; import net.Indyuce.mmocore.skilltree.tree.SkillTree;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
@ -32,6 +33,7 @@ import java.util.*;
public class SkillTreeViewer extends EditableInventory { public class SkillTreeViewer extends EditableInventory {
protected final Map<DisplayInfo, Icon> icons = new HashMap<>(); protected final Map<DisplayInfo, Icon> icons = new HashMap<>();
protected final Map<SkillTreeStatus, String> statusNames = new HashMap<>();
public SkillTreeViewer() { public SkillTreeViewer() {
super("skill-tree"); super("skill-tree");
@ -40,20 +42,24 @@ public class SkillTreeViewer extends EditableInventory {
@Override @Override
public void reload(FileConfiguration config) { public void reload(FileConfiguration config) {
super.reload(config); super.reload(config);
if (config.contains("status-names"))
for (SkillTreeStatus skillTreeStatus : SkillTreeStatus.values())
statusNames.put(skillTreeStatus, config.getString("status-names." + UtilityMethods.ymlName(skillTreeStatus.name()), skillTreeStatus.name()));
//Loads all the pathDisplayInfo //Loads all the pathDisplayInfo
for (PathStatus status : PathStatus.values()) for (PathStatus status : PathStatus.values())
for (PathType pathType : PathType.values()) { for (PathType pathType : PathType.values()) {
if (!config.contains("display.paths." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(pathType.name()))) { if (!config.contains("display.paths." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(pathType.name()))) {
MMOCore.log("Missing path type: " + MMOCoreUtils.ymlName(pathType.name()) + " for status: " + MMOCoreUtils.ymlName(status.name())); MMOCore.log(Level.WARNING, "An error occurred while loading skill tree GUI: Missing path type: " + MMOCoreUtils.ymlName(pathType.name()) + " for status: " + MMOCoreUtils.ymlName(status.name()));
continue; continue;
} }
icons.put(new PathDisplayInfo(pathType, status), new Icon(config.getConfigurationSection("display.paths." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(pathType.name())))); icons.put(new PathDisplayInfo(pathType, status), new Icon(config.getConfigurationSection("display.paths." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(pathType.name()))));
} }
//Loads all the nodeDisplayInfo //Loads all the nodeDisplayInfo
for (NodeStatus status : NodeStatus.values()) for (SkillTreeStatus status : SkillTreeStatus.values())
for (NodeType nodeType : NodeType.values()) { for (NodeType nodeType : NodeType.values()) {
if (!config.contains("display.nodes." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(nodeType.name()))) { if (!config.contains("display.nodes." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(nodeType.name()))) {
MMOCore.log("Missing node type: " + MMOCoreUtils.ymlName(nodeType.name()) + " for status: " + MMOCoreUtils.ymlName(status.name())); MMOCore.log(Level.WARNING, "An error occurred while loading skill tree GUI: Missing node type: " + MMOCoreUtils.ymlName(nodeType.name()) + " for status: " + MMOCoreUtils.ymlName(status.name()));
continue; continue;
} }
icons.put(new NodeDisplayInfo(nodeType, status), new Icon(config.getConfigurationSection("display.nodes." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(nodeType.name())))); icons.put(new NodeDisplayInfo(nodeType, status), new Icon(config.getConfigurationSection("display.nodes." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(nodeType.name()))));
@ -219,10 +225,10 @@ public class SkillTreeViewer extends EditableInventory {
if (inv.getSkillTree().isNode(coordinates)) { if (inv.getSkillTree().isNode(coordinates)) {
SkillTreeNode node = inv.getSkillTree().getNode(coordinates); SkillTreeNode node = inv.getSkillTree().getNode(coordinates);
List<String> lore = new ArrayList<>(); List<String> lore = new ArrayList<>();
Placeholders holders = getPlaceholders(inv, n);
getLore().forEach(str -> { getLore().forEach(str -> {
if (str.contains("{node-lore}")) { if (str.contains("{node-lore}")) {
lore.addAll(node.getLore(inv.getPlayerData())); node.getLore(inv.getPlayerData()).forEach(s -> lore.add(holders.apply(inv.getPlayer(), s)));
} else if (str.contains("{strong-parents}")) { } else if (str.contains("{strong-parents}")) {
lore.addAll(getParentsLore(inv, node, node.getParents(ParentType.STRONG))); lore.addAll(getParentsLore(inv, node, node.getParents(ParentType.STRONG)));
} else if (str.contains("{soft-parents}")) { } else if (str.contains("{soft-parents}")) {
@ -230,7 +236,7 @@ public class SkillTreeViewer extends EditableInventory {
} else if (str.contains("{incompatible-parents}")) { } else if (str.contains("{incompatible-parents}")) {
lore.addAll(getParentsLore(inv, node, node.getParents(ParentType.INCOMPATIBLE))); lore.addAll(getParentsLore(inv, node, node.getParents(ParentType.INCOMPATIBLE)));
} else } else
lore.add(getPlaceholders(inv, n).apply(inv.getPlayer(), str)); lore.add(holders.apply(inv.getPlayer(), str));
}); });
meta.setLore(lore); meta.setLore(lore);
meta.setDisplayName(node.getName()); meta.setDisplayName(node.getName());
@ -272,7 +278,8 @@ public class SkillTreeViewer extends EditableInventory {
if (inv.getSkillTree().isNode(inv.getCoordinates(n))) { if (inv.getSkillTree().isNode(inv.getCoordinates(n))) {
SkillTreeNode node = inv.getNode(n); SkillTreeNode node = inv.getNode(n);
holders.register("current-level", inv.getPlayerData().getNodeLevel(node)); holders.register("current-level", inv.getPlayerData().getNodeLevel(node));
holders.register("current-state", inv.getPlayerData().getNodeStatus(node)); SkillTreeStatus status = inv.getPlayerData().getNodeStatus(node);
holders.register("current-state", statusNames.getOrDefault(status, status.name()));
holders.register("max-level", node.getMaxLevel()); holders.register("max-level", node.getMaxLevel());
holders.register("max-children", node.getMaxChildren()); holders.register("max-children", node.getMaxChildren());
holders.register("size", node.getSize()); holders.register("size", node.getSize());
@ -347,18 +354,18 @@ public class SkillTreeViewer extends EditableInventory {
if (skillTree.isNode(coordinates)) { if (skillTree.isNode(coordinates)) {
SkillTreeNode node = skillTree.getNode(coordinates); SkillTreeNode node = skillTree.getNode(coordinates);
NodeStatus nodeStatus = playerData.getNodeStatus(node); SkillTreeStatus skillTreeStatus = playerData.getNodeStatus(node);
//If the node has its own display, it will be shown. //If the node has its own display, it will be shown.
if (node.hasIcon(nodeStatus)) if (node.hasIcon(skillTreeStatus))
return node.getIcon(nodeStatus); return node.getIcon(skillTreeStatus);
NodeType nodeType = NodeType.getNodeType(hasUpPathOrNode, hasRightPathOrNode, hasDownPathOrNode, hasLeftPathOrNode); NodeType nodeType = NodeType.getNodeType(hasUpPathOrNode, hasRightPathOrNode, hasDownPathOrNode, hasLeftPathOrNode);
DisplayInfo displayInfo = new NodeDisplayInfo(nodeType, nodeStatus); DisplayInfo displayInfo = new NodeDisplayInfo(nodeType, skillTreeStatus);
//Takes the display defined in the skill tree config if it exists. //Takes the display defined in the skill tree config if it exists.
if (skillTree.hasIcon(displayInfo)) if (skillTree.hasIcon(displayInfo))
return skillTree.getIcon(displayInfo); return skillTree.getIcon(displayInfo);
Icon icon = icons.get(displayInfo); Icon icon = icons.get(displayInfo);
Validate.notNull(icon, "The node " + node.getFullId() + " has no icon for the type " + nodeType + " and the status " + nodeStatus); Validate.notNull(icon, "The node " + node.getFullId() + " has no icon for the type " + nodeType + " and the status " + skillTreeStatus);
return icon; return icon;
} else { } else {
PathType pathType = PathType.getPathType(hasUpPathOrNode, hasRightPathOrNode, hasDownPathOrNode, hasLeftPathOrNode); PathType pathType = PathType.getPathType(hasUpPathOrNode, hasRightPathOrNode, hasDownPathOrNode, hasLeftPathOrNode);
@ -486,7 +493,7 @@ public class SkillTreeViewer extends EditableInventory {
MMOCore.plugin.configManager.getSimpleMessage("upgrade-skill-node", "skill-node", node.getName(), "level", "" + playerData.getNodeLevel(node)).send(player); MMOCore.plugin.configManager.getSimpleMessage("upgrade-skill-node", "skill-node", node.getName(), "level", "" + playerData.getNodeLevel(node)).send(player);
MMOCore.plugin.soundManager.getSound(SoundEvent.LEVEL_UP).playTo(getPlayer()); MMOCore.plugin.soundManager.getSound(SoundEvent.LEVEL_UP).playTo(getPlayer());
open(); open();
} else if (playerData.getNodeStatus(node) == NodeStatus.LOCKED || playerData.getNodeStatus(node) == NodeStatus.FULLY_LOCKED) { } else if (playerData.getNodeStatus(node) == SkillTreeStatus.LOCKED || playerData.getNodeStatus(node) == SkillTreeStatus.FULLY_LOCKED) {
MMOCore.plugin.configManager.getSimpleMessage("locked-node").send(player); MMOCore.plugin.configManager.getSimpleMessage("locked-node").send(player);
MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer()); MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer());

View File

@ -1,25 +1,25 @@
package net.Indyuce.mmocore.gui.skilltree.display; package net.Indyuce.mmocore.gui.skilltree.display;
import net.Indyuce.mmocore.skilltree.NodeStatus; import net.Indyuce.mmocore.skilltree.SkillTreeStatus;
import java.util.Objects; import java.util.Objects;
public class NodeDisplayInfo implements DisplayInfo{ public class NodeDisplayInfo implements DisplayInfo{
private NodeStatus nodeStatus; private SkillTreeStatus skillTreeStatus;
private NodeType nodeType; private NodeType nodeType;
public NodeDisplayInfo(NodeType nodeType,NodeStatus nodeStatus) { public NodeDisplayInfo(NodeType nodeType, SkillTreeStatus skillTreeStatus) {
this.nodeStatus = nodeStatus; this.skillTreeStatus = skillTreeStatus;
this.nodeType = nodeType; this.nodeType = nodeType;
} }
public NodeStatus getNodeState() { public SkillTreeStatus getNodeState() {
return nodeStatus; return skillTreeStatus;
} }
public NodeStatus getNodeStatus() { public SkillTreeStatus getNodeStatus() {
return nodeStatus; return skillTreeStatus;
} }
public NodeType getNodeType() { public NodeType getNodeType() {
@ -31,18 +31,18 @@ public class NodeDisplayInfo implements DisplayInfo{
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
NodeDisplayInfo that = (NodeDisplayInfo) o; NodeDisplayInfo that = (NodeDisplayInfo) o;
return nodeStatus == that.nodeStatus && nodeType == that.nodeType; return skillTreeStatus == that.skillTreeStatus && nodeType == that.nodeType;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(nodeStatus, nodeType); return Objects.hash(skillTreeStatus, nodeType);
} }
@Override @Override
public String toString() { public String toString() {
return "NodeDisplayInfo{" + return "NodeDisplayInfo{" +
"nodeStatus=" + nodeStatus + "nodeStatus=" + skillTreeStatus +
", nodeType=" + nodeType + ", nodeType=" + nodeType +
'}'; '}';
} }

View File

@ -17,7 +17,7 @@ public class KingdomsXGuildModule implements GuildModule {
@Override @Override
public AbstractGuild getGuild(PlayerData playerData) { public AbstractGuild getGuild(PlayerData playerData) {
KingdomPlayer kPlayer = Kingdoms.get().getDataHandlers().getKingdomPlayerManager().getData(playerData.getUniqueId()); KingdomPlayer kPlayer = KingdomPlayer.getKingdomPlayer(playerData.getPlayer());
if (kPlayer == null) if (kPlayer == null)
return null; return null;
@ -28,7 +28,7 @@ public class KingdomsXGuildModule implements GuildModule {
@Override @Override
public Relationship getRelationship(Player player, Player target) { public Relationship getRelationship(Player player, Player target) {
final KingdomPlayer player1 = Kingdoms.get().getDataHandlers().getKingdomPlayerManager().getData(player.getUniqueId()); final KingdomPlayer player1 = KingdomPlayer.getKingdomPlayer(player);
if (player1 == null) if (player1 == null)
return Relationship.GUILD_NEUTRAL; return Relationship.GUILD_NEUTRAL;
@ -36,7 +36,7 @@ public class KingdomsXGuildModule implements GuildModule {
if (kingdom1 == null) if (kingdom1 == null)
return Relationship.GUILD_NEUTRAL; return Relationship.GUILD_NEUTRAL;
final KingdomPlayer player2 = Kingdoms.get().getDataHandlers().getKingdomPlayerManager().getData(target.getUniqueId()); final KingdomPlayer player2 = KingdomPlayer.getKingdomPlayer(target.getPlayer());
if (player2 == null) if (player2 == null)
return Relationship.GUILD_NEUTRAL; return Relationship.GUILD_NEUTRAL;

View File

@ -11,55 +11,63 @@ import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public class FishingDropItem implements Weighted { public class FishingDropItem implements Weighted {
private final RandomAmount experience, tugs; private final RandomAmount experience, tugs, vanillaExp;
private final DropItem dropItem; private final DropItem dropItem;
public FishingDropItem(MMOLineConfig config) { public FishingDropItem(MMOLineConfig config) {
config.validateKeys("tugs", "experience"); config.validateKeys("tugs", "experience");
tugs = new RandomAmount(config.getString("tugs")); tugs = new RandomAmount(config.getString("tugs"));
experience = new RandomAmount(config.getString("experience")); experience = new RandomAmount(config.getString("experience"));
vanillaExp = config.contains("vanilla-exp") ? new RandomAmount(config.getString("vanilla-experience")) : new RandomAmount(0, 0);
dropItem = MMOCore.plugin.loadManager.loadDropItem(config);
}
dropItem = MMOCore.plugin.loadManager.loadDropItem(config); /**
} * An item cannot have a negative weight. Since drop items have 0 weight
* by default, MMOCore takes 1 as minimum value if the item weight is
* negative or equal to 0
*/
@Override
public double getWeight() {
return dropItem.getWeight() <= 0 ? 1 : dropItem.getWeight();
}
/** public DropItem getItem() {
* An item cannot have a negative weight. Since drop items have 0 weight return dropItem;
* by default, MMOCore takes 1 as minimum value if the item weight is }
* negative or equal to 0
*/
@Override
public double getWeight() {
return dropItem.getWeight() <= 0 ? 1 : dropItem.getWeight();
}
public DropItem getItem() { public RandomAmount getExperience() {
return dropItem; return experience;
} }
public RandomAmount getExperience() { public RandomAmount getVanillaExp() {
return experience; return vanillaExp;
} }
public RandomAmount getTugs() { public RandomAmount getTugs() {
return tugs; return tugs;
} }
public int rollExperience() { public int rollExperience() {
return experience.calculateInt(); return experience.calculateInt();
} }
public int rollTugs() { public int rollVanillaExp() {
return tugs.calculateInt(); return vanillaExp.calculateInt();
} }
public DropItem getDropItem() { public int rollTugs() {
return dropItem; return tugs.calculateInt();
} }
@Nullable public DropItem getDropItem() {
public ItemStack collect(LootBuilder builder) { return dropItem;
dropItem.collect(builder); }
return builder.getLoot().stream().findAny().orElse(null);
} @Nullable
public ItemStack collect(LootBuilder builder) {
dropItem.collect(builder);
return builder.getLoot().stream().findAny().orElse(null);
}
} }

View File

@ -20,7 +20,7 @@ import java.util.*;
public class ClassSkill implements CooldownObject, Unlockable { public class ClassSkill implements CooldownObject, Unlockable {
private final RegisteredSkill skill; private final RegisteredSkill skill;
private final int unlockLevel, maxSkillLevel; private final int unlockLevel, maxSkillLevel;
private final boolean unlockedByDefault; private final boolean unlockedByDefault, needsBound;
private final Map<String, LinearValue> parameters = new HashMap<>(); private final Map<String, LinearValue> parameters = new HashMap<>();
/** /**
@ -37,10 +37,15 @@ public class ClassSkill implements CooldownObject, Unlockable {
} }
public ClassSkill(RegisteredSkill skill, int unlockLevel, int maxSkillLevel, boolean unlockedByDefault) { public ClassSkill(RegisteredSkill skill, int unlockLevel, int maxSkillLevel, boolean unlockedByDefault) {
this(skill, unlockLevel, maxSkillLevel, unlockedByDefault, MMOCore.plugin.configManager.passiveSkillNeedBound);
}
public ClassSkill(RegisteredSkill skill, int unlockLevel, int maxSkillLevel, boolean unlockedByDefault, boolean needsBound) {
this.skill = skill; this.skill = skill;
this.unlockLevel = unlockLevel; this.unlockLevel = unlockLevel;
this.maxSkillLevel = maxSkillLevel; this.maxSkillLevel = maxSkillLevel;
this.unlockedByDefault = unlockedByDefault; this.unlockedByDefault = unlockedByDefault;
this.needsBound = needsBound;
for (String param : skill.getHandler().getParameters()) for (String param : skill.getHandler().getParameters())
this.parameters.put(param, skill.getParameterInfo(param)); this.parameters.put(param, skill.getParameterInfo(param));
} }
@ -50,6 +55,7 @@ public class ClassSkill implements CooldownObject, Unlockable {
unlockLevel = config.getInt("level"); unlockLevel = config.getInt("level");
maxSkillLevel = config.getInt("max-level"); maxSkillLevel = config.getInt("max-level");
unlockedByDefault = config.getBoolean("unlocked-by-default", true); unlockedByDefault = config.getBoolean("unlocked-by-default", true);
needsBound = config.getBoolean("needs-bound", MMOCore.plugin.configManager.passiveSkillNeedBound);
for (String param : skill.getHandler().getParameters()) { for (String param : skill.getHandler().getParameters()) {
LinearValue defaultValue = skill.getParameterInfo(param); LinearValue defaultValue = skill.getParameterInfo(param);
this.parameters.put(param, config.isConfigurationSection(param) ? readLinearValue(defaultValue, config.getConfigurationSection(param)) : defaultValue); this.parameters.put(param, config.isConfigurationSection(param) ? readLinearValue(defaultValue, config.getConfigurationSection(param)) : defaultValue);
@ -78,6 +84,10 @@ public class ClassSkill implements CooldownObject, Unlockable {
return unlockedByDefault; return unlockedByDefault;
} }
public boolean needsBound() {
return needsBound;
}
@Override @Override
public String getUnlockNamespacedKey() { public String getUnlockNamespacedKey() {
return "skill:" + skill.getHandler().getId().toLowerCase(); return "skill:" + skill.getHandler().getId().toLowerCase();
@ -90,18 +100,17 @@ public class ClassSkill implements CooldownObject, Unlockable {
playerData.unbindSkill(slot); playerData.unbindSkill(slot);
}); });
//Update the stats to remove the passive skill if it is locked //Update the stats to remove the passive skill if it is locked
if (!MMOCore.plugin.configManager.passiveSkillNeedBound && getSkill().getTrigger().isPassive()) if (!needsBound && getSkill().getTrigger().isPassive())
playerData.getStats().updateStats(); playerData.getStats().updateStats();
} }
@Override @Override
public void whenUnlocked(PlayerData playerData) { public void whenUnlocked(PlayerData playerData) {
if (!MMOCore.plugin.configManager.passiveSkillNeedBound && getSkill().getTrigger().isPassive()) if (!needsBound && getSkill().getTrigger().isPassive())
playerData.getStats().updateStats(); playerData.getStats().updateStats();
} }
/** /**
* Skill modifiers are now called parameters. * Skill modifiers are now called parameters.
*/ */
@ -109,6 +118,7 @@ public class ClassSkill implements CooldownObject, Unlockable {
public void addModifier(String modifier, LinearValue linear) { public void addModifier(String modifier, LinearValue linear) {
addParameter(modifier, linear); addParameter(modifier, linear);
} }
/** /**
* This method can only override default parameters and * This method can only override default parameters and
* will throw an error when trying to define non existing modifiers * will throw an error when trying to define non existing modifiers
@ -165,7 +175,8 @@ public class ClassSkill implements CooldownObject, Unlockable {
*/ */
public PassiveSkill toPassive(PlayerData caster) { public PassiveSkill toPassive(PlayerData caster) {
Validate.isTrue(skill.getTrigger().isPassive(), "Skill is active"); Validate.isTrue(skill.getTrigger().isPassive(), "Skill is active");
return new PassiveSkill("MMOCorePassiveSkill", toCastable(caster), EquipmentSlot.OTHER, ModifierSource.OTHER); //MMOCorePassiveSkillNotBound to identify passive skills that don't need to be bound
return new PassiveSkill("MMOCorePassiveSkill" + (!needsBound ? "NotBound" : ""), toCastable(caster), EquipmentSlot.OTHER, ModifierSource.OTHER);
} }
@Override @Override

View File

@ -29,11 +29,11 @@ public class BoundSkillInfo implements Closable {
this.playerData = playerData; this.playerData = playerData;
// Apply skill buffs associated to the slot // Apply skill buffs associated to the slot
for (SkillModifierTrigger skillBuffTrigger : skillSlot.getSkillBuffTriggers()) for (SkillModifierTrigger skillModifierTrigger : skillSlot.getSkillModifierTriggers())
if (skillBuffTrigger.getTargetSkills().contains(classSkill.getSkill().getHandler())) if (skillModifierTrigger.getTargetSkills().contains(classSkill.getSkill().getHandler()))
skillBuffTrigger.apply(playerData, classSkill.getSkill().getHandler()); skillModifierTrigger.apply(playerData, classSkill.getSkill().getHandler());
if (classSkill.getSkill().getTrigger().isPassive()) { if (classSkill.getSkill().getTrigger().isPassive()&& classSkill.needsBound()) {
registered = classSkill.toPassive(playerData); registered = classSkill.toPassive(playerData);
registered.register(playerData.getMMOPlayerData()); registered.register(playerData.getMMOPlayerData());
} else registered = null; } else registered = null;
@ -64,9 +64,9 @@ public class BoundSkillInfo implements Closable {
open = false; open = false;
// Unregister skill if passive // Unregister skill if passive
if (isPassive()) registered.unregister(playerData.getMMOPlayerData()); if (isPassive()&& classSkill.needsBound()) registered.unregister(playerData.getMMOPlayerData());
// Remove skill buffs associated to the slot // Remove skill buffs associated to the slot
skillSlot.getSkillBuffTriggers().forEach(skillBuffTrigger -> skillBuffTrigger.remove(playerData, classSkill.getSkill().getHandler())); skillSlot.getSkillModifierTriggers().forEach(skillBuffTrigger -> skillBuffTrigger.remove(playerData, classSkill.getSkill().getHandler()));
} }
} }

View File

@ -22,10 +22,10 @@ public class SkillSlot implements Unlockable {
private final boolean isUnlockedByDefault; private final boolean isUnlockedByDefault;
private final boolean canManuallyBind; private final boolean canManuallyBind;
private final List<SkillModifierTrigger> skillBuffTriggers = new ArrayList<>(); private final List<SkillModifierTrigger> skillModifierTriggers = new ArrayList<>();
private final Material item; private final Material item;
public SkillSlot(int slot, int modelData, String formula, String name, List<String> lore, boolean isUnlockedByDefault, boolean canManuallyBind, List<SkillModifierTrigger> skillBuffTriggers) { public SkillSlot(int slot, int modelData, String formula, String name, List<String> lore, boolean isUnlockedByDefault, boolean canManuallyBind, List<SkillModifierTrigger> skillModifierTriggers) {
this.slot = slot; this.slot = slot;
this.modelData = modelData; this.modelData = modelData;
this.formula = formula; this.formula = formula;
@ -34,7 +34,7 @@ public class SkillSlot implements Unlockable {
this.item = null; this.item = null;
this.canManuallyBind = canManuallyBind; this.canManuallyBind = canManuallyBind;
this.isUnlockedByDefault = isUnlockedByDefault; this.isUnlockedByDefault = isUnlockedByDefault;
this.skillBuffTriggers.addAll(skillBuffTriggers); this.skillModifierTriggers.addAll(skillModifierTriggers);
} }
public SkillSlot(ConfigurationSection section) { public SkillSlot(ConfigurationSection section) {
@ -49,7 +49,7 @@ public class SkillSlot implements Unlockable {
if (section.contains("skill-buffs")) if (section.contains("skill-buffs"))
for (String skillBuff : section.getStringList("skill-buffs")) for (String skillBuff : section.getStringList("skill-buffs"))
if (skillBuff.startsWith("skill_buff")) if (skillBuff.startsWith("skill_buff"))
skillBuffTriggers.add((SkillModifierTrigger) MMOCore.plugin.loadManager.loadTrigger(new MMOLineConfig(skillBuff))); skillModifierTriggers.add((SkillModifierTrigger) MMOCore.plugin.loadManager.loadTrigger(new MMOLineConfig(skillBuff)));
} }
public int getSlot() { public int getSlot() {
@ -81,8 +81,8 @@ public class SkillSlot implements Unlockable {
return isUnlockedByDefault; return isUnlockedByDefault;
} }
public List<SkillModifierTrigger> getSkillBuffTriggers() { public List<SkillModifierTrigger> getSkillModifierTriggers() {
return skillBuffTriggers; return skillModifierTriggers;
} }
public boolean canManuallyBind() { public boolean canManuallyBind() {

View File

@ -12,6 +12,7 @@ import net.Indyuce.mmocore.api.event.PlayerKeyPressEvent;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.gui.api.item.Placeholders; import net.Indyuce.mmocore.gui.api.item.Placeholders;
import net.Indyuce.mmocore.skill.cast.*; import net.Indyuce.mmocore.skill.cast.*;
import org.bukkit.GameMode;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@ -70,6 +71,8 @@ public class KeyCombos implements SkillCastingListener {
public void whenPressingKey(PlayerKeyPressEvent event) { public void whenPressingKey(PlayerKeyPressEvent event) {
PlayerData playerData = event.getData(); PlayerData playerData = event.getData();
Player player = playerData.getPlayer(); Player player = playerData.getPlayer();
if (player.getGameMode() == GameMode.CREATIVE && !MMOCore.plugin.configManager.canCreativeCast)
return;
// Start combo when there is an initializer key // Start combo when there is an initializer key
if (!event.getData().isCasting() && initializerKey != null) { if (!event.getData().isCasting() && initializerKey != null) {
@ -79,8 +82,9 @@ public class KeyCombos implements SkillCastingListener {
if (event.getPressed().shouldCancelEvent()) event.setCancelled(true); if (event.getPressed().shouldCancelEvent()) event.setCancelled(true);
// Start combo // Start combo
playerData.setSkillCasting(new CustomSkillCastingInstance(playerData)); if (playerData.setSkillCasting(new CustomSkillCastingInstance(playerData)) && beginComboSound != null)
if (beginComboSound != null) beginComboSound.playTo(player); beginComboSound.playTo(player);
} }
return; return;
} }
@ -95,8 +99,8 @@ public class KeyCombos implements SkillCastingListener {
final @NotNull ComboMap comboMap = Objects.requireNonNullElse(playerData.getProfess().getComboMap(), this.comboMap); final @NotNull ComboMap comboMap = Objects.requireNonNullElse(playerData.getProfess().getComboMap(), this.comboMap);
if (comboMap.isComboStart(event.getPressed())) { if (comboMap.isComboStart(event.getPressed())) {
casting = new CustomSkillCastingInstance(playerData); casting = new CustomSkillCastingInstance(playerData);
playerData.setSkillCasting(casting); if (playerData.setSkillCasting(new CustomSkillCastingInstance(playerData)) && beginComboSound != null)
if (beginComboSound != null) beginComboSound.playTo(player); beginComboSound.playTo(player);
} }
} }

View File

@ -56,8 +56,9 @@ public class SkillBar implements SkillCastingListener {
// Enter spell casting // Enter spell casting
final PlayerData playerData = event.getData(); 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.getBoundSkills().isEmpty()) {
playerData.setSkillCasting(new CustomSkillCastingInstance(playerData)); if (playerData.setSkillCasting(new CustomSkillCastingInstance(playerData))) {
MMOCore.plugin.soundManager.getSound(SoundEvent.SPELL_CAST_BEGIN).playTo(player); MMOCore.plugin.soundManager.getSound(SoundEvent.SPELL_CAST_BEGIN).playTo(player);
}
} }
} }

View File

@ -4,6 +4,7 @@ import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.player.EquipmentSlot; import io.lumine.mythic.lib.api.player.EquipmentSlot;
import io.lumine.mythic.lib.player.PlayerMetadata; import io.lumine.mythic.lib.player.PlayerMetadata;
import io.lumine.mythic.lib.skill.trigger.TriggerMetadata; import io.lumine.mythic.lib.skill.trigger.TriggerMetadata;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.SoundObject; import net.Indyuce.mmocore.api.SoundObject;
import net.Indyuce.mmocore.api.event.PlayerKeyPressEvent; import net.Indyuce.mmocore.api.event.PlayerKeyPressEvent;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
@ -11,6 +12,7 @@ import net.Indyuce.mmocore.skill.cast.PlayerKey;
import net.Indyuce.mmocore.skill.cast.SkillCastingInstance; import net.Indyuce.mmocore.skill.cast.SkillCastingInstance;
import net.Indyuce.mmocore.skill.cast.SkillCastingListener; import net.Indyuce.mmocore.skill.cast.SkillCastingListener;
import net.Indyuce.mmocore.skill.cast.SkillCastingMode; import net.Indyuce.mmocore.skill.cast.SkillCastingMode;
import org.bukkit.GameMode;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@ -56,7 +58,8 @@ public class SkillScroller implements SkillCastingListener {
public void whenPressingKey(PlayerKeyPressEvent event) { public void whenPressingKey(PlayerKeyPressEvent event) {
PlayerData playerData = event.getData(); PlayerData playerData = event.getData();
Player player = playerData.getPlayer(); Player player = playerData.getPlayer();
if (player.getGameMode() == GameMode.CREATIVE && !MMOCore.plugin.configManager.canCreativeCast)
return;
if (event.getPressed() == enterKey) { if (event.getPressed() == enterKey) {
// Leave casting mode // Leave casting mode
@ -77,7 +80,10 @@ public class SkillScroller implements SkillCastingListener {
if (event.getPressed().shouldCancelEvent()) event.setCancelled(true); if (event.getPressed().shouldCancelEvent()) event.setCancelled(true);
// Enter casting mode // Enter casting mode
playerData.setSkillCasting(new CustomSkillCastingInstance(playerData)); if (!playerData.setSkillCasting(new CustomSkillCastingInstance(playerData))) {
return;
}
if (enterSound != null) enterSound.playTo(player); if (enterSound != null) enterSound.playTo(player);
} }

View File

@ -9,12 +9,10 @@ import net.Indyuce.mmocore.experience.ExpCurve;
import net.Indyuce.mmocore.experience.ExperienceObject; import net.Indyuce.mmocore.experience.ExperienceObject;
import net.Indyuce.mmocore.experience.droptable.ExperienceTable; import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
import net.Indyuce.mmocore.gui.api.item.Placeholders; import net.Indyuce.mmocore.gui.api.item.Placeholders;
import net.Indyuce.mmocore.gui.skilltree.SkillTreeViewer;
import net.Indyuce.mmocore.gui.skilltree.display.Icon; import net.Indyuce.mmocore.gui.skilltree.display.Icon;
import net.Indyuce.mmocore.skilltree.tree.ParentInformation; import net.Indyuce.mmocore.skilltree.tree.ParentInformation;
import net.Indyuce.mmocore.skilltree.tree.SkillTree; import net.Indyuce.mmocore.skilltree.tree.SkillTree;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -30,7 +28,7 @@ public class SkillTreeNode implements ExperienceObject {
private String permissionRequired; private String permissionRequired;
private final Map<NodeStatus, Icon> icons = new HashMap<>(); private final Map<SkillTreeStatus, Icon> icons = new HashMap<>();
private IntegerCoordinates coordinates; private IntegerCoordinates coordinates;
/** /**
@ -68,7 +66,7 @@ public class SkillTreeNode implements ExperienceObject {
this.id = config.getName(); this.id = config.getName();
this.tree = tree; this.tree = tree;
if (config.isConfigurationSection("display")) { if (config.isConfigurationSection("display")) {
for (NodeStatus status : NodeStatus.values()) { for (SkillTreeStatus status : SkillTreeStatus.values()) {
String ymlStatus = MMOCoreUtils.ymlName(status.name()); String ymlStatus = MMOCoreUtils.ymlName(status.name());
if (!config.isConfigurationSection("display." + ymlStatus)) { if (!config.isConfigurationSection("display." + ymlStatus)) {
MMOCore.log("Could not find node display for status " + ymlStatus + " for node " + id + " in tree " + tree.getId() + ". Using default display."); MMOCore.log("Could not find node display for status " + ymlStatus + " for node " + id + " in tree " + tree.getId() + ". Using default display.");
@ -105,11 +103,11 @@ public class SkillTreeNode implements ExperienceObject {
return tree; return tree;
} }
public boolean hasIcon(NodeStatus status) { public boolean hasIcon(SkillTreeStatus status) {
return icons.containsKey(status); return icons.containsKey(status);
} }
public Icon getIcon(NodeStatus status) { public Icon getIcon(SkillTreeStatus status) {
return icons.get(status); return icons.get(status);
} }

View File

@ -7,13 +7,13 @@ import net.Indyuce.mmocore.skilltree.tree.SkillTree;
public record SkillTreePath(SkillTree tree, IntegerCoordinates coordinates, SkillTreeNode from, SkillTreeNode to) { public record SkillTreePath(SkillTree tree, IntegerCoordinates coordinates, SkillTreeNode from, SkillTreeNode to) {
public PathStatus getStatus(PlayerData playerData) { public PathStatus getStatus(PlayerData playerData) {
NodeStatus fromStatus = playerData.getNodeStatus(from); SkillTreeStatus fromStatus = playerData.getNodeStatus(from);
NodeStatus toStatus = playerData.getNodeStatus(to); SkillTreeStatus toStatus = playerData.getNodeStatus(to);
if (fromStatus == NodeStatus.UNLOCKED && toStatus == NodeStatus.UNLOCKED) if (fromStatus == SkillTreeStatus.UNLOCKED && toStatus == SkillTreeStatus.UNLOCKED)
return PathStatus.UNLOCKED; return PathStatus.UNLOCKED;
if ((fromStatus == NodeStatus.UNLOCKABLE && toStatus == NodeStatus.LOCKED) || (fromStatus == NodeStatus.LOCKED && toStatus == NodeStatus.UNLOCKABLE)) if ((fromStatus == SkillTreeStatus.UNLOCKABLE && toStatus == SkillTreeStatus.LOCKED) || (fromStatus == SkillTreeStatus.LOCKED && toStatus == SkillTreeStatus.UNLOCKABLE))
return PathStatus.UNLOCKABLE; return PathStatus.UNLOCKABLE;
if (fromStatus == NodeStatus.FULLY_LOCKED || toStatus == NodeStatus.FULLY_LOCKED) if (fromStatus == SkillTreeStatus.FULLY_LOCKED || toStatus == SkillTreeStatus.FULLY_LOCKED)
return PathStatus.FULLY_LOCKED; return PathStatus.FULLY_LOCKED;
return PathStatus.LOCKED; return PathStatus.LOCKED;
} }

View File

@ -1,6 +1,6 @@
package net.Indyuce.mmocore.skilltree; package net.Indyuce.mmocore.skilltree;
public enum NodeStatus { public enum SkillTreeStatus {
/** /**
* The player does not have access to this skill tree node just yet. * The player does not have access to this skill tree node just yet.

View File

@ -12,7 +12,6 @@ import net.Indyuce.mmocore.skilltree.*;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -103,7 +102,7 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje
} }
//Loads all the nodeDisplayInfo //Loads all the nodeDisplayInfo
for (NodeStatus status : NodeStatus.values()) for (SkillTreeStatus status : SkillTreeStatus.values())
for (NodeType nodeType : NodeType.values()) { for (NodeType nodeType : NodeType.values()) {
ConfigurationSection section = config.getConfigurationSection("display.nodes." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(nodeType.name())); ConfigurationSection section = config.getConfigurationSection("display.nodes." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(nodeType.name()));
if (section != null) if (section != null)
@ -173,9 +172,9 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje
*/ */
private void setupNodeStateFrom(SkillTreeNode node, PlayerData playerData) { private void setupNodeStateFrom(SkillTreeNode node, PlayerData playerData) {
if (playerData.getNodeLevel(node) > 0) { if (playerData.getNodeLevel(node) > 0) {
playerData.setNodeState(node, NodeStatus.UNLOCKED); playerData.setNodeState(node, SkillTreeStatus.UNLOCKED);
} else if (playerData.getNodeLevel(node) == 0 && node.isRoot()) { } else if (playerData.getNodeLevel(node) == 0 && node.isRoot()) {
playerData.setNodeState(node, NodeStatus.UNLOCKABLE); playerData.setNodeState(node, SkillTreeStatus.UNLOCKABLE);
} else { } else {
Set<SkillTreeNode> strongParents = node.getParents(ParentType.STRONG); Set<SkillTreeNode> strongParents = node.getParents(ParentType.STRONG);
Set<SkillTreeNode> softParents = node.getParents(ParentType.SOFT); Set<SkillTreeNode> softParents = node.getParents(ParentType.SOFT);
@ -199,7 +198,7 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje
numberChildren++; numberChildren++;
//We must check if the parent is Fully Locked or not and if it can unlock a new node(with its max children constraint) //We must check if the parent is Fully Locked or not and if it can unlock a new node(with its max children constraint)
if (numberChildren >= strongParent.getMaxChildren() || playerData.getNodeStatus(strongParent) == NodeStatus.FULLY_LOCKED) if (numberChildren >= strongParent.getMaxChildren() || playerData.getNodeStatus(strongParent) == SkillTreeStatus.FULLY_LOCKED)
isFullyLockedFromStrongParent = true; isFullyLockedFromStrongParent = true;
} }
@ -213,7 +212,7 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje
for (SkillTreeNode child : softParent.getChildren()) for (SkillTreeNode child : softParent.getChildren())
if (playerData.getNodeLevel(child) > 0) if (playerData.getNodeLevel(child) > 0)
numberChildren++; numberChildren++;
if (numberChildren < softParent.getMaxChildren() && playerData.getNodeStatus(softParent) != NodeStatus.FULLY_LOCKED) if (numberChildren < softParent.getMaxChildren() && playerData.getNodeStatus(softParent) != SkillTreeStatus.FULLY_LOCKED)
isFullyLockedFromSoftParent = false; isFullyLockedFromSoftParent = false;
} }
for (SkillTreeNode incompatibleParent : incompatibleParents) { for (SkillTreeNode incompatibleParent : incompatibleParents) {
@ -226,11 +225,11 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje
boolean isFullyLocked = isFullyLockedFromSoftParent || isFullyLockedFromStrongParent || isFullyLockedFromIncompatibleParent; boolean isFullyLocked = isFullyLockedFromSoftParent || isFullyLockedFromStrongParent || isFullyLockedFromIncompatibleParent;
boolean isUnlockable = isUnlockableFromSoftParent && isUnlockableFromStrongParent; boolean isUnlockable = isUnlockableFromSoftParent && isUnlockableFromStrongParent;
if (isFullyLocked) if (isFullyLocked)
playerData.setNodeState(node, NodeStatus.FULLY_LOCKED); playerData.setNodeState(node, SkillTreeStatus.FULLY_LOCKED);
else if (isUnlockable) else if (isUnlockable)
playerData.setNodeState(node, NodeStatus.UNLOCKABLE); playerData.setNodeState(node, SkillTreeStatus.UNLOCKABLE);
else else
playerData.setNodeState(node, NodeStatus.LOCKED); playerData.setNodeState(node, SkillTreeStatus.LOCKED);
} }
//We recursively call the algorithm for all the children of the current node //We recursively call the algorithm for all the children of the current node
for (SkillTreeNode child : node.getChildren()) for (SkillTreeNode child : node.getChildren())

View File

@ -61,7 +61,7 @@ public class FishingListener implements Listener {
private final Player player; private final Player player;
private final FishHook hook; private final FishHook hook;
private final int fishStrength, experienceDropped; private final int fishStrength, experienceDropped, vanillaExpDropped;
private int currentPulls; private int currentPulls;
@ -82,7 +82,7 @@ public class FishingListener implements Listener {
this.fishStrength = (int) Math.floor(caught.rollTugs() * (1 - PlayerData.get(player).getStats().getStat("FISHING_STRENGTH") / 100)); this.fishStrength = (int) Math.floor(caught.rollTugs() * (1 - PlayerData.get(player).getStats().getStat("FISHING_STRENGTH") / 100));
this.experienceDropped = caught.rollExperience(); this.experienceDropped = caught.rollExperience();
this.vanillaExpDropped = caught.rollVanillaExp();
fishing.add(player.getUniqueId()); fishing.add(player.getUniqueId());
runTaskTimer(MMOCore.plugin, 0, 2); runTaskTimer(MMOCore.plugin, 0, 2);
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin); Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
@ -195,7 +195,7 @@ public class FishingListener implements Listener {
player.getWorld().playSound(player.getLocation(), VersionSound.BLOCK_NOTE_BLOCK_HAT.toSound(), 1, 0); player.getWorld().playSound(player.getLocation(), VersionSound.BLOCK_NOTE_BLOCK_HAT.toSound(), 1, 0);
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
location.getWorld().spawnParticle(Particle.FIREWORKS_SPARK, location, 0, 4 * (RANDOM.nextDouble() - .5), RANDOM.nextDouble() + 1, 4 * (RANDOM.nextDouble() - .5), .08); location.getWorld().spawnParticle(Particle.FIREWORKS_SPARK, location, 0, 4 * (RANDOM.nextDouble() - .5), RANDOM.nextDouble() + 1, 4 * (RANDOM.nextDouble() - .5), .08);
player.giveExp(vanillaExpDropped);
if (MMOCore.plugin.fishingManager.hasLinkedProfession()) if (MMOCore.plugin.fishingManager.hasLinkedProfession())
playerData.getCollectionSkills().giveExperience(MMOCore.plugin.fishingManager.getLinkedProfession(), experienceDropped, EXPSource.FISHING, location, true); playerData.getCollectionSkills().giveExperience(MMOCore.plugin.fishingManager.getLinkedProfession(), experienceDropped, EXPSource.FISHING, location, true);
} }

View File

@ -222,8 +222,11 @@ death-exp-loss:
# Maximum number of skill slots. This means that you cannot unlock more than X skill slots. # Maximum number of skill slots. This means that you cannot unlock more than X skill slots.
max-skill-slots: 8 max-skill-slots: 8
# When set to true, passive skills must be bound in order to take effect. # When set to true, passive skills must be bound in order to take effect.
# When set to false, unlocked skills will take effect right away. # When set to false, unlocked skills will take effect right away.
# This is only the default behavior for skills but can be overridden by specifying true/false to
# the needs-bound field in the class skills section.
passive-skill-need-bound: true passive-skill-need-bound: true
# Set this to true to allow players in # Set this to true to allow players in

View File

@ -77,7 +77,9 @@ items:
function: 'skill-tree-node' function: 'skill-tree-node'
slots: [1,2,3,4,5,6,7,8,10,11,12,13,14,15,16,17,19,20,21,22,23,24,25,26,28,29,30,31,32,33,34,35,37,38,39,40,41,42,43,44] slots: [1,2,3,4,5,6,7,8,10,11,12,13,14,15,16,17,19,20,21,22,23,24,25,26,28,29,30,31,32,33,34,35,37,38,39,40,41,42,43,44]
#The lore that will be displayed after the lore of the node #The lore that will be displayed after the lore of the node.
#The {node-lore} placeholder will be replaced by the lore specified in the skill tree node config.
#All the placeholders you see here can also be used in the node lore.
lore: lore:
- '&7Current State: &6{current-state}' - '&7Current State: &6{current-state}'
- '&7Current Level: &6{current-level}' - '&7Current Level: &6{current-level}'
@ -99,6 +101,15 @@ items:
- '&e◆Points spent for {skill-tree}&e:&6 {point-spent}' - '&e◆Points spent for {skill-tree}&e:&6 {point-spent}'
- '&e◆Current {skill-tree} &epoints: &6{skill-tree-points}' - '&e◆Current {skill-tree} &epoints: &6{skill-tree-points}'
- '&e◆Current &6global&e points: &6{global-points}' - '&e◆Current &6global&e points: &6{global-points}'
#This is the name that will be displayed for each status.
status-names:
unlocked: 'Unlocked'
unlockable: 'Unlockable'
locked: 'Locked'
fully-locked: 'Fully Locked'
display: display:
paths: paths:
unlocked: unlocked: