mirror of
https://gitlab.com/phoenix-dvpmt/mmocore.git
synced 2024-11-23 00:05:52 +01:00
!skills update
This commit is contained in:
parent
839af53c62
commit
5142437848
11
pom.xml
11
pom.xml
@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>net.Indyuce</groupId>
|
||||
<artifactId>MMOCore</artifactId>
|
||||
<version>1.8.3</version>
|
||||
<version>1.9</version>
|
||||
<name>MMOCore</name>
|
||||
<description>Offer your players a brand new RPG experience!!</description>
|
||||
|
||||
@ -125,7 +125,7 @@
|
||||
<dependency>
|
||||
<groupId>io.lumine</groupId>
|
||||
<artifactId>MythicLib-dist</artifactId>
|
||||
<version>1.2</version>
|
||||
<version>1.3-R11</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@ -177,12 +177,5 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>me.vagdedes.spartan</groupId>
|
||||
<artifactId>SpartanAPI</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -13,8 +13,6 @@ import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import net.Indyuce.mmocore.api.util.debug.DebugMode;
|
||||
import net.Indyuce.mmocore.command.*;
|
||||
import net.Indyuce.mmocore.comp.MMOCoreTargetRestriction;
|
||||
import net.Indyuce.mmocore.comp.anticheat.AntiCheatSupport;
|
||||
import net.Indyuce.mmocore.comp.anticheat.SpartanPlugin;
|
||||
import net.Indyuce.mmocore.comp.citizens.CitizenInteractEventListener;
|
||||
import net.Indyuce.mmocore.comp.citizens.CitizensMMOLoader;
|
||||
import net.Indyuce.mmocore.comp.mythicmobs.MythicHook;
|
||||
@ -41,6 +39,9 @@ import net.Indyuce.mmocore.manager.profession.*;
|
||||
import net.Indyuce.mmocore.manager.social.BoosterManager;
|
||||
import net.Indyuce.mmocore.manager.social.PartyManager;
|
||||
import net.Indyuce.mmocore.manager.social.RequestManager;
|
||||
import net.Indyuce.mmocore.skill.list.Ambers;
|
||||
import net.Indyuce.mmocore.skill.list.Neptune_Gift;
|
||||
import net.Indyuce.mmocore.skill.list.Sneaky_Picky;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandMap;
|
||||
@ -57,15 +58,9 @@ public class MMOCore extends LuminePlugin {
|
||||
|
||||
public ConfigManager configManager;
|
||||
public WaypointManager waypointManager;
|
||||
public RestrictionManager restrictionManager;
|
||||
public SoundManager soundManager;
|
||||
public RequestManager requestManager;
|
||||
public ConfigItemManager configItems;
|
||||
public VaultEconomy economy;
|
||||
public AntiCheatSupport antiCheatSupport;
|
||||
public RegionHandler regionHandler = new DefaultRegionHandler();
|
||||
public PlaceholderParser placeholderParser = new DefaultParser();
|
||||
public DataProvider dataProvider = new YAMLDataProvider();
|
||||
public final PlayerActionBar actionBarManager = new PlayerActionBar();
|
||||
public final SkillManager skillManager = new SkillManager();
|
||||
public final ClassManager classManager = new ClassManager();
|
||||
@ -77,6 +72,13 @@ public class MMOCore extends LuminePlugin {
|
||||
public final ProfessionManager professionManager = new ProfessionManager();
|
||||
public final net.Indyuce.mmocore.manager.ExperienceManager experience = new net.Indyuce.mmocore.manager.ExperienceManager();
|
||||
public final LootChestManager lootChests = new LootChestManager();
|
||||
public final MMOLoadManager loadManager = new MMOLoadManager();
|
||||
public final RestrictionManager restrictionManager = new RestrictionManager();
|
||||
|
||||
public VaultEconomy economy;
|
||||
public RegionHandler regionHandler = new DefaultRegionHandler();
|
||||
public PlaceholderParser placeholderParser = new DefaultParser();
|
||||
public DataProvider dataProvider = new YAMLDataProvider();
|
||||
|
||||
// Profession managers
|
||||
public final net.Indyuce.mmocore.manager.profession.CustomBlockManager mineManager = new net.Indyuce.mmocore.manager.profession.CustomBlockManager();
|
||||
@ -85,8 +87,6 @@ public class MMOCore extends LuminePlugin {
|
||||
public final EnchantManager enchantManager = new EnchantManager();
|
||||
public final SmithingManager smithingManager = new SmithingManager();
|
||||
|
||||
public final MMOLoadManager loadManager = new MMOLoadManager();
|
||||
|
||||
public boolean shouldDebugSQL = false;
|
||||
|
||||
private static final int MYTHICLIB_COMPATIBILITY_INDEX = 1;
|
||||
@ -118,6 +118,11 @@ public class MMOCore extends LuminePlugin {
|
||||
|
||||
if (Bukkit.getPluginManager().getPlugin("MythicMobs") != null)
|
||||
loadManager.registerLoader(new MythicMobsMMOLoader());
|
||||
|
||||
// Register MMOCore specific skills
|
||||
MythicLib.plugin.getSkills().registerSkillHandler(new Ambers());
|
||||
MythicLib.plugin.getSkills().registerSkillHandler(new Neptune_Gift());
|
||||
MythicLib.plugin.getSkills().registerSkillHandler(new Sneaky_Picky());
|
||||
}
|
||||
|
||||
public void enable() {
|
||||
@ -156,11 +161,6 @@ public class MMOCore extends LuminePlugin {
|
||||
getLogger().log(Level.INFO, "Hooked onto WorldGuard");
|
||||
}
|
||||
|
||||
if (Bukkit.getPluginManager().getPlugin("Spartan") != null) {
|
||||
antiCheatSupport = new SpartanPlugin();
|
||||
getLogger().log(Level.INFO, "Hooked onto Spartan");
|
||||
}
|
||||
|
||||
if (Bukkit.getPluginManager().getPlugin("MythicMobs") != null) {
|
||||
Bukkit.getServer().getPluginManager().registerEvents(new MythicHook(), this);
|
||||
MMOCore.plugin.getLogger().log(Level.INFO, "Hooked onto MythicMobs");
|
||||
@ -368,9 +368,9 @@ public class MMOCore extends LuminePlugin {
|
||||
|
||||
questManager.initialize(clearBefore);
|
||||
lootChests.initialize(clearBefore);
|
||||
restrictionManager.initialize(clearBefore);
|
||||
|
||||
waypointManager = new WaypointManager(new ConfigFile("waypoints").getConfig());
|
||||
restrictionManager = new RestrictionManager(new ConfigFile("restrictions").getConfig());
|
||||
requestManager = new RequestManager();
|
||||
soundManager = new SoundManager(new ConfigFile("sounds").getConfig());
|
||||
configItems = new ConfigItemManager(new ConfigFile("items").getConfig());
|
||||
@ -401,10 +401,6 @@ public class MMOCore extends LuminePlugin {
|
||||
return getFile();
|
||||
}
|
||||
|
||||
public boolean hasAntiCheat() {
|
||||
return antiCheatSupport != null;
|
||||
}
|
||||
|
||||
public boolean hasEconomy() {
|
||||
return economy != null && economy.isValid();
|
||||
}
|
||||
|
@ -42,6 +42,10 @@ public class ConfigFile {
|
||||
config = YamlConfiguration.loadConfiguration(file = new File(plugin.getDataFolder() + folder, (this.name = name) + ".yml"));
|
||||
}
|
||||
|
||||
public boolean exists() {
|
||||
return file.exists();
|
||||
}
|
||||
|
||||
public FileConfiguration getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
@ -1,48 +0,0 @@
|
||||
package net.Indyuce.mmocore.api.event;
|
||||
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.skill.Skill.SkillInfo;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
public class PlayerPostCastSkillEvent extends PlayerDataEvent {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private final SkillInfo skill;
|
||||
private final SkillMetadata result;
|
||||
|
||||
/**
|
||||
* Called right after a player casts a skill.
|
||||
*
|
||||
* @param playerData Player casting the skill
|
||||
* @param skill Skill being cast
|
||||
* @param result SKill casting result
|
||||
*/
|
||||
public PlayerPostCastSkillEvent(PlayerData playerData, SkillInfo skill, SkillMetadata result) {
|
||||
super(playerData);
|
||||
|
||||
this.skill = skill;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public SkillInfo getCast() {
|
||||
return skill;
|
||||
}
|
||||
|
||||
public SkillMetadata getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean wasSuccessful() {
|
||||
return result.isSuccessful();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
package net.Indyuce.mmocore.api.event;
|
||||
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.skill.Skill.SkillInfo;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
public class PlayerPreCastSkillEvent extends PlayerDataEvent implements Cancellable {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private final SkillInfo skill;
|
||||
|
||||
private boolean cancelled;
|
||||
|
||||
/**
|
||||
* Called right before a player casts a skill. This occurs before
|
||||
* checking for mana, stamina costs and ability cooldown.
|
||||
*
|
||||
* @param playerData Player casting the skill
|
||||
* @param skill Skill being cast
|
||||
*/
|
||||
public PlayerPreCastSkillEvent(PlayerData playerData, SkillInfo skill) {
|
||||
super(playerData);
|
||||
|
||||
this.skill = skill;
|
||||
}
|
||||
|
||||
public SkillInfo getCast() {
|
||||
return skill;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean value) {
|
||||
cancelled = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@ 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.CooldownInfo;
|
||||
import io.lumine.mythic.lib.player.cooldown.CooldownMap;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.ConfigMessage;
|
||||
@ -27,11 +26,8 @@ import net.Indyuce.mmocore.experience.EXPSource;
|
||||
import net.Indyuce.mmocore.experience.PlayerProfessions;
|
||||
import net.Indyuce.mmocore.listener.SpellCast.SkillCasting;
|
||||
import net.Indyuce.mmocore.manager.SoundManager;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.Skill.SkillInfo;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata.CancelReason;
|
||||
import net.Indyuce.mmocore.skill.ClassSkill;
|
||||
import net.Indyuce.mmocore.skill.RegisteredSkill;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.*;
|
||||
@ -72,7 +68,7 @@ public class PlayerData extends OfflinePlayerData implements Closable {
|
||||
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<SkillInfo> boundSkills = new ArrayList<>();
|
||||
private final List<ClassSkill> boundSkills = new ArrayList<>();
|
||||
private final PlayerProfessions collectSkills = new PlayerProfessions(this);
|
||||
private final PlayerAttributes attributes = new PlayerAttributes(this);
|
||||
private final Map<String, SavedClassInformation> classSlots = new HashMap<>();
|
||||
@ -139,7 +135,7 @@ public class PlayerData extends OfflinePlayerData implements Closable {
|
||||
} catch (NullPointerException npe1) {
|
||||
boundSkills.remove(j);
|
||||
try {
|
||||
MMOCore.log(Level.SEVERE, "[Userdata] Could not find skill " + boundSkills.get(j).getSkill().getId() + " in class "
|
||||
MMOCore.log(Level.SEVERE, "[Userdata] Could not find skill " + boundSkills.get(j).getSkill().getHandler().getId() + " in class "
|
||||
+ getProfess().getId() + " while refreshing player data.");
|
||||
} catch (NullPointerException npe2) {
|
||||
MMOCore.log(Level.SEVERE,
|
||||
@ -719,12 +715,12 @@ public class PlayerData extends OfflinePlayerData implements Closable {
|
||||
return getAttributes().mapPoints();
|
||||
}
|
||||
|
||||
public int getSkillLevel(Skill skill) {
|
||||
return skills.getOrDefault(skill.getId(), 1);
|
||||
public int getSkillLevel(RegisteredSkill skill) {
|
||||
return skills.getOrDefault(skill.getHandler().getId(), 1);
|
||||
}
|
||||
|
||||
public void setSkillLevel(Skill skill, int level) {
|
||||
setSkillLevel(skill.getId(), level);
|
||||
public void setSkillLevel(RegisteredSkill skill, int level) {
|
||||
setSkillLevel(skill.getHandler().getId(), level);
|
||||
}
|
||||
|
||||
public void setSkillLevel(String skill, int level) {
|
||||
@ -735,12 +731,12 @@ public class PlayerData extends OfflinePlayerData implements Closable {
|
||||
skills.remove(skill);
|
||||
}
|
||||
|
||||
/*
|
||||
* better use getProfess().findSkill(skill).isPresent()
|
||||
/**
|
||||
* @deprecated use {@link PlayerClass#findSkill(RegisteredSkill)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean hasSkillUnlocked(Skill skill) {
|
||||
return getProfess().hasSkill(skill.getId()) && hasSkillUnlocked(getProfess().getSkill(skill.getId()));
|
||||
public boolean hasSkillUnlocked(RegisteredSkill skill) {
|
||||
return getProfess().hasSkill(skill.getHandler().getId()) && hasSkillUnlocked(getProfess().getSkill(skill.getHandler().getId()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -753,8 +749,8 @@ public class PlayerData extends OfflinePlayerData implements Closable {
|
||||
*
|
||||
* @return If the player unlocked the skill
|
||||
*/
|
||||
public boolean hasSkillUnlocked(SkillInfo info) {
|
||||
return getLevel() >= info.getUnlockLevel();
|
||||
public boolean hasSkillUnlocked(ClassSkill skill) {
|
||||
return getLevel() >= skill.getUnlockLevel();
|
||||
}
|
||||
|
||||
public Map<String, Integer> mapSkillLevels() {
|
||||
@ -789,7 +785,7 @@ public class PlayerData extends OfflinePlayerData implements Closable {
|
||||
this.profess = profess;
|
||||
|
||||
// Clear old skills
|
||||
for (Iterator<SkillInfo> iterator = boundSkills.iterator(); iterator.hasNext(); )
|
||||
for (Iterator<ClassSkill> iterator = boundSkills.iterator(); iterator.hasNext(); )
|
||||
if (!getProfess().hasSkill(iterator.next().getSkill()))
|
||||
iterator.remove();
|
||||
|
||||
@ -801,11 +797,11 @@ public class PlayerData extends OfflinePlayerData implements Closable {
|
||||
return slot < boundSkills.size();
|
||||
}
|
||||
|
||||
public SkillInfo getBoundSkill(int slot) {
|
||||
public ClassSkill getBoundSkill(int slot) {
|
||||
return slot >= boundSkills.size() ? null : boundSkills.get(slot);
|
||||
}
|
||||
|
||||
public void setBoundSkill(int slot, SkillInfo skill) {
|
||||
public void setBoundSkill(int slot, ClassSkill skill) {
|
||||
if (boundSkills.size() < 6)
|
||||
boundSkills.add(skill);
|
||||
else
|
||||
@ -816,7 +812,7 @@ public class PlayerData extends OfflinePlayerData implements Closable {
|
||||
boundSkills.remove(slot);
|
||||
}
|
||||
|
||||
public List<SkillInfo> getBoundSkills() {
|
||||
public List<ClassSkill> getBoundSkills() {
|
||||
return boundSkills;
|
||||
}
|
||||
|
||||
@ -849,59 +845,6 @@ public class PlayerData extends OfflinePlayerData implements Closable {
|
||||
combat = new CombatRunnable(this);
|
||||
}
|
||||
|
||||
public SkillMetadata cast(Skill skill) {
|
||||
return cast(getProfess().getSkill(skill));
|
||||
}
|
||||
|
||||
public SkillMetadata cast(SkillInfo skill) {
|
||||
|
||||
PlayerPreCastSkillEvent preEvent = new PlayerPreCastSkillEvent(this, skill);
|
||||
Bukkit.getPluginManager().callEvent(preEvent);
|
||||
if (preEvent.isCancelled())
|
||||
return new SkillMetadata(this, skill, CancelReason.OTHER);
|
||||
|
||||
// Check for mana/stamina/cooldown and cast skill
|
||||
CasterMetadata casterMeta = new CasterMetadata(this);
|
||||
SkillMetadata cast = skill.getSkill().whenCast(casterMeta, skill);
|
||||
|
||||
// Send failure messages
|
||||
if (!cast.isSuccessful()) {
|
||||
if (!skill.getSkill().isPassive() && isOnline()) {
|
||||
if (cast.getCancelReason() == CancelReason.LOCKED)
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-unlocked-skill").send(getPlayer());
|
||||
|
||||
if (cast.getCancelReason() == CancelReason.MANA)
|
||||
MMOCore.plugin.configManager.getSimpleMessage("casting.no-mana", "mana", getProfess().getManaDisplay().getName()).send(getPlayer());
|
||||
|
||||
if (cast.getCancelReason() == CancelReason.STAMINA)
|
||||
MMOCore.plugin.configManager.getSimpleMessage("casting.no-stamina").send(getPlayer());
|
||||
|
||||
if (cast.getCancelReason() == CancelReason.COOLDOWN)
|
||||
MMOCore.plugin.configManager.getSimpleMessage("casting.on-cooldown").send(getPlayer());
|
||||
}
|
||||
|
||||
PlayerPostCastSkillEvent postEvent = new PlayerPostCastSkillEvent(this, skill, cast);
|
||||
Bukkit.getPluginManager().callEvent(postEvent);
|
||||
return cast;
|
||||
}
|
||||
|
||||
// Apply cooldown, mana and stamina costs
|
||||
if (!noCooldown) {
|
||||
|
||||
// Cooldown
|
||||
double flatCooldownReduction = Math.max(0, Math.min(1, getStats().getStat(StatType.COOLDOWN_REDUCTION) / 100));
|
||||
CooldownInfo cooldownHandler = getCooldownMap().applyCooldown(cast.getSkill(), cast.getCooldown());
|
||||
cooldownHandler.reduceInitialCooldown(flatCooldownReduction);
|
||||
|
||||
giveMana(-cast.getManaCost(), PlayerResourceUpdateEvent.UpdateReason.SKILL_COST);
|
||||
giveStamina(-cast.getStaminaCost(), PlayerResourceUpdateEvent.UpdateReason.SKILL_COST);
|
||||
}
|
||||
|
||||
PlayerPostCastSkillEvent postEvent = new PlayerPostCastSkillEvent(this, skill, cast);
|
||||
Bukkit.getPluginManager().callEvent(postEvent);
|
||||
return cast;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mmoData.hashCode();
|
||||
|
@ -7,8 +7,7 @@ import io.lumine.mythic.lib.api.stat.modifier.ModifierSource;
|
||||
import io.lumine.mythic.lib.api.stat.modifier.ModifierType;
|
||||
import io.lumine.mythic.lib.api.stat.modifier.StatModifier;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.comp.mythicmobs.MythicSkill;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.ClassSkill;
|
||||
|
||||
public class PlayerStats {
|
||||
private final PlayerData data;
|
||||
@ -82,8 +81,8 @@ public class PlayerStats {
|
||||
* This updates the player's passive skills
|
||||
*/
|
||||
data.getMMOPlayerData().unregisterSkillTriggers("MMOCorePassiveSkill");
|
||||
for (Skill.SkillInfo skill : data.getProfess().getSkills())
|
||||
if (skill.getSkill().isPassive() && skill.getSkill() instanceof MythicSkill)
|
||||
data.getMMOPlayerData().registerSkillTrigger(((MythicSkill) skill.getSkill()).toMythicLib());
|
||||
for (ClassSkill skill : data.getProfess().getSkills())
|
||||
if (skill.getSkill().hasTrigger())
|
||||
data.getMMOPlayerData().registerSkillTrigger(skill.toPassive(data));
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,10 @@ package net.Indyuce.mmocore.api.util;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import io.lumine.mythic.lib.comp.target.InteractionType;
|
||||
import io.lumine.mythic.lib.version.VersionMaterial;
|
||||
import io.lumine.mythic.utils.holograms.Hologram;
|
||||
import io.lumine.mythic.utils.serialize.Position;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@ -173,26 +171,6 @@ public class MMOCoreUtils {
|
||||
return entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param player Player casting a spell/basic attack
|
||||
* @param target The target entity
|
||||
* @return If the player can attack the entity
|
||||
*/
|
||||
public static boolean canTarget(PlayerData player, Entity target) {
|
||||
return canTarget(player, target, InteractionType.OFFENSE_SKILL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param player Player casting a spell/basic attack
|
||||
* @param target The target entity
|
||||
* @param interaction Whether the action is an attack or a buff, this does
|
||||
* impact the outcome of the friendly fire check
|
||||
* @return If the player can target the entity given the attack type (buff or attack)
|
||||
*/
|
||||
public static boolean canTarget(PlayerData player, Entity target, InteractionType interaction) {
|
||||
return target instanceof LivingEntity && MythicLib.plugin.getEntities().canTarget(player.getPlayer(), target, interaction);
|
||||
}
|
||||
|
||||
public static void heal(LivingEntity target, double value) {
|
||||
double max = target.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
|
||||
double gain = Math.min(max, target.getHealth() + value) - target.getHealth();
|
||||
|
@ -1,9 +0,0 @@
|
||||
package net.Indyuce.mmocore.comp.anticheat;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public abstract class AntiCheatSupport {
|
||||
public abstract void disableAntiCheat(Player player, Map<CheatType, Integer> map);
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
package net.Indyuce.mmocore.comp.anticheat;
|
||||
|
||||
public enum CheatType {
|
||||
GENERAL_EXPLOITS("Exploits"),
|
||||
NO_SWING("NoSwing"),
|
||||
MOVEMENT("IrregularMovements"),
|
||||
CLIPPING("Clip"),
|
||||
IMPOSSIBLE_ACTION("ImpossibleActions"),
|
||||
INVENTORY_CLEAR("ItemDrops"),
|
||||
INVENTORY_CLICKS("InventoryClicks"),
|
||||
AUTO_SPRINT("Sprint"),
|
||||
JESUS("Jesus"),
|
||||
NO_SLOWDOWN("NoSlowdown"),
|
||||
CRITICAL_HITS("Criticals"),
|
||||
NUKER("Nuker"),
|
||||
GHOST_HAND("GhostHand"),
|
||||
LIQUIDS("Liquids"),
|
||||
BLOCK_REACH("BlockReach"),
|
||||
ELYTRA("ElytraMove"),
|
||||
BOAT("BoatMove"),
|
||||
FAST_BOW("FastBow"),
|
||||
FAST_CLICK("FastClicks"),
|
||||
FAST_HEAL("FastHeal"),
|
||||
FLYING("Fly"),
|
||||
HIT_REACH("HitReach"),
|
||||
FAST_BREAK("FastBreak"),
|
||||
FAST_PLACE("FastPlace"),
|
||||
SPEED("Speed"),
|
||||
NO_FALL("NoFall"),
|
||||
ILLEGAL_POS("IllegalPosition"),
|
||||
FAST_EAT("FastEat"),
|
||||
VELOCITY("Velocity"),
|
||||
KILLAURA("KillAura");
|
||||
|
||||
private final String spartan;
|
||||
|
||||
CheatType(String spartan) {
|
||||
this.spartan = spartan;
|
||||
}
|
||||
|
||||
public String toSpartan() {
|
||||
return spartan;
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
package net.Indyuce.mmocore.comp.anticheat;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import me.vagdedes.spartan.api.API;
|
||||
import me.vagdedes.spartan.system.Enums.HackType;
|
||||
|
||||
public class SpartanPlugin extends AntiCheatSupport {
|
||||
@Override
|
||||
public void disableAntiCheat(Player player, Map<CheatType, Integer> map) {
|
||||
for(Entry<CheatType, Integer> entry : map.entrySet())
|
||||
API.cancelCheck(player, fromCheatType(entry.getKey()), entry.getValue());
|
||||
}
|
||||
|
||||
private HackType fromCheatType(CheatType ct) {
|
||||
return HackType.valueOf(ct.toSpartan());
|
||||
}
|
||||
}
|
@ -10,9 +10,10 @@ import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
|
||||
import net.Indyuce.mmocore.api.player.attribute.PlayerAttributes;
|
||||
import net.Indyuce.mmocore.comp.mythicmobs.load.CurrencyItemDrop;
|
||||
import net.Indyuce.mmocore.comp.mythicmobs.load.GoldPouchDrop;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.RegisteredSkill;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.util.Optional;
|
||||
@ -39,23 +40,14 @@ public class MythicHook implements Listener {
|
||||
event.register(new CurrencyItemDrop("NOTE", event.getConfig()));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void b(MythicReloadedEvent event) {
|
||||
|
||||
// When MM is reloaded, reload placeholders because they are no longer registered
|
||||
registerPlaceholders();
|
||||
|
||||
// Reload MMOCore skills as well
|
||||
for (Skill skill : MMOCore.plugin.skillManager.getActive())
|
||||
if (skill instanceof MythicSkill)
|
||||
try {
|
||||
String skillId = ((MythicSkill) skill).getSkill().getInternalName();
|
||||
Optional<io.lumine.xikage.mythicmobs.skills.Skill> opt = MythicMobs.inst().getSkillManager().getSkill(skillId);
|
||||
Validate.isTrue(opt.isPresent(), "Could not find skill with ID '" + skillId + "'");
|
||||
((MythicSkill) skill).setSkill(opt.get());
|
||||
} catch (RuntimeException exception) {
|
||||
MMOCore.log(Level.WARNING, "Could not reload MM skill '" + skill.getId() + "': " + exception.getMessage());
|
||||
}
|
||||
// Reload skills
|
||||
MMOCore.plugin.skillManager.initialize(true);
|
||||
}
|
||||
|
||||
private void registerPlaceholders() {
|
||||
|
@ -1,218 +0,0 @@
|
||||
package net.Indyuce.mmocore.comp.mythicmobs;
|
||||
|
||||
import io.lumine.mythic.lib.api.player.EquipmentSlot;
|
||||
import io.lumine.mythic.lib.api.stat.modifier.ModifierSource;
|
||||
import io.lumine.mythic.lib.api.util.EnumUtils;
|
||||
import io.lumine.mythic.lib.player.cooldown.CooldownInfo;
|
||||
import io.lumine.mythic.lib.skill.trigger.PassiveSkill;
|
||||
import io.lumine.mythic.lib.skill.trigger.TriggerMetadata;
|
||||
import io.lumine.mythic.lib.skill.trigger.TriggerType;
|
||||
import io.lumine.mythic.lib.skill.trigger.TriggeredSkill;
|
||||
import io.lumine.xikage.mythicmobs.MythicMobs;
|
||||
import io.lumine.xikage.mythicmobs.adapters.AbstractEntity;
|
||||
import io.lumine.xikage.mythicmobs.adapters.AbstractLocation;
|
||||
import io.lumine.xikage.mythicmobs.adapters.bukkit.BukkitAdapter;
|
||||
import io.lumine.xikage.mythicmobs.mobs.GenericCaster;
|
||||
import io.lumine.xikage.mythicmobs.skills.SkillCaster;
|
||||
import io.lumine.xikage.mythicmobs.skills.SkillTrigger;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.event.PlayerPostCastSkillEvent;
|
||||
import net.Indyuce.mmocore.api.event.PlayerPreCastSkillEvent;
|
||||
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.IntegerLinearValue;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.comp.anticheat.CheatType;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class MythicSkill extends Skill implements TriggeredSkill {
|
||||
private final Map<CheatType, Integer> antiCheat = new HashMap<>();
|
||||
private final PassiveSkill mythicLibSkill;
|
||||
|
||||
// Not final so that it can be changed when MM is reloaded
|
||||
private io.lumine.xikage.mythicmobs.skills.Skill skill;
|
||||
|
||||
public MythicSkill(String id, FileConfiguration config) {
|
||||
super(id);
|
||||
|
||||
String mmId = config.getString("mythicmobs-skill-id");
|
||||
Validate.notNull(mmId, "Could not find MM skill ID");
|
||||
|
||||
Optional<io.lumine.xikage.mythicmobs.skills.Skill> opt = MythicMobs.inst().getSkillManager().getSkill(mmId);
|
||||
Validate.isTrue(opt.isPresent(), "Could not find MM skill " + mmId);
|
||||
skill = opt.get();
|
||||
|
||||
String format = config.getString("material");
|
||||
Validate.notNull(format, "Could not load skill material");
|
||||
setIcon(MMOCoreUtils.readIcon(format));
|
||||
|
||||
setName(config.getString("name"));
|
||||
setLore(config.getStringList("lore"));
|
||||
|
||||
for (String key : config.getKeys(false)) {
|
||||
Object mod = config.get(key);
|
||||
if (mod instanceof ConfigurationSection)
|
||||
addModifier(key, readLinearValue((ConfigurationSection) mod));
|
||||
}
|
||||
|
||||
if (config.isConfigurationSection("disable-anti-cheat"))
|
||||
for (String key : config.getKeys(false)) {
|
||||
Optional<CheatType> cheatType = EnumUtils.getIfPresent(CheatType.class, key.toUpperCase());
|
||||
if (cheatType.isPresent() && config.isInt("disable-anti-cheat." + key))
|
||||
antiCheat.put(cheatType.get(), config.getInt("disable-anti-cheat." + key));
|
||||
else
|
||||
MMOCore.log(Level.WARNING, "Invalid Anti-Cheat configuration for '" + id + "'!");
|
||||
}
|
||||
|
||||
if (config.isString("passive-type")) {
|
||||
Optional<TriggerType> passiveType = EnumUtils.getIfPresent(TriggerType.class, config.getString("passive-type").toUpperCase());
|
||||
Validate.isTrue(passiveType.isPresent(), "Invalid passive skill type");
|
||||
setPassive();
|
||||
mythicLibSkill = new PassiveSkill("MMOCorePassiveSkill", passiveType.get(), this, EquipmentSlot.OTHER, ModifierSource.OTHER);
|
||||
} else
|
||||
mythicLibSkill = null;
|
||||
}
|
||||
|
||||
public Map<CheatType, Integer> getAntiCheat() {
|
||||
return antiCheat;
|
||||
}
|
||||
|
||||
public io.lumine.xikage.mythicmobs.skills.Skill getSkill() {
|
||||
return skill;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when reloading MMOCore. Something convenient to do is to
|
||||
* reload the MMOCore skills that are linked to a MM skill whenever
|
||||
* MM is reloaded, so that changes to the skill are taken into account
|
||||
* in MMOCore skills.
|
||||
*
|
||||
* @param skill Newest version of skill
|
||||
*/
|
||||
public void setSkill(@NotNull io.lumine.xikage.mythicmobs.skills.Skill skill) {
|
||||
Validate.notNull(skill);
|
||||
this.skill = skill;
|
||||
}
|
||||
|
||||
public PassiveSkill toMythicLib() {
|
||||
return mythicLibSkill;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillMetadata whenCast(CasterMetadata caster, SkillInfo skill) {
|
||||
SkillMetadata cast = new SkillMetadata(caster, skill);
|
||||
if (isPassive() || !cast.isSuccessful())
|
||||
return cast;
|
||||
|
||||
// Gather MythicMobs skill info
|
||||
HashSet<AbstractEntity> targetEntities = new HashSet<>();
|
||||
HashSet<AbstractLocation> targetLocations = new HashSet<>();
|
||||
|
||||
AbstractEntity trigger = BukkitAdapter.adapt(caster.getPlayer());
|
||||
SkillCaster skillCaster = new GenericCaster(trigger);
|
||||
io.lumine.xikage.mythicmobs.skills.SkillMetadata skillMeta = new io.lumine.xikage.mythicmobs.skills.SkillMetadata(SkillTrigger.CAST, skillCaster, trigger, BukkitAdapter.adapt(caster.getPlayer().getLocation()), targetEntities, targetLocations, 1);
|
||||
|
||||
// Disable anticheat
|
||||
if (MMOCore.plugin.hasAntiCheat())
|
||||
MMOCore.plugin.antiCheatSupport.disableAntiCheat(caster.getPlayer(), antiCheat);
|
||||
|
||||
// Place cast skill info in a variable
|
||||
skillMeta.getVariables().putObject("MMOSkill", cast);
|
||||
skillMeta.getVariables().putObject("MMOStatMap", caster.getStats());
|
||||
|
||||
// Yo is that me or the second argument is f***ing useless
|
||||
if (this.skill.usable(skillMeta, SkillTrigger.CAST))
|
||||
this.skill.execute(skillMeta);
|
||||
else
|
||||
cast.abort();
|
||||
|
||||
return cast;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to load double modifiers from the config with a specific type, since
|
||||
* modifiers have initially a type for mmocore default skills
|
||||
*/
|
||||
private LinearValue readLinearValue(ConfigurationSection section) {
|
||||
return section.getBoolean("int") ? new IntegerLinearValue(section) : new LinearValue(section);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TriggerMetadata triggerMeta) {
|
||||
PlayerData playerData = PlayerData.get(triggerMeta.getAttack().getPlayer().getUniqueId());
|
||||
if (!playerData.getProfess().hasSkill(this))
|
||||
return;
|
||||
|
||||
// Check for Bukkit pre cast event
|
||||
Skill.SkillInfo skill = playerData.getProfess().getSkill(this);
|
||||
PlayerPreCastSkillEvent preEvent = new PlayerPreCastSkillEvent(playerData, skill);
|
||||
Bukkit.getPluginManager().callEvent(preEvent);
|
||||
if (preEvent.isCancelled())
|
||||
return;
|
||||
|
||||
// Gather MMOCore skill info
|
||||
CasterMetadata caster = new CasterMetadata(playerData);
|
||||
SkillMetadata cast = new SkillMetadata(caster, skill);
|
||||
if (!cast.isSuccessful())
|
||||
return;
|
||||
|
||||
// Gather MythicMobs skill info
|
||||
HashSet<AbstractEntity> targetEntities = new HashSet<>();
|
||||
HashSet<AbstractLocation> targetLocations = new HashSet<>();
|
||||
|
||||
// The only difference
|
||||
if (triggerMeta.getTarget() != null)
|
||||
targetEntities.add(BukkitAdapter.adapt(triggerMeta.getTarget()));
|
||||
|
||||
AbstractEntity trigger = BukkitAdapter.adapt(caster.getPlayer());
|
||||
SkillCaster skillCaster = new GenericCaster(trigger);
|
||||
io.lumine.xikage.mythicmobs.skills.SkillMetadata skillMeta = new io.lumine.xikage.mythicmobs.skills.SkillMetadata(SkillTrigger.API, skillCaster, trigger, BukkitAdapter.adapt(caster.getPlayer().getEyeLocation()), targetEntities, targetLocations, 1);
|
||||
|
||||
// Check if the MythicMobs skill can be cast
|
||||
if (!this.skill.usable(skillMeta, SkillTrigger.CAST)) {
|
||||
cast.abort();
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable anticheat
|
||||
if (MMOCore.plugin.hasAntiCheat())
|
||||
MMOCore.plugin.antiCheatSupport.disableAntiCheat(caster.getPlayer(), antiCheat);
|
||||
|
||||
// Place cast skill info in a variable
|
||||
skillMeta.getVariables().putObject("MMOSkill", cast);
|
||||
skillMeta.getVariables().putObject("MMOStatMap", caster.getStats());
|
||||
|
||||
// Apply cooldown, mana and stamina costs
|
||||
if (!playerData.noCooldown) {
|
||||
|
||||
// Cooldown
|
||||
double flatCooldownReduction = Math.max(0, Math.min(1, playerData.getStats().getStat(StatType.COOLDOWN_REDUCTION) / 100));
|
||||
CooldownInfo cooldownHandler = playerData.getCooldownMap().applyCooldown(cast.getSkill(), cast.getCooldown());
|
||||
cooldownHandler.reduceInitialCooldown(flatCooldownReduction);
|
||||
|
||||
// Mana and stamina cost
|
||||
playerData.giveMana(-cast.getManaCost(), PlayerResourceUpdateEvent.UpdateReason.SKILL_COST);
|
||||
playerData.giveStamina(-cast.getStaminaCost(), PlayerResourceUpdateEvent.UpdateReason.SKILL_COST);
|
||||
}
|
||||
|
||||
// Execute the MythicMobs skill
|
||||
this.skill.execute(skillMeta);
|
||||
|
||||
Bukkit.getPluginManager().callEvent(new PlayerPostCastSkillEvent(playerData, skill, cast));
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import net.Indyuce.mmocore.api.quest.PlayerQuests;
|
||||
import net.Indyuce.mmocore.experience.PlayerProfessions;
|
||||
import net.Indyuce.mmocore.experience.Profession;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.RegisteredSkill;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
@ -61,7 +61,7 @@ public class RPGPlaceholders extends PlaceholderExpansion {
|
||||
|
||||
else if (identifier.startsWith("skill_level_")) {
|
||||
String id = identifier.substring(12);
|
||||
Skill skill = Objects.requireNonNull(MMOCore.plugin.skillManager.get(id), "Could not find skill with ID '" + id + "'");
|
||||
RegisteredSkill skill = Objects.requireNonNull(MMOCore.plugin.skillManager.getSkill(id), "Could not find skill with ID '" + id + "'");
|
||||
return String.valueOf(playerData.getSkillLevel(skill));
|
||||
}
|
||||
|
||||
|
@ -25,10 +25,7 @@ public class Profession {
|
||||
|
||||
/**
|
||||
* Experience given to the main player level whenever he levels up this profession
|
||||
*
|
||||
* @deprecated Being replaced by {@link ExperienceTable}
|
||||
*/
|
||||
@Deprecated
|
||||
private final LinearValue experience;
|
||||
|
||||
public Profession(String id, FileConfiguration config) {
|
||||
@ -111,10 +108,6 @@ public class Profession {
|
||||
return maxLevel > 0;
|
||||
}
|
||||
|
||||
public int calculateExperience(int x) {
|
||||
return (int) experience.calculate(x);
|
||||
}
|
||||
|
||||
public LinearValue getExperience() {
|
||||
return experience;
|
||||
}
|
||||
|
@ -5,14 +5,14 @@ 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.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.Skill.SkillInfo;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.gui.api.EditableInventory;
|
||||
import net.Indyuce.mmocore.gui.api.GeneratedInventory;
|
||||
import net.Indyuce.mmocore.gui.api.item.InventoryItem;
|
||||
import net.Indyuce.mmocore.gui.api.item.Placeholders;
|
||||
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
|
||||
import net.Indyuce.mmocore.skill.ClassSkill;
|
||||
import net.Indyuce.mmocore.skill.RegisteredSkill;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
@ -28,385 +28,383 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SkillList extends EditableInventory {
|
||||
public SkillList() {
|
||||
super("skill-list");
|
||||
}
|
||||
|
||||
@Override
|
||||
public InventoryItem load(String function, ConfigurationSection config) {
|
||||
|
||||
if (function.equals("skill"))
|
||||
return new SkillItem(config);
|
||||
|
||||
if (function.equals("switch"))
|
||||
return new SwitchItem(config);
|
||||
|
||||
if (function.equals("level"))
|
||||
return new LevelItem(config);
|
||||
|
||||
if (function.equals("upgrade"))
|
||||
return new InventoryItem<SkillViewerInventory>(config) {
|
||||
|
||||
@Override
|
||||
public Placeholders getPlaceholders(SkillViewerInventory inv, int n) {
|
||||
Skill selected = 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());
|
||||
|
||||
return holders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDisplay(SkillViewerInventory inv) {
|
||||
return !inv.binding;
|
||||
}
|
||||
};
|
||||
|
||||
if (function.equals("slot"))
|
||||
return new InventoryItem<SkillViewerInventory>(config) {
|
||||
private final String none = MythicLib.plugin.parseColors(config.getString("no-skill"));
|
||||
private final Material emptyMaterial = Material
|
||||
.valueOf(config.getString("empty-item").toUpperCase().replace("-", "_").replace(" ", "_"));
|
||||
private final int emptyCMD = config.getInt("empty-custom-model-data", getModelData());
|
||||
|
||||
@Override
|
||||
public Placeholders getPlaceholders(SkillViewerInventory inv, int n) {
|
||||
Skill selected = inv.selected.getSkill();
|
||||
Skill skill = inv.getPlayerData().hasSkillBound(n) ? inv.getPlayerData().getBoundSkill(n).getSkill() : null;
|
||||
|
||||
Placeholders holders = new Placeholders();
|
||||
|
||||
holders.register("skill", skill == null ? none : skill.getName());
|
||||
holders.register("index", "" + (n + 1));
|
||||
holders.register("slot", MMOCoreUtils.intToRoman(n + 1));
|
||||
holders.register("selected", selected.getName());
|
||||
|
||||
return holders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack display(SkillViewerInventory inv, int n) {
|
||||
ItemStack item = super.display(inv, n);
|
||||
if (!inv.getPlayerData().hasSkillBound(n)) {
|
||||
item.setType(emptyMaterial);
|
||||
|
||||
if (MythicLib.plugin.getVersion().isStrictlyHigher(1, 13)) {
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setCustomModelData(emptyCMD);
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDisplay(SkillViewerInventory inv) {
|
||||
return inv.binding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDifferentDisplay() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
return new SimplePlaceholderItem(config);
|
||||
}
|
||||
|
||||
public GeneratedInventory newInventory(PlayerData data) {
|
||||
return new SkillViewerInventory(data, this);
|
||||
}
|
||||
|
||||
public class SwitchItem extends SimplePlaceholderItem<SkillViewerInventory> {
|
||||
private final SimplePlaceholderItem binding, upgrading;
|
||||
|
||||
public SwitchItem(ConfigurationSection config) {
|
||||
super(config);
|
||||
|
||||
Validate.isTrue(config.contains("binding"), "Config must have 'binding'");
|
||||
Validate.isTrue(config.contains("upgrading"), "Config must have 'upgrading'");
|
||||
|
||||
binding = new SimplePlaceholderItem(config.getConfigurationSection("binding"));
|
||||
upgrading = new SimplePlaceholderItem(config.getConfigurationSection("upgrading"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack display(SkillViewerInventory inv, int n) {
|
||||
return inv.binding ? upgrading.display(inv) : binding.display(inv);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDisplay(SkillViewerInventory inv) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class LevelItem extends InventoryItem<SkillViewerInventory> {
|
||||
private final int offset;
|
||||
|
||||
public LevelItem(ConfigurationSection config) {
|
||||
super(config);
|
||||
|
||||
offset = config.getInt("offset");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDifferentDisplay() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack display(SkillViewerInventory inv, int n) {
|
||||
|
||||
SkillInfo skill = inv.selected;
|
||||
int skillLevel = inv.getPlayerData().getSkillLevel(skill.getSkill()) + n - offset;
|
||||
if (skillLevel < 1)
|
||||
return new ItemStack(Material.AIR);
|
||||
|
||||
List<String> lore = new ArrayList<>(getLore());
|
||||
int index = lore.indexOf("{lore}");
|
||||
lore.remove(index);
|
||||
List<String> skillLore = skill.calculateLore(inv.getPlayerData(), skillLevel);
|
||||
for (int j = 0; j < skillLore.size(); j++)
|
||||
lore.add(index + j, skillLore.get(j));
|
||||
|
||||
for (int j = 0; j < lore.size(); j++)
|
||||
lore.set(j, ChatColor.GRAY + MythicLib.plugin.parseColors(lore.get(j)));
|
||||
|
||||
ItemStack item = new ItemStack(getMaterial());
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setDisplayName(MythicLib.plugin.parseColors(getName().replace("{skill}", skill.getSkill().getName())
|
||||
.replace("{roman}", MMOCoreUtils.intToRoman(skillLevel)).replace("{level}", "" + skillLevel)));
|
||||
meta.addItemFlags(ItemFlag.values());
|
||||
meta.setLore(lore);
|
||||
if (MythicLib.plugin.getVersion().isStrictlyHigher(1, 13))
|
||||
meta.setCustomModelData(getModelData());
|
||||
item.setItemMeta(meta);
|
||||
|
||||
return NBTItem.get(item).addTag(new ItemTag("skillId", skill.getSkill().getId())).toItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Placeholders getPlaceholders(SkillViewerInventory inv, int n) {
|
||||
return new Placeholders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDisplay(SkillViewerInventory inv) {
|
||||
return !inv.binding;
|
||||
}
|
||||
}
|
||||
|
||||
public class SkillItem extends InventoryItem<SkillViewerInventory> {
|
||||
private final int selectedSkillSlot;
|
||||
|
||||
public SkillItem(ConfigurationSection config) {
|
||||
super(Material.BARRIER, config);
|
||||
|
||||
selectedSkillSlot = config.getInt("selected-slot");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDifferentDisplay() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack display(SkillViewerInventory inv, int n) {
|
||||
|
||||
/*
|
||||
* calculate placeholders
|
||||
*/
|
||||
SkillInfo skill = inv.skills.get(mod(n + inv.getPlayerData().skillGuiDisplayOffset, inv.skills.size()));
|
||||
Placeholders holders = getPlaceholders(inv.getPlayerData(), skill);
|
||||
|
||||
List<String> lore = new ArrayList<>(getLore());
|
||||
|
||||
int index = lore.indexOf("{lore}");
|
||||
lore.remove(index);
|
||||
List<String> skillLore = skill.calculateLore(inv.getPlayerData());
|
||||
for (int j = 0; j < skillLore.size(); j++)
|
||||
lore.add(index + j, skillLore.get(j));
|
||||
|
||||
boolean unlocked = skill.getUnlockLevel() <= inv.getPlayerData().getLevel();
|
||||
|
||||
lore.removeIf(next -> (next.startsWith("{unlocked}") && !unlocked) || (next.startsWith("{locked}") && unlocked) || (next.startsWith("{max_level}") && (!skill.hasMaxLevel() || skill.getMaxLevel() > inv.getPlayerData().getSkillLevel(skill.getSkill()))));
|
||||
|
||||
for (int j = 0; j < lore.size(); j++)
|
||||
lore.set(j, ChatColor.GRAY + holders.apply(inv.getPlayer(), lore.get(j)));
|
||||
|
||||
/*
|
||||
* generate item
|
||||
*/
|
||||
ItemStack item = skill.getSkill().getIcon();
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setDisplayName(holders.apply(inv.getPlayer(), getName()));
|
||||
meta.addItemFlags(ItemFlag.values());
|
||||
meta.setLore(lore);
|
||||
item.setItemMeta(meta);
|
||||
|
||||
return NBTItem.get(item).addTag(new ItemTag("skillId", skill.getSkill().getId())).toItem();
|
||||
}
|
||||
|
||||
public Placeholders getPlaceholders(PlayerData player, SkillInfo skill) {
|
||||
Placeholders holders = new Placeholders();
|
||||
holders.register("skill", skill.getSkill().getName());
|
||||
holders.register("unlock", "" + skill.getUnlockLevel());
|
||||
holders.register("level", "" + player.getSkillLevel(skill.getSkill()));
|
||||
return holders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Placeholders getPlaceholders(SkillViewerInventory inv, int n) {
|
||||
return new Placeholders();
|
||||
}
|
||||
}
|
||||
|
||||
public class SkillViewerInventory extends GeneratedInventory {
|
||||
|
||||
/*
|
||||
* cached information
|
||||
*/
|
||||
private final List<SkillInfo> skills;
|
||||
private final List<Integer> skillSlots;
|
||||
private final List<Integer> slotSlots;
|
||||
|
||||
private boolean binding;
|
||||
private SkillInfo selected;
|
||||
|
||||
public SkillViewerInventory(PlayerData playerData, EditableInventory editable) {
|
||||
super(playerData, editable);
|
||||
|
||||
skills = new ArrayList<>(playerData.getProfess().getSkills());
|
||||
skillSlots = getEditable().getByFunction("skill").getSlots();
|
||||
slotSlots = getEditable().getByFunction("slot").getSlots();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String calculateName() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
int selectedSkillSlot = ((SkillItem) getEditable().getByFunction("skill")).selectedSkillSlot;
|
||||
selected = skills.get(mod(selectedSkillSlot + playerData.skillGuiDisplayOffset, skills.size()));
|
||||
|
||||
super.open();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
|
||||
|
||||
if (skillSlots.contains(event.getRawSlot())
|
||||
&& event.getRawSlot() != ((SkillItem) getEditable().getByFunction("skill")).selectedSkillSlot) {
|
||||
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 1, 2);
|
||||
playerData.skillGuiDisplayOffset = (playerData.skillGuiDisplayOffset + (event.getRawSlot() - 13)) % skills.size();
|
||||
open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.getFunction().equals("previous")) {
|
||||
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 1, 2);
|
||||
playerData.skillGuiDisplayOffset = (playerData.skillGuiDisplayOffset - 1) % skills.size();
|
||||
open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.getFunction().equals("next")) {
|
||||
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 1, 2);
|
||||
playerData.skillGuiDisplayOffset = (playerData.skillGuiDisplayOffset + 1) % skills.size();
|
||||
open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.getFunction().equals("switch")) {
|
||||
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 1, 2);
|
||||
binding = !binding;
|
||||
open();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* binding or unbinding skills.
|
||||
*/
|
||||
if (binding) {
|
||||
for (int index = 0; index < slotSlots.size(); index++) {
|
||||
int slot = slotSlots.get(index);
|
||||
if (event.getRawSlot() == slot) {
|
||||
|
||||
// unbind if there is a current spell.
|
||||
if (event.getAction() == InventoryAction.PICKUP_HALF) {
|
||||
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();
|
||||
return;
|
||||
}
|
||||
|
||||
if (selected == null)
|
||||
return;
|
||||
|
||||
if (selected.getSkill().isPassive()) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-active-skill").send(player);
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!playerData.hasSkillUnlocked(selected)) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-unlocked-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.setBoundSkill(index, selected);
|
||||
open();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* upgrading a player skill
|
||||
*/
|
||||
} else if (item.getFunction().equals("upgrade")) {
|
||||
if (!playerData.hasSkillUnlocked(selected)) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-unlocked-skill").send(player);
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (playerData.getSkillPoints() < 1) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-enough-skill-points").send(player);
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (selected.hasMaxLevel() && playerData.getSkillLevel(selected.getSkill()) >= selected.getMaxLevel()) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("skill-max-level-hit").send(player);
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int mod(int x, int n) {
|
||||
return x < 0 ? (x + n) : (x % n);
|
||||
}
|
||||
public SkillList() {
|
||||
super("skill-list");
|
||||
}
|
||||
|
||||
@Override
|
||||
public InventoryItem load(String function, ConfigurationSection config) {
|
||||
|
||||
if (function.equals("skill"))
|
||||
return new SkillItem(config);
|
||||
|
||||
if (function.equals("switch"))
|
||||
return new SwitchItem(config);
|
||||
|
||||
if (function.equals("level"))
|
||||
return new LevelItem(config);
|
||||
|
||||
if (function.equals("upgrade"))
|
||||
return new InventoryItem<SkillViewerInventory>(config) {
|
||||
|
||||
@Override
|
||||
public Placeholders getPlaceholders(SkillViewerInventory inv, int n) {
|
||||
RegisteredSkill selected = 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());
|
||||
|
||||
return holders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDisplay(SkillViewerInventory inv) {
|
||||
return !inv.binding;
|
||||
}
|
||||
};
|
||||
|
||||
if (function.equals("slot"))
|
||||
return new InventoryItem<SkillViewerInventory>(config) {
|
||||
private final String none = MythicLib.plugin.parseColors(config.getString("no-skill"));
|
||||
private final Material emptyMaterial = Material
|
||||
.valueOf(config.getString("empty-item").toUpperCase().replace("-", "_").replace(" ", "_"));
|
||||
private final int emptyCMD = config.getInt("empty-custom-model-data", getModelData());
|
||||
|
||||
@Override
|
||||
public Placeholders getPlaceholders(SkillViewerInventory inv, int n) {
|
||||
RegisteredSkill selected = inv.selected.getSkill();
|
||||
RegisteredSkill skill = inv.getPlayerData().hasSkillBound(n) ? inv.getPlayerData().getBoundSkill(n).getSkill() : null;
|
||||
|
||||
Placeholders holders = new Placeholders();
|
||||
|
||||
holders.register("skill", skill == null ? none : skill.getName());
|
||||
holders.register("index", "" + (n + 1));
|
||||
holders.register("slot", MMOCoreUtils.intToRoman(n + 1));
|
||||
holders.register("selected", selected.getName());
|
||||
|
||||
return holders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack display(SkillViewerInventory inv, int n) {
|
||||
ItemStack item = super.display(inv, n);
|
||||
if (!inv.getPlayerData().hasSkillBound(n)) {
|
||||
item.setType(emptyMaterial);
|
||||
|
||||
if (MythicLib.plugin.getVersion().isStrictlyHigher(1, 13)) {
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setCustomModelData(emptyCMD);
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDisplay(SkillViewerInventory inv) {
|
||||
return inv.binding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDifferentDisplay() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
return new SimplePlaceholderItem(config);
|
||||
}
|
||||
|
||||
public GeneratedInventory newInventory(PlayerData data) {
|
||||
return new SkillViewerInventory(data, this);
|
||||
}
|
||||
|
||||
public class SwitchItem extends SimplePlaceholderItem<SkillViewerInventory> {
|
||||
private final SimplePlaceholderItem binding, upgrading;
|
||||
|
||||
public SwitchItem(ConfigurationSection config) {
|
||||
super(config);
|
||||
|
||||
Validate.isTrue(config.contains("binding"), "Config must have 'binding'");
|
||||
Validate.isTrue(config.contains("upgrading"), "Config must have 'upgrading'");
|
||||
|
||||
binding = new SimplePlaceholderItem(config.getConfigurationSection("binding"));
|
||||
upgrading = new SimplePlaceholderItem(config.getConfigurationSection("upgrading"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack display(SkillViewerInventory inv, int n) {
|
||||
return inv.binding ? upgrading.display(inv) : binding.display(inv);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDisplay(SkillViewerInventory inv) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class LevelItem extends InventoryItem<SkillViewerInventory> {
|
||||
private final int offset;
|
||||
|
||||
public LevelItem(ConfigurationSection config) {
|
||||
super(config);
|
||||
|
||||
offset = config.getInt("offset");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDifferentDisplay() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack display(SkillViewerInventory inv, int n) {
|
||||
|
||||
ClassSkill skill = inv.selected;
|
||||
int skillLevel = inv.getPlayerData().getSkillLevel(skill.getSkill()) + n - offset;
|
||||
if (skillLevel < 1)
|
||||
return new ItemStack(Material.AIR);
|
||||
|
||||
List<String> lore = new ArrayList<>(getLore());
|
||||
int index = lore.indexOf("{lore}");
|
||||
lore.remove(index);
|
||||
List<String> skillLore = skill.calculateLore(inv.getPlayerData(), skillLevel);
|
||||
for (int j = 0; j < skillLore.size(); j++)
|
||||
lore.add(index + j, skillLore.get(j));
|
||||
|
||||
for (int j = 0; j < lore.size(); j++)
|
||||
lore.set(j, ChatColor.GRAY + MythicLib.plugin.parseColors(lore.get(j)));
|
||||
|
||||
ItemStack item = new ItemStack(getMaterial());
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setDisplayName(MythicLib.plugin.parseColors(getName().replace("{skill}", skill.getSkill().getName())
|
||||
.replace("{roman}", MMOCoreUtils.intToRoman(skillLevel)).replace("{level}", "" + skillLevel)));
|
||||
meta.addItemFlags(ItemFlag.values());
|
||||
meta.setLore(lore);
|
||||
if (MythicLib.plugin.getVersion().isStrictlyHigher(1, 13))
|
||||
meta.setCustomModelData(getModelData());
|
||||
item.setItemMeta(meta);
|
||||
|
||||
return NBTItem.get(item).addTag(new ItemTag("skillId", skill.getSkill().getHandler().getId())).toItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Placeholders getPlaceholders(SkillViewerInventory inv, int n) {
|
||||
return new Placeholders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDisplay(SkillViewerInventory inv) {
|
||||
return !inv.binding;
|
||||
}
|
||||
}
|
||||
|
||||
public class SkillItem extends InventoryItem<SkillViewerInventory> {
|
||||
private final int selectedSkillSlot;
|
||||
|
||||
public SkillItem(ConfigurationSection config) {
|
||||
super(Material.BARRIER, config);
|
||||
|
||||
selectedSkillSlot = config.getInt("selected-slot");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDifferentDisplay() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack display(SkillViewerInventory inv, int n) {
|
||||
|
||||
/*
|
||||
* calculate placeholders
|
||||
*/
|
||||
ClassSkill skill = inv.skills.get(mod(n + inv.getPlayerData().skillGuiDisplayOffset, inv.skills.size()));
|
||||
Placeholders holders = getPlaceholders(inv.getPlayerData(), skill);
|
||||
|
||||
List<String> lore = new ArrayList<>(getLore());
|
||||
|
||||
int index = lore.indexOf("{lore}");
|
||||
lore.remove(index);
|
||||
List<String> skillLore = skill.calculateLore(inv.getPlayerData());
|
||||
for (int j = 0; j < skillLore.size(); j++)
|
||||
lore.add(index + j, skillLore.get(j));
|
||||
|
||||
boolean unlocked = skill.getUnlockLevel() <= inv.getPlayerData().getLevel();
|
||||
|
||||
lore.removeIf(next -> (next.startsWith("{unlocked}") && !unlocked) || (next.startsWith("{locked}") && unlocked) || (next.startsWith("{max_level}") && (!skill.hasMaxLevel() || skill.getMaxLevel() > inv.getPlayerData().getSkillLevel(skill.getSkill()))));
|
||||
|
||||
for (int j = 0; j < lore.size(); j++)
|
||||
lore.set(j, ChatColor.GRAY + holders.apply(inv.getPlayer(), lore.get(j)));
|
||||
|
||||
/*
|
||||
* generate item
|
||||
*/
|
||||
ItemStack item = skill.getSkill().getIcon();
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setDisplayName(holders.apply(inv.getPlayer(), getName()));
|
||||
meta.addItemFlags(ItemFlag.values());
|
||||
meta.setLore(lore);
|
||||
item.setItemMeta(meta);
|
||||
|
||||
return NBTItem.get(item).addTag(new ItemTag("skillId", skill.getSkill().getHandler().getId())).toItem();
|
||||
}
|
||||
|
||||
public Placeholders getPlaceholders(PlayerData player, ClassSkill skill) {
|
||||
Placeholders holders = new Placeholders();
|
||||
holders.register("skill", skill.getSkill().getName());
|
||||
holders.register("unlock", "" + skill.getUnlockLevel());
|
||||
holders.register("level", "" + player.getSkillLevel(skill.getSkill()));
|
||||
return holders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Placeholders getPlaceholders(SkillViewerInventory inv, int n) {
|
||||
return new Placeholders();
|
||||
}
|
||||
}
|
||||
|
||||
public class SkillViewerInventory extends GeneratedInventory {
|
||||
|
||||
// Cached information
|
||||
private final List<ClassSkill> skills;
|
||||
private final List<Integer> skillSlots;
|
||||
private final List<Integer> slotSlots;
|
||||
|
||||
private boolean binding;
|
||||
private ClassSkill selected;
|
||||
|
||||
public SkillViewerInventory(PlayerData playerData, EditableInventory editable) {
|
||||
super(playerData, editable);
|
||||
|
||||
skills = new ArrayList<>(playerData.getProfess().getSkills());
|
||||
skillSlots = getEditable().getByFunction("skill").getSlots();
|
||||
slotSlots = getEditable().getByFunction("slot").getSlots();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String calculateName() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
int selectedSkillSlot = ((SkillItem) getEditable().getByFunction("skill")).selectedSkillSlot;
|
||||
selected = skills.get(mod(selectedSkillSlot + playerData.skillGuiDisplayOffset, skills.size()));
|
||||
|
||||
super.open();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void whenClicked(InventoryClickEvent event, InventoryItem item) {
|
||||
|
||||
if (skillSlots.contains(event.getRawSlot())
|
||||
&& event.getRawSlot() != ((SkillItem) getEditable().getByFunction("skill")).selectedSkillSlot) {
|
||||
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 1, 2);
|
||||
playerData.skillGuiDisplayOffset = (playerData.skillGuiDisplayOffset + (event.getRawSlot() - 13)) % skills.size();
|
||||
open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.getFunction().equals("previous")) {
|
||||
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 1, 2);
|
||||
playerData.skillGuiDisplayOffset = (playerData.skillGuiDisplayOffset - 1) % skills.size();
|
||||
open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.getFunction().equals("next")) {
|
||||
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 1, 2);
|
||||
playerData.skillGuiDisplayOffset = (playerData.skillGuiDisplayOffset + 1) % skills.size();
|
||||
open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.getFunction().equals("switch")) {
|
||||
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 1, 2);
|
||||
binding = !binding;
|
||||
open();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* binding or unbinding skills.
|
||||
*/
|
||||
if (binding) {
|
||||
for (int index = 0; index < slotSlots.size(); index++) {
|
||||
int slot = slotSlots.get(index);
|
||||
if (event.getRawSlot() == slot) {
|
||||
|
||||
// unbind if there is a current spell.
|
||||
if (event.getAction() == InventoryAction.PICKUP_HALF) {
|
||||
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();
|
||||
return;
|
||||
}
|
||||
|
||||
if (selected == null)
|
||||
return;
|
||||
|
||||
if (selected.getSkill().isPassive()) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-active-skill").send(player);
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!playerData.hasSkillUnlocked(selected)) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-unlocked-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.setBoundSkill(index, selected);
|
||||
open();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* upgrading a player skill
|
||||
*/
|
||||
} else if (item.getFunction().equals("upgrade")) {
|
||||
if (!playerData.hasSkillUnlocked(selected)) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-unlocked-skill").send(player);
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (playerData.getSkillPoints() < 1) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-enough-skill-points").send(player);
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (selected.hasMaxLevel() && playerData.getSkillLevel(selected.getSkill()) >= selected.getMaxLevel()) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("skill-max-level-hit").send(player);
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int mod(int x, int n) {
|
||||
return x < 0 ? (x + n) : (x % n);
|
||||
}
|
||||
}
|
@ -39,9 +39,7 @@ public class BlockListener implements Listener {
|
||||
String savedData = event.getBlock().getBlockData().getAsString();
|
||||
Block block = event.getBlock();
|
||||
|
||||
/*
|
||||
* Check for custom mining in the current region first.
|
||||
*/
|
||||
// Check for custom mining in the current region first.
|
||||
boolean customMine = MMOCore.plugin.mineManager.isEnabled(player, block.getLocation());
|
||||
if (!customMine)
|
||||
return;
|
||||
@ -70,9 +68,7 @@ public class BlockListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extra breaking conditions.
|
||||
*/
|
||||
// Extra breaking conditions.
|
||||
if (!info.getBlock().breakRestrictions(block)) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
|
@ -1,10 +1,13 @@
|
||||
package net.Indyuce.mmocore.listener;
|
||||
|
||||
import io.lumine.mythic.lib.api.player.EquipmentSlot;
|
||||
import io.lumine.mythic.lib.player.PlayerMetadata;
|
||||
import io.lumine.mythic.lib.skill.trigger.TriggerMetadata;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.manager.ConfigManager;
|
||||
import net.Indyuce.mmocore.manager.SoundManager;
|
||||
import net.Indyuce.mmocore.skill.Skill.SkillInfo;
|
||||
import net.Indyuce.mmocore.skill.ClassSkill;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -80,7 +83,7 @@ public class SpellCast implements Listener {
|
||||
return;
|
||||
|
||||
/*
|
||||
* when the event is cancelled, another playerItemHeldEvent is
|
||||
* 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.
|
||||
*/
|
||||
@ -91,12 +94,14 @@ public class SpellCast implements Listener {
|
||||
int slot = event.getNewSlot() + (event.getNewSlot() >= player.getInventory().getHeldItemSlot() ? -1 : 0);
|
||||
|
||||
/*
|
||||
* the event is called again soon after the first since when
|
||||
* 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 && playerData.hasSkillBound(slot))
|
||||
playerData.cast(playerData.getBoundSkill(slot));
|
||||
if (slot >= 0 && playerData.hasSkillBound(slot)) {
|
||||
PlayerMetadata caster = playerData.getMMOPlayerData().getStatMap().cache(EquipmentSlot.MAIN_HAND);
|
||||
playerData.getBoundSkill(slot).toCastable(playerData).cast(new TriggerMetadata(caster, null, null));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@ -123,9 +128,9 @@ public class SpellCast implements Listener {
|
||||
StringBuilder str = new StringBuilder();
|
||||
if (!data.isOnline()) return str.toString();
|
||||
for (int j = 0; j < data.getBoundSkills().size(); j++) {
|
||||
SkillInfo skill = data.getBoundSkill(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.getSkill()).getRemaining() / 1000))
|
||||
? onCooldown.replace("{cooldown}", String.valueOf(data.getCooldownMap().getInfo(skill).getRemaining() / 1000))
|
||||
: noMana(data, skill) ? noMana : ready).replace("{index}", "" + (j + 1 + (data.getPlayer().getInventory().getHeldItemSlot()
|
||||
<= j ? 1 : 0))).replace("{skill}", data.getBoundSkill(j).getSkill().getName()));
|
||||
}
|
||||
@ -138,11 +143,11 @@ public class SpellCast implements Listener {
|
||||
* 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, SkillInfo skill) {
|
||||
return data.getCooldownMap().isOnCooldown(skill.getSkill());
|
||||
private boolean onCooldown(PlayerData data, ClassSkill skill) {
|
||||
return data.getCooldownMap().isOnCooldown(skill);
|
||||
}
|
||||
|
||||
private boolean noMana(PlayerData data, SkillInfo skill) {
|
||||
private boolean noMana(PlayerData data, ClassSkill skill) {
|
||||
return skill.getSkill().hasModifier("mana") && skill.getModifier("mana", data.getSkillLevel(skill.getSkill())) > data.getMana();
|
||||
}
|
||||
|
||||
|
@ -1,128 +1,84 @@
|
||||
package net.Indyuce.mmocore.manager;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.skill.handler.SkillHandler;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.ConfigFile;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.skill.RegisteredSkill;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.*;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.ConfigFile;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.comp.mythicmobs.MythicSkill;
|
||||
|
||||
public class SkillManager implements MMOCoreManager {
|
||||
private final Map<String, Skill> skills = new LinkedHashMap<>();
|
||||
private final Map<String, RegisteredSkill> skills = new LinkedHashMap<>();
|
||||
|
||||
private boolean hasLoadedDefaultSkills;
|
||||
public void registerSkill(RegisteredSkill skill) {
|
||||
skills.put(skill.getHandler().getId().toUpperCase(), skill);
|
||||
}
|
||||
|
||||
public void register(Skill skill) {
|
||||
skills.put(skill.getId().toUpperCase(), skill);
|
||||
}
|
||||
public RegisteredSkill getSkill(String id) {
|
||||
return skills.get(id.toUpperCase());
|
||||
}
|
||||
|
||||
public Skill get(String id) {
|
||||
return skills.get(id.toUpperCase());
|
||||
}
|
||||
public boolean hasSkill(String id) {
|
||||
return skills.containsKey(id.toUpperCase());
|
||||
}
|
||||
|
||||
public boolean has(String id) {
|
||||
return skills.containsKey(id.toUpperCase());
|
||||
}
|
||||
public Collection<RegisteredSkill> getAll() {
|
||||
return skills.values();
|
||||
}
|
||||
|
||||
public Collection<Skill> getAll() {
|
||||
return skills.values();
|
||||
}
|
||||
public void initialize(boolean clearBefore) {
|
||||
|
||||
public Set<Skill> getActive() {
|
||||
return skills.values().stream().filter(skill -> !skill.isPassive()).collect(Collectors.toSet());
|
||||
}
|
||||
if (clearBefore)
|
||||
skills.clear();
|
||||
|
||||
public Set<String> getKeys() {
|
||||
return skills.keySet();
|
||||
}
|
||||
File skillsFolder = new File(MMOCore.plugin.getDataFolder() + "/skills");
|
||||
if (!skillsFolder.exists())
|
||||
skillsFolder.mkdir();
|
||||
|
||||
@Override
|
||||
public void initialize(boolean clearBefore) {
|
||||
// Check for default files
|
||||
File skillFolder = new File(MMOCore.plugin.getDataFolder() + "/skills");
|
||||
if (!skillFolder.exists())
|
||||
try {
|
||||
skillFolder.mkdir();
|
||||
|
||||
if (clearBefore) {
|
||||
for (SkillHandler handler : MythicLib.plugin.getSkills().getHandlers()) {
|
||||
InputStream res = MMOCore.plugin.getResource("default/skills/" + handler.getLowerCaseId() + ".yml");
|
||||
if (res != null)
|
||||
Files.copy(res, new File(MMOCore.plugin.getDataFolder() + "/skills/" + handler.getLowerCaseId() + ".yml").getAbsoluteFile().toPath());
|
||||
}
|
||||
} catch (IOException exception) {
|
||||
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not save default skill configs: " + exception.getMessage());
|
||||
}
|
||||
|
||||
// Only remove custom skills
|
||||
Iterator<Skill> ite = skills.values().iterator();
|
||||
while (ite.hasNext()) {
|
||||
Skill next = ite.next();
|
||||
if (next instanceof MythicSkill)
|
||||
ite.remove();
|
||||
}
|
||||
}
|
||||
for (SkillHandler handler : MythicLib.plugin.getSkills().getHandlers()) {
|
||||
|
||||
if (!hasLoadedDefaultSkills)
|
||||
try {
|
||||
hasLoadedDefaultSkills = true;
|
||||
JarFile jarFile = new JarFile(MMOCore.plugin.getJarFile());
|
||||
JarEntry entry;
|
||||
for (Enumeration<JarEntry> en = jarFile.entries(); en.hasMoreElements();)
|
||||
if ((entry = en.nextElement()).getName().startsWith("net/Indyuce/mmocore/skill/list/")
|
||||
&& !entry.isDirectory() && !entry.getName().contains("$"))
|
||||
register((Skill) Class.forName(entry.getName().replace("/", ".").replace(".class", "")).getDeclaredConstructor().newInstance());
|
||||
jarFile.close();
|
||||
} catch (IOException | InstantiationException | IllegalAccessException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException exception) {
|
||||
exception.printStackTrace();
|
||||
MMOCore.log(Level.WARNING, "Could not load skills! Careful with player data :(");
|
||||
}
|
||||
// Check if config file exists
|
||||
ConfigFile config = new ConfigFile("/skills", handler.getLowerCaseId());
|
||||
if (!config.exists()) {
|
||||
config.getConfig().set("name", MMOCoreUtils.caseOnWords(handler.getId().replace("_", " ").replace("-", " ").toLowerCase()));
|
||||
config.getConfig().set("lore", Arrays.asList("This is the default skill description", "", "&e{cooldown}s Cooldown", "&9Costs {mana} {mana_name}"));
|
||||
config.getConfig().set("material", "BOOK");
|
||||
for (Object mod : handler.getModifiers()) {
|
||||
config.getConfig().set(mod + ".base", 0);
|
||||
config.getConfig().set(mod + ".per-level", 0);
|
||||
config.getConfig().set(mod + ".min", 0);
|
||||
config.getConfig().set(mod + ".max", 0);
|
||||
}
|
||||
config.save();
|
||||
}
|
||||
|
||||
if (!new File(MMOCore.plugin.getDataFolder() + "/skills").exists())
|
||||
new File(MMOCore.plugin.getDataFolder() + "/skills").mkdir();
|
||||
|
||||
File mythicMobs = new File(MMOCore.plugin.getDataFolder() + "/skills/mythic-mobs");
|
||||
if (!mythicMobs.exists())
|
||||
mythicMobs.mkdir();
|
||||
|
||||
// Load MythicMobs addon skills
|
||||
if (Bukkit.getPluginManager().getPlugin("MythicMobs") != null)
|
||||
for (File file : mythicMobs.listFiles()) {
|
||||
try {
|
||||
register(new MythicSkill(file.getName().substring(0, file.getName().length() - 4).toUpperCase(),
|
||||
YamlConfiguration.loadConfiguration(file)));
|
||||
} catch (Exception exception) {
|
||||
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load skill from " + file.getName() + ": " + exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Load configuration for default skills
|
||||
for (Skill skill : getAll())
|
||||
if (!(skill instanceof MythicSkill)) {
|
||||
File file = new File(MMOCore.plugin.getDataFolder() + "/skills", skill.getLowerCaseId() + ".yml");
|
||||
ConfigFile config = new ConfigFile("/skills", skill.getLowerCaseId());
|
||||
|
||||
if (!file.exists()) {
|
||||
config.getConfig().set("name", skill.getName());
|
||||
config.getConfig().set("lore", skill.getLore());
|
||||
|
||||
/*
|
||||
* It does support custom modeled items but it does not
|
||||
* provide default configs for that.
|
||||
*/
|
||||
config.getConfig().set("material", skill.getIcon().getType().name());
|
||||
|
||||
for (String mod : skill.getModifiers()) {
|
||||
LinearValue value = skill.getModifierInfo(mod);
|
||||
config.getConfig().set(mod + ".base", value.getBaseValue());
|
||||
config.getConfig().set(mod + ".per-level", value.getPerLevel());
|
||||
if (value.hasMax())
|
||||
config.getConfig().set(mod + ".max", value.getMax());
|
||||
if (value.hasMin())
|
||||
config.getConfig().set(mod + ".min", value.getMin());
|
||||
}
|
||||
config.save();
|
||||
}
|
||||
|
||||
skill.update(config.getConfig());
|
||||
}
|
||||
}
|
||||
RegisteredSkill skill = new RegisteredSkill(handler, config.getConfig());
|
||||
this.skills.put(handler.getId(), skill);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ public class MySQLPlayerDataManager extends PlayerDataManager {
|
||||
|
||||
sql.updateJSONArray("waypoints", data.getWaypoints());
|
||||
sql.updateJSONArray("friends", data.getFriends().stream().map(UUID::toString).collect(Collectors.toList()));
|
||||
sql.updateJSONArray("bound_skills", data.getBoundSkills().stream().map(skill -> skill.getSkill().getId()).collect(Collectors.toList()));
|
||||
sql.updateJSONArray("bound_skills", data.getBoundSkills().stream().map(skill -> skill.getSkill().getHandler().getId()).collect(Collectors.toList()));
|
||||
|
||||
sql.updateJSONObject("skills", data.mapSkillLevels().entrySet());
|
||||
|
||||
|
@ -95,7 +95,7 @@ public class YAMLPlayerDataManager extends PlayerDataManager {
|
||||
data.mapSkillLevels().forEach((key1, value) -> config.set("skill." + key1, value));
|
||||
|
||||
List<String> boundSkills = new ArrayList<>();
|
||||
data.getBoundSkills().forEach(skill -> boundSkills.add(skill.getSkill().getId()));
|
||||
data.getBoundSkills().forEach(skill -> boundSkills.add(skill.getSkill().getHandler().getId()));
|
||||
config.set("bound-skills", boundSkills);
|
||||
|
||||
config.set("attribute", null);
|
||||
|
87
src/main/java/net/Indyuce/mmocore/skill/CastableSkill.java
Normal file
87
src/main/java/net/Indyuce/mmocore/skill/CastableSkill.java
Normal file
@ -0,0 +1,87 @@
|
||||
package net.Indyuce.mmocore.skill;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.comp.flags.CustomFlag;
|
||||
import io.lumine.mythic.lib.player.cooldown.CooldownInfo;
|
||||
import io.lumine.mythic.lib.skill.Skill;
|
||||
import io.lumine.mythic.lib.skill.SkillMetadata;
|
||||
import io.lumine.mythic.lib.skill.handler.SkillHandler;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
|
||||
public class CastableSkill extends Skill {
|
||||
private final ClassSkill skill;
|
||||
private final int skillLevel;
|
||||
|
||||
public CastableSkill(ClassSkill skill, int skillLevel) {
|
||||
this.skill = skill;
|
||||
this.skillLevel = skillLevel;
|
||||
}
|
||||
|
||||
public ClassSkill getSkill() {
|
||||
return skill;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getResult(SkillMetadata skillMeta) {
|
||||
PlayerData playerData = PlayerData.get(skillMeta.getCaster().getData().getUniqueId());
|
||||
|
||||
// If the caster has unlocked that skill
|
||||
if (!playerData.hasSkillUnlocked(skill)) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("not-unlocked-skill").send(playerData.getPlayer());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cooldown check
|
||||
if (!skillMeta.getCaster().getData().getCooldownMap().isOnCooldown(this)) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("casting.on-cooldown").send(playerData.getPlayer());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mana cost
|
||||
if (playerData.getMana() < getModifier("mana")) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("casting.no-mana", "mana", playerData.getProfess().getManaDisplay().getName()).send(playerData.getPlayer());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stamina cost
|
||||
if (playerData.getStamina() < getModifier("stamina")) {
|
||||
MMOCore.plugin.configManager.getSimpleMessage("casting.no-stamina").send(playerData.getPlayer());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ability flag
|
||||
if (!MythicLib.plugin.getFlags().isFlagAllowed(skillMeta.getCaster().getPlayer(), CustomFlag.MMO_ABILITIES))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void whenCast(SkillMetadata skillMeta) {
|
||||
PlayerData casterData = PlayerData.get(skillMeta.getCaster().getData().getUniqueId());
|
||||
|
||||
// Apply cooldown, mana and stamina costs
|
||||
if (!casterData.noCooldown) {
|
||||
|
||||
// Cooldown
|
||||
double flatCooldownReduction = Math.max(0, Math.min(1, skillMeta.getCaster().getStat("COOLDOWN_REDUCTION") / 100));
|
||||
CooldownInfo cooldownHandler = skillMeta.getCaster().getData().getCooldownMap().applyCooldown(this, getModifier("cooldown"));
|
||||
cooldownHandler.reduceInitialCooldown(flatCooldownReduction);
|
||||
|
||||
casterData.giveMana(-getModifier("mana"), PlayerResourceUpdateEvent.UpdateReason.SKILL_COST);
|
||||
casterData.giveStamina(-getModifier("stamina"), PlayerResourceUpdateEvent.UpdateReason.SKILL_COST);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillHandler<?> getHandler() {
|
||||
return skill.getSkill().getHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getModifier(String mod) {
|
||||
return skill.getModifier(mod, skillLevel);
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.player.EquipmentSlot;
|
||||
import io.lumine.mythic.lib.api.stat.StatMap;
|
||||
import io.lumine.mythic.lib.damage.AttackMetadata;
|
||||
import io.lumine.mythic.lib.damage.DamageMetadata;
|
||||
import io.lumine.mythic.lib.damage.DamageType;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class CasterMetadata {
|
||||
private final Player player;
|
||||
private final PlayerData caster;
|
||||
private final StatMap.CachedStatMap stats;
|
||||
|
||||
/**
|
||||
* Instantiated every time a player casts a skill. This is
|
||||
* used to temporarily cache the player's statistics
|
||||
*
|
||||
* @param caster Player casting the skill
|
||||
*/
|
||||
public CasterMetadata(PlayerData caster) {
|
||||
this.player = caster.getPlayer();
|
||||
this.caster = caster;
|
||||
this.stats = caster.getMMOPlayerData().getStatMap().cache(EquipmentSlot.MAIN_HAND);
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public PlayerData getPlayerData() {
|
||||
return caster;
|
||||
}
|
||||
|
||||
public StatMap.CachedStatMap getStats() {
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that makes a player deal damage to a specific
|
||||
* entity. This creates the attackMetadata based on the data
|
||||
* stored by the CasterMetadata, and calls it using MythicLib
|
||||
* damage manager
|
||||
*
|
||||
* @param target Target entity
|
||||
* @param damage Damage dealt
|
||||
* @param types Type of target
|
||||
* @return
|
||||
*/
|
||||
public void attack(LivingEntity target, double damage, DamageType... types) {
|
||||
AttackMetadata attackMeta = new AttackMetadata(new DamageMetadata(damage, types), stats);
|
||||
MythicLib.plugin.getDamage().damage(attackMeta, target);
|
||||
}
|
||||
}
|
123
src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java
Normal file
123
src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java
Normal file
@ -0,0 +1,123 @@
|
||||
package net.Indyuce.mmocore.skill;
|
||||
|
||||
import io.lumine.mythic.lib.api.player.EquipmentSlot;
|
||||
import io.lumine.mythic.lib.api.stat.modifier.ModifierSource;
|
||||
import io.lumine.mythic.lib.player.cooldown.CooldownObject;
|
||||
import io.lumine.mythic.lib.skill.trigger.PassiveSkill;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.IntegerLinearValue;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ClassSkill implements CooldownObject {
|
||||
private final RegisteredSkill skill;
|
||||
private final int unlockLevel, maxSkillLevel;
|
||||
private final Map<String, LinearValue> modifiers = new HashMap<>();
|
||||
|
||||
public ClassSkill(RegisteredSkill skill, int unlockLevel) {
|
||||
this(skill, unlockLevel, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class used to save information about skills IN A CLASS CONTEXT i.e at
|
||||
* which level the skill can be unlocked, etc.
|
||||
*/
|
||||
public ClassSkill(RegisteredSkill skill, int unlockLevel, int maxSkillLevel) {
|
||||
this.skill = skill;
|
||||
this.unlockLevel = unlockLevel;
|
||||
this.maxSkillLevel = maxSkillLevel;
|
||||
|
||||
for (String mod : skill.getHandler().getModifiers())
|
||||
this.modifiers.put(mod, skill.getModifierInfo(mod));
|
||||
}
|
||||
|
||||
public ClassSkill(RegisteredSkill skill, ConfigurationSection config) {
|
||||
this.skill = skill;
|
||||
unlockLevel = config.getInt("level");
|
||||
maxSkillLevel = config.getInt("max-level");
|
||||
|
||||
for (String mod : skill.getHandler().getModifiers()) {
|
||||
LinearValue defaultValue = skill.getModifierInfo(mod);
|
||||
this.modifiers.put(mod, config.isConfigurationSection(mod) ? readLinearValue(defaultValue, config.getConfigurationSection(mod)) : defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
public RegisteredSkill getSkill() {
|
||||
return skill;
|
||||
}
|
||||
|
||||
public int getUnlockLevel() {
|
||||
return unlockLevel;
|
||||
}
|
||||
|
||||
public boolean hasMaxLevel() {
|
||||
return maxSkillLevel > 0;
|
||||
}
|
||||
|
||||
public int getMaxLevel() {
|
||||
return maxSkillLevel;
|
||||
}
|
||||
|
||||
/*
|
||||
* this method can only OVERRIDE default modifiers
|
||||
*/
|
||||
public void addModifier(String modifier, LinearValue linear) {
|
||||
if (modifiers.containsKey(modifier))
|
||||
modifiers.put(modifier, linear);
|
||||
}
|
||||
|
||||
public double getModifier(String modifier, int level) {
|
||||
return modifiers.get(modifier).calculate(level);
|
||||
}
|
||||
|
||||
public List<String> calculateLore(PlayerData data) {
|
||||
return calculateLore(data, data.getSkillLevel(skill));
|
||||
}
|
||||
|
||||
public List<String> calculateLore(PlayerData data, int x) {
|
||||
List<String> list = new ArrayList<>();
|
||||
|
||||
Map<String, String> placeholders = calculateModifiers(x);
|
||||
placeholders.put("mana_name", data.getProfess().getManaDisplay().getName());
|
||||
skill.getLore().forEach(str -> list.add(applyPlaceholders(placeholders, str)));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private String applyPlaceholders(Map<String, String> placeholders, String str) {
|
||||
while (str.contains("{") && str.substring(str.indexOf("{")).contains("}")) {
|
||||
String holder = str.substring(str.indexOf("{") + 1, str.indexOf("}"));
|
||||
str = str.replace("{" + holder + "}", placeholders.getOrDefault(holder, "PHE"));
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
private Map<String, String> calculateModifiers(int x) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
modifiers.keySet().forEach(modifier -> map.put(modifier, modifiers.get(modifier).getDisplay(x)));
|
||||
return map;
|
||||
}
|
||||
|
||||
private LinearValue readLinearValue(LinearValue current, ConfigurationSection config) {
|
||||
return current instanceof IntegerLinearValue ? new IntegerLinearValue(config) : new LinearValue(config);
|
||||
}
|
||||
|
||||
public CastableSkill toCastable(PlayerData caster) {
|
||||
return new CastableSkill(this, caster.getSkillLevel(getSkill()));
|
||||
}
|
||||
|
||||
public PassiveSkill toPassive(PlayerData caster) {
|
||||
Validate.isTrue(skill.hasTrigger(), "Skill is active");
|
||||
return new PassiveSkill("MMOCorePassiveSkill", skill.getTrigger(), toCastable(caster), EquipmentSlot.OTHER, ModifierSource.OTHER);
|
||||
}
|
||||
|
||||
public String getCooldownPath() {
|
||||
return "skill_" + skill.getHandler().getId();
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill;
|
||||
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class PassiveSkill extends Skill implements Listener {
|
||||
public PassiveSkill() {
|
||||
super();
|
||||
}
|
||||
|
||||
public PassiveSkill(String id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillMetadata whenCast(CasterMetadata casterMeta, SkillInfo skill) {
|
||||
return new SkillMetadata(casterMeta, skill);
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.skill.Skill.SkillInfo;
|
||||
|
||||
/**
|
||||
* Note: any method which return longs returns milliseconds.
|
||||
*
|
||||
* @author cympe
|
||||
*/
|
||||
public class PlayerSkillData {
|
||||
private final Map<String, Long> cooldowns = new HashMap<>();
|
||||
private final PlayerData data;
|
||||
|
||||
public PlayerSkillData(PlayerData data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public long getCooldown(SkillInfo skill) {
|
||||
return Math.max(0, lastCast(skill.getSkill()) - System.currentTimeMillis()
|
||||
+ (long) (1000. * skill.getModifier("cooldown", data.getSkillLevel(skill.getSkill()))));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param skill
|
||||
* Skill that was cast
|
||||
* @return Last time stamp the skill was cast or 0 if never
|
||||
*/
|
||||
public long lastCast(Skill skill) {
|
||||
return cooldowns.containsKey(skill.getId()) ? cooldowns.get(skill.getId()) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the last time the player cast the skill at current time
|
||||
*
|
||||
* @param skill
|
||||
* Skill being cast
|
||||
*/
|
||||
public void setLastCast(Skill skill) {
|
||||
setLastCast(skill, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the last time the player cast the skill at given time
|
||||
*
|
||||
* @param ms
|
||||
* Time stammp
|
||||
* @param skill
|
||||
* Skill being cast
|
||||
*/
|
||||
public void setLastCast(Skill skill, long ms) {
|
||||
cooldowns.put(skill.getId(), ms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces the remaining cooldown of a specific skill
|
||||
*
|
||||
* @param skill
|
||||
* Skill cast
|
||||
* @param value
|
||||
* Amount of skill cooldown instant reduction.
|
||||
* @param relative
|
||||
* If the cooldown reduction is relative to the remaining
|
||||
* cooldown. If set to true, instant reduction is equal to
|
||||
* (value) * (skill cooldown). If set to false, instant reduction
|
||||
* is the given flat value
|
||||
*/
|
||||
public void reduceCooldown(SkillInfo skill, double value, boolean relative) {
|
||||
long reduction = (long) (relative ? value * (double) getCooldown(skill) : value * 1000.);
|
||||
cooldowns.put(skill.getSkill().getId(), lastCast(skill.getSkill()) + reduction);
|
||||
}
|
||||
}
|
121
src/main/java/net/Indyuce/mmocore/skill/RegisteredSkill.java
Normal file
121
src/main/java/net/Indyuce/mmocore/skill/RegisteredSkill.java
Normal file
@ -0,0 +1,121 @@
|
||||
package net.Indyuce.mmocore.skill;
|
||||
|
||||
import io.lumine.mythic.lib.skill.handler.SkillHandler;
|
||||
import io.lumine.mythic.lib.skill.trigger.TriggerType;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class RegisteredSkill {
|
||||
private final SkillHandler<?> handler;
|
||||
|
||||
private final String name;
|
||||
private final Map<String, LinearValue> defaultModifiers = new HashMap<>();
|
||||
private final ItemStack icon;
|
||||
private final List<String> lore;
|
||||
private final TriggerType triggerType;
|
||||
|
||||
public RegisteredSkill(SkillHandler<?> handler, ConfigurationSection config) {
|
||||
this.handler = handler;
|
||||
|
||||
name = Objects.requireNonNull(config.getString("name"), "Could not find skill name");
|
||||
icon = MMOCoreUtils.readIcon(Objects.requireNonNull(config.getString("material"), "Could not find skill icon"));
|
||||
lore = Objects.requireNonNull(config.getStringList("lore"), "Could not find skill lore");
|
||||
|
||||
// Trigger type
|
||||
Validate.isTrue(getHandler().isTriggerable() || !config.contains("passive-type"), "Cannot change the trigger type of a default passive skill");
|
||||
triggerType = config.contains("passive-type") ? TriggerType.valueOf(config.getString("passive-type").toUpperCase().replace(" ", "_").replace("-", "_")) : null;
|
||||
|
||||
for (String mod : handler.getModifiers())
|
||||
defaultModifiers.put(mod, config.contains(mod) ? new LinearValue(config.getConfigurationSection(mod)) : LinearValue.ZERO);
|
||||
}
|
||||
|
||||
public RegisteredSkill(SkillHandler<?> handler, String name, ItemStack icon, List<String> lore, @Nullable TriggerType triggerType) {
|
||||
this.handler = handler;
|
||||
this.name = name;
|
||||
this.icon = icon;
|
||||
this.lore = lore;
|
||||
this.triggerType = triggerType;
|
||||
}
|
||||
|
||||
public SkillHandler<?> getHandler() {
|
||||
return handler;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<String> getLore() {
|
||||
return lore;
|
||||
}
|
||||
|
||||
public ItemStack getIcon() {
|
||||
return icon.clone();
|
||||
}
|
||||
|
||||
public boolean hasModifier(String modifier) {
|
||||
return defaultModifiers.containsKey(modifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* There are three types of MMOCore skills:
|
||||
* - skills with no trigger type (therefore active)
|
||||
* - default passive skills with no trigger type
|
||||
* - custom skills with a trigger type (therefore passive)
|
||||
* <p>
|
||||
* Illegal:
|
||||
* - default passive skills with a trigger type
|
||||
*
|
||||
* @return If the skill should
|
||||
*/
|
||||
public boolean hasTrigger() {
|
||||
return triggerType != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Two types of passive skills:
|
||||
* - custom passive skills, with a trigger type
|
||||
* - default passive skills which are untriggerable
|
||||
* <p>
|
||||
* This option dictates whether or not it
|
||||
* can be cast when in casting mode.
|
||||
*
|
||||
* @return If the given skill is passive
|
||||
*/
|
||||
public boolean isPassive() {
|
||||
return triggerType != null || !getHandler().isTriggerable();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TriggerType getTrigger() {
|
||||
return Objects.requireNonNull(triggerType, "Skill has no trigger");
|
||||
}
|
||||
|
||||
public void addModifier(String modifier, LinearValue linear) {
|
||||
defaultModifiers.put(modifier, linear);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void addModifierIfNone(String mod, LinearValue defaultValue) {
|
||||
if (!hasModifier(mod))
|
||||
addModifier(mod, defaultValue);
|
||||
}
|
||||
|
||||
public LinearValue getModifierInfo(String modifier) {
|
||||
return defaultModifiers.get(modifier);
|
||||
}
|
||||
|
||||
public double getModifier(String modifier, int level) {
|
||||
return defaultModifiers.get(modifier).calculate(level);
|
||||
}
|
||||
}
|
@ -1,231 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill;
|
||||
|
||||
import io.lumine.mythic.lib.player.cooldown.CooldownObject;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.IntegerLinearValue;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public abstract class Skill implements CooldownObject {
|
||||
private final String id;
|
||||
|
||||
private String name;
|
||||
private ItemStack icon = new ItemStack(Material.BOOK);
|
||||
private List<String> lore;
|
||||
private boolean passive;
|
||||
|
||||
private final Map<String, LinearValue> modifiers = new HashMap<>();
|
||||
private final Skill skill = this;
|
||||
|
||||
protected static final Random random = new Random();
|
||||
|
||||
public Skill() {
|
||||
id = getClass().getSimpleName().toUpperCase();
|
||||
name = getClass().getSimpleName().replace("_", " ");
|
||||
|
||||
Validate.notNull(id, "ID cannot be null");
|
||||
Validate.notNull(id, "Name cannot be null");
|
||||
|
||||
// Default modifiers
|
||||
addModifierIfNone("mana", LinearValue.ZERO);
|
||||
addModifierIfNone("stamina", LinearValue.ZERO);
|
||||
}
|
||||
|
||||
public Skill(String id) {
|
||||
this.id = id.toUpperCase().replace(" ", "_").replace("-", "_");
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setMaterial(Material material) {
|
||||
setIcon(new ItemStack(material));
|
||||
}
|
||||
|
||||
public void setIcon(ItemStack item) {
|
||||
this.icon = item;
|
||||
}
|
||||
|
||||
public void setLore(String... lore) {
|
||||
setLore(Arrays.asList(lore));
|
||||
}
|
||||
|
||||
public void setLore(List<String> lore) {
|
||||
this.lore = lore;
|
||||
}
|
||||
|
||||
public void setPassive() {
|
||||
passive = true;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getLowerCaseId() {
|
||||
return id.replace("_", "-").toLowerCase();
|
||||
}
|
||||
|
||||
public List<String> getLore() {
|
||||
return lore;
|
||||
}
|
||||
|
||||
public ItemStack getIcon() {
|
||||
return icon.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCooldownPath() {
|
||||
return "mmocore_skill_" + id.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Passive skills do not display any message when trying to cast them
|
||||
*
|
||||
* @return If the skill is passive
|
||||
*/
|
||||
public boolean isPassive() {
|
||||
return passive;
|
||||
}
|
||||
|
||||
public boolean hasModifier(String modifier) {
|
||||
return modifiers.containsKey(modifier);
|
||||
}
|
||||
|
||||
public void addModifier(String modifier, LinearValue linear) {
|
||||
modifiers.put(modifier, linear);
|
||||
}
|
||||
|
||||
public void addModifierIfNone(String mod, LinearValue defaultValue) {
|
||||
if (!hasModifier(mod))
|
||||
addModifier(mod, defaultValue);
|
||||
}
|
||||
|
||||
public LinearValue getModifierInfo(String modifier) {
|
||||
return modifiers.get(modifier);
|
||||
}
|
||||
|
||||
public double getModifier(String modifier, int level) {
|
||||
return modifiers.get(modifier).calculate(level);
|
||||
}
|
||||
|
||||
public Set<String> getModifiers() {
|
||||
return modifiers.keySet();
|
||||
}
|
||||
|
||||
public void update(FileConfiguration config) {
|
||||
name = config.getString("name", "INVALID NAME");
|
||||
lore = config.getStringList("lore");
|
||||
icon = MMOCoreUtils.readIcon(config.getString("material", "DIRT"));
|
||||
|
||||
for (String modifier : modifiers.keySet())
|
||||
if (config.contains(modifier))
|
||||
modifiers.put(modifier, readLinearValue(modifiers.get(modifier), config.getConfigurationSection(modifier)));
|
||||
}
|
||||
|
||||
private LinearValue readLinearValue(LinearValue current, ConfigurationSection config) {
|
||||
return current instanceof IntegerLinearValue ? new IntegerLinearValue(config) : new LinearValue(config);
|
||||
}
|
||||
|
||||
public abstract SkillMetadata whenCast(CasterMetadata casterMeta, SkillInfo skill);
|
||||
|
||||
public SkillInfo newSkillInfo(ConfigurationSection config) {
|
||||
return new SkillInfo(config);
|
||||
}
|
||||
|
||||
public SkillInfo newSkillInfo(int level) {
|
||||
return new SkillInfo(level);
|
||||
}
|
||||
|
||||
public class SkillInfo {
|
||||
private final int level, max;
|
||||
private final Map<String, LinearValue> modifiers = new HashMap<>(skill.modifiers);
|
||||
|
||||
/*
|
||||
* class used to save information about skills IN A CLASS CONTEXT i.e at
|
||||
* which level the skill can be unlocked, etc.
|
||||
*/
|
||||
public SkillInfo(int level) {
|
||||
this.level = level;
|
||||
this.max = 0;
|
||||
}
|
||||
|
||||
public SkillInfo(ConfigurationSection config) {
|
||||
level = config.getInt("level");
|
||||
max = config.getInt("max-level");
|
||||
|
||||
for (String key : config.getKeys(false))
|
||||
if (config.get(key) instanceof ConfigurationSection && modifiers.containsKey(key))
|
||||
modifiers.put(key, readLinearValue(modifiers.get(key), config.getConfigurationSection(key)));
|
||||
}
|
||||
|
||||
public Skill getSkill() {
|
||||
return skill;
|
||||
}
|
||||
|
||||
public int getUnlockLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public boolean hasMaxLevel() {
|
||||
return max > 0;
|
||||
}
|
||||
|
||||
public int getMaxLevel() {
|
||||
return max;
|
||||
}
|
||||
|
||||
/*
|
||||
* this method can only OVERRIDE default modifiers
|
||||
*/
|
||||
public void addModifier(String modifier, LinearValue linear) {
|
||||
if (modifiers.containsKey(modifier))
|
||||
modifiers.put(modifier, linear);
|
||||
}
|
||||
|
||||
public double getModifier(String modifier, int level) {
|
||||
return modifiers.get(modifier).calculate(level);
|
||||
}
|
||||
|
||||
public List<String> calculateLore(PlayerData data) {
|
||||
return calculateLore(data, data.getSkillLevel(skill));
|
||||
}
|
||||
|
||||
public List<String> calculateLore(PlayerData data, int x) {
|
||||
List<String> list = new ArrayList<>();
|
||||
|
||||
Map<String, String> placeholders = calculateModifiers(x);
|
||||
placeholders.put("mana_name", data.getProfess().getManaDisplay().getName());
|
||||
lore.forEach(str -> list.add(applyPlaceholders(placeholders, str)));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private String applyPlaceholders(Map<String, String> placeholders, String str) {
|
||||
while (str.contains("{") && str.substring(str.indexOf("{")).contains("}")) {
|
||||
String holder = str.substring(str.indexOf("{") + 1, str.indexOf("}"));
|
||||
str = str.replace("{" + holder + "}", placeholders.getOrDefault(holder, "PHE"));
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
private Map<String, String> calculateModifiers(int x) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
modifiers.keySet().forEach(modifier -> map.put(modifier, modifiers.get(modifier).getDisplay(x)));
|
||||
return map;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,71 +1,80 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.event.PlayerAttackEvent;
|
||||
import io.lumine.mythic.lib.api.player.MMOPlayerData;
|
||||
import io.lumine.mythic.lib.damage.DamageType;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import io.lumine.mythic.lib.skill.SkillMetadata;
|
||||
import io.lumine.mythic.lib.skill.handler.SkillHandler;
|
||||
import io.lumine.mythic.lib.skill.result.def.SimpleSkillResult;
|
||||
import io.lumine.mythic.lib.skill.trigger.PassiveSkill;
|
||||
import io.lumine.mythic.lib.skill.trigger.TriggerMetadata;
|
||||
import io.lumine.mythic.lib.util.EntityLocationType;
|
||||
import io.lumine.mythic.lib.util.ParabolicProjectile;
|
||||
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.api.util.math.particle.ParabolicProjectile;
|
||||
import net.Indyuce.mmocore.skill.PassiveSkill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
public class Ambers extends PassiveSkill {
|
||||
public class Ambers extends SkillHandler<SimpleSkillResult> implements Listener {
|
||||
public Ambers() {
|
||||
super();
|
||||
super(false);
|
||||
|
||||
setMaterial(Material.EMERALD);
|
||||
setLore("Dealing magic damage has &630% &7chance", "of dropping an amber on the ground.", "", "When picked up, ambers stack and",
|
||||
"refund &9{percent}% &7of your missing mana.", "", "&oAmbers can be used in other damaging skills.",
|
||||
"&oThe more you collect, the more powerful the skills.", "", "&e{cooldown}s Cooldown");
|
||||
setPassive();
|
||||
registerModifiers("percent");
|
||||
}
|
||||
|
||||
addModifier("cooldown", new LinearValue(3, -.1, 1, 3));
|
||||
addModifier("percent", new LinearValue(10, .1, 10, 20));
|
||||
@Override
|
||||
public SimpleSkillResult getResult(SkillMetadata meta) {
|
||||
return new SimpleSkillResult(meta.hasAttackBound() && meta.hasTargetEntity() && meta.getTargetEntityOrNull() instanceof LivingEntity);
|
||||
}
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
|
||||
@Override
|
||||
public void whenCast(SimpleSkillResult result, SkillMetadata skillMeta) {
|
||||
LivingEntity target = (LivingEntity) skillMeta.getTargetEntityOrNull();
|
||||
Location loc = target.getLocation();
|
||||
|
||||
double a = random.nextDouble() * 2 * Math.PI;
|
||||
new Amber(skillMeta.getCaster().getData(), EntityLocationType.BODY.getLocation(target), loc.clone().add(4 * Math.cos(a), 0, 4 * Math.sin(a)), skillMeta.getModifier("percent"));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void a(PlayerAttackEvent event) {
|
||||
PlayerData data = PlayerData.get(event.getData().getUniqueId());
|
||||
if (!event.getAttack().getDamage().hasType(DamageType.SKILL) || !data.getProfess().hasSkill(this))
|
||||
public void spawnAmber(PlayerAttackEvent event) {
|
||||
MMOPlayerData data = event.getData();
|
||||
if (!event.getAttack().getDamage().hasType(DamageType.SKILL))
|
||||
return;
|
||||
|
||||
SkillMetadata cast = data.cast(this);
|
||||
if (!cast.isSuccessful())
|
||||
PassiveSkill passive = data.getPassiveSkill(this);
|
||||
if (passive == null)
|
||||
return;
|
||||
|
||||
Location loc = event.getEntity().getLocation();
|
||||
double a = random.nextDouble() * 2 * Math.PI;
|
||||
|
||||
new Amber(data, loc.add(0, event.getEntity().getHeight() / 2, 0), loc.clone().add(4 * Math.cos(a), 0, 4 * Math.sin(a)), cast.getModifier("percent"));
|
||||
passive.getTriggeredSkill().cast(new TriggerMetadata(event.getAttack(), event.getEntity()));
|
||||
}
|
||||
|
||||
public static class Amber extends BukkitRunnable {
|
||||
private final Location loc;
|
||||
private final PlayerData data;
|
||||
private final MMOPlayerData data;
|
||||
private final double percent;
|
||||
|
||||
private int j;
|
||||
|
||||
private Amber(PlayerData data, Location source, Location loc, double percent) {
|
||||
private Amber(MMOPlayerData data, Location source, Location loc, double percent) {
|
||||
this.loc = loc;
|
||||
this.data = data;
|
||||
this.percent = percent / 100;
|
||||
|
||||
final Amber amber = this;
|
||||
new ParabolicProjectile(source, loc, Particle.REDSTONE, () -> amber.runTaskTimer(MMOCore.plugin, 0, 3), 1, Color.ORANGE, 1.3f);
|
||||
new ParabolicProjectile(source, loc, Particle.REDSTONE, () -> amber.runTaskTimer(MythicLib.plugin, 0, 3), 1, Color.ORANGE, 1.3f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!data.isOnline()) return;
|
||||
if (j++ > 66 || !data.getPlayer().getWorld().equals(loc.getWorld())) {
|
||||
if (j++ > 66 || !data.isOnline() || !data.getPlayer().getWorld().equals(loc.getWorld())) {
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
@ -74,7 +83,11 @@ public class Ambers extends PassiveSkill {
|
||||
|
||||
data.getPlayer().playSound(data.getPlayer().getLocation(), Sound.BLOCK_END_PORTAL_FRAME_FILL, 1, 1);
|
||||
// data.getSkillData().ambers++;
|
||||
data.giveMana((data.getStats().getStat(StatType.MAX_MANA) - data.getMana()) * percent, PlayerResourceUpdateEvent.UpdateReason.SKILL_REGENERATION);
|
||||
|
||||
// Give mana back
|
||||
PlayerData playerData = PlayerData.get(data.getUniqueId());
|
||||
double missingMana = data.getStatMap().getStat("MAX_MANA") - playerData.getMana();
|
||||
playerData.giveMana(missingMana * percent, PlayerResourceUpdateEvent.UpdateReason.SKILL_REGENERATION);
|
||||
|
||||
cancel();
|
||||
return;
|
||||
|
@ -1,50 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.api.event.PlayerAttackEvent;
|
||||
import io.lumine.mythic.lib.damage.DamageType;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.skill.PassiveSkill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
||||
public class Backstab extends PassiveSkill {
|
||||
public Backstab() {
|
||||
super();
|
||||
|
||||
setMaterial(Material.FLINT);
|
||||
setLore("Backstabs deal &c{extra}%&7 damage.", "", "&9Costs {mana} {mana_name}");
|
||||
setPassive();
|
||||
|
||||
addModifier("cooldown", new LinearValue(0, 0));
|
||||
addModifier("mana", new LinearValue(8, 1));
|
||||
addModifier("extra", new LinearValue(50, 20));
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void a(PlayerAttackEvent event) {
|
||||
PlayerData data = PlayerData.get(event.getData().getUniqueId());
|
||||
LivingEntity target = event.getEntity();
|
||||
if (!event.getAttack().getDamage().hasType(DamageType.WEAPON)
|
||||
|| event.getPlayer().getEyeLocation().getDirection().angle(target.getEyeLocation().getDirection()) > Math.PI / 6
|
||||
|| !data.getProfess().hasSkill(this))
|
||||
return;
|
||||
|
||||
SkillMetadata cast = data.cast(this);
|
||||
if (!cast.isSuccessful())
|
||||
return;
|
||||
|
||||
data.cast(cast.getInfo());
|
||||
event.getAttack().getDamage().multiply(1 + cast.getModifier("extra") / 100, DamageType.PHYSICAL);
|
||||
target.getWorld().spawnParticle(Particle.CRIT, target.getLocation().add(0, target.getHeight() / 2, 0), 32, 0, 0, 0, .05);
|
||||
target.getWorld().playSound(target.getLocation(), Sound.ENTITY_ENDERMAN_HURT, 1, 1.5f);
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.damage.DamageType;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import net.Indyuce.mmocore.skill.metadata.TargetSkillMetadata;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
public class Combo_Attack extends Skill {
|
||||
public Combo_Attack() {
|
||||
super();
|
||||
|
||||
setMaterial(Material.IRON_SWORD);
|
||||
setLore("Violenty slashes your target &8{count}", "times for a total of &8{damage} &7damage.", "", "&e{cooldown}s Cooldown", "&9Costs {mana} {mana_name}");
|
||||
|
||||
addModifier("cooldown", new LinearValue(20, -.1, 5, 20));
|
||||
addModifier("damage", new LinearValue(9, .3));
|
||||
addModifier("count", new LinearValue(3, .2));
|
||||
addModifier("mana", new LinearValue(10, -.1, 3, 5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillMetadata whenCast(CasterMetadata caster, SkillInfo skill) {
|
||||
TargetSkillMetadata cast = new TargetSkillMetadata(caster, skill, 3);
|
||||
if (!cast.isSuccessful())
|
||||
return cast;
|
||||
|
||||
new BukkitRunnable() {
|
||||
final int count = (int) cast.getModifier("count");
|
||||
final double damage = cast.getModifier("damage") / count;
|
||||
final LivingEntity target = cast.getTarget();
|
||||
|
||||
int c;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (c++ > count || caster.getPlayerData().isOnline()) {
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
target.getWorld().playSound(target.getLocation(), Sound.ENTITY_PLAYER_ATTACK_KNOCKBACK, 1, 2);
|
||||
target.getWorld().spawnParticle(Particle.CRIT, target.getLocation().add(0, target.getHeight() / 2, 0), 24, 0, 0, 0, .7);
|
||||
caster.attack(target, damage, DamageType.SKILL, DamageType.PHYSICAL);
|
||||
}
|
||||
}.runTaskTimer(MMOCore.plugin, 0, 5);
|
||||
return cast;
|
||||
}
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.version.VersionMaterial;
|
||||
import io.lumine.mythic.lib.version.VersionSound;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import net.Indyuce.mmocore.skill.metadata.TargetSkillMetadata;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class Control extends Skill {
|
||||
public Control() {
|
||||
super();
|
||||
setMaterial(VersionMaterial.MAGENTA_DYE.toMaterial());
|
||||
setLore("Your target is temporarily slowed for &8{duration} &7seconds.", "As soon as you left click, it gets", "pushed back where you are looking at.", "Knockback force: &f{knockback}%", "", "&e{cooldown}s Cooldown", "&9Costs {mana} {mana_name}");
|
||||
|
||||
addModifier("cooldown", new LinearValue(18, -.3, 10, 20));
|
||||
addModifier("mana", new LinearValue(15, 1.5));
|
||||
addModifier("knockback", new LinearValue(30, 3));
|
||||
addModifier("duration", new LinearValue(2, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillMetadata whenCast(CasterMetadata caster, SkillInfo skill) {
|
||||
TargetSkillMetadata cast = new TargetSkillMetadata(caster, skill, 7);
|
||||
if (!cast.isSuccessful())
|
||||
return cast;
|
||||
|
||||
caster.getPlayer().getWorld().playSound(caster.getPlayer().getLocation(), Sound.BLOCK_END_PORTAL_FRAME_FILL, 1, 1);
|
||||
cast.getTarget().addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 20 * 2, 0));
|
||||
new TelekinesyRunnable(caster, cast.getTarget(), cast.getModifier("knockback") / 100, cast.getModifier("duration"));
|
||||
return cast;
|
||||
}
|
||||
|
||||
public static class TelekinesyRunnable extends BukkitRunnable implements Listener {
|
||||
private final LivingEntity entity;
|
||||
private final CasterMetadata caster;
|
||||
|
||||
private final double f, d;
|
||||
|
||||
private int j;
|
||||
|
||||
public TelekinesyRunnable(CasterMetadata caster, LivingEntity entity, double force, double duration) {
|
||||
this.entity = entity;
|
||||
this.caster = caster;
|
||||
|
||||
d = duration * 20;
|
||||
f = force;
|
||||
|
||||
runTaskTimer(MMOCore.plugin, 0, 1);
|
||||
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void a(PlayerInteractEvent event) {
|
||||
if (event.getPlayer().equals(caster.getPlayer()) && event.getAction().name().contains("LEFT_CLICK")) {
|
||||
Vector vec = caster.getPlayer().getEyeLocation().getDirection().multiply(3 * f);
|
||||
vec.setY(Math.max(.5, vec.getY() / 2));
|
||||
entity.setVelocity(vec);
|
||||
|
||||
/*
|
||||
* try not to interfere with other potion effects
|
||||
*/
|
||||
PotionEffect effect = entity.getPotionEffect(PotionEffectType.SLOW);
|
||||
if (effect.getDuration() < d && effect.getAmplifier() == 0)
|
||||
entity.removePotionEffect(PotionEffectType.SLOW);
|
||||
|
||||
entity.getWorld().spawnParticle(Particle.SPELL_WITCH, entity.getLocation().add(0, entity.getHeight() / 2, 0), 16);
|
||||
entity.getWorld().playSound(entity.getLocation(), VersionSound.ENTITY_FIREWORK_ROCKET_BLAST.toSound(), 2, 1);
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!caster.getPlayerData().isOnline() || entity.isDead() || j++ >= d) {
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
double a = (double) j / 3;
|
||||
entity.getWorld().spawnParticle(Particle.SPELL_WITCH, entity.getLocation().add(Math.cos(a), entity.getHeight() / 2, Math.sin(a)), 0);
|
||||
}
|
||||
|
||||
private void close() {
|
||||
cancel();
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.damage.DamageType;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import net.Indyuce.mmocore.skill.metadata.TargetSkillMetadata;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
|
||||
public class Deep_Wound extends Skill {
|
||||
public Deep_Wound() {
|
||||
super();
|
||||
setMaterial(Material.REDSTONE);
|
||||
setLore("You puncture your target, dealing &c{damage} &7damage.", "Damage is increased up to &c+{extra}% &7based",
|
||||
"on your target's missing health.", "", "&e{cooldown}s Cooldown", "&9Costs {mana} {mana_name}");
|
||||
|
||||
addModifier("cooldown", new LinearValue(20, -.1, 5, 20));
|
||||
addModifier("mana", new LinearValue(8, 3));
|
||||
addModifier("damage", new LinearValue(5, 1.5));
|
||||
addModifier("extra", new LinearValue(50, 20));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillMetadata whenCast(CasterMetadata caster, SkillInfo skill) {
|
||||
TargetSkillMetadata cast = new TargetSkillMetadata(caster, skill, 3);
|
||||
if (!cast.isSuccessful())
|
||||
return cast;
|
||||
|
||||
LivingEntity target = cast.getTarget();
|
||||
target.getWorld().playSound(target.getLocation(), Sound.ENTITY_ZOMBIE_ATTACK_IRON_DOOR, 2, 2);
|
||||
target.getWorld().spawnParticle(Particle.CRIT, target.getLocation().add(0, target.getHeight() / 2, 0), 32, 0, 0, 0, .7);
|
||||
target.getWorld().spawnParticle(Particle.BLOCK_CRACK, target.getLocation().add(0, target.getHeight() / 2, 0), 32, 0, 0, 0, 2,
|
||||
Material.REDSTONE_BLOCK.createBlockData());
|
||||
|
||||
double max = target.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
|
||||
double ratio = (max - target.getHealth()) / max;
|
||||
|
||||
double damage = cast.getModifier("damage") * (1 + cast.getModifier("extra") * ratio / 100);
|
||||
caster.attack(target, damage, DamageType.SKILL, DamageType.PHYSICAL);
|
||||
return cast;
|
||||
}
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.api.event.PlayerAttackEvent;
|
||||
import io.lumine.mythic.lib.damage.DamageType;
|
||||
import io.lumine.mythic.lib.version.VersionMaterial;
|
||||
import io.lumine.mythic.lib.version.VersionSound;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.api.util.math.particle.SmallParticleEffect;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class Empowered_Attack extends Skill {
|
||||
private static final double perb = 5;
|
||||
|
||||
public Empowered_Attack() {
|
||||
super();
|
||||
setMaterial(VersionMaterial.BONE_MEAL.toMaterial());
|
||||
setLore("You charge your weapon with lightning.", "Your next attack deals &f{extra}% &7extra damage", "and spreads to enemies within &f{radius} &7blocks", "for &f{ratio}% &7of the initial damage.", "", "&e{cooldown}s Cooldown", "&9Costs {mana} {mana_name}");
|
||||
|
||||
addModifier("cooldown", new LinearValue(10, -.2, 5, 10));
|
||||
addModifier("mana", new LinearValue(4, 1));
|
||||
addModifier("radius", new LinearValue(4, 0));
|
||||
addModifier("ratio", new LinearValue(30, 10, 30, 100));
|
||||
addModifier("extra", new LinearValue(30, 8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillMetadata whenCast(CasterMetadata caster, SkillInfo skill) {
|
||||
SkillMetadata cast = new SkillMetadata(caster, skill);
|
||||
if (!cast.isSuccessful())
|
||||
return cast;
|
||||
|
||||
caster.getPlayer().playSound(caster.getPlayer().getLocation(), Sound.BLOCK_END_PORTAL_FRAME_FILL, 1, 1);
|
||||
new EmpoweredAttack(caster, cast.getModifier("extra"), cast.getModifier("ratio"), cast.getModifier("radius"));
|
||||
return cast;
|
||||
}
|
||||
|
||||
private void drawVector(Location loc, Vector vec) {
|
||||
|
||||
double steps = vec.length() * perb;
|
||||
Vector v = vec.clone().normalize().multiply((double) 1 / perb);
|
||||
|
||||
for (int j = 0; j < Math.min(steps, 124); j++)
|
||||
loc.getWorld().spawnParticle(Particle.FIREWORKS_SPARK, loc.add(v), 0);
|
||||
}
|
||||
|
||||
public class EmpoweredAttack implements Listener {
|
||||
private final CasterMetadata caster;
|
||||
private final double c, r, rad;
|
||||
|
||||
public EmpoweredAttack(CasterMetadata caster, double extra, double ratio, double radius) {
|
||||
this.caster = caster;
|
||||
this.c = 1 + extra / 100;
|
||||
this.r = ratio / 100;
|
||||
this.rad = radius;
|
||||
|
||||
if (caster.getPlayerData().isOnline())
|
||||
new SmallParticleEffect(caster.getPlayer(), Particle.FIREWORKS_SPARK);
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(MMOCore.plugin, this::close, 80);
|
||||
}
|
||||
|
||||
private void close() {
|
||||
PlayerAttackEvent.getHandlerList().unregister(this);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void a(PlayerAttackEvent event) {
|
||||
if (!caster.getPlayerData().isOnline()) return;
|
||||
if (event.getPlayer().equals(caster.getPlayer()) && event.getAttack().getDamage().hasType(DamageType.WEAPON)) {
|
||||
close();
|
||||
|
||||
Entity target = event.getEntity();
|
||||
|
||||
/*
|
||||
* play lightning effect
|
||||
*/
|
||||
final Location loc = target.getLocation().add(0, target.getHeight() / 2, 0);
|
||||
for (int j = 0; j < 3; j++) {
|
||||
Location clone = loc.clone();
|
||||
double a = random.nextDouble() * Math.PI * 2;
|
||||
loc.add(Math.cos(a), 5, Math.sin(a));
|
||||
drawVector(clone, loc.clone().subtract(clone).toVector());
|
||||
}
|
||||
|
||||
target.getWorld().playSound(target.getLocation(), VersionSound.ENTITY_FIREWORK_ROCKET_BLAST.toSound(), 2, .5f);
|
||||
target.getWorld().spawnParticle(Particle.FIREWORKS_SPARK, target.getLocation().add(0, target.getHeight() / 2, 0), 32, 0, 0, 0, .2);
|
||||
|
||||
double sweep = event.getAttack().getDamage().getDamage() * r;
|
||||
Location src = target.getLocation().add(0, target.getHeight() / 2, 0);
|
||||
|
||||
for (Entity entity : target.getNearbyEntities(rad, rad, rad))
|
||||
if (MMOCoreUtils.canTarget(caster.getPlayerData(), entity)) {
|
||||
drawVector(src, entity.getLocation().add(0, entity.getHeight() / 2, 0).subtract(src).toVector());
|
||||
caster.attack((LivingEntity) entity, sweep, DamageType.PHYSICAL, DamageType.SKILL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply damage afterwards otherwise the damage dealt to nearby
|
||||
* entities scale with the extra ability damage.
|
||||
*/
|
||||
event.getAttack().getDamage().multiply(1 + c, DamageType.WEAPON);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.api.event.PlayerAttackEvent;
|
||||
import io.lumine.mythic.lib.damage.DamageType;
|
||||
import io.lumine.mythic.lib.version.VersionSound;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.api.util.math.particle.SmallParticleEffect;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
public class Evade extends Skill {
|
||||
public Evade() {
|
||||
super();
|
||||
setMaterial(Material.LEATHER_BOOTS);
|
||||
setLore("You become imune to damage for &8{duration} &7seconds.", "Cancels when dealing weapon damage.", "", "&e{cooldown}s Cooldown",
|
||||
"&9Costs {mana} {mana_name}");
|
||||
|
||||
addModifier("cooldown", new LinearValue(20, 0));
|
||||
addModifier("mana", new LinearValue(8, 3));
|
||||
addModifier("duration", new LinearValue(2, .3, 2, 10));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillMetadata whenCast(CasterMetadata caster, SkillInfo skill) {
|
||||
SkillMetadata cast = new SkillMetadata(caster, skill);
|
||||
if (!cast.isSuccessful())
|
||||
return cast;
|
||||
|
||||
caster.getPlayer().getWorld().playSound(caster.getPlayer().getLocation(), VersionSound.ENTITY_ENDERMAN_TELEPORT.toSound(), 1, 2);
|
||||
new SmallParticleEffect(caster.getPlayer(), Particle.CLOUD);
|
||||
new EvadeSkill(caster.getPlayerData(), cast.getModifier("duration"));
|
||||
return cast;
|
||||
}
|
||||
|
||||
private static class EvadeSkill extends BukkitRunnable implements Listener {
|
||||
private final PlayerData data;
|
||||
|
||||
public EvadeSkill(PlayerData data, double duration) {
|
||||
this.data = data;
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
|
||||
runTaskTimer(MMOCore.plugin, 0, 1);
|
||||
Bukkit.getScheduler().runTaskLater(MMOCore.plugin, this::close, (long) (duration * 20));
|
||||
}
|
||||
|
||||
private void close() {
|
||||
cancel();
|
||||
EntityDamageEvent.getHandlerList().unregister(this);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void a(EntityDamageEvent event) {
|
||||
if (!data.isOnline()) return;
|
||||
if (event.getEntity().equals(data.getPlayer()))
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void b(PlayerAttackEvent event) {
|
||||
if (event.getAttack().getDamage().hasType(DamageType.WEAPON) && !event.isCancelled() && PlayerData.get(event.getData().getUniqueId()).equals(data))
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!data.isOnline() || data.getPlayer().isDead())
|
||||
close();
|
||||
else
|
||||
data.getPlayer().getWorld().spawnParticle(Particle.CLOUD, data.getPlayer().getLocation().add(0, 1, 0), 0);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.api.event.PlayerAttackEvent;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.skill.PassiveSkill;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class Fire_Berserker extends PassiveSkill {
|
||||
public Fire_Berserker() {
|
||||
super();
|
||||
setMaterial(Material.FLINT_AND_STEEL);
|
||||
setLore("You deal &c{extra}% &7more damage when on fire.");
|
||||
setPassive();
|
||||
|
||||
addModifier("extra", new LinearValue(10, 5));
|
||||
// addModifier("duration", new LinearValue(10, .1));
|
||||
// addModifier("cooldown", new LinearValue(30, 0));
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void a(PlayerAttackEvent event) {
|
||||
PlayerData data = PlayerData.get(event.getData().getUniqueId());
|
||||
if (event.getPlayer().getFireTicks() > 0) {
|
||||
Optional<SkillInfo> skill = data.getProfess().findSkill(this);
|
||||
skill.ifPresent(skillInfo -> event.getAttack().getDamage().multiply(1 + skillInfo.getModifier("extra", data.getSkillLevel(this)) / 100));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.player.EquipmentSlot;
|
||||
import io.lumine.mythic.lib.api.stat.StatMap;
|
||||
import io.lumine.mythic.lib.damage.DamageType;
|
||||
import io.lumine.mythic.lib.version.VersionMaterial;
|
||||
import io.lumine.mythic.lib.version.VersionSound;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.api.util.math.VectorRotation;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class Fire_Rage extends Skill {
|
||||
public Fire_Rage() {
|
||||
super();
|
||||
setMaterial(VersionMaterial.FIRE_CHARGE.toMaterial());
|
||||
setLore("For {duration} seconds, you slow down and are able", "to cast up to {count} fireballs by left clicking.", "", "Fireballs deal &c{damage} &7damage upon contact", "and ignite your target for &c{ignite} &7seconds.", "&e{cooldown}s Cooldown", "&9Costs {mana} {mana_name}");
|
||||
|
||||
addModifier("duration", new LinearValue(8, 0));
|
||||
addModifier("count", new LinearValue(4, 0));
|
||||
addModifier("mana", new LinearValue(15, 1));
|
||||
addModifier("damage", new LinearValue(5, 3));
|
||||
addModifier("ignite", new LinearValue(2, .1));
|
||||
addModifier("cooldown", new LinearValue(9, -.1, 1, 5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillMetadata whenCast(CasterMetadata caster, SkillInfo skill) {
|
||||
SkillMetadata cast = new SkillMetadata(caster, skill);
|
||||
if (!cast.isSuccessful())
|
||||
return cast;
|
||||
|
||||
new Rage(caster, cast);
|
||||
return cast;
|
||||
}
|
||||
|
||||
public class Rage extends BukkitRunnable implements Listener {
|
||||
private final CasterMetadata caster;
|
||||
private final StatMap.CachedStatMap cachedStats;
|
||||
private final int count, ignite;
|
||||
private final double damage;
|
||||
|
||||
private int c;
|
||||
private double b;
|
||||
private long last = System.currentTimeMillis();
|
||||
|
||||
/*
|
||||
* time the player needs to wait before firing two fireballs.
|
||||
*/
|
||||
private static final long timeOut = 700;
|
||||
|
||||
public Rage(CasterMetadata caster, SkillMetadata cast) {
|
||||
this.caster = caster;
|
||||
this.cachedStats = caster.getPlayerData().getMMOPlayerData().getStatMap().cache(EquipmentSlot.MAIN_HAND);
|
||||
this.ignite = (int) (20 * cast.getModifier("ignite"));
|
||||
this.damage = cast.getModifier("damage");
|
||||
c = count = (int) cast.getModifier("count");
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
|
||||
Bukkit.getScheduler().runTaskLater(MMOCore.plugin, this::close, (long) (cast.getModifier("duration") * 20));
|
||||
runTaskTimer(MMOCore.plugin, 0, 1);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void a(PlayerInteractEvent event) {
|
||||
if (event.getPlayer().equals(caster.getPlayer()) && event.getAction().name().contains("LEFT_CLICK") && (System.currentTimeMillis() - last) > timeOut) {
|
||||
last = System.currentTimeMillis();
|
||||
castEffect();
|
||||
fireball(c < 2);
|
||||
if (c-- < 2)
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
private void castEffect() {
|
||||
VectorRotation rotation = new VectorRotation(caster.getPlayer().getEyeLocation());
|
||||
for (double a = 0; a < Math.PI * 2; a += Math.PI / 13) {
|
||||
Vector vec = rotation.rotate(new Vector(Math.cos(a), Math.sin(a), 0)).add(caster.getPlayer().getEyeLocation().getDirection().multiply(.5)).multiply(.3);
|
||||
caster.getPlayer().getWorld().spawnParticle(Particle.FLAME, caster.getPlayer().getLocation().add(0, 1.3, 0).add(caster.getPlayer().getEyeLocation().getDirection().multiply(.5)), 0, vec.getX(), vec.getY(), vec.getZ(), .3);
|
||||
}
|
||||
}
|
||||
|
||||
private void close() {
|
||||
if (isCancelled())
|
||||
return;
|
||||
|
||||
cancel();
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
|
||||
private void fireball(boolean last) {
|
||||
if (last) {
|
||||
caster.getPlayer().removePotionEffect(PotionEffectType.SLOW);
|
||||
caster.getPlayer().removePotionEffect(PotionEffectType.SLOW);
|
||||
}
|
||||
|
||||
caster.getPlayer().getWorld().playSound(caster.getPlayer().getLocation(), VersionSound.ENTITY_FIREWORK_ROCKET_BLAST.toSound(), 1, last ? 0 : 1);
|
||||
new BukkitRunnable() {
|
||||
int j = 0;
|
||||
final Vector vec = caster.getPlayer().getEyeLocation().getDirection();
|
||||
final Location loc = caster.getPlayer().getLocation().add(0, 1.3, 0);
|
||||
|
||||
public void run() {
|
||||
if (j++ > 40)
|
||||
cancel();
|
||||
|
||||
loc.add(vec);
|
||||
|
||||
if (j % 2 == 0)
|
||||
loc.getWorld().playSound(loc, Sound.BLOCK_FIRE_AMBIENT, 2, 1);
|
||||
loc.getWorld().spawnParticle(Particle.FLAME, loc, 4, .1, .1, .1, 0);
|
||||
loc.getWorld().spawnParticle(Particle.LAVA, loc, 0);
|
||||
|
||||
for (Entity target : MMOCoreUtils.getNearbyChunkEntities(loc))
|
||||
if (MythicLib.plugin.getVersion().getWrapper().isInBoundingBox(target, loc) && MMOCoreUtils.canTarget(caster.getPlayerData(), target)) {
|
||||
loc.getWorld().spawnParticle(Particle.LAVA, loc, 8);
|
||||
loc.getWorld().spawnParticle(Particle.FLAME, loc, 32, 0, 0, 0, .1);
|
||||
loc.getWorld().playSound(loc, Sound.ENTITY_BLAZE_HURT, 2, 1);
|
||||
target.setFireTicks(target.getFireTicks() + ignite);
|
||||
caster.attack((LivingEntity) target, damage, DamageType.SKILL, DamageType.PROJECTILE, DamageType.MAGIC);
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
}.runTaskTimer(MMOCore.plugin, 0, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (caster.getPlayer().isDead() || !caster.getPlayer().isOnline()) {
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
b += Math.PI / 30;
|
||||
for (int j = 0; j < c; j++) {
|
||||
double a = Math.PI * 2 * j / count + b;
|
||||
caster.getPlayer().spawnParticle(Particle.FLAME, caster.getPlayer().getLocation().add(Math.cos(a) * 1.5, 1 + Math.sin(a * 1.5) * .7, Math.sin(a) * 1.5), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.damage.DamageType;
|
||||
import io.lumine.mythic.lib.version.VersionSound;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.api.util.math.particle.ParabolicProjectile;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import net.Indyuce.mmocore.skill.metadata.TargetSkillMetadata;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class Fire_Storm extends Skill {
|
||||
public Fire_Storm() {
|
||||
super();
|
||||
setMaterial(Material.BLAZE_POWDER);
|
||||
setLore("Casts a flurry of 6 fire projectiles onto", "nearby enemies, proritizing the initial",
|
||||
"target. Each projectile deals &c{damage} &7damage", "and ignite the target for &c{ignite} &7seconds.", "",
|
||||
"&e{cooldown}s Cooldown", "&9Costs {mana} {mana_name}");
|
||||
|
||||
addModifier("mana", new LinearValue(15, 2));
|
||||
addModifier("damage", new LinearValue(5, 3));
|
||||
addModifier("ignite", new LinearValue(2, .1));
|
||||
addModifier("cooldown", new LinearValue(5, -.1, 1, 5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillMetadata whenCast(CasterMetadata caster, SkillInfo skill) {
|
||||
TargetSkillMetadata cast = new TargetSkillMetadata(caster, skill, 20);
|
||||
if (!cast.isSuccessful()) return cast;
|
||||
|
||||
LivingEntity target = cast.getTarget();
|
||||
|
||||
final double damage = cast.getModifier("damage");
|
||||
final int ignite = (int) (20 * cast.getModifier("ignite"));
|
||||
|
||||
caster.getPlayer().getWorld().playSound(caster.getPlayer().getLocation(), VersionSound.ENTITY_FIREWORK_ROCKET_BLAST.toSound(), 1, 1);
|
||||
new BukkitRunnable() {
|
||||
int j = 0;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (j++ > 5 || caster.getPlayer().isDead() || !caster.getPlayer().isOnline() || target.isDead() || !caster.getPlayer().getWorld()
|
||||
.equals(target.getWorld())) {
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO dynamic target location
|
||||
|
||||
caster.getPlayer().getWorld().playSound(caster.getPlayer().getLocation(), Sound.BLOCK_FIRE_AMBIENT, 1, 1);
|
||||
new ParabolicProjectile(caster.getPlayer().getLocation().add(0, 1, 0), target.getLocation().add(0, target.getHeight() / 2, 0),
|
||||
randomVector(caster.getPlayer()), () -> {
|
||||
target.getWorld().playSound(target.getLocation(), VersionSound.ENTITY_FIREWORK_ROCKET_TWINKLE.toSound(), 1, 2);
|
||||
target.getWorld().spawnParticle(Particle.SMOKE_NORMAL, target.getLocation().add(0, target.getHeight() / 2, 0), 8, 0, 0, 0, .15);
|
||||
caster.attack(target, damage, DamageType.SKILL, DamageType.PROJECTILE, DamageType.MAGIC);
|
||||
target.setFireTicks(ignite);
|
||||
|
||||
}, 2, Particle.FLAME);
|
||||
}
|
||||
}.runTaskTimer(MMOCore.plugin, 0, 4);
|
||||
return cast;
|
||||
}
|
||||
|
||||
private Vector randomVector(Player player) {
|
||||
double a = Math.toRadians(player.getEyeLocation().getYaw() + 90);
|
||||
a += (random.nextBoolean() ? 1 : -1) * (random.nextDouble() * 2 + 1) * Math.PI / 6;
|
||||
return new Vector(Math.cos(a), .8, Math.sin(a)).normalize().multiply(.4);
|
||||
}
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.MMORayTraceResult;
|
||||
import io.lumine.mythic.lib.damage.DamageType;
|
||||
import io.lumine.mythic.lib.version.VersionMaterial;
|
||||
import io.lumine.mythic.lib.version.VersionSound;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class Fireball extends Skill {
|
||||
public Fireball() {
|
||||
super();
|
||||
setMaterial(VersionMaterial.FIRE_CHARGE.toMaterial());
|
||||
setLore("Casts a deadly fireball onto your", "target, dealing &c{damage} &7damage upon contact", "and igniting it for &c{ignite} &7seconds.", "", "Shatters into 3 blazing hot shards which stick", "to walls and explode 3 seconds later, dealing", "&c{ratio}% &7of the initial spell damage.", "", "&e{cooldown}s Cooldown", "&9Costs {mana} {mana_name}");
|
||||
|
||||
addModifier("mana", new LinearValue(15, 1));
|
||||
addModifier("damage", new LinearValue(5, 3));
|
||||
addModifier("ignite", new LinearValue(2, .1));
|
||||
addModifier("ratio", new LinearValue(50, 3));
|
||||
addModifier("cooldown", new LinearValue(9, -.1, 1, 5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillMetadata whenCast(CasterMetadata caster, SkillInfo skill) {
|
||||
SkillMetadata cast = new SkillMetadata(caster, skill);
|
||||
if (!cast.isSuccessful())
|
||||
return cast;
|
||||
|
||||
caster.getPlayer().getWorld().playSound(caster.getPlayer().getLocation(), VersionSound.ENTITY_FIREWORK_ROCKET_BLAST.toSound(), 1, 1);
|
||||
new BukkitRunnable() {
|
||||
int j = 0;
|
||||
final Vector vec = caster.getPlayer().getEyeLocation().getDirection();
|
||||
final Location loc = caster.getPlayer().getLocation().add(0, 1.3, 0);
|
||||
|
||||
public void run() {
|
||||
if (j++ > 40) {
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
loc.add(vec);
|
||||
|
||||
if (j % 3 == 0)
|
||||
loc.getWorld().playSound(loc, Sound.BLOCK_FIRE_AMBIENT, 2, 1);
|
||||
loc.getWorld().spawnParticle(Particle.FLAME, loc, 4, .02, .02, .02, 0);
|
||||
loc.getWorld().spawnParticle(Particle.LAVA, loc, 0);
|
||||
|
||||
for (Entity target : MMOCoreUtils.getNearbyChunkEntities(loc))
|
||||
if (MythicLib.plugin.getVersion().getWrapper().isInBoundingBox(target, loc) && MMOCoreUtils.canTarget(caster.getPlayerData(), target)) {
|
||||
loc.getWorld().spawnParticle(Particle.LAVA, loc, 8);
|
||||
loc.getWorld().spawnParticle(Particle.FLAME, loc, 32, 0, 0, 0, .1);
|
||||
loc.getWorld().playSound(loc, Sound.ENTITY_BLAZE_HURT, 2, 1);
|
||||
target.setFireTicks((int) (target.getFireTicks() + cast.getModifier("ignite") * 20));
|
||||
double damage = cast.getModifier("damage");
|
||||
caster.attack((LivingEntity) target, damage, DamageType.SKILL, DamageType.PROJECTILE, DamageType.MAGIC);
|
||||
|
||||
new BukkitRunnable() {
|
||||
int i = 0;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (i++ > 2) {
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
double range = 2.5 * (1 + random.nextDouble());
|
||||
Vector dir = randomDirection();
|
||||
loc.getWorld().playSound(loc, Sound.ENTITY_BLAZE_HURT, 2, 1.5f);
|
||||
|
||||
MMORayTraceResult result = MythicLib.plugin.getVersion().getWrapper().rayTrace(loc, dir, range, entity -> MMOCoreUtils.canTarget(caster.getPlayerData(), entity));
|
||||
if (result.hasHit())
|
||||
caster.attack(result.getHit(), damage, DamageType.SKILL, DamageType.PROJECTILE, DamageType.MAGIC);
|
||||
result.draw(loc.clone(), dir, 8, tick -> tick.getWorld().spawnParticle(Particle.FLAME, tick, 0));
|
||||
|
||||
}
|
||||
}.runTaskTimer(MMOCore.plugin, 3, 3);
|
||||
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}.runTaskTimer(MMOCore.plugin, 0, 1);
|
||||
return cast;
|
||||
}
|
||||
|
||||
private Vector randomDirection() {
|
||||
double x = random.nextDouble() - .5, y = (random.nextDouble() - .2) / 2, z = random.nextDouble() - .5;
|
||||
Vector dir = new Vector(x, y, z);
|
||||
return dir.lengthSquared() == 0 ? new Vector(1, 0, 0) : dir.normalize();
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.damage.DamageType;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.api.util.math.particle.SmallParticleEffect;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import net.Indyuce.mmocore.skill.metadata.TargetSkillMetadata;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
|
||||
public class Furtive_Strike extends Skill {
|
||||
public Furtive_Strike() {
|
||||
super();
|
||||
setMaterial(Material.COAL);
|
||||
setLore("Deals &c{damage} &7damage, increased by &c{extra}% &7if", "there are not any enemies within &c{radius} &7blocks.", "", "&e{cooldown}s Cooldown", "&9Costs {mana} {mana_name}");
|
||||
|
||||
addModifier("cooldown", new LinearValue(20, -.1, 5, 20));
|
||||
addModifier("mana", new LinearValue(8, 3));
|
||||
addModifier("damage", new LinearValue(5, 1.5));
|
||||
addModifier("extra", new LinearValue(50, 20));
|
||||
addModifier("radius", new LinearValue(7, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillMetadata whenCast(CasterMetadata caster, SkillInfo skill) {
|
||||
TargetSkillMetadata cast = new TargetSkillMetadata(caster, skill, 3);
|
||||
if (!cast.isSuccessful())
|
||||
return cast;
|
||||
|
||||
LivingEntity target = cast.getTarget();
|
||||
target.getWorld().playSound(target.getLocation(), Sound.ENTITY_ZOMBIE_ATTACK_IRON_DOOR, 2, 1.5f);
|
||||
target.getWorld().spawnParticle(Particle.CRIT, target.getLocation().add(0, target.getHeight() / 2, 0), 32, 0, 0, 0, .5);
|
||||
target.getWorld().spawnParticle(Particle.SMOKE_NORMAL, target.getLocation().add(0, target.getHeight() / 2, 0), 64, 0, 0, 0, .08);
|
||||
|
||||
double damage = cast.getModifier("damage");
|
||||
|
||||
double radius = cast.getModifier("radius");
|
||||
if (target.getNearbyEntities(radius, radius, radius).stream().allMatch(entity -> entity.equals(caster.getPlayer()))) {
|
||||
new SmallParticleEffect(target, Particle.SPELL_WITCH);
|
||||
damage *= 1 + cast.getModifier("extra") / 100;
|
||||
}
|
||||
|
||||
caster.attack(target, damage, DamageType.SKILL, DamageType.PHYSICAL);
|
||||
return cast;
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.comp.target.InteractionType;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.api.util.math.particle.SmallParticleEffect;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import net.Indyuce.mmocore.skill.metadata.TargetSkillMetadata;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
|
||||
public class Greater_Healings extends Skill {
|
||||
public Greater_Healings() {
|
||||
super();
|
||||
setMaterial(Material.GOLDEN_APPLE);
|
||||
setLore("Instantly grants &a{heal} &7HP to the", "target. Sneak to cast it on yourself.", "", "&e{cooldown}s Cooldown", "&9Costs {mana} {mana_name}");
|
||||
|
||||
addModifier("mana", new LinearValue(4, 2));
|
||||
addModifier("heal", new LinearValue(10, 4));
|
||||
addModifier("cooldown", new LinearValue(9, -.1, 1, 5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillMetadata whenCast(CasterMetadata caster, SkillInfo skill) {
|
||||
SkillMetadata cast = caster.getPlayer().isSneaking() ? new SkillMetadata(caster, skill) : new TargetSkillMetadata(caster, skill, 50, InteractionType.SUPPORT_SKILL);
|
||||
if (!cast.isSuccessful())
|
||||
return cast;
|
||||
|
||||
LivingEntity target = cast instanceof TargetSkillMetadata ? ((TargetSkillMetadata) cast).getTarget() : caster.getPlayer();
|
||||
|
||||
double max = target.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
|
||||
target.setHealth(Math.min(max, target.getHealth() + cast.getModifier("heal")));
|
||||
|
||||
new SmallParticleEffect(target, Particle.HEART, 1);
|
||||
target.getWorld().playSound(target.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 2, 2);
|
||||
return cast;
|
||||
}
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.comp.target.InteractionType;
|
||||
import io.lumine.mythic.lib.version.VersionMaterial;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import net.Indyuce.mmocore.skill.metadata.TargetSkillMetadata;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
public class Human_Shield extends Skill {
|
||||
public Human_Shield() {
|
||||
super();
|
||||
setMaterial(VersionMaterial.TOTEM_OF_UNDYING.toMaterial());
|
||||
setLore("Casts a protection charm onto target ally,", "reducing damage taken by &a{reduction}%&7.", "&a{redirect}% &7of this damage is redirected to you.", "Charm is cancelled when reaching &c{low}%&7 health.", "Lasts &a{duration} &7seconds.", "", "&e{cooldown}s Cooldown", "&9Costs {mana} {mana_name}");
|
||||
|
||||
addModifier("cooldown", new LinearValue(18, -.3, 14, 18));
|
||||
addModifier("mana", new LinearValue(15, 1.5));
|
||||
addModifier("reduction", new LinearValue(30, 3, 30, 70));
|
||||
addModifier("redirect", new LinearValue(30, -2, 20, 30));
|
||||
addModifier("duration", new LinearValue(7, 0));
|
||||
addModifier("low", new LinearValue(10, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillMetadata whenCast(CasterMetadata caster, SkillInfo skill) {
|
||||
TargetSkillMetadata cast = new TargetSkillMetadata(caster, skill, 7, InteractionType.SUPPORT_SKILL);
|
||||
if (!cast.isSuccessful())
|
||||
return cast;
|
||||
|
||||
if (!(cast.getTarget() instanceof Player)) {
|
||||
cast.abort();
|
||||
return cast;
|
||||
}
|
||||
|
||||
caster.getPlayer().getWorld().playSound(caster.getPlayer().getLocation(), Sound.ENTITY_BLAZE_AMBIENT, 1, 1);
|
||||
new HumanShield(caster.getPlayerData(), (Player) cast.getTarget(), cast.getModifier("reduction"), cast.getModifier("redirect"), cast.getModifier("duration"), cast.getModifier("low"));
|
||||
return cast;
|
||||
}
|
||||
|
||||
public static class HumanShield extends BukkitRunnable implements Listener {
|
||||
private final PlayerData data;
|
||||
private final Player target;
|
||||
private final double r, rd, d, l;
|
||||
|
||||
private int j;
|
||||
|
||||
public HumanShield(PlayerData data, Player target, double reduction, double redirect, double duration, double low) {
|
||||
this.target = target;
|
||||
this.data = data;
|
||||
|
||||
r = 1 - Math.min(1, reduction / 100);
|
||||
rd = redirect / 100;
|
||||
d = duration * 20;
|
||||
l = low / 100;
|
||||
|
||||
runTaskTimer(MMOCore.plugin, 0, 1);
|
||||
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void a(EntityDamageEvent event) {
|
||||
if (event.getEntity().equals(target)) {
|
||||
|
||||
double damage = event.getDamage() * r;
|
||||
event.setDamage(damage);
|
||||
|
||||
double health = data.getPlayer().getHealth() - damage * rd;
|
||||
if (health > data.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue() * l)
|
||||
data.getPlayer().setHealth(health);
|
||||
else {
|
||||
data.getPlayer().setHealth(1);
|
||||
close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!data.isOnline() || data.getPlayer().isDead() || !target.isOnline() || target.isDead() || j++ >= d) {
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
double a = (double) j / 5;
|
||||
target.getWorld().spawnParticle(Particle.VILLAGER_HAPPY, target.getLocation().add(Math.cos(a), 1 + Math.sin(a / 3) / 1.3, Math.sin(a)), 0);
|
||||
}
|
||||
|
||||
private void close() {
|
||||
cancel();
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.damage.DamageType;
|
||||
import io.lumine.mythic.lib.version.VersionMaterial;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.api.util.math.Line3D;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.metadata.LocationSkillMetadata;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class Ice_Spikes extends Skill {
|
||||
private static final double radius = 3;
|
||||
|
||||
public Ice_Spikes() {
|
||||
super();
|
||||
setMaterial(VersionMaterial.SNOWBALL.toMaterial());
|
||||
setLore("Ice spikes summon from the ground", "and shatter, each dealing &9{damage} &7damage", "to hit enemies and slowing them down", "for &9{slow} &7seconds.", "", "&e{cooldown}s Cooldown", "&9Costs {mana} {mana_name}");
|
||||
|
||||
addModifier("cooldown", new LinearValue(6, -.1, 2, 6));
|
||||
addModifier("mana", new LinearValue(20, 2));
|
||||
addModifier("damage", new LinearValue(3, 1));
|
||||
addModifier("slow", new LinearValue(4, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillMetadata whenCast(CasterMetadata caster, SkillInfo skill) {
|
||||
LocationSkillMetadata cast = new LocationSkillMetadata(caster, skill, 20);
|
||||
if (!cast.isSuccessful())
|
||||
return cast;
|
||||
|
||||
Location loc = cast.getHit();
|
||||
double damage = cast.getModifier("damage");
|
||||
int slow = (int) (20 * cast.getModifier("slow"));
|
||||
|
||||
new BukkitRunnable() {
|
||||
int j = 0;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
if (j++ > 8) {
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
Location loc1 = loc.clone().add(offset() * radius, 0, offset() * radius).add(0, 2, 0);
|
||||
loc.getWorld().spawnParticle(Particle.FIREWORKS_SPARK, loc1, 32, 0, 2, 0, 0);
|
||||
loc.getWorld().spawnParticle(Particle.SNOWBALL, loc1, 32, 0, 2, 0, 0);
|
||||
loc.getWorld().playSound(loc1, Sound.BLOCK_GLASS_BREAK, 2, 0);
|
||||
|
||||
Line3D line = new Line3D(loc.toVector(), loc.toVector().add(new Vector(0, 1, 0)));
|
||||
for (Entity entity : MMOCoreUtils.getNearbyChunkEntities(loc1))
|
||||
if (line.distanceSquared(entity.getLocation().toVector()) < radius && Math.abs(entity.getLocation().getY() - loc1.getY()) < 10 && MMOCoreUtils.canTarget(caster.getPlayerData(), entity)) {
|
||||
caster.attack((LivingEntity) entity, damage, DamageType.SKILL, DamageType.MAGIC);
|
||||
((LivingEntity) entity).addPotionEffect(new PotionEffect(PotionEffectType.SLOW, slow, 0));
|
||||
}
|
||||
}
|
||||
}.runTaskTimer(MMOCore.plugin, 0, 5);
|
||||
return cast;
|
||||
}
|
||||
|
||||
private double offset() {
|
||||
return random.nextDouble() * (random.nextBoolean() ? 1 : -1);
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.comp.target.InteractionType;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.api.util.math.particle.SmallParticleEffect;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import net.Indyuce.mmocore.skill.metadata.TargetSkillMetadata;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
|
||||
public class Minor_Healings extends Skill {
|
||||
public Minor_Healings() {
|
||||
super();
|
||||
setMaterial(Material.GOLDEN_APPLE);
|
||||
setLore("Instantly grants &a{heal} &7HP to the", "target. Sneak to cast it on yourself.", "", "&e{cooldown}s Cooldown", "&9Costs {mana} {mana_name}");
|
||||
|
||||
addModifier("mana", new LinearValue(4, 2));
|
||||
addModifier("heal", new LinearValue(4, 2));
|
||||
addModifier("cooldown", new LinearValue(9, -.1, 1, 5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillMetadata whenCast(CasterMetadata caster, SkillInfo skill) {
|
||||
SkillMetadata cast = caster.getPlayer().isSneaking() ? new SkillMetadata(caster, skill) : new TargetSkillMetadata(caster, skill, 50, InteractionType.SUPPORT_SKILL);
|
||||
if (!cast.isSuccessful())
|
||||
return cast;
|
||||
|
||||
LivingEntity target = cast instanceof TargetSkillMetadata ? ((TargetSkillMetadata) cast).getTarget() : caster.getPlayer();
|
||||
|
||||
double max = target.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
|
||||
target.setHealth(Math.min(max, target.getHealth() + cast.getModifier("heal")));
|
||||
|
||||
new SmallParticleEffect(target, Particle.HEART, 1);
|
||||
target.getWorld().playSound(target.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 2, 2);
|
||||
return cast;
|
||||
}
|
||||
}
|
@ -1,40 +1,41 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import net.Indyuce.mmocore.skill.PassiveSkill;
|
||||
import org.bukkit.Bukkit;
|
||||
import io.lumine.mythic.lib.skill.SkillMetadata;
|
||||
import io.lumine.mythic.lib.skill.handler.SkillHandler;
|
||||
import io.lumine.mythic.lib.skill.result.def.SimpleSkillResult;
|
||||
import io.lumine.mythic.lib.skill.trigger.PassiveSkill;
|
||||
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import io.lumine.mythic.lib.version.VersionMaterial;
|
||||
public class Neptune_Gift extends SkillHandler<SimpleSkillResult> implements Listener {
|
||||
public Neptune_Gift() {
|
||||
super(false);
|
||||
|
||||
public class Neptune_Gift extends PassiveSkill {
|
||||
public Neptune_Gift() {
|
||||
super("NEPTUNE_GIFT");
|
||||
setName("Neptune's Gift");
|
||||
registerModifiers("extra");
|
||||
}
|
||||
|
||||
setMaterial(VersionMaterial.LILY_PAD.toMaterial());
|
||||
setLore("Resource regeneration is increased by &8{extra}% &7when standing in water.");
|
||||
setPassive();
|
||||
@Override
|
||||
public SimpleSkillResult getResult(SkillMetadata meta) {
|
||||
throw new RuntimeException("Not supported");
|
||||
}
|
||||
|
||||
addModifier("extra", new LinearValue(30, 5));
|
||||
@Override
|
||||
public void whenCast(SimpleSkillResult result, SkillMetadata skillMeta) {
|
||||
throw new RuntimeException("Not supported");
|
||||
}
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
|
||||
}
|
||||
@EventHandler
|
||||
public void a(PlayerResourceUpdateEvent event) {
|
||||
PlayerData data = event.getData();
|
||||
if (event.getPlayer().getLocation().getBlock().getType() == Material.WATER) {
|
||||
PassiveSkill skill = event.getData().getMMOPlayerData().getPassiveSkill(this);
|
||||
if (skill == null)
|
||||
return;
|
||||
|
||||
@EventHandler
|
||||
public void a(PlayerResourceUpdateEvent event) {
|
||||
PlayerData data = event.getData();
|
||||
if (event.getPlayer().getLocation().getBlock().getType() == Material.WATER) {
|
||||
Optional<SkillInfo> skill = data.getProfess().findSkill(this);
|
||||
skill.ifPresent(skillInfo -> event.setAmount(event.getAmount() * (1 + skillInfo.getModifier("extra", data.getSkillLevel(this)) / 100)));
|
||||
}
|
||||
}
|
||||
event.setAmount(event.getAmount() * (1 + skill.getTriggeredSkill().getModifier("extra") / 100));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,134 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.api.event.PlayerAttackEvent;
|
||||
import io.lumine.mythic.lib.damage.DamageType;
|
||||
import io.lumine.mythic.lib.version.VersionMaterial;
|
||||
import io.lumine.mythic.lib.version.VersionSound;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.api.util.math.particle.ParabolicProjectile;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.PassiveSkill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
;
|
||||
|
||||
public class Power_Mark extends PassiveSkill {
|
||||
public Power_Mark() {
|
||||
super();
|
||||
setMaterial(VersionMaterial.WITHER_SKELETON_SKULL.toMaterial());
|
||||
setLore("Attacking an enemy applies a deadly", "magical mark which spreads accross the", "ground. This mark accumulates &6{ratio}%", "of the damage dealt to the initial", "target over &6{duration} &7seconds.", "", "After this duration, the mark bursts, dealing", "accumulated damage to nearby enemies and", "stunning them for &6{stun}+ &7seconds.", "", "The more damage, the longer the stun.", "", "&e{cooldown}s Cooldown");
|
||||
setPassive();
|
||||
|
||||
addModifier("stun", new LinearValue(.4, .03));
|
||||
addModifier("ratio", new LinearValue(10, 5));
|
||||
addModifier("duration", new LinearValue(10, .1));
|
||||
addModifier("cooldown", new LinearValue(30, 0));
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void a(PlayerAttackEvent event) {
|
||||
PlayerData data = PlayerData.get(event.getData().getUniqueId());
|
||||
if (!event.getAttack().getDamage().hasType(DamageType.WEAPON) || !data.getProfess().hasSkill(this))
|
||||
return;
|
||||
|
||||
SkillMetadata cast = data.cast(this);
|
||||
if (!cast.isSuccessful())
|
||||
return;
|
||||
|
||||
new PowerMark(new CasterMetadata(data), cast, event.getEntity().getLocation());
|
||||
}
|
||||
|
||||
public class PowerMark extends BukkitRunnable implements Listener {
|
||||
private final CasterMetadata caster;
|
||||
private final Location loc;
|
||||
|
||||
private final double duration;
|
||||
private final double ratio;
|
||||
private double stun;
|
||||
|
||||
private double accumulate;
|
||||
private int j;
|
||||
|
||||
public PowerMark(CasterMetadata caster, SkillMetadata cast, Location loc) {
|
||||
this.caster = caster;
|
||||
this.loc = loc;
|
||||
|
||||
loc.getWorld().playSound(loc, Sound.BLOCK_END_PORTAL_FRAME_FILL, 2, 1);
|
||||
|
||||
duration = cast.getModifier("duration");
|
||||
ratio = cast.getModifier("ratio") / 100;
|
||||
stun = cast.getModifier("stun");
|
||||
|
||||
runTaskTimer(MMOCore.plugin, 0, 1);
|
||||
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
|
||||
}
|
||||
|
||||
private void unregister() {
|
||||
PlayerAttackEvent.getHandlerList().unregister(this);
|
||||
cancel();
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void stackDamage(PlayerAttackEvent event) {
|
||||
if (!event.isCancelled() && j < 20 * (duration - 2) && radiusCheck(event.getEntity().getLocation()) && event.getPlayer().equals(caster.getPlayer())) {
|
||||
accumulate += event.getAttack().getDamage().getDamage() * ratio;
|
||||
new ParabolicProjectile(event.getEntity().getLocation().add(0, event.getEntity().getHeight() / 2, 0), loc, () -> loc.getWorld().playSound(loc, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1), Color.PURPLE);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean radiusCheck(Location loc) {
|
||||
return loc.getWorld().equals(this.loc.getWorld()) && loc.distanceSquared(this.loc) < 16;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (j++ > duration * 20) {
|
||||
unregister();
|
||||
|
||||
for (double a = 0; a < Math.PI * 2; a += Math.PI * 2 / 17)
|
||||
new ParabolicProjectile(loc, loc.clone().add(6 * Math.cos(a), 0, 6 * Math.sin(a)), Particle.SPELL_WITCH);
|
||||
|
||||
loc.getWorld().playSound(loc, Sound.ENTITY_GENERIC_EXPLODE, 2, 0);
|
||||
loc.getWorld().spawnParticle(Particle.EXPLOSION_LARGE, loc.clone().add(0, 1, 0), 16, 2, 2, 2, 0);
|
||||
loc.getWorld().spawnParticle(Particle.EXPLOSION_NORMAL, loc.clone().add(0, 1, 0), 24, 0, 0, 0, .3f);
|
||||
|
||||
stun += Math.log(Math.max(1, accumulate - 10)) / 8;
|
||||
|
||||
for (Entity entity : MMOCoreUtils.getNearbyChunkEntities(loc))
|
||||
if (entity.getLocation().distanceSquared(loc) < 25 && MMOCoreUtils.canTarget(caster.getPlayerData(), entity)) {
|
||||
((LivingEntity) entity).addPotionEffect(new PotionEffect(PotionEffectType.SLOW, (int) (stun * 20), 10, false, false));
|
||||
caster.attack((LivingEntity) entity, accumulate, DamageType.SKILL, DamageType.MAGIC);
|
||||
entity.setVelocity(format(entity.getLocation().subtract(loc).toVector().setY(0)).setY(.3));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (j % 2 == 0 && j > 20 * (duration - 2))
|
||||
loc.getWorld().playSound(loc, VersionSound.BLOCK_NOTE_BLOCK_PLING.toSound(), 1, (float) (1 + (j - 20 * (duration - 2)) / 40));
|
||||
|
||||
double a = (double) j / 16;
|
||||
double r = Math.sqrt(Math.min(duration * 2 - (double) j / 10, 4)) * 2;
|
||||
for (double k = 0; k < Math.PI * 2; k += Math.PI * 2 / 5)
|
||||
loc.getWorld().spawnParticle(Particle.SPELL_WITCH, loc.clone().add(r * Math.cos(k + a), 0, r * Math.sin(k + a)), 0);
|
||||
}
|
||||
}
|
||||
|
||||
private Vector format(Vector vec) {
|
||||
return vec.length() < .01 ? new Vector(0, 0, 0) : vec.normalize();
|
||||
}
|
||||
}
|
@ -1,48 +1,50 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.api.event.PlayerAttackEvent;
|
||||
import io.lumine.mythic.lib.api.player.MMOPlayerData;
|
||||
import io.lumine.mythic.lib.damage.DamageType;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import io.lumine.mythic.lib.skill.SkillMetadata;
|
||||
import io.lumine.mythic.lib.skill.handler.SkillHandler;
|
||||
import io.lumine.mythic.lib.skill.result.def.SimpleSkillResult;
|
||||
import io.lumine.mythic.lib.skill.trigger.PassiveSkill;
|
||||
import io.lumine.mythic.lib.skill.trigger.TriggerMetadata;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.skill.PassiveSkill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class Sneaky_Picky extends PassiveSkill {
|
||||
public class Sneaky_Picky extends SkillHandler<SimpleSkillResult> implements Listener {
|
||||
public Sneaky_Picky() {
|
||||
super();
|
||||
setMaterial(Material.DIAMOND_SWORD);
|
||||
setLore("Your attack is empowered by &f{extra}% &7when", "delivering the first blow during a fight.", "", "&9Costs {mana} {mana_name}");
|
||||
setPassive();
|
||||
super(false);
|
||||
|
||||
addModifier("cooldown", new LinearValue(0, 0));
|
||||
addModifier("mana", new LinearValue(8, 1));
|
||||
addModifier("extra", new LinearValue(50, 20));
|
||||
registerModifiers("extra");
|
||||
}
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
|
||||
@Override
|
||||
public SimpleSkillResult getResult(SkillMetadata meta) {
|
||||
return new SimpleSkillResult(meta.hasAttackBound() && meta.hasTargetEntity() && meta.getTargetEntityOrNull() instanceof LivingEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void whenCast(SimpleSkillResult result, SkillMetadata skillMeta) {
|
||||
LivingEntity target = (LivingEntity) skillMeta.getTargetEntity();
|
||||
skillMeta.getAttack().getDamage().multiply(1 + skillMeta.getModifier("extra") / 100, DamageType.WEAPON);
|
||||
target.getWorld().spawnParticle(Particle.SMOKE_NORMAL, target.getLocation().add(0, target.getHeight() / 2, 0), 64, 0, 0, 0, .05);
|
||||
target.getWorld().playSound(target.getLocation(), Sound.ENTITY_ZOMBIE_ATTACK_IRON_DOOR, 1, 2);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void a(PlayerAttackEvent event) {
|
||||
PlayerData data = PlayerData.get(event.getData().getUniqueId());
|
||||
if (!event.getAttack().getDamage().hasType(DamageType.WEAPON) || data.isInCombat() || !data.getProfess().hasSkill(this))
|
||||
MMOPlayerData data = event.getData();
|
||||
if (!event.getAttack().getDamage().hasType(DamageType.WEAPON) || PlayerData.get(data.getUniqueId()).isInCombat())
|
||||
return;
|
||||
|
||||
SkillMetadata cast = data.cast(this);
|
||||
if (!cast.isSuccessful())
|
||||
PassiveSkill skill = data.getPassiveSkill(this);
|
||||
if (skill == null)
|
||||
return;
|
||||
|
||||
data.cast(cast.getInfo());
|
||||
|
||||
event.getAttack().getDamage().multiply(1 + cast.getModifier("extra") / 100, DamageType.WEAPON);
|
||||
LivingEntity target = event.getEntity();
|
||||
target.getWorld().spawnParticle(Particle.SMOKE_NORMAL, target.getLocation().add(0, target.getHeight() / 2, 0), 64, 0, 0, 0, .05);
|
||||
target.getWorld().playSound(target.getLocation(), Sound.ENTITY_ZOMBIE_ATTACK_IRON_DOOR, 1, 2);
|
||||
skill.getTriggeredSkill().cast(new TriggerMetadata(event.getAttack(), event.getEntity()));
|
||||
}
|
||||
}
|
||||
|
@ -1,98 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.version.VersionMaterial;
|
||||
import io.lumine.mythic.lib.version.VersionSound;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.api.util.math.particle.ParabolicProjectile;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import net.Indyuce.mmocore.skill.metadata.TargetSkillMetadata;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
public class Telekinesy extends Skill {
|
||||
public Telekinesy() {
|
||||
super();
|
||||
setMaterial(VersionMaterial.MAGENTA_DYE.toMaterial());
|
||||
setLore("You take the control over your target", "for &9{duration} &7seconds. Left click to throw him.", "Knockback force: &f{knockback}%", "", "&e{cooldown}s Cooldown", "&9Costs {mana} {mana_name}");
|
||||
|
||||
addModifier("cooldown", new LinearValue(20, -.3, 10, 20));
|
||||
addModifier("mana", new LinearValue(20, 2));
|
||||
addModifier("knockback", new LinearValue(50, 10));
|
||||
addModifier("duration", new LinearValue(3, .1, 3, 6));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillMetadata whenCast(CasterMetadata caster, SkillInfo skill) {
|
||||
TargetSkillMetadata cast = new TargetSkillMetadata(caster, skill, 7);
|
||||
if (!cast.isSuccessful())
|
||||
return cast;
|
||||
|
||||
caster.getPlayer().getWorld().playSound(caster.getPlayer().getLocation(), Sound.BLOCK_END_PORTAL_FRAME_FILL, 1, 1);
|
||||
new TelekinesyRunnable(caster.getPlayerData(), cast.getTarget(), cast.getModifier("duration"), cast.getModifier("knockback") / 100);
|
||||
return cast;
|
||||
}
|
||||
|
||||
public static class TelekinesyRunnable extends BukkitRunnable implements Listener {
|
||||
private final Entity entity;
|
||||
private final PlayerData data;
|
||||
|
||||
private final long duration;
|
||||
private final double d, f;
|
||||
|
||||
private int j;
|
||||
|
||||
public TelekinesyRunnable(PlayerData data, Entity entity, double duration, double force) {
|
||||
this.entity = entity;
|
||||
this.data = data;
|
||||
|
||||
d = data.getPlayer().getLocation().distance(entity.getLocation());
|
||||
f = force;
|
||||
this.duration = (long) (20 * duration);
|
||||
|
||||
runTaskTimer(MMOCore.plugin, 0, 1);
|
||||
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void a(PlayerInteractEvent event) {
|
||||
if (event.getPlayer().equals(data.getPlayer()) && event.getAction().name().contains("LEFT_CLICK")) {
|
||||
entity.setVelocity(data.getPlayer().getEyeLocation().getDirection().multiply(1.5 * f));
|
||||
entity.getWorld().playSound(entity.getLocation(), VersionSound.ENTITY_FIREWORK_ROCKET_BLAST.toSound(), 2, 1);
|
||||
entity.getWorld().spawnParticle(Particle.SPELL_WITCH, entity.getLocation().add(0, entity.getHeight() / 2, 0), 16);
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!data.isOnline() || entity.isDead() || j++ >= duration) {
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (j % 8 == 0)
|
||||
new ParabolicProjectile(data.getPlayer().getEyeLocation(), entity.getLocation().add(0, entity.getHeight() / 2, 0), Particle.SPELL_WITCH);
|
||||
|
||||
Location loc = data.getPlayer().getEyeLocation().add(data.getPlayer().getEyeLocation().getDirection().multiply(d));
|
||||
entity.setVelocity(loc.subtract(entity.getLocation().add(0, entity.getHeight() / 2, 0)).toVector().multiply(2));
|
||||
entity.setFallDistance(0);
|
||||
}
|
||||
|
||||
private void close() {
|
||||
cancel();
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.version.VersionSound;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.api.util.math.particle.ParabolicProjectile;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
public class Warp extends Skill {
|
||||
public Warp() {
|
||||
super();
|
||||
setMaterial(Material.ENDER_PEARL);
|
||||
setLore("Teleports you to target location.", "Max. Range: &5{range}", "", "&e{cooldown}s Cooldown", "&9Costs {mana} {mana_name}");
|
||||
|
||||
addModifier("cooldown", new LinearValue(15, -.3, 2, 15));
|
||||
addModifier("mana", new LinearValue(8, 3));
|
||||
addModifier("range", new LinearValue(16, 1, 0, 100));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillMetadata whenCast(CasterMetadata caster, SkillInfo skill) {
|
||||
WarpSkillMetadata cast = new WarpSkillMetadata(caster, skill);
|
||||
if (!cast.isSuccessful())
|
||||
return cast;
|
||||
|
||||
caster.getPlayer().getWorld().playSound(caster.getPlayer().getLocation(), Sound.BLOCK_END_PORTAL_FRAME_FILL, 1, 2);
|
||||
|
||||
Location loc = cast.block.getLocation().add(0, 1, 0);
|
||||
loc.setYaw(caster.getPlayer().getLocation().getYaw());
|
||||
loc.setPitch(caster.getPlayer().getLocation().getPitch());
|
||||
|
||||
new ParabolicProjectile(caster.getPlayer().getLocation().add(0, 1, 0), loc.clone().add(0, 1, 0), () -> {
|
||||
if (caster.getPlayer().isOnline() && !caster.getPlayer().isDead()) {
|
||||
caster.getPlayer().teleport(loc);
|
||||
caster.getPlayer().getWorld().spawnParticle(Particle.EXPLOSION_LARGE, caster.getPlayer().getLocation().add(0, 1, 0), 0);
|
||||
caster.getPlayer().getWorld().spawnParticle(Particle.SPELL_INSTANT, caster.getPlayer().getLocation().add(0, 1, 0), 32, 0, 0, 0, .1);
|
||||
caster.getPlayer().getWorld().playSound(caster.getPlayer().getLocation(), VersionSound.ENTITY_ENDERMAN_TELEPORT.toSound(), 1, 1);
|
||||
}
|
||||
}, 2, Particle.SPELL_INSTANT);
|
||||
return cast;
|
||||
}
|
||||
|
||||
private class WarpSkillMetadata extends SkillMetadata {
|
||||
private Block block;
|
||||
|
||||
public WarpSkillMetadata(CasterMetadata caster, SkillInfo skill) {
|
||||
super(caster, skill);
|
||||
|
||||
if (isSuccessful() && (block = caster.getPlayer().getTargetBlock(null, (int) getModifier("range"))) == null)
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.list;
|
||||
|
||||
import io.lumine.mythic.lib.version.VersionMaterial;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.api.util.math.particle.ParabolicProjectile;
|
||||
import net.Indyuce.mmocore.api.util.math.particle.SmallParticleEffect;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.metadata.SkillMetadata;
|
||||
import net.Indyuce.mmocore.skill.metadata.TargetSkillMetadata;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class Weaken extends Skill {
|
||||
public Weaken() {
|
||||
super();
|
||||
setMaterial(VersionMaterial.MAGENTA_DYE.toMaterial());
|
||||
setLore("The target is weakened for", "&8{duration} &7seconds and is dealt", "&7extra &8{ratio}% &7damage.", "", "&e{cooldown}s Cooldown", "&9Costs {mana} {mana_name}");
|
||||
|
||||
addModifier("cooldown", new LinearValue(20, -.1, 5, 20));
|
||||
addModifier("mana", new LinearValue(4, 1));
|
||||
addModifier("ratio", new LinearValue(30, 3));
|
||||
addModifier("duration", new LinearValue(10, -.1, 5, 10));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkillMetadata whenCast(CasterMetadata caster, SkillInfo skill) {
|
||||
TargetSkillMetadata cast = new TargetSkillMetadata(caster, skill, 7);
|
||||
if (!cast.isSuccessful())
|
||||
return cast;
|
||||
|
||||
LivingEntity target = cast.getTarget();
|
||||
new ParabolicProjectile(caster.getPlayer().getLocation().add(0, 1, 0), target.getLocation().add(0, target.getHeight() / 2, 0), randomVector(caster.getPlayer()), () -> {
|
||||
if (!target.isDead())
|
||||
new Weakened(target, cast.getModifier("ratio"), cast.getModifier("duration"));
|
||||
}, 2, Particle.SPELL_WITCH);
|
||||
return cast;
|
||||
}
|
||||
|
||||
private Vector randomVector(Player player) {
|
||||
double a = Math.toRadians(player.getEyeLocation().getYaw() + 90);
|
||||
a += (random.nextBoolean() ? 1 : -1) * (random.nextDouble() + .5) * Math.PI / 6;
|
||||
return new Vector(Math.cos(a), .8, Math.sin(a)).normalize().multiply(.4);
|
||||
}
|
||||
|
||||
public static class Weakened implements Listener {
|
||||
private final Entity entity;
|
||||
private final double c;
|
||||
|
||||
public Weakened(Entity entity, double ratio, double duration) {
|
||||
this.entity = entity;
|
||||
this.c = 1 + ratio / 100;
|
||||
|
||||
new SmallParticleEffect(entity, Particle.SPELL_WITCH);
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(MMOCore.plugin, () -> EntityDamageByEntityEvent.getHandlerList().unregister(this), (int) duration * 20);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void a(EntityDamageByEntityEvent event) {
|
||||
if (event.getEntity().equals(entity)) {
|
||||
event.getEntity().getWorld().spawnParticle(Particle.SPELL_WITCH, entity.getLocation().add(0, entity.getHeight() / 2, 0), 16, .5, .5, .5, 0);
|
||||
event.setDamage(event.getDamage() * c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.metadata;
|
||||
|
||||
import io.lumine.mythic.lib.comp.target.InteractionType;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill.SkillInfo;
|
||||
import org.bukkit.FluidCollisionMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
|
||||
public class LocationSkillMetadata extends SkillMetadata {
|
||||
private Location loc;
|
||||
|
||||
/**
|
||||
* @param caster Player casting the skill
|
||||
* @param skill Skill being cast
|
||||
* @param range Skill raycast range
|
||||
*/
|
||||
public LocationSkillMetadata(CasterMetadata caster, SkillInfo skill, double range) {
|
||||
this(caster, skill, range, InteractionType.OFFENSE_SKILL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param caster Player casting the skill
|
||||
* @param skill Skill being cast
|
||||
* @param range Skill raycast range
|
||||
* @param interaction If the skill is a friendly or offense skill. This determines if it
|
||||
* can be cast on party members or not.
|
||||
*/
|
||||
public LocationSkillMetadata(CasterMetadata caster, SkillInfo skill, double range, InteractionType interaction) {
|
||||
super(caster, skill);
|
||||
|
||||
if (isSuccessful()) {
|
||||
|
||||
RayTraceResult result = caster.getPlayer().getWorld().rayTrace(caster.getPlayer().getEyeLocation(),
|
||||
caster.getPlayer().getEyeLocation().getDirection(), range, FluidCollisionMode.ALWAYS, true, 1.0D,
|
||||
entity -> MMOCoreUtils.canTarget(caster.getPlayerData(), entity, interaction));
|
||||
if (result == null)
|
||||
abort(CancelReason.OTHER);
|
||||
else
|
||||
loc = result.getHitBlock() != null ? result.getHitBlock().getLocation()
|
||||
: result.getHitEntity() != null ? result.getHitEntity().getLocation() : null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasHit() {
|
||||
return loc != null;
|
||||
}
|
||||
|
||||
public Location getHit() {
|
||||
return loc;
|
||||
}
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.metadata;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.comp.flags.CustomFlag;
|
||||
import io.lumine.mythic.lib.comp.mythicmobs.MythicSkillInfo;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill;
|
||||
import net.Indyuce.mmocore.skill.Skill.SkillInfo;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class SkillMetadata implements MythicSkillInfo {
|
||||
private final SkillInfo skill;
|
||||
private final int level;
|
||||
private final double mana, cooldown, stamina;
|
||||
|
||||
private CancelReason cancelReason;
|
||||
|
||||
public SkillMetadata(CasterMetadata caster, SkillInfo skill) {
|
||||
this.skill = skill;
|
||||
|
||||
PlayerData data = caster.getPlayerData();
|
||||
|
||||
level = data.getSkillLevel(skill.getSkill());
|
||||
cooldown = skill.getSkill().hasModifier("cooldown") ? getModifier("cooldown") : 0;
|
||||
mana = skill.getSkill().hasModifier("mana") ? getModifier("mana") : 0;
|
||||
stamina = skill.getSkill().hasModifier("stamina") ? getModifier("stamina") : 0;
|
||||
cancelReason = !data.hasSkillUnlocked(skill) ? CancelReason.LOCKED
|
||||
: data.getCooldownMap().isOnCooldown(getSkill()) ? CancelReason.COOLDOWN
|
||||
: mana > data.getMana() ? CancelReason.MANA
|
||||
: stamina > data.getStamina() ? CancelReason.STAMINA
|
||||
: !data.isOnline() ? CancelReason.OTHER
|
||||
: !MythicLib.plugin.getFlags().isFlagAllowed(data.getPlayer(), CustomFlag.MMO_ABILITIES) ? CancelReason.FLAG
|
||||
: null;
|
||||
}
|
||||
|
||||
public SkillMetadata(PlayerData data, SkillInfo skill, CancelReason reason) {
|
||||
this.skill = skill;
|
||||
this.cancelReason = reason;
|
||||
|
||||
level = data.getSkillLevel(skill.getSkill());
|
||||
cooldown = skill.getSkill().hasModifier("cooldown") ? getModifier("cooldown") : 0;
|
||||
mana = skill.getSkill().hasModifier("mana") ? getModifier("mana") : 0;
|
||||
stamina = skill.getSkill().hasModifier("stamina") ? getModifier("stamina") : 0;
|
||||
}
|
||||
|
||||
public Skill getSkill() {
|
||||
return skill.getSkill();
|
||||
}
|
||||
|
||||
public SkillInfo getInfo() {
|
||||
return skill;
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public double getStaminaCost() {
|
||||
return stamina;
|
||||
}
|
||||
|
||||
public double getManaCost() {
|
||||
return mana;
|
||||
}
|
||||
|
||||
public double getCooldown() {
|
||||
return cooldown;
|
||||
}
|
||||
|
||||
public boolean isSuccessful() {
|
||||
return cancelReason == null;
|
||||
}
|
||||
|
||||
public CancelReason getCancelReason() {
|
||||
return cancelReason;
|
||||
}
|
||||
|
||||
public void abort() {
|
||||
abort(CancelReason.OTHER);
|
||||
}
|
||||
|
||||
public void abort(CancelReason reason) {
|
||||
cancelReason = Objects.requireNonNull(reason, "Reason cannot be null");
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getModifier(String modifier) {
|
||||
return skill.getModifier(modifier, level);
|
||||
}
|
||||
|
||||
public enum CancelReason {
|
||||
|
||||
/**
|
||||
* Flag plugin like WorldGuard or any other
|
||||
*/
|
||||
FLAG,
|
||||
|
||||
/**
|
||||
* Not enough stamina
|
||||
*/
|
||||
MANA,
|
||||
|
||||
/**
|
||||
* Not enough mana
|
||||
*/
|
||||
STAMINA,
|
||||
|
||||
/**
|
||||
* Skill still on cooldown
|
||||
*/
|
||||
COOLDOWN,
|
||||
|
||||
/**
|
||||
* Skill is locked
|
||||
*/
|
||||
LOCKED,
|
||||
|
||||
/**
|
||||
* Anything else, used for instance when MythicMobs
|
||||
* skill conditions prevent the skill from casting or
|
||||
* when the Bukkit pre cast event is cancelled
|
||||
*/
|
||||
OTHER;
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package net.Indyuce.mmocore.skill.metadata;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.MMORayTraceResult;
|
||||
import io.lumine.mythic.lib.comp.target.InteractionType;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.skill.CasterMetadata;
|
||||
import net.Indyuce.mmocore.skill.Skill.SkillInfo;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
|
||||
public class TargetSkillMetadata extends SkillMetadata {
|
||||
private LivingEntity target;
|
||||
|
||||
/**
|
||||
* @param caster Player casting the skill
|
||||
* @param skill Skill being cast
|
||||
* @param range Skill raycast range
|
||||
*/
|
||||
public TargetSkillMetadata(CasterMetadata caster, SkillInfo skill, double range) {
|
||||
this(caster, skill, range, InteractionType.OFFENSE_SKILL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param caster Player casting the skill
|
||||
* @param skill Skill being cast
|
||||
* @param range Skill raycast range
|
||||
* @param interaction If the skill is a friendly or offense skill. This determines if it
|
||||
* can be cast on party members or not.
|
||||
*/
|
||||
public TargetSkillMetadata(CasterMetadata caster, SkillInfo skill, double range, InteractionType interaction) {
|
||||
super(caster, skill);
|
||||
|
||||
if (isSuccessful()) {
|
||||
MMORayTraceResult result = MythicLib.plugin.getVersion().getWrapper().rayTrace(caster.getPlayer(), range, entity -> MMOCoreUtils.canTarget(caster.getPlayerData(), entity, interaction));
|
||||
if (!result.hasHit())
|
||||
abort();
|
||||
else
|
||||
target = result.getHit();
|
||||
}
|
||||
}
|
||||
|
||||
public LivingEntity getTarget() {
|
||||
return target;
|
||||
}
|
||||
}
|
33
src/main/resources/default/skills/ambers.yml
Normal file
33
src/main/resources/default/skills/ambers.yml
Normal file
@ -0,0 +1,33 @@
|
||||
name: Ambers
|
||||
lore:
|
||||
- Dealing magic damage has &630% &7chance
|
||||
- of dropping an amber on the ground.
|
||||
- ''
|
||||
- When picked up, ambers stack and
|
||||
- refund &9{percent}% &7of your missing mana.
|
||||
- ''
|
||||
- '&oAmbers can be used in other damaging skills.'
|
||||
- '&oThe more you collect, the more powerful the skills.'
|
||||
- ''
|
||||
- '&e{cooldown}s Cooldown'
|
||||
material: EMERALD
|
||||
mana:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
cooldown:
|
||||
base: 3.0
|
||||
per-level: -0.1
|
||||
max: 3.0
|
||||
min: 1.0
|
||||
percent:
|
||||
base: 10.0
|
||||
per-level: 0.1
|
||||
max: 20.0
|
||||
min: 10.0
|
20
src/main/resources/default/skills/backstab.yml
Normal file
20
src/main/resources/default/skills/backstab.yml
Normal file
@ -0,0 +1,20 @@
|
||||
name: Backstab
|
||||
lore:
|
||||
- Backstabs deal &c{extra}%&7 damage.
|
||||
- ''
|
||||
- '&9Costs {mana} {mana_name}'
|
||||
material: FLINT
|
||||
mana:
|
||||
base: 8.0
|
||||
per-level: 1.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
extra:
|
||||
base: 50.0
|
||||
per-level: 20.0
|
||||
cooldown:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
29
src/main/resources/default/skills/combo-attack.yml
Normal file
29
src/main/resources/default/skills/combo-attack.yml
Normal file
@ -0,0 +1,29 @@
|
||||
name: Combo Attack
|
||||
lore:
|
||||
- Violenty slashes your target &8{count}
|
||||
- times for a total of &8{damage} &7damage.
|
||||
- ''
|
||||
- '&e{cooldown}s Cooldown'
|
||||
- '&9Costs {mana} {mana_name}'
|
||||
material: IRON_SWORD
|
||||
damage:
|
||||
base: 9.0
|
||||
per-level: 0.3
|
||||
mana:
|
||||
base: 10.0
|
||||
per-level: -0.1
|
||||
max: 5.0
|
||||
min: 3.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
cooldown:
|
||||
base: 20.0
|
||||
per-level: -0.1
|
||||
max: 20.0
|
||||
min: 5.0
|
||||
count:
|
||||
base: 3.0
|
||||
per-level: 0.2
|
29
src/main/resources/default/skills/control.yml
Normal file
29
src/main/resources/default/skills/control.yml
Normal file
@ -0,0 +1,29 @@
|
||||
name: Control
|
||||
lore:
|
||||
- Your target is temporarily slowed for &8{duration} &7seconds.
|
||||
- As soon as you left click, it gets
|
||||
- pushed back where you are looking at.
|
||||
- 'Knockback force: &f{knockback}%'
|
||||
- ''
|
||||
- '&e{cooldown}s Cooldown'
|
||||
- '&9Costs {mana} {mana_name}'
|
||||
material: MAGENTA_DYE
|
||||
duration:
|
||||
base: 2.0
|
||||
per-level: 0.0
|
||||
mana:
|
||||
base: 15.0
|
||||
per-level: 1.5
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
cooldown:
|
||||
base: 18.0
|
||||
per-level: -0.3
|
||||
max: 20.0
|
||||
min: 10.0
|
||||
knockback:
|
||||
base: 30.0
|
||||
per-level: 3.0
|
28
src/main/resources/default/skills/deep-wound.yml
Normal file
28
src/main/resources/default/skills/deep-wound.yml
Normal file
@ -0,0 +1,28 @@
|
||||
name: Deep Wound
|
||||
lore:
|
||||
- You puncture your target, dealing &c{damage} &7damage.
|
||||
- Damage is increased up to &c+{extra}% &7based
|
||||
- on your target's missing health.
|
||||
- ''
|
||||
- '&e{cooldown}s Cooldown'
|
||||
- '&9Costs {mana} {mana_name}'
|
||||
material: REDSTONE
|
||||
damage:
|
||||
base: 5.0
|
||||
per-level: 1.5
|
||||
mana:
|
||||
base: 8.0
|
||||
per-level: 3.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
extra:
|
||||
base: 50.0
|
||||
per-level: 20.0
|
||||
cooldown:
|
||||
base: 20.0
|
||||
per-level: -0.1
|
||||
max: 20.0
|
||||
min: 5.0
|
34
src/main/resources/default/skills/empowered-attack.yml
Normal file
34
src/main/resources/default/skills/empowered-attack.yml
Normal file
@ -0,0 +1,34 @@
|
||||
name: Empowered Attack
|
||||
lore:
|
||||
- You charge your weapon with lightning.
|
||||
- Your next attack deals &f{extra}% &7extra damage
|
||||
- and spreads to enemies within &f{radius} &7blocks
|
||||
- for &f{ratio}% &7of the initial damage.
|
||||
- ''
|
||||
- '&e{cooldown}s Cooldown'
|
||||
- '&9Costs {mana} {mana_name}'
|
||||
material: BONE_MEAL
|
||||
mana:
|
||||
base: 4.0
|
||||
per-level: 1.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
extra:
|
||||
base: 30.0
|
||||
per-level: 8.0
|
||||
cooldown:
|
||||
base: 10.0
|
||||
per-level: -0.2
|
||||
max: 10.0
|
||||
min: 5.0
|
||||
radius:
|
||||
base: 4.0
|
||||
per-level: 0.0
|
||||
ratio:
|
||||
base: 30.0
|
||||
per-level: 10.0
|
||||
max: 100.0
|
||||
min: 30.0
|
24
src/main/resources/default/skills/evade.yml
Normal file
24
src/main/resources/default/skills/evade.yml
Normal file
@ -0,0 +1,24 @@
|
||||
name: Evade
|
||||
lore:
|
||||
- You become imune to damage for &8{duration} &7seconds.
|
||||
- Cancels when dealing weapon damage.
|
||||
- ''
|
||||
- '&e{cooldown}s Cooldown'
|
||||
- '&9Costs {mana} {mana_name}'
|
||||
material: LEATHER_BOOTS
|
||||
duration:
|
||||
base: 2.0
|
||||
per-level: 0.3
|
||||
max: 10.0
|
||||
min: 2.0
|
||||
mana:
|
||||
base: 8.0
|
||||
per-level: 3.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
cooldown:
|
||||
base: 20.0
|
||||
per-level: 0.0
|
17
src/main/resources/default/skills/fire-berserker.yml
Normal file
17
src/main/resources/default/skills/fire-berserker.yml
Normal file
@ -0,0 +1,17 @@
|
||||
name: Fire Berserker
|
||||
lore:
|
||||
- You deal &c{extra}% &7more damage when on fire.
|
||||
material: FLINT_AND_STEEL
|
||||
mana:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
extra:
|
||||
base: 10.0
|
||||
per-level: 5.0
|
35
src/main/resources/default/skills/fire-rage.yml
Normal file
35
src/main/resources/default/skills/fire-rage.yml
Normal file
@ -0,0 +1,35 @@
|
||||
name: Fire Rage
|
||||
lore:
|
||||
- For {duration} seconds, you slow down and are able
|
||||
- to cast up to {count} fireballs by left clicking.
|
||||
- ''
|
||||
- Fireballs deal &c{damage} &7damage upon contact
|
||||
- and ignite your target for &c{ignite} &7seconds.
|
||||
- '&e{cooldown}s Cooldown'
|
||||
- '&9Costs {mana} {mana_name}'
|
||||
material: FIRE_CHARGE
|
||||
duration:
|
||||
base: 8.0
|
||||
per-level: 0.0
|
||||
damage:
|
||||
base: 5.0
|
||||
per-level: 3.0
|
||||
ignite:
|
||||
base: 2.0
|
||||
per-level: 0.1
|
||||
mana:
|
||||
base: 15.0
|
||||
per-level: 1.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
count:
|
||||
base: 4.0
|
||||
per-level: 0.0
|
||||
cooldown:
|
||||
base: 9.0
|
||||
per-level: -0.1
|
||||
max: 5.0
|
||||
min: 1.0
|
29
src/main/resources/default/skills/fire-storm.yml
Normal file
29
src/main/resources/default/skills/fire-storm.yml
Normal file
@ -0,0 +1,29 @@
|
||||
name: Fire Storm
|
||||
lore:
|
||||
- Casts a flurry of 6 fire projectiles onto
|
||||
- nearby enemies, proritizing the initial
|
||||
- target. Each projectile deals &c{damage} &7damage
|
||||
- and ignite the target for &c{ignite} &7seconds.
|
||||
- ''
|
||||
- '&e{cooldown}s Cooldown'
|
||||
- '&9Costs {mana} {mana_name}'
|
||||
material: BLAZE_POWDER
|
||||
damage:
|
||||
base: 5.0
|
||||
per-level: 3.0
|
||||
ignite:
|
||||
base: 2.0
|
||||
per-level: 0.1
|
||||
mana:
|
||||
base: 15.0
|
||||
per-level: 2.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
cooldown:
|
||||
base: 5.0
|
||||
per-level: -0.1
|
||||
max: 5.0
|
||||
min: 1.0
|
35
src/main/resources/default/skills/fireball.yml
Normal file
35
src/main/resources/default/skills/fireball.yml
Normal file
@ -0,0 +1,35 @@
|
||||
name: Fireball
|
||||
lore:
|
||||
- Casts a deadly fireball onto your
|
||||
- target, dealing &c{damage} &7damage upon contact
|
||||
- and igniting it for &c{ignite} &7seconds.
|
||||
- ''
|
||||
- Shatters into 3 blazing hot shards which stick
|
||||
- to walls and explode 3 seconds later, dealing
|
||||
- '&c{ratio}% &7of the initial spell damage.'
|
||||
- ''
|
||||
- '&e{cooldown}s Cooldown'
|
||||
- '&9Costs {mana} {mana_name}'
|
||||
material: FIRE_CHARGE
|
||||
damage:
|
||||
base: 5.0
|
||||
per-level: 3.0
|
||||
ignite:
|
||||
base: 2.0
|
||||
per-level: 0.1
|
||||
mana:
|
||||
base: 15.0
|
||||
per-level: 1.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
cooldown:
|
||||
base: 9.0
|
||||
per-level: -0.1
|
||||
max: 5.0
|
||||
min: 1.0
|
||||
ratio:
|
||||
base: 50.0
|
||||
per-level: 3.0
|
30
src/main/resources/default/skills/furtive-strike.yml
Normal file
30
src/main/resources/default/skills/furtive-strike.yml
Normal file
@ -0,0 +1,30 @@
|
||||
name: Furtive Strike
|
||||
lore:
|
||||
- Deals &c{damage} &7damage, increased by &c{extra}% &7if
|
||||
- there are not any enemies within &c{radius} &7blocks.
|
||||
- ''
|
||||
- '&e{cooldown}s Cooldown'
|
||||
- '&9Costs {mana} {mana_name}'
|
||||
material: COAL
|
||||
damage:
|
||||
base: 5.0
|
||||
per-level: 1.5
|
||||
mana:
|
||||
base: 8.0
|
||||
per-level: 3.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
extra:
|
||||
base: 50.0
|
||||
per-level: 20.0
|
||||
cooldown:
|
||||
base: 20.0
|
||||
per-level: -0.1
|
||||
max: 20.0
|
||||
min: 5.0
|
||||
radius:
|
||||
base: 7.0
|
||||
per-level: 0.0
|
24
src/main/resources/default/skills/greater-healings.yml
Normal file
24
src/main/resources/default/skills/greater-healings.yml
Normal file
@ -0,0 +1,24 @@
|
||||
name: Greater Healings
|
||||
lore:
|
||||
- Instantly grants &a{heal} &7HP to the
|
||||
- target. Sneak to cast it on yourself.
|
||||
- ''
|
||||
- '&e{cooldown}s Cooldown'
|
||||
- '&9Costs {mana} {mana_name}'
|
||||
material: GOLDEN_APPLE
|
||||
mana:
|
||||
base: 4.0
|
||||
per-level: 2.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
heal:
|
||||
base: 10.0
|
||||
per-level: 4.0
|
||||
cooldown:
|
||||
base: 9.0
|
||||
per-level: -0.1
|
||||
max: 5.0
|
||||
min: 1.0
|
40
src/main/resources/default/skills/human-shield.yml
Normal file
40
src/main/resources/default/skills/human-shield.yml
Normal file
@ -0,0 +1,40 @@
|
||||
name: Human Shield
|
||||
lore:
|
||||
- Casts a protection charm onto target ally,
|
||||
- reducing damage taken by &a{reduction}%&7.
|
||||
- '&a{redirect}% &7of this damage is redirected to you.'
|
||||
- Charm is cancelled when reaching &c{low}%&7 health.
|
||||
- Lasts &a{duration} &7seconds.
|
||||
- ''
|
||||
- '&e{cooldown}s Cooldown'
|
||||
- '&9Costs {mana} {mana_name}'
|
||||
material: TOTEM_OF_UNDYING
|
||||
redirect:
|
||||
base: 30.0
|
||||
per-level: -2.0
|
||||
max: 30.0
|
||||
min: 20.0
|
||||
duration:
|
||||
base: 7.0
|
||||
per-level: 0.0
|
||||
mana:
|
||||
base: 15.0
|
||||
per-level: 1.5
|
||||
low:
|
||||
base: 10.0
|
||||
per-level: 0.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
cooldown:
|
||||
base: 18.0
|
||||
per-level: -0.3
|
||||
max: 18.0
|
||||
min: 14.0
|
||||
reduction:
|
||||
base: 30.0
|
||||
per-level: 3.0
|
||||
max: 70.0
|
||||
min: 30.0
|
29
src/main/resources/default/skills/ice-spikes.yml
Normal file
29
src/main/resources/default/skills/ice-spikes.yml
Normal file
@ -0,0 +1,29 @@
|
||||
name: Ice Spikes
|
||||
lore:
|
||||
- Ice spikes summon from the ground
|
||||
- and shatter, each dealing &9{damage} &7damage
|
||||
- to hit enemies and slowing them down
|
||||
- for &9{slow} &7seconds.
|
||||
- ''
|
||||
- '&e{cooldown}s Cooldown'
|
||||
- '&9Costs {mana} {mana_name}'
|
||||
material: SNOWBALL
|
||||
damage:
|
||||
base: 3.0
|
||||
per-level: 1.0
|
||||
mana:
|
||||
base: 20.0
|
||||
per-level: 2.0
|
||||
slow:
|
||||
base: 4.0
|
||||
per-level: 0.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
cooldown:
|
||||
base: 6.0
|
||||
per-level: -0.1
|
||||
max: 6.0
|
||||
min: 2.0
|
24
src/main/resources/default/skills/minor-healings.yml
Normal file
24
src/main/resources/default/skills/minor-healings.yml
Normal file
@ -0,0 +1,24 @@
|
||||
name: Minor Healings
|
||||
lore:
|
||||
- Instantly grants &a{heal} &7HP to the
|
||||
- target. Sneak to cast it on yourself.
|
||||
- ''
|
||||
- '&e{cooldown}s Cooldown'
|
||||
- '&9Costs {mana} {mana_name}'
|
||||
material: GOLDEN_APPLE
|
||||
mana:
|
||||
base: 4.0
|
||||
per-level: 2.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
heal:
|
||||
base: 4.0
|
||||
per-level: 2.0
|
||||
cooldown:
|
||||
base: 9.0
|
||||
per-level: -0.1
|
||||
max: 5.0
|
||||
min: 1.0
|
7
src/main/resources/default/skills/neptune-gift.yml
Normal file
7
src/main/resources/default/skills/neptune-gift.yml
Normal file
@ -0,0 +1,7 @@
|
||||
name: Neptune's Gift
|
||||
lore:
|
||||
- Resource regeneration is increased by &8{extra}% &7when standing in water.
|
||||
material: LILY_PAD
|
||||
extra:
|
||||
base: 30.0
|
||||
per-level: 5.0
|
38
src/main/resources/default/skills/power-mark.yml
Normal file
38
src/main/resources/default/skills/power-mark.yml
Normal file
@ -0,0 +1,38 @@
|
||||
name: Power Mark
|
||||
lore:
|
||||
- Attacking an enemy applies a deadly
|
||||
- magical mark which spreads accross the
|
||||
- ground. This mark accumulates &6{ratio}%
|
||||
- of the damage dealt to the initial
|
||||
- target over &6{duration} &7seconds.
|
||||
- ''
|
||||
- After this duration, the mark bursts, dealing
|
||||
- accumulated damage to nearby enemies and
|
||||
- stunning them for &6{stun}+ &7seconds.
|
||||
- ''
|
||||
- The more damage, the longer the stun.
|
||||
- ''
|
||||
- '&e{cooldown}s Cooldown'
|
||||
material: WITHER_SKELETON_SKULL
|
||||
duration:
|
||||
base: 10.0
|
||||
per-level: 0.1
|
||||
mana:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
cooldown:
|
||||
base: 30.0
|
||||
per-level: 0.0
|
||||
stun:
|
||||
base: 0.4
|
||||
per-level: 0.03
|
||||
ratio:
|
||||
base: 10.0
|
||||
per-level: 5.0
|
21
src/main/resources/default/skills/sneaky-picky.yml
Normal file
21
src/main/resources/default/skills/sneaky-picky.yml
Normal file
@ -0,0 +1,21 @@
|
||||
name: Sneaky Picky
|
||||
lore:
|
||||
- Your attack is empowered by &f{extra}% &7when
|
||||
- delivering the first blow during a fight.
|
||||
- ''
|
||||
- '&9Costs {mana} {mana_name}'
|
||||
material: DIAMOND_SWORD
|
||||
mana:
|
||||
base: 8.0
|
||||
per-level: 1.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
extra:
|
||||
base: 50.0
|
||||
per-level: 20.0
|
||||
cooldown:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
30
src/main/resources/default/skills/telekinesy.yml
Normal file
30
src/main/resources/default/skills/telekinesy.yml
Normal file
@ -0,0 +1,30 @@
|
||||
name: Telekinesy
|
||||
lore:
|
||||
- You take the control over your target
|
||||
- for &9{duration} &7seconds. Left click to throw him.
|
||||
- 'Knockback force: &f{knockback}%'
|
||||
- ''
|
||||
- '&e{cooldown}s Cooldown'
|
||||
- '&9Costs {mana} {mana_name}'
|
||||
material: MAGENTA_DYE
|
||||
duration:
|
||||
base: 3.0
|
||||
per-level: 0.1
|
||||
max: 6.0
|
||||
min: 3.0
|
||||
mana:
|
||||
base: 20.0
|
||||
per-level: 2.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
cooldown:
|
||||
base: 20.0
|
||||
per-level: -0.3
|
||||
max: 20.0
|
||||
min: 10.0
|
||||
knockback:
|
||||
base: 50.0
|
||||
per-level: 10.0
|
26
src/main/resources/default/skills/warp.yml
Normal file
26
src/main/resources/default/skills/warp.yml
Normal file
@ -0,0 +1,26 @@
|
||||
name: Warp
|
||||
lore:
|
||||
- Teleports you to target location.
|
||||
- 'Max. Range: &5{range}'
|
||||
- ''
|
||||
- '&e{cooldown}s Cooldown'
|
||||
- '&9Costs {mana} {mana_name}'
|
||||
material: ENDER_PEARL
|
||||
mana:
|
||||
base: 8.0
|
||||
per-level: 3.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
cooldown:
|
||||
base: 15.0
|
||||
per-level: -0.3
|
||||
max: 15.0
|
||||
min: 2.0
|
||||
range:
|
||||
base: 16.0
|
||||
per-level: 1.0
|
||||
max: 100.0
|
||||
min: 0.0
|
30
src/main/resources/default/skills/weaken.yml
Normal file
30
src/main/resources/default/skills/weaken.yml
Normal file
@ -0,0 +1,30 @@
|
||||
name: Weaken
|
||||
lore:
|
||||
- The target is weakened for
|
||||
- '&8{duration} &7seconds and is dealt'
|
||||
- '&7extra &8{ratio}% &7damage.'
|
||||
- ''
|
||||
- '&e{cooldown}s Cooldown'
|
||||
- '&9Costs {mana} {mana_name}'
|
||||
material: MAGENTA_DYE
|
||||
duration:
|
||||
base: 10.0
|
||||
per-level: -0.1
|
||||
max: 10.0
|
||||
min: 5.0
|
||||
mana:
|
||||
base: 4.0
|
||||
per-level: 1.0
|
||||
stamina:
|
||||
base: 0.0
|
||||
per-level: 0.0
|
||||
max: 0.0
|
||||
min: 0.0
|
||||
cooldown:
|
||||
base: 20.0
|
||||
per-level: -0.1
|
||||
max: 20.0
|
||||
min: 5.0
|
||||
ratio:
|
||||
base: 30.0
|
||||
per-level: 3.0
|
Loading…
Reference in New Issue
Block a user