Limax Client[1.3]

Hud(RAlt): Ad Blocker, Auto Play(new kill mode auto-reconnect), ZoomHack, Tracers, SkinHack, and more functions!!!

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

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

Tendrás que instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Tendrás que instalar una extensión como Tampermonkey antes de poder instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name        Limax Client[1.3]
// @namespace   Violentmonkey Scripts
// @match       *://limax.io/*
// @icon        https://limax.io/img/limax.ico
// @grant       GM_addStyle
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_deleteValue
// @grant       GM.getValue
// @grant       GM.setValue
// @grant       GM.deleteValue
// @grant       unsafeWindow
// @version     1.3
// @author      Drik
// @description Hud(RAlt): Ad Blocker, Auto Play(new kill mode auto-reconnect), ZoomHack, Tracers, SkinHack, and more functions!!!
// @run-at      document-idle
// @license     MIT
// ==/UserScript==

// version 1.2: new functions, ZoomHack, SkinHack
// version 1.3: new function(Skip Animations), fixed nickname save, fix bugs(tracers,esp draws), HUD update: added ping counter, Fixed time bug, Auto Play: added auto-reconnect function, Auto nick has been removed


(async function() {
    'use strict';

    const STORAGE_KEY = 'lt';

    const defaults = {
        visible: false,
        AdBlocker: false,
        BetterLeaderBoard: false,
        AutoPlay: false,
        AutoPlayKillMode: false,
        AutoReconnect: false,
        Tracers: false,
        ESP: false,
        SkipAnimations: false,
        HUD: false,
        Zoom: false,
        SkinHack: false,
        ToggleKey: 'AltRight',
        Theme: 'dark'
    };

    async function gmGet(key, def) {
        try {
            if (typeof GM_getValue === 'function') return GM_getValue(key, def);
            if (typeof GM === 'object' && typeof GM.getValue === 'function') return await GM.getValue(key, def);
        } catch (e) {}
        return def;
    }

    async function gmSet(key, val) {
        try {
            if (typeof GM_setValue === 'function') return GM_setValue(key, val);
            if (typeof GM === 'object' && typeof GM.setValue === 'function') return await GM.setValue(key, val);
        } catch (e) {}
    }

    async function gmDelete(key) {
        try {
            if (typeof GM_deleteValue === 'function') return GM_deleteValue(key);
            if (typeof GM === 'object' && typeof GM.deleteValue === 'function') return await GM.deleteValue(key);
        } catch (e) {}
    }

    const raw = await gmGet(STORAGE_KEY, null);
    let state = (() => {
        try {
            if (!raw) return Object.assign({}, defaults);
            const p = JSON.parse(raw);
            return Object.assign({}, defaults, p);
        } catch (e) {
            return Object.assign({}, defaults);
        }
    })();

    GM_addStyle(`
    @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700;800;900&display=swap');

    :root {
      --bg: rgba(18,18,20,0.95);
      --panel: linear-gradient(135deg, rgba(255,255,255,0.03), rgba(255,255,255,0.01));
      --accent: linear-gradient(90deg,#6ee7b7,#3b82f6);
      --muted: rgba(255,255,255,0.62);
      --shadow: 0 6px 24px rgba(2,6,23,0.6);
    }

    .theme-white {
      --bg: rgba(255,255,255,0.98);
      --panel: linear-gradient(135deg, rgba(255,255,255,0.9), rgba(250,250,255,0.85));
      --accent: linear-gradient(90deg,#fef3c7,#c7d2fe);
      --muted: rgba(12,34,56,0.6);
      --shadow: 0 8px 30px rgba(2,6,23,0.06);
    }

    #limax-toolbox {
      font-family: 'Inter', ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif !important;
      -webkit-font-smoothing: antialiased !important;
      -moz-osx-font-smoothing: grayscale !important;
      text-rendering: optimizeLegibility !important;
      position: fixed;
      right: 40px;
      top: 40px;
      width: 720px;
      max-width: calc(100% - 80px);
      z-index: 2147483647;
      border-radius: 12px;
      background: var(--bg);
      padding: 18px;
      box-shadow: var(--shadow);
      color: #e6eef8;
      display: none;
      backdrop-filter: blur(8px) saturate(120%);
      border: 1px solid rgba(255,255,255,0.03);
      line-height: 1.18;
    }

    #limax-toolbox, #limax-toolbox * { font-family: 'Inter', ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif !important; }

    #limax-toolbox.show { display:block; animation: dropIn 220ms cubic-bezier(.2,.9,.3,1); }
    @keyframes dropIn { from { transform: translateY(-8px) scale(.995); opacity: 0; } to { transform: translateY(0) scale(1); opacity: 1; } }

    .lt-header { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:12px; }
    .lt-title { display:flex; gap:12px; align-items:center; }
    .lt-logo { min-width:120px; height:44px; border-radius:10px; background:var(--accent); display:flex; align-items:center; justify-content:center; font-weight:800; color:#04263b; font-size:14px; padding:0 12px; }
    .lt-h1 { font-size:18px; font-weight:700; margin:0; color: var(--muted); }
    .lt-sub { font-size:12px; color:var(--muted); margin-top:2px; }

    .lt-grid { display:grid; grid-template-columns:1fr 1fr; gap:14px; }

    .lt-card { background:var(--panel); border-radius:10px; padding:12px; min-height:92px; display:flex; flex-direction:column; justify-content:space-between; transition: transform .12s, box-shadow .12s; border:1px solid rgba(0,0,0,0.03); color: var(--muted);}
    .lt-card:hover { transform: translateY(-4px); box-shadow: 0 10px 30px rgba(2,6,23,0.06); }
    .title-row { display:flex; justify-content:space-between; align-items:center; gap:8px; }
    .lt-card h3 { margin:0; font-size:14px; font-weight:700; color: inherit; }
    .lt-card p { margin:8px 0 0 0; font-size:12px; color:var(--muted); line-height:1.25; }

    .lt-switch { position:relative; width:56px; height:30px; border-radius:999px; background: rgba(255,255,255,0.06); display:flex; align-items:center; padding:4px; cursor:pointer; box-sizing:border-box; }
    .lt-switch.on { background: linear-gradient(90deg,#34d399,#3b82f6); box-shadow: 0 6px 18px rgba(59,130,246,0.18); }
    .lt-switch .knob { width:22px; height:22px; border-radius:50%; background:#fff; transform: translateX(0); transition: transform .14s; box-shadow: 0 6px 16px rgba(2,6,23,0.25); }
    .lt-switch.on .knob { transform: translateX(26px); }

    .lt-controls { margin-top:10px; display:flex; gap:10px; align-items:center; flex-wrap:wrap; }
    .lt-input { background: rgba(0,0,0,0.12); border: 1px solid rgba(255,255,255,0.04); color: #eaf6ff; padding:8px 10px; border-radius:8px; outline:none; min-width:160px; font-size:13px; }
    .lt-small { font-size:12px; color:var(--muted); }

    .lt-footer { margin-top:14px; display:flex; justify-content:space-between; align-items:center; gap:12px; }
    .lt-toggle-key { font-weight:700; font-size:12px; color:#cfefff; }
    .lt-footer .save { background: linear-gradient(90deg,#60a5fa,#7dd3fc); color:#04263b; border-radius:10px; padding:8px 12px; font-weight:700; cursor:pointer; border:none; }

    .lt-btn { padding:8px 10px; border-radius:8px; background: rgba(0,0,0,0.12); border:1px solid rgba(255,255,255,0.02); cursor:pointer; color:var(--muted); font-size:13px; }

    @media (max-width:780px) { #limax-toolbox{ right:16px; left:16px;} .lt-grid{grid-template-columns:1fr;} .lt-logo{min-width:96px;font-size:13px;padding:0 8px;} }
  `);

    const root = document.createElement('div');
    root.id = 'limax-toolbox';
    if (state.Theme === 'white') root.classList.add('theme-white');
    document.body.appendChild(root);

    let adIv = null;
    let lbIv = null;
    let trRunner = null;
    let espRunner = null;

    let hudRunner = null;

    let _arWasInGame = false;
    let _arFired = false;

    let _pingMs = -1;
    let _pingPending = false;
    let _pingSentAt = 0;
    let _lastPingTime = 0;
    let _hudSessionStart = 0;
    const _PING_IV = 0x7D0;

    const _NativeWS = unsafeWindow.WebSocket;
    const _nativeSend = _NativeWS.prototype.send;
    const _nativeAEL = _NativeWS.prototype.addEventListener;

    _NativeWS.prototype.send = function(data) {
        if (!_pingPending && typeof data === 'string' && performance.now() - _lastPingTime >= _PING_IV) {
            try {
                const p = JSON.parse(data);
                if (p[0] === 0) {
                    _pingPending = true;
                    _pingSentAt = performance.now();
                }
            } catch {}
        }
        return _nativeSend.call(this, data);
    };

    _NativeWS.prototype.addEventListener = function(type, fn, ...rest) {
        if (type === 'message') {
            const wrapped = function(e) {
                if (_pingPending && e.data instanceof ArrayBuffer) {
                    _pingMs = Math.round(performance.now() - _pingSentAt);
                    _pingPending = false;
                    _lastPingTime = performance.now();
                }
                return fn.call(this, e);
            };
            return _nativeAEL.call(this, type, wrapped, ...rest);
        }
        if (type === 'close' && this.url?.includes('limax')) {
            const wrapped = (e) => {
                fn.call(this, e);
                if (_arWasInGame && state.AutoReconnect) _arSchedule('socket.close');
            };
            return _nativeAEL.call(this, type, wrapped, ...rest);
        }
        return _nativeAEL.call(this, type, fn, ...rest);
    };

    const _onmsgDesc = Object.getOwnPropertyDescriptor(_NativeWS.prototype, 'onmessage');
    const _msgStore = new WeakMap();
    Object.defineProperty(_NativeWS.prototype, 'onmessage', {
        configurable: true,
        get() {
            return _msgStore.get(this) ?? null;
        },
        set(fn) {
            _msgStore.set(this, fn);
            if (typeof fn !== 'function') {
                _onmsgDesc?.set?.call(this, fn);
                return;
            }
            _onmsgDesc?.set?.call(this, function(e) {
                if (_pingPending && e.data instanceof ArrayBuffer) {
                    _pingMs = Math.round(performance.now() - _pingSentAt);
                    _pingPending = false;
                    _lastPingTime = performance.now();
                }
                return fn.call(this, e);
            });
        },
    });

    const _oncloseDesc = Object.getOwnPropertyDescriptor(_NativeWS.prototype, 'onclose');
    const _closeStore = new WeakMap();
    Object.defineProperty(_NativeWS.prototype, 'onclose', {
        configurable: true,
        get() {
            return _closeStore.get(this) ?? null;
        },
        set(fn) {
            _closeStore.set(this, fn);
            if (typeof fn !== 'function') {
                _oncloseDesc?.set?.call(this, fn);
                return;
            }
            _oncloseDesc?.set?.call(this, function(e) {
                fn.call(this, e);
                if (_arWasInGame && state.AutoReconnect && this.url?.includes('limax')) _arSchedule('onclose');
            });
        },
    });

    unsafeWindow.WebSocket = function(...args) {
        const ws = new _NativeWS(...args);
        if (ws.url?.includes('limax')) {
            ws.addEventListener('open', () => {
                _hudSessionStart = Date.now();
                _pingMs = -1;
                _pingPending = false;
            });
            ws.addEventListener('close', () => {
                _hudSessionStart = 0;
                _pingMs = -1;
                _pingPending = false;
            });
        }
        return ws;
    };
    unsafeWindow.WebSocket.prototype = _NativeWS.prototype;
    Object.assign(unsafeWindow.WebSocket, {
        CONNECTING: 0,
        OPEN: 1,
        CLOSING: 2,
        CLOSED: 3
    });

    function _arWaitAndStart(src) {
        if (_arFired || !_arWasInGame || unsafeWindow.game_is_show || unsafeWindow.wait_banner_rendering || typeof unsafeWindow.start !== 'function') return;
        if (unsafeWindow.disa_interface) {
            requestAnimationFrame(() => _arWaitAndStart(src));
            return;
        }
        _arFired = true;
        unsafeWindow.disa_interface = true;
        unsafeWindow.start();
    }

    function _arSchedule(src) {
        _arFired = false;
        requestAnimationFrame(() => requestAnimationFrame(() => _arWaitAndStart(src)));
    }

    function _hookQuitForAR() {
        if (typeof unsafeWindow.quit_game !== 'function') {
            requestAnimationFrame(_hookQuitForAR);
            return;
        }
        const orig = unsafeWindow.quit_game;
        unsafeWindow.quit_game = function() {
            orig.call(this);
            if (_arWasInGame && state.AutoReconnect) _arSchedule('quit_game');
        };
    }
    _hookQuitForAR();

    function _watchGameForAR() {
        let prev = false;

        function tick() {
            const cur = Boolean(unsafeWindow.game_is_show);
            if (cur && !prev) {
                _arWasInGame = true;
                _arFired = false;
            }
            prev = cur;
            requestAnimationFrame(tick);
        }
        requestAnimationFrame(tick);
    }
    _watchGameForAR();

    let _saOrigDisplay = null;
    let _saOrigQuit = null;
    let _saOrigSTO = null;
    let _saCssEl = null;

    function startSkipAnimations() {
        _saCssEl = document.createElement('style');
        _saCssEl.textContent = `*:not(#limax-toolbox):not(#limax-toolbox *):not(#logo):not(#logoi){transition:none!important;animation-duration:0.001ms!important;animation-delay:0ms!important;}`;
        document.head.appendChild(_saCssEl);

        _saOrigSTO = unsafeWindow.setTimeout;
        unsafeWindow.setTimeout = function(fn, delay, ...args) {
            if (typeof fn === 'function' && (fn.name === 'display_game' || fn === unsafeWindow.display_game)) return _saOrigSTO.call(unsafeWindow, fn, 0, ...args);
            return _saOrigSTO.call(unsafeWindow, fn, delay, ...args);
        };

        function patchSA() {
            if (typeof unsafeWindow.display_game !== 'function' || typeof unsafeWindow.quit_game !== 'function') {
                requestAnimationFrame(patchSA);
                return;
            }
            if (!_saOrigDisplay) {
                _saOrigDisplay = unsafeWindow.display_game;
                unsafeWindow.display_game = function() {
                    if (typeof unsafeWindow.opacity === 'number' && unsafeWindow.opacity > 0) unsafeWindow.opacity = 0;
                    return _saOrigDisplay.call(this);
                };
            }
            if (!_saOrigQuit) {
                _saOrigQuit = unsafeWindow.quit_game;
                unsafeWindow.quit_game = function() {
                    _saOrigQuit.call(this);
                    requestAnimationFrame(() => {
                        const playi = document.getElementById('playi');
                        if (playi && playi.src && playi.src.includes('.gif')) playi.src = playi.src.replace('.gif', '.png');
                    });
                };
            }
        }
        requestAnimationFrame(patchSA);
    }

    function stopSkipAnimations() {
        if (_saCssEl) {
            _saCssEl.remove();
            _saCssEl = null;
        }
        if (_saOrigSTO) {
            unsafeWindow.setTimeout = _saOrigSTO;
            _saOrigSTO = null;
        }
        if (_saOrigDisplay && unsafeWindow.display_game !== _saOrigDisplay) {
            unsafeWindow.display_game = _saOrigDisplay;
            _saOrigDisplay = null;
        }
        if (_saOrigQuit && unsafeWindow.quit_game !== _saOrigQuit) {
            unsafeWindow.quit_game = _saOrigQuit;
            _saOrigQuit = null;
        }
    }

    let zoomValue = 1.0;
    const ZOOM_MIN = 0.2;
    const ZOOM_MAX = 2.0;
    const ZOOM_STEP = 0.1;

    const _wDesc = Object.getOwnPropertyDescriptor(unsafeWindow, 'innerWidth') ||
        Object.getOwnPropertyDescriptor(Object.getPrototypeOf(unsafeWindow), 'innerWidth');
    const _hDesc = Object.getOwnPropertyDescriptor(unsafeWindow, 'innerHeight') ||
        Object.getOwnPropertyDescriptor(Object.getPrototypeOf(unsafeWindow), 'innerHeight');
    const _realW = () => _wDesc.get.call(unsafeWindow);
    const _realH = () => _hDesc.get.call(unsafeWindow);

    Object.defineProperty(unsafeWindow, 'innerWidth', {
        configurable: true,
        get: () => (state.Zoom && zoomValue !== 1.0) ? Math.round(_realW() / zoomValue) : _realW()
    });
    Object.defineProperty(unsafeWindow, 'innerHeight', {
        configurable: true,
        get: () => (state.Zoom && zoomValue !== 1.0) ? Math.round(_realH() / zoomValue) : _realH()
    });

    const _nativeGBCR = Element.prototype.getBoundingClientRect;
    Element.prototype.getBoundingClientRect = function() {
        if (!state.Zoom || this !== unsafeWindow.canvas || zoomValue === 1.0) return _nativeGBCR.call(this);
        return {
            left: 0,
            top: 0,
            right: _realW(),
            bottom: _realH(),
            width: _realW(),
            height: _realH(),
            x: 0,
            y: 0
        };
    };

    function _patchGetMousePos() {
        if (typeof unsafeWindow.getMousePos !== 'function') {
            requestAnimationFrame(_patchGetMousePos);
            return;
        }
        const _orig = unsafeWindow.getMousePos;
        unsafeWindow.getMousePos = function(canvas, e) {
            if (!state.Zoom || zoomValue === 1.0) return _orig(canvas, e);
            return {
                x: e.clientX / zoomValue,
                y: e.clientY / zoomValue
            };
        };
    }
    _patchGetMousePos();

    function _applyZoomCss() {
        const cvs = unsafeWindow.canvas;
        if (!cvs) return;
        if (!state.Zoom || zoomValue === 1.0) {
            cvs.style.transform = '';
            cvs.style.transformOrigin = '';
            cvs.style.position = '';
            cvs.style.left = '';
            cvs.style.top = '';
        } else {
            cvs.style.transformOrigin = 'top left';
            cvs.style.transform = `scale(${zoomValue})`;
            cvs.style.position = 'fixed';
            cvs.style.left = '0';
            cvs.style.top = '0';
        }
        unsafeWindow.dispatchEvent(new Event('resize'));
        _updateZoomLabel();
    }

    function _updateZoomLabel() {
        const lbl = document.getElementById('_zoom_label');
        if (lbl) lbl.textContent = `zoom: ${zoomValue.toFixed(1)}x`;
    }

    let _zoomWheelBound = false;

    function _bindZoomWheel() {
        if (_zoomWheelBound) return;
        _zoomWheelBound = true;
        window.addEventListener('wheel', (e) => {
            if (!state.Zoom || !e.ctrlKey) return;
            e.preventDefault();
            zoomValue = e.deltaY < 0 ?
                Math.min(ZOOM_MAX, +(zoomValue + ZOOM_STEP).toFixed(2)) :
                Math.max(ZOOM_MIN, +(zoomValue - ZOOM_STEP).toFixed(2));
            _applyZoomCss();
        }, {
            passive: false
        });
        window.addEventListener('keydown', (e) => {
            if (state.Zoom && e.ctrlKey && e.key === '0') {
                zoomValue = 1.0;
                _applyZoomCss();
            }
        });
    }

    const _SH_THEMES = ['c1', 'c2', 'c3', 'c4'];
    const _SH_TOTAL = 40;
    let _shVirtual = 0;
    let _shTheme = 'c2';
    let _shActive = false;
    let _shBtnL = null;
    let _shBtnR = null;
    const _origGetById = document.getElementById.bind(document);

    document.getElementById = function(id) {
        if (_shActive && typeof id === 'string' && id.startsWith('skin_')) {
            const parts = id.split('_');
            if (parts.length === 3) return _origGetById(`skin_${_shTheme}_${parts[2]}`) || _origGetById(id);
        }
        return _origGetById(id);
    };

    function _shRenderGrdbpi(slot, color) {
        const arr = [];
        for (let d = 1; d < 50; d++) {
            const f = document.createElement('canvas');
            f.width = d;
            f.height = d;
            const e = d / 2,
                l = Math.max(e - 2, 1);
            const ctx = f.getContext('2d');
            ctx.beginPath();
            ctx.globalAlpha = 0.1;
            ctx.arc(e, e, l, 0, Math.PI * 2);
            ctx.fillStyle = color;
            ctx.fill();
            ctx.globalAlpha = 1;
            ctx.beginPath();
            ctx.arc(e, e, l / 1.4, 0, Math.PI * 2);
            ctx.fillStyle = color;
            ctx.fill();
            arr.push(f);
        }
        unsafeWindow.txt_pck.grdbpi[slot] = arr;
    }

    function _shApply(v) {
        const win = unsafeWindow;
        const pack = Math.floor(v / 10);
        const slot = v % 10;
        const theme = _SH_THEMES[pack];
        _shTheme = theme;
        win.current_skin = slot;
        if (!win._sh_color_patched) {
            win.skin_color = [...win.pack_skin_color[1]];
            win._sh_color_patched = true;
        }
        const color = win.pack_skin_color[pack][slot];
        win.skin_color[slot] = color;
        win.skin_scale[slot] = win.pack_skin_scale[pack][slot];
        const img = _origGetById(`skin_${theme}_${slot}`);
        if (img) win.txt_pck.skin[slot] = img;
        _shRenderGrdbpi(slot, color);
        const names = {
            c1: 'Candy',
            c2: 'Space',
            c3: 'Ice',
            c4: 'Dark'
        };
        const lbl = _origGetById('_sh_label');
        if (lbl) lbl.textContent = `${names[theme]}  ·  ${slot + 1}/10  (${v + 1}/${_SH_TOTAL})`;
    }

    function _shWaitReady(fn) {
        const win = unsafeWindow;
        if (win.pack_skin_color && win.pack_skin_scale && win.skin_color && win.skin_scale && win.txt_pck?.skin && win.txt_pck?.grdbpi && _origGetById('select_left')) fn();
        else setTimeout(() => _shWaitReady(fn), 100);
    }

    function startSkinHack() {
        if (_shActive) return;
        _shActive = true;
        _shWaitReady(() => {
            _shVirtual = unsafeWindow.current_skin || 0;
            const btnL = _origGetById('select_left');
            const btnR = _origGetById('select_right');
            if (!btnL || !btnR) return;
            _shBtnL = btnL.cloneNode(true);
            _shBtnR = btnR.cloneNode(true);
            btnL.parentNode.replaceChild(_shBtnL, btnL);
            btnR.parentNode.replaceChild(_shBtnR, btnR);
            _shBtnL.addEventListener('click', () => {
                _shVirtual = (_shVirtual - 1 + _SH_TOTAL) % _SH_TOTAL;
                _shApply(_shVirtual);
            });
            _shBtnR.addEventListener('click', () => {
                _shVirtual = (_shVirtual + 1) % _SH_TOTAL;
                _shApply(_shVirtual);
            });
            _shApply(_shVirtual);
            if (!_origGetById('_sh_label')) {
                const lbl = document.createElement('div');
                lbl.id = '_sh_label';
                Object.assign(lbl.style, {
                    textAlign: 'center',
                    marginTop: '430px',
                    color: '#2fcc6e',
                    fontFamily: 'monospace',
                    fontSize: '11px',
                    letterSpacing: '1px',
                });
                const skinSel = _origGetById('select_skin');
                if (skinSel) skinSel.after(lbl);
            }
        });
    }

    function stopSkinHack() {
        _shActive = false;
        const lbl = _origGetById('_sh_label');
        if (lbl) lbl.remove();

        if (_shBtnL) {
            const origL = _shBtnL.cloneNode(true);
            origL.id = 'select_left';
            if (_shBtnL.parentNode) _shBtnL.parentNode.replaceChild(origL, _shBtnL);
            origL.onclick = function() {
                if (unsafeWindow.disa_interface) return;
                unsafeWindow.current_skin--;
                if (unsafeWindow.game_mode === unsafeWindow.TEAM_MODE && unsafeWindow.current_skin < 0) unsafeWindow.current_skin = 1;
                else if (unsafeWindow.current_skin < 0) unsafeWindow.current_skin = unsafeWindow.MAX_SKIN - 1;
            };
            _shBtnL = null;
        }
        if (_shBtnR) {
            const origR = _shBtnR.cloneNode(true);
            origR.id = 'select_right';
            if (_shBtnR.parentNode) _shBtnR.parentNode.replaceChild(origR, _shBtnR);
            origR.onclick = function() {
                if (unsafeWindow.disa_interface) return;
                unsafeWindow.current_skin++;
                if (unsafeWindow.game_mode === unsafeWindow.TEAM_MODE && unsafeWindow.current_skin >= 2) unsafeWindow.current_skin = 0;
                else if (unsafeWindow.current_skin >= unsafeWindow.MAX_SKIN) unsafeWindow.current_skin = 0;
            };
            _shBtnR = null;
        }
    }

    function adStart() {
        const S = ['#advert', '#vertad', '#crossPromotion'];
        const w = (typeof unsafeWindow !== 'undefined') ? unsafeWindow : window;
        const hide = el => {
            if (!el) return;
            try {
                el.style.setProperty('pointer-events', 'none', 'important');
                el.style.setProperty('opacity', '0', 'important');
                el.style.setProperty('visibility', 'hidden', 'important');
                el.style.setProperty('display', 'none', 'important');
            } catch (e) {}
        };
        const hideAll = () => S.forEach(sel => document.querySelectorAll(sel).forEach(hide));
        const patch = () => {
            try {
                hideAll();
                if (!w) return;
                w.wait_banner_rendering = 0;
                w.adinplay_counter = 0;
                w.ADINPLAY_LOOP = 1e9;
                if (w.Widget && typeof w.Widget === 'object') {
                    try {
                        w.Widget.preroll = function() {
                            try {
                                w.start && w.start();
                            } catch (e) {}
                        };
                    } catch (e) {}
                    try {
                        w.Widget.play = function() {
                            try {
                                w.start && w.start();
                            } catch (e) {}
                        };
                    } catch (e) {}
                    try {
                        w.Widget.adsRefresh = function() {};
                    } catch (e) {}
                    try {
                        w.Widget.refresh = function() {};
                    } catch (e) {}
                    try {
                        w.Widget.stop = function() {};
                    } catch (e) {}
                }
                const p = document.getElementById('play');
                if (p) p.onclick = function() {
                    try {
                        if (!w.disa_interface && w.wait_banner_rendering === 0) {
                            w.disa_interface = true;
                            w.start && w.start();
                        }
                    } catch (e) {}
                };
            } catch (e) {}
        };
        patch();
        adIv = setInterval(patch, 777);
    }

    function adStop() {
        if (adIv) {
            clearInterval(adIv);
            adIv = null;
        }
    }

    function lbStart() {
        const w = (typeof unsafeWindow !== 'undefined') ? unsafeWindow : window;

        function tick() {
            try {
                if (!w) return;
                const arr = Array.isArray(w.players) ? w.players.filter(p => p != null) : [];
                const map = {};
                arr.forEach(p => map[p.id] = p.score || 0);
                const cand = [];
                if (Array.isArray(w.players_nickname)) {
                    for (let i = 0; i < w.players_nickname.length; i++) {
                        const name = w.players_nickname[i];
                        if (name && name !== " ") cand.push({
                            id: i,
                            nickname: (typeof w.filterBadWords === 'function' ? w.filterBadWords(name) : name),
                            score: map[i] || 0
                        });
                    }
                }
                arr.forEach(p => {
                    if (!cand.find(x => x.id === p.id)) cand.push({
                        id: p.id,
                        nickname: (w.players_nickname && w.players_nickname[p.id]) ? (typeof w.filterBadWords === 'function' ? w.filterBadWords(w.players_nickname[p.id]) : w.players_nickname[p.id]) : " ",
                        score: p.score || 0
                    });
                });
                if (cand.length === 0) return;
                cand.sort((a, b) => b.score - a.score);
                const N = Math.min(10, cand.length);
                const top = {
                    nickname: [],
                    score: [],
                    id: [],
                    rank: "?",
                    total: cand.length
                };
                for (let i = 0; i < N; i++) {
                    top.nickname.push(cand[i].nickname);
                    top.score.push(cand[i].score);
                    top.id.push(cand[i].id);
                }
                const idx = cand.findIndex(x => x.id === w.true_id);
                if (idx >= 0) top.rank = idx + 1;
                if (typeof w.draw_leaderboard === 'function') w.draw_leaderboard(top);
                if (typeof w.draw_personal_info === 'function') w.draw_personal_info(top);
            } catch (e) {}
        }
        tick();
        lbIv = setInterval(tick, 150);
    }

    function lbStop() {
        if (lbIv) {
            clearInterval(lbIv);
            lbIv = null;
        }
    }

    function makeTracers() {
        let ctx = null,
            canvas = null,
            raf = null,
            lastPatched = null;

        function getCanvas() {
            return document.getElementById('myCanvas');
        }

        function safeHas(a, i) {
            return a && typeof a[i] !== 'undefined';
        }

        function hexToRgba(hex, a) {
            if (!hex) return 'rgba(255,255,255,' + a + ')';
            if (hex[0] === '#') hex = hex.slice(1);
            if (hex.length === 3) hex = hex.split('').map(c => c + c).join('');
            let r = parseInt(hex.slice(0, 2), 16);
            let g = parseInt(hex.slice(2, 4), 16);
            let b = parseInt(hex.slice(4, 6), 16);
            return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
        }

        function draw() {
            try {
                if (!state.Tracers) return;
                if (typeof players === 'undefined' || typeof players_show_pos === 'undefined') return;
                if (typeof id === 'undefined' || !players || !players[id]) return;
                let meIndex = players[id].id;
                if (typeof players_show_pos[meIndex] === 'undefined') return;
                canvas = canvas || getCanvas();
                if (!canvas) return;
                ctx = ctx || canvas.getContext('2d');
                let cam = {
                    x: canvas.width / 2 - players_show_pos[meIndex].x,
                    y: canvas.height / 2 - players_show_pos[meIndex].y
                };
                ctx.save();
                ctx.setTransform(1, 0, 0, 1, 0, 0);
                let ps = typeof player_scale !== 'undefined' && player_scale !== -1 ? player_scale : 1;
                ctx.scale(ps, ps);
                let offset = (ps - 1) / (2 * ps);
                ctx.translate(-canvas.width * offset, -canvas.height * offset);
                ctx.lineCap = 'round';
                ctx.lineJoin = 'round';
                for (let i = 0; i < players.length; i++) {
                    let p = players[i];
                    if (!p) continue;
                    let pid = p.id;
                    if (pid === meIndex) continue;
                    if (!safeHas(players_show_pos, pid)) continue;
                    if (safeHas(players_alpha, pid) && players_alpha[pid] <= 0) continue;
                    let sx = players_show_pos[pid].x + cam.x,
                        sy = players_show_pos[pid].y + cam.y;
                    let mx = players_show_pos[meIndex].x + cam.x,
                        my = players_show_pos[meIndex].y + cam.y;
                    let dx = sx - mx,
                        dy = sy - my,
                        dist = Math.hypot(dx, dy) || 1;
                    let baseW = Math.max(0.6, Math.min(2.2, 1.8 - dist * 0.004));
                    let skinIdx = safeHas(players_skin, pid) ? players_skin[pid] : 0;
                    let rawColor = (typeof skin_color !== 'undefined' && skin_color[skinIdx]) ? skin_color[skinIdx] : '#ffffff';
                    let alphaFactor = Math.min(1, (safeHas(players_alpha, pid) ? players_alpha[pid] / 100 : 1) * 0.95);
                    let glow = hexToRgba(rawColor, 0.12 * alphaFactor);
                    let coreS = hexToRgba(rawColor, 0.98 * alphaFactor);
                    let coreE = hexToRgba(rawColor, 0.36 * alphaFactor);
                    let gx = mx + dx * 0.5,
                        gy = my + dy * 0.5;
                    let nx = -dy,
                        ny = dx;
                    let nlen = Math.hypot(nx, ny) || 1;
                    nx /= nlen;
                    ny /= nlen;
                    let side = (pid % 2 === 0) ? 1 : -1;
                    let curve = Math.min(100, dist * 0.10);
                    let cx = gx + nx * curve * side,
                        cy = gy + ny * curve * side;
                    ctx.save();
                    ctx.shadowBlur = Math.max(5, baseW * 2.5);
                    ctx.shadowColor = glow;
                    ctx.lineWidth = baseW * 1.8;
                    ctx.beginPath();
                    ctx.moveTo(mx, my);
                    ctx.quadraticCurveTo(cx, cy, sx, sy);
                    ctx.strokeStyle = hexToRgba(rawColor, 0.20 * alphaFactor);
                    ctx.globalCompositeOperation = 'lighter';
                    ctx.stroke();
                    ctx.restore();
                    ctx.save();
                    let grad = ctx.createLinearGradient(mx, my, sx, sy);
                    grad.addColorStop(0, coreS);
                    grad.addColorStop(0.6, coreE);
                    grad.addColorStop(1, hexToRgba(rawColor, 0.06 * alphaFactor));
                    ctx.lineWidth = baseW;
                    ctx.beginPath();
                    ctx.moveTo(mx, my);
                    ctx.quadraticCurveTo(cx, cy, sx, sy);
                    ctx.strokeStyle = grad;
                    ctx.globalCompositeOperation = 'lighter';
                    ctx.stroke();
                    ctx.restore();
                    ctx.save();
                    let dotR = Math.max(2.5, Math.min(6, baseW * 1.1));
                    let rg = ctx.createRadialGradient(sx, sy, 0, sx, sy, dotR * 3);
                    rg.addColorStop(0, hexToRgba(rawColor, 0.98 * alphaFactor));
                    rg.addColorStop(0.3, hexToRgba(rawColor, 0.45 * alphaFactor));
                    rg.addColorStop(1, hexToRgba(rawColor, 0.0));
                    ctx.globalCompositeOperation = 'lighter';
                    ctx.beginPath();
                    ctx.fillStyle = rg;
                    ctx.arc(sx, sy, dotR * 1.8, 0, Math.PI * 2);
                    ctx.fill();
                    ctx.beginPath();
                    ctx.fillStyle = hexToRgba('#ffffff', 0.85 * alphaFactor);
                    ctx.arc(sx - Math.min(2, dotR * 0.5), sy - Math.min(2, dotR * 0.5), Math.max(0.8, dotR * 0.45), 0, Math.PI * 2);
                    ctx.fill();
                    ctx.restore();
                }
                ctx.restore();
                ctx.globalAlpha = 1;
                ctx.globalCompositeOperation = 'source-over';
            } catch (e) {}
        }

        function loop() {
            if (!state.Tracers) {
                raf = null;
                return;
            }
            try {
                if (typeof unsafeWindow.animateGame === 'function' && unsafeWindow.animateGame !== lastPatched) {
                    const origAG = unsafeWindow.animateGame;
                    lastPatched = unsafeWindow.animateGame = function() {
                        const res = origAG.apply(this, arguments);
                        try {
                            draw();
                        } catch (e) {}
                        return res;
                    };
                }
                draw();
            } catch (e) {}
            raf = requestAnimationFrame(loop);
        }
        return {
            start: () => {
                if (!raf) loop();
            },
            stop: () => {
                if (raf) {
                    cancelAnimationFrame(raf);
                    raf = null;
                }
            }
        };
    }

    function makeESP() {
        let ctx = null,
            canvas = null,
            raf = null,
            prevPred = {};
        const MAX_TARGETS = 12,
            SMOOTH = 0.22,
            LEAD_MIN = 0.06,
            LEAD_MAX = 1.0,
            DIST_TO_LEAD = 600;

        function getCanvas() {
            return document.getElementById('myCanvas');
        }

        function safeHas(a, i) {
            return a && typeof a[i] !== 'undefined';
        }

        function hexToRgba(hex, a) {
            if (!hex) return 'rgba(255,255,255,' + a + ')';
            if (hex[0] === '#') hex = hex.slice(1);
            if (hex.length === 3) hex = hex.split('').map(c => c + c).join('');
            let r = parseInt(hex.slice(0, 2), 16);
            let g = parseInt(hex.slice(2, 4), 16);
            let b = parseInt(hex.slice(4, 6), 16);
            return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
        }

        function draw() {
            try {
                if (!state.ESP) return;
                if (typeof players === 'undefined' || typeof players_show_pos === 'undefined') return;
                if (typeof id === 'undefined' || !players || players === -1) return;
                if (!players[id]) return;
                let meNum = players[id].id;
                if (typeof players_show_pos[meNum] === 'undefined') return;
                canvas = canvas || getCanvas();
                if (!canvas) return;
                ctx = ctx || canvas.getContext('2d');
                ctx.save();
                ctx.setTransform(1, 0, 0, 1, 0, 0);
                let ps = (typeof player_scale !== 'undefined' && player_scale !== -1) ? player_scale : 1;
                ctx.scale(ps, ps);
                let offset = (ps - 1) / (2 * ps);
                ctx.translate(-canvas.width * offset, -canvas.height * offset);
                let cam = {
                    x: canvas.width / 2 - players_show_pos[meNum].x,
                    y: canvas.height / 2 - players_show_pos[meNum].y
                };
                let targets = [];
                for (let i = 0; i < players.length; i++) {
                    let p = players[i];
                    if (!p) continue;
                    let pid = p.id;
                    if (pid === meNum) continue;
                    if (!safeHas(players_show_pos, pid)) continue;
                    if (safeHas(players_alpha, pid) && players_alpha[pid] <= 0) continue;
                    let sx = players_show_pos[pid].x + cam.x,
                        sy = players_show_pos[pid].y + cam.y,
                        mx = players_show_pos[meNum].x + cam.x,
                        my = players_show_pos[meNum].y + cam.y;
                    let dx = sx - mx,
                        dy = sy - my,
                        dist = Math.hypot(dx, dy);
                    targets.push({
                        p,
                        dist,
                        px: sx,
                        py: sy
                    });
                }
                targets.sort((a, b) => a.dist - b.dist);
                targets = targets.slice(0, MAX_TARGETS);
                for (let t of targets) {
                    let p = t.p,
                        pid = p.id,
                        dist = t.dist;
                    let ang = (safeHas(players_angle, pid) ? players_angle[pid] : 0) + Math.PI;
                    let speed = safeHas(players_speed, pid) ? players_speed[pid] : 0;
                    let lead = Math.min(LEAD_MAX, Math.max(LEAD_MIN, dist / DIST_TO_LEAD));
                    let lx = players_show_pos[pid].x + Math.cos(ang) * speed * lead;
                    let ly = players_show_pos[pid].y + Math.sin(ang) * speed * lead;
                    if (!prevPred[pid]) prevPred[pid] = {
                        x: lx,
                        y: ly
                    };
                    prevPred[pid].x = prevPred[pid].x * (1 - SMOOTH) + lx * SMOOTH;
                    prevPred[pid].y = prevPred[pid].y * (1 - SMOOTH) + ly * SMOOTH;
                    let px = prevPred[pid].x + cam.x,
                        py = prevPred[pid].y + cam.y;
                    let size = Math.max(8, Math.min(48, (safeHas(players_radius, pid) ? players_radius[pid] : 12) * 0.95));
                    ctx.save();
                    ctx.globalCompositeOperation = 'lighter';
                    ctx.shadowBlur = Math.max(6, size * 1.8);
                    ctx.shadowColor = 'rgba(255,50,50,0.55)';
                    let g = ctx.createLinearGradient(px - size, py - size, px + size, py + size);
                    g.addColorStop(0, hexToRgba('#ff3b3b', 0.98));
                    g.addColorStop(0.6, hexToRgba('#ff6767', 0.42));
                    g.addColorStop(1, hexToRgba('#ff3b3b', 0.06));
                    ctx.fillStyle = g;
                    ctx.strokeStyle = hexToRgba('#ff1a1a', 0.98);
                    ctx.lineWidth = Math.max(1, size * 0.12);
                    ctx.beginPath();
                    ctx.rect(px - size, py - size, size * 2, size * 2);
                    ctx.fill();
                    ctx.stroke();
                    ctx.restore();
                    ctx.save();
                    ctx.beginPath();
                    ctx.globalAlpha = 0.92;
                    ctx.fillStyle = hexToRgba('#ffffff', 0.9);
                    ctx.arc(px - Math.min(3, size * 0.12), py - Math.min(3, size * 0.12), Math.max(1, size * 0.18), 0, Math.PI * 2);
                    ctx.fill();
                    ctx.restore();
                }
                ctx.restore();
                ctx.globalCompositeOperation = 'source-over';
            } catch (e) {}
        }

        function loop() {
            if (!state.ESP) {
                raf = null;
                return;
            }
            try {
                draw();
            } catch (e) {}
            raf = requestAnimationFrame(loop);
        }
        return {
            start: () => {
                if (!raf) loop();
            },
            stop: () => {
                if (raf) {
                    cancelAnimationFrame(raf);
                    raf = null;
                }
            }
        };
    }

    function injectBot() {
        try {
            if (unsafeWindow && unsafeWindow.AutoBot) return;
        } catch (e) {}
        const botSrc = "(" + (function() {
            try {
                var OrigWS = window.WebSocket;
                var sockRef = null;
                var enemyPositionHistory = [];
                var lastLoggedMyRadius = 0;

                function wrapSocket(url, protocols) {
                    var s = protocols ? new OrigWS(url, protocols) : new OrigWS(url);
                    try {
                        if ((url && url.indexOf("limax.io") !== -1) || (url && url.indexOf("127.0.0.1") !== -1)) sockRef = s;
                    } catch (e) {}
                    s.addEventListener("open", function() {
                        try {
                            var initialRadius = (window.players_radius && window.players_radius[window.true_id]) ? window.players_radius[window.true_id] : 25;
                            lastLoggedMyRadius = initialRadius;
                        } catch (e) {}
                    });
                    var origSend = s.send.bind(s);
                    s.send = function(data) {
                        return origSend(data);
                    };
                    s.addEventListener("close", function() {
                        if (sockRef === s) sockRef = null;
                    });
                    return s;
                }
                window.WebSocket = function(url, protocols) {
                    return wrapSocket(url, protocols);
                };
                window.WebSocket.prototype = OrigWS.prototype;
                var enabled = false;
                var loopIv = null;
                var RATE_MS = 16;
                var F_D = 300;
                var F_P = 700;
                var P_F = 2.3;
                var T_C = 10;
                var ltt = 0;
                var PBW = 6;
                var killMode = false;
                var KMS = 300;
                var K_R = 250;
                var KTS = 55;
                var KTSI = 10;
                var S_B = 200;
                var S_R_D = 200;
                var EST = 1777;
                var KCR = 148;
                var KTIM = 195;
                var KRTB = 24;
                var KTBS = 15;
                var KTBD = 13;
                var SER = 27;
                var MTR = 520;
                var MTMD = 380;
                var STW = 2.5;
                var kltp = 0;
                var DRIK_XD = Date.now();
                var leva = 0;

                function getMyPos() {
                    try {
                        if (typeof window.true_id === 'undefined' || window.true_id === -1) return null;
                        return (window.players_show_pos && window.players_show_pos[window.true_id]) ? window.players_show_pos[window.true_id] : null;
                    } catch (e) {
                        return null;
                    }
                }

                function getMyScore() {
                    try {
                        if (typeof window.id !== 'undefined' && window.players && window.players[window.id] && window.players[window.id].id === window.true_id) return window.players[window.id].score || 0;
                        if (window.players && Array.isArray(window.players)) {
                            for (var i = 0; i < window.players.length; i++) {
                                var p = window.players[i];
                                if (p && p.id === window.true_id) return p.score || 0;
                            }
                        }
                        return (typeof window.score !== 'undefined') ? window.score : 0;
                    } catch (e) {
                        return 0;
                    }
                }

                function getMyRadius() {
                    return (window.players_radius && window.players_radius[window.true_id]) ? window.players_radius[window.true_id] : 25;
                }

                function getPlayerRadius(pid) {
                    return (window.players_radius && window.players_radius[pid]) ? window.players_radius[pid] : 25;
                }

                function gatherTraps() {
                    var traps = [];
                    try {
                        var pt = window.players_trap || window.trap_map || [];
                        if (Array.isArray(pt)) {
                            for (var pid = 0; pid < pt.length; pid++) {
                                var arr = pt[pid];
                                if (!arr) continue;
                                for (var ti = 0; ti < arr.length; ti++) {
                                    var t = arr[ti];
                                    if (!t) continue;
                                    var tx = (typeof t.x !== 'undefined') ? t.x : ((typeof t.rx !== 'undefined') ? t.rx : 0);
                                    var ty = (typeof t.y !== 'undefined') ? t.y : ((typeof t.ry !== 'undefined') ? t.ry : 0);
                                    var tr = (typeof t.radius !== 'undefined') ? t.radius : ((typeof t.r !== 'undefined') ? t.r : (t.instRadius || 0));
                                    traps.push({
                                        x: tx,
                                        y: ty,
                                        r: tr,
                                        owner: pid,
                                        lifetime: (t.lifetime || 0)
                                    });
                                }
                            }
                        } else if (typeof pt === 'object') {
                            for (var k in pt) {
                                if (!pt.hasOwnProperty(k)) continue;
                                var list = pt[k];
                                if (!list) continue;
                                for (var j = 0; j < list.length; j++) {
                                    var t = list[j];
                                    if (!t) continue;
                                    var tx = (typeof t.x !== 'undefined') ? t.x : ((typeof t.rx !== 'undefined') ? t.rx : 0);
                                    var ty = (typeof t.y !== 'undefined') ? t.y : ((typeof t.ry !== 'undefined') ? t.ry : 0);
                                    var tr = (typeof t.radius !== 'undefined') ? t.radius : ((typeof t.r !== 'undefined') ? t.r : 0);
                                    traps.push({
                                        x: tx,
                                        y: ty,
                                        r: tr,
                                        owner: k,
                                        lifetime: (t.lifetime || 0)
                                    });
                                }
                            }
                        }
                    } catch (e) {}
                    return traps;
                }

                function distance(x1, y1, x2, y2) {
                    var dx = x1 - x2,
                        dy = y1 - y2;
                    return Math.sqrt(dx * dx + dy * dy);
                }

                function PJP(px, py, x1, y1, x2, y2) {
                    var Cx = x2 - x1,
                        Cy = y2 - y1;
                    var len_sq = Cx * Cx + Cy * Cy;
                    if (len_sq === 0) return 0;
                    return ((px - x1) * Cx + (py - y1) * Cy) / len_sq;
                }

                function PLD(px, py, x1, y1, x2, y2) {
                    var A = px - x1,
                        B = py - y1,
                        C = x2 - x1,
                        D = y2 - y1;
                    var dot = A * C + B * D;
                    var len_sq = C * C + D * D;
                    var param = -1;
                    if (len_sq !== 0) param = dot / len_sq;
                    var xx, yy;
                    if (param < 0) {
                        xx = x1;
                        yy = y1;
                    } else if (param > 1) {
                        xx = x2;
                        yy = y2;
                    } else {
                        xx = x1 + param * C;
                        yy = y1 + param * D;
                    }
                    var dx = px - xx,
                        dy = py - yy;
                    return Math.sqrt(dx * dx + dy * dy);
                }

                function TNP(traps, x, y, buf) {
                    buf = buf || 0;
                    for (var i = 0; i < traps.length; i++) {
                        var t = traps[i];
                        if (distance(t.x, t.y, x, y) <= (t.r || 0) + buf) return true;
                    }
                    return false;
                }

                function PIT(traps, x1, y1, x2, y2, excludeOwner) {
                    for (var i = 0; i < traps.length; i++) {
                        var t = traps[i];
                        if (typeof excludeOwner !== 'undefined' && t.owner == excludeOwner) continue;
                        var extra = (typeof window.true_id !== 'undefined' && t.owner != window.true_id) ? 30 : 0;
                        var d = PLD(t.x, t.y, x1, y1, x2, y2);
                        if (d <= (t.r || 0) + 14 + extra) return true;
                    }
                    return false;
                }

                function PlayerAndID() {
                    try {
                        var me = getMyPos();
                        if (!me || !window.players_show_pos || !window.players) return null;
                        var bestD = Infinity;
                        var bestId = null;
                        for (var i = 0; i < window.players.length; i++) {
                            var p = window.players[i];
                            if (!p || p.id === window.true_id) continue;
                            var pos = window.players_show_pos[p.id];
                            if (!pos) continue;
                            var dx = pos.x - me.x,
                                dy = pos.y - me.y,
                                d2 = dx * dx + dy * dy;
                            if (d2 < bestD) {
                                bestD = d2;
                                bestId = p.id;
                            }
                        }
                        return bestId === null ? null : {
                            id: bestId,
                            d2: bestD,
                            dist: Math.sqrt(bestD)
                        };
                    } catch (e) {
                        return null;
                    }
                }

                function NPI() {
                    try {
                        var best = PlayerAndID();
                        if (!best) return null;
                        var p = null;
                        for (var i = 0; i < window.players.length; i++) {
                            if (window.players[i] && window.players[i].id === best.id) {
                                p = window.players[i];
                                break;
                            }
                        }
                        var pos = (window.players_show_pos && window.players_show_pos[best.id]) ? window.players_show_pos[best.id] : null;
                        return {
                            id: best.id,
                            dist: best.dist,
                            player: p,
                            pos: pos
                        };
                    } catch (e) {
                        return null;
                    }
                }

                function GNT(me, excludeId, maxCount) {
                    var threats = [];
                    try {
                        for (var i = 0; i < window.players.length; i++) {
                            var p = window.players[i];
                            if (!p || p.id === window.true_id || p.id === excludeId) continue;
                            var pos = window.players_show_pos ? window.players_show_pos[p.id] : null;
                            if (!pos) continue;
                            var d = distance(me.x, me.y, pos.x, pos.y);
                            if (d > 520) continue;
                            var r = (window.players_radius && window.players_radius[p.id]) ? window.players_radius[p.id] : 25;
                            var score = p.score || 0;
                            var pvx = p.vx || 0;
                            var pvy = p.vy || 0;
                            var speed = Math.sqrt(pvx * pvx + pvy * pvy);
                            threats.push({
                                id: p.id,
                                pos: pos,
                                dist: d,
                                radius: r,
                                score: score,
                                vx: pvx,
                                vy: pvy,
                                speed: speed
                            });
                        }
                        threats.sort(function(a, b) {
                            return a.dist - b.dist;
                        });
                        return threats.slice(0, maxCount || 4);
                    } catch (e) {
                        return [];
                    }
                }

                function CMR(me, threats) {
                    var rx = 0,
                        ry = 0;
                    for (var i = 0; i < threats.length; i++) {
                        var t = threats[i];
                        var dx = me.x - t.pos.x;
                        var dy = me.y - t.pos.y;
                        var d = Math.max(t.dist - t.radius - getMyRadius(), 40);
                        var w = (t.score / 200 + t.radius / 30 + (380 - t.dist) * 0.02) / (d * d);
                        if (t.speed > 25) w *= 1.6;
                        rx += dx * w;
                        ry += dy * w;
                    }
                    return normalize(rx, ry);
                }

                function sendControl(angle, trapFlag) {
                    try {
                        if (!sockRef && window.socket) sockRef = window.socket;
                        if (!sockRef) return;
                        if (!isFinite(angle)) angle = 0;
                        var t = trapFlag ? 1 : 0;
                        sockRef.send("[" + 0 + "," + angle + "," + t + "]");
                    } catch (e) {}
                }

                function normalize(x, y) {
                    var L = Math.sqrt(x * x + y * y);
                    if (L === 0) return {
                        x: 0,
                        y: 0
                    };
                    return {
                        x: x / L,
                        y: y / L
                    };
                }

                function safeApproach(targetX, targetY, me, traps, excludeOwner) {
                    var angle = Math.atan2(targetY - me.y, targetX - me.x) + Math.PI;
                    if (!PIT(traps, me.x, me.y, targetX, targetY, excludeOwner)) return {
                        x: targetX,
                        y: targetY,
                        angle: angle
                    };
                    var best = null;
                    var bestScore = Infinity;
                    var steps = 36;
                    var dists = [40, 80, 140, 220];
                    for (var s = 0; s < dists.length; s++) {
                        var distOffset = dists[s];
                        for (var i = 0; i < steps; i++) {
                            var a = -Math.PI + (i / steps) * (2 * Math.PI);
                            var ca = Math.cos(a),
                                sa = Math.sin(a);
                            var nx = targetX + ca * distOffset,
                                ny = targetY + sa * distOffset;
                            var penalty = 0;
                            if (PIT(traps, me.x, me.y, nx, ny, excludeOwner)) penalty += 1000000;
                            for (var ti = 0; ti < traps.length; ti++) {
                                var t = traps[ti];
                                if (typeof excludeOwner !== 'undefined' && t.owner == excludeOwner) continue;
                                var td = distance(nx, ny, t.x, t.y) - (t.r || 0);
                                if (td < 0) penalty += (15000 + Math.abs(td) * 80);
                                else if (td < 120) penalty += (1200 - td * 6);
                            }
                            var d = distance(me.x, me.y, nx, ny);
                            var score = d + penalty + distOffset * 0.2;
                            if (score < bestScore) {
                                bestScore = score;
                                best = {
                                    x: nx,
                                    y: ny,
                                    angle: Math.atan2(ny - me.y, nx - me.x) + Math.PI
                                };
                            }
                        }
                    }
                    if (best) return best;
                    return {
                        x: targetX,
                        y: targetY,
                        angle: angle
                    };
                }

                function GCT(me, enemyPos, enemyR, myR, desiredBase) {
                    var dx = me.x - enemyPos.x;
                    var dy = me.y - enemyPos.y;
                    var dist = Math.sqrt(dx * dx + dy * dy) || 1;
                    var ux = dx / dist;
                    var uy = dy / dist;
                    var px = -uy;
                    var py = ux;
                    var extra = enemyR * 0.6;
                    var targetX = enemyPos.x + ux * (desiredBase + extra) + px * 85;
                    var targetY = enemyPos.y + uy * (desiredBase + extra) + py * 85;
                    return {
                        x: targetX,
                        y: targetY
                    };
                }

                function UEPH(info) {
                    if (!info || !info.pos) return;
                    var now = Date.now();
                    enemyPositionHistory.push({
                        ts: now,
                        x: info.pos.x,
                        y: info.pos.y
                    });
                    while (enemyPositionHistory.length > 0 && now - enemyPositionHistory[0].ts > 3000) enemyPositionHistory.shift();
                }

                function EMS(info) {
                    UEPH(info);
                    var now = Date.now();
                    if (enemyPositionHistory.length < 5) return false;
                    var relevant = enemyPositionHistory.filter(function(p) {
                        return now - p.ts <= EST;
                    });
                    if (relevant.length < 4) return false;
                    var first = relevant[0];
                    var last = relevant[relevant.length - 1];
                    var totalDx = last.x - first.x;
                    var totalDy = last.y - first.y;
                    var totalDist = Math.sqrt(totalDx * totalDx + totalDy * totalDy);
                    if (totalDist < 35) return false;
                    var mainAngle = Math.atan2(totalDy, totalDx);
                    var maxDeviation = 0;
                    for (var i = 1; i < relevant.length; i++) {
                        var prev = relevant[i - 1];
                        var curr = relevant[i];
                        var segDx = curr.x - prev.x;
                        var segDy = curr.y - prev.y;
                        var segDist = Math.sqrt(segDx * segDx + segDy * segDy);
                        if (segDist < 6) continue;
                        var segAngle = Math.atan2(segDy, segDx);
                        var delta = Math.abs(segAngle - mainAngle);
                        if (delta > Math.PI) delta = 2 * Math.PI - delta;
                        if (delta > maxDeviation) maxDeviation = delta;
                    }
                    return maxDeviation < 0.25;
                }

                function PKB() {
                    var me = getMyPos();
                    if (!me) return false;
                    var myScore = getMyScore();
                    if (myScore <= KMS) return false;
                    var info = NPI();
                    if (!info || !info.pos || !info.player) return false;
                    var enemyScore = info.player.score || 0;
                    if (enemyScore < 100) return false;
                    var myR = getMyRadius();
                    var enemyR = getPlayerRadius(info.id);
                    var traps = gatherTraps();
                    if (EEE(me, traps)) return true;
                    var currentRadius = myR;
                    lastLoggedMyRadius = currentRadius;
                    var threats = GNT(me, info.id, 4);
                    var HST = false;
                    var secondaryDir = {
                        x: 0,
                        y: 0
                    };
                    if (threats.length > 0) {
                        var rep = CMR(me, threats);
                        if (rep.x !== 0 || rep.y !== 0) {
                            HST = true;
                            secondaryDir = rep;
                        }
                    }
                    var IST = EMS(info);
                    var desiredCircleR = myR + enemyR + KCR + (enemyR * 0.55);
                    var pvx = info.player.vx || 0;
                    var pvy = info.player.vy || 0;
                    var predX = info.pos.x + pvx * P_F * 1.75;
                    var predY = info.pos.y + pvy * P_F * 1.75;
                    var distToPred = distance(me.x, me.y, predX, predY);
                    var now = Date.now();
                    var shouldRam = IST || (enemyR < SER);
                    if (shouldRam) {
                        var ramAngle = Math.atan2(predY - me.y, predX - me.x) + Math.PI;
                        if (now - kltp > 90) {
                            for (var i = 0; i < KRTB; i++) {
                                (function(a, d) {
                                    setTimeout(function() {
                                        sendControl(a, 1);
                                    }, d);
                                })(ramAngle, i * KTBD);
                            }
                            kltp = now;
                            setTimeout(function() {
                                sendControl(ramAngle, 0);
                            }, KRTB * KTBD + 55);
                        } else {
                            sendControl(ramAngle, 0);
                        }
                        return true;
                    }
                    if (HST && threats.length >= 1) {
                        var threatAngle = Math.atan2(secondaryDir.y, secondaryDir.x) + Math.PI;
                        sendControl(threatAngle, 0);
                        return true;
                    }
                    var currDist = distance(me.x, me.y, info.pos.x, info.pos.y);
                    if (currDist < desiredCircleR - 48) {
                        var pushAngle = Math.atan2(me.y - info.pos.y, me.x - info.pos.x) + Math.PI;
                        sendControl(pushAngle, 0);
                        return true;
                    }
                    var target = GCT(me, info.pos, enemyR, myR, desiredCircleR);
                    var safe = safeApproach(target.x, target.y, me, traps, info.id);
                    var moveAngle = safe ? safe.angle : Math.atan2(target.y - me.y, target.x - me.x) + Math.PI;
                    if (now - kltp > KTIM) {
                        var trapAngle = moveAngle;
                        for (var k = 0; k < KTBS; k++) {
                            (function(a, d) {
                                setTimeout(function() {
                                    sendControl(a, 1);
                                }, d);
                            })(trapAngle, k * KTBD);
                        }
                        kltp = now;
                        setTimeout(function() {
                            sendControl(moveAngle, 0);
                        }, KTBS * KTBD + 65);
                    } else {
                        sendControl(moveAngle, 0);
                    }
                    return true;
                }

                function EEE(me, traps) {
                    var rep = RVR(me, traps);
                    if (!rep || rep.minDanger > 160) return false;
                    var v = normalize(rep.rx, rep.ry);
                    if (v.x === 0 && v.y === 0) return false;
                    var push = 920;
                    var targetX = me.x + v.x * push;
                    var targetY = me.y + v.y * push;
                    var angle = Math.atan2(targetY - me.y, targetX - me.x) + Math.PI;
                    sendControl(angle, 0);
                    for (var k = 1; k <= 3; k++) {
                        (function(a, d) {
                            setTimeout(function() {
                                sendControl(a, 0);
                            }, d);
                        })(angle, k * 40);
                    }
                    return true;
                }

                function RVR(me, traps) {
                    var rx = 0,
                        ry = 0,
                        minDanger = Infinity;
                    for (var i = 0; i < traps.length; i++) {
                        var t = traps[i];
                        if (typeof window.true_id !== 'undefined' && t.owner == window.true_id) continue;
                        var dcenter = distance(me.x, me.y, t.x, t.y);
                        var d = dcenter - (t.r || 0);
                        if (d < minDanger) minDanger = d;
                        var dd = Math.max(d, 0.1);
                        var w = 1 / (dd * dd);
                        rx += (me.x - t.x) * w;
                        ry += (me.y - t.y) * w;
                    }
                    return {
                        rx: rx,
                        ry: ry,
                        minDanger: minDanger
                    };
                }

                function FCBS(traps) {
                    try {
                        var update_map = window.update_bonus_map || window.player_update_bonus_map || [];
                        var bonus_map = window.bonus_map || window.bonusMap || null;
                        var player_bonus_map = window.player_bonus_map || window.playerBonusMap || window.player_bonus_map;
                        var me = getMyPos();
                        if (!me) return null;
                        var best = null;
                        var bestScore = Infinity;
                        for (var i = 0; i < update_map.length; i++) {
                            var idb = update_map[i];
                            var bx = 0,
                                by = 0,
                                isPlayerBonus = false;
                            if (typeof idb === 'number' && bonus_map && typeof bonus_map[idb] !== 'undefined') {
                                var b = bonus_map[idb];
                                if (!b) continue;
                                bx = (typeof b.rx !== 'undefined') ? b.rx : ((typeof b.x !== 'undefined') ? b.x : 0);
                                by = (typeof b.ry !== 'undefined') ? b.ry : ((typeof b.y !== 'undefined') ? b.y : 0);
                            } else {
                                isPlayerBonus = true;
                                try {
                                    var BIG = (typeof window.BONUS_DEAD_KEY !== 'undefined') ? window.BONUS_DEAD_KEY : 1000000;
                                    if (BIG && idb >= BIG) {
                                        var j = Math.floor(idb / BIG) - 1;
                                        var k = idb % BIG;
                                        var pb = (player_bonus_map && player_bonus_map[j]) ? player_bonus_map[j][k] : null;
                                        if (!pb) continue;
                                        bx = (typeof pb.rx !== 'undefined') ? pb.rx : ((typeof pb.x !== 'undefined') ? pb.x : 0);
                                        by = (typeof pb.ry !== 'undefined') ? pb.ry : ((typeof pb.y !== 'undefined') ? pb.y : 0);
                                    } else continue;
                                } catch (e) {
                                    continue;
                                }
                            }
                            var dx = bx - me.x,
                                dy = by - me.y;
                            var d = Math.sqrt(dx * dx + dy * dy);
                            if (isPlayerBonus && TNP(traps, bx, by, PBW)) continue;
                            var penalty = 0;
                            if (PIT(traps, me.x, me.y, bx, by)) penalty += 1000000;
                            for (var tI = 0; tI < traps.length; tI++) {
                                var t = traps[tI];
                                var td = distance(bx, by, t.x, t.y) - (t.r || 0);
                                if (td < 0) penalty += (10000 + Math.abs(td) * 50);
                                else if (td < 60) penalty += (600 - td * 5);
                            }
                            var score = d + penalty;
                            if (score < bestScore) {
                                bestScore = score;
                                best = {
                                    x: bx,
                                    y: by,
                                    isPlayerBonus: isPlayerBonus,
                                    d: d
                                };
                            }
                        }
                        return best;
                    } catch (e) {
                        return null;
                    }
                }

                function botTick() {
                    try {
                        if (!sockRef && window.socket) sockRef = window.socket;
                        if (!sockRef) return;
                        if (typeof window.game_is_show !== 'undefined' && !window.game_is_show) return;
                        var me = getMyPos();
                        if (!me) return;
                        var traps = gatherTraps();
                        if (EEE(me, traps)) return;
                        if (killMode) {
                            if (PKB()) return;
                        }
                        var nearestP = PlayerAndID();
                        var isFlee = nearestP && nearestP.dist < F_D;
                        if (isFlee) {
                            var pPos = window.players_show_pos[nearestP.id];
                            if (!pPos) return;
                            var pvx = 0,
                                pvy = 0;
                            try {
                                for (var i = 0; i < window.players.length; i++) {
                                    var pe = window.players[i];
                                    if (pe && pe.id === nearestP.id) {
                                        if (typeof pe.vx !== 'undefined') pvx = pe.vx;
                                        if (typeof pe.vy !== 'undefined') pvy = pe.vy;
                                        break;
                                    }
                                }
                            } catch (e) {}
                            var predX = pPos.x + pvx * P_F;
                            var predY = pPos.y + pvy * P_F;
                            var dx = me.x - predX,
                                dy = me.y - predY;
                            var dist = Math.sqrt(dx * dx + dy * dy) || 1;
                            var ux = dx / dist,
                                uy = dy / dist;
                            var push = F_P + Math.max(0, (F_D - dist)) * 2;
                            var targetX = me.x + ux * push,
                                targetY = me.y + uy * push;
                            if (PIT(traps, me.x, me.y, targetX, targetY)) {
                                var rx = 0,
                                    ry = 0,
                                    totalw = 0;
                                for (var ti = 0; ti < traps.length; ti++) {
                                    var t = traps[ti];
                                    var td = distance(me.x, me.y, t.x, t.y) - Math.max(1, t.r || 0);
                                    if (td <= 0) td = 0.1;
                                    var w = 1 / (td * td);
                                    rx += (me.x - t.x) * w;
                                    ry += (me.y - t.y) * w;
                                    totalw += w;
                                }
                                if (totalw > 0) {
                                    rx /= totalw;
                                    ry /= totalw;
                                    var rlen = Math.sqrt(rx * rx + ry * ry) || 1;
                                    rx /= rlen;
                                    ry /= rlen;
                                    targetX = me.x + rx * push;
                                    targetY = me.y + ry * push;
                                }
                            }
                            var angle = Math.atan2(targetY - me.y, targetX - me.x) + Math.PI;
                            var now = Date.now();
                            var wantTrap = (getMyScore() > 1000 && (now - ltt) > T_C);
                            if (wantTrap) {
                                ltt = now;
                                sendControl(angle, 1);
                                setTimeout(function() {
                                    sendControl(angle, 0);
                                }, 80);
                            } else sendControl(angle, 0);
                            return;
                        }
                        var target = FCBS(traps);
                        if (target) {
                            var dx = target.x - me.x,
                                dy = target.y - me.y;
                            var angle = Math.atan2(dy, dx) + Math.PI;
                            sendControl(angle, 0);
                            return;
                        }
                        var jitter = (Math.random() - 0.5) * 0.6;
                        var base = (typeof window.mouseangle !== 'undefined') ? window.mouseangle : 0;
                        sendControl(base + jitter, 0);
                    } catch (e) {}
                }

                function startBot() {
                    if (loopIv) clearInterval(loopIv);
                    loopIv = setInterval(botTick, RATE_MS);
                }

                function stopBot() {
                    if (loopIv) {
                        clearInterval(loopIv);
                        loopIv = null;
                    }
                }
                window.AutoBot = {
                    start: function() {
                        startBot();
                    },
                    stop: function() {
                        stopBot();
                    },
                    setKill: function(v) {
                        killMode = !!v;
                    },
                    isRunning: function() {
                        return !!loopIv;
                    }
                };
                try {
                    if (window.socket) sockRef = window.socket;
                } catch (e) {}
                return {};
            } catch (e) {}
        }).toString() + ")();";
        try {
            const s = document.createElement('script');
            s.textContent = botSrc;
            (document.documentElement).appendChild(s);
            s.parentNode.removeChild(s);
        } catch (e) {}
    }

    try {
        injectBot();
    } catch (e) {}

    function startHUD() {
        if (hudRunner) return;
        const W = unsafeWindow;
        const css = `
    #HUD {
      position: fixed;
      top: 8px;
      left: 50%;
      transform: translateX(-50%);
      z-index: 99999;
      padding: 8px 14px;
      font-family: Arial, Helvetica, sans-serif;
      font-size: 13px;
      color: #ffffff;
      background: rgba(6,10,20,0.55);
      border-radius: 8px;
      display: none;
      white-space: nowrap;
      pointer-events: none;
      user-select: none;
    }
    #HUD.show { display: block; }
    #HUD.hidden { display: none; }
    #HUD .item { margin: 0 8px; display: inline-block; }
    #HUD .ping-good { color: #4ade80; }
    #HUD .ping-mid  { color: #facc15; }
    #HUD .ping-bad  { color: #f87171; }
    `;
        if (typeof GM_addStyle === 'function') GM_addStyle(css);
        if (document.getElementById('HUD')) return;
        const hud = document.createElement('div');
        hud.id = 'HUD';
        const spanFPS = document.createElement('span');
        spanFPS.className = 'item';
        const spanTime = document.createElement('span');
        spanTime.className = 'item';
        const spanPlayers = document.createElement('span');
        spanPlayers.className = 'item';
        const spanPing = document.createElement('span');
        spanPing.className = 'item';
        hud.appendChild(spanFPS);
        hud.appendChild(spanTime);
        hud.appendChild(spanPlayers);
        hud.appendChild(spanPing);
        document.body.appendChild(hud);
        let lastGameShow = Boolean(W.game_is_show);
        let rafLast = performance.now();
        let rafFPS = 0;
        let lastUpdate = 0;
        const Interval = 0xC7;

        function pad(v) {
            return v.toString().padStart(2, '0');
        }

        function formatTime(ms) {
            if (!ms || ms <= 0) return '00:00:00';
            const s = Math.floor(ms / 1000);
            return `${pad(Math.floor(s / 3600))}:${pad(Math.floor((s % 3600) / 60))}:${pad(s % 60)}`;
        }

        function readFPS() {
            try {
                if (W.fps && typeof W.fps.fps === 'number') return Math.round(W.fps.fps);
            } catch (e) {}
            return null;
        }

        function countPlayers() {
            try {
                const el = document.getElementById('perso_information');
                if (el) {
                    const m = el.textContent.match(/out of (\d+)/);
                    if (m) return parseInt(m[1], 10);
                }
            } catch (e) {}
            return 0;
        }

        function pingClass(ms) {
            if (ms < 0) return '';
            if (ms < 0x50) return 'ping-good';
            if (ms < 0x96) return 'ping-mid';
            return 'ping-bad';
        }

        function updateLogic(now) {
            const gameShow = Boolean(W.game_is_show);
            if (!gameShow && lastGameShow) {
                _pingMs = -1;
                _pingPending = false;
            }
            lastGameShow = gameShow;
            if (!state.HUD || !gameShow) {
                hud.className = 'hidden';
                return;
            }
            hud.className = 'show';
            let fpsVal = readFPS();
            if (fpsVal === null) fpsVal = rafFPS || 0;
            const timeVal = _hudSessionStart ? formatTime(Date.now() - _hudSessionStart) : '00:00:00';
            const playersVal = countPlayers();
            const pc = pingClass(_pingMs);
            const ping = _pingMs >= 0 ? _pingMs : '-';
            spanFPS.textContent = `FPS: ${fpsVal}`;
            spanTime.textContent = `Time: ${timeVal}`;
            spanPlayers.textContent = `Players: ${playersVal}`;
            spanPing.innerHTML = `Ping: <span class="${pc}">${ping}${_pingMs >= 0 ? 'ms' : ''}</span>`;
        }

        function rafLoop(now) {
            const dt = now - rafLast;
            rafLast = now;
            if (dt > 0) rafFPS = Math.round(1000 / dt);
            if (now - lastUpdate >= Interval) {
                lastUpdate = now;
                updateLogic(now);
            }
            requestAnimationFrame(rafLoop);
        }
        requestAnimationFrame(rafLoop);
        hudRunner = {
            stop: () => {
                try {
                    hud.remove();
                } catch (e) {}
                hudRunner = null;
            }
        };
    }

    function stopHUD() {
        if (!hudRunner && document.getElementById('HUD')) {
            try {
                document.getElementById('HUD').remove();
            } catch (e) {}
            hudRunner = null;
        } else if (hudRunner) {
            try {
                document.getElementById('HUD') && document.getElementById('HUD').remove();
            } catch (e) {}
            hudRunner = null;
        }
    }

    function applyFeature(key, on) {
        try {
            if (key === 'AdBlocker') {
                if (on) adStart();
                else adStop();
            } else if (key === 'BetterLeaderBoard') {
                if (on) lbStart();
                else lbStop();
            } else if (key === 'Tracers') {
                if (on) {
                    trRunner = trRunner || makeTracers();
                    trRunner.start();
                } else {
                    if (trRunner) trRunner.stop();
                }
            } else if (key === 'ESP') {
                if (on) {
                    espRunner = espRunner || makeESP();
                    espRunner.start();
                } else {
                    if (espRunner) espRunner.stop();
                }
            } else if (key === 'SkipAnimations') {
                if (on) startSkipAnimations();
                else stopSkipAnimations();
            } else if (key === 'AutoReconnect') {} else if (key === 'AutoPlay') {
                try {
                    const api = unsafeWindow && unsafeWindow.AutoBot;
                    if (api && typeof api.start === 'function') {
                        if (on) {
                            api.setKill(!!state.AutoPlayKillMode);
                            api.start();
                        } else {
                            api.stop();
                        }
                    } else {
                        injectBot();
                        setTimeout(() => {
                            try {
                                const api2 = unsafeWindow && unsafeWindow.AutoBot;
                                if (api2 && on) {
                                    api2.setKill(!!state.AutoPlayKillMode);
                                    api2.start();
                                } else if (api2 && !on) {
                                    api2.stop();
                                }
                            } catch (e) {}
                        }, 0x12c);
                    }
                } catch (e) {}
            } else if (key === 'HUD') {
                if (on) startHUD();
                else stopHUD();
            } else if (key === 'Zoom') {
                if (on) {
                    _bindZoomWheel();
                    _applyZoomCss();
                } else {
                    zoomValue = 1.0;
                    _applyZoomCss();
                }
            } else if (key === 'SkinHack') {
                if (on) startSkinHack();
                else stopSkinHack();
            }
        } catch (e) {}
    }

    function applyAll() {
        Object.keys(defaults).forEach(k => {
            if (k === 'visible' || k === 'ToggleKey' || k === 'Theme') return;
            applyFeature(k, !!state[k]);
        });
    }

    function escapeHtml(s) {
        return String(s || '').replace(/[&<>"']/g, function(m) {
            return ({
                '&': '&amp;',
                '<': '&lt;',
                '>': '&gt;',
                '"': '&quot;',
                "'": '&#39;'
            })[m];
        });
    }

    function render() {
        root.classList.toggle('theme-white', state.Theme === 'white');
        root.innerHTML = `
      <div class="lt-header">
        <div class="lt-title">
          <div class="lt-logo">Limax Client</div>
          <div>
            <div class="lt-h1">Limax Client</div>
            <div class="lt-sub">The game is better with this script :D</div>
          </div>
        </div>
        <div style="display:flex;gap:10px;align-items:center"></div>
      </div>

      <div class="lt-grid">
        <div class="lt-card" data-feature="AdBlocker">
          <div class="title-row">
            <h3>AdBlocker</h3>
            <div class="lt-switch ${state.AdBlocker ? 'on' : ''}" data-switch="AdBlocker" role="switch" aria-checked="${!!state.AdBlocker}"><div class="knob"></div></div>
          </div>
          <p class="lt-small">Removes common ads/overlays and forces play handlers to skip banners</p>
        </div>

        <div class="lt-card" data-feature="BetterLeaderBoard">
          <div class="title-row">
            <h3>Better LeaderBoard</h3>
            <div class="lt-switch ${state.BetterLeaderBoard ? 'on' : ''}" data-switch="BetterLeaderBoard" role="switch" aria-checked="${!!state.BetterLeaderBoard}"><div class="knob"></div></div>
          </div>
          <p class="lt-small">Collects player scores and redraws leaderboard with accurate sorting and rank</p>
        </div>

        <div class="lt-card" data-feature="AutoPlay">
          <div class="title-row">
            <h3>Auto Play</h3>
            <div class="lt-switch ${state.AutoPlay ? 'on' : ''}" data-switch="AutoPlay" role="switch" aria-checked="${!!state.AutoPlay}"><div class="knob"></div></div>
          </div>
          <p class="lt-small">Auto-gather && basic combat routines</p>
          <div class="lt-controls" data-controls-for="AutoPlay" style="display:${state.AutoPlay ? 'flex' : 'none'};flex-direction:column;gap:6px">
            <label class="lt-small" style="display:flex;align-items:center;gap:8px">
              <input type="checkbox" class="lt-input-checkbox" id="autoPlayKill" ${state.AutoPlayKillMode ? 'checked' : ''}>
              <span>Kill Mode</span>
            </label>
            <label class="lt-small" style="display:flex;align-items:center;gap:8px">
              <input type="checkbox" class="lt-input-checkbox" id="autoReconnect" ${state.AutoReconnect ? 'checked' : ''}>
              <span>Auto-reconnect</span>
            </label>
          </div>
        </div>

        <div class="lt-card" data-feature="Tracers">
          <div class="title-row">
            <h3>Tracers</h3>
            <div class="lt-switch ${state.Tracers ? 'on' : ''}" data-switch="Tracers" role="switch" aria-checked="${!!state.Tracers}"><div class="knob"></div></div>
          </div>
          <p class="lt-small">Draws smooth curved lines from you to players for easier tracking</p>
        </div>

        <div class="lt-card" data-feature="ESP">
          <div class="title-row">
            <h3>ESP</h3>
            <div class="lt-switch ${state.ESP ? 'on' : ''}" data-switch="ESP" role="switch" aria-checked="${!!state.ESP}"><div class="knob"></div></div>
          </div>
          <p class="lt-small">Predictive lead boxes and visual markers for nearby players</p>
        </div>

        <div class="lt-card" data-feature="SkipAnimations">
          <div class="title-row">
            <h3>Skip Animations</h3>
            <div class="lt-switch ${state.SkipAnimations ? 'on' : ''}" data-switch="SkipAnimations" role="switch" aria-checked="${!!state.SkipAnimations}"><div class="knob"></div></div>
          </div>
          <p class="lt-small">Skips death and server join animations instantly</p>
        </div>

        <div class="lt-card" data-feature="HUD">
          <div class="title-row">
            <h3>HUD</h3>
            <div class="lt-switch ${state.HUD ? 'on' : ''}" data-switch="HUD" role="switch" aria-checked="${!!state.HUD}"><div class="knob"></div></div>
          </div>
          <p class="lt-small">HUD showing FPS, in-game session time, and active players count</p>
        </div>

        <div class="lt-card" data-feature="ClickGUI">
          <div class="title-row">
            <h3>ClickGUI</h3>
            <div class="lt-switch on" role="switch" aria-checked="true" style="opacity:0.6;cursor:default;"><div class="knob"></div></div>
          </div>
          <p class="lt-small">Menu controls: keybind and theme</p>
          <div class="lt-controls" data-controls-for="ClickGUI" style="display:flex;flex-direction:column;gap:8px;margin-top:8px">
            <div style="display:flex;gap:8px;align-items:center">
              <button class="lt-btn" id="changeKeyBtn">Change Key</button>
              <div class="lt-small" id="currentKeyDisplay">${FKD(state.ToggleKey)} - toggle</div>
            </div>
            <div style="display:flex;gap:8px;align-items:center">
              <button class="lt-btn" id="themeDarkBtn">Dark</button>
              <button class="lt-btn" id="themeWhiteBtn">White</button>
              <div class="lt-small">Current: ${escapeHtml(capitalize(state.Theme || 'dark'))}</div>
            </div>
          </div>
        </div>

        <div class="lt-card" data-feature="Zoom">
          <div class="title-row">
            <h3>Zoom</h3>
            <div class="lt-switch ${state.Zoom ? 'on' : ''}" data-switch="Zoom" role="switch" aria-checked="${!!state.Zoom}"><div class="knob"></div></div>
          </div>
          <p class="lt-small">Default zoom hack, CTRL+ mouse wheel</p>
          <div class="lt-controls" style="display:${state.Zoom ? 'flex' : 'none'};align-items:center;gap:8px;margin-top:4px">
            <span class="lt-small" id="_zoom_label">zoom: ${zoomValue.toFixed(1)}x</span>
          </div>
        </div>

        <div class="lt-card" data-feature="SkinHack">
          <div class="title-row">
            <h3>SkinHack</h3>
            <div class="lt-switch ${state.SkinHack ? 'on' : ''}" data-switch="SkinHack" role="switch" aria-checked="${!!state.SkinHack}"><div class="knob"></div></div>
          </div>
          <p class="lt-small">Visual skin hack. Select as in the game (arrows)</p>
        </div>

      </div>

      <div class="lt-footer">
        <div></div>
        <div style="display:flex;gap:10px;align-items:center">
          <div class="lt-toggle-key" id="lt-toggle-key">${FKD(state.ToggleKey)} - toggle</div>
          <button class="save" id="lt-close">Close</button>
        </div>
      </div>
    `;
        attachHandlers();
    }

    function FKD(code) {
        if (!code) return 'AltRight';
        return code.replace('Key', '').replace('Digit', '').replace('Arrow', '').replace('Right', 'Right').replace('Left', 'Left');
    }

    function capitalize(s) {
        if (!s) return s;
        return s.charAt(0).toUpperCase() + s.slice(1);
    }

    function attachHandlers() {
        const switches = root.querySelectorAll('[data-switch]');
        switches.forEach(el => {
            const key = el.getAttribute('data-switch');
            if (key === 'ClickGUI') return;
            el.onclick = async function() {
                state[key] = !state[key];
                if (key === 'AutoPlay' && !state.AutoPlay) state.AutoPlayKillMode = false;
                await saveState();
                applyFeature(key, !!state[key]);
                render();
            };
        });

        const autoPlayKill = root.querySelector('#autoPlayKill');
        if (autoPlayKill) {
            autoPlayKill.onchange = async function() {
                state.AutoPlayKillMode = !!this.checked;
                await saveState();
                try {
                    if (unsafeWindow && unsafeWindow.AutoBot) unsafeWindow.AutoBot.setKill(!!state.AutoPlayKillMode);
                } catch (e) {}
                render();
            };
        }

        const autoReconnect = root.querySelector('#autoReconnect');
        if (autoReconnect) {
            autoReconnect.onchange = async function() {
                state.AutoReconnect = !!this.checked;
                await saveState();
                render();
            };
        }

        const closeBtn = root.querySelector('#lt-close');
        closeBtn.onclick = function() {
            toggle(false);
            render();
        };

        const changeKeyBtn = root.querySelector('#changeKeyBtn');
        const currentKeyDisplay = root.querySelector('#currentKeyDisplay');
        const ltToggleKey = root.querySelector('#lt-toggle-key');
        if (changeKeyBtn) {
            changeKeyBtn.onclick = function() {
                startBinding(changeKeyBtn, currentKeyDisplay, ltToggleKey);
            };
        }

        const themeDarkBtn = root.querySelector('#themeDarkBtn');
        const themeWhiteBtn = root.querySelector('#themeWhiteBtn');
        if (themeDarkBtn) {
            themeDarkBtn.onclick = async function() {
                state.Theme = 'dark';
                await saveState();
                render();
            };
        }
        if (themeWhiteBtn) {
            themeWhiteBtn.onclick = async function() {
                state.Theme = 'white';
                await saveState();
                render();
            };
        }

        function startBinding(buttonEl, displayEl, footerEl) {
            buttonEl.textContent = 'Press key...';
            let done = false;

            function finish(ok, code) {
                if (done) return;
                done = true;
                window.removeEventListener('keydown', onKey, true);
                window.removeEventListener('mousedown', onMouse, true);
                buttonEl.textContent = 'Change Key';
                if (ok && code) {
                    const invalid = (code === 'Escape' || code === 'MouseLeft' || code === 'MouseRight');
                    if (invalid) {
                        state.ToggleKey = defaults.ToggleKey;
                    } else {
                        state.ToggleKey = code;
                    }
                } else {
                    state.ToggleKey = defaults.ToggleKey;
                }
                saveState().then(() => {
                    render();
                });
            }

            function onKey(e) {
                e.stopPropagation();
                e.preventDefault();
                const code = e.code || e.key || null;
                if (!code) {
                    finish(false);
                    return;
                }
                if (code === 'Escape') {
                    finish(false);
                    return;
                }
                finish(true, code);
            }

            function onMouse(e) {
                e.stopPropagation();
                e.preventDefault();
                finish(false);
            }
            window.addEventListener('keydown', onKey, true);
            window.addEventListener('mousedown', onMouse, true);
        }
    }

    function toggle(force) {
        const should = typeof force === 'boolean' ? force : !state.visible;
        state.visible = should;
        saveState();
        if (should) root.classList.add('show');
        else root.classList.remove('show');
    }

    async function saveState() {
        try {
            await gmSet(STORAGE_KEY, JSON.stringify(state));
        } catch (e) {}
    }

    document.addEventListener('keydown', function(e) {
        const bind = state.ToggleKey || defaults.ToggleKey;
        if (e.code === bind) {
            e.preventDefault();
            toggle();
            render();
            return;
        }
        if (e.key === 'Escape') {
            toggle(false);
            render();
        }
    }, true);

    render();
    applyAll();

    try {
        if (state.AutoPlay) {
            try {
                if (unsafeWindow && unsafeWindow.AutoBot) {
                    unsafeWindow.AutoBot.setKill(!!state.AutoPlayKillMode);
                    unsafeWindow.AutoBot.start();
                }
            } catch (e) {}
        }
    } catch (e) {}

    if (state.visible) toggle(true);

    window.LimaxClient = {
        getState: () => JSON.parse(JSON.stringify(state)),
        setState: async (ns) => {
            state = Object.assign({}, state, ns);
            await saveState();
            applyAll();
            render();
        },
        gmDelete
    };

})();

// XD

GM_addStyle(`
  #logo {
    position: absolute !important;
    overflow: visible !important;
    background: transparent !important;
    text-align: center !important;
    display: block !important;
    isolation: isolate !important;
  }

  #logo > img#logoi {
    display: none !important;
  }

  #logo::after {
    content: "Limax Client" !important;
    position: absolute !important;
    left: 50% !important;
    top: 50% !important;
    transform: translate(-50%, -50%) !important;
    white-space: nowrap !important;
    pointer-events: none !important;
    user-select: none !important;
    -webkit-user-select: none !important;
    font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif !important;
    font-size: 27px !important;
    font-weight: 900 !important;
    letter-spacing: 0.04em !important;
    color: transparent !important;
    background: linear-gradient(
      90deg,
      #f7ffff 0%,
      #8cf3ff 18%,
      #76ffb4 36%,
      #f7ff8d 52%,
      #79d9ff 70%,
      #ffffff 100%
    ) !important;
    background-size: 100% 100% !important;
    -webkit-background-clip: text !important;
    background-clip: text !important;
    -webkit-text-fill-color: transparent !important;
    text-shadow:
      0 1px 0 rgba(255,255,255,0.22),
      0 0 10px rgba(118, 255, 180, 0.14),
      0 0 18px rgba(121, 217, 255, 0.18),
      0 8px 18px rgba(0,0,0,0.18) !important;
    filter:
      drop-shadow(0 0 2px rgba(255,255,255,0.12))
      drop-shadow(0 0 10px rgba(110,255,180,0.10))
      drop-shadow(0 0 14px rgba(120,210,255,0.10)) !important;
  }

  #logo::before {
    content: "" !important;
    position: absolute !important;
    left: 50% !important;
    top: 58% !important;
    width: 78% !important;
    height: 2px !important;
    transform: translateX(-50%) !important;
    background: linear-gradient(
      90deg,
      rgba(0,0,0,0) 0%,
      rgba(120,255,190,0.0) 15%,
      rgba(120,255,190,0.45) 42%,
      rgba(120,220,255,0.45) 58%,
      rgba(0,0,0,0) 100%
    ) !important;
    box-shadow:
      0 0 10px rgba(120,255,190,0.10),
      0 0 14px rgba(120,220,255,0.10) !important;
    pointer-events: none !important;
  }
`);

(function() {
    'use strict';

    const win = unsafeWindow;

    const PREFIX = 'lx_';
    const EXPIRE_DAYS = 365;

    function encode(val) {
        try {
            return encodeURIComponent(String(val));
        } catch {
            return String(val);
        }
    }

    function decode(val) {
        try {
            return decodeURIComponent(String(val));
        } catch {
            return String(val);
        }
    }

    function setRaw(key, value, days) {
        const d = new Date();
        d.setTime(d.getTime() + (days || EXPIRE_DAYS) * 864e5);
        document.cookie = encode(key) + '=' + encode(value) + '; expires=' + d.toUTCString() + '; path=/';
        try {
            localStorage.setItem(PREFIX + key, value);
        } catch {}
    }

    function getRaw(key) {
        try {
            const ls = localStorage.getItem(PREFIX + key);
            if (ls !== null) return ls;
        } catch {}
        const name = encode(key) + '=';
        const parts = document.cookie.split(';');
        for (let i = 0; i < parts.length; i++) {
            const c = parts[i].trim();
            if (c.startsWith(name)) {
                try {
                    return decode(c.substring(name.length));
                } catch {
                    return c.substring(name.length);
                }
            }
        }
        return null;
    }

    function removeRaw(key) {
        document.cookie = encode(key) + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/';
        try {
            localStorage.removeItem(PREFIX + key);
        } catch {}
    }

    function getAll() {
        const res = {};
        try {
            for (let i = 0; i < localStorage.length; i++) {
                const k = localStorage.key(i);
                if (k && k.startsWith(PREFIX)) res[k.slice(PREFIX.length)] = localStorage.getItem(k);
            }
        } catch {}
        const parts = document.cookie.split(';');
        for (let i = 0; i < parts.length; i++) {
            const eq = parts[i].indexOf('=');
            if (eq < 0) continue;
            const k = decode(parts[i].slice(0, eq).trim());
            const v = decode(parts[i].slice(eq + 1).trim());
            if (!(k in res)) res[k] = v;
        }
        return res;
    }

    const api = function(key, value, attributes) {
        if (arguments.length > 1) {
            const days = (attributes && typeof attributes.expires === 'number') ? attributes.expires : EXPIRE_DAYS;
            setRaw(key, value, days);
            return value;
        }
        if (!key) return getAll();
        return getRaw(key);
    };

    api.set = function(key, value, attributes) {
        const days = (attributes && typeof attributes.expires === 'number') ? attributes.expires : EXPIRE_DAYS;
        setRaw(key, value, days);
        return value;
    };

    api.get = function(key) {
        if (!key) return getAll();
        return getRaw(key);
    };

    api.getJSON = function(key) {
        const val = getRaw(key);
        if (val === null) return undefined;
        try {
            return JSON.parse(val);
        } catch {
            return val;
        }
    };

    api.remove = function(key) {
        removeRaw(key);
    };

    api.defaults = {};

    api.withConverter = function() {
        return api;
    };

    api.noConflict = function() {
        return api;
    };

    win.Cookies = api;

    function restoreNick() {
        const nick = document.getElementById('nick');
        if (!nick) {
            requestAnimationFrame(restoreNick);
            return;
        }
        const saved = getRaw('username');
        if (saved) nick.value = saved;
        nick.addEventListener('input', () => {
            if (nick.value) setRaw('username', nick.value, EXPIRE_DAYS);
        });
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', restoreNick);
    } else {
        restoreNick();
    }

})();