Skip to content

Commit 029257c

Browse files
committed
Add knocback reduction for fast attacks
1 parent c22f7a0 commit 029257c

10 files changed

+54
-7
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# 1.5.5
22
- Add attack speed cap
3+
- Add knockback reduction for fast attacks (configurable)
34
- Improve back to back animation overlapping
45
- Fix offhand arm invisible while 2H animations
56
- Rework feinting
6-
- Update `staff` and `battlestaff` persets
7+
- Update `staff` and `battlestaff` presets
78

89
# 1.5.4
910
- Fix attacking hostile mounts/vehicles (Thanks to Emily Darrow)

common/src/main/java/net/bettercombat/config/ServerConfig.java

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ public class ServerConfig implements ConfigData {
3636
public boolean movement_speed_applied_smoothly = true;
3737
@Comment("Determines whether or not to apply movement speed reduction while attacking mounted")
3838
public boolean movement_speed_effected_while_mounting = false;
39+
@Comment("Attacks faster than a vanilla sword will do smaller knockback, proportionally.")
40+
public boolean knockback_reduced_for_fast_attacks = true;
3941
@Comment("Multiplier for `attack_range`, during target lookup on both sides. " +
4042
"Large sized entities may be colliding with weapon hitbox, but center of entities can have bigger distance than `attack_range`")
4143
public float target_search_range_multiplier = 2F;

common/src/main/java/net/bettercombat/logic/WeaponAttributesFallback.java

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package net.bettercombat.logic;
22

33
import net.bettercombat.BetterCombat;
4+
import net.bettercombat.utils.PatternMatching;
45
import net.minecraft.entity.EquipmentSlot;
56
import net.minecraft.entity.attribute.EntityAttribute;
67
import net.minecraft.entity.attribute.EntityAttributes;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package net.bettercombat.logic.knockback;
2+
3+
public interface ConfigurableKnockback {
4+
void setKnockbackMultiplier_BetterCombat(float strength);
5+
}

common/src/main/java/net/bettercombat/mixin/LivingEntityInject.java common/src/main/java/net/bettercombat/mixin/LivingEntityMixin.java

+16-1
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@
22

33
import net.bettercombat.logic.PlayerAttackHelper;
44
import net.bettercombat.logic.PlayerAttackProperties;
5+
import net.bettercombat.logic.knockback.ConfigurableKnockback;
56
import net.minecraft.entity.LivingEntity;
67
import net.minecraft.entity.attribute.EntityAttribute;
78
import net.minecraft.entity.player.PlayerEntity;
89
import org.spongepowered.asm.mixin.Mixin;
910
import org.spongepowered.asm.mixin.injection.At;
1011
import org.spongepowered.asm.mixin.injection.Inject;
12+
import org.spongepowered.asm.mixin.injection.ModifyVariable;
1113
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
1214

1315
@Mixin(LivingEntity.class)
14-
public class LivingEntityInject {
16+
public class LivingEntityMixin implements ConfigurableKnockback {
1517

1618
// FEATURE: Dual wielded attacking - Client side weapon cooldown for offhand
1719

@@ -32,4 +34,17 @@ public void getAttributeValue_Inject(EntityAttribute attribute, CallbackInfoRetu
3234
}
3335
}
3436
}
37+
38+
// MARK: ConfigurableKnockback
39+
private float customKnockbackMultiplier_BetterCombat = 1;
40+
41+
@Override
42+
public void setKnockbackMultiplier_BetterCombat(float value) {
43+
customKnockbackMultiplier_BetterCombat = value;
44+
}
45+
46+
@ModifyVariable(method = "takeKnockback", at = @At("HEAD"), ordinal = 0, argsOnly = true)
47+
public double takeKnockback_HEAD_changeStrength(double knockbackStrength) {
48+
return knockbackStrength * customKnockbackMultiplier_BetterCombat;
49+
}
3550
}

common/src/main/java/net/bettercombat/mixin/client/MinecraftClientInject.java

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import net.bettercombat.config.ClientConfigWrapper;
1515
import net.bettercombat.logic.*;
1616
import net.bettercombat.network.Packets;
17+
import net.bettercombat.utils.PatternMatching;
1718
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
1819
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
1920
import net.minecraft.block.BlockState;

