Debug Automatic WayPoints

This commit is contained in:
Ka0rX 2022-06-13 20:38:34 +02:00
parent 7fee8736ed
commit a5ab2c9269
10 changed files with 449 additions and 88 deletions

View File

@ -3,9 +3,11 @@ package net.Indyuce.mmocore.api.player;
import io.lumine.mythic.lib.api.player.MMOPlayerData;
import io.lumine.mythic.lib.player.TemporaryPlayerData;
import io.lumine.mythic.lib.player.cooldown.CooldownMap;
import io.lumine.mythic.lib.player.modifier.PlayerModifier;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.api.SoundEvent;
import net.Indyuce.mmocore.api.quest.trigger.Trigger;
import net.Indyuce.mmocore.player.Unlockable;
import net.Indyuce.mmocore.tree.IntegerCoordinates;
import net.Indyuce.mmocore.tree.NodeState;
@ -78,7 +80,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
*/
@Nullable
private PlayerClass profess;
private int level, classPoints, skillPoints, attributePoints, attributeReallocationPoints,skillTreeReallocationPoints;// skillReallocationPoints,
private int level, classPoints, skillPoints, attributePoints, attributeReallocationPoints, skillTreeReallocationPoints;// skillReallocationPoints,
private double experience;
private double mana, stamina, stellium;
private Guild guild;
@ -217,12 +219,26 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
return skillTreePoints.containsKey(treeId);
}
public void removeModifiersFrom(SkillTree skillTree) {
for (SkillTreeNode node : skillTree.getNodes()) {
for (int i = 0; i < node.getMaxLevel(); i++) {
List<PlayerModifier> modifiers = node.getModifiers(i);
if (modifiers != null) {
for (PlayerModifier modifier : modifiers) {
modifier.unregister(getMMOPlayerData());
}
}
}
}
}
public boolean canIncrementNodeLevel(SkillTreeNode node) {
NodeState nodeState = nodeStates.get(node);
//Check the State of the node
if (nodeState != NodeState.UNLOCKED && nodeState != NodeState.UNLOCKABLE)
return false;
return getNodeLevel(node)<node.getMaxLevel()&&(skillTreePoints.get(node.getTree().getId()) > 0 || skillTreePoints.get("global") > 0);
return getNodeLevel(node) < node.getMaxLevel() && (skillTreePoints.get(node.getTree().getId()) > 0 || skillTreePoints.get("global") > 0);
}
/**
@ -231,14 +247,37 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
*/
public <T extends SkillTree> void incrementNodeLevel(SkillTreeNode node) {
setNodeLevel(node, getNodeLevel(node) + 1);
//Triggers the triggers of the node
List<Trigger> triggers = node.getTriggers(getNodeLevel(node));
if (triggers != null) {
for (Trigger trigger : triggers) {
trigger.apply(this);
}
}
//Applies player modifiers
List<PlayerModifier> modifiers = node.getModifiers(getNodeLevel(node));
if (modifiers != null) {
Bukkit.broadcastMessage("Modifier: "+modifiers.size());
for (PlayerModifier modifier : modifiers) {
modifier.register(getMMOPlayerData());
}
}
Bukkit.broadcastMessage(playerStats.getStat(StatType.HEALTH_REGENERATION)+"");
if (nodeStates.get(node) == NodeState.UNLOCKABLE)
setNodeState(node, NodeState.UNLOCKED);
if (skillTreePoints.get(node.getTree().getId()) > 0)
withdrawSkillTreePoints(node.getTree().getId(), 1);
else
withdrawSkillTreePoints("global", 1);
//We unload the nodeStates map and reload it completely
nodeStates= new HashMap<>();
//We unload the nodeStates map (for the skill tree) and reload it completely
for (SkillTreeNode node1 : node.getTree().getNodes()) {
nodeStates.remove(node1);
}
node.getTree().setupNodeState(this);
}
@ -250,13 +289,18 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
SkillTree skillTree = node.getTree();
DisplayInfo displayInfo = new DisplayInfo(nodeStates.get(node), node.getSize());
return skillTree.getIcon(displayInfo);
}
public Icon getIcon(SkillTree skillTree, IntegerCoordinates coordinates) {
if (skillTree.isNode(coordinates)) {
SkillTreeNode node = skillTree.getNode(coordinates);
if (nodeStates.get(node) == null) {
skillTree.getNodes().forEach(nodee -> Bukkit.broadcastMessage(nodee.getId() + " " + nodeStates.get(nodee)));
}
DisplayInfo displayInfo = new DisplayInfo(nodeStates.get(node), node.getSize());
return skillTree.getIcon(displayInfo);
}
@ -399,7 +443,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
}
public void giveSkillTreeReallocationPoints(int amount) {
skillTreeReallocationPoints+=amount;
skillTreeReallocationPoints += amount;
}
@Override

