diff --git a/src/main/kotlin/com/lambda/interaction/managers/rotating/visibilty/RotationTargets.kt b/src/main/kotlin/com/lambda/interaction/managers/rotating/visibilty/RotationTargets.kt index d0ae3a11f..bb5f55c70 100644 --- a/src/main/kotlin/com/lambda/interaction/managers/rotating/visibilty/RotationTargets.kt +++ b/src/main/kotlin/com/lambda/interaction/managers/rotating/visibilty/RotationTargets.kt @@ -33,6 +33,9 @@ import net.minecraft.util.hit.EntityHitResult import net.minecraft.util.hit.HitResult import net.minecraft.util.math.BlockPos import net.minecraft.util.math.Direction +import net.minecraft.util.math.Vec3d +import kotlin.math.atan2 +import kotlin.math.hypot @DslMarker annotation class RotationDsl @@ -50,6 +53,15 @@ fun lookAt(angle: Rotation, maxAngleDistance: Double = 0.001) = RotationManager.activeRotation dist angle < maxAngleDistance }) { angle } +@RotationDsl +fun lookAt(pos: Vec3d) = + RotationTarget(null) { + val direction = pos.subtract(player.eyePos).normalize() + val yaw = Math.toDegrees(atan2(direction.z, direction.x)) - 90.0 + val pitch = -Math.toDegrees(atan2(direction.y, hypot(direction.x, direction.z))) + Rotation(yaw, pitch) + } + @RotationDsl fun lookInDirection(direction: PlaceDirection) = RotationTarget(null, { diff --git a/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt b/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt index bf6264eac..d3e194926 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/Freecam.kt @@ -26,9 +26,12 @@ import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.interaction.managers.rotating.Rotation import com.lambda.interaction.managers.rotating.RotationConfig import com.lambda.interaction.managers.rotating.RotationMode +import com.lambda.interaction.managers.rotating.visibilty.lookAt import com.lambda.interaction.managers.rotating.visibilty.lookAtHit import com.lambda.module.Module import com.lambda.module.tag.ModuleTag +import com.lambda.util.Describable +import com.lambda.util.NamedEnum import com.lambda.util.extension.rotation import com.lambda.util.math.interpolate import com.lambda.util.math.plus @@ -44,6 +47,10 @@ import com.lambda.util.player.MovementUtils.roundedStrafing import com.lambda.util.player.MovementUtils.verticalMovement import com.lambda.util.world.raycast.RayCastUtils.orMiss import net.minecraft.client.option.Perspective +import net.minecraft.util.hit.BlockHitResult +import net.minecraft.util.hit.HitResult +import net.minecraft.util.math.BlockPos +import net.minecraft.util.math.Direction import net.minecraft.util.math.Vec3d object Freecam : Module( @@ -52,14 +59,19 @@ object Freecam : Module( tag = ModuleTag.PLAYER, autoDisable = true, ) { - private val speed by setting("Speed", 0.5, 0.1..1.0, 0.1) + private val speed by setting("Speed", 0.5, 0.1..1.0, 0.1, "Freecam movement speed", unit = "m/s") private val sprint by setting("Sprint Multiplier", 3.0, 0.1..10.0, 0.1, description = "Set below 1.0 to fly slower on sprint.") private val reach by setting("Reach", 10.0, 1.0..100.0, 1.0, "Freecam reach distance") - private val rotateToTarget by setting("Rotate to target", false) + private val rotateMode by setting("Rotate Mode", FreecamRotationMode.None, "Rotation mode") + .onValueChange { _, it -> if (it == FreecamRotationMode.LookAtTarget) mc.crosshairTarget = BlockHitResult.createMissed(Vec3d.ZERO, Direction.UP, BlockPos.ORIGIN) } + private val relative by setting("Relative", false, "Moves freecam relative to player position") + .onValueChange { _, it -> if (it) lastPlayerPosition = player.pos } + private val keepYLevel by setting("Keep Y Level", false, "Don't change the camera y-level on player movement") { relative } override val rotationConfig = RotationConfig.Instant(RotationMode.Lock) private var lastPerspective = Perspective.FIRST_PERSON + private var lastPlayerPosition: Vec3d = Vec3d.ZERO private var prevPosition: Vec3d = Vec3d.ZERO private var position: Vec3d = Vec3d.ZERO private val lerpPos: Vec3d @@ -90,6 +102,7 @@ object Freecam : Module( position = player.eyePos rotation = player.rotation velocity = Vec3d.ZERO + lastPlayerPosition = player.pos } onDisable { @@ -97,10 +110,17 @@ object Freecam : Module( } listen { - if (!rotateToTarget) return@listen - - mc.crosshairTarget?.let { - lookAtHit(it)?.requestBy(this@Freecam) + when (rotateMode) { + FreecamRotationMode.None -> return@listen + FreecamRotationMode.KeepRotation -> lookAt(rotation).requestBy(this@Freecam) + FreecamRotationMode.LookAtTarget -> + mc.crosshairTarget?.let { + when (it) { + is BlockHitResult -> lookAt(it.pos).requestBy(this@Freecam) + else -> lookAtHit(it)?.requestBy(this@Freecam) + + } + } } } @@ -135,14 +155,26 @@ object Freecam : Module( // Update position prevPosition = position position += velocity - } - listen { - it.cancel() + if (relative) { + val delta = player.pos.subtract(lastPlayerPosition) + position += if (keepYLevel) Vec3d(delta.x, 0.0, delta.z) else delta + lastPlayerPosition = player.pos + } + } + listen(priority = 1) { event -> // Higher priority then RotationManager to run before RotationManager modifies mc.crosshairTarget mc.crosshairTarget = rotation .rayCast(reach, lerpPos) .orMiss // Can't be null (otherwise mc will spam "Null returned as 'hitResult', this shouldn't happen!") + + mc.crosshairTarget?.let { if (it.type != HitResult.Type.MISS) event.cancel() } } } + + enum class FreecamRotationMode(override val displayName: String, override val description: String) : NamedEnum, Describable { + None("None", "No rotation changes"), + LookAtTarget("Look At Target", "Look at the block or entity under your crosshair"), + KeepRotation("Keep Rotation", "Look in the same direction as the camera"); + } }