/** * Handles attribute menu interaction * * @param event event details */ @EventHandler public void onClick(InventoryClickEvent event) { // Class selection if (InventoryManager.isMatching(event.getInventory(), MENU_KEY)) { // Do nothing when clicking outside the inventory if (event.getSlot() == -999) { return; } boolean top = event.getRawSlot() < event.getView().getTopInventory().getSize(); AttributeManager manager = SkillAPI.getAttributeManager(); // Interact with the skill tree when clicking in the top region if (top) { if (event.getSlot() < manager.getKeys().size() || event.getCursor() != null) { event.setCancelled(true); PlayerData data = SkillAPI.getPlayerData((Player) event.getWhoClicked()); if (event.isRightClick() && SkillAPI.getSettings().isAttributesDowngrade()) { data.refundAttribute(manager.getKeys().toArray()[event.getSlot()].toString()); } else if (event.isLeftClick()) { Object[] keys = manager.getKeys().toArray(); data.upAttribute(keys[event.getSlot()].toString()); } data.openAttributeMenu(); } } // Do not allow shift clicking items into the inventory else if (event.isShiftClick()) { event.setCancelled(true); } } }
/** * Updates the player's max health and mana using class data. * * @param player player to update the health and mana for */ public void updateHealthAndMana(Player player) { if (player == null) { return; } // Update maxes double health = bonusHealth; maxMana = bonusMana; for (PlayerClass c : classes.values()) { health += c.getHealth(); maxMana += c.getMana(); } if (health == bonusHealth) { health += SkillAPI.getSettings().getDefaultHealth(); } if (health == 0) { health = 20; } if (SkillAPI.getSettings().isModifyHealth()) VersionManager.setMaxHealth(player, health); mana = Math.min(mana, maxMana); // Health scaling is available starting with 1.6.2 if (SkillAPI.getSettings().isModifyHealth() && VersionManager.isVersionAtLeast(VersionManager.V1_6_2)) { if (SkillAPI.getSettings().isOldHealth()) { player.setHealthScaled(true); player.setHealthScale(20); } else { player.setHealthScaled(false); } } }
/** * Cancels firing a bow with a disabled weapon * * @param event event details */ @EventHandler public void onShoot(EntityShootBowEvent event) { if (event.getEntity() instanceof Player) { if (InventoryTask.cannotUse( SkillAPI.getPlayerData((Player) event.getEntity()), event.getBow())) { SkillAPI.getLanguage() .sendMessage(ErrorNodes.CANNOT_USE, event.getEntity(), FilterType.COLOR); event.setCancelled(true); } } }
/** * Initializes a new account data representation for a player. * * @param player player to store the data for */ public PlayerData(OfflinePlayer player, boolean init) { this.player = player; this.skillBar = new PlayerSkillBar(this); this.combos = new PlayerCombos(this); this.init = SkillAPI.isLoaded() && init; this.scheme = "default"; for (String group : SkillAPI.getGroups()) { GroupSettings settings = SkillAPI.getSettings().getGroupSettings(group); RPGClass rpgClass = settings.getDefault(); if (rpgClass != null && settings.getPermission() == null) { setClass(rpgClass); } } }
/** * Resets the class data for the owner under the given group. This will remove the profession * entirely, leaving no remaining data until the player professes again to a starting class. * * @param group group to reset */ public void reset(String group) { stopPassives(getPlayer()); clearBonuses(); PlayerClass playerClass = classes.remove(group); if (playerClass != null) { // Remove skills RPGClass data = playerClass.getData(); for (Skill skill : data.getSkills()) { skills.remove(skill.getName()); combos.removeSkill(skill); } // Update GUI features if (getPlayer() != null) { ClassBoardManager.clear(new VersionPlayer(getPlayer())); } // Call the event Bukkit.getPluginManager().callEvent(new PlayerClassChangeEvent(playerClass, data, null)); } // Restore default class if applicable GroupSettings settings = SkillAPI.getSettings().getGroupSettings(group); RPGClass rpgClass = settings.getDefault(); if (rpgClass != null && settings.getPermission() == null) { setClass(rpgClass); } updateHealthAndMana(player.getPlayer()); }
/** Updates the cooldowns on skill bars each second */ @Override public void run() { for (Player player : Bukkit.getServer().getOnlinePlayers()) { PlayerData data = SkillAPI.getPlayerData(player); if (data.hasClass()) { data.getSkillBar().updateCooldowns(); } } }
/** * Gives the player attribute points without costing attribute points. * * @param key attribute to give points for * @param amount amount to give */ public void giveAttribute(String key, int amount) { key = key.toLowerCase(); int current = getAttribute(key); int max = SkillAPI.getAttributeManager().getAttribute(key).getMax(); amount = Math.min(amount, max - current); if (amount > 0) { attributes.put(key, current + amount); } }
/** * Retrieves the data of the professed class under the main class group. The "main" group is * determined by the setting in the config. * * @return main professed class data or null if not professed for the main group */ public PlayerClass getMainClass() { String main = SkillAPI.getSettings().getMainGroup(); if (classes.containsKey(main)) { return classes.get(main); } else if (classes.size() > 0) { return classes.values().toArray(new PlayerClass[classes.size()])[0]; } else { return null; } }
/** Opens the attribute menu */ public void openAttributeMenu() { Player player = getPlayer(); if (SkillAPI.getSettings().isAttributesEnabled() && player != null) { AttributeManager manager = SkillAPI.getAttributeManager(); Inventory inv = InventoryManager.createInventory( AttributeListener.MENU_KEY, (manager.getKeys().size() + 8) / 9, "Attributes (" + attribPoints + " points)"); int i = 0; for (String key : manager.getKeys()) { ItemStack icon = manager.getAttribute(key).getIcon().clone(); ItemMeta meta = icon.getItemMeta(); meta.setDisplayName(meta.getDisplayName().replace("{amount}", "" + getAttribute(key))); icon.setItemMeta(meta); inv.setItem(i++, icon); } player.openInventory(inv); } }
/** * Scales a dynamic skill's value using global modifiers * * @param component component holding the value * @param key key of the value * @param value unmodified value * @param self whether or not the player is the target * @return the modified value */ public double scaleDynamic(EffectComponent component, String key, double value, boolean self) { AttributeManager manager = SkillAPI.getAttributeManager(); if (manager == null) return value; for (String attr : manager.getKeys()) { int amount = getAttribute(attr); if (amount > 0) { value = manager.getAttribute(attr).modify(component, key, self, value, amount); } } return value; }
/** * Scales a stat value using the player's attributes * * @param stat stat key * @param value base value * @return modified value */ public double scaleStat(String stat, double value) { AttributeManager manager = SkillAPI.getAttributeManager(); if (manager == null) return value; for (String key : manager.getKeys()) { int amount = getAttribute(key); if (amount > 0) { value = manager.getAttribute(key).modifyStat(stat, value, amount); } } return value; }
/** * Apply skill damage/defense attribute buffs * * @param event event details */ @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) public void onSkillDamage(SkillDamageEvent event) { // Skill Damage if (event.getDamager() instanceof Player) { Player player = (Player) event.getDamager(); PlayerData data = SkillAPI.getPlayerData(player); double newAmount = data.scaleStat(AttributeManager.PHYSICAL_DAMAGE, event.getDamage()); event.setDamage(newAmount); } // Skill Defense if (event.getTarget() instanceof Player) { Player player = (Player) event.getTarget(); PlayerData data = SkillAPI.getPlayerData(player); double newAmount = data.scaleStat(AttributeManager.PHYSICAL_DEFENSE, event.getDamage()); event.setDamage(newAmount); } }
/** * Cancels left clicks on disabled items * * @param event event details */ @EventHandler(priority = EventPriority.LOWEST) public void onAttack(EntityDamageByEntityEvent event) { if (event.getDamager() instanceof Player) { Player player = (Player) event.getDamager(); if (InventoryTask.cannotUse(SkillAPI.getPlayerData(player), player.getItemInHand())) { SkillAPI.getLanguage().sendMessage(ErrorNodes.CANNOT_USE, player, FilterType.COLOR); event.setCancelled(true); } } if (event.getEntity() instanceof Player && VersionManager.isVersionAtLeast(VersionManager.V1_9_0)) { Player player = (Player) event.getEntity(); if (event.getDamage(EntityDamageEvent.DamageModifier.BLOCKING) < 0 && InventoryTask.cannotUse( SkillAPI.getPlayerData(player), player.getInventory().getItemInMainHand())) { SkillAPI.getLanguage() .sendMessage(ErrorNodes.CANNOT_USE, event.getEntity(), FilterType.COLOR); event.setDamage(EntityDamageEvent.DamageModifier.BLOCKING, 0); } } }
/** * Invests a point in the attribute if the player has any remaining attribute points. If the * player has no remaining points, this will do nothing. * * @param key attribute key */ public void upAttribute(String key) { key = key.toLowerCase(); int current = getAttribute(key); int max = SkillAPI.getAttributeManager().getAttribute(key).getMax(); if (attribPoints > 0 && current < max) { PlayerUpAttributeEvent event = new PlayerUpAttributeEvent(this, key); Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) return; attributes.put(key, current + 1); attribPoints--; } }
/** * Executes the command * * @param command owning command * @param plugin plugin reference * @param sender sender of the command * @param args arguments */ @Override public void execute( ConfigurableCommand command, Plugin plugin, CommandSender sender, String[] args) { // Needs two arguments if (args.length < 2) { command.displayHelp(sender); } // Switch accounts if valid number else { OfflinePlayer player = VersionManager.getOfflinePlayer(args[0], false); if (player == null) { command.sendMessage(sender, NOT_PLAYER, "&4That is not a valid player name"); return; } PlayerAccounts accounts = SkillAPI.getPlayerAccountData(player); try { int id = Integer.parseInt(args[1]); if (accounts.getAccountLimit() >= id && id > 0) { accounts.setAccount(id); command.sendMessage( sender, CHANGED, ChatColor.GOLD + "{player}'s" + ChatColor.DARK_GREEN + " active account has been changed", Filter.PLAYER.setReplacement(player.getName())); if (player.isOnline()) { command.sendMessage( (Player) player, TARGET, ChatColor.DARK_GREEN + "Your account has been forced to " + ChatColor.GOLD + "Account #{account}", RPGFilter.ACCOUNT.setReplacement(id + "")); } return; } } catch (Exception ex) { // Invalid ID } command.sendMessage(sender, NOT_ACCOUNT, ChatColor.RED + "That is not a valid account ID"); } }
private void autoLevel(Skill skill) { PlayerSkill data = skills.get(skill.getKey()); if (data == null) return; if (!SkillAPI.isLoaded()) return; int lastLevel = data.getLevel(); while (data.getData().canAutoLevel() && !data.isMaxed() && data.getLevelReq() <= data.getPlayerClass().getLevel()) { upgradeSkill(skill); if (lastLevel == data.getLevel()) { break; } lastLevel++; } }
/** * Professes the player into the class if they are able to. This will reset the class data if the * group options are set to reset upon profession. Otherwise, all skills, experience, and levels * of the current class under the group will be retained and carried over into the new profession. * * @param rpgClass class to profess into * @return true if successfully professed, false otherwise */ public boolean profess(RPGClass rpgClass) { if (rpgClass != null && canProfess(rpgClass)) { // Reset data if applicable if (SkillAPI.getSettings().getGroupSettings(rpgClass.getGroup()).isProfessReset()) { reset(rpgClass.getGroup()); } // Inherit previous class data if any PlayerClass current = classes.get(rpgClass.getGroup()); RPGClass previous; if (current == null) { previous = null; current = new PlayerClass(this, rpgClass); classes.put(rpgClass.getGroup(), current); } else { previous = current.getData(); current.setClassData(rpgClass); } // Add skills for (Skill skill : rpgClass.getSkills()) { if (!skills.containsKey(skill.getKey())) { skills.put(skill.getKey(), new PlayerSkill(this, skill, current)); combos.addSkill(skill); } } Bukkit.getPluginManager() .callEvent(new PlayerClassChangeEvent(current, previous, current.getData())); updateHealthAndMana(getPlayer()); updateScoreboard(); return true; } else { return false; } }
/** Checks all players for mana regeneration each interval */ public void run() { for (Player player : plugin.getServer().getOnlinePlayers()) { PlayerData data = SkillAPI.getPlayerData(player); data.regenMana(); } }
/** * Starts a new task for regenerating mana over time. The task is started automatically so don't * initialize this class unless wanting to start a new task. * * @param plugin SkillAPI reference */ public ManaTask(SkillAPI plugin) { this.plugin = plugin; runTaskTimer( plugin, SkillAPI.getSettings().getGainFreq(), SkillAPI.getSettings().getGainFreq()); }
/** * Casts a skill for the player. In order to cast the skill, the player must be online, have the * skill unlocked, have enough mana, have the skill off cooldown, and have a proper target if * applicable. * * @param skill skill to cast * @return true if successfully cast the skill, false otherwise */ public boolean cast(PlayerSkill skill) { // Invalid skill if (skill == null) { throw new IllegalArgumentException("Skill cannot be null"); } SkillStatus status = skill.getStatus(); int level = skill.getLevel(); double cost = skill.getData().getManaCost(level); // Not unlocked if (level <= 0) { return false; } // On Cooldown if (status == SkillStatus.ON_COOLDOWN) { SkillAPI.getLanguage() .sendMessage( ErrorNodes.COOLDOWN, getPlayer(), FilterType.COLOR, RPGFilter.COOLDOWN.setReplacement(skill.getCooldown() + ""), RPGFilter.SKILL.setReplacement(skill.getData().getName())); } // Not enough mana else if (status == SkillStatus.MISSING_MANA) { SkillAPI.getLanguage() .sendMessage( ErrorNodes.MANA, getPlayer(), FilterType.COLOR, RPGFilter.SKILL.setReplacement(skill.getData().getName()), RPGFilter.MANA.setReplacement(getMana() + ""), RPGFilter.COST.setReplacement((int) Math.ceil(cost) + ""), RPGFilter.MISSING.setReplacement((int) Math.ceil(cost - getMana()) + "")); } // Skill Shots else if (skill.getData() instanceof SkillShot) { Player p = getPlayer(); PlayerCastSkillEvent event = new PlayerCastSkillEvent(this, skill, p); Bukkit.getPluginManager().callEvent(event); // Make sure it isn't cancelled if (!event.isCancelled()) { try { if (((SkillShot) skill.getData()).cast(p, level)) { skill.startCooldown(); if (SkillAPI.getSettings().isShowSkillMessages()) { skill.getData().sendMessage(p, SkillAPI.getSettings().getMessageRadius()); } if (SkillAPI.getSettings().isManaEnabled()) { useMana(cost, ManaCost.SKILL_CAST); } return true; } } catch (Exception ex) { Bukkit.getLogger() .severe( "Failed to cast skill - " + skill.getData().getName() + ": Internal skill error"); ex.printStackTrace(); } } } // Target Skills else if (skill.getData() instanceof TargetSkill) { Player p = getPlayer(); LivingEntity target = TargetHelper.getLivingTarget(p, skill.getData().getRange(level)); // Must have a target if (target == null) { return false; } PlayerCastSkillEvent event = new PlayerCastSkillEvent(this, skill, p); Bukkit.getPluginManager().callEvent(event); // Make sure it isn't cancelled if (!event.isCancelled()) { try { if (((TargetSkill) skill.getData()) .cast(p, target, level, !SkillAPI.getSettings().canAttack(p, target))) { skill.startCooldown(); if (SkillAPI.getSettings().isShowSkillMessages()) { skill.getData().sendMessage(p, SkillAPI.getSettings().getMessageRadius()); } if (SkillAPI.getSettings().isManaEnabled()) { useMana(cost, ManaCost.SKILL_CAST); } return true; } } catch (Exception ex) { Bukkit.getLogger() .severe( "Failed to cast skill - " + skill.getData().getName() + ": Internal skill error"); ex.printStackTrace(); } } } return false; }
/** * Gives players bonus stats on respawn * * @param event event details */ @EventHandler(priority = EventPriority.HIGH) public void onRespawn(PlayerRespawnEvent event) { updatePlayer(SkillAPI.getPlayerData(event.getPlayer())); }
/** * Initializes the listener. This is automatically handled by SkillAPI and shouldn't be * instantiated by other plugins. * * @param api SkillAPI reference */ public AttributeListener(SkillAPI api) { api.getServer().getPluginManager().registerEvents(this, api); }