Загрузка данных
package fun.wonderful.client.modules.impl.combat.components.rotations;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec2f;
import net.minecraft.util.math.Vec3d;
import fun.wonderful.api.QClient;
import fun.wonderful.api.storages.implement.RotationStorage;
import fun.wonderful.api.utils.combat.IdealHitUtils;
import fun.wonderful.api.utils.rotate.Rotation;
import fun.wonderful.api.utils.rotate.RotationUtils;
import fun.wonderful.client.modules.impl.combat.Aura;
import fun.wonderful.client.modules.impl.combat.components.RotationsSystem;
public class FuntimeRotation extends RotationsSystem implements QClient {
private final Aura aura;
private LivingEntity trackedTarget;
private Vec3d hitPoint;
private float pointX;
private float pointY;
private float pointZ;
private float pointTargetX;
private float pointTargetY;
private float pointTargetZ;
private int pointChangeIn;
private int pointChangeAfterCalls;
private float smoothYawFactor;
private float smoothPitchFactor;
private float smoothYawFactorTarget;
private float smoothPitchFactorTarget;
private int overshootTicks;
private float overshootYaw;
private float overshootPitch;
private float noiseTime;
private float driftYaw;
private float driftPitch;
public FuntimeRotation(Aura aura) {
this.aura = aura;
reset();
}
public void reset() {
trackedTarget = null;
hitPoint = null;
pointX = 0.0F;
pointY = 0.0F;
pointZ = 0.0F;
pointTargetX = 0.0F;
pointTargetY = 0.0F;
pointTargetZ = 0.0F;
pointChangeIn = 0;
pointChangeAfterCalls = randomCallWindow();
smoothYawFactor = 0.082F;
smoothPitchFactor = 0.064F;
smoothYawFactorTarget = smoothYawFactor;
smoothPitchFactorTarget = smoothPitchFactor;
overshootTicks = 0;
overshootYaw = 0.0F;
overshootPitch = 0.0F;
noiseTime = (float) (Math.random() * Math.PI * 2.0);
driftYaw = 0.0F;
driftPitch = 0.0F;
}
@Override
public void updateRotations(LivingEntity target) {
if (mc.player == null || target == null) {
return;
}
boolean attackMoment = isAttackMoment();
if (trackedTarget != target) {
trackedTarget = target;
resetPointState(target);
}
if (++pointChangeIn >= pointChangeAfterCalls) {
selectNewPointTarget(target);
pointChangeIn = 0;
pointChangeAfterCalls = randomCallWindow();
}
pointX = MathHelper.lerp(0.065F, pointX, pointTargetX);
pointY = MathHelper.lerp(0.065F, pointY, pointTargetY);
pointZ = MathHelper.lerp(0.065F, pointZ, pointTargetZ);
hitPoint = getHitPoint(target);
smoothYawFactor = MathHelper.lerp(0.07F, smoothYawFactor, smoothYawFactorTarget);
smoothPitchFactor = MathHelper.lerp(0.07F, smoothPitchFactor, smoothPitchFactorTarget);
Vec2f current = new Vec2f(mc.player.getYaw(), mc.player.getPitch());
Vec2f baseRot = RotationUtils.getRotations(getPredictedPoint(target, hitPoint));
float rawYawDelta = MathHelper.wrapDegrees(baseRot.x - current.x);
float rawPitchDelta = baseRot.y - current.y;
updateOvershoot(rawYawDelta, rawPitchDelta, attackMoment);
updateDriftAndNoise(rawYawDelta, rawPitchDelta, attackMoment);
float targetYaw = baseRot.x + driftYaw + overshootYaw;
float targetPitch = MathHelper.clamp(baseRot.y + driftPitch + overshootPitch, -89.5F, 89.5F);
float yawDelta = MathHelper.wrapDegrees(targetYaw - current.x);
float pitchDelta = targetPitch - current.y;
float easedYawStep = buildAxisStep(yawDelta, smoothYawFactor, true, attackMoment);
float easedPitchStep = buildAxisStep(pitchDelta, smoothPitchFactor, false, attackMoment);
float snappedYaw = snapAngle(current.x, current.x + easedYawStep);
float snappedPitch = MathHelper.clamp(snapAngle(current.y, current.y + easedPitchStep), -89.5F, 89.5F);
Vec2f targetRot = new Vec2f(snappedYaw, snappedPitch);
aura.setRotationSnapshots(current, targetRot);
float yawSpeed = MathHelper.clamp(Math.abs(MathHelper.wrapDegrees(snappedYaw - current.x)), getSensitivityGcd(), attackMoment ? 7.5F : 4.25F);
float pitchSpeed = MathHelper.clamp(Math.abs(snappedPitch - current.y), getSensitivityGcd(), attackMoment ? 4.75F : 2.8F);
RotationStorage.update(
new Rotation(snappedYaw, snappedPitch),
yawSpeed,
pitchSpeed,
yawSpeed,
pitchSpeed,
1,
1,
Aura.clientLook.isState()
);
rotate = targetRot;
}
private void resetPointState(LivingEntity target) {
Box box = target.getBoundingBox();
pointX = randomRange(-0.18F, 0.18F);
pointY = randomRange(0.34F, 0.76F);
pointZ = randomRange(-0.18F, 0.18F);
pointTargetX = pointX;
pointTargetY = pointY;
pointTargetZ = pointZ;
hitPoint = new Vec3d(
box.getCenter().x + box.getLengthX() * pointX,
box.minY + box.getLengthY() * pointY,
box.getCenter().z + box.getLengthZ() * pointZ
);
selectNewPointTarget(target);
}
private void selectNewPointTarget(LivingEntity target) {
Box box = target.getBoundingBox();
pointTargetX = randomRange(-0.42F, 0.42F);
pointTargetY = randomRange(0.18F, 0.88F);
pointTargetZ = randomRange(-0.42F, 0.42F);
if (Math.abs(box.getLengthX() * (pointTargetX - pointX)) < 0.02D) {
pointTargetX = MathHelper.clamp(pointTargetX + Math.copySign(0.08F, pointTargetX == 0.0F ? 1.0F : pointTargetX), -0.46F, 0.46F);
}
if (Math.abs(box.getLengthY() * (pointTargetY - pointY)) < 0.02D) {
pointTargetY = MathHelper.clamp(pointTargetY + 0.06F, 0.16F, 0.90F);
}
if (Math.abs(box.getLengthZ() * (pointTargetZ - pointZ)) < 0.02D) {
pointTargetZ = MathHelper.clamp(pointTargetZ - Math.copySign(0.08F, pointTargetZ == 0.0F ? 1.0F : pointTargetZ), -0.46F, 0.46F);
}
smoothYawFactorTarget = randomRange(0.065F, 0.11F);
smoothPitchFactorTarget = randomRange(0.05F, 0.09F);
}
private Vec3d getHitPoint(LivingEntity target) {
Box box = target.getBoundingBox();
return new Vec3d(
box.getCenter().x + box.getLengthX() * pointX,
box.minY + box.getLengthY() * pointY,
box.getCenter().z + box.getLengthZ() * pointZ
);
}
private void updateOvershoot(float yawDelta, float pitchDelta, boolean attackMoment) {
if (overshootTicks > 0) {
overshootYaw *= 0.38F;
overshootPitch *= 0.38F;
overshootTicks--;
return;
}
overshootYaw = 0.0F;
overshootPitch = 0.0F;
float sharpTurn = Math.abs(yawDelta) + Math.abs(pitchDelta) * 0.45F;
if (attackMoment && sharpTurn > 46.0F && Math.random() < 0.07D) {
overshootTicks = 1 + (int) (Math.random() * 2.0D);
overshootYaw = Math.copySign(randomRange(0.5F, 1.05F), yawDelta == 0.0F ? 1.0F : yawDelta);
overshootPitch = Math.copySign(randomRange(0.12F, 0.35F), pitchDelta == 0.0F ? 1.0F : pitchDelta);
}
}
private void updateDriftAndNoise(float yawDelta, float pitchDelta, boolean attackMoment) {
float yawAbs = Math.abs(yawDelta);
float pitchAbs = Math.abs(pitchDelta);
boolean stableHold = yawAbs < 1.6F && pitchAbs < 1.2F;
noiseTime += attackMoment ? 0.12F : 0.075F;
driftYaw *= attackMoment ? 0.22F : 0.74F;
driftPitch *= attackMoment ? 0.22F : 0.74F;
if (stableHold) {
float yawAmp = randomRange(0.02F, 0.07F);
float pitchAmp = randomRange(0.02F, 0.06F);
driftYaw += (float) Math.sin(noiseTime * 0.95F) * yawAmp;
driftPitch += (float) Math.cos(noiseTime * 1.08F) * pitchAmp;
}
}
private float buildAxisStep(float delta, float smoothingFactor, boolean yawAxis, boolean attackMoment) {
float absDelta = Math.abs(delta);
if (absDelta < 1.0E-4F) {
return 0.0F;
}
float axisBias = yawAxis ? randomRange(0.82F, 0.98F) : randomRange(0.74F, 0.92F);
float attackBoost = attackMoment ? (yawAxis ? 1.10F : 1.04F) : 0.92F;
float eased = 1.0F - (float) Math.exp(-absDelta * smoothingFactor * axisBias * attackBoost);
float step = delta * eased;
float minStep = getSensitivityGcd();
float maxStep = yawAxis
? (attackMoment ? 5.8F : 3.2F)
: (attackMoment ? 3.6F : 2.1F);
return MathHelper.clamp(step, -maxStep, maxStep) + Math.copySign(Math.min(minStep, absDelta), delta) * 0.05F;
}
private float snapAngle(float current, float target) {
float gcd = getSensitivityGcd();
if (gcd <= 0.0F) {
return target;
}
float delta = MathHelper.wrapDegrees(target - current);
float snappedDelta = Math.round(delta / gcd) * gcd;
if (snappedDelta == 0.0F && Math.abs(delta) >= gcd * 0.35F) {
snappedDelta = Math.copySign(gcd, delta);
}
return current + snappedDelta;
}
private float getSensitivityGcd() {
float sensitivity = mc.options.getMouseSensitivity().getValue().floatValue();
float f = sensitivity * 0.6F + 0.2F;
return f * f * f * 8.0F;
}
private boolean isAttackMoment() {
float attackThreshold = Math.max(0.82F, IdealHitUtils.getAICooldown() - 0.12F);
boolean readyByCooldown = mc.player.getAttackCooldownProgress(1.5F) >= attackThreshold;
boolean fallingForCrit = !mc.player.isOnGround()
&& mc.player.getVelocity().y < 0.0D
&& mc.player.fallDistance > 0.0F;
return readyByCooldown || fallingForCrit;
}
private int randomCallWindow() {
return 3 + (int) (Math.random() * 5.0D);
}
private float randomRange(float min, float max) {
return min + (float) Math.random() * (max - min);
}
}