getTriggers() {
+ return triggers;
+ }
+}
diff --git a/src/main/java/net/Indyuce/mmocore/api/player/profess/event/EventTriggerHandler.java b/src/main/java/net/Indyuce/mmocore/api/player/profess/event/EventTriggerHandler.java
new file mode 100644
index 00000000..3645d281
--- /dev/null
+++ b/src/main/java/net/Indyuce/mmocore/api/player/profess/event/EventTriggerHandler.java
@@ -0,0 +1,8 @@
+package net.Indyuce.mmocore.api.player.profess.event;
+
+import org.bukkit.event.Listener;
+
+@Deprecated
+public interface EventTriggerHandler extends Listener {
+ boolean handles(String event);
+}
diff --git a/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/AttackEventTrigger.java b/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/AttackEventTrigger.java
new file mode 100644
index 00000000..e2b3d8e7
--- /dev/null
+++ b/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/AttackEventTrigger.java
@@ -0,0 +1,33 @@
+package net.Indyuce.mmocore.api.player.profess.event.trigger;
+
+import io.lumine.mythic.lib.api.event.PlayerAttackEvent;
+import io.lumine.mythic.lib.damage.DamageType;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.player.profess.PlayerClass;
+import net.Indyuce.mmocore.api.player.profess.event.EventTriggerHandler;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+
+@Deprecated
+public class AttackEventTrigger implements EventTriggerHandler {
+
+ @Override
+ public boolean handles(String event) {
+ return event.endsWith("-damage");
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void a(PlayerAttackEvent event) {
+ // We don't want players dying by themselves when using an enderpearl.
+ if (event.getPlayer().equals(event.getEntity())) return;
+
+ PlayerData player = PlayerData.get(event.getData().getUniqueId());
+ PlayerClass profess = player.getProfess();
+
+ for (DamageType type : event.getAttack().getDamage().collectTypes()) {
+ String path = type.getPath() + "-damage";
+ if (profess.hasEventTriggers(path))
+ profess.getEventTriggers(path).getTriggers().forEach(trigger -> trigger.apply(player));
+ }
+ }
+}
diff --git a/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/BlockBrokenTrigger.java b/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/BlockBrokenTrigger.java
new file mode 100644
index 00000000..89ad08c8
--- /dev/null
+++ b/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/BlockBrokenTrigger.java
@@ -0,0 +1,24 @@
+package net.Indyuce.mmocore.api.player.profess.event.trigger;
+
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.block.BlockBreakEvent;
+
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.player.profess.event.EventTriggerHandler;
+
+@Deprecated
+public class BlockBrokenTrigger implements EventTriggerHandler {
+
+ @Override
+ public boolean handles(String event) {
+ return event.startsWith("break-block");
+ }
+
+ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+ public void a(BlockBreakEvent event) {
+ PlayerData player = PlayerData.get(event.getPlayer());
+ if (player.getProfess().hasEventTriggers("break-block"))
+ player.getProfess().getEventTriggers("break-block").getTriggers().forEach(trigger -> trigger.apply(player));
+ }
+}
diff --git a/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/BlockPlacedTrigger.java b/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/BlockPlacedTrigger.java
new file mode 100644
index 00000000..bf6c751c
--- /dev/null
+++ b/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/BlockPlacedTrigger.java
@@ -0,0 +1,24 @@
+package net.Indyuce.mmocore.api.player.profess.event.trigger;
+
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.block.BlockPlaceEvent;
+
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.player.profess.event.EventTriggerHandler;
+
+@Deprecated
+public class BlockPlacedTrigger implements EventTriggerHandler {
+
+ @Override
+ public boolean handles(String event) {
+ return event.startsWith("place-block");
+ }
+
+ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+ public void a(BlockPlaceEvent event) {
+ PlayerData player = PlayerData.get(event.getPlayer());
+ if (player.getProfess().hasEventTriggers("place-block"))
+ player.getProfess().getEventTriggers("place-block").getTriggers().forEach(trigger -> trigger.apply(player));
+ }
+}
diff --git a/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/ClassChosenEventTrigger.java b/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/ClassChosenEventTrigger.java
new file mode 100644
index 00000000..7e504fb7
--- /dev/null
+++ b/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/ClassChosenEventTrigger.java
@@ -0,0 +1,29 @@
+package net.Indyuce.mmocore.api.player.profess.event.trigger;
+
+import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.player.profess.event.EventTriggerHandler;
+import org.bukkit.Bukkit;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+
+@Deprecated
+public class ClassChosenEventTrigger implements EventTriggerHandler {
+
+ @Override
+ public boolean handles(String event) {
+ return event.startsWith("class-chosen");
+ }
+
+ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+ public void a(PlayerChangeClassEvent event) {
+ PlayerData player = event.getData();
+ if (event.getNewClass().hasEventTriggers("class-chosen")) {
+ Bukkit.getScheduler().runTaskLater(MMOCore.plugin, () -> {
+ event.getNewClass().getEventTriggers("class-chosen").getTriggers().forEach(trigger -> trigger.apply(player));
+ }, 1);
+
+ }
+ }
+}
diff --git a/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/LevelUpEventTrigger.java b/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/LevelUpEventTrigger.java
new file mode 100644
index 00000000..325aaf5d
--- /dev/null
+++ b/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/LevelUpEventTrigger.java
@@ -0,0 +1,42 @@
+package net.Indyuce.mmocore.api.player.profess.event.trigger;
+
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+
+import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.player.profess.PlayerClass;
+import net.Indyuce.mmocore.api.player.profess.event.EventTriggerHandler;
+
+@Deprecated
+public class LevelUpEventTrigger implements EventTriggerHandler {
+
+ @Override
+ public boolean handles(String event) {
+ return event.startsWith("level-up");
+ }
+
+ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+ public void a(PlayerLevelUpEvent event) {
+ PlayerData player = event.getData();
+ PlayerClass profess = player.getProfess();
+
+ for(int i = event.getOldLevel(); i < event.getNewLevel(); i++) {
+ int level = i + 1;
+ if(event.hasProfession()) {
+ String prof = event.getProfession().getId().toLowerCase();
+ processTrigger(player, profess, "level-up-" + prof);
+ processTrigger(player, profess, "level-up-" + prof + "-" + level);
+ } else {
+ processTrigger(player, profess, "level-up");
+ processTrigger(player, profess, "level-up-" + level);
+ if(profess.getMaxLevel() == level)
+ processTrigger(player, profess, "level-up-max");
+ }
+ }
+ }
+
+ public void processTrigger(PlayerData player, PlayerClass profess, String trigger) {
+ if(profess.hasEventTriggers(trigger)) profess.getEventTriggers(trigger).getTriggers().forEach(t -> t.apply(player));
+ }
+}
diff --git a/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/MultipleLevelUpEventTrigger.java b/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/MultipleLevelUpEventTrigger.java
new file mode 100644
index 00000000..20f4800b
--- /dev/null
+++ b/src/main/java/net/Indyuce/mmocore/api/player/profess/event/trigger/MultipleLevelUpEventTrigger.java
@@ -0,0 +1,48 @@
+package net.Indyuce.mmocore.api.player.profess.event.trigger;
+
+import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.player.profess.PlayerClass;
+import net.Indyuce.mmocore.api.player.profess.event.EventTriggerHandler;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+
+import java.text.DecimalFormat;
+
+@Deprecated
+public class MultipleLevelUpEventTrigger implements EventTriggerHandler {
+
+ @Override
+ public boolean handles(String event) {
+ return event.startsWith("level-up-multiple");
+ }
+
+ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+ public void a(PlayerLevelUpEvent event) {
+ PlayerData player = event.getData();
+ PlayerClass profess = player.getProfess();
+
+ for(int i = event.getOldLevel(); i < event.getNewLevel(); i++) {
+ int level = i + 1;
+
+ for (String t : profess.getEventTriggers()){
+ if (t.startsWith("level-up-multiple")) {
+ String[] split = t.split("-");
+ double multiple = Double.parseDouble(split[split.length-1]);
+ if (level / multiple % 1 == 0) {
+ DecimalFormat f = new DecimalFormat("#");
+ if (event.hasProfession()) {
+ processTrigger(player, profess, "level-up-multiple-" + event.getProfession().getId().toLowerCase() + "-" + f.format(multiple));
+ } else {
+ processTrigger(player, profess, "level-up-multiple-" + f.format(multiple));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void processTrigger(PlayerData player, PlayerClass profess, String trigger) {
+ if(profess.hasEventTriggers(trigger)) profess.getEventTriggers(trigger).getTriggers().forEach(t -> t.apply(player));
+ }
+}
diff --git a/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java b/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java
index 2aa6a2c9..be0912c7 100644
--- a/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java
+++ b/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java
@@ -7,7 +7,12 @@ import io.lumine.mythic.lib.api.stat.modifier.StatModifier;
import io.lumine.mythic.lib.player.modifier.ModifierSource;
import io.lumine.mythic.lib.player.modifier.ModifierType;
import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.skill.ClassSkill;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Locale;
public class PlayerStats {
private final PlayerData data;
@@ -37,6 +42,25 @@ public class PlayerStats {
return getMap().getInstance(stat);
}
+ /**
+ * Allows for stat type enum to have dynamic professions.
+ * ID FORMAT: STAT_TYPE_HERE_PROFESSION_HERE
+ *
+ * @param type the type of stat
+ * @param profession the stat's specific permission
+ * @return instance of found stat
+ * @author Ehhthan
+ */
+ @NotNull
+ public StatInstance getInstance(StatType type, @Nullable Profession profession) {
+ if (profession == null)
+ return getInstance(type);
+ else {
+ String id = (type.name() + '_' + profession.getId()).replace('-', '_').replace(' ', '_').toUpperCase(Locale.ROOT);
+ return getInstance(id);
+ }
+ }
+
/*
* applies relative attributes on the base stat too
*/
@@ -78,11 +102,11 @@ public class PlayerStats {
* as statistics (when the player level changes, when his class
* changes, when he logs on..)
*
- * This updates the player's passive skills
+ * This updates the player's PASSIVE skills
*/
data.getMMOPlayerData().getPassiveSkillMap().removeModifiers("MMOCorePassiveSkill");
for (ClassSkill skill : data.getProfess().getSkills())
- if (skill.getSkill().hasTrigger())
+ if (skill.getSkill().getTrigger().isPassive())
data.getMMOPlayerData().getPassiveSkillMap().addModifier(skill.toPassive(data));
}
}
diff --git a/src/main/java/net/Indyuce/mmocore/experience/PlayerProfessions.java b/src/main/java/net/Indyuce/mmocore/experience/PlayerProfessions.java
index 5a257b20..4d1287fd 100644
--- a/src/main/java/net/Indyuce/mmocore/experience/PlayerProfessions.java
+++ b/src/main/java/net/Indyuce/mmocore/experience/PlayerProfessions.java
@@ -10,6 +10,7 @@ import net.Indyuce.mmocore.api.SoundEvent;
import net.Indyuce.mmocore.api.event.PlayerExperienceGainEvent;
import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent;
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.particle.SmallParticleEffect;
import org.apache.commons.lang.Validate;
@@ -164,6 +165,9 @@ public class PlayerProfessions {
value = MMOCore.plugin.boosterManager.calculateExp(profession, value);
+ // Adds functionality for additional experience per profession.
+ value *= 1 + playerData.getStats().getInstance(StatType.ADDITIONAL_EXPERIENCE, profession).getTotal() / 100;
+
// Display hologram
if (hologramLocation != null)
MMOCoreUtils.displayIndicator(hologramLocation.add(.5, 1.5, .5), MMOCore.plugin.configManager.getSimpleMessage("exp-hologram", "exp", "" + value).message());
diff --git a/src/main/java/net/Indyuce/mmocore/gui/SkillList.java b/src/main/java/net/Indyuce/mmocore/gui/SkillList.java
index fe98c1f4..a60e027d 100644
--- a/src/main/java/net/Indyuce/mmocore/gui/SkillList.java
+++ b/src/main/java/net/Indyuce/mmocore/gui/SkillList.java
@@ -353,7 +353,7 @@ public class SkillList extends EditableInventory {
if (selected == null)
return;
- if (selected.getSkill().isPassive()) {
+ if (selected.getSkill().getTrigger().isPassive()) {
MMOCore.plugin.configManager.getSimpleMessage("not-active-skill").send(player);
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
return;
diff --git a/src/main/java/net/Indyuce/mmocore/guild/GuildModuleType.java b/src/main/java/net/Indyuce/mmocore/guild/GuildModuleType.java
index 48e03605..bca192f4 100644
--- a/src/main/java/net/Indyuce/mmocore/guild/GuildModuleType.java
+++ b/src/main/java/net/Indyuce/mmocore/guild/GuildModuleType.java
@@ -1,13 +1,18 @@
package net.Indyuce.mmocore.guild;
import net.Indyuce.mmocore.guild.compat.FactionsGuildModule;
+import net.Indyuce.mmocore.guild.compat.GuildsGuildModule;
import net.Indyuce.mmocore.guild.compat.UltimateClansGuildModule;
+import net.Indyuce.mmocore.guild.provided.MMOCoreGuildModule;
import org.bukkit.Bukkit;
import javax.inject.Provider;
public enum GuildModuleType {
FACTIONS("Factions", FactionsGuildModule::new),
+ GUILDS("Guilds", GuildsGuildModule::new),
+ KINGDOMSX("Guilds", GuildsGuildModule::new),
+ MMOCORE("MMOCore", MMOCoreGuildModule::new),
ULTIMATE_CLANS("UltimateClans", UltimateClansGuildModule::new),
;
diff --git a/src/main/java/net/Indyuce/mmocore/guild/compat/FactionsGuildModule.java b/src/main/java/net/Indyuce/mmocore/guild/compat/FactionsGuildModule.java
index f7470a10..066b6181 100644
--- a/src/main/java/net/Indyuce/mmocore/guild/compat/FactionsGuildModule.java
+++ b/src/main/java/net/Indyuce/mmocore/guild/compat/FactionsGuildModule.java
@@ -6,6 +6,7 @@ import com.massivecraft.factions.Faction;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.guild.AbstractGuild;
import net.Indyuce.mmocore.guild.GuildModule;
+import org.jetbrains.annotations.NotNull;
public class FactionsGuildModule implements GuildModule {
@@ -16,6 +17,8 @@ public class FactionsGuildModule implements GuildModule {
}
class CustomGuild implements AbstractGuild {
+
+ @NotNull
private final Faction faction;
CustomGuild(Faction faction) {
diff --git a/src/main/java/net/Indyuce/mmocore/guild/compat/GuildsGuildModule.java b/src/main/java/net/Indyuce/mmocore/guild/compat/GuildsGuildModule.java
index d1fdb2ae..bfeca8ce 100644
--- a/src/main/java/net/Indyuce/mmocore/guild/compat/GuildsGuildModule.java
+++ b/src/main/java/net/Indyuce/mmocore/guild/compat/GuildsGuildModule.java
@@ -5,6 +5,7 @@ import me.glaremasters.guilds.guild.Guild;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.guild.AbstractGuild;
import net.Indyuce.mmocore.guild.GuildModule;
+import org.jetbrains.annotations.NotNull;
public class GuildsGuildModule implements GuildModule {
@@ -15,6 +16,8 @@ public class GuildsGuildModule implements GuildModule {
}
class CustomGuild implements AbstractGuild {
+
+ @NotNull
private final Guild guild;
CustomGuild(Guild guild) {
diff --git a/src/main/java/net/Indyuce/mmocore/guild/compat/KingdomsXGuildModule.java b/src/main/java/net/Indyuce/mmocore/guild/compat/KingdomsXGuildModule.java
new file mode 100644
index 00000000..21487d76
--- /dev/null
+++ b/src/main/java/net/Indyuce/mmocore/guild/compat/KingdomsXGuildModule.java
@@ -0,0 +1,30 @@
+package net.Indyuce.mmocore.guild.compat;
+
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.guild.AbstractGuild;
+import net.Indyuce.mmocore.guild.GuildModule;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.kingdoms.constants.kingdom.Kingdom;
+import org.kingdoms.constants.player.KingdomPlayer;
+import org.kingdoms.main.Kingdoms;
+
+public class KingdomsXGuildModule implements GuildModule {
+
+ @Override
+ public AbstractGuild getGuild(PlayerData playerData) {
+ KingdomPlayer kPlayer = Kingdoms.get().getDataHandlers().getKingdomPlayerManager().getData(playerData.getUniqueId());
+ Kingdom kingdom = kPlayer == null ? null : kPlayer.getKingdom();
+ return kingdom == null ? null : new CustomGuild(kingdom);
+ }
+
+ class CustomGuild implements AbstractGuild {
+
+ @NotNull
+ private final Kingdom kingdom;
+
+ CustomGuild(Kingdom kingdom) {
+ this.kingdom = kingdom;
+ }
+ }
+}
diff --git a/src/main/java/net/Indyuce/mmocore/guild/compat/UltimateClansGuildModule.java b/src/main/java/net/Indyuce/mmocore/guild/compat/UltimateClansGuildModule.java
index 7b9bd060..1005db38 100644
--- a/src/main/java/net/Indyuce/mmocore/guild/compat/UltimateClansGuildModule.java
+++ b/src/main/java/net/Indyuce/mmocore/guild/compat/UltimateClansGuildModule.java
@@ -6,6 +6,7 @@ import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.guild.AbstractGuild;
import net.Indyuce.mmocore.guild.GuildModule;
import org.bukkit.Bukkit;
+import org.jetbrains.annotations.NotNull;
public class UltimateClansGuildModule implements GuildModule {
private static final UClans API = (UClans) Bukkit.getPluginManager().getPlugin("UltimateCLans");
@@ -15,8 +16,9 @@ public class UltimateClansGuildModule implements GuildModule {
return API.getPlayerAPI().hasClan(playerData.getUniqueId()) ? new CustomGuild(API.getClanAPI().getClan(API.getPlayerAPI().getClanID(playerData.getUniqueId()))) : null;
}
-
class CustomGuild implements AbstractGuild {
+
+ @NotNull
private final ClanData clan;
CustomGuild(ClanData clan) {
diff --git a/src/main/java/net/Indyuce/mmocore/listener/ClassTriggers.java b/src/main/java/net/Indyuce/mmocore/listener/ClassTriggers.java
new file mode 100644
index 00000000..02dd14a1
--- /dev/null
+++ b/src/main/java/net/Indyuce/mmocore/listener/ClassTriggers.java
@@ -0,0 +1,92 @@
+package net.Indyuce.mmocore.listener;
+
+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.event.PlayerChangeClassEvent;
+import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.player.playerclass.ClassTrigger;
+import net.Indyuce.mmocore.player.playerclass.ClassTriggerType;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.BlockBreakEvent;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This class still uses quest triggers because this was implemented
+ * in 1.9 and 1.9 is big enough as an update.
+ *
+ * Future implementation will utilize skill mechanics. MMOCore 1.10
+ * will merge the quest triggers with the ML skill mechanics.
+ *
+ * @author jules
+ * @see {@link ClassTrigger}
+ */
+public class ClassTriggers implements Listener {
+
+ @Deprecated
+ private static final Map damageTriggers = new HashMap<>();
+
+ static {
+ damageTriggers.put(DamageType.MAGIC, ClassTriggerType.MAGIC_DAMAGE);
+ damageTriggers.put(DamageType.PHYSICAL, ClassTriggerType.PHYSICAL_DAMAGE);
+ damageTriggers.put(DamageType.PROJECTILE, ClassTriggerType.PROJECTILE_DAMAGE);
+ damageTriggers.put(DamageType.WEAPON, ClassTriggerType.WEAPON_DAMAGE);
+ damageTriggers.put(DamageType.SKILL, ClassTriggerType.SKILL_DAMAGE);
+ }
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onAttack(PlayerAttackEvent event) {
+ for (Map.Entry entry : damageTriggers.entrySet())
+ if (event.getDamage().hasType(entry.getKey()))
+ applyTriggers(event.getPlayer(), entry.getValue()); //, () -> new TriggerMetadata(event.getAttack(), event.getEntity())
+ }
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onClassChange(PlayerChangeClassEvent event) {
+ Bukkit.getScheduler().runTask(MMOCore.plugin, () -> applyTriggers(event.getData(), ClassTriggerType.CLASS_CHOSEN));
+ }
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onLevelUp(PlayerLevelUpEvent event) {
+ applyTriggers(event.getData(), ClassTriggerType.LEVEL_UP);
+ }
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onBlockBreak(BlockBreakEvent event) {
+ applyTriggers(event.getPlayer(), ClassTriggerType.BREAK_BLOCK);
+ }
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onBlockPlace(BlockBreakEvent event) {
+ applyTriggers(event.getPlayer(), ClassTriggerType.PLACE_BLOCK);
+ }
+
+ private void applyTriggers(Player player, ClassTriggerType type) {
+ applyTriggers(PlayerData.get(player), type);
+ }
+
+ private void applyTriggers(PlayerData player, ClassTriggerType type) {
+ //return applyTriggers(player, type, () -> new TriggerMetadata(player.getMMOPlayerData().getStatMap().cache(EquipmentSlot.MAIN_HAND), null, null));
+ ClassTrigger trigger = player.getProfess().getClassTrigger(type);
+ if (trigger != null)
+ trigger.trigger(player);
+ }
+
+ // @Nullable
+ // private SkillResult applyTriggers(Player player, ClassTriggerType type, Provider triggerMetaProvider) {
+ // return applyTriggers(PlayerData.get(player), type, triggerMetaProvider);
+ // }
+
+ // @Nullable
+ // private SkillResult applyTriggers(PlayerData player, ClassTriggerType type, Provider triggerMetaProvider) {
+ // ClassTrigger trigger = player.getProfess().getClassTrigger(type);
+ // return trigger == null ? null : trigger.trigger(triggerMetaProvider.get());
+ // }
+}
diff --git a/src/main/java/net/Indyuce/mmocore/loot/droptable/dropitem/fishing/FishingDropItem.java b/src/main/java/net/Indyuce/mmocore/loot/droptable/dropitem/fishing/FishingDropItem.java
index e18c9674..b1754716 100644
--- a/src/main/java/net/Indyuce/mmocore/loot/droptable/dropitem/fishing/FishingDropItem.java
+++ b/src/main/java/net/Indyuce/mmocore/loot/droptable/dropitem/fishing/FishingDropItem.java
@@ -15,9 +15,7 @@ public class FishingDropItem {
private final int weight;
- public FishingDropItem(String value) {
- MMOLineConfig config = new MMOLineConfig(value);
-
+ public FishingDropItem(MMOLineConfig config) {
config.validate("tugs", "experience");
tugs = new RandomAmount(config.getString("tugs"));
diff --git a/src/main/java/net/Indyuce/mmocore/manager/ClassManager.java b/src/main/java/net/Indyuce/mmocore/manager/ClassManager.java
index f173cc23..e94bb005 100644
--- a/src/main/java/net/Indyuce/mmocore/manager/ClassManager.java
+++ b/src/main/java/net/Indyuce/mmocore/manager/ClassManager.java
@@ -4,14 +4,16 @@ import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.ClassOption;
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
+import net.Indyuce.mmocore.api.player.profess.event.EventTriggerHandler;
+import net.Indyuce.mmocore.api.player.profess.event.trigger.*;
import org.apache.commons.lang.Validate;
+import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.configuration.file.YamlConfiguration;
+import org.bukkit.event.HandlerList;
import java.io.File;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
import java.util.logging.Level;
public class ClassManager implements MMOCoreManager {
@@ -23,6 +25,26 @@ public class ClassManager implements MMOCoreManager {
*/
private PlayerClass defaultClass;
+ /**
+ * Same different types of trigger events to be able to
+ * map them later in the player class instances.
+ */
+ private final Set triggerHandlers = new HashSet<>();
+
+ public ClassManager() {
+ registerEvent(new LevelUpEventTrigger());
+ registerEvent(new AttackEventTrigger());
+ registerEvent(new ClassChosenEventTrigger());
+ registerEvent(new BlockBrokenTrigger());
+ registerEvent(new BlockPlacedTrigger());
+ registerEvent(new MultipleLevelUpEventTrigger());
+ }
+
+ @Deprecated
+ public void registerEvent(EventTriggerHandler handler) {
+ triggerHandlers.add(handler);
+ }
+
public void register(PlayerClass playerClass) {
map.put(playerClass.getId(), playerClass);
}
@@ -48,15 +70,18 @@ public class ClassManager implements MMOCoreManager {
return defaultClass;
}
- public void reloadPlayerClasses() {
- PlayerData.getAll().forEach(data -> data.setClass(get(data.getProfess().getId())));
- }
-
@Override
public void initialize(boolean clearBefore) {
- if (clearBefore)
+ if (clearBefore) {
map.clear();
+ /*
+ * Do not clear the list of trigger listeners, since it's only setup
+ * once the server loads and it is never modified.
+ */
+ triggerHandlers.forEach(HandlerList::unregisterAll);
+ }
+
for (File file : new File(MMOCore.plugin.getDataFolder() + "/classes").listFiles())
try {
String id = file.getName().substring(0, file.getName().length() - 4);
@@ -74,5 +99,8 @@ public class ClassManager implements MMOCoreManager {
defaultClass = map.values().stream().filter(profess -> profess.hasOption(ClassOption.DEFAULT)).findFirst()
.orElse(new PlayerClass("HUMAN", "Human", Material.LEATHER_BOOTS));
+
+ // Register event triggers
+ triggerHandlers.forEach(handler -> Bukkit.getPluginManager().registerEvents(handler, MMOCore.plugin));
}
}
diff --git a/src/main/java/net/Indyuce/mmocore/manager/profession/FishingManager.java b/src/main/java/net/Indyuce/mmocore/manager/profession/FishingManager.java
index 10aecdde..4c400de1 100644
--- a/src/main/java/net/Indyuce/mmocore/manager/profession/FishingManager.java
+++ b/src/main/java/net/Indyuce/mmocore/manager/profession/FishingManager.java
@@ -68,10 +68,10 @@ public class FishingManager extends SpecificProfessionManager {
for (String str : list)
try {
- FishingDropItem dropItem = new FishingDropItem(str);
+ FishingDropItem dropItem = new FishingDropItem(new MMOLineConfig(str));
maxWeight += dropItem.getWeight();
items.add(dropItem);
- } catch (IllegalArgumentException | IndexOutOfBoundsException exception) {
+ } catch (RuntimeException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING,
"Could not load item '" + str + "' from fishing drop table '" + id + "': " + exception.getMessage());
}
@@ -91,14 +91,11 @@ public class FishingManager extends SpecificProfessionManager {
}
public FishingDropItem getRandomItem() {
- int weight = random.nextInt(maxWeight);
+ int randomCoefficient = random.nextInt(maxWeight);
- for (FishingDropItem item : items) {
- weight -= item.getWeight();
-
- if (weight <= 0)
+ for (FishingDropItem item : items)
+ if ((randomCoefficient -= item.getWeight()) <= 0)
return item;
- }
throw new NullPointerException("Could not find item in drop table");
}
diff --git a/src/main/java/net/Indyuce/mmocore/party/PartyModuleType.java b/src/main/java/net/Indyuce/mmocore/party/PartyModuleType.java
index c1bb3dc3..f6b0370a 100644
--- a/src/main/java/net/Indyuce/mmocore/party/PartyModuleType.java
+++ b/src/main/java/net/Indyuce/mmocore/party/PartyModuleType.java
@@ -1,21 +1,18 @@
package net.Indyuce.mmocore.party;
-import net.Indyuce.mmocore.party.compat.DungeonsPartyModule;
-import net.Indyuce.mmocore.party.compat.McMMOPartyModule;
-import net.Indyuce.mmocore.party.compat.PAFPartyModule;
-import net.Indyuce.mmocore.party.compat.PartiesPartyModule;
+import net.Indyuce.mmocore.party.compat.*;
import net.Indyuce.mmocore.party.provided.MMOCorePartyModule;
import org.bukkit.Bukkit;
import javax.inject.Provider;
public enum PartyModuleType {
- DUNGEONSXL("DungeonsXL", () -> new DungeonsPartyModule()),
- MMOCORE("MMOCore", () -> new MMOCorePartyModule()),
- PARTY_AND_FRIENDS("PartyAndFriends", () -> new PAFPartyModule()),
- PARTIES("Parties", () -> new PartiesPartyModule()),
- MCMMO("mcMMO", () -> new McMMOPartyModule()),
- // DUNGEONS("Dungeons", null),
+ DUNGEONS("Dungeons", DungeonsPartyModule::new),
+ DUNGEONSXL("DungeonsXL", DungeonsXLPartyModule::new),
+ MCMMO("mcMMO", McMMOPartyModule::new),
+ MMOCORE("MMOCore", MMOCorePartyModule::new),
+ PARTIES("Parties", PartiesPartyModule::new),
+ PARTY_AND_FRIENDS("PartyAndFriends", PAFPartyModule::new),
;
private final String pluginName;
diff --git a/src/main/java/net/Indyuce/mmocore/party/compat/DungeonsPartyModule.java b/src/main/java/net/Indyuce/mmocore/party/compat/DungeonsPartyModule.java
index edda8c06..a2992622 100644
--- a/src/main/java/net/Indyuce/mmocore/party/compat/DungeonsPartyModule.java
+++ b/src/main/java/net/Indyuce/mmocore/party/compat/DungeonsPartyModule.java
@@ -1,52 +1,38 @@
package net.Indyuce.mmocore.party.compat;
-import de.erethon.dungeonsxl.DungeonsXL;
-import de.erethon.dungeonsxl.api.player.PlayerGroup;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.party.AbstractParty;
import net.Indyuce.mmocore.party.PartyModule;
import org.bukkit.entity.Player;
-import java.util.ArrayList;
import java.util.List;
-import java.util.UUID;
+@Deprecated
public class DungeonsPartyModule implements PartyModule {
@Override
public AbstractParty getParty(PlayerData playerData) {
- PlayerGroup group = DungeonsXL.getInstance().getPlayerGroup(playerData.getPlayer());
- return group == null ? null : new CustomParty(group);
+ throw new RuntimeException("Not supported");
}
class CustomParty implements AbstractParty {
- private final PlayerGroup group;
- public CustomParty(PlayerGroup group) {
- this.group = group;
+ public CustomParty() {
}
@Override
public boolean hasMember(Player player) {
- return group.getMembers().contains(player.getUniqueId());
+ throw new RuntimeException("Not supported");
}
@Override
public List getOnlineMembers() {
- List list = new ArrayList<>();
-
- for (UUID playerUid : group.getMembers().getUniqueIds()) {
- PlayerData found = PlayerData.get(playerUid);
- if (found.isOnline())
- list.add(found);
- }
-
- return list;
+ throw new RuntimeException("Not supported");
}
@Override
public int countMembers() {
- return group.getMembers().getUniqueIds().size();
+ throw new RuntimeException("Not supported");
}
}
}
diff --git a/src/main/java/net/Indyuce/mmocore/party/compat/DungeonsXLPartyModule.java b/src/main/java/net/Indyuce/mmocore/party/compat/DungeonsXLPartyModule.java
new file mode 100644
index 00000000..efb32c8e
--- /dev/null
+++ b/src/main/java/net/Indyuce/mmocore/party/compat/DungeonsXLPartyModule.java
@@ -0,0 +1,52 @@
+package net.Indyuce.mmocore.party.compat;
+
+import de.erethon.dungeonsxl.DungeonsXL;
+import de.erethon.dungeonsxl.api.player.PlayerGroup;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.party.AbstractParty;
+import net.Indyuce.mmocore.party.PartyModule;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+public class DungeonsXLPartyModule implements PartyModule {
+
+ @Override
+ public AbstractParty getParty(PlayerData playerData) {
+ PlayerGroup group = DungeonsXL.getInstance().getPlayerGroup(playerData.getPlayer());
+ return group == null ? null : new CustomParty(group);
+ }
+
+ class CustomParty implements AbstractParty {
+ private final PlayerGroup group;
+
+ public CustomParty(PlayerGroup group) {
+ this.group = group;
+ }
+
+ @Override
+ public boolean hasMember(Player player) {
+ return group.getMembers().contains(player.getUniqueId());
+ }
+
+ @Override
+ public List getOnlineMembers() {
+ List list = new ArrayList<>();
+
+ for (UUID playerUid : group.getMembers().getUniqueIds()) {
+ PlayerData found = PlayerData.get(playerUid);
+ if (found.isOnline())
+ list.add(found);
+ }
+
+ return list;
+ }
+
+ @Override
+ public int countMembers() {
+ return group.getMembers().getUniqueIds().size();
+ }
+ }
+}
diff --git a/src/main/java/net/Indyuce/mmocore/player/playerclass/ClassTrigger.java b/src/main/java/net/Indyuce/mmocore/player/playerclass/ClassTrigger.java
new file mode 100644
index 00000000..c043c3cd
--- /dev/null
+++ b/src/main/java/net/Indyuce/mmocore/player/playerclass/ClassTrigger.java
@@ -0,0 +1,64 @@
+package net.Indyuce.mmocore.player.playerclass;
+
+import io.lumine.mythic.lib.UtilityMethods;
+import io.lumine.mythic.lib.api.MMOLineConfig;
+import io.lumine.mythic.lib.skill.custom.mechanic.Mechanic;
+import io.lumine.mythic.lib.skill.result.SkillResult;
+import io.lumine.mythic.lib.skill.trigger.TriggerMetadata;
+import net.Indyuce.mmocore.MMOCore;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import net.Indyuce.mmocore.api.quest.trigger.Trigger;
+import net.Indyuce.mmocore.listener.ClassTriggers;
+import org.apache.commons.lang.Validate;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Class triggers are shortcuts for the MythicLib custom
+ * passive skill creation system.
+ *
+ * A class trigger is defined by a {@link ClassTriggerType} which
+ * determines when the action is performed, and a set of {@link Mechanic}
+ * which determines what happens when triggered.
+ *
+ * Class triggers fully replace 'event triggers' which were an
+ * over simplified implementation of passive skills.
+ *
+ * @author jules
+ * @see {@link ClassTriggers}
+ */
+public class ClassTrigger {
+ private final ClassTriggerType type;
+ private final List triggers = new ArrayList<>();
+ // private final CustomSkill skill = new CustomSkill("classTrigger", false);
+ // private final Skill castableSkill = new SimpleSkill(new MythicLibSkillHandler(skill));
+
+ public ClassTrigger(String triggerTypeString, List mechanicStringList) {
+ Validate.notNull(mechanicStringList, "Mechanic list cannot be null");
+ type = ClassTriggerType.valueOf(UtilityMethods.enumName(triggerTypeString));
+
+
+ for (String key : mechanicStringList) {
+ MMOLineConfig config = new MMOLineConfig(key);
+ triggers.add(MMOCore.plugin.loadManager.loadTrigger(config));
+ // ConfigObject config = new LineConfigObject(new MMOLineConfig(key));
+ // Mechanic mechanic = MythicLib.plugin.getSkills().loadMechanic(config);
+ // skill.getMechanics().add(mechanic);
+ }
+ }
+
+ public ClassTriggerType getType() {
+ return type;
+ }
+
+ @Deprecated
+ public SkillResult trigger(TriggerMetadata triggerMeta) {
+ // return castableSkill.cast(triggerMeta);
+ return null;
+ }
+
+ public void trigger(PlayerData player) {
+ triggers.forEach(trigger -> trigger.apply(player));
+ }
+}
diff --git a/src/main/java/net/Indyuce/mmocore/player/playerclass/ClassTriggerType.java b/src/main/java/net/Indyuce/mmocore/player/playerclass/ClassTriggerType.java
new file mode 100644
index 00000000..47f662fd
--- /dev/null
+++ b/src/main/java/net/Indyuce/mmocore/player/playerclass/ClassTriggerType.java
@@ -0,0 +1,26 @@
+package net.Indyuce.mmocore.player.playerclass;
+
+public enum ClassTriggerType {
+ BREAK_BLOCK,
+
+ PLACE_BLOCK,
+
+ CLASS_CHOSEN,
+
+ LEVEL_UP,
+
+ @Deprecated
+ MAGIC_DAMAGE,
+
+ @Deprecated
+ PHYSICAL_DAMAGE,
+
+ @Deprecated
+ PROJECTILE_DAMAGE,
+
+ @Deprecated
+ WEAPON_DAMAGE,
+
+ @Deprecated
+ SKILL_DAMAGE;
+}
diff --git a/src/main/java/net/Indyuce/mmocore/skill/CastableSkill.java b/src/main/java/net/Indyuce/mmocore/skill/CastableSkill.java
index d2cc4184..97748824 100644
--- a/src/main/java/net/Indyuce/mmocore/skill/CastableSkill.java
+++ b/src/main/java/net/Indyuce/mmocore/skill/CastableSkill.java
@@ -6,16 +6,20 @@ 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 io.lumine.mythic.lib.skill.trigger.TriggerType;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
import net.Indyuce.mmocore.api.player.PlayerActivity;
import net.Indyuce.mmocore.api.player.PlayerData;
+import org.jetbrains.annotations.NotNull;
public class CastableSkill extends Skill {
private final ClassSkill skill;
private final int skillLevel;
public CastableSkill(ClassSkill skill, int skillLevel) {
+ super(skill.getSkill().getTrigger());
+
this.skill = skill;
this.skillLevel = skillLevel;
}
@@ -27,32 +31,33 @@ public class CastableSkill extends Skill {
@Override
public boolean getResult(SkillMetadata skillMeta) {
PlayerData playerData = PlayerData.get(skillMeta.getCaster().getData().getUniqueId());
+ boolean loud = !getTrigger().isSilent();
// If the caster has unlocked that skill
if (!playerData.hasSkillUnlocked(skill)) {
- MMOCore.plugin.configManager.getSimpleMessage("not-unlocked-skill").send(playerData.getPlayer());
+ if (loud) MMOCore.plugin.configManager.getSimpleMessage("not-unlocked-skill").send(playerData.getPlayer());
return false;
}
// Global cooldown check
- if (!skill.getSkill().isPassive() && playerData.getActivityTimeOut(PlayerActivity.CAST_SKILL) > 0)
+ if (!getTrigger().isPassive() && playerData.getActivityTimeOut(PlayerActivity.CAST_SKILL) > 0)
return false;
// Cooldown check
if (skillMeta.getCaster().getData().getCooldownMap().isOnCooldown(this)) {
- MMOCore.plugin.configManager.getSimpleMessage("casting.on-cooldown").send(playerData.getPlayer());
+ if (loud) 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());
+ if (loud) 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());
+ if (loud) MMOCore.plugin.configManager.getSimpleMessage("casting.no-stamina").send(playerData.getPlayer());
return false;
}
diff --git a/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java b/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java
index d4a70658..6234e544 100644
--- a/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java
+++ b/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java
@@ -114,8 +114,8 @@ public class ClassSkill implements CooldownObject {
}
public PassiveSkill toPassive(PlayerData caster) {
- Validate.isTrue(skill.hasTrigger(), "Skill is active");
- return new PassiveSkill("MMOCorePassiveSkill", skill.getTrigger(), toCastable(caster), EquipmentSlot.OTHER, ModifierSource.OTHER);
+ Validate.isTrue(skill.getTrigger().isPassive(), "Skill is active");
+ return new PassiveSkill("MMOCorePassiveSkill", toCastable(caster), EquipmentSlot.OTHER, ModifierSource.OTHER);
}
@Override
diff --git a/src/main/java/net/Indyuce/mmocore/skill/RegisteredSkill.java b/src/main/java/net/Indyuce/mmocore/skill/RegisteredSkill.java
index fc17ba66..8d0e48bc 100644
--- a/src/main/java/net/Indyuce/mmocore/skill/RegisteredSkill.java
+++ b/src/main/java/net/Indyuce/mmocore/skill/RegisteredSkill.java
@@ -1,5 +1,6 @@
package net.Indyuce.mmocore.skill;
+import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.skill.handler.SkillHandler;
import io.lumine.mythic.lib.skill.trigger.TriggerType;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
@@ -27,13 +28,13 @@ public class RegisteredSkill {
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;
+ triggerType = getHandler().isTriggerable() ? (config.contains("passive-type") ? TriggerType.valueOf(UtilityMethods.enumName(config.getString("passive-type"))) : TriggerType.CAST) : TriggerType.API;
for (String mod : handler.getModifiers())
defaultModifiers.put(mod, config.contains(mod) ? new LinearValue(config.getConfigurationSection(mod)) : LinearValue.ZERO);
@@ -67,35 +68,6 @@ public class RegisteredSkill {
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)
- *
- * 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
- *
- * 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");
diff --git a/src/main/java/net/Indyuce/mmocore/skill/custom/mechanic/ManaMechanic.java b/src/main/java/net/Indyuce/mmocore/skill/custom/mechanic/ManaMechanic.java
new file mode 100644
index 00000000..ebd6e8b6
--- /dev/null
+++ b/src/main/java/net/Indyuce/mmocore/skill/custom/mechanic/ManaMechanic.java
@@ -0,0 +1,33 @@
+package net.Indyuce.mmocore.skill.custom.mechanic;
+
+import io.lumine.mythic.lib.UtilityMethods;
+import io.lumine.mythic.lib.skill.SkillMetadata;
+import io.lumine.mythic.lib.skill.custom.mechanic.type.TargetMechanic;
+import io.lumine.mythic.lib.util.DoubleFormula;
+import io.lumine.mythic.lib.util.configobject.ConfigObject;
+import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import org.apache.commons.lang.Validate;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+
+public class ManaMechanic extends TargetMechanic {
+ private final DoubleFormula amount;
+ private final PlayerResourceUpdateEvent.UpdateReason reason;
+
+ public ManaMechanic(ConfigObject config) {
+ super(config);
+
+ config.validateKeys("amount");
+
+ amount = new DoubleFormula(config.getString("amount"));
+ reason = PlayerResourceUpdateEvent.UpdateReason.valueOf(UtilityMethods.enumName(config.getString("reason", "CUSTOM")));
+ }
+
+ @Override
+ public void cast(SkillMetadata meta, Entity target) {
+ Validate.isTrue(target instanceof Player, "Target is not a player");
+ PlayerData targetData = PlayerData.get(target.getUniqueId());
+ targetData.giveMana(amount.evaluate(meta), reason);
+ }
+}
diff --git a/src/main/java/net/Indyuce/mmocore/skill/custom/mechanic/StaminaMechanic.java b/src/main/java/net/Indyuce/mmocore/skill/custom/mechanic/StaminaMechanic.java
new file mode 100644
index 00000000..3d6e4bd8
--- /dev/null
+++ b/src/main/java/net/Indyuce/mmocore/skill/custom/mechanic/StaminaMechanic.java
@@ -0,0 +1,33 @@
+package net.Indyuce.mmocore.skill.custom.mechanic;
+
+import io.lumine.mythic.lib.UtilityMethods;
+import io.lumine.mythic.lib.skill.SkillMetadata;
+import io.lumine.mythic.lib.skill.custom.mechanic.type.TargetMechanic;
+import io.lumine.mythic.lib.util.DoubleFormula;
+import io.lumine.mythic.lib.util.configobject.ConfigObject;
+import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import org.apache.commons.lang.Validate;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+
+public class StaminaMechanic extends TargetMechanic {
+ private final DoubleFormula amount;
+ private final PlayerResourceUpdateEvent.UpdateReason reason;
+
+ public StaminaMechanic(ConfigObject config) {
+ super(config);
+
+ config.validateKeys("amount");
+
+ amount = new DoubleFormula(config.getString("amount"));
+ reason = PlayerResourceUpdateEvent.UpdateReason.valueOf(UtilityMethods.enumName(config.getString("reason", "CUSTOM")));
+ }
+
+ @Override
+ public void cast(SkillMetadata meta, Entity target) {
+ Validate.isTrue(target instanceof Player, "Target is not a player");
+ PlayerData targetData = PlayerData.get(target.getUniqueId());
+ targetData.giveStamina(amount.evaluate(meta), reason);
+ }
+}
diff --git a/src/main/java/net/Indyuce/mmocore/skill/custom/mechanic/StelliumMechanic.java b/src/main/java/net/Indyuce/mmocore/skill/custom/mechanic/StelliumMechanic.java
new file mode 100644
index 00000000..92ecb179
--- /dev/null
+++ b/src/main/java/net/Indyuce/mmocore/skill/custom/mechanic/StelliumMechanic.java
@@ -0,0 +1,33 @@
+package net.Indyuce.mmocore.skill.custom.mechanic;
+
+import io.lumine.mythic.lib.UtilityMethods;
+import io.lumine.mythic.lib.skill.SkillMetadata;
+import io.lumine.mythic.lib.skill.custom.mechanic.type.TargetMechanic;
+import io.lumine.mythic.lib.util.DoubleFormula;
+import io.lumine.mythic.lib.util.configobject.ConfigObject;
+import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
+import net.Indyuce.mmocore.api.player.PlayerData;
+import org.apache.commons.lang.Validate;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+
+public class StelliumMechanic extends TargetMechanic {
+ private final DoubleFormula amount;
+ private final PlayerResourceUpdateEvent.UpdateReason reason;
+
+ public StelliumMechanic(ConfigObject config) {
+ super(config);
+
+ config.validateKeys("amount");
+
+ amount = new DoubleFormula(config.getString("amount"));
+ reason = PlayerResourceUpdateEvent.UpdateReason.valueOf(UtilityMethods.enumName(config.getString("reason", "CUSTOM")));
+ }
+
+ @Override
+ public void cast(SkillMetadata meta, Entity target) {
+ Validate.isTrue(target instanceof Player, "Target is not a player");
+ PlayerData targetData = PlayerData.get(target.getUniqueId());
+ targetData.giveStellium(amount.evaluate(meta), reason);
+ }
+}