Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: PointerESP (HUD) #4526

Open
wants to merge 5 commits into
base: nextgen
Choose a base branch
from
Open
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
30 changes: 30 additions & 0 deletions src-theme/public/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,36 @@
}
]
},
{
"name": "PointerESP",
"value": [
{
"name": "Enabled",
"value": true
},
{
"name": "Alignment",
"value": [
{
"name": "Horizontal",
"value": "CenterTranslated"
},
{
"name": "HorizontalOffset",
"value": 0
},
{
"name": "Vertical",
"value": "CenterTranslated"
},
{
"name": "VerticalOffset",
"value": 0
}
]
}
]
},
{
"name": "Effects",
"value": [
Expand Down
6 changes: 5 additions & 1 deletion src-theme/src/integration/events.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {Component, PlayerData, Proxy, Server, TextComponent} from "./types";
import type {Component, PlayerData, Pointer, Proxy, Server, TextComponent} from "./types";

export interface ToggleModuleEvent {
moduleName: string;
Expand Down Expand Up @@ -51,6 +51,10 @@ export interface BlockCountChangeEvent {
count?: number;
}

export interface PointerInfoEvent {
pointers?: Pointer[];
}

export interface AccountManagerAdditionEvent {
username: string | null;
error: string | null;
Expand Down
7 changes: 7 additions & 0 deletions src-theme/src/integration/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,3 +404,10 @@ export interface EntityHitResult extends HitResult {
entityType: string;
entityPos: Vec3;
}

export interface Pointer {
radius: number;
color: string;
rotateX: number;
rotateZ: number;
}
3 changes: 3 additions & 0 deletions src-theme/src/routes/hud/Hud.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import Keystrokes from "./elements/keystrokes/Keystrokes.svelte";
import Effects from "./elements/Effects.svelte";
import BlockCounter from "./elements/BlockCounter.svelte";
import PointerESP from "./elements/pointeresp/PointerESP.svelte";
import Text from "./elements/Text.svelte";

let zoom = 100;
Expand Down Expand Up @@ -54,6 +55,8 @@
<TargetHud/>
{:else if c.name === "BlockCounter"}
<BlockCounter/>
{:else if c.name === "PointerESP"}
<PointerESP/>
{:else if c.name === "Hotbar"}
<HotBar/>
{:else if c.name === "Scoreboard"}
Expand Down
27 changes: 27 additions & 0 deletions src-theme/src/routes/hud/elements/pointeresp/PointerESP.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script lang="ts">

import {listen} from "../../../../integration/ws";
import type {PointerInfoEvent} from "../../../../integration/events";
import type {Pointer} from "../../../../integration/types";
import PointerView from "./PointerView.svelte";

let pointers: Pointer[] | undefined;

listen("pointerInfo", (e: PointerInfoEvent) => {
pointers = e.pointers;
});
</script>

<div class="container">
{#if pointers}
{#each pointers as pointer}
<PointerView {...pointer}/>
{/each}
{/if}
</div>

<style lang="scss">
.container {
position: relative;
}
</style>
22 changes: 22 additions & 0 deletions src-theme/src/routes/hud/elements/pointeresp/PointerView.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script lang="ts">
export let color: string;
export let radius: number;
export let rotateX: number;
export let rotateZ: number;
</script>

<div class="pointer" style="
transform-origin: 50% {radius}px;
transform: translateY(-{radius}px) rotateX({rotateX}deg) rotateZ({rotateZ}deg);
border-bottom: 16px solid {color};
"></div>

<style lang="scss">
.pointer {
width: 0;
height: 0;
position: absolute;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ val ALL_EVENT_CLASSES: Array<KClass<out Event>> = arrayOf(
ServerPingedEvent::class,
TargetChangeEvent::class,
BlockCountChangeEvent::class,
PointerInfoEvent::class,
GameModeChangeEvent::class,
ComponentsUpdate::class,
ResourceReloadEvent::class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,19 @@ class TargetChangeEvent(val target: PlayerData?) : Event()
@WebSocketEvent
class BlockCountChangeEvent(val count: Int?) : Event()

@Nameable("pointerInfo")
@WebSocketEvent
class PointerInfoEvent(
val pointers: Array<Pointer>?
) : Event() {
class Pointer(
val radius: Int,
val color: String,
val rotateX: Float,
val rotateZ: Float
)
}

@Nameable("clientChatStateChange")
@WebSocketEvent
class ClientChatStateChange(val state: State) : Event() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ object ModuleManager : Listenable, Iterable<Module> by modules {
ModuleNoSwing,
ModuleCustomAmbience,
ModuleProphuntESP,
ModulePointerESP,
ModuleQuickPerspectiveSwap,
ModuleRotations,
ModuleSilentHotbar,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package net.ccbluex.liquidbounce.features.module.modules.render

import net.ccbluex.liquidbounce.config.ChoiceConfigurable
import net.ccbluex.liquidbounce.event.EventManager
import net.ccbluex.liquidbounce.event.events.OverlayRenderEvent
import net.ccbluex.liquidbounce.event.events.PointerInfoEvent
import net.ccbluex.liquidbounce.event.handler
import net.ccbluex.liquidbounce.features.module.Category
import net.ccbluex.liquidbounce.features.module.Module
import net.ccbluex.liquidbounce.render.GenericColorMode
import net.ccbluex.liquidbounce.render.GenericEntityHealthColorMode
import net.ccbluex.liquidbounce.render.GenericStaticColorMode
import net.ccbluex.liquidbounce.render.engine.Color4b
import net.ccbluex.liquidbounce.utils.client.toDegrees
import net.ccbluex.liquidbounce.utils.kotlin.mapArray
import net.ccbluex.liquidbounce.utils.math.minus
import net.minecraft.entity.LivingEntity
import java.awt.Color
import kotlin.math.atan2

object ModulePointerESP : Module("PointerESP", Category.RENDER) {

override val translationBaseKey: String
get() = "liquidbounce.module.pointerEsp"

private val modes = choices("ColorMode", 0) {
arrayOf(
DistanceColor,
GenericEntityHealthColorMode(it),
GenericStaticColorMode(it, Color4b.WHITE),
)
}

private object DistanceColor : GenericColorMode<LivingEntity>("Distance") {
override val parent: ChoiceConfigurable<*>
get() = modes

private val gradientRange by floatRange("GradientRange", 8f..48f, 0f..256f)
private val saturation by float("Saturation", 1f, 0f..1f)
private val brightness by float("Brightness", 1f, 0f..1f)

override fun getColor(param: LivingEntity): Color4b {
val length = gradientRange.endInclusive - gradientRange.start
val hue = (param.distanceTo(player).coerceIn(gradientRange) - gradientRange.start) / length / 3f
return Color4b(Color.getHSBColor(hue, saturation, brightness)) // Red to Green
}
}

private val renderRadius by int("RenderRadius", 150, 0..1000)

private val pitchLimit by floatRange("PitchLimit", 30f..90f, 0f..90f).onChanged {
negativePitchLimit = -it.endInclusive..-it.start
}

private var negativePitchLimit: ClosedFloatingPointRange<Float> = -pitchLimit.endInclusive..-pitchLimit.start

private var prevRotateX = 0f

val renderHandler = handler<OverlayRenderEvent> { event ->
val rotateX = player.pitch.let { p ->
when {
p in -pitchLimit.start..pitchLimit.start -> prevRotateX // keep prev
p < 0 -> 90f + p.coerceIn(negativePitchLimit)
else -> 90f + p.coerceIn(pitchLimit)
}
}

val pointers = ModuleESP.findRenderedEntities().mapArray {
val diff = it.pos - player.pos

val angle = (player.yaw - 90f - atan2(diff.z, diff.x).toFloat().toDegrees()).let { theta ->
if (mc.options.perspective.isFrontView) {
-theta
} else {
theta
}
}

PointerInfoEvent.Pointer(
renderRadius,
modes.activeChoice.getColor(it).toHex(alpha = true),
rotateX,
angle
)
}

EventManager.callEvent(PointerInfoEvent(pointers))

prevRotateX = rotateX
}

override fun disable() {
EventManager.callEvent(PointerInfoEvent(null))
prevRotateX = 0f
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ enum class ComponentType(
MINIMAP("Minimap", createComponent = { MinimapComponent }),
TARGET_HUD("TargetHud"),
BLOCK_COUNTER("BlockCounter"),
POINTER_ESP("PointerESP"),
KEYSTROKES("Keystrokes"),
TACO("Taco");

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

import net.ccbluex.liquidbounce.config.Choice
import net.ccbluex.liquidbounce.config.ChoiceConfigurable
import net.ccbluex.liquidbounce.features.module.modules.misc.ModuleTeams
import net.ccbluex.liquidbounce.render.engine.Color4b
import net.ccbluex.liquidbounce.render.utils.rainbow
import net.ccbluex.liquidbounce.utils.entity.getActualHealth
Expand Down Expand Up @@ -44,7 +45,6 @@ class MapColorMode(

}


class GenericEntityHealthColorMode(
override val parent: ChoiceConfigurable<*>
) : GenericColorMode<LivingEntity>("Health") {
Expand Down
Loading