Skill combos merge

This commit is contained in:
Jules 2022-08-08 18:13:50 +02:00
commit bfb33cd7a7
30 changed files with 595 additions and 302 deletions

View File

@ -13,7 +13,8 @@ public enum SoundEvent {
SELECT_CLASS,
LEVEL_ATTRIBUTE,
RESET_ATTRIBUTES,
NOT_ENOUGH_POINTS,
RESET_SKILLS
,NOT_ENOUGH_POINTS,
CANCEL_QUEST,
START_QUEST,
CLOSE_LOOT_CHEST,

View File

@ -77,7 +77,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;
@ -416,6 +416,19 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
return skillPoints;
}
public void giveSkillReallocationPoints(int value) {
skillReallocationPoints+=value;
}
public int countSkillPointsWhenReallocate() {
int sum = 0;
for(ClassSkill skill:getProfess().getSkills()) {
//0 if the skill is level 1(just unlocked) or 0 locked.
sum+=Math.max(0,getSkillLevel(skill.getSkill())-1);
}
return sum;
}
public int getAttributePoints() {
return attributePoints;
}
@ -531,6 +544,14 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
attributeReallocationPoints = Math.max(0, value);
}
public void setSkillReallocationPoints(int value) {
skillReallocationPoints = Math.max(0, value);
}
public int getSkillReallocationPoints() {
return skillReallocationPoints;
}
public void setSkillPoints(int value) {
skillPoints = Math.max(0, value);
}
@ -1038,7 +1059,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc
public void setBoundSkill(int slot, ClassSkill skill) {
Validate.notNull(skill, "Skill cannot be null");
if (boundSkills.size() < 6)
if (boundSkills.size() < getProfess().getMaxBoundSkills())
boundSkills.add(skill);
else
boundSkills.set(slot, skill);

View File

@ -31,12 +31,15 @@ import net.Indyuce.mmocore.loot.chest.particle.CastingParticle;
import net.Indyuce.mmocore.player.stats.StatInfo;
import net.Indyuce.mmocore.skill.ClassSkill;
import net.Indyuce.mmocore.skill.RegisteredSkill;
import net.Indyuce.mmocore.skill.cast.KeyCombo;
import net.Indyuce.mmocore.skill.cast.PlayerKey;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.craftbukkit.libs.org.apache.commons.lang3.Validate;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
@ -65,10 +68,16 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
@NotNull
private final CastingParticle castParticle;
private final int maxBoundSkills;
private final List<PassiveSkill> classScripts = new LinkedList();
private final Map<String, LinearValue> stats = new HashMap<>();
private final Map<String, ClassSkill> skills = new LinkedHashMap<>();
private final List<Subclass> subclasses = new ArrayList<>();
private final List<PassiveSkill> classScripts = new LinkedList<>();
// If the class redefines its own key combos.
private final Map<KeyCombo, Integer> combos = new HashMap<>();
private int longestCombo;
private final Map<PlayerResource, ResourceRegeneration> resourceHandlers = new HashMap<>();
@Deprecated
@ -110,7 +119,7 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
? MMOCore.plugin.experience.getCurveOrThrow(
config.get("exp-curve").toString().toLowerCase().replace("_", "-").replace(" ", "-"))
: ExpCurve.DEFAULT;
maxBoundSkills = config.getInt("max-bound-skills", 6);
ExperienceTable expTable = null;
if (config.contains("exp-table"))
try {
@ -132,6 +141,23 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load script '" + key + "' from class '" + id + "': " + exception.getMessage());
}
// Load different combos
if (config.contains("key-combos"))
for (String key : config.getConfigurationSection("key-combos").getKeys(false))
try {
int spellSlot = Integer.valueOf(key);
Validate.isTrue(spellSlot >= 0, "Spell slot must be at least 0");
Validate.isTrue(!combos.values().contains(spellSlot), "There is already a key combo with the same skill slot");
KeyCombo combo = new KeyCombo();
for (String str : config.getStringList("key-combos." + key))
combo.registerKey(PlayerKey.valueOf(UtilityMethods.enumName(str)));
combos.put(combo, spellSlot);
longestCombo = Math.max(longestCombo, combo.countKeys());
} catch (RuntimeException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load key combo '" + key + "': " + exception.getMessage());
}
if (config.contains("triggers"))
for (String key : config.getConfigurationSection("triggers").getKeys(false))
try {
@ -227,7 +253,7 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
this.icon = new ItemStack(material);
setOption(ClassOption.DISPLAY, false);
setOption(ClassOption.DEFAULT, false);
maxBoundSkills = 6;
for (PlayerResource resource : PlayerResource.values())
resourceHandlers.put(resource, new ResourceRegeneration(resource));
}
@ -283,6 +309,10 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
return expCurve;
}
public int getMaxBoundSkills() {
return maxBoundSkills;
}
@NotNull
public ExperienceTable getExperienceTable() {
return Objects.requireNonNull(expTable, "Class has no exp table");
@ -406,6 +436,15 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
return stats.keySet();
}
@Nullable
public Map<KeyCombo, Integer> getKeyCombos() {
return combos;
}
public int getLongestCombo() {
return longestCombo;
}
@NotNull
private LinearValue getStatInfo(String stat) {
LinearValue found = stats.get(stat);

View File

@ -50,6 +50,7 @@ public class CommandVerbose {
public enum CommandType {
ATTRIBUTE,
SKILL,
CLASS,
EXPERIENCE,
LEVEL,

View File

@ -6,33 +6,35 @@ import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
import org.bukkit.command.CommandSender;
public class AdminCommandTreeNode extends CommandTreeNode {
public AdminCommandTreeNode(CommandTreeNode parent) {
super(parent, "admin");
addChild(new HideActionBarCommandTreeNode(this));
addChild(new NoCooldownCommandTreeNode(this));
addChild(new ResetCommandTreeNode(this));
addChild(new InfoCommandTreeNode(this));
addChild(new ClassCommandTreeNode(this));
addChild(new ForceClassCommandTreeNode(this));
addChild(new ExportDataTreeNode(this));
public AdminCommandTreeNode(CommandTreeNode parent) {
super(parent, "admin");
addChild(new ExperienceCommandTreeNode(this));
addChild(new LevelCommandTreeNode(this));
addChild(new AttributeCommandTreeNode(this));
addChild(new HideActionBarCommandTreeNode(this));
addChild(new NoCooldownCommandTreeNode(this));
addChild(new ResetCommandTreeNode(this));
addChild(new InfoCommandTreeNode(this));
addChild(new ClassCommandTreeNode(this));
addChild(new ForceClassCommandTreeNode(this));
addChild(new ExportDataTreeNode(this));
addChild(new PointsCommandTreeNode("skill", this, PlayerData::setSkillPoints, PlayerData::giveSkillPoints, PlayerData::getSkillPoints));
addChild(new PointsCommandTreeNode("class", this, PlayerData::setClassPoints, PlayerData::giveClassPoints, PlayerData::getClassPoints));
addChild(new PointsCommandTreeNode("attribute", this, PlayerData::setAttributePoints, PlayerData::giveAttributePoints, PlayerData::getAttributePoints));
addChild(new PointsCommandTreeNode("attr-realloc", this, PlayerData::setAttributeReallocationPoints, PlayerData::giveAttributeReallocationPoints, PlayerData::getAttributeReallocationPoints));
addChild(new PointsCommandTreeNode("skill-tree-realloc",this,PlayerData::setSkillTreeReallocationPoints,PlayerData::giveSkillTreeReallocationPoints,PlayerData::getSkillTreeReallocationPoints));
addChild(new SkillTreePointsCommandTreeNode(this,(playerData,val,id)->playerData.setSkillTreePoints(id,val),(playerData, val, id)->playerData.giveSkillTreePoints(id,val),(playerData,id)->playerData.getSkillTreePoint(id)));
for (PlayerResource res : PlayerResource.values())
addChild(new ResourceCommandTreeNode(res.name().toLowerCase(), this, res));
}
addChild(new ExperienceCommandTreeNode(this));
addChild(new LevelCommandTreeNode(this));
addChild(new AttributeCommandTreeNode(this));
addChild(new SkillCommandTreeNode(this));
@Override
public CommandResult execute(CommandSender sender, String[] args) {
return CommandResult.THROW_USAGE;
}
addChild(new PointsCommandTreeNode("skill", this, PlayerData::setSkillPoints, PlayerData::giveSkillPoints, PlayerData::getSkillPoints));
addChild(new PointsCommandTreeNode("class", this, PlayerData::setClassPoints, PlayerData::giveClassPoints, PlayerData::getClassPoints));
addChild(new PointsCommandTreeNode("attribute", this, PlayerData::setAttributePoints, PlayerData::giveAttributePoints, PlayerData::getAttributePoints));
addChild(new PointsCommandTreeNode("attr-realloc", this, PlayerData::setAttributeReallocationPoints, PlayerData::giveAttributeReallocationPoints, PlayerData::getAttributeReallocationPoints));
addChild(new PointsCommandTreeNode("skill-realloc", this, PlayerData::setSkillReallocationPoints, PlayerData::giveSkillReallocationPoints, PlayerData::getSkillReallocationPoints));
addChild(new PointsCommandTreeNode("skill-tree-realloc", this, PlayerData::setSkillTreeReallocationPoints, PlayerData::giveSkillTreeReallocationPoints, PlayerData::getSkillTreeReallocationPoints));
for (PlayerResource res : PlayerResource.values())
addChild(new ResourceCommandTreeNode(res.name().toLowerCase(), this, res));
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
return CommandResult.THROW_USAGE;
}
}

View File

@ -0,0 +1,92 @@
package net.Indyuce.mmocore.command.rpg.admin;
import io.lumine.mythic.lib.command.api.CommandTreeNode;
import io.lumine.mythic.lib.command.api.Parameter;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.CommandVerbose;
import net.Indyuce.mmocore.skill.ClassSkill;
import net.Indyuce.mmocore.skill.RegisteredSkill;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Collection;
import java.util.List;
import java.util.function.BiFunction;
public class SkillCommandTreeNode extends CommandTreeNode {
public SkillCommandTreeNode(CommandTreeNode parent) {
super(parent, "skill");
addChild(new ActionCommandTreeNode(this, "give", (old, amount) -> old + amount));
addChild(new ActionCommandTreeNode(this, "set", (old, amount) -> amount));
}
public class ActionCommandTreeNode extends CommandTreeNode {
private final BiFunction<Integer, Integer, Integer> change;
public ActionCommandTreeNode(CommandTreeNode parent, String type, BiFunction<Integer, Integer, Integer> change) {
super(parent, type);
this.change = change;
addParameter(Parameter.PLAYER);
addParameter(new Parameter("<attribute>",
(explorer, list) -> MMOCore.plugin.skillManager.getAll().forEach(skill -> list.add(skill.getHandler().getId().toUpperCase()))));
addParameter(Parameter.AMOUNT);
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 6)
return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
return CommandResult.FAILURE;
}
PlayerData playerData = PlayerData.get(player);
RegisteredSkill skill = MMOCore.plugin.skillManager.getSkill(args[4]);
if (skill == null) {
sender.sendMessage(ChatColor.RED + "Could not find the skill called " + args[4] + ".");
return CommandResult.FAILURE;
}
ClassSkill classSkill=null;
for(ClassSkill var:playerData.getProfess().getSkills()) {
if(var.getSkill().equals(skill))
classSkill=var;
}
if(classSkill==null||classSkill.getUnlockLevel() > playerData.getLevel()) {
sender.sendMessage(ChatColor.RED+ skill.getName()+" is not unlockable for "+player.getName()+".");
return CommandResult.FAILURE;
}
int amount;
try {
amount = Integer.parseInt(args[5]);
} catch (Exception e) {
sender.sendMessage(ChatColor.RED + args[5] + " is not a valid number.");
return CommandResult.FAILURE;
}
int value = change.apply(playerData.getSkillLevel(skill), amount);
playerData.setSkillLevel(skill, value);
CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.GOLD + player.getName() + ChatColor.YELLOW
+ " is now level " + ChatColor.GOLD + value + ChatColor.YELLOW + " for " + skill.getName() + ".");
return CommandResult.SUCCESS;
}
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
return CommandResult.THROW_USAGE;
}
}

