diff --git a/pom.xml b/pom.xml index 0677a122..9a2e4a3e 100644 --- a/pom.xml +++ b/pom.xml @@ -140,7 +140,7 @@ io.lumine MythicLib-dist - 1.3-R21-SNAPSHOT + 1.3-R27-SNAPSHOT provided @@ -208,6 +208,13 @@ provided + + org.denizen + Dungeons + 1.0 + provided + + com.massivecraft @@ -230,6 +237,13 @@ provided + + org.kingdoms.main + Kingdoms + 1.11.15.0.0.0.1.1 + provided + + diff --git a/src/main/java/net/Indyuce/mmocore/MMOCore.java b/src/main/java/net/Indyuce/mmocore/MMOCore.java index 2a86dc55..78409150 100644 --- a/src/main/java/net/Indyuce/mmocore/MMOCore.java +++ b/src/main/java/net/Indyuce/mmocore/MMOCore.java @@ -101,7 +101,7 @@ public class MMOCore extends LuminePlugin { public boolean shouldDebugSQL = false; - private static final int MYTHICLIB_COMPATIBILITY_INDEX = 4; + private static final int MYTHICLIB_COMPATIBILITY_INDEX = 7; public MMOCore() { plugin = this; @@ -276,6 +276,7 @@ public class MMOCore extends LuminePlugin { Bukkit.getPluginManager().registerEvents(new FishingListener(), this); Bukkit.getPluginManager().registerEvents(new PlayerCollectStats(), this); Bukkit.getPluginManager().registerEvents(new PlayerPressKeyListener(), this); + Bukkit.getPluginManager().registerEvents(new ClassTriggers(), this); /* * Initialize player data from all online players. This is very important to do diff --git a/src/main/java/net/Indyuce/mmocore/api/MMOCoreAPI.java b/src/main/java/net/Indyuce/mmocore/api/MMOCoreAPI.java index 03fdfa92..a5a65a3c 100644 --- a/src/main/java/net/Indyuce/mmocore/api/MMOCoreAPI.java +++ b/src/main/java/net/Indyuce/mmocore/api/MMOCoreAPI.java @@ -7,6 +7,7 @@ import io.lumine.mythic.lib.skill.Skill; import io.lumine.mythic.lib.skill.handler.SkillHandler; import io.lumine.mythic.lib.skill.result.SkillResult; import io.lumine.mythic.lib.skill.trigger.TriggerMetadata; +import io.lumine.mythic.lib.skill.trigger.TriggerType; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.party.AbstractParty; @@ -110,7 +111,7 @@ public class MMOCoreAPI { PlayerMetadata casterMeta = playerData.getMMOPlayerData().getStatMap().cache(EquipmentSlot.MAIN_HAND); TriggerMetadata triggerMeta = new TriggerMetadata(casterMeta, null, null); RegisteredSkill registered = MMOCore.plugin.skillManager.getSkill(skill.getId()); - Skill cast = registered == null ? new SimpleSkill(skill) : new CastableSkill(new ClassSkill(registered, 0), level); + Skill cast = registered == null ? new SimpleSkill(TriggerType.CAST, skill) : new CastableSkill(new ClassSkill(registered, 0), level); return cast.cast(triggerMeta); } } diff --git a/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index 8f9a5f78..5742b8e4 100644 --- a/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -245,7 +245,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc @Override public int getClaims(ExperienceObject object, ExperienceTable table, ExperienceItem item) { String key = object.getKey() + "." + table.getId() + "." + item.getId(); - return tableItemClaims.get(key); + return tableItemClaims.getOrDefault(key, 0); } @Override diff --git a/src/main/java/net/Indyuce/mmocore/api/player/attribute/AttributeModifier.java b/src/main/java/net/Indyuce/mmocore/api/player/attribute/AttributeModifier.java index 4c87bf9a..108d3ebb 100644 --- a/src/main/java/net/Indyuce/mmocore/api/player/attribute/AttributeModifier.java +++ b/src/main/java/net/Indyuce/mmocore/api/player/attribute/AttributeModifier.java @@ -66,8 +66,8 @@ public class AttributeModifier extends PlayerModifier { Validate.notNull(str, "String cannot be null"); Validate.notEmpty(str, "String cannot be empty"); - type = str.toCharArray()[str.length() - 1] == '%' ? io.lumine.mythic.lib.player.modifier.ModifierType.RELATIVE : io.lumine.mythic.lib.player.modifier.ModifierType.FLAT; - value = Double.parseDouble(type == io.lumine.mythic.lib.player.modifier.ModifierType.RELATIVE ? str.substring(0, str.length() - 1) : str); + type = str.toCharArray()[str.length() - 1] == '%' ? ModifierType.RELATIVE : ModifierType.FLAT; + value = Double.parseDouble(type == ModifierType.RELATIVE ? str.substring(0, str.length() - 1) : str); this.attribute = attribute; } @@ -76,7 +76,7 @@ public class AttributeModifier extends PlayerModifier { this.attribute = object.getString("attribute"); this.value = object.getDouble("value"); - type = object.getBoolean("multiplicative", false) ? io.lumine.mythic.lib.player.modifier.ModifierType.RELATIVE : io.lumine.mythic.lib.player.modifier.ModifierType.FLAT; + type = object.getBoolean("multiplicative", false) ? ModifierType.RELATIVE : ModifierType.FLAT; } public String getAttribute() { diff --git a/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java b/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java index a7ca96e8..633f8f9d 100644 --- a/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java +++ b/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java @@ -7,6 +7,7 @@ import io.lumine.mythic.lib.api.MMOLineConfig; import io.lumine.mythic.lib.api.util.PostLoadObject; import io.lumine.mythic.lib.version.VersionMaterial; import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.player.profess.event.EventTrigger; import net.Indyuce.mmocore.api.player.profess.resource.ManaDisplayOptions; import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource; import net.Indyuce.mmocore.api.player.profess.resource.ResourceRegeneration; @@ -20,6 +21,8 @@ import net.Indyuce.mmocore.experience.droptable.ExperienceTable; import net.Indyuce.mmocore.experience.provider.ExperienceDispenser; import net.Indyuce.mmocore.experience.provider.MainExperienceDispenser; import net.Indyuce.mmocore.experience.source.type.ExperienceSource; +import net.Indyuce.mmocore.player.playerclass.ClassTrigger; +import net.Indyuce.mmocore.player.playerclass.ClassTriggerType; import net.Indyuce.mmocore.skill.ClassSkill; import net.Indyuce.mmocore.skill.RegisteredSkill; import net.md_5.bungee.api.ChatColor; @@ -31,8 +34,8 @@ import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.lang.reflect.Field; import java.util.*; import java.util.logging.Level; @@ -50,9 +53,12 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject { private final Map stats = new HashMap<>(); private final Map skills = new LinkedHashMap<>(); private final List subclasses = new ArrayList<>(); - + private final Map classTriggers = new HashMap<>(); private final Map resourceHandlers = new HashMap<>(); + @Deprecated + private final Map eventTriggers = new HashMap<>(); + private final CastingParticle castParticle; public PlayerClass(String id, FileConfiguration config) { @@ -101,6 +107,16 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject { } this.expTable = expTable; + if (config.contains("triggers")) + for (String key : config.getConfigurationSection("triggers").getKeys(false)) { + try { + String format = key.toLowerCase().replace("_", "-").replace(" ", "-"); + eventTriggers.put(format, new EventTrigger(format, config.getStringList("triggers." + key))); + } catch (IllegalArgumentException exception) { + MMOCore.log(Level.WARNING, "Could not load trigger '" + key + "' from class '" + id + "':" + exception.getMessage()); + } + } + if (config.contains("attributes")) for (String key : config.getConfigurationSection("attributes").getKeys(false)) try { @@ -279,6 +295,26 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject { return options.containsKey(option) ? options.get(option) : option.getDefault(); } + @Nullable + public ClassTrigger getClassTrigger(ClassTriggerType type) { + return classTriggers.get(type); + } + + @Deprecated + public Set getEventTriggers() { + return eventTriggers.keySet(); + } + + @Deprecated + public boolean hasEventTriggers(String name) { + return eventTriggers.containsKey(name); + } + + @Deprecated + public EventTrigger getEventTriggers(String name) { + return eventTriggers.get(name); + } + @Deprecated public void setStat(StatType type, double base, double perLevel) { setStat(type, new LinearValue(base, perLevel)); diff --git a/src/main/java/net/Indyuce/mmocore/api/player/profess/event/EventTrigger.java b/src/main/java/net/Indyuce/mmocore/api/player/profess/event/EventTrigger.java new file mode 100644 index 00000000..17923fbd --- /dev/null +++ b/src/main/java/net/Indyuce/mmocore/api/player/profess/event/EventTrigger.java @@ -0,0 +1,43 @@ +package net.Indyuce.mmocore.api.player.profess.event; + +import io.lumine.mythic.lib.api.MMOLineConfig; +import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.api.quest.trigger.Trigger; +import net.Indyuce.mmocore.experience.droptable.ExperienceTable; +import org.apache.commons.lang.Validate; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; + +/** + * @deprecated Should have NEVER been implemented that way + */ +@Deprecated +public class EventTrigger { + private final String event; + private final Set triggers = new LinkedHashSet<>(); + + public EventTrigger(String event, List list) { + Validate.notNull(list, "Could not load trigger list"); + + this.event = event; + + for (String format : list) + try { + triggers.add(MMOCore.plugin.loadManager.loadTrigger(new MMOLineConfig(format))); + } catch (IllegalArgumentException exception) { + MMOCore.plugin.getLogger().log(Level.WARNING, + "Could not load trigger '" + format + "' from event trigger '" + event + "': " + exception.getMessage()); + } + } + + public String getEvent() { + return event; + } + + public Set 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); + } +}