Skill Slots Update

This commit is contained in:
Ka0rX 2023-03-19 10:53:40 +01:00
parent 1718e04ba5
commit 2ec66e92ef
6 changed files with 161 additions and 35 deletions

View File

@ -5,6 +5,7 @@ import io.lumine.mythic.lib.api.player.MMOPlayerData;
import io.lumine.mythic.lib.api.stat.StatInstance;
import io.lumine.mythic.lib.api.stat.modifier.StatModifier;
import io.lumine.mythic.lib.player.cooldown.CooldownMap;
import io.lumine.mythic.lib.player.skill.PassiveSkill;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.api.SoundEvent;
@ -17,6 +18,7 @@ import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.api.player.profess.SavedClassInformation;
import net.Indyuce.mmocore.api.player.profess.Subclass;
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
import net.Indyuce.mmocore.api.player.profess.skillbinding.BoundSkillInfo;
import net.Indyuce.mmocore.api.player.social.FriendRequest;
import net.Indyuce.mmocore.api.player.stats.PlayerStats;
import net.Indyuce.mmocore.api.quest.PlayerQuests;
@ -91,7 +93,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
private final List<UUID> friends = new ArrayList<>();
private final Set<String> waypoints = new HashSet<>();
private final Map<String, Integer> skills = new HashMap<>();
private final List<ClassSkill> boundSkills = new ArrayList<>();
private final Map<Integer,BoundSkillInfo> boundSkills = new HashMap<>();
private final PlayerProfessions collectSkills = new PlayerProfessions(this);
private final PlayerAttributes attributes = new PlayerAttributes(this);
private final Map<String, SavedClassInformation> classSlots = new HashMap<>();
@ -164,13 +166,13 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
MMOCore.log(Level.SEVERE, "[Userdata] Could not find class " + getProfess().getId() + " while refreshing player data.");
}
int j = 0;
while (j < boundSkills.size())
Iterator<Integer> ite=boundSkills.keySet().iterator();
while (ite.hasNext())
try {
boundSkills.set(j, Objects.requireNonNull(getProfess().getSkill(boundSkills.get(j).getSkill())));
int slot=ite.next();
BoundSkillInfo boundSkillInfo=new BoundSkillInfo(boundSkills.get(slot));
boundSkills.put(slot, boundSkillInfo);
} catch (Exception ignored) {
} finally {
j++;
}
for (SkillTree skillTree : getProfess().getSkillTrees())
@ -1047,10 +1049,23 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
public void setSkillLevel(String skill, int level) {
skills.put(skill, level);
refreshBoundedSkill(skill);
}
public void resetSkillLevel(String skill) {
skills.remove(skill);
refreshBoundedSkill(skill);
}
public void refreshBoundedSkill(String skill) {
boundSkills.values()
.stream()
.filter(skillInfo->skillInfo.getClassSkill().getSkill().getHandler().getId().equals(skill))
.forEach(BoundSkillInfo::refresh);
//TODO Remove test:
Bukkit.broadcastMessage("match"+boundSkills.values()
.stream()
.filter(skillInfo->skillInfo.getClassSkill().getSkill().getHandler().getId().equals(skill)).toList().size());
}
@Deprecated
@ -1108,8 +1123,8 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
this.profess = profess;
// Clear old skills
for (Iterator<ClassSkill> iterator = boundSkills.iterator(); iterator.hasNext(); )
if (!getProfess().hasSkill(iterator.next().getSkill()))
for (Iterator<BoundSkillInfo> iterator = boundSkills.values().iterator(); iterator.hasNext(); )
if (!getProfess().hasSkill(iterator.next().getClassSkill().getSkill()))
iterator.remove();
// Update stats
@ -1122,7 +1137,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
}
public ClassSkill getBoundSkill(int slot) {
return slot >= boundSkills.size() ? null : boundSkills.get(slot);
return slot >= boundSkills.size() ? null : boundSkills.get(slot).getClassSkill();
}
@ -1140,8 +1155,18 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
*/
public void bindSkill(int slot, ClassSkill skill) {
Validate.notNull(skill, "Skill cannot be null");
if (slot >= 0)
boundSkills.set(slot, skill);
//Unbinds the previous skill (Important for passive skills.
if (boundSkills.containsKey(slot))
boundSkills.get(slot).unbind();
if (slot >= 0) {
if (skill.getSkill().getTrigger().isPassive()) {
PassiveSkill passiveSkill = skill.toPassive(this);
passiveSkill.register(mmoData);
boundSkills.put(slot, new BoundSkillInfo(skill, this, passiveSkill.getUniqueId()));
} else {
boundSkills.put(slot, new BoundSkillInfo(skill, this));
}
}
}
public void unbindSkill(int slot) {
@ -1150,7 +1175,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
public List<ClassSkill> getBoundSkills() {
return boundSkills;
return boundSkills.values().stream().map(BoundSkillInfo::getClassSkill).collect(Collectors.toList());
}
@NotNull

View File

@ -21,7 +21,7 @@ import net.Indyuce.mmocore.api.player.profess.event.EventTrigger;
import net.Indyuce.mmocore.api.player.profess.resource.ManaDisplayOptions;
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
import net.Indyuce.mmocore.api.player.profess.resource.ResourceRegeneration;
import net.Indyuce.mmocore.api.player.profess.skillslot.SkillSlot;
import net.Indyuce.mmocore.api.player.profess.skillbinding.SkillSlot;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
import net.Indyuce.mmocore.experience.EXPSource;

View File

@ -0,0 +1,67 @@
package net.Indyuce.mmocore.api.player.profess.skillbinding;
import io.lumine.mythic.lib.player.skill.PassiveSkill;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.skill.ClassSkill;
import java.util.Objects;
import java.util.UUID;
public class BoundSkillInfo {
private final PlayerData playerData;
private final ClassSkill classSkill;
private UUID passiveSkillUUID;
public BoundSkillInfo(ClassSkill classSkill, PlayerData playerData) {
this.classSkill = classSkill;
this.playerData = playerData;
}
public BoundSkillInfo(ClassSkill classSkill, PlayerData playerData, UUID passiveSkillUUID) {
this.classSkill = classSkill;
this.playerData = playerData;
this.passiveSkillUUID = passiveSkillUUID;
}
/**
* Used on update to refresh the classSkill & all references to old data.
*/
public BoundSkillInfo(BoundSkillInfo info) {
this.playerData=info.getPlayerData();
this.classSkill= Objects.requireNonNull(playerData.getProfess().getSkill(info.getClassSkill().getSkill()));
info.unbind();
PassiveSkill passiveSkill = classSkill.toPassive(playerData);
passiveSkill.register(playerData.getMMOPlayerData());
this.passiveSkillUUID=passiveSkill.getUniqueId();
}
public ClassSkill getClassSkill() {
return classSkill;
}
public PlayerData getPlayerData() {
return playerData;
}
public UUID getPassiveSkillUUID() {
return passiveSkillUUID;
}
/**
* This is used to refresh the PassiveSkill playerModifier so it is always associated to the
*/
public void refresh() {
if (classSkill.getSkill().getTrigger().isPassive()) {
playerData.getMMOPlayerData().getPassiveSkillMap().removeModifier(passiveSkillUUID);
PassiveSkill passiveSkill = classSkill.toPassive(playerData);
passiveSkill.register(playerData.getMMOPlayerData());
this.passiveSkillUUID=passiveSkill.getUniqueId();
}
}
public void unbind() {
if (classSkill.getSkill().getTrigger().isPassive()) {
playerData.getMMOPlayerData().getPassiveSkillMap().removeModifier(passiveSkillUUID);
}
}
}

View File

@ -1,11 +1,12 @@
package net.Indyuce.mmocore.api.player.profess.skillslot;
package net.Indyuce.mmocore.api.player.profess.skillbinding;
import io.lumine.mythic.lib.api.math.BooleanExpressionParser;
import io.lumine.mythic.lib.MythicLib;
import net.Indyuce.mmocore.comp.mythicmobs.MythicHook;
import net.Indyuce.mmocore.skill.ClassSkill;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import javax.script.ScriptException;
import java.util.List;
public class SkillSlot {
@ -49,6 +50,7 @@ public class SkillSlot {
public Material getItem() {
return item;
}
public boolean hasItem() {
return item != null;
}
@ -58,6 +60,16 @@ public class SkillSlot {
}
public boolean canPlaceSkill(ClassSkill classSkill) {
return new BooleanExpressionParser(expression).parse(classSkill.getSkill().getCategories());
String parsedExpression = expression;
for (String category : classSkill.getSkill().getCategories())
parsedExpression = parsedExpression.replace("<" + category + ">", "true");
parsedExpression = parsedExpression.replaceAll("<.*>", "false");
try {
boolean res = (boolean) MythicLib.plugin.getScriptEngine().eval(parsedExpression);
return res;
} catch (ScriptException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -5,6 +5,7 @@ import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.NBTItem;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.skillbinding.SkillSlot;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import net.Indyuce.mmocore.gui.api.EditableInventory;
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
@ -28,6 +29,7 @@ import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.stream.Collectors;
public class SkillList extends EditableInventory {
public SkillList() {
@ -65,22 +67,36 @@ public class SkillList extends EditableInventory {
return new SlotItem(config) {
@Override
public ItemStack display(SkillViewerInventory inv, int n) {
if (n >= inv.getPlayerData().getSkillSlotLimit()) {
if (!inv.getPlayerData().getProfess().hasSlot(n)) {
return new ItemStack(Material.AIR);
}
SkillSlot skillSlot = inv.getPlayerData().getProfess().getSkillSlot(n);
ItemStack item = super.display(inv, n);
if (!inv.getPlayerData().hasSkillBound(n)) {
item.setType(super.emptyMaterial);
if (MythicLib.plugin.getVersion().isStrictlyHigher(1, 13)) {
//If there is an item filled in the slot config it shows it, else shows the default item.
Material material = skillSlot.hasItem() ? skillSlot.getItem() : super.emptyMaterial;
int customModelData = skillSlot.hasItem() ? skillSlot.getModelData() : super.emptyCMD;
item.setType(material);
ItemMeta meta = item.getItemMeta();
meta.setCustomModelData(super.emptyCMD);
meta.setDisplayName(MMOCore.plugin.placeholderParser.parse(inv.getPlayerData().getPlayer(),skillSlot.getName()));
List<String> lore=skillSlot.getLore()
.stream()
.map(str->MMOCore.plugin.placeholderParser.parse(inv.getPlayerData().getPlayer(),str))
.collect(Collectors.toList());
meta.setLore(lore);
if (MythicLib.plugin.getVersion().isStrictlyHigher(1, 13)) {
meta.setCustomModelData(customModelData);
}
item.setItemMeta(meta);
}
}
return item;
}
/**
* This should only be called when there is a skill bound.
*/
@Override
public Placeholders getPlaceholders(SkillViewerInventory inv, int n) {
Placeholders holders = super.getPlaceholders(inv, n);
@ -297,8 +313,7 @@ public class SkillList extends EditableInventory {
// Cached information
private final List<ClassSkill> skills;
private final List<Integer> skillSlots;
private final List<Integer> activeSlotSlots;
private final List<Integer> passiveSlotSlots;
private final List<Integer> slotSlots;
//The skill the player Selected
private ClassSkill selected;
@ -309,9 +324,8 @@ public class SkillList extends EditableInventory {
skills = new ArrayList<>(playerData.getProfess().getSkills());
skillSlots = getEditable().getByFunction("skill").getSlots();
Validate.notNull(getEditable().getByFunction("active-slot"), "Your skill GUI config file is out-of-date, please regenerate it.");
activeSlotSlots = getEditable().getByFunction("active-slot").getSlots();
passiveSlotSlots = getEditable().getByFunction("passive-slot").getSlots();
Validate.notNull(getEditable().getByFunction("slot"), "Your skill GUI config file is out-of-date, please regenerate it.");
slotSlots = getEditable().getByFunction("slot").getSlots();
selected = skills.get(page * skillSlots.size());
}
@ -379,9 +393,9 @@ public class SkillList extends EditableInventory {
/*
* binding or unbinding skills.
*/
if (item.getFunction().equals("active-slot")) {
int index = activeSlotSlots.indexOf(context.getSlot());
if (item.getFunction().equals("slot")) {
int index = slotSlots.indexOf(context.getSlot());
SkillSlot skillSlot=playerData.getProfess().getSkillSlot(index);
// unbind if there is a current spell.
if (context.getClickType() == ClickType.RIGHT) {
if (!playerData.hasSkillBound(index)) {
@ -404,6 +418,13 @@ public class SkillList extends EditableInventory {
return;
}
if(!skillSlot.canPlaceSkill(selected)){
MMOCore.plugin.configManager.getSimpleMessage("not-compatible-skill").send(player);
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
return;
}
player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 2);
playerData.bindSkill(index, selected);
open();

View File

@ -199,6 +199,7 @@ not-enough-skill-points-shift: '&cYou need {shift_points} skill points.'
upgrade-skill: '&eYour &6{skill} &eis now Level &6{level}&e!'
not-unlocked-skill: '&cYou have not unlocked that skill yet.'
no-skill-bound: '&cYou don''t have any skill bound to this slot.'
not-compatible-skill: '&cThe selected skill is not compatible with this slot.'
skill-max-level-hit: '&cYou already hit the max level for that skill.'
no-skill-placeholder: 'No Skill Bound'
not-skill-reallocation-point: '&cYou do not have 1 skill reallocation point.'