common/src/main/java/net/bettercombat/network/ServerNetwork.java

+18-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
import net.bettercombat.logic.PlayerAttackProperties;
1010
import net.bettercombat.logic.TargetHelper;
1111
import net.bettercombat.logic.WeaponRegistry;
12+
import net.bettercombat.logic.knockback.ConfigurableKnockback;
1213
import net.bettercombat.mixin.LivingEntityAccessor;
14+
import net.bettercombat.utils.MathHelp;
1315
import net.bettercombat.utils.SoundHelper;
1416
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
1517
import net.fabricmc.fabric.api.networking.v1.PlayerLookup;
@@ -23,7 +25,6 @@
2325
import net.minecraft.entity.attribute.EntityAttributeModifier;
2426
import net.minecraft.entity.attribute.EntityAttributes;
2527
import net.minecraft.entity.decoration.ArmorStandEntity;
26-
import net.minecraft.entity.mob.HostileEntity;
2728
import net.minecraft.entity.projectile.PersistentProjectileEntity;
2829
import net.minecraft.network.PacketByteBuf;
2930
import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket;
@@ -114,6 +115,10 @@ public static void initializeHandlers() {
114115
SoundHelper.playSound(world, player, attack.swingSound());
115116
}
116117

118+
var attackCooldown = PlayerAttackHelper.getAttackCooldownTicksCapped(player);
119+
var knockbackMultiplier = BetterCombat.config.knockback_reduced_for_fast_attacks
120+
? MathHelp.clamp(attackCooldown / 12.5F, 0.1F, 1F)
121+
: 1F;
117122
var lastAttackedTicks = ((LivingEntityAccessor)player).getLastAttackedTicks();
118123
if (!useVanillaPacket) {
119124
player.setSneaking(request.isSneaking());
@@ -133,8 +138,13 @@ public static void initializeHandlers() {
133138
|| (entity instanceof ArmorStandEntity && ((ArmorStandEntity)entity).isMarker())) {
134139
continue;
135140
}
136-
if (BetterCombat.config.allow_fast_attacks && entity instanceof LivingEntity) {
137-
((LivingEntity)entity).timeUntilRegen = 0;
141+
if (entity instanceof LivingEntity livingEntity) {
142+
if (BetterCombat.config.allow_fast_attacks) {
143+
livingEntity.timeUntilRegen = 0;
144+
}
145+
if (knockbackMultiplier != 1F) {
146+
((ConfigurableKnockback)livingEntity).setKnockbackMultiplier_BetterCombat(knockbackMultiplier);
147+
}
138148
}
139149
((LivingEntityAccessor) player).setLastAttackedTicks(lastAttackedTicks);
140150
// System.out.println("Server - Attacking hand: " + (hand.isOffHand() ? "offhand" : "mainhand") + " CD: " + player.getAttackCooldownProgress(0));
@@ -153,6 +163,11 @@ public static void initializeHandlers() {
153163
player.attack(entity);
154164
}
155165
}
166+
if (entity instanceof LivingEntity livingEntity) {
167+
if (knockbackMultiplier != 1F) {
168+
((ConfigurableKnockback)livingEntity).setKnockbackMultiplier_BetterCombat(1F);
169+
}
170+
}
156171
}
157172

158173
if (!useVanillaPacket) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package net.bettercombat.utils;
2+
3+
public class MathHelp {
4+
public static float clamp(float value, float min, float max) {
5+
return Math.max(Math.min(value, max), min);
6+
}
7+
}

common/src/main/java/net/bettercombat/logic/PatternMatching.java common/src/main/java/net/bettercombat/utils/PatternMatching.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package net.bettercombat.logic;
1+
package net.bettercombat.utils;
22

33
import java.util.regex.Matcher;
44
import java.util.regex.Pattern;

common/src/main/resources/bettercombat.mixins.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"EnchantmentMixin",
88
"ItemStackMixin",
99
"LivingEntityAccessor",
10-
"LivingEntityInject",
10+
"LivingEntityMixin",
1111
"PlayerEntityAccessor",
1212
"PlayerEntityMixin",
1313
"ServerPlayNetworkHandlerMixin",

0 commit comments

Comments
 (0)