Fixed modifier application

This commit is contained in:
Indyuce 2022-08-18 15:51:40 +02:00
parent dbd1936609
commit b89734a211
7 changed files with 72 additions and 99 deletions

View File

@ -2,7 +2,7 @@ package net.Indyuce.mmoitems.api;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.api.player.EquipmentSlot;
import io.lumine.mythic.lib.player.modifier.ModifierSource;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.item.util.identify.UnidentifiedItem;
import net.Indyuce.mmoitems.manager.TypeManager;
@ -22,46 +22,45 @@ import java.util.Objects;
public class Type {
// Slashing
public static final Type SWORD = new Type(TypeSet.SLASHING, "SWORD", true, EquipmentSlot.MAIN_HAND);
public static final Type SWORD = new Type(TypeSet.SLASHING, "SWORD", true, ModifierSource.MELEE_WEAPON);
// Piercing
public static final Type DAGGER = new Type(TypeSet.PIERCING, "DAGGER", true, EquipmentSlot.MAIN_HAND);
public static final Type SPEAR = new Type(TypeSet.PIERCING, "SPEAR", true, EquipmentSlot.MAIN_HAND);
public static final Type DAGGER = new Type(TypeSet.PIERCING, "DAGGER", true, ModifierSource.MELEE_WEAPON);
public static final Type SPEAR = new Type(TypeSet.PIERCING, "SPEAR", true, ModifierSource.MELEE_WEAPON);
// Blunt
public static final Type HAMMER = new Type(TypeSet.BLUNT, "HAMMER", true, EquipmentSlot.MAIN_HAND);
public static final Type GAUNTLET = new Type(TypeSet.BLUNT, "GAUNTLET", true, EquipmentSlot.MAIN_HAND);
public static final Type HAMMER = new Type(TypeSet.BLUNT, "HAMMER", true, ModifierSource.MELEE_WEAPON);
public static final Type GAUNTLET = new Type(TypeSet.BLUNT, "GAUNTLET", true, ModifierSource.MELEE_WEAPON);
// Range
public static final Type WHIP = new Type(TypeSet.RANGE, "WHIP", true, EquipmentSlot.MAIN_HAND);
public static final Type STAFF = new Type(TypeSet.RANGE, "STAFF", true, EquipmentSlot.MAIN_HAND);
public static final Type BOW = new Type(TypeSet.RANGE, "BOW", true, EquipmentSlot.MAIN_HAND);
public static final Type CROSSBOW = new Type(TypeSet.RANGE, "CROSSBOW", false, EquipmentSlot.MAIN_HAND);
public static final Type MUSKET = new Type(TypeSet.RANGE, "MUSKET", true, EquipmentSlot.MAIN_HAND);
public static final Type LUTE = new Type(TypeSet.RANGE, "LUTE", true, EquipmentSlot.MAIN_HAND);
public static final Type WHIP = new Type(TypeSet.RANGE, "WHIP", true, ModifierSource.RANGED_WEAPON);
public static final Type STAFF = new Type(TypeSet.RANGE, "STAFF", true, ModifierSource.RANGED_WEAPON);
public static final Type BOW = new Type(TypeSet.RANGE, "BOW", true, ModifierSource.RANGED_WEAPON);
public static final Type CROSSBOW = new Type(TypeSet.RANGE, "CROSSBOW", false, ModifierSource.RANGED_WEAPON);
public static final Type MUSKET = new Type(TypeSet.RANGE, "MUSKET", true, ModifierSource.RANGED_WEAPON);
public static final Type LUTE = new Type(TypeSet.RANGE, "LUTE", true, ModifierSource.RANGED_WEAPON);
// Hand Accessories
public static final Type CATALYST = new Type(TypeSet.OFFHAND, "CATALYST", false, EquipmentSlot.MAIN_HAND);
public static final Type OFF_CATALYST = new Type(TypeSet.OFFHAND, "OFF_CATALYST", false, EquipmentSlot.OFF_HAND);
public static final Type MAIN_CATALYST = new Type(TypeSet.OFFHAND, "MAIN_CATALYST", false, EquipmentSlot.MAIN_HAND);
public static final Type CATALYST = new Type(TypeSet.EXTRA, "CATALYST", false, ModifierSource.HAND_ITEM);
public static final Type OFF_CATALYST = new Type(TypeSet.EXTRA, "OFF_CATALYST", false, ModifierSource.OFFHAND_ITEM);
public static final Type MAIN_CATALYST = new Type(TypeSet.EXTRA, "MAIN_CATALYST", false, ModifierSource.MAINHAND_ITEM);
// Any
public static final Type ORNAMENT = new Type(TypeSet.EXTRA, "ORNAMENT", false, EquipmentSlot.OTHER);
public static final Type ORNAMENT = new Type(TypeSet.EXTRA, "ORNAMENT", false, ModifierSource.OTHER);
// Extra
public static final Type ARMOR = new Type(TypeSet.EXTRA, "ARMOR", false, EquipmentSlot.ARMOR);
public static final Type TOOL = new Type(TypeSet.EXTRA, "TOOL", false, EquipmentSlot.MAIN_HAND);
public static final Type CONSUMABLE = new Type(TypeSet.EXTRA, "CONSUMABLE", false, EquipmentSlot.MAIN_HAND);
public static final Type MISCELLANEOUS = new Type(TypeSet.EXTRA, "MISCELLANEOUS", false, EquipmentSlot.MAIN_HAND);
public static final Type GEM_STONE = new Type(TypeSet.EXTRA, "GEM_STONE", false, null);
public static final Type SKIN = new Type(TypeSet.EXTRA, "SKIN", false, null);
public static final Type ACCESSORY = new Type(TypeSet.EXTRA, "ACCESSORY", false, EquipmentSlot.ACCESSORY);
public static final Type BLOCK = new Type(TypeSet.EXTRA, "BLOCK", false, null);
public static final Type ARMOR = new Type(TypeSet.EXTRA, "ARMOR", false, ModifierSource.OTHER);
public static final Type TOOL = new Type(TypeSet.EXTRA, "TOOL", false, ModifierSource.MELEE_WEAPON);
public static final Type CONSUMABLE = new Type(TypeSet.EXTRA, "CONSUMABLE", false, ModifierSource.MAINHAND_ITEM);
public static final Type MISCELLANEOUS = new Type(TypeSet.EXTRA, "MISCELLANEOUS", false, ModifierSource.MAINHAND_ITEM);
public static final Type GEM_STONE = new Type(TypeSet.EXTRA, "GEM_STONE", false, ModifierSource.VOID);
public static final Type SKIN = new Type(TypeSet.EXTRA, "SKIN", false, ModifierSource.VOID);
public static final Type ACCESSORY = new Type(TypeSet.EXTRA, "ACCESSORY", false, ModifierSource.OTHER);
public static final Type BLOCK = new Type(TypeSet.EXTRA, "BLOCK", false, ModifierSource.VOID);
private final String id;
private final TypeSet set;
@Nullable
private final EquipmentSlot equipType;
private final ModifierSource modifierSource;
private final boolean weapon;
private String name;
@ -91,14 +90,14 @@ public class Type {
private final List<ItemStat> available = new ArrayList<>();
@Deprecated
public Type(@NotNull TypeSet set, @NotNull String id, boolean weapon, @NotNull EquipmentSlot equipType, boolean fourGUIMode) {
this(set, id, weapon, equipType);
public Type(TypeSet set, String id, boolean weapon, ModifierSource modSource, boolean fourGUIMode) {
this(set, id, weapon, modSource);
}
public Type(@NotNull TypeSet set, @NotNull String id, boolean weapon, @NotNull EquipmentSlot equipType) {
public Type(TypeSet set, String id, boolean weapon, ModifierSource modSource) {
this.set = set;
this.id = id.toUpperCase().replace("-", "_").replace(" ", "_");
this.equipType = equipType;
this.modifierSource = modSource;
this.weapon = weapon;
this.loreFormat = null;
}
@ -110,7 +109,7 @@ public class Type {
set = (parent != null ? parent.set : TypeSet.EXTRA);
weapon = (parent != null && parent.weapon);
equipType = (parent != null ? parent.equipType : EquipmentSlot.OTHER);
modifierSource = (parent != null ? parent.modifierSource : ModifierSource.OTHER);
this.loreFormat = config.getString("LoreFormat", (parent != null ? parent.loreFormat : null));
}
@ -156,9 +155,8 @@ public class Type {
return name;
}
@Nullable
public EquipmentSlot getEquipmentType() {
return equipType;
public ModifierSource getModifierSource() {
return modifierSource;
}
public ItemStack getItem() {
@ -185,15 +183,7 @@ public class Type {
* @return Does it display as four rows in /mmoitems browse?
*/
public boolean isFourGUIMode() {
return getSupertype().equipType == EquipmentSlot.ARMOR;
}
/**
* @return If an item can be equipped in both hands
*/
public boolean isHandItem() {
final @NotNull Type supertype = getSupertype();
return supertype.equipType == EquipmentSlot.MAIN_HAND && !supertype.equals(MAIN_CATALYST);
return getSupertype().modifierSource == ModifierSource.ARMOR;
}
/**

View File

@ -27,7 +27,7 @@ public enum TypeSet {
* Slashing weapons deal damage in a cone behind the player's initial
* target, which makes it a deadly AoE weapon for warriors
*/
SLASHING(ModifierSource.MELEE_WEAPON, (attack, damager, target, weapon) -> {
SLASHING((attack, damager, target, weapon) -> {
if (!MMOItems.plugin.getConfig().getBoolean("item-ability.slashing.enabled") || damager.isOnCooldown(CooldownType.SET_TYPE_ATTACK))
return;
@ -53,7 +53,7 @@ public enum TypeSet {
* increased which makes it a perfect 'double or nothing' weapon for
* assassins
*/
PIERCING(ModifierSource.MELEE_WEAPON, (attack, damager, target, weapon) -> {
PIERCING((attack, damager, target, weapon) -> {
if (!MMOItems.plugin.getConfig().getBoolean("item-ability.piercing.enabled") || damager.isOnCooldown(CooldownType.SET_TYPE_ATTACK))
return;
@ -77,7 +77,7 @@ public enum TypeSet {
* Blunt weapons are like 1.9 sweep attacks. They damage all enemies nearby
* and apply a slight knockback
*/
BLUNT(ModifierSource.MELEE_WEAPON, (attack, damager, target, weapon) -> {
BLUNT((attack, damager, target, weapon) -> {
final Random random = new Random();
float pitchRange = 0.7f + random.nextFloat() * (0.9f - 0.7f);
@ -114,49 +114,32 @@ public enum TypeSet {
}
}),
/**
* Any item type can may apply their stats even when worn in offhand.
* They're the only items with that specific property
*/
OFFHAND(ModifierSource.OTHER),
/**
* Ranged attacks based weapons. when the player is too squishy to fight in
* the middle of the battle-field, these weapons allow him to take some
* distance and still deal some good damage
*/
RANGE(ModifierSource.RANGED_WEAPON),
RANGE,
/**
* Any other item type, like armor, consumables, etc. They all have their
* very specific passive depending on their item type
*/
EXTRA(ModifierSource.OTHER);
/**
* Interface between MMOItems' type sets and MythicLibs' modifierSources which let
* MythicLib know what type of item is giving some stat modifiers to a player
*/
private final ModifierSource modifierSource;
EXTRA;
private final SetAttackHandler attackHandler;
private final String name;
private TypeSet(ModifierSource modifierSource) {
this(modifierSource, null);
private TypeSet() {
this(null);
}
private TypeSet(ModifierSource modifierSource, SetAttackHandler attackHandler) {
private TypeSet(SetAttackHandler attackHandler) {
this.attackHandler = attackHandler;
this.modifierSource = modifierSource;
this.name = MMOUtils.caseOnWords(name().toLowerCase());
}
public ModifierSource getModifierSource() {
return modifierSource;
}
public boolean hasAttackEffect() {
return attackHandler != null;
}

View File

@ -211,14 +211,14 @@ public class PlayerData {
// Abilities
if (item.hasData(ItemStats.ABILITIES))
for (AbilityData abilityData : ((AbilityListData) item.getData(ItemStats.ABILITIES)).getAbilities()) {
ModifierSource modSource = equipped.getCached().getType() == null ? ModifierSource.OTHER : equipped.getCached().getType().getItemSet().getModifierSource();
ModifierSource modSource = equipped.getCached().getType().getModifierSource();
mmoData.getPassiveSkillMap().addModifier(new PassiveSkill("MMOItemsItem", abilityData, equipped.getSlot(), modSource));
}
// Modifier application rules
final ModifierSource source = item.getType().getItemSet().getModifierSource();
final ModifierSource source = item.getType().getModifierSource();
final EquipmentSlot equipmentSlot = equipped.getSlot();
if (source.isWeapon() && equipmentSlot == EquipmentSlot.MAIN_HAND.getOppositeHand())
if (!EquipmentSlot.MAIN_HAND.isCompatible(source, equipmentSlot))
continue;
// Apply permanent potion effects

View File

@ -70,8 +70,7 @@ public class PlayerStats {
double value = item.getNBT().getStat(stat.getId());
if (value != 0) {
final Type type = item.getCached().getType();
final ModifierSource source = type == null ? ModifierSource.OTHER : type.getItemSet().getModifierSource();
final ModifierSource source = item.getCached().getType().getModifierSource();
// Apply hand weapon stat offset
if (source.isWeapon() && stat instanceof AttackWeaponStat)

View File

@ -2,11 +2,14 @@ package net.Indyuce.mmoitems.api.player.inventory;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.api.player.EquipmentSlot;
import io.lumine.mythic.lib.player.modifier.ModifierSource;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem;
import org.apache.commons.lang.Validate;
import org.bukkit.inventory.ItemStack;
import javax.annotation.Nullable;
import java.util.Objects;
public class EquippedItem {
@ -54,33 +57,23 @@ public class EquippedItem {
}
/**
* The slot this equipped item is defined to be, will this <code>Type</code>
* actually add register its modifiers to the player when held here?
* <p>
* There's a difference between registering modifiers and applying it stats.
* For instance, modifiers from both hands are registered if the placement is
* legal but might not be taken into account during stat calculation!
* <p>
* An <code>OFF_CATALYST</code> may only add in the <code>OFFHAND</code>, and such.
* This is a small optimization which reduces the amount of items
* taken into account by the MMOItems player inventory handler.
*
* @return If item placement is legal
*/
public boolean isPlacementLegal() {
// Find item type
final String typeFormat = item.getString("MMOITEMS_ITEM_TYPE");
final Type type = typeFormat == null ? null : Type.get(typeFormat);
// Vanilla items are ignored
final @Nullable String typeFormat = item.getString("MMOITEMS_ITEM_TYPE");
if (typeFormat == null)
return false;
final @Nullable Type type = MMOItems.plugin.getTypes().get(typeFormat);
if (type == null)
return false;
// Equips anywhere
if (slot == EquipmentSlot.OTHER || type.getEquipmentType() == EquipmentSlot.OTHER)
return true;
// Hand items
if (type.isHandItem())
return slot.isHand();
return slot == type.getEquipmentType();
final ModifierSource modSource = type.getModifierSource();
return EquipmentSlot.OFF_HAND.isCompatible(modSource, slot) || EquipmentSlot.MAIN_HAND.isCompatible(modSource, slot);
}
}

View File

@ -8,6 +8,8 @@ import org.apache.commons.lang.Validate;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.logging.Level;
@ -20,9 +22,15 @@ public class TypeManager implements Reloadable {
*/
public void reload() {
map.clear();
registerAll(Type.ACCESSORY, Type.ARMOR, Type.BLOCK, Type.BOW, Type.CATALYST, Type.CONSUMABLE, Type.CROSSBOW, Type.DAGGER, Type.GAUNTLET,
Type.GEM_STONE, Type.SKIN, Type.HAMMER, Type.LUTE, Type.MISCELLANEOUS, Type.MUSKET, Type.OFF_CATALYST, Type.ORNAMENT, Type.SPEAR,
Type.STAFF, Type.SWORD, Type.TOOL, Type.WHIP);
// Load default types
for (Field field : Type.class.getFields())
try {
if (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers()) && field.get(null) instanceof Type)
register((Type) field.get(null));
} catch (Exception exception) {
MMOItems.plugin.getLogger().log(Level.WARNING, "Couldn't register type called '" + field.getName() + "': " + exception.getMessage());
}
/*
* Register all other types. Important: check if the map already

View File

@ -180,7 +180,7 @@ OFF_CATALYST:
display: PRISMARINE_CRYSTALS
name: 'Catalyst (Offhand)'
unident-item:
name: '&f#prefix#Unidentified Offhand Catalyst'
name: '&f#prefix#Unidentified Catalyst'
lore:
- '&7This item is unidentified. I must'
- '&7find a way to identify it!'
@ -194,7 +194,7 @@ MAIN_CATALYST:
display: PRISMARINE_CRYSTALS
name: 'Catalyst (Mainhand)'
unident-item:
name: '&f#prefix#Unidentified Offhand Catalyst'
name: '&f#prefix#Unidentified Catalyst'
lore:
- '&7This item is unidentified. I must'
- '&7find a way to identify it!'