Maciej916 / Ma-Enchants

Adds various new enchant and curses to the game
GNU Lesser General Public License v3.0
3 stars 8 forks source link

[1.19.2 Forge] Switching between weapons with different Fastter Attack lvl doesn't changes attack speed. #48

Open Averso opened 1 year ago

Averso commented 1 year ago

If I set some weapons with different Faster Attack lvl in toolbar, then switching between them (using mouse scroll) doesn't apply proper enchant lvl.

Here I have swords with this enchantment arranged from V to I. The last one sword lvl 1 has attack speed value as the first one with enchantment lvl 5: image image

Here's code example that could solve that (in HandlerFasterAttack.java):

 public static void handlerPlayerTick(Player player) {
        IPlayerCapability enchantsCap = PlayerUtil.getAliveEnchantsCapability(player);
        if (enchantsCap == null) return;

        ItemStack stack = player.getItemInHand(player.getUsedItemHand());
        int lvl = stack.getEnchantmentLevel(ModEnchantments.FASTER_ATTACK.get());
        if (lvl > 0) {
            if (enchantsCap.getFasterAttack() == 0) {
                HandlerFasterAttack.upgradeAttackSpeed(player, enchantsCap, lvl);
            } else if (enchantsCap.getFasterAttack() != lvl) {
                HandlerFasterAttack.restoreAttackSpeed(player, enchantsCap);
                HandlerFasterAttack.upgradeAttackSpeed(player, enchantsCap, lvl);
            }
        } else {
            if (enchantsCap.getFasterAttack() != 0) {
                HandlerFasterAttack.restoreAttackSpeed(player, enchantsCap);
            }
        }
    }

    public static void upgradeAttackSpeed(Player player, IPlayerCapability enchantsCap, int enchantmentLvl) {
        double baseAttack = Objects.requireNonNull(player.getAttribute(Attributes.ATTACK_SPEED)).getBaseValue();
        Objects.requireNonNull(player.getAttribute(Attributes.ATTACK_SPEED)).setBaseValue(baseAttack * enchantmentLvl);
        enchantsCap.setFasterAttack(enchantmentLvl);
    }

    public static void restoreAttackSpeed(Player player, IPlayerCapability enchantsCap) {
        double attackSpeed = Objects.requireNonNull(player.getAttribute(Attributes.ATTACK_SPEED)).getBaseValue();
        Objects.requireNonNull(player.getAttribute(Attributes.ATTACK_SPEED)).setBaseValue(attackSpeed / enchantsCap.getFasterAttack());
        player.removeEffect(ModMobEffects.FASTER_ATTACK.get());
        enchantsCap.setFasterAttack(0);
    }
SiverDX commented 1 year ago

my fix for this looks like this

@Mixin(value = HandlerFasterAttack.class, remap = false)
public abstract class MixinHandlerFasterAttack {
    @Unique private static final String ATTRIBUTE_UUID = "578e84b7-327d-4a19-87f1-cb5de98a977d";

    /**
     * @author Cadentem
     * @reason Fix broken implementation
     */
    @Overwrite
    public static void handlerPlayerTick(final Player player) {
        if (player.tickCount % 10 != 0) {
            return;
        }

        AttributeInstance attribute = player.getAttribute(Attributes.ATTACK_SPEED);

        if (attribute != null) {
            int level = player.getItemInHand(player.getUsedItemHand()).getEnchantmentLevel(ModEnchantments.FASTER_ATTACK.get());
            AttributeModifier modifier = attribute.getModifier(UUID.fromString(ATTRIBUTE_UUID));

            if (modifier != null) {
                attribute.removeModifier(modifier);
            }

            if (level > 0) {
                attribute.addTransientModifier(new AttributeModifier(UUID.fromString(ATTRIBUTE_UUID), "Faster Attack enchantment", level, AttributeModifier.Operation.MULTIPLY_BASE));
            }
        }
    }
}