damageColor = new HashMap<>();
+
+ @NotNull public static final String SKMOD_DAMAGE_TYPE_DAMAGE = "\u00a7o■";
+ @NotNull public static final String SKMOD_DAMAGE_TYPE_BLACK = "\u00a7c!";
+ @NotNull public static final String SKMOD_DAMAGE_TYPE_AND = "\u00a77 ";
+ @NotNull public static final String SKMOD_DAMAGE_TYPE_COMMA = "\u00a77,";
+ @NotNull public static final String SKMOD_DAMAGE_TYPE_OR = "\u00a77/";
+
+ /**
+ * Usually the displayed name of the trigger is just... the name of the trigger.
+ *
+ * However, when using the Damage Type skill modifier, this can be misleading;
+ * for example, the {@link TriggerType#ATTACK} will no longer trigger with any attack.
+ *
+ * This method will rename it correctly; for example: WEAPON MAGIC = Magic Attack
+ *
+ * This only supports the trigger {@link TriggerType#ATTACK}
+ *
+ * @param trigger The trigger by which this skill fires
+ * @param attackType The encoded skill modifier value
+ *
+ * @return The way the trigger should display in lore.
+ */
+ @NotNull public String getTriggerDisplayName(@NotNull TriggerType trigger, double attackType) {
+
+ // Use the default?
+ String triggerDisplayName = MMOItems.plugin.getLanguage().getCastingModeName(trigger);
+
+ // If no skill modifiers are used, or the config option is disabled
+ if (attackType == 0 || !isAdvancedTriggerDisplay()) {
+ //APP//MythicCraftingManager.log("\u00a78ABT\u00a73 APP\u00a7c No advanced trigger display\u00a7e " + attackType);
+ return triggerDisplayName; }
+
+ // Currently, only ATTACK trigger is supported
+ if (!TriggerType.ATTACK.equals(trigger)) {
+ //APP//MythicCraftingManager.log("\u00a78ABT\u00a73 APP\u00a7c Not a supported trigger");
+ return triggerDisplayName; }
+
+ boolean named = false;
+ boolean orMode = false;
+ if (attackType < 0) { orMode = true; attackType *= -1; }
+ String separatorSymbol = (orMode ? SKMOD_DAMAGE_TYPE_OR : SKMOD_DAMAGE_TYPE_AND);
+
+ // Decode
+ ArrayList white = DamageType.getWhitelist(attackType);
+ ArrayList black = DamageType.getBlacklist(attackType);
+
+ // Currently, only ATTACK trigger is supported
+ if (white.isEmpty()) {
+ //APP//MythicCraftingManager.log("\u00a78ABT\u00a73 APP\u00a7c Empty whitelist, blacklist is not supported");
+ return triggerDisplayName; }
+
+ // Special names sector
+ if (TriggerType.ATTACK.equals(trigger)) {
+ //APP//MythicCraftingManager.log("\u00a78ABT\u00a73 APP\u00a77 Identified as the ATTACK trigger");
+
+ // Very specific overrides
+ if (white.size() == 1 && white.contains(DamageType.MINION)) {
+
+ // Minion Attack
+ triggerDisplayName = getDamageName(DamageType.MINION) + SKMOD_DAMAGE_TYPE_AND + getAttackName(AttackType.WEAPON);
+ named = true;
+
+ } else if (white.size() == 1 && white.contains(DamageType.DOT)) {
+
+ // Lingering Attack
+ triggerDisplayName = getDamageName(DamageType.DOT) + SKMOD_DAMAGE_TYPE_AND + getAttackName(AttackType.WEAPON);
+ named = true;
+
+ } else if (white.size() == 2 && white.contains(DamageType.MINION) && white.contains(DamageType.PROJECTILE)) {
+
+ // Minion Ranged Attack
+ triggerDisplayName = getDamageName(DamageType.MINION) + SKMOD_DAMAGE_TYPE_AND + getDamageName(DamageType.PROJECTILE) + SKMOD_DAMAGE_TYPE_AND + getAttackName(AttackType.WEAPON);
+ named = true;
+
+ } else if (white.size() == 2 && white.contains(DamageType.MINION) && white.contains(DamageType.MAGIC)) {
+
+ // Minion Magic Attack
+ triggerDisplayName = getDamageName(DamageType.MINION) + SKMOD_DAMAGE_TYPE_AND + getDamageName(DamageType.MAGIC) + SKMOD_DAMAGE_TYPE_AND + getAttackName(AttackType.WEAPON);
+ named = true;
+
+ } else {
+
+ // Skill, Attack, or generic damage
+ boolean isWeapon = white.contains(DamageType.WEAPON);
+ boolean isSkill = white.contains(DamageType.SKILL);
+ boolean both = isWeapon && isSkill;
+ boolean neither = !isWeapon && !isSkill;
+
+ // Elemental type
+ StringBuilder builder = new StringBuilder();
+ for (DamageType whitelisted : white) {
+
+ // Ignore weapon and skill
+ if (whitelisted == DamageType.WEAPON ||
+ whitelisted == DamageType.SKILL) {
+ continue; }
+
+ // Append separator
+ if (builder.length() > 1) { builder.append(separatorSymbol); }
+
+ // Append the type
+ builder
+ //.append(damageColors(whitelisted.getColor())) // Sawala doesn't think colours are gud
+ .append(getDamageName(whitelisted));
+ }
+
+ String latter;
+ String built = builder.toString();
+ String former = "";
+
+ // Requires any other damage type?
+ if (built.length() > 0) {
+ if (neither) { latter = SKMOD_DAMAGE_TYPE_AND + getAttackName(AttackType.NEITHER); }
+ else if (both) { latter = SKMOD_DAMAGE_TYPE_AND + getAttackName(AttackType.BOTH); }
+ else if (isWeapon) { latter = SKMOD_DAMAGE_TYPE_AND + getAttackName(AttackType.WEAPON); }
+ else { latter = SKMOD_DAMAGE_TYPE_AND + getAttackName(AttackType.SKILL); }
+
+ // Only characterized by weapon
+ } else {
+
+ if (neither) { latter = getAttackName(AttackType.NEITHER); }
+ else if (both) { latter = getAttackName(AttackType.BOTH); }
+ else if (isWeapon) { latter = getAttackName(AttackType.WEAPON); }
+ else { latter = getAttackName(AttackType.SKILL); }
+ }
+
+ //APP//MythicCraftingManager.log("\u00a78ABT\u00a73 APP\u00a77 Former:\u00a73 " + former);
+ //APP//MythicCraftingManager.log("\u00a78ABT\u00a73 APP\u00a77 Built:\u00a73 " + built);
+ //APP//MythicCraftingManager.log("\u00a78ABT\u00a73 APP\u00a77 Latter:\u00a73 " + latter);
+
+ named = true;
+ triggerDisplayName = former + built + latter;
+ }
+ }
+
+ // Just display the damage type restriction as squares
+ else if (TriggerType.KILL_ENTITY.equals(trigger)) {
+
+ // Elemental type
+ StringBuilder builder = new StringBuilder();
+ for (DamageType whitelisted : white) {
+
+ // Append separator
+ if (builder.length() > 1) { builder.append(separatorSymbol); }
+
+ // Append the type
+ builder
+ //.append(damageColors(whitelisted.getColor())) // Sawala doesn't think colours are gud
+ .append(getDamageName(whitelisted));
+ }
+
+ named = true;
+ triggerDisplayName = builder + SKMOD_DAMAGE_TYPE_AND + triggerDisplayName;
+ }
+
+ // No special name just default it
+ if (!named) {
+
+ // Append that
+ triggerDisplayName += " " + damageTypeRestrictionDisplay(separatorSymbol, white, black);
+ }
+
+ return triggerDisplayName;
+ }
+
+ /**
+ * @param damageTypeRestriction Number that encodes for the damage type restriction
+ *
+ * @return A nice chain of colored boxes (real) that represents this damage type restriction.
+ */
+ @NotNull String damageTypeRestrictionDisplay(double damageTypeRestriction) {
+
+ boolean orMode = false;
+ if (damageTypeRestriction < 0) { orMode = true; damageTypeRestriction *= -1; }
+ String separatorSymbol = (orMode ? SKMOD_DAMAGE_TYPE_OR : SKMOD_DAMAGE_TYPE_AND);
+
+ // Decode
+ ArrayList white = DamageType.getWhitelist(damageTypeRestriction);
+ ArrayList black = DamageType.getBlacklist(damageTypeRestriction);
+
+ // Just build the string man
+ return damageTypeRestrictionDisplay(separatorSymbol, white, black);
+ }
+
+ /**
+ *
+ * @param separatorSymbol Separator symbol to use between whitelisted damage types
+ * @param white Damage types whitelisted
+ * @param black Damage types blacklisted
+ *
+ * @return A nice chain of colored boxes (real) that represents this damage type restriction.
+ */
+ @NotNull String damageTypeRestrictionDisplay(@NotNull String separatorSymbol, @NotNull ArrayList white, @NotNull ArrayList black) {
+
+ StringBuilder append = new StringBuilder();
+ for (DamageType w : white) {
+
+ // Append separator
+ if (append.length() > 1) { append.append(separatorSymbol); }
+
+ // Append damage
+ append.append(damageColors(w.getColor())).append(SKMOD_DAMAGE_TYPE_DAMAGE);
+ }
+
+ // Separator for blacklist
+ if (append.length() > 1 && black.size() > 0) { append.append(SKMOD_DAMAGE_TYPE_COMMA); }
+
+ for (DamageType b : black) {
+
+ // Append separator
+ if (append.length() > 1) { append.append(SKMOD_DAMAGE_TYPE_AND); }
+
+ // Append damage
+ append.append(SKMOD_DAMAGE_TYPE_BLACK).append(damageColors(b.getColor())).append(SKMOD_DAMAGE_TYPE_DAMAGE);
+ }
+
+ return append.toString();
+ }
+
+ /**
+ * @param in The colored string in the default format
+ *
+ * @return Color overridden by user-specified counterpart.
+ */
+ @NotNull public String damageColors(@Nullable String in) {
+ //SDC//MythicCraftingManager.log("\u00a78ABT\u00a7c SDC\u00a77 Recoloring\u00a7b " + in);
+ if (in == null) { return ""; }
+ if (!isAdvancedRecoloring()) { return in; }
+
+ /*
+ * Sawala's agony color replacements
+ *
+ * Because I literally had everything consistent in &8 &a &9 and he was like &4 &2 ;
+ * what on earth even is ffs for magic damage some ugly ass deep blue (I sleep)
+ */
+ for (DamageType ty : damageColor.keySet()) {
+
+ //SDC//MythicCraftingManager.log("\u00a78ABT\u00a7c SDC\u00a7e +\u00a77 Damage Type\u00a7b " + ty.toString());
+ //SDC//MythicCraftingManager.log("\u00a78ABT\u00a7c SDC\u00a7e +\u00a77 Default Col\u00a7b " + ty.getColor() + "O");
+ //SDC//MythicCraftingManager.log("\u00a78ABT\u00a7c SDC\u00a7e +\u00a77 Override Cl\u00a7b " + getDamageColor(ty) + "O");
+
+ // Both & and §
+ in = in.replace(ty.getColor().replace('\u00a7', '&'), getDamageColor(ty));
+ in = in.replace(ty.getColor(), getDamageColor(ty));
+ }
+ //SDC//MythicCraftingManager.log("\u00a78ABT\u00a7c SDC\u00a77 Result\u00a7b " + in);
+
+ // he he ha ha
+ return in;
+ }
+}
+
+/**
+ * A way to classify and translate the result of an {@link io.lumine.mythic.lib.damage.AttackMetadata},
+ */
+enum AttackType {
+
+ /**
+ * Dealing damage with weapons (real), Attacks.
+ */
+ WEAPON,
+
+ /**
+ * Dealing damage with abilities, Ability Hits.
+ */
+ SKILL,
+
+ /**
+ * No information on skill or weapon damage,
+ * treated as just generic Damage.
+ */
+ NEITHER,
+
+ /**
+ * Both skill and weapon damage types are present,
+ * this would make sense if the lore of the ability
+ * implies that your weapon is being used in the attack.
+ *
+ * Compare simply casting a fireball, vs simply hitting
+ * with a baton, vs coating the baton with magic fire and
+ * then attacking with it.
+ * The last case would be an 'Ability-Assisted Attack'
+ */
+ BOTH
+}
\ No newline at end of file
diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/gui/edition/AbilityEdition.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/gui/edition/AbilityEdition.java
index bd5f1e1e..a0deeffb 100644
--- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/gui/edition/AbilityEdition.java
+++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/gui/edition/AbilityEdition.java
@@ -1,5 +1,7 @@
package net.Indyuce.mmoitems.gui.edition;
+import io.lumine.mythic.lib.damage.DamageType;
+import io.lumine.mythic.lib.skill.handler.SkillHandler;
import io.lumine.mythic.lib.skill.trigger.TriggerType;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.MMOItems;
@@ -22,6 +24,8 @@ import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.text.DecimalFormat;
import java.util.ArrayList;
@@ -64,16 +68,14 @@ public class AbilityEdition extends EditionInventory {
abilityItemMeta.setLore(abilityItemLore);
abilityItem.setItemMeta(abilityItemMeta);
+ TriggerType castMode = null;
if (ability != null) {
String castModeConfigString = getEditedSection().getString("ability." + configKey + ".mode");
String castModeFormat = castModeConfigString == null ? ""
: castModeConfigString.toUpperCase().replace(" ", "_").replace("-", "_").replaceAll("[^A-Z0-9_]", "");
- TriggerType castMode;
try {
castMode = TriggerType.valueOf(castModeFormat);
- } catch (RuntimeException exception) {
- castMode = null;
- }
+ } catch (RuntimeException ignored) { }
ItemStack castModeItem = new ItemStack(Material.ARMOR_STAND);
ItemMeta castModeItemMeta = castModeItem.getItemMeta();
@@ -96,6 +98,8 @@ public class AbilityEdition extends EditionInventory {
if (ability != null) {
ConfigurationSection section = getEditedSection().getConfigurationSection("ability." + configKey);
for (String modifier : ability.getHandler().getModifiers()) {
+ if (!sensibleModifier(modifier, castMode)) { continue; }
+
ItemStack modifierItem = VersionMaterial.GRAY_DYE.toItem();
ItemMeta modifierItemMeta = modifierItem.getItemMeta();
modifierItemMeta.setDisplayName(ChatColor.GREEN + MMOUtils.caseOnWords(modifier.toLowerCase().replace("-", " ")));
@@ -105,9 +109,32 @@ public class AbilityEdition extends EditionInventory {
modifierItemLore.add("");
try {
+
+ // Current Value Yeah
+ NumericStatFormula heuh = new NumericStatFormula(section.get(modifier));
+ String currentValue = heuh.toString();
+ if (SkillHandler.SKMOD_DAMAGE_TYPE.equals(modifier)) {
+ double dam = heuh.getBase();
+ boolean orMode = dam < 0;
+ if (orMode) { dam *= -1; }
+
+ // Parse display
+ ArrayList whitelist = DamageType.getWhitelist(dam);
+ ArrayList blacklist = DamageType.getBlacklist(dam);
+
+ // I guess append
+ StringBuilder builder = new StringBuilder(orMode ? "OR" : "");
+ for (DamageType white : whitelist) { if (builder.length() > 0) { builder.append(" "); } builder.append(white); }
+ for (DamageType black : blacklist) { if (builder.length() > 0) { builder.append(" "); } builder.append("!").append(black); }
+
+ // Build Input
+ currentValue = builder.toString() + " \u00a78(\u00a79" + heuh.toString() + "\u00a78)";
+ }
+
modifierItemLore.add(ChatColor.GRAY + "Current Value: " + ChatColor.GOLD
- + (section.contains(modifier) ? new NumericStatFormula(section.get(modifier)).toString()
+ + (section.contains(modifier) ? currentValue
: MODIFIER_FORMAT.format(ability.getDefaultModifier(modifier))));
+
} catch (IllegalArgumentException exception) {
modifierItemLore.add(ChatColor.GRAY + "Could not read value. Using default");
}
@@ -146,6 +173,29 @@ public class AbilityEdition extends EditionInventory {
return inv;
}
+ /**
+ * Some modifiers, like Timer or Damage Type Restriction,
+ * only make sense if used in the triggers where they are
+ * supported.
+ *
+ * @param modifier Modifier in question
+ * @param trigger Trigger in question
+ *
+ * @return If this modifier makes sense for this trigger
+ */
+ boolean sensibleModifier(@NotNull String modifier, @Nullable TriggerType trigger) {
+
+ // Missing cast mode might as well show all modifiers
+ if (trigger == null) { return true; }
+
+ // These modifiers only work with the specific trigger
+ if (modifier.equals(SkillHandler.SKMOD_DAMAGE_TYPE)) { return trigger.equals(TriggerType.ATTACK); }
+ if (modifier.equals(SkillHandler.SKMOD_TIMER)) { return trigger.equals(TriggerType.TIMER); }
+
+ // Modifier is compatible with any trigger by default
+ return true;
+ }
+
@Override
public void whenClicked(InventoryClickEvent event) {
ItemStack item = event.getCurrentItem();
diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/ConfigManager.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/ConfigManager.java
index 9cf6b78c..83e78b40 100644
--- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/ConfigManager.java
+++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/ConfigManager.java
@@ -7,6 +7,7 @@ import net.Indyuce.mmoitems.api.ConfigFile;
import net.Indyuce.mmoitems.api.ReforgeOptions;
import net.Indyuce.mmoitems.api.item.util.ConfigItem;
import net.Indyuce.mmoitems.api.item.util.ConfigItems;
+import net.Indyuce.mmoitems.api.util.DamageTypeRestrictionSettings;
import net.Indyuce.mmoitems.api.util.NumericStatFormula;
import net.Indyuce.mmoitems.api.util.message.Message;
import net.Indyuce.mmoitems.stat.GemUpgradeScaling;
@@ -36,6 +37,7 @@ public class ConfigManager implements Reloadable {
// cached config files
private ConfigFile loreFormat, stats, dynLore;
+ private FileConfiguration abilities;
// Language
private final Map triggerTypeNames = new HashMap<>();
@@ -48,6 +50,8 @@ public class ConfigManager implements Reloadable {
public NumericStatFormula defaultItemCapacity;
public ReforgeOptions revisionOptions, gemRevisionOptions, phatLootsOptions;
public final List opStats = new ArrayList<>();
+ public boolean abilitiesBypassEncumbering, disableOffhandAbilities;
+ public DamageTypeRestrictionSettings damageTypeRestrictionSettings;
public ConfigManager() {
mkdir("layouts");
@@ -144,7 +148,7 @@ public class ConfigManager implements Reloadable {
// Trigger types
triggerTypeNames.clear();
- final FileConfiguration abilities = new ConfigFile("/language", "abilities").getConfig();
+ abilities = new ConfigFile("/language", "abilities").getConfig();
for (TriggerType type : TriggerType.values())
triggerTypeNames.put(type, abilities.getString("cast-mode." + type.getLowerCaseId(), type.getName()));
}
@@ -155,6 +159,7 @@ public class ConfigManager implements Reloadable {
loreFormat = new ConfigFile("/language", "lore-format");
stats = new ConfigFile("/language", "stats");
dynLore = new ConfigFile("/language", "dynamic-lore");
+ abilities = new ConfigFile("/language", "abilities").getConfig();
loadTranslations();
@@ -173,6 +178,8 @@ public class ConfigManager implements Reloadable {
keepSoulboundOnDeath = MMOItems.plugin.getConfig().getBoolean("soulbound.keep-on-death");
rerollOnItemUpdate = MMOItems.plugin.getConfig().getBoolean("item-revision.reroll-when-updated");
levelSpread = MMOItems.plugin.getConfig().getDouble("item-level-spread");
+ abilitiesBypassEncumbering = MMOItems.plugin.getConfig().getBoolean("abilities-bypass-encumbering", !MMOItems.plugin.getConfig().getBoolean("two-handed-item-restriction", true));
+ disableOffhandAbilities = MMOItems.plugin.getConfig().getBoolean("disable-abilities-in-offhand", false);
opStatsEnabled = MMOItems.plugin.getConfig().getBoolean("op-item-stats.enabled");
opStats.clear();
@@ -187,6 +194,8 @@ public class ConfigManager implements Reloadable {
gemRevisionOptions = gemKeepData != null ? new ReforgeOptions(gemKeepData) : new ReforgeOptions(false, false, false, false, false, false, false, true);
phatLootsOptions = phatLoots != null ? new ReforgeOptions(phatLoots) : new ReforgeOptions(false, false, false, false, false, false, false, true);
+ damageTypeRestrictionSettings = new DamageTypeRestrictionSettings(abilities.getConfigurationSection("damage-type-restriction"));
+
List exemptedPhatLoots = MMOItems.plugin.getConfig().getStringList("item-revision.disable-phat-loot");
for (String epl : exemptedPhatLoots)
phatLootsOptions.addToBlacklist(epl);
diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/stat/Abilities.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/stat/Abilities.java
index 63a9a223..64e78981 100644
--- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/stat/Abilities.java
+++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/stat/Abilities.java
@@ -5,8 +5,15 @@ import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.SupportedNBTTagValues;
import io.lumine.mythic.lib.api.util.AltChar;
+import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackCategory;
+import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackProvider;
+import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
+import io.lumine.mythic.lib.damage.DamageType;
+import io.lumine.mythic.lib.skill.handler.SkillHandler;
import io.lumine.mythic.lib.skill.trigger.TriggerType;
import net.Indyuce.mmoitems.MMOItems;
+import net.Indyuce.mmoitems.api.util.DamageTypeRestrictionSettings;
+import net.Indyuce.mmoitems.api.util.message.FFPMMOItems;
import net.Indyuce.mmoitems.util.MMOUtils;
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
import net.Indyuce.mmoitems.api.item.mmoitem.ReadMMOItem;
@@ -56,16 +63,24 @@ public class Abilities extends ItemStat
//Modify Lore
List abilityLore = new ArrayList<>();
boolean splitter = !MMOItems.plugin.getLanguage().abilitySplitter.equals("");
+ DamageTypeRestrictionSettings settings = MMOItems.plugin.getLanguage().damageTypeRestrictionSettings;
String modifierFormat = ItemStat.translate("ability-modifier"), abilityFormat = ItemStat.translate("ability-format");
data.getAbilities().forEach(ability -> {
- abilityLore.add(abilityFormat.replace("{trigger}", MMOItems.plugin.getLanguage().getCastingModeName(ability.getTrigger())).replace("{ability}", ability.getAbility().getName()));
+
+ // Replace name of trigger, as well as name of ability
+ String triggerDisplayName = settings.getTriggerDisplayName(ability.getTrigger(), ability.getModifier(SkillHandler.SKMOD_DAMAGE_TYPE));
+ abilityLore.add(abilityFormat.replace("{trigger}", triggerDisplayName).replace("{ability}", ability.getAbility().getName()));
for (String modifier : ability.getModifiers()) {
+
+ // Damage Type Modifier does not display in lore
+ if (modifier.equals(SkillHandler.SKMOD_DAMAGE_TYPE)) { continue; }
+
item.getLore().registerPlaceholder("ability_" + ability.getAbility().getHandler().getId().toLowerCase() + "_" + modifier,
MythicLib.plugin.getMMOConfig().decimal.format(ability.getModifier(modifier)));
- abilityLore.add(modifierFormat.replace("{modifier}", ability.getAbility().getModifierName(modifier)).replace("{value}",
+ abilityLore.add(modifierFormat.replace("{modifier}", settings.damageColors(ability.getAbility().getModifierName(modifier))).replace("{value}",
MythicLib.plugin.getMMOConfig().decimal.format(ability.getModifier(modifier))));
}
@@ -133,8 +148,65 @@ public class Abilities extends ItemStat
+ ChatColor.GRAY + ".");
return;
}
+ String number = message;
- new NumericStatFormula(message).fillConfigurationSection(inv.getEditedSection(), "ability." + configKey + "." + edited,
+ // If we are editing the damage types and the provided value is not a number already
+ if (SkillHandler.SKMOD_DAMAGE_TYPE.equals(edited) && !SilentNumbers.IntTryParse(number)) {
+
+ // Might come in handy....
+ FriendlyFeedbackProvider ffp = new FriendlyFeedbackProvider(FFPMMOItems.get());
+ ffp.activatePrefix(true, "Edition");
+ boolean failure = false;
+
+ // Or Mode
+ boolean orMode = message.startsWith("OR ");
+ if (orMode) { message = message.substring("OR ".length()); }
+
+ // Build arrays
+ ArrayList whitelisted = new ArrayList<>();
+ ArrayList blacklisted = new ArrayList<>();
+
+ // Split by spaces
+ String[] typesSplit = message.split(" ");
+ for (String ty : typesSplit) {
+
+ // Crop blacklist
+ boolean blacklist = false;
+ String observed = ty.toUpperCase().replace("-", "_").replace(" ", "_");
+ if (observed.startsWith("!")) { observed = observed.substring(1); blacklist = true; }
+
+ // Identify Damage Type
+ try {
+
+ // Un-parse
+ DamageType damageType = DamageType.valueOf(observed);
+
+ // Add to the lists
+ if (blacklist) { blacklisted.add(damageType); } else { whitelisted.add(damageType); }
+
+ // Mention
+ } catch (IllegalArgumentException ignored) {
+
+ // no
+ failure = true;
+
+ ffp.log(FriendlyFeedbackCategory.ERROR, "Unknown damage type '$r{0}$b' in '$u{1}$b'. ", observed, ty);
+ }
+ }
+
+ // Cancel
+ if (failure) {
+
+ // Errors
+ ffp.sendAllTo(inv.getPlayer());
+ throw new IllegalArgumentException("$bInvalid input! Please specify damage types to require or blacklist, for example: '$eMAGIC WEAPON !SKILL$b' or '$eOR PHYSICAL PROJECTILE MINION !MAGIC$b'. ");
+ }
+
+ // Bake number
+ number = String.valueOf(DamageType.encodeDamageTypeMatch(whitelisted, blacklisted, orMode));
+ }
+
+ new NumericStatFormula(number).fillConfigurationSection(inv.getEditedSection(), "ability." + configKey + "." + edited,
FormulaSaveOption.NONE);
inv.registerTemplateEdition();
inv.getPlayer().sendMessage(MMOItems.plugin.getPrefix() + ChatColor.GOLD + MMOUtils.caseOnWords(edited.replace("-", " ")) + ChatColor.GRAY
diff --git a/MMOItems-Dist/src/main/resources/default/language/abilities.yml b/MMOItems-Dist/src/main/resources/default/language/abilities.yml
index ef8efc9b..14a98aa1 100644
--- a/MMOItems-Dist/src/main/resources/default/language/abilities.yml
+++ b/MMOItems-Dist/src/main/resources/default/language/abilities.yml
@@ -21,3 +21,42 @@ cast-mode:
trident-hit: Trident Hit
damaged-by-entity: Damaged By Entity
shift-right-click: Shift Right Click
+
+# For the On Attack trigger there exists the
+# Modifier 'Damage Type Restriction' that supports
+# advanced translation logic
+damage-type-restrictions:
+
+ ## -----
+ ## Translate the damage types
+ damage-type-translations:
+ MAGIC: "Magic"
+ PHYSICAL: "Melee"
+ PROJECTILE: "Ranged"
+ WEAPON: "Weapon"
+ SKILL: "Skill"
+ UNARMED: "Unarmed"
+ ON_HIT: "Reaction"
+ MINION: "Minion"
+ DOT: "Lingering"
+
+ ## -----
+ # Translate the types of attack
+ attack-type-translations:
+ WEAPON: "Attack"
+ SKILL: "Ability Hit"
+ NEITHER: "Damage"
+ BOTH: "Ability-Assisted Attack"
+
+ ## -----
+ ## Change the color of scalings
+ # damage-type-colors:
+ # MAGIC: "&9"
+ # PHYSICAL: "&8"
+ # WEAPON: "&7"
+ # SKILL: "&f"
+ # PROJECTILE: "&a"
+ # UNARMED: "&e"
+ # ON_HIT: "&0"
+ # MINION: "&d"
+ # DOT: "&3"
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 326ada34..93242623 100644
--- a/pom.xml
+++ b/pom.xml
@@ -57,7 +57,7 @@
io.lumine
MythicLib-dist
- 1.5.1-SNAPSHOT
+ 1.5.2-SNAPSHOT
provided