Skip to content

Commit

Permalink
feats(legacy): New rotation randomization pattern mode "LazyFlick" + …
Browse files Browse the repository at this point in the history
…MinRotationDifferenceResetTiming option. (#5528)

dedicated to polar anticheat
  • Loading branch information
mems01 authored Feb 4, 2025
1 parent c12c08e commit a548ec6
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ object Aimbot : Module("Aimbot", Category.COMBAT) {
private val maxAngleChange by float("MaxAngleChange", 10f, 1F..180F) { horizontalAim || verticalAim }
private val inViewMaxAngleChange by float("InViewMaxAngleChange", 35f, 1f..180f) { horizontalAim || verticalAim }
private val generateSpotBasedOnDistance by boolean(
"GenerateSpotBasedOnDistance",
false
"GenerateSpotBasedOnDistance", false
) { horizontalAim || verticalAim }
private val predictClientMovement by int("PredictClientMovement", 2, 0..5)
private val predictEnemyPosition by float("PredictEnemyPosition", 1.5f, -1f..2f)
Expand Down Expand Up @@ -70,6 +69,9 @@ object Aimbot : Module("Aimbot", Category.COMBAT) {
private val horizontalBodySearchRange by floatRange("HorizontalBodySearchRange", 0f..1f, 0f..1f) { horizontalAim }

private val minRotationDifference by float("MinRotationDifference", 0f, 0f..2f) { verticalAim || horizontalAim }
private val minRotationDifferenceResetTiming by choices(
"MinRotationDifferenceResetTiming", arrayOf("OnStart", "Always"), "OnStart"
) { verticalAim || horizontalAim }

private val fov by float("FOV", 180F, 1F..180F)
private val lock by boolean("Lock", true) { horizontalAim || verticalAim }
Expand All @@ -93,17 +95,17 @@ object Aimbot : Module("Aimbot", Category.COMBAT) {
// Clicking delay
if (mc.gameSettings.keyBindAttack.isKeyDown) clickTimer.reset()

if (onClick && (clickTimer.hasTimePassed(150) ||
!mc.gameSettings.keyBindAttack.isKeyDown && AutoClicker.handleEvents())
) {
if (onClick && (clickTimer.hasTimePassed(150) || !mc.gameSettings.keyBindAttack.isKeyDown && AutoClicker.handleEvents())) {
return@handler
}

// Search for the best enemy to target
val entity = world.loadedEntityList.filter {
Backtrack.runWithNearestTrackedDistance(it) {
isSelected(it, true) && player.canEntityBeSeen(it)
&& player.getDistanceToEntityBox(it) <= range && rotationDifference(it) <= fov
isSelected(
it,
true
) && player.canEntityBeSeen(it) && player.getDistanceToEntityBox(it) <= range && rotationDifference(it) <= fov
}
}.minByOrNull { player.getDistanceToEntityBox(it) } ?: return@handler

Expand Down Expand Up @@ -139,8 +141,7 @@ object Aimbot : Module("Aimbot", Category.COMBAT) {
val boundingBox = entity.hitBox.offset(prediction)
val (currPos, oldPos) = player.currPos to player.prevPos

val simPlayer =
SimulatedPlayer.fromClientPlayer(RotationUtils.modifiedInput)
val simPlayer = SimulatedPlayer.fromClientPlayer(RotationUtils.modifiedInput)

simPlayer.rotationYaw = (currentRotation ?: player.rotation).yaw

Expand Down Expand Up @@ -205,6 +206,7 @@ object Aimbot : Module("Aimbot", Category.COMBAT) {
realisticTurnSpeed.toFloat(),
legitimize = legitimize,
minRotationDiff = minRotationDifference,
minRotationDiffResetTiming = minRotationDifferenceResetTiming,
)

rotation.toPlayer(player, horizontalAim, verticalAim)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,65 @@ package net.ccbluex.liquidbounce.utils.rotation

import net.ccbluex.liquidbounce.config.Configurable
import net.ccbluex.liquidbounce.features.module.Module
import net.ccbluex.liquidbounce.utils.extensions.plus
import net.ccbluex.liquidbounce.utils.extensions.random
import net.ccbluex.liquidbounce.utils.extensions.times
import net.ccbluex.liquidbounce.utils.rotation.RotationUtils.angleDifference
import net.ccbluex.liquidbounce.utils.rotation.RotationUtils.getVectorForRotation
import net.ccbluex.liquidbounce.utils.rotation.RotationUtils.lastRotations
import net.minecraft.util.AxisAlignedBB
import net.minecraft.util.Vec3
import kotlin.math.sign

class RandomizationSettings(owner: Module, generalApply: () -> Boolean = { true }): Configurable("Randomization") {
class RandomizationSettings(owner: Module, val generalApply: () -> Boolean = { true }): Configurable("Randomization") {

val randomize by boolean("RandomizeRotations", false) { generalApply() }
val yawRandomizationChance by floatRange("YawRandomizationChance", 0.8f..1.0f, 0f..1f) { randomize }
val yawRandomizationRange by floatRange("YawRandomizationRange", 5f..10f, 0f..30f)
{ randomize && yawRandomizationChance.start != 1F }
val pitchRandomizationChance by floatRange("PitchRandomizationChance", 0.8f..1.0f, 0f..1f) { randomize }
val pitchRandomizationRange by floatRange("PitchRandomizationRange", 5f..10f, 0f..30f)
{ randomize && pitchRandomizationChance.start != 1F }
private val randomizationPattern by choices("RandomizationPattern", arrayOf("None", "Zig-Zag", "LazyFlick"), "None") { generalApply() }
private val yawRandomizationChance by floatRange("YawRandomizationChance", 0.8f..1.0f, 0f..1f) { randomizationChosen }
private val yawRandomizationRange by floatRange("YawRandomizationRange", 5f..10f, 0f..30f)
{ isZizZagActive && !randomizationChosen && yawRandomizationChance.start != 1F }
private val yawSpeedIncreaseMultiplier by intRange("YawSpeedIncreaseMultiplier", 50..120, 0..500, suffix = "%") { !isZizZagActive && randomizationChosen }
private val pitchRandomizationChance by floatRange("PitchRandomizationChance", 0.8f..1.0f, 0f..1f) { randomizationChosen }
private val pitchRandomizationRange by floatRange("PitchRandomizationRange", 5f..10f, 0f..30f)
{ randomizationChosen && pitchRandomizationChance.start != 1F }

private val isZizZagActive
get() = randomizationPattern == "Zig-Zag"

val randomizationChosen
get() = randomizationPattern != "None" && generalApply()

fun processNextSpot(box: AxisAlignedBB, rotation: Rotation, eyes: Vec3, range: Double) {
val intercept = box.calculateIntercept(eyes, eyes + getVectorForRotation(lastRotations.random()) * range)

// Smooth out randomized rotation pattern using previous rotation to simulate natural movement
val pitchMovement = angleDifference(rotation.pitch, lastRotations[2].pitch).sign.takeIf { it != 0f } ?: (-1..1).random().toFloat()
val yawMovement = angleDifference(rotation.yaw, lastRotations[2].yaw)

val yawSign = yawMovement.sign.takeIf { it != 0f } ?: arrayOf(-1f, 1f).random()

val yawIncrease = if (Math.random() > yawRandomizationChance.random()) {
if (!isZizZagActive) {
yawSpeedIncreaseMultiplier.random() / 100f * yawMovement
} else {
yawRandomizationRange.random() * yawSign
}
} else 0f

val pitchIncrease = if (Math.random() > pitchRandomizationChance.random()) {
if (!isZizZagActive) {
pitchRandomizationRange.random() + pitchMovement
} else {
pitchRandomizationRange.random() * pitchMovement
}
} else 0f

if (isZizZagActive || intercept?.hitVec == null) {
rotation.yaw += yawIncrease
rotation.pitch += pitchIncrease

rotation.fixedSensitivity()
}
}

init {
owner.addValues(this.values)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import kotlin.math.abs

// TODO: refactor them all

class AlwaysRotationSettings(owner: Module, generalApply: () -> Boolean = { true }) : RotationSettings(owner, generalApply) {
class AlwaysRotationSettings(owner: Module, generalApply: () -> Boolean = { true }) :
RotationSettings(owner, generalApply) {
override val rotationsValue = super.rotationsValue.apply { excludeWithState(true) }
override val rotationsActive: Boolean = true
}
Expand All @@ -38,10 +39,10 @@ open class RotationSettings(owner: Module, generalApply: () -> Boolean = { true

open val legitimizeValue = boolean("Legitimize", false) { rotationsActive && generalApply() }

open val horizontalAngleChangeValue = floatRange("HorizontalAngleChange", 180f..180f, 1f..180f)
{ rotationsActive && generalApply() }
open val verticalAngleChangeValue = floatRange("VerticalAngleChange", 180f..180f, 1f..180f)
{ rotationsActive && generalApply() }
open val horizontalAngleChangeValue =
floatRange("HorizontalAngleChange", 180f..180f, 1f..180f) { rotationsActive && generalApply() }
open val verticalAngleChangeValue =
floatRange("VerticalAngleChange", 180f..180f, 1f..180f) { rotationsActive && generalApply() }

open val angleResetDifferenceValue = float("AngleResetDifference", 5f.withGCD(), 0.0f..180f) {
rotationsActive && applyServerSide && generalApply()
Expand All @@ -51,6 +52,10 @@ open class RotationSettings(owner: Module, generalApply: () -> Boolean = { true
"MinRotationDifference", 2f, 0f..4f
) { rotationsActive && generalApply() }

open val minRotationDifferenceResetTimingValue = choices(
"MinRotationDifferenceResetTiming", arrayOf("OnStart", "OnSlowDown", "Always"), "OnStart"
) { rotationsActive && generalApply() }

// Variables for easier access
val rotations by rotationsValue
val applyServerSide by applyServerSideValue
Expand All @@ -67,6 +72,7 @@ open class RotationSettings(owner: Module, generalApply: () -> Boolean = { true
val verticalAngleChange by verticalAngleChangeValue
val angleResetDifference by angleResetDifferenceValue
val minRotationDifference by minRotationDifferenceValue
val minRotationDifferenceResetTiming by minRotationDifferenceResetTimingValue

var prioritizeRequest = false
var immediate = false
Expand Down Expand Up @@ -98,8 +104,7 @@ open class RotationSettings(owner: Module, generalApply: () -> Boolean = { true
}

fun shouldPerformShortStop(): Boolean {
if (abs(rotDiffBuildUp) < rotationDiffBuildUpToStop || !simulateShortStop)
return false
if (abs(rotDiffBuildUp) < rotationDiffBuildUpToStop || !simulateShortStop) return false

if (maxThresholdReachAttempts < maxThresholdAttemptsToStop) {
maxThresholdReachAttempts++
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ object RotationUtils : MinecraftInstance, Listenable {
/**
* Our final rotation point, which [currentRotation] follows.
*/
var targetRotation: Rotation? = null
private var targetRotation: Rotation? = null

/**
* The current rotation that is responsible for aiming at objects, synchronizing movement, etc.
Expand Down Expand Up @@ -78,7 +78,9 @@ object RotationUtils : MinecraftInstance, Listenable {
* @param blockPos target block
*/
fun faceBlock(
blockPos: BlockPos?, throughWalls: Boolean = true, targetUpperFace: Boolean = false,
blockPos: BlockPos?,
throughWalls: Boolean = true,
targetUpperFace: Boolean = false,
hRange: ClosedFloatingPointRange<Double> = 0.0..1.0
): VecRotation? {
val world = mc.theWorld ?: return null
Expand Down Expand Up @@ -253,24 +255,8 @@ object RotationUtils : MinecraftInstance, Listenable {
var attackRotation: Pair<Rotation, Float>? = null
var lookRotation: Pair<Rotation, Float>? = null

randomization?.takeIf { it.randomize }?.run {
val yawMovement =
angleDifference(currRotation.yaw, lastRotations[2].yaw).sign.takeIf { it != 0f } ?: arrayOf(
-1f, 1f
).random()
val pitchMovement =
angleDifference(currRotation.pitch, lastRotations[2].pitch).sign.takeIf { it != 0f } ?: arrayOf(
-1f, 1f
).random()

currRotation.yaw += if (Math.random() > yawRandomizationChance.random()) {
yawRandomizationRange.random() * yawMovement
} else 0f
currRotation.pitch += if (Math.random() > pitchRandomizationChance.random()) {
pitchRandomizationRange.random() * pitchMovement
} else 0f

currRotation.fixedSensitivity()
randomization?.takeIf { it.randomizationChosen }?.run {
processNextSpot(bb, currRotation, eyes, scanRange.toDouble())
}

val (hMin, hMax) = horizontalSearch.start.toDouble() to min(horizontalSearch.endInclusive + 0.01, 1.0)
Expand Down Expand Up @@ -351,6 +337,7 @@ object RotationUtils : MinecraftInstance, Listenable {
vSpeed,
!settings.instant && settings.legitimize,
settings.minRotationDifference,
settings.minRotationDifferenceResetTiming
)
}

Expand All @@ -361,6 +348,7 @@ object RotationUtils : MinecraftInstance, Listenable {
vSpeed: Float = hSpeed,
legitimize: Boolean,
minRotationDiff: Float,
minRotationDiffResetTiming: String,
): Rotation {
var (yawDiff, pitchDiff) = angleDifferences(targetRotation, currentRotation)

Expand All @@ -373,43 +361,62 @@ object RotationUtils : MinecraftInstance, Listenable {
yawDiff = 0F
pitchDiff = 0F
} else if (isShortStopActive || activeSettings?.shouldPerformShortStop() == true) {
// Use the tick scheduling to our advantage as we can check if short stop is still active.
if (!isShortStopActive) {
WaitTickUtils.schedule(activeSettings?.shortStopDuration?.random()?.plus(1) ?: 0, this)
}

activeSettings?.resetSimulateShortStopData()

val slowdown = { (0F..0.1F).random() }
val yawSlowdown = (0F..0.1F).random()
val pitchSlowdown = (0F..0.1F).random()

yawDiff = (yawDiff * slowdown()).withGCD()
pitchDiff = (pitchDiff * slowdown()).withGCD()
yawDiff = (yawDiff * yawSlowdown).withGCD()
pitchDiff = (pitchDiff * pitchSlowdown).withGCD()
}

var (straightLineYaw, straightLinePitch) =
abs(yawDiff safeDiv rotationDifference) * hSpeed to abs(pitchDiff safeDiv rotationDifference) * vSpeed
var (straightLineYaw, straightLinePitch) = run {
val baseYawSpeed = abs(yawDiff safeDiv rotationDifference) * hSpeed
val basePitchSpeed = abs(pitchDiff safeDiv rotationDifference) * vSpeed

// Apply imperfect correlation
if (legitimize) {
baseYawSpeed * (0.9F..1.1F).random()
basePitchSpeed * (0.9F..1.1F).random()
}

baseYawSpeed to basePitchSpeed
}

straightLineYaw = yawDiff.coerceIn(-straightLineYaw, straightLineYaw)
straightLinePitch = pitchDiff.coerceIn(-straightLinePitch, straightLinePitch)

val (minYaw, minPitch) = {
nextFloat(min(minRotationDiff, getFixedAngleDelta()), minRotationDiff).withGCD()
}.let {
it() to it()
// Humans usually have some small jitter when moving their mouse from point A to point B.
// Usually when a rotation axis' difference is prioritized.
if (rotationDifference > 0F) {
val yawJitter = (-0.03F..0.03F).random() * straightLineYaw
val pitchJitter = (-0.02F..0.02F).random() * straightLinePitch

straightLineYaw += yawJitter
straightLinePitch += pitchJitter
}

applySlowDown(straightLineYaw, minYaw, true, legitimize) {
val minYaw = nextFloat(min(minRotationDiff, getFixedAngleDelta()), minRotationDiff).withGCD()
val minPitch = nextFloat(min(minRotationDiff, getFixedAngleDelta()), minRotationDiff).withGCD()

applySlowDown(straightLineYaw, minYaw, minRotationDiffResetTiming, true, legitimize) {
straightLineYaw = it
}

applySlowDown(straightLinePitch, minPitch, false, legitimize) {
applySlowDown(straightLinePitch, minPitch, minRotationDiffResetTiming, false, legitimize) {
straightLinePitch = it
}

return currentRotation.plus(Rotation(straightLineYaw, straightLinePitch))
}

private fun applySlowDown(diff: Float, min: Float, yaw: Boolean, applyRealism: Boolean, action: (Float) -> Unit) {
private fun applySlowDown(
diff: Float, min: Float, timing: String, yaw: Boolean, applyRealism: Boolean, action: (Float) -> Unit
) {
if (diff == 0f) {
action(diff)
return
Expand All @@ -420,8 +427,9 @@ object RotationUtils : MinecraftInstance, Listenable {
}

val diffAbs = abs(diff)
val isSlowingDown = diffAbs <= abs(lastTick1)

if (lastTick1 == 0f && diffAbs.withGCD() <= min) {
if (diffAbs.withGCD() <= min && (timing == "Always" || timing == "OnSlowDown" && isSlowingDown || timing == "OnStart" && lastTick1 == 0F)) {
action(0f)
return
}
Expand All @@ -443,7 +451,7 @@ object RotationUtils : MinecraftInstance, Listenable {

val new = (lastTick1..diff).lerpWith(range.random())

if (abs(new.withGCD()) <= min && diffAbs <= abs(lastTick1)) {
if (abs(new.withGCD()) <= min && isSlowingDown) {
action(diff)
} else {
action(new)
Expand Down Expand Up @@ -636,7 +644,6 @@ object RotationUtils : MinecraftInstance, Listenable {
val serverRotation = currentRotation ?: serverRotation

if (resetTicks == 0) {

if (isDifferenceAcceptableForReset(serverRotation, playerRotation, settings)) {
resetRotation()
return
Expand Down Expand Up @@ -666,11 +673,9 @@ object RotationUtils : MinecraftInstance, Listenable {
private fun isDifferenceAcceptableForReset(
curr: Rotation, target: Rotation, options: RotationSettings
): Boolean {
if (!options.applyServerSide)
return true
if (!options.applyServerSide) return true

if (rotationDifference(target, curr) > options.angleResetDifference)
return false
if (rotationDifference(target, curr) > options.angleResetDifference) return false

// We use the last rotation saved 2 ticks ago because we have not updated the currentRotation yet.
val diffs = angleDifferences(target, curr).abs
Expand Down Expand Up @@ -760,10 +765,9 @@ object RotationUtils : MinecraftInstance, Listenable {
}

enum class BodyPoint(val rank: Int, val range: ClosedFloatingPointRange<Double>, val displayName: String) {
HEAD(1, 0.75..0.9, "Head"),
BODY(0, 0.5..0.75, "Body"),
FEET(-1, 0.1..0.4, "Feet"),
UNKNOWN(-2, 0.0..0.0, "Unknown");
HEAD(1, 0.75..0.9, "Head"), BODY(0, 0.5..0.75, "Body"), FEET(-1, 0.1..0.4, "Feet"), UNKNOWN(
-2, 0.0..0.0, "Unknown"
);

companion object {
fun fromString(point: String): BodyPoint {
Expand Down

0 comments on commit a548ec6

Please sign in to comment.