fix(combat): restore KillAura tick / attack / multi logic from Recaf

Several Recaf-side behaviors were missing or wrong in the current
KillAura, which is why the module felt 'broken':

- onTick short-circuit was too aggressive: any non-null mc.screen
  killed everything. Recaf only bails for AbstractContainerScreen and
  for the rotation-owning helpers (Helper / AntiWeb / AntiTNT /
  MidPearl / Stuck / AutoWebPlace), plus ItemUtil.hasServerItem().
  Pure UI screens (chat, F3, vanilla menus that aren't containers) now
  no longer wipe the target.
- Switch trigger used the wrong counter: it compared the float
  'attacks' accumulator against switchAttackTimes, but Recaf has a
  separate per-attack counter (attackTimes) compared against
  switchDelay. Added the missing field and swapped the predicate so
  Switch Delay actually controls how long we stay on a target.
- Attack pacing was reduced to a flat 'attacks += aps/20'. Recaf only
  feeds the accumulator in Smooth mode and uses
  MathUtil.randomDouble(switchAttackTimes, aps) / 20.0 to jitter the
  rate; Snap mode instead waits for getAttackStrengthScale >= 0.9F
  and respects a sprintCounter cooldown set from
  getCurrentItemAttackStrengthDelay(). AntiKB.NoXZMode and sprintSync
  scale the rate too.
- attackEntity() now bumps attackTimes, gates the actual attack +
  swing on (sprintTickCounter % 2 == 0) when sprintSync is on, runs
  the magicCrit + crit pair when targetHud is on, and seeds
  sprintCounter for Snap mode.
- doAttack() / multiAttack now use RotationUtil.getHitDistance along
  the active rotation rather than just closestPoint distance, which
  is what Recaf does. Dropped a defensive 'attack target if not
  hovering anyone' fallback that was not in Recaf.
- updateTargets() guards against the null getTargets() can return so
  targetList is always a usable list.
- onDisable now also clears sprintCounter and attackTimes alongside
  sprintTickCounter so re-enabling the module starts from a clean
  state.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
Shirona1337andClaude Opus 4.7 committed 2026-05-22 13:52:07 +08:00
1 parent 9dd2a25a1b
commit 49ad2adf74
1 file changed
+88 -34
@@ -8,6 +8,7 @@ import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity;
@@ -36,12 +37,20 @@ import shit.zen.event.impl.TickEvent;
import shit.zen.event.impl.WorldChangeEvent;
import shit.zen.modules.Category;
import shit.zen.modules.Module;
import shit.zen.modules.impl.combat.antikb.NoXZMode;
import shit.zen.modules.impl.player.AntiTNT;
import shit.zen.modules.impl.player.AntiWeb;
import shit.zen.modules.impl.player.AutoWebPlace;
import shit.zen.modules.impl.player.Helper;
import shit.zen.modules.impl.player.MidPearl;
import shit.zen.modules.impl.player.Stuck;
import shit.zen.modules.impl.world.Teams;
import shit.zen.settings.impl.BooleanSetting;
import shit.zen.settings.impl.ModeSetting;
import shit.zen.settings.impl.NumberSetting;
import shit.zen.utils.game.ItemUtil;
import shit.zen.utils.game.RotationUtil;
import shit.zen.utils.math.MathUtil;
import shit.zen.utils.rotation.Rotation;
import shit.zen.utils.rotation.RotationHandler;
import shit.zen.event.EventTarget;
@@ -64,7 +73,7 @@ public class KillAura extends Module {
public final BooleanSetting targetEsp;
public final BooleanSetting noUseItem;
public final BooleanSetting aboveTarget;
public final NumberSetting attackRange;
public final NumberSetting aimRange;
public final NumberSetting aps;
public final NumberSetting switchAttackTimes;
public final NumberSetting switchSize;
@@ -75,9 +84,9 @@ public class KillAura extends Module {
public final ModeSetting sortMode;
public final ModeSetting attackMode;
private RotationUtil.BestHitInfo prevBestHit;
private RotationUtil.BestHitInfo currentBestHit;
private final int attackTimes;
private RotationUtil.BestHitInfo prevBestHit;
private int attackTimes;
private float attacks;
private int targetIndex;
public int sprintTickCounter;
@@ -98,7 +107,7 @@ public class KillAura extends Module {
this.targetEsp = new BooleanSetting("Target ESP", false);
this.noUseItem = new BooleanSetting("No Use Item", false);
this.aboveTarget = new BooleanSetting("Above Target", false);
this.attackRange = new NumberSetting("Attack Range", 5.0, 1.0, 6.0, 0.1);
this.aimRange = new NumberSetting("Aim Range", 5.0, 1.0, 6.0, 0.1);
this.aps = new NumberSetting("APS", 10.0, 1.0, 20.0, 1.0);
this.switchAttackTimes = new NumberSetting("Switch Attack Times", 10.0, 1.0, 20.0, 1.0);
this.switchSize = new NumberSetting("Switch Size", 1.0, 1.0, 5.0, 1.0,
@@ -109,7 +118,6 @@ public class KillAura extends Module {
this.rotationsMode = new ModeSetting("Rotations", "Smooth", "Snap").withDefault("Smooth");
this.sortMode = new ModeSetting("Sort", "Distance", "FOV", "Health", "None").withDefault("Distance");
this.attackMode = new ModeSetting("Attack Mode", "Single", "Switch", "Multi", "None").withDefault("Single");
this.attackTimes = 0;
this.attacks = 0.0f;
INSTANCE = this;
}
@@ -132,6 +140,7 @@ public class KillAura extends Module {
aimingTarget = null;
this.sprintTickCounter = 0;
this.sprintCounter = 0;
this.attackTimes = 0;
super.onDisable();
}
@@ -194,30 +203,40 @@ public class KillAura extends Module {
@EventTarget
public void onTick(TickEvent event) {
if (mc.player == null || mc.level == null) {
if (!ZenClient.isReady()) {
return;
}
if (mc.screen != null) {
if (mc.screen instanceof AbstractContainerScreen
|| ItemUtil.hasServerItem()
|| (Stuck.INSTANCE != null && Stuck.INSTANCE.isEnabled())
|| (Helper.INSTANCE != null && Helper.INSTANCE.isEnabled() && Helper.targetRotation != null)
|| AntiWeb.targetRotation != null
|| AntiTNT.targetRotation != null
|| MidPearl.targetRotation != null
|| this.isWebPlacing()) {
target = null;
aimingTarget = null;
this.rotation = null;
this.currentBestHit = null;
this.rotation = null;
this.prevBestHit = null;
targetList.clear();
this.sprintTickCounter = 0;
this.attacks = 0.0f;
this.sprintCounter = 0;
return;
}
boolean isSwitch = this.switchSize.getValue().intValue() > 1;
boolean isSwitch = this.switchSize.getValue().intValue() > 1
|| this.infSwitch.getValue()
|| this.multiAttack.getValue();
this.updateTargets();
aimingTarget = this.getTarget();
this.prevBestHit = this.currentBestHit;
this.currentBestHit = null;
this.rotation = null;
if (aimingTarget != null) {
RotationUtil.BestHitInfo hit = RotationUtil.getBestHit(aimingTarget);
this.currentBestHit = hit;
if (hit != null && hit.rotation() != null) {
this.rotation = hit.rotation();
}
this.currentBestHit = RotationUtil.getBestHit(aimingTarget);
this.rotation = this.currentBestHit != null ? this.currentBestHit.rotation() : null;
} else {
this.rotation = null;
}
if (targetList.isEmpty()) {
target = null;
@@ -226,10 +245,10 @@ public class KillAura extends Module {
if (this.targetIndex > targetList.size() - 1) {
this.targetIndex = 0;
}
boolean switchByAttacks = this.attacks >= this.switchAttackTimes.getValue().floatValue();
boolean switchByDistance = this.currentBestHit != null && this.currentBestHit.distance() > 3.0;
if (targetList.size() > 1 && (switchByAttacks || switchByDistance)) {
this.attacks = 0.0f;
if (targetList.size() > 1
&& (this.attackTimes >= this.switchDelay.getValue().intValue()
|| (this.currentBestHit != null && this.currentBestHit.distance() > 3.0))) {
this.attackTimes = 0;
for (int i = 0; i < targetList.size(); ++i) {
++this.targetIndex;
if (this.targetIndex > targetList.size() - 1) {
@@ -246,7 +265,29 @@ public class KillAura extends Module {
this.targetIndex = 0;
}
target = targetList.get(this.targetIndex);
this.attacks += this.aps.getValue().floatValue() / 20.0f;
if (this.rotationsMode.is("Smooth")) {
float apsValue;
float minApsValue;
if (NoXZMode.isAttacking) {
int kbAttackAmount = AntiKB.INSTANCE != null
? AntiKB.INSTANCE.attackAmount.getValue().intValue()
: 0;
apsValue = this.aps.getValue().floatValue() - kbAttackAmount;
minApsValue = this.switchAttackTimes.getValue().floatValue() - kbAttackAmount;
} else {
apsValue = this.aps.getValue().floatValue();
minApsValue = this.switchAttackTimes.getValue().floatValue();
}
if (this.sprintSync.getValue()) {
apsValue *= 2.0f;
minApsValue *= 2.0f;
}
this.attacks += (float)(MathUtil.randomDouble(minApsValue, apsValue) / 20.0);
} else if (this.sprintCounter > 0) {
--this.sprintCounter;
} else if (mc.player.getAttackStrengthScale(0.0f) >= 0.9f) {
this.doAttack();
}
}
@EventTarget
@@ -282,10 +323,12 @@ public class KillAura extends Module {
}
if (this.multiAttack.getValue()) {
int attacked = 0;
Rotation aimRot = RotationHandler.targetRotation != null
? RotationHandler.targetRotation
: this.rotation;
for (Entity entity : targetList) {
if (!this.isValidAttack(entity)) continue;
Vec3 closest = RotationUtil.closestPoint(mc.player.getEyePosition(), entity.getBoundingBox());
if (closest.distanceTo(mc.player.getEyePosition()) >= 3.0) continue;
if (aimRot == null) break;
if (RotationUtil.getHitDistance(entity, mc.player.getEyePosition(), aimRot) >= 3.0) continue;
this.attackEntity(entity);
if (++attacked >= 2) {
break;
@@ -293,11 +336,7 @@ public class KillAura extends Module {
}
} else if (hitResult != null && hitResult.getType() == HitResult.Type.ENTITY) {
Entity hitEntity = ((EntityHitResult) hitResult).getEntity();
if (this.isValidAttack(hitEntity)) {
this.attackEntity(hitEntity);
}
} else if (target != null && this.isValidAttack(target)) {
this.attackEntity(target);
this.attackEntity(hitEntity);
}
}
@@ -305,7 +344,7 @@ public class KillAura extends Module {
Entity entity = target;
if (entity == null) {
List<Entity> list = this.getTargets();
if (list != null && !list.isEmpty()) {
if (!list.isEmpty()) {
entity = list.get(0);
}
}
@@ -319,7 +358,8 @@ public class KillAura extends Module {
}
public void updateTargets() {
targetList = this.getTargets();
List<Entity> next = this.getTargets();
targetList = next != null ? next : new ArrayList<>();
}
public boolean isValidTarget(Entity entity) {
@@ -337,7 +377,7 @@ public class KillAura extends Module {
if (this.aboveTarget.getValue() && player.getY() >= mc.player.getY() + 0.05f) {
return true;
}
if (ZenClient.isOwner(entity.getName().getString())) return false;
// if (ZenClient.isOwner(entity.getName().getString())) return false;
}
if (Teams.isSameTeam(entity)) return false;
if (entity instanceof Player && !(Boolean) this.attackPlayer.getValue()) return false;
@@ -362,7 +402,7 @@ public class KillAura extends Module {
return false;
}
Vec3 vec3 = RotationUtil.closestPoint(mc.player.getEyePosition(), entity.getBoundingBox());
if (vec3.distanceTo(mc.player.getEyePosition()) > this.attackRange.getValue().floatValue()) {
if (vec3.distanceTo(mc.player.getEyePosition()) > this.aimRange.getValue().floatValue()) {
return false;
}
return RotationUtil.isEntityInFov(entity, this.fov.getValue().floatValue() / 2.0f);
@@ -372,6 +412,10 @@ public class KillAura extends Module {
if (mc.player == null || mc.gameMode == null || entity == null) {
return;
}
if (this.isWebPlacing()) {
return;
}
++this.attackTimes;
float currentYaw = mc.player.getYRot();
float currentPitch = mc.player.getXRot();
Rotation targetRot = RotationHandler.targetRotation != null
@@ -379,10 +423,20 @@ public class KillAura extends Module {
: (this.rotation != null ? this.rotation : new Rotation(currentYaw, currentPitch));
mc.player.setYRot(targetRot.getYaw());
mc.player.setXRot(targetRot.getPitch());
mc.gameMode.attack(mc.player, entity);
mc.player.swing(InteractionHand.MAIN_HAND);
boolean performAttack = !this.sprintSync.getValue() || this.sprintTickCounter % 2 == 0;
if (performAttack) {
mc.gameMode.attack(mc.player, entity);
mc.player.swing(InteractionHand.MAIN_HAND);
}
if (this.targetHud.getValue() && entity instanceof LivingEntity living) {
mc.player.magicCrit(living);
mc.player.crit(living);
}
mc.player.setYRot(currentYaw);
mc.player.setXRot(currentPitch);
if (this.rotationsMode.is("Snap")) {
this.sprintCounter = (int) mc.player.getCurrentItemAttackStrengthDelay();
}
}
private boolean isWebPlacing() {