package nuclear.module.impl.combat;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.monster.MonsterEntity;
import net.minecraft.entity.passive.AnimalEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Hand;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.vector.Vector2f;
import nuclear.control.Manager;
import nuclear.control.events.Event;
import nuclear.control.events.impl.player.EventInput;
import nuclear.control.events.impl.player.EventMotion;
import nuclear.control.events.impl.player.EventUpdate;
import nuclear.module.TypeList;
import nuclear.module.api.Annotation;
import nuclear.module.api.Module;
import nuclear.module.settings.imp.BooleanSetting;
import nuclear.module.settings.imp.ModeSetting;
import nuclear.module.settings.imp.MultiBoxSetting;
import nuclear.module.settings.imp.SliderSetting;
import nuclear.utils.move.MoveUtil;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
@Annotation(name = "AttackAura", type = TypeList.Combat, desc = "Автоатака с ротациями")
public class AttackAura extends Module {
public static LivingEntity target;
public static Vector2f rotate = new Vector2f(0.0F, 0.0F);
private float lastSentYaw;
private float lastSentPitch;
private final SpookyTimeState spookyState = new SpookyTimeState();
private static class RotationProfile {
private final boolean snap;
private final boolean visualThirdPerson;
private final float yawSpeedMul;
private final float pitchSpeedMul;
private final float yawJitter;
private final float pitchJitter;
private final float visualYawOffset;
private final float visualPitchMul;
private final float visualBodyStep;
private RotationProfile(boolean snap, boolean visualThirdPerson, float yawSpeedMul, float pitchSpeedMul,
float yawJitter, float pitchJitter, float visualYawOffset, float visualPitchMul, float visualBodyStep) {
this.snap = snap;
this.visualThirdPerson = visualThirdPerson;
this.yawSpeedMul = yawSpeedMul;
this.pitchSpeedMul = pitchSpeedMul;
this.yawJitter = yawJitter;
this.pitchJitter = pitchJitter;
this.visualYawOffset = visualYawOffset;
this.visualPitchMul = visualPitchMul;
this.visualBodyStep = visualBodyStep;
}
}
public final ModeSetting sortingMode = new ModeSetting("Сортировка", "Дистанция",
"Дистанция", "Здоровье", "Поле зрения");
public final ModeSetting rotationMode = new ModeSetting("Ротация", "Smooth",
"Smooth", "Snap", "Legit", "Spooky", "FunTime", "BMW", "LonyGrief", "SpookyTime");
public final ModeSetting sprintMode = new ModeSetting("Спринт", "Обычный",
"Обычный", "Легитный");
public final SliderSetting attackDistance = new SliderSetting("Дистанция", 3.1F, 2.5F, 6.0F, 0.1F);
public final SliderSetting rotationSpeed = new SliderSetting("Скорость ротации", 28.0F, 1.0F, 180.0F, 1.0F);
public final MultiBoxSetting targetFilters = new MultiBoxSetting("Цели",
new BooleanSetting("Игроки", true),
new BooleanSetting("Мобы", true),
new BooleanSetting("Животные", false),
new BooleanSetting("Невидимки", true));
public final MultiBoxSetting featureSettings = new MultiBoxSetting("Настройки",
new BooleanSetting("Только криты", false),
new BooleanSetting("Водная коррекция", false),
new BooleanSetting("Сквозь стены", false),
new BooleanSetting("Не бить при еде", true));
public AttackAura() {
addSettings(sortingMode, rotationMode, sprintMode, attackDistance, rotationSpeed, targetFilters, featureSettings);
}
public static LivingEntity getTarget() {
return target;
}
@Override
public boolean onEvent(Event event) {
if (mc.player == null || mc.world == null) {
return false;
}
RotationProfile profile = getRotationProfile();
if (event instanceof EventInput) {
EventInput input = (EventInput) event;
if (target != null && rotate != null) {
MoveUtil.fixMovement(input, rotate.x);
}
return false;
}
if (event instanceof EventMotion) {
EventMotion motion = (EventMotion) event;
if (target != null && rotate != null) {
motion.setYaw(rotate.x);
motion.setPitch(rotate.y);
lastSentYaw = rotate.x;
lastSentPitch = rotate.y;
applyVisualRotation(profile, rotate.x, rotate.y);
}
return false;
}
if (!(event instanceof EventUpdate)) {
return false;
}
target = findBestTarget();
if (target == null) {
rotate = new Vector2f(mc.player.rotationYaw, mc.player.rotationPitch);
if (rotationMode.is("SpookyTime")) {
SpookyTimeRotation.RotationResult result = spookyState.calculate(
System.currentTimeMillis(),
rotate.x, rotate.y,
rotate.x, rotate.y,
lastSentYaw, lastSentPitch,
0.005,
this.isEnabled(),
false
);
if (result != null) {
rotate = new Vector2f(result.yaw, result.pitch);
}
}
return false;
}
float[] rotations = getRotationsToEntity(target);
applyRotation(rotations[0], rotations[1], profile);
if (canAttack(target) && mc.playerController != null) {
mc.playerController.attackEntity(mc.player, target);
mc.player.swingArm(Hand.MAIN_HAND);
}
return false;
}
private void applyVisualRotation(RotationProfile profile, float yaw, float pitch) {
if (!profile.visualThirdPerson) {
return;
}
float visualYaw = MathHelper.wrapDegrees(yaw + profile.visualYawOffset);
float visualPitch = MathHelper.clamp(pitch * profile.visualPitchMul, -90.0F, 90.0F);
float bodyDelta = MathHelper.wrapDegrees(visualYaw - mc.player.renderYawOffset);
float bodyYaw = mc.player.renderYawOffset + MathHelper.clamp(bodyDelta, -profile.visualBodyStep, profile.visualBodyStep);
mc.player.rotationYawHead = visualYaw;
mc.player.prevRotationYawHead = visualYaw;
mc.player.rotationPitchHead = visualPitch;
mc.player.prevRotationPitchHead = visualPitch;
mc.player.renderYawOffset = bodyYaw;
mc.player.prevRenderYawOffset = bodyYaw;
}
private LivingEntity findBestTarget() {
List<LivingEntity> candidates = new ArrayList<>();
double range = attackDistance.getValue().doubleValue();
for (Entity entity : mc.world.getAllEntities()) {
if (!(entity instanceof LivingEntity)) {
continue;
}
LivingEntity living = (LivingEntity) entity;
if (!isValidTarget(living, range)) {
continue;
}
candidates.add(living);
}
if (candidates.isEmpty()) {
return null;
}
sortTargets(candidates);
return candidates.get(0);
}
private boolean isValidTarget(LivingEntity living, double range) {
if (living == null || living == mc.player || !living.isAlive() || living.getHealth() <= 0.0F) {
return false;
}
if (AntiBot.isBot(living)) {
return false;
}
if (mc.player.getDistance(living) > range) {
return false;
}
if (!targetFilters.get("Невидимки") && living.isInvisible()) {
return false;
}
if (!featureSettings.get("Сквозь стены") && !mc.player.canEntityBeSeen(living)) {
return false;
}
if (living instanceof PlayerEntity) {
if (Manager.FRIEND_MANAGER != null && living.getName() != null
&& Manager.FRIEND_MANAGER.isFriend(living.getName().getString())) {
return false;
}
return targetFilters.get("Игроки");
}
if (living instanceof MonsterEntity) {
return targetFilters.get("Мобы");
}
if (living instanceof AnimalEntity) {
return targetFilters.get("Животные");
}
return targetFilters.get("Мобы");
}
private void sortTargets(List<LivingEntity> targets) {
if (sortingMode.is("Здоровье")) {
targets.sort(Comparator.comparingDouble(LivingEntity::getHealth));
return;
}
if (sortingMode.is("Поле зрения")) {
targets.sort(Comparator.comparingDouble(this::getFovDiff));
return;
}
targets.sort(Comparator.comparingDouble(mc.player::getDistance));
}
private double getFovDiff(LivingEntity targetEntity) {
float[] rot = getRotationsToEntity(targetEntity);
float baseYaw = rotate != null ? rotate.x : mc.player.rotationYaw;
float basePitch = rotate != null ? rotate.y : mc.player.rotationPitch;
float yawDiff = Math.abs(MathHelper.wrapDegrees(rot[0] - baseYaw));
float pitchDiff = Math.abs(rot[1] - basePitch);
return yawDiff + pitchDiff * 0.35D;
}
private boolean canAttack(LivingEntity targetEntity) {
if (targetEntity == null) {
return false;
}
if (featureSettings.get("Не бить при еде") && mc.player.isHandActive()) {
return false;
}
if (featureSettings.get("Только криты")) {
boolean canCrit = !mc.player.isOnGround() && mc.player.fallDistance > 0.0F && !mc.player.isInWater() && !mc.player.isOnLadder();
if (!canCrit) {
return false;
}
}
return mc.player.getCooledAttackStrength(0.5F) >= 0.92F;
}
private float[] getRotationsToEntity(LivingEntity entity) {
double dx = entity.getPosX() - mc.player.getPosX();
double dz = entity.getPosZ() - mc.player.getPosZ();
double dy = (entity.getPosYEye() - 0.15D) - mc.player.getPosYEye();
double dist = Math.sqrt(dx * dx + dz * dz);
float yaw = (float) (Math.toDegrees(Math.atan2(dz, dx)) - 90.0D);
float pitch = (float) (-Math.toDegrees(Math.atan2(dy, dist)));
pitch = MathHelper.clamp(pitch, -90.0F, 90.0F);
return new float[]{yaw, pitch};
}
private void applyRotation(float targetYaw, float targetPitch, RotationProfile profile) {
float currentYaw = rotate != null ? rotate.x : mc.player.rotationYaw;
float currentPitch = rotate != null ? rotate.y : mc.player.rotationPitch;
if (rotationMode.is("SpookyTime")) {
SpookyTimeRotation.RotationResult result = spookyState.calculate(
System.currentTimeMillis(),
currentYaw, currentPitch,
targetYaw, targetPitch,
lastSentYaw, lastSentPitch,
0.005,
this.isEnabled(),
target != null
);
if (result != null) {
rotate = new Vector2f(result.yaw, result.pitch);
} else {
rotate = new Vector2f(currentYaw, currentPitch);
}
return;
}
if (profile.snap) {
rotate = new Vector2f(
MathHelper.wrapDegrees(targetYaw),
MathHelper.clamp(targetPitch, -90.0F, 90.0F)
);
return;
}
float speed = rotationSpeed.getValue().floatValue();
float profileYawSpeed = speed * profile.yawSpeedMul;
float profilePitchSpeed = speed * profile.pitchSpeedMul;
float ticks = mc.player.ticksExisted;
float modeYawJitter = (float) Math.sin(ticks * 0.37F) * profile.yawJitter;
float modePitchJitter = (float) Math.cos(ticks * 0.41F) * profile.pitchJitter;
float yaw = smoothRotation(currentYaw, targetYaw + modeYawJitter, profileYawSpeed);
float pitch = smoothRotation(currentPitch, targetPitch + modePitchJitter, profilePitchSpeed);
rotate = new Vector2f(yaw, MathHelper.clamp(pitch, -90.0F, 90.0F));
}
private RotationProfile getRotationProfile() {
if (rotationMode.is("Snap")) {
return new RotationProfile(true, true, 1.0F, 1.0F, 0.0F, 0.0F, 0.0F, 1.0F, 180.0F);
}
if (rotationMode.is("Legit")) {
return new RotationProfile(false, true, 0.43F, 0.38F, 0.45F, 0.22F, 0.0F, 0.98F, 20.0F);
}
if (rotationMode.is("Spooky")) {
return new RotationProfile(false, true, 1.35F, 1.28F, 1.35F, 0.70F, 1.6F, 1.05F, 38.0F);
}
if (rotationMode.is("FunTime")) {
return new RotationProfile(false, true, 0.82F, 0.76F, 0.90F, 0.40F, 0.8F, 1.0F, 30.0F);
}
if (rotationMode.is("BMW")) {
return new RotationProfile(false, true, 1.24F, 0.94F, 0.72F, 0.28F, -0.6F, 0.94F, 26.0F);
}
if (rotationMode.is("LonyGrief")) {
return new RotationProfile(false, true, 1.08F, 1.04F, 0.35F, 0.15F, 0.3F, 1.0F, 34.0F);
}
if (rotationMode.is("SpookyTime")) {
return new RotationProfile(false, true, 1.0F, 1.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F);
}
return new RotationProfile(false, true, 1.0F, 1.0F, 0.20F, 0.08F, 0.0F, 1.0F, 24.0F);
}
private float smoothRotation(float current, float targetValue, float maxStep) {
float delta = MathHelper.wrapDegrees(targetValue - current);
return current + MathHelper.clamp(delta, -maxStep, maxStep);
}
@Override
protected void onEnable() {
if (mc.player != null) {
rotate = new Vector2f(mc.player.rotationYaw, mc.player.rotationPitch);
lastSentYaw = mc.player.rotationYaw;
lastSentPitch = mc.player.rotationPitch;
}
spookyState.reset();
}
@Override
protected void onDisable() {
target = null;
if (mc.player != null) {
rotate = new Vector2f(mc.player.rotationYaw, mc.player.rotationPitch);
}
}
// ================== ВНУТРЕННИЙ КЛАСС ДЛЯ SPOOKY TIME ==================
private static class SpookyTimeState {
private static final Random RANDOM = new Random();
private static final long HOLD_LAST_ROTATION_MS = 20L;
private static final long RETURN_DURATION_MS = 70L;
private boolean returningToPreviousRotation = false;
private long holdUntilTimeMs = 0L;
private boolean smoothingBackToPreviousRotation = false;
private long smoothingStartTimeMs = 0L;
private float savedStartYaw = 0.0f;
private float savedStartPitch = 0.0f;
private float savedEndYaw = 0.0f;
private float savedEndPitch = 0.0f;
private boolean hadTargetOnPreviousTick = false;
private boolean moduleEnabledOnPreviousTick = false;
public void reset() {
returningToPreviousRotation = false;
holdUntilTimeMs = 0L;
smoothingBackToPreviousRotation = false;
smoothingStartTimeMs = 0L;
hadTargetOnPreviousTick = false;
moduleEnabledOnPreviousTick = false;
}
public SpookyTimeRotation.RotationResult calculate(
long currentTimeMs,
float currentYaw,
float currentPitch,
float targetYaw,
float targetPitch,
float lastServerYaw,
float lastServerPitch,
double mouseStep,
boolean moduleEnabled,
boolean hasTarget
) {
// Защита от NaN
currentYaw = validateAngle(currentYaw);
currentPitch = validateAngle(currentPitch);
targetYaw = validateAngle(targetYaw);
targetPitch = validateAngle(targetPitch);
lastServerYaw = validateAngle(lastServerYaw);
lastServerPitch = validateAngle(lastServerPitch);
boolean hasCombatTarget = moduleEnabled && hasTarget;
if (!hasCombatTarget) {
boolean targetWasLost = hadTargetOnPreviousTick;
boolean moduleWasDisabled = moduleEnabledOnPreviousTick && !moduleEnabled;
if ((targetWasLost || moduleWasDisabled) && !returningToPreviousRotation && !smoothingBackToPreviousRotation) {
returningToPreviousRotation = true;
holdUntilTimeMs = currentTimeMs + HOLD_LAST_ROTATION_MS;
smoothingBackToPreviousRotation = false;
smoothingStartTimeMs = 0L;
savedStartYaw = currentYaw;
savedStartPitch = currentPitch;
savedEndYaw = targetYaw;
savedEndPitch = targetPitch;
}
hadTargetOnPreviousTick = false;
moduleEnabledOnPreviousTick = moduleEnabled;
if (returningToPreviousRotation && currentTimeMs < holdUntilTimeMs) {
return snapToMouseStep(savedStartYaw, savedStartPitch, mouseStep, lastServerYaw, lastServerPitch);
}
if (returningToPreviousRotation && !smoothingBackToPreviousRotation) {
smoothingBackToPreviousRotation = true;
smoothingStartTimeMs = currentTimeMs;
}
if (!smoothingBackToPreviousRotation) {
return snapToMouseStep(targetYaw, targetPitch, mouseStep, lastServerYaw, lastServerPitch);
}
float returnProgress = clamp((currentTimeMs - smoothingStartTimeMs) / (float) RETURN_DURATION_MS, 0.0f, 1.0f);
float easedProgress = returnProgress * (0.5f + 0.5f * returnProgress);
float interpolatedYaw = lerpAngle(easedProgress, savedStartYaw, savedEndYaw);
float interpolatedPitch = clamp(lerp(easedProgress, savedStartPitch, savedEndPitch), -89.0f, 90.0f);
if (returnProgress >= 1.0f) {
returningToPreviousRotation = false;
holdUntilTimeMs = 0L;
smoothingBackToPreviousRotation = false;
smoothingStartTimeMs = 0L;
}
return snapToMouseStep(interpolatedYaw, interpolatedPitch, mouseStep, lastServerYaw, lastServerPitch);
}
hadTargetOnPreviousTick = true;
moduleEnabledOnPreviousTick = true;
returningToPreviousRotation = false;
holdUntilTimeMs = 0L;
smoothingBackToPreviousRotation = false;
smoothingStartTimeMs = 0L;
float yawDelta = wrapDegrees(targetYaw - currentYaw);
float pitchDelta = wrapDegrees(targetPitch - currentPitch);
float totalDelta = (float) Math.hypot(Math.abs(yawDelta), Math.abs(pitchDelta));
if (totalDelta < 0.0001f) {
totalDelta = 0.0001f;
}
float maxYawStep = Math.abs(yawDelta / totalDelta) * 130.0f;
float maxPitchStep = Math.abs(pitchDelta / totalDelta) * 130.0f;
float baseYaw = lerp(0.85f, currentYaw, currentYaw + clamp(yawDelta, -maxYawStep, maxYawStep));
float basePitch = lerp(0.85f, currentPitch, currentPitch + clamp(pitchDelta, -maxPitchStep, maxPitchStep));
float yawNoise = (float) (randomFloat(1.0f, 2.0f) * Math.sin(currentTimeMs / 160.0));
float pitchNoise = (float) (randomFloat(0.2f, 0.8f) * Math.cos(currentTimeMs / 160.0));
float finalYaw = baseYaw + yawNoise;
float finalPitch = clamp(basePitch + pitchNoise, -89.0f, 90.0f);
return snapToMouseStep(finalYaw, finalPitch, mouseStep, lastServerYaw, lastServerPitch);
}
private SpookyTimeRotation.RotationResult snapToMouseStep(
float targetYaw,
float targetPitch,
double mouseStep,
float lastServerYaw,
float lastServerPitch
) {
if (mouseStep <= 0.0) {
return new SpookyTimeRotation.RotationResult(targetYaw, targetPitch, 0.0, 0.0, 0.0);
}
float snappedYaw = quantize(targetYaw, lastServerYaw, mouseStep, true);
float snappedPitch = quantize(targetPitch, lastServerPitch, mouseStep, false);
return new SpookyTimeRotation.RotationResult(
snappedYaw,
clamp(snappedPitch, -90.0f, 90.0f),
0.0, 0.0, 0.0
);
}
private float quantize(float targetValue, float previousValue, double step, boolean wrapAngle) {
float deltaValue = wrapAngle ? wrapDegrees(targetValue - previousValue) : (targetValue - previousValue);
return previousValue + Math.round(deltaValue / (float) step) * (float) step;
}
private float clamp(float value, float minValue, float maxValue) {
return Math.max(minValue, Math.min(maxValue, value));
}
private float lerp(float progress, float startValue, float endValue) {
return startValue + progress * (endValue - startValue);
}
private float lerpAngle(float progress, float startAngle, float endAngle) {
return startAngle + progress * wrapDegrees(endAngle - startAngle);
}
private float wrapDegrees(float angle) {
if (Float.isNaN(angle) || Float.isInfinite(angle)) return 0.0f;
float wrappedAngle = angle % 360.0f;
if (wrappedAngle >= 180.0f) {
wrappedAngle -= 360.0f;
}
if (wrappedAngle < -180.0f) {
wrappedAngle += 360.0f;
}
return wrappedAngle;
}
private float randomFloat(float minValue, float maxValue) {
return minValue + RANDOM.nextFloat() * (maxValue - minValue);
}
private float validateAngle(float angle) {
if (Float.isNaN(angle) || Float.isInfinite(angle)) return 0.0f;
return angle;
}
}
// ================== ВСПОМОГАТЕЛЬНЫЙ КЛАСС РЕЗУЛЬТАТА ==================
public static final class SpookyTimeRotation {
public static final class RotationResult {
public final float yaw;
public final float pitch;
public final double aimOffsetX;
public final double aimOffsetY;
public final double aimOffsetZ;
public RotationResult(float yaw, float pitch, double aimOffsetX, double aimOffsetY, double aimOffsetZ) {
this.yaw = yaw;
this.pitch = pitch;
this.aimOffsetX = aimOffsetX;
this.aimOffsetY = aimOffsetY;
this.aimOffsetZ = aimOffsetZ;
}
}
}
}
&&