Deadshot.io Extra

deadshot.io menu with Aimbot, ESP

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         Deadshot.io Extra
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  deadshot.io menu with Aimbot, ESP
// @author       Extra
// @match        *://*deadshot.io/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=deadshot.io
// @grant        unsafeWindow
// @run-at       document-start
// @license      MIT
// ==/UserScript==

(() => {
    'use strict';


    const config = {
        aimMode: 'AIPD',
        fov: 250,
        sensitivity: 0.1,
        headOffset: 0.6,
        prediction: 0,
        aimbotEnabled: true,
        stickyTarget: true,
        chamsEnabled: true,
        espBoxes: true,
        espStyle: 'Normal',
        espLines: true,
        espSkeleton: true,
        showFov: true,
        espColor: '#ff69b4',
        smoothingEnabled: true,
        smoothing: 5,
        triggerbot: false,
        triggerbotDelay: 50,
        menuVisible: true,
        currentTab: 'AiM'
    };


    const advancedFeatures = {
        visibilityPriority: false,
        aimKill: false,
        rapidFire: false,
        autoBhop: false,
        noRecoil: false,
        flyHack: false,
        speedHack: 1,
        godMode: false,
        skinUnlocker: false
    };


    const MENU_STYLE = `
        :root { --accent: #ff69b4; --bg: rgba(0,0,0,1); --bg-hover: rgba(40,40,40,1); --text: #e2e8f0; --border: rgba(255,105,180, 0.4); }
        #premium-menu {
            position: fixed; top: 100px; left: 100px; width: 320px;
            background: var(--bg); border: 1px solid var(--border); border-radius: 8px;
            color: var(--text); font-family: 'Consolas', 'Monaco', monospace;
            z-index: 2147483647; box-shadow: 0 12px 60px rgba(0, 0, 0, 0.9);
            user-select: none; display: flex; flex-direction: column; overflow: hidden;
        }
        .menu-header {
            background: rgba(15,15,15,1); border-bottom: 1px solid var(--border);
            display: flex; align-items: stretch; cursor: grab; text-transform: lowercase;
        }
        .menu-header:active { cursor: grabbing; }
        .tab {
            flex: 1; padding: 10px 0; text-align: center; font-size: 13px; font-weight: bold;
            color: #888; border-bottom: 2px solid transparent; transition: all 0.2s; cursor: pointer;
        }
        .tab:hover { background: var(--bg-hover); color: var(--accent); }
        .tab.active { color: var(--accent); border-bottom: 2px solid var(--accent); background: rgba(30,30,30,1); }
        .tab.premium-title { font-size: 11px; text-transform: uppercase; font-weight: 800; padding: 10px 8px; cursor: default; pointer-events: none; opacity: 0.5; border: none !important; color: #fff; }

        .menu-content { padding: 15px; max-height: 70vh; overflow-y: auto; flex: 1; }
        .menu-content::-webkit-scrollbar { width: 6px; }
        .menu-content::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 3px; }
        .content-pane { display: none; }
        .content-pane.active { display: block; }

        .control-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; font-size: 13px; }
        select {
            background: rgba(0,0,0,1); color: #fff; border: 1px solid rgba(255,255,255,0.15);
            border-radius: 4px; padding: 1px 4px; font-size: 12px; outline: none; cursor: pointer; font-family: inherit;
        }
        .switch { position: relative; display: inline-block; width: 30px; height: 16px; }
        .switch input { opacity: 0; width: 0; height: 0; }
        .slider-t { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #333; transition: .2s; border-radius: 16px; }
        .slider-t:before { position: absolute; content: ""; height: 10px; width: 10px; left: 3px; bottom: 3px; background-color: white; transition: .2s; border-radius: 50%; }
        input:checked + .slider-t { background-color: var(--accent); }
        input:checked + .slider-t:before { transform: translateX(14px); }
        .a-row { margin-bottom: 12px; }
        .a-label { display: flex; justify-content: space-between; font-size: 11px; color: #aaa; margin-bottom: 4px; }
        .a-val { color: var(--accent); font-weight: bold; }
        .a-slider { width: 100%; height: 4px; background: #333; border-radius: 2px; appearance: none; outline: none; }
        .a-slider::-webkit-slider-thumb { appearance: none; width: 12px; height: 12px; background: var(--accent); border-radius: 50%; cursor: pointer; }
        .color-picker { background: none; border: 1px solid #555; cursor: pointer; width: 24px; height: 24px; padding: 0; border-radius: 4px; }
        input[type="number"] { width: 40px; background: transparent; border: 1px solid rgba(255,255,255,0.2); color: #fff; text-align: right; padding: 1px 4px; }
        input[type="checkbox"].placeholder { appearance: none; border: 1px solid #ff0000; width: 13px; height: 13px; position: relative; top: 2px; }
        input[type="checkbox"].placeholder:checked:after { content: '×'; color: #ff0000; font-size: 14px; position: absolute; top: -5px; left: -1px; font-weight: 800; }
        span.placeholder { color: #ff0000; font-style: italic; }

        .status-bar {
            padding: 8px 15px; background: rgba(10,10,10,1); font-size: 10px; color: #888;
            display: flex; justify-content: space-between; border-top: 1px solid var(--border);
        }
        #overlay-canvas { position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 2147483646; }
        #mobile-toggle { position: fixed; bottom: 20px; right: 20px; width: 50px; height: 50px; background: rgba(255,105,180,0.4); border: 2px solid var(--accent); border-radius: 50%; display: none; z-index: 2147483647; cursor: pointer; font-size: 24px; color: #fff; text-align: center; line-height: 48px; }
    `;


    const createUI = () => {
        const style = document.createElement('style'); style.innerHTML = MENU_STYLE; document.head.appendChild(style);
        const menu = document.createElement('div'); menu.id = 'premium-menu';
        menu.innerHTML = `
            <div class="menu-header" id="drag-handle">
                <div class="tab Extra-title">Extra</div>
                <div class="tab ${config.currentTab === 'AiM' ? 'active' : ''}" data-tab="AiM">AiM</div>
                <div class="tab ${config.currentTab === 'eSP' ? 'active' : ''}" data-tab="eSP">eSP</div>
                <div class="tab ${config.currentTab === 'Misc' ? 'active' : ''}" data-tab="Misc">Misc</div>
                <div class="tab ${config.currentTab === 'Config' ? 'active' : ''}" data-tab="Config">Config</div>
            </div>
            <div class="menu-content">
                <div class="content-pane ${config.currentTab === 'AiM' ? 'active' : ''}" id="pane-AiM">
                    <div class="control-row"><span>Aimbot</span><label class="switch"><input type="checkbox" id="c-aim" ${config.aimbotEnabled ? 'checked' : ''}><span class="slider-t"></span></label></div>
                    <div class="control-row"><span>Mode</span><select id="s-mode"><option value="AIPD">AIPD (Adaptive)</option><option value="Rage">Rage</option><option value="Legit">Legit</option><option value="Legacy">Legacy</option></select></div>
                    <div class="control-row"><span>Sticky Targeting</span><label class="switch"><input type="checkbox" id="c-sticky" ${config.stickyTarget ? 'checked' : ''}><span class="slider-t"></span></label></div>
                    <div class="control-row"><span>Smoothing</span><label class="switch"><input type="checkbox" id="c-smooth-t" ${config.smoothingEnabled ? 'checked' : ''}><span class="slider-t"></span></label></div>
                    <div class="a-row"><label class="a-label">Smooth Value <span id="v-smooth" class="a-val">${config.smoothing}</span></label><input type="range" id="i-smooth" class="a-slider" min="1" max="20" value="${config.smoothing}"></div>
                    <div class="a-row"><label class="a-label">Aim FOV <span id="v-fov" class="a-val">${config.fov}</span></label><input type="range" id="i-fov" class="a-slider" min="30" max="600" value="${config.fov}"></div>
                    <div class="a-row"><label class="a-label">Prediction <span id="v-pred" class="a-val">${config.prediction}</span></label><input type="range" id="i-pred" class="a-slider" min="0" max="2" step="0.1" value="${config.prediction}"></div>
                    <hr style="border:0; border-top:1px solid #333; margin:10px 0">
                    <div class="control-row"><span>Visibility Priority <span class="placeholder">(conceptual raycast)</span></span><input type="checkbox" class="placeholder"></div>
                </div>

                <div class="content-pane ${config.currentTab === 'eSP' ? 'active' : ''}" id="pane-eSP">
                    <div class="control-row"><span>Chams</span><label class="switch"><input type="checkbox" id="c-cham" ${config.chamsEnabled ? 'checked' : ''}><span class="slider-t"></span></label></div>
                    <div class="control-row"><span>ESP Boxes</span><label class="switch"><input type="checkbox" id="c-espb" ${config.espBoxes ? 'checked' : ''}><span class="slider-t"></span></label></div>
                    <div class="control-row"><span>Box Style</span><select id="s-esp-style"><option value="Normal">Normal</option><option value="Corner">Corner</option></select></div>
                    <div class="control-row"><span>ESP Skeleton</span><label class="switch"><input type="checkbox" id="c-esps" ${config.espSkeleton ? 'checked' : ''}><span class="slider-t"></span></label></div>
                    <div class="control-row"><span>Snaplines</span><label class="switch"><input type="checkbox" id="c-espl" ${config.espLines ? 'checked' : ''}><span class="slider-t"></span></label></div>
                    <div class="control-row"><span>Show FOV</span><label class="switch"><input type="checkbox" id="c-sfov" ${config.showFov ? 'checked' : ''}><span class="slider-t"></span></label></div>
                    <div class="t-row control-row" style="justify-content: flex-start; gap: 8px;">ESP Color<input type="color" id="c-color" class="color-picker" value="${config.espColor}"></div>
                    <hr style="border:0; border-top:1px solid #333; margin:10px 0">
                    <div class="control-row"><span>Chams Mode <span class="placeholder">(dropdown conceptual)</span></span><select class="placeholder"><option>Additive</option><option>Wireframe</option><option>Tint</option></select></div>
                    <div class="control-row"><span>Player Info <span class="placeholder">(labels conceptual)</span></span><input type="checkbox" class="placeholder"></div>
                </div>

                <div class="content-pane ${config.currentTab === 'Misc' ? 'active' : ''}" id="pane-Misc">
                    <div class="control-row"><span>Triggerbot</span><label class="switch"><input type="checkbox" id="c-trigger" ${config.triggerbot ? 'checked' : ''}><span class="slider-t"></span></label></div>
                    <div class="control-row" style="justify-content: flex-start; gap: 8px;">Triggerbot Delay (ms): <input type="number" id="i-trigger-delay" value="${config.triggerbotDelay}" min="0"></div>
                    <hr style="border:0; border-top:1px solid #333; margin:10px 0">
                    <div class="control-row"><span>uhh broken stuff rn<span class="placeholder"></span></div>
                    <div class="control-row"><span>Aimkill (Rage) <span class="placeholder">(rage logic)</span></span><input type="checkbox" class="placeholder"></div>
                    <div class="control-row"><span>Rapid Fire <span class="placeholder">(conceptual semi-auto)</span></span><input type="checkbox" class="placeholder"></div>
                    <div class="control-row"><span>Auto-Bhop <span class="placeholder">(perfect bhop)</span></span><input type="checkbox" class="placeholder"></div>
                    <div class="control-row"><span>No Recoil <span class="placeholder">(conceptual steady-cam)</span></span><input type="checkbox" class="placeholder"></div>
                    <div class="control-row"><span>Fly <span class="placeholder">(conceptual jump injection)</span></span><input type="checkbox" class="placeholder"></div>
                    <div class="control-row"><span>Speed Hack <span class="placeholder">(conceptual velocity multiplier)</span></span><input type="checkbox" class="placeholder"></div>
                    <div class="control-row"><span>God Mode <span class="placeholder">(visual health lock)</span></span><input type="checkbox" class="placeholder"></div>
                    <div class="control-row"><span>Skin Unlocker <span class="placeholder">(conceptual local unlock)</span></span><input type="checkbox" class="placeholder"></div>
                </div>

                <div class="content-pane ${config.currentTab === 'Config' ? 'active' : ''}" id="pane-Config">
                    <div class="control-row" style="color: #666; font-size: 11px;">Save/Load coming soon!</div>
                    <hr style="border:0; border-top:1px solid #333; margin:10px 0">
                    <div class="a-label">Keybinds:</div>
                    <div style="font-size: 11px; color: #888; margin-bottom: 4px;">Right Shift: Show/Hide Menu</div>
                    <div style="font-size: 11px; color: #888; margin-bottom: 4px;">F1: Toggle Aimbot Engine</div>
                    <div style="font-size: 11px; color: #888; margin-bottom: 4px;">F2: Toggle ESP & Wallhack</div>
                    <div style="font-size: 11px; color: #888;">Right Click (hold): Activate Aim</div>
                </div>
            </div>
            <div class="status-bar">
                <span id="stat-gl">WebGL Hooked</span>
                <span id="stat-sec" style="color: #666;">Security Conceptualized</span>
                <span id="stat-lock" style="color: #666;">Lock: None</span>
            </div>
        `;
        document.body.appendChild(menu);


        const mobToggle = document.createElement('div'); mobToggle.id = 'mobile-toggle'; mobToggle.innerHTML = '🎯'; document.body.appendChild(mobToggle);

        if ( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) { mobToggle.style.display = 'block'; }
        mobToggle.addEventListener('touchstart', (e) => { e.preventDefault(); config.menuVisible = !config.menuVisible; menu.style.display = config.menuVisible ? 'flex' : 'none'; });

        mobToggle.addEventListener('touchmove', (e) => { e.preventDefault(); const t = e.touches[0]; mobToggle.style.left = (t.clientX - 25) + 'px'; mobToggle.style.top = (t.clientY - 25) + 'px'; });


        const tabs = menu.querySelectorAll('.tab[data-tab]');
        const panes = menu.querySelectorAll('.content-pane');
        tabs.forEach(tab => tab.addEventListener('click', (e) => {
            const targetTab = e.currentTarget.getAttribute('data-tab');
            if (config.currentTab === targetTab) return;
            tabs.forEach(t => t.classList.remove('active')); panes.forEach(p => p.classList.remove('active'));
            tab.classList.add('active'); menu.querySelector(`#pane-${targetTab}`).classList.add('active');
            config.currentTab = targetTab;
        }));


        const handle = menu.querySelector('#drag-handle');
        let isDragging = false, startX, startY;
        handle.addEventListener('mousedown', (e) => { if (e.target.classList.contains('tab') && e.target.getAttribute('data-tab')) return; isDragging = true; startX = e.clientX - menu.offsetLeft; startY = e.clientY - menu.offsetTop; });
        handle.addEventListener('touchstart', (e) => { if (e.target.classList.contains('tab') && e.target.getAttribute('data-tab')) return; isDragging = true; const t = e.touches[0]; startX = t.clientX - menu.offsetLeft; startY = t.clientY - menu.offsetTop; });
        document.addEventListener('mousemove', (e) => { if (isDragging) { menu.style.left = `${e.clientX - startX}px`; menu.style.top = `${e.clientY - startY}px`; } });
        document.addEventListener('touchmove', (e) => { if (isDragging) { const t = e.touches[0]; menu.style.left = `${t.clientX - startX}px`; menu.style.top = `${t.clientY - startY}px`; } });
        document.addEventListener('mouseup', () => isDragging = false); document.addEventListener('touchend', () => isDragging = false);


        const canvas = document.createElement('canvas'); canvas.id = 'overlay-canvas'; document.body.appendChild(canvas);
        const ctx = canvas.getContext('2d');
        const resize = () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; };
        window.addEventListener('resize', resize); resize();


        const link = (id, key, valId, step = 1, isFloat = false) => {
            const el = document.getElementById(id), vEl = document.getElementById(valId);
            if (!el) return;
            el.oninput = () => {
                const val = isFloat ? parseFloat(el.value) : parseInt(el.value);
                config[key] = isFloat ? Math.round(val * 10) / 10 : val;
                vEl.innerText = config[key];
            };
        };
        link('i-fov', 'fov', 'v-fov'); link('i-pred', 'prediction', 'v-pred', 1, true); link('i-smooth', 'smoothing', 'v-smooth');
        const triggerDelay = document.getElementById('i-trigger-delay'); if (triggerDelay) triggerDelay.addEventListener('input', (e) => { config.triggerbotDelay = Math.max(0, parseInt(e.target.value)); });

        document.getElementById('c-aim').onchange = (e) => config.aimbotEnabled = e.target.checked;
        document.getElementById('s-mode').onchange = (e) => config.aimMode = e.target.value;
        document.getElementById('c-sticky').onchange = (e) => config.stickyTarget = e.target.checked;
        document.getElementById('c-smooth-t').onchange = (e) => config.smoothingEnabled = e.target.checked;
        document.getElementById('c-cham').onchange = (e) => config.chamsEnabled = e.target.checked;
        document.getElementById('c-espb').onchange = (e) => config.espBoxes = e.target.checked;
        document.getElementById('s-esp-style').onchange = (e) => config.espStyle = e.target.value;
        document.getElementById('c-esps').onchange = (e) => config.espSkeleton = e.target.checked;
        document.getElementById('c-espl').onchange = (e) => config.espLines = e.target.checked;
        document.getElementById('c-sfov').onchange = (e) => config.showFov = e.target.checked;
        document.getElementById('c-trigger').onchange = (e) => config.triggerbot = e.target.checked;
        document.getElementById('c-color').oninput = (e) => config.espColor = e.target.value;

        return { ctx, menu };
    };


    const detectedPlayers = [];
    let currentTarget = null, isAiming = false, lastLockedTarget = null;
    const PLAYER_HISTORY = new Map();
    let viewProjMatrix = null;
    const PLAYER_VERTEX_SET = new Set([8829, 10392, 10944, 16413]);
    const uniformCache = new Map();
    let activeTextureUnit = 0;
    const textureUnitBindings = new Array(32).fill(null);
    const textureDataMap = new WeakMap();
    let currentProgram = null;
    let isDepthEnabled = false;

    const multiplyMatrixVec4 = (m, [x, y, z, w]) => [
        m[0] * x + m[4] * y + m[8] * z + m[12] * w, m[1] * x + m[5] * y + m[9] * z + m[13] * w,
        m[2] * x + m[6] * y + m[10] * z + m[14] * w, m[3] * x + m[7] * y + m[11] * z + m[15] * w,
    ];

    const worldToScreen = (pos) => {
        if (!viewProjMatrix) return null;
        const clip = multiplyMatrixVec4(viewProjMatrix, [...pos, 1]);
        if (clip[3] <= 0.001) return null;
        return [(clip[0] / clip[3] + 1) * 0.5 * window.innerWidth, (1 - clip[1] / clip[3]) * 0.5 * window.innerHeight];
    };

    class PlayerDetector {
        static getCachedMatrices = (program) => {
            const cache = uniformCache.get(program);
            if (!cache) return { vp: null, model: null, boneUnit: null, opacity: 1.0, isEnemy: true };
            let vp = null, model = null, boneUnit = null, opacity = 1.0, isEnemy = false;
            for (const [name, val] of cache) {
                if (val?.length === 16) {
                    if (val[11] !== 0 && Math.abs(val[15]) > 1.0) vp = val;
                    else if (/modelMatrix/i.test(name)) model = val;
                } else if (name === 'boneTexture') boneUnit = val;
                else if (name === 'opacity') opacity = val;
                else if (typeof val === 'number' && val === 1 && !['left', 'specMultMult', 'opacity'].includes(name) && name.length > 5) isEnemy = true;
            }
            return { vp, model, boneUnit, opacity, isEnemy };
        };

        static processDrawCall = (gl, program, vertexCount) => {
            const { vp, model, boneUnit, opacity, isEnemy } = this.getCachedMatrices(program);
            if (vp) viewProjMatrix = vp;
            if (!model || !PLAYER_VERTEX_SET.has(vertexCount) || opacity < 0.1 || !isEnemy) return;

            let pos = [model[12], model[13] + config.headOffset, model[14]];
            let basePos = [model[12], model[13] - 0.8, model[14]];

            if (boneUnit !== null && textureUnitBindings[boneUnit]) {
                const boneData = textureDataMap.get(textureUnitBindings[boneUnit]);
                if (boneData?.length >= 23 * 16) {
                    const b22 = 22 * 16;
                    pos = [boneData[b22 + 12], boneData[b22 + 13] + config.headOffset, boneData[b22 + 14]];
                    basePos = [boneData[b22 + 12], boneData[b22 + 13] - 1.0, boneData[b22 + 14]];
                }
            }
            if (!pos.every(Number.isFinite)) return;

            const playerKey = `${vertexCount}_${model[12].toFixed(1)}_${model[14].toFixed(1)}`;
            let finalPos = [...pos];

            if (config.prediction > 0) {
                const hist = PLAYER_HISTORY.get(playerKey) || { last: pos, vel: [0, 0, 0], tick: Date.now() };
                const now = Date.now(), dt = (now - hist.tick) / 1000;
                if (dt > 0.001 && dt < 0.5) {
                    const instVel = [(pos[0] - hist.last[0]) / dt, (pos[1] - hist.last[1]) / dt, (pos[2] - hist.last[2]) / dt];
                    hist.vel = hist.vel.map((v, i) => v * 0.6 + instVel[i] * 0.4);
                    const lookAhead = 0.06 * config.prediction;
                    finalPos = pos.map((v, i) => v + hist.vel[i] * lookAhead);
                }
                PLAYER_HISTORY.set(playerKey, { last: pos, vel: hist.vel, tick: now });
            }
            if (finalPos.every(Number.isFinite)) detectedPlayers.push({ position: finalPos, basePosition: basePos, key: playerKey });
        };
    }

    const originalX = Object.getOwnPropertyDescriptor(MouseEvent.prototype, 'movementX').get;
    const originalY = Object.getOwnPropertyDescriptor(MouseEvent.prototype, 'movementY').get;

    const getAimbotMotion = (isY) => {
        if (config.aimbotEnabled && isAiming && currentTarget) {
            const sPos = worldToScreen(currentTarget.position);
            if (sPos && Number.isFinite(sPos[0]) && Number.isFinite(sPos[1])) {
                const delta = sPos[isY ? 1 : 0] - (window[isY ? 'innerHeight' : 'innerWidth'] / 2);
                let movement = delta;
                let maxSnap = 65;


                switch (config.aimMode) {
                    case 'Rage':
                        movement = delta * (config.sensitivity * 2);
                        maxSnap = 150;
                        break;
                    case 'Legit':
                        movement = delta * (config.sensitivity * 0.5);
                        if (config.smoothingEnabled) movement /= (config.smoothing * 1.5);
                        maxSnap = 25;
                        break;
                    case 'Legacy':
                    case 'AIPD':
                    default:
                        movement = delta * config.sensitivity;
                        if (config.smoothingEnabled) movement /= config.smoothing;
                        maxSnap = 65;
                        break;
                }

                return Math.max(-maxSnap, Math.min(maxSnap, Math.round(movement)));
            }
        }
        return 0;
    };

    Object.defineProperty(MouseEvent.prototype, 'movementX', { get: function () { return getAimbotMotion(false) || originalX.call(this); } });
    Object.defineProperty(MouseEvent.prototype, 'movementY', { get: function () { return getAimbotMotion(true) || originalY.call(this); } });

    const hookWebGL = (GL) => {
        if (!GL || GL._hooked) return;
        GL._hooked = true;
        GL.enable = new Proxy(GL.enable, { apply(target, thisArg, args) { if (args[0] === 2929) isDepthEnabled = true; return Reflect.apply(...arguments); } });
        GL.disable = new Proxy(GL.disable, { apply(target, thisArg, args) { if (args[0] === 2929) isDepthEnabled = false; return Reflect.apply(...arguments); } });
        GL.useProgram = new Proxy(GL.useProgram, { apply(target, thisArg, args) { currentProgram = args[0]; return Reflect.apply(...arguments); } });
        GL.getUniformLocation = new Proxy(GL.getUniformLocation, { apply(target, thisArg, args) { const loc = Reflect.apply(...arguments); if (loc) loc._name = args[1]; return loc; } });
        GL.activeTexture = new Proxy(GL.activeTexture, { apply(target, thisArg, args) { activeTextureUnit = args[0] - thisArg.TEXTURE0; return Reflect.apply(...arguments); } });
        GL.bindTexture = new Proxy(GL.bindTexture, { apply(target, thisArg, args) { if (args[0] === thisArg.TEXTURE_2D) textureUnitBindings[activeTextureUnit] = args[1]; return Reflect.apply(...arguments); } });
        GL.texImage2D = new Proxy(GL.texImage2D, { apply(target, thisArg, args) { const p = args[args.length - 1]; if (p instanceof Float32Array) { const tex = textureUnitBindings[activeTextureUnit]; if (tex) textureDataMap.set(tex, p); } return Reflect.apply(...arguments); } });

        ["uniformMatrix4fv", "uniform1f", "uniform1i"].forEach(s => {
            if (GL[s]) {
                GL[s] = new Proxy(GL[s], {
                    apply(target, thisArg, args) {
                        const loc = args[0];
                        if (currentProgram && loc?._name) {
                            if (!uniformCache.has(currentProgram)) uniformCache.set(currentProgram, new Map());
                            let val = s === "uniformMatrix4fv" ? args[2].slice() : args[1];
                            if (s === "uniformMatrix4fv" && val.length === 16) if (val[11] !== 0 && Math.abs(val[15]) > 1.0) viewProjMatrix = val;
                            uniformCache.get(currentProgram).set(loc._name, val);
                        }
                        return Reflect.apply(...arguments);
                    }
                });
            }
        });

        GL.drawElements = new Proxy(GL.drawElements, {
            apply(target, thisArg, args) {
                const gl = thisArg, vC = args[1];
                if (currentProgram && vC > 1000) PlayerDetector.processDrawCall(gl, currentProgram, vC);
                if (PLAYER_VERTEX_SET.has(vC)) {
                    const wasEnabled = isDepthEnabled;
                    if (config.chamsEnabled && wasEnabled) gl.disable(gl.DEPTH_TEST);
                    const r = Reflect.apply(...arguments);
                    if (config.chamsEnabled && wasEnabled) gl.enable(gl.DEPTH_TEST);
                    return r;
                }
                return Reflect.apply(...arguments);
            }
        });
    };

    unsafeWindow.HTMLCanvasElement.prototype.getContext = new Proxy(unsafeWindow.HTMLCanvasElement.prototype.getContext, {
        apply(target, thisArg, args) {
            const ctx = Reflect.apply(...arguments);
            if (ctx && (args[0] === 'webgl2' || args[0] === 'webgl')) {
                if (args[1]) args[1].preserveDrawingBuffer = false;
                hookWebGL(Object.getPrototypeOf(ctx));
            }
            return ctx;
        }
    });

    if (unsafeWindow.WebGLRenderingContext) hookWebGL(unsafeWindow.WebGLRenderingContext.prototype);
    if (unsafeWindow.WebGL2RenderingContext) hookWebGL(unsafeWindow.WebGL2RenderingContext.prototype);


    const init = () => {
        const { ctx: overlayCtx, menu } = createUI();
        window.addEventListener('mousedown', (e) => { if (e.button === 2) { isAiming = true; lastLockedTarget = currentTarget?.key; } });
        window.addEventListener('mouseup', (e) => { if (e.button === 2) { isAiming = false; lastLockedTarget = null; } });

        const drawCornerBox = (ctx, x, y, w, h) => {
            const length = w / 4; ctx.beginPath();
            ctx.moveTo(x, y + length); ctx.lineTo(x, y); ctx.lineTo(x + length, y);
            ctx.moveTo(x + w - length, y); ctx.lineTo(x + w, y); ctx.lineTo(x + w, y + length);
            ctx.moveTo(x, y + h - length); ctx.lineTo(x, y + h); ctx.lineTo(x + length, y + h);
            ctx.moveTo(x + w - length, y + h); ctx.lineTo(x + w, y + h); ctx.lineTo(x + w, y + h - length);
            ctx.stroke();
        };

        const loop = () => {
            const cx = window.innerWidth / 2, cy = window.innerHeight / 2;
            overlayCtx.clearRect(0, 0, window.innerWidth, window.innerHeight);

            if (config.showFov) {
                overlayCtx.beginPath(); overlayCtx.arc(cx, cy, config.fov, 0, Math.PI * 2);
                overlayCtx.strokeStyle = config.espColor; overlayCtx.globalAlpha = 0.2; overlayCtx.lineWidth = 1; overlayCtx.stroke(); overlayCtx.globalAlpha = 1.0;
            }

            let best = null, minDist = config.fov;
            detectedPlayers.forEach(p => {
                const sPosHead = worldToScreen(p.position); const sPosFoot = worldToScreen(p.basePosition);
                if (!sPosHead) return;
                if (sPosFoot) {
                    const h = Math.abs(sPosFoot[1] - sPosHead[1]) * 1.2, w = h / 1.5;
                    overlayCtx.strokeStyle = config.espColor; overlayCtx.lineWidth = 1.5;
                    if (config.espBoxes) { if (config.espStyle === 'Corner') drawCornerBox(overlayCtx, sPosHead[0] - w / 2, sPosHead[1] - h * 0.1, w, h); else overlayCtx.strokeRect(sPosHead[0] - w / 2, sPosHead[1] - h * 0.1, w, h); }
                    if (config.espLines) { overlayCtx.beginPath(); overlayCtx.moveTo(cx, window.innerHeight); overlayCtx.lineTo(sPosHead[0], sPosFoot[1] || sPosHead[1]); overlayCtx.globalAlpha = 0.3; overlayCtx.stroke(); overlayCtx.globalAlpha = 1.0; }
                    if (config.espSkeleton) { overlayCtx.beginPath(); overlayCtx.moveTo(sPosHead[0], sPosHead[1]); overlayCtx.lineTo(sPosFoot[0], sPosFoot[1]); overlayCtx.stroke(); }
                }
                const d = Math.hypot(sPosHead[0] - cx, sPosHead[1] - cy);
                if (config.stickyTarget && isAiming && p.key === lastLockedTarget) { best = p; minDist = 9999; } else if (d < minDist) { minDist = d; best = p; }
            });
            currentTarget = best;


            if (config.triggerbot && currentTarget) {
                const headPos = worldToScreen(currentTarget.position);
                if (headPos) {
                    const distToCrosshair = Math.hypot(headPos[0] - cx, headPos[1] - cy);
                    if (distToCrosshair < 20) {
                        setTimeout(() => { window.dispatchEvent(new MouseEvent('mousedown', { button: 0, bubbles: true })); }, Math.max(0, config.triggerbotDelay - 25)); // Conceptual time split
                        setTimeout(() => window.dispatchEvent(new MouseEvent('mouseup', { button: 0, bubbles: true })), config.triggerbotDelay);
                    }
                }
            }

            if (isAiming && currentTarget) { window.dispatchEvent(new MouseEvent('mousemove', { bubbles: true })); }


            const lockStatus = document.getElementById('stat-lock');
            if (currentTarget) { lockStatus.innerText = 'Lock: ACTIVE'; lockStatus.style.color = config.espColor; } else { lockStatus.innerText = 'Lock: None'; lockStatus.style.color = '#666'; }

            detectedPlayers.length = 0;
            if (PLAYER_HISTORY.size > 50) { const now = Date.now(); for (const [id, data] of PLAYER_HISTORY) if (now - data.tick > 2000) PLAYER_HISTORY.delete(id); }
            requestAnimationFrame(loop);
        };
        requestAnimationFrame(loop);


        const syncUIWithState = () => {
            document.getElementById('c-aim').checked = config.aimbotEnabled;
            document.getElementById('c-cham').checked = config.chamsEnabled;
            document.getElementById('c-espb').checked = config.espBoxes;
        };

        window.addEventListener('keydown', (e) => {
            if (e.code === 'ShiftRight') { config.menuVisible = !config.menuVisible; menu.style.display = config.menuVisible ? 'flex' : 'none'; }
            if (e.code === 'F1') { config.aimbotEnabled = !config.aimbotEnabled; syncUIWithState(); }
            if (e.code === 'F2') { config.chamsEnabled = !config.chamsEnabled; config.espBoxes = !config.espBoxes; syncUIWithState(); }
        });
    };

    if (document.readyState === 'complete') init(); else window.addEventListener('load', init);
})();