View File

@ -4,6 +4,7 @@ import io.lumine.mythic.lib.MythicLib;
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.SoundEvent;
import net.Indyuce.mmocore.gui.api.InventoryClickContext;
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
@ -14,6 +15,7 @@ import net.Indyuce.mmocore.gui.api.GeneratedInventory;
import net.Indyuce.mmocore.gui.api.item.Placeholders;
import net.Indyuce.mmocore.skill.ClassSkill;
import net.Indyuce.mmocore.skill.RegisteredSkill;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Sound;
@ -46,6 +48,23 @@ public class SkillList extends EditableInventory {
if (function.equals("upgrade"))
return new UpgradeItem(config);
if (function.equals("reallocation")) {
return new InventoryItem(config) {
@Override
public Placeholders getPlaceholders(GeneratedInventory inv, int n) {
Placeholders holders = new Placeholders();
holders.register("skill_points", inv.getPlayerData().getSkillPoints());
holders.register("points", inv.getPlayerData().getSkillReallocationPoints());
holders.register("total", inv.getPlayerData().countSkillPointsWhenReallocate());
return holders;
}
};
}
if (function.equals("slot"))
return new InventoryItem<SkillViewerInventory>(config) {
private final String none = MythicLib.plugin.parseColors(config.getString("no-skill"));
@ -70,6 +89,9 @@ public class SkillList extends EditableInventory {
@Override
public ItemStack display(SkillViewerInventory inv, int n) {
if (n >= inv.getPlayerData().getProfess().getMaxBoundSkills()) {
return new ItemStack(Material.AIR);
}
ItemStack item = super.display(inv, n);
if (!inv.getPlayerData().hasSkillBound(n)) {
item.setType(emptyMaterial);
@ -225,27 +247,27 @@ public class SkillList extends EditableInventory {
return new Placeholders();
}
}
public class UpgradeItem extends InventoryItem<SkillViewerInventory> {
private int shiftCost=1;
private int shiftCost = 1;
public UpgradeItem(ConfigurationSection config) {
super(config);
if(config.contains("shift-cost")) {
if (config.contains("shift-cost")) {
this.shiftCost = config.getInt("shift-cost");
if (shiftCost < 1) {
MMOCore.log(Level.WARNING, "Upgrade shift-cost cannot be less than 1. Using default value: 1");
shiftCost = 1;
}
}
}
@Override
public Placeholders getPlaceholders(SkillViewerInventory inv, int n) {
RegisteredSkill selected = inv.selected == null ? null : inv.selected.getSkill();
Placeholders holders = new Placeholders();
holders.register("skill_caps", selected.getName().toUpperCase());
holders.register("skill", selected.getName());
holders.register("skill_points", "" + inv.getPlayerData().getSkillPoints());
@ -253,7 +275,7 @@ public class SkillList extends EditableInventory {
return holders;
}
}
public class SkillViewerInventory extends GeneratedInventory {
// Cached information
@ -305,6 +327,35 @@ public class SkillList extends EditableInventory {
return;
}
if(item.getFunction().equals("reallocation")) {
int spent= getPlayerData().countSkillPointsWhenReallocate();
if (spent < 1) {
MMOCore.plugin.configManager.getSimpleMessage("no-skill-points-spent").send(player);
MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer());
return;
}
if (playerData.getSkillReallocationPoints() < 1) {
MMOCore.plugin.configManager.getSimpleMessage("not-skill-reallocation-point").send(player);
MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer());
return;
}
for(ClassSkill skill:playerData.getProfess().getSkills()) {
playerData.setSkillLevel(skill.getSkill(), 1);
}
playerData.giveSkillPoints(spent);
playerData.setSkillReallocationPoints(playerData.getSkillReallocationPoints()-1);
MMOCore.plugin.configManager.getSimpleMessage("skill-points-reallocated", "points", "" + playerData.getSkillPoints()).send(player);
MMOCore.plugin.soundManager.getSound(SoundEvent.RESET_SKILLS).playTo(getPlayer());
open();
}
if (item.getFunction().equals("previous")) {
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 1, 2);
page--;
@ -325,15 +376,13 @@ public class SkillList extends EditableInventory {
if (item.getFunction().equals("slot")) {
int index = slotSlots.indexOf(context.getSlot());
// unbind if there is a current spell.
KEy // unbind if there is a current spell.
if (context.getClickType() == ClickType.RIGHT) {
if (!playerData.hasSkillBound(index)) {
MMOCore.plugin.configManager.getSimpleMessage("no-skill-bound").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.unbindSkill(index);
open();
@ -349,6 +398,7 @@ public class SkillList extends EditableInventory {
return;
}
if (!playerData.hasSkillUnlocked(selected)) {
MMOCore.plugin.configManager.getSimpleMessage("not-unlocked-skill").send(player);
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
@ -367,7 +417,7 @@ public class SkillList extends EditableInventory {
*/
if (item.getFunction().equals("upgrade")) {
int shiftCost = ((UpgradeItem) item).shiftCost;
if (!playerData.hasSkillUnlocked(selected)) {
MMOCore.plugin.configManager.getSimpleMessage("not-unlocked-skill").send(player);
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
@ -385,21 +435,21 @@ public class SkillList extends EditableInventory {
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
return;
}
if (context.getClickType().isShiftClick()) {
if (playerData.getSkillPoints() < shiftCost) {
MMOCore.plugin.configManager.getSimpleMessage("not-enough-skill-points-shift", "shift_points", "" + shiftCost).send(player);
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
return;
}
playerData.giveSkillPoints(-shiftCost);
playerData.setSkillLevel(selected.getSkill(), playerData.getSkillLevel(selected.getSkill()) + shiftCost);
} else {
playerData.giveSkillPoints(-1);
playerData.setSkillLevel(selected.getSkill(), playerData.getSkillLevel(selected.getSkill()) + 1);
}
MMOCore.plugin.configManager.getSimpleMessage("upgrade-skill", "skill", selected.getSkill().getName(), "level",
"" + playerData.getSkillLevel(selected.getSkill())).send(player);
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1, 2);

View File

@ -19,11 +19,11 @@ import java.util.logging.Level;
public abstract class EditableInventory {
private final String id;
private FileConfiguration config;
private AdaptorType adaptorType;
private String name;
private int slots;
protected double radius, angleGap, verticalGap, curvature, verticalOffset, interactSensitivity;
/*
* This set is linked so it keeps the order/priority in
@ -39,17 +39,10 @@ public abstract class EditableInventory {
}
public void reload(FileConfiguration config) {
this.config = config;
this.adaptorType = AdaptorType.valueOf(UtilityMethods.enumName(config.getString("adaptor-type", "classic-adaptor")));
Validate.notNull(adaptorType, config.getString("adaptor-type") + " does not correspond to an adaptor-type.");//TODO
this.radius = config.getDouble("radius", 2);
this.angleGap = config.getDouble("angle-gap", 10);
this.verticalGap = config.getDouble("vertical-gap", 1);
this.curvature = config.getDouble("curvature", 1);
this.verticalOffset = config.getDouble("vertical-offset", 0);
this.interactSensitivity = config.getDouble("interact-sensitivity", 0.97);
this.name = config.getString("name");
Validate.notNull(name, "Name must not be null");
@ -91,28 +84,9 @@ public abstract class EditableInventory {
return adaptorType;
}
public double getRadius() {
return radius;
}
public double getAngleGap() {
return angleGap;
}
public double getVerticalGap() {
return verticalGap;
}
public double getInteractSensitivity() {
return interactSensitivity;
}
public double getCurvature() {
return curvature;
}
public double getVerticalOffset() {
return verticalOffset;
public FileConfiguration getConfig() {
return config;
}
public InventoryItem getByFunction(String function) {

View File

@ -20,7 +20,6 @@ public abstract class GeneratedInventory extends PluginInventory {
public GeneratedInventory(PlayerData playerData, EditableInventory editable) {
super(playerData);
this.editable = editable;
this.adaptor = editable.getAdaptorType().supply(this);
}
@ -30,6 +29,7 @@ public abstract class GeneratedInventory extends PluginInventory {
}
public EditableInventory getEditable() {
return editable;
}
@ -62,8 +62,8 @@ public abstract class GeneratedInventory extends PluginInventory {
return ((ClassicAdaptor) adaptor).getInventory();
}
@Override
public void open() {
/*
* Very important, in order to prevent ghost items, the loaded items map
* must be cleared when the inventory is updated or open at least twice
@ -75,7 +75,7 @@ public abstract class GeneratedInventory extends PluginInventory {
/**
* @deprecated Not a fan of that implementation.
* Better work with {@link InventoryItem#setDisplayed(Inventory, GeneratedInventory)}
* Better work with {@link InventoryItem#setDisplayed(Inventory, GeneratedInventory)}
*/
@Deprecated
public void dynamicallyUpdateItem(InventoryItem<?> item, int n, ItemStack placed, Consumer<ItemStack> update) {
@ -83,6 +83,7 @@ public abstract class GeneratedInventory extends PluginInventory {
}
@Override
public void whenClicked(InventoryClickContext context) {
context.setCancelled(true);
InventoryItem item = getBySlot(context.getSlot());

View File

@ -48,10 +48,13 @@ public class ThreeDimAdaptor extends Adaptor {
private final HashMap<ItemStack, ArmorStand> hiddenArmorStand = new HashMap<>();
protected double radius, angleGap, verticalGap, curvature, verticalOffset, interactSensitivity;
private boolean firstTime = true;
private final Vector direction = generated.getPlayer().getEyeLocation().getDirection().setY(0);
private final Location location = generated.getPlayer().getLocation().add(new Vector(0, generated.getEditable().getVerticalOffset(), 0));
private final Location location;
//Zoomed=-1 no armorstand are under zoom
private int zoomed = -1;
@ -59,6 +62,14 @@ public class ThreeDimAdaptor extends Adaptor {
public ThreeDimAdaptor(GeneratedInventory generated) {
super(generated);
this.radius = generated.getEditable().getConfig().getDouble("radius", 2);
this.angleGap = generated.getEditable().getConfig().getDouble("angle-gap", 10);
this.verticalGap = generated.getEditable().getConfig().getDouble("vertical-gap", 1);
this.curvature = generated.getEditable().getConfig().getDouble("curvature", 1);
this.verticalOffset = generated.getEditable().getConfig().getDouble("vertical-offset", 0);
this.interactSensitivity = generated.getEditable().getConfig().getDouble("interact-sensitivity", 0.97);
location = generated.getPlayer().getLocation().add(new Vector(0, verticalOffset, 0));
}
@ -180,9 +191,12 @@ public class ThreeDimAdaptor extends Adaptor {
private void setItem(ItemStack item, int n, double percentage) {
Location location = getLocation(n, percentage);
if(item.getType().toString().contains("SKULL")||item.getType().toString().contains("HEAD")) {
location.add(new Vector(0,4.9,0));
}
//We create the armorStand corresponding to display the item
ArmorStand armorStand = (ArmorStand) generated.getPlayer().getWorld().spawnEntity(location, EntityType.ARMOR_STAND);
armorStand.setVisible(false);
armorStand.setVisible(true);
armorStand.setSmall(false);
armorStand.setArms(true);
armorStand.setGravity(false);
@ -317,13 +331,13 @@ public class ThreeDimAdaptor extends Adaptor {
Location cloneLocation = location.clone();
Vector cloneDirection = direction.clone().rotateAroundAxis(new Vector(0, 1, 0),
-((n % 9) - 4) * generated.getEditable().getAngleGap() * Math.PI / 180);
-((n % 9) - 4) * angleGap * Math.PI / 180);
//Curvature of 1: r=cst Curvature of 1: r=R/cos(angle) (a plane)
double radius = percentage * generated.getEditable().getRadius() / Math.cos((1 - generated.getEditable().getCurvature())
* -((n % 9) - 4) * generated.getEditable().getAngleGap() * Math.PI / 180);
double radius = percentage * this.radius / Math.cos((1 - curvature)
* -((n % 9) - 4) * angleGap * Math.PI / 180);
cloneDirection = cloneDirection.normalize().multiply(radius);
cloneDirection.add(new Vector(0, percentage * generated.getEditable().getVerticalGap() * ((generated.getEditable().getSlots() - n - 1) / 9), 1));
cloneDirection.add(new Vector(0, percentage * verticalGap * ((generated.getEditable().getSlots() - n - 1) / 9), 1));
//We get the final direction
cloneLocation.add(cloneDirection);
@ -380,33 +394,36 @@ public class ThreeDimAdaptor extends Adaptor {
if (!e.getFrom().getBlock().getLocation().equals(e.getTo().getBlock().getLocation()))
ThreeDimAdaptor.this.close();
else {
//If the player no longer looks at the zoom as:
if (zoomed != -1 && generated.getPlayer().getLocation().getDirection().normalize().dot(
armorStands.get(zoomed).getLocation().add(new Vector(0, 0.25 * armorStands.get(zoomed).getHeight(), 0))
.subtract(generated.getPlayer().getLocation()).toVector().normalize()) < generated.getEditable().getInteractSensitivity()) {
armorStands.get(zoomed).teleport(getLocation(zoomed, 1));
zoomed = -1;
removeLore();
int closest = -1;
double closestScalar = 1;
for (int n : armorStands.keySet()) {
ArmorStand as = armorStands.get(n);
Location asLocation = as.getLocation().add(new Vector(0, 0.25 * as.getHeight(), 0));
double scalar = generated.getPlayer().getLocation().getDirection().normalize().dot(
asLocation.subtract(generated.getPlayer().getLocation()).toVector().normalize());
if (scalar > interactSensitivity && scalar < closestScalar) {
closestScalar = scalar;
closest = n;
}
}
if (zoomed == -1) {
for (int n : armorStands.keySet()) {
ArmorStand as = armorStands.get(n);
Location asLocation = as.getLocation().add(new Vector(0, 0.25 * as.getHeight(), 0));
double scalar = generated.getPlayer().getLocation().getDirection().normalize().dot(
asLocation.subtract(generated.getPlayer().getLocation()).toVector().normalize());
if (scalar > generated.getEditable().getInteractSensitivity()) {
as.teleport(getLocation(n, 0.75));
zoomed = n;
displayLore(zoomed);
}
if (closest != zoomed) {
if (zoomed != -1) {
removeLore();
armorStands.get(zoomed).teleport(getLocation(zoomed, 1));
}
if (closest != -1) {
armorStands.get(zoomed).teleport(getLocation(closest, 0.75));
zoomed = closest;
displayLore(closest);
}
}
}
}
@ -416,7 +433,11 @@ public class ThreeDimAdaptor extends Adaptor {
@EventHandler
public void onInteract(PlayerInteractAtEntityEvent event) {
if (event.getPlayer().equals(generated.getPlayer()))
if (event.getRightClicked() instanceof ArmorStand armorStand) {
if (event.getRightClicked() instanceof ArmorStand armorStand)
event.setCancelled(true);
/*
if (armorStands.values().contains(armorStand)) {
PersistentDataContainer container = armorStand.getPersistentDataContainer();
int slot = container.get(new NamespacedKey(MMOCore.plugin, "slot"), PersistentDataType.INTEGER);
@ -428,6 +449,7 @@ public class ThreeDimAdaptor extends Adaptor {
generated.whenClicked(new InventoryClickContext(slot, armorStand.getEquipment().getItem(EquipmentSlot.HEAD), clickType, event));
}
}
*/
}
@EventHandler
@ -465,35 +487,40 @@ public class ThreeDimAdaptor extends Adaptor {
}
}
@EventHandler
public void onDamage(EntityDamageByEntityEvent event) {
if (event.getDamager() instanceof Player player) {
if (event.getDamager() instanceof Player player)
if (player.equals(generated.getPlayer()))
if (event.getEntity() instanceof ArmorStand armorStand) {
if (armorStands.values().contains(armorStand)) {
PersistentDataContainer container = armorStand.getPersistentDataContainer();
int slot = container.get(new NamespacedKey(MMOCore.plugin, "slot"), PersistentDataType.INTEGER);
ClickType clickType;
if (player.isSneaking())
clickType = ClickType.SHIFT_LEFT;
else
clickType = ClickType.LEFT;
ItemStack itemStack = armorStand.getEquipment().getItem(EquipmentSlot.HEAD);
generated.whenClicked(new InventoryClickContext(slot, itemStack, clickType, event));
}
}
}
if (event.getEntity() instanceof ArmorStand armorStand)
if (armorStands.values().contains(armorStand))
event.setCancelled(true);
}
/*
PersistentDataContainer container = armorStand.getPersistentDataContainer();
int slot = container.get(new NamespacedKey(MMOCore.plugin, "slot"), PersistentDataType.INTEGER);
ClickType clickType;
if(player.isSneaking())
clickType =ClickType.SHIFT_LEFT;
else
clickType =ClickType.LEFT;
ItemStack itemStack = armorStand.getEquipment().getItem(EquipmentSlot.HEAD);
generated.whenClicked(new
InventoryClickContext(slot, itemStack, clickType, event));
}
}
}
*/
@Override
public void whenClosed() {
}
}
}

View File

@ -13,6 +13,7 @@ import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerSwapHandItemsEvent;
import org.bukkit.event.player.PlayerToggleSneakEvent;
import org.bukkit.inventory.EquipmentSlot;
/**
* This registers all the KeyPress events. All events are registered
@ -32,7 +33,7 @@ public class PlayerPressKeyListener implements Listener {
@EventHandler(priority = EventPriority.LOWEST)
public void registerClickKey(PlayerInteractEvent event) {
if (event.useItemInHand() != Event.Result.DENY && event.getAction().name().contains("CLICK")) {
if (event.useItemInHand() != Event.Result.DENY && event.getAction().name().contains("CLICK")&&event.getHand().equals(EquipmentSlot.HAND)) {
boolean rightClick = event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK;
PlayerKeyPressEvent called = new PlayerKeyPressEvent(PlayerData.get(event.getPlayer()), rightClick ? PlayerKey.RIGHT_CLICK : PlayerKey.LEFT_CLICK, event);
Bukkit.getPluginManager().callEvent(called);

View File

@ -28,7 +28,7 @@ public class ConfigManager {
public ChatColor staminaFull, staminaHalf, staminaEmpty;
public long combatLogTimer, lootChestExpireTime, lootChestPlayerCooldown, globalSkillCooldown;
public double lootChestsChanceWeight, fishingDropsChanceWeight;
public int maxPartyLevelDifference;
public int maxPartyLevelDifference,maxBoundSkills;
private final FileConfiguration messages;
@ -116,6 +116,7 @@ public class ConfigManager {
canCreativeCast = MMOCore.plugin.getConfig().getBoolean("can-creative-cast");
cobbleGeneratorXP = MMOCore.plugin.getConfig().getBoolean("should-cobblestone-generators-give-exp");
saveDefaultClassInfo = MMOCore.plugin.getConfig().getBoolean("save-default-class-info");
maxBoundSkills= MMOCore.plugin.getConfig().getInt("max-bound-skills",6);
}
private ChatColor getColorOrDefault(String key, ChatColor defaultColor) {

View File

@ -26,6 +26,7 @@ public class SkillManager implements MMOCoreManager {
skills.put(skill.getHandler().getId().toUpperCase(), skill);
}
@Nullable
public RegisteredSkill getSkill(String id) {
return skills.get(id.toUpperCase());

View File

@ -16,7 +16,7 @@ import java.util.*;
public abstract class PlayerDataManager {
private final static Map<UUID, PlayerData> data = Collections.synchronizedMap(new HashMap<>());
private DefaultPlayerData defaultData = new DefaultPlayerData(1, 0, 0, 0, 0);
private DefaultPlayerData defaultData = new DefaultPlayerData(1, 0, 0, 0, 0,0);
public PlayerData get(OfflinePlayer player) {
return get(player.getUniqueId());
@ -134,7 +134,7 @@ public abstract class PlayerDataManager {
public abstract void saveData(PlayerData data);
public class DefaultPlayerData {
private final int level, classPoints, skillPoints, attributePoints, attrReallocPoints;
private final int level, classPoints, skillPoints, attributePoints, attrReallocPoints,skillReallocPoints;
public DefaultPlayerData(ConfigurationSection config) {
level = config.getInt("level", 1);
@ -142,14 +142,17 @@ public abstract class PlayerDataManager {
skillPoints = config.getInt("skill-points");
attributePoints = config.getInt("attribute-points");
attrReallocPoints = config.getInt("attribute-realloc-points");
skillReallocPoints=config.getInt("skill-realloc-points",0);
}
public DefaultPlayerData(int level, int classPoints, int skillPoints, int attributePoints, int attrReallocPoints) {
public DefaultPlayerData(int level, int classPoints, int skillPoints, int attributePoints, int attrReallocPoints,int skillReallocPoints) {
this.level = level;
this.classPoints = classPoints;
this.skillPoints = skillPoints;
this.attributePoints = attributePoints;
this.attrReallocPoints = attrReallocPoints;
this.skillReallocPoints=skillReallocPoints;
}
public int getLevel() {
@ -172,6 +175,10 @@ public abstract class PlayerDataManager {
return attributePoints;
}
public int getSkillReallocPoints() {
return skillReallocPoints;
}
public void apply(PlayerData player) {
player.setLevel(level);
player.setClassPoints(classPoints);

View File

@ -35,6 +35,11 @@ public class MySQLPlayerDataManager extends PlayerDataManager {
BukkitRunnable runnable = new BukkitRunnable() {
@Override
public void run() {
//To prevent infinite loops
if (System.currentTimeMillis() - startTime > 4000) {
cancel();
return;
}
provider.getResult("SELECT * FROM mmocore_playerdata WHERE uuid = '" + data.getUniqueId() + "';", (result) -> {
try {
@ -55,6 +60,7 @@ public class MySQLPlayerDataManager extends PlayerDataManager {
data.setClassPoints(result.getInt("class_points"));
data.setSkillPoints(result.getInt("skill_points"));
data.setSkillReallocationPoints(result.getInt("skill_reallocation_points"));
data.setAttributePoints(result.getInt("attribute_points"));
data.setAttributeReallocationPoints(result.getInt("attribute_realloc_points"));
data.setLevel(result.getInt("level"));
@ -121,6 +127,7 @@ public class MySQLPlayerDataManager extends PlayerDataManager {
data.setLevel(getDefaultData().getLevel());
data.setClassPoints(getDefaultData().getClassPoints());
data.setSkillPoints(getDefaultData().getSkillPoints());
data.setSkillReallocationPoints(getDefaultData().getSkillReallocPoints());
data.setAttributePoints(getDefaultData().getAttributePoints());
data.setAttributeReallocationPoints(getDefaultData().getAttrReallocPoints());
data.setExperience(0);
@ -145,11 +152,12 @@ public class MySQLPlayerDataManager extends PlayerDataManager {
@Override
public void saveData(PlayerData data) {
MySQLTableEditor sql = new MySQLTableEditor(MySQLTableEditor.Table.PLAYERDATA, data.getUniqueId(),provider);
MySQLTableEditor sql = new MySQLTableEditor(MySQLTableEditor.Table.PLAYERDATA, data.getUniqueId(), provider);
MMOCore.sqlDebug("Saving data for: '" + data.getUniqueId() + "'...");
sql.updateData("class_points", data.getClassPoints());
sql.updateData("skill_points", data.getSkillPoints());
sql.updateData("skill_reallocation_points",data.getSkillReallocationPoints());
sql.updateData("attribute_points", data.getAttributePoints());
sql.updateData("attribute_realloc_points", data.getAttributeReallocationPoints());
sql.updateData("level", data.getLevel());

View File

@ -30,6 +30,7 @@ public class YAMLPlayerDataManager extends PlayerDataManager {
data.setClassPoints(config.getInt("class-points", getDefaultData().getClassPoints()));
data.setSkillPoints(config.getInt("skill-points", getDefaultData().getSkillPoints()));
data.setSkillReallocationPoints(config.getInt("skill-reallocation-points",getDefaultData().getSkillReallocPoints()));
data.setAttributePoints(config.getInt("attribute-points", getDefaultData().getAttributePoints()));
data.setAttributeReallocationPoints(config.getInt("attribute-realloc-points", getDefaultData().getAttrReallocPoints()));
data.setLevel(config.getInt("level", getDefaultData().getLevel()));
@ -90,6 +91,7 @@ public class YAMLPlayerDataManager extends PlayerDataManager {
config.set("class-points", data.getClassPoints());
config.set("skill-points", data.getSkillPoints());
config.set("skill-reallocation-points",data.getSkillReallocationPoints());
config.set("attribute-points", data.getAttributePoints());
// config.set("skill-realloc-points", skillReallocationPoints);
config.set("attribute-realloc-points", data.getAttributeReallocationPoints());

View File

@ -49,13 +49,6 @@ public class KeyCombos implements Listener {
@Nullable
private final SoundObject beginComboSound, comboClickSound, failComboSound;
/**
* Essentially the inverse of the {@link #combos} map. This maps
* the skill slot to the corresponding key combo. There's no problem
* because the maps are 100% bijective
*/
private static final Map<Integer, KeyCombo> PUBLIC_COMBOS = new HashMap<>();
public KeyCombos(ConfigurationSection config) {
int longestCombo = 0;
@ -72,8 +65,6 @@ public class KeyCombos implements Listener {
combos.put(combo, spellSlot);
longestCombo = Math.max(longestCombo, combo.countKeys());
PUBLIC_COMBOS.put(spellSlot, combo);
} catch (RuntimeException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load key combo '" + key + "': " + exception.getMessage());
}
@ -112,6 +103,7 @@ public class KeyCombos implements Listener {
}
// Adding pressed key
CustomSkillCastingHandler casting = (CustomSkillCastingHandler) playerData.getSkillCasting();
casting.current.registerKey(event.getPressed());
@ -123,8 +115,8 @@ public class KeyCombos implements Listener {
event.setCancelled(true);
// Hash current combo and check
if (combos.containsKey(casting.current)) {
int spellSlot = combos.get(casting.current) - 1;
if (casting.classCombos.containsKey(casting.current)) {
int spellSlot = casting.classCombos.get(casting.current) - 1;
playerData.leaveCastingMode();
// Cast spell
@ -136,7 +128,7 @@ public class KeyCombos implements Listener {
}
// Check if current combo is too large
if (casting.current.countKeys() >= longestCombo) {
if (casting.current.countKeys() >= casting.classLongestCombo) {
playerData.leaveCastingMode();
if (failComboSound != null)
failComboSound.playTo(player);
@ -167,20 +159,36 @@ public class KeyCombos implements Listener {
event.setCancelled(true);
}
/**
* Loads the player current combos & the combos applicable to the player (combos defined in its class or the default combos of the config.yml)
*/
private class CustomSkillCastingHandler extends SkillCastingHandler {
private final KeyCombo current = new KeyCombo();
//Combos used: default combos from the config or the combos defined in the player class.
private final Map<KeyCombo, Integer> classCombos;
private int classLongestCombo;
CustomSkillCastingHandler(PlayerData caster) {
super(caster, 10);
if (!caster.getProfess().getKeyCombos().isEmpty()) {
classCombos=caster.getProfess().getKeyCombos();
classLongestCombo=caster.getProfess().getLongestCombo();
} else {
classCombos = combos;
classLongestCombo=longestCombo;
}
}
@Override
public void onTick() {
if (actionBarOptions != null)
getCaster().displayActionBar(actionBarOptions.format(current));
getCaster().displayActionBar(actionBarOptions.format(this));
}
}
private class ActionBarOptions {
private final String separator, noKey;
@ -198,18 +206,19 @@ public class KeyCombos implements Listener {
keyNames.put(key, Objects.requireNonNull(config.getString("key-name." + key.name()), "Could not find translation for key " + key.name()));
}
public String format(KeyCombo currentCombo) {
public String format(CustomSkillCastingHandler casting) {
// Join all keys with separator
String builder = currentCombo.countKeys() == 0 ? noKey : keyNames.get(currentCombo.getAt(0));
String builder = casting.current.countKeys() == 0 ? noKey : keyNames.get(casting.current.getAt(0));
int j = 1;
for (; j < currentCombo.countKeys(); j++)
builder += separator + keyNames.get(currentCombo.getAt(j));
for (; j < casting.current.countKeys(); j++)
builder += separator + keyNames.get(casting.current.getAt(j));
// All remaining
for (; j < longestCombo; j++)
for (; j < casting.classLongestCombo; j++)
builder += separator + noKey;
return MythicLib.plugin.parseColors(builder);
}
}

View File

@ -17,124 +17,131 @@ import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.Objects;
public class SkillBar implements Listener {
private final PlayerKey mainKey;
private final PlayerKey mainKey;
public SkillBar(ConfigurationSection config) {
mainKey = PlayerKey.valueOf(UtilityMethods.enumName(Objects.requireNonNull(config.getString("open"), "Could not find open key")));
}
public SkillBar(ConfigurationSection config) {
mainKey = PlayerKey.valueOf(UtilityMethods.enumName(Objects.requireNonNull(config.getString("open"), "Could not find open key")));
}
@EventHandler
public void a(PlayerKeyPressEvent event) {
if (event.getPressed() != mainKey) return;
@EventHandler
public void a(PlayerKeyPressEvent event) {
if (event.getPressed() != mainKey) return;
// Always cancel event
if (event.getPressed().shouldCancelEvent()) event.setCancelled(true);
// Always cancel event
if (event.getPressed().shouldCancelEvent()) event.setCancelled(true);
// Enter spell casting
Player player = event.getData().getPlayer();
PlayerData playerData = event.getData();
if (player.getGameMode() != GameMode.SPECTATOR && (MMOCore.plugin.configManager.canCreativeCast || player.getGameMode() != GameMode.CREATIVE) && !playerData.isCasting() && !playerData.getBoundSkills()
.isEmpty()) {
playerData.setSkillCasting(new CustomSkillCastingHandler(playerData));
MMOCore.plugin.soundManager.getSound(SoundEvent.SPELL_CAST_BEGIN).playTo(player);
}
}
// Enter spell casting
Player player = event.getData().getPlayer();
PlayerData playerData = event.getData();
if (player.getGameMode() != GameMode.SPECTATOR && (MMOCore.plugin.configManager.canCreativeCast || player.getGameMode() != GameMode.CREATIVE) && !playerData.isCasting() && !playerData.getBoundSkills()
.isEmpty()) {
playerData.setSkillCasting(new CustomSkillCastingHandler(playerData));
MMOCore.plugin.soundManager.getSound(SoundEvent.SPELL_CAST_BEGIN).playTo(player);
}
}
private class CustomSkillCastingHandler extends SkillCastingHandler {
private final String ready = MMOCore.plugin.configManager.getSimpleMessage("casting.action-bar.ready").message();
private final String onCooldown = MMOCore.plugin.configManager.getSimpleMessage("casting.action-bar.on-cooldown").message();
private final String noMana = MMOCore.plugin.configManager.getSimpleMessage("casting.action-bar.no-mana").message();
private final String noStamina = MMOCore.plugin.configManager.getSimpleMessage("casting.action-bar.no-stamina").message();
private final String split = MMOCore.plugin.configManager.getSimpleMessage("casting.split").message();
private class CustomSkillCastingHandler extends SkillCastingHandler {
private final String ready = MMOCore.plugin.configManager.getSimpleMessage("casting.action-bar.ready").message();
private final String onCooldown = MMOCore.plugin.configManager.getSimpleMessage("casting.action-bar.on-cooldown").message();
private final String noMana = MMOCore.plugin.configManager.getSimpleMessage("casting.action-bar.no-mana").message();
private final String noStamina = MMOCore.plugin.configManager.getSimpleMessage("casting.action-bar.no-stamina").message();
private final String split = MMOCore.plugin.configManager.getSimpleMessage("casting.split").message();
private int j;
private int j;
CustomSkillCastingHandler(PlayerData playerData) {
super(playerData, 1);
}
CustomSkillCastingHandler(PlayerData playerData) {
super(playerData, 1);
}
@EventHandler
public void onSkillCast(PlayerItemHeldEvent event) {
Player player = event.getPlayer();
if (!getCaster().isOnline()) return;
if (!event.getPlayer().equals(getCaster().getPlayer())) return;
@EventHandler
public void onSkillCast(PlayerItemHeldEvent event) {
Player player = event.getPlayer();
if (!getCaster().isOnline()) return;
if (!event.getPlayer().equals(getCaster().getPlayer())) return;
/*
* When the event is cancelled, another playerItemHeldEvent is
* called and previous and next slots are equal. the event must not
* listen to that non-player called event.
*/
if (event.getPreviousSlot() == event.getNewSlot()) return;
/*
* When the event is cancelled, another playerItemHeldEvent is
* called and previous and next slots are equal. the event must not
* listen to that non-player called event.
*/
if (event.getPreviousSlot() == event.getNewSlot()) return;
event.setCancelled(true);
int slot = event.getNewSlot() + (event.getNewSlot() >= player.getInventory().getHeldItemSlot() ? -1 : 0);
event.setCancelled(true);
int slot = event.getNewSlot() + (event.getNewSlot() >= player.getInventory().getHeldItemSlot() ? -1 : 0);
/*
* The event is called again soon after the first since when
* cancelling the first one, the player held item slot must go back
* to the previous one.
*/
if (slot >= 0 && getCaster().hasSkillBound(slot)) {
PlayerMetadata caster = getCaster().getMMOPlayerData().getStatMap().cache(EquipmentSlot.MAIN_HAND);
getCaster().getBoundSkill(slot).toCastable(getCaster()).cast(new TriggerMetadata(caster, null, null));
}
}
/*
* The event is called again soon after the first since when
* cancelling the first one, the player held item slot must go back
* to the previous one.
*/
if (slot >= 0 && getCaster().hasSkillBound(slot)) {
PlayerMetadata caster = getCaster().getMMOPlayerData().getStatMap().cache(EquipmentSlot.MAIN_HAND);
getCaster().getBoundSkill(slot).toCastable(getCaster()).cast(new TriggerMetadata(caster, null, null));
}
}
@EventHandler
public void stopCasting(PlayerKeyPressEvent event) {
Player player = event.getPlayer();
if (event.getPressed() == mainKey && event.getPlayer().equals(getCaster().getPlayer())) {
MMOCore.plugin.soundManager.getSound(SoundEvent.SPELL_CAST_END).playTo(player);
MMOCore.plugin.configManager.getSimpleMessage("casting.no-longer").send(getCaster().getPlayer());
PlayerData.get(player).leaveCastingMode();
}
}
@EventHandler
public void stopCasting(PlayerKeyPressEvent event) {
Player player = event.getPlayer();
if (event.getPressed() == mainKey && event.getPlayer().equals(getCaster().getPlayer())) {
MMOCore.plugin.soundManager.getSound(SoundEvent.SPELL_CAST_END).playTo(player);
private String getFormat(PlayerData data) {
StringBuilder str = new StringBuilder();
if (!data.isOnline()) return str.toString();
for (int j = 0; j < data.getBoundSkills().size(); j++) {
ClassSkill skill = data.getBoundSkill(j);
str.append((str.length() == 0) ? "" : split).append((onCooldown(data, skill) ? onCooldown.replace("{cooldown}",
String.valueOf(data.getCooldownMap().getInfo(skill).getRemaining() / 1000)) : noMana(data, skill) ? noMana : (noStamina(
data, skill) ? noStamina : ready)).replace("{index}",
"" + (j + 1 + (data.getPlayer().getInventory().getHeldItemSlot() <= j ? 1 : 0)))
.replace("{skill}", data.getBoundSkill(j).getSkill().getName()));
}
return MMOCore.plugin.placeholderParser.parse(data.getPlayer(),str.toString());
}
new BukkitRunnable() {
@Override
public void run() {
MMOCore.plugin.configManager.getSimpleMessage("casting.no-longer").send(getCaster().getPlayer());
}
}.runTask(MMOCore.plugin);
PlayerData.get(player).leaveCastingMode();
}
}
/**
* We don't even need to check if the skill has the 'cooldown'
* modifier. We just look for an entry in the cooldown map which
* won't be here if the skill has no cooldown.
*/
private boolean onCooldown(PlayerData data, ClassSkill skill) {
return data.getCooldownMap().isOnCooldown(skill);
}
private String getFormat(PlayerData data) {
StringBuilder str = new StringBuilder();
if (!data.isOnline()) return str.toString();
for (int j = 0; j < data.getBoundSkills().size(); j++) {
ClassSkill skill = data.getBoundSkill(j);
str.append((str.length() == 0) ? "" : split).append((onCooldown(data, skill) ? onCooldown.replace("{cooldown}",
String.valueOf(data.getCooldownMap().getInfo(skill).getRemaining() / 1000)) : noMana(data, skill) ? noMana : (noStamina(
data, skill) ? noStamina : ready)).replace("{index}",
"" + (j + 1 + (data.getPlayer().getInventory().getHeldItemSlot() <= j ? 1 : 0)))
.replace("{skill}", data.getBoundSkill(j).getSkill().getName()));
}
return MMOCore.plugin.placeholderParser.parse(data.getPlayer(), str.toString());
}
private boolean noMana(PlayerData data, ClassSkill skill) {
return skill.getSkill().hasModifier("mana") && skill.getModifier("mana", data.getSkillLevel(skill.getSkill())) > data.getMana();
}
/**
* We don't even need to check if the skill has the 'cooldown'
* modifier. We just look for an entry in the cooldown map which
* won't be here if the skill has no cooldown.
*/
private boolean onCooldown(PlayerData data, ClassSkill skill) {
return data.getCooldownMap().isOnCooldown(skill);
}
private boolean noStamina(PlayerData data, ClassSkill skill) {
return skill.getSkill().hasModifier("stamina") && skill.getModifier("stamina",
data.getSkillLevel(skill.getSkill())) > data.getStamina();
}
private boolean noMana(PlayerData data, ClassSkill skill) {
return skill.getSkill().hasModifier("mana") && skill.getModifier("mana", data.getSkillLevel(skill.getSkill())) > data.getMana();
}
@Override
public void onTick() {
if (j % 20 == 0) getCaster().displayActionBar(getFormat(getCaster()));
private boolean noStamina(PlayerData data, ClassSkill skill) {
return skill.getSkill().hasModifier("stamina") && skill.getModifier("stamina",
data.getSkillLevel(skill.getSkill())) > data.getStamina();
}
for (int k = 0; k < 2; k++) {
double a = (double) j++ / 5;
getCaster().getProfess().getCastParticle()
.display(getCaster().getPlayer().getLocation().add(Math.cos(a), 1 + Math.sin(a / 3) / 1.3, Math.sin(a)));
}
}
}
@Override
public void onTick() {
if (j % 20 == 0) getCaster().displayActionBar(getFormat(getCaster()));
for (int k = 0; k < 2; k++) {
double a = (double) j++ / 5;
getCaster().getProfess().getCastParticle()
.display(getCaster().getPlayer().getLocation().add(Math.cos(a), 1 + Math.sin(a / 3) / 1.3, Math.sin(a)));
}
}
}
}

View File

@ -31,9 +31,11 @@ default-playerdata:
level: 1
class-points: 0
skill-points: 0
skill-realloc-points: 0
attribute-points: 0
attribute-realloc-points: 0
# The list of all conditions which must be met for the
# BLOCK REGEN and BLOCK RESTRICTIONS to apply. Set to
# 'custom-mine-conditions: []' to disable custom mining entirely.
@ -89,6 +91,7 @@ skill-casting:
mode: SKILL_BAR
open: SWAP_HANDS
loot-chests:
# Time in seconds it takes for a loot chest to
@ -241,6 +244,7 @@ resource-bar-colors:
# false - Never verbose
command-verbose:
attribute: true
skill: true
class: true
experience: true
level: true

View File

@ -100,6 +100,11 @@ skills:
level: 15
max-level: 30
#The number of skills a player can bound.
max-bound-skills: 6
# Experience sources for main class experience.
main-exp-sources:
- 'killmob{type=ZOMBIE;amount=1-3}'

View File

@ -20,6 +20,9 @@ options:
# Must match an existing exp curve filename from the 'expcurves' folder
exp-curve: levels
#The number of skills a player can bound.
max-bound-skills: 5
# Experience sources for main class experience.
main-exp-sources:
- 'killmob{type=ZOMBIE;amount=1-3}'

View File

@ -54,6 +54,8 @@ mana:
cast-particle:
particle: SPELL_INSTANT
# Special resource regeneration: (when out of combat),
# players can regen a set % of their maximum mana/missing mana.
# This % can scale with the player level.
@ -140,6 +142,11 @@ skills:
level: 15
max-level: 30
#The number of skills a player can bound.
max-bound-skills: 6
# Experience sources for main class experience.
main-exp-sources:
- 'killmob{type=ZOMBIE;amount=1-3}'

View File

@ -33,6 +33,8 @@ max-level: 100
exp-table: class_exp_table
# Particles displayed around the player
# when he enters the casting mode.
cast-particle:
@ -85,6 +87,11 @@ attributes:
base: .105
per-level: 0
#The number of skills a player can bound.
max-bound-skills: 5
# Experience sources for main class experience.
main-exp-sources:
- 'killmob{type=ZOMBIE;amount=1-3}'

View File

@ -30,6 +30,8 @@ display:
# Must match an existing exp curve filename from the 'expcurves' folder
exp-curve: levels
# The maximum level players can reach
max-level: 100
@ -75,6 +77,11 @@ attributes:
base: .095
per-level: 0
#The number of skills a player can bound.
max-bound-skills: 5
# Experience sources for main class experience.
main-exp-sources:
- 'killmob{type=ZOMBIE;amount=1-3}'

View File

@ -33,6 +33,7 @@ max-level: 100
exp-table: class_exp_table
options:
# Mana and health regen only applies when out of combat
off-combat-mana-regen: true
@ -80,6 +81,10 @@ attributes:
base: .105
per-level: 0
#The number of skills a player can bound.
max-bound-skills: 5
# Experience sources for main class experience.
main-exp-sources:
- 'killmob{type=ZOMBIE;amount=1-3}'

View File

@ -116,6 +116,11 @@ attributes:
base: 4.2
per-level: 0.05
#The number of skills a player can bound.
max-bound-skills: 5
# Experience sources for main class experience.
main-exp-sources:
- 'killmob{type=ZOMBIE;amount=1-3}'

View File

@ -2,6 +2,7 @@
# GUI display name
name: Player Attributes
# Number of slots in your inventory. Must be
# between 9 and 54 and must be a multiple of 9.
slots: 27
@ -11,70 +12,61 @@ items:
slots: [26]
function: reallocation
item: CAULDRON
name: '&aReallocate Skill Points'
name: '&aAttribute Points'
lore:
- ''
- 'You have spent a total of &6{total}&7 skill points.'
- '&7Right click to reallocate them.'
- ''
- '&eCosts 1 attribute reallocation point.'
- '&e◆ Attribute Reallocation Points: &6{points}'
- ''
- 'You have spent a total of &6{total}&7 attribute points.'
- '&7Right click to reallocate them.'
- ''
- '&eCosts 1 attribute reallocation point.'
- '&e◆ Attribute Reallocation Points: &6{points}'
str:
slots: [11]
function: attribute_strength
shift-cost: 10
name: '&a{name}'
item: GOLDEN_APPLE
lore: # {buffs} returns amount of buffs
- ''
- '&7Points Spent: &6{spent}&7/&6{max}'
- '&7Current {name}: &6&l{current}'
- ''
- '&8When Leveled Up:'
- '&7 +{buff_weapon_damage}% Weapon Damage (&a+{total_weapon_damage}%&7)'
- '&7 +{buff_max_health}% Max Health (&a+{total_max_health}%&7)'
- ''
- '&eClick to level up for 1 attribute point.'
- '&eShift-Click to level up for {shift_points} attribute points.'
- ''
- '&e◆ Current Attribute Points: {attribute_points}'
- ''
- '&7Points Spent: &6{spent}&7/&6{max}'
- '&7Current {name}: &6&l{current}'
- ''
- '&8When Leveled Up:'
- '&7 +{buff_weapon_damage}% Weapon Damage (&a+{total_weapon_damage}%&7)'
- '&7 +{buff_max_health} Max Health (&a+{total_max_health}&7)'
- ''
- '&eClick to level up for 1 attribute point.'
- '&e◆ Current Attribute Points: {attribute_points}'
dex:
slots: [13]
function: attribute_dexterity
shift-cost: 10
name: '&a{name}'
item: LEATHER_BOOTS
hide-flags: true
lore:
- ''
- '&7Points Spent: &6{spent}&7/&6{max}'
- '&7Current {name}: &6&l{current}'
- ''
- '&8When Leveled Up:'
- '&7 +{buff_physical_damage}% Physical Damage (&a+{total_physical_damage}%&7)'
- '&7 +{buff_projectile_damage}% Projectile Damage (&a+{total_projectile_damage}%&7)'
- '&7 +{buff_attack_speed}% Attack Speed (&a+{total_attack_speed}&7)'
- ''
- '&eClick to level up for 1 attribute point.'
- '&eShift-Click to level up for {shift_points} attribute points.'
- ''
- '&e◆ Current Attribute Points: {attribute_points}'
- ''
- '&7Points Spent: &6{spent}&7/&6{max}'
- '&7Current {name}: &6&l{current}'
- ''
- '&8When Leveled Up:'
- '&7 +{buff_physical_damage}% Physical Damage (&a+{total_physical_damage}%&7)'
- '&7 +{buff_projectile_damage}% Projectile Damage (&a+{total_projectile_damage}%&7)'
- '&7 +{buff_attack_speed} Attack Speed (&a+{total_attack_speed}&7)'
- ''
- '&eClick to level up for 1 attribute point.'
- '&e◆ Current Attribute Points: {attribute_points}'
int:
slots: [15]
function: attribute_intelligence
shift-cost: 10
name: '&a{name}'
item: BOOK
lore:
- ''
- '&7Points Spent: &6{spent}&7/&6{max}'
- '&7Current {name}: &6&l{current}'
- ''
- '&8When Leveled Up:'
- '&7 +{buff_magic_damage}% Magic Damage (&a+{total_magic_damage}%&7)'
- '&7 +{buff_cooldown_reduction}% Cooldown Reduction (&a+{total_cooldown_reduction}%&7)'
- ''
- '&eClick to level up for 1 attribute point.'
- '&eShift-Click to level up for {shift_points} attribute points.'
- ''
- '&e◆ Current Attribute Points: {attribute_points}'
- ''
- '&7Points Spent: &6{spent}&7/&6{max}'
- '&7Current {name}: &6&l{current}'
- ''
- '&8When Leveled Up:'
- '&7 +{buff_magic_damage}% Magic Damage (&a+{total_magic_damage}%&7)'
- '&7 +{buff_cooldown_reduction}% Cooldown Reduction (&a+{total_cooldown_reduction}%&7)'
- ''
- '&eClick to level up for 1 attribute point.'
- '&e◆ Current Attribute Points: {attribute_points}'

View File

@ -33,6 +33,18 @@ items:
name: '&aPrevious'
lore: { }
reallocate:
slots: [26]
function: reallocation
item: CAULDRON
name: '&aReallocate Skill Points'
lore:
- ''
- 'You have spent a total of &6{total}&7 skill points.'
- '&7Right click to reallocate them.'
- ''
- '&eCosts 1 skill reallocation point.'
- '&e◆ Skill Reallocation Points: &6{points}'
#switch:
#
@ -87,11 +99,9 @@ items:
upgrade:
slots: [ 15 ]
function: upgrade
shift-cost: 10
item: GREEN_STAINED_GLASS_PANE
name: '&a&lUPGRADE {skill_caps}'
lore:
- '&7Costs 1 skill point.'
- '&7Shift-Click to spend {shift_points} points'
- ''
- '&eCurrent Skill Points: {skill_points}'

View File

@ -157,7 +157,7 @@ no-permission-for-class:
# Attributes
no-attribute-points-spent: '&cYou have not spent any attribute points.'
not-attribute-reallocation-point: '&cYou do not have 1 reallocation point.'
not-attribute-point: '&cYou don''t have 1 attribute point.'
not-attribute-point: '&cYou have no attribute point.'
not-attribute-point-shift: '&cYou must have &4{shift_points} &cattribute points.'
attribute-points-reallocated: '&eYou successfully reset your attributes. You now have &6{points} &eattribute points.'
attribute-max-points-hit: '&cYou cannot level up this attribute anymore.'
@ -173,8 +173,11 @@ no-skill-bound: '&cYou don''t have any skill bound to this slot.'
not-active-skill: '&cThis is not an active skill.'
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.'
no-skill-points-spent: '&cYou have not spent any skill points.'
skill-points-reallocated: '&eYou successfully reset your attributes. You now have &6{points} &eskill points.'
#Skill Tree
# Skill Trees
no-skill-tree-points-spent: '&cYou have not spent any skill tree points.'
locked-node: '&cThis skill is locked!'
upgrade-skill-node: '&eYour skill node &6{skill-node} &eis now Level &6{level}&e!'

View File

@ -19,6 +19,7 @@ select-class: UI_TOAST_CHALLENGE_COMPLETE
level-attribute: ENTITY_PLAYER_LEVELUP
reset-attributes: ENTITY_PLAYER_LEVELUP
reset-skills: ENTITY_PLAYER_LEVELUP
level-skill-tree-node: ENTITY_PLAYER_LEVELUP
reset-skill-tree: ENTITY_PLAYER_LEVELUP