Add probe to try to attack the entity behind the block
This commit is contained in:
parent
fd19d4bf63
commit
4d16c1f7a1
@ -23,14 +23,12 @@ import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.passive.AnimalEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.projectile.ProjectileUtil;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.fluid.Fluids;
|
||||
import net.minecraft.item.BowItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.hit.EntityHitResult;
|
||||
import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.util.math.*;
|
||||
import net.minecraft.world.RaycastContext;
|
||||
@ -38,11 +36,14 @@ import org.joml.Vector3d;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
public class Prediction extends Module {
|
||||
private final SettingGroup sgGeneral = settings.getDefaultGroup();
|
||||
private final SettingGroup sgTarget = settings.createGroup("Target");
|
||||
private final SettingGroup sgSimulation = settings.createGroup("Simulation");
|
||||
private final SettingGroup sgProbe = settings.createGroup("Probe");
|
||||
private final SettingGroup sgSpeed = settings.createGroup("Aim Speed");
|
||||
private final SettingGroup sgRender = settings.createGroup("Render");
|
||||
|
||||
@ -55,14 +56,6 @@ public class Prediction extends Module {
|
||||
.build()
|
||||
);
|
||||
|
||||
public final Setting<Integer> simulationSteps = sgGeneral.add(new IntSetting.Builder()
|
||||
.name("simulation-steps")
|
||||
.description("How many steps to simulate projectiles. Zero for no limit.")
|
||||
.defaultValue(250)
|
||||
.sliderMax(5000)
|
||||
.build()
|
||||
);
|
||||
|
||||
public final Setting<Integer> iterationSteps = sgGeneral.add(new IntSetting.Builder()
|
||||
.name("iteration-steps")
|
||||
.description("How many iterations to aim projectiles. Zero for no limit.")
|
||||
@ -77,7 +70,7 @@ public class Prediction extends Module {
|
||||
.description("How much accuracy is needed to aim a projectile.")
|
||||
.defaultValue(0.5)
|
||||
.sliderMax(1)
|
||||
.visible(() -> iterationSteps.get() == 0)
|
||||
.visible(() -> predictionLevel.get() >= 1 && iterationSteps.get() == 0)
|
||||
.build()
|
||||
);
|
||||
|
||||
@ -148,6 +141,78 @@ public class Prediction extends Module {
|
||||
.build()
|
||||
);
|
||||
|
||||
public final Setting<Integer> simulationSteps = sgSimulation.add(new IntSetting.Builder()
|
||||
.name("simulation-steps")
|
||||
.description("How many steps to simulate projectiles. Zero for no limit.")
|
||||
.defaultValue(250)
|
||||
.sliderMax(5000)
|
||||
.build()
|
||||
);
|
||||
|
||||
public final Setting<Double> eyeHeightOffset = sgSimulation.add(new DoubleSetting.Builder()
|
||||
.name("eye-height-offset")
|
||||
.description("What is the offset of the actual projectile launch position from eye height.")
|
||||
.defaultValue(-0.1)
|
||||
.sliderMin(-1.0)
|
||||
.sliderMax(1.0)
|
||||
.build()
|
||||
);
|
||||
|
||||
public final Setting<Double> gravity = sgSimulation.add(new DoubleSetting.Builder()
|
||||
.name("gravity")
|
||||
.description("What is the acceleration of gravity on the projectile.")
|
||||
.defaultValue(0.05000000074505806)
|
||||
.sliderMin(0.04)
|
||||
.sliderMax(0.06)
|
||||
.build()
|
||||
);
|
||||
|
||||
public final Setting<Double> airDrag = sgSimulation.add(new DoubleSetting.Builder()
|
||||
.name("air-drag")
|
||||
.description("What is the drag value of the projectile in air.")
|
||||
.defaultValue(0.99)
|
||||
.sliderMin(0.95)
|
||||
.sliderMax(1.0)
|
||||
.build()
|
||||
);
|
||||
|
||||
public final Setting<Double> waterDrag = sgSimulation.add(new DoubleSetting.Builder()
|
||||
.name("water-drag")
|
||||
.description("What is the drag value of the projectile in water.")
|
||||
.defaultValue(0.6)
|
||||
.sliderMin(0)
|
||||
.sliderMax(1)
|
||||
.build()
|
||||
);
|
||||
|
||||
private final Setting<Boolean> enableProbe = sgProbe.add(new BoolSetting.Builder()
|
||||
.name("enable-probe")
|
||||
.description("Enable/disable block probes.")
|
||||
.defaultValue(false)
|
||||
.visible(() -> predictionLevel.get() >= 1)
|
||||
.build()
|
||||
);
|
||||
|
||||
private final Setting<Double> probeRange = sgProbe.add(new DoubleSetting.Builder()
|
||||
.name("probe-range")
|
||||
.description("The maximum range of probe placement.")
|
||||
.defaultValue(1)
|
||||
.range(0, 4)
|
||||
.sliderMax(4)
|
||||
.visible(enableProbe::get)
|
||||
.build()
|
||||
);
|
||||
|
||||
private final Setting<Double> probeInterval = sgProbe.add(new DoubleSetting.Builder()
|
||||
.name("probe-interval")
|
||||
.description("The minimum interval of probe placement.")
|
||||
.defaultValue(0.5)
|
||||
.range(0, 1)
|
||||
.sliderMax(1)
|
||||
.visible(enableProbe::get)
|
||||
.build()
|
||||
);
|
||||
|
||||
private final Setting<Boolean> instant = sgSpeed.add(new BoolSetting.Builder()
|
||||
.name("instant-look")
|
||||
.description("Instantly looks at the entity.")
|
||||
@ -166,7 +231,7 @@ public class Prediction extends Module {
|
||||
|
||||
private final Setting<Boolean> enableRender = sgRender.add(new BoolSetting.Builder()
|
||||
.name("enable-render")
|
||||
.description("Enable/Disable Render Indication.")
|
||||
.description("Enable/disable render indication.")
|
||||
.defaultValue(true)
|
||||
.build()
|
||||
);
|
||||
@ -220,11 +285,8 @@ public class Prediction extends Module {
|
||||
|
||||
@EventHandler
|
||||
private void onTick(TickEvent.Post event) {
|
||||
if (mc.options.attackKey.isPressed() || !isSelectableTarget(targetEntity)) {
|
||||
targetEntity = TargetUtils.get(this::isSelectableTarget, priority.get());
|
||||
}
|
||||
|
||||
clearPath();
|
||||
calculateTarget();
|
||||
if (targetEntity != null) calculateAngle();
|
||||
}
|
||||
|
||||
@ -232,9 +294,7 @@ public class Prediction extends Module {
|
||||
private void onRender(Render3DEvent event) {
|
||||
float tickDelta = mc.world.getTickManager().isFrozen() ? 1 : event.tickDelta;
|
||||
|
||||
boolean canAim = aimAssist.get() && (isHitTarget || !aimOnlyHit.get()) && mc.options.useKey.isPressed() && InvUtils.testInHands(Items.BOW);
|
||||
|
||||
if (canAim) aim(event.tickDelta);
|
||||
if (aimAssist.get()) aim(event.tickDelta);
|
||||
if (enableRender.get()) renderPath(event);
|
||||
}
|
||||
|
||||
@ -268,29 +328,22 @@ public class Prediction extends Module {
|
||||
return BowItem.getPullProgress(mc.player.getItemUseTime());
|
||||
}
|
||||
|
||||
private static final double gravity = 0.05000000074505806;
|
||||
private static final double airDrag = 0.99;
|
||||
private static final double waterDrag = 0.6;
|
||||
|
||||
// These variables are set by the onTick()
|
||||
// These variables are set by the calculateTarget()
|
||||
private Entity targetEntity;
|
||||
private Box targetBox;
|
||||
|
||||
// These variables are set by the calculateAngle()
|
||||
private boolean targetCompleted;
|
||||
private double targetYaw;
|
||||
private double targetPitch;
|
||||
private double targetCharge;
|
||||
|
||||
// These variables are set by the calculatePath() for prediction level >= 1
|
||||
private double targetHighPitch;
|
||||
private double targetLowPitch;
|
||||
|
||||
// These variables are set by the calculatePath()
|
||||
private final Pool<Vector3d> vectorPool = new Pool<>(Vector3d::new);
|
||||
private final List<Vector3d> points = new ArrayList<>();
|
||||
private boolean hitQuad = false, hitQuadHorizontal = false;
|
||||
private final Vector3d hitQuad1 = new Vector3d();
|
||||
private final Vector3d hitQuad2 = new Vector3d();
|
||||
private Entity collidingEntity = null;
|
||||
private boolean isHitTarget;
|
||||
|
||||
private void clearPath() {
|
||||
@ -298,7 +351,6 @@ public class Prediction extends Module {
|
||||
points.clear();
|
||||
|
||||
hitQuad = false;
|
||||
collidingEntity = null;
|
||||
isHitTarget = false;
|
||||
}
|
||||
|
||||
@ -310,7 +362,7 @@ public class Prediction extends Module {
|
||||
Vector3d lastPosition = new Vector3d(0.0, 0.0, 0.0);
|
||||
Vector3d position = new Vector3d(0.0, 0.0, 0.0);
|
||||
Vector3d velocity = new Vector3d(0.0, 0.0, 0.0);
|
||||
position.set(mc.player.getX(), mc.player.getY(), mc.player.getZ()).add(0, mc.player.getEyeHeight(mc.player.getPose()), 0);
|
||||
position.set(mc.player.getX(), mc.player.getY(), mc.player.getZ()).add(0, mc.player.getEyeHeight(mc.player.getPose()) + eyeHeightOffset.get(), 0);
|
||||
|
||||
double yaw = targetYaw;
|
||||
double pitch = targetPitch;
|
||||
@ -323,8 +375,9 @@ public class Prediction extends Module {
|
||||
velocity.add(mc.player.getVelocity().x, mc.player.isOnGround() ? 0.0D : mc.player.getVelocity().y, mc.player.getVelocity().z);
|
||||
|
||||
HitResult hitResult = null;
|
||||
Direction hitDirection = null;
|
||||
|
||||
for (int i = 0; i < (simulationSteps.get() > 0 ? simulationSteps.get() : Integer.MAX_VALUE) && hitResult == null; i++) {
|
||||
for (int i = 0; i < (simulationSteps.get() > 0 ? simulationSteps.get() : Integer.MAX_VALUE) && !hitQuad && !isHitTarget; i++) {
|
||||
points.add(vectorPool.get().set(position));
|
||||
|
||||
lastPosition.set(position);
|
||||
@ -335,8 +388,8 @@ public class Prediction extends Module {
|
||||
if (fluidState.getFluid() == Fluids.WATER || fluidState.getFluid() == Fluids.FLOWING_WATER)
|
||||
isTouchingWater = position.y - (int) position.y <= fluidState.getHeight();
|
||||
|
||||
velocity.mul(isTouchingWater ? waterDrag : airDrag);
|
||||
velocity.sub(0, gravity, 0);
|
||||
velocity.mul(isTouchingWater ? waterDrag.get() : airDrag.get());
|
||||
velocity.sub(0, gravity.get(), 0);
|
||||
|
||||
if (position.y < mc.world.getBottomY()) {
|
||||
hitResult = MissHitResult.INSTANCE;
|
||||
@ -356,64 +409,94 @@ public class Prediction extends Module {
|
||||
);
|
||||
if (hitResult.getType() != HitResult.Type.MISS) {
|
||||
position = new Vector3d(hitResult.getPos().x, hitResult.getPos().y, hitResult.getPos().z);
|
||||
hitQuad = true;
|
||||
hitQuad1.set(position);
|
||||
hitQuad2.set(position);
|
||||
hitDirection = ((BlockHitResult) hitResult).getSide();
|
||||
}
|
||||
|
||||
Box box = new Box(
|
||||
lastPosition.x - (EntityType.ARROW.getWidth() / 2f),
|
||||
lastPosition.y,
|
||||
lastPosition.z - (EntityType.ARROW.getWidth() / 2f),
|
||||
lastPosition.x + (EntityType.ARROW.getWidth() / 2f),
|
||||
lastPosition.y + EntityType.ARROW.getHeight(),
|
||||
lastPosition.z + (EntityType.ARROW.getWidth() / 2f)
|
||||
).stretch(velocity.x, velocity.y, velocity.z).expand(1.0D);
|
||||
HitResult hitResultEntity = ProjectileUtil.getEntityCollision(mc.world, null,
|
||||
new Vec3d(lastPosition.x, lastPosition.y, lastPosition.z), new Vec3d(position.x, position.y, position.z),
|
||||
box, entity -> !entity.isSpectator() && entity.isAlive() && entity.canHit() && entity != mc.player
|
||||
);
|
||||
if (hitResultEntity != null) {
|
||||
hitResult = hitResultEntity;
|
||||
if (!targetBox.stretch(velocity.x, velocity.y, velocity.z).expand(4.0).contains(position.x, position.y, position.z))
|
||||
continue;
|
||||
|
||||
Box extendedBox = targetBox;
|
||||
|
||||
if (enableProbe.get()) {
|
||||
hitResult = mc.world.raycast(new RaycastContext(
|
||||
targetBox.getCenter(), targetBox.getCenter().add(-(targetBox.getLengthX() + EntityType.ARROW.getWidth()) / 2.0, 0, 0),
|
||||
RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.NONE, mc.player)
|
||||
);
|
||||
|
||||
double extendedMinX = hitResult.getType() != HitResult.Type.MISS ? hitResult.getPos().x : targetBox.minX - EntityType.ARROW.getWidth() / 2.0;
|
||||
|
||||
hitResult = mc.world.raycast(new RaycastContext(
|
||||
targetBox.getCenter(), targetBox.getCenter().add(0, -(targetBox.getLengthY() + EntityType.ARROW.getHeight()) / 2.0, 0),
|
||||
RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.NONE, mc.player)
|
||||
);
|
||||
|
||||
double extendedMinY = hitResult.getType() != HitResult.Type.MISS ? hitResult.getPos().y : targetBox.minY - EntityType.ARROW.getHeight() / 2.0;
|
||||
|
||||
hitResult = mc.world.raycast(new RaycastContext(
|
||||
targetBox.getCenter(), targetBox.getCenter().add(0, 0, -(targetBox.getLengthZ() + EntityType.ARROW.getWidth()) / 2.0),
|
||||
RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.NONE, mc.player)
|
||||
);
|
||||
|
||||
double extendedMinZ = hitResult.getType() != HitResult.Type.MISS ? hitResult.getPos().z : targetBox.minZ - EntityType.ARROW.getWidth() / 2.0;
|
||||
|
||||
hitResult = mc.world.raycast(new RaycastContext(
|
||||
targetBox.getCenter(), targetBox.getCenter().add((targetBox.getLengthX() + EntityType.ARROW.getWidth()) / 2.0, 0, 0),
|
||||
RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.NONE, mc.player)
|
||||
);
|
||||
|
||||
double extendedMaxX = hitResult.getType() != HitResult.Type.MISS ? hitResult.getPos().x : targetBox.maxX + EntityType.ARROW.getWidth() / 2.0;
|
||||
|
||||
hitResult = mc.world.raycast(new RaycastContext(
|
||||
targetBox.getCenter(), targetBox.getCenter().add(0, (targetBox.getLengthY() + EntityType.ARROW.getHeight()) / 2.0, 0),
|
||||
RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.NONE, mc.player)
|
||||
);
|
||||
|
||||
double extendedMaxY = hitResult.getType() != HitResult.Type.MISS ? hitResult.getPos().y : targetBox.maxY + EntityType.ARROW.getHeight() / 2.0;
|
||||
|
||||
hitResult = mc.world.raycast(new RaycastContext(
|
||||
targetBox.getCenter(), targetBox.getCenter().add(0, 0, (targetBox.getLengthZ() + EntityType.ARROW.getWidth()) / 2.0),
|
||||
RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.NONE, mc.player)
|
||||
);
|
||||
|
||||
double extendedMaxZ = hitResult.getType() != HitResult.Type.MISS ? hitResult.getPos().z : targetBox.maxZ + EntityType.ARROW.getWidth() / 2.0;
|
||||
|
||||
extendedBox = new Box(extendedMinX, extendedMinY, extendedMinZ, extendedMaxX, extendedMaxY, extendedMaxZ);
|
||||
}
|
||||
|
||||
hitResult = hitResult.getType() == HitResult.Type.MISS ? null : hitResult;
|
||||
Optional<Vec3d> optional = extendedBox.raycast(new Vec3d(lastPosition.x, lastPosition.y, lastPosition.z), new Vec3d(position.x, position.y, position.z));
|
||||
|
||||
if (optional.isPresent()) {
|
||||
isHitTarget = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hitResult != null) {
|
||||
if (hitResult.getType() == HitResult.Type.BLOCK) {
|
||||
BlockHitResult r = (BlockHitResult) hitResult;
|
||||
|
||||
hitQuad = true;
|
||||
hitQuad1.set(r.getPos().x, r.getPos().y, r.getPos().z);
|
||||
hitQuad2.set(r.getPos().x, r.getPos().y, r.getPos().z);
|
||||
|
||||
if (r.getSide() == Direction.UP || r.getSide() == Direction.DOWN) {
|
||||
hitQuadHorizontal = true;
|
||||
hitQuad1.x -= 0.25;
|
||||
hitQuad1.z -= 0.25;
|
||||
hitQuad2.x += 0.25;
|
||||
hitQuad2.z += 0.25;
|
||||
}
|
||||
else if (r.getSide() == Direction.NORTH || r.getSide() == Direction.SOUTH) {
|
||||
hitQuadHorizontal = false;
|
||||
hitQuad1.x -= 0.25;
|
||||
hitQuad1.y -= 0.25;
|
||||
hitQuad2.x += 0.25;
|
||||
hitQuad2.y += 0.25;
|
||||
}
|
||||
else {
|
||||
hitQuadHorizontal = false;
|
||||
hitQuad1.z -= 0.25;
|
||||
hitQuad1.y -= 0.25;
|
||||
hitQuad2.z += 0.25;
|
||||
hitQuad2.y += 0.25;
|
||||
}
|
||||
|
||||
points.add(Utils.set(vectorPool.get(), hitResult.getPos()));
|
||||
if (hitQuad) {
|
||||
if (hitDirection == Direction.UP || hitDirection == Direction.DOWN) {
|
||||
hitQuadHorizontal = true;
|
||||
hitQuad1.x -= 0.25;
|
||||
hitQuad1.z -= 0.25;
|
||||
hitQuad2.x += 0.25;
|
||||
hitQuad2.z += 0.25;
|
||||
}
|
||||
else if (hitResult.getType() == HitResult.Type.ENTITY) {
|
||||
collidingEntity = ((EntityHitResult) hitResult).getEntity();
|
||||
points.add(Utils.set(vectorPool.get(), hitResult.getPos()).add(0, collidingEntity.getHeight() / 2, 0));
|
||||
isHitTarget = collidingEntity == targetEntity;
|
||||
else if (hitDirection == Direction.NORTH || hitDirection == Direction.SOUTH) {
|
||||
hitQuadHorizontal = false;
|
||||
hitQuad1.x -= 0.25;
|
||||
hitQuad1.y -= 0.25;
|
||||
hitQuad2.x += 0.25;
|
||||
hitQuad2.y += 0.25;
|
||||
}
|
||||
else {
|
||||
hitQuadHorizontal = false;
|
||||
hitQuad1.z -= 0.25;
|
||||
hitQuad1.y -= 0.25;
|
||||
hitQuad2.z += 0.25;
|
||||
hitQuad2.y += 0.25;
|
||||
}
|
||||
|
||||
points.add(Utils.set(vectorPool.get(), hitResult.getPos()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -448,37 +531,31 @@ public class Prediction extends Module {
|
||||
}
|
||||
}
|
||||
|
||||
if (collidingEntity != null) {
|
||||
double x = (collidingEntity.getX() - collidingEntity.prevX) * event.tickDelta;
|
||||
double y = (collidingEntity.getY() - collidingEntity.prevY) * event.tickDelta;
|
||||
double z = (collidingEntity.getZ() - collidingEntity.prevZ) * event.tickDelta;
|
||||
|
||||
Box box = collidingEntity.getBoundingBox();
|
||||
if (targetEntity != null) {
|
||||
Box box = targetEntity.getBoundingBox();
|
||||
event.renderer.box(
|
||||
x + box.minX, y + box.minY, z + box.minZ, x + box.maxX, y + box.maxY, z + box.maxZ,
|
||||
targetBox,
|
||||
isHitTarget ? hitSideColor.get() : missSideColor.get(),
|
||||
isHitTarget ? hitLineColor.get() : missLineColor.get(),
|
||||
shapeMode.get(), 0
|
||||
);
|
||||
}
|
||||
|
||||
if (!isHitTarget && targetEntity != null) {
|
||||
double x = (targetEntity.getX() - targetEntity.prevX) * event.tickDelta;
|
||||
double y = (targetEntity.getY() - targetEntity.prevY) * event.tickDelta;
|
||||
double z = (targetEntity.getZ() - targetEntity.prevZ) * event.tickDelta;
|
||||
|
||||
Box box = targetEntity.getBoundingBox();
|
||||
event.renderer.box(
|
||||
x + box.minX, y + box.minY, z + box.minZ, x + box.maxX, y + box.maxY, z + box.maxZ,
|
||||
missSideColor.get(), missLineColor.get(), shapeMode.get(), 0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private double calculateHeightOffset(Vector3d targetPosition, double pitch) {
|
||||
private void calculateTarget() {
|
||||
if (mc.options.attackKey.isPressed() || !isSelectableTarget(targetEntity)) {
|
||||
targetEntity = TargetUtils.get(this::isSelectableTarget, priority.get());
|
||||
}
|
||||
|
||||
if (targetEntity == null) return;
|
||||
|
||||
targetBox = targetEntity.getBoundingBox();
|
||||
}
|
||||
|
||||
private double calculateHeightOffset(double pitch) {
|
||||
double targetDistance = Math.sqrt(
|
||||
(targetPosition.x - mc.player.getX()) * (targetPosition.x - mc.player.getX()) +
|
||||
(targetPosition.z - mc.player.getZ()) * (targetPosition.z - mc.player.getZ())
|
||||
(targetBox.getCenter().x - mc.player.getX()) * (targetBox.getCenter().x - mc.player.getX()) +
|
||||
(targetBox.getCenter().z - mc.player.getZ()) * (targetBox.getCenter().z - mc.player.getZ())
|
||||
);
|
||||
|
||||
if (getCurrentCharge() <= 0) return Double.NaN;
|
||||
@ -487,9 +564,9 @@ public class Prediction extends Module {
|
||||
Vector3d lastPosition = new Vector3d(0.0, 0.0, 0.0);
|
||||
Vector3d position = new Vector3d(0.0, 0.0, 0.0);
|
||||
Vector3d velocity = new Vector3d(0.0, 0.0, 0.0);
|
||||
position.set(mc.player.getX(), mc.player.getY(), mc.player.getZ()).add(0, mc.player.getEyeHeight(mc.player.getPose()), 0);
|
||||
position.set(mc.player.getX(), mc.player.getY(), mc.player.getZ()).add(0, mc.player.getEyeHeight(mc.player.getPose()) + eyeHeightOffset.get(), 0);
|
||||
|
||||
double yaw = Rotations.getYaw(new Vec3d(targetPosition.x, targetPosition.y, targetPosition.z));
|
||||
double yaw = Rotations.getYaw(new Vec3d(targetBox.getCenter().x, targetBox.getCenter().y, targetBox.getCenter().z));
|
||||
|
||||
double x = -Math.sin(yaw * 0.017453292) * Math.cos(pitch * 0.017453292);
|
||||
double y = -Math.sin(pitch * 0.017453292);
|
||||
@ -507,8 +584,8 @@ public class Prediction extends Module {
|
||||
if (fluidState.getFluid() == Fluids.WATER || fluidState.getFluid() == Fluids.FLOWING_WATER)
|
||||
isTouchingWater = position.y - (int) position.y <= fluidState.getHeight();
|
||||
|
||||
velocity.mul(isTouchingWater ? waterDrag : airDrag);
|
||||
velocity.sub(0, gravity, 0);
|
||||
velocity.mul(isTouchingWater ? waterDrag.get() : airDrag.get());
|
||||
velocity.sub(0, gravity.get(), 0);
|
||||
|
||||
if (position.y < mc.world.getBottomY()) return Double.NEGATIVE_INFINITY;
|
||||
|
||||
@ -523,7 +600,7 @@ public class Prediction extends Module {
|
||||
);
|
||||
|
||||
if (distance > targetDistance) {
|
||||
return MathHelper.lerp((targetDistance - laseDistance) / (distance - laseDistance), lastPosition.y, position.y) - targetPosition.y;
|
||||
return MathHelper.lerp((targetDistance - laseDistance) / (distance - laseDistance), lastPosition.y, position.y) - targetBox.getCenter().y;
|
||||
}
|
||||
}
|
||||
|
||||
@ -533,6 +610,8 @@ public class Prediction extends Module {
|
||||
private void calculateAngle() {
|
||||
if (targetEntity == null) return;
|
||||
|
||||
targetCompleted = false;
|
||||
|
||||
// parabolic prediction
|
||||
if (predictionLevel.get() == 0) {
|
||||
double posX = targetEntity.getPos().getX();
|
||||
@ -559,42 +638,43 @@ public class Prediction extends Module {
|
||||
}
|
||||
|
||||
targetCharge = 1.0;
|
||||
targetCompleted = true;
|
||||
|
||||
calculatePath();
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3d targetPosition = new Vector3d(targetEntity.getX(), targetEntity.getY() + targetEntity.getHeight() / 2.0, targetEntity.getZ());
|
||||
double highestPitch = 0.0;
|
||||
boolean findPitch = false;
|
||||
|
||||
// Basic physics prediction
|
||||
if (predictionLevel.get() == 1) {
|
||||
if (predictionLevel.get() >= 1) {
|
||||
// Solve for the highest pitch
|
||||
double highestPitch;
|
||||
{
|
||||
double minPitch = -90.0;
|
||||
double maxPitch = 90.0;
|
||||
for (int i = 0; iterationSteps.get() > 0 ? i < iterationSteps.get() : maxPitch - minPitch > iterationEpsilon.get(); i++) {
|
||||
double mid1 = minPitch + (maxPitch - minPitch) / 3.0;
|
||||
double mid2 = maxPitch - (maxPitch - minPitch) / 3.0;
|
||||
double mid1Height = calculateHeightOffset(targetPosition, mid1);
|
||||
double mid2Height = calculateHeightOffset(targetPosition, mid2);
|
||||
double mid1Height = calculateHeightOffset(mid1);
|
||||
double mid2Height = calculateHeightOffset(mid2);
|
||||
if (Double.isNaN(mid1Height) || Double.isNaN(mid2Height)) return;
|
||||
if (mid1Height < mid2Height)
|
||||
minPitch = mid1;
|
||||
else maxPitch = mid2;
|
||||
}
|
||||
highestPitch = (minPitch + maxPitch) / 2.0;
|
||||
if (calculateHeightOffset(targetPosition, highestPitch) < 0.0) return;
|
||||
if (calculateHeightOffset(highestPitch) < 0.0) return;
|
||||
}
|
||||
|
||||
// Solve for the low pitch
|
||||
double targetLowPitch = highestPitch;
|
||||
{
|
||||
targetLowPitch = highestPitch;
|
||||
double minPitch = highestPitch;
|
||||
double maxPitch = 90.0;
|
||||
for (int i = 0; iterationSteps.get() > 0 ? i < iterationSteps.get() : maxPitch - minPitch > iterationEpsilon.get(); i++) {
|
||||
double mid = (minPitch + maxPitch) / 2.0;
|
||||
double midHeight = calculateHeightOffset(targetPosition, mid);
|
||||
double midHeight = calculateHeightOffset(mid);
|
||||
if (Double.isNaN(midHeight)) {
|
||||
targetLowPitch = Double.NaN;
|
||||
break;
|
||||
@ -606,48 +686,116 @@ public class Prediction extends Module {
|
||||
if (!Double.isNaN(targetLowPitch)) targetLowPitch = (minPitch + maxPitch) / 2.0;
|
||||
}
|
||||
|
||||
if (!Double.isNaN(targetLowPitch))
|
||||
{
|
||||
if (!Double.isNaN(targetLowPitch)) {
|
||||
findPitch = true;
|
||||
|
||||
targetPitch = targetLowPitch;
|
||||
targetYaw = Rotations.getYaw(targetEntity);
|
||||
targetCharge = getCurrentCharge();
|
||||
targetCompleted = true;
|
||||
|
||||
calculatePath();
|
||||
}
|
||||
}
|
||||
|
||||
// Solve for the high pitch
|
||||
if (!isHitTarget && allowHighThrows.get()) {
|
||||
targetHighPitch = highestPitch;
|
||||
double minPitch = -90.0;
|
||||
double maxPitch = highestPitch;
|
||||
for (int i = 0; iterationSteps.get() > 0 ? i < iterationSteps.get() : maxPitch - minPitch > iterationEpsilon.get(); i++) {
|
||||
double mid = (minPitch + maxPitch) / 2.0;
|
||||
double midHeight = calculateHeightOffset(targetPosition, mid);
|
||||
if (Double.isNaN(midHeight)) {
|
||||
targetHighPitch = Double.NaN;
|
||||
break;
|
||||
}
|
||||
if (midHeight <= 0)
|
||||
minPitch = mid;
|
||||
else maxPitch = mid;
|
||||
// If you can't hit because a block is blocking, try to use a probe.
|
||||
if (targetCompleted && !isHitTarget && findPitch && enableProbe.get()) {
|
||||
int numProbe = (int) (probeRange.get() / probeInterval.get());
|
||||
boolean[][] arrayProbe = new boolean[numProbe * 2 + 1][numProbe * 2 + 1];
|
||||
|
||||
double targetDistance = Math.sqrt(
|
||||
(targetBox.getCenter().x - mc.player.getX()) * (targetBox.getCenter().x - mc.player.getX()) +
|
||||
(targetBox.getCenter().z - mc.player.getZ()) * (targetBox.getCenter().z - mc.player.getZ())
|
||||
);
|
||||
|
||||
double delta = Math.atan2(targetDistance, probeInterval.get());
|
||||
|
||||
double centerYaw = targetYaw;
|
||||
double centerPitch = targetPitch;
|
||||
|
||||
for (int i = 0; i < numProbe * 2 + 1; ++i) {
|
||||
for (int j = 0; j < numProbe * 2 + 1; ++j) {
|
||||
targetYaw = centerYaw - (i - numProbe) * delta;
|
||||
targetPitch = centerPitch - (j - numProbe) * delta;
|
||||
calculatePath();
|
||||
arrayProbe[i][j] = isHitTarget;
|
||||
}
|
||||
if (!Double.isNaN(targetHighPitch)) targetHighPitch = (minPitch + maxPitch) / 2.0;
|
||||
}
|
||||
|
||||
if (!isHitTarget && !Double.isNaN(targetHighPitch) && allowHighThrows.get()) {
|
||||
int[][][] validProbe = new int[numProbe * 2 + 1][numProbe * 2 + 1][4];
|
||||
|
||||
for (int i = 0; i < numProbe * 2 + 1; ++i) {
|
||||
for (int j = 0; j < numProbe * 2 + 1; ++j) {
|
||||
if (i == 0) validProbe[i][j][0] = arrayProbe[i][j] ? 1 : 0;
|
||||
else validProbe[i][j][0] = (arrayProbe[i][j] ? 1 : 0) + validProbe[i - 1][j][0];
|
||||
if (j == 0) validProbe[i][j][1] = arrayProbe[i][j] ? 1 : 0;
|
||||
else validProbe[i][j][1] = (arrayProbe[i][j] ? 1 : 0) + validProbe[i][j - 1][1];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = numProbe * 2; i >= 0; --i) {
|
||||
for (int j = numProbe * 2; j >= 0; --j) {
|
||||
if (i == numProbe * 2) validProbe[i][j][2] = arrayProbe[i][j] ? 1 : 0;
|
||||
else validProbe[i][j][2] = (arrayProbe[i][j] ? 1 : 0) + validProbe[i + 1][j][2];
|
||||
if (j == numProbe * 2) validProbe[i][j][3] = arrayProbe[i][j] ? 1 : 0;
|
||||
else validProbe[i][j][3] = (arrayProbe[i][j] ? 1 : 0) + validProbe[i][j + 1][3];
|
||||
}
|
||||
}
|
||||
|
||||
int maxProbe = 0;
|
||||
targetYaw = centerYaw;
|
||||
targetPitch = centerPitch;
|
||||
|
||||
for (int i = numProbe * 2; i >= 0; --i) {
|
||||
for (int j = numProbe * 2; j >= 0; --j) {
|
||||
int x = Math.max(Math.min(validProbe[i][j][0], validProbe[i][j][1]), Math.min(validProbe[i][j][2], validProbe[i][j][3]));
|
||||
if (x > maxProbe) {
|
||||
maxProbe = x;
|
||||
targetYaw = centerYaw - (i - numProbe) * delta;
|
||||
targetPitch = centerPitch - (j - numProbe) * delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
calculatePath();
|
||||
}
|
||||
|
||||
// Solve for the high pitch if allowed
|
||||
if (!isHitTarget && allowHighThrows.get()) {
|
||||
double targetHighPitch = highestPitch;
|
||||
double minPitch = -90.0;
|
||||
double maxPitch = highestPitch;
|
||||
for (int i = 0; iterationSteps.get() > 0 ? i < iterationSteps.get() : maxPitch - minPitch > iterationEpsilon.get(); i++) {
|
||||
double mid = (minPitch + maxPitch) / 2.0;
|
||||
double midHeight = calculateHeightOffset(mid);
|
||||
if (Double.isNaN(midHeight)) {
|
||||
targetHighPitch = Double.NaN;
|
||||
break;
|
||||
}
|
||||
if (midHeight <= 0)
|
||||
minPitch = mid;
|
||||
else maxPitch = mid;
|
||||
}
|
||||
|
||||
if (!Double.isNaN(targetHighPitch)) {
|
||||
targetHighPitch = (minPitch + maxPitch) / 2.0;
|
||||
|
||||
targetPitch = targetHighPitch;
|
||||
targetYaw = Rotations.getYaw(targetEntity);
|
||||
targetCharge = getCurrentCharge();
|
||||
targetCompleted = true;
|
||||
|
||||
calculatePath();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void aim(double tickDelta) {
|
||||
if (targetEntity == null) return;
|
||||
if (!targetCompleted) return;
|
||||
if (!isHitTarget && aimOnlyHit.get()) return;
|
||||
if (!mc.options.useKey.isPressed()) return;
|
||||
if (!InvUtils.testInHands(Items.BOW)) return;
|
||||
|
||||
if (instant.get()) {
|
||||
mc.player.setYaw((float) targetYaw);
|
||||
|
Reference in New Issue
Block a user