Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -274,15 +274,14 @@ private static HitResult hookRaycast(HitResult original, Entity camera, double b
var throughWallsRange = ModuleReach.INSTANCE.getEntity().getInteractionThroughWallsRange$liquidbounce();

if (throughWallsRange > 0.0) {
var hitEntityResult = EntityRaytracingKt.findEntityInCrosshair(throughWallsRange, rotation, null);
var hitEntityResult = EntityRaytracingKt.findEntityInCrosshair(throughWallsRange, throughWallsRange, rotation, null);

if (hitEntityResult != null && hitEntityResult.getType() == HitResult.Type.ENTITY) {
return hitEntityResult;
}
}
}


return RaytracingKt.traceFromPlayer(
rotation,
Math.max(blockInteractionRange, entityInteractionRange),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,21 +60,24 @@ import net.ccbluex.liquidbounce.utils.aiming.utils.raytraceBox
import net.ccbluex.liquidbounce.utils.block.SwingMode
import net.ccbluex.liquidbounce.utils.combat.CombatManager
import net.ccbluex.liquidbounce.utils.combat.attackEntity
import net.ccbluex.liquidbounce.utils.combat.shouldBeAttacked
import net.ccbluex.liquidbounce.utils.entity.rotation
import net.ccbluex.liquidbounce.utils.entity.squaredBoxedDistanceTo
import net.ccbluex.liquidbounce.utils.inventory.InventoryManager.isInventoryOpen
import net.ccbluex.liquidbounce.utils.inventory.isInContainerScreen
import net.ccbluex.liquidbounce.utils.kotlin.Priority
import net.ccbluex.liquidbounce.utils.math.sq
import net.ccbluex.liquidbounce.utils.raytracing.attackableSelector
import net.ccbluex.liquidbounce.utils.raytracing.entitySelector
import net.ccbluex.liquidbounce.utils.raytracing.findEntityInCrosshair
import net.ccbluex.liquidbounce.utils.raytracing.isLookingAtEntity
import net.ccbluex.liquidbounce.utils.raytracing.traceFromPlayer
import net.ccbluex.liquidbounce.utils.render.TargetRenderer
import net.minecraft.client.gui.screens.inventory.ContainerScreen
import net.minecraft.world.InteractionHand
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.item.ItemStack
import net.minecraft.world.phys.BlockHitResult
import net.minecraft.world.phys.EntityHitResult
import net.minecraft.world.phys.HitResult

/**
* KillAura module
Expand Down Expand Up @@ -152,7 +155,7 @@ object ModuleKillAura : ClientModule("KillAura", ModuleCategories.COMBAT) {
}

@Suppress("unused")
private val gameHandler = tickHandler {
private val attackHandler = tickHandler {
if (player.isDeadOrDying || player.isSpectator) {
return@tickHandler
}
Expand Down Expand Up @@ -183,75 +186,43 @@ object ModuleKillAura : ClientModule("KillAura", ModuleCategories.COMBAT) {
return@tickHandler
}

// todo: prepare exact rotation beforehand
val rotation = (if (rotations.rotationTiming == ON_TICK) {
findRotation(target, range.interactionRange, range.interactionThroughWallsRange)?.rotation
} else {
null
} ?: RotationManager.currentRotation ?: player.rotation).normalize()

val crosshairTarget = when {
raycast != TRACE_NONE -> {
findEntityInCrosshair(range.interactionRange.toDouble(), rotation, predicate = {
when (raycast) {
TRACE_ONLYENEMY -> it.shouldBeAttacked()
TRACE_ALL -> true
else -> false
}
})?.entity ?: target
}
else -> target
}

if (crosshairTarget is LivingEntity && crosshairTarget.shouldBeAttacked() && crosshairTarget != target) {
targetTracker.target = crosshairTarget
}

attackTarget(crosshairTarget, rotation)
}

val shouldBlockSprinting
get() = !ModuleElytraTarget.running
&& criticalsSelectionMode.shouldStopSprinting(clicker, targetTracker.target)
debugParameter("Rotation") { rotation }

@Suppress("unused")
private val sprintHandler = handler<SprintEvent> { event ->
if (shouldBlockSprinting && (event.source == SprintEvent.Source.MOVEMENT_TICK ||
event.source == SprintEvent.Source.INPUT)) {
event.sprint = false
val selector = when (raycast) {
// We only care about our own entity.
TRACE_NONE -> entitySelector(target)
// We care about all attackable entities.
TRACE_ONLYENEMY -> attackableSelector()
// We care about everyone.
TRACE_ALL -> null
}
}

@Suppress("CognitiveComplexMethod", "CyclomaticComplexMethod")
private suspend fun attackTarget(target: Entity, rotation: Rotation) {
// Make it seem like we are blocking
KillAuraAutoBlock.makeSeemBlock()

debugParameter("Rotation") { rotation }
debugParameter("Target") { target.scoreboardName }

val attackHitResult = isLookingAtEntity(
toEntity = target,
rotation = rotation,
// Either we find our entity in crosshair, or we trace a block.
val hitResult = findEntityInCrosshair(
range = range.interactionRange.toDouble(),
throughWallsRange = range.interactionThroughWallsRange.toDouble()
)

debugParameter("Target Hit Result") { attackHitResult?.location }
throughWallsRange = range.interactionThroughWallsRange.toDouble(),
rotation = rotation,
predicate = selector
) ?: traceFromPlayer(rotation = rotation)

val isInRange = ModuleElytraTarget.canIgnoreKillAuraRotations ||
attackHitResult != null && range.isInRange(pos = attackHitResult.location)
debugParameter("Is In Range") { isInRange }
debugParameter("Hit Result") { hitResult }

// Check if our target is in range, otherwise deal with auto block
if (!isInRange) {
KillAuraAutoBlock.makeSeemBlock()
if (!startAttack(hitResult, rotation)) {
if (KillAuraAutoBlock.enabled && KillAuraAutoBlock.onScanRange &&
player.squaredBoxedDistanceTo(target) <= range.scanRange.sq()
) {
KillAuraAutoBlock.startBlocking()
return
return@tickHandler
}

// Make sure we are not blocking
val hasUnblocked = KillAuraAutoBlock.stopBlocking()

// Deal with fake swing
Expand All @@ -262,39 +233,76 @@ object ModuleKillAura : ClientModule("KillAura", ModuleCategories.COMBAT) {

dealWithFakeSwing(target)
}
return
}
}

debugParameter("Valid Rotation") { rotation }
val shouldBlockSprinting
get() = !ModuleElytraTarget.running
&& criticalsSelectionMode.shouldStopSprinting(clicker, targetTracker.target)

val itemStack = player.getItemInHand(InteractionHand.MAIN_HAND)
@Suppress("unused")
private val sprintHandler = handler<SprintEvent> { event ->
if (shouldBlockSprinting && (event.source == SprintEvent.Source.MOVEMENT_TICK ||
event.source == SprintEvent.Source.INPUT)) {
event.sprint = false
}
}

@Suppress("CognitiveComplexMethod", "CyclomaticComplexMethod", "ReturnCount")
private suspend fun startAttack(hitResult: HitResult, rotation: Rotation): Boolean {
if (player.isHandsBusy || !clicker.isClickTick) {
return false
}

val itemStack = player.mainHandItem
if (!canAttackWithItemStack(itemStack)) {
return false
}

when (hitResult) {
is EntityHitResult if (hitResult.type == HitResult.Type.ENTITY) -> {
val target = hitResult.entity

val isInRange = ModuleElytraTarget.canIgnoreKillAuraRotations ||
range.isInRange(pos = hitResult.location)
debugParameter("Is In Range") { isInRange }
if (!isInRange) {
return false
}

// Attack enemy, according to the attack scheduler
if (clicker.isClickTick && canAttackNow(target, itemStack)) {
clicker.attack(rotation) {
// On each click, we check if we are still ready to attack
if (!canAttackNow(target, itemStack)) {
return@attack false
if (canAttackTarget(target)) {
return false
}

// Attack enemy
attackEntity(target, SwingMode.DO_NOT_HIDE, keepSprint && !shouldBlockSprinting)
range.update()
KillAuraNotifyWhenFail.failedHitsIncrement = 0
clicker.attack(rotation) {
// On each click, we check if we are still ready to attack
if (!canAttackTarget(target)) {
return@attack false
}

GenericDebugRecorder.recordDebugInfo(ModuleKillAura, "attackEntity", JsonObject().apply {
add("player", GenericDebugRecorder.debugObject(player))
add("targetPos", GenericDebugRecorder.debugObject(target))
})
// Attack enemy
attackEntity(target, SwingMode.DO_NOT_HIDE, keepSprint && !shouldBlockSprinting)
range.update()
KillAuraNotifyWhenFail.failedHitsIncrement = 0

true
GenericDebugRecorder.recordDebugInfo(ModuleKillAura, "attackEntity", JsonObject().apply {
add("player", GenericDebugRecorder.debugObject(player))
add("targetPos", GenericDebugRecorder.debugObject(target))
})
true
}
return true
}
is BlockHitResult if (hitResult.type == HitResult.Type.BLOCK) -> {
// todo: handle block hit
}
else -> {
// todo: set misstime and reset strength ticket
return false
}
} else if (KillAuraAutoBlock.currentTickOff > 0 && clicker.willClickAt(KillAuraAutoBlock.currentTickOff)
&& KillAuraAutoBlock.shouldUnblockToHit) {
KillAuraAutoBlock.stopBlocking(pauses = true)
} else {
KillAuraAutoBlock.startBlocking()
}

return false
}

private fun updateTarget() {
Expand Down Expand Up @@ -421,26 +429,27 @@ object ModuleKillAura : ClientModule("KillAura", ModuleCategories.COMBAT) {
/**
* Check if we can attack the target at the current moment
*/
internal fun canAttackNow(
target: Entity? = null,
itemStack: ItemStack = player.getItemInHand(InteractionHand.MAIN_HAND)
): Boolean {
if (!itemStack.isItemEnabled(world.enabledFeatures())) {
internal fun canAttackTarget(target: Entity? = null): Boolean {
val criticalHitAllowed = target == null || player.isFallFlying || criticalsSelectionMode.isCriticalHit(target)
if (!criticalHitAllowed) {
return false
}

if (player.cannotAttackWithItem(itemStack, 0)) {
val isInventoryBlockingAttack = (isInventoryOpen || isInContainerScreen) &&
!ignoreOpenInventory && !simulateInventoryClosing
return !isInventoryBlockingAttack
}

internal fun canAttackWithItemStack(itemStack: ItemStack): Boolean {
if (!itemStack.isItemEnabled(world.enabledFeatures())) {
return false
}

val criticalHitAllowed = target == null || player.isFallFlying || criticalsSelectionMode.isCriticalHit(target)
if (!criticalHitAllowed) {
if (player.cannotAttackWithItem(itemStack, 0)) {
return false
}

val isInventoryBlockingAttack = (isInventoryOpen || isInContainerScreen) &&
!ignoreOpenInventory && !simulateInventoryClosing
return !isInventoryBlockingAttack
return true
}

enum class RaycastMode(override val choiceName: String) : NamedChoice {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import net.ccbluex.liquidbounce.event.events.AttackEntityEvent
import net.ccbluex.liquidbounce.event.handler
import net.ccbluex.liquidbounce.features.module.modules.combat.killaura.KillAuraClicker.attack
import net.ccbluex.liquidbounce.features.module.modules.combat.killaura.ModuleKillAura
import net.ccbluex.liquidbounce.features.module.modules.combat.killaura.ModuleKillAura.canAttackNow
import net.ccbluex.liquidbounce.features.module.modules.combat.killaura.ModuleKillAura.canAttackTarget
import net.ccbluex.liquidbounce.features.module.modules.combat.killaura.features.KillAuraFailSwing.additionalRange
import net.ccbluex.liquidbounce.features.module.modules.combat.killaura.features.KillAuraNotifyWhenFail.Box
import net.ccbluex.liquidbounce.features.module.modules.combat.killaura.features.KillAuraNotifyWhenFail.Sound
Expand Down Expand Up @@ -64,7 +64,7 @@ internal object KillAuraFailSwing : ToggleableConfigurable(ModuleKillAura, "Fail
}

suspend fun dealWithFakeSwing(target: Entity?) {
if (!enabled || !canAttackNow()) {
if (!enabled || !canAttackTarget()) {
return
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package net.ccbluex.liquidbounce.utils.raytracing

import net.ccbluex.liquidbounce.utils.aiming.data.Rotation
import net.ccbluex.liquidbounce.utils.client.mc
import net.ccbluex.liquidbounce.utils.combat.shouldBeAttacked
import net.ccbluex.liquidbounce.utils.math.sq
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.EntitySelector
Expand All @@ -29,6 +30,7 @@ import java.util.function.Predicate

fun Entity.findEntityInCrosshair(
range: Double,
throughWallsRange: Double = range,
rotation: Rotation,
predicate: Predicate<Entity>? = null,
): EntityHitResult? {
Expand All @@ -38,7 +40,7 @@ fun Entity.findEntityInCrosshair(
val vec3d3 = cameraVec.add(rotationVec.x * range, rotationVec.y * range, rotationVec.z * range)
val box = boundingBox.expandTowards(rotationVec.scale(range)).inflate(1.0, 1.0, 1.0)

val hitResult = ProjectileUtil.getEntityHitResult(
val entityHitResult = ProjectileUtil.getEntityHitResult(
this,
cameraVec,
vec3d3,
Expand All @@ -47,43 +49,39 @@ fun Entity.findEntityInCrosshair(
range.sq()
)

return hitResult
return entityHitResult?.takeIf { hitResult ->
val distanceSqr = cameraVec.distanceToSqr(hitResult.location)

distanceSqr <= throughWallsRange.sq() ||
distanceSqr <= range.sq() && hasLineOfSight(cameraVec, hitResult.location)
}
}

fun findEntityInCrosshair(
range: Double,
throughWallsRange: Double = range,
rotation: Rotation,
predicate: Predicate<Entity>? = null,
): EntityHitResult? = mc.cameraEntity?.findEntityInCrosshair(range, rotation, predicate)
): EntityHitResult? = mc.cameraEntity?.findEntityInCrosshair(range, throughWallsRange, rotation, predicate)

fun entitySelector(selected: Entity) = Predicate<Entity> { entity ->
entity == selected
}

fun attackableSelector() = Predicate<Entity> { entity ->
entity.shouldBeAttacked()
}

/**
* Allows you to check if your enemy is behind a wall
*/
fun isLookingAtEntity(
toEntity: Entity,
range: Double,
rotation: Rotation,
) = findEntityInCrosshair(range, rotation) { entity ->
!entity.isSpectator && entity.isPickable && entity == toEntity
}
) = findEntityInCrosshair(range, range, rotation, entitySelector(toEntity))

fun isLookingAtEntity(
fromEntity: Entity = mc.cameraEntity!!,
toEntity: Entity,
rotation: Rotation,
range: Double,
throughWallsRange: Double,
): EntityHitResult? {
val cameraVec = fromEntity.eyePosition
val entityHitResult = fromEntity.findEntityInCrosshair(range, rotation) { entity ->
entity == toEntity
} ?: return null

val distance = cameraVec.distanceToSqr(entityHitResult.location)

// Either within through-walls range, or within normal range and has line of sight
return entityHitResult.takeIf {
distance <= throughWallsRange.sq()
|| distance <= range.sq() && hasLineOfSight(cameraVec, entityHitResult.location)
}
}
) = fromEntity.findEntityInCrosshair(range, throughWallsRange, rotation, entitySelector(toEntity))
Loading