Add constant speed straight moving target prediction

This commit is contained in:
Redstone1024 2024-08-28 16:56:04 +08:00
parent 4885d3fef8
commit 9bc3a40748

View File

@ -51,26 +51,44 @@ public class Prediction extends Module {
.name("prediction-level") .name("prediction-level")
.description("The intelligence level for entity position prediction.") .description("The intelligence level for entity position prediction.")
.defaultValue(0) .defaultValue(0)
.range(0, 1) .range(0, 2)
.sliderMax(1) .sliderMax(2)
.build() .build()
); );
public final Setting<Integer> iterationSteps = sgGeneral.add(new IntSetting.Builder() public final Setting<Integer> simulationAngleSteps = sgGeneral.add(new IntSetting.Builder()
.name("iteration-steps") .name("simulation-angle-steps")
.description("How many iterations to aim projectiles. Zero for no limit.") .description("How many steps to simulate aim angle. Zero for no limit.")
.defaultValue(20) .defaultValue(20)
.sliderMax(100) .sliderMax(100)
.visible(() -> predictionLevel.get() >= 1) .visible(() -> predictionLevel.get() >= 1)
.build() .build()
); );
public final Setting<Double> iterationEpsilon = sgGeneral.add(new DoubleSetting.Builder() public final Setting<Double> angleEpsilon = sgGeneral.add(new DoubleSetting.Builder()
.name("iteration-epsilon") .name("angle-epsilon")
.description("How much accuracy is needed to aim a projectile.") .description("How much accuracy to simulate aim angle.")
.defaultValue(0.5) .defaultValue(0.5)
.sliderMax(1) .sliderMax(1)
.visible(() -> predictionLevel.get() >= 1 && iterationSteps.get() == 0) .visible(() -> predictionLevel.get() >= 1 && simulationAngleSteps.get() == 0)
.build()
);
public final Setting<Integer> simulationTargetSteps = sgGeneral.add(new IntSetting.Builder()
.name("simulation-target-steps")
.description("How many steps to simulate aim target. Zero for no limit.")
.defaultValue(2)
.sliderMax(10)
.visible(() -> predictionLevel.get() >= 2)
.build()
);
public final Setting<Double> targetEpsilon = sgGeneral.add(new DoubleSetting.Builder()
.name("target-epsilon")
.description("How much accuracy to simulate aim target.")
.defaultValue(1)
.sliderMax(4)
.visible(() -> predictionLevel.get() >= 2 && simulationTargetSteps.get() == 0)
.build() .build()
); );
@ -158,6 +176,15 @@ public class Prediction extends Module {
.build() .build()
); );
public final Setting<Integer> projectTickOffset = sgSimulation.add(new IntSetting.Builder()
.name("project-tick-offset")
.description("What is the offset of the project tick.")
.defaultValue(2)
.sliderMin(0)
.sliderMax(20)
.build()
);
public final Setting<Double> gravity = sgSimulation.add(new DoubleSetting.Builder() public final Setting<Double> gravity = sgSimulation.add(new DoubleSetting.Builder()
.name("gravity") .name("gravity")
.description("What is the acceleration of gravity on the projectile.") .description("What is the acceleration of gravity on the projectile.")
@ -244,6 +271,22 @@ public class Prediction extends Module {
.build() .build()
); );
private final Setting<SettingColor> targetSideColor = sgRender.add(new ColorSetting.Builder()
.name("target-side-color")
.description("The side color for target.")
.defaultValue(new SettingColor(255, 0, 0, 35))
.visible(enableRender::get)
.build()
);
private final Setting<SettingColor> targetLineColor = sgRender.add(new ColorSetting.Builder()
.name("target-line-color")
.description("The line color for target.")
.defaultValue(new SettingColor(255, 0, 0))
.visible(enableRender::get)
.build()
);
private final Setting<SettingColor> missSideColor = sgRender.add(new ColorSetting.Builder() private final Setting<SettingColor> missSideColor = sgRender.add(new ColorSetting.Builder()
.name("miss-side-color") .name("miss-side-color")
.description("The side color for miss.") .description("The side color for miss.")
@ -287,15 +330,76 @@ public class Prediction extends Module {
private void onTick(TickEvent.Post event) { private void onTick(TickEvent.Post event) {
clearPath(); clearPath();
calculateTarget(); calculateTarget();
if (targetEntity != null) calculateAngle();
} }
@EventHandler @EventHandler
private void onRender(Render3DEvent event) { private void onRender(Render3DEvent event) {
float tickDelta = mc.world.getTickManager().isFrozen() ? 1 : event.tickDelta;
if (aimAssist.get()) aim(event.tickDelta); if (aimAssist.get()) aim(event.tickDelta);
if (enableRender.get()) renderPath(event);
if (!enableRender.get()) return;
Vector3d lastPoint = null;
for (Vector3d point : points) {
if (lastPoint != null) {
event.renderer.line(
lastPoint.x, lastPoint.y, lastPoint.z, point.x, point.y, point.z,
isHitTarget ? hitLineColor.get() : missLineColor.get()
);
}
lastPoint = point;
}
if (hitQuad) {
if (hitQuadHorizontal) {
event.renderer.sideHorizontal(
hitQuad1.x, hitQuad1.y, hitQuad1.z, hitQuad1.x + 0.5, hitQuad1.z + 0.5,
isHitTarget ? hitSideColor.get() : missSideColor.get(),
isHitTarget ? hitLineColor.get() : missLineColor.get(),
shapeMode.get()
);
}
else {
event.renderer.sideVertical(
hitQuad1.x, hitQuad1.y, hitQuad1.z, hitQuad2.x, hitQuad2.y, hitQuad2.z,
isHitTarget ? hitSideColor.get() : missSideColor.get(),
isHitTarget ? hitLineColor.get() : missLineColor.get(),
shapeMode.get()
);
}
}
if (targetEntity != null) {
if (targetCompleted) {
if (targetEntity.getBoundingBox().getCenter().distanceTo(targetBox.getCenter()) < 0.5) {
event.renderer.box(
targetEntity.getBoundingBox(),
isHitTarget ? hitSideColor.get() : missSideColor.get(),
isHitTarget ? hitLineColor.get() : missLineColor.get(),
shapeMode.get(), 0
);
}
else {
event.renderer.box(
targetEntity.getBoundingBox(),
targetSideColor.get(), targetLineColor.get(),
shapeMode.get(), 0
);
event.renderer.box(
targetBox,
isHitTarget ? hitSideColor.get() : missSideColor.get(),
isHitTarget ? hitLineColor.get() : missLineColor.get(),
shapeMode.get(), 0
);
}
}
else {
event.renderer.box(
targetEntity.getBoundingBox(),
targetSideColor.get(), targetLineColor.get(),
shapeMode.get(), 0
);
}
}
} }
@Override @Override
@ -318,19 +422,20 @@ public class Prediction extends Module {
return !(entity instanceof AnimalEntity) || babies.get() || !((AnimalEntity) entity).isBaby(); return !(entity instanceof AnimalEntity) || babies.get() || !((AnimalEntity) entity).isBaby();
} }
private double getCurrentCharge(){ private double getCurrentCharge() {
ItemStack itemStack = mc.player.getMainHandStack(); ItemStack itemStack = mc.player.getMainHandStack();
if (!(itemStack.getItem() instanceof BowItem)) { if (!(itemStack.getItem() instanceof BowItem)) {
itemStack = mc.player.getOffHandStack(); itemStack = mc.player.getOffHandStack();
if (!(itemStack.getItem() instanceof BowItem)) return 0.0; if (!(itemStack.getItem() instanceof BowItem)) return 0.0;
} }
return BowItem.getPullProgress(mc.player.getItemUseTime()); return BowItem.getPullProgress(mc.player.getItemUseTime() + projectTickOffset.get());
} }
// These variables are set by the calculateTarget() // These variables are set by the calculateTarget()
private Entity targetEntity; private Entity targetEntity;
private Box targetBox; private Box targetBox;
private Vector3d targetLastPosition;
// These variables are set by the calculateAngle() // These variables are set by the calculateAngle()
private boolean targetCompleted; private boolean targetCompleted;
@ -345,6 +450,7 @@ public class Prediction extends Module {
private final Vector3d hitQuad1 = new Vector3d(); private final Vector3d hitQuad1 = new Vector3d();
private final Vector3d hitQuad2 = new Vector3d(); private final Vector3d hitQuad2 = new Vector3d();
private boolean isHitTarget; private boolean isHitTarget;
private int hitTime;
private void clearPath() { private void clearPath() {
for (Vector3d point : points) vectorPool.free(point); for (Vector3d point : points) vectorPool.free(point);
@ -377,7 +483,7 @@ public class Prediction extends Module {
HitResult hitResult = null; HitResult hitResult = null;
Direction hitDirection = null; Direction hitDirection = null;
for (int i = 0; i < (simulationSteps.get() > 0 ? simulationSteps.get() : Integer.MAX_VALUE) && !hitQuad && !isHitTarget; i++) { for (hitTime = 0; hitTime < (simulationSteps.get() > 0 ? simulationSteps.get() : Integer.MAX_VALUE) && !hitQuad && !isHitTarget; hitTime++) {
points.add(vectorPool.get().set(position)); points.add(vectorPool.get().set(position));
lastPosition.set(position); lastPosition.set(position);
@ -500,56 +606,37 @@ public class Prediction extends Module {
} }
} }
private void renderPath(Render3DEvent event) {
Vector3d lastPoint = null;
for (Vector3d point : points) {
if (lastPoint != null) {
event.renderer.line(
lastPoint.x, lastPoint.y, lastPoint.z, point.x, point.y, point.z,
isHitTarget ? hitLineColor.get() : missLineColor.get()
);
}
lastPoint = point;
}
if (hitQuad) {
if (hitQuadHorizontal) {
event.renderer.sideHorizontal(
hitQuad1.x, hitQuad1.y, hitQuad1.z, hitQuad1.x + 0.5, hitQuad1.z + 0.5,
isHitTarget ? hitSideColor.get() : missSideColor.get(),
isHitTarget ? hitLineColor.get() : missLineColor.get(),
shapeMode.get()
);
}
else {
event.renderer.sideVertical(
hitQuad1.x, hitQuad1.y, hitQuad1.z, hitQuad2.x, hitQuad2.y, hitQuad2.z,
isHitTarget ? hitSideColor.get() : missSideColor.get(),
isHitTarget ? hitLineColor.get() : missLineColor.get(),
shapeMode.get()
);
}
}
if (targetEntity != null) {
Box box = targetEntity.getBoundingBox();
event.renderer.box(
targetBox,
isHitTarget ? hitSideColor.get() : missSideColor.get(),
isHitTarget ? hitLineColor.get() : missLineColor.get(),
shapeMode.get(), 0
);
}
}
private void calculateTarget() { private void calculateTarget() {
if (mc.options.attackKey.isPressed() || !isSelectableTarget(targetEntity)) { if (mc.options.attackKey.isPressed() || !isSelectableTarget(targetEntity)) {
targetEntity = TargetUtils.get(this::isSelectableTarget, priority.get()); targetEntity = TargetUtils.get(this::isSelectableTarget, priority.get());
if (targetEntity != null) targetLastPosition = new Vector3d(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ());
} }
if (targetEntity == null) return; if (targetEntity == null) return;
targetBox = targetEntity.getBoundingBox(); targetBox = targetEntity.getBoundingBox();
calculateAngle();
if (predictionLevel.get() >= 2) {
Box lastTargetBox = mc.player.getBoundingBox();
for (int i = 0; simulationTargetSteps.get() > 0 ? i < simulationTargetSteps.get() :
targetBox.getCenter().distanceTo(lastTargetBox.getCenter()) > targetEpsilon.get(); i++) {
if (!targetCompleted) break;
Vec3d velocity = new Vec3d(
targetEntity.getX() - targetLastPosition.x,
0,
targetEntity.getZ() - targetLastPosition.z
);
targetBox = targetEntity.getBoundingBox().offset(velocity.multiply(hitTime + projectTickOffset.get()));
calculateAngle();
}
}
targetLastPosition = new Vector3d(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ());
} }
private double calculateHeightOffset(double pitch) { private double calculateHeightOffset(double pitch) {
@ -653,7 +740,7 @@ public class Prediction extends Module {
{ {
double minPitch = -90.0; double minPitch = -90.0;
double maxPitch = 90.0; double maxPitch = 90.0;
for (int i = 0; iterationSteps.get() > 0 ? i < iterationSteps.get() : maxPitch - minPitch > iterationEpsilon.get(); i++) { for (int i = 0; simulationAngleSteps.get() > 0 ? i < simulationAngleSteps.get() : maxPitch - minPitch > angleEpsilon.get(); i++) {
double mid1 = minPitch + (maxPitch - minPitch) / 3.0; double mid1 = minPitch + (maxPitch - minPitch) / 3.0;
double mid2 = maxPitch - (maxPitch - minPitch) / 3.0; double mid2 = maxPitch - (maxPitch - minPitch) / 3.0;
double mid1Height = calculateHeightOffset(mid1); double mid1Height = calculateHeightOffset(mid1);
@ -672,7 +759,7 @@ public class Prediction extends Module {
{ {
double minPitch = highestPitch; double minPitch = highestPitch;
double maxPitch = 90.0; double maxPitch = 90.0;
for (int i = 0; iterationSteps.get() > 0 ? i < iterationSteps.get() : maxPitch - minPitch > iterationEpsilon.get(); i++) { for (int i = 0; simulationAngleSteps.get() > 0 ? i < simulationAngleSteps.get() : maxPitch - minPitch > angleEpsilon.get(); i++) {
double mid = (minPitch + maxPitch) / 2.0; double mid = (minPitch + maxPitch) / 2.0;
double midHeight = calculateHeightOffset(mid); double midHeight = calculateHeightOffset(mid);
if (Double.isNaN(midHeight)) { if (Double.isNaN(midHeight)) {
@ -690,7 +777,7 @@ public class Prediction extends Module {
findPitch = true; findPitch = true;
targetPitch = targetLowPitch; targetPitch = targetLowPitch;
targetYaw = Rotations.getYaw(targetEntity); targetYaw = Rotations.getYaw(targetBox.getCenter());
targetCharge = getCurrentCharge(); targetCharge = getCurrentCharge();
targetCompleted = true; targetCompleted = true;
@ -775,7 +862,7 @@ public class Prediction extends Module {
double targetHighPitch = highestPitch; double targetHighPitch = highestPitch;
double minPitch = -90.0; double minPitch = -90.0;
double maxPitch = highestPitch; double maxPitch = highestPitch;
for (int i = 0; iterationSteps.get() > 0 ? i < iterationSteps.get() : maxPitch - minPitch > iterationEpsilon.get(); i++) { for (int i = 0; simulationAngleSteps.get() > 0 ? i < simulationAngleSteps.get() : maxPitch - minPitch > angleEpsilon.get(); i++) {
double mid = (minPitch + maxPitch) / 2.0; double mid = (minPitch + maxPitch) / 2.0;
double midHeight = calculateHeightOffset(mid); double midHeight = calculateHeightOffset(mid);
if (Double.isNaN(midHeight)) { if (Double.isNaN(midHeight)) {
@ -791,7 +878,7 @@ public class Prediction extends Module {
targetHighPitch = (minPitch + maxPitch) / 2.0; targetHighPitch = (minPitch + maxPitch) / 2.0;
targetPitch = targetHighPitch; targetPitch = targetHighPitch;
targetYaw = Rotations.getYaw(targetEntity); targetYaw = Rotations.getYaw(targetBox.getCenter());
targetCharge = getCurrentCharge(); targetCharge = getCurrentCharge();
targetCompleted = true; targetCompleted = true;