View File

@ -20,8 +20,8 @@ import java.util.stream.Collectors;
public class SkillTreePointsCommandTreeNode extends CommandTreeNode {
BiFunction<PlayerData, String,Integer> get;
public SkillTreePointsCommandTreeNode(CommandTreeNode parent, TriConsumer<PlayerData, Integer, String> give,
TriConsumer<PlayerData, Integer, String> set, BiFunction<PlayerData, String,Integer> get) {
public SkillTreePointsCommandTreeNode(CommandTreeNode parent, TriConsumer<PlayerData, Integer, String> set,
TriConsumer<PlayerData, Integer, String> give, BiFunction<PlayerData, String,Integer> get) {
super(parent, "skill-tree-points");
addChild(new ActionCommandTreeNode(this, "give", give));
addChild(new ActionCommandTreeNode(this, "set", set));

View File

@ -181,7 +181,7 @@ public class SkillTreeViewer extends EditableInventory {
//If it is path we remove the display name and the lore.
else {
meta.setLore(new ArrayList<>());
meta.setDisplayName("");
meta.setDisplayName(" ");
}
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
PersistentDataContainer container = meta.getPersistentDataContainer();
@ -297,6 +297,8 @@ public class SkillTreeViewer extends EditableInventory {
//We remove all the nodeStates progress
playerData.giveSkillTreePoints(skillTree.getId(), reallocated);
playerData.giveSkillTreeReallocationPoints(-1);
//We unregister all the modifiers or the player
playerData.removeModifiersFrom(skillTree);
for (SkillTreeNode node : skillTree.getNodes()) {
playerData.setNodeLevel(node, 0);
playerData.setNodeState(node, NodeState.LOCKED);

View File

@ -23,7 +23,6 @@ public class IntegerCoordinates {
public int getX() {
return x;
}
public int getY() {
return y;
}

View File

@ -2,7 +2,10 @@ package net.Indyuce.mmocore.tree;
import com.gmail.nossr50.mcmmo.acf.annotation.HelpSearchTags;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.player.modifier.PlayerModifier;
import io.lumine.mythic.lib.util.configobject.ConfigObject;
import io.lumine.mythic.lib.util.configobject.LineConfigObject;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.trigger.Trigger;
@ -17,6 +20,7 @@ import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.logging.Level;
//We must use generics to get the type of the corresponding tree
public class SkillTreeNode implements Unlockable {
@ -30,8 +34,8 @@ public class SkillTreeNode implements Unlockable {
private final HashMap<NodeContext, List<String>> lores = new HashMap<>();
//TODO modifiers depending on level with drop tables
private final HashMap<Integer, HashSet<PlayerModifier>> modifiers = new HashMap<>();
private final HashMap<Integer, HashSet<Trigger>> triggers = new HashMap<>();
private final HashMap<Integer, List<PlayerModifier>> modifiers = new HashMap<>();
private final HashMap<Integer, List<Trigger>> triggers = new HashMap<>();
//The max level the skill tree node can have and the max amount of children it can have.
private final int maxLevel, maxChildren, size;
private final ArrayList<SkillTreeNode> children = new ArrayList<>();
@ -43,7 +47,7 @@ public class SkillTreeNode implements Unlockable {
private final HashMap<SkillTreeNode, Integer> softParents = new HashMap<>();
private final HashMap<SkillTreeNode ,Integer> strongParents = new HashMap<>();
private final HashMap<SkillTreeNode, Integer> strongParents = new HashMap<>();
public SkillTreeNode(SkillTree tree, ConfigurationSection config) {
@ -59,7 +63,7 @@ public class SkillTreeNode implements Unlockable {
for (String state : Objects.requireNonNull(config.getConfigurationSection("lores")).getKeys(false)) {
NodeState nodeState = NodeState.valueOf(MMOCoreUtils.toEnumName(state));
if (nodeState == NodeState.UNLOCKED) {
//TODO: Message could'nt load ... instead of exception
//TODO: Message could'nt load ... instead of exce/*99+*-*99**9+-ption
ConfigurationSection section = config.getConfigurationSection("lores." + state);
for (String level : section.getKeys(false)) {
lores.put(new NodeContext(nodeState, Integer.parseInt(level)), section.getStringList(level));
@ -68,6 +72,45 @@ public class SkillTreeNode implements Unlockable {
lores.put(new NodeContext(nodeState, 0), config.getStringList("lores." + state));
}
}
//We load the triggers
if (config.contains("triggers")) {
try {
ConfigurationSection section = config.getConfigurationSection("triggers");
for (String level : section.getKeys(false)) {
int value = Integer.parseInt(level);
for (String str : section.getStringList(level)) {
Trigger trigger = MMOCore.plugin.loadManager.loadTrigger(new MMOLineConfig(str));
if (!triggers.containsKey(value)) {
triggers.put(value, new ArrayList<>());
}
triggers.get(value).add(trigger);
}
}
} catch (NumberFormatException e) {
MMOCore.plugin.getLogger().log(Level.WARNING, "Couldn't load triggers for the skill node " + tree.getId() + "." + id + " :Problem with the Number Format.");
}
}
//We load the player Modifiers
if (config.contains("modifiers")) {
try {
ConfigurationSection section = config.getConfigurationSection("modifiers");
for (String level : section.getKeys(false)) {
int value = Integer.parseInt(level);
for (String str : section.getStringList(level)) {
PlayerModifier modifier = MythicLib.plugin.getModifiers().loadPlayerModifier(new LineConfigObject(new MMOLineConfig(str)));
if (!modifiers.containsKey(value)) {
modifiers.put(value, new ArrayList<>());
}
modifiers.get(value).add(modifier);
}
}
} catch (NumberFormatException e) {
MMOCore.plugin.getLogger().log(Level.WARNING, "Couldn't load modifiers for the skill node " + tree.getId() + "." + id+ " :Problem with the Number Format.");
}
}
maxLevel = config.contains("max-level") ? config.getInt("max-level") : 1;
maxChildren = config.contains("max-children") ? config.getInt("max-children") : 1;
//If coordinates are precised adn we are not wiht an automaticTree we set them up
@ -90,6 +133,11 @@ public class SkillTreeNode implements Unlockable {
return tree;
}
public void setIsRoot() {
isRoot = true;
}
public boolean isRoot() {
return isRoot;
}
@ -148,19 +196,19 @@ public class SkillTreeNode implements Unlockable {
}
public String getName() {
return MythicLib.plugin.parseColors( name);
return MythicLib.plugin.parseColors(name);
}
public IntegerCoordinates getCoordinates() {
return coordinates;
}
public Set<PlayerModifier> getModifiers(int level) {
public List<PlayerModifier> getModifiers(int level) {
return modifiers.get(level);
}
public Set<Trigger> getTriggers(int level) {
public List<Trigger> getTriggers(int level) {
return triggers.get(level);
}
@ -244,15 +292,14 @@ public class SkillTreeNode implements Unlockable {
public List<String> getLore(PlayerData playerData) {
Placeholders holders = getPlaceholders(playerData);
List<String> parsedLore = new ArrayList<>();
NodeContext context= new NodeContext(playerData.getNodeState(this),playerData.getNodeLevel(this));
NodeContext context = new NodeContext(playerData.getNodeState(this), playerData.getNodeLevel(this));
lores.get(context).forEach(string -> parsedLore.add(
MythicLib.plugin.parseColors( holders.apply(playerData.getPlayer(), string))));
MythicLib.plugin.parseColors(holders.apply(playerData.getPlayer(), string))));
return parsedLore;
}
/**
* @param namespacedKey Something like "skill_tree:tree_name_1_5"
* @return The corresponding skill tree node
@ -315,6 +362,4 @@ public class SkillTreeNode implements Unlockable {
}
}

View File

@ -1,5 +1,6 @@
package net.Indyuce.mmocore.tree.skilltree;
import com.guillaumevdn.questcreator.integration.mythicmobs.v4.element.ElementMythicMobsObjective;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.tree.IntegerCoordinates;
import net.Indyuce.mmocore.tree.ParentType;
@ -16,8 +17,7 @@ import java.util.logging.Level;
/**
* Skill Trees where you only need to fill the strong and soft
*/
public class AutomaticSkillTree extends SkillTree {
private SkillTreeNode root;
public class AutomaticSkillTree extends SkillTree {
//Hash map to store the number of left and right branches of each node
private final HashMap<SkillTreeNode, Branches> nodeBranches = new HashMap<>();
@ -31,17 +31,17 @@ public class AutomaticSkillTree extends SkillTree {
//We setup the children and parents for each node.
for(SkillTreeNode node:nodes.values()) {
ConfigurationSection section = config.getConfigurationSection("nodes."+node.getId() + ".children.soft");
if(section!=null) {
for (SkillTreeNode node : nodes.values()) {
ConfigurationSection section = config.getConfigurationSection("nodes." + node.getId() + ".children.soft");
if (section != null) {
for (String child : section.getKeys(false)) {
node.addChild(getNode(child));
getNode(child).addParent(node, section.getInt(child), ParentType.SOFT);
}
}
section = config.getConfigurationSection("nodes."+node.getId() + ".children.strong");
section = config.getConfigurationSection("nodes." + node.getId() + ".children.strong");
if(section!=null) {
if (section != null) {
for (String child : section.getKeys(false)) {
node.addChild(getNode(child));
getNode(child).addParent(node, section.getInt(child), ParentType.STRONG);
@ -51,23 +51,24 @@ public class AutomaticSkillTree extends SkillTree {
}
//We find the root of the tree wich is
for (SkillTreeNode node : nodes.values()) {
if (node.getSoftParents().size() == 0&&node.getStrongParents().size()==0) {
Validate.isTrue(root == null, "You can't have 2 roots on one automatic skill tree. You have "+(root!=null?root.getName():"")+" and "+node.getName()+".");
root = node;
if (node.getSoftParents().size() == 0 && node.getStrongParents().size() == 0) {
Validate.isTrue(roots.size() == 0, "You can't have 2 roots on one automatic skill tree. You have " + (roots.size() != 0 ? roots.get(0).getName() : "") + " and " + node.getName() + ".");
//We mark the node as a root also
roots.add(node);
node.setIsRoot();
}
}
//We setup the width of all the nodes recursively
setupTreeWidth(root);
setupTreeWidth(roots.get(0));
//We recursively setup all the coordinates of the tree nodes
root.setCoordinates(new IntegerCoordinates(0, 0));
setupCoordinates(root);
roots.get(0).setCoordinates(new IntegerCoordinates(0, 0));
setupCoordinates(roots.get(0));
//We get and cache the values of minX,minY,maxX and maxY
minX = nodeBranches.get(root).getLeftBranches();
minX = nodeBranches.get(roots.get(0)).getLeftBranches();
minY = 0;
maxX = nodeBranches.get(root).getRightBranches();
maxX = nodeBranches.get(roots.get(0)).getRightBranches();
for (SkillTreeNode node : nodes.values()) {
if (node.getCoordinates().getY() > maxY)
@ -86,26 +87,29 @@ public class AutomaticSkillTree extends SkillTree {
* @param node the root
*/
private void setupCoordinates(SkillTreeNode node) {
if (node.isRoot()) {
node.setCoordinates(new IntegerCoordinates(0, 2));
}
int childrenSize = node.getChildren().size();
int x = node.getCoordinates().getX();
;
int y = node.getCoordinates().getY();
;
int leftOffset = 0;
int rightOffset = 0;
for (int i = 0; i < childrenSize; i++) {
SkillTreeNode child = node.getChildren().get(i);
if (childrenSize % 2 == 0 && i == 0) {
child.setCoordinates(new IntegerCoordinates(x, y + 2));
if (childrenSize % 2 == 1 && i == 0) {
child.setCoordinates(new IntegerCoordinates(x, y - 2));
leftOffset += 2 + nodeBranches.get(child).getLeftBranches();
rightOffset += 2 + nodeBranches.get(child).getRightBranches();
} else if (i % 2 == 0) {
child.setCoordinates(new IntegerCoordinates(x - leftOffset - 2 - nodeBranches.get(child).getWidth(), y + 2));
for(SkillTreeNode skillTree : nodeBranches.keySet())
leftOffset += 2 + nodeBranches.get(child).getWidth();
child.setCoordinates(new IntegerCoordinates(x - leftOffset - 2 - nodeBranches.get(child).getWidth(), y - 2));
for (SkillTreeNode skillTree : nodeBranches.keySet())
leftOffset += 2 + nodeBranches.get(child).getWidth();
} else {
child.setCoordinates(new IntegerCoordinates(x + rightOffset + 2 + nodeBranches.get(child).getWidth(), y + 2));
child.setCoordinates(new IntegerCoordinates(x + rightOffset + 2 + nodeBranches.get(child).getWidth(), y - 2));
rightOffset += 2 + nodeBranches.get(child).getWidth();
}
@ -113,11 +117,12 @@ public class AutomaticSkillTree extends SkillTree {
int childX = child.getCoordinates().getX();
int childY = child.getCoordinates().getY();
int parentX = node.getSoftParents().size()!=0?((SkillTreeNode)node.getSoftParents().toArray()[0]).getCoordinates().getX():((SkillTreeNode)node.getStrongParents().toArray()[0]).getCoordinates().getX();
paths.add(new IntegerCoordinates(childX, childY - 1));
int parentX=node.getCoordinates().getX();
paths.add(new IntegerCoordinates(childX, childY + 1));
int offset = childX > parentX ? -1 : 1;
while (childX != parentX) {
paths.add(new IntegerCoordinates(childX, childY - 2));
paths.add(new IntegerCoordinates(childX, childY + 2));
childX += offset;
}
@ -155,7 +160,7 @@ public class AutomaticSkillTree extends SkillTree {
}
}
nodeBranches.put(node,new Branches(leftBranches,rightBranches));
nodeBranches.put(node, new Branches(leftBranches, rightBranches));
}
private class Branches {

View File

@ -2,6 +2,7 @@ package net.Indyuce.mmocore.tree.skilltree;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.util.PostLoadObject;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import net.Indyuce.mmocore.manager.registry.RegisterObject;
@ -39,7 +40,7 @@ import java.util.logging.Level;
*/
public abstract class SkillTree extends PostLoadObject implements RegisterObject {
private final String id, name;
private final List<String> lore=new ArrayList<>();
private final List<String> lore = new ArrayList<>();
private final Material item;
//2 different maps to get the nodes
@ -51,13 +52,13 @@ public abstract class SkillTree extends PostLoadObject implements RegisterObject
//Caches the height of the skill tree
protected int minX, minY, maxX, maxY;
protected final HashMap<DisplayInfo, Icon> icons = new HashMap<>();
protected final HashSet<SkillTreeNode> roots = new HashSet<>();
protected final List<SkillTreeNode> roots = new ArrayList<>();
public SkillTree(ConfigurationSection config) {
super(config);
this.id = Objects.requireNonNull(config.getString("id"), "Could not find skill tree id");
this.name = MythicLib.plugin.parseColors(Objects.requireNonNull(config.getString("name"), "Could not find skill tree name"));
Objects.requireNonNull(config.getStringList("lore"),"Could not find skill tree lore").forEach(str->lore.add(MythicLib.plugin.parseColors(str )));
Objects.requireNonNull(config.getStringList("lore"), "Could not find skill tree lore").forEach(str -> lore.add(MythicLib.plugin.parseColors(str)));
this.item = Material.valueOf(MMOCoreUtils.toEnumName(Objects.requireNonNull(config.getString("item"))));
Validate.isTrue(config.isConfigurationSection("nodes"), "Could not find any nodes in the tree");
for (String key : config.getConfigurationSection("nodes").getKeys(false)) {
@ -84,19 +85,14 @@ public abstract class SkillTree extends PostLoadObject implements RegisterObject
for (String key : config.getConfigurationSection("icons").getKeys(false)) {
if (key.equalsIgnoreCase("path")) {
icons.put(DisplayInfo.pathInfo, new Icon(config.getConfigurationSection("icons." + key)));
continue;
}
for (String size : config.getConfigurationSection("icons." + key).getKeys(false)) {
if(key.equalsIgnoreCase("path")) {
DisplayInfo displayInfo = DisplayInfo.pathInfo;
Icon icon = new Icon(config.getConfigurationSection("icons." + key));
icons.put(displayInfo, icon);
DisplayInfo displayInfo = new DisplayInfo(NodeState.valueOf(MMOCoreUtils.toEnumName(key)), Integer.parseInt(size));
Icon icon = new Icon(config.getConfigurationSection("icons." + key + "." + size));
icons.put(displayInfo, icon);
}
else {
DisplayInfo displayInfo = new DisplayInfo(NodeState.valueOf(MMOCoreUtils.toEnumName(key)), Integer.parseInt(size));
Icon icon = new Icon(config.getConfigurationSection("icons." + key + "." + size));
icons.put(displayInfo, icon);
}}
}
}
} catch (Exception e) {
Bukkit.getLogger().log(Level.WARNING, "Couldn't load icons for the skill tree " + id);
@ -120,8 +116,7 @@ public abstract class SkillTree extends PostLoadObject implements RegisterObject
protected abstract void whenPostLoaded(@NotNull ConfigurationSection configurationSection);
public Icon getIcon(DisplayInfo info) {
Validate.isTrue(icons.containsKey(info),"The icon corresponding to "+(info.getNodeState()==null? "path": "node-state: "+info.getNodeState()
+" ,size: "+info.getSize())+" doesn't exist in the icons of the skill-tree yml." );
Validate.isTrue(icons.containsKey(info), "The icon corresponding to " + info + " doesn't exist for the skill tree " + id + ".");
return icons.get(info);
}
@ -181,19 +176,23 @@ public abstract class SkillTree extends PostLoadObject implements RegisterObject
}
public List<SkillTreeNode> getRoots() {
return roots;
}
/**
* Update recursively the state of all the nodes that are children of this node (Used when we change the state of a node)
*/
public void setupNodeStateFrom(SkillTreeNode node, PlayerData playerData) {
if (playerData.getNodeLevel(node) > 0) {
if (playerData.getNodeLevel(node) > 0) {
playerData.setNodeState(node, NodeState.UNLOCKED);
} else if (playerData.getNodeLevel(node) == 0 && node.isRoot()) {
playerData.setNodeState(node, NodeState.UNLOCKABLE);
} else {
boolean isUnlockableFromStrongParent = true;
boolean isUnlockableFromSoftParent = false;
boolean isFullyLockedFromStrongParent = false;
boolean isFullyLockedFromSoftParent = true;
boolean isUnlockableFromStrongParent = node.getStrongParents().size()==0?true:true;
boolean isUnlockableFromSoftParent = node.getSoftParents().size()==0?true:false;
boolean isFullyLockedFromStrongParent = node.getStrongParents().size()==0?false:false;
boolean isFullyLockedFromSoftParent = node.getSoftParents().size()==0?false:true;
for (SkillTreeNode strongParent : node.getStrongParents()) {
if (playerData.getNodeLevel(strongParent) < node.getParentNeededLevel(strongParent)) {
@ -209,6 +208,9 @@ public abstract class SkillTree extends PostLoadObject implements RegisterObject
if (numberChildren >= strongParent.getMaxChildren() || playerData.getNodeState(strongParent) == NodeState.FULLY_LOCKED)
isFullyLockedFromStrongParent = true;
}
for (SkillTreeNode softParent : node.getSoftParents()) {
if (playerData.getNodeLevel(softParent) > node.getParentNeededLevel(softParent)) {
isUnlockableFromSoftParent = true;
@ -219,8 +221,9 @@ public abstract class SkillTree extends PostLoadObject implements RegisterObject
if (playerData.getNodeLevel(child) > 0)
numberChildren++;
if (numberChildren < softParent.getMaxChildren() && playerData.getNodeState(softParent) != NodeState.FULLY_LOCKED)
isFullyLockedFromStrongParent = false;
isFullyLockedFromSoftParent = false;
}
boolean isFullyLocked = isFullyLockedFromSoftParent || isFullyLockedFromStrongParent;
boolean isUnlockable = isUnlockableFromSoftParent && isUnlockableFromStrongParent;
if (isFullyLocked)

View File

@ -42,6 +42,8 @@ public class DisplayInfo {
if(!(obj instanceof DisplayInfo))
return false;
DisplayInfo displayInfo= (DisplayInfo) obj;
if(nodeState==null)
return displayInfo.getNodeState()==null;
return nodeState==displayInfo.getNodeState()&&size==displayInfo.getSize();
}

View File

@ -0,0 +1,143 @@
id: autocombat
name: AutoCombat
type: automatic
item: GOLDEN_AXE
lore:
- '&6This autoskill tree is used for combat abilities!'
nodes:
strength:
name: 'Combat strength'
children:
strong:
force: 2
max-level: 2
size: 1
lores:
unlocked:
1 :
- "&eYou are level 1"
2:
- "&eYou are level 2"
locked:
- "&4This skill is locked"
unlockable:
- "&aThis skill is unlockable"
fully-locked:
- '&aThis is skill is fully locked'
#modifers
force:
name: 'Force'
size: 1
max-children: 1
children:
strong:
weaponry: 1
archery: 1
lores:
unlocked:
1 :
- "&eYou are level 1"
2:
- "&eYou are level 2"
locked:
- "&4This skill is locked"
unlockable:
- "&aThis skill is unlockable"
fully-locked:
- '&aThis is skill is fully locked'
weaponry:
name: 'Weaponry'
max-level: 2
size: 1
lores:
unlocked:
1 :
- "&eYou are level 1"
2:
- "&eYou are level 2"
locked:
- "&4This skill is locked"
unlockable:
- "&aThis skill is unlockable"
fully-locked:
- '&aThis is skill is fully locked'
archery:
name: 'Archery'
max-level: 2
size: 1
children:
strong:
archery2: 2
lores:
unlocked:
1 :
- "&eYou are level 1"
2:
- "&eYou are level 2"
locked:
- "&4This skill is locked"
unlockable:
- "&aThis skill is unlockable"
fully-locked:
- '&aThis is skill is fully locked'
archery2:
name: 'Archery2'
max-level: 2
size: 1
children:
strong:
archery3: 1
lores:
unlocked:
1 :
- "&eYou are level 1"
2:
- "&eYou are level 2"
locked:
- "&4This skill is locked"
unlockable:
- "&aThis skill is unlockable"
fully-locked:
- '&aThis is skill is fully locked'
archery3:
name: 'Archery3'
max-level: 2
size: 1
lores:
unlocked:
1 :
- "&eYou are level 1"
2:
- "&eYou are level 2"
locked:
- "&4This skill is locked"
unlockable:
- "&aThis skill is unlockable"
fully-locked:
- '&aThis is skill is fully locked'
icons:
unlocked:
1:
item: 'GREEN_DYE'
locked:
1:
item: "BROWN_DYE"
unlockable:
1:
item: "BLUE_DYE"
fully-locked:
1:
item: "BLACK_DYE"
path:
item: "WHITE_DYE"

View File

@ -1,34 +1,152 @@
id: 'combat'
name: 'Combat Skill Tree'
#The type of the Skill tree, can be :
#'linked'->You must only precise nodes coordinates. 2 adjacent nodes will be affiliated. The root is at coordinates 0,0.
#'automatic'-> You must only precise the children(there can more than 1) of each node. Each node can only have one parent and the root has none.
# The display coordinates will be automatically calculated to have a good render.
#'custom'-> You must precise coordinates and children for each node, each node can have multiple parents and children.
# The coordinates are only used for display on the GUI but will not have any impact on the affiliation between nodes.
name: '&4Combat'
lore:
- '&6This skill tree is used for combat abilities!'
type: 'linked'
#The item that will represent the skill tree in the GUI
item: 'DIAMOND_SWORD'
item: 'DIAMOND_AXE'
nodes:
strength:
name: 'Combat strength'
#Coordinates of the node
coordinates:
x: 0
y: 0
strength2:
name: 'Combat strength 2'
max-level: 2
is-root: true
size: 1
lores:
unlocked:
1 :
- "&eYou are level 1"
2:
- "&eYou are level 2"
locked:
- "&4This skill is locked"
unlockable:
- "&aThis skill is unlockable"
fully-locked:
- '&aThis is skill is fully locked'
#modifers
force:
name: 'Force'
size: 1
max-children: 1
coordinates:
x: 1
y: 0
lores:
unlocked:
1 :
- "&eYou are level 1"
2:
- "&eYou are level 2"
locked:
- "&4This skill is locked"
unlockable:
- "&aThis skill is unlockable"
fully-locked:
- '&aThis is skill is fully locked'
weaponry:
name: 'Weaponry'
coordinates:
x: 2
y: 0
max-level: 2
size: 1
lores:
unlocked:
1 :
- "&eYou are level 1"
2:
- "&eYou are level 2"
locked:
- "&4This skill is locked"
unlockable:
- "&aThis skill is unlockable"
fully-locked:
- '&aThis is skill is fully locked'
archery:
name: 'Archery'
coordinates:
x: 1
y: 1
max-level: 2
size: 1
lores:
unlocked:
1 :
- "&eYou are level 1"
2:
- "&eYou are level 2"
locked:
- "&4This skill is locked"
unlockable:
- "&aThis skill is unlockable"
fully-locked:
- '&aThis is skill is fully locked'
archery2:
name: 'Archery2'
coordinates:
x: 1
y: 2
max-level: 2
size: 1
lores:
unlocked:
1 :
- "&eYou are level 1"
2:
- "&eYou are level 2"
locked:
- "&4This skill is locked"
unlockable:
- "&aThis skill is unlockable"
fully-locked:
- '&aThis is skill is fully locked'
archery3:
name: 'Archery3'
coordinates:
x: 1
y: 3
max-level: 2
size: 1
lores:
unlocked:
1 :
- "&eYou are level 1"
2:
- "&eYou are level 2"
locked:
- "&4This skill is locked"
unlockable:
- "&aThis skill is unlockable"
fully-locked:
- '&aThis is skill is fully locked'
paths:
coordinates:
x: 2
y: 2
icons:
unlocked:
1:
item: 'GREEN_DYE'
locked:
1:
item: "BROWN_DYE"
unlockable:
1:
item: "BLUE_DYE"
fully-locked:
1:
item: "BLACK_DYE"
path:
item: "WHITE_DYE"