Bonker Client

Advanced Bonk.io client with trajectory prediction, ESP, player tracking, and more

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         Bonker Client
// @version      2.5
// @description  Advanced Bonk.io client with trajectory prediction, ESP, player tracking, and more
// @author       levifrsn63
// @icon         https://bonk.io/graphics/tt/favicon-32x32.png
// @match        https://bonk.io/*
// @match        https://bonk.io/gameframe-release.html
// @run-at       document-end
// @grant        none
// @namespace    https://greasyfork.org/users/1015072
// ==/UserScript==

(function () {
    "use strict";

    function injector(func) {
        if (
            window.location.hostname === "bonk.io" &&
            window.location.pathname !== "/gameframe-release.html"
        ) {
            const waitForFrame = setInterval(() => {
                const frame = document.getElementById("maingameframe");
                if (frame && frame.contentWindow && frame.contentDocument) {
                    const script = document.createElement("script");
                    script.textContent = `(${func.toString()})();`;
                    frame.contentDocument.head.appendChild(script);
                    clearInterval(waitForFrame);
                }
            }, 500);
        } else {
            func();
        }
    }

    injector(function () {
        const scope = window;
        if (!scope.PIXI || !scope.PIXI.Graphics) return;

        // Prevent duplicate UI creation
        if (scope._trajectoryDebugLoaded) return;
        scope._trajectoryDebugLoaded = true;

        //Constants
        const BASE_RADIUS_PPM = 19.709589041095892;

        const PHYSICS = {
            GRAVITY: 197,
            VEL_MULT: 592,
            VEL_BASE: 301,
        };

        const CONFIG = {
            MAX_CHARGE: 1.5,
            KEY: "KeyZ",
            POINTS: 50,
            SIM_TIME: 10.0,
            DRAW_ENEMIES: true,
            REQUIRE_KEY_FOR_SELF: false,
            SHOW_TRAJECTORY: true, // Changed from ALWAYS_SHOW_SELF - now controls if trajectory shows at all
            DRAW_NEAREST_LINE: false,
            DRAW_ALL_PLAYER_LINES: false,
            DRAW_SELF_HITBOX: false,
            MUTE_MUSIC: false,
            HIDE_UI_KEY: "KeyO",

            // Aimbot settings
            AIMBOT_ENABLED: true,
            AIMBOT_PREDICTION: 1.2,
            AIMBOT_MULTIPLIER: 1.2,
            AIMBOT_GRAVITY: 200,
            HEAVY_BOT: false,
            HEAVY_BOT_DISTANCE: 1.1,

            LOCAL: {
                COLOR: 0xd3d3d3,
                THICKNESS: 2,
                ALPHA: 0.1,
            },

            ENEMY: {
                COLOR: 0xd3d3d3,
                THICKNESS: 2,
                ALPHA: 0.1,
            },

            NEAREST_LINE: {
                COLOR: 0xff0000,
                THICKNESS: 3,
                ALPHA: 0.6,
            },

            ALL_PLAYERS_LINE: {
                COLOR: 0xff0000,
                NEAREST_COLOR: 0x00ff00,
                THICKNESS: 1,
                ALPHA: 0.4,
            },

            SELF_HITBOX: {
                OUTLINE_COLOR: 0x00ff00,
                FILL_COLOR: 0x00ff00,
                OUTLINE_THICKNESS: 3,
                FILL_ALPHA: 0.15,
                OUTLINE_ALPHA: 0.8,
            },
        };

        let uiCompletelyHidden = false;
        let isFullscreen = false;
        let isResizing = false;
        let resizeStartX, resizeStartY, resizeStartWidth, resizeStartHeight;

        // Load settings from localStorage
        function loadSettings() {
            try {
                const saved = localStorage.getItem("bonkTrajectorySettings");
                if (saved) {
                    const settings = JSON.parse(saved);
                    if (settings.DRAW_ENEMIES !== undefined)
                        CONFIG.DRAW_ENEMIES = settings.DRAW_ENEMIES;
                    if (settings.SHOW_TRAJECTORY !== undefined)
                        CONFIG.SHOW_TRAJECTORY = settings.SHOW_TRAJECTORY;
                    if (settings.DRAW_NEAREST_LINE !== undefined)
                        CONFIG.DRAW_NEAREST_LINE = settings.DRAW_NEAREST_LINE;
                    if (settings.DRAW_ALL_PLAYER_LINES !== undefined)
                        CONFIG.DRAW_ALL_PLAYER_LINES =
                            settings.DRAW_ALL_PLAYER_LINES;
                    if (settings.DRAW_SELF_HITBOX !== undefined)
                        CONFIG.DRAW_SELF_HITBOX = settings.DRAW_SELF_HITBOX;
                    if (settings.MUTE_MUSIC !== undefined)
                        CONFIG.MUTE_MUSIC = settings.MUTE_MUSIC;
                    if (settings.HIDE_UI_KEY !== undefined)
                        CONFIG.HIDE_UI_KEY = settings.HIDE_UI_KEY;
                    if (settings.LOCAL_COLOR !== undefined)
                        CONFIG.LOCAL.COLOR = settings.LOCAL_COLOR;
                    if (settings.LOCAL_ALPHA !== undefined)
                        CONFIG.LOCAL.ALPHA = settings.LOCAL_ALPHA;
                    if (settings.LOCAL_THICKNESS !== undefined)
                        CONFIG.LOCAL.THICKNESS = settings.LOCAL_THICKNESS;
                    if (settings.ENEMY_COLOR !== undefined)
                        CONFIG.ENEMY.COLOR = settings.ENEMY_COLOR;
                    if (settings.ENEMY_ALPHA !== undefined)
                        CONFIG.ENEMY.ALPHA = settings.ENEMY_ALPHA;
                    if (settings.ENEMY_THICKNESS !== undefined)
                        CONFIG.ENEMY.THICKNESS = settings.ENEMY_THICKNESS;
                    if (settings.NEAREST_LINE_COLOR !== undefined)
                        CONFIG.NEAREST_LINE.COLOR = settings.NEAREST_LINE_COLOR;
                    if (settings.NEAREST_LINE_ALPHA !== undefined)
                        CONFIG.NEAREST_LINE.ALPHA = settings.NEAREST_LINE_ALPHA;
                    if (settings.NEAREST_LINE_THICKNESS !== undefined)
                        CONFIG.NEAREST_LINE.THICKNESS =
                            settings.NEAREST_LINE_THICKNESS;
                    if (settings.HITBOX_OUTLINE_THICKNESS !== undefined)
                        CONFIG.SELF_HITBOX.OUTLINE_THICKNESS =
                            settings.HITBOX_OUTLINE_THICKNESS;
                    if (settings.HEAVY_BOT !== undefined)
                        CONFIG.HEAVY_BOT = settings.HEAVY_BOT;
                    if (settings.HEAVY_BOT_DISTANCE !== undefined)
                        CONFIG.HEAVY_BOT_DISTANCE = settings.HEAVY_BOT_DISTANCE;
                }
            } catch (e) {
                // Silently handle settings load errors
            }
        }

        // Save settings to localStorage
        function saveSettings() {
            try {
                const settings = {
                    DRAW_ENEMIES: CONFIG.DRAW_ENEMIES,
                    SHOW_TRAJECTORY: CONFIG.SHOW_TRAJECTORY,
                    DRAW_NEAREST_LINE: CONFIG.DRAW_NEAREST_LINE,
                    DRAW_ALL_PLAYER_LINES: CONFIG.DRAW_ALL_PLAYER_LINES,
                    DRAW_SELF_HITBOX: CONFIG.DRAW_SELF_HITBOX,
                    MUTE_MUSIC: CONFIG.MUTE_MUSIC,
                    HIDE_UI_KEY: CONFIG.HIDE_UI_KEY,
                    LOCAL_COLOR: CONFIG.LOCAL.COLOR,
                    LOCAL_ALPHA: CONFIG.LOCAL.ALPHA,
                    LOCAL_THICKNESS: CONFIG.LOCAL.THICKNESS,
                    ENEMY_COLOR: CONFIG.ENEMY.COLOR,
                    ENEMY_ALPHA: CONFIG.ENEMY.ALPHA,
                    ENEMY_THICKNESS: CONFIG.ENEMY.THICKNESS,
                    NEAREST_LINE_COLOR: CONFIG.NEAREST_LINE.COLOR,
                    NEAREST_LINE_ALPHA: CONFIG.NEAREST_LINE.ALPHA,
                    NEAREST_LINE_THICKNESS: CONFIG.NEAREST_LINE.THICKNESS,
                    HITBOX_OUTLINE_THICKNESS:
                        CONFIG.SELF_HITBOX.OUTLINE_THICKNESS,
                    HEAVY_BOT: CONFIG.HEAVY_BOT,
                    HEAVY_BOT_DISTANCE: CONFIG.HEAVY_BOT_DISTANCE,
                };
                localStorage.setItem(
                    "bonkTrajectorySettings",
                    JSON.stringify(settings),
                );
            } catch (e) {
                // Silently handle settings save errors
            }
        }

        // Load settings on startup
        loadSettings();

        let myUserName = null;
        let myPlayerContainer = null;
        let gameWorld = null;
        let myPlayerID = -1;
        let arcGraphics = null;
        let isHoldingKey = false;
        let currentPPM = BASE_RADIUS_PPM;
        let pixiObjectId = 0;

        // RGB transition for self hitbox
        let hueValue = 0;
        const HUE_SPEED = 5;

        // Separate faster RGB for client name
        let nameHueValue = 0;
        const NAME_HUE_SPEED = 10;

        // Aimbot helper functions from original.js
        function positive(angle) {
            while (angle < 0) angle += Math.PI * 2;
            while (angle > Math.PI * 2) angle -= Math.PI * 2;
            return angle;
        }

        function angle_between(a1, a2) {
            const diff = positive(a1 - a2);
            if (diff > Math.PI) return Math.PI * 2 - diff;
            return diff;
        }

        function angle_between2(a1, a2) {
            const diff = positive(a1 - a2);
            if (diff > Math.PI) return -(Math.PI * 2 - diff);
            return diff;
        }

        function fire(type, evt, el) {
            if (el) {
                const e = new Event(type, { bubbles: true, cancelable: true });
                Object.assign(e, evt);
                el.dispatchEvent(e);
            }
        }

        // Aimbot variables
        let aimbotStarted = 0;
        let leftRight = [37, 39]; // Left and right arrow key codes
        let currentIS = null;
        let scale = 1;
        let now = 0;
        let multiplier = CONFIG.AIMBOT_MULTIPLIER;
        let gravity = CONFIG.AIMBOT_GRAVITY;
        let prediction = CONFIG.AIMBOT_PREDICTION;

        // Create Main UI
        function createMainUI() {
            const panel = document.createElement("div");
            panel.id = "trajectory-main-panel";
            panel.style.cssText = `
                position: fixed;
                top: 10px;
                right: 10px;
                background: #f0f0f0;
                color: #000000;
                padding: 0;
                border: 2px solid #808080;
                font-family: 'Arial', 'Helvetica', sans-serif;
                font-size: 12px;
                z-index: 10000;
                min-width: 280px;
                width: 320px;
                max-height: 90vh;
                box-shadow: 2px 2px 0px #404040;
                resize: none;
                display: flex;
                flex-direction: column;
            `;

            panel.innerHTML = `
                <div id="panel-header" style="
                    background: linear-gradient(to bottom, #ffffff 0%, #d4d0c8 100%);
                    border-bottom: 2px solid #808080;
                    padding: 4px 6px;
                    cursor: move;
                    user-select: none;
                    font-weight: bold;
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                ">
                    <span>Bonker Nigga Client </span>
                    <button id="toggle-debug" style="
                        background: #d4d0c8;
                        border: 1px outset #ffffff;
                        padding: 2px 8px;
                        cursor: pointer;
                        font-size: 11px;
                        font-weight: normal;
                    ">Hide</button>
                </div>
                <div id="collapsed-client-info" style="
                    display: none;
                    padding: 4px 8px;
                    text-align: center;
                    font-size: 11px;
                    background: #f0f0f0;
                    border-bottom: 2px solid #808080;
                ">
                    <span style="font-weight: bold;">Client:</span> <span id="collapsed-name" style="font-style: italic;">Loading...</span>
                </div>
                <div id="tabs-container" style="display: flex; background: #e0e0e0; border-bottom: 2px solid #808080;">
                    <button class="tab-button" data-tab="visual" style="
                        flex: 1;
                        padding: 8px 4px;
                        background: #d4d0c8;
                        border: 1px outset #ffffff;
                        cursor: pointer;
                        font-size: 11px;
                        font-weight: bold;
                        border-right: 1px solid #808080;
                    ">Visual</button>
                    <button class="tab-button" data-tab="bots" style="
                        flex: 1;
                        padding: 8px 4px;
                        background: #d4d0c8;
                        border: 1px outset #ffffff;
                        cursor: pointer;
                        font-size: 11px;
                        font-weight: bold;
                        border-right: 1px solid #808080;
                    ">Bots</button>
                    <button class="tab-button" data-tab="other" style="
                        flex: 1;
                        padding: 8px 4px;
                        background: #d4d0c8;
                        border: 1px outset #ffffff;
                        cursor: pointer;
                        font-size: 11px;
                        font-weight: bold;
                        border-right: 1px solid #808080;
                    ">Other</button>
                    <button class="tab-button" data-tab="settings" style="
                        flex: 1;
                        padding: 8px 4px;
                        background: #d4d0c8;
                        border: 1px outset #ffffff;
                        cursor: pointer;
                        font-size: 11px;
                        font-weight: bold;
                    ">Settings</button>
                </div>
                <div id="settings-container" style="padding: 8px; background: #f0f0f0; overflow-y: auto; flex: 1; min-height: 0;">
                    <div id="tab-visual" class="tab-content" style="display: block;">
                        <fieldset style="border: 2px groove #d4d0c8; padding: 8px; margin-bottom: 8px; border-radius: 8px;">
                            <legend style="font-weight: bold; padding: 0 4px;">Trajectory Settings</legend>
                            <div style="margin-bottom: 6px;">
                                <label style="display: flex; align-items: center; cursor: pointer;">
                                    <input type="checkbox" id="show-trajectory-toggle" ${CONFIG.SHOW_TRAJECTORY ? "checked" : ""} style="margin-right: 6px;">
                                    <span>Show trajectory</span>
                                </label>
                            </div>
                            <div style="margin-bottom: 6px;">
                                <label style="display: flex; align-items: center; cursor: pointer;">
                                    <input type="checkbox" id="draw-enemies-toggle" ${CONFIG.DRAW_ENEMIES ? "checked" : ""} style="margin-right: 6px;">
                                    <span>Draw enemy trajectories</span>
                                </label>
                            </div>
                        </fieldset>

                        <fieldset style="border: 2px groove #d4d0c8; padding: 8px; margin-bottom: 8px; border-radius: 8px;">
                            <legend style="font-weight: bold; padding: 0 4px;">Player Lines</legend>
                            <div style="margin-bottom: 6px;">
                                <label style="display: flex; align-items: center; cursor: pointer;">
                                    <input type="radio" name="line-mode" id="nearest-line-toggle" ${CONFIG.DRAW_NEAREST_LINE ? "checked" : ""} style="margin-right: 6px;">
                                    <span>Line to nearest player</span>
                                </label>
                            </div>
                            <div style="margin-bottom: 6px;">
                                <label style="display: flex; align-items: center; cursor: pointer;">
                                    <input type="radio" name="line-mode" id="all-lines-toggle" ${CONFIG.DRAW_ALL_PLAYER_LINES ? "checked" : ""} style="margin-right: 6px;">
                                    <span>Lines to all players</span>
                                </label>
                            </div>
                            <div style="margin-bottom: 6px;">
                                <label style="display: flex; align-items: center; cursor: pointer;">
                                    <input type="radio" name="line-mode" id="no-lines-toggle" ${!CONFIG.DRAW_NEAREST_LINE && !CONFIG.DRAW_ALL_PLAYER_LINES ? "checked" : ""} style="margin-right: 6px;">
                                    <span>Off</span>
                                </label>
                            </div>
                            <div style="margin-top: 10px; margin-bottom: 6px;">
                                <label style="display: flex; align-items: center; cursor: pointer;">
                                    <input type="checkbox" id="self-hitbox-toggle" ${CONFIG.DRAW_SELF_HITBOX ? "checked" : ""} style="margin-right: 6px;">
                                    <span style="font-weight: bold;">Highlight my hitbox (RGB)</span>
                                </label>
                            </div>
                        </fieldset>

                        <details style="border: 2px groove #d4d0c8; padding: 0; margin-bottom: 8px; border-radius: 8px; overflow: hidden;">
                            <summary style="cursor: pointer; font-weight: bold; padding: 8px; background: #e8e8e8; list-style-position: inside;">Appearance</summary>
                            <div style="padding: 8px;">
                                <div style="margin-bottom: 8px;">
                                    <label style="display: block; margin-bottom: 4px; font-weight: bold;">Arrow Trajectory (Self):</label>
                                    <input type="color" id="color-picker-self" value="#d3d3d3" style="width: 100%; height: 30px; border: 1px inset #808080; cursor: pointer;">
                                </div>

                                <div style="margin-bottom: 8px;">
                                    <label style="display: block; margin-bottom: 4px; font-weight: bold;">Enemy Trajectories:</label>
                                    <input type="color" id="color-picker-enemy" value="#d3d3d3" style="width: 100%; height: 30px; border: 1px inset #808080; cursor: pointer;">
                                </div>

                                <div style="margin-bottom: 8px;">
                                    <label style="display: block; margin-bottom: 4px; font-weight: bold;">Nearest Player Line:</label>
                                    <input type="color" id="color-picker-nearest" value="#ff0000" style="width: 100%; height: 30px; border: 1px inset #808080; cursor: pointer;">
                                </div>

                                <div style="margin-bottom: 10px; padding-top: 10px; border-top: 1px solid #ccc;">
                                    <label style="display: block; margin-bottom: 3px; font-weight: bold;">Player Trajectory Opacity: <span id="player-trajectory-opacity-value">${Math.round(CONFIG.LOCAL.ALPHA * 100)}%</span></label>
                                    <input type="range" id="player-trajectory-opacity-slider" min="10" max="100" step="5" value="${CONFIG.LOCAL.ALPHA * 100}" style="width: 100%;">
                                </div>

                                <div style="margin-bottom: 10px;">
                                    <label style="display: block; margin-bottom: 3px; font-weight: bold;">Enemy Trajectory Opacity: <span id="enemy-trajectory-opacity-value">${Math.round(CONFIG.ENEMY.ALPHA * 100)}%</span></label>
                                    <input type="range" id="enemy-trajectory-opacity-slider" min="10" max="100" step="5" value="${CONFIG.ENEMY.ALPHA * 100}" style="width: 100%;">
                                </div>

                                <div style="margin-bottom: 10px;">
                                    <label style="display: block; margin-bottom: 3px; font-weight: bold;">Player Lines Opacity: <span id="player-lines-opacity-value">${Math.round(CONFIG.NEAREST_LINE.ALPHA * 100)}%</span></label>
                                    <input type="range" id="player-lines-opacity-slider" min="10" max="100" step="5" value="${CONFIG.NEAREST_LINE.ALPHA * 100}" style="width: 100%;">
                                </div>

                                <div style="margin-bottom: 10px; padding-top: 10px; border-top: 1px solid #ccc;">
                                    <label style="display: block; margin-bottom: 3px; font-weight: bold;">Trajectory Thickness: <span id="trajectory-thickness-value">${CONFIG.LOCAL.THICKNESS}</span>px</label>
                                    <input type="range" id="trajectory-thickness-slider" min="1" max="10" step="1" value="${CONFIG.LOCAL.THICKNESS}" style="width: 100%;">
                                </div>

                                <div style="margin-bottom: 10px;">
                                    <label style="display: block; margin-bottom: 3px; font-weight: bold;">Player Lines Thickness: <span id="player-lines-thickness-value">${CONFIG.NEAREST_LINE.THICKNESS}</span>px</label>
                                    <input type="range" id="player-lines-thickness-slider" min="1" max="10" step="1" value="${CONFIG.NEAREST_LINE.THICKNESS}" style="width: 100%;">
                                </div>

                                <div style="margin-bottom: 10px;">
                                    <label style="display: block; margin-bottom: 3px; font-weight: bold;">Self Hitbox Outline: <span id="hitbox-thickness-value">${CONFIG.SELF_HITBOX.OUTLINE_THICKNESS}</span>px</label>
                                    <input type="range" id="hitbox-thickness-slider" min="1" max="10" step="1" value="${CONFIG.SELF_HITBOX.OUTLINE_THICKNESS}" style="width: 100%;">
                                </div>
                            </div>
                        </details>
                    </div>

                    <div id="tab-bots" class="tab-content" style="display: none;">
                        <fieldset style="border: 2px groove #d4d0c8; padding: 8px; margin-bottom: 8px; border-radius: 8px;">
                            <legend style="font-weight: bold; padding: 0 4px;">Aimbot</legend>
                            <div style="margin-bottom: 6px;">
                                <label style="display: flex; align-items: center; cursor: pointer;">
                                    <input type="checkbox" id="aimbot-enabled-toggle" ${CONFIG.AIMBOT_ENABLED ? "checked" : ""} style="margin-right: 6px;">
                                    <span style="font-weight: bold;">Enable Aimbot</span>
                                </label>
                            </div>
                            <div style="margin-bottom: 6px;">
                                <label style="display: flex; align-items: center; cursor: pointer;">
                                    <input type="checkbox" id="heavy-bot-toggle" ${CONFIG.HEAVY_BOT ? "checked" : ""} style="margin-right: 6px;">
                                    <span style="font-weight: bold;">Heavy Bot</span>
                                </label>
                            </div>
                            <div id="bots-info-box" style="margin-top: 10px; padding: 8px; background: #fffacd; border: 1px solid #ffd700; border-radius: 4px; display: none;">
                                <div style="font-size: 11px; color: #333; margin-bottom: 4px;"><strong>Info:</strong></div>
                                <div style="font-size: 10px; color: #666; line-height: 1.3;">
                                    • Auto-aims at nearest player<br>
                                    • Uses arrow keys to control<br>
                                    • Includes trajectory prediction<br>
                                    • Works with child "e" (arrow)
                                </div>
                            </div>
                        </fieldset>
                    </div>

                    <div id="tab-other" class="tab-content" style="display: none;">
                        <div style="color: #909296; font-size: 11px; font-weight: 700; text-transform: uppercase; margin-bottom: 15px; letter-spacing: 1px;">Networking</div>
                        <div style="background: #141517; border-radius: 6px; padding: 10px; font-family: monospace; font-size: 11px; color: #a5d8ff; max-height: 200px; overflow-y: auto; margin-bottom: 10px;">
                            <div style="color: #666; font-style: italic;">No active connections...</div>
                        </div>
                    </div>

                    <div id="tab-settings" class="tab-content" style="display: none;">
                        <details style="border: 2px groove #d4d0c8; padding: 0; margin-bottom: 8px; border-radius: 8px; overflow: hidden;" open>
                            <summary style="cursor: pointer; font-weight: bold; padding: 8px; background: #e8e8e8; list-style-position: inside;">Settings</summary>
                            <div style="padding: 8px;">
                                <div style="margin-bottom: 12px;">
                                    <label style="display: block; margin-bottom: 4px; font-weight: bold;">Hide UI Hotkey:</label>
                                    <input type="text" id="hide-ui-key-input" value="${CONFIG.HIDE_UI_KEY}" readonly style="
                                        width: 100%;
                                        padding: 4px;
                                        background: #ffffff;
                                        border: 1px inset #808080;
                                        cursor: pointer;
                                        text-align: center;
                                    " placeholder="Press a key...">
                                    <div style="font-size: 10px; color: #666; margin-top: 2px;">Click and press any key to set hotkey</div>
                                </div>

                                <div style="margin-bottom: 10px; padding-top: 10px; border-top: 1px solid #ccc;">
                                    <label style="display: block; margin-bottom: 3px; font-weight: bold;">Player Trajectory Opacity: <span id="player-trajectory-opacity-value">${Math.round(CONFIG.LOCAL.ALPHA * 100)}%</span></label>
                                    <input type="range" id="player-trajectory-opacity-slider" min="10" max="100" step="5" value="${CONFIG.LOCAL.ALPHA * 100}" style="width: 100%;">
                                </div>

                                <div style="margin-bottom: 10px;">
                                    <label style="display: block; margin-bottom: 3px; font-weight: bold;">Enemy Trajectory Opacity: <span id="enemy-trajectory-opacity-value">${Math.round(CONFIG.ENEMY.ALPHA * 100)}%</span></label>
                                    <input type="range" id="enemy-trajectory-opacity-slider" min="10" max="100" step="5" value="${CONFIG.ENEMY.ALPHA * 100}" style="width: 100%;">
                                </div>

                                <div style="margin-bottom: 10px;">
                                    <label style="display: block; margin-bottom: 3px; font-weight: bold;">Player Lines Opacity: <span id="player-lines-opacity-value">${Math.round(CONFIG.NEAREST_LINE.ALPHA * 100)}%</span></label>
                                    <input type="range" id="player-lines-opacity-slider" min="10" max="100" step="5" value="${CONFIG.NEAREST_LINE.ALPHA * 100}" style="width: 100%;">
                                </div>

                                <div style="margin-bottom: 10px; padding-top: 10px; border-top: 1px solid #ccc;">
                                    <label style="display: block; margin-bottom: 3px; font-weight: bold;">Trajectory Thickness: <span id="trajectory-thickness-value">${CONFIG.LOCAL.THICKNESS}</span>px</label>
                                    <input type="range" id="trajectory-thickness-slider" min="1" max="10" step="1" value="${CONFIG.LOCAL.THICKNESS}" style="width: 100%;">
                                </div>

                                <div style="margin-bottom: 10px;">
                                    <label style="display: block; margin-bottom: 3px; font-weight: bold;">Player Lines Thickness: <span id="player-lines-thickness-value">${CONFIG.NEAREST_LINE.THICKNESS}</span>px</label>
                                    <input type="range" id="player-lines-thickness-slider" min="1" max="10" step="1" value="${CONFIG.NEAREST_LINE.THICKNESS}" style="width: 100%;">
                                </div>

                                <div style="margin-bottom: 10px;">
                                    <label style="display: block; margin-bottom: 3px; font-weight: bold;">Self Hitbox Outline: <span id="hitbox-thickness-value">${CONFIG.SELF_HITBOX.OUTLINE_THICKNESS}</span>px</label>
                                    <input type="range" id="hitbox-thickness-slider" min="1" max="10" step="1" value="${CONFIG.SELF_HITBOX.OUTLINE_THICKNESS}" style="width: 100%;">
                                </div>

                                <div style="margin-bottom: 10px; padding-top: 10px; border-top: 1px solid #ccc;">
                                    <label style="display: block; margin-bottom: 4px; font-weight: bold;">Heavy Bot Distance (m): <span id="heavy-dist-settings-val">${CONFIG.HEAVY_BOT_DISTANCE.toFixed(2)}</span></label>
                                    <input type="range" id="heavy-dist-settings-slider" min="0.8" max="2" step="0.01" value="${CONFIG.HEAVY_BOT_DISTANCE}" style="width: 100%;">
                                </div>
                            </div>
                        </details>
                    </div>
                </div>
                <div style="
                    background: #d4d0c8;
                    border-top: 2px solid #808080;
                    padding: 4px 8px;
                    font-size: 10px;
                    text-align: center;
                    flex-shrink: 0;
                ">
                    <span style="font-weight: bold;">Client:</span> <span id="client-name" style="font-style: italic;">Loading...</span>
                </div>
                <div id="resize-handle" style="
                    position: absolute;
                    bottom: 0;
                    right: 0;
                    width: 16px;
                    height: 16px;
                    cursor: nwse-resize;
                    z-index: 10;
                    background: linear-gradient(135deg, transparent 0%, transparent 40%, #808080 40%, #808080 45%, transparent 45%, transparent 55%, #808080 55%, #808080 60%, transparent 60%);
                "></div>
            `;

            document.body.appendChild(panel);

            // Tab functionality
            const tabButtons = panel.querySelectorAll(".tab-button");
            const tabContents = panel.querySelectorAll(".tab-content");

            function switchTab(tabName) {
                tabContents.forEach((content) => {
                    content.style.display =
                        content.id === `tab-${tabName}` ? "block" : "none";
                });

                tabButtons.forEach((button) => {
                    if (button.dataset.tab === tabName) {
                        button.style.background = "#c0c0c0";
                        button.style.border = "1px solid #444";
                        button.style.borderRadius = "4px";
                    } else {
                        button.style.background = "#d4d0c8";
                        button.style.border = "1px outset #ffffff";
                        button.style.borderRadius = "0px";
                    }
                });
            }

            tabButtons.forEach((button) => {
                button.addEventListener("click", () => {
                    switchTab(button.dataset.tab);
                });
            });

            // Initialize first tab
            switchTab("visual");

            // Make panel draggable
            const header = document.getElementById("panel-header");
            let isDragging = false;
            let currentX;
            let currentY;
            let initialX;
            let initialY;
            let xOffset = 0;
            let yOffset = 0;

            header.addEventListener("mousedown", dragStart);
            document.addEventListener("mousemove", drag);
            document.addEventListener("mouseup", dragEnd);

            function dragStart(e) {
                if (e.target === document.getElementById("toggle-debug")) {
                    return;
                }

                initialX = e.clientX - xOffset;
                initialY = e.clientY - yOffset;

                if (e.target === header || header.contains(e.target)) {
                    isDragging = true;
                }
            }

            function drag(e) {
                if (isDragging) {
                    e.preventDefault();

                    currentX = e.clientX - initialX;
                    currentY = e.clientY - initialY;

                    xOffset = currentX;
                    yOffset = currentY;

                    setTranslate(currentX, currentY, panel);
                }
            }

            function dragEnd(e) {
                initialX = currentX;
                initialY = currentY;
                isDragging = false;
            }

            function setTranslate(xPos, yPos, el) {
                el.style.transform = `translate(${xPos}px, ${yPos}px)`;
            }

            // Make panel resizable by dragging bottom-right corner
            const resizeHandle = document.getElementById("resize-handle");

            resizeHandle.addEventListener("mousedown", (e) => {
                e.stopPropagation();
                e.preventDefault();
                isResizing = true;
                resizeStartX = e.clientX;
                resizeStartY = e.clientY;

                const rect = panel.getBoundingClientRect();
                resizeStartWidth = rect.width;
                resizeStartHeight = rect.height;

                const currentTransform = panel.style.transform;
                if (currentTransform && currentTransform !== "none") {
                    const matrix = new DOMMatrix(currentTransform);
                    panel.style.left = rect.left + "px";
                    panel.style.top = rect.top + "px";
                    panel.style.transform = "";
                    xOffset = 0;
                    yOffset = 0;
                }
            });

            document.addEventListener("mousemove", (e) => {
                if (isResizing) {
                    e.preventDefault();
                    const deltaX = e.clientX - resizeStartX;
                    const deltaY = e.clientY - resizeStartY;

                    const newWidth = resizeStartWidth + deltaX;
                    const newHeight = resizeStartHeight + deltaY;

                    const finalWidth = Math.max(280, Math.min(800, newWidth));
                    const finalHeight = Math.max(
                        150,
                        Math.min(window.innerHeight - 50, newHeight),
                    );

                    panel.style.width = finalWidth + "px";
                    panel.style.height = finalHeight + "px";
                }
            });

            document.addEventListener("mouseup", () => {
                if (isResizing) {
                    isResizing = false;
                }
            });

            // Fullscreen detection and UI centering
            const checkFullscreen = () => {
                const wasFullscreen = isFullscreen;
                isFullscreen = document.body.classList.contains("fullscreen");

                if (isFullscreen && !wasFullscreen) {
                    panel.style.left = "50%";
                    panel.style.top = "50%";
                    panel.style.right = "auto";
                    panel.style.transform = "translate(-50%, -50%)";
                    xOffset = 0;
                    yOffset = 0;
                } else if (!isFullscreen && wasFullscreen) {
                    panel.style.left = "auto";
                    panel.style.top = "10px";
                    panel.style.right = "10px";
                    panel.style.transform = "";
                    xOffset = 0;
                    yOffset = 0;
                }
            };

            setInterval(checkFullscreen, 500);

            // Event listeners
            document.getElementById("toggle-debug").onclick = () => {
                const settingsContainer =
                    document.getElementById("settings-container");
                const toggleBtn = document.getElementById("toggle-debug");
                const tabsContainer = document.getElementById("tabs-container");
                const collapsedInfo = document.getElementById("collapsed-client-info");
                const footers = panel.querySelectorAll('div[style*="border-top: 2px solid #808080;"]');
                const mainFooter = footers[footers.length - 1];

                if (settingsContainer.style.display === "none") {
                    settingsContainer.style.display = "block";
                    if (tabsContainer) tabsContainer.style.display = "flex";
                    if (collapsedInfo) collapsedInfo.style.display = "none";
                    if (mainFooter) mainFooter.style.display = "block";
                    toggleBtn.textContent = "Hide";
                    panel.style.width = "320px";
                } else {
                    settingsContainer.style.display = "none";
                    if (tabsContainer) tabsContainer.style.display = "none";
                    if (collapsedInfo) collapsedInfo.style.display = "block";
                    if (mainFooter) mainFooter.style.display = "none";
                    toggleBtn.textContent = "Show";
                    panel.style.width = "220px";
                }
            };

            const showTraj = document.getElementById("show-trajectory-toggle");
            const drawEnemies = document.getElementById("draw-enemies-toggle");
            const selfHitbox = document.getElementById("self-hitbox-toggle");
            const aimbotEnabled = document.getElementById(
                "aimbot-enabled-toggle",
            );

            if (showTraj)
                showTraj.addEventListener("change", (e) => {
                    CONFIG.SHOW_TRAJECTORY = e.target.checked;
                    saveSettings();
                });
            if (drawEnemies)
                drawEnemies.addEventListener("change", (e) => {
                    CONFIG.DRAW_ENEMIES = e.target.checked;
                    saveSettings();
                });
            if (selfHitbox)
                selfHitbox.addEventListener("change", (e) => {
                    CONFIG.DRAW_SELF_HITBOX = e.target.checked;
                    saveSettings();
                    if (e.target.checked && aimbotEnabled)
                        aimbotEnabled.checked = false;
                    updateToggleStyles();
                });
            if (aimbotEnabled)
                aimbotEnabled.addEventListener("change", (e) => {
                    CONFIG.AIMBOT_ENABLED = e.target.checked;
                    saveSettings();
                    if (e.target.checked && selfHitbox)
                        selfHitbox.checked = false;
                    updateToggleStyles();
                });

            // Hotkey to completely hide UI
            document.addEventListener("keydown", (e) => {
                if (e.code === CONFIG.HIDE_UI_KEY) {
                    uiCompletelyHidden = !uiCompletelyHidden;
                    panel.style.display = uiCompletelyHidden ? "none" : "block";
                }
            });

            // Advanced settings - keybind configuration
            const hideKeyInput = document.getElementById("hide-ui-key-input");
            hideKeyInput.addEventListener("click", () => {
                hideKeyInput.value = "Press any key...";
                hideKeyInput.style.background = "#ffffcc";

                const keyHandler = (e) => {
                    e.preventDefault();
                    CONFIG.HIDE_UI_KEY = e.code;
                    hideKeyInput.value = e.code;
                    hideKeyInput.style.background = "#ffffff";
                    saveSettings();
                    document.removeEventListener("keydown", keyHandler);
                };

                document.addEventListener("keydown", keyHandler);
            });

            document
                .getElementById("show-trajectory-toggle")
                .addEventListener("change", (e) => {
                    CONFIG.SHOW_TRAJECTORY = e.target.checked;
                    saveSettings();
                });

            document
                .getElementById("draw-enemies-toggle")
                .addEventListener("change", (e) => {
                    CONFIG.DRAW_ENEMIES = e.target.checked;
                    saveSettings();
                });

            // Radio button handlers for line modes
            document
                .getElementById("nearest-line-toggle")
                .addEventListener("change", (e) => {
                    if (e.target.checked) {
                        CONFIG.DRAW_NEAREST_LINE = true;
                        CONFIG.DRAW_ALL_PLAYER_LINES = false;
                        saveSettings();
                    }
                });

            document
                .getElementById("all-lines-toggle")
                .addEventListener("change", (e) => {
                    if (e.target.checked) {
                        CONFIG.DRAW_ALL_PLAYER_LINES = true;
                        CONFIG.DRAW_NEAREST_LINE = false;
                        saveSettings();
                    }
                });

            document
                .getElementById("no-lines-toggle")
                .addEventListener("change", (e) => {
                    if (e.target.checked) {
                        CONFIG.DRAW_NEAREST_LINE = false;
                        CONFIG.DRAW_ALL_PLAYER_LINES = false;
                        saveSettings();
                    }
                });

            document
                .getElementById("self-hitbox-toggle")
                .addEventListener("change", (e) => {
                    CONFIG.DRAW_SELF_HITBOX = e.target.checked;
                    saveSettings();
                    if (e.target.checked) {
                        document.getElementById(
                            "aimbot-enabled-toggle",
                        ).disabled = true;
                    } else {
                        document.getElementById(
                            "aimbot-enabled-toggle",
                        ).disabled = false;
                    }
                });

            document
                .getElementById("aimbot-enabled-toggle")
                .addEventListener("change", (e) => {
                    CONFIG.AIMBOT_ENABLED = e.target.checked;
                    saveSettings();
                    if (e.target.checked) {
                        document.getElementById("self-hitbox-toggle").disabled =
                            true;
                    } else {
                        document.getElementById("self-hitbox-toggle").disabled =
                            false;
                    }
                });

            document
                .getElementById("heavy-bot-toggle")
                .addEventListener("change", (e) => {
                    CONFIG.HEAVY_BOT = e.target.checked;
                    saveSettings();
                });

            // Heavy bot activation distance slider
            const heavyDistSlider = document.getElementById(
                "heavy-dist-settings-slider",
            );
            const heavyDistVal = document.getElementById(
                "heavy-dist-settings-val",
            );
            if (heavyDistSlider) {
                heavyDistSlider.addEventListener("input", (e) => {
                    const val = parseFloat(e.target.value);
                    CONFIG.HEAVY_BOT_DISTANCE = val;
                    if (heavyDistVal) heavyDistVal.textContent = val.toFixed(2);
                    saveSettings();
                });
            }

            // Opacity sliders
            document
                .getElementById("player-trajectory-opacity-slider")
                .addEventListener("input", (e) => {
                    CONFIG.LOCAL.ALPHA = parseFloat(e.target.value) / 100;
                    document.getElementById(
                        "player-trajectory-opacity-value",
                    ).textContent = e.target.value + "%";
                    saveSettings();
                });

            document
                .getElementById("enemy-trajectory-opacity-slider")
                .addEventListener("input", (e) => {
                    CONFIG.ENEMY.ALPHA = parseFloat(e.target.value) / 100;
                    document.getElementById(
                        "enemy-trajectory-opacity-value",
                    ).textContent = e.target.value + "%";
                    saveSettings();
                });

            document
                .getElementById("player-lines-opacity-slider")
                .addEventListener("input", (e) => {
                    const opacity = parseFloat(e.target.value) / 100;
                    CONFIG.NEAREST_LINE.ALPHA = opacity;
                    CONFIG.ALL_PLAYERS_LINE.ALPHA = opacity;
                    document.getElementById(
                        "player-lines-opacity-value",
                    ).textContent = e.target.value + "%";
                    saveSettings();
                });

            // Thickness sliders
            document
                .getElementById("trajectory-thickness-slider")
                .addEventListener("input", (e) => {
                    const thickness = parseInt(e.target.value);
                    CONFIG.LOCAL.THICKNESS = thickness;
                    CONFIG.ENEMY.THICKNESS = thickness;
                    document.getElementById(
                        "trajectory-thickness-value",
                    ).textContent = thickness;
                    saveSettings();
                });

            document
                .getElementById("player-lines-thickness-slider")
                .addEventListener("input", (e) => {
                    const thickness = parseInt(e.target.value);
                    CONFIG.NEAREST_LINE.THICKNESS = thickness;
                    CONFIG.ALL_PLAYERS_LINE.THICKNESS = Math.max(
                        1,
                        thickness - 2,
                    );
                    document.getElementById(
                        "player-lines-thickness-value",
                    ).textContent = thickness;
                    saveSettings();
                });

            document
                .getElementById("hitbox-thickness-slider")
                .addEventListener("input", (e) => {
                    const thickness = parseInt(e.target.value);
                    CONFIG.SELF_HITBOX.OUTLINE_THICKNESS = thickness;
                    document.getElementById(
                        "hitbox-thickness-value",
                    ).textContent = thickness;
                    saveSettings();
                });

            // Helper function to convert hex color string to integer
            function hexToInt(hex) {
                return parseInt(hex.replace("#", ""), 16);
            }

            // Helper function to convert integer to hex color string
            function intToHex(int) {
                return "#" + int.toString(16).padStart(6, "0");
            }

            // Self trajectory color
            document
                .getElementById("color-picker-self")
                .addEventListener("input", (e) => {
                    const color = hexToInt(e.target.value);
                    CONFIG.LOCAL.COLOR = color;
                    saveSettings();
                });

            // Enemy trajectory color
            document
                .getElementById("color-picker-enemy")
                .addEventListener("input", (e) => {
                    const color = hexToInt(e.target.value);
                    CONFIG.ENEMY.COLOR = color;
                    saveSettings();
                });

            // Nearest player line color
            document
                .getElementById("color-picker-nearest")
                .addEventListener("input", (e) => {
                    const color = hexToInt(e.target.value);
                    CONFIG.NEAREST_LINE.COLOR = color;
                    saveSettings();
                });

            // Initialize color pickers with saved values
            document.getElementById("color-picker-self").value = intToHex(
                CONFIG.LOCAL.COLOR,
            );
            document.getElementById("color-picker-enemy").value = intToHex(
                CONFIG.ENEMY.COLOR,
            );
            document.getElementById("color-picker-nearest").value = intToHex(
                CONFIG.NEAREST_LINE.COLOR,
            );

            // Initialize Heavy Bot slider and value
            const heavyDistSettingsSlider = document.getElementById(
                "heavy-dist-settings-slider",
            );
            const heavyDistSettingsVal = document.getElementById(
                "heavy-dist-settings-val",
            );
            if (heavyDistSettingsSlider && heavyDistSettingsVal) {
                heavyDistSettingsSlider.value = CONFIG.HEAVY_BOT_DISTANCE;
                heavyDistSettingsVal.textContent =
                    CONFIG.HEAVY_BOT_DISTANCE.toFixed(2);
            }

            // Initialize sliders with saved values
            document.getElementById("trajectory-thickness-value").textContent =
                CONFIG.LOCAL.THICKNESS;
            document.getElementById(
                "player-lines-thickness-value",
            ).textContent = CONFIG.NEAREST_LINE.THICKNESS;
            document.getElementById("hitbox-thickness-value").textContent =
                CONFIG.SELF_HITBOX.OUTLINE_THICKNESS;
        }

        // Update client name with RGB animation
        function updateClientName() {
            const clientNameSpan = document.getElementById("client-name");
            if (clientNameSpan && myUserName) {
                nameHueValue = (nameHueValue + NAME_HUE_SPEED) % 360;
                const rgbColor = hsvToRgb(nameHueValue, 1.0, 0.8);
                const hexColor = "#" + rgbColor.toString(16).padStart(6, "0");
                clientNameSpan.textContent = myUserName;
                clientNameSpan.style.color = hexColor;
                clientNameSpan.style.fontWeight = "bold";
            }

            // Update collapsed client name with RGB animation
            const collapsedNameSpan = document.getElementById("collapsed-name");
            if (collapsedNameSpan && myUserName) {
                const rgbColor = hsvToRgb(nameHueValue, 1.0, 0.8);
                const hexColor = "#" + rgbColor.toString(16).padStart(6, "0");
                collapsedNameSpan.textContent = myUserName;
                collapsedNameSpan.style.color = hexColor;
            }
        }

        // Initialize UI after a short delay
        setTimeout(createMainUI, 1000);
        setInterval(updateClientName, 100);

        //Websocket hook
        const originalSend = scope.WebSocket.prototype.send;
        scope.WebSocket.prototype.send = function (args) {
            if (typeof args === "string" && args.startsWith("42[12,")) {
                try {
                    const json = JSON.parse(args.substring(2));
                    myUserName = json[1].userName;
                } catch (e) {}
            }
            return originalSend.apply(this, arguments);
        };

        //PIXI hook
        const originalDrawCircle = scope.PIXI.Graphics.prototype.drawCircle;
        scope.PIXI.Graphics.prototype.drawCircle = function (...args) {
            const radius = args[2];
            const parent = this.parent;

            setTimeout(() => {
                if (parent && parent.visible) {
                    if (parent._bonkId === undefined)
                        parent._bonkId = pixiObjectId++;

                    let foundName = null;
                    if (parent.children) {
                        for (let i = 0; i < parent.children.length; i++) {
                            const c = parent.children[i];
                            if (c && c._text) {
                                foundName = c._text;
                                break;
                            }
                        }
                    }

                    if (foundName) {
                        if (!myUserName) {
                            try {
                                const topBar = window.parent.document
                                    .getElementById("maingameframe")
                                    .contentWindow.document.getElementById(
                                        "pretty_top_name",
                                    );
                                if (topBar) {
                                    myUserName = topBar.textContent.trim();
                                }
                            } catch (e) {
                                // Silently handle username errors
                            }
                        }

                        if (
                            myUserName &&
                            foundName.trim() === myUserName.trim()
                        ) {
                            myPlayerContainer = parent;
                            myPlayerID = parent._bonkId;

                            if (parent.parent) {
                                gameWorld = parent.parent;
                            }

                            if (radius > 5 && radius < 60) currentPPM = radius;
                        }
                    }
                }
            }, 0);

            return originalDrawCircle.apply(this, args);
        };

        function getGlobalTransform(obj) {
            if (!obj || !obj.transform) return { x: 0, y: 0, rot: 0 };
            obj.updateTransform();
            const wt = obj.transform.worldTransform;
            const globalPos = obj.getGlobalPosition();
            return {
                x: globalPos.x,
                y: globalPos.y,
                rot: Math.atan2(wt.b, wt.a),
            };
        }

        // Convert HSV to RGB for smooth color transitions
        function hsvToRgb(h, s, v) {
            h = h / 60;
            const c = v * s;
            const x = c * (1 - Math.abs((h % 2) - 1));
            const m = v - c;

            let r, g, b;
            if (h >= 0 && h < 1) {
                r = c;
                g = x;
                b = 0;
            } else if (h >= 1 && h < 2) {
                r = x;
                g = c;
                b = 0;
            } else if (h >= 2 && h < 3) {
                r = 0;
                g = c;
                b = x;
            } else if (h >= 3 && h < 4) {
                r = 0;
                g = x;
                b = c;
            } else if (h >= 4 && h < 5) {
                r = x;
                g = 0;
                b = c;
            } else {
                r = c;
                g = 0;
                b = x;
            }

            r = Math.round((r + m) * 255);
            g = Math.round((g + m) * 255);
            b = Math.round((b + m) * 255);

            return (r << 16) | (g << 8) | b;
        }

        document.addEventListener("keydown", (e) => {
            if (e.code === CONFIG.KEY) isHoldingKey = true;
        });
        document.addEventListener("keyup", (e) => {
            if (e.code === CONFIG.KEY) isHoldingKey = false;
        });

        const originalRAF = scope.requestAnimationFrame;

        scope.requestAnimationFrame = function (callback) {
            if (!arcGraphics && scope.PIXI) {
                arcGraphics = new scope.PIXI.Graphics();
            }

            let myPosition = null;
            let nearestPlayer = null;
            let nearestDistance = Infinity;
            let allPlayers = [];

            if (gameWorld && gameWorld.transform && arcGraphics) {
                if (arcGraphics.parent !== gameWorld) {
                    gameWorld.addChild(arcGraphics);
                }

                arcGraphics.clear();

                const children = gameWorld.children;

                // First pass: find my position and identify all players
                for (let i = 0; i < children.length; i++) {
                    const playerObj = children[i];

                    if (!playerObj || !playerObj.visible || !playerObj.children)
                        continue;

                    let isMe = false;
                    let isPlayer = false;
                    let playerName = null;

                    for (let j = 0; j < playerObj.children.length; j++) {
                        const child = playerObj.children[j];
                        if (child && child._text) {
                            isPlayer = true;
                            playerName = child._text.trim();
                            if (
                                myUserName &&
                                playerName === myUserName.trim()
                            ) {
                                isMe = true;
                            }
                            break;
                        }
                    }

                    if (!isPlayer) continue;

                    if (isMe) {
                        const myTransform = getGlobalTransform(playerObj);
                        myPosition = {
                            x: myTransform.x,
                            y: myTransform.y,
                            obj: playerObj,
                        };
                    }
                }

                // Second pass: draw trajectories and find nearest player
                for (let i = 0; i < children.length; i++) {
                    const playerObj = children[i];

                    if (!playerObj || !playerObj.visible || !playerObj.children)
                        continue;

                    let isMe = false;
                    let isPlayer = false;
                    let playerName = null;

                    for (let j = 0; j < playerObj.children.length; j++) {
                        const child = playerObj.children[j];
                        if (child && child._text) {
                            isPlayer = true;
                            playerName = child._text.trim();
                            if (
                                myUserName &&
                                playerName === myUserName.trim()
                            ) {
                                isMe = true;
                            }
                            break;
                        }
                    }

                    if (!isPlayer) continue;

                    // Add to player list (skip self)
                    if (!isMe) {
                        const distPx = myPosition
                            ? Math.sqrt(
                                  (playerObj.x - myPosition.x) ** 2 +
                                      (playerObj.y - myPosition.y) ** 2,
                              )
                            : 0;
                    }

                    // Calculate distance to this player if not me
                    if (!isMe && myPosition) {
                        const playerTransform = getGlobalTransform(playerObj);
                        const dx = playerTransform.x - myPosition.x;
                        const dy = playerTransform.y - myPosition.y;
                        const distance = Math.sqrt(dx * dx + dy * dy);

                        const playerData = {
                            obj: playerObj,
                            name: playerName,
                            x: playerTransform.x,
                            y: playerTransform.y,
                            distance: distance,
                        };

                        allPlayers.push(playerData);

                        if (distance < nearestDistance) {
                            nearestDistance = distance;
                            nearestPlayer = playerData;
                        }
                    }

                    if (!isMe && !CONFIG.DRAW_ENEMIES) continue;

                    let aimerChild = null;
                    for (let j = 0; j < playerObj.children.length; j++) {
                        const c = playerObj.children[j];
                        if (
                            c.constructor.name === "e" ||
                            c.constructor.name === "h"
                        ) {
                            aimerChild = c;
                            break;
                        }
                    }

                    const arrowVisible =
                        aimerChild &&
                        aimerChild.visible &&
                        aimerChild.alpha > 0.1;

                    let shouldDraw = false;

                    if (isMe) {
                        // Only draw my trajectory if SHOW_TRAJECTORY is enabled AND arrow is visible
                        shouldDraw = CONFIG.SHOW_TRAJECTORY && arrowVisible;
                    } else {
                        shouldDraw = arrowVisible;
                    }

                    if (shouldDraw) {
                        const settings = isMe ? CONFIG.LOCAL : CONFIG.ENEMY;
                        arcGraphics.lineStyle(
                            settings.THICKNESS,
                            settings.COLOR,
                            settings.ALPHA,
                        );

                        if (!playerObj._bonkChargeStart) {
                            playerObj._bonkChargeStart = Date.now();
                        }

                        const scale = currentPPM / BASE_RADIUS_PPM;
                        const G_term = PHYSICS.GRAVITY * scale;
                        const h = Math.min(
                            (Date.now() - playerObj._bonkChargeStart) / 1000.0,
                            CONFIG.MAX_CHARGE,
                        );
                        const V_total =
                            (PHYSICS.VEL_MULT * h + PHYSICS.VEL_BASE) * scale;

                        const tf = getGlobalTransform(aimerChild);
                        const n = -tf.rot;
                        const cos_n = Math.cos(n);
                        const sin_n = Math.sin(n);

                        const startLocal = gameWorld.toLocal({
                            x: tf.x,
                            y: tf.y,
                        });
                        arcGraphics.moveTo(startLocal.x, startLocal.y);

                        const dt = CONFIG.SIM_TIME / CONFIG.POINTS;

                        for (let k = 1; k <= CONFIG.POINTS; k++) {
                            const t = k * dt;
                            const dx = V_total * cos_n * t;
                            const dy =
                                V_total * sin_n * t - G_term * Math.pow(t, 2);

                            const pLoc = gameWorld.toLocal({
                                x: tf.x + dx,
                                y: tf.y - dy,
                            });

                            arcGraphics.lineTo(pLoc.x, pLoc.y);
                        }
                    } else {
                        playerObj._bonkChargeStart = 0;
                    }
                }

                // Draw line to nearest player
                if (CONFIG.DRAW_NEAREST_LINE && myPosition && nearestPlayer) {
                    arcGraphics.lineStyle(
                        CONFIG.NEAREST_LINE.THICKNESS,
                        CONFIG.NEAREST_LINE.COLOR,
                        CONFIG.NEAREST_LINE.ALPHA,
                    );

                    const startLocal = gameWorld.toLocal({
                        x: myPosition.x,
                        y: myPosition.y,
                    });
                    const endLocal = gameWorld.toLocal({
                        x: nearestPlayer.x,
                        y: nearestPlayer.y,
                    });

                    arcGraphics.moveTo(startLocal.x, startLocal.y);
                    arcGraphics.lineTo(endLocal.x, endLocal.y);
                }

                // Draw lines to all players (red for normal, green for nearest)
                if (
                    CONFIG.DRAW_ALL_PLAYER_LINES &&
                    myPosition &&
                    allPlayers.length > 0
                ) {
                    const startLocal = gameWorld.toLocal({
                        x: myPosition.x,
                        y: myPosition.y,
                    });

                    allPlayers.forEach((player) => {
                        const isNearest =
                            nearestPlayer && player.obj === nearestPlayer.obj;
                        const lineColor = isNearest
                            ? CONFIG.ALL_PLAYERS_LINE.NEAREST_COLOR
                            : CONFIG.ALL_PLAYERS_LINE.COLOR;
                        const lineThickness = isNearest
                            ? CONFIG.ALL_PLAYERS_LINE.THICKNESS + 1
                            : CONFIG.ALL_PLAYERS_LINE.THICKNESS;

                        arcGraphics.lineStyle(
                            lineThickness,
                            lineColor,
                            CONFIG.ALL_PLAYERS_LINE.ALPHA,
                        );

                        const endLocal = gameWorld.toLocal({
                            x: player.x,
                            y: player.y,
                        });
                        arcGraphics.moveTo(startLocal.x, startLocal.y);
                        arcGraphics.lineTo(endLocal.x, endLocal.y);
                    });
                }
            }

            // Draw self hitbox ESP
            if (
                CONFIG.DRAW_SELF_HITBOX &&
                gameWorld &&
                gameWorld.transform &&
                arcGraphics &&
                myPlayerContainer
            ) {
                const myTransform = getGlobalTransform(myPlayerContainer);
                const myLocal = gameWorld.toLocal({
                    x: myTransform.x,
                    y: myTransform.y,
                });
                const radius = currentPPM;

                // Update hue for smooth RGB transition
                hueValue = (hueValue + HUE_SPEED) % 360;
                const rgbColor = hsvToRgb(hueValue, 1.0, 1.0);

                // Draw filled circle with RGB transition
                arcGraphics.beginFill(rgbColor, CONFIG.SELF_HITBOX.FILL_ALPHA);
                arcGraphics.lineStyle(
                    CONFIG.SELF_HITBOX.OUTLINE_THICKNESS,
                    rgbColor,
                    CONFIG.SELF_HITBOX.OUTLINE_ALPHA,
                );
                arcGraphics.drawCircle(myLocal.x, myLocal.y, radius);
                arcGraphics.endFill();
            }

            // ...
            if (CONFIG.AIMBOT_ENABLED && myPosition && nearestPlayer) {
                // Find the arrow child for my player
                let myArrowChild = null;
                for (let j = 0; j < myPosition.obj.children.length; j++) {
                    const c = myPosition.obj.children[j];
                    if (
                        c.constructor.name === "e" ||
                        c.constructor.name === "h"
                    ) {
                        myArrowChild = c;
                        break;
                    }
                }

                if (myArrowChild && myArrowChild.visible) {
                    now = Date.now();

                    if (aimbotStarted === 0) {
                        aimbotStarted = now;
                    }

                    const scalePPM = (currentIS?.physics?.ppm ?? 7) / 7;
                    const scalePPMInv = 1 / scalePPM;
                    const scale2 = 1000 / scale;
                    const Dstarted =
                        Math.min((now - aimbotStarted) / 1000, 10 / 3) /
                        (10 / 3);
                    const v =
                        (multiplier * (Dstarted * 100 + 15)) / scalePPMInv;
                    const g = gravity / scalePPMInv;

                    const mypos = myPosition.obj.transform.position;
                    const targetpos = nearestPlayer.obj.transform.position;
                    let deltapos = [
                        targetpos.x - mypos.x,
                        targetpos.y - mypos.y,
                    ];

                    const distance = Math.sqrt(
                        deltapos[0] ** 2 + deltapos[1] ** 2,
                    );
                    const dis = (distance / v) * prediction;

                    // Add prediction for target movement with acceleration compensation
                    const targetChild = nearestPlayer.obj.children[0];
                    if (targetChild) {
                        deltapos[0] +=
                            (targetChild.xvel || 0) * scale2 * dis +
                            ((targetChild.xacc || 0) * scale2 * dis ** 2) / 2;
                        deltapos[1] +=
                            (targetChild.yvel || 0) * scale2 * dis +
                            ((targetChild.yacc || 0) * scale2 * dis ** 2) / 2;
                    }
                    deltapos[1] = -deltapos[1]; // Invert Y for ballistic calculation

                    let angle = positive(-Math.atan2(deltapos[1], deltapos[0]));
                    const rot = myArrowChild.transform.rotation;
                    const rotPositive = positive(rot);
                    angle = positive(angle);

                    const alpha = deltapos[0];
                    const beta = deltapos[1];
                    const v_squared = v ** 2;
                    const eff = (2 * v_squared) / g;
                    const rootterm = eff * (eff - 2 * beta) - 2 * alpha ** 2;

                    if (rootterm >= 0) {
                        const gamma_first = eff + Math.sqrt(rootterm);
                        const gamma_second = eff - Math.sqrt(rootterm);
                        const theta_first = positive(
                            -Math.atan2(gamma_first, alpha),
                        );
                        const theta_second = positive(
                            -Math.atan2(gamma_second, alpha),
                        );

                        if (
                            angle_between(angle, theta_first) <
                            angle_between(angle, theta_second)
                        ) {
                            angle = theta_first;
                        } else {
                            angle = theta_second;
                        }
                    }

                    // Auto-aim is always on when aimbot is enabled
                    const min = angle_between(angle, rotPositive);
                    const gamerenderer =
                        document.getElementById("gamerenderer");

                    if (angle_between2(angle, rotPositive) < 0) {
                        fire(
                            "keydown",
                            { keyCode: leftRight[0] },
                            gamerenderer,
                        );
                        fire("keyup", { keyCode: leftRight[1] }, gamerenderer);
                    } else {
                        fire("keyup", { keyCode: leftRight[0] }, gamerenderer);
                        fire(
                            "keydown",
                            { keyCode: leftRight[1] },
                            gamerenderer,
                        );
                    }

                    if (min < 0.05) {
                        fire("keyup", { keyCode: leftRight[0] }, gamerenderer);
                        fire("keyup", { keyCode: leftRight[1] }, gamerenderer);
                    }
                } else if (aimbotStarted > 0) {
                    aimbotStarted = 0;
                    const gamerenderer =
                        document.getElementById("gamerenderer");
                    fire("keyup", { keyCode: leftRight[0] }, gamerenderer);
                    fire("keyup", { keyCode: leftRight[1] }, gamerenderer);
                }
            } else if (aimbotStarted > 0) {
                aimbotStarted = 0;
                const gamerenderer = document.getElementById("gamerenderer");
                fire("keyup", { keyCode: leftRight[0] }, gamerenderer);
                fire("keyup", { keyCode: leftRight[1] }, gamerenderer);
            }

            // Heavy Bot logic
            if (CONFIG.HEAVY_BOT && myPosition && nearestPlayer) {
                const targetpos = nearestPlayer.obj.transform.position;
                const mypos = myPosition.obj.transform.position;
                const deltapos = [targetpos.x - mypos.x, targetpos.y - mypos.y];
                const distancePx = Math.sqrt(
                    deltapos[0] ** 2 + deltapos[1] ** 2,
                );

                // Convert pixels to meters using current PPM
                const ppm = currentIS?.physics?.ppm ?? 7;
                const distanceMeters = distancePx / (ppm * 5);
                const radiusMeters = currentPPM / (ppm * 5);

                const triggerDistance =
                    radiusMeters + CONFIG.HEAVY_BOT_DISTANCE;

                const gamerenderer = document.getElementById("gamerenderer");
                if (distanceMeters <= triggerDistance) {
                    fire("keydown", { keyCode: 32, which: 32 }, gamerenderer); // Space keydown
                    scope._heavyBotIsPressing = true;
                } else if (scope._heavyBotIsPressing) {
                    fire("keyup", { keyCode: 32, which: 32 }, gamerenderer); // Space keyup
                    scope._heavyBotIsPressing = false;
                }
            } else if (scope._heavyBotIsPressing) {
                const gamerenderer = document.getElementById("gamerenderer");
                fire("keyup", { keyCode: 32, which: 32 }, gamerenderer);
                scope._heavyBotIsPressing = false;
            }

            return originalRAF.call(scope, callback);
        };
    });
})();