Fixed modifier application

This commit is contained in:
Indyuce 2022-08-18 12:48:50 +02:00
parent 4706dd0ac0
commit dbd1936609
11 changed files with 88 additions and 73 deletions

View File

@ -42,24 +42,25 @@ public class Type {
// 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.OTHER);
public static final Type BOTH_CATALYST = new Type(TypeSet.OFFHAND, "BOTH_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);
// Any
public static final Type ORNAMENT = new Type(TypeSet.EXTRA, "ORNAMENT", false, EquipmentSlot.ANY);
public static final Type ORNAMENT = new Type(TypeSet.EXTRA, "ORNAMENT", false, EquipmentSlot.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, EquipmentSlot.OTHER);
public static final Type SKIN = new Type(TypeSet.EXTRA, "SKIN", false, EquipmentSlot.OTHER);
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, EquipmentSlot.OTHER);
public static final Type BLOCK = new Type(TypeSet.EXTRA, "BLOCK", false, null);
private final String id;
private final TypeSet set;
@Nullable
private final EquipmentSlot equipType;
private final boolean weapon;
@ -155,6 +156,7 @@ public class Type {
return name;
}
@Nullable
public EquipmentSlot getEquipmentType() {
return equipType;
}
@ -163,10 +165,18 @@ public class Type {
return item.clone();
}
/**
* @deprecated Use {@link #getSupertype()}
*/
@Deprecated
public boolean isSubtype() {
return parent != null;
}
/**
* @deprecated Use {@link #getSupertype()}
*/
@Deprecated
public Type getParent() {
return parent;
}
@ -175,15 +185,15 @@ public class Type {
* @return Does it display as four rows in /mmoitems browse?
*/
public boolean isFourGUIMode() {
return equipType == EquipmentSlot.ARMOR;
return getSupertype().equipType == EquipmentSlot.ARMOR;
}
/**
* @return Should its stats apply in offhand
* @return If an item can be equipped in both hands
*/
public boolean isOffhandItem() {
final Type supertype = getSupertype();
return supertype.equals(OFF_CATALYST) || supertype.equals(BOTH_CATALYST);
public boolean isHandItem() {
final @NotNull Type supertype = getSupertype();
return supertype.equipType == EquipmentSlot.MAIN_HAND && !supertype.equals(MAIN_CATALYST);
}
/**
@ -199,11 +209,8 @@ public class Type {
*/
public Type getSupertype() {
Type parentMost = this;
while (parentMost.isSubtype()) {
parentMost = parentMost.getParent();
}
while (parentMost.parent != null)
parentMost = parentMost.parent;
return parentMost;
}
@ -212,11 +219,12 @@ public class Type {
* or if this type is a subtype of the given type.
*/
public boolean corresponds(Type type) {
return equals(type) || (isSubtype() && getParent().equals(type));
return getSupertype().equals(type);
}
@Deprecated
public boolean corresponds(TypeSet set) {
return getItemSet() == set;
return getSupertype().getItemSet() == set;
}
/**
@ -298,8 +306,8 @@ public class Type {
* @param id The type id
* @return The type or null if it couldn't be found
*/
public static @Nullable
Type get(@Nullable String id) {
@Nullable
public static Type get(@Nullable String id) {
if (id == null) {
return null;
}

View File

@ -26,7 +26,7 @@ public class Weapon extends UseItem {
@Override
public boolean checkItemRequirements() {
if (playerData.areHandsFull()) {
if (playerData.isEncumbered()) {
Message.HANDS_TOO_CHARGED.format(ChatColor.RED).send(getPlayer());
return false;
}

View File

@ -4,7 +4,7 @@ import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.api.player.EquipmentSlot;
import io.lumine.mythic.lib.player.PlayerMetadata;
import io.lumine.mythic.lib.skill.trigger.TriggerType;
import io.lumine.mythic.lib.util.ProjectileTrigger;
import io.lumine.mythic.lib.util.CustomProjectile;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.MMOItems;
import org.bukkit.GameMode;
@ -41,6 +41,6 @@ public class Crossbow extends UntargetedWeapon {
// Trigger abilities
stats.getData().triggerSkills(TriggerType.SHOOT_BOW, arrow);
new ProjectileTrigger(stats.getData(), ProjectileTrigger.ProjectileType.ARROW, arrow, slot);
new CustomProjectile(stats.getData(), CustomProjectile.ProjectileType.ARROW, arrow, slot);
}
}

View File

@ -67,7 +67,7 @@ public class MMOItemTemplate extends PostLoadObject implements ItemReference {
protected void whenPostLoaded(ConfigurationSection config) {
FriendlyFeedbackProvider ffp = new FriendlyFeedbackProvider(FFPMMOItems.get());
ffp.activatePrefix(true, getType().toString() + " " + getId());
ffp.activatePrefix(true, getType().getId() + " " + getId());
if (config.contains("option"))
for (TemplateOption option : TemplateOption.values())

View File

@ -53,7 +53,7 @@ public class PlayerData {
private final Map<PotionEffectType, PotionEffect> permanentEffects = new HashMap<>();
private final Set<ParticleRunnable> itemParticles = new HashSet<>();
private ParticleRunnable overridingItemParticles = null;
private boolean handsFull = false;
private boolean encumbered = false;
@Nullable
private SetBonuses setBonuses = null;
private final PlayerStats stats;
@ -118,25 +118,28 @@ public class PlayerData {
overridingItemParticles.cancel();
}
@Deprecated
public boolean areHandsFull() {
return isEncumbered();
}
/**
* @return If the player hands are full i.e if the player is holding
* two items in their hands, one being two handed
*/
public boolean areHandsFull() {
if (!mmoData.isOnline())
return false;
public boolean isEncumbered() {
// Get the mainhand and offhand items.
NBTItem main = MythicLib.plugin.getVersion().getWrapper().getNBTItem(getPlayer().getInventory().getItemInMainHand());
NBTItem off = MythicLib.plugin.getVersion().getWrapper().getNBTItem(getPlayer().getInventory().getItemInOffHand());
final NBTItem main = MythicLib.plugin.getVersion().getWrapper().getNBTItem(getPlayer().getInventory().getItemInMainHand());
final NBTItem off = MythicLib.plugin.getVersion().getWrapper().getNBTItem(getPlayer().getInventory().getItemInOffHand());
// Is either hand two-handed?
boolean mainhand_twohanded = main.getBoolean(ItemStats.TWO_HANDED.getNBTPath());
boolean offhand_twohanded = off.getBoolean(ItemStats.TWO_HANDED.getNBTPath());
final boolean mainhand_twohanded = main.getBoolean(ItemStats.TWO_HANDED.getNBTPath());
final boolean offhand_twohanded = off.getBoolean(ItemStats.TWO_HANDED.getNBTPath());
// Is either hand encumbering: Not NULL, not AIR, and not Handworn
boolean mainhand_encumbering = (main.getItem() != null && main.getItem().getType() != Material.AIR && !main.getBoolean(ItemStats.HANDWORN.getNBTPath()));
boolean offhand_encumbering = (off.getItem() != null && off.getItem().getType() != Material.AIR && !off.getBoolean(ItemStats.HANDWORN.getNBTPath()));
final boolean mainhand_encumbering = (main.getItem() != null && main.getItem().getType() != Material.AIR && !main.getBoolean(ItemStats.HANDWORN.getNBTPath()));
final boolean offhand_encumbering = (off.getItem() != null && off.getItem().getType() != Material.AIR && !off.getBoolean(ItemStats.HANDWORN.getNBTPath()));
// Will it encumber?
return (mainhand_twohanded && offhand_encumbering) || (mainhand_encumbering && offhand_twohanded);
@ -177,10 +180,10 @@ public class PlayerData {
permissions.clear();
/*
* Updates the full-hands boolean, this way it can be cached and used in
* the updateEffects() method
* Updates the encumbered boolean, this way it can be
* cached and used in the updateEffects() method
*/
handsFull = areHandsFull();
encumbered = isEncumbered();
// Find all the items the player can actually use
for (EquippedItem item : MMOItems.plugin.getInventory().getInventory(getPlayer())) {
@ -203,10 +206,19 @@ public class PlayerData {
Bukkit.getPluginManager().callEvent(new RefreshInventoryEvent(inventory.getEquipped(), getPlayer(), this));
for (EquippedItem equipped : inventory.getEquipped()) {
VolatileMMOItem item = equipped.getCached();
final VolatileMMOItem item = equipped.getCached();
// Stats which don't apply from off hand
if (equipped.getSlot() == EquipmentSlot.OFF_HAND && equipped.getCached().getType().getEquipmentType() != EquipmentSlot.OFF_HAND)
// 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();
mmoData.getPassiveSkillMap().addModifier(new PassiveSkill("MMOItemsItem", abilityData, equipped.getSlot(), modSource));
}
// Modifier application rules
final ModifierSource source = item.getType().getItemSet().getModifierSource();
final EquipmentSlot equipmentSlot = equipped.getSlot();
if (source.isWeapon() && equipmentSlot == EquipmentSlot.MAIN_HAND.getOppositeHand())
continue;
// Apply permanent potion effects
@ -227,16 +239,8 @@ public class PlayerData {
itemParticles.add(particleData.start(this));
}
// Abilities
if (item.hasData(ItemStats.ABILITIES) && (MMOItems.plugin.getConfig().getBoolean("abilities-bypass-encumbering") || !handsFull))
for (AbilityData abilityData : ((AbilityListData) item.getData(ItemStats.ABILITIES)).getAbilities()) {
ModifierSource modSource = equipped.getCached().getType() == null ? ModifierSource.OTHER : equipped.getCached().getType().getItemSet().getModifierSource();
mmoData.getPassiveSkillMap().addModifier(new PassiveSkill("MMOItemsItem", abilityData, equipped.getSlot(), modSource));
}
// Apply permissions if Vault exists
if (MMOItems.plugin.hasPermissions() && item.hasData(ItemStats.GRANTED_PERMISSIONS)) {
permissions.addAll(((StringListData) item.getData(ItemStats.GRANTED_PERMISSIONS)).getList());
Permission perms = MMOItems.plugin.getVault().getPermissions();
permissions.forEach(perm -> {
@ -311,7 +315,7 @@ public class PlayerData {
permanentEffects.values().forEach(effect -> getPlayer().addPotionEffect(effect));
// Two handed slowness
if (handsFull)
if (encumbered)
getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 40, 1, true, false));
}

View File

@ -70,12 +70,11 @@ public class PlayerStats {
double value = item.getNBT().getStat(stat.getId());
if (value != 0) {
Type type = item.getCached().getType();
ModifierSource source = type == null ? ModifierSource.OTHER : type.getItemSet().getModifierSource();
final Type type = item.getCached().getType();
final ModifierSource source = type == null ? ModifierSource.OTHER : type.getItemSet().getModifierSource();
// Apply hand weapon stat offset
if (item.getSlot() == EquipmentSlot.MAIN_HAND && stat instanceof AttackWeaponStat)
if (source.isWeapon() && stat instanceof AttackWeaponStat)
value -= ((AttackWeaponStat) stat).getOffset(playerData);
packet.addModifier(new StatModifier("MMOItem-" + index++, stat.getId(), value, ModifierType.FLAT, item.getSlot(), source));

View File

@ -55,8 +55,12 @@ public class EquippedItem {
/**
* The slot this equipped item is defined to be, will this <code>Type</code>
* actually add its stats to the player when held here?
* <p></p>
* 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.
*/
public boolean isPlacementLegal() {
@ -70,12 +74,12 @@ public class EquippedItem {
return false;
// Equips anywhere
if (slot == EquipmentSlot.ANY)
if (slot == EquipmentSlot.OTHER || type.getEquipmentType() == EquipmentSlot.OTHER)
return true;
// Does it work in offhand
if (slot == EquipmentSlot.OFF_HAND)
return type.isOffhandItem();
// Hand items
if (type.isHandItem())
return slot.isHand();
return slot == type.getEquipmentType();
}

View File

@ -36,8 +36,8 @@ public class OrnamentPlayerInventory implements PlayerInventory, Listener {
// Ornaments
for (ItemStack item : player.getInventory().getContents()) {
NBTItem nbtItem;
if (item != null && (nbtItem = MythicLib.plugin.getVersion().getWrapper().getNBTItem(item)).hasType() && Type.get(nbtItem.getType()).getEquipmentType() == EquipmentSlot.ANY)
list.add(new EquippedItem(nbtItem, EquipmentSlot.ANY));
if (item != null && (nbtItem = MythicLib.plugin.getVersion().getWrapper().getNBTItem(item)).hasType() && Type.get(nbtItem.getType()).getSupertype().equals(Type.ORNAMENT))
list.add(new EquippedItem(nbtItem, EquipmentSlot.OTHER));
}
return list;
@ -47,7 +47,7 @@ public class OrnamentPlayerInventory implements PlayerInventory, Listener {
public void a(EntityPickupItemEvent event) {
if (event.getEntityType() == EntityType.PLAYER) {
NBTItem nbt = NBTItem.get(event.getItem().getItemStack());
if (nbt.hasType() && Type.get(nbt.getType()).getEquipmentType() == EquipmentSlot.ANY)
if (nbt.hasType() && Type.get(nbt.getType()).getSupertype().equals(Type.ORNAMENT))
PlayerData.get((Player) event.getEntity()).updateInventory();
}
}
@ -55,7 +55,7 @@ public class OrnamentPlayerInventory implements PlayerInventory, Listener {
@EventHandler(ignoreCancelled = true)
public void b(PlayerDropItemEvent event) {
NBTItem nbt = NBTItem.get(event.getItemDrop().getItemStack());
if (nbt.hasType() && Type.get(nbt.getType()).getEquipmentType() == EquipmentSlot.ANY)
if (nbt.hasType() && Type.get(nbt.getType()).getSupertype().equals(Type.ORNAMENT))
PlayerData.get(event.getPlayer()).updateInventory();
}
}

View File

@ -286,7 +286,7 @@ public class ItemUse implements Listener {
}
// Have to get hand manually because 1.15 and below does not have event.getHand()
ItemStack itemInMainHand = playerData.getPlayer().getInventory().getItemInMainHand();
final ItemStack itemInMainHand = playerData.getPlayer().getInventory().getItemInMainHand();
final EquipmentSlot bowSlot = itemInMainHand.isSimilar(event.getBow()) ? EquipmentSlot.MAIN_HAND : EquipmentSlot.OFF_HAND;
MMOItems.plugin.getEntities().registerCustomProjectile(item, playerData.getStats().newTemporary(bowSlot), event.getProjectile(), event.getForce());
}

View File

@ -138,13 +138,13 @@ public class PlayerListener implements Listener {
if (!(event.getEntity() instanceof Trident) || !(event.getEntity().getShooter() instanceof Player))
return;
InteractItem item = new InteractItem((Player) event.getEntity().getShooter(), Material.TRIDENT);
final InteractItem item = new InteractItem((Player) event.getEntity().getShooter(), Material.TRIDENT);
if (!item.hasItem())
return;
NBTItem nbtItem = MythicLib.plugin.getVersion().getWrapper().getNBTItem(item.getItem());
Type type = Type.get(nbtItem.getType());
PlayerData playerData = PlayerData.get((Player) event.getEntity().getShooter());
final NBTItem nbtItem = MythicLib.plugin.getVersion().getWrapper().getNBTItem(item.getItem());
final Type type = Type.get(nbtItem.getType());
final PlayerData playerData = PlayerData.get((Player) event.getEntity().getShooter());
if (type != null) {
final Weapon weapon = new Weapon(playerData, nbtItem);

View File

@ -161,10 +161,10 @@ LUTE:
- '{range}&8- &7Lvl Range: &e#range#'
- '{tier}&8- &7Item Tier: #prefix##tier#'
# Applies stats in mainhand only
# Applies stats in both hands
CATALYST:
display: PRISMARINE_SHARD
name: 'Catalyst (Mainhand)'
name: 'Catalyst'
unident-item:
name: '&f#prefix#Unidentified Catalyst'
lore:
@ -189,10 +189,10 @@ OFF_CATALYST:
- '{range}&8- &7Lvl Range: &e#range#'
- '{tier}&8- &7Item Tier: #prefix##tier#'
# Applies stats in both hands
BOTH_CATALYST:
# Applies stats in mainhand only
MAIN_CATALYST:
display: PRISMARINE_CRYSTALS
name: 'Catalyst'
name: 'Catalyst (Mainhand)'
unident-item:
name: '&f#prefix#Unidentified Offhand Catalyst'
lore: