kitty klient

kitty klient — a MooMoo.io client with adaptive zoom, fast autoheal, gear automation, combat tools, visual markers, position prediction, quick builds, anti-boost spikes, and an in-game controls HUD. Hotkeys: U friend-pick, I enemy-pick, C cleanup, P autoheal, R insta, Q food, F trap/Shift+F boost-break, V spike, Z three windmills behind, H selected deployable; hold Q/F/V/Z/H to spam.

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

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

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==UserScript==
// @name         kitty klient
// @version      3.57.1
// @icon         https://static.wikia.nocookie.net/belugacinematicuniversefanon/images/6/6a/Beluga.jpg/revision/latest?cb=20231226224904
// @description  kitty klient — a MooMoo.io client with adaptive zoom, fast autoheal, gear automation, combat tools, visual markers, position prediction, quick builds, anti-boost spikes, and an in-game controls HUD. Hotkeys: U friend-pick, I enemy-pick, C cleanup, P autoheal, R insta, Q food, F trap/Shift+F boost-break, V spike, Z three windmills behind, H selected deployable; hold Q/F/V/Z/H to spam.
// @match        *://moomoo.io/*
// @match        *://*.moomoo.io/*
// @grant        none
// @run-at       document-start
// @namespace    thisisirrelevandandidontknowwhygreasyforkneedsthisanyways
// @license      MIT
// ==/UserScript==
 
(() => {
    "use strict";
 
    const MIN_VIEW_MULTIPLIER = 0.5;
    const MAX_VIEW_MULTIPLIER = 1 / 0.15;
    const ZOOM_STEP = 1.1;
    const TRACKPAD_PIXELS_PER_ZOOM_STEP = 360;
    const INDICATOR_ID = "moomoo-scroll-zoom-indicator";
    const HUD_ID = "moomoo-op-hud";
    const HUD_STORAGE_KEY = "moomoo-op-hud-settings-v1";
    const KILL_MESSAGE_AUTO_MIGRATION_KEY = "kitty-klient-kill-message-auto-v1";
    const TAB_SYNC_BRIDGE_KEY = "kitty-klient-tab-sync-bridge-v1";
    const KITTY_KLIENT_VERSION = "3.57.1";
    const KITTY_UPDATE_POPUP_ID = "kitty-klient-update-popup";
    const KITTY_UPDATE_DISMISS_KEY = "kitty-klient-dismissed-update-v1";
    const KITTY_UPDATE_API = "https://api.greasyfork.org/en/scripts/592072.json";
    const KITTY_UPDATE_FALLBACK_URL = "https://update.greasyfork.org/scripts/592072/kitty%20klient.user.js";
    const HUD_DEFAULTS = Object.freeze({
        autoHeal: true,
        soldierAuto: true,
        movementGear: true,
        passiveSpikeAvoidance: true,
        trapEscape: true,
        antiBoost: true,
        antiBoostInsta: true,
        threatTrap: true,
        autoCloseSpike: true,
        reloadSpike: true,
        shieldDefense: true,
        musketRecharge: true,
        autoPurchase: false,
        matThief: false,
        mobSteal: false,
        spinningWindmills: false,
        esp: true,
        espLines: true,
        predictionGhost: true,
        cooldownBars: true,
        bullHelmet: true,
        tankRightClick: true,
        allItemsUnlock: true,
        instaKill: false,
        autoInsta: true,
        autoSpikeInsta: true,
        autoSpikeSpam: true,
        antiInsta: true,
        instaSync: true,
        boostBreak: true,
        boostChat: true,
        materialReply: true,
        syncLeader: false,
        syncFollower: false,
        soldierRange: 400,
        combatRange: 400,
        gearHoldTicks: 3,
        passiveSpikeEnemyRange: 400,
        antiBoostRange: 200,
        reactionMs: 25,
        debugPanel: false,
        killMessageEnabled: true,
        killMessage: "gg",
        friendNames: []
    });
    const HUD_BOOLEAN_KEYS = Object.freeze([
        "autoHeal",
        "soldierAuto",
        "movementGear",
        "passiveSpikeAvoidance",
        "trapEscape",
        "antiBoost",
        "antiBoostInsta",
        "threatTrap",
        "autoCloseSpike",
        "reloadSpike",
        "shieldDefense",
        "musketRecharge",
        "autoPurchase",
        "matThief",
        "mobSteal",
        "spinningWindmills",
        "esp",
        "espLines",
        "predictionGhost",
        "cooldownBars",
        "bullHelmet",
        "tankRightClick",
        "allItemsUnlock",
        "instaKill",
        "autoInsta",
        "autoSpikeInsta",
        "autoSpikeSpam",
        "antiInsta",
        "instaSync",
        "boostBreak",
        "boostChat",
        "materialReply",
        "syncLeader",
        "syncFollower",
        "debugPanel",
        "killMessageEnabled"
    ]);
    const HUD_NUMERIC_BOUNDS = Object.freeze({
        soldierRange: Object.freeze({ min: 100, max: 1000, step: 10 }),
        combatRange: Object.freeze({ min: 100, max: 1000, step: 10 }),
        gearHoldTicks: Object.freeze({ min: 1, max: 8, step: 1 }),
        passiveSpikeEnemyRange: Object.freeze({ min: 0, max: 1200, step: 25 }),
        antiBoostRange: Object.freeze({ min: 80, max: 500, step: 10 }),
        reactionMs: Object.freeze({ min: 10, max: 100, step: 5 })
    });
    const GAME_BUNDLE = /\/assets\/index-[\w-]+\.js(?:\?.*)?$/;
    const VIEWPORT_MARKER = "const _=y.maxScreenWidth,L=y.maxScreenHeight;";
    const HOTKEY_MARKER = "t==69?wl():t==67?tl():t==88?gl():";
    const FOOD_HOTKEY_MARKER = "t==81?je(v.items[0]):";
    const FOOD_KEYUP_MARKER = "function pl(e){if(v&&v.alive){const t=e.which||e.keyCode||0;";
    const MOVEMENT_KEYDOWN_MARKER = "bt[t]?Tt():t==32&&(U=1,ke())";
    const MOVEMENT_KEYUP_MARKER = "bt[t]?Tt():t==32&&(U=0,ke())";
    const BACKDROP_GRID_MARKER = "k.globalAlpha=.06,k.beginPath();for(var i=-oe;i<_;i+=L/18)i>0&&(k.moveTo(i,0),k.lineTo(i,L));for(let c=-ae;c<L;c+=L/18)i>0&&(k.moveTo(0,c),k.lineTo(_,c));k.stroke(),k.globalAlpha=1,";
    // The HUD kill-message hook wraps this local game function. Validate it before
    // injecting so a renamed game bundle falls back cleanly instead of half-loading.
    const PLAYER_STAT_UPDATE_MARKER = "function Kl(";
    const CHAT_DISPLAY_MARKER = "function dl(";
    // __mmInsta depends on both functions below to bind a target by SID and
    // to coexist with the game's normal attack dispatch. Missing either means
    // the complete patched bundle is abandoned in favor of the original.
    const INSTA_PLAYER_LOOKUP_MARKER = "function Rt(";
    const INSTA_PLAYER_ATTACK_MARKER = "function Pl(";
    const BUNDLE_RETRY_LIMIT = 8;
    const BUNDLE_RETRY_DELAY_MS = 250;
    const PATCHED_MODULE_RETRY_LIMIT = 3;
    let viewMultiplier = 1 / 0.75;
    let hideIndicatorTimer = 0;
    let gameScriptHijacked = false;
    let originalBundleLoaded = false;
    let restoreBundleInsertionGuards = () => {};
    let hudMounted = false;
    let hudSettingsSent = false;
    let hudState = { ...HUD_DEFAULTS };
    let hudOpen = false;
    const hudControls = new Map();
    window.__MooMooScrollZoomMultiplier = viewMultiplier;

    // Arm the game-bundle interception before theme installation, HUD work, or
    // any optional network request. This userscript is intentionally large;
    // waiting until its final lines left a first-navigation race where the
    // outer UI loaded but MooMoo's original module escaped unpatched.
    installSynchronousBundleGuards();

    const gameBundleObserver = new MutationObserver((records) => {
        for (const record of records) {
            for (const node of record.addedNodes) {
                if (node.nodeType === Node.ELEMENT_NODE && node.tagName === "SCRIPT") {
                    interceptGameBundle(node);
                } else if (node.nodeType === Node.ELEMENT_NODE && node.querySelectorAll) {
                    node.querySelectorAll("script[src]").forEach(interceptGameBundle);
                }
            }
        }
    });

    gameBundleObserver.observe(document, { childList: true, subtree: true });
    document.querySelectorAll("script[src]").forEach(interceptGameBundle);

    // Firefox exposes a cancellable last-chance event for parser-inserted
    // scripts. Chromium simply ignores this listener and uses the synchronous
    // DOM guards plus the observer above.
    document.addEventListener("beforescriptexecute", (event) => {
        const script = event.target;
        if (script instanceof HTMLScriptElement && interceptGameBundle(script)) {
            event.preventDefault();
            event.stopImmediatePropagation();
        }
    }, true);

    document.addEventListener("readystatechange", () => {
        if (!gameScriptHijacked && document.readyState === "interactive") {
            document.querySelectorAll("script[src]").forEach(interceptGameBundle);
        }
    }, { once: true });

    window.addEventListener("load", () => {
        // If the page never produced the MooMoo module, stop wrapping DOM APIs.
        // Normal successful interception restores them immediately in claimGameBundle.
        if (!gameScriptHijacked) restoreBundleInsertionGuards();
    }, { once: true });

    function installCanvasTextTheme() {
        const prototype = window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype;
        if (!prototype || prototype.__kittyKlientTextTheme) return;
        Object.defineProperty(prototype, "__kittyKlientTextTheme", { value: true });
        ["fillText", "strokeText"].forEach((method) => {
            const original = prototype[method];
            if (typeof original !== "function") return;
            prototype[method] = function (...args) {
                const previousShadowColor = this.shadowColor;
                const previousShadowBlur = this.shadowBlur;
                const previousFillStyle = this.fillStyle;
                try {
                    this.shadowColor = "#8b5cf6";
                    this.shadowBlur = Math.max(8, Number(this.shadowBlur) || 0);
                    if (method === "fillText") {
                        const current = String(previousFillStyle || "").replace(/\s+/g, "").toLowerCase();
                        const dark = current === "#000" || current === "#000000" || current === "black" ||
                            /^rgba?\((?:0,){2}0(?:,|\))/.test(current);
                        this.fillStyle = dark ? "#050505" : "#ffffff";
                    }
                    return original.apply(this, args);
                } finally {
                    this.shadowColor = previousShadowColor;
                    this.shadowBlur = previousShadowBlur;
                    this.fillStyle = previousFillStyle;
                }
            };
        });
    }

    function applyKittyNameTrademark() {
        const input = document.getElementById("nameInput");
        if (!input) return;
        const storedOriginal = Number(input.dataset.kittyOriginalNameMax);
        const originalMax = Number.isFinite(storedOriginal) && storedOriginal > 2
            ? storedOriginal
            : Math.max(3, Number(input.maxLength) || 15);
        const nameLimit = Math.max(1, originalMax - 2);
        input.dataset.kittyOriginalNameMax = String(originalMax);
        input.dataset.kittyNameLimit = String(nameLimit);
        input.maxLength = nameLimit;
        input.setAttribute("maxlength", String(nameLimit));
        input.placeholder = "Enter Name (k- added)";
        const normalize = () => {
            const normalized = String(input.value || "")
                .replace(/^(?:k-)+/i, "")
                .slice(0, nameLimit);
            if (input.value !== normalized) input.value = normalized;
        };
        normalize();
        if (!input.dataset.kittyNameTrademarkBound) {
            input.dataset.kittyNameTrademarkBound = "1";
            input.addEventListener("input", normalize);
            input.addEventListener("change", normalize);
            input.addEventListener("focus", normalize);
        }
    }

    function applyKittyBrand() {
        applyKittyNameTrademark();
        if (document.title !== "kitty klient") document.title = "kitty klient";
        const menu = document.getElementById("mainMenu") || document.body;
        if (!menu) return;
        const candidates = menu.querySelectorAll("#gameName,.gameName,h1,h2,[class*='title'],[id*='title']");
        candidates.forEach((element) => {
            const text = (element.textContent || "").trim();
            if (text.length <= 32 && /moo\s*moo(?:\.io)?/i.test(text)) {
                element.textContent = "kitty klient";
                element.dataset.kittyBrand = "";
            }
        });
    }

    function installKittyTheme() {
        if (!document.documentElement || document.getElementById("kitty-klient-theme")) return;
        const style = document.createElement("style");
        style.id = "kitty-klient-theme";
        style.textContent = [
            ":root{--kitty-purple:#a855f7;--kitty-purple-deep:#6d28d9;--kitty-black:#08050d}",
            "body,button,input,select,textarea,label,#gameUI,#mainMenu,#menuCardHolder,.menuCard,.menuButton,.settingRadio,.leaderboardItem,.leaderScore,.notificationText,.allianceItem,.storeItem,#itemInfoHolder,#loadingText,#diedText{color:#fff!important;text-shadow:0 0 4px #8b5cf6,0 0 11px rgba(168,85,247,.9)!important}",
            ".menuCard,#guideCard,#serverBrowser,#storeHolder,#allianceHolder,#allianceManager,#chatBox{background-color:rgba(5,3,9,.82)!important;border-color:rgba(168,85,247,.7)!important;box-shadow:0 0 18px rgba(139,92,246,.4)!important}",
            "#mainMenu{background:rgba(5,3,9,.5)!important;border:0!important;box-shadow:none!important}#menuCardHolder,#storeMenu,#allianceMenu,#chatHolder{background:transparent!important;border:0!important;box-shadow:none!important;backdrop-filter:none!important}",
            "#menuContainer{width:min(1100px,calc(100vw - 28px))!important;left:50%!important;transform:translate(-50%,-50%)!important}#storeHolder{width:min(400px,calc(100vw - 40px))!important;box-sizing:border-box!important}#storeMenu>div:first-child{width:min(400px,calc(100vw - 40px));margin-inline:auto}#storeMenu .storeTab{width:calc(50% - 7px)!important;box-sizing:border-box!important}#allianceHolder,#allianceManager{width:min(370px,calc(100vw - 40px))!important;box-sizing:border-box!important;margin-inline:auto!important}#chatBox{width:min(420px,calc(100vw - 40px))!important;box-sizing:border-box!important}",
            "#mainMenu button,#mainMenu input,#mainMenu select,#enterGame,.menuButton,.allianceButtonM,.joinAlBtn{background:rgba(8,5,13,.82)!important;border:1px solid rgba(168,85,247,.72)!important;color:#fff!important;box-shadow:0 0 10px rgba(139,92,246,.28)!important}",
            "#mainMenu button:hover,#enterGame:hover,.menuButton:hover,.allianceButtonM:hover,.joinAlBtn:hover{border-color:#c084fc!important;box-shadow:0 0 16px rgba(168,85,247,.72)!important}",
            "[data-kitty-brand],#gameName.kitty-klient-brand{font-family:'Segoe Print','Bradley Hand','Brush Script MT',cursive!important;font-style:italic!important;font-weight:900!important;letter-spacing:.045em!important;text-transform:lowercase!important;color:#07030b!important;-webkit-text-stroke:1px #17101f;text-shadow:-2px 1px 0 #a855f7,2px -1px 0 #6d28d9,0 0 8px #c084fc,0 0 22px #7c3aed!important;transform:skewX(-9deg) rotate(-1deg)!important}",
            "#kitty-klient-metrics{position:fixed;z-index:2147483645;right:14px;top:62%;transform:translateY(-50%);display:grid;gap:5px;padding:9px 10px;border:1px solid rgba(168,85,247,.68);border-radius:10px;background:rgba(5,3,9,.68);box-shadow:0 0 18px rgba(139,92,246,.38);backdrop-filter:blur(7px);pointer-events:none;color:#fff;font:800 11px/1.15 ui-monospace,SFMono-Regular,Menlo,monospace;text-shadow:0 0 7px #8b5cf6}",
            "#kitty-klient-metrics span{display:flex;justify-content:space-between;gap:10px;min-width:92px}#kitty-klient-metrics b{color:#c084fc;font-weight:900}",
            "#kitty-klient-update-popup{position:fixed;z-index:2147483647;top:18px;right:18px;width:min(330px,calc(100vw - 36px));box-sizing:border-box;padding:17px 17px 16px;border:1px solid rgba(192,132,252,.82);border-radius:14px;background:linear-gradient(145deg,rgba(8,5,13,.94),rgba(30,12,48,.88));box-shadow:0 0 28px rgba(139,92,246,.5),inset 0 0 22px rgba(168,85,247,.08);backdrop-filter:blur(12px);color:#fff;font:600 13px/1.45 system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;text-shadow:0 0 7px rgba(168,85,247,.8);animation:kitty-update-enter .22s ease-out both}",
            "#kitty-klient-update-popup .kitty-update-title{margin:0 30px 5px 0;color:#fff;font-size:18px;font-weight:900;letter-spacing:.01em}#kitty-klient-update-popup .kitty-update-copy{margin:0 0 12px;color:#eee}#kitty-klient-update-popup .kitty-update-versions{display:flex;align-items:center;gap:7px;margin:0 0 14px;color:#d8b4fe;font:800 11px/1.2 ui-monospace,SFMono-Regular,Menlo,monospace;text-shadow:0 0 8px #7c3aed}",
            "#kitty-klient-update-popup .kitty-update-download{display:flex;align-items:center;justify-content:center;min-height:38px;padding:0 14px;border:1px solid #c084fc;border-radius:9px;background:linear-gradient(135deg,#7c3aed,#a855f7);color:#fff!important;font-size:13px;font-weight:900;text-decoration:none;box-shadow:0 0 15px rgba(168,85,247,.46);text-shadow:0 0 7px #4c1d95!important;transition:transform .12s ease,filter .12s ease}#kitty-klient-update-popup .kitty-update-download:hover{filter:brightness(1.13);transform:translateY(-1px)}",
            "#kitty-klient-update-popup .kitty-update-close{position:absolute;top:8px;right:9px;width:30px;height:30px;padding:0;border:0;border-radius:8px;background:transparent;color:#e9d5ff!important;font:900 23px/28px Arial,sans-serif;cursor:pointer;text-shadow:0 0 9px #a855f7!important}#kitty-klient-update-popup .kitty-update-close:hover{background:rgba(168,85,247,.2);color:#fff!important}@keyframes kitty-update-enter{from{opacity:0;transform:translateY(-9px) scale(.98)}to{opacity:1;transform:none}}",
            "@media(max-width:700px){#kitty-klient-metrics{right:8px;top:60%;font-size:9px;padding:7px}#menuContainer{width:calc(100vw - 16px)!important;white-space:normal!important}}"
        ].join("");
        (document.head || document.documentElement).appendChild(style);
        applyKittyBrand();
        const observer = new MutationObserver(applyKittyBrand);
        observer.observe(document.documentElement, { childList: true, subtree: true });
    }

    function mountMetrics() {
        if (!document.body || document.getElementById("kitty-klient-metrics")) return;
        const metrics = document.createElement("div");
        metrics.id = "kitty-klient-metrics";
        metrics.setAttribute("aria-label", "kitty klient performance");
        metrics.innerHTML = "<span>PING <b data-metric='ping'>--</b></span>" +
            "<span>FPS <b data-metric='fps'>--</b></span>" +
            "<span>PACKETS <b data-metric='packets'>0</b></span>";
        document.body.appendChild(metrics);
    }

    installCanvasTextTheme();

    // Firefox can place a patched blob module in a messaging context that is
    // separate from the userscript's normal page context. Bridge tab-sync
    // traffic through the page-level storage event as a reliable fallback.
    window.addEventListener("MooMooTabSyncOutbound", (event) => {
        const payload = typeof event.detail === "string" ? event.detail : "";
        if (!payload || payload.length > 1200) return;
        try {
            localStorage.setItem(TAB_SYNC_BRIDGE_KEY, payload);
        } catch {
            // BroadcastChannel remains available when storage is blocked.
        }
    });
    window.addEventListener("storage", (event) => {
        if (!event || event.key !== TAB_SYNC_BRIDGE_KEY || !event.newValue) return;
        window.dispatchEvent(new CustomEvent("MooMooTabSyncInbound", { detail: event.newValue }));
    });
 
    function showZoomIndicator(message) {
        if (!document.body) return;
 
        let indicator = document.getElementById(INDICATOR_ID);
        if (!indicator) {
            indicator = document.createElement("div");
            indicator.id = INDICATOR_ID;
            indicator.style.cssText = [
                "position:fixed",
                "top:16px",
                "left:50%",
                "z-index:2147483647",
                "transform:translateX(-50%)",
                "padding:6px 10px",
                "border-radius:6px",
                "background:rgba(0,0,0,.65)",
                "color:#fff",
                "font:700 14px Arial,sans-serif",
                "pointer-events:none",
                "transition:opacity .2s"
            ].join(";");
            document.body.appendChild(indicator);
        }
 
        // A larger viewport multiplier means more of the map is visible.
        indicator.textContent = message || `Zoom: ${Math.round((1 / viewMultiplier) * 100)}%`;
        indicator.style.opacity = "1";
        clearTimeout(hideIndicatorTimer);
        hideIndicatorTimer = window.setTimeout(() => {
            indicator.style.opacity = "0";
        }, 900);
    }
 
    function applyViewportSize() {
        window.__MooMooScrollZoomMultiplier = viewMultiplier;
        if (typeof window.__MooMooScrollZoomSetViewport === "function") {
            window.__MooMooScrollZoomSetViewport(viewMultiplier);
        }
    }
 
    function isGameSurface(target) {
        return target instanceof Element && Boolean(target.closest("#gameCanvas, #touch-controls-fullscreen"));
    }
 
    function isLikelyTrackpadScroll(event) {
        // Physical mouse wheels normally report line-mode or a large pixel delta.
        // Trackpads emit frequent, small pixel-mode deltas.
        return event.deltaMode === WheelEvent.DOM_DELTA_PIXEL && Math.abs(event.deltaY) < 50;
    }
 
    document.addEventListener("wheel", (event) => {
        if (!isGameSurface(event.target) || event.ctrlKey || event.deltaY === 0) return;
 
        event.preventDefault();
        event.stopImmediatePropagation();
        const zoomStep = isLikelyTrackpadScroll(event)
            ? Math.pow(ZOOM_STEP, Math.abs(event.deltaY) / TRACKPAD_PIXELS_PER_ZOOM_STEP)
            : ZOOM_STEP;
        viewMultiplier = Math.min(
            MAX_VIEW_MULTIPLIER,
            Math.max(MIN_VIEW_MULTIPLIER, viewMultiplier * (event.deltaY > 0 ? zoomStep : 1 / zoomStep))
        );
        applyViewportSize();
        showZoomIndicator();
    }, { capture: true, passive: false });
 
    window.addEventListener("MooMooScrollZoomAutoheal", (event) => {
        showZoomIndicator(`Autoheal: ${event.detail ? "On" : "Off"}`);
    });
 
    window.addEventListener("MooMooScrollZoomMonkeyTail", (event) => {
        showZoomIndicator(event.detail);
    });
 
    window.addEventListener("MooMooScrollZoomShiftSpeed", (event) => {
        showZoomIndicator(event.detail);
    });
 
    window.addEventListener("MooMooScrollZoomStatus", (event) => {
        showZoomIndicator(event.detail);
    });
 
    function clampHudNumber(key, value) {
        const bounds = HUD_NUMERIC_BOUNDS[key];
        if (!bounds || !Number.isFinite(value)) return HUD_DEFAULTS[key];
        return Math.min(bounds.max, Math.max(bounds.min, value));
    }
 
    function normalizeHudSettings(candidate) {
        const settings = { ...HUD_DEFAULTS };
        if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) return settings;
 
        HUD_BOOLEAN_KEYS.forEach((key) => {
            if (typeof candidate[key] === "boolean") settings[key] = candidate[key];
        });
        Object.keys(HUD_NUMERIC_BOUNDS).forEach((key) => {
            if (Number.isFinite(candidate[key])) settings[key] = clampHudNumber(key, candidate[key]);
        });
        if (typeof candidate.killMessage === "string") {
            settings.killMessage = candidate.killMessage.slice(0, 30);
        }
        if (Array.isArray(candidate.friendNames)) {
            const seen = new Set();
            settings.friendNames = candidate.friendNames.reduce((names, value) => {
                const name = typeof value === "string" ? value.trim().slice(0, 15) : "";
                const key = name.toLowerCase();
                if (name && !seen.has(key) && names.length < 30) {
                    seen.add(key);
                    names.push(name);
                }
                return names;
            }, []);
        }
        return settings;
    }
 
    function readHudSettings() {
        try {
            const settings = normalizeHudSettings(JSON.parse(localStorage.getItem(HUD_STORAGE_KEY) || "{}"));
            // Apply the requested auto death-message default once without
            // discarding the rest of the player's saved HUD configuration.
            if (localStorage.getItem(KILL_MESSAGE_AUTO_MIGRATION_KEY) !== "1") {
                settings.killMessageEnabled = true;
                if (!settings.killMessage.trim()) settings.killMessage = HUD_DEFAULTS.killMessage;
                localStorage.setItem(KILL_MESSAGE_AUTO_MIGRATION_KEY, "1");
            }
            return settings;
        } catch {
            return { ...HUD_DEFAULTS };
        }
    }
 
    function saveHudSettings() {
        try {
            // A tab role is intentionally per-tab. Persisting it would make a
            // freshly opened tab unexpectedly become another leader/follower.
            const settings = normalizeHudSettings(hudState);
            settings.syncLeader = false;
            settings.syncFollower = false;
            localStorage.setItem(HUD_STORAGE_KEY, JSON.stringify(settings));
        } catch {
            // Saved settings are optional; the mod still works when storage is unavailable.
        }
    }
 
    function sendHudCommand(detail) {
        window.dispatchEvent(new CustomEvent("MooMooOPHudCommand", { detail }));
    }
 
    function setHudControlValue(key, value) {
        const control = hudControls.get(key);
        if (!control) return;
        if (control.type === "checkbox") control.checked = Boolean(value);
        else control.value = value == null ? "" : String(value);
    }
 
    function renderHud() {
        Object.entries(hudState).forEach(([key, value]) => setHudControlValue(key, value));
        const friendList = document.querySelector("#" + HUD_ID + " [data-hud-friends]");
        if (friendList) {
            friendList.textContent = "";
            const names = Array.isArray(hudState.friendNames) ? hudState.friendNames : [];
            if (!names.length) {
                const empty = document.createElement("small");
                empty.textContent = "No friends yet — every non-teammate starts as an enemy.";
                friendList.appendChild(empty);
            } else {
                names.forEach((name) => {
                    const chip = document.createElement("span");
                    chip.className = "mm-hud-friend-chip";
                    chip.textContent = name;
                    friendList.appendChild(chip);
                });
            }
        }
        const status = document.querySelector("#" + HUD_ID + " [data-hud-status]");
        if (!status) return;
        const enabled = [
            hudState.autoHeal && "heal",
            hudState.soldierAuto && "soldier",
            hudState.movementGear && "speed",
            hudState.matThief && "mat thief",
            hudState.mobSteal && "mob steal",
            hudState.antiBoost && "spikes",
            hudState.antiBoostInsta && "boost insta",
            hudState.syncLeader && "sync leader",
            hudState.syncFollower && "sync follower"
        ].filter(Boolean);
        status.textContent = enabled.length ? "Active: " + enabled.join(" · ") : "Automation paused";
        const debug = document.querySelector("#" + HUD_ID + " [data-hud-debug]");
        if (debug) {
            debug.hidden = !hudState.debugPanel;
            debug.textContent = hudState.debugPanel
                ? (typeof hudState.debugText === "string" && hudState.debugText) || "Waiting for live game state…"
                : "";
        }
    }
 
    function addHudToggle(container, key, label, subtitle) {
        const row = document.createElement("label");
        row.className = "mm-hud-row";
        const text = document.createElement("span");
        const title = document.createElement("strong");
        title.textContent = label;
        const hint = document.createElement("small");
        hint.textContent = subtitle;
        text.append(title, hint);
        const input = document.createElement("input");
        input.type = "checkbox";
        input.checked = Boolean(hudState[key]);
        input.addEventListener("change", () => {
            hudState[key] = input.checked;
            saveHudSettings();
            sendHudCommand({ type: "set", key, value: input.checked });
            renderHud();
        });
        row.append(text, input);
        container.appendChild(row);
        hudControls.set(key, input);
    }
 
    function addHudNumber(container, key, label, subtitle) {
        const bounds = HUD_NUMERIC_BOUNDS[key];
        const row = document.createElement("label");
        row.className = "mm-hud-number";
        const text = document.createElement("span");
        const title = document.createElement("strong");
        title.textContent = label;
        const hint = document.createElement("small");
        hint.textContent = subtitle;
        text.append(title, hint);
        const input = document.createElement("input");
        input.type = "number";
        input.min = String(bounds.min);
        input.max = String(bounds.max);
        input.step = String(bounds.step);
        input.value = String(hudState[key]);
        input.addEventListener("change", () => {
            const value = clampHudNumber(key, Number(input.value));
            hudState[key] = value;
            saveHudSettings();
            sendHudCommand({ type: "set", key, value });
            renderHud();
        });
        row.append(text, input);
        container.appendChild(row);
        hudControls.set(key, input);
    }
 
    function addHudSection(panel, heading) {
        const section = document.createElement("section");
        section.className = "mm-hud-section";
        const title = document.createElement("h3");
        title.textContent = heading;
        section.appendChild(title);
        panel.appendChild(section);
        return section;
    }
 
    function mountHud() {
        if (hudMounted || !document.body) return;
        if (document.getElementById(HUD_ID)) {
            hudMounted = true;
            return;
        }
        hudMounted = true;
        hudState = { ...hudState, ...readHudSettings() };
 
        const style = document.createElement("style");
        style.id = HUD_ID + "-style";
        style.textContent = [
            "#moomoo-op-hud{--mm-bg:rgba(5,3,9,.78);--mm-surface:rgba(20,12,30,.72);--mm-line:rgba(168,85,247,.4);--mm-text:#fff;--mm-muted:#d8b4fe;--mm-accent:#a855f7;position:fixed;z-index:2147483646;inset:0;display:grid;place-items:center;padding:28px;font:13px/1.3 system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;color:var(--mm-text);pointer-events:none;background:rgba(0,0,0,.08);backdrop-filter:blur(2px)}",
            "#moomoo-op-hud.mm-hud-collapsed{display:none}#moomoo-op-hud *,#moomoo-op-hud *:before,#moomoo-op-hud *:after{box-sizing:border-box}#moomoo-op-hud button,#moomoo-op-hud input{font:inherit}",
            "#moomoo-op-hud .mm-hud-panel{pointer-events:auto;width:min(1040px,calc(100vw - 56px));height:min(720px,calc(100vh - 56px));display:grid;grid-template-rows:auto auto minmax(0,1fr);overflow:hidden;border:1px solid rgba(192,132,252,.7);border-radius:18px;background:var(--mm-bg);box-shadow:0 0 24px rgba(139,92,246,.38),0 22px 70px rgba(0,0,0,.7);backdrop-filter:blur(16px)}",
            "#moomoo-op-hud .mm-hud-head{display:flex;align-items:center;justify-content:space-between;gap:18px;padding:18px 20px 12px;border-bottom:1px solid var(--mm-line)}#moomoo-op-hud .mm-hud-brand{margin:0;font-family:'Segoe Print','Bradley Hand','Brush Script MT',cursive;font-style:italic;font-size:29px;line-height:1;color:#050208!important;-webkit-text-stroke:1px #17101f;text-shadow:-2px 1px 0 #a855f7,2px -1px 0 #6d28d9,0 0 13px #c084fc!important;transform:skewX(-8deg)}",
            "#moomoo-op-hud .mm-hud-status{margin:0;color:#fff;font-size:11px;font-weight:800;text-align:right;text-shadow:0 0 8px #8b5cf6}#moomoo-op-hud .mm-hud-escape{color:var(--mm-muted);font-size:10px;white-space:nowrap}",
            "#moomoo-op-hud .mm-hud-nav{display:flex;gap:6px;padding:10px 14px;border-bottom:1px solid var(--mm-line);overflow-x:auto}#moomoo-op-hud .mm-hud-nav button{border:1px solid transparent;border-radius:9px;background:transparent;color:#fff;padding:8px 13px;cursor:pointer;font-weight:800;text-shadow:0 0 7px #8b5cf6}#moomoo-op-hud .mm-hud-nav button:hover,#moomoo-op-hud .mm-hud-nav button.mm-active{border-color:#a855f7;background:rgba(109,40,217,.28);box-shadow:0 0 12px rgba(168,85,247,.35)}",
            "#moomoo-op-hud .mm-hud-pages{min-height:0;overflow:auto;padding:14px}#moomoo-op-hud .mm-hud-page{display:none;grid-template-columns:repeat(2,minmax(0,1fr));align-content:start;gap:12px}#moomoo-op-hud .mm-hud-page.mm-active{display:grid}",
            "#moomoo-op-hud .mm-hud-section{padding:13px 14px;border:1px solid var(--mm-line);border-radius:12px;background:var(--mm-surface);box-shadow:inset 0 0 18px rgba(109,40,217,.08)}#moomoo-op-hud h3{margin:0 0 8px;font-size:11px;text-transform:uppercase;letter-spacing:.11em;color:#d8b4fe;text-shadow:0 0 7px #7c3aed}",
            "#moomoo-op-hud .mm-hud-row,#moomoo-op-hud .mm-hud-number{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:6px 0;cursor:pointer}#moomoo-op-hud .mm-hud-row span,#moomoo-op-hud .mm-hud-number span{display:grid;gap:2px}#moomoo-op-hud strong{font-size:13px;color:#fff;text-shadow:0 0 6px #7c3aed}#moomoo-op-hud small{color:var(--mm-muted);font-size:10px}",
            "#moomoo-op-hud input[type='checkbox']{appearance:none;width:36px;height:20px;margin:0;border:1px solid var(--mm-line);border-radius:999px;background:#21172b;position:relative;flex:0 0 auto;cursor:pointer}#moomoo-op-hud input[type='checkbox']:after{content:'';position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;background:#fff;box-shadow:0 0 7px #c084fc;transition:transform .14s ease}#moomoo-op-hud input[type='checkbox']:checked{background:#7c3aed;border-color:#c084fc;box-shadow:0 0 10px rgba(168,85,247,.65)}#moomoo-op-hud input[type='checkbox']:checked:after{transform:translateX(16px)}",
            "#moomoo-op-hud input[type='number']{width:68px;border:1px solid var(--mm-line);border-radius:7px;background:#09050e;color:#fff;padding:6px;text-align:right}#moomoo-op-hud .mm-hud-message{width:100%;border:1px solid var(--mm-line);border-radius:8px;background:#09050e;color:#fff;padding:8px;margin:3px 0 7px}",
            "#moomoo-op-hud .mm-hud-reset{border:1px solid var(--mm-line);border-radius:8px;background:#0b0711;color:#fff;padding:8px;cursor:pointer}#moomoo-op-hud .mm-hud-reset:hover{border-color:var(--mm-accent);box-shadow:0 0 11px rgba(168,85,247,.45)}#moomoo-op-hud .mm-hud-keys{margin:0;padding-left:16px;color:var(--mm-muted);font-size:11px;display:grid;gap:4px}",
            "#moomoo-op-hud .mm-hud-friend-actions{display:grid;grid-template-columns:1fr auto auto;gap:6px;align-items:center}#moomoo-op-hud .mm-hud-friend-actions .mm-hud-message{margin:3px 0 7px}#moomoo-op-hud .mm-hud-friend-list{display:flex;flex-wrap:wrap;gap:6px;min-height:24px;align-items:center}#moomoo-op-hud .mm-hud-friend-chip{border:1px solid rgba(250,204,21,.68);border-radius:999px;background:rgba(250,204,21,.12);color:#fff;padding:4px 8px;box-shadow:0 0 8px rgba(250,204,21,.28);text-shadow:0 0 6px #eab308}",
            "#moomoo-op-hud .mm-hud-debug{margin:4px 0 7px;white-space:pre-wrap;overflow-wrap:anywhere;border:1px solid var(--mm-line);border-radius:8px;background:rgba(0,0,0,.45);color:#fff;padding:8px;font:10px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;text-shadow:0 0 6px #7c3aed}",
            "@media(max-width:720px){#moomoo-op-hud{padding:10px}#moomoo-op-hud .mm-hud-panel{width:calc(100vw - 20px);height:calc(100vh - 20px)}#moomoo-op-hud .mm-hud-page{grid-template-columns:1fr}#moomoo-op-hud .mm-hud-head{padding:14px}#moomoo-op-hud .mm-hud-brand{font-size:23px}}"
        ].join("");
        (document.head || document.documentElement).appendChild(style);
 
        const root = document.createElement("aside");
        root.id = HUD_ID;
        root.className = "mm-hud-collapsed";
        root.setAttribute("aria-label", "kitty klient controls");
        const panel = document.createElement("div");
        panel.className = "mm-hud-panel";
        panel.addEventListener("mousedown", (event) => event.stopPropagation());
        panel.addEventListener("click", (event) => event.stopPropagation());
 
        const head = document.createElement("header");
        head.className = "mm-hud-head";
        const brand = document.createElement("h2");
        brand.className = "mm-hud-brand";
        brand.textContent = "kitty klient";
        const headInfo = document.createElement("div");
        const status = document.createElement("p");
        status.className = "mm-hud-status";
        status.dataset.hudStatus = "";
        const escapeHint = document.createElement("span");
        escapeHint.className = "mm-hud-escape";
        escapeHint.textContent = "ESC toggles · WASDFVR returns straight to the game";
        headInfo.append(status, escapeHint);
        head.append(brand, headInfo);

        const nav = document.createElement("nav");
        nav.className = "mm-hud-nav";
        const pages = document.createElement("div");
        pages.className = "mm-hud-pages";
        const pageMap = new Map();
        const activatePage = (name) => {
            nav.querySelectorAll("button").forEach((button) => button.classList.toggle("mm-active", button.dataset.page === name));
            pages.querySelectorAll(".mm-hud-page").forEach((page) => page.classList.toggle("mm-active", page.dataset.page === name));
        };
        const addPage = (name, label) => {
            const button = document.createElement("button");
            button.type = "button";
            button.dataset.page = name;
            button.textContent = label;
            button.addEventListener("click", () => activatePage(name));
            nav.appendChild(button);
            const page = document.createElement("div");
            page.className = "mm-hud-page";
            page.dataset.page = name;
            pages.appendChild(page);
            pageMap.set(name, page);
            return page;
        };
        const automationPage = addPage("automation", "Automation");
        const combatPage = addPage("combat", "Combat");
        const visualsPage = addPage("visuals", "Visuals");
        const syncPage = addPage("sync", "Sync");
        const configPage = addPage("config", "Config");
        panel.append(head, nav, pages);
 
        const automation = addHudSection(automationPage, "Automation");
        addHudToggle(automation, "autoHeal", "Autoheal", "Immediate first food, then tick-paced recovery");
        addHudToggle(automation, "soldierAuto", "Soldier helmet", "Idle protection and combat range");
        addHudToggle(automation, "movementGear", "Movement gear", "Speed gear while moving, EMP Helmet while idle and safe, plus adaptive tails");
        addHudToggle(automation, "passiveSpikeAvoidance", "Passive spike avoidance", "After movement release, counter residual velocity that would carry you into a damaging spike");
        addHudToggle(automation, "trapEscape", "Trap escape", "Build behind you while continuously breaking the locking trap");
        addHudToggle(automation, "antiBoost", "Auto boost block", "Two-spike wall, short retreat, and temporary shield against rushers");
        addHudToggle(automation, "antiBoostInsta", "Anti-boost insta", "Full-insta an enemy boost-rushing into range");
        addHudToggle(automation, "threatTrap", "Auto close trap", "Place a pit trap between you and nearby enemies or hostile animals");
        addHudToggle(automation, "autoCloseSpike", "Auto close spike", "Place a spike near close threats when no enabled pit trap is available");
        addHudToggle(automation, "reloadSpike", "Reload spike", "Defend with one spike while Musket or Turret Gear reloads");
        addHudToggle(automation, "shieldDefense", "Shield defense", "Face polearm and turret attacks");
        addHudToggle(automation, "musketRecharge", "Weapon recharge", "Main-first resumable queue for every cooling weapon");
        addHudToggle(automation, "autoPurchase", "Auto purchase", "Monkey Tail → Soldier → Stick/Bull path → gear → wings");
        addHudToggle(automation, "matThief", "Mat thief", "Last-hit nearby mills, turrets, and teleporters; starts disabled");
        addHudToggle(automation, "mobSteal", "Mob steal", "Predictively last-hit one-swing animals in range; starts disabled");
        addHudToggle(automation, "spinningWindmills", "Spinning windmills", "Continuously place mills in rotating collision-free slots; starts disabled");

        const tabSync = addHudSection(syncPage, "Tab sync (same game)");
        addHudToggle(tabSync, "syncLeader", "Sync leader", "Share this tab’s position, equipment, selections, and attacks");
        addHudToggle(tabSync, "syncFollower", "Sync follower", "Follow the leader in a tight orbit and replay its actions with positional aim");
 
        const visuals = addHudSection(visualsPage, "Visuals");
        addHudToggle(visuals, "esp", "Player & animal markers", "Colored circles around players and animals");
        addHudToggle(visuals, "espLines", "Player connection lines", "Lines to friends, teammates, and enemies; hostile lines are thicker");
        addHudToggle(visuals, "predictionGhost", "Prediction ghost", "A translucent copy projects ahead by half your live ping");
        addHudToggle(visuals, "cooldownBars", "Tool cooldown bars", "Small refill bars beneath players show both tool cooldowns");
 
        const actions = addHudSection(combatPage, "Gear & boost controls");
        addHudToggle(actions, "bullHelmet", "Bull helmet", "Bull through the configured swing window, Soldier during reload, then restores your hat");
        addHudToggle(actions, "tankRightClick", "Tank right-click", "Tank uses the configured hold, then Soldier; falls back to any primary when slot two is empty");
        addHudToggle(actions, "allItemsUnlock", "Preview every upgrade", "Shows every same-age choice but disables selections the server would reject");
        addHudToggle(actions, "instaKill", "R insta", "Bull primary + Turret Gear secondary combo");
        addHudToggle(actions, "autoInsta", "Click insta", "Left-click starts the ready full combo when an enemy is close");
        addHudToggle(actions, "autoSpikeInsta", "Spike-tick strike", "Turret Gear + insta-primary swing on predicted allied-spike contact");
        addHudToggle(actions, "autoSpikeSpam", "Trapped-player spikes", "Predictive tangent solver auto-places against exposed trapped enemies");
        addHudToggle(actions, "antiInsta", "Anti insta", "Places a spike against a lethal incoming projectile volley");
        addHudToggle(actions, "instaSync", "Insta sync", "Predictively matches allied-player and allied-turret projectile arrivals");
        addHudToggle(actions, "boostBreak", "Shift + F boost-break", "Place, break, and move on cooldown");
        addHudToggle(actions, "boostChat", "Shift + F chat", "Send shuffled speed messages");

        const friends = addHudSection(combatPage, "Friends");
        const friendHint = document.createElement("small");
        friendHint.textContent = "Press U, then click a player to add them. Press I, then click a player to mark them as an enemy. Friends stay ignored unless they betray you.";
        const friendList = document.createElement("div");
        friendList.className = "mm-hud-friend-list";
        friendList.dataset.hudFriends = "";
        friends.append(friendHint, friendList);

        const tuning = addHudSection(configPage, "Distance tuning");
        addHudNumber(tuning, "soldierRange", "Soldier radius", "Pixels");
        addHudNumber(tuning, "combatRange", "Combat radius", "Tail behavior cutoff");
        addHudNumber(tuning, "gearHoldTicks", "Gear hold", "Minimum server ticks for Bull, Soldier, right-click Tank, and trap-breaking Tank stages");
        addHudNumber(tuning, "passiveSpikeEnemyRange", "Avoidance enemy cutoff", "Passive spike avoidance pauses when an enemy is within this many pixels");
        addHudNumber(tuning, "antiBoostRange", "Spike radius", "Pixels");
        addHudNumber(tuning, "reactionMs", "Reaction scan", "Milliseconds between live-state checks");

        const diagnostics = addHudSection(configPage, "Diagnostics");
        addHudToggle(diagnostics, "debugPanel", "Runtime debug", "Show live owner, target, trap, and cooldown reasons");
        const debugReadout = document.createElement("pre");
        debugReadout.className = "mm-hud-debug";
        debugReadout.dataset.hudDebug = "";
        debugReadout.hidden = !hudState.debugPanel;
        diagnostics.appendChild(debugReadout);
 
        const messages = addHudSection(configPage, "Chat automation");
        addHudToggle(messages, "materialReply", "Material request reply", "Tell teammates and friends your current wood and stone when they ask for materials");
        addHudToggle(messages, "killMessageEnabled", "Auto send on kill", "Posts a chat line when your kill count rises");
        const message = document.createElement("input");
        message.className = "mm-hud-message";
        message.type = "text";
        message.maxLength = 30;
        message.placeholder = "Example: gg!";
        message.value = hudState.killMessage;
        message.addEventListener("input", () => {
            hudState.killMessage = message.value.slice(0, 30);
            saveHudSettings();
            sendHudCommand({ type: "set", key: "killMessage", value: hudState.killMessage });
        });
        messages.appendChild(message);
        hudControls.set("killMessage", message);
 
        const hotkeys = addHudSection(configPage, "Hotkeys");
        const keyList = document.createElement("ul");
        keyList.className = "mm-hud-keys";
        ["U + click add friend · I + click mark enemy", "C cleanup (W/A/S/D/F/V/R/H/Z or click cancels)", "P autoheal", "Q food · F trap · V spikes · Z 3 windmills behind · H selected build", "Shift + F boost-break · Shift + T betrayal insta", "Left-click Bull · Right-click Tank"].forEach((line) => {
            const item = document.createElement("li");
            item.textContent = line;
            keyList.appendChild(item);
        });
        const reset = document.createElement("button");
        reset.className = "mm-hud-reset";
        reset.type = "button";
        reset.textContent = "Reset saved settings";
        reset.addEventListener("click", () => {
            hudState = { ...HUD_DEFAULTS };
            saveHudSettings();
            sendHudCommand({ type: "hydrate", settings: { ...HUD_DEFAULTS } });
            renderHud();
        });
        hotkeys.append(keyList, reset);
 
        root.appendChild(panel);
        document.body.appendChild(root);
        activatePage("automation");
        renderHud();
    }
 
    function scheduleHudMount() {
        const mountAll = () => {
            installKittyTheme();
            mountMetrics();
            mountHud();
        };
        if (document.body) mountAll();
        else document.addEventListener("DOMContentLoaded", mountAll, { once: true });
    }

    function compareKittyVersions(left, right) {
        const leftParts = String(left || "").match(/\d+/g) || [];
        const rightParts = String(right || "").match(/\d+/g) || [];
        const length = Math.max(leftParts.length, rightParts.length);
        for (let index = 0; index < length; index += 1) {
            const difference = Number(leftParts[index] || 0) - Number(rightParts[index] || 0);
            if (difference) return difference > 0 ? 1 : -1;
        }
        return 0;
    }

    function safeKittyDownloadUrl(candidate) {
        try {
            const url = new URL(candidate || KITTY_UPDATE_FALLBACK_URL);
            if (
                url.protocol === "https:" &&
                url.hostname === "update.greasyfork.org" &&
                /^\/scripts\/592072(?:\/|$)/.test(url.pathname)
            ) return url.href;
        } catch {
            // The fixed GreasyFork installer remains the safe fallback.
        }
        return KITTY_UPDATE_FALLBACK_URL;
    }

    function mountKittyUpdatePopup(latestVersion, downloadUrl) {
        if (!document.body || document.getElementById(KITTY_UPDATE_POPUP_ID)) return;
        try {
            if (sessionStorage.getItem(KITTY_UPDATE_DISMISS_KEY) === latestVersion) return;
        } catch {
            // A blocked session store should not prevent an update notice.
        }

        const popup = document.createElement("aside");
        popup.id = KITTY_UPDATE_POPUP_ID;
        popup.setAttribute("role", "dialog");
        popup.setAttribute("aria-labelledby", "kitty-update-title");
        popup.setAttribute("aria-describedby", "kitty-update-copy");

        const title = document.createElement("h2");
        title.id = "kitty-update-title";
        title.className = "kitty-update-title";
        title.textContent = "Update available";

        const copy = document.createElement("p");
        copy.id = "kitty-update-copy";
        copy.className = "kitty-update-copy";
        copy.textContent = "A newer Kitty Klient build is ready.";

        const versions = document.createElement("div");
        versions.className = "kitty-update-versions";
        versions.textContent = KITTY_KLIENT_VERSION + "  →  " + latestVersion;

        const download = document.createElement("a");
        download.className = "kitty-update-download";
        download.href = safeKittyDownloadUrl(downloadUrl);
        download.target = "_blank";
        download.rel = "noopener noreferrer";
        download.textContent = "Download update";

        const close = document.createElement("button");
        close.className = "kitty-update-close";
        close.type = "button";
        close.setAttribute("aria-label", "Dismiss update notice");
        close.textContent = "×";
        close.addEventListener("click", () => {
            try {
                sessionStorage.setItem(KITTY_UPDATE_DISMISS_KEY, latestVersion);
            } catch {
                // Closing still works when storage is unavailable.
            }
            popup.remove();
        });

        popup.append(title, copy, versions, download, close);
        document.body.appendChild(popup);
    }

    async function checkForKittyUpdate() {
        const controller = typeof AbortController === "function" ? new AbortController() : null;
        const timeout = window.setTimeout(() => controller && controller.abort(), 5000);
        try {
            const response = await fetch(KITTY_UPDATE_API, {
                cache: "no-store",
                credentials: "omit",
                signal: controller ? controller.signal : undefined
            });
            if (!response.ok) return;
            const release = await response.json();
            const latestVersion = typeof release.version === "string" ? release.version.trim() : "";
            if (!latestVersion || compareKittyVersions(latestVersion, KITTY_KLIENT_VERSION) <= 0) return;
            const showPopup = () => mountKittyUpdatePopup(latestVersion, release.code_url);
            if (document.body) showPopup();
            else document.addEventListener("DOMContentLoaded", showPopup, { once: true });
        } catch {
            // Update checks are optional and must never interfere with the client.
        } finally {
            window.clearTimeout(timeout);
        }
    }

    let escapeClaimedByGameMenu = false;

    function isGameSubmenuOpen() {
        return ["allianceMenu", "storeMenu", "chatHolder"].some((id) => {
            const menu = document.getElementById(id);
            if (!menu) return false;
            return menu.style.display === "block" || window.getComputedStyle(menu).display !== "none";
        });
    }

    function closeHud(root) {
        hudOpen = false;
        root.classList.add("mm-hud-collapsed");
        root.setAttribute("aria-hidden", "true");
    }

    document.addEventListener("keydown", (event) => {
        const root = document.getElementById(HUD_ID);
        if (event.key === "Escape") {
            if (!root) return;
            if (escapeClaimedByGameMenu) {
                // Do not let a held Escape key close the game menu and then
                // toggle Kitty Klient open on the first repeat event.
                event.preventDefault();
                event.stopImmediatePropagation();
                return;
            }
            if (isGameSubmenuOpen()) {
                escapeClaimedByGameMenu = true;
                closeHud(root);
                const active = document.activeElement;
                if (active && active.matches("input,textarea,[contenteditable='true']")) active.blur();
                // Keep the trusted Escape event flowing. The game's own close
                // handler dismisses store, alliance, and the chat text box.
                return;
            }
            hudOpen = root.classList.contains("mm-hud-collapsed");
            root.classList.toggle("mm-hud-collapsed", !hudOpen);
            root.setAttribute("aria-hidden", String(!hudOpen));
            event.preventDefault();
            event.stopImmediatePropagation();
            return;
        }
        if (!root) return;
        if (hudOpen && /^[wasdfvrui]$/i.test(event.key)) {
            closeHud(root);
            // Keep the real trusted key event flowing into the game so movement
            // and held actions begin immediately after the menu disappears.
        }
    }, true);

    document.addEventListener("keyup", (event) => {
        if (event.key === "Escape") escapeClaimedByGameMenu = false;
    }, true);

    window.addEventListener("MooMooKittyMetrics", (event) => {
        if (!event.detail || typeof event.detail !== "object") return;
        mountMetrics();
        const metrics = document.getElementById("kitty-klient-metrics");
        if (!metrics) return;
        const setMetric = (name, value) => {
            const field = metrics.querySelector("[data-metric='" + name + "']");
            if (field) field.textContent = value;
        };
        setMetric("ping", Number.isFinite(event.detail.ping) ? Math.round(event.detail.ping) + "ms" : "--");
        setMetric("fps", Number.isFinite(event.detail.fps) ? String(Math.round(event.detail.fps)) : "--");
        const packetText = String(Math.max(0, Number(event.detail.packets) || 0)) +
            (Number.isFinite(event.detail.pps) ? " · " + Math.round(event.detail.pps) + "/s" : "");
        setMetric("packets", packetText);
    });

    window.addEventListener("MooMooFriendPickNotice", (event) => {
        if (typeof event.detail === "string" && event.detail) {
            showZoomIndicator(event.detail);
        }
    });
 
    window.addEventListener("MooMooOPHudState", (event) => {
        if (!event.detail || typeof event.detail !== "object") return;
        const debugText = typeof event.detail.debugText === "string" ? event.detail.debugText : hudState.debugText;
        hudState = { ...normalizeHudSettings({ ...hudState, ...event.detail }), debugText };
        if (!hudSettingsSent) {
            hudSettingsSent = true;
            sendHudCommand({ type: "hydrate", settings: readHudSettings() });
        }
        saveHudSettings();
        renderHud();
    });

    window.addEventListener("MooMooFriendState", (event) => {
        const detail = event.detail;
        if (!detail || typeof detail.name !== "string") return;
        const name = detail.name.trim().slice(0, 15);
        if (!name) return;
        const key = name.toLowerCase();
        const names = Array.isArray(hudState.friendNames) ? hudState.friendNames.slice() : [];
        const existing = names.findIndex((entry) => entry.toLowerCase() === key);
        if (detail.type === "remove" && existing >= 0) names.splice(existing, 1);
        else if (detail.type === "add" && existing < 0) names.push(name);
        else return;
        hudState.friendNames = normalizeHudSettings({ friendNames: names }).friendNames;
        saveHudSettings();
        renderHud();
    });
 
    scheduleHudMount();
    void checkForKittyUpdate();
 
    function patchedViewportCode() {
        // This string replaces a matching section of the game bundle at runtime.
        return `
const __mmZoomBaseWidth = y.maxScreenWidth,
  __mmZoomBaseHeight = y.maxScreenHeight;
let __mmSoldierRange = 400,
  __mmCombatRange = 400,
  __mmGearHoldTicks = 3,
  __mmPassiveSpikeEnemyRange = 400,
  __mmAntiBoostRange = 200,
  __mmSoldierAutoEnabled = !0,
  __mmMovementGearEnabled = !0,
  __mmPassiveSpikeAvoidanceEnabled = !0,
  __mmTrapEscapeEnabled = !0,
  __mmAntiBoostEnabled = !0,
  __mmAntiBoostInstaEnabled = !0,
  __mmThreatTrapEnabled = !0,
  __mmAutoCloseSpikeEnabled = !0,
  __mmReloadSpikeEnabled = !0,
  __mmShieldDefenseEnabled = !0,
  __mmMusketRechargeEnabled = !0,
  __mmAutoPurchaseEnabled = !1,
  __mmMatThiefEnabled = !1,
  __mmMobStealEnabled = !1,
  __mmSpinningWindmillsEnabled = !1,
  __mmEspEnabled = !0,
  __mmEspLinesEnabled = !0,
  __mmPredictionGhostEnabled = !0,
  __mmCooldownBarsEnabled = !0,
  __mmBullHelmetEnabled = !0,
  __mmTankRightClickEnabled = !0,
  __mmAllItemsUnlockEnabled = !0,
  __mmInstaUiEnabled = !1,
  __mmAutoInstaEnabled = !0,
  __mmAutoSpikeInstaEnabled = !0,
  __mmAutoSpikeSpamEnabled = !0,
  __mmAntiInstaEnabled = !0,
  __mmInstaSyncEnabled = !0,
  __mmBoostBreakEnabled = !0,
  __mmBoostChatEnabled = !0,
  __mmMaterialReplyEnabled = !0,
  __mmSyncLeaderEnabled = !1,
  __mmSyncFollowerEnabled = !1,
  __mmDebugPanelEnabled = !1,
  __mmKillMessageEnabled = !0,
  __mmKillMessage = "gg",
  __mmReactionMs = 25;
const __mmShieldWeapon = 11,
  __mmToolHammer = 0,
  __mmMcGrabby = 14,
  __mmShortSword = 3,
  __mmPolearmWeapon = 5,
  __mmTurretGear = 53,
  __mmTurretGearRange = 700,
  __mmEmpHelmet = 22,
  __mmFullInstaRangeMultiplier = 1.5,
  __mmThreatTrapRange = 300,
  __mmThreatAnimalRange = 200,
  __mmThreatTrapCooldownMs = 650,
  __mmTrapCollisionPadding = 14,
  __mmTrapAlertRangeReduction = 10,
  __mmShieldDefenseRange = 240,
  __mmShieldDefenseMs = 750,
  __mmBoosterHat = 12,
  __mmSnowHat = 15,
  __mmSnowHatPrice = 600,
  __mmFlipperHat = 31,
  __mmFlipperHatPrice = 2500,
  __mmGreatHammer = 10,
  __mmKatana = 4,
  __mmMusket = 15,
  __mmAngelWings = 13,
  __mmShadowWings = 19,
  __mmBloodWings = 18,
  __mmCorruptXWings = 21;
const __mmOriginalWeaponPrerequisites =
    b && Array.isArray(b.weapons)
      ? b.weapons.map(function (__mmWeapon) {
          return __mmWeapon && __mmWeapon.pre;
        })
      : [],
  __mmOriginalItemPrerequisites =
    b && Array.isArray(b.list)
      ? b.list.map(function (__mmItem) {
          return __mmItem && __mmItem.pre;
        })
      : [];
const __mmAutoPurchaseEntries = Object.freeze({
  monkeyTail: Object.freeze({ id: 11, tail: !0, price: 2e3 }),
  soldier: Object.freeze({ id: 6, tail: !1, price: 4e3 }),
  bull: Object.freeze({ id: 7, tail: !1, price: 6e3 }),
  booster: Object.freeze({ id: 12, tail: !1, price: 6e3 }),
  emp: Object.freeze({ id: 22, tail: !1, price: 6e3 }),
  turret: Object.freeze({ id: 53, tail: !1, price: 1e4 }),
  tank: Object.freeze({ id: 40, tail: !1, price: 15e3 }),
  shadow: Object.freeze({ id: 19, tail: !0, price: 15e3 }),
  angel: Object.freeze({ id: 13, tail: !0, price: 15e3 }),
  blood: Object.freeze({ id: 18, tail: !0, price: 2e4 }),
  corrupt: Object.freeze({ id: 21, tail: !0, price: 2e4 }),
});
let _ = y.maxScreenWidth,
  L = y.maxScreenHeight;
let __mmFoodSpamTimer = 0;
let __mmAutoHealTimer = 0,
  __mmAutoHealEnabled = !0,
  __mmAutoHealWasHealing = !1,
  __mmAutoHealPending = !1,
  __mmAutoHealBitesRemaining = 0,
  __mmAutoHealNextBiteAt = 0,
  __mmAutoHealLastObservedHealth = null,
  __mmAutoHealLastDamageAt = 0,
  __mmAutoHealShameCount = 0,
  __mmLastWeapon = null,
  __mmLastBuildItem = null,
  __mmAutoHealWeapon = null;
let __mmAutoPurchaseTimer = 0,
  __mmAutoPurchasePending = null;
let __mmMatThiefTimer = 0,
  __mmMatThiefReleaseTimer = 0,
  __mmMatThiefAimAngle = null,
  __mmMatThiefReturnAngle = null,
  __mmMatThiefRestoreTool = null,
  __mmMatThiefAttackHeld = !1;
const __mmMatThiefReservations = new WeakMap();
let __mmCleanupActive = !1,
  __mmCleanupTimer = 0,
  __mmCleanupProgressTimer = 0,
  __mmCleanupOriginX = 0,
  __mmCleanupOriginY = 0,
  __mmCleanupTarget = null,
  __mmCleanupSavedTool = null,
  __mmCleanupWeapon = null,
  __mmCleanupAttackHeld = !1,
  __mmCleanupAimAngle = null,
  __mmCleanupMoveAngle = null,
  __mmCleanupTargetHealth = null,
  __mmCleanupProgressAt = 0,
  __mmCleanupEmptySince = 0,
  __mmCleanupChatStep = 0;
const __mmCleanupReservations = new WeakMap();
let __mmMobStealTimer = 0,
  __mmMobStealReleaseTimer = 0,
  __mmMobStealAimAngle = null,
  __mmMobStealRestoreTool = null,
  __mmMobStealRestoreHat = null,
  __mmMobStealRestoreTail = null,
  __mmMobStealAttackHeld = !1;
const __mmMobStealMotion = Object.create(null),
  __mmMobStealReservations = Object.create(null);
let __mmAutoInstaTimer = 0;
let __mmAutoSpikeInstaTimer = 0,
  __mmAutoSpikeInstaLastAt = 0,
  __mmSpikeTickStrikeTimer = 0,
  __mmSpikeTickStrikeTool = null,
  __mmSpikeTickStrikeHat = null,
  __mmSpikeTickStrikeAimAngle = null,
  __mmSpikeTickStrikeHeld = !1;
const __mmAutoSpikeInstaMotion = Object.create(null);
let __mmAutoSpikeSpamTimer = 0,
  __mmAutoSpikeSpamLastAt = 0,
  __mmAutoSpikeSpamGhost = null,
  __mmAutoSpikeSpamCandidateKey = null,
  __mmAutoSpikeSpamCandidateSince = 0,
  __mmAutoSpikeSpamAimAngle = null,
  __mmAutoSpikeSpamAimUntil = 0;
const __mmAutoSpikeSpamReservations = [];
const __mmAutoSpikeSpamMotion = Object.create(null);
let __mmAntiInstaTimer = 0,
  __mmAntiInstaLastAt = 0,
  __mmAntiInstaUntil = 0,
  __mmAntiInstaActionTimer = 0;
let __mmInstaSyncLoopTimer = 0,
  __mmInstaSyncTimer = 0,
  __mmInstaSyncReleaseTimer = 0,
  __mmInstaSyncPending = !1,
  __mmInstaSyncFiring = !1,
  __mmInstaSyncLastAt = 0,
  __mmInstaSyncRestoreTool = null,
  __mmInstaSyncRestoreHat = null,
  __mmInstaSyncWeaponHeld = !1;
const __mmInstaSyncProjectileStates = new WeakMap();
let __mmMovementGearTimer = 0,
  __mmMovementGearPreviousHat = null,
  __mmMovementGearPreviousTail = null,
  __mmProximityTailPrevious = null;
let __mmPassiveSpikeMotionTimer = 0,
  __mmPassiveSpikePendingTimer = 0,
  __mmPassiveSpikeCorrectionTimer = 0,
  __mmPassiveSpikeCorrecting = !1,
  __mmPassiveSpikeMotion = null;
let __mmFlipperPurchaseAt = 0,
  __mmSnowPurchaseAt = 0;
let __mmShiftSpeedActive = !1,
  __mmShiftMode = 0,
  __mmShiftPreviousHat = null,
  __mmShiftPreviousTail = null,
  __mmShiftRestoreTimer = 0,
  __mmShiftSpeedTimer = 0,
  __mmShiftGearPurchaseTimer = 0;
let __mmBoostBreakTimer = 0,
  __mmBoostBreakHeld = !1,
  __mmBoostBreakCooldownWeapon = null,
  __mmBoostBreakReadyAt = 0,
  __mmBoostBreakStrikeTimer = 0,
  __mmBoostBreakStriking = !1,
  __mmBoostBreakPreviousWeapon = null,
  __mmBoostMoveDirection = null,
  __mmBoostTankPreviousHat = null,
  __mmBoostChatTimer = 0,
  __mmBoostChatOrder = [],
  __mmBoostChatIndex = 0;
let __mmSoldierAutoTimer = 0,
  __mmSoldierRestoreTimer = 0,
  __mmSoldierPreviousHat = null;
let __mmShieldDefenseTimer = 0,
  __mmShieldDefenseWeapon = null;
let __mmAntiBoostTimer = 0,
  __mmAntiBoostLast = 0,
  __mmAntiBoostBlockTimer = 0,
  __mmAntiBoostMoveTimer = 0,
  __mmAntiBoostBlockTool = null,
  __mmAntiBoostBlockAimAngle = null,
  __mmAntiBoostBackingUp = !1;
let __mmThreatTrapTimer = 0,
  __mmThreatTrapLastAt = 0,
  __mmThreatTrapLastKey = null;
const __mmThreatTrapPlacements = Object.create(null);
let __mmTrapAlertTimer = 0,
  __mmTrapAlertUntil = 0,
  __mmTrapChatIncidentActive = !1;
let __mmFriendlyTrapChatTimer = 0,
  __mmFriendlyTrapChatLastAt = 0;
const __mmFriendlyTrapChatIncidents = Object.create(null);
let __mmReloadSpikeTimer = 0,
  __mmReloadSpikePlaced = !1,
  __mmTurretReloadUntil = 0;
const __mmEnemyBoostTrail = {};
const __mmSyncProtocol = "kitty-klient-tab-sync-v1";
const __mmSyncStorageKey = "kitty-klient-tab-sync-state-v1";
let __mmSyncChannel = null;
try {
  typeof BroadcastChannel === "function" &&
    (__mmSyncChannel = new BroadcastChannel(__mmSyncProtocol));
} catch (__mmSyncChannelError) {}
const __mmSyncTabId = (function () {
  try {
    const __mmStored = sessionStorage.getItem("kitty-klient-tab-sync-id");
    if (__mmStored) return __mmStored;
    const __mmId =
      Date.now().toString(36) + "-" + Math.random().toString(36).slice(2, 10);
    return (sessionStorage.setItem("kitty-klient-tab-sync-id", __mmId), __mmId);
  } catch (__mmStorageError) {
    return Date.now().toString(36) + "-" + Math.random().toString(36).slice(2, 10);
  }
})();
let __mmSyncTimer = 0,
  __mmSyncMoveActive = !1,
  __mmSyncLeaderState = null,
  __mmSyncSelectionBlockedUntil = 0,
  __mmSyncGearPairDispatch = !1,
  __mmSyncStatus = "off";
let __mmBuildSpamTimer = 0,
  __mmBuildSpamKey = 0;
let __mmWindmillRowTimer = 0,
  __mmWindmillHoldTimer = 0,
  __mmWindmillHeld = !1,
  __mmWindmillRowWeapon = null;
let __mmSpinningWindmillTimer = 0,
  __mmSpinningWindmillAngle = 0,
  __mmSpinningWindmillLastAt = 0;
const __mmSpinningWindmillReservations = [];
let __mmWeaponRechargeTimer = 0,
  __mmWeaponRechargePreviousTool = null,
  __mmWeaponRechargeActiveWeapon = null,
  __mmWeaponRechargeSelectAt = 0;
let __mmPredictionLastX = null,
  __mmPredictionLastY = null,
  __mmPredictionLastAt = 0;
let __mmPrimaryHeld = !1,
  __mmSecondaryHeld = !1,
  __mmHeldAttackTimer = 0,
  __mmPrimaryBullArmTimer = 0,
  __mmPrimaryBullSwingPending = !1,
  __mmPrimaryManualReadyAt = 0,
  __mmSecondaryTankArmTimer = 0,
  __mmSecondaryTankSwingPending = !1,
  __mmSecondaryManualReadyAt = 0,
  __mmSecondaryGearStage = null,
  __mmSecondaryGearTimer = 0,
  __mmSecondaryTankHoldUntil = 0,
  __mmSecondarySoldierHoldUntil = 0,
  __mmPrimaryClickHat = null,
  __mmPrimaryClickTail = null,
  __mmPrimaryGearStage = null,
  __mmPrimaryGearTimer = 0,
  __mmPrimaryBullHoldUntil = 0,
  __mmPrimarySoldierHoldUntil = 0,
  __mmRightClickHat = null,
  __mmLastNormalHat = 0;
// Equipment packets are acknowledged by the game state. Keep local rendering
// authoritative and merely debounce duplicate requests while that update is in
// flight; directly rewriting skinIndex/tailIndex caused visible frame flicker.
let __mmPendingHat = null,
  __mmPendingHatAt = 0,
  __mmPendingTail = null,
  __mmPendingTailAt = 0;
let __mmTrapAttackTimer = 0,
  __mmTrapAttackActive = !1,
  __mmTrapAimAngle = null,
  __mmTrapWeapon = null,
  __mmTrapHat = null,
  __mmTrapAttackHeld = !1,
  __mmTrapAttackHeldWeapon = null,
  __mmTrapTankHoldUntil = 0,
  __mmTrapWeaponSelectAt = 0,
  __mmTrapHatRestoreTimer = 0,
  __mmTrapHatRestoreAttempts = 0,
  __mmTrapBuildTimer = 0,
  __mmTrapBuildAttemptKey = null,
  __mmTrapBuildWeapon = null;
let __mmLiveStateTimer = 0,
  __mmDebugHudTimer = 0;
let __mmMetricFrames = 0,
  __mmMetricPackets = 0,
  __mmMetricPacketWindow = 0,
  __mmMetricFps = 0,
  __mmMetricPps = 0,
  __mmMetricUpdatedAt = performance.now();
let __mmMouseAimReturnTimer = 0,
  __mmSendingMouseAimReturn = !1;
const __mmBreakableHealth = new WeakMap(),
  __mmRecentPlayerSwings = Object.create(null),
  __mmPlayerToolCooldowns = Object.create(null);
const __mmFriendNames = new Map(),
  __mmFriendEnemies = new Set(),
  __mmFriendAttackWindows = Object.create(null);
let __mmFriendPickMode = null;
const __mmLiveState = {
  updatedAt: 0,
  alive: !1,
  enemies: [],
  animals: [],
  nearestEnemy: null,
  nearestEnemyDistance: Infinity,
  nearbyTrap: null,
  trapped: !1,
  health: 0,
  maxHealth: 0,
  primaryReady: !1,
  secondaryReady: !1,
};
const __mmActionPriorities = Object.freeze({
  trapEscape: 100,
  antiInsta: 95,
  autoHeal: 90,
  insta: 80,
  spikeTickStrike: 82,
  instaSync: 75,
  shieldDefense: 85,
  antiBoostBlock: 88,
  boostBreak: 65,
  manualAttack: 60,
  cleanup: 55,
  spikeSpam: 93,
  threatTrap: 45,
  reloadSpike: 40,
  mobSteal: 38,
  matThief: 35,
  spinningWindmills: 15,
  weaponRecharge: 20,
  movementGear: 10,
  soldierGear: 10,
});
let __mmActionOwner = "idle",
  __mmActionReason = "waiting",
  __mmActionSince = 0,
  __mmActionLastDecision = "waiting";
function __mmActionPriority(__mmOwner) {
  return Number(__mmActionPriorities[__mmOwner]) || 0;
}
function __mmActionAvailable(__mmOwner) {
  return __mmActionOwner === "idle" || __mmActionOwner === __mmOwner;
}
function __mmActionCanPreempt(__mmOwner) {
  return (
    __mmActionAvailable(__mmOwner) ||
    __mmActionPriority(__mmOwner) > __mmActionPriority(__mmActionOwner)
  );
}
function __mmActionClaim(__mmOwner, __mmReason) {
  if (
    __mmActionOwner === "cleanup" &&
    __mmOwner !== "cleanup" &&
    __mmActionPriority(__mmOwner) > __mmActionPriority("cleanup")
  )
    __mmStopCleanup("preempted by " + __mmOwner, !1);
  if (
    __mmActionOwner === "spikeTickStrike" &&
    __mmOwner !== "spikeTickStrike" &&
    __mmActionPriority(__mmOwner) > __mmActionPriority("spikeTickStrike")
  )
    __mmStopSpikeTickStrike("preempted by " + __mmOwner);
  if (
    __mmActionOwner === "antiBoostBlock" &&
    __mmOwner !== "antiBoostBlock" &&
    __mmActionPriority(__mmOwner) > __mmActionPriority("antiBoostBlock")
  )
    __mmStopAntiBoostBlock("preempted by " + __mmOwner);
  if (
    __mmActionOwner === "weaponRecharge" &&
    __mmOwner !== "weaponRecharge" &&
    __mmActionPriority(__mmOwner) > __mmActionPriority("weaponRecharge")
  )
    __mmPauseWeaponRecharge(!0);
  if (
    __mmActionOwner === "matThief" &&
    __mmOwner !== "matThief" &&
    __mmActionPriority(__mmOwner) > __mmActionPriority("matThief")
  )
    __mmFinishMatThief("preempted by " + __mmOwner);
  if (
    __mmActionOwner === "mobSteal" &&
    __mmOwner !== "mobSteal" &&
    __mmActionPriority(__mmOwner) > __mmActionPriority("mobSteal")
  )
    __mmFinishMobSteal("preempted by " + __mmOwner);
  if (!__mmActionAvailable(__mmOwner)) {
    __mmActionLastDecision =
      __mmOwner +
      " blocked by " +
      __mmActionOwner +
      " (requested " +
      __mmActionPriority(__mmOwner) +
      ", active " +
      __mmActionPriority(__mmActionOwner) +
      "): " +
      (__mmReason || "busy");
    return !1;
  }
  if (__mmActionOwner === __mmOwner) {
    ((__mmActionReason = __mmReason || __mmActionReason),
      (__mmActionLastDecision = __mmOwner + ": " + __mmActionReason));
    return !0;
  }
  ((__mmActionOwner = __mmOwner),
    (__mmActionReason = __mmReason || "active"),
    (__mmActionSince = Date.now()),
    (__mmActionLastDecision = __mmOwner + ": " + __mmActionReason));
  return !0;
}
function __mmActionRelease(__mmOwner, __mmReason) {
  if (__mmActionOwner !== __mmOwner) return !1;
  ((__mmActionOwner = "idle"),
    (__mmActionReason = "idle"),
    (__mmActionSince = 0),
    (__mmActionLastDecision = __mmOwner + ": " + (__mmReason || "complete")));
  return !0;
}
function __mmActionMayRestore(__mmOwner) {
  return __mmActionOwner === __mmOwner || __mmActionOwner === "idle";
}
function __mmUpdateLiveState() {
  const __mmNow = Date.now(),
    __mmEnemies = [],
    __mmAnimals = [],
    __mmSeenEntities = Object.create(null);
  let __mmNearest = null,
    __mmNearestDistance = Infinity;
  if (!v || !v.alive) {
    ((__mmLiveState.updatedAt = __mmNow),
      (__mmLiveState.alive = !1),
      (__mmLiveState.enemies = __mmEnemies),
      (__mmLiveState.animals = __mmAnimals),
      (__mmLiveState.nearestEnemy = null),
      (__mmLiveState.nearestEnemyDistance = Infinity),
      (__mmLiveState.nearbyTrap = null),
      (__mmLiveState.trapped = !1));
    return __mmLiveState;
  }
  if (typeof E !== "undefined" && Array.isArray(E))
    for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex += 1) {
      const __mmPlayer = E[__mmIndex];
      const __mmKey = __mmThreatTargetKey(__mmPlayer);
      __mmKey != null && (__mmSeenEntities[__mmKey] = !0);
      if (!__mmIsEnemyPlayer(__mmPlayer)) continue;
      const __mmDistance = Math.hypot(__mmPlayer.x - v.x, __mmPlayer.y - v.y);
      if (!Number.isFinite(__mmDistance)) continue;
      __mmEnemies.push(__mmPlayer);
      if (__mmDistance < __mmNearestDistance) {
        ((__mmNearest = __mmPlayer), (__mmNearestDistance = __mmDistance));
      }
    }
  if (typeof N !== "undefined" && Array.isArray(N))
    for (let __mmIndex = 0; __mmIndex < N.length; __mmIndex += 1) {
      const __mmAnimal = N[__mmIndex];
      const __mmKey = __mmThreatTargetKey(__mmAnimal);
      __mmKey != null && (__mmSeenEntities[__mmKey] = !0);
      __mmAnimal && __mmAnimal.active !== !1 && __mmAnimals.push(__mmAnimal);
    }
  for (const __mmKey in __mmThreatTrapPlacements)
    __mmSeenEntities[__mmKey] || delete __mmThreatTrapPlacements[__mmKey];
  for (const __mmKey in __mmUnknownTeamSeen)
    __mmSeenEntities[__mmKey] || delete __mmUnknownTeamSeen[__mmKey];
  const __mmTrap = __mmNearestLockingTrap();
  ((__mmLiveState.updatedAt = __mmNow),
    (__mmLiveState.alive = !0),
    (__mmLiveState.enemies = __mmEnemies),
    (__mmLiveState.animals = __mmAnimals),
    (__mmLiveState.nearestEnemy = __mmNearest),
    (__mmLiveState.nearestEnemyDistance = __mmNearestDistance),
    (__mmLiveState.nearbyTrap = __mmTrap),
    (__mmLiveState.trapped = !!(v.lockMove || __mmTrap)),
    (__mmLiveState.health = Number(v.health) || 0),
    (__mmLiveState.maxHealth = Number(v.maxHealth) || 0),
    (__mmLiveState.primaryReady = !!__mmWeaponReady(v.weapons && v.weapons[0])),
    (__mmLiveState.secondaryReady = !!__mmWeaponReady(v.weapons && v.weapons[1])));
  return __mmLiveState;
}
function __mmLiveStateFresh() {
  return Date.now() - __mmLiveState.updatedAt <= 2 * __mmFastCheckMs();
}
function __mmCurrentNearbyTrap() {
  return __mmLiveStateFresh() ? __mmLiveState.nearbyTrap : __mmNearestLockingTrap();
}
function __mmIsTrapped() {
  return !!(v && v.alive && (v.lockMove || __mmCurrentNearbyTrap()));
}
function __mmRuntimeDebugText() {
  const __mmState = __mmLiveState,
    __mmEnemy = __mmState.nearestEnemy,
    __mmReload = v && v.weapons
      ? "main " + (__mmState.primaryReady ? "ready" : "reload") +
        " · secondary " + (__mmState.secondaryReady ? "ready" : "reload")
      : "weapons unavailable",
    __mmOwnerAge = __mmActionSince ? Date.now() - __mmActionSince : 0;
  return [
    "owner: " + __mmActionOwner + (__mmActionSince ? " (" + __mmOwnerAge + "ms)" : ""),
    "reason: " + __mmActionReason,
    "last: " + __mmActionLastDecision,
    "enemy: " +
      (__mmEnemy
        ? String(__mmEnemy.sid) + " at " + Math.round(__mmState.nearestEnemyDistance)
        : "none"),
    "trap: " + (__mmState.trapped ? "locked/collision" : "clear"),
    "reload: " + __mmReload,
    "scan: " + __mmReactionMs + "ms · state age " +
      (Date.now() - __mmState.updatedAt) + "ms",
  ].join("\\n");
}
function __mmStartLiveState() {
  if (__mmLiveStateTimer) return;
  (__mmUpdateLiveState(),
    (__mmLiveStateTimer = setInterval(__mmUpdateLiveState, __mmFastCheckMs())));
}
function __mmStartDebugHud() {
  __mmDebugHudTimer ||
    (__mmDebugHudTimer = setInterval(function () {
      __mmDebugPanelEnabled && __mmPublishHudState();
    }, 200));
}
const __mmUnknownTeamSeen = {},
  __mmUnknownTeamGraceMs = 1500;
const __mmBoostChatLines = [
  "WHEEEEEE!",
  "Wooo-hooo!",
  "ZOOOOOM!",
  "Can't catch me!",
  "I AM SPEEEEED!",
  "I'M COMING FOR YOU!",
  "AAAHHHHH!",
];
const __mmOriginalSelect = je;
je = function (__mmItem, __mmIsWeapon) {
  __mmIsWeapon
    ? (__mmLastWeapon = __mmItem)
    : __mmIsPlaceableItem(__mmItem) && (__mmLastBuildItem = __mmItem);
  const __mmResult = __mmOriginalSelect(__mmItem, __mmIsWeapon);
  return (__mmSyncPublishSelection(__mmItem, __mmIsWeapon), __mmResult);
};
function __mmPrepareTrademarkNameInput() {
  // Do not touch MooMoo's minified name-input binding here. This patch block is
  // inserted before that top-level const is initialized in the current bundle,
  // so even testing the binding aborts the whole module through the TDZ.
  const __mmNameInput = document.getElementById("nameInput");
  if (!__mmNameInput) return 13;
  const __mmStoredOriginal = Number(__mmNameInput.dataset.kittyOriginalNameMax),
    __mmOriginalMax =
      Number.isFinite(__mmStoredOriginal) && __mmStoredOriginal > 2
        ? __mmStoredOriginal
        : Math.max(3, Number(__mmNameInput.maxLength) || 15),
    __mmLimit = Math.max(1, __mmOriginalMax - 2),
    __mmRaw = String(__mmNameInput.value || "")
      .replace(/^(?:k-)+/i, "")
      .slice(0, __mmLimit);
  (__mmNameInput.dataset.kittyOriginalNameMax = String(__mmOriginalMax),
    __mmNameInput.dataset.kittyNameLimit = String(__mmLimit),
    (__mmNameInput.maxLength = __mmLimit),
    __mmNameInput.setAttribute("maxlength", String(__mmLimit)),
    (__mmNameInput.placeholder = "Enter Name (k- added)"),
    __mmNameInput.value !== __mmRaw && (__mmNameInput.value = __mmRaw));
  return __mmLimit;
}
function __mmTrademarkPlayerName(__mmName) {
  const __mmLimit = __mmPrepareTrademarkNameInput(),
    __mmRaw = String(__mmName || "")
      .replace(/^(?:k-)+/i, "")
      .slice(0, __mmLimit);
  return "k-" + __mmRaw;
}
__mmPrepareTrademarkNameInput();
const __mmOriginalSocketSend = O.send;
O.send = function () {
  if (arguments[0] === "H" && !__mmAllowUpgradePacket(arguments[1]))
    return;
  if (
    arguments[0] === "M" &&
    arguments[1] &&
    typeof arguments[1] === "object"
  )
    arguments[1] = {
      ...arguments[1],
      name: __mmTrademarkPlayerName(arguments[1].name),
    };
  const __mmResult = __mmOriginalSocketSend.apply(this, arguments);
  return (
    (__mmMetricPackets += 1),
    (__mmMetricPacketWindow += 1),
    __mmSyncObserveSocketSend(arguments),
    __mmObserveForcedDirectionPacket(arguments),
    __mmResult
  );
};
const __mmOriginalPlayerAttack = Pl;
const __mmOriginalHealthUpdate = $l;
const __mmOriginalAnimalUpdate = Xl;
const __mmOriginalPlayerStatUpdate = Kl;
const __mmOriginalChatDisplay = dl;
const __mmOriginalUpgradeDisplay = Un;
const __mmOriginalObjectRender = Ge;
const __mmOriginalObjectHit = Wl;
const __mmOriginalAimDirection = Ci;
const __mmOriginalRender = Cl;
Ci = function () {
  return __mmTrapAttackActive && Number.isFinite(__mmTrapAimAngle)
    ? __mmTrapAimAngle
    : Number.isFinite(__mmMatThiefAimAngle)
      ? __mmMatThiefAimAngle
    : Number.isFinite(__mmMobStealAimAngle)
      ? __mmMobStealAimAngle
    : Number.isFinite(__mmAntiBoostBlockAimAngle)
      ? __mmAntiBoostBlockAimAngle
    : Number.isFinite(__mmSpikeTickStrikeAimAngle)
      ? __mmSpikeTickStrikeAimAngle
    : __mmCleanupActive && Number.isFinite(__mmCleanupAimAngle)
      ? __mmCleanupAimAngle
    : Date.now() < __mmAutoSpikeSpamAimUntil &&
        Number.isFinite(__mmAutoSpikeSpamAimAngle)
      ? __mmAutoSpikeSpamAimAngle
    : __mmOriginalAimDirection.apply(this, arguments);
};
function __mmRawMouseAimDirection() {
  // Read the cursor coordinates directly so X/lockDir cannot freeze this at
  // the pre-automation angle. The normal Ci helper intentionally preserves
  // its old angle while X is enabled.
  const __mmMouseX = Number(On) - Number(De) / 2,
    __mmMouseY = Number(Hn) - Number(Ae) / 2;
  if (Number.isFinite(__mmMouseX) && Number.isFinite(__mmMouseY)) {
    const __mmDirectAngle = Math.atan2(__mmMouseY, __mmMouseX);
    return typeof M.fixTo === "function"
      ? M.fixTo(__mmDirectAngle, 2)
      : __mmDirectAngle;
  }
  let __mmAngle = 0;
  try {
    __mmAngle = Number(__mmOriginalAimDirection());
  } catch (__mmMouseAimError) {}
  // Zero is a valid direction (cursor directly on the positive X axis), so
  // never use a truthiness fallback here.
  return Number.isFinite(__mmAngle) ? __mmAngle : 0;
}
function __mmForcedDirectionStillActive() {
  return !!(
    (__mmTrapAttackActive && Number.isFinite(__mmTrapAimAngle)) ||
    Number.isFinite(__mmMatThiefAimAngle) ||
    Number.isFinite(__mmMobStealAimAngle) ||
    Number.isFinite(__mmAntiBoostBlockAimAngle) ||
    Number.isFinite(__mmSpikeTickStrikeAimAngle) ||
    (__mmCleanupActive && Number.isFinite(__mmCleanupAimAngle)) ||
    (Date.now() < __mmAutoSpikeSpamAimUntil &&
      Number.isFinite(__mmAutoSpikeSpamAimAngle)) ||
    __mmInsta.isActive() ||
    __mmInstaSyncPending ||
    __mmInstaSyncFiring
  );
}
function __mmReturnDirectionToMouse() {
  __mmMouseAimReturnTimer = 0;
  if (!v || !v.alive) return;
  if (__mmForcedDirectionStillActive()) {
    __mmMouseAimReturnTimer = setTimeout(
      __mmReturnDirectionToMouse,
      __mmFastCheckMs(),
    );
    return;
  }
  const __mmAngle = __mmRawMouseAimDirection();
  try {
    // Update the game's cached aim as well as the server. When X is active,
    // Ci returns this cache instead of sampling the cursor on the next frame.
    ((It = __mmAngle),
      (__mmSendingMouseAimReturn = !0),
      O.send("D", __mmAngle));
  } finally {
    __mmSendingMouseAimReturn = !1;
  }
}
function __mmScheduleMouseAimReturn() {
  if (__mmSendingMouseAimReturn) return;
  __mmMouseAimReturnTimer && clearTimeout(__mmMouseAimReturnTimer);
  __mmMouseAimReturnTimer = setTimeout(
    __mmReturnDirectionToMouse,
    __mmServerTickMs(),
  );
}
function __mmObserveForcedDirectionPacket(__mmArgs) {
  if (__mmSendingMouseAimReturn || !__mmArgs) return;
  const __mmPacket = __mmArgs[0];
  if (
    __mmPacket === "F" &&
    __mmArgs[2] != null &&
    Number.isFinite(Number(__mmArgs[2]))
  ) {
    __mmScheduleMouseAimReturn();
    return;
  }
  if (
    __mmPacket !== "D" ||
    __mmArgs[1] == null ||
    !Number.isFinite(Number(__mmArgs[1]))
  )
    return;
  const __mmSent = Number(__mmArgs[1]),
    __mmMouse = __mmRawMouseAimDirection(),
    __mmDifference = Math.abs(
      Math.atan2(
        Math.sin(__mmSent - __mmMouse),
        Math.cos(__mmSent - __mmMouse),
      ),
    );
  __mmDifference > 0.001 && __mmScheduleMouseAimReturn();
}
// R insta owns one short-lived interaction at a time. It deliberately uses the
// same client actions as normal input and yields to safety/manual automation.
// State transitions are intentionally limited to:
// idle -> validate -> arm -> waitForRange -> executeBurst -> cleanup -> idle.
const __mmInsta = {
  state: "idle",
  timer: 0,
  targetSid: null,
  targetOptional: !1,
  automatic: !1,
  betrayal: !1,
  snapshot: null,
  primaryWeapon: null,
  pendingSecondaryWeapon: null,
  attackHeld: !1,
  trapHandoff: null,
  isActive() {
    return this.state !== "idle" && this.state !== "cleanup";
  },
  isEmergencyHealth() {
    return !!(
      v &&
      v.alive &&
      Number(v.health) <= Math.max(20, Number(v.maxHealth) * 0.2)
    );
  },
  runtimeReady() {
    return !!(
      typeof v !== "undefined" &&
      v &&
      typeof b !== "undefined" &&
      b &&
      b.weapons &&
      b.list &&
      typeof E !== "undefined" &&
      Array.isArray(E) &&
      typeof Rt === "function" &&
      typeof je === "function" &&
      typeof O !== "undefined" &&
      O &&
      typeof O.send === "function" &&
      typeof Ci === "function" &&
      typeof y !== "undefined" &&
      y
    );
  },
  tick() {
    return __mmServerTickMs();
  },
  schedule(__mmCallback) {
    this.timer && clearTimeout(this.timer);
    this.timer = setTimeout(() => {
      this.timer = 0;
      __mmCallback();
    }, this.tick());
  },
  isPriorityConflict() {
    const __mmTrapHandoffAvailable = !!(
      __mmIsTrapped() &&
      (__mmActionOwner === "trapEscape" || __mmTrapAttackActive)
    );
    return !!(
      !v ||
      !v.alive ||
      (!__mmActionCanPreempt("insta") && !__mmTrapHandoffAvailable) ||
      __mmPrimaryHeld ||
      __mmSecondaryHeld ||
      (__mmTrapAttackActive && !__mmTrapHandoffAvailable) ||
      __mmBoostBreakHeld ||
      __mmBuildSpamTimer ||
      __mmFoodSpamTimer ||
      Date.now() < __mmAntiInstaUntil ||
      __mmInstaSyncPending ||
      __mmInstaSyncFiring ||
      (this.isEmergencyHealth() && !__mmIsTrapped())
    );
  },
  suspendTrapEscape() {
    if (!__mmIsTrapped() || !__mmTrapEscapeEnabled) return;
    this.trapHandoff = {
      resume: !0,
      weapon:
        __mmTrapWeapon != null ? __mmTrapWeapon : __mmSelectedWeapon(),
      hat: __mmTrapHat != null ? __mmTrapHat : v.skinIndex,
    };
    (__mmTrapAttackActive || __mmActionOwner === "trapEscape") &&
      __mmStopTrapAttack();
  },
  capture() {
    this.snapshot = {
      weapon:
        this.trapHandoff && this.trapHandoff.weapon != null
          ? this.trapHandoff.weapon
          : __mmSelectedWeapon(),
      hat:
        this.trapHandoff && this.trapHandoff.hat != null
          ? this.trapHandoff.hat
          : v.skinIndex,
      tail: v.tailIndex,
      primaryHeld: __mmPrimaryHeld,
      secondaryHeld: __mmSecondaryHeld,
      heldPulse: !!__mmHeldAttackTimer,
      movementGear: __mmMovementGearEnabled,
      soldierAuto: __mmSoldierAutoEnabled,
      autoHeal: __mmAutoHealEnabled,
    };
  },
  nearestEnemy() {
    if (__mmLiveStateFresh()) return __mmLiveState.nearestEnemy;
    if (!v || !v.alive || !Array.isArray(E)) return null;
    let __mmClosest = null;
    let __mmClosestDistance = Infinity;
    for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex += 1) {
      const __mmPlayer = E[__mmIndex];
      if (
        !__mmIsEnemyPlayer(__mmPlayer) ||
        !Number.isFinite(Number(__mmPlayer.x)) ||
        !Number.isFinite(Number(__mmPlayer.y))
      )
        continue;
      const __mmDx = __mmPlayer.x - v.x;
      const __mmDy = __mmPlayer.y - v.y;
      const __mmDistance = __mmDx * __mmDx + __mmDy * __mmDy;
      if (__mmDistance < __mmClosestDistance) {
        __mmClosest = __mmPlayer;
        __mmClosestDistance = __mmDistance;
      }
    }
    return __mmClosest;
  },
  target() {
    if (this.targetSid == null) return null;
    let __mmTarget = null;
    try {
      __mmTarget = Rt(this.targetSid);
    } catch (__mmLookupError) {}
    if (!__mmTarget && Array.isArray(E)) {
      for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex += 1) {
        const __mmPlayer = E[__mmIndex];
        if (__mmPlayer && String(__mmPlayer.sid) === String(this.targetSid)) {
          __mmTarget = __mmPlayer;
          break;
        }
      }
    }
    return __mmTarget &&
      String(__mmTarget.sid) === String(this.targetSid) &&
      (__mmIsEnemyPlayer(__mmTarget) ||
        (this.betrayal &&
          __mmTarget !== v &&
          __mmTarget.alive &&
          __mmTarget.visible)) &&
      Number.isFinite(Number(__mmTarget.x)) &&
      Number.isFinite(Number(__mmTarget.y))
      ? __mmTarget
      : null;
  },
  weaponData(__mmWeapon) {
    return b && b.weapons && __mmWeapon != null ? b.weapons[__mmWeapon] : null;
  },
  supportedPrimary() {
    if (!v || !v.alive || !v.weapons) return null;
    const __mmWeapon = v.weapons[0];
    if (
      __mmWeapon !== __mmShortSword &&
      __mmWeapon !== __mmKatana &&
      __mmWeapon !== __mmPolearmWeapon
    )
      return null;
    const __mmData = this.weaponData(__mmWeapon);
    return __mmData &&
      __mmData.projectile == null &&
      __mmWeapon;
  },
  inRange(__mmWeapon, __mmTarget) {
    const __mmData = this.weaponData(__mmWeapon);
    const __mmRange = __mmData && Number(__mmData.range);
    if (
      !v ||
      !__mmTarget ||
      !Number.isFinite(__mmRange) ||
      __mmRange <= 0
    )
      return !1;
    const __mmReach =
      (__mmRange +
        (Number(v.scale) || 0) +
        (Number(__mmTarget.scale) || 0)) *
      __mmFullInstaRangeMultiplier;
    return Math.hypot(__mmTarget.x - v.x, __mmTarget.y - v.y) <= __mmReach;
  },
  canFullBurst(__mmTarget) {
    const __mmPrimary = this.supportedPrimary(),
      __mmSecondary = v && v.weapons && v.weapons[1],
      __mmSecondaryData = this.weaponData(__mmSecondary);
    return !!(
      __mmPrimary != null &&
      __mmTarget &&
      this.inRange(__mmPrimary, __mmTarget) &&
      __mmSecondary != null &&
      __mmSecondary !== __mmPrimary &&
      __mmSecondary !== __mmShieldWeapon &&
      __mmSecondaryData &&
      !__mmSecondaryData.shield
    );
  },
  aim(__mmTarget) {
    return __mmTarget
      ? Math.atan2(__mmTarget.y - v.y, __mmTarget.x - v.x)
      : Ci();
  },
  damageTail() {
    if (!v || !v.alive) return null;
    if (v.tails && v.tails[__mmCorruptXWings]) return __mmCorruptXWings;
    return (this.snapshot && this.snapshot.tail === 11) || v.tailIndex === 11
      ? 0
      : null;
  },
  context(__mmRequireRange) {
    if (
      (!__mmInstaUiEnabled && !this.automatic) ||
      !this.runtimeReady() ||
      this.isPriorityConflict()
    )
      return null;
    const __mmPrimary = this.supportedPrimary();
    if (__mmPrimary == null) return null;
    const __mmTarget = this.target();
    if (!__mmTarget && !this.targetOptional) return null;
    if (__mmRequireRange && __mmTarget && !this.inRange(__mmPrimary, __mmTarget))
      return null;
    return { primary: __mmPrimary, target: __mmTarget };
  },
  selectDamageGear() {
    if (!v || !v.alive) return;
    // Dispatch both equipment packets from this same local/server-tick phase.
    __mmEquipGearPair(
      v.skins && v.skins[7] ? 7 : null,
      this.damageTail(),
      !0,
    );
  },
  selectSecondaryDamageGear() {
    if (!v || !v.alive) return;
    // Re-send the damage tail in the exact Turret packet phase too. This keeps
    // the secondary stage paired even if the Bull-stage acknowledgement has
    // not reached the client yet.
    __mmEquipGearPair(
      v.skins && v.skins[__mmTurretGear] ? __mmTurretGear : null,
      this.damageTail(),
      !0,
    );
  },
  turretReady() {
    return !!(
      v &&
      v.alive &&
      v.skins &&
      v.skins[__mmTurretGear] &&
      Date.now() >= __mmTurretReloadUntil
    );
  },
  turretInRange(__mmTarget) {
    if (!v || !__mmTarget) return !1;
    const __mmReach =
      __mmTurretGearRange +
      (Number(v.scale) || 0) +
      (Number(__mmTarget.scale) || 0);
    return Math.hypot(__mmTarget.x - v.x, __mmTarget.y - v.y) <= __mmReach;
  },
  finishTurretPoke() {
    this.state === "turretPoke" && this.cleanup("turret-poke-complete");
  },
  startTurretPoke(__mmTarget) {
    if (!this.turretReady() || !__mmTarget) return !1;
    this.state = "turretPoke";
    __mmEquipHatNow(__mmTurretGear);
    // Keep the game's aim direction on the distant target while Turret Gear
    // is active. Turret Gear fires on its own cooldown; no normal attack is
    // sent in this out-of-melee-range branch.
    try {
      O.send("D", this.aim(__mmTarget));
    } catch (__mmTurretAimError) {}
    // This is a best-effort troll shot: no weapon/loadout or distance gate and
    // no server acknowledgement wait. Restore on the next local server tick.
    this.schedule(() => this.finishTurretPoke());
    return !0;
  },
  start(__mmOptions = {}) {
    if (this.state !== "idle") return !1;
    // A real R burst has priority over a scheduled friendly-shot sync and idle
    // reloading, but never steals selection from an emergency action.
    __mmActionOwner === "instaSync" && __mmStopInstaSync();
    __mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
    this.suspendTrapEscape();
    if (
      !__mmActionClaim(
        "insta",
        __mmOptions.betrayal
          ? "betrayal combo"
          : __mmOptions.automatic
            ? "auto target"
            : "R combo",
      )
    ) {
      const __mmResumeTrap = !!(
        this.trapHandoff &&
        this.trapHandoff.resume &&
        v &&
        v.alive &&
        __mmIsTrapped()
      );
      this.trapHandoff = null;
      __mmResumeTrap && __mmBreakTrap();
      return !1;
    }
    this.state = "validate";
    this.targetOptional = !!__mmOptions.targetOptional;
    this.automatic = !!__mmOptions.automatic;
    this.betrayal = !!__mmOptions.betrayal;
    if (!this.runtimeReady()) return (this.cleanup("runtime-unavailable"), !1);
    this.capture();
    const __mmRequestedTarget =
      __mmOptions.targetSid == null ? null : Rt(__mmOptions.targetSid),
      __mmTarget =
        __mmRequestedTarget &&
        (__mmIsEnemyPlayer(__mmRequestedTarget) ||
          (this.betrayal &&
            __mmRequestedTarget !== v &&
            __mmRequestedTarget.alive &&
            __mmRequestedTarget.visible))
          ? __mmRequestedTarget
          : this.betrayal
            ? null
            : this.nearestEnemy();
    if (__mmTarget) this.targetSid = __mmTarget.sid;
    if (
      !this.automatic &&
      !this.betrayal &&
      __mmInstaUiEnabled &&
      __mmTarget &&
      !this.canFullBurst(__mmTarget) &&
      this.startTurretPoke(__mmTarget)
    )
      return !0;
    const __mmContext = this.context(!1);
    if (!__mmContext) return (this.cleanup("validation-failed"), !1);
    this.primaryWeapon = __mmContext.primary;
    this.state = "arm";
    this.arm();
    return !0;
  },
  canAutoStart() {
    if (
      !__mmAutoInstaEnabled ||
      this.state !== "idle" ||
      !this.runtimeReady() ||
      this.isPriorityConflict()
    )
      return !1;
    const __mmPrimary = this.supportedPrimary(),
      __mmTarget = this.nearestEnemy();
    if (
      __mmPrimary == null ||
      !__mmTarget ||
      !this.inRange(__mmPrimary, __mmTarget) ||
      !__mmWeaponReady(__mmPrimary)
    )
      return !1;
    const __mmSecondary = v.weapons && v.weapons[1],
      __mmSecondaryData = this.weaponData(__mmSecondary);
    if (
      __mmSecondary == null ||
      __mmSecondary === __mmPrimary ||
      __mmSecondary === __mmShieldWeapon ||
      !__mmSecondaryData ||
      __mmSecondaryData.shield ||
      !__mmWeaponReady(__mmSecondary)
    )
      return !1;
    return !(
      v.skins &&
      v.skins[__mmTurretGear] &&
      !this.turretReady()
    );
  },
  arm() {
    const __mmContext = this.context(!1);
    if (!__mmContext) return void this.cleanup("arm-invalid");
    this.primaryWeapon = __mmContext.primary;
    // Do not change gear until the target is actually in reach.
    this.state = "waitForRange";
    this.waitForRange();
  },
  waitForRange() {
    if (this.state !== "waitForRange") return;
    const __mmContext = this.context(!1);
    if (!__mmContext) return void this.cleanup("target-or-state-lost");
    this.primaryWeapon = __mmContext.primary;
    if (__mmContext.target && !this.inRange(__mmContext.primary, __mmContext.target))
      return void (
        this.startTurretPoke(__mmContext.target) ||
          this.cleanup("out-of-range")
      );
    // Bull and the primary are sent together. Keep the attack held for one
    // tick, then send Turret Gear and aim before the secondary.
    this.state = "executeBurst";
    this.selectDamageGear();
    this.executeBurst();
  },
  releaseAttack() {
    if (!this.attackHeld) return;
    try {
      O && O.send && O.send("F", 0, null);
    } catch (__mmReleaseError) {}
    this.attackHeld = !1;
  },
  sendAttack(__mmItem, __mmIsWeapon, __mmTarget) {
    if (!v || !v.alive || __mmItem == null) return !1;
    this.releaseAttack();
    try {
      const __mmAngle = this.aim(__mmTarget);
      je(__mmItem, !!__mmIsWeapon);
      O.send("F", 1, __mmAngle);
      this.attackHeld = !0;
      return !0;
    } catch (__mmAttackError) {
      this.attackHeld = !1;
      return !1;
    }
  },
  executeBurst() {
    if (this.state !== "executeBurst") return;
    const __mmContext = this.context(!0);
    if (!__mmContext)
      return void this.cleanup("primary-unavailable");
    if (!this.sendAttack(__mmContext.primary, !0, __mmContext.target))
      return void this.cleanup("primary-send-failed");
    this.schedule(() => this.executeFollowup());
  },
  secondaryFollowup() {
    if (!v || !v.weapons) return null;
    const __mmWeapon = v.weapons[1],
      __mmData = this.weaponData(__mmWeapon);
    return __mmWeapon != null &&
      __mmWeapon !== this.primaryWeapon &&
      __mmWeapon !== __mmShieldWeapon &&
      __mmData &&
      !__mmData.shield
      ? __mmWeapon
      : null;
  },
  executeFollowup() {
    if (this.state !== "executeBurst") return;
    // Every swing remains down for a full authoritative tick. Release it just
    // before choosing the next combo step so the following press is a fresh
    // attack rather than an ignored held state.
    this.releaseAttack();
    // The opening hit may knock the target out of primary melee range. Keep
    // the confirmed target but let the equipped secondary make its own shot.
    const __mmContext = this.context(!1);
    if (!__mmContext) return void this.cleanup("followup-invalid");
    const __mmSecondary = this.secondaryFollowup();
    if (__mmSecondary == null) return void this.cleanup("secondary-unavailable");
    // Turret Gear and aim go out now; the secondary follows one fixed tick
    // later, without waiting on reload or server-confirmation state.
    this.pendingSecondaryWeapon = __mmSecondary;
    this.selectSecondaryDamageGear();
    try {
      O.send("D", this.aim(__mmContext.target));
    } catch (__mmSecondaryAimError) {}
    return void this.schedule(() => this.fireSecondaryFollowup());
  },
  fireSecondaryFollowup() {
    if (this.state !== "executeBurst") return;
    const __mmWeapon = this.pendingSecondaryWeapon,
      __mmContext = this.context(!1);
    if (__mmWeapon == null || !__mmContext)
      return void this.cleanup("secondary-context-lost");
    if (!this.sendAttack(__mmWeapon, !0, __mmContext.target))
      return void this.cleanup("secondary-send-failed");
    // Hold the secondary swing for one game tick, then restore the pre-R
    // weapon and gear. No reload-state polling or extra build follow-up.
    ((this.pendingSecondaryWeapon = null),
      this.schedule(() => this.cleanup("complete")));
  },
  cleanup(__mmReason) {
    const __mmSnapshot = this.snapshot,
      __mmCompletedFullInsta = __mmReason === "complete",
      __mmRestore = __mmActionMayRestore("insta"),
      __mmResumeTrap = !!(
        this.trapHandoff &&
        this.trapHandoff.resume &&
        __mmTrapEscapeEnabled &&
        v &&
        v.alive &&
        __mmIsTrapped()
      );
    this.state = "cleanup";
    this.timer && clearTimeout(this.timer);
    this.timer = 0;
    this.releaseAttack();
    if (v && v.alive && __mmSnapshot && __mmRestore) {
      __mmEquipGearPair(__mmSnapshot.hat, __mmSnapshot.tail, !0);
      __mmSnapshot.weapon != null && __mmRestoreWeapon(__mmSnapshot.weapon);
      (__mmSnapshot.primaryHeld || __mmSnapshot.secondaryHeld) &&
        (__mmPrimaryHeld || __mmSecondaryHeld) &&
        __mmResumeHeldAttack();
    }
    this.snapshot = null;
    this.targetSid = null;
    this.targetOptional = !1;
    this.automatic = !1;
    this.betrayal = !1;
    this.primaryWeapon = null;
    this.pendingSecondaryWeapon = null;
    this.trapHandoff = null;
    this.reason = __mmReason || "cancelled";
    this.state = "idle";
    __mmActionRelease("insta", this.reason);
    __mmCompletedFullInsta && __mmSendChat("Meow!");
    // These loops were gated while the burst owned gear/selection. Run their
    // normal updates now instead of changing their user-configured toggles.
    if (v && v.alive) {
      __mmResumeTrap && __mmBreakTrap();
      __mmUpdateMovementGear();
      __mmUpdateSoldier();
      __mmUpdateWeaponRecharge();
      __mmAutoHeal();
    }
  },
  cancel(__mmReason) {
    this.cleanup(__mmReason || "cancelled");
  },
};
function __mmNearestBetrayalTarget() {
  if (!v || !v.alive || !Array.isArray(E) || __mmTeamKey(v) == null)
    return null;
  let __mmClosest = null,
    __mmClosestDistance = Infinity;
  for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
    const __mmPlayer = E[__mmIndex];
    if (
      !__mmPlayer ||
      !__mmPlayer.alive ||
      !__mmPlayer.visible ||
      __mmPlayer === v ||
      String(__mmPlayer.sid) === String(v.sid) ||
      !__mmSameTeam(__mmPlayer) ||
      __mmIsFriendPlayer(__mmPlayer) ||
      !Number.isFinite(Number(__mmPlayer.x)) ||
      !Number.isFinite(Number(__mmPlayer.y))
    )
      continue;
    const __mmDistance =
      (__mmPlayer.x - v.x) ** 2 + (__mmPlayer.y - v.y) ** 2;
    if (__mmDistance < __mmClosestDistance)
      ((__mmClosest = __mmPlayer), (__mmClosestDistance = __mmDistance));
  }
  return __mmClosest;
}
function __mmBetrayalInstaReady(__mmTarget) {
  if (
    !__mmInstaUiEnabled ||
    !__mmTarget ||
    __mmInsta.state !== "idle" ||
    !__mmInsta.runtimeReady() ||
    __mmIsTrapped() ||
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmTrapAttackActive ||
    __mmBoostBreakHeld ||
    __mmBuildSpamTimer ||
    __mmFoodSpamTimer ||
    Date.now() < __mmAntiInstaUntil ||
    __mmInsta.isEmergencyHealth() ||
    !__mmActionAvailable("insta")
  )
    return !1;
  const __mmPrimary = __mmInsta.supportedPrimary();
  if (
    __mmPrimary == null ||
    !__mmWeaponReady(__mmPrimary) ||
    !__mmInsta.inRange(__mmPrimary, __mmTarget)
  )
    return !1;
  const __mmSecondary = v.weapons && v.weapons[1],
    __mmSecondaryData = __mmInsta.weaponData(__mmSecondary);
  if (
    __mmSecondary == null ||
    __mmSecondary === __mmPrimary ||
    __mmSecondary === __mmShieldWeapon ||
    !__mmSecondaryData ||
    __mmSecondaryData.shield ||
    !__mmWeaponReady(__mmSecondary)
  )
    return !1;
  return !(
    v.skins &&
    v.skins[__mmTurretGear] &&
    !__mmInsta.turretReady()
  );
}
function __mmStartBetrayalInsta() {
  const __mmTarget = __mmNearestBetrayalTarget();
  if (!__mmTarget) return !1;
  __mmActionOwner === "matThief" &&
    __mmFinishMatThief("betrayal insta");
  __mmActionOwner === "mobSteal" &&
    __mmFinishMobSteal("betrayal insta");
  __mmActionOwner === "instaSync" && __mmStopInstaSync();
  __mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
  if (!__mmBetrayalInstaReady(__mmTarget)) return !1;
  // Send leave first and deliberately assume success. The betrayal target flag
  // keeps this exact former teammate valid until the combo finishes, avoiding
  // any wait for the server's team-state acknowledgement.
  O.send("N");
  return __mmInsta.start({ targetSid: __mmTarget.sid, betrayal: !0 });
}
function __mmTeamKey(__mmPlayer) {
  if (!__mmPlayer) return null;
  const __mmTeam = __mmPlayer.team;
  return typeof __mmTeam === "number"
    ? __mmTeam > 0
      ? "n:" + __mmTeam
      : null
    : typeof __mmTeam === "string" && __mmTeam.trim()
      ? "s:" + __mmTeam
      : null;
}
function __mmNormalizeFriendName(__mmName) {
  return typeof __mmName === "string"
    ? __mmName.trim().slice(0, 15).toLowerCase()
    : "";
}
function __mmFriendDisplayName(__mmName) {
  return typeof __mmName === "string" ? __mmName.trim().slice(0, 15) : "";
}
function __mmIsFriendPlayer(__mmPlayer) {
  const __mmKey = __mmNormalizeFriendName(__mmPlayer && __mmPlayer.name);
  return !!(
    __mmKey &&
    __mmFriendNames.has(__mmKey) &&
    !__mmFriendEnemies.has(__mmKey)
  );
}
function __mmDispatchFriendState(__mmType, __mmName) {
  window.dispatchEvent(
    new CustomEvent("MooMooFriendState", {
      detail: { type: __mmType, name: __mmName },
    }),
  );
}
function __mmAddFriend(__mmName, __mmAnnounce) {
  const __mmDisplay = __mmFriendDisplayName(__mmName),
    __mmKey = __mmNormalizeFriendName(__mmDisplay);
  if (!__mmKey) return !1;
  (__mmFriendNames.set(__mmKey, __mmDisplay),
    __mmFriendEnemies.delete(__mmKey),
    __mmDispatchFriendState("add", __mmDisplay),
    __mmAnnounce && __mmSendChat("Added friend, " + __mmDisplay + "!"),
    __mmPublishHudState());
  return !0;
}
function __mmRemoveFriend(__mmName, __mmAnnounce) {
  const __mmKey = __mmNormalizeFriendName(__mmName),
    __mmDisplay =
      __mmFriendNames.get(__mmKey) || __mmFriendDisplayName(__mmName);
  if (!__mmKey || !__mmDisplay) return !1;
  (__mmFriendNames.delete(__mmKey),
    __mmFriendEnemies.add(__mmKey),
    delete __mmFriendAttackWindows[__mmKey],
    __mmDispatchFriendState("remove", __mmDisplay),
    __mmAnnounce && __mmSendChat(__mmDisplay + " is an enemy!"),
    __mmPublishHudState());
  return !0;
}
function __mmFriendPickNotice(__mmMessage) {
  window.dispatchEvent(
    new CustomEvent("MooMooFriendPickNotice", {
      detail: String(__mmMessage || ""),
    }),
  );
}
function __mmArmFriendPick(__mmMode) {
  if (!v || !v.alive) return !1;
  const __mmNext =
    __mmMode === "friend" || __mmMode === "enemy" ? __mmMode : null;
  if (__mmFriendPickMode === __mmNext) {
    (__mmFriendPickMode = null,
      __mmFriendPickNotice("Player selection cancelled"));
    return !1;
  }
  __mmFriendPickMode = __mmNext;
  __mmFriendPickNotice(
    __mmNext === "friend"
      ? "Click a player to add friend"
      : "Click a player to mark enemy",
  );
  return !0;
}
function __mmPlayerAtFriendPick(__mmEvent) {
  if (!v || !v.alive || !Array.isArray(E) || !__mmEvent) return null;
  const __mmSurface =
      document.getElementById("gameCanvas") ||
      (__mmEvent.target instanceof Element
        ? __mmEvent.target.closest("#gameCanvas,#touch-controls-fullscreen")
        : null),
    __mmRect =
      __mmSurface && typeof __mmSurface.getBoundingClientRect === "function"
        ? __mmSurface.getBoundingClientRect()
        : null;
  if (!__mmRect || __mmRect.width <= 0 || __mmRect.height <= 0) return null;
  const __mmViewportWidth = Math.max(1, Number(_) || Number(De) || __mmRect.width),
    __mmViewportHeight = Math.max(1, Number(L) || Number(Ae) || __mmRect.height),
    __mmLeft = Number(oe) - __mmViewportWidth / 2,
    __mmTop = Number(ae) - __mmViewportHeight / 2;
  let __mmBest = null,
    __mmBestDistance = Infinity;
  for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
    const __mmPlayer = E[__mmIndex];
    if (
      !__mmPlayer ||
      !__mmPlayer.alive ||
      !__mmPlayer.visible ||
      __mmPlayer === v ||
      String(__mmPlayer.sid) === String(v.sid)
    )
      continue;
    const __mmScreenX =
        __mmRect.left +
        ((Number(__mmPlayer.x) - __mmLeft) / __mmViewportWidth) *
          __mmRect.width,
      __mmScreenY =
        __mmRect.top +
        ((Number(__mmPlayer.y) - __mmTop) / __mmViewportHeight) *
          __mmRect.height,
      __mmDistance = Math.hypot(
        Number(__mmEvent.clientX) - __mmScreenX,
        Number(__mmEvent.clientY) - __mmScreenY,
      ),
      __mmHitRadius = Math.max(
        24,
        ((Number(__mmPlayer.scale) || 35) / __mmViewportWidth) *
          __mmRect.width +
          16,
      );
    if (__mmDistance <= __mmHitRadius && __mmDistance < __mmBestDistance)
      ((__mmBest = __mmPlayer), (__mmBestDistance = __mmDistance));
  }
  return __mmBest;
}
document.addEventListener(
  "mousedown",
  function (__mmEvent) {
    if (!__mmFriendPickMode || !__mmIsGameClick(__mmEvent)) return;
    (__mmEvent.preventDefault(), __mmEvent.stopImmediatePropagation());
    __mmCleanupActive && __mmStopCleanup("friend selection click", !1);
    const __mmPlayer = __mmPlayerAtFriendPick(__mmEvent);
    if (!__mmPlayer) {
      __mmFriendPickNotice("No player there - click again");
      return;
    }
    const __mmMode = __mmFriendPickMode;
    __mmFriendPickMode = null;
    if (__mmMode === "friend") {
      (__mmAddFriend(__mmPlayer.name, !0),
        __mmFriendPickNotice("Friend: " + __mmPlayer.name));
    } else {
      (__mmRemoveFriend(__mmPlayer.name, !0),
        __mmFriendPickNotice("Enemy: " + __mmPlayer.name));
    }
  },
  !0,
);
window.addEventListener("blur", function () {
  __mmFriendPickMode = null;
});
function __mmReplaceFriends(__mmNames) {
  const __mmPrevious = Array.from(__mmFriendNames.keys()),
    __mmNext = new Map();
  if (Array.isArray(__mmNames)) {
    for (let __mmIndex = 0; __mmIndex < __mmNames.length; __mmIndex++) {
      const __mmDisplay = __mmFriendDisplayName(__mmNames[__mmIndex]),
        __mmKey = __mmNormalizeFriendName(__mmDisplay);
      __mmKey && !__mmNext.has(__mmKey) && __mmNext.set(__mmKey, __mmDisplay);
      if (__mmNext.size >= 30) break;
    }
  }
  __mmFriendNames.clear();
  __mmNext.forEach(function (__mmDisplay, __mmKey) {
    (__mmFriendNames.set(__mmKey, __mmDisplay),
      __mmFriendEnemies.delete(__mmKey));
  });
  for (let __mmIndex = 0; __mmIndex < __mmPrevious.length; __mmIndex++)
    __mmNext.has(__mmPrevious[__mmIndex]) ||
      __mmFriendEnemies.add(__mmPrevious[__mmIndex]);
}
function __mmFriendAttackAimedAtUs(__mmPlayer, __mmWeapon) {
  if (!v || !v.alive || !__mmPlayer || !__mmPlayer.alive) return !1;
  const __mmWeaponId =
      __mmWeapon == null ? __mmPlayer.weaponIndex : Number(__mmWeapon),
    __mmWeaponData = b.weapons && b.weapons[__mmWeaponId],
    __mmAttackAngle = Number(__mmPlayer.dir),
    __mmTargetAngle = Math.atan2(v.y - __mmPlayer.y, v.x - __mmPlayer.x),
    __mmAngleDifference = Math.abs(
      Math.atan2(
        Math.sin(__mmAttackAngle - __mmTargetAngle),
        Math.cos(__mmAttackAngle - __mmTargetAngle),
      ),
    ),
    __mmDistance = Math.hypot(v.x - __mmPlayer.x, v.y - __mmPlayer.y),
    __mmReach = __mmWeaponData
      ? __mmWeaponData.projectile != null
        ? 900
        : (Number(__mmWeaponData.range) || 0) +
          (Number(__mmPlayer.scale) || 35) +
          (Number(v.scale) || 35) +
          45
      : 220;
  return __mmAngleDifference <= 0.72 && __mmDistance <= __mmReach;
}
function __mmObserveFriendAttack(__mmPlayerSid, __mmDidHit, __mmWeapon) {
  const __mmPlayer = Rt(__mmPlayerSid);
  if (!__mmIsFriendPlayer(__mmPlayer)) return;
  const __mmKey = __mmNormalizeFriendName(__mmPlayer.name);
  if (!__mmFriendAttackAimedAtUs(__mmPlayer, __mmWeapon)) return;
  const __mmNow = Date.now(),
    __mmWeaponId =
      __mmWeapon == null ? Number(__mmPlayer.weaponIndex) : Number(__mmWeapon),
    __mmWindow =
      __mmFriendAttackWindows[__mmKey] ||
      (__mmFriendAttackWindows[__mmKey] = {
        lastAt: 0,
        lastWeapon: null,
        lastAimedAt: 0,
        damageStartedAt: 0,
        damage: 0,
      }),
    __mmRapidDistinct =
      __mmWindow.lastAt > 0 &&
      __mmNow - __mmWindow.lastAt <= Math.max(300, __mmServerTickMs() * 3) &&
      __mmWindow.lastWeapon != null &&
      __mmWindow.lastWeapon !== __mmWeaponId &&
      ([__mmShortSword, __mmKatana, __mmPolearmWeapon].includes(__mmWeaponId) ||
        [__mmShortSword, __mmKatana, __mmPolearmWeapon].includes(
          __mmWindow.lastWeapon,
        )),
    __mmInstaPrimary = [
      __mmShortSword,
      __mmKatana,
      __mmPolearmWeapon,
    ].includes(__mmWeaponId),
    __mmInstaGear =
      Number(__mmPlayer.skinIndex) === 7 ||
      Number(__mmPlayer.skinIndex) === __mmTurretGear;
  ((__mmWindow.lastAt = __mmNow),
    (__mmWindow.lastWeapon = __mmWeaponId),
    (__mmWindow.lastAimedAt = __mmNow));
  (__mmRapidDistinct || (__mmInstaPrimary && __mmInstaGear)) &&
    __mmRemoveFriend(__mmPlayer.name, !0);
}
function __mmObserveFriendDamage(__mmDamage) {
  if (!(Number(__mmDamage) > 0) || !v || !v.alive) return;
  const __mmNow = Date.now();
  let __mmBestKey = "",
    __mmBestAt = 0;
  __mmFriendNames.forEach(function (__mmDisplay, __mmKey) {
    const __mmWindow = __mmFriendAttackWindows[__mmKey];
    if (
      __mmWindow &&
      __mmNow - __mmWindow.lastAimedAt <= 850 &&
      __mmWindow.lastAimedAt > __mmBestAt
    )
      ((__mmBestKey = __mmKey), (__mmBestAt = __mmWindow.lastAimedAt));
  });
  if (!__mmBestKey) return;
  const __mmWindow = __mmFriendAttackWindows[__mmBestKey];
  if (
    !__mmWindow.damageStartedAt ||
    __mmNow - __mmWindow.damageStartedAt > 1200
  )
    ((__mmWindow.damageStartedAt = __mmNow), (__mmWindow.damage = 0));
  __mmWindow.damage += Number(__mmDamage);
  __mmWindow.damage > 20 &&
    __mmRemoveFriend(__mmFriendNames.get(__mmBestKey), !0);
}
function __mmSameTeam(__mmPlayer) {
  const __mmOwnTeam = __mmTeamKey(v),
    __mmOtherTeam = __mmTeamKey(__mmPlayer);
  return (
    __mmOwnTeam != null &&
    __mmOtherTeam != null &&
    __mmOwnTeam === __mmOtherTeam
  );
}
function __mmIsEnemyPlayer(__mmPlayer) {
  const __mmFriendKey = __mmNormalizeFriendName(
      __mmPlayer && __mmPlayer.name,
    ),
    __mmBetrayedFriend =
      !!__mmFriendKey && __mmFriendEnemies.has(__mmFriendKey);
  if (
    !__mmPlayer ||
    !__mmPlayer.alive ||
    !__mmPlayer.visible ||
    (Number.isFinite(Number(__mmPlayer.health)) &&
      Number(__mmPlayer.health) <= 0) ||
    !v ||
    !v.alive ||
    __mmPlayer === v ||
    __mmPlayer.sid === v.sid
  )
    return !1;
  if (
    !__mmBetrayedFriend &&
    (__mmSameTeam(__mmPlayer) || __mmIsFriendPlayer(__mmPlayer))
  )
    return !1;
  const __mmOwnTeam = __mmTeamKey(v),
    __mmOtherTeam = __mmTeamKey(__mmPlayer);
  if (__mmOwnTeam != null && __mmOtherTeam == null) {
    const __mmSid = String(__mmPlayer.sid),
      __mmNow = Date.now(),
      __mmSeen =
        __mmUnknownTeamSeen[__mmSid] ||
        (__mmUnknownTeamSeen[__mmSid] = __mmNow);
    return __mmNow - __mmSeen >= __mmUnknownTeamGraceMs;
  }
  return !0;
}
function __mmSyncPost(__mmMessage) {
  if (!__mmSyncLeaderEnabled || !v || !v.alive) return;
  const __mmPacket = {
    ...__mmMessage,
    sender: __mmSyncTabId,
    leaderSid: v.sid,
    sentAt: Date.now(),
  };
  try {
    __mmSyncChannel && __mmSyncChannel.postMessage(__mmPacket);
  } catch (__mmSyncPostError) {}
  try {
    window.dispatchEvent(
      new CustomEvent("MooMooTabSyncOutbound", {
        detail: JSON.stringify(__mmPacket),
      }),
    );
  } catch (__mmSyncBridgeError) {}
}
function __mmSetSyncStatus(__mmStatus) {
  if (__mmSyncStatus === __mmStatus) return;
  ((__mmSyncStatus = __mmStatus),
    window.dispatchEvent(
      new CustomEvent("MooMooScrollZoomStatus", {
        detail: "Sync: " + __mmStatus,
      }),
    ));
}
function __mmSyncBroadcastState() {
  if (!__mmSyncLeaderEnabled || !v || !v.alive) return;
  const __mmAim = Ci(),
    __mmAimDistance = 1800,
    __mmState = {
    type: "state",
    x: v.x,
    y: v.y,
    aimX: v.x + Math.cos(__mmAim) * __mmAimDistance,
    aimY: v.y + Math.sin(__mmAim) * __mmAimDistance,
  };
  (__mmSyncPost(__mmState),
    // BroadcastChannel is the fast path. This small storage-event fallback
    // still lets a second same-origin tab acquire the leader when a browser
    // has isolated the injected bundle's BroadcastChannel context.
    (() => {
      try {
        localStorage.setItem(
          __mmSyncStorageKey,
          JSON.stringify({
            ...__mmState,
            sender: __mmSyncTabId,
            leaderSid: v.sid,
            sentAt: Date.now(),
          }),
        );
      } catch (__mmSyncStorageWriteError) {}
    })());
}
function __mmSyncLeaderPlayer(__mmMessage) {
  const __mmState = __mmSyncLeaderState;
  if (
    !__mmSyncFollowerEnabled ||
    !v ||
    !v.alive ||
    !__mmState ||
    Date.now() - __mmState.receivedAt > 800 ||
    (__mmMessage &&
      (__mmMessage.sender !== __mmState.sender ||
        String(__mmMessage.leaderSid) !== String(__mmState.leaderSid)))
  )
    return null;
  const __mmLeader = Rt(__mmState.leaderSid);
  if (
    __mmLeader &&
    __mmLeader.alive &&
    __mmLeader !== v &&
    String(__mmLeader.sid) === String(__mmState.leaderSid)
  )
    return __mmLeader;
  // The player list only includes players the local client currently knows
  // about. Keep following the explicitly enabled local leader while they are
  // off-screen, then switch to their authoritative in-match position as soon
  // as the follower can see them.
  return Number.isFinite(Number(__mmState.x)) &&
    Number.isFinite(Number(__mmState.y))
    ? __mmState
    : null;
}
function __mmSyncStopFollowMovement() {
  if (!__mmSyncMoveActive) return;
  ((__mmSyncMoveActive = !1), (Kt = null), Tt());
}
function __mmSyncFollowTick() {
  if (!__mmSyncFollowerEnabled || !v || !v.alive)
    return void __mmSyncStopFollowMovement();
  const __mmLeader = __mmSyncLeaderPlayer();
  if (!__mmLeader)
    return (__mmSetSyncStatus("waiting for leader"), void __mmSyncStopFollowMovement());
  __mmSetSyncStatus("following");
  // Target a small rotating offset around the leader instead of their exact
  // center. That keeps the companion close without colliding or pushing them.
  const __mmOrbitRadius = (v.scale || 35) + (__mmLeader.scale || 35) + 30,
    __mmOrbit = (Date.now() / 680 + 0.85) % (Math.PI * 2),
    __mmTargetX = __mmLeader.x + Math.cos(__mmOrbit) * __mmOrbitRadius,
    __mmTargetY = __mmLeader.y + Math.sin(__mmOrbit) * __mmOrbitRadius,
    __mmDx = __mmTargetX - v.x,
    __mmDy = __mmTargetY - v.y;
  if (__mmDx * __mmDx + __mmDy * __mmDy < 64)
    return void __mmSyncStopFollowMovement();
  const __mmDirection = Math.atan2(__mmDy, __mmDx);
  (O.send("9", __mmDirection),
    (Kt = __mmDirection),
    (__mmSyncMoveActive = !0));
}
function __mmSyncOwnsSelection(__mmItem, __mmIsWeapon) {
  return !!(
    v &&
    v.alive &&
    Number.isFinite(Number(__mmItem)) &&
    (__mmIsWeapon
      ? v.weapons && v.weapons.includes(__mmItem)
      : v.items && v.items.includes(__mmItem))
  );
}
function __mmSyncHandleMessage(__mmEvent) {
  const __mmMessage = __mmEvent && __mmEvent.data;
  if (
    !__mmSyncFollowerEnabled ||
    !__mmMessage ||
    __mmMessage.sender === __mmSyncTabId ||
    typeof __mmMessage !== "object"
  )
    return;
  if (__mmMessage.type === "state") {
    const __mmLeader = Rt(__mmMessage.leaderSid);
    if (
      v &&
      String(__mmMessage.leaderSid) !== String(v.sid) &&
      Number.isFinite(Number(__mmMessage.x)) &&
      Number.isFinite(Number(__mmMessage.y))
    ) {
      // The role is explicitly enabled in both local tabs. Do not require the
      // leader to be visible before following, otherwise two far-apart spawns
      // can never meet. When visible, the live player object is preferred.
      __mmSyncLeaderState = {
        ...__mmMessage,
        x:
          __mmLeader && __mmLeader.alive ? __mmLeader.x : Number(__mmMessage.x),
        y:
          __mmLeader && __mmLeader.alive ? __mmLeader.y : Number(__mmMessage.y),
        receivedAt: Date.now(),
      };
      __mmSyncFollowTick();
    }
    return;
  }
  const __mmLeader = __mmSyncLeaderPlayer(__mmMessage);
  if (!__mmLeader) return;
  if (__mmMessage.type === "selection") {
    if (!__mmSyncOwnsSelection(__mmMessage.item, !!__mmMessage.isWeapon)) {
      __mmSyncSelectionBlockedUntil = Date.now() + 900;
      return;
    }
    ((__mmSyncSelectionBlockedUntil = 0),
      je(__mmMessage.item, !!__mmMessage.isWeapon));
    return;
  }
  if (__mmMessage.type === "gear") {
    __mmMessage.tail
      ? __mmEquipTailNow(__mmMessage.item)
      : __mmEquipHatNow(__mmMessage.item);
    return;
  }
  if (__mmMessage.type === "gearPair") {
    __mmEquipGearPair(__mmMessage.hat, __mmMessage.tail, !0);
    return;
  }
  if (
    __mmMessage.type !== "attack" ||
    Date.now() < __mmSyncSelectionBlockedUntil
  )
    return;
  const __mmAimX = Number(__mmMessage.aimX),
    __mmAimY = Number(__mmMessage.aimY),
    __mmAngle =
      Number.isFinite(__mmAimX) && Number.isFinite(__mmAimY)
        ? Math.atan2(__mmAimY - v.y, __mmAimX - v.x)
        : Ci();
  O.send("F", __mmMessage.state ? 1 : 0, __mmAngle);
}
function __mmSyncPublishSelection(__mmItem, __mmIsWeapon) {
  __mmSyncPost({
    type: "selection",
    item: __mmItem,
    isWeapon: !!__mmIsWeapon,
  });
}
function __mmSyncPublishGear(__mmItem, __mmTail) {
  __mmSyncPost({ type: "gear", item: __mmItem, tail: !!__mmTail });
}
function __mmSyncPublishGearPair(__mmHat, __mmTail) {
  __mmSyncPost({ type: "gearPair", hat: __mmHat, tail: __mmTail });
}
function __mmSyncObserveSocketSend(__mmArguments) {
  if (!__mmSyncLeaderEnabled || !v || !v.alive) return;
  if (__mmArguments[0] === "c") {
    if (__mmSyncGearPairDispatch) return;
    __mmSyncPublishGear(__mmArguments[2], !!__mmArguments[3]);
    return;
  }
  if (__mmArguments[0] !== "F") return;
  const __mmAngle = Number(__mmArguments[2]),
    __mmDirection = Number.isFinite(__mmAngle) ? __mmAngle : Ci(),
    __mmAimDistance = 1800;
  __mmSyncPost({
    type: "attack",
    state: __mmArguments[1] ? 1 : 0,
    aimX: v.x + Math.cos(__mmDirection) * __mmAimDistance,
    aimY: v.y + Math.sin(__mmDirection) * __mmAimDistance,
  });
}
function __mmUpdateTabSync() {
  __mmSyncLeaderEnabled && __mmSyncBroadcastState();
  __mmSyncFollowerEnabled && __mmSyncFollowTick();
}
function __mmStartTabSync() {
  (__mmUpdateTabSync(),
    __mmSyncTimer ||
      (__mmSyncTimer = setInterval(__mmUpdateTabSync, __mmFastCheckMs())));
}
function __mmStopTabSync() {
  if (__mmSyncLeaderEnabled || __mmSyncFollowerEnabled) return;
  (__mmSyncTimer && clearInterval(__mmSyncTimer),
    (__mmSyncTimer = 0),
    (__mmSyncLeaderState = null),
    (__mmSyncSelectionBlockedUntil = 0),
    __mmSyncStopFollowMovement());
}
function __mmSetSyncLeader(__mmEnabled) {
  ((__mmSyncLeaderEnabled = !!__mmEnabled),
    __mmSyncLeaderEnabled && (__mmSyncFollowerEnabled = !1),
    __mmSyncLeaderEnabled ? __mmStartTabSync() : __mmStopTabSync(),
    __mmSetSyncStatus(__mmSyncLeaderEnabled ? "broadcasting" : "off"),
    __mmPublishHudState());
}
function __mmSetSyncFollower(__mmEnabled) {
  ((__mmSyncFollowerEnabled = !!__mmEnabled),
    __mmSyncFollowerEnabled && (__mmSyncLeaderEnabled = !1),
    __mmSyncFollowerEnabled ? __mmStartTabSync() : __mmStopTabSync(),
    __mmSetSyncStatus(__mmSyncFollowerEnabled ? "waiting for leader" : "off"),
    __mmPublishHudState());
}
__mmSyncChannel && __mmSyncChannel.addEventListener("message", __mmSyncHandleMessage);
window.addEventListener("storage", function (__mmStorageEvent) {
  if (!__mmStorageEvent || __mmStorageEvent.key !== __mmSyncStorageKey) return;
  try {
    __mmStorageEvent.newValue &&
      __mmSyncHandleMessage({ data: JSON.parse(__mmStorageEvent.newValue) });
  } catch (__mmSyncStorageReadError) {}
});
window.addEventListener("MooMooTabSyncInbound", function (__mmSyncBridgeEvent) {
  try {
    typeof __mmSyncBridgeEvent.detail === "string" &&
      __mmSyncHandleMessage({ data: JSON.parse(__mmSyncBridgeEvent.detail) });
  } catch (__mmSyncBridgeReadError) {}
});
function __mmDrawPredictionGhost(__mmLeft, __mmTop) {
  if (!__mmPredictionGhostEnabled || !v || !v.alive) return;
  const __mmNow = Date.now();
  if (__mmPredictionLastX == null || __mmPredictionLastY == null) {
    ((__mmPredictionLastX = v.x),
      (__mmPredictionLastY = v.y),
      (__mmPredictionLastAt = __mmNow));
    return;
  }
  const __mmElapsed = Math.max(
      1,
      Math.min(120, __mmNow - __mmPredictionLastAt),
    ),
    __mmPing = Number(window.pingTime),
    __mmLeadMs = Number.isFinite(__mmPing)
      ? Math.max(0, Math.min(1e3, __mmPing * 0.5))
      : 0,
    __mmPredictedX = Math.max(
      0,
      Math.min(
        y.mapScale,
        v.x + ((v.x - __mmPredictionLastX) / __mmElapsed) * __mmLeadMs,
      ),
    ),
    __mmPredictedY = Math.max(
      0,
      Math.min(
        y.mapScale,
        v.y + ((v.y - __mmPredictionLastY) / __mmElapsed) * __mmLeadMs,
      ),
    );
  ((__mmPredictionLastX = v.x),
    (__mmPredictionLastY = v.y),
    (__mmPredictionLastAt = __mmNow));
  const __mmScreenX = __mmPredictedX - __mmLeft,
    __mmScreenY = __mmPredictedY - __mmTop;
  if (
    __mmScreenX < -(v.scale || 35) ||
    __mmScreenX > _ + (v.scale || 35) ||
    __mmScreenY < -(v.scale || 35) ||
    __mmScreenY > L + (v.scale || 35)
  )
    return;
  (k.save(),
    (k.globalAlpha = 0.3),
    k.translate(__mmScreenX, __mmScreenY),
    k.rotate(Ci() + v.dirPlus),
    Dl(v, k),
    k.restore());
}
function __mmDrawEsp() {
  if (!v || !v.alive || !k) return;
  try {
    const __mmLeft = oe - _ / 2,
      __mmTop = ae - L / 2;
    __mmDrawPredictionGhost(__mmLeft, __mmTop);
    if (
      (!__mmEspEnabled && !__mmEspLinesEnabled) ||
      !Array.isArray(E) ||
      !Array.isArray(N)
    )
      return;
    const __mmOwnX = v.x - __mmLeft,
      __mmOwnY = v.y - __mmTop;
    (k.save(), (k.globalAlpha = 0.72));
    if (__mmEspLinesEnabled) {
      for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
        const __mmPlayer = E[__mmIndex];
        if (
          !__mmPlayer ||
          !__mmPlayer.alive ||
          !__mmPlayer.visible ||
          __mmPlayer === v ||
          __mmPlayer.sid === v.sid
        )
          continue;
        const __mmFriendly =
            __mmIsFriendPlayer(__mmPlayer) || __mmSameTeam(__mmPlayer),
          __mmColor = __mmIsFriendPlayer(__mmPlayer)
            ? "#facc15"
            : __mmSameTeam(__mmPlayer)
              ? "#a855f7"
              : "#ff4d5d",
          __mmX = __mmPlayer.x - __mmLeft,
          __mmY = __mmPlayer.y - __mmTop;
        ((k.lineWidth = __mmFriendly ? 1.5 : 3.5),
          (k.strokeStyle = __mmColor),
          k.beginPath(),
          k.moveTo(__mmOwnX, __mmOwnY),
          k.lineTo(__mmX, __mmY),
          k.stroke());
      }
    }
    if (__mmEspEnabled) {
      ((k.lineWidth = 2), (k.globalAlpha = 0.9));
      for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
        const __mmPlayer = E[__mmIndex];
        if (
          !__mmPlayer ||
          !__mmPlayer.alive ||
          !__mmPlayer.visible ||
          __mmPlayer === v ||
          __mmPlayer.sid === v.sid
        )
          continue;
        const __mmColor = __mmIsFriendPlayer(__mmPlayer)
          ? "#facc15"
          : __mmSameTeam(__mmPlayer)
            ? "#a855f7"
            : "#ff4d5d";
        ((k.strokeStyle = __mmColor),
          k.beginPath(),
          k.arc(
            __mmPlayer.x - __mmLeft,
            __mmPlayer.y - __mmTop,
            Math.max(10, (__mmPlayer.scale || 35) + 5),
            0,
            Math.PI * 2,
          ),
          k.stroke());
      }
      k.strokeStyle = "#48df79";
      for (let __mmIndex = 0; __mmIndex < N.length; __mmIndex++) {
        const __mmAnimal = N[__mmIndex];
        if (!__mmAnimal || !__mmAnimal.active || !__mmAnimal.visible) continue;
        (k.beginPath(),
          k.arc(
            __mmAnimal.x - __mmLeft,
            __mmAnimal.y - __mmTop,
            Math.max(9, (__mmAnimal.scale || 35) + 4),
            0,
            Math.PI * 2,
          ),
          k.stroke());
      }
    }
    k.restore();
  } catch (__mmError) {
    try {
      k && k.restore();
    } catch (__mmIgnore) {}
  }
}
const __mmStructureTintCache = Object.create(null);
function __mmOwnStructure(__mmObject) {
  if (!v || !__mmObject || !__mmObject.owner) return !1;
  const __mmOwner = __mmObject.owner,
    __mmOwnerSid = __mmOwner.sid;
  return !!(
    __mmOwner === v ||
    (__mmOwnerSid != null && String(__mmOwnerSid) === String(v.sid))
  );
}
function __mmTintableStructure(__mmObject) {
  const __mmItem = __mmObject && b && b.list && b.list[__mmObject.id],
    __mmName = String(__mmItem && __mmItem.name || "").toLowerCase();
  return !!(
    __mmObject &&
    __mmObject.isItem &&
    (__mmOwnStructure(__mmObject) ||
      __mmName.includes("spikes") ||
      __mmName === "turret" ||
      __mmName === "pit trap")
  );
}
function __mmFriendlyStructure(__mmObject) {
  if (!v || !__mmObject || !__mmObject.owner) return !1;
  const __mmOwner = __mmObject.owner,
    __mmOwnerSid = __mmOwner.sid;
  if (__mmOwnStructure(__mmObject)) return !0;
  if (__mmSameTeam(__mmOwner)) return !0;
  const __mmOwnerPlayer = typeof Rt === "function" ? Rt(__mmOwnerSid) : null;
  return !!(__mmOwnerPlayer && __mmSameTeam(__mmOwnerPlayer));
}
function __mmTintedStructureSprite(__mmObject, __mmRelationship) {
  const __mmBase = Di(__mmObject),
    __mmKind =
      __mmRelationship === "own"
        ? "own"
        : __mmRelationship === "friendly" || __mmRelationship === !0
          ? "friendly"
          : "enemy",
    __mmColor =
      __mmKind === "own"
        ? "#d8b4fe"
        : __mmKind === "friendly"
          ? "#a855f7"
          : "#ef233c",
    __mmKey = String(__mmObject.id) + ":" + __mmColor + ":" +
      __mmBase.width + "x" + __mmBase.height;
  let __mmTinted = __mmStructureTintCache[__mmKey];
  if (__mmTinted) return __mmTinted;
  __mmTinted = document.createElement("canvas");
  __mmTinted.width = __mmBase.width;
  __mmTinted.height = __mmBase.height;
  const __mmContext = __mmTinted.getContext("2d");
  (__mmContext.drawImage(__mmBase, 0, 0),
    (__mmContext.globalCompositeOperation = "source-atop"),
    (__mmContext.globalAlpha = __mmKind === "own" ? 0.7 : 0.8),
    (__mmContext.fillStyle = __mmColor),
    __mmContext.fillRect(0, 0, __mmTinted.width, __mmTinted.height),
    (__mmContext.globalCompositeOperation = "source-over"),
    (__mmContext.globalAlpha = 0.34),
    __mmContext.drawImage(__mmBase, 0, 0));
  __mmStructureTintCache[__mmKey] = __mmTinted;
  return __mmTinted;
}
function __mmDrawStructureTints(__mmLayer, __mmLeft, __mmTop) {
  if (!v || !v.alive || !Array.isArray(ge)) return;
  for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
    const __mmObject = ge[__mmIndex];
    if (
      !__mmObject ||
      !__mmObject.active ||
      __mmObject.layer !== __mmLayer ||
      !__mmTintableStructure(__mmObject)
    )
      continue;
    const __mmX = __mmObject.x + __mmObject.xWiggle - __mmLeft,
      __mmY = __mmObject.y + __mmObject.yWiggle - __mmTop;
    if (!ts(__mmX, __mmY, __mmObject.scale + (__mmObject.blocker || 0))) continue;
    const __mmRelationship = __mmOwnStructure(__mmObject)
        ? "own"
        : __mmFriendlyStructure(__mmObject)
          ? "friendly"
          : "enemy",
      __mmSprite = __mmTintedStructureSprite(
        __mmObject,
        __mmRelationship,
      );
    (k.save(),
      (k.globalAlpha = __mmObject.hideFromEnemy ? 0.76 : 0.9),
      k.translate(__mmX, __mmY),
      k.rotate(__mmObject.dir),
      k.drawImage(__mmSprite, -__mmSprite.width / 2, -__mmSprite.height / 2),
      k.restore());
  }
}
function __mmDrawAutoSpikeSpamGhost() {
  const __mmGhost = __mmAutoSpikeSpamGhost,
    __mmData = __mmGhost && b && b.list && b.list[__mmGhost.item];
  if (!v || !v.alive || !__mmGhost || !__mmData || !k) return;
  const __mmLeft = oe - _ / 2,
    __mmTop = ae - L / 2,
    __mmX = __mmGhost.x - __mmLeft,
    __mmY = __mmGhost.y - __mmTop;
  if (!ts(__mmX, __mmY, __mmGhost.scale + 12)) return;
  const __mmSprite = __mmTintedStructureSprite(__mmData, "friendly");
  (k.save(),
    (k.globalAlpha = 0.42),
    k.translate(__mmX, __mmY),
    k.rotate(__mmGhost.angle),
    k.drawImage(
      __mmSprite,
      -__mmSprite.width / 2,
      -__mmSprite.height / 2,
    ),
    k.rotate(-__mmGhost.angle),
    (k.globalAlpha = 0.9),
    (k.strokeStyle = "#c084fc"),
    (k.lineWidth = 2),
    k.setLineDash([5, 4]),
    k.beginPath(),
    k.arc(0, 0, __mmGhost.scale + 3, 0, Math.PI * 2),
    k.stroke(),
    k.restore());
}
function __mmBreakableState(__mmObject) {
  if (!__mmObject || !Number.isFinite(Number(__mmObject.health))) return null;
  const __mmBaseHealth = Number(__mmObject.health);
  if (__mmBaseHealth <= 0) return null;
  let __mmState = __mmBreakableHealth.get(__mmObject);
  if (
    !__mmState ||
    String(__mmState.sid) !== String(__mmObject.sid) ||
    __mmState.baseHealth !== __mmBaseHealth
  ) {
    __mmState = {
      sid: __mmObject.sid,
      baseHealth: __mmBaseHealth,
      health: __mmBaseHealth,
    };
    __mmBreakableHealth.set(__mmObject, __mmState);
  }
  return __mmState;
}
function __mmPlayerHatData(__mmPlayer) {
  if (!__mmPlayer || !Array.isArray(Ze)) return null;
  for (let __mmIndex = 0; __mmIndex < Ze.length; __mmIndex++)
    if (Ze[__mmIndex].id === __mmPlayer.skinIndex) return Ze[__mmIndex];
  return null;
}
function __mmToolCooldownDuration(__mmPlayer, __mmWeaponId) {
  const __mmWeapon = b && b.weapons && b.weapons[__mmWeaponId];
  if (!__mmWeapon) return 0;
  const __mmBaseSpeed = Number(__mmWeapon.speed),
    __mmHat = __mmPlayerHatData(__mmPlayer),
    __mmHatSpeed = Number(__mmHat && __mmHat.atkSpd),
    __mmMultiplier = Number.isFinite(__mmHatSpeed) && __mmHatSpeed > 0
      ? __mmHatSpeed
      : 1;
  return Number.isFinite(__mmBaseSpeed) && __mmBaseSpeed > 0
    ? Math.max(1, __mmBaseSpeed * __mmMultiplier)
    : 0;
}
function __mmTrackPlayerToolCooldown(__mmPlayerSid, __mmWeaponId) {
  if (__mmPlayerSid == null) return;
  let __mmPlayer = null;
  try {
    __mmPlayer = Rt(__mmPlayerSid);
  } catch (__mmLookupError) {}
  if (
    !__mmPlayer &&
    v &&
    v.sid != null &&
    String(v.sid) === String(__mmPlayerSid)
  )
    __mmPlayer = v;
  const __mmResolvedWeapon = Number(
      __mmWeaponId == null && __mmPlayer
        ? __mmPlayer.weaponIndex
        : __mmWeaponId,
    ),
    __mmDuration = __mmToolCooldownDuration(
      __mmPlayer,
      __mmResolvedWeapon,
    );
  if (!Number.isInteger(__mmResolvedWeapon) || !__mmDuration) return;
  const __mmKey = String(__mmPlayerSid),
    __mmNow = Date.now(),
    __mmState =
      __mmPlayerToolCooldowns[__mmKey] ||
      (__mmPlayerToolCooldowns[__mmKey] = {
        weapons: Object.create(null),
        updatedAt: __mmNow,
      });
  ((__mmState.weapons[String(__mmResolvedWeapon)] = {
    weapon: __mmResolvedWeapon,
    duration: __mmDuration,
    startedAt: __mmNow,
    readyAt: __mmNow + __mmDuration,
  }),
    (__mmState.updatedAt = __mmNow));
}
function __mmPlayerCooldownRows(__mmPlayer, __mmNow) {
  if (!__mmPlayer || __mmPlayer.sid == null) return [];
  const __mmIsLocal = !!(
      v && String(__mmPlayer.sid) === String(v.sid)
    ),
    __mmState = __mmPlayerToolCooldowns[String(__mmPlayer.sid)],
    __mmIds = [];
  function __mmAddWeapon(__mmWeaponId) {
    if (__mmWeaponId == null) return;
    const __mmId = Number(__mmWeaponId);
    Number.isInteger(__mmId) &&
      b &&
      b.weapons &&
      b.weapons[__mmId] &&
      !__mmIds.includes(__mmId) &&
      __mmIds.push(__mmId);
  }
  if (__mmIsLocal && Array.isArray(v.weapons)) {
    __mmAddWeapon(v.weapons[0]);
    __mmAddWeapon(v.weapons[1]);
  } else {
    __mmAddWeapon(__mmPlayer.weaponIndex);
    if (__mmState && __mmState.weapons) {
      Object.keys(__mmState.weapons)
        .map(function (__mmKey) {
          return __mmState.weapons[__mmKey];
        })
        .sort(function (__mmA, __mmB) {
          return (__mmB.startedAt || 0) - (__mmA.startedAt || 0);
        })
        .forEach(function (__mmEntry) {
          __mmAddWeapon(__mmEntry.weapon);
        });
    }
  }
  return __mmIds.slice(0, 2).map(function (__mmWeaponId) {
    const __mmTracked =
        __mmState && __mmState.weapons
          ? __mmState.weapons[String(__mmWeaponId)]
          : null,
      __mmDuration = Math.max(
        1,
        Number(__mmTracked && __mmTracked.duration) ||
          __mmToolCooldownDuration(__mmPlayer, __mmWeaponId) ||
          1,
      ),
      __mmRemaining = __mmIsLocal
        ? Math.max(
            0,
            Number(v.reloads && v.reloads[__mmWeaponId]) || 0,
          )
        : Math.max(
            0,
            Number(__mmTracked && __mmTracked.readyAt) - __mmNow || 0,
          );
    return {
      weapon: __mmWeaponId,
      ratio: Math.max(0, Math.min(1, 1 - __mmRemaining / Math.max(__mmDuration, __mmRemaining))),
    };
  });
}
function __mmDrawPlayerCooldownBars() {
  if (
    !__mmCooldownBarsEnabled ||
    !v ||
    !v.alive ||
    !k ||
    !Array.isArray(E)
  )
    return;
  try {
    const __mmLeft = oe - _ / 2,
      __mmTop = ae - L / 2,
      __mmNow = Date.now(),
      __mmPlayers = E.slice();
    !__mmPlayers.some(function (__mmPlayer) {
      return __mmPlayer === v ||
        (__mmPlayer && String(__mmPlayer.sid) === String(v.sid));
    }) && __mmPlayers.push(v);
    k.save();
    for (let __mmIndex = 0; __mmIndex < __mmPlayers.length; __mmIndex++) {
      const __mmPlayer = __mmPlayers[__mmIndex];
      if (
        !__mmPlayer ||
        !__mmPlayer.alive ||
        (__mmPlayer !== v && !__mmPlayer.visible)
      )
        continue;
      const __mmRows = __mmPlayerCooldownRows(__mmPlayer, __mmNow);
      if (!__mmRows.length) continue;
      const __mmX = __mmPlayer.x - __mmLeft,
        __mmY = __mmPlayer.y - __mmTop,
        __mmScale = Number(__mmPlayer.scale) || 35,
        __mmNameOffset = Number(y && y.nameY) || 0,
        __mmWidth = 46,
        __mmHeight = 5,
        __mmGap = 3,
        __mmStartX = Math.round(__mmX - __mmWidth / 2),
        __mmStartY = Math.round(__mmY + __mmScale + __mmNameOffset + 21);
      if (
        __mmStartX > _ + __mmWidth ||
        __mmStartX < -__mmWidth ||
        __mmStartY > L + 20 ||
        __mmStartY < -20
      )
        continue;
      for (let __mmRow = 0; __mmRow < __mmRows.length; __mmRow++) {
        const __mmBarY = __mmStartY + __mmRow * (__mmHeight + __mmGap),
          __mmRatio = __mmRows[__mmRow].ratio,
          __mmFill = __mmRow === 0 ? "#a855f7" : "#d8b4fe";
        ((k.fillStyle = "rgba(5, 3, 9, 0.82)"),
          k.fillRect(__mmStartX, __mmBarY, __mmWidth, __mmHeight),
          (k.fillStyle = __mmFill),
          (k.shadowColor = __mmFill),
          (k.shadowBlur = __mmRatio >= 1 ? 5 : 2),
          k.fillRect(
            __mmStartX + 1,
            __mmBarY + 1,
            Math.max(0, (__mmWidth - 2) * __mmRatio),
            __mmHeight - 2,
          ),
          (k.shadowBlur = 0),
          (k.strokeStyle = "rgba(216, 180, 254, 0.72)"),
          (k.lineWidth = 1),
          k.strokeRect(__mmStartX + 0.5, __mmBarY + 0.5, __mmWidth - 1, __mmHeight - 1));
      }
    }
    k.restore();
  } catch (__mmCooldownDrawError) {
    try {
      k && k.restore();
    } catch (__mmIgnore) {}
  }
}
function __mmWeaponStructureDamage(__mmPlayer, __mmWeaponId, __mmObject) {
  if (!__mmPlayer || !b || !b.weapons || !__mmObject) return 0;
  const __mmWeapon = b.weapons[__mmWeaponId];
  if (!__mmWeapon) return 0;
  if (__mmWeapon.projectile != null) {
    const __mmProjectile = b.projectiles && b.projectiles[__mmWeapon.projectile];
    return __mmObject.projDmg && __mmProjectile
      ? Math.max(0, Number(__mmProjectile.dmg) || 0)
      : 0;
  }
  const __mmVariant =
      y && y.weaponVariants && y.weaponVariants[__mmPlayer.weaponVariant],
    __mmVariantMultiplier = Number(__mmVariant && __mmVariant.val) || 1,
    __mmStructureMultiplier = Number(__mmWeapon.sDmg) || 1,
    __mmHat = __mmPlayerHatData(__mmPlayer),
    __mmHatMultiplier = Number(__mmHat && __mmHat.bDmg) || 1;
  return Math.max(
    0,
    (Number(__mmWeapon.dmg) || 0) *
      __mmVariantMultiplier *
      __mmStructureMultiplier *
      __mmHatMultiplier,
  );
}
function __mmCurrentStructureDamage(__mmObject) {
  if (!v || !v.alive || Number(v.buildIndex) >= 0) return 0;
  return __mmWeaponStructureDamage(v, v.weaponIndex, __mmObject);
}
function __mmMatThiefStructureAllowed(__mmObject) {
  if (
    !v ||
    !v.alive ||
    !__mmObject ||
    !__mmObject.active ||
    !__mmObject.isItem ||
    !__mmObject.owner
  )
    return !1;
  const __mmOwnerSid = __mmObject.owner.sid;
  // Teammate structures are intentional targets too, but the local player's
  // own placed structures must never be selected.
  if (
    __mmObject.owner === v ||
    (__mmOwnerSid != null && String(__mmOwnerSid) === String(v.sid))
  )
    return !1;
  const __mmOwnerPlayer =
    __mmOwnerSid != null && typeof Rt === "function"
      ? Rt(__mmOwnerSid)
      : __mmObject.owner;
  if (__mmIsFriendPlayer(__mmOwnerPlayer)) return !1;
  const __mmItem = b && b.list && b.list[__mmObject.id],
    __mmName = String((__mmItem && __mmItem.name) || "").toLowerCase();
  return (
    __mmName === "windmill" ||
    __mmName === "faster windmill" ||
    __mmName === "power mill" ||
    __mmName === "turret" ||
    __mmName === "teleporter"
  );
}
function __mmMatThiefWeaponCandidates() {
  if (!v || !v.alive || !Array.isArray(v.weapons)) return [];
  const __mmWeapons = [],
    __mmSeen = new Set();
  for (let __mmIndex = 0; __mmIndex < v.weapons.length; __mmIndex++) {
    const __mmWeapon = v.weapons[__mmIndex],
      __mmData = b && b.weapons && b.weapons[__mmWeapon];
    if (
      __mmWeapon == null ||
      __mmSeen.has(__mmWeapon) ||
      !__mmData ||
      __mmData.projectile != null ||
      !__mmWeaponReady(__mmWeapon)
    )
      continue;
    (__mmSeen.add(__mmWeapon), __mmWeapons.push(__mmWeapon));
  }
  return __mmWeapons;
}
function __mmMatThiefTargetsForWeapon(__mmWeapon, __mmNow) {
  if (!v || !v.alive || !Array.isArray(ge)) return [];
  const __mmWeaponData = b && b.weapons && b.weapons[__mmWeapon],
    __mmRange = Number(__mmWeaponData && __mmWeaponData.range);
  if (!Number.isFinite(__mmRange) || __mmRange <= 0) return [];
  const __mmTargets = [];
  for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
    const __mmObject = ge[__mmIndex];
    if (!__mmMatThiefStructureAllowed(__mmObject)) continue;
    const __mmReservedUntil = Number(__mmMatThiefReservations.get(__mmObject));
    if (Number.isFinite(__mmReservedUntil) && __mmReservedUntil > __mmNow)
      continue;
    const __mmState = __mmBreakableState(__mmObject),
      __mmDamage = __mmWeaponStructureDamage(v, __mmWeapon, __mmObject);
    if (!__mmState || __mmDamage <= 0 || __mmState.health > __mmDamage + 0.001)
      continue;
    const __mmDx = __mmObject.x - v.x,
      __mmDy = __mmObject.y - v.y,
      __mmDistance = Math.hypot(__mmDx, __mmDy),
      // Match the server gather check: center distance minus structure scale
      // must fit inside the selected weapon's range.
      __mmReach = __mmRange + (Number(__mmObject.scale) || 0);
    if (__mmDistance > __mmReach) continue;
    __mmTargets.push({
      object: __mmObject,
      angle: Math.atan2(__mmDy, __mmDx),
      distance: __mmDistance,
    });
  }
  return __mmTargets;
}
function __mmMatThiefAngleDifference(__mmFirst, __mmSecond) {
  return Math.atan2(
    Math.sin(__mmSecond - __mmFirst),
    Math.cos(__mmSecond - __mmFirst),
  );
}
function __mmMatThiefAimPlan(__mmTargets) {
  if (!__mmTargets.length) return null;
  const __mmGatherAngle = Math.max(0.05, Number(y && y.gatherAngle) || 0.35),
    __mmCandidateAngles = [];
  for (let __mmIndex = 0; __mmIndex < __mmTargets.length; __mmIndex++)
    __mmCandidateAngles.push(__mmTargets[__mmIndex].angle);
  for (let __mmFirst = 0; __mmFirst < __mmTargets.length; __mmFirst++)
    for (
      let __mmSecond = __mmFirst + 1;
      __mmSecond < __mmTargets.length;
      __mmSecond++
    ) {
      const __mmDifference = __mmMatThiefAngleDifference(
        __mmTargets[__mmFirst].angle,
        __mmTargets[__mmSecond].angle,
      );
      Math.abs(__mmDifference) <= 2 * __mmGatherAngle + 0.0001 &&
        __mmCandidateAngles.push(
          __mmTargets[__mmFirst].angle + __mmDifference / 2,
        );
    }
  let __mmBest = null;
  for (
    let __mmAngleIndex = 0;
    __mmAngleIndex < __mmCandidateAngles.length;
    __mmAngleIndex++
  ) {
    const __mmAim = __mmCandidateAngles[__mmAngleIndex],
      __mmCovered = __mmTargets.filter(
        (__mmTarget) =>
          Math.abs(__mmMatThiefAngleDifference(__mmAim, __mmTarget.angle)) <=
          __mmGatherAngle + 0.0001,
      ),
      __mmDistanceScore = __mmCovered.reduce(
        (__mmTotal, __mmTarget) => __mmTotal + __mmTarget.distance,
        0,
      );
    if (
      !__mmBest ||
      __mmCovered.length > __mmBest.targets.length ||
      (__mmCovered.length === __mmBest.targets.length &&
        __mmDistanceScore < __mmBest.distanceScore)
    )
      __mmBest = {
        angle: __mmAim,
        targets: __mmCovered,
        distanceScore: __mmDistanceScore,
      };
  }
  return __mmBest;
}
function __mmMatThiefPlan() {
  const __mmNow = Date.now(),
    __mmWeapons = __mmMatThiefWeaponCandidates(),
    __mmSelected = __mmSelectedWeapon();
  let __mmBest = null;
  for (let __mmIndex = 0; __mmIndex < __mmWeapons.length; __mmIndex++) {
    const __mmWeapon = __mmWeapons[__mmIndex],
      __mmTargets = __mmMatThiefTargetsForWeapon(__mmWeapon, __mmNow),
      __mmAim = __mmMatThiefAimPlan(__mmTargets);
    if (!__mmAim || !__mmAim.targets.length) continue;
    const __mmData = b.weapons[__mmWeapon],
      __mmDamage = __mmWeaponStructureDamage(
        v,
        __mmWeapon,
        __mmAim.targets[0].object,
      ),
      __mmPlan = {
        weapon: __mmWeapon,
        angle: __mmAim.angle,
        targets: __mmAim.targets,
        distanceScore: __mmAim.distanceScore,
        damage: __mmDamage,
        speed: Math.max(50, Number(__mmData.speed) || 400),
      },
      __mmPlanUsesSelected = __mmWeapon === __mmSelected,
      __mmBestUsesSelected = __mmBest && __mmBest.weapon === __mmSelected;
    if (
      !__mmBest ||
      __mmPlan.targets.length > __mmBest.targets.length ||
      (__mmPlan.targets.length === __mmBest.targets.length &&
        __mmPlanUsesSelected &&
        !__mmBestUsesSelected) ||
      (__mmPlan.targets.length === __mmBest.targets.length &&
        __mmPlanUsesSelected === __mmBestUsesSelected &&
        (__mmPlan.distanceScore < __mmBest.distanceScore ||
          (__mmPlan.distanceScore === __mmBest.distanceScore &&
            __mmPlan.damage > __mmBest.damage)))
    )
      __mmBest = __mmPlan;
  }
  return __mmBest;
}
function __mmFinishMatThief(__mmReason) {
  const __mmAim = __mmMatThiefAimAngle,
    __mmReturnAngle = __mmMatThiefReturnAngle,
    __mmTool = __mmMatThiefRestoreTool,
    __mmRestore = __mmActionMayRestore("matThief");
  (__mmMatThiefReleaseTimer && clearTimeout(__mmMatThiefReleaseTimer),
    (__mmMatThiefReleaseTimer = 0),
    __mmMatThiefAttackHeld && O.send("F", 0, __mmAim),
    (__mmMatThiefAttackHeld = !1),
    (__mmMatThiefAimAngle = null),
    (__mmMatThiefReturnAngle = null),
    (__mmMatThiefRestoreTool = null),
    __mmRestore && __mmRestoreTool(__mmTool),
    __mmRestore &&
      Number.isFinite(__mmReturnAngle) &&
      O.send("D", __mmReturnAngle),
    __mmActionRelease("matThief", __mmReason || "last hit complete"));
}
function __mmUpdateMatThief() {
  if (
    !__mmMatThiefEnabled ||
    document.hidden ||
    !v ||
    !v.alive ||
    v.lockMove ||
    __mmMatThiefReleaseTimer ||
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmTrapAttackActive ||
    __mmBoostBreakHeld ||
    __mmBuildSpamTimer ||
    __mmFoodSpamTimer ||
    __mmInsta.isActive() ||
    __mmSyncFollowerEnabled ||
    (__mmActionOwner !== "idle" && __mmActionOwner !== "weaponRecharge")
  )
    return;
  const __mmPlan = __mmMatThiefPlan();
  if (!__mmPlan) return;
  __mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
  if (!__mmActionClaim("matThief", "one-hit structure")) return;
  let __mmReturnAngle;
  try {
    __mmReturnAngle = __mmOriginalAimDirection();
  } catch (__mmAimError) {
    __mmReturnAngle = 0;
  }
  const __mmNow = Date.now(),
    __mmReservationUntil =
      __mmNow + Math.max(__mmPlan.speed, 2 * __mmServerTickMs());
  for (let __mmIndex = 0; __mmIndex < __mmPlan.targets.length; __mmIndex++)
    __mmMatThiefReservations.set(
      __mmPlan.targets[__mmIndex].object,
      __mmReservationUntil,
    );
  ((__mmMatThiefReturnAngle = __mmReturnAngle),
    (__mmMatThiefRestoreTool = __mmSelectedTool()),
    (__mmMatThiefAimAngle = __mmPlan.angle),
    O.send("D", __mmPlan.angle),
    je(__mmPlan.weapon, !0),
    O.send("F", 1, __mmPlan.angle),
    (__mmMatThiefAttackHeld = !0),
    (__mmMatThiefReleaseTimer = setTimeout(function () {
      __mmFinishMatThief("last hit sent");
    }, __mmServerTickMs())));
}
function __mmStartMatThief() {
  __mmMatThiefEnabled &&
    !__mmMatThiefTimer &&
    (__mmMatThiefTimer = setInterval(__mmUpdateMatThief, __mmFastCheckMs()));
}
function __mmStopMatThief() {
  (__mmMatThiefTimer && clearInterval(__mmMatThiefTimer),
    (__mmMatThiefTimer = 0),
    __mmFinishMatThief("mode disabled"));
}
function __mmMobStealEntityKey(__mmAnimal) {
  if (!__mmAnimal) return null;
  const __mmId =
    __mmAnimal.sid != null
      ? __mmAnimal.sid
      : __mmAnimal.id != null
        ? __mmAnimal.id
        : __mmAnimal.index;
  return __mmId == null ? null : "mob:" + String(__mmId);
}
function __mmMobStealVariantMultiplier(__mmWeapon) {
  const __mmVariants = y && y.weaponVariants,
    __mmXp = Number(v && v.weaponXP && v.weaponXP[__mmWeapon]) || 0;
  if (!Array.isArray(__mmVariants)) return 1;
  for (let __mmIndex = __mmVariants.length - 1; __mmIndex >= 0; __mmIndex--)
    if (__mmXp >= (Number(__mmVariants[__mmIndex].xp) || 0))
      return Number(__mmVariants[__mmIndex].val) || 1;
  return 1;
}
function __mmMobStealTailData(__mmTail) {
  if (typeof pa === "undefined" || !Array.isArray(pa)) return null;
  for (let __mmIndex = 0; __mmIndex < pa.length; __mmIndex++)
    if (Number(pa[__mmIndex].id) === Number(__mmTail)) return pa[__mmIndex];
  return null;
}
function __mmMobStealDamage(__mmWeapon, __mmUseBull, __mmStripMonkeyTail) {
  const __mmData = b && b.weapons && b.weapons[__mmWeapon];
  if (!__mmData || __mmData.projectile != null) return 0;
  const __mmHat = __mmUseBull
      ? __mmPlayerHatData({ skinIndex: 7 })
      : __mmPlayerHatData(v),
    __mmTail = __mmStripMonkeyTail
      ? null
      : __mmMobStealTailData(v && v.tailIndex),
    __mmHatMultiplier = Number(__mmHat && __mmHat.dmgMultO) || 1,
    __mmTailMultiplier = Number(__mmTail && __mmTail.dmgMultO) || 1;
  return Math.max(
    0,
    (Number(__mmData.dmg) || 0) *
      __mmMobStealVariantMultiplier(__mmWeapon) *
      __mmHatMultiplier *
      __mmTailMultiplier,
  );
}
function __mmMobStealWeaponCandidates() {
  if (!v || !v.alive || !Array.isArray(v.weapons)) return [];
  const __mmUseBull = !!(
      __mmBullHelmetEnabled && __mmCanEquipHat(7)
    ),
    __mmStripMonkeyTail = Number(v.tailIndex) === 11,
    __mmSelected = __mmSelectedWeapon(),
    __mmCandidates = [],
    __mmSeen = new Set();
  for (let __mmIndex = 0; __mmIndex < v.weapons.length; __mmIndex++) {
    const __mmWeapon = v.weapons[__mmIndex],
      __mmData = b && b.weapons && b.weapons[__mmWeapon],
      __mmRange = Number(__mmData && __mmData.range),
      __mmDamage = __mmMobStealDamage(
        __mmWeapon,
        __mmUseBull,
        __mmStripMonkeyTail,
      );
    if (
      __mmWeapon == null ||
      __mmSeen.has(__mmWeapon) ||
      !__mmData ||
      __mmData.projectile != null ||
      __mmData.shield ||
      !Number.isFinite(__mmRange) ||
      __mmRange <= 0 ||
      __mmDamage <= 0 ||
      !__mmWeaponReady(__mmWeapon)
    )
      continue;
    (__mmSeen.add(__mmWeapon),
      __mmCandidates.push({
        weapon: __mmWeapon,
        range: __mmRange,
        damage: __mmDamage,
        speed: Math.max(50, Number(__mmData.speed) || 400),
        selected: __mmWeapon === __mmSelected,
        useBull: __mmUseBull,
        stripMonkeyTail: __mmStripMonkeyTail,
      }));
  }
  return __mmCandidates;
}
function __mmMobStealPredictPoint(
  __mmEntity,
  __mmKey,
  __mmNow,
  __mmLeadMs,
) {
  const __mmX = Number(__mmEntity && __mmEntity.x),
    __mmY = Number(__mmEntity && __mmEntity.y);
  if (!Number.isFinite(__mmX) || !Number.isFinite(__mmY)) return null;
  const __mmPrevious = __mmMobStealMotion[__mmKey],
    __mmElapsed = __mmPrevious
      ? Math.max(1, Math.min(250, __mmNow - __mmPrevious.at))
      : 0;
  let __mmVelocityX = __mmPrevious
      ? (__mmX - __mmPrevious.x) / __mmElapsed
      : 0,
    __mmVelocityY = __mmPrevious
      ? (__mmY - __mmPrevious.y) / __mmElapsed
      : 0;
  const __mmServerElapsed = Number(__mmEntity.t2) - Number(__mmEntity.t1),
    __mmServerVelocityX =
      (Number(__mmEntity.x2) - Number(__mmEntity.x1)) / __mmServerElapsed,
    __mmServerVelocityY =
      (Number(__mmEntity.y2) - Number(__mmEntity.y1)) / __mmServerElapsed;
  if (
    Number.isFinite(__mmServerVelocityX) &&
    Number.isFinite(__mmServerVelocityY) &&
    __mmServerElapsed > 0 &&
    __mmServerElapsed <= 500
  ) {
    ((__mmVelocityX = __mmPrevious
      ? __mmServerVelocityX * 0.75 + __mmVelocityX * 0.25
      : __mmServerVelocityX),
      (__mmVelocityY = __mmPrevious
        ? __mmServerVelocityY * 0.75 + __mmVelocityY * 0.25
        : __mmServerVelocityY));
  }
  __mmMobStealMotion[__mmKey] = { x: __mmX, y: __mmY, at: __mmNow };
  return {
    x: Math.max(0, Math.min(y.mapScale, __mmX + __mmVelocityX * __mmLeadMs)),
    y: Math.max(0, Math.min(y.mapScale, __mmY + __mmVelocityY * __mmLeadMs)),
  };
}
function __mmMobStealPlan() {
  if (!v || !v.alive || !Array.isArray(N)) return null;
  const __mmWeapons = __mmMobStealWeaponCandidates();
  if (!__mmWeapons.length) return null;
  const __mmNow = Date.now(),
    __mmPing = Number(window.pingTime),
    __mmLeadMs = Math.min(
      300,
      __mmServerTickMs() +
        (Number.isFinite(__mmPing) ? Math.max(0, __mmPing / 2) : 0),
    ),
    __mmSelf = __mmMobStealPredictPoint(
      v,
      "self",
      __mmNow,
      __mmLeadMs,
    ),
    __mmSeen = Object.create(null);
  if (!__mmSelf) return null;
  __mmSeen.self = !0;
  let __mmBest = null;
  for (let __mmIndex = 0; __mmIndex < N.length; __mmIndex++) {
    const __mmAnimal = N[__mmIndex],
      __mmKey = __mmMobStealEntityKey(__mmAnimal);
    if (__mmKey == null) continue;
    __mmSeen[__mmKey] = !0;
    const __mmPrediction = __mmMobStealPredictPoint(
      __mmAnimal,
      __mmKey,
      __mmNow,
      __mmLeadMs,
    );
    if (
      !__mmPrediction ||
      !__mmAnimal ||
      __mmAnimal.active === !1 ||
      __mmAnimal.alive === !1 ||
      !__mmAnimal.visible ||
      !(Number(__mmAnimal.health) > 0) ||
      Number(__mmMobStealReservations[__mmKey]) > __mmNow
    )
      continue;
    for (
      let __mmWeaponIndex = 0;
      __mmWeaponIndex < __mmWeapons.length;
      __mmWeaponIndex++
    ) {
      const __mmWeapon = __mmWeapons[__mmWeaponIndex];
      if (Number(__mmAnimal.health) > __mmWeapon.damage + 0.001) continue;
      const __mmDx = __mmPrediction.x - __mmSelf.x,
        __mmDy = __mmPrediction.y - __mmSelf.y,
        __mmDistance = Math.hypot(__mmDx, __mmDy),
        // Match the server gather hitbox for players and AI targets.
        __mmReach =
          __mmWeapon.range + (Number(__mmAnimal.scale) || 35) * 1.8;
      if (__mmDistance > __mmReach) continue;
      const __mmScore =
        __mmDistance / Math.max(1, __mmReach) +
        (__mmWeapon.selected ? 0 : 0.08);
      if (!__mmBest || __mmScore < __mmBest.score)
        __mmBest = {
          animal: __mmAnimal,
          key: __mmKey,
          weapon: __mmWeapon.weapon,
          damage: __mmWeapon.damage,
          speed: __mmWeapon.speed,
          useBull: __mmWeapon.useBull,
          stripMonkeyTail: __mmWeapon.stripMonkeyTail,
          x: __mmPrediction.x,
          y: __mmPrediction.y,
          angle: Math.atan2(__mmDy, __mmDx),
          score: __mmScore,
        };
    }
  }
  for (const __mmKey in __mmMobStealMotion)
    __mmSeen[__mmKey] || delete __mmMobStealMotion[__mmKey];
  for (const __mmKey in __mmMobStealReservations)
    Number(__mmMobStealReservations[__mmKey]) <= __mmNow &&
      delete __mmMobStealReservations[__mmKey];
  return __mmBest;
}
function __mmFinishMobSteal(__mmReason) {
  const __mmAim = __mmMobStealAimAngle,
    __mmHadAim = Number.isFinite(__mmMobStealAimAngle),
    __mmTool = __mmMobStealRestoreTool,
    __mmHat = __mmMobStealRestoreHat,
    __mmTail = __mmMobStealRestoreTail,
    __mmRestore = __mmActionMayRestore("mobSteal");
  (__mmMobStealReleaseTimer && clearTimeout(__mmMobStealReleaseTimer),
    (__mmMobStealReleaseTimer = 0),
    __mmMobStealAttackHeld && O.send("F", 0, __mmAim),
    (__mmMobStealAttackHeld = !1),
    (__mmMobStealAimAngle = null),
    (__mmMobStealRestoreTool = null),
    (__mmMobStealRestoreHat = null),
    (__mmMobStealRestoreTail = null),
    __mmRestore && __mmRestoreTool(__mmTool),
    __mmRestore && __mmEquipGearPair(__mmHat, __mmTail, !0),
    __mmActionRelease("mobSteal", __mmReason || "predicted last hit complete"),
    __mmHadAim && __mmScheduleMouseAimReturn(),
    v && v.alive && __mmUpdateWeaponRecharge());
}
function __mmStartMobStealAttack(__mmPlan) {
  if (!__mmPlan || !v || !v.alive) return !1;
  (__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0),
    __mmActionOwner === "matThief" &&
      __mmFinishMatThief("mob steal last hit"));
  if (!__mmActionClaim("mobSteal", "predicted one-hit mob")) return !1;
  const __mmNow = Date.now();
  (__mmMobStealReservations[__mmPlan.key] =
    __mmNow + Math.max(__mmPlan.speed, 2 * __mmServerTickMs()),
    (__mmMobStealRestoreTool = __mmSelectedTool()),
    (__mmMobStealRestoreHat = __mmPlan.useBull ? v.skinIndex : null),
    (__mmMobStealRestoreTail = __mmPlan.stripMonkeyTail ? v.tailIndex : null),
    __mmEquipGearPair(
      __mmPlan.useBull ? 7 : null,
      __mmPlan.stripMonkeyTail ? 0 : null,
      !0,
    ),
    (__mmMobStealAimAngle = __mmPlan.angle),
    O.send("D", __mmPlan.angle),
    je(__mmPlan.weapon, !0),
    O.send("F", 1, __mmPlan.angle),
    (__mmMobStealAttackHeld = !0),
    (__mmMobStealReleaseTimer = setTimeout(function () {
      __mmFinishMobSteal("predicted last hit sent");
    }, __mmServerTickMs())));
  return !0;
}
function __mmUpdateMobSteal() {
  if (
    !__mmMobStealEnabled ||
    document.hidden ||
    !v ||
    !v.alive ||
    v.lockMove ||
    __mmMobStealReleaseTimer ||
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmTrapAttackActive ||
    __mmBoostBreakHeld ||
    __mmBuildSpamTimer ||
    __mmFoodSpamTimer ||
    __mmInsta.isActive() ||
    __mmSyncFollowerEnabled ||
    !(
      __mmActionOwner === "idle" ||
      __mmActionOwner === "weaponRecharge" ||
      __mmActionOwner === "matThief"
    )
  )
    return;
  const __mmPlan = __mmMobStealPlan();
  __mmPlan && __mmStartMobStealAttack(__mmPlan);
}
function __mmStartMobSteal() {
  __mmMobStealEnabled &&
    !__mmMobStealTimer &&
    (__mmMobStealTimer = setInterval(__mmUpdateMobSteal, 5));
}
function __mmStopMobSteal() {
  (__mmMobStealTimer && clearInterval(__mmMobStealTimer),
    (__mmMobStealTimer = 0),
    __mmFinishMobSteal("mode disabled"));
}
function __mmRecordPlayerSwing(__mmPlayerSid, __mmWeapon) {
  if (__mmPlayerSid == null) return;
  __mmTrackPlayerToolCooldown(__mmPlayerSid, __mmWeapon);
  __mmRecentPlayerSwings[String(__mmPlayerSid)] = {
    at: Date.now(),
    weapon: __mmWeapon,
  };
}
function __mmObservedObjectHitDamage(__mmObject, __mmHitAngle) {
  if (!__mmObject || !Array.isArray(E)) return 0;
  const __mmNow = Date.now();
  let __mmBestDamage = 0,
    __mmBestScore = Infinity;
  for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
    const __mmPlayer = E[__mmIndex],
      __mmRecent =
        __mmPlayer && __mmRecentPlayerSwings[String(__mmPlayer.sid)];
    if (!__mmPlayer || !__mmPlayer.alive || !__mmRecent) continue;
    const __mmAge = __mmNow - __mmRecent.at,
      __mmWeaponId =
        __mmRecent.weapon == null ? __mmPlayer.weaponIndex : __mmRecent.weapon,
      __mmWeapon = b.weapons && b.weapons[__mmWeaponId];
    if (__mmAge < 0 || __mmAge > 900 || !__mmWeapon) continue;
    const __mmDx = __mmObject.x - __mmPlayer.x,
      __mmDy = __mmObject.y - __mmPlayer.y,
      __mmDistance = Math.hypot(__mmDx, __mmDy),
      __mmDirection = Math.atan2(__mmDy, __mmDx),
      __mmAngleDifference = M.getAngleDist(__mmDirection, __mmHitAngle),
      __mmMeleeReach =
        (Number(__mmWeapon.range) || 0) + (Number(__mmObject.scale) || 0) + 16;
    if (
      __mmWeapon.projectile == null &&
      (__mmDistance > __mmMeleeReach || __mmAngleDifference > 0.32)
    )
      continue;
    const __mmDamage = __mmWeaponStructureDamage(
      __mmPlayer,
      __mmWeaponId,
      __mmObject,
    );
    if (!__mmDamage) continue;
    const __mmScore = __mmAge +
      (__mmWeapon.projectile == null ? __mmDistance : 300);
    if (__mmScore < __mmBestScore) {
      ((__mmBestScore = __mmScore), (__mmBestDamage = __mmDamage));
    }
  }
  return __mmBestDamage || __mmCurrentStructureDamage(__mmObject);
}
function __mmObserveObjectHit(__mmAngle, __mmObjectSid) {
  const __mmObject = typeof ns === "function" ? ns(__mmObjectSid) : null,
    __mmState = __mmBreakableState(__mmObject);
  if (!__mmObject || !__mmState) return;
  const __mmDamage = __mmObservedObjectHitDamage(
    __mmObject,
    Number(__mmAngle) || 0,
  );
  if (__mmDamage > 0)
    __mmState.health = Math.max(0, __mmState.health - __mmDamage);
}
function __mmDrawBreakableHitCounts() {
  if (!v || !v.alive || !k || !Array.isArray(ge)) return;
  const __mmLeft = oe - _ / 2,
    __mmTop = ae - L / 2;
  (k.save(),
    (k.textAlign = "center"),
    (k.textBaseline = "middle"));
  for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
    const __mmObject = ge[__mmIndex],
      __mmState = __mmBreakableState(__mmObject);
    if (!__mmObject || !__mmObject.active || !__mmState) continue;
    const __mmX = __mmObject.x + __mmObject.xWiggle - __mmLeft,
      __mmY = __mmObject.y + __mmObject.yWiggle - __mmTop;
    if (!ts(__mmX, __mmY, (Number(__mmObject.scale) || 35) + 10)) continue;
    const __mmDamage = __mmCurrentStructureDamage(__mmObject),
      __mmHits = __mmDamage > 0
        ? String(Math.max(0, Math.ceil(__mmState.health / __mmDamage)))
        : "∞";
    ((k.globalAlpha = 0.96),
      (k.shadowColor = "#a855f7"),
      (k.shadowBlur = 8),
      (k.strokeStyle = "rgba(5,3,9,.92)"),
      (k.lineWidth = 4),
      (k.font = "900 20px Hammersmith One, Arial, sans-serif"),
      k.strokeText(__mmHits, __mmX, __mmY),
      (k.fillStyle = "#ffffff"),
      k.fillText(__mmHits, __mmX, __mmY));
  }
  k.restore();
}
Ge = function (__mmLayer, __mmLeft, __mmTop) {
  const __mmResult = __mmOriginalObjectRender.apply(this, arguments);
  return (__mmDrawStructureTints(__mmLayer, __mmLeft, __mmTop), __mmResult);
};
Wl = function (__mmAngle, __mmObjectSid) {
  __mmObserveObjectHit(__mmAngle, __mmObjectSid);
  return __mmOriginalObjectHit.apply(this, arguments);
};
function __mmUpdateMetrics() {
  __mmMetricFrames += 1;
  const __mmNow = performance.now(),
    __mmElapsed = __mmNow - __mmMetricUpdatedAt;
  if (__mmElapsed < 500) return;
  ((__mmMetricFps = __mmMetricFrames * 1000 / __mmElapsed),
    (__mmMetricPps = __mmMetricPacketWindow * 1000 / __mmElapsed),
    (__mmMetricFrames = 0),
    (__mmMetricPacketWindow = 0),
    (__mmMetricUpdatedAt = __mmNow),
    window.dispatchEvent(
      new CustomEvent("MooMooKittyMetrics", {
        detail: {
          ping: Number.isFinite(Number(window.pingTime)) ? Number(window.pingTime) : null,
          fps: __mmMetricFps,
          packets: __mmMetricPackets,
          pps: __mmMetricPps,
        },
      }),
    ));
}
Cl = function () {
  const __mmResult = __mmOriginalRender.apply(this, arguments);
  return (
    __mmUpdateMetrics(),
    __mmDrawEsp(),
    __mmDrawPlayerCooldownBars(),
    __mmDrawAutoSpikeSpamGhost(),
    __mmDrawBreakableHitCounts(),
    __mmResult
  );
};
function __mmIsPlaceableItem(__mmItem) {
  const __mmData = b && b.list && b.list[__mmItem];
  return !!(__mmData && __mmData.group && __mmData.group.place);
}
function __mmSelectedPlaceableItem() {
  if (!v) return null;
  return __mmIsPlaceableItem(__mmLastBuildItem)
    ? __mmLastBuildItem
    : __mmIsPlaceableItem(v.buildIndex)
      ? v.buildIndex
      : null;
}
function __mmCanEquipHat(__mmHat) {
  return __mmHat === 0 || !!(v && v.skins && v.skins[__mmHat]);
}
function __mmShiftHeld() {
  return typeof ne !== "undefined" && !!ne[16];
}
function __mmPlayerMoving() {
  return (
    typeof ne !== "undefined" &&
    !!(
      ne[87] ||
      ne[38] ||
      ne[83] ||
      ne[40] ||
      ne[65] ||
      ne[37] ||
      ne[68] ||
      ne[39]
    )
  );
}
function __mmHasStick() {
  return !!(v && v.weapons && v.weapons.includes(8));
}
function __mmAutoPurchaseQueue() {
  const __mmEntries = __mmAutoPurchaseEntries;
  return __mmHasStick()
    ? [
        __mmEntries.monkeyTail,
        __mmEntries.soldier,
        __mmEntries.booster,
        __mmEntries.emp,
        __mmEntries.turret,
        __mmEntries.tank,
        __mmEntries.shadow,
        __mmEntries.angel,
        __mmEntries.blood,
        __mmEntries.corrupt,
      ]
    : [
        __mmEntries.monkeyTail,
        __mmEntries.soldier,
        __mmEntries.bull,
        __mmEntries.booster,
        __mmEntries.emp,
        __mmEntries.turret,
        __mmEntries.tank,
        __mmEntries.shadow,
        __mmEntries.angel,
        __mmEntries.blood,
        __mmEntries.corrupt,
      ];
}
function __mmOwnsAutoPurchaseEntry(__mmEntry) {
  return !!(
    v &&
    __mmEntry &&
    ( __mmEntry.tail
      ? v.tails && v.tails[__mmEntry.id]
      : v.skins && v.skins[__mmEntry.id])
  );
}
function __mmUpdateAutoPurchase() {
  if (
    !__mmAutoPurchaseEnabled ||
    __mmSyncFollowerEnabled ||
    __mmInsta.isActive() ||
    !v ||
    !v.alive
  )
    return;
  if (
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmTrapAttackActive ||
    __mmBoostBreakHeld
  )
    return;
  const __mmNow = Date.now(),
    __mmPending = __mmAutoPurchasePending;
  if (__mmPending) {
    if (__mmOwnsAutoPurchaseEntry(__mmPending))
      __mmAutoPurchasePending = null;
    else if (__mmNow - __mmPending.at < Math.max(350, __mmServerTickMs() * 3))
      return;
    else __mmAutoPurchasePending = null;
  }
  const __mmQueue = __mmAutoPurchaseQueue();
  for (let __mmIndex = 0; __mmIndex < __mmQueue.length; __mmIndex++) {
    const __mmEntry = __mmQueue[__mmIndex];
    if (__mmOwnsAutoPurchaseEntry(__mmEntry)) continue;
    // Preserve the requested order: do not spend on a later item until the
    // next missing purchase is affordable.
    if ((Number(v.points) || 0) < __mmEntry.price) return;
    ((__mmAutoPurchasePending = { ...__mmEntry, at: __mmNow }),
      Xn(__mmEntry.id, __mmEntry.tail));
    return;
  }
}
function __mmStartAutoPurchase() {
  __mmAutoPurchaseTimer ||
    (__mmAutoPurchaseTimer = setInterval(
      __mmUpdateAutoPurchase,
      __mmFastCheckMs(),
    ));
}
function __mmStopAutoPurchase() {
  (__mmAutoPurchaseTimer && clearInterval(__mmAutoPurchaseTimer),
    (__mmAutoPurchaseTimer = 0),
    (__mmAutoPurchasePending = null));
}
function __mmEnemyWithinCombatRange() {
  if (!v || !v.alive) return !1;
  if (__mmLiveStateFresh())
    return __mmLiveState.nearestEnemyDistance <= __mmCombatRange;
  for (let __mmEnemyIndex = 0; __mmEnemyIndex < E.length; __mmEnemyIndex++) {
    const __mmEnemy = E[__mmEnemyIndex];
    if (!__mmIsEnemyPlayer(__mmEnemy)) continue;
    const __mmDx = __mmEnemy.x - v.x,
      __mmDy = __mmEnemy.y - v.y;
    if (__mmDx * __mmDx + __mmDy * __mmDy <= __mmCombatRange * __mmCombatRange)
      return !0;
  }
  return !1;
}
let __mmLastUpgradePacketAt = 0;
function __mmUpgradeSelection(__mmSelection) {
  const __mmIndex = Number(__mmSelection),
    __mmWeaponCount = b && Array.isArray(b.weapons) ? b.weapons.length : 0;
  if (!Number.isInteger(__mmIndex) || __mmIndex < 0) return null;
  if (__mmIndex < __mmWeaponCount)
    return {
      entry: b.weapons[__mmIndex],
      prerequisite: __mmOriginalWeaponPrerequisites[__mmIndex],
      owned: v && v.weapons,
    };
  const __mmItemIndex = __mmIndex - __mmWeaponCount;
  return {
    entry: b && b.list && b.list[__mmItemIndex],
    prerequisite: __mmOriginalItemPrerequisites[__mmItemIndex],
    owned: v && v.items,
  };
}
function __mmUpgradeServerSafe(__mmSelection) {
  const __mmChoice = __mmUpgradeSelection(__mmSelection);
  if (
    !v ||
    !v.alive ||
    !__mmChoice ||
    !__mmChoice.entry ||
    !(Number(v.upgradePoints) > 0)
  )
    return !1;
  const __mmRequiredAge = Number(__mmChoice.entry.age),
    __mmCurrentUpgradeAge = Number(v.upgrAge);
  if (
    Number.isFinite(__mmRequiredAge) &&
    Number.isFinite(__mmCurrentUpgradeAge) &&
    __mmRequiredAge !== __mmCurrentUpgradeAge
  )
    return !1;
  return (
    __mmChoice.prerequisite == null ||
    (Array.isArray(__mmChoice.owned) &&
      __mmChoice.owned.includes(__mmChoice.prerequisite))
  );
}
function __mmUpgradeBlockedNotice() {
  window.dispatchEvent(
    new CustomEvent("MooMooScrollZoomStatus", {
      detail: "Upgrade blocked: wrong weapon path",
    }),
  );
}
function __mmAllowUpgradePacket(__mmSelection) {
  if (!__mmUpgradeServerSafe(__mmSelection))
    return (__mmUpgradeBlockedNotice(), !1);
  const __mmNow = Date.now();
  if (__mmNow - __mmLastUpgradePacketAt < 350) return !1;
  return ((__mmLastUpgradePacketAt = __mmNow), !0);
}
function __mmMarkUnsafeUpgradeChoices() {
  if (!b || !Array.isArray(b.weapons) || !Array.isArray(b.list)) return;
  const __mmTotal = b.weapons.length + b.list.length;
  for (let __mmIndex = 0; __mmIndex < __mmTotal; __mmIndex++) {
    const __mmElement = document.getElementById("upgradeItem" + __mmIndex);
    if (!__mmElement || __mmUpgradeServerSafe(__mmIndex)) continue;
    ((__mmElement.style.opacity = "0.28"),
      (__mmElement.style.filter = "grayscale(1)"),
      (__mmElement.style.cursor = "not-allowed"),
      (__mmElement.title = "Blocked: server prerequisite not met"),
      __mmElement.setAttribute("aria-disabled", "true"),
      (__mmElement.onclick = function () {
        __mmUpgradeBlockedNotice();
      }));
  }
}
function __mmApplyAllItemsUnlock() {
  const __mmApply = function (__mmEntries, __mmOriginal) {
    if (!Array.isArray(__mmEntries)) return;
    for (let __mmIndex = 0; __mmIndex < __mmEntries.length; __mmIndex++) {
      const __mmEntry = __mmEntries[__mmIndex],
        __mmPrerequisite = __mmOriginal[__mmIndex];
      if (!__mmEntry || __mmPrerequisite == null) continue;
      __mmEntry.pre = __mmAllItemsUnlockEnabled
        ? null
        : __mmPrerequisite;
    }
  };
  // This mode is a preview only: same-age choices are rendered, while the
  // original prerequisites remain available to the packet guard below.
  (__mmApply(b && b.weapons, __mmOriginalWeaponPrerequisites),
    __mmApply(b && b.list, __mmOriginalItemPrerequisites));
}
function __mmHudState() {
  return {
    autoHeal: __mmAutoHealEnabled,
    soldierAuto: __mmSoldierAutoEnabled,
    movementGear: __mmMovementGearEnabled,
    passiveSpikeAvoidance: __mmPassiveSpikeAvoidanceEnabled,
    trapEscape: __mmTrapEscapeEnabled,
    antiBoost: __mmAntiBoostEnabled,
    antiBoostInsta: __mmAntiBoostInstaEnabled,
    threatTrap: __mmThreatTrapEnabled,
    autoCloseSpike: __mmAutoCloseSpikeEnabled,
    reloadSpike: __mmReloadSpikeEnabled,
    shieldDefense: __mmShieldDefenseEnabled,
    musketRecharge: __mmMusketRechargeEnabled,
    autoPurchase: __mmAutoPurchaseEnabled,
    matThief: __mmMatThiefEnabled,
    mobSteal: __mmMobStealEnabled,
    spinningWindmills: __mmSpinningWindmillsEnabled,
    esp: __mmEspEnabled,
    espLines: __mmEspLinesEnabled,
    predictionGhost: __mmPredictionGhostEnabled,
    cooldownBars: __mmCooldownBarsEnabled,
    bullHelmet: __mmBullHelmetEnabled,
    tankRightClick: __mmTankRightClickEnabled,
    allItemsUnlock: __mmAllItemsUnlockEnabled,
    instaKill: __mmInstaUiEnabled,
    autoInsta: __mmAutoInstaEnabled,
    autoSpikeInsta: __mmAutoSpikeInstaEnabled,
    autoSpikeSpam: __mmAutoSpikeSpamEnabled,
    antiInsta: __mmAntiInstaEnabled,
    instaSync: __mmInstaSyncEnabled,
    boostBreak: __mmBoostBreakEnabled,
    boostChat: __mmBoostChatEnabled,
    materialReply: __mmMaterialReplyEnabled,
    syncLeader: __mmSyncLeaderEnabled,
    syncFollower: __mmSyncFollowerEnabled,
    soldierRange: __mmSoldierRange,
    combatRange: __mmCombatRange,
    gearHoldTicks: __mmGearHoldTicks,
    passiveSpikeEnemyRange: __mmPassiveSpikeEnemyRange,
    antiBoostRange: __mmAntiBoostRange,
    reactionMs: __mmReactionMs,
    debugPanel: __mmDebugPanelEnabled,
    debugText: __mmRuntimeDebugText(),
    killMessageEnabled: __mmKillMessageEnabled,
    killMessage: __mmKillMessage,
    friendNames: Array.from(__mmFriendNames.values()),
  };
}
function __mmPublishHudState() {
  window.dispatchEvent(
    new CustomEvent("MooMooOPHudState", { detail: __mmHudState() }),
  );
}
function __mmSetAutoHeal(__mmEnabled) {
  ((__mmAutoHealEnabled = !!__mmEnabled),
    !__mmAutoHealEnabled &&
      __mmAutoHealWasHealing &&
      ((__mmAutoHealWasHealing = !1), __mmRestoreAutoHealWeapon()),
    window.dispatchEvent(
      new CustomEvent("MooMooScrollZoomAutoheal", {
        detail: __mmAutoHealEnabled,
      }),
    ),
    __mmPublishHudState());
}
function __mmSetSoldierAuto(__mmEnabled) {
  __mmSoldierAutoEnabled = !!__mmEnabled;
  if (
    !__mmSoldierAutoEnabled &&
    v &&
    v.alive &&
    __mmSoldierPreviousHat != null
  ) {
    const __mmHat = __mmSoldierPreviousHat;
    ((__mmSoldierPreviousHat = null),
      v.skinIndex === 6 && __mmCanEquipHat(__mmHat) && __mmEquipHatNow(__mmHat));
  }
  __mmPublishHudState();
}
function __mmSetMovementGear(__mmEnabled) {
  ((__mmMovementGearEnabled = !!__mmEnabled),
    !__mmMovementGearEnabled &&
      (__mmRestoreMovementGear(), __mmRestoreProximityTail()),
    __mmPublishHudState());
}
function __mmSetHudNumber(__mmKey, __mmValue) {
  const __mmNumber = Number(__mmValue);
  if (!Number.isFinite(__mmNumber)) return;
  (__mmKey === "soldierRange"
    ? (__mmSoldierRange = Math.max(100, Math.min(1000, __mmNumber)))
    : __mmKey === "combatRange"
      ? (__mmCombatRange = Math.max(100, Math.min(1000, __mmNumber)))
      : __mmKey === "gearHoldTicks"
        ? (__mmGearHoldTicks = Math.max(1, Math.min(8, Math.round(__mmNumber))))
        : __mmKey === "passiveSpikeEnemyRange"
          ? (__mmPassiveSpikeEnemyRange = Math.max(0, Math.min(1200, __mmNumber)))
          : __mmKey === "antiBoostRange"
            ? (__mmAntiBoostRange = Math.max(80, Math.min(500, __mmNumber)))
            : __mmKey === "reactionMs" &&
              ((__mmReactionMs = Math.max(10, Math.min(100, __mmNumber))),
              __mmLiveStateTimer &&
                (clearInterval(__mmLiveStateTimer),
                (__mmLiveStateTimer = 0),
                __mmStartLiveState())),
    __mmPublishHudState());
}
function __mmSetHudToggle(__mmKey, __mmValue) {
  const __mmEnabled = !!__mmValue;
  if (__mmKey === "autoHeal") return void __mmSetAutoHeal(__mmEnabled);
  if (__mmKey === "soldierAuto") return void __mmSetSoldierAuto(__mmEnabled);
  if (__mmKey === "movementGear") return void __mmSetMovementGear(__mmEnabled);
  if (__mmKey === "passiveSpikeAvoidance")
    ((__mmPassiveSpikeAvoidanceEnabled = __mmEnabled),
      __mmEnabled
        ? __mmStartPassiveSpikeAvoidance()
        : __mmStopPassiveSpikeAvoidance());
  else if (__mmKey === "trapEscape")
    ((__mmTrapEscapeEnabled = __mmEnabled),
      __mmEnabled ? __mmStartTrapEscape() : __mmStopTrapEscape());
  else if (__mmKey === "antiBoost")
    ((__mmAntiBoostEnabled = __mmEnabled),
      !__mmEnabled && __mmStopAntiBoostBlock("hud disabled"));
  else if (__mmKey === "antiBoostInsta")
    __mmAntiBoostInstaEnabled = __mmEnabled;
  else if (__mmKey === "threatTrap") __mmThreatTrapEnabled = __mmEnabled;
  else if (__mmKey === "autoCloseSpike")
    __mmAutoCloseSpikeEnabled = __mmEnabled;
  else if (__mmKey === "reloadSpike") __mmReloadSpikeEnabled = __mmEnabled;
  else if (__mmKey === "shieldDefense")
    ((__mmShieldDefenseEnabled = __mmEnabled),
      !__mmEnabled && __mmStopShieldDefense("hud disabled"));
  else if (__mmKey === "musketRecharge")
    ((__mmMusketRechargeEnabled = __mmEnabled),
      !__mmEnabled && __mmStopWeaponRecharge(!1));
  else if (__mmKey === "autoPurchase")
    ((__mmAutoPurchaseEnabled = __mmEnabled),
      __mmEnabled ? (__mmStartAutoPurchase(), __mmUpdateAutoPurchase()) : __mmStopAutoPurchase());
  else if (__mmKey === "matThief")
    ((__mmMatThiefEnabled = __mmEnabled),
      __mmEnabled ? (__mmStartMatThief(), __mmUpdateMatThief()) : __mmStopMatThief());
  else if (__mmKey === "mobSteal")
    ((__mmMobStealEnabled = __mmEnabled),
      __mmEnabled ? (__mmStartMobSteal(), __mmUpdateMobSteal()) : __mmStopMobSteal());
  else if (__mmKey === "spinningWindmills")
    ((__mmSpinningWindmillsEnabled = __mmEnabled),
      __mmEnabled
        ? (__mmStartSpinningWindmills(), __mmUpdateSpinningWindmills())
        : __mmStopSpinningWindmills());
  else if (__mmKey === "esp") __mmEspEnabled = __mmEnabled;
  else if (__mmKey === "espLines") __mmEspLinesEnabled = __mmEnabled;
  else if (__mmKey === "predictionGhost")
    __mmPredictionGhostEnabled = __mmEnabled;
  else if (__mmKey === "cooldownBars")
    __mmCooldownBarsEnabled = __mmEnabled;
  else if (__mmKey === "bullHelmet") {
    __mmBullHelmetEnabled = __mmEnabled;
    if (
      !__mmEnabled &&
      v &&
      (__mmPrimaryClickHat != null || __mmPrimaryClickTail != null)
    )
      __mmForceRestoreBullForPrimary();
  } else if (__mmKey === "tankRightClick")
    ((__mmTankRightClickEnabled = __mmEnabled),
      !__mmEnabled &&
        (__mmStopSecondary(), __mmForceRestoreRightClickHat()));
  else if (__mmKey === "allItemsUnlock")
    ((__mmAllItemsUnlockEnabled = __mmEnabled),
      __mmApplyAllItemsUnlock());
  else if (__mmKey === "instaKill") {
    ((__mmInstaUiEnabled = __mmEnabled),
      !__mmEnabled && __mmInsta.cancel("hud-disabled"));
  }
  else if (__mmKey === "autoInsta") {
    ((__mmAutoInstaEnabled = __mmEnabled),
      !__mmEnabled &&
        __mmInsta.automatic &&
        __mmInsta.cancel("auto-insta-disabled"));
  }
  else if (__mmKey === "autoSpikeInsta")
    ((__mmAutoSpikeInstaEnabled = __mmEnabled),
      !__mmEnabled && __mmStopSpikeTickStrike("hud disabled"));
  else if (__mmKey === "autoSpikeSpam") {
    __mmAutoSpikeSpamEnabled = __mmEnabled;
    if (!__mmEnabled) {
      ((__mmAutoSpikeSpamGhost = null),
        (__mmAutoSpikeSpamCandidateKey = null),
        (__mmAutoSpikeSpamCandidateSince = 0));
    }
  }
  else if (__mmKey === "antiInsta") {
    __mmAntiInstaEnabled = __mmEnabled;
    if (!__mmEnabled && __mmActionOwner === "antiInsta") {
      (__mmAntiInstaActionTimer && clearTimeout(__mmAntiInstaActionTimer),
        (__mmAntiInstaActionTimer = 0),
        __mmActionRelease("antiInsta", "hud disabled"));
    }
  }
  else if (__mmKey === "instaSync") {
    __mmInstaSyncEnabled = __mmEnabled;
    !__mmEnabled && __mmStopInstaSync();
  }
  else if (__mmKey === "boostBreak") {
    ((__mmBoostBreakEnabled = __mmEnabled),
      !__mmEnabled && __mmStopBoostBreak());
  } else if (__mmKey === "boostChat") {
    ((__mmBoostChatEnabled = __mmEnabled), !__mmEnabled && __mmStopBoostChat());
  } else if (__mmKey === "materialReply") {
    __mmMaterialReplyEnabled = __mmEnabled;
  } else if (__mmKey === "syncLeader") {
    __mmSetSyncLeader(__mmEnabled);
    return;
  } else if (__mmKey === "syncFollower") {
    __mmSetSyncFollower(__mmEnabled);
    return;
  } else if (__mmKey === "debugPanel")
    __mmDebugPanelEnabled = __mmEnabled;
  else if (__mmKey === "killMessageEnabled")
    __mmKillMessageEnabled = __mmEnabled;
  else return;
  __mmPublishHudState();
}
function __mmSetHudValue(__mmKey, __mmValue) {
  if (__mmKey === "killMessage")
    return (
      (__mmKillMessage = String(__mmValue || "").slice(0, 30)),
      void __mmPublishHudState()
    );
  __mmKey === "soldierRange" ||
  __mmKey === "combatRange" ||
  __mmKey === "gearHoldTicks" ||
  __mmKey === "passiveSpikeEnemyRange" ||
  __mmKey === "antiBoostRange" ||
  __mmKey === "reactionMs"
    ? __mmSetHudNumber(__mmKey, __mmValue)
    : __mmSetHudToggle(__mmKey, __mmValue);
}
function __mmApplyHudSettings(__mmSettings) {
  if (!__mmSettings || typeof __mmSettings !== "object") return;
  Object.prototype.hasOwnProperty.call(__mmSettings, "friendNames") &&
    __mmReplaceFriends(__mmSettings.friendNames);
  const __mmKeys = [
    "autoHeal",
    "soldierAuto",
    "movementGear",
    "passiveSpikeAvoidance",
    "trapEscape",
    "antiBoost",
    "antiBoostInsta",
    "threatTrap",
    "autoCloseSpike",
    "reloadSpike",
    "shieldDefense",
    "musketRecharge",
    "autoPurchase",
    "matThief",
    "mobSteal",
    "spinningWindmills",
    "esp",
    "espLines",
    "predictionGhost",
    "cooldownBars",
    "bullHelmet",
    "tankRightClick",
    "allItemsUnlock",
    "instaKill",
    "autoInsta",
    "autoSpikeInsta",
    "autoSpikeSpam",
    "antiInsta",
    "instaSync",
    "boostBreak",
    "boostChat",
    "materialReply",
    "syncLeader",
    "syncFollower",
    "debugPanel",
    "killMessageEnabled",
    "killMessage",
    "soldierRange",
    "combatRange",
    "gearHoldTicks",
    "passiveSpikeEnemyRange",
    "antiBoostRange",
    "reactionMs",
  ];
  for (let __mmIndex = 0; __mmIndex < __mmKeys.length; __mmIndex++) {
    const __mmKey = __mmKeys[__mmIndex];
    Object.prototype.hasOwnProperty.call(__mmSettings, __mmKey) &&
      __mmSetHudValue(__mmKey, __mmSettings[__mmKey]);
  }
  __mmPublishHudState();
}
function __mmHandleHudCommand(__mmEvent) {
  const __mmCommand = __mmEvent.detail || {};
  if (__mmCommand.type === "hydrate")
    return void __mmApplyHudSettings(__mmCommand.settings);
  if (__mmCommand.type === "set")
    return void __mmSetHudValue(__mmCommand.key, __mmCommand.value);
  if (__mmCommand.type === "friend-add")
    return void __mmAddFriend(__mmCommand.name, !0);
  if (__mmCommand.type === "friend-remove")
    return void __mmRemoveFriend(__mmCommand.name, !0);
  __mmPublishHudState();
}
window.addEventListener("MooMooOPHudCommand", __mmHandleHudCommand);
function __mmTankGearActive() {
  return !!(v && v.skinIndex === 40);
}
function __mmMovementGearActive() {
  return (
    __mmMovementGearPreviousHat != null || __mmMovementGearPreviousTail != null
  );
}
function __mmRememberNormalHat() {
  v && v.alive && v.skinIndex !== 40 && (__mmLastNormalHat = v.skinIndex);
}
function __mmEquipHatNow(__mmHat, __mmOverridePending) {
  if (
    !v ||
    !v.alive ||
    __mmHat == null ||
    (__mmHat !== 0 && !(v.skins && v.skins[__mmHat]))
  )
    return !1;
  const __mmHasConflictingPendingEquip = !!(
    __mmOverridePending &&
    __mmPendingHat != null &&
    __mmPendingHat !== __mmHat
  );
  if (v.skinIndex === __mmHat && !__mmHasConflictingPendingEquip) {
    __mmPendingHat === __mmHat &&
      ((__mmPendingHat = null), (__mmPendingHatAt = 0));
    return !0;
  }
  const __mmNow = Date.now();
  if (
    __mmPendingHat === __mmHat &&
    __mmNow - __mmPendingHatAt < __mmServerTickMs()
  )
    return !0;
  return (
    O.send("c", 0, __mmHat, !1),
    (__mmPendingHat = __mmHat),
    (__mmPendingHatAt = __mmNow),
    __mmHat !== 40 && (__mmLastNormalHat = __mmHat),
    !0
  );
}
function __mmEquipTailNow(__mmTail, __mmOverridePending) {
  if (
    !v ||
    !v.alive ||
    __mmTail == null ||
    (__mmTail !== 0 && !(v.tails && v.tails[__mmTail]))
  )
    return !1;
  const __mmHasConflictingPendingEquip = !!(
    __mmOverridePending &&
    __mmPendingTail != null &&
    __mmPendingTail !== __mmTail
  );
  if (v.tailIndex === __mmTail && !__mmHasConflictingPendingEquip) {
    __mmPendingTail === __mmTail &&
      ((__mmPendingTail = null), (__mmPendingTailAt = 0));
    return !0;
  }
  const __mmNow = Date.now();
  if (
    __mmPendingTail === __mmTail &&
    __mmNow - __mmPendingTailAt < __mmServerTickMs()
  )
    return !0;
  return (
    O.send("c", 0, __mmTail, !0),
    (__mmPendingTail = __mmTail),
    (__mmPendingTailAt = __mmNow),
    !0
  );
}
function __mmEquipGearPair(__mmHat, __mmTail, __mmOverridePending) {
  if (!v || !v.alive) return !1;
  const __mmHatValid = !!(
      __mmHat != null &&
      (__mmHat === 0 || (v.skins && v.skins[__mmHat]))
    ),
    __mmTailValid = !!(
      __mmTail != null &&
      (__mmTail === 0 || (v.tails && v.tails[__mmTail]))
    ),
    __mmNow = Date.now(),
    __mmTick = __mmServerTickMs(),
    // Combat/restore pairs must remain pairs even if one side is already the
    // visible value or has an identical request awaiting acknowledgement.
    __mmForcePair = !!(
      __mmOverridePending &&
      __mmHatValid &&
      __mmTailValid
    ),
    __mmHatConflict = !!(
      __mmOverridePending &&
      __mmPendingHat != null &&
      __mmPendingHat !== __mmHat
    ),
    __mmTailConflict = !!(
      __mmOverridePending &&
      __mmPendingTail != null &&
      __mmPendingTail !== __mmTail
    ),
    __mmSendHat = !!(
      __mmHatValid &&
      (__mmForcePair ||
        v.skinIndex !== __mmHat ||
        __mmHatConflict) &&
      (__mmForcePair ||
        __mmPendingHat !== __mmHat ||
        __mmNow - __mmPendingHatAt >= __mmTick)
    ),
    __mmSendTail = !!(
      __mmTailValid &&
      (__mmForcePair ||
        v.tailIndex !== __mmTail ||
        __mmTailConflict) &&
      (__mmForcePair ||
        __mmPendingTail !== __mmTail ||
        __mmNow - __mmPendingTailAt >= __mmTick)
    );
  // Decide both slots first, then emit both socket packets synchronously with
  // the same timestamp. No timer, microtask, acknowledgement, or helper call
  // is allowed between the paired packets.
  const __mmWasPairing = __mmSyncGearPairDispatch;
  __mmSyncGearPairDispatch = !0;
  try {
    (__mmSendHat &&
      (O.send("c", 0, __mmHat, !1),
      (__mmPendingHat = __mmHat),
      (__mmPendingHatAt = __mmNow),
      __mmHat !== 40 && (__mmLastNormalHat = __mmHat)),
      __mmSendTail &&
        (O.send("c", 0, __mmTail, !0),
        (__mmPendingTail = __mmTail),
        (__mmPendingTailAt = __mmNow)));
  } finally {
    __mmSyncGearPairDispatch = __mmWasPairing;
  }
  !__mmWasPairing &&
    (__mmHat != null || __mmTail != null) &&
    __mmSyncPublishGearPair(__mmHat, __mmTail);
  return __mmSendHat || __mmSendTail;
}
function __mmSetProximityTail(__mmTail) {
  if (!v || __mmTail == null) return;
  (__mmProximityTailPrevious == null &&
    (__mmProximityTailPrevious = v.tailIndex),
    __mmEquipTailNow(__mmTail));
}
function __mmRestoreProximityTail() {
  if (__mmProximityTailPrevious == null) return;
  if (!v || !v.alive) return void (__mmProximityTailPrevious = null);
  const __mmTail = __mmProximityTailPrevious;
  ((__mmProximityTailPrevious = null), __mmEquipTailNow(__mmTail));
}
function __mmClearIdleMonkeyTail() {
  if (
    !v ||
    !v.alive ||
    __mmPlayerMoving() ||
    __mmBoostBreakHeld ||
    v.tailIndex !== 11
  )
    return;
  const __mmTail = __mmMovementGearPreviousTail;
  __mmMovementGearPreviousTail = null;
  const __mmRestoreTail =
    __mmTail === 0 || (__mmTail != null && v.tails && v.tails[__mmTail])
      ? __mmTail
      : 0;
  __mmEquipTailNow(__mmRestoreTail);
}
function __mmHeldAttackWeapon() {
  return !v || !v.alive || !v.weapons
    ? null
    : __mmSecondaryHeld
      ? __mmRightClickWeapon()
      : __mmPrimaryHeld
        ? v.weapons[0]
        : null;
}
function __mmSendWeaponAttack(__mmState) {
  O.send("F", __mmState, null);
}
function __mmPulseHeldAttack() {
  const __mmWeapon = __mmHeldAttackWeapon();
  if (__mmWeapon == null) return;
  if (__mmSecondaryHeld) return void __mmPulseSecondaryWeapon();
  if (__mmPrimaryHeld && __mmBullPrimaryAvailable())
    return void __mmPulsePrimaryBullWeapon();
  (je(__mmWeapon, !0), __mmSendWeaponAttack(1));
}
function __mmStartHeldAttackPulse() {
  __mmPulseHeldAttack();
  if (__mmHeldAttackTimer) return;
  __mmHeldAttackTimer = setInterval(function () {
    __mmHeldAttackWeapon() != null
      ? __mmPulseHeldAttack()
      : __mmStopHeldAttackPulse();
  }, __mmServerTickMs());
}
function __mmStopHeldAttackPulse() {
  if (__mmPrimaryHeld || __mmSecondaryHeld) return;
  (__mmHeldAttackTimer &&
    (clearInterval(__mmHeldAttackTimer), (__mmHeldAttackTimer = 0)),
    v && v.alive && __mmSendWeaponAttack(0));
}
function __mmResumeHeldAttack() {
  if (
    __mmTrapAttackActive &&
    __mmTrapAttackHeld &&
    __mmTrapAttackHeldWeapon != null
  ) {
    const __mmAngle = Number.isFinite(__mmTrapAimAngle)
      ? __mmTrapAimAngle
      : Ci();
    (je(__mmTrapAttackHeldWeapon, !0),
      O.send("D", __mmAngle),
      O.send("F", 1, __mmAngle));
    return;
  }
  __mmPulseHeldAttack();
}
function __mmCanEat() {
  if (!v || !v.alive || v.items[0] == null) return !1;
  const __mmFood = b.list[v.items[0]];
  if (!__mmFood || !__mmFood.consume || !__mmFood.req) return !1;
  for (
    let __mmReqIndex = 0;
    __mmReqIndex < __mmFood.req.length;
    __mmReqIndex += 2
  )
    if ((v[__mmFood.req[__mmReqIndex]] || 0) < __mmFood.req[__mmReqIndex + 1])
      return !1;
  return !0;
}
function __mmFoodCharges() {
  if (!__mmCanEat()) return 0;
  const __mmFood = b.list[v.items[0]];
  let __mmCharges = Infinity;
  for (
    let __mmReqIndex = 0;
    __mmReqIndex < __mmFood.req.length;
    __mmReqIndex += 2
  )
    __mmCharges = Math.min(
      __mmCharges,
      Math.floor(
        (v[__mmFood.req[__mmReqIndex]] || 0) / __mmFood.req[__mmReqIndex + 1],
      ),
    );
  return Number.isFinite(__mmCharges) ? Math.max(0, __mmCharges) : 0;
}
function __mmUseFood() {
  if (!__mmCanEat()) return;
  const __mmTool = __mmSelectedTool();
  (je(v.items[0]),
    O.send("F", 1, Ci()),
    O.send("F", 0, Ci()),
    __mmRestoreTool(__mmTool),
    __mmResumeHeldAttack());
}
function __mmUseFoodBurst(__mmCount) {
  const __mmBites = Math.min(Math.max(0, __mmCount | 0), __mmFoodCharges());
  if (!__mmBites) return;
  const __mmFood = v.items[0],
    __mmAngle = Ci(),
    __mmTool = __mmSelectedTool();
  for (let __mmBite = 0; __mmBite < __mmBites; __mmBite++)
    (je(__mmFood), O.send("F", 1, __mmAngle), O.send("F", 0, __mmAngle));
  (__mmRestoreTool(__mmTool), __mmResumeHeldAttack());
}
function __mmAtFullHealth() {
  return v && v.alive && v.health >= v.maxHealth;
}
function __mmSelectedWeapon() {
  return !v || !v.alive
    ? null
    : v.weapons.includes(__mmLastWeapon)
      ? __mmLastWeapon
      : v.weapons.includes(v.weaponIndex)
        ? v.weaponIndex
        : v.weapons[0];
}
function __mmHoldingMcGrabby() {
  return !!(
    v &&
    v.alive &&
    Number(v.buildIndex) < 0 &&
    Number(__mmSelectedWeapon()) === __mmMcGrabby
  );
}
function __mmRestoreWeapon(__mmWeapon) {
  v && v.alive && v.weapons.includes(__mmWeapon) && je(__mmWeapon, !0);
}
function __mmSelectedTool() {
  if (!v || !v.alive) return null;
  const __mmBuild = Number(v.buildIndex);
  if (
    Number.isInteger(__mmBuild) &&
    __mmBuild >= 0 &&
    v.items &&
    v.items.includes(__mmBuild)
  )
    return { item: __mmBuild, weapon: !1 };
  const __mmWeapon = __mmSelectedWeapon();
  return __mmWeapon == null ? null : { item: __mmWeapon, weapon: !0 };
}
function __mmRestoreTool(__mmTool) {
  if (!v || !v.alive || !__mmTool) return;
  __mmTool.weapon
    ? __mmRestoreWeapon(__mmTool.item)
    : v.items && v.items.includes(__mmTool.item) && je(__mmTool.item);
}
const __mmCleanupRadius = 1000,
  __mmCleanupInputKeys = Object.freeze({
    87: !0,
    65: !0,
    83: !0,
    68: !0,
    70: !0,
    86: !0,
    82: !0,
    72: !0,
    90: !0,
  });
function __mmCleanupObjectScale(__mmObject) {
  if (!__mmObject) return 0;
  if (typeof __mmObject.getScale === "function") {
    const __mmScale = Number(__mmObject.getScale(0.6, !!__mmObject.isItem));
    if (Number.isFinite(__mmScale) && __mmScale > 0) return __mmScale;
  }
  return Math.max(
    1,
    Number(__mmObject.blocker) ||
      Number(__mmObject.scale) ||
      Number(b && b.list && b.list[__mmObject.id] && b.list[__mmObject.id].scale) ||
      35,
  );
}
function __mmCleanupIsSpike(__mmObject) {
  const __mmItem = __mmObject && b && b.list && b.list[__mmObject.id],
    __mmName = String((__mmItem && __mmItem.name) || "").toLowerCase();
  return __mmName.includes("spikes");
}
function __mmCleanupStructureAllowed(__mmObject) {
  const __mmData = __mmObject && b && b.list && b.list[__mmObject.id];
  if (
    !__mmCleanupActive ||
    !__mmObject ||
    !__mmObject.active ||
    !__mmObject.isItem ||
    !__mmData ||
    !__mmData.group ||
    !__mmData.group.place
  )
    return !1;
  const __mmState = __mmBreakableState(__mmObject),
    __mmLiveHealth = Number(__mmObject.health),
    __mmHealth = __mmState
      ? Number(__mmState.health)
      : Number.isFinite(__mmLiveHealth)
        ? __mmLiveHealth
        : Number(__mmData.health);
  if (!Number.isFinite(__mmHealth) || __mmHealth <= 0.001) return !1;
  const __mmDx = Number(__mmObject.x) - __mmCleanupOriginX,
    __mmDy = Number(__mmObject.y) - __mmCleanupOriginY;
  return (
    Number.isFinite(__mmDx) &&
    Number.isFinite(__mmDy) &&
    __mmDx * __mmDx + __mmDy * __mmDy <=
      __mmCleanupRadius * __mmCleanupRadius
  );
}
function __mmCleanupSafeDistance(__mmObject) {
  return (
    (Number(v && v.scale) || 35) +
    __mmCleanupObjectScale(__mmObject) +
    (__mmCleanupIsSpike(__mmObject) ? 18 : 8)
  );
}
function __mmCleanupWeaponPlan(__mmObject) {
  if (!v || !v.alive || !Array.isArray(v.weapons)) return null;
  const __mmSafe = __mmCleanupSafeDistance(__mmObject),
    __mmScale = __mmCleanupObjectScale(__mmObject);
  let __mmBest = null;
  for (let __mmIndex = 0; __mmIndex < v.weapons.length; __mmIndex++) {
    const __mmWeapon = v.weapons[__mmIndex],
      __mmData = b && b.weapons && b.weapons[__mmWeapon];
    if (!__mmData || __mmData.projectile != null) continue;
    const __mmDamage = __mmWeaponStructureDamage(v, __mmWeapon, __mmObject),
      __mmRange = Number(__mmData.range) || 0,
      __mmReach = __mmRange + __mmScale - 5,
      __mmSpeed = Math.max(50, Number(__mmData.speed) || 400);
    if (__mmDamage <= 0 || __mmReach < __mmSafe + 2) continue;
    const __mmScore = __mmDamage / __mmSpeed + __mmRange / 1e6;
    if (
      !__mmBest ||
      __mmScore > __mmBest.score ||
      (__mmScore === __mmBest.score && __mmReach > __mmBest.reach)
    )
      __mmBest = {
        weapon: __mmWeapon,
        damage: __mmDamage,
        speed: __mmSpeed,
        reach: __mmReach,
        safe: __mmSafe,
        score: __mmScore,
      };
  }
  return __mmBest;
}
function __mmCleanupHasRemaining() {
  if (!Array.isArray(ge)) return !1;
  for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++)
    if (__mmCleanupStructureAllowed(ge[__mmIndex])) return !0;
  return !1;
}
function __mmCleanupNearestTarget(__mmNow) {
  if (!v || !v.alive || !Array.isArray(ge)) return null;
  let __mmBest = null,
    __mmBestDistance = Infinity;
  for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
    const __mmObject = ge[__mmIndex];
    if (!__mmCleanupStructureAllowed(__mmObject)) continue;
    const __mmReservedUntil = Number(__mmCleanupReservations.get(__mmObject));
    if (Number.isFinite(__mmReservedUntil) && __mmReservedUntil > __mmNow)
      continue;
    const __mmPlan = __mmCleanupWeaponPlan(__mmObject);
    if (!__mmPlan) {
      __mmCleanupReservations.set(__mmObject, __mmNow + 750);
      continue;
    }
    const __mmDistance = Math.hypot(
      Number(__mmObject.x) - Number(v.x),
      Number(__mmObject.y) - Number(v.y),
    );
    if (Number.isFinite(__mmDistance) && __mmDistance < __mmBestDistance)
      ((__mmBestDistance = __mmDistance),
        (__mmBest = { object: __mmObject, plan: __mmPlan }));
  }
  return __mmBest;
}
function __mmCleanupSetMovement(__mmAngle) {
  if (!v || !v.alive) {
    ((__mmCleanupMoveAngle = null), (Kt = null));
    return;
  }
  if (!Number.isFinite(__mmAngle)) {
    if (__mmCleanupMoveAngle == null) return;
    ((__mmCleanupMoveAngle = null), (Kt = null), O.send("9", null));
    return;
  }
  const __mmFixed =
    typeof M.fixTo === "function" ? M.fixTo(__mmAngle, 2) : __mmAngle,
    __mmDifference =
      __mmCleanupMoveAngle == null
        ? Infinity
        : Math.abs(
            Math.atan2(
              Math.sin(__mmFixed - __mmCleanupMoveAngle),
              Math.cos(__mmFixed - __mmCleanupMoveAngle),
            ),
          );
  if (__mmDifference < 0.04) return;
  ((__mmCleanupMoveAngle = __mmFixed),
    (Kt = __mmFixed),
    O.send("9", __mmFixed));
}
function __mmCleanupReleaseAttack() {
  if (!__mmCleanupAttackHeld) return;
  (O.send(
    "F",
    0,
    Number.isFinite(__mmCleanupAimAngle) ? __mmCleanupAimAngle : null,
  ),
    (__mmCleanupAttackHeld = !1),
    (__mmCleanupAimAngle = null),
    (__mmCleanupWeapon = null));
}
function __mmCleanupSteeringAngle(__mmDesired, __mmTarget) {
  if (!v || !v.alive || !Array.isArray(ge)) return __mmDesired;
  const __mmOffsets = [0, 0.24, -0.24, 0.48, -0.48, 0.78, -0.78, 1.08, -1.08, 1.57, -1.57],
    __mmPlayerScale = Number(v.scale) || 35,
    __mmStep = 90;
  let __mmBestAngle = __mmDesired,
    __mmBestScore = Infinity;
  for (let __mmOffsetIndex = 0; __mmOffsetIndex < __mmOffsets.length; __mmOffsetIndex++) {
    const __mmAngle = __mmDesired + __mmOffsets[__mmOffsetIndex],
      __mmEndX = Number(v.x) + Math.cos(__mmAngle) * __mmStep,
      __mmEndY = Number(v.y) + Math.sin(__mmAngle) * __mmStep;
    let __mmScore = Math.abs(__mmOffsets[__mmOffsetIndex]) * 15;
    for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
      const __mmObject = ge[__mmIndex];
      if (
        !__mmObject ||
        __mmObject === __mmTarget ||
        !__mmObject.active
      )
        continue;
      const __mmClearance =
          __mmPlayerScale +
          __mmCleanupObjectScale(__mmObject) +
          (__mmCleanupIsSpike(__mmObject) ? 20 : 6),
        __mmDistanceSquared = __mmSegmentDistanceSquared(
          Number(v.x),
          Number(v.y),
          __mmEndX,
          __mmEndY,
          Number(__mmObject.x),
          Number(__mmObject.y),
        );
      if (__mmDistanceSquared < __mmClearance * __mmClearance) {
        const __mmDistance = Math.sqrt(Math.max(0, __mmDistanceSquared));
        __mmScore +=
          1e4 + (__mmClearance - __mmDistance) *
          (__mmCleanupIsSpike(__mmObject) ? 100 : 25);
      }
    }
    if (__mmScore < __mmBestScore)
      ((__mmBestScore = __mmScore), (__mmBestAngle = __mmAngle));
  }
  return __mmBestAngle;
}
function __mmCleanupAttackTarget(__mmEntry, __mmAngle, __mmNow) {
  const __mmObject = __mmEntry.object,
    __mmPlan = __mmEntry.plan,
    __mmState = __mmBreakableState(__mmObject),
    __mmData = b && b.list && b.list[__mmObject.id],
    __mmLiveHealth = Number(__mmObject.health),
    __mmHealth = __mmState
      ? Number(__mmState.health)
      : Number.isFinite(__mmLiveHealth)
        ? __mmLiveHealth
        : Number(__mmData && __mmData.health) || 1;
  __mmCleanupSetMovement(null);
  __mmCleanupAimAngle = __mmAngle;
  if (__mmCleanupWeapon !== __mmPlan.weapon) {
    (__mmCleanupReleaseAttack(),
      (__mmCleanupWeapon = __mmPlan.weapon),
      je(__mmPlan.weapon, !0));
  }
  if (!__mmCleanupAttackHeld)
    (O.send("D", __mmAngle),
      O.send("F", 1, __mmAngle),
      (__mmCleanupAttackHeld = !0));
  else O.send("D", __mmAngle);
  if (
    __mmCleanupTargetHealth == null ||
    __mmHealth < __mmCleanupTargetHealth - 0.001
  )
    ((__mmCleanupTargetHealth = __mmHealth),
      (__mmCleanupProgressAt = __mmNow));
  const __mmStallMs = Math.max(
    2200,
    __mmPlan.speed *
      (Math.max(1, Math.ceil(__mmHealth / Math.max(1, __mmPlan.damage))) + 2) +
      __mmServerTickMs() * 2,
  );
  if (__mmNow - __mmCleanupProgressAt > __mmStallMs) {
    (__mmCleanupReleaseAttack(),
      __mmCleanupReservations.set(__mmObject, __mmNow + 900),
      (__mmCleanupTarget = null),
      (__mmCleanupTargetHealth = null));
  }
}
function __mmUpdateCleanup() {
  if (!__mmCleanupActive) return;
  if (document.hidden || !v || !v.alive)
    return void __mmStopCleanup("runtime unavailable", !1);
  if (__mmActionOwner !== "cleanup")
    return void __mmStopCleanup("action ownership lost", !1);
  const __mmNow = Date.now();
  let __mmEntry = __mmCleanupTarget;
  if (!__mmEntry || !__mmCleanupStructureAllowed(__mmEntry.object)) {
    (__mmCleanupReleaseAttack(),
      (__mmCleanupTarget = null),
      (__mmCleanupTargetHealth = null),
      (__mmEntry = __mmCleanupNearestTarget(__mmNow)));
    if (__mmEntry) {
      ((__mmCleanupTarget = __mmEntry),
        (__mmCleanupTargetHealth = null),
        (__mmCleanupProgressAt = __mmNow),
        (__mmCleanupEmptySince = 0));
    }
  }
  if (!__mmEntry) {
    (__mmCleanupSetMovement(null), __mmCleanupReleaseAttack());
    if (__mmCleanupHasRemaining()) {
      __mmCleanupEmptySince = 0;
      return;
    }
    __mmCleanupEmptySince || (__mmCleanupEmptySince = __mmNow);
    if (__mmNow - __mmCleanupEmptySince >= Math.max(650, Number(y && y.chatCooldown) + 100 || 650))
      __mmStopCleanup("radius complete", !0);
    return;
  }
  const __mmObject = __mmEntry.object,
    __mmDx = Number(__mmObject.x) - Number(v.x),
    __mmDy = Number(__mmObject.y) - Number(v.y),
    __mmDistance = Math.hypot(__mmDx, __mmDy),
    __mmAngle = Math.atan2(__mmDy, __mmDx),
    __mmSafe = __mmEntry.plan.safe,
    __mmReach = __mmEntry.plan.reach,
    __mmStopDistance = Math.max(
      __mmSafe + 2,
      Math.min(__mmReach - 4, __mmSafe + 14),
    );
  if (!Number.isFinite(__mmDistance)) {
    __mmCleanupTarget = null;
    return;
  }
  if (__mmDistance < __mmSafe) {
    (__mmCleanupReleaseAttack(),
      __mmCleanupSetMovement(
        __mmCleanupSteeringAngle(__mmAngle + Math.PI, __mmObject),
      ));
    return;
  }
  if (__mmDistance > __mmStopDistance) {
    (__mmCleanupReleaseAttack(),
      __mmCleanupSetMovement(
        __mmCleanupSteeringAngle(__mmAngle, __mmObject),
      ));
    return;
  }
  if (__mmDistance <= __mmReach)
    return void __mmCleanupAttackTarget(__mmEntry, __mmAngle, __mmNow);
  __mmCleanupSetMovement(__mmCleanupSteeringAngle(__mmAngle, __mmObject));
}
function __mmCleanupProgressChat() {
  if (!__mmCleanupActive) return;
  const __mmLines = ["Cleaning.", "Cleaning..", "Cleaning..."];
  (__mmSendChat(__mmLines[__mmCleanupChatStep % __mmLines.length]),
    (__mmCleanupChatStep += 1));
}
function __mmStartCleanup() {
  if (__mmCleanupActive || document.hidden || !v || !v.alive) return !1;
  (__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0),
    __mmActionOwner === "matThief" && __mmFinishMatThief("cleanup started"),
    __mmActionOwner === "mobSteal" && __mmFinishMobSteal("cleanup started"));
  if (!__mmActionClaim("cleanup", "clearing 1000px radius")) return !1;
  (__mmRestoreMovementGear(),
    (__mmCleanupActive = !0),
    (__mmCleanupOriginX = Number(v.x) || 0),
    (__mmCleanupOriginY = Number(v.y) || 0),
    (__mmCleanupTarget = null),
    (__mmCleanupSavedTool = __mmSelectedTool()),
    (__mmCleanupWeapon = null),
    (__mmCleanupAttackHeld = !1),
    (__mmCleanupAimAngle = null),
    (__mmCleanupMoveAngle = null),
    (__mmCleanupTargetHealth = null),
    (__mmCleanupProgressAt = Date.now()),
    (__mmCleanupEmptySince = 0),
    (__mmCleanupChatStep = 0),
    __mmCleanupProgressChat(),
    (__mmCleanupProgressTimer = setInterval(
      __mmCleanupProgressChat,
      Math.max(750, (Number(y && y.chatCooldown) || 500) + 150),
    )),
    (__mmCleanupTimer = setInterval(__mmUpdateCleanup, __mmFastCheckMs())),
    __mmUpdateCleanup());
  return !0;
}
function __mmStopCleanup(__mmReason, __mmCompleted) {
  if (!__mmCleanupActive && __mmActionOwner !== "cleanup") return;
  const __mmTool = __mmCleanupSavedTool,
    __mmCanRestore = __mmActionMayRestore("cleanup");
  ((__mmCleanupActive = !1),
    __mmCleanupTimer && clearInterval(__mmCleanupTimer),
    (__mmCleanupTimer = 0),
    __mmCleanupProgressTimer && clearInterval(__mmCleanupProgressTimer),
    (__mmCleanupProgressTimer = 0),
    __mmCleanupSetMovement(null),
    __mmCleanupReleaseAttack(),
    (__mmCleanupTarget = null),
    (__mmCleanupSavedTool = null),
    (__mmCleanupWeapon = null),
    (__mmCleanupAimAngle = null),
    (__mmCleanupTargetHealth = null),
    (__mmCleanupEmptySince = 0),
    __mmCanRestore && __mmRestoreTool(__mmTool),
    __mmActionRelease("cleanup", __mmReason || "stopped"),
    __mmScheduleMouseAimReturn(),
    __mmCompleted && __mmSendChat("Nice and tidy!"));
}
function __mmToggleCleanup() {
  return __mmCleanupActive
    ? (__mmStopCleanup("C toggled off", !1), !1)
    : __mmStartCleanup();
}
function __mmCleanupInputKey(__mmKey) {
  __mmCleanupActive &&
    __mmCleanupInputKeys[Number(__mmKey)] &&
    __mmStopCleanup("manual key", !1);
}
document.addEventListener(
  "mousedown",
  function (__mmEvent) {
    __mmCleanupActive &&
      __mmEvent.isTrusted &&
      __mmStopCleanup("manual click", !1);
  },
  !0,
);
function __mmWeaponIsReloading(__mmWeapon) {
  if (
    !v ||
    !v.alive ||
    !v.weapons ||
    __mmWeapon == null ||
    !v.weapons.includes(__mmWeapon)
  )
    return !1;
  const __mmReload = v.reloads && Number(v.reloads[__mmWeapon]);
  return Number.isFinite(__mmReload) && __mmReload > 0;
}
function __mmMusketIsReloading() {
  return __mmWeaponIsReloading(__mmMusket);
}
function __mmTurretGearIsReloading() {
  return !!(
    v &&
    v.alive &&
    v.skinIndex === __mmTurretGear &&
    Date.now() < __mmTurretReloadUntil
  );
}
function __mmTrackTurretGearReload(__mmPlayerSid) {
  if (
    !v ||
    !v.alive ||
    __mmPlayerSid !== v.sid ||
    v.skinIndex !== __mmTurretGear
  )
    return;
  // Turret Gear fires once every 2.5 seconds. The client does not expose a
  // reload entry for hats, so keep a local cooldown from its attack event.
  __mmTurretReloadUntil = Math.max(__mmTurretReloadUntil, Date.now() + 2500);
}
function __mmWeaponRechargeOverridden() {
  return (
    !v ||
    !v.alive ||
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmInsta.attackHeld ||
    __mmTrapAttackActive ||
    __mmBoostBreakHeld ||
    __mmBuildSpamTimer ||
    __mmFoodSpamTimer ||
    __mmAutoHealWasHealing ||
    __mmShieldDefenseTimer ||
    !__mmActionAvailable("weaponRecharge")
  );
}
function __mmNextWeaponToRecharge() {
  if (!v || !v.alive || !v.weapons) return null;
  const __mmSeen = new Set();
  // Inventory order is main first, then secondary/any additional weapons.
  // Checking every slot makes the queue survive weapon upgrades and swaps.
  for (let __mmIndex = 0; __mmIndex < v.weapons.length; __mmIndex++) {
    const __mmWeapon = v.weapons[__mmIndex];
    if (__mmWeapon == null || __mmSeen.has(__mmWeapon)) continue;
    __mmSeen.add(__mmWeapon);
    if (__mmWeaponIsReloading(__mmWeapon)) return __mmWeapon;
  }
  return null;
}
function __mmWeaponRechargeSelected(__mmWeapon) {
  return !!(
    v &&
    v.alive &&
    Number(v.buildIndex) < 0 &&
    Number(v.weaponIndex) === Number(__mmWeapon)
  );
}
function __mmWeaponRechargeCurrentTool() {
  if (!v || !v.alive) return null;
  const __mmBuild = Number(v.buildIndex);
  if (
    Number.isInteger(__mmBuild) &&
    __mmBuild >= 0 &&
    v.items &&
    v.items.includes(__mmBuild)
  )
    return { item: __mmBuild, weapon: !1 };
  const __mmWeapon = Number(v.weaponIndex);
  return v.weapons && v.weapons.includes(__mmWeapon)
    ? { item: __mmWeapon, weapon: !0 }
    : __mmSelectedTool();
}
function __mmSelectWeaponForRecharge(__mmWeapon) {
  if (__mmWeaponRechargeSelected(__mmWeapon)) return !0;
  const __mmNow = Date.now();
  if (__mmNow - __mmWeaponRechargeSelectAt >= 25) {
    ((__mmWeaponRechargeSelectAt = __mmNow), je(__mmWeapon, !0));
  }
  return __mmWeaponRechargeSelected(__mmWeapon);
}
function __mmPauseWeaponRecharge(__mmRestore) {
  const __mmActive = __mmWeaponRechargeActiveWeapon,
    __mmPrevious = __mmWeaponRechargePreviousTool;
  (__mmRestore &&
    __mmActionMayRestore("weaponRecharge") &&
    __mmActive != null &&
    __mmPrevious != null &&
    __mmWeaponRechargeSelected(__mmActive) &&
    __mmRestoreTool(__mmPrevious),
    (__mmWeaponRechargeActiveWeapon = null),
    (__mmWeaponRechargeSelectAt = 0),
    __mmActionRelease("weaponRecharge", "reload paused"));
}
function __mmStopWeaponRecharge(__mmRestore) {
  const __mmPrevious = __mmWeaponRechargePreviousTool;
  ((__mmWeaponRechargeActiveWeapon = null),
    (__mmWeaponRechargePreviousTool = null),
    (__mmWeaponRechargeSelectAt = 0),
    __mmRestore &&
      __mmPrevious != null &&
      __mmActionMayRestore("weaponRecharge") &&
      __mmRestoreTool(__mmPrevious),
    __mmActionRelease("weaponRecharge", "reload queue complete"));
}
function __mmUpdateWeaponRecharge() {
  if (
    !__mmMusketRechargeEnabled ||
    __mmSyncFollowerEnabled ||
    !v ||
    !v.alive ||
    !v.weapons
  )
    return void __mmStopWeaponRecharge(!1);
  const __mmTarget = __mmNextWeaponToRecharge(),
    __mmActive = __mmWeaponRechargeActiveWeapon;
  // Manual clicks and higher-priority actions pause selection but retain both
  // the original tool and the server-reported cooldown queue. If a reload
  // finishes during the override, restoration waits until input is released.
  if (__mmWeaponRechargeOverridden()) {
    __mmActive != null && __mmPauseWeaponRecharge(!1);
    return;
  }
  if (__mmTarget == null) return void __mmStopWeaponRecharge(!0);
  if (__mmActive === __mmTarget) {
    __mmSelectWeaponForRecharge(__mmTarget);
    return;
  }
  // A newly cooling main preempts the secondary. A completed main advances to
  // the secondary immediately in this same scan without clearing queue state.
  if (__mmActive != null) {
    ((__mmWeaponRechargeActiveWeapon = __mmTarget),
      (__mmWeaponRechargeSelectAt = 0),
      __mmSelectWeaponForRecharge(__mmTarget));
    return;
  }
  if (!__mmActionClaim("weaponRecharge", "idle reload")) return;
  ((__mmWeaponRechargeActiveWeapon = __mmTarget),
    __mmWeaponRechargePreviousTool == null &&
      (__mmWeaponRechargePreviousTool = __mmWeaponRechargeCurrentTool()),
    (__mmWeaponRechargeSelectAt = 0),
    __mmSelectWeaponForRecharge(__mmTarget));
}
function __mmStartWeaponRecharge() {
  __mmWeaponRechargeTimer ||
    (__mmWeaponRechargeTimer = setInterval(__mmUpdateWeaponRecharge, 5));
}
function __mmRestoreAutoHealWeapon() {
  // __mmUseFood restores the selected weapon after each safe food use. Keep
  // this cleanup hook for the HUD toggle and for older event paths.
  __mmAutoHealWeapon = null;
}
function __mmAutoHealFoodValue() {
  if (!v || v.items[0] == null) return 20;
  const __mmFood = b.list[v.items[0]];
  const __mmDescription = String((__mmFood && __mmFood.desc) || "");
  const __mmMatch = __mmDescription.match(/restores\\s+(\\d+)\\s+health/i);
  return __mmMatch ? Math.max(1, Number(__mmMatch[1])) : 20;
}
function __mmObserveAutoHealHealth(__mmHealth) {
  const __mmCurrentHealth = Number(__mmHealth);
  if (!Number.isFinite(__mmCurrentHealth)) return !1;
  const __mmNow = Date.now(),
    __mmHadHealth = __mmAutoHealLastObservedHealth != null,
    __mmTookDamage =
      __mmHadHealth &&
      __mmCurrentHealth < __mmAutoHealLastObservedHealth,
    __mmHealed =
      __mmHadHealth &&
      __mmCurrentHealth > __mmAutoHealLastObservedHealth;
  if (__mmTookDamage)
    ((__mmAutoHealPending = !0),
      (__mmAutoHealBitesRemaining = 0),
      (__mmAutoHealNextBiteAt = 0),
      (__mmAutoHealLastDamageAt = __mmNow));
  // Track manual healing too. Autoheal predicts its own result at send time
  // and clears LastDamageAt there, so its later health packet is not counted
  // twice. This mirrors the server's <=120ms increment / late-heal -2 rule.
  if (__mmHealed && __mmAutoHealLastDamageAt) {
    const __mmElapsed = __mmNow - __mmAutoHealLastDamageAt;
    ((__mmAutoHealShameCount =
      __mmElapsed <= 120
        ? Math.min(8, __mmAutoHealShameCount + 1)
        : Math.max(0, __mmAutoHealShameCount - 2)),
      (__mmAutoHealLastDamageAt = 0));
  }
  // Queue one catch-up heal if the script begins while already injured. Later
  // heals are queued only by actual damage packets, so the 10ms backup loop
  // cannot resend the same burst while the server is processing it.
  if (
    !__mmTookDamage &&
    __mmAutoHealLastObservedHealth == null &&
    v &&
    v.alive &&
    __mmCurrentHealth < v.maxHealth
  )
    ((__mmAutoHealPending = !0),
      (__mmAutoHealBitesRemaining = 0),
      (__mmAutoHealNextBiteAt = 0));
  __mmAutoHealLastObservedHealth = __mmCurrentHealth;
  return __mmTookDamage;
}
function __mmAutoHealRecordFoodAttempt(__mmNow) {
  if (!__mmAutoHealLastDamageAt) return;
  const __mmElapsed = __mmNow - __mmAutoHealLastDamageAt;
  ((__mmAutoHealShameCount =
    __mmElapsed <= 120
      ? Math.min(8, __mmAutoHealShameCount + 1)
      : Math.max(0, __mmAutoHealShameCount - 2)),
    // The server consumes the saved hit timestamp on this food attempt. Clear
    // ours immediately as well; no acknowledgement retry is involved.
    (__mmAutoHealLastDamageAt = 0));
}
function __mmAutoHealSafeAt(__mmEmergency, __mmFoodValue) {
  if (!__mmAutoHealLastDamageAt || __mmAutoHealShameCount < 5)
    return 0;
  const __mmLowHealth =
    v.health <= Math.max(35, Number(__mmFoodValue) || 20);
  // Survival wins over Shame prevention. At non-critical health, 135ms from
  // the received damage packet is deliberately beyond the server's 120ms
  // comparison and turns this heal into a two-point counter reduction.
  return __mmEmergency || __mmLowHealth
    ? 0
    : __mmAutoHealLastDamageAt + 135;
}
function __mmResetAutoHeal() {
  ((__mmAutoHealWasHealing = !1),
    (__mmAutoHealPending = !1),
    (__mmAutoHealBitesRemaining = 0),
    (__mmAutoHealNextBiteAt = 0),
    (__mmAutoHealLastObservedHealth = v && v.alive ? Number(v.health) : null),
    __mmRestoreAutoHealWeapon());
}
function __mmAutoHeal(__mmEmergency) {
  if (!__mmAutoHealEnabled || !v || !v.alive)
    return void __mmResetAutoHeal();
  __mmObserveAutoHealHealth(v.health);
  // Shame! (hat 45) means the server is rejecting food for its 30-second
  // penalty. Do not burn resources or flood selection/attack packets during it.
  if (Number(v.skinIndex) === 45) {
    ((__mmAutoHealShameCount = 8),
      (__mmAutoHealPending = !1),
      (__mmAutoHealBitesRemaining = 0),
      (__mmAutoHealNextBiteAt = 0));
    return;
  }
  if (v.health >= v.maxHealth || !__mmCanEat()) return void __mmResetAutoHeal();
  if (__mmAutoHealPending) {
    // Calculate the whole refill from the hit packet, then keep sending it on
    // the server tick. This is optimistic (it never waits for a heal reply),
    // but avoids the current server dropping a pile of same-frame F packets.
    const __mmMissingHealth = Math.max(0, v.maxHealth - v.health),
      __mmFoodValue = __mmAutoHealFoodValue(),
      __mmNow = Date.now(),
      __mmSafeAt = __mmAutoHealSafeAt(__mmEmergency, __mmFoodValue);
    ((__mmAutoHealBitesRemaining = Math.min(
      Math.ceil(__mmMissingHealth / __mmFoodValue),
      __mmFoodCharges(),
    )),
      (__mmAutoHealPending = !1),
      (__mmAutoHealNextBiteAt = Math.max(__mmNow, __mmSafeAt || 0)));
  }
  if (!__mmAutoHealBitesRemaining || Date.now() < __mmAutoHealNextBiteAt)
    return;
  // A held mouse attack remains the action owner while food is pulsed between
  // swings. __mmUseFood restores the selected tool and resumes the live held
  // attack immediately, so healing does not require releasing either button.
  const __mmHealingDuringHeldAttack = !!(
      __mmActionOwner === "manualAttack" &&
      (__mmPrimaryHeld || __mmSecondaryHeld)
    ),
    __mmOwnsAction = __mmHealingDuringHeldAttack
      ? !1
      : __mmActionClaim("autoHeal", "food recovery");
  if (
    !__mmOwnsAction &&
    !__mmHealingDuringHeldAttack &&
    !(__mmEmergency && __mmActionOwner === "trapEscape")
  )
    return;
  const __mmFoodSentAt = Date.now();
  ((__mmAutoHealWasHealing = !0),
    __mmAutoHealRecordFoodAttempt(__mmFoodSentAt),
    __mmUseFood(),
    (__mmAutoHealWasHealing = !1),
    (__mmAutoHealBitesRemaining -= 1),
    (__mmAutoHealNextBiteAt =
      Date.now() + Math.max(1, __mmServerTickMs())),
    __mmOwnsAction && __mmActionRelease("autoHeal", "food sent"));
}
function __mmToggleAutoHeal() {
  __mmSetAutoHeal(!__mmAutoHealEnabled);
}
function __mmTemporaryHatOverlay() {
  return (
    !v ||
    !v.alive ||
    __mmSyncFollowerEnabled ||
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmTrapAttackActive ||
    __mmBoostBreakHeld ||
    __mmTankGearActive() ||
    __mmPrimaryClickHat != null ||
    __mmRightClickHat != null ||
    __mmTrapHat != null ||
    (__mmSoldierPreviousHat != null &&
      !(__mmShiftSpeedActive && __mmShiftMode === 1))
  );
}
function __mmInSnowBiome() {
  return !!(
    v &&
    Number.isFinite(Number(v.y)) &&
    y &&
    Number.isFinite(Number(y.snowBiomeTop)) &&
    v.y <= y.snowBiomeTop
  );
}
function __mmInWater() {
  if (
    !v ||
    !y ||
    !Number.isFinite(Number(v.y)) ||
    !Number.isFinite(Number(y.mapScale)) ||
    !Number.isFinite(Number(y.riverWidth))
  )
    return !1;
  const __mmRiverMiddle = y.mapScale / 2,
    __mmRiverHalf = y.riverWidth / 2;
  return (
    v.y >= __mmRiverMiddle - __mmRiverHalf &&
    v.y <= __mmRiverMiddle + __mmRiverHalf
  );
}
function __mmBuyFlipperHat() {
  if (
    !__mmInWater() ||
    !v ||
    !v.alive ||
    (v.skins && v.skins[__mmFlipperHat]) ||
    (v.points || 0) < __mmFlipperHatPrice ||
    Date.now() - __mmFlipperPurchaseAt < 500
  )
    return !1;
  return ((__mmFlipperPurchaseAt = Date.now()), Xn(__mmFlipperHat, !1), !0);
}
function __mmBuySnowHat() {
  if (
    !__mmInSnowBiome() ||
    !v ||
    !v.alive ||
    (v.skins && v.skins[__mmSnowHat]) ||
    (v.points || 0) < __mmSnowHatPrice ||
    Date.now() - __mmSnowPurchaseAt < 500
  )
    return !1;
  return ((__mmSnowPurchaseAt = Date.now()), Xn(__mmSnowHat, !1), !0);
}
function __mmSpeedHat() {
  return __mmInWater()
    ? __mmFlipperHat
    : __mmInSnowBiome()
      ? v && v.skins && v.skins[__mmSnowHat]
        ? __mmSnowHat
        : __mmBoosterHat
      : __mmBoosterHat;
}
function __mmShiftHasSpeedGear() {
  const __mmHat = __mmSpeedHat();
  return !!(v && v.skins && v.skins[__mmHat] && v.tails && v.tails[11]);
}
function __mmShiftBaseHat() {
  return __mmTrapHat != null
    ? __mmTrapHat
    : __mmRightClickHat != null
      ? __mmRightClickHat
      : __mmPrimaryClickHat != null
        ? __mmPrimaryClickHat
        : __mmSoldierPreviousHat != null
          ? __mmSoldierPreviousHat
          : v
            ? v.skinIndex
            : null;
}
function __mmUpdateShiftSpeed() {
  if (
    !__mmShiftSpeedActive ||
    __mmShiftMode !== 1 ||
    __mmInsta.isActive()
  )
    return;
  (__mmInWater() && __mmBuyFlipperHat(),
    __mmInSnowBiome() && __mmBuySnowHat(),
    __mmSoldierPreviousHat != null && __mmPauseSoldierForBreaking());
  if (__mmTemporaryHatOverlay()) return;
  const __mmHat = __mmSpeedHat();
  if (!v.skins || !v.skins[__mmHat]) return;
  __mmEquipGearPair(__mmHat, 11);
}
function __mmRestoreShiftSpeed() {
  if (__mmShiftPreviousHat == null && __mmShiftPreviousTail == null) return;
  if (!v || !v.alive)
    return void ((__mmShiftPreviousHat = null), (__mmShiftPreviousTail = null));
  // Do not restore the tail early while a temporary combat hat still owns the
  // gear tick. Wait, then restore both saved slots in the same callback.
  if (__mmTemporaryHatOverlay())
    return void (
      __mmShiftRestoreTimer ||
      (__mmShiftRestoreTimer = setTimeout(function () {
        ((__mmShiftRestoreTimer = 0), __mmRestoreShiftSpeed());
      }, __mmServerTickMs()))
    );
  const __mmHat = __mmShiftPreviousHat,
    __mmTail = __mmShiftPreviousTail;
  ((__mmShiftPreviousHat = null),
    (__mmShiftPreviousTail = null),
    __mmEquipGearPair(__mmHat, __mmTail, !0));
}
function __mmStartShiftSpeedGear() {
  if (!v || !v.alive || !__mmShiftHasSpeedGear()) return;
  ((__mmShiftMode = 1),
    (__mmShiftPreviousHat = __mmShiftBaseHat()),
    (__mmShiftPreviousTail = v.tailIndex),
    __mmShiftSpeedTimer ||
      (__mmShiftSpeedTimer = setInterval(
        __mmUpdateShiftSpeed,
        __mmFastCheckMs(),
      )),
    __mmUpdateShiftSpeed());
}
function __mmWatchShiftGearPurchase() {
  if (__mmShiftGearPurchaseTimer) return;
  __mmShiftGearPurchaseTimer = setInterval(function () {
    if (!__mmShiftSpeedActive)
      return (
        clearInterval(__mmShiftGearPurchaseTimer),
        void (__mmShiftGearPurchaseTimer = 0)
      );
    if (!__mmShiftHasSpeedGear()) return;
    (clearInterval(__mmShiftGearPurchaseTimer),
      (__mmShiftGearPurchaseTimer = 0),
      __mmStartShiftSpeedGear(),
      window.dispatchEvent(
        new CustomEvent("MooMooScrollZoomShiftSpeed", {
          detail: "Shift speed: On",
        }),
      ));
  }, __mmFastCheckMs());
}
function __mmBuySnowHatOnShift() {
  return __mmBuySnowHat()
    ? (__mmWatchShiftGearPurchase(), !0)
    : !1;
}
function __mmBuyMonkeyTailOnShift() {
  if (
    __mmInSnowBiome() ||
    !v ||
    !v.alive ||
    (v.tails && v.tails[11]) ||
    (v.points || 0) < 2e3
  )
    return !1;
  return (Xn(11, !0), __mmWatchShiftGearPurchase(), !0);
}
function __mmStartShiftSpeed() {
  if (__mmShiftSpeedActive) return;
  ((__mmShiftSpeedActive = !0),
    __mmBuySnowHatOnShift(),
    __mmBuyMonkeyTailOnShift());
  if (__mmShiftHasSpeedGear()) {
    (__mmStartShiftSpeedGear(),
      window.dispatchEvent(
        new CustomEvent("MooMooScrollZoomShiftSpeed", {
          detail: "Shift speed: On",
        }),
      ));
    return;
  }
  ((__mmShiftMode = 2),
    window.dispatchEvent(
      new CustomEvent("MooMooScrollZoomShiftSpeed", {
        detail: "Shift speed gear unavailable",
      }),
    ));
}
function __mmStopShiftSpeed() {
  if (!__mmShiftSpeedActive) return;
  const __mmMode = __mmShiftMode;
  ((__mmShiftSpeedActive = !1),
    (__mmShiftMode = 0),
    __mmShiftSpeedTimer &&
      (clearInterval(__mmShiftSpeedTimer), (__mmShiftSpeedTimer = 0)),
    __mmShiftGearPurchaseTimer &&
      (clearInterval(__mmShiftGearPurchaseTimer),
      (__mmShiftGearPurchaseTimer = 0)),
    __mmStopBoostBreak(),
    __mmMode === 1 && __mmRestoreShiftSpeed(),
    window.dispatchEvent(
      new CustomEvent("MooMooScrollZoomShiftSpeed", {
        detail: "Shift speed: Off",
      }),
    ));
}
function __mmRestoreMovementGear(__mmForceNoMonkey) {
  if (!__mmMovementGearActive()) return;
  if (!v || !v.alive)
    return void ((__mmMovementGearPreviousHat = null),
    (__mmMovementGearPreviousTail = null));
  if (
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmTrapAttackActive ||
    __mmBoostBreakHeld ||
    __mmTankGearActive()
  )
    return;
  const __mmHat = __mmMovementGearPreviousHat,
    __mmTail =
      __mmForceNoMonkey && !__mmHasStick() ? 0 : __mmMovementGearPreviousTail;
  ((__mmMovementGearPreviousHat = null),
    (__mmMovementGearPreviousTail = null),
    __mmEquipGearPair(__mmHat, __mmTail));
}
function __mmUpdateMovementGear() {
  if (!__mmMovementGearEnabled)
    return void (__mmRestoreMovementGear(),
    __mmRestoreProximityTail(),
    __mmClearIdleMonkeyTail());
  if (!v || !v.alive)
    return void (__mmRestoreMovementGear(), __mmRestoreProximityTail());
  if (!__mmActionAvailable("movementGear")) return;
  if (__mmInsta.isActive()) return;
  // Existing combat actions own their hat and tail until they finish, avoiding
  // tick-by-tick flicker between movement and combat gear.
  if (
    __mmSyncFollowerEnabled ||
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmTrapAttackActive ||
    __mmBoostBreakHeld ||
    __mmTankGearActive()
  )
    return;
  __mmInSnowBiome() && __mmBuySnowHat();
  __mmRememberNormalHat();
  const __mmEnemyNearby = __mmEnemyWithinCombatRange(),
    __mmMoving = __mmPlayerMoving();
  if (__mmEnemyNearby) {
    __mmRestoreMovementGear(!0);
    const __mmTail =
      __mmMoving && v.tails && v.tails[__mmShadowWings]
        ? __mmShadowWings
        : !__mmMoving && v.tails && v.tails[__mmBloodWings]
          ? __mmBloodWings
          : __mmMoving
            ? null
            : 0;
    return __mmTail == null
      ? void __mmRestoreProximityTail()
      : void __mmSetProximityTail(__mmTail);
  }
  __mmRestoreProximityTail();
  if (!__mmMoving && !__mmBoostBreakHeld) {
    if (!(v.skins && v.skins[__mmEmpHelmet])) {
      __mmRestoreMovementGear();
      if (v.tails && v.tails[__mmAngelWings])
        return void __mmEquipTailNow(__mmAngelWings);
      return void __mmClearIdleMonkeyTail();
    }
    if (!__mmMovementGearActive()) {
      ((__mmMovementGearPreviousHat = __mmShiftBaseHat()),
        (__mmMovementGearPreviousTail = v.tailIndex),
        __mmPauseSoldierForBreaking());
    }
    const __mmIdleTail =
      v.tails && v.tails[__mmAngelWings]
        ? __mmAngelWings
        : __mmMovementGearPreviousTail;
    // EMP Helmet's anti-turret protection is the stationary, out-of-combat
    // phase of this gear loop. Its paired tail leaves in the same packet tick.
    return void __mmEquipGearPair(__mmEmpHelmet, __mmIdleTail);
  }
  if (__mmTankGearActive()) return;
  if (
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmTrapAttackActive ||
    __mmBoostBreakHeld
  )
    return void __mmRestoreMovementGear();
  __mmInWater() && __mmBuyFlipperHat();
  const __mmHat = __mmSpeedHat(),
    __mmHasHat = !!(v.skins && v.skins[__mmHat]),
    __mmHasTail = !!(v.tails && v.tails[11]);
  if (!__mmMovementGearActive()) {
    ((__mmMovementGearPreviousHat = __mmShiftBaseHat()),
      (__mmMovementGearPreviousTail = v.tailIndex),
      __mmPauseSoldierForBreaking());
  }
  // Snow uses owned Snow Hat first and Booster Hat while the snow purchase is
  // unavailable or still being acknowledged; do not go bald in that gap.
  __mmEquipGearPair(__mmHasHat ? __mmHat : 0, __mmHasTail ? 11 : null);
}
function __mmStartMovementGear() {
  __mmMovementGearTimer ||
    ((__mmMovementGearTimer = setInterval(
      __mmUpdateMovementGear,
      __mmFastCheckMs(),
    )),
    __mmUpdateMovementGear());
}
function __mmUpdatePassiveSpikeMotion() {
  if (!v || !v.alive) {
    __mmPassiveSpikeMotion = null;
    return;
  }
  const __mmNow = Date.now(),
    __mmPrevious = __mmPassiveSpikeMotion,
    __mmElapsed = __mmPrevious
      ? Math.max(1, Math.min(250, __mmNow - __mmPrevious.at))
      : 0,
    __mmSampleVelocityX = __mmElapsed
      ? (Number(v.x) - __mmPrevious.x) / __mmElapsed
      : 0,
    __mmSampleVelocityY = __mmElapsed
      ? (Number(v.y) - __mmPrevious.y) / __mmElapsed
      : 0,
    __mmVelocityX = __mmPrevious && __mmElapsed < 250
      ? __mmSampleVelocityX * 0.72 + __mmPrevious.velocityX * 0.28
      : __mmSampleVelocityX,
    __mmVelocityY = __mmPrevious && __mmElapsed < 250
      ? __mmSampleVelocityY * 0.72 + __mmPrevious.velocityY * 0.28
      : __mmSampleVelocityY;
  __mmPassiveSpikeMotion = {
    x: Number(v.x) || 0,
    y: Number(v.y) || 0,
    at: __mmNow,
    velocityX: Number.isFinite(__mmVelocityX) ? __mmVelocityX : 0,
    velocityY: Number.isFinite(__mmVelocityY) ? __mmVelocityY : 0,
  };
}
function __mmPassiveSpikeVelocity() {
  let __mmVelocityX = Number(
      __mmPassiveSpikeMotion && __mmPassiveSpikeMotion.velocityX,
    ) || 0,
    __mmVelocityY = Number(
      __mmPassiveSpikeMotion && __mmPassiveSpikeMotion.velocityY,
    ) || 0;
  const __mmServerElapsed = Number(v && v.t2) - Number(v && v.t1),
    __mmServerVelocityX =
      (Number(v && v.x2) - Number(v && v.x1)) / __mmServerElapsed,
    __mmServerVelocityY =
      (Number(v && v.y2) - Number(v && v.y1)) / __mmServerElapsed,
    __mmTrackedSpeed = Math.hypot(__mmVelocityX, __mmVelocityY),
    __mmServerSpeed = Math.hypot(__mmServerVelocityX, __mmServerVelocityY);
  if (
    Number.isFinite(__mmServerVelocityX) &&
    Number.isFinite(__mmServerVelocityY) &&
    __mmServerElapsed > 0 &&
    __mmServerElapsed <= 500 &&
    __mmServerSpeed > __mmTrackedSpeed
  )
    ((__mmVelocityX = __mmServerVelocityX),
      (__mmVelocityY = __mmServerVelocityY));
  return { x: __mmVelocityX, y: __mmVelocityY };
}
function __mmPassiveSpikeEnemyNearby() {
  if (
    !v ||
    !v.alive ||
    !Array.isArray(E) ||
    __mmPassiveSpikeEnemyRange <= 0
  )
    return !1;
  const __mmRangeSquared =
    __mmPassiveSpikeEnemyRange * __mmPassiveSpikeEnemyRange;
  for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
    const __mmPlayer = E[__mmIndex];
    if (!__mmIsEnemyPlayer(__mmPlayer)) continue;
    const __mmDx = __mmPlayer.x - v.x,
      __mmDy = __mmPlayer.y - v.y;
    if (__mmDx * __mmDx + __mmDy * __mmDy <= __mmRangeSquared) return !0;
  }
  return !1;
}
function __mmPassiveSpikeThreat() {
  if (!v || !v.alive || !Array.isArray(ge)) return null;
  const __mmVelocity = __mmPassiveSpikeVelocity(),
    __mmSpeed = Math.hypot(__mmVelocity.x, __mmVelocity.y);
  if (!Number.isFinite(__mmSpeed) || __mmSpeed < 0.01) return null;
  const __mmLeadMs = Math.max(
      150,
      Math.min(280, __mmServerTickMs() * 1.8),
    ),
    __mmCoastDistance = Math.min(95, __mmSpeed * __mmLeadMs),
    __mmEndX = v.x + (__mmVelocity.x / __mmSpeed) * __mmCoastDistance,
    __mmEndY = v.y + (__mmVelocity.y / __mmSpeed) * __mmCoastDistance;
  let __mmBest = null,
    __mmBestDistance = Infinity;
  for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
    const __mmSpike = ge[__mmIndex],
      __mmData = __mmSpike && b && b.list && b.list[__mmSpike.id],
      __mmName = String(__mmData && __mmData.name || "").toLowerCase();
    if (
      !__mmSpike ||
      !__mmSpike.active ||
      !__mmSpike.isItem ||
      !__mmName.includes("spikes") ||
      __mmSpikeOwnedByUsOrAlly(__mmSpike)
    )
      continue;
    const __mmToSpikeX = __mmSpike.x - v.x,
      __mmToSpikeY = __mmSpike.y - v.y,
      __mmToward =
        __mmToSpikeX * __mmVelocity.x +
        __mmToSpikeY * __mmVelocity.y;
    if (__mmToward <= 0) continue;
    const __mmRadius =
        (Number(v.scale) || 35) +
        (Number(__mmSpike.scale) || Number(__mmData.scale) || 45) +
        4,
      __mmPathDistanceSquared = __mmSegmentDistanceSquared(
        v.x,
        v.y,
        __mmEndX,
        __mmEndY,
        __mmSpike.x,
        __mmSpike.y,
      ),
      __mmCenterDistanceSquared =
        __mmToSpikeX * __mmToSpikeX + __mmToSpikeY * __mmToSpikeY;
    if (
      __mmPathDistanceSquared <= __mmRadius * __mmRadius &&
      __mmCenterDistanceSquared < __mmBestDistance
    )
      ((__mmBest = __mmSpike),
        (__mmBestDistance = __mmCenterDistanceSquared));
  }
  return __mmBest;
}
function __mmStopPassiveSpikeCorrection(__mmUserMovementTakingOver) {
  (__mmPassiveSpikePendingTimer &&
    clearTimeout(__mmPassiveSpikePendingTimer),
    (__mmPassiveSpikePendingTimer = 0),
    __mmPassiveSpikeCorrectionTimer &&
      clearTimeout(__mmPassiveSpikeCorrectionTimer),
    (__mmPassiveSpikeCorrectionTimer = 0));
  if (!__mmPassiveSpikeCorrecting) return;
  ((__mmPassiveSpikeCorrecting = !1), (Kt = null));
  __mmUserMovementTakingOver || Tt();
}
function __mmRunPassiveSpikeCorrection() {
  __mmPassiveSpikePendingTimer = 0;
  if (
    !__mmPassiveSpikeAvoidanceEnabled ||
    !v ||
    !v.alive ||
    (typeof ul === "function" && ul() != null) ||
    __mmPassiveSpikeEnemyNearby() ||
    __mmSyncFollowerEnabled ||
    __mmBoostBackingUp ||
    __mmBoostBreakHeld ||
    __mmTrapAttackActive ||
    __mmInsta.isActive() ||
    __mmIsTrapped()
  )
    return;
  const __mmSpike = __mmPassiveSpikeThreat();
  if (!__mmSpike) return;
  const __mmAway = Math.atan2(v.y - __mmSpike.y, v.x - __mmSpike.x),
    __mmDuration = Math.max(75, Math.min(140, __mmServerTickMs()));
  ((__mmPassiveSpikeCorrecting = !0),
    (Kt = __mmAway),
    O.send("9", __mmAway),
    (__mmPassiveSpikeCorrectionTimer = setTimeout(function () {
      __mmStopPassiveSpikeCorrection(!1);
    }, __mmDuration)));
}
function __mmPassiveSpikeMovementPressed() {
  __mmStopPassiveSpikeCorrection(!0);
}
function __mmPassiveSpikeMovementReleased() {
  if (
    !__mmPassiveSpikeAvoidanceEnabled ||
    (typeof ul === "function" && ul() != null)
  )
    return;
  __mmPassiveSpikePendingTimer && clearTimeout(__mmPassiveSpikePendingTimer);
  __mmPassiveSpikePendingTimer = setTimeout(__mmRunPassiveSpikeCorrection, 0);
}
function __mmStartPassiveSpikeAvoidance() {
  if (!__mmPassiveSpikeAvoidanceEnabled || __mmPassiveSpikeMotionTimer) return;
  (__mmUpdatePassiveSpikeMotion(),
    (__mmPassiveSpikeMotionTimer = setInterval(
      __mmUpdatePassiveSpikeMotion,
      Math.max(8, __mmFastCheckMs()),
    )));
}
function __mmStopPassiveSpikeAvoidance() {
  (__mmPassiveSpikeMotionTimer && clearInterval(__mmPassiveSpikeMotionTimer),
    (__mmPassiveSpikeMotionTimer = 0),
    (__mmPassiveSpikeMotion = null),
    __mmStopPassiveSpikeCorrection(!1));
}
function __mmBoostPadItem() {
  if (!v || !v.items) return null;
  for (let __mmItemIndex = 0; __mmItemIndex < v.items.length; __mmItemIndex++) {
    const __mmItem = v.items[__mmItemIndex],
      __mmData = b.list[__mmItem];
    if (__mmData && __mmData.boostSpeed) return __mmItem;
  }
  return null;
}
function __mmHasPitTrap() {
  if (!v || !v.items) return !1;
  for (let __mmItemIndex = 0; __mmItemIndex < v.items.length; __mmItemIndex++) {
    const __mmData = b.list[v.items[__mmItemIndex]];
    if (__mmData && __mmData.trap) return !0;
  }
  return !1;
}
function __mmCanUseBuildItem(__mmItem) {
  const __mmData = b.list[__mmItem];
  if (!v || !__mmData || !__mmData.req) return !1;
  for (
    let __mmReqIndex = 0;
    __mmReqIndex < __mmData.req.length;
    __mmReqIndex += 2
  )
    if ((v[__mmData.req[__mmReqIndex]] || 0) < __mmData.req[__mmReqIndex + 1])
      return !1;
  return !0;
}
function __mmThreatTrapItem() {
  if (!v || !v.items || !b || !b.list) return null;
  if (__mmThreatTrapEnabled)
    for (let __mmItemIndex = 0; __mmItemIndex < v.items.length; __mmItemIndex++) {
      const __mmItem = v.items[__mmItemIndex],
        __mmData = b.list[__mmItem];
      if (__mmData && __mmData.trap && __mmCanUseBuildItem(__mmItem))
        return __mmItem;
    }
  // Pit traps keep priority when both controls are enabled. Spikes have their
  // own switch and remain blocked while Mc Grabby is actively selected.
  if (!__mmAutoCloseSpikeEnabled || __mmHoldingMcGrabby()) return null;
  for (let __mmItemIndex = 0; __mmItemIndex < v.items.length; __mmItemIndex++) {
    const __mmItem = v.items[__mmItemIndex],
      __mmData = b.list[__mmItem];
    if (
      __mmData &&
      typeof __mmData.name === "string" &&
      __mmData.name.indexOf("spikes") !== -1 &&
      __mmCanUseBuildItem(__mmItem)
    )
      return __mmItem;
  }
  return null;
}
function __mmThreatTeleporterItem() {
  if (!v || !v.items || !b || !b.list) return null;
  for (let __mmItemIndex = 0; __mmItemIndex < v.items.length; __mmItemIndex++) {
    const __mmItem = v.items[__mmItemIndex],
      __mmData = b.list[__mmItem];
    if (
      __mmData &&
      String(__mmData.name || "").toLowerCase() === "teleporter" &&
      __mmCanUseBuildItem(__mmItem)
    )
      return __mmItem;
  }
  return null;
}
function __mmThreatTrapAnimalName(__mmAnimal) {
  return String((__mmAnimal && __mmAnimal.name) || "").trim().toLowerCase();
}
function __mmThreatAnimalIsWolf(__mmAnimal) {
  return __mmThreatTrapAnimalName(__mmAnimal) === "wolf";
}
function __mmThreatItemIsPitTrap(__mmItem) {
  const __mmData = b && b.list && b.list[__mmItem];
  return !!(__mmData && __mmData.trap);
}
function __mmThreatTeleporterAnimalAllowed(__mmAnimal) {
  const __mmName = __mmThreatTrapAnimalName(__mmAnimal);
  return !!(
    __mmAnimal &&
    __mmAnimal.active &&
    __mmAnimal.alive &&
    __mmAnimal.visible &&
    (__mmName === "moostafa" || __mmName === "moofie")
  );
}
function __mmThreatTrapAnimalAllowed(__mmAnimal) {
  if (
    !__mmAnimal ||
    !__mmAnimal.active ||
    !__mmAnimal.alive ||
    !__mmAnimal.visible ||
    !__mmAnimal.hostile
  )
    return !1;
  const __mmName = __mmThreatTrapAnimalName(__mmAnimal);
  return __mmName !== "moostafa" && __mmName !== "moofie";
}
function __mmThreatTargetKey(__mmTarget) {
  if (!__mmTarget) return null;
  const __mmId =
    __mmTarget.sid != null
      ? __mmTarget.sid
      : __mmTarget.id != null
        ? __mmTarget.id
        : __mmTarget.index != null
          ? __mmTarget.index
          : null;
  return __mmId == null ? null : String(__mmId);
}
function __mmRememberThreatTrap(__mmTarget, __mmItem, __mmAngle) {
  const __mmKey = __mmThreatTargetKey(__mmTarget),
    __mmData = b && b.list && b.list[__mmItem];
  if (!__mmKey || !__mmData || !__mmData.trap || !v) return;
  const __mmPlaceDistance =
      (Number(v.scale) || 35) +
      (Number(__mmData.scale) || 50) +
      (Number(__mmData.placeOffset) || 0),
    __mmCollisionScale = Math.max(
      10,
      (Number(__mmData.scale) || 50) * (Number(__mmData.colDiv) || 1),
    );
  __mmThreatTrapPlacements[__mmKey] = {
    x: v.x + Math.cos(__mmAngle) * __mmPlaceDistance,
    y: v.y + Math.sin(__mmAngle) * __mmPlaceDistance,
    scale: __mmCollisionScale,
    // Keep only a brief acknowledgement bridge; never retain a stale target
    // position after a death or despawn.
    expiresAt: Date.now() + 2500,
  };
}
function __mmThreatAlreadyTrapped(__mmTarget) {
  if (
    !__mmTarget ||
    !X ||
    typeof X.getGridArrays !== "function" ||
    !Number.isFinite(Number(__mmTarget.x)) ||
    !Number.isFinite(Number(__mmTarget.y))
  )
    return !1;
  const __mmTargetScale = Number(__mmTarget.scale) || 35;
  if (__mmTarget.lockMove) return !0;
  const __mmTargetKey = __mmThreatTargetKey(__mmTarget),
    __mmRememberedTrap =
      __mmTargetKey && __mmThreatTrapPlacements[__mmTargetKey];
  if (__mmRememberedTrap) {
    if (__mmRememberedTrap.expiresAt <= Date.now())
      delete __mmThreatTrapPlacements[__mmTargetKey];
    else if (
      Math.hypot(
        __mmRememberedTrap.x - __mmTarget.x,
        __mmRememberedTrap.y - __mmTarget.y,
      ) <=
        __mmTargetScale + __mmRememberedTrap.scale + 10
    )
      return !0;
  }
  let __mmGrids;
  try {
    __mmGrids = X.getGridArrays(
      __mmTarget.x,
      __mmTarget.y,
      __mmTargetScale + 60,
    );
  } catch (__mmGridError) {
    return !1;
  }
  if (!Array.isArray(__mmGrids)) return !1;
  for (let __mmGridIndex = 0; __mmGridIndex < __mmGrids.length; __mmGridIndex++)
    for (
      let __mmObjectIndex = 0;
      __mmObjectIndex < __mmGrids[__mmGridIndex].length;
      __mmObjectIndex++
    ) {
      const __mmObject = __mmGrids[__mmGridIndex][__mmObjectIndex];
      if (!__mmObject || !__mmObject.active || !__mmObject.trap) continue;
      const __mmTrapScale =
        typeof __mmObject.getScale === "function"
          ? __mmObject.getScale()
          : Number(__mmObject.scale) || 50;
      if (
        Math.hypot(
          __mmObject.x - __mmTarget.x,
          __mmObject.y - __mmTarget.y,
        ) <=
          __mmTargetScale +
            Math.max(__mmTrapScale, Number(__mmObject.scale) || 0) +
            10
      )
        return !0;
    }
  return !1;
}
function __mmThreatTrapTarget(__mmTrap, __mmTeleporter) {
  if (!v || !v.alive) return null;
  const __mmPlayers = __mmLiveStateFresh() ? __mmLiveState.enemies : E,
    __mmAnimals = __mmLiveStateFresh() ? __mmLiveState.animals : N;
  let __mmClosest = null,
    __mmClosestDistance = Infinity;
  const __mmConsider = function (
    __mmTarget,
    __mmType,
    __mmItem,
    __mmRange,
  ) {
    if (
      !__mmTarget ||
      __mmThreatAlreadyTrapped(__mmTarget) ||
      !Number.isFinite(Number(__mmTarget.x)) ||
      !Number.isFinite(Number(__mmTarget.y))
    )
      return;
    const __mmDistance = Math.hypot(__mmTarget.x - v.x, __mmTarget.y - v.y);
    if (__mmDistance > __mmRange || __mmDistance >= __mmClosestDistance)
      return;
    const __mmId =
      __mmTarget.sid != null
        ? __mmTarget.sid
        : __mmTarget.id != null
          ? __mmTarget.id
          : __mmTarget.index != null
            ? __mmTarget.index
            : Math.round(__mmTarget.x) + ":" + Math.round(__mmTarget.y);
    ((__mmClosest = {
      target: __mmTarget,
      key: __mmType + ":" + __mmId,
      item: __mmItem,
      distance: __mmDistance,
    }),
      (__mmClosestDistance = __mmDistance));
  };
  if (__mmTrap != null && Array.isArray(__mmPlayers))
    for (let __mmIndex = 0; __mmIndex < __mmPlayers.length; __mmIndex++) {
      const __mmPlayer = __mmPlayers[__mmIndex];
      __mmIsEnemyPlayer(__mmPlayer) &&
        __mmConsider(__mmPlayer, "player", __mmTrap, __mmThreatTrapRange);
    }
  if (Array.isArray(__mmAnimals))
    for (let __mmIndex = 0; __mmIndex < __mmAnimals.length; __mmIndex++) {
      const __mmAnimal = __mmAnimals[__mmIndex];
      __mmTrap != null &&
        __mmThreatTrapAnimalAllowed(__mmAnimal) &&
        // Wolves are easy melee kills and flee after spike damage. They are
        // still trapped normally whenever the chosen item is a real pit trap.
        (!__mmThreatAnimalIsWolf(__mmAnimal) ||
          __mmThreatItemIsPitTrap(__mmTrap)) &&
        __mmConsider(
          __mmAnimal,
          "animal",
          __mmTrap,
          __mmThreatAnimalRange,
        );
      __mmTeleporter != null &&
        __mmThreatTeleporterAnimalAllowed(__mmAnimal) &&
        __mmConsider(
          __mmAnimal,
          "teleporter",
          __mmTeleporter,
          __mmThreatAnimalRange,
        );
    }
  return __mmClosest;
}
function __mmPlaceThreatTrap() {
  if (
    (!__mmThreatTrapEnabled && !__mmAutoCloseSpikeEnabled) ||
    !v ||
    !v.alive ||
    v.lockMove ||
    __mmInsta.isActive() ||
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmTrapAttackActive ||
    __mmBoostBreakHeld ||
    __mmBuildSpamTimer ||
    __mmFoodSpamTimer
  )
    return !1;
  const __mmTrap = __mmThreatTrapItem(),
    __mmTeleporter = __mmThreatTrapEnabled
      ? __mmThreatTeleporterItem()
      : null,
    __mmThreat = __mmThreatTrapTarget(__mmTrap, __mmTeleporter),
    __mmNow = Date.now();
  if (
    !__mmThreat ||
    (__mmThreat.key === __mmThreatTrapLastKey &&
      __mmNow - __mmThreatTrapLastAt < __mmThreatTrapCooldownMs)
  )
    return !1;
  // Only take action ownership after a real, non-cooled-down threat exists.
  // Claiming first used to cancel Cleanup on every empty 25ms scan.
  if (!__mmActionClaim("threatTrap", "nearby hostile")) return !1;
  // Build placement is angle-based and always occurs at the player's placement
  // radius, so aiming at the threat puts the defensive item between us.
  const __mmAngle = Math.atan2(
      __mmThreat.target.y - v.y,
      __mmThreat.target.x - v.x,
    ),
    __mmWeapon = __mmSelectedWeapon();
  try {
    (je(__mmThreat.item),
      O.send("F", 1, __mmAngle),
      O.send("F", 0, __mmAngle),
      __mmRememberThreatTrap(__mmThreat.target, __mmThreat.item, __mmAngle),
      __mmWeapon != null && __mmRestoreWeapon(__mmWeapon),
      (__mmThreatTrapLastAt = __mmNow),
      (__mmThreatTrapLastKey = __mmThreat.key),
      __mmActionRelease("threatTrap", "placed"));
    return !0;
  } catch (__mmThreatTrapError) {
    return (__mmActionRelease("threatTrap", "placement failed"), !1);
  }
}
function __mmStartThreatTrap() {
  __mmThreatTrapTimer ||
    (__mmThreatTrapTimer = setInterval(
      __mmPlaceThreatTrap,
      __mmFastCheckMs(),
    ));
}
function __mmNearestEnemy() {
  if (!v || !v.alive) return null;
  if (__mmLiveStateFresh()) return __mmLiveState.nearestEnemy;
  let __mmClosest = null,
    __mmClosestDistance = Infinity;
  for (let __mmPlayerIndex = 0; __mmPlayerIndex < E.length; __mmPlayerIndex++) {
    const __mmPlayer = E[__mmPlayerIndex];
    if (!__mmIsEnemyPlayer(__mmPlayer)) continue;
    const __mmDx = __mmPlayer.x - v.x,
      __mmDy = __mmPlayer.y - v.y,
      __mmDistance = __mmDx * __mmDx + __mmDy * __mmDy;
    if (__mmDistance < __mmClosestDistance) {
      ((__mmClosestDistance = __mmDistance), (__mmClosest = __mmPlayer));
    }
  }
  return __mmClosest;
}
function __mmWeaponReady(__mmWeapon) {
  if (!v || !v.alive || __mmWeapon == null) return !1;
  const __mmReload = v.reloads && Number(v.reloads[__mmWeapon]);
  return !Number.isFinite(__mmReload) || __mmReload <= 0;
}
function __mmBoostBreakWeapon() {
  if (!v || !v.weapons) return null;
  if (v.weapons.includes(__mmGreatHammer)) return __mmGreatHammer;
  const __mmMainWeapon = v.weapons[0];
  return __mmMainWeapon === __mmKatana || __mmMainWeapon === __mmPolearmWeapon
    ? __mmMainWeapon
    : null;
}
function __mmCanBoostBreak() {
  const __mmPad = __mmBoostPadItem();
  return !!(
    v &&
    v.alive &&
    v.skins &&
    v.skins[40] &&
    __mmPad != null &&
    !__mmHasPitTrap() &&
    __mmCanUseBuildItem(__mmPad) &&
    __mmBoostBreakWeapon() != null &&
    !__mmInsta.isActive() &&
    !__mmPrimaryHeld &&
    !__mmSecondaryHeld &&
    !__mmTrapAttackActive
  );
}
function __mmBoostBreakWeaponReady() {
  const __mmWeapon = __mmBoostBreakWeapon(),
    __mmReload = v && v.reloads && Number(v.reloads[__mmWeapon]);
  if (__mmWeapon == null || (Number.isFinite(__mmReload) && __mmReload > 0))
    return !1;
  return !(
    __mmBoostBreakCooldownWeapon === __mmWeapon &&
    Date.now() < __mmBoostBreakReadyAt
  );
}
function __mmShuffleBoostChat() {
  __mmBoostChatOrder = __mmBoostChatLines.slice();
  for (
    let __mmIndex = __mmBoostChatOrder.length - 1;
    __mmIndex > 0;
    __mmIndex--
  ) {
    const __mmRandom = Math.floor(Math.random() * (__mmIndex + 1)),
      __mmSwap = __mmBoostChatOrder[__mmIndex];
    ((__mmBoostChatOrder[__mmIndex] = __mmBoostChatOrder[__mmRandom]),
      (__mmBoostChatOrder[__mmRandom] = __mmSwap));
  }
  __mmBoostChatIndex = 0;
}
function __mmSendChat(__mmMessage) {
  typeof on === "function" &&
    typeof __mmMessage === "string" &&
    on(__mmMessage.slice(0, 30));
}
let __mmMaterialReplyLastAt = 0;
function __mmChatMentionsMaterials(__mmMessage) {
  if (typeof __mmMessage !== "string") return !1;
  const __mmWords = __mmMessage
    .toLowerCase()
    .replace(/[@4]/g, "a")
    .replace(/1/g, "i")
    .replace(/3/g, "e")
    .replace(/0/g, "o")
    .replace(/5/g, "s")
    .replace(/7/g, "t")
    .replace(/[^a-z]+/g, " ")
    .trim();
  return /(?:^|\s)(?:mats?|materials?|resources?|res|supplies|wood|stone)(?:\s|$)/.test(
    __mmWords,
  );
}
function __mmReplyToMaterialRequest(__mmPlayerSid, __mmMessage) {
  if (
    !__mmMaterialReplyEnabled ||
    !v ||
    !v.alive ||
    __mmPlayerSid == null ||
    String(__mmPlayerSid) === String(v.sid) ||
    !__mmChatMentionsMaterials(__mmMessage)
  )
    return;
  let __mmPlayer = null;
  try {
    __mmPlayer = Rt(__mmPlayerSid);
  } catch (__mmLookupError) {}
  if (
    !__mmPlayer ||
    (!__mmSameTeam(__mmPlayer) && !__mmIsFriendPlayer(__mmPlayer))
  )
    return;
  const __mmNow = Date.now(),
    __mmCooldown = Math.max(2500, (Number(y && y.chatCooldown) || 500) * 2);
  if (__mmNow - __mmMaterialReplyLastAt < __mmCooldown) return;
  const __mmWood = Math.max(0, Math.floor(Number(v.wood) || 0)),
    __mmStone = Math.max(0, Math.floor(Number(v.stone) || 0));
  ((__mmMaterialReplyLastAt = __mmNow),
    __mmSendChat("Wood " + __mmWood + " Stone " + __mmStone));
}
let __mmModReplyLastAt = 0;
const __mmModReplyText = "kitty klient",
  __mmModReplyCooldownMs = 5000;
function __mmChatMentionsMod(__mmMessage) {
  if (typeof __mmMessage !== "string") return !1;
  const __mmNormalized = __mmMessage
      .toLowerCase()
      .replace(/[@4]/g, "a")
      .replace(/1/g, "i")
      .replace(/3/g, "e")
      .replace(/0/g, "o")
      .replace(/5/g, "s")
      .replace(/7/g, "t"),
    __mmWords = __mmNormalized.replace(/[^a-z]+/g, " ").trim(),
    __mmCompact = __mmNormalized.replace(/[^a-z]+/g, "");
  // Match direct questions and casual accusations without depending on exact
  // phrasing or punctuation. Distinctive compact forms also catch "h a c k"
  // and similarly spaced-out attempts.
  return !!(
    /(?:^|\s)(?:mod(?:s|ded)?|hack(?:s|er|ing|ed)?|hax|client|klient|macro(?:s)?|script(?:s|ed)?|userscript|cheat(?:s|er|ing|ed)?|tampermonkey)(?:\s|$)/.test(
      __mmWords,
    ) ||
    /(?:hack|hax|client|klient|macro|userscript|tampermonkey)/.test(
      __mmCompact,
    )
  );
}
function __mmReplyToModQuestion(__mmPlayerSid, __mmMessage) {
  if (
    !v ||
    !v.alive ||
    __mmPlayerSid === v.sid ||
    !__mmChatMentionsMod(__mmMessage)
  )
    return;
  const __mmNow = Date.now();
  if (__mmNow - __mmModReplyLastAt < __mmModReplyCooldownMs) return;
  ((__mmModReplyLastAt = __mmNow), __mmSendChat(__mmModReplyText));
}
function __mmSendBoostChat() {
  if (!__mmBoostBreakHeld || !__mmShiftHeld() || !v || !v.alive) return;
  if (!__mmBoostChatOrder.length) __mmShuffleBoostChat();
  __mmSendChat(
    __mmBoostChatOrder[__mmBoostChatIndex++ % __mmBoostChatOrder.length],
  );
}
function __mmStartBoostChat() {
  if (!__mmBoostChatEnabled || __mmBoostChatTimer) return;
  (__mmShuffleBoostChat(),
    __mmSendBoostChat(),
    (__mmBoostChatTimer = setInterval(
      __mmSendBoostChat,
      Math.max(550, Number(y.chatCooldown) || 500),
    )));
}
function __mmStopBoostChat() {
  (__mmBoostChatTimer &&
    (clearInterval(__mmBoostChatTimer), (__mmBoostChatTimer = 0)),
    __mmShuffleBoostChat());
}
function __mmStartBoostForward(__mmAngle) {
  ((__mmBoostMoveDirection = __mmAngle),
    O.send("9", __mmAngle),
    (Kt = __mmAngle));
}
function __mmFinishBoostBreakGear() {
  if (!v || !v.alive) return;
  const __mmEnemyNearby = __mmEnemyWithinCombatRange(),
    __mmTail =
      !__mmEnemyNearby && v.tails && v.tails[11] && v.tailIndex !== 11
        ? 11
        : __mmEnemyNearby && !__mmHasStick() && v.tailIndex === 11
          ? 0
          : null,
    __mmSpeed = __mmSpeedHat();
  let __mmHat = null;
  if (!__mmEnemyNearby && v.skins && v.skins[__mmSpeed]) __mmHat = __mmSpeed;
  else if (
    __mmBoostTankPreviousHat != null &&
    v.skinIndex === 40 &&
    __mmCanEquipHat(__mmBoostTankPreviousHat)
  )
    __mmHat = __mmBoostTankPreviousHat;
  else if (
    __mmInSnowBiome() &&
    v.skins &&
    v.skins[__mmBoosterHat] &&
    v.skinIndex !== __mmBoosterHat
  )
    __mmHat = __mmBoosterHat;
  __mmEquipGearPair(__mmHat, __mmTail, !0);
}
function __mmSelectBoostBreakWeapon(__mmWeapon) {
  if (!v || !v.weapons || !v.weapons.includes(__mmWeapon)) return !1;
  return ((__mmLastWeapon = __mmWeapon), je(__mmWeapon, !0), !0);
}
function __mmFinishBoostBreakStrike(__mmWeapon, __mmAngle) {
  __mmBoostBreakStrikeTimer = 0;
  const __mmPreviousWeapon = __mmBoostBreakPreviousWeapon;
  __mmBoostBreakPreviousWeapon = null;
  if (!__mmBoostBreakHeld || !v || !v.alive)
    return void (__mmBoostBreakStriking = !1);
  (__mmSelectBoostBreakWeapon(__mmWeapon) &&
    (O.send("F", 1, __mmAngle), O.send("F", 0, __mmAngle)),
    __mmRestoreWeapon(__mmPreviousWeapon),
    __mmFinishBoostBreakGear(),
    (__mmBoostBreakCooldownWeapon = __mmWeapon),
    (__mmBoostBreakReadyAt =
      Date.now() + Math.max(1, Number(b.weapons[__mmWeapon].speed) || 400)),
    (__mmBoostBreakStriking = !1));
}
function __mmBoostBreakTick() {
  if (__mmBoostBreakStriking) return;
  if (!__mmBoostBreakHeld || !__mmShiftHeld() || !__mmCanBoostBreak())
    return void __mmStopBoostBreak();
  if (!__mmBoostBreakWeaponReady()) return;
  const __mmPad = __mmBoostPadItem();
  if (__mmPad == null || !__mmCanUseBuildItem(__mmPad))
    return void __mmStopBoostBreak();
  const __mmWeapon = __mmBoostBreakWeapon();
  if (__mmWeapon == null) return void __mmStopBoostBreak();
  const __mmAngle = Ci(),
    __mmTail =
      !__mmEnemyWithinCombatRange() &&
      v.tails &&
      v.tails[11] &&
      v.tailIndex !== 11
        ? 11
        : null;
  (__mmPauseSoldierForBreaking(),
    __mmBoostTankPreviousHat == null &&
      (__mmBoostTankPreviousHat = v.skinIndex),
    __mmEquipGearPair(40, __mmTail, !0),
    je(__mmPad),
    O.send("F", 1, __mmAngle),
    O.send("F", 0, __mmAngle),
    __mmStartBoostForward(__mmAngle),
    (__mmBoostBreakPreviousWeapon = __mmSelectedWeapon()),
    (__mmBoostBreakStriking = !0),
    __mmSelectBoostBreakWeapon(__mmWeapon),
    (__mmBoostBreakStrikeTimer = setTimeout(function () {
      __mmFinishBoostBreakStrike(__mmWeapon, __mmAngle);
    }, __mmServerTickMs())));
}
function __mmStartBoostBreak() {
  __mmInsta.isActive() && __mmInsta.cancel("boost-break");
  if (!__mmBoostBreakEnabled || !__mmShiftHeld() || !__mmCanBoostBreak())
    return;
  if (!__mmActionClaim("boostBreak", "shift boost-break")) return;
  ((__mmBoostBreakHeld = !0),
    __mmBoostBreakTimer ||
      (__mmBoostBreakTimer = setInterval(
        __mmBoostBreakTick,
        __mmServerTickMs(),
      )),
    __mmStartBoostChat(),
    __mmBoostBreakTick());
}
function __mmStopBoostBreak() {
  const __mmRestore = __mmActionMayRestore("boostBreak");
  ((__mmBoostBreakHeld = !1),
    __mmBoostBreakTimer &&
      (clearInterval(__mmBoostBreakTimer), (__mmBoostBreakTimer = 0)),
    __mmBoostBreakStrikeTimer &&
      (clearTimeout(__mmBoostBreakStrikeTimer),
      (__mmBoostBreakStrikeTimer = 0)),
    (__mmBoostBreakStriking = !1),
    __mmRestore &&
      __mmBoostBreakPreviousWeapon != null &&
      __mmRestoreWeapon(__mmBoostBreakPreviousWeapon),
    (__mmBoostBreakPreviousWeapon = null),
    __mmStopBoostChat(),
    (__mmBoostBreakCooldownWeapon = null),
    (__mmBoostBreakReadyAt = 0));
  if (__mmRestore && v && v.alive && __mmBoostTankPreviousHat != null) {
    const __mmHat = __mmBoostTankPreviousHat;
    ((__mmBoostTankPreviousHat = null),
      v.skinIndex === 40 && __mmCanEquipHat(__mmHat) && __mmEquipHatNow(__mmHat));
  } else __mmBoostTankPreviousHat = null;
  (__mmBoostMoveDirection != null &&
    ((Kt = null), Tt(), (__mmBoostMoveDirection = null)),
    __mmActionRelease("boostBreak", "boost-break complete"),
    __mmUpdateMovementGear());
}
function __mmStartAutoHeal() {
  __mmAutoHealTimer || (__mmAutoHealTimer = setInterval(__mmAutoHeal, 10));
}
function __mmUpdateAutoInsta() {
  return !!(
    __mmInsta.canAutoStart() &&
    __mmInsta.start({ automatic: !0 })
  );
}
function __mmStartAutoInsta() {
  // Auto Insta is intentionally input-assisted. The primary mousedown path
  // calls __mmUpdateAutoInsta; proximity by itself never starts a combo.
  __mmAutoInstaTimer && clearInterval(__mmAutoInstaTimer);
  __mmAutoInstaTimer = 0;
}
function __mmSpikeHostileToEnemy(__mmSpike, __mmEnemy) {
  if (!__mmSpike || !__mmEnemy || !__mmSpike.owner) return !0;
  const __mmOwner = __mmSpike.owner,
    __mmOwnerSid = __mmOwner.sid;
  if (
    __mmOwner === __mmEnemy ||
    String(__mmOwnerSid) === String(__mmEnemy.sid)
  )
    return !1;
  const __mmOwnerPlayer = typeof Rt === "function" ? Rt(__mmOwnerSid) : null,
    __mmOwnerTeam = __mmTeamKey(__mmOwnerPlayer || __mmOwner),
    __mmEnemyTeam = __mmTeamKey(__mmEnemy);
  return !(
    __mmOwnerTeam != null &&
    __mmEnemyTeam != null &&
    __mmOwnerTeam === __mmEnemyTeam
  );
}
function __mmPredictEnemyNextTick(__mmEnemy, __mmNow) {
  const __mmSid = String(__mmEnemy.sid),
    __mmPrevious = __mmAutoSpikeInstaMotion[__mmSid],
    __mmSampleElapsed = __mmPrevious
      ? Math.max(1, Math.min(250, __mmNow - __mmPrevious.at))
      : 0;
  let __mmVelocityX = __mmPrevious
      ? (__mmEnemy.x - __mmPrevious.x) / __mmSampleElapsed
      : 0,
    __mmVelocityY = __mmPrevious
      ? (__mmEnemy.y - __mmPrevious.y) / __mmSampleElapsed
      : 0;
  const __mmServerElapsed = Number(__mmEnemy.t2) - Number(__mmEnemy.t1),
    __mmServerVelocityX =
      (Number(__mmEnemy.x2) - Number(__mmEnemy.x1)) / __mmServerElapsed,
    __mmServerVelocityY =
      (Number(__mmEnemy.y2) - Number(__mmEnemy.y1)) / __mmServerElapsed;
  if (
    Number.isFinite(__mmServerVelocityX) &&
    Number.isFinite(__mmServerVelocityY) &&
    __mmServerElapsed > 0 &&
    __mmServerElapsed <= 500
  ) {
    ((__mmVelocityX = __mmPrevious
      ? __mmServerVelocityX * 0.75 + __mmVelocityX * 0.25
      : __mmServerVelocityX),
      (__mmVelocityY = __mmPrevious
        ? __mmServerVelocityY * 0.75 + __mmVelocityY * 0.25
        : __mmServerVelocityY));
  }
  __mmAutoSpikeInstaMotion[__mmSid] = {
    x: __mmEnemy.x,
    y: __mmEnemy.y,
    at: __mmNow,
  };
  const __mmLeadMs = __mmServerTickMs();
  return {
    x: __mmEnemy.x + __mmVelocityX * __mmLeadMs,
    y: __mmEnemy.y + __mmVelocityY * __mmLeadMs,
    velocityX: __mmVelocityX,
    velocityY: __mmVelocityY,
  };
}
function __mmSegmentDistanceSquared(
  __mmStartX,
  __mmStartY,
  __mmEndX,
  __mmEndY,
  __mmPointX,
  __mmPointY,
) {
  const __mmPathX = __mmEndX - __mmStartX,
    __mmPathY = __mmEndY - __mmStartY,
    __mmLengthSquared = __mmPathX * __mmPathX + __mmPathY * __mmPathY;
  if (__mmLengthSquared <= 1e-6)
    return (
      (__mmPointX - __mmStartX) ** 2 + (__mmPointY - __mmStartY) ** 2
    );
  const __mmProgress = Math.max(
      0,
      Math.min(
        1,
        ((__mmPointX - __mmStartX) * __mmPathX +
          (__mmPointY - __mmStartY) * __mmPathY) /
          __mmLengthSquared,
      ),
    ),
    __mmClosestX = __mmStartX + __mmPathX * __mmProgress,
    __mmClosestY = __mmStartY + __mmPathY * __mmProgress;
  return (
    (__mmPointX - __mmClosestX) ** 2 +
    (__mmPointY - __mmClosestY) ** 2
  );
}
function __mmSpikeOwnedByUsOrAlly(__mmSpike) {
  if (!v || !v.alive || !__mmSpike || !__mmSpike.owner) return !1;
  const __mmOwner = __mmSpike.owner,
    __mmOwnerSid = __mmOwner.sid;
  if (
    __mmOwner === v ||
    (__mmOwnerSid != null && String(__mmOwnerSid) === String(v.sid))
  )
    return !0;
  const __mmOwnerPlayer =
    __mmOwnerSid != null && typeof Rt === "function" ? Rt(__mmOwnerSid) : null;
  return __mmSameTeam(__mmOwnerPlayer || __mmOwner);
}
function __mmEnemyWillHitSpikeNextTick(__mmEnemy, __mmPrediction) {
  if (!Array.isArray(ge)) return !1;
  const __mmSpeedSquared =
    __mmPrediction.velocityX * __mmPrediction.velocityX +
    __mmPrediction.velocityY * __mmPrediction.velocityY;
  if (__mmSpeedSquared <= 1e-6) return !1;
  for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
    const __mmSpike = ge[__mmIndex],
      __mmData = __mmSpike && b.list && b.list[__mmSpike.id],
      __mmName = String(__mmData && __mmData.name || "").toLowerCase();
    if (
      !__mmSpike ||
      !__mmSpike.active ||
      !__mmSpike.isItem ||
      !__mmName.includes("spikes") ||
      !__mmSpikeOwnedByUsOrAlly(__mmSpike) ||
      !__mmSpikeHostileToEnemy(__mmSpike, __mmEnemy)
    )
      continue;
    const __mmCollisionRadius =
        (Number(__mmEnemy.scale) || 35) +
        (Number(__mmSpike.scale) || Number(__mmData.scale) || 45),
      __mmCurrentDistanceSquared =
        (__mmEnemy.x - __mmSpike.x) ** 2 +
        (__mmEnemy.y - __mmSpike.y) ** 2,
      __mmPredictedDistanceSquared =
        (__mmPrediction.x - __mmSpike.x) ** 2 +
        (__mmPrediction.y - __mmSpike.y) ** 2,
      __mmPathDistanceSquared = __mmSegmentDistanceSquared(
        __mmEnemy.x,
        __mmEnemy.y,
        __mmPrediction.x,
        __mmPrediction.y,
        __mmSpike.x,
        __mmSpike.y,
      );
    if (
      __mmPredictedDistanceSquared < __mmCurrentDistanceSquared &&
      __mmPathDistanceSquared <= __mmCollisionRadius * __mmCollisionRadius
    )
      return !0;
  }
  return !1;
}
function __mmFullInstaReadyFor(__mmEnemy) {
  if (
    !v ||
    !v.alive ||
    !__mmEnemy ||
    __mmInsta.state !== "idle" ||
    !__mmInsta.runtimeReady() ||
    __mmInsta.isPriorityConflict() ||
    !v.skins ||
    !v.skins[7] ||
    !v.skins[__mmTurretGear] ||
    !__mmInsta.turretReady()
  )
    return !1;
  const __mmPrimary = __mmInsta.supportedPrimary(),
    __mmSecondary = v.weapons && v.weapons[1],
    __mmSecondaryData = __mmInsta.weaponData(__mmSecondary);
  return !!(
    __mmPrimary != null &&
    __mmIsEnemyPlayer(__mmEnemy) &&
    __mmInsta.inRange(__mmPrimary, __mmEnemy) &&
    __mmWeaponReady(__mmPrimary) &&
    __mmSecondary != null &&
    __mmSecondary !== __mmPrimary &&
    __mmSecondary !== __mmShieldWeapon &&
    __mmSecondaryData &&
    !__mmSecondaryData.shield &&
    __mmWeaponReady(__mmSecondary)
  );
}
function __mmSpikeTickStrikeReady(__mmEnemy, __mmPrediction) {
  if (
    !__mmAutoSpikeInstaEnabled ||
    !v ||
    !v.alive ||
    !__mmEnemy ||
    !__mmPrediction ||
    __mmSpikeTickStrikeTimer ||
    __mmInsta.isActive() ||
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmTrapAttackActive ||
    __mmBoostBreakHeld ||
    __mmBuildSpamTimer ||
    __mmFoodSpamTimer ||
    __mmShieldDefenseTimer ||
    __mmIsTrapped() ||
    !(
      __mmActionAvailable("spikeTickStrike") ||
      __mmActionOwner === "weaponRecharge" ||
      __mmActionOwner === "matThief" ||
      __mmActionOwner === "mobSteal" ||
      __mmActionOwner === "instaSync"
    )
  )
    return !1;
  const __mmPrimary = __mmInsta.supportedPrimary(),
    __mmPredictedTarget = {
      x: __mmPrediction.x,
      y: __mmPrediction.y,
      scale: __mmEnemy.scale,
    };
  return !!(
    __mmPrimary != null &&
    __mmWeaponReady(__mmPrimary) &&
    __mmInsta.inRange(__mmPrimary, __mmPredictedTarget)
  );
}
function __mmStopSpikeTickStrike(__mmReason) {
  const __mmTool = __mmSpikeTickStrikeTool,
    __mmHat = __mmSpikeTickStrikeHat,
    __mmRestore = __mmActionMayRestore("spikeTickStrike");
  (__mmSpikeTickStrikeTimer && clearTimeout(__mmSpikeTickStrikeTimer),
    (__mmSpikeTickStrikeTimer = 0),
    __mmSpikeTickStrikeHeld && O.send("F", 0, __mmSpikeTickStrikeAimAngle),
    (__mmSpikeTickStrikeHeld = !1),
    (__mmSpikeTickStrikeTool = null),
    (__mmSpikeTickStrikeHat = null),
    (__mmSpikeTickStrikeAimAngle = null),
    __mmRestore && __mmHat != null && __mmEquipHatNow(__mmHat, !0),
    __mmRestore && __mmRestoreTool(__mmTool),
    __mmActionRelease(
      "spikeTickStrike",
      __mmReason || "predicted spike strike complete",
    ),
    v && v.alive && __mmUpdateWeaponRecharge());
}
function __mmStartSpikeTickStrike(__mmEnemy, __mmPrediction) {
  if (!__mmSpikeTickStrikeReady(__mmEnemy, __mmPrediction)) return !1;
  (__mmActionOwner === "instaSync" && __mmStopInstaSync(),
    __mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0),
    __mmActionOwner === "matThief" &&
      __mmFinishMatThief("predicted spike strike"),
    __mmActionOwner === "mobSteal" &&
      __mmFinishMobSteal("predicted spike strike"));
  if (!__mmActionClaim("spikeTickStrike", "predicted allied-spike contact"))
    return !1;
  const __mmPrimary = __mmInsta.supportedPrimary(),
    __mmAngle = Math.atan2(__mmPrediction.y - v.y, __mmPrediction.x - v.x);
  if (__mmPrimary == null)
    return (__mmActionRelease("spikeTickStrike", "primary unavailable"), !1);
  ((__mmSpikeTickStrikeTool = __mmSelectedTool()),
    (__mmSpikeTickStrikeHat = v.skinIndex),
    (__mmSpikeTickStrikeAimAngle = __mmAngle),
    __mmInsta.turretReady() && __mmEquipHatNow(__mmTurretGear),
    O.send("D", __mmAngle),
    je(__mmPrimary, !0),
    O.send("F", 1, __mmAngle),
    (__mmSpikeTickStrikeHeld = !0),
    (__mmSpikeTickStrikeTimer = setTimeout(function () {
      __mmStopSpikeTickStrike("predicted spike strike complete");
    }, __mmServerTickMs())));
  return !0;
}
function __mmUpdateAutoSpikeInsta() {
  const __mmNow = Date.now(),
    __mmSeen = Object.create(null);
  if (!__mmAutoSpikeInstaEnabled || !v || !v.alive || !Array.isArray(E)) return;
  for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
    const __mmEnemy = E[__mmIndex];
    if (!__mmIsEnemyPlayer(__mmEnemy)) continue;
    const __mmSid = String(__mmEnemy.sid),
      __mmPrediction = __mmPredictEnemyNextTick(__mmEnemy, __mmNow);
    __mmSeen[__mmSid] = !0;
    if (
      __mmNow - __mmAutoSpikeInstaLastAt >= __mmServerTickMs() &&
      __mmEnemyWillHitSpikeNextTick(__mmEnemy, __mmPrediction) &&
      __mmStartSpikeTickStrike(__mmEnemy, __mmPrediction)
    ) {
      __mmAutoSpikeInstaLastAt = __mmNow;
      return;
    }
  }
  for (const __mmSid in __mmAutoSpikeInstaMotion)
    __mmSeen[__mmSid] || delete __mmAutoSpikeInstaMotion[__mmSid];
}
function __mmStartAutoSpikeInsta() {
  __mmAutoSpikeInstaTimer ||
    (__mmAutoSpikeInstaTimer = setInterval(__mmUpdateAutoSpikeInsta, 5));
}
function __mmAutoSpikeSpamGhostStillRelevant() {
  const __mmGhost = __mmAutoSpikeSpamGhost;
  if (!__mmGhost || __mmGhost.targetSid == null || !v || !v.alive)
    return !1;
  let __mmEnemy = null;
  try {
    __mmEnemy = Rt(__mmGhost.targetSid);
  } catch (__mmLookupError) {}
  return !!(
    __mmIsEnemyPlayer(__mmEnemy) &&
    __mmAutoSpikeSpamTrapForEnemy(__mmEnemy)
  );
}
function __mmAutoSpikeSpamResetCandidate(__mmForceGhostClear) {
  ((__mmForceGhostClear || !__mmAutoSpikeSpamGhostStillRelevant()) &&
    (__mmAutoSpikeSpamGhost = null),
    (__mmAutoSpikeSpamCandidateKey = null),
    (__mmAutoSpikeSpamCandidateSince = 0));
}
function __mmAutoSpikeSpamCleanReservations(__mmNow) {
  for (let __mmIndex = __mmAutoSpikeSpamReservations.length - 1; __mmIndex >= 0; __mmIndex--)
    __mmAutoSpikeSpamReservations[__mmIndex].expiresAt <= __mmNow &&
      __mmAutoSpikeSpamReservations.splice(__mmIndex, 1);
}
function __mmAutoSpikeSpamHasCapacity(__mmSpike) {
  const __mmData = b && b.list && b.list[__mmSpike];
  if (
    __mmSpike == null ||
    !__mmData ||
    !__mmData.group ||
    !__mmCanUseBuildItem(__mmSpike) ||
    __mmMaxBuildCount(__mmSpike) < 1
  )
    return !1;
  const __mmLimit = y.inSandbox
      ? __mmData.group.sandboxLimit || Math.max(__mmData.group.limit * 3, 99)
      : __mmData.group.limit,
    __mmPlaced = Number(v.itemCounts && v.itemCounts[__mmData.group.id]) || 0;
  return !__mmLimit ||
    __mmPlaced + __mmAutoSpikeSpamReservations.length < __mmLimit;
}
function __mmAutoSpikeSpamTrapForEnemy(__mmEnemy) {
  if (!__mmEnemy || !Array.isArray(ge)) return null;
  let __mmClosest = null,
    __mmClosestDistance = Infinity;
  for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
    const __mmTrap = ge[__mmIndex];
    if (
      !__mmTrap ||
      !__mmTrap.active ||
      !__mmTrap.trap ||
      !__mmSpikeHostileToEnemy(__mmTrap, __mmEnemy)
    )
      continue;
    const __mmTrapCollisionScale =
        typeof __mmTrap.getScale === "function"
          ? Number(__mmTrap.getScale()) || 0
          : (Number(__mmTrap.scale) || 50) * (Number(__mmTrap.colDiv) || 1),
      __mmDistance = Math.hypot(
        __mmEnemy.x - __mmTrap.x,
        __mmEnemy.y - __mmTrap.y,
      ),
      // Allow for a little dangling/jitter around the trap edge. Hostility and
      // active-trap checks still prevent unrelated structures from qualifying.
      __mmLockRange =
        (Number(__mmEnemy.scale) || 35) + __mmTrapCollisionScale + 14;
    if (__mmDistance <= __mmLockRange && __mmDistance < __mmClosestDistance) {
      ((__mmClosest = __mmTrap), (__mmClosestDistance = __mmDistance));
    }
  }
  return __mmClosest;
}
function __mmAutoSpikeSpamTarget() {
  if (!v || !v.alive || !Array.isArray(E)) return null;
  let __mmClosest = null,
    __mmClosestDistance = Infinity;
  for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
    const __mmEnemy = E[__mmIndex];
    if (!__mmIsEnemyPlayer(__mmEnemy)) continue;
    const __mmTrap = __mmAutoSpikeSpamTrapForEnemy(__mmEnemy);
    if (!__mmTrap) continue;
    const __mmDistance = Math.hypot(__mmEnemy.x - v.x, __mmEnemy.y - v.y);
    if (__mmDistance < __mmClosestDistance) {
      ((__mmClosest = { enemy: __mmEnemy, trap: __mmTrap }),
        (__mmClosestDistance = __mmDistance));
    }
  }
  return __mmClosest;
}
function __mmAutoSpikeSpamObjectScale(__mmObject) {
  if (!__mmObject) return 0;
  if (Number(__mmObject.blocker) > 0) return Number(__mmObject.blocker);
  if (typeof __mmObject.getScale === "function") {
    // Match the server's checkItemLocation scale arguments for a normal build.
    const __mmScale = Number(__mmObject.getScale(0.6, !!__mmObject.isItem));
    if (Number.isFinite(__mmScale) && __mmScale > 0) return __mmScale;
  }
  return Number(__mmObject.scale) || 0;
}
function __mmAutoSpikeSpamPositionClear(__mmX, __mmY, __mmSpikeScale) {
  if (
    __mmX - __mmSpikeScale < 0 ||
    __mmY - __mmSpikeScale < 0 ||
    __mmX + __mmSpikeScale > y.mapScale ||
    __mmY + __mmSpikeScale > y.mapScale ||
    (__mmY >= y.mapScale / 2 - y.riverWidth / 2 &&
      __mmY <= y.mapScale / 2 + y.riverWidth / 2)
  )
    return !1;
  for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
    const __mmObject = ge[__mmIndex];
    if (!__mmObject || !__mmObject.active) continue;
    const __mmObjectScale = __mmAutoSpikeSpamObjectScale(__mmObject),
      // Match the game's collision boundary instead of adding a stricter
      // two-pixel buffer around every nearby structure.
      __mmMinimum = __mmSpikeScale + __mmObjectScale;
    if (
      (__mmObject.x - __mmX) ** 2 + (__mmObject.y - __mmY) ** 2 <
      __mmMinimum * __mmMinimum
    )
      return !1;
  }
  for (let __mmIndex = 0; __mmIndex < __mmAutoSpikeSpamReservations.length; __mmIndex++) {
    const __mmReservation = __mmAutoSpikeSpamReservations[__mmIndex],
      __mmMinimum = __mmSpikeScale + __mmReservation.scale;
    if (
      (__mmReservation.x - __mmX) ** 2 +
        (__mmReservation.y - __mmY) ** 2 <
      __mmMinimum * __mmMinimum
    )
      return !1;
  }
  return !0;
}
function __mmAutoSpikeSpamPredictionLead() {
  const __mmPing = Number(window.pingTime);
  return Math.max(
    10,
    Math.min(
      65,
      __mmServerTickMs() * 0.16 +
        (Number.isFinite(__mmPing) ? Math.max(0, __mmPing) * 0.5 : 0),
    ),
  );
}
function __mmAutoSpikeSpamPredictedEnemy(__mmTarget, __mmNow) {
  const __mmEnemy = __mmTarget && __mmTarget.enemy,
    __mmTrap = __mmTarget && __mmTarget.trap;
  if (!__mmEnemy) return null;
  const __mmKey = String(__mmEnemy.sid),
    __mmPrevious = __mmAutoSpikeSpamMotion[__mmKey],
    __mmMoved = !!(
      __mmPrevious &&
      Math.hypot(
        __mmEnemy.x - __mmPrevious.x,
        __mmEnemy.y - __mmPrevious.y,
      ) > 0.001
    ),
    // Only advance the sample clock when the coordinates actually change.
    // The solver runs every 5 ms, while player coordinates commonly update
    // once per render/server step; advancing it on identical scans creates a
    // false, extremely high velocity on the next real update.
    __mmSampleElapsed = __mmMoved
      ? Math.max(1, Math.min(250, __mmNow - __mmPrevious.sampleAt))
      : 0,
    __mmSampleFresh = !!(
      __mmPrevious &&
      __mmNow - __mmPrevious.sampleAt <= 250
    ),
    __mmSampleVelocityX = __mmMoved
      ? (__mmEnemy.x - __mmPrevious.x) / __mmSampleElapsed
      : __mmSampleFresh
        ? __mmPrevious.sampleVelocityX
        : 0,
    __mmSampleVelocityY = __mmMoved
      ? (__mmEnemy.y - __mmPrevious.y) / __mmSampleElapsed
      : __mmSampleFresh
        ? __mmPrevious.sampleVelocityY
        : 0,
    __mmServerElapsed = Number(__mmEnemy.t2) - Number(__mmEnemy.t1),
    __mmServerVelocityX =
      (Number(__mmEnemy.x2) - Number(__mmEnemy.x1)) / __mmServerElapsed,
    __mmServerVelocityY =
      (Number(__mmEnemy.y2) - Number(__mmEnemy.y1)) / __mmServerElapsed,
    __mmHasServerVelocity = !!(
      Number.isFinite(__mmServerVelocityX) &&
      Number.isFinite(__mmServerVelocityY) &&
      __mmServerElapsed > 0 &&
      __mmServerElapsed <= 500
    );
  let __mmVelocityX = __mmHasServerVelocity
      ? __mmServerVelocityX * 0.68 + __mmSampleVelocityX * 0.32
      : __mmSampleVelocityX,
    __mmVelocityY = __mmHasServerVelocity
      ? __mmServerVelocityY * 0.68 + __mmSampleVelocityY * 0.32
      : __mmSampleVelocityY;
  if (__mmPrevious) {
    ((__mmVelocityX = __mmVelocityX * 0.72 + __mmPrevious.velocityX * 0.28),
      (__mmVelocityY = __mmVelocityY * 0.72 + __mmPrevious.velocityY * 0.28));
  }
  __mmAutoSpikeSpamMotion[__mmKey] = {
    x: __mmMoved || !__mmPrevious ? __mmEnemy.x : __mmPrevious.x,
    y: __mmMoved || !__mmPrevious ? __mmEnemy.y : __mmPrevious.y,
    sampleAt:
      __mmMoved || !__mmPrevious ? __mmNow : __mmPrevious.sampleAt,
    sampleVelocityX: __mmSampleVelocityX,
    sampleVelocityY: __mmSampleVelocityY,
    velocityX: __mmVelocityX,
    velocityY: __mmVelocityY,
  };
  const __mmLeadMs = __mmAutoSpikeSpamPredictionLead(),
    __mmRawLeadX = __mmVelocityX * __mmLeadMs,
    __mmRawLeadY = __mmVelocityY * __mmLeadMs,
    __mmLeadDistance = Math.hypot(__mmRawLeadX, __mmRawLeadY),
    __mmLeadScale = __mmLeadDistance > 14 ? 14 / __mmLeadDistance : 1;
  let __mmX = __mmEnemy.x + __mmRawLeadX * __mmLeadScale,
    __mmY = __mmEnemy.y + __mmRawLeadY * __mmLeadScale;
  if (__mmTrap) {
    const __mmTrapScale =
        typeof __mmTrap.getScale === "function"
          ? Number(__mmTrap.getScale()) || Number(__mmTrap.scale) || 50
          : Number(__mmTrap.scale) || 50,
      __mmLockRadius = (Number(__mmEnemy.scale) || 35) + __mmTrapScale + 14,
      __mmTrapDx = __mmX - __mmTrap.x,
      __mmTrapDy = __mmY - __mmTrap.y,
      __mmTrapDistance = Math.hypot(__mmTrapDx, __mmTrapDy);
    if (__mmTrapDistance > __mmLockRadius && __mmTrapDistance > 0) {
      ((__mmX = __mmTrap.x + (__mmTrapDx / __mmTrapDistance) * __mmLockRadius),
        (__mmY = __mmTrap.y + (__mmTrapDy / __mmTrapDistance) * __mmLockRadius));
    }
  }
  return {
    x: __mmX,
    y: __mmY,
    scale: __mmEnemy.scale,
    sid: __mmEnemy.sid,
  };
}
function __mmAutoSpikeSpamPredictedOrigin() {
  if (!v || !v.alive) return null;
  let __mmVelocityX = Number(
      __mmPassiveSpikeMotion && __mmPassiveSpikeMotion.velocityX,
    ) || 0,
    __mmVelocityY = Number(
      __mmPassiveSpikeMotion && __mmPassiveSpikeMotion.velocityY,
    ) || 0;
  const __mmServerElapsed = Number(v.t2) - Number(v.t1),
    __mmServerVelocityX = (Number(v.x2) - Number(v.x1)) / __mmServerElapsed,
    __mmServerVelocityY = (Number(v.y2) - Number(v.y1)) / __mmServerElapsed;
  if (
    Number.isFinite(__mmServerVelocityX) &&
    Number.isFinite(__mmServerVelocityY) &&
    __mmServerElapsed > 0 &&
    __mmServerElapsed <= 500
  ) {
    ((__mmVelocityX = __mmVelocityX * 0.35 + __mmServerVelocityX * 0.65),
      (__mmVelocityY = __mmVelocityY * 0.35 + __mmServerVelocityY * 0.65));
  }
  const __mmLeadMs = __mmAutoSpikeSpamPredictionLead(),
    __mmLeadX = __mmVelocityX * __mmLeadMs,
    __mmLeadY = __mmVelocityY * __mmLeadMs,
    __mmDistance = Math.hypot(__mmLeadX, __mmLeadY),
    __mmScale = __mmDistance > 10 ? 10 / __mmDistance : 1;
  return {
    x: v.x + __mmLeadX * __mmScale,
    y: v.y + __mmLeadY * __mmScale,
  };
}
function __mmAutoSpikeSpamCandidate(__mmTarget, __mmSpike) {
  if (!__mmTarget || !v) return null;
  const __mmNow = Date.now(),
    __mmEnemy = __mmAutoSpikeSpamPredictedEnemy(__mmTarget, __mmNow),
    __mmOrigin = __mmAutoSpikeSpamPredictedOrigin(),
    __mmData = b.list[__mmSpike],
    __mmSpikeScale = Number(__mmData.scale) || 49,
    __mmPlacementRadius =
      (Number(v.scale) || 35) +
      __mmSpikeScale +
      (Number(__mmData.placeOffset) || 0),
    __mmTouchRadius =
      (Number(__mmEnemy.scale) || 35) + __mmSpikeScale - 2,
    __mmTargetDx = __mmEnemy.x - __mmOrigin.x,
    __mmTargetDy = __mmEnemy.y - __mmOrigin.y,
    __mmTargetDistance = Math.hypot(__mmTargetDx, __mmTargetDy);
  if (
    __mmTargetDistance <= 1e-6 ||
    __mmTargetDistance > __mmPlacementRadius + __mmTouchRadius + 10 ||
    __mmTargetDistance < Math.abs(__mmPlacementRadius - __mmTouchRadius) - 10
  )
    return null;
  const __mmBaseAngle = Math.atan2(__mmTargetDy, __mmTargetDx),
    __mmCosOffset = Math.max(
      -1,
      Math.min(
        1,
        (__mmPlacementRadius * __mmPlacementRadius +
          __mmTargetDistance * __mmTargetDistance -
          __mmTouchRadius * __mmTouchRadius) /
          (2 * __mmPlacementRadius * __mmTargetDistance),
      ),
    ),
    __mmIntersectionOffset = Math.acos(__mmCosOffset),
    __mmSeeds = [
      __mmBaseAngle - __mmIntersectionOffset,
      __mmBaseAngle + __mmIntersectionOffset,
    ];
  let __mmBest = null,
    __mmBestScore = Infinity;
  for (let __mmSeedIndex = 0; __mmSeedIndex < __mmSeeds.length; __mmSeedIndex++) {
    let __mmSeedFound = !1;
    for (let __mmStep = 0; __mmStep <= 140 && !__mmSeedFound; __mmStep++) {
      const __mmOffset = __mmStep * 0.0025,
        __mmSigns = __mmStep === 0 ? [0] : [-1, 1];
      for (
        let __mmSignIndex = 0;
        __mmSignIndex < __mmSigns.length;
        __mmSignIndex++
      ) {
        const __mmSignedOffset = __mmOffset * __mmSigns[__mmSignIndex],
          __mmAngle = __mmSeeds[__mmSeedIndex] + __mmSignedOffset,
          __mmX = __mmOrigin.x + Math.cos(__mmAngle) * __mmPlacementRadius,
          __mmY = __mmOrigin.y + Math.sin(__mmAngle) * __mmPlacementRadius,
          __mmEnemyDistance = Math.hypot(
            __mmX - __mmEnemy.x,
            __mmY - __mmEnemy.y,
          ),
          __mmTouchError = Math.abs(__mmEnemyDistance - __mmTouchRadius);
        if (
          __mmEnemyDistance > __mmTouchRadius + 4 ||
          __mmEnemyDistance < __mmTouchRadius - 9 ||
          !__mmAutoSpikeSpamPositionClear(__mmX, __mmY, __mmSpikeScale)
        )
          continue;
        const __mmScore =
          __mmTouchError * 12 + Math.abs(__mmSignedOffset) * 2;
        if (__mmScore < __mmBestScore) {
          ((__mmBestScore = __mmScore),
            (__mmBest = {
              item: __mmSpike,
              x: __mmX,
              y: __mmY,
              angle: __mmAngle,
              scale: __mmSpikeScale,
              targetSid: __mmEnemy.sid,
            }));
        }
        __mmSeedFound = !0;
      }
    }
  }
  return __mmBest;
}
function __mmPlaceAutoSpikeSpam(__mmCandidate, __mmNow) {
  if (
    !__mmCandidate ||
    __mmHoldingMcGrabby() ||
    !__mmAutoSpikeSpamHasCapacity(__mmCandidate.item) ||
    !__mmActionClaim("spikeSpam", "trapped enemy edge")
  )
    return !1;
  const __mmTool = __mmSelectedTool();
  try {
    ((__mmAutoSpikeSpamAimAngle = __mmCandidate.angle),
      (__mmAutoSpikeSpamAimUntil = __mmNow + __mmServerTickMs()),
      O.send("D", __mmCandidate.angle),
      je(__mmCandidate.item),
      O.send("F", 1, __mmCandidate.angle),
      O.send("F", 0, __mmCandidate.angle),
      __mmRestoreTool(__mmTool),
      __mmAutoSpikeSpamReservations.push({
        x: __mmCandidate.x,
        y: __mmCandidate.y,
        scale: __mmCandidate.scale,
        expiresAt: __mmNow + 650,
      }),
      (__mmAutoSpikeSpamLastAt = __mmNow),
      __mmActionRelease("spikeSpam", "spike placed"),
      __mmAutoSpikeSpamResetCandidate());
    return !0;
  } catch (__mmSpikeSpamError) {
    (__mmActionRelease("spikeSpam", "placement failed"),
      __mmAutoSpikeSpamResetCandidate());
    return !1;
  }
}
function __mmAutoSpikeSpamCanPlaceNow() {
  return !!(
    v &&
    v.alive &&
    !v.lockMove &&
    !__mmInsta.isActive() &&
    !__mmPrimaryHeld &&
    !__mmSecondaryHeld &&
    !__mmTrapAttackActive &&
    !__mmBoostBreakHeld &&
    !__mmBuildSpamTimer &&
    !__mmFoodSpamTimer &&
    (__mmActionAvailable("spikeSpam") ||
      __mmActionOwner === "weaponRecharge" ||
      __mmActionOwner === "matThief" ||
      __mmActionOwner === "mobSteal")
  );
}
function __mmUpdateAutoSpikeSpam() {
  const __mmNow = Date.now();
  __mmAutoSpikeSpamCleanReservations(__mmNow);
  if (
    !__mmAutoSpikeSpamEnabled ||
    !v ||
    !v.alive
  )
    return void __mmAutoSpikeSpamResetCandidate(!0);
  const __mmSpike = __mmSpikeItem();
  if (!__mmAutoSpikeSpamHasCapacity(__mmSpike))
    return void __mmAutoSpikeSpamResetCandidate();
  const __mmTarget = __mmAutoSpikeSpamTarget(),
    __mmCandidate = __mmAutoSpikeSpamCandidate(__mmTarget, __mmSpike);
  if (!__mmCandidate) return void __mmAutoSpikeSpamResetCandidate();
  __mmAutoSpikeSpamGhost = __mmCandidate;
  const __mmKey =
    String(__mmCandidate.targetSid) + ":" +
    Math.round(__mmCandidate.x / 3) + ":" +
    Math.round(__mmCandidate.y / 3);
  if (__mmKey !== __mmAutoSpikeSpamCandidateKey) {
    ((__mmAutoSpikeSpamCandidateKey = __mmKey),
      (__mmAutoSpikeSpamCandidateSince = __mmNow));
  }
  // Previewing is independent from action ownership. Keep drawing the legal
  // non-colliding position while a click, insta, or reload temporarily blocks
  // placement instead of erasing the ghost every 10ms. After placement, the
  // last valid ghost remains pinned until this target is no longer trapped.
  if (!__mmAutoSpikeSpamCanPlaceNow()) return;
  if (
    __mmNow - __mmAutoSpikeSpamLastAt >=
      Math.max(5, Math.min(10, __mmServerTickMs() * 0.08))
  ) {
    __mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
    __mmActionOwner === "matThief" &&
      __mmFinishMatThief("trapped-player spike priority");
    __mmActionOwner === "mobSteal" &&
      __mmFinishMobSteal("trapped-player spike priority");
    __mmPlaceAutoSpikeSpam(__mmCandidate, __mmNow);
  }
}
function __mmStartAutoSpikeSpam() {
  __mmAutoSpikeSpamTimer ||
    (__mmAutoSpikeSpamTimer = setInterval(__mmUpdateAutoSpikeSpam, 5));
}
function __mmStartFoodSpam() {
  __mmInsta.isActive() && __mmInsta.cancel("food-input");
  if (__mmFoodSpamTimer) return;
  (__mmUseFood(),
    (__mmFoodSpamTimer = setInterval(__mmUseFood, 1e3 / y.serverUpdateRate)));
}
function __mmStopFoodSpam() {
  __mmFoodSpamTimer &&
    (clearInterval(__mmFoodSpamTimer), (__mmFoodSpamTimer = 0));
}
function __mmUseBuild(__mmItemSlot) {
  if (!v || !v.alive) return;
  const __mmWeapon = __mmSelectedWeapon(),
    __mmItem = __mmItemSlot < 0 ? v.buildIndex : v.items[__mmItemSlot];
  if (__mmItem == null || __mmItem <= 0) return;
  (__mmItemSlot >= 0 && je(__mmItem),
    O.send("F", 1, Ci()),
    O.send("F", 0, Ci()),
    __mmRestoreWeapon(__mmWeapon));
}
function __mmUseBuildItem(__mmItem) {
  if (
    !v ||
    !v.alive ||
    __mmItem == null ||
    __mmItem <= 0 ||
    !__mmCanUseBuildItem(__mmItem)
  )
    return;
  const __mmWeapon = __mmSelectedWeapon();
  (je(__mmItem),
    O.send("F", 1, Ci()),
    O.send("F", 0, Ci()),
    __mmRestoreWeapon(__mmWeapon));
}
function __mmSpikeItem() {
  if (!v || !v.items) return null;
  for (let __mmItemIndex = 0; __mmItemIndex < v.items.length; __mmItemIndex++) {
    const __mmItem = v.items[__mmItemIndex],
      __mmData = b.list[__mmItem];
    if (
      __mmData &&
      typeof __mmData.name === "string" &&
      __mmData.name.indexOf("spikes") !== -1
    )
      return __mmItem;
  }
  return null;
}
function __mmLethalProjectileVolley() {
  if (!v || !v.alive || !Array.isArray(Ve)) return null;
  const __mmPlayerRadius = Number(v.scale) || 35,
    __mmHorizonMs = 650;
  let __mmDamage = 0,
    __mmFirstThreat = null,
    __mmFirstImpactMs = Infinity;
  for (
    let __mmProjectileIndex = 0;
    __mmProjectileIndex < Ve.length;
    __mmProjectileIndex++
  ) {
    const __mmProjectile = Ve[__mmProjectileIndex];
    if (!__mmProjectile || !__mmProjectile.active) continue;
    const __mmX = Number(__mmProjectile.x),
      __mmY = Number(__mmProjectile.y),
      __mmDirection = Number(__mmProjectile.dir),
      __mmSpeed = Number(__mmProjectile.speed),
      __mmDamageValue = Number(__mmProjectile.dmg);
    if (
      !Number.isFinite(__mmX) ||
      !Number.isFinite(__mmY) ||
      !Number.isFinite(__mmDirection) ||
      !Number.isFinite(__mmSpeed) ||
      __mmSpeed <= 0 ||
      !Number.isFinite(__mmDamageValue) ||
      __mmDamageValue <= 0
    )
      continue;
    const __mmToPlayerX = v.x - __mmX,
      __mmToPlayerY = v.y - __mmY,
      __mmForward =
        __mmToPlayerX * Math.cos(__mmDirection) +
        __mmToPlayerY * Math.sin(__mmDirection),
      __mmSide = Math.abs(
        __mmToPlayerX * Math.sin(__mmDirection) -
          __mmToPlayerY * Math.cos(__mmDirection),
      ),
      __mmHitRadius = __mmPlayerRadius + (Number(__mmProjectile.scale) || 0),
      __mmImpactMs = __mmForward / __mmSpeed,
      __mmRemainingRange = Number(__mmProjectile.range);
    if (
      __mmForward < 0 ||
      __mmSide > __mmHitRadius ||
      __mmImpactMs > __mmHorizonMs ||
      (Number.isFinite(__mmRemainingRange) &&
        __mmForward > __mmRemainingRange + __mmHitRadius)
    )
      continue;
    (__mmDamage += __mmDamageValue,
      __mmImpactMs < __mmFirstImpactMs &&
        ((__mmFirstImpactMs = __mmImpactMs),
          (__mmFirstThreat = __mmProjectile)));
  }
  return __mmFirstThreat && __mmDamage >= Number(v.health)
    ? {
        damage: __mmDamage,
        angle: Math.atan2(__mmFirstThreat.y - v.y, __mmFirstThreat.x - v.x),
      }
    : null;
}
function __mmCanUseAntiInsta() {
  return !!(
    __mmAntiInstaEnabled &&
    !__mmHoldingMcGrabby() &&
    __mmActionAvailable("antiInsta") &&
    v &&
    v.alive &&
    !__mmPrimaryHeld &&
    !__mmSecondaryHeld &&
    !__mmTrapAttackActive &&
    !__mmBoostBreakHeld &&
    !__mmBuildSpamTimer &&
    !__mmFoodSpamTimer &&
    !__mmShieldDefenseTimer
  );
}
function __mmPlaceAntiInstaSpike(__mmAngle) {
  if (__mmHoldingMcGrabby()) return !1;
  const __mmSpike = __mmSpikeItem();
  if (__mmSpike == null || !__mmCanUseBuildItem(__mmSpike)) return !1;
  const __mmTool = __mmSelectedTool();
  (je(__mmSpike),
    O.send("F", 1, __mmAngle),
    O.send("F", 0, __mmAngle),
    __mmRestoreTool(__mmTool));
  return !0;
}
function __mmUpdateAntiInsta() {
  if (
    !__mmAntiInstaEnabled ||
    !v ||
    !v.alive ||
    __mmHoldingMcGrabby()
  )
    return;
  const __mmNow = Date.now();
  if (__mmNow - __mmAntiInstaLastAt < 450) return;
  const __mmThreat = __mmLethalProjectileVolley();
  if (!__mmThreat) return;
  // A lethal volley takes priority over a queued combo, but we never switch
  // selection out from underneath a real held attack or another build action.
  __mmInsta.isActive() && __mmInsta.cancel("lethal-projectile");
  __mmInstaSyncPending || __mmInstaSyncFiring ? __mmStopInstaSync() : null;
  if (!__mmActionCanPreempt("antiInsta")) return;
  __mmActionOwner === "shieldDefense" &&
    __mmStopShieldDefense("lethal projectile priority");
  __mmBoostBreakHeld && __mmStopBoostBreak();
  __mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
  if (!__mmActionClaim("antiInsta", "lethal projectile")) return;
  if (!__mmCanUseAntiInsta())
    return void __mmActionRelease("antiInsta", "unsafe to place");
  if (!__mmPlaceAntiInstaSpike(__mmThreat.angle))
    return void __mmActionRelease("antiInsta", "no spike");
  ((__mmAntiInstaLastAt = __mmNow),
    (__mmAntiInstaUntil = __mmNow + Math.max(140, __mmServerTickMs())),
    __mmAntiInstaActionTimer && clearTimeout(__mmAntiInstaActionTimer),
    (__mmAntiInstaActionTimer = setTimeout(function () {
      ((__mmAntiInstaActionTimer = 0),
        __mmActionRelease("antiInsta", "threat window complete"));
    }, Math.max(140, __mmServerTickMs()))));
}
function __mmStartAntiInsta() {
  __mmAntiInstaTimer ||
    (__mmAntiInstaTimer = setInterval(__mmUpdateAntiInsta, 25));
}
function __mmProjectileTravelDistance(__mmFrom, __mmTarget) {
  return Math.max(
    0,
    Math.hypot(__mmTarget.x - __mmFrom.x, __mmTarget.y - __mmFrom.y) -
      (Number(__mmFrom.scale) || 35) -
      (Number(__mmTarget.scale) || 35),
  );
}
function __mmDirectFriendlyProjectileSource(__mmProjectile) {
  if (!v || !v.alive || !__mmProjectile || !__mmProjectile.owner) return null;
  const __mmOwner = __mmProjectile.owner,
    __mmOwnerSid = __mmOwner.sid;
  // A normal shot from this player should not recursively trigger another
  // sync shot. Personal structures are allowed through the nested owner path.
  if (
    __mmOwner === v ||
    (__mmOwnerSid != null && String(__mmOwnerSid) === String(v.sid))
  )
    return null;
  let __mmOwnerPlayer =
    __mmOwnerSid != null && typeof Rt === "function" ? Rt(__mmOwnerSid) : null;
  if (__mmSameTeam(__mmOwnerPlayer || __mmOwner))
    return __mmOwnerPlayer || __mmOwner;
  const __mmStructureOwner = __mmOwner.owner,
    __mmStructureOwnerSid = __mmStructureOwner && __mmStructureOwner.sid;
  if (!__mmStructureOwner) return null;
  if (String(__mmStructureOwnerSid) === String(v.sid)) return __mmOwner;
  __mmOwnerPlayer =
    __mmStructureOwnerSid != null && typeof Rt === "function"
      ? Rt(__mmStructureOwnerSid)
      : null;
  return __mmSameTeam(__mmOwnerPlayer || __mmStructureOwner)
    ? __mmOwner
    : null;
}
function __mmFriendlyProjectileSource(__mmProjectile) {
  if (!__mmProjectile || !Array.isArray(E)) return null;
  const __mmX = Number(__mmProjectile.x),
    __mmY = Number(__mmProjectile.y),
    __mmDirection = Number(__mmProjectile.dir);
  if (
    !Number.isFinite(__mmX) ||
    !Number.isFinite(__mmY) ||
    !Number.isFinite(__mmDirection)
  )
    return null;
  let __mmClosest = null,
    __mmClosestDistance = Infinity;
  for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
    const __mmPlayer = E[__mmIndex];
    if (
      !__mmPlayer ||
      !__mmPlayer.alive ||
      !__mmPlayer.visible ||
      !__mmSameTeam(__mmPlayer)
    )
      continue;
    const __mmDx = __mmX - __mmPlayer.x,
      __mmDy = __mmY - __mmPlayer.y,
      __mmDistance = Math.hypot(__mmDx, __mmDy),
      __mmForward =
        __mmDx * Math.cos(__mmDirection) +
        __mmDy * Math.sin(__mmDirection),
      __mmSide = Math.abs(
        __mmDx * Math.sin(__mmDirection) -
          __mmDy * Math.cos(__mmDirection),
      );
    if (
      __mmForward < -35 ||
      __mmSide > 125 ||
      __mmDistance > Math.max(320, (Number(__mmPlayer.scale) || 35) + 180) ||
      __mmDistance >= __mmClosestDistance
    )
      continue;
    ((__mmClosest = __mmPlayer), (__mmClosestDistance = __mmDistance));
  }
  return __mmClosest;
}
function __mmPersonalTurretProjectileSource(__mmProjectile) {
  if (!v || !v.alive || !__mmProjectile || !Array.isArray(ge)) return null;
  const __mmX = Number(__mmProjectile.x),
    __mmY = Number(__mmProjectile.y),
    __mmDirection = Number(__mmProjectile.dir);
  if (
    !Number.isFinite(__mmX) ||
    !Number.isFinite(__mmY) ||
    !Number.isFinite(__mmDirection)
  )
    return null;
  for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
    const __mmObject = ge[__mmIndex],
      __mmItem = __mmObject && b.list[__mmObject.id];
    if (
      !__mmObject ||
      !__mmObject.active ||
      !__mmItem ||
      String(__mmItem.name || "").toLowerCase() !== "turret" ||
      !__mmObject.owner
    )
      continue;
    const __mmOwnerSid = __mmObject.owner.sid,
      __mmOwnerPlayer =
        String(__mmOwnerSid) === String(v.sid)
          ? v
          : typeof Rt === "function"
            ? Rt(__mmOwnerSid)
            : null;
    if (
      String(__mmOwnerSid) !== String(v.sid) &&
      !__mmSameTeam(__mmOwnerPlayer || __mmObject.owner)
    )
      continue;
    const __mmDx = __mmX - __mmObject.x,
      __mmDy = __mmY - __mmObject.y,
      __mmDistance = Math.hypot(__mmDx, __mmDy),
      __mmForward =
        __mmDx * Math.cos(__mmDirection) +
        __mmDy * Math.sin(__mmDirection),
      __mmSide = Math.abs(
        __mmDx * Math.sin(__mmDirection) -
          __mmDy * Math.cos(__mmDirection),
      );
    if (
      __mmForward >= -35 &&
      __mmSide <= Math.max(150, Number(__mmObject.scale) || 0) &&
      __mmDistance <= Math.max(340, (Number(__mmObject.scale) || 45) + 200)
    )
      return __mmObject;
  }
  return null;
}
function __mmSyncPlayerVelocity(__mmPlayer) {
  if (!__mmPlayer) return { x: 0, y: 0 };
  const __mmElapsed = Number(__mmPlayer.t2) - Number(__mmPlayer.t1),
    __mmX =
      (Number(__mmPlayer.x2) - Number(__mmPlayer.x1)) / __mmElapsed,
    __mmY =
      (Number(__mmPlayer.y2) - Number(__mmPlayer.y1)) / __mmElapsed;
  return __mmElapsed > 0 &&
    __mmElapsed <= 500 &&
    Number.isFinite(__mmX) &&
    Number.isFinite(__mmY)
    ? { x: Math.max(-1.5, Math.min(1.5, __mmX)), y: Math.max(-1.5, Math.min(1.5, __mmY)) }
    : { x: 0, y: 0 };
}
function __mmProjectileEnemyTarget(__mmProjectile) {
  const __mmPlayers = __mmLiveStateFresh() ? __mmLiveState.enemies : E;
  if (!__mmProjectile || !Array.isArray(__mmPlayers)) return null;
  const __mmX = Number(__mmProjectile.x),
    __mmY = Number(__mmProjectile.y),
    __mmDirection = Number(__mmProjectile.dir),
    __mmSpeed = Number(__mmProjectile.speed),
    __mmRange = Number(__mmProjectile.range);
  if (
    !Number.isFinite(__mmX) ||
    !Number.isFinite(__mmY) ||
    !Number.isFinite(__mmDirection) ||
    !Number.isFinite(__mmSpeed) ||
    __mmSpeed <= 0
  )
    return null;
  let __mmTarget = null,
    __mmForwardBest = Infinity;
  for (let __mmIndex = 0; __mmIndex < __mmPlayers.length; __mmIndex++) {
    const __mmPlayer = __mmPlayers[__mmIndex];
    if (!__mmIsEnemyPlayer(__mmPlayer)) continue;
    let __mmDx = __mmPlayer.x - __mmX,
      __mmDy = __mmPlayer.y - __mmY,
      __mmForward =
        __mmDx * Math.cos(__mmDirection) +
        __mmDy * Math.sin(__mmDirection);
    const __mmVelocity = __mmSyncPlayerVelocity(__mmPlayer),
      __mmInitialArrival = Math.max(0, __mmForward) / __mmSpeed,
      __mmLead = Math.min(400, __mmInitialArrival);
    (__mmDx += __mmVelocity.x * __mmLead,
      __mmDy += __mmVelocity.y * __mmLead,
      (__mmForward =
        __mmDx * Math.cos(__mmDirection) +
        __mmDy * Math.sin(__mmDirection)));
    const __mmSide = Math.abs(
        __mmDx * Math.sin(__mmDirection) -
          __mmDy * Math.cos(__mmDirection),
      ),
      __mmHitRadius =
        (Number(__mmPlayer.scale) || 35) +
        (Number(__mmProjectile.scale) || 0) +
        18;
    if (
      __mmForward < 0 ||
      __mmSide > __mmHitRadius ||
      (Number.isFinite(__mmRange) && __mmForward > __mmRange + __mmHitRadius) ||
      __mmForward >= __mmForwardBest
    )
      continue;
    ((__mmTarget = __mmPlayer), (__mmForwardBest = __mmForward));
  }
  return __mmTarget
    ? {
        target: __mmTarget,
        arrivalMs: __mmForwardBest / __mmSpeed,
      }
    : null;
}
function __mmSyncProjectileWeapons(__mmTarget) {
  if (!v || !v.alive || !v.weapons || !__mmTarget) return [];
  const __mmDistance = __mmProjectileTravelDistance(v, __mmTarget);
  const __mmShots = [],
    __mmSeen = new Set();
  for (const __mmWeapon of [v.weapons[1], v.weapons[0]]) {
    if (__mmWeapon == null || __mmSeen.has(__mmWeapon)) continue;
    __mmSeen.add(__mmWeapon);
    const __mmWeaponData =
        b.weapons[__mmWeapon],
      __mmProjectile =
        __mmWeaponData && __mmWeaponData.projectile != null
          ? b.projectiles[__mmWeaponData.projectile]
          : null,
      __mmSpeed = __mmProjectile && Number(__mmProjectile.speed),
      __mmRange = __mmProjectile && Number(__mmProjectile.range);
    if (
      !__mmWeaponData ||
      !__mmProjectile ||
      !__mmWeaponReady(__mmWeapon) ||
      !Number.isFinite(__mmSpeed) ||
      __mmSpeed <= 0 ||
      !Number.isFinite(__mmRange) ||
      __mmDistance > __mmRange
    )
      continue;
    __mmShots.push({
      type: "projectile",
      weapon: __mmWeapon,
      // A weapon packet normally lands between server updates. Include half a
      // tick of launch latency so the arrival scheduler does not fire late.
      travelMs:
        Math.min(55, __mmServerTickMs() * 0.5) +
        __mmDistance / __mmSpeed,
    });
  }
  return __mmShots;
}
function __mmSyncTurretShot(__mmTarget) {
  if (
    !v ||
    !v.alive ||
    !__mmTarget ||
    !v.skins ||
    !v.skins[__mmTurretGear] ||
    !__mmInsta.turretReady()
  )
    return null;
  const __mmDistance = __mmProjectileTravelDistance(v, __mmTarget);
  if (__mmDistance > __mmTurretGearRange) return null;
  // Turret shots use the bullet travel profile. Account for one gear-apply
  // tick before its shot can leave the player.
  return {
    type: "turret",
    travelMs: __mmServerTickMs() + __mmDistance / 3.6,
  };
}
function __mmSyncShotsForTarget(__mmTarget) {
  const __mmTurret = __mmSyncTurretShot(__mmTarget);
  return (__mmTurret ? [__mmTurret] : []).concat(
    __mmSyncProjectileWeapons(__mmTarget),
  );
}
function __mmSyncAimAngle(__mmTarget, __mmTravelMs) {
  const __mmVelocity = __mmSyncPlayerVelocity(__mmTarget),
    __mmPing = Number(window.pingTime),
    __mmLead = Math.min(
      450,
      Math.max(0, Number(__mmTravelMs) || 0) +
        (Number.isFinite(__mmPing) ? Math.max(0, __mmPing / 2) : 0),
    ),
    __mmTargetX = __mmTarget.x + __mmVelocity.x * __mmLead,
    __mmTargetY = __mmTarget.y + __mmVelocity.y * __mmLead;
  return Math.atan2(__mmTargetY - v.y, __mmTargetX - v.x);
}
function __mmCanFireInstaSync() {
  return !!(
    __mmInstaSyncEnabled &&
    (__mmActionAvailable("instaSync") ||
      __mmActionOwner === "weaponRecharge" ||
      __mmActionOwner === "matThief" ||
      __mmActionOwner === "mobSteal") &&
    v &&
    v.alive &&
    !__mmInsta.isActive() &&
    !__mmPrimaryHeld &&
    !__mmSecondaryHeld &&
    !__mmTrapAttackActive &&
    !__mmBoostBreakHeld &&
    !__mmBuildSpamTimer &&
    !__mmFoodSpamTimer &&
    !__mmShieldDefenseTimer &&
    !__mmInstaSyncFiring
  );
}
function __mmFinishInstaSync() {
  const __mmTool = __mmInstaSyncRestoreTool,
    __mmHat = __mmInstaSyncRestoreHat,
    __mmRestore = __mmActionMayRestore("instaSync");
  (__mmInstaSyncReleaseTimer && clearTimeout(__mmInstaSyncReleaseTimer),
    (__mmInstaSyncReleaseTimer = 0),
    __mmInstaSyncWeaponHeld && O.send("F", 0, null),
    (__mmInstaSyncWeaponHeld = !1),
    (__mmInstaSyncRestoreTool = null),
    (__mmInstaSyncRestoreHat = null),
    (__mmInstaSyncFiring = !1),
    __mmRestore && __mmHat != null && __mmEquipHatNow(__mmHat),
    __mmRestore && __mmRestoreTool(__mmTool),
    __mmActionRelease("instaSync", "sync shot complete"));
}
function __mmStopInstaSync() {
  (__mmInstaSyncTimer && clearTimeout(__mmInstaSyncTimer),
    (__mmInstaSyncTimer = 0),
    (__mmInstaSyncPending = !1),
    __mmFinishInstaSync());
}
function __mmFireInstaSync(__mmShot, __mmTargetSid) {
  ((__mmInstaSyncTimer = 0), (__mmInstaSyncPending = !1));
  let __mmTarget = null;
  try {
    __mmTarget = Rt(__mmTargetSid);
  } catch (__mmLookupError) {}
  if (!__mmCanFireInstaSync() || !__mmIsEnemyPlayer(__mmTarget))
    return void __mmFinishInstaSync();
  const __mmAngle = __mmSyncAimAngle(__mmTarget, __mmShot.travelMs);
  ((__mmInstaSyncFiring = !0), (__mmInstaSyncLastAt = Date.now()));
  if (__mmShot.type === "turret") {
    ((__mmInstaSyncRestoreHat = v.skinIndex),
      __mmEquipHatNow(__mmTurretGear),
      O.send("D", __mmAngle),
      (__mmInstaSyncReleaseTimer = setTimeout(
        __mmFinishInstaSync,
        __mmServerTickMs(),
      )));
    return;
  }
  if (
    __mmShot.weapon == null ||
    !__mmWeaponReady(__mmShot.weapon) ||
    !v.weapons.includes(__mmShot.weapon)
  )
    return void __mmFinishInstaSync();
  ((__mmInstaSyncRestoreTool = __mmSelectedTool()),
    je(__mmShot.weapon, !0),
    O.send("D", __mmAngle),
    O.send("F", 1, __mmAngle),
    (__mmInstaSyncWeaponHeld = !0),
    (__mmInstaSyncReleaseTimer = setTimeout(
      __mmFinishInstaSync,
      __mmServerTickMs(),
    )));
}
function __mmScheduleInstaSync(__mmProjectile, __mmTargetInfo) {
  if (
    !__mmCanFireInstaSync() ||
    __mmInstaSyncPending ||
    Date.now() - __mmInstaSyncLastAt < 45
  )
    return !1;
  const __mmShots = __mmSyncShotsForTarget(__mmTargetInfo.target),
    __mmPing = Number(window.pingTime),
    __mmOneWayPing = Number.isFinite(__mmPing) ? Math.max(0, __mmPing / 2) : 0;
  let __mmChoice = null;
  for (let __mmIndex = 0; __mmIndex < __mmShots.length; __mmIndex++) {
    const __mmShot = __mmShots[__mmIndex],
      __mmRawDelay =
        __mmTargetInfo.arrivalMs - __mmShot.travelMs - __mmOneWayPing;
    // Do not schedule a shot that is already meaningfully too late. Among
    // viable shots, prefer the one that can leave soonest for less aim drift.
    if (__mmRawDelay < -35 || __mmRawDelay > 900) continue;
    const __mmDelay = Math.max(0, Math.round(__mmRawDelay));
    if (!__mmChoice || __mmDelay < __mmChoice.delay)
      __mmChoice = { shot: __mmShot, delay: __mmDelay };
  }
  if (!__mmChoice) return !1;
  if (!__mmActionClaim("instaSync", "friendly projectile")) return !1;
  ((__mmInstaSyncPending = !0),
    __mmChoice.delay <= 1
      ? __mmFireInstaSync(__mmChoice.shot, __mmTargetInfo.target.sid)
      : (__mmInstaSyncTimer = setTimeout(function () {
          __mmFireInstaSync(__mmChoice.shot, __mmTargetInfo.target.sid);
        }, __mmChoice.delay)));
  return !0;
}
function __mmUpdateInstaSync() {
  if (
    !__mmInstaSyncEnabled ||
    __mmInstaSyncPending ||
    __mmInstaSyncFiring ||
    !Array.isArray(Ve)
  )
    return;
  for (let __mmIndex = 0; __mmIndex < Ve.length; __mmIndex++) {
    const __mmProjectile = Ve[__mmIndex];
    if (!__mmProjectile) continue;
    const __mmSid = __mmProjectile.sid,
      __mmRange = Number(__mmProjectile.range),
      __mmPreviousState = __mmInstaSyncProjectileStates.get(__mmProjectile),
      __mmNewGeneration = !!(
        __mmProjectile.active &&
        (!__mmPreviousState ||
          !__mmPreviousState.active ||
          (__mmSid != null && String(__mmSid) !== __mmPreviousState.sid) ||
          (Number.isFinite(__mmRange) &&
            Number.isFinite(__mmPreviousState.range) &&
            __mmRange > __mmPreviousState.range + 20))
      ),
      __mmState = __mmNewGeneration
        ? {
            active: !0,
            handled: !1,
            sid: __mmSid == null ? "" : String(__mmSid),
            range: __mmRange,
          }
        : __mmPreviousState || {
            active: !!__mmProjectile.active,
            handled: !1,
            sid: __mmSid == null ? "" : String(__mmSid),
            range: __mmRange,
          };
    ((__mmState.active = !!__mmProjectile.active),
      (__mmState.range = __mmRange),
      __mmInstaSyncProjectileStates.set(__mmProjectile, __mmState));
    if (!__mmProjectile.active || __mmState.handled) continue;
    if (
      !__mmDirectFriendlyProjectileSource(__mmProjectile) &&
      !__mmFriendlyProjectileSource(__mmProjectile) &&
      !__mmPersonalTurretProjectileSource(__mmProjectile)
    )
      continue;
    const __mmTargetInfo = __mmProjectileEnemyTarget(__mmProjectile);
    if (!__mmTargetInfo) continue;
    if (__mmScheduleInstaSync(__mmProjectile, __mmTargetInfo)) {
      __mmState.handled = !0;
      return;
    }
  }
}
function __mmStartInstaSync() {
  __mmInstaSyncLoopTimer ||
    (__mmInstaSyncLoopTimer = setInterval(__mmUpdateInstaSync, 5));
}
function __mmMaxBuildCount(__mmItem) {
  const __mmData = b.list[__mmItem];
  if (!v || !__mmData || !__mmData.req) return 0;
  let __mmCount = Infinity;
  for (
    let __mmReqIndex = 0;
    __mmReqIndex < __mmData.req.length;
    __mmReqIndex += 2
  )
    __mmCount = Math.min(
      __mmCount,
      Math.floor(
        (v[__mmData.req[__mmReqIndex]] || 0) / __mmData.req[__mmReqIndex + 1],
      ),
    );
  return Number.isFinite(__mmCount) ? Math.max(0, __mmCount) : 0;
}
function __mmEnemyNearBoostPad(__mmPlayer) {
  if (!__mmPlayer || !__mmPlayer.alive) return !1;
  const __mmGrids = X.getGridArrays(__mmPlayer.x, __mmPlayer.y, 180);
  for (let __mmGridIndex = 0; __mmGridIndex < __mmGrids.length; __mmGridIndex++)
    for (
      let __mmItemIndex = 0;
      __mmItemIndex < __mmGrids[__mmGridIndex].length;
      __mmItemIndex++
    ) {
      const __mmObject = __mmGrids[__mmGridIndex][__mmItemIndex];
      if (!__mmObject.active || !__mmObject.boostSpeed) continue;
      const __mmRange = __mmPlayer.scale + __mmObject.scale + 80,
        __mmDx = __mmPlayer.x - __mmObject.x,
        __mmDy = __mmPlayer.y - __mmObject.y;
      if (__mmDx * __mmDx + __mmDy * __mmDy <= __mmRange * __mmRange) return !0;
    }
  return !1;
}
function __mmAntiBoostAngles(__mmAngle, __mmCount) {
  if (__mmCount <= 1) return [__mmAngle];
  return [__mmAngle - 0.46, __mmAngle + 0.46];
}
function __mmPlaceAntiBoostSpikes(__mmAngle) {
  // Boost-rush defense is the one automatic spike exception while Mc Grabby
  // is selected, matching the anti-boost insta safety path.
  if (__mmHoldingMcGrabby() && !__mmAntiBoostInstaEnabled) return 0;
  const __mmSpike = __mmSpikeItem(),
    __mmCount = Math.min(2, __mmMaxBuildCount(__mmSpike));
  if (__mmSpike == null || __mmCount < 1) return 0;
  const __mmTool = __mmSelectedTool(),
    __mmAngles = __mmAntiBoostAngles(__mmAngle, __mmCount);
  je(__mmSpike);
  for (let __mmIndex = 0; __mmIndex < __mmAngles.length; __mmIndex++)
    (O.send("F", 1, __mmAngles[__mmIndex]),
      O.send("F", 0, __mmAngles[__mmIndex]));
  (__mmRestoreTool(__mmTool), __mmResumeHeldAttack());
  return __mmAngles.length;
}
function __mmStopAntiBoostRetreat() {
  (__mmAntiBoostMoveTimer && clearTimeout(__mmAntiBoostMoveTimer),
    (__mmAntiBoostMoveTimer = 0));
  if (!__mmAntiBoostBackingUp) return;
  ((__mmAntiBoostBackingUp = !1), (Kt = null), Tt());
}
function __mmStopAntiBoostBlock(__mmReason) {
  const __mmTool = __mmAntiBoostBlockTool,
    __mmRestore = __mmActionMayRestore("antiBoostBlock");
  (__mmAntiBoostBlockTimer && clearTimeout(__mmAntiBoostBlockTimer),
    (__mmAntiBoostBlockTimer = 0),
    __mmStopAntiBoostRetreat(),
    (__mmAntiBoostBlockTool = null),
    (__mmAntiBoostBlockAimAngle = null),
    __mmRestore && __mmRestoreTool(__mmTool),
    __mmActionRelease(
      "antiBoostBlock",
      __mmReason || "boost block complete",
    ));
}
function __mmStartAntiBoostBlock(__mmEnemy) {
  if (
    !__mmAntiBoostEnabled ||
    !v ||
    !v.alive ||
    !__mmEnemy ||
    __mmAntiBoostBlockTimer
  )
    return !1;
  __mmActionOwner === "shieldDefense" &&
    __mmStopShieldDefense("boost block priority");
  if (!__mmActionClaim("antiBoostBlock", "boost-pad rush")) return !1;
  const __mmToward = Math.atan2(__mmEnemy.y - v.y, __mmEnemy.x - v.x),
    __mmAway = __mmToward + Math.PI,
    __mmWindow = Math.max(180, 3 * __mmServerTickMs());
  ((__mmAntiBoostBlockTool = __mmSelectedTool()),
    (__mmAntiBoostBlockAimAngle = __mmToward),
    __mmPlaceAntiBoostSpikes(__mmToward),
    O.send("D", __mmToward),
    O.send("9", __mmAway),
    (Kt = __mmAway),
    (__mmAntiBoostBackingUp = !0),
    v.weapons &&
      v.weapons.includes(__mmShieldWeapon) &&
      je(__mmShieldWeapon, !0),
    (__mmAntiBoostMoveTimer = setTimeout(
      __mmStopAntiBoostRetreat,
      Math.max(120, 2 * __mmServerTickMs()),
    )),
    (__mmAntiBoostBlockTimer = setTimeout(function () {
      __mmStopAntiBoostBlock("boost block complete");
    }, __mmWindow)));
  return !0;
}
function __mmUpdateAntiBoostSpikes() {
  // An active burst owns its complete primary -> turret -> secondary window.
  if (__mmInsta.isActive()) return;
  if (
    (!__mmAntiBoostEnabled && !__mmAntiBoostInstaEnabled) ||
    !v ||
    !v.alive ||
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmTrapAttackActive ||
    __mmBoostBreakHeld
  )
    return;
  const __mmNow = Date.now();
  for (let __mmPlayerIndex = 0; __mmPlayerIndex < E.length; __mmPlayerIndex++) {
    const __mmEnemy = E[__mmPlayerIndex];
    if (!__mmIsEnemyPlayer(__mmEnemy)) continue;
    const __mmSid = String(__mmEnemy.sid),
      __mmTrail =
        __mmEnemyBoostTrail[__mmSid] ||
        (__mmEnemyBoostTrail[__mmSid] = {
          x: __mmEnemy.x,
          y: __mmEnemy.y,
          time: __mmNow,
          boostAt: 0,
        }),
      __mmDx = __mmEnemy.x - __mmTrail.x,
      __mmDy = __mmEnemy.y - __mmTrail.y,
      __mmToPlayerX = v.x - __mmEnemy.x,
      __mmToPlayerY = v.y - __mmEnemy.y,
      __mmDistance =
        __mmToPlayerX * __mmToPlayerX + __mmToPlayerY * __mmToPlayerY;
    if (__mmEnemyNearBoostPad(__mmEnemy)) __mmTrail.boostAt = __mmNow;
    const __mmFreshBoost = __mmNow - __mmTrail.boostAt <= 700,
      __mmMovingToward =
        __mmDx * __mmDx + __mmDy * __mmDy > 0.25 &&
        __mmDx * __mmToPlayerX + __mmDy * __mmToPlayerY > 0;
    ((__mmTrail.x = __mmEnemy.x),
      (__mmTrail.y = __mmEnemy.y),
      (__mmTrail.time = __mmNow));
    if (
      __mmFreshBoost &&
      __mmDistance <= __mmAntiBoostRange * __mmAntiBoostRange &&
      __mmMovingToward
    ) {
      if (
        __mmAntiBoostInstaEnabled &&
        __mmFullInstaReadyFor(__mmEnemy) &&
        __mmInsta.start({ automatic: !0, targetSid: __mmEnemy.sid })
      ) {
        ((__mmAntiBoostLast = __mmNow), (__mmTrail.boostAt = 0));
        return;
      }
      if (
        __mmAntiBoostEnabled &&
        __mmNow - __mmAntiBoostLast >= 350 &&
        __mmStartAntiBoostBlock(__mmEnemy)
      ) {
        ((__mmAntiBoostLast = __mmNow),
          (__mmTrail.boostAt = 0));
        return;
      }
    }
  }
}
function __mmStartAntiBoostSpikes() {
  __mmAntiBoostTimer ||
    (__mmAntiBoostTimer = setInterval(
      __mmUpdateAntiBoostSpikes,
      __mmFastCheckMs(),
    ));
}
function __mmReloadSpikeTarget() {
  if (!v || !v.alive) return null;
  if (!__mmMusketIsReloading() && !__mmTurretGearIsReloading()) return null;
  const __mmEnemy = __mmNearestEnemy();
  if (!__mmEnemy) return null;
  const __mmDx = __mmEnemy.x - v.x;
  const __mmDy = __mmEnemy.y - v.y;
  const __mmRange = Math.min(220, Math.max(120, __mmCombatRange));
  return __mmDx * __mmDx + __mmDy * __mmDy <= __mmRange * __mmRange
    ? __mmEnemy
    : null;
}
function __mmPlaceReloadSpike(__mmTarget) {
  if (__mmHoldingMcGrabby()) return !1;
  const __mmSpike = __mmSpikeItem();
  if (
    !__mmTarget ||
    __mmSpike == null ||
    !__mmCanUseBuildItem(__mmSpike)
  )
    return !1;
  const __mmTool = __mmSelectedTool();
  const __mmAngle = Math.atan2(__mmTarget.y - v.y, __mmTarget.x - v.x);
      (je(__mmSpike),
    O.send("F", 1, __mmAngle),
    O.send("F", 0, __mmAngle),
    __mmRestoreTool(__mmTool));
  return !0;
}
function __mmUpdateReloadSpike() {
  const __mmReloading = __mmMusketIsReloading() || __mmTurretGearIsReloading();
  if (!__mmReloading) return void (__mmReloadSpikePlaced = !1);
  if (
    !__mmReloadSpikeEnabled ||
    __mmReloadSpikePlaced ||
    __mmHoldingMcGrabby() ||
    !v ||
    !v.alive ||
    __mmInsta.isActive() ||
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmTrapAttackActive ||
    __mmBoostBreakHeld ||
    __mmFoodSpamTimer ||
    __mmAutoHealWasHealing ||
    __mmBuildSpamTimer
  )
    return;
  const __mmTarget = __mmReloadSpikeTarget();
  if (!__mmTarget || !__mmActionClaim("reloadSpike", "reload defense")) return;
  (__mmPlaceReloadSpike(__mmTarget) && (__mmReloadSpikePlaced = !0),
    __mmActionRelease("reloadSpike", "reload defense sent"));
}
function __mmStartReloadSpike() {
  __mmReloadSpikeTimer ||
    (__mmReloadSpikeTimer = setInterval(__mmUpdateReloadSpike, 25));
}
function __mmStopBuildSpam(__mmKey) {
  (!__mmKey || __mmKey == __mmBuildSpamKey) &&
    (__mmBuildSpamTimer && clearInterval(__mmBuildSpamTimer),
    (__mmBuildSpamTimer = 0),
    (__mmBuildSpamKey = 0));
}
function __mmStartBuildSpam(__mmItemSlot, __mmKey) {
  __mmInsta.isActive() && __mmInsta.cancel("build-input");
  if (__mmBuildSpamTimer && __mmBuildSpamKey == __mmKey) return;
  (__mmStopBuildSpam(),
    (__mmBuildSpamKey = __mmKey),
    __mmUseBuild(__mmItemSlot),
    (__mmBuildSpamTimer = setInterval(function () {
      __mmUseBuild(__mmItemSlot);
    }, 1e3 / y.serverUpdateRate)));
}
function __mmStartBuildItemSpam(__mmItem, __mmKey) {
  __mmInsta.isActive() && __mmInsta.cancel("build-input");
  if (__mmBuildSpamTimer && __mmBuildSpamKey == __mmKey) return;
  (__mmStopBuildSpam(),
    (__mmBuildSpamKey = __mmKey),
    __mmUseBuildItem(__mmItem),
    (__mmBuildSpamTimer = setInterval(
      function () {
        __mmUseBuildItem(__mmItem);
      },
      1e3 / Math.max(1, Number(y.serverUpdateRate) || 9),
    )));
}
function __mmStartSelectedBuildSpam(__mmKey) {
  const __mmItem = __mmSelectedPlaceableItem();
  __mmItem != null && __mmStartBuildItemSpam(__mmItem, __mmKey);
}
function __mmWindmillItem() {
  if (!v || !v.items) return null;
  for (let __mmItemIndex = 0; __mmItemIndex < v.items.length; __mmItemIndex++) {
    const __mmItem = v.items[__mmItemIndex],
      __mmData = b.list[__mmItem];
    if (
      __mmData &&
      typeof __mmData.name === "string" &&
      __mmData.name.indexOf("mill") !== -1
    )
      return __mmItem;
  }
  return null;
}
function __mmCleanSpinningWindmillReservations(__mmNow) {
  for (
    let __mmIndex = __mmSpinningWindmillReservations.length - 1;
    __mmIndex >= 0;
    __mmIndex--
  )
    __mmSpinningWindmillReservations[__mmIndex].expiresAt <= __mmNow &&
      __mmSpinningWindmillReservations.splice(__mmIndex, 1);
}
function __mmSpinningWindmillCapacity(__mmItem) {
  const __mmData = b && b.list && b.list[__mmItem];
  if (
    !v ||
    !__mmData ||
    !__mmData.group ||
    !__mmCanUseBuildItem(__mmItem)
  )
    return 0;
  const __mmResourceCount = __mmMaxBuildCount(__mmItem),
    __mmLimit = y.inSandbox
      ? __mmData.group.sandboxLimit || Math.max(__mmData.group.limit * 3, 99)
      : __mmData.group.limit,
    __mmPlaced = Number(v.itemCounts && v.itemCounts[__mmData.group.id]) || 0,
    __mmSlots = __mmLimit
      ? Math.max(
          0,
          __mmLimit - __mmPlaced - __mmSpinningWindmillReservations.length,
        )
      : __mmResourceCount;
  return Math.max(0, Math.min(__mmResourceCount, __mmSlots));
}
function __mmSpinningWindmillPositionClear(
  __mmX,
  __mmY,
  __mmScale,
) {
  if (
    __mmX - __mmScale < 0 ||
    __mmY - __mmScale < 0 ||
    __mmX + __mmScale > y.mapScale ||
    __mmY + __mmScale > y.mapScale ||
    (__mmY >= y.mapScale / 2 - y.riverWidth / 2 &&
      __mmY <= y.mapScale / 2 + y.riverWidth / 2)
  )
    return !1;
  for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
    const __mmObject = ge[__mmIndex];
    if (!__mmObject || !__mmObject.active) continue;
    const __mmMinimum =
      __mmScale + __mmAutoSpikeSpamObjectScale(__mmObject);
    if (
      (__mmObject.x - __mmX) ** 2 + (__mmObject.y - __mmY) ** 2 <
      __mmMinimum * __mmMinimum
    )
      return !1;
  }
  for (
    let __mmIndex = 0;
    __mmIndex < __mmSpinningWindmillReservations.length;
    __mmIndex++
  ) {
    const __mmReservation = __mmSpinningWindmillReservations[__mmIndex],
      __mmMinimum = __mmScale + __mmReservation.scale;
    if (
      (__mmReservation.x - __mmX) ** 2 +
        (__mmReservation.y - __mmY) ** 2 <
      __mmMinimum * __mmMinimum
    )
      return !1;
  }
  return !0;
}
function __mmSpinningWindmillCandidate(__mmItem) {
  if (!v || !v.alive) return null;
  const __mmData = b.list[__mmItem],
    __mmScale = Number(__mmData.scale) || 45,
    __mmDistance =
      (Number(v.scale) || 35) +
      __mmScale +
      (Number(__mmData.placeOffset) || 0),
    __mmStep = Math.PI / 24,
    __mmStart = __mmSpinningWindmillAngle;
  // Search center-out from the rotating phase so a nearby obstacle moves the
  // mill to the closest legal slot instead of stopping the spinner entirely.
  for (let __mmOffset = 0; __mmOffset < 48; __mmOffset++) {
    const __mmRingStep = Math.ceil(__mmOffset / 2),
      __mmSign = __mmOffset === 0 || __mmOffset % 2 ? 1 : -1,
      __mmAngle = __mmStart + __mmRingStep * __mmStep * __mmSign,
      __mmX = v.x + Math.cos(__mmAngle) * __mmDistance,
      __mmY = v.y + Math.sin(__mmAngle) * __mmDistance;
    if (!__mmSpinningWindmillPositionClear(__mmX, __mmY, __mmScale))
      continue;
    return {
      item: __mmItem,
      angle: __mmAngle,
      x: __mmX,
      y: __mmY,
      scale: __mmScale,
      nextAngle: __mmAngle + __mmStep,
    };
  }
  return null;
}
function __mmUpdateSpinningWindmills() {
  const __mmNow = Date.now();
  __mmCleanSpinningWindmillReservations(__mmNow);
  if (
    !__mmSpinningWindmillsEnabled ||
    !v ||
    !v.alive ||
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmInsta.isActive() ||
    __mmTrapAttackActive ||
    __mmBoostBreakHeld ||
    __mmBuildSpamTimer ||
    __mmWindmillHeld ||
    __mmFoodSpamTimer ||
    __mmAutoHealWasHealing ||
    !__mmActionAvailable("spinningWindmills") ||
    __mmNow - __mmSpinningWindmillLastAt < __mmServerTickMs()
  )
    return;
  const __mmItem = __mmWindmillItem();
  if (__mmItem == null || !__mmSpinningWindmillCapacity(__mmItem)) return;
  const __mmCandidate = __mmSpinningWindmillCandidate(__mmItem);
  if (!__mmCandidate) {
    __mmSpinningWindmillAngle += Math.PI / 24;
    return;
  }
  if (!__mmActionClaim("spinningWindmills", "rotating mill placement")) return;
  const __mmTool = __mmSelectedTool();
  try {
    (je(__mmCandidate.item),
      O.send("F", 1, __mmCandidate.angle),
      O.send("F", 0, __mmCandidate.angle),
      __mmRestoreTool(__mmTool),
      (__mmSpinningWindmillAngle = __mmCandidate.nextAngle),
      (__mmSpinningWindmillLastAt = __mmNow),
      __mmSpinningWindmillReservations.push({
        x: __mmCandidate.x,
        y: __mmCandidate.y,
        scale: __mmCandidate.scale,
        expiresAt: __mmNow + 650,
      }),
      __mmScheduleMouseAimReturn());
  } finally {
    __mmActionRelease("spinningWindmills", "mill sent");
  }
}
function __mmStartSpinningWindmills() {
  if (!__mmSpinningWindmillsEnabled || __mmSpinningWindmillTimer) return;
  ((__mmSpinningWindmillAngle = Ci() + Math.PI),
    (__mmSpinningWindmillTimer = setInterval(
      __mmUpdateSpinningWindmills,
      10,
    )));
}
function __mmStopSpinningWindmills() {
  (__mmSpinningWindmillTimer && clearInterval(__mmSpinningWindmillTimer),
    (__mmSpinningWindmillTimer = 0),
    (__mmSpinningWindmillLastAt = 0),
    (__mmSpinningWindmillReservations.length = 0),
    __mmActionRelease("spinningWindmills", "spinner disabled"));
}
function __mmStopWindmillRow() {
  const __mmWeapon = __mmWindmillRowWeapon;
  ((__mmWindmillRowTimer && clearTimeout(__mmWindmillRowTimer),
    (__mmWindmillRowTimer = 0),
    (__mmWindmillRowWeapon = null),
    __mmWeapon != null && __mmRestoreWeapon(__mmWeapon)));
}
function __mmStartWindmillHold() {
  if (__mmWindmillHeld) return;
  ((__mmWindmillHeld = !0),
    __mmPlaceWindmillRow(),
    (__mmWindmillHoldTimer = setInterval(
      __mmPlaceWindmillRow,
      __mmServerTickMs(),
    )));
}
function __mmStopWindmillHold() {
  ((__mmWindmillHeld = !1),
    __mmWindmillHoldTimer && clearInterval(__mmWindmillHoldTimer),
    (__mmWindmillHoldTimer = 0),
    __mmStopWindmillRow());
}
function __mmPlaceWindmillRow() {
  if (__mmWindmillRowTimer || !v || !v.alive) return;
  const __mmWindmill = __mmWindmillItem();
  if (__mmWindmill == null || !__mmCanUseBuildItem(__mmWindmill)) return;
  const __mmWeapon = __mmSelectedWeapon(),
    __mmBehind = Ci() + Math.PI,
    __mmData = b.list[__mmWindmill],
    __mmPlaceDistance =
      (v.scale || 35) +
      (__mmData.scale || 45) +
      (Number(__mmData.placeOffset) || 0),
    // The angular separation is derived from the mill diameter and its true
    // placement distance, so the three mills touch side-to-side instead of
    // overlapping behind the player.
    __mmSideOffset =
      2 *
      Math.asin(
        Math.min(
          0.999,
          (2 * (__mmData.scale || 45)) / (2 * __mmPlaceDistance),
        ),
      ),
    __mmCount = Math.min(3, __mmMaxBuildCount(__mmWindmill)),
    __mmAngles =
      __mmCount === 1
        ? [__mmBehind]
        : __mmCount === 2
          ? [__mmBehind - __mmSideOffset / 2, __mmBehind + __mmSideOffset / 2]
          : [__mmBehind, __mmBehind - __mmSideOffset, __mmBehind + __mmSideOffset];
  if (!__mmCount) return;
  __mmWindmillRowWeapon = __mmWeapon;
  je(__mmWindmill);
  for (let __mmIndex = 0; __mmIndex < __mmAngles.length; __mmIndex++)
    (O.send("F", 1, __mmAngles[__mmIndex]),
      O.send("F", 0, __mmAngles[__mmIndex]));
  // Keep a one-tick key-repeat guard, but do not make the row wait three ticks.
  __mmWindmillRowTimer = setTimeout(__mmStopWindmillRow, __mmServerTickMs());
}
function __mmNearestLockingTrap() {
  if (!v || !v.alive) return null;
  let __mmClosest = null,
    __mmClosestDistance = Infinity;
  const __mmSeen = new Set(),
    __mmConsider = function (__mmObject) {
      if (
        !__mmObject ||
        __mmSeen.has(__mmObject) ||
        !__mmObject.active ||
        !__mmObject.trap ||
        __mmFriendlyStructure(__mmObject)
      )
        return;
      __mmSeen.add(__mmObject);
      const __mmRange =
          (Number(v.scale) || 35) +
          (Number(__mmObject.scale) || 45) +
          __mmTrapCollisionPadding,
        __mmDistance =
          (__mmObject.x - v.x) ** 2 + (__mmObject.y - v.y) ** 2;
      if (__mmDistance > __mmRange * __mmRange) return;
      __mmDistance < __mmClosestDistance &&
        ((__mmClosestDistance = __mmDistance), (__mmClosest = __mmObject));
    };
  try {
    const __mmGrids = X.getGridArrays(v.x, v.y, Math.max(180, v.scale * 5));
    for (let __mmGridIndex = 0; __mmGridIndex < __mmGrids.length; __mmGridIndex++)
      for (
        let __mmItemIndex = 0;
        __mmItemIndex < __mmGrids[__mmGridIndex].length;
        __mmItemIndex++
      )
        __mmConsider(__mmGrids[__mmGridIndex][__mmItemIndex]);
  } catch (__mmTrapGridError) {}
  // Item-grid visibility can lag a trap collision by one update. Scan the
  // render object list too, so the escape routine starts on the first lock tick.
  if (typeof ge !== "undefined" && Array.isArray(ge))
    for (let __mmItemIndex = 0; __mmItemIndex < ge.length; __mmItemIndex++)
      __mmConsider(ge[__mmItemIndex]);
  return __mmClosest;
}
function __mmFriendlyTrapForPlayer(__mmPlayer) {
  if (!v || !v.alive || !__mmPlayer || !Array.isArray(ge)) return null;
  let __mmClosest = null,
    __mmClosestDistance = Infinity;
  for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
    const __mmTrap = ge[__mmIndex];
    if (
      !__mmTrap ||
      !__mmTrap.active ||
      !__mmTrap.trap ||
      !__mmFriendlyStructure(__mmTrap)
    )
      continue;
    const __mmTrapScale =
        typeof __mmTrap.getScale === "function"
          ? Number(__mmTrap.getScale()) || Number(__mmTrap.scale) || 50
          : Number(__mmTrap.scale) || 50,
      __mmLockRange =
        (Number(__mmPlayer.scale) || 35) +
        Math.max(__mmTrapScale, Number(__mmTrap.scale) || 0) +
        12,
      __mmDistance = Math.hypot(
        Number(__mmPlayer.x) - Number(__mmTrap.x),
        Number(__mmPlayer.y) - Number(__mmTrap.y),
      ),
      __mmCaught =
        __mmDistance <= __mmLockRange &&
        (!!__mmPlayer.lockMove || __mmDistance <= __mmLockRange - 5);
    if (__mmCaught && __mmDistance < __mmClosestDistance)
      ((__mmClosest = __mmTrap), (__mmClosestDistance = __mmDistance));
  }
  return __mmClosest;
}
function __mmUpdateFriendlyTrapChat() {
  const __mmNow = Date.now(),
    __mmSeen = Object.create(null);
  let __mmFriendIncident = null,
    __mmEnemyIncident = null;
  if (v && v.alive && Array.isArray(E)) {
    for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
      const __mmPlayer = E[__mmIndex];
      if (
        !__mmPlayer ||
        !__mmPlayer.alive ||
        __mmPlayer === v ||
        String(__mmPlayer.sid) === String(v.sid) ||
        (Number.isFinite(Number(__mmPlayer.health)) &&
          Number(__mmPlayer.health) <= 0) ||
        Math.hypot(
          Number(__mmPlayer.x) - Number(v.x),
          Number(__mmPlayer.y) - Number(v.y),
        ) > 1500
      )
        continue;
      const __mmFriend = __mmIsFriendPlayer(__mmPlayer),
        __mmFriendKey = __mmNormalizeFriendName(__mmPlayer.name),
        __mmBetrayed =
          !!__mmFriendKey && __mmFriendEnemies.has(__mmFriendKey),
        __mmEnemy = !__mmFriend &&
          (__mmBetrayed || !__mmSameTeam(__mmPlayer));
      if (!__mmFriend && !__mmEnemy) continue;
      const __mmTrap = __mmFriendlyTrapForPlayer(__mmPlayer);
      if (!__mmTrap) continue;
      const __mmKind = __mmFriend ? "friend" : "enemy",
        __mmKey = __mmKind + ":" + String(__mmPlayer.sid),
        __mmIncident =
          __mmFriendlyTrapChatIncidents[__mmKey] ||
          (__mmFriendlyTrapChatIncidents[__mmKey] = {
            announced: !1,
            lastSeen: __mmNow,
          });
      ((__mmIncident.lastSeen = __mmNow), (__mmSeen[__mmKey] = !0));
      if (!__mmIncident.announced) {
        const __mmCandidate = {
          key: __mmKey,
          player: __mmPlayer,
          trap: __mmTrap,
        };
        __mmFriend
          ? (__mmFriendIncident || (__mmFriendIncident = __mmCandidate))
          : (__mmEnemyIncident || (__mmEnemyIncident = __mmCandidate));
      }
    }
  }
  for (const __mmKey in __mmFriendlyTrapChatIncidents) {
    const __mmIncident = __mmFriendlyTrapChatIncidents[__mmKey];
    if (!__mmSeen[__mmKey] && __mmNow - __mmIncident.lastSeen > 450)
      delete __mmFriendlyTrapChatIncidents[__mmKey];
  }
  const __mmCandidate = __mmFriendIncident || __mmEnemyIncident,
    __mmCooldown = Math.max(
      750,
      (Number(y && y.chatCooldown) || 500) + 150,
    );
  if (
    !__mmCandidate ||
    __mmNow - __mmFriendlyTrapChatLastAt < __mmCooldown
  )
    return;
  const __mmIncident = __mmFriendlyTrapChatIncidents[__mmCandidate.key];
  if (!__mmIncident || __mmIncident.announced) return;
  ((__mmIncident.announced = !0),
    (__mmFriendlyTrapChatLastAt = __mmNow),
    __mmSendChat(
      __mmCandidate.key.startsWith("friend:")
        ? "Uh oh! let me free you!"
        : "Ha, I have you in my trap!",
    ));
}
function __mmStartFriendlyTrapChat() {
  __mmFriendlyTrapChatTimer ||
    ((__mmFriendlyTrapChatTimer = setInterval(
      __mmUpdateFriendlyTrapChat,
      __mmFastCheckMs(),
    )),
    __mmUpdateFriendlyTrapChat());
}
function __mmTrapAngle() {
  const __mmTrap = __mmNearestLockingTrap();
  return __mmTrap == null
    ? null
    : Math.round(100 * Math.atan2(__mmTrap.y - v.y, __mmTrap.x - v.x)) / 100;
}
function __mmTrapBuildKey(__mmTrap) {
  if (!__mmTrap) return null;
  const __mmId =
    __mmTrap.sid != null
      ? __mmTrap.sid
      : __mmTrap.id != null
        ? __mmTrap.id
        : null;
  return __mmId != null
    ? "id:" + __mmId
    : "pos:" + Math.round(__mmTrap.x) + ":" + Math.round(__mmTrap.y);
}
function __mmAffordableBuildItem(__mmMatches) {
  if (!v || !v.items || !b || !b.list) return null;
  for (let __mmIndex = 0; __mmIndex < v.items.length; __mmIndex++) {
    const __mmItem = v.items[__mmIndex],
      __mmData = b.list[__mmItem];
    if (
      __mmData &&
      __mmMatches(__mmData, __mmItem) &&
      __mmCanUseBuildItem(__mmItem)
    )
      return __mmItem;
  }
  return null;
}
function __mmTrapEmergencyFallbackItem() {
  const __mmTrap = __mmAffordableBuildItem((__mmData) => !!__mmData.trap);
  if (__mmTrap != null) return __mmTrap;
  const __mmWindmill = __mmAffordableBuildItem(
    (__mmData) =>
      typeof __mmData.name === "string" && __mmData.name.indexOf("mill") !== -1,
  );
  if (__mmWindmill != null) return __mmWindmill;
  const __mmWall = __mmAffordableBuildItem(
    (__mmData) =>
      typeof __mmData.name === "string" && __mmData.name.indexOf("wall") !== -1,
  );
  if (__mmWall != null) return __mmWall;
  const __mmUtilityNames = [
    "turret",
    "teleporter",
    "boost pad",
    "platform",
    "healing pad",
    "blocker",
    "spawn pad",
    "sapling",
    "mine",
  ];
  for (
    let __mmNameIndex = 0;
    __mmNameIndex < __mmUtilityNames.length;
    __mmNameIndex++
  ) {
    const __mmName = __mmUtilityNames[__mmNameIndex],
      __mmItem = __mmAffordableBuildItem(
        (__mmData) => __mmData.name === __mmName,
      );
    if (__mmItem != null) return __mmItem;
  }
  return null;
}
function __mmTrapEmergencyBuildPlan(__mmTrap) {
  const __mmBehind = Ci() + Math.PI,
    __mmSpike = __mmSpikeItem(),
    __mmSpikeCount = __mmHoldingMcGrabby()
      ? 0
      : Math.min(2, __mmMaxBuildCount(__mmSpike));
  if (__mmSpike != null && __mmSpikeCount > 0)
    return __mmSpikeCount === 1
      ? [{ item: __mmSpike, angle: __mmBehind }]
      : [
          { item: __mmSpike, angle: __mmBehind - 0.42 },
          { item: __mmSpike, angle: __mmBehind + 0.42 },
        ];
  const __mmFallback = __mmTrapEmergencyFallbackItem();
  return __mmFallback == null
    ? []
    : [{ item: __mmFallback, angle: __mmBehind }];
}
function __mmStopTrapBuildEscape(__mmClearAttempt = !0) {
  const __mmWeapon = __mmTrapAttackActive
    ? __mmTrapAttackHeldWeapon || __mmTrapBreakWeapon(__mmCurrentNearbyTrap())
    : __mmTrapBuildWeapon;
  ((__mmTrapBuildTimer && clearTimeout(__mmTrapBuildTimer),
    (__mmTrapBuildTimer = 0),
    (__mmTrapBuildWeapon = null),
    __mmClearAttempt && (__mmTrapBuildAttemptKey = null),
    __mmWeapon != null && __mmRestoreWeapon(__mmWeapon)));
}
function __mmStartTrapBuildEscape(__mmTrap) {
  if (!v || !v.alive || !__mmIsTrapped() || __mmTrapBuildTimer) return;
  const __mmTrapKey = __mmTrap ? __mmTrapBuildKey(__mmTrap) : "locked";
  if (__mmTrapKey == null || __mmTrapBuildAttemptKey === __mmTrapKey) return;
  // Mark before sending. If a collision or packet rejection prevents placement,
  // this exact trap is not retried until it is gone or a new trap catches us.
  __mmTrapBuildAttemptKey = __mmTrapKey;
  const __mmPlan = __mmTrapEmergencyBuildPlan(__mmTrap);
  if (!__mmPlan.length) return;
  let __mmIndex = 0;
  __mmTrapBuildWeapon = __mmSelectedWeapon();
  const __mmPlaceNext = function () {
    const __mmCurrentTrap = __mmNearestLockingTrap();
    if (
      !v ||
      !v.alive ||
      !__mmIsTrapped() ||
      (__mmTrap && __mmTrapBuildKey(__mmCurrentTrap) !== __mmTrapKey)
    )
      return void __mmStopTrapBuildEscape();
    const __mmEntry = __mmPlan[__mmIndex++];
    if (!__mmEntry || !__mmCanUseBuildItem(__mmEntry.item))
      return void __mmStopTrapBuildEscape(!1);
    (je(__mmEntry.item),
      O.send("F", 1, __mmEntry.angle),
      O.send("F", 0, __mmEntry.angle),
      __mmResumeHeldAttack());
    if (__mmIndex < __mmPlan.length) {
      __mmTrapBuildTimer = setTimeout(__mmPlaceNext, __mmServerTickMs());
      return;
    }
    __mmStopTrapBuildEscape(!1);
  };
  __mmPlaceNext();
}
function __mmEquipTankForTrap() {
  if (!v || !v.alive || !v.skins || !v.skins[40] || __mmRightClickHat != null)
    return;
  (__mmTrapHat == null && (__mmTrapHat = v.skinIndex),
    v.skinIndex !== 40 && __mmEquipHatNow(40, !0));
}
function __mmEquipTrapDowntimeHat() {
  if (!v || !v.alive || __mmTrapHat == null || __mmRightClickHat != null)
    return;
  const __mmHat = v.skins && v.skins[6] ? 6 : __mmTrapHat;
  __mmEquipHatNow(__mmHat, !0);
}
function __mmUpdateTrapEscapeGear(__mmWeapon) {
  if (!__mmTrapAttackActive || !v || !v.alive || __mmWeapon == null) return;
  __mmTrapHat == null && (__mmTrapHat = v.skinIndex);
  if (!v.skins || !v.skins[40] || __mmRightClickHat != null) return;
  const __mmReload = v.reloads && Number(v.reloads[__mmWeapon]),
    __mmTankWindow =
      Date.now() < __mmTrapTankHoldUntil ||
      !Number.isFinite(__mmReload) ||
      __mmReload <= __mmServerTickMs();
  __mmTankWindow
    ? __mmEquipTankForTrap()
    : __mmEquipTrapDowntimeHat();
}
function __mmObserveTrapEscapeSwing(__mmPlayerSid, __mmWeapon) {
  const __mmResolvedWeapon =
    __mmWeapon == null ? Number(v && v.weaponIndex) : Number(__mmWeapon);
  if (
    !v ||
    !v.alive ||
    !__mmTrapAttackActive ||
    String(__mmPlayerSid) !== String(v.sid) ||
    (__mmTrapAttackHeldWeapon != null &&
      __mmResolvedWeapon !== Number(__mmTrapAttackHeldWeapon))
  )
    return;
  ((__mmTrapTankHoldUntil = Date.now() + __mmGearHoldMs()),
    __mmEquipTankForTrap());
}
function __mmCancelTrapHatRestoreTimer() {
  (__mmTrapHatRestoreTimer && clearTimeout(__mmTrapHatRestoreTimer),
    (__mmTrapHatRestoreTimer = 0));
}
function __mmScheduleTrapHatRestore() {
  __mmCancelTrapHatRestoreTimer();
  __mmTrapHatRestoreTimer = setTimeout(function () {
    ((__mmTrapHatRestoreTimer = 0), __mmRestoreTrapHat());
  }, __mmServerTickMs());
}
function __mmRestoreTrapHat() {
  __mmCancelTrapHatRestoreTimer();
  if (__mmTrapHat == null) return;
  if (!v || !v.alive) {
    ((__mmTrapHat = null), (__mmTrapHatRestoreAttempts = 0));
    return;
  }
  if (
    __mmTrapAttackActive ||
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmRightClickHat != null ||
    __mmInsta.isActive() ||
    __mmInstaSyncPending ||
    __mmInstaSyncFiring ||
    __mmBoostBreakHeld ||
    (__mmActionOwner !== "idle" && __mmActionOwner !== "trapEscape")
  )
    return void __mmScheduleTrapHatRestore();
  const __mmHat = __mmTrapHat,
    __mmPendingConflict = !!(
      __mmPendingHat != null &&
      __mmPendingHat !== __mmHat &&
      Date.now() - __mmPendingHatAt < __mmGearHoldMs()
    );
  if (v.skinIndex === __mmHat && !__mmPendingConflict) {
    ((__mmPendingHat === __mmHat &&
      ((__mmPendingHat = null), (__mmPendingHatAt = 0))),
      (__mmTrapHat = null),
      (__mmTrapHatRestoreAttempts = 0));
    return;
  }
  (__mmCanEquipHat(__mmHat) && __mmEquipHatNow(__mmHat, !0),
    (__mmTrapHatRestoreAttempts += 1));
  if (__mmTrapHatRestoreAttempts < 6)
    return void __mmScheduleTrapHatRestore();
  ((__mmTrapHat = null), (__mmTrapHatRestoreAttempts = 0));
}
function __mmStopTrapAttack() {
  const __mmRestore = __mmActionMayRestore("trapEscape"),
    __mmReleaseAngle = Number.isFinite(__mmTrapAimAngle)
      ? __mmTrapAimAngle
      : Ci();
  (__mmStopTrapBuildEscape(),
    __mmTrapAttackHeld && O.send("F", 0, __mmReleaseAngle),
    (__mmTrapAttackHeld = !1),
    (__mmTrapAttackHeldWeapon = null),
    (__mmTrapTankHoldUntil = 0),
    (__mmTrapWeaponSelectAt = 0),
    __mmTrapAttackActive &&
      ((__mmTrapAttackActive = !1),
      __mmRestore && __mmRestoreWeapon(__mmTrapWeapon),
      (__mmTrapWeapon = null)),
    (__mmTrapAimAngle = null),
    __mmRestoreTrapHat(),
    __mmActionRelease("trapEscape", "trap clear"));
}
function __mmPauseSoldierForBreaking() {
  __mmCancelSoldierRestore();
  if (__mmSoldierPreviousHat == null || !v || !v.alive || v.skinIndex !== 6)
    return;
  const __mmPreviousHat = __mmSoldierPreviousHat;
  ((__mmSoldierPreviousHat = null),
    __mmCanEquipHat(__mmPreviousHat) && __mmEquipHatNow(__mmPreviousHat));
}
function __mmTrapWeaponRange(__mmWeapon, __mmTrap) {
  const __mmData = b && b.weapons && b.weapons[__mmWeapon];
  if (!__mmData || __mmData.projectile != null) return 0;
  return (
    (Number(__mmData.range) || 0) +
    (v.scale || 35) +
    (__mmTrap.scale || 35) +
    8
  );
}
function __mmTrapBreakWeapon(__mmTrap) {
  if (!v || !v.weapons || !__mmTrap) return null;
  const __mmCandidates = [
    __mmGreatHammer,
    v.weapons[0],
    v.weapons[1],
  ];
  const __mmDistance = Math.hypot(__mmTrap.x - v.x, __mmTrap.y - v.y);
  for (
    let __mmIndex = 0;
    __mmIndex < __mmCandidates.length;
    __mmIndex += 1
  ) {
    const __mmWeapon = __mmCandidates[__mmIndex];
    if (
      __mmWeapon == null ||
      !v.weapons.includes(__mmWeapon) ||
      __mmDistance > __mmTrapWeaponRange(__mmWeapon, __mmTrap)
    )
      continue;
    return __mmWeapon;
  }
  return null;
}
function __mmBreakTrap() {
  if (
    !__mmTrapEscapeEnabled ||
    !v ||
    !v.alive ||
    !__mmIsTrapped()
  )
    return void __mmStopTrapAttack();
  // The insta owns the same weapon, hat, and aim channels for only a few
  // ticks. Leave the trap interval alive but idle until cleanup hands control
  // back, instead of cancelling the combo on its next fast scan.
  if (__mmInsta.isActive()) return;
  // Being genuinely trapped is still a safety priority; an idle trap-escape
  // interval must not otherwise terminate every R insta burst.
  if (!__mmActionCanPreempt("trapEscape")) return;
  const __mmTrapRestoreHat =
    __mmPrimaryClickHat != null
      ? __mmPrimaryClickHat
      : __mmRightClickHat != null
        ? __mmRightClickHat
        : __mmSoldierPreviousHat != null
          ? __mmSoldierPreviousHat
          : v.skinIndex;
  if (__mmInsta.isActive()) __mmInsta.cancel("trap-escape");
  (__mmInstaSyncPending || __mmInstaSyncFiring) && __mmStopInstaSync();
  __mmBoostBreakHeld && __mmStopBoostBreak();
  __mmActionOwner === "shieldDefense" && __mmStopShieldDefense("trap priority");
  __mmPrimaryHeld && __mmStopPrimaryInput();
  (__mmPrimaryClickHat != null || __mmPrimaryClickTail != null) &&
    __mmForceRestoreBullForPrimary();
  __mmSecondaryHeld && __mmStopSecondary();
  __mmRightClickHat != null && __mmForceRestoreRightClickHat();
  __mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
  if (__mmActionOwner === "antiInsta") {
    (__mmAntiInstaActionTimer && clearTimeout(__mmAntiInstaActionTimer),
      (__mmAntiInstaActionTimer = 0),
      __mmActionRelease("antiInsta", "trap priority"));
  }
  if (!__mmActionClaim("trapEscape", "locked pit trap")) return;
  __mmAutoHeal(!0);
  const __mmTrap = __mmCurrentNearbyTrap();
  if (__mmTrap == null)
    return void __mmStartTrapBuildEscape(null);
  const __mmAngle = Math.atan2(__mmTrap.y - v.y, __mmTrap.x - v.x);
  (__mmTrapAttackActive ||
    (__mmCancelTrapHatRestoreTimer(),
    (__mmTrapHatRestoreAttempts = 0),
    __mmPauseSoldierForBreaking(),
    (__mmTrapAttackActive = !0),
    (__mmTrapWeapon = __mmSelectedWeapon()),
    (__mmTrapHat == null && (__mmTrapHat = __mmTrapRestoreHat))));
  // Lock the normal client aim source onto the trap. Cl reads Ci every render,
  // so this turns the player toward the structure immediately and keeps every
  // break swing pointed at it until the trap is gone.
  (__mmTrapAimAngle = __mmAngle,
    __mmStartTrapBuildEscape(__mmTrap));
  const __mmWeapon = __mmTrapBreakWeapon(__mmTrap);
  if (__mmWeapon == null) return;
  __mmUpdateTrapEscapeGear(__mmWeapon);
  if (
    !__mmTrapAttackHeld ||
    __mmTrapAttackHeldWeapon !== __mmWeapon
  ) {
    (__mmTrapAttackHeld && O.send("F", 0, __mmAngle),
      je(__mmWeapon, !0),
      O.send("D", __mmAngle),
      O.send("F", 1, __mmAngle),
      (__mmTrapAttackHeld = !0),
      (__mmTrapAttackHeldWeapon = __mmWeapon),
      (__mmTrapWeaponSelectAt = Date.now()));
  } else if (
    (Number(v.buildIndex) >= 0 || Number(v.weaponIndex) !== Number(__mmWeapon)) &&
    Date.now() - __mmTrapWeaponSelectAt >= 25
  )
    ((__mmTrapWeaponSelectAt = Date.now()), je(__mmWeapon, !0));
}
function __mmStartTrapEscape() {
  __mmTrapAttackTimer ||
    (__mmTrapAttackTimer = setInterval(__mmBreakTrap, __mmFastCheckMs()));
}
function __mmWithinTrapAlertRange(__mmTrap) {
  if (!v || !__mmTrap) return !1;
  const __mmRange = Math.max(
      0,
      (Number(v.scale) || 35) +
        (Number(__mmTrap.scale) || 45) +
        __mmTrapCollisionPadding -
        __mmTrapAlertRangeReduction,
    ),
    __mmDistance = (__mmTrap.x - v.x) ** 2 + (__mmTrap.y - v.y) ** 2;
  return Number.isFinite(__mmDistance) && __mmDistance <= __mmRange ** 2;
}
function __mmUpdateTrapAlert() {
  const __mmNow = Date.now(),
    __mmNearbyTrap = v && v.alive ? __mmCurrentNearbyTrap() : null;
  // The movement lock can arrive a tick late. Check the actual pit-trap collision
  // too, using a slightly tighter alert radius to avoid premature warnings.
  const __mmIncident = !!(
    v &&
    v.alive &&
    (v.lockMove || __mmWithinTrapAlertRange(__mmNearbyTrap))
  );
  if (__mmIncident) {
    __mmTrapAlertUntil = __mmNow + 400;
    if (!__mmTrapChatIncidentActive) {
      (__mmTrapChatIncidentActive = !0,
        __mmSendChat("Oh no! A trap!"));
    }
  } else if (__mmNow >= __mmTrapAlertUntil) {
    __mmTrapChatIncidentActive = !1;
  }
  const __mmTrapped = !!(v && v.alive && (__mmIncident || __mmNow < __mmTrapAlertUntil));
  let __mmAlert = document.getElementById("kitty-klient-trap-alert");
  if (!__mmAlert && !__mmTrapped) return;
  if (!__mmAlert) {
    if (!document.body) return;
    ((__mmAlert = document.createElement("div")),
      (__mmAlert.id = "kitty-klient-trap-alert"),
      (__mmAlert.setAttribute("role", "status")),
      (__mmAlert.setAttribute("aria-live", "assertive")),
      (__mmAlert.style.cssText =
        "position:fixed;top:18%;left:50%;z-index:2147483647;transform:translate(-50%,-8px);padding:7px 11px;border:1px solid #ffb4b4;border-radius:7px;background:rgba(127,20,28,.92);color:#fff;font:700 14px Arial,sans-serif;letter-spacing:.01em;box-shadow:0 5px 18px rgba(0,0,0,.36);pointer-events:none;opacity:0;transition:opacity .12s ease,transform .12s ease;"),
      document.body.appendChild(__mmAlert));
  }
  (__mmAlert.textContent = "Oh no! A trap!"),
    (__mmAlert.style.opacity = __mmTrapped ? "1" : "0"),
    (__mmAlert.style.transform = __mmTrapped
      ? "translate(-50%,0)"
      : "translate(-50%,-8px)");
}
function __mmStartTrapAlert() {
  __mmTrapAlertTimer ||
    (__mmTrapAlertTimer = setInterval(__mmUpdateTrapAlert, __mmFastCheckMs()));
}
function __mmStopTrapEscape() {
  (__mmTrapAttackTimer &&
    (clearInterval(__mmTrapAttackTimer), (__mmTrapAttackTimer = 0)),
    __mmStopTrapAttack());
}
function __mmCanAutoSoldier() {
  return (
    __mmSoldierAutoEnabled &&
    __mmActionAvailable("soldierGear") &&
    v &&
    v.alive &&
    v.skinIndex !== 40 &&
    v.skins &&
    v.skins[6] &&
    !__mmSyncFollowerEnabled &&
    !__mmInsta.isActive() &&
    !__mmMovementGearActive() &&
    !__mmPlayerMoving() &&
    !__mmPrimaryHeld &&
    !__mmSecondaryHeld &&
    !__mmTrapAttackActive &&
    !__mmBoostBreakHeld &&
    __mmPrimaryClickHat == null &&
    __mmRightClickHat == null
  );
}
function __mmEnemyWithinSoldierRange() {
  if (!v || !v.alive) return !1;
  if (__mmLiveStateFresh())
    return __mmLiveState.nearestEnemyDistance <= __mmSoldierRange;
  for (let __mmPlayerIndex = 0; __mmPlayerIndex < E.length; __mmPlayerIndex++) {
    const __mmPlayer = E[__mmPlayerIndex];
    if (!__mmIsEnemyPlayer(__mmPlayer)) continue;
    const __mmDx = __mmPlayer.x - v.x,
      __mmDy = __mmPlayer.y - v.y;
    if (
      __mmDx * __mmDx + __mmDy * __mmDy <=
      __mmSoldierRange * __mmSoldierRange
    )
      return !0;
  }
  return !1;
}
function __mmCancelSoldierRestore() {
  __mmSoldierRestoreTimer &&
    (clearTimeout(__mmSoldierRestoreTimer), (__mmSoldierRestoreTimer = 0));
}
function __mmEquipSoldier() {
  if (!__mmCanAutoSoldier()) return;
  __mmCancelSoldierRestore();
  if (v.skinIndex !== 6) {
    (__mmSoldierPreviousHat == null && (__mmSoldierPreviousHat = v.skinIndex),
      __mmEquipHatNow(6));
  }
}
function __mmRestoreSoldier() {
  if (!__mmCanAutoSoldier() || __mmSoldierPreviousHat == null) return;
  const __mmPreviousHat = __mmSoldierPreviousHat;
  __mmSoldierPreviousHat = null;
  v.skinIndex === 6 &&
    __mmPreviousHat !== 6 &&
    __mmCanEquipHat(__mmPreviousHat) &&
    __mmEquipHatNow(__mmPreviousHat);
}
function __mmUpdateSoldier() {
  __mmCanAutoSoldier() && __mmEquipSoldier();
}
function __mmStartSoldierAuto() {
  __mmSoldierAutoTimer ||
    (__mmSoldierAutoTimer = setInterval(
      __mmUpdateSoldier,
      __mmFastCheckMs(),
    ));
}
function __mmTurretGearCanFire(__mmPlayer) {
  return __mmPlayer.skinIndex === __mmTurretGear;
}
function __mmAiEnemySnapshot(__mmPlayer) {
  const __mmDx = __mmPlayer.x - v.x,
    __mmDy = __mmPlayer.y - v.y;
  return {
    distance: Math.round(Math.sqrt(__mmDx * __mmDx + __mmDy * __mmDy)),
    health: Number(__mmPlayer.health) || 0,
    maxHealth: Number(__mmPlayer.maxHealth) || 0,
    weapon: Number(__mmPlayer.weaponIndex) || 0,
    hat: Number(__mmPlayer.skinIndex) || 0,
    tail: Number(__mmPlayer.tailIndex) || 0,
    turretGear: __mmPlayer.skinIndex === __mmTurretGear,
  };
}
function __mmAiContext() {
  if (!v) return { available: !1 };
  const __mmEnemies = [];
  for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
    const __mmPlayer = E[__mmIndex];
    if (
      !__mmPlayer ||
      !__mmPlayer.alive ||
      __mmPlayer === v ||
      __mmPlayer.sid === v.sid ||
      !__mmIsEnemyPlayer(__mmPlayer)
    )
      continue;
    __mmEnemies.push(__mmAiEnemySnapshot(__mmPlayer));
  }
  __mmEnemies.sort(function (__mmFirst, __mmSecond) {
    return __mmFirst.distance - __mmSecond.distance;
  });
  const __mmAngle = __mmTrapAngle();
  return {
    available: !0,
    modVersion: "3.15.0",
    player: {
      alive: !!v.alive,
      health: Number(v.health) || 0,
      maxHealth: Number(v.maxHealth) || 0,
      gold: Number(v.points) || 0,
      wood: Number(v.wood) || 0,
      food: Number(v.food) || 0,
      stone: Number(v.stone) || 0,
      weapons: Array.isArray(v.weapons) ? v.weapons.slice(0, 4) : [],
      selectedWeapon: __mmSelectedWeapon(),
      hat: Number(v.skinIndex) || 0,
      tail: Number(v.tailIndex) || 0,
      trapped: __mmIsTrapped(),
      foodItem: v.items ? v.items[0] : null,
    },
    nearbyEnemies: __mmEnemies.slice(0, 8),
    nearbyTrap: { detected: __mmAngle != null, angle: __mmAngle },
    features: { autoHeal: __mmAutoHealEnabled, soldierRange: __mmSoldierRange },
  };
}
function __mmPublishAiContext() {
  window.dispatchEvent(
    new CustomEvent("MooMooAIContext", { detail: __mmAiContext() }),
  );
}
window.addEventListener("MooMooAIRequestContext", __mmPublishAiContext);
function __mmCanUseShieldDefense() {
  return (
    __mmShieldDefenseEnabled &&
    __mmActionAvailable("shieldDefense") &&
    v &&
    v.alive &&
    v.weapons.includes(__mmShieldWeapon) &&
    !__mmInsta.isActive() &&
    !__mmPrimaryHeld &&
    !__mmSecondaryHeld &&
    !__mmTrapAttackActive
  );
}
function __mmStopShieldDefense(__mmReason) {
  const __mmWeapon = __mmShieldDefenseWeapon,
    __mmRestore = __mmActionMayRestore("shieldDefense");
  ((__mmShieldDefenseTimer && clearTimeout(__mmShieldDefenseTimer),
    (__mmShieldDefenseTimer = 0),
    (__mmShieldDefenseWeapon = null),
    __mmRestore &&
      !__mmPrimaryHeld &&
      !__mmSecondaryHeld &&
      !__mmTrapAttackActive &&
      __mmWeapon != null &&
      __mmWeapon !== __mmShieldWeapon &&
      __mmRestoreWeapon(__mmWeapon),
    __mmActionRelease("shieldDefense", __mmReason || "defense complete")));
}
function __mmUseShieldDefense(__mmPlayer) {
  if (!__mmCanUseShieldDefense()) return;
  const __mmDistance = (__mmPlayer.x - v.x) ** 2 + (__mmPlayer.y - v.y) ** 2;
  if (__mmDistance > __mmShieldDefenseRange * __mmShieldDefenseRange) return;
  if (!__mmActionClaim("shieldDefense", "polearm defense")) return;
  const __mmWeapon = __mmSelectedWeapon();
  (__mmShieldDefenseTimer && clearTimeout(__mmShieldDefenseTimer),
    __mmShieldDefenseWeapon == null && (__mmShieldDefenseWeapon = __mmWeapon),
    je(__mmShieldWeapon, !0),
    O.send("9", Math.atan2(__mmPlayer.y - v.y, __mmPlayer.x - v.x)),
    (__mmShieldDefenseTimer = setTimeout(function () {
      __mmStopShieldDefense("defense complete");
    }, __mmShieldDefenseMs)));
}
function __mmHandleEnemyPolearmSwing(__mmPlayerSid, __mmWeapon) {
  const __mmPlayer = Rt(__mmPlayerSid);
  if (
    !__mmIsEnemyPlayer(__mmPlayer) ||
    (__mmPlayer.weaponIndex !== __mmPolearmWeapon &&
      __mmWeapon !== __mmPolearmWeapon) ||
    !__mmTurretGearCanFire(__mmPlayer)
  )
    return;
  __mmUseShieldDefense(__mmPlayer);
}
window.addEventListener("blur", __mmStopFoodSpam);
window.addEventListener("blur", function () {
  __mmStopBuildSpam();
});
function __mmIsGameClick(__mmEvent) {
  return (
    __mmEvent.target instanceof Element &&
    __mmEvent.target.closest("#gameCanvas,#touch-controls-fullscreen")
  );
}
function __mmPrimaryWeaponReady() {
  if (!v || !v.alive || !v.weapons || v.weapons[0] == null) return !1;
  const __mmReload = v.reloads && Number(v.reloads[v.weapons[0]]);
  return (
    Date.now() >= __mmPrimaryManualReadyAt &&
    (!Number.isFinite(__mmReload) || __mmReload <= 0)
  );
}
function __mmManualWeaponCooldown(__mmWeapon) {
  const __mmData = b && b.weapons && b.weapons[__mmWeapon];
  return Math.max(
    __mmServerTickMs(),
    Number(__mmData && __mmData.speed) || __mmServerTickMs(),
  );
}
function __mmGearHoldMs() {
  return __mmServerTickMs() * Math.max(
    1,
    Math.min(8, Math.round(Number(__mmGearHoldTicks) || 3)),
  );
}
function __mmBullPrimaryAvailable() {
  return !!(
    __mmBullHelmetEnabled &&
    v &&
    v.alive &&
    v.weapons &&
    v.weapons[0] != null &&
    v.weapons[0] !== 8 &&
    v.skins &&
    v.skins[7] &&
    !__mmSecondaryHeld &&
    __mmRightClickHat == null
  );
}
function __mmPrimaryDamageTail() {
  if (!v || !v.alive) return null;
  if (v.tails && v.tails[__mmCorruptXWings]) {
    __mmPrimaryClickTail == null && (__mmPrimaryClickTail = v.tailIndex);
    return __mmCorruptXWings;
  }
  if (v.tailIndex === 11) {
    __mmPrimaryClickTail == null && (__mmPrimaryClickTail = v.tailIndex);
    return 0;
  }
  return null;
}
function __mmClearPrimaryGearTimer() {
  (__mmPrimaryGearTimer && clearTimeout(__mmPrimaryGearTimer),
    (__mmPrimaryGearTimer = 0));
}
function __mmSchedulePrimaryGear(__mmCallback, __mmAt) {
  __mmClearPrimaryGearTimer();
  __mmPrimaryGearTimer = setTimeout(function () {
    (__mmPrimaryGearTimer = 0, __mmCallback());
  }, Math.max(1, Number(__mmAt) - Date.now()));
}
function __mmEquipBullForPrimary() {
  if (!__mmBullPrimaryAvailable() || !__mmPrimaryWeaponReady()) return;
  (__mmClearPrimaryGearTimer(),
    (__mmPrimaryGearStage = "bull"),
    (__mmPrimarySoldierHoldUntil = 0),
    __mmPrimaryClickHat == null && (__mmPrimaryClickHat = v.skinIndex),
    // Force Bull past the Soldier packet from the previous cooldown window.
    __mmEquipGearPair(7, __mmPrimaryDamageTail(), !0));
}
function __mmEquipPrimaryDowntimeHat() {
  if (!v || !v.alive || __mmPrimaryClickHat == null) return;
  const __mmNow = Date.now();
  if (
    __mmPrimaryGearStage === "bull" &&
    __mmNow < __mmPrimaryBullHoldUntil
  )
    return void __mmSchedulePrimaryGear(
      __mmEquipPrimaryDowntimeHat,
      __mmPrimaryBullHoldUntil,
    );
  const __mmHat = v.skins && v.skins[6] ? 6 : __mmPrimaryClickHat;
  (__mmClearPrimaryGearTimer(),
    __mmPrimaryGearStage !== "soldier" &&
      ((__mmPrimaryGearStage = "soldier"),
      (__mmPrimarySoldierHoldUntil = __mmNow + __mmGearHoldMs())),
    // Soldier and the saved non-damage tail replace Bull/damage-tail as one
    // pair; otherwise the tail visibly and functionally trails the hat phase.
    __mmEquipGearPair(__mmHat, __mmPrimaryClickTail, !0));
  !__mmPrimaryHeld &&
    __mmSchedulePrimaryGear(
      __mmRestoreBullForPrimary,
      __mmPrimarySoldierHoldUntil,
    );
}
function __mmRestoreBullForPrimary() {
  if (__mmPrimaryHeld || __mmSecondaryHeld || __mmRightClickHat != null) return;
  if (!v || !v.alive) {
    (__mmClearPrimaryGearTimer(),
      (__mmPrimaryClickHat = null),
      (__mmPrimaryClickTail = null),
      (__mmPrimaryGearStage = null),
      (__mmPrimaryBullHoldUntil = 0),
      (__mmPrimarySoldierHoldUntil = 0));
    return;
  }
  const __mmNow = Date.now();
  if (
    __mmPrimaryGearStage === "bull" &&
    __mmNow < __mmPrimaryBullHoldUntil
  )
    return void __mmSchedulePrimaryGear(
      __mmEquipPrimaryDowntimeHat,
      __mmPrimaryBullHoldUntil,
    );
  if (__mmPrimaryGearStage === "bull")
    return void __mmEquipPrimaryDowntimeHat();
  if (
    __mmPrimaryGearStage === "soldier" &&
    __mmNow < __mmPrimarySoldierHoldUntil
  )
    return void __mmSchedulePrimaryGear(
      __mmRestoreBullForPrimary,
      __mmPrimarySoldierHoldUntil,
    );
  const __mmHat = __mmPrimaryClickHat,
    __mmTail = __mmPrimaryClickTail;
  (__mmClearPrimaryGearTimer(),
    (__mmPrimaryClickHat = null),
    (__mmPrimaryClickTail = null),
    (__mmPrimaryGearStage = null),
    (__mmPrimaryBullHoldUntil = 0),
    (__mmPrimarySoldierHoldUntil = 0),
    // Override both still-pending damage-gear packets together. A quick release
    // can arrive before either acknowledgement, so the restore must be paired.
    __mmEquipGearPair(__mmHat, __mmTail, !0));
}
function __mmForceRestoreBullForPrimary() {
  if (__mmPrimaryClickHat == null && __mmPrimaryClickTail == null) return;
  const __mmHat = __mmPrimaryClickHat,
    __mmTail = __mmPrimaryClickTail;
  (__mmClearPrimaryGearTimer(),
    (__mmPrimaryClickHat = null),
    (__mmPrimaryClickTail = null),
    (__mmPrimaryGearStage = null),
    (__mmPrimaryBullHoldUntil = 0),
    (__mmPrimarySoldierHoldUntil = 0),
    v && v.alive && __mmEquipGearPair(__mmHat, __mmTail, !0));
}
function __mmFirePrimaryBullWeapon() {
  __mmPrimaryBullArmTimer = 0;
  const __mmWeapon = v && v.weapons ? v.weapons[0] : null;
  if (!__mmPrimaryHeld || !__mmBullPrimaryAvailable() || __mmWeapon == null)
    return (
      (__mmPrimaryBullSwingPending = !1),
      void (__mmPrimaryHeld
        ? __mmEquipPrimaryDowntimeHat()
        : __mmRestoreBullForPrimary())
    );
  (je(__mmWeapon, !0),
    __mmSendWeaponAttack(1),
    __mmSendWeaponAttack(0),
    (__mmPrimaryManualReadyAt =
      Date.now() + __mmManualWeaponCooldown(__mmWeapon)),
    (__mmPrimaryBullSwingPending = !1),
    // Keep Bull through the configured post-swing window, then give Soldier
    // its own minimum window before any restore or next Bull cycle.
    (__mmPrimaryGearStage = "bull"),
    (__mmPrimaryBullHoldUntil = Date.now() + __mmGearHoldMs()),
    __mmEquipPrimaryDowntimeHat());
}
function __mmPulsePrimaryBullWeapon() {
  if (!__mmPrimaryHeld || !__mmBullPrimaryAvailable()) return;
  __mmPrimaryClickHat == null && (__mmPrimaryClickHat = v.skinIndex);
  if (__mmPrimaryBullSwingPending) return;
  if (
    __mmPrimaryGearStage === "soldier" &&
    Date.now() < __mmPrimarySoldierHoldUntil
  )
    return;
  if (!__mmPrimaryWeaponReady()) return void __mmEquipPrimaryDowntimeHat();
  __mmEquipBullForPrimary();
  if (__mmPrimaryClickHat == null) return void __mmSendWeaponAttack(1);
  (je(v.weapons[0], !0),
    (__mmPrimaryBullSwingPending = !0),
    (__mmPrimaryBullArmTimer = setTimeout(
      __mmFirePrimaryBullWeapon,
      __mmServerTickMs(),
    )));
}
function __mmStartPrimaryInput() {
  if (__mmPrimaryHeld || !v || !v.alive || v.weapons[0] == null) return !1;
  __mmActionOwner === "instaSync" && __mmStopInstaSync();
  __mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
  if (!__mmActionClaim("manualAttack", "left click")) return !1;
  ((__mmPrimaryHeld = !0),
    __mmStartHeldAttackPulse(),
    __mmAtFullHealth() && __mmStopFoodSpam());
  return !0;
}
function __mmStopPrimaryInput() {
  ((__mmPrimaryHeld = !1),
    __mmPrimaryBullArmTimer &&
      (clearTimeout(__mmPrimaryBullArmTimer), (__mmPrimaryBullArmTimer = 0)),
    (__mmPrimaryBullSwingPending = !1),
    __mmStopHeldAttackPulse(),
    __mmSecondaryHeld && __mmPulseHeldAttack(),
    __mmRestoreBullForPrimary(),
    __mmRestoreTrapHat(),
    !__mmSecondaryHeld && __mmActionRelease("manualAttack", "left click released"));
  __mmUpdateWeaponRecharge();
}
document.addEventListener(
  "mousedown",
  function (__mmEvent) {
    if (!__mmIsGameClick(__mmEvent) || __mmEvent.button !== 0) return;
    // Mouse modes are exclusive. Cancel every right-click state and its pending
    // Tank timer before the new left-click becomes authoritative.
    (__mmSecondaryHeld ||
      __mmSecondaryTankArmTimer ||
      __mmSecondaryTankSwingPending ||
      __mmRightClickHat != null) &&
      (__mmFinishSecondaryInput(), __mmForceRestoreRightClickHat());
    // A real click always wins over the queued R burst; cancel first, then
    // allow this existing input path to proceed normally.
    __mmInsta.isActive() && __mmInsta.cancel("manual-primary");
    __mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
    if (__mmUpdateAutoInsta()) {
      (__mmEvent.preventDefault(), __mmEvent.stopImmediatePropagation());
      return;
    }
    if (!__mmStartPrimaryInput()) return;
    (__mmEvent.preventDefault(),
      __mmEvent.stopImmediatePropagation(),
      null);
  },
  !0,
);
document.addEventListener(
  "mouseup",
  function (__mmEvent) {
    if (__mmEvent.button !== 0 || !__mmPrimaryHeld) return;
    (__mmEvent.preventDefault(),
      __mmEvent.stopImmediatePropagation(),
      __mmStopPrimaryInput());
  },
  !0,
);
function __mmSecondaryWeapon() {
  return v && v.alive && v.weapons && v.weapons[1] != null
    ? v.weapons[1]
    : null;
}
function __mmSecondaryWeaponReady() {
  const __mmWeapon = __mmSecondaryWeapon();
  if (__mmWeapon == null) return !1;
  const __mmReload = v.reloads && Number(v.reloads[__mmWeapon]);
  return !Number.isFinite(__mmReload) || __mmReload <= 0;
}
function __mmRightClickWeapon() {
  const __mmPrimary = v && v.alive && v.weapons ? v.weapons[0] : null,
    __mmSecondary = __mmSecondaryWeapon(),
    __mmData =
      __mmSecondary == null ? null : b && b.weapons && b.weapons[__mmSecondary];
  return __mmSecondary == null
    ? __mmPrimary
    : __mmData && __mmData.projectile != null && __mmPrimary != null
      ? __mmPrimary
      : __mmSecondary;
}
function __mmRightClickWeaponReady() {
  const __mmWeapon = __mmRightClickWeapon();
  return (
    __mmWeapon != null &&
    Date.now() >= __mmSecondaryManualReadyAt &&
    __mmWeaponReady(__mmWeapon)
  );
}
function __mmServerTickMs() {
  return Math.max(
    60,
    Math.ceil(1e3 / Math.max(1, Number(y && y.serverUpdateRate) || 9)),
  );
}
function __mmFastCheckMs() {
  // State detection should react between server updates; action paths retain
  // their separate server-tick rate limits before sending packets.
  return Math.min(
    Math.max(10, Number(__mmReactionMs) || 25),
    __mmServerTickMs(),
  );
}
function __mmEquipTankForSecondary() {
  if (
    !__mmTankRightClickEnabled ||
    !v ||
    !v.alive ||
    !__mmRightClickWeaponReady() ||
    !v.skins ||
    !v.skins[40]
  )
    return;
  (__mmSecondaryGearTimer && clearTimeout(__mmSecondaryGearTimer),
    (__mmSecondaryGearTimer = 0),
    (__mmSecondaryGearStage = "tank"),
    (__mmSecondarySoldierHoldUntil = 0),
    __mmRightClickHat == null && (__mmRightClickHat = v.skinIndex),
    // Override the Soldier cooldown packet before arming the Tank swing.
    __mmEquipHatNow(40, !0));
}
function __mmClearSecondaryGearTimer() {
  (__mmSecondaryGearTimer && clearTimeout(__mmSecondaryGearTimer),
    (__mmSecondaryGearTimer = 0));
}
function __mmScheduleSecondaryGear(__mmCallback, __mmAt) {
  __mmClearSecondaryGearTimer();
  __mmSecondaryGearTimer = setTimeout(function () {
    ((__mmSecondaryGearTimer = 0), __mmCallback());
  }, Math.max(1, Number(__mmAt) - Date.now()));
}
function __mmEquipSecondaryDowntimeHat() {
  if (!v || !v.alive || __mmRightClickHat == null) return;
  const __mmNow = Date.now();
  if (
    __mmSecondaryGearStage === "tank" &&
    __mmNow < __mmSecondaryTankHoldUntil
  )
    return void __mmScheduleSecondaryGear(
      __mmEquipSecondaryDowntimeHat,
      __mmSecondaryTankHoldUntil,
    );
  const __mmHat = v.skins && v.skins[6] ? 6 : __mmRightClickHat;
  (__mmClearSecondaryGearTimer(),
    __mmSecondaryGearStage !== "soldier" &&
      ((__mmSecondaryGearStage = "soldier"),
      (__mmSecondarySoldierHoldUntil = __mmNow + __mmGearHoldMs())),
    __mmEquipHatNow(__mmHat, !0));
  !__mmSecondaryHeld &&
    __mmScheduleSecondaryGear(
      __mmRestoreRightClickHat,
      __mmSecondarySoldierHoldUntil,
    );
}
function __mmRestoreRightClickHat() {
  if (__mmRightClickHat == null) return void __mmClearSecondaryGearTimer();
  if (__mmSecondaryHeld) return;
  if (!v || !v.alive) {
    (__mmClearSecondaryGearTimer(),
      (__mmRightClickHat = null),
      (__mmSecondaryGearStage = null),
      (__mmSecondaryTankHoldUntil = 0),
      (__mmSecondarySoldierHoldUntil = 0));
    return;
  }
  const __mmNow = Date.now();
  if (
    __mmSecondaryGearStage === "tank" &&
    __mmNow < __mmSecondaryTankHoldUntil
  )
    return void __mmScheduleSecondaryGear(
      __mmEquipSecondaryDowntimeHat,
      __mmSecondaryTankHoldUntil,
    );
  if (__mmSecondaryGearStage === "tank")
    return void __mmEquipSecondaryDowntimeHat();
  if (
    __mmSecondaryGearStage === "soldier" &&
    __mmNow < __mmSecondarySoldierHoldUntil
  )
    return void __mmScheduleSecondaryGear(
      __mmRestoreRightClickHat,
      __mmSecondarySoldierHoldUntil,
    );
  const __mmHat = __mmRightClickHat;
  // Force the saved hat past a pending Tank Gear equip. Without this override,
  // a release received before the equip acknowledgement could leave Tank on.
  (__mmClearSecondaryGearTimer(),
    (__mmRightClickHat = null),
    (__mmSecondaryGearStage = null),
    (__mmSecondaryTankHoldUntil = 0),
    (__mmSecondarySoldierHoldUntil = 0),
    __mmEquipHatNow(__mmHat, !0));
}
function __mmForceRestoreRightClickHat() {
  if (__mmRightClickHat == null) return void __mmClearSecondaryGearTimer();
  const __mmHat = __mmRightClickHat;
  (__mmClearSecondaryGearTimer(),
    (__mmRightClickHat = null),
    (__mmSecondaryGearStage = null),
    (__mmSecondaryTankHoldUntil = 0),
    (__mmSecondarySoldierHoldUntil = 0),
    v && v.alive && __mmEquipHatNow(__mmHat, !0));
}
function __mmFireSecondaryTankWeapon() {
  __mmSecondaryTankArmTimer = 0;
  if (!__mmSecondaryHeld || !__mmRightClickWeaponReady())
    return (
      (__mmSecondaryTankSwingPending = !1),
      void (__mmSecondaryHeld
        ? __mmEquipSecondaryDowntimeHat()
        : __mmRestoreRightClickHat())
    );
  const __mmWeapon = __mmRightClickWeapon();
  if (__mmWeapon == null)
    return (
      (__mmSecondaryTankSwingPending = !1),
      void __mmRestoreRightClickHat()
    );
  (je(__mmWeapon, !0),
    __mmSendWeaponAttack(1),
    __mmSendWeaponAttack(0),
    (__mmSecondaryManualReadyAt =
      Date.now() + __mmManualWeaponCooldown(__mmWeapon)),
    (__mmSecondaryTankSwingPending = !1),
    (__mmSecondaryGearStage = "tank"),
    (__mmSecondaryTankHoldUntil = Date.now() + __mmGearHoldMs()),
    __mmEquipSecondaryDowntimeHat());
}
function __mmPulseSecondaryWeapon() {
  if (!__mmSecondaryHeld || __mmSecondaryTankSwingPending) return;
  const __mmWeapon = __mmRightClickWeapon(),
    __mmUseTank = !!(__mmTankRightClickEnabled && v && v.skins && v.skins[40]);
  if (__mmWeapon == null) return;
  if (!__mmUseTank)
    return (je(__mmWeapon, !0), void __mmSendWeaponAttack(1));
  __mmRightClickHat == null && (__mmRightClickHat = v.skinIndex);
  if (
    __mmSecondaryGearStage === "soldier" &&
    Date.now() < __mmSecondarySoldierHoldUntil
  )
    return;
  if (!__mmRightClickWeaponReady())
    return void __mmEquipSecondaryDowntimeHat();
  __mmEquipTankForSecondary();
  if (__mmRightClickHat == null)
    return (je(__mmWeapon, !0), void __mmSendWeaponAttack(1));
  ((__mmSecondaryTankSwingPending = !0),
    (__mmSecondaryTankArmTimer = setTimeout(
      __mmFireSecondaryTankWeapon,
      __mmServerTickMs(),
    )));
}
function __mmStopSecondary() {
  ((__mmSecondaryHeld = !1),
    __mmSecondaryTankArmTimer &&
      (clearTimeout(__mmSecondaryTankArmTimer),
      (__mmSecondaryTankArmTimer = 0)),
    (__mmSecondaryTankSwingPending = !1),
    __mmStopHeldAttackPulse(),
    __mmPrimaryHeld && __mmPulseHeldAttack(),
    __mmRestoreRightClickHat(),
    __mmRestoreTrapHat(),
    !__mmPrimaryHeld && __mmActionRelease("manualAttack", "right click released"));
  __mmUpdateWeaponRecharge();
}
function __mmFinishSecondaryInput() {
  (__mmStopSecondary(), __mmRestoreBullForPrimary());
}
document.addEventListener(
  "mousedown",
  function (__mmEvent) {
    if (__mmEvent.button !== 2 || !__mmIsGameClick(__mmEvent))
      return void __mmRestoreRightClickHat();
    __mmInsta.isActive() && __mmInsta.cancel("manual-secondary");
    __mmActionOwner === "instaSync" && __mmStopInstaSync();
    __mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
    if (!__mmTankRightClickEnabled || __mmRightClickWeapon() == null)
      return void __mmRestoreRightClickHat();
    // A right-click handoff must fully release the left attack first. This
    // clears the Bull arm timer and prevents a late primary pulse from winning
    // after the secondary has already started.
    (__mmPrimaryHeld ||
      __mmPrimaryBullArmTimer ||
      __mmPrimaryBullSwingPending ||
      __mmPrimaryClickHat != null) &&
      (__mmStopPrimaryInput(), __mmForceRestoreBullForPrimary());
    if (!__mmActionClaim("manualAttack", "right click")) return;
    (__mmEvent.preventDefault(),
      __mmEvent.stopImmediatePropagation(),
      (__mmSecondaryHeld = !0),
      __mmStartHeldAttackPulse());
  },
  !0,
);
document.addEventListener(
  "mouseup",
  function (__mmEvent) {
    if (
      __mmEvent.button !== 2 ||
      (!__mmSecondaryHeld && __mmRightClickHat == null)
    )
      return;
    (__mmEvent.preventDefault(),
      __mmEvent.stopImmediatePropagation(),
      __mmFinishSecondaryInput());
  },
  !0,
);
document.addEventListener(
  "pointerup",
  function (__mmEvent) {
    if (__mmEvent.button === 0 && __mmPrimaryHeld) __mmStopPrimaryInput();
    if (
      __mmEvent.button === 2 &&
      (__mmSecondaryHeld ||
        __mmSecondaryTankArmTimer ||
        __mmSecondaryTankSwingPending ||
        __mmRightClickHat != null)
    )
      __mmFinishSecondaryInput();
  },
  !0,
);
document.addEventListener(
  "pointermove",
  function (__mmEvent) {
    if (__mmEvent.pointerType && __mmEvent.pointerType !== "mouse") return;
    __mmPrimaryHeld && !(__mmEvent.buttons & 1) && __mmStopPrimaryInput();
    __mmSecondaryHeld && !(__mmEvent.buttons & 2) && __mmFinishSecondaryInput();
  },
  !0,
);
document.addEventListener(
  "pointercancel",
  function () {
    (__mmStopPrimaryInput(), __mmFinishSecondaryInput());
  },
  !0,
);
document.addEventListener(
  "contextmenu",
  function (__mmEvent) {
    __mmIsGameClick(__mmEvent) && __mmEvent.preventDefault();
  },
  !0,
);
window.addEventListener("blur", function () {
  (__mmStopPrimaryInput(),
    __mmStopSecondary(),
    __mmStopCleanup("window blur", !1),
    __mmFinishMatThief("window blur"),
    __mmFinishMobSteal("window blur"),
    __mmStopWindmillHold(),
    __mmStopInstaSync(),
    __mmStopSpikeTickStrike("window blur"),
    __mmStopAntiBoostBlock("window blur"),
    __mmInsta.cancel("window-blur"),
    __mmRestoreBullForPrimary(),
    __mmStopShiftSpeed(),
    __mmRestoreMovementGear());
});
document.addEventListener("visibilitychange", function () {
  document.hidden &&
    (__mmStopPrimaryInput(),
    __mmStopSecondary(),
    __mmStopCleanup("document hidden", !1),
    __mmFinishMatThief("document hidden"),
    __mmFinishMobSteal("document hidden"),
    __mmStopWindmillHold(),
    __mmStopInstaSync(),
    __mmStopSpikeTickStrike("document hidden"),
    __mmStopAntiBoostBlock("document hidden"),
    __mmInsta.cancel("document-hidden"),
    __mmStopShiftSpeed(),
    __mmRestoreMovementGear());
});
function __mmSendKillMessage() {
  if (!__mmKillMessageEnabled || !__mmKillMessage || !v || !v.alive) return;
  __mmSendChat(__mmKillMessage);
}
__mmApplyAllItemsUnlock();
__mmStartLiveState();
__mmStartDebugHud();
__mmStartAutoHeal();
__mmStartAutoSpikeSpam();
__mmStartAutoInsta();
__mmStartAutoSpikeInsta();
__mmStartTrapAlert();
__mmStartFriendlyTrapChat();
__mmStartTrapEscape();
__mmStartSoldierAuto();
__mmStartMovementGear();
__mmStartPassiveSpikeAvoidance();
__mmStartWeaponRecharge();
__mmStartAutoPurchase();
__mmStartMobSteal();
__mmStartSpinningWindmills();
__mmStartAntiInsta();
__mmStartInstaSync();
__mmStartAntiBoostSpikes();
__mmStartThreatTrap();
__mmStartReloadSpike();
Xl = function () {
  const __mmResult = __mmOriginalAnimalUpdate.apply(this, arguments);
  __mmMobStealEnabled && __mmUpdateMobSteal();
  return __mmResult;
};
$l = function (__mmPlayerSid, __mmHealth) {
  const __mmPreviousHealth =
    v && __mmPlayerSid === v.sid ? Number(v.health) : null;
  const __mmResult = __mmOriginalHealthUpdate.apply(this, arguments);
  if (v && __mmPlayerSid === v.sid) {
    Number.isFinite(__mmPreviousHealth) &&
      Number.isFinite(Number(__mmHealth)) &&
      __mmObserveFriendDamage(
        Math.max(0, __mmPreviousHealth - Number(__mmHealth)),
      );
    const __mmTookDamage = __mmObserveAutoHealHealth(__mmHealth);
    // A confirmed hit always takes priority over a queued insta. Healing is
    // packet-driven, so do it now rather than deferring for combat cleanup.
    __mmInsta.isActive() && __mmTookDamage &&
      __mmInsta.cancel("health-damage");
    __mmAutoHeal();
  }
  return __mmResult;
};
Kl = function (__mmKey, __mmValue, __mmRefresh) {
  const __mmPreviousKills =
      v && __mmKey === "kills" ? Number(v.kills) || 0 : null,
    __mmResult = __mmOriginalPlayerStatUpdate.apply(this, arguments);
  return (
    __mmPreviousKills != null &&
      Number(__mmValue) > __mmPreviousKills &&
      __mmSendKillMessage(),
    __mmResult
  );
};
Un = function () {
  const __mmResult = __mmOriginalUpgradeDisplay.apply(this, arguments);
  (__mmMarkUnsafeUpgradeChoices(), __mmResult);
  return __mmResult;
};
Pl = function (__mmPlayerSid, __mmDidHit, __mmWeapon) {
  __mmRecordPlayerSwing(__mmPlayerSid, __mmWeapon);
  __mmObserveTrapEscapeSwing(__mmPlayerSid, __mmWeapon);
  __mmObserveFriendAttack(__mmPlayerSid, __mmDidHit, __mmWeapon);
  __mmTrackTurretGearReload(__mmPlayerSid);
  __mmHandleEnemyPolearmSwing(__mmPlayerSid, __mmWeapon);
  return __mmOriginalPlayerAttack.apply(this, arguments);
};
dl = function (__mmPlayerSid, __mmMessage) {
  const __mmResult = __mmOriginalChatDisplay.apply(this, arguments);
  (__mmReplyToMaterialRequest(__mmPlayerSid, __mmMessage),
    __mmReplyToModQuestion(__mmPlayerSid, __mmMessage),
    __mmResult);
  return __mmResult;
};
window.addEventListener("blur", __mmStopTrapAttack);
__mmPublishHudState();
window.__MooMooScrollZoomSetViewport = function (__mmZoomMultiplier) {
  const __mmMultiplier = Math.max(
    0.5,
    Math.min(6.666666666666667, Number(__mmZoomMultiplier) || 1),
  );
  _ = y.maxScreenWidth = __mmZoomBaseWidth * __mmMultiplier;
  L = y.maxScreenHeight = __mmZoomBaseHeight * __mmMultiplier;
  bi();
};
setTimeout(function () {
  window.__MooMooScrollZoomSetViewport(
    window.__MooMooScrollZoomMultiplier || 1,
  );
}, 0);
`;
    }
    function patchedHotkeyCode() {
        // Item slots 2 and 4 are the current spike and pit-trap upgrades.
  return "__mmCleanupInputKey(t),t==85?__mmArmFriendPick('friend'):t==73?__mmArmFriendPick('enemy'):t==67?__mmToggleCleanup():t==84&&__mmShiftHeld()?__mmStartBetrayalInsta():t==82?__mmInsta.start():t==80?__mmToggleAutoHeal():t==90?__mmStartWindmillHold():t==72?__mmStartSelectedBuildSpam(72):t==70&&__mmShiftHeld()?__mmStartBoostBreak():t==70&&v.items[4]!=null?__mmStartBuildSpam(4,70):t==86&&v.items[2]!=null?__mmStartBuildSpam(2,86):" + HOTKEY_MARKER;
    }
 
    function patchedFoodHotkeyCode() {
        return "t==81?__mmStartFoodSpam():";
    }
 
    function patchedFoodKeyupCode() {
  // R is deliberately absent: one keydown starts a burst, repeat keydowns are
  // ignored by __mmInsta, and keyup must not cancel an armed range wait.
  return "function pl(e){const __mmFoodKey=e.which||e.keyCode||0;__mmFoodKey==16&&__mmStopBoostBreak();__mmFoodKey==70&&__mmStopBoostBreak();__mmFoodKey==81&&__mmStopFoodSpam();__mmFoodKey==90&&__mmStopWindmillHold();(__mmFoodKey==70||__mmFoodKey==72||__mmFoodKey==86)&&__mmStopBuildSpam(__mmFoodKey);if(v&&v.alive){const t=e.which||e.keyCode||0;";
    }

    function patchedMovementKeydownCode() {
        return "bt[t]?(__mmPassiveSpikeMovementPressed(),Tt()):t==32&&(U=1,ke())";
    }

    function patchedMovementKeyupCode() {
        return "bt[t]?(__mmPassiveSpikeMovementReleased(),Tt()):t==32&&(U=0,ke())";
    }
 
    function wait(milliseconds) {
        return new Promise((resolve) => window.setTimeout(resolve, milliseconds));
    }
 
    function loadOriginalBundle(originalUrl) {
        if (originalBundleLoaded) return;
 
        originalBundleLoaded = true;
        const fallbackScript = document.createElement("script");
        fallbackScript.type = "module";
        fallbackScript.src = originalUrl;
        (document.head || document.documentElement).appendChild(fallbackScript);
    }
 
    async function fetchBundleSource(originalUrl) {
        let lastError;
 
        for (let attempt = 1; attempt <= BUNDLE_RETRY_LIMIT; attempt += 1) {
            try {
                const response = await fetch(originalUrl, { cache: "force-cache" });
                if (!response.ok) throw new Error(`bundle request failed (${response.status})`);
                return await response.text();
            } catch (error) {
                lastError = error;
                if (attempt < BUNDLE_RETRY_LIMIT) {
                    console.warn(`[MooMoo Scroll Zoom] bundle attempt ${attempt} failed; retrying.`);
                    await wait(BUNDLE_RETRY_DELAY_MS * attempt);
                }
            }
        }
 
        throw lastError || new Error("bundle request failed");
    }
 
    function loadPatchedModule(patchedSource) {
        return new Promise((resolve, reject) => {
            const blobUrl = URL.createObjectURL(new Blob([patchedSource], { type: "text/javascript" }));
            const patchedScript = document.createElement("script");
            patchedScript.type = "module";
            patchedScript.src = blobUrl;
            patchedScript.onload = () => {
                URL.revokeObjectURL(blobUrl);
                resolve();
            };
            patchedScript.onerror = () => {
                URL.revokeObjectURL(blobUrl);
                patchedScript.remove();
                reject(new Error("patched game bundle could not load"));
            };
            (document.head || document.documentElement).appendChild(patchedScript);
        });
    }

    function waitForDocumentParsed() {
        if (document.readyState !== "loading") return Promise.resolve();
        return new Promise((resolve) => {
            document.addEventListener("DOMContentLoaded", resolve, { once: true });
        });
    }
 
    function findMissingPatchMarkers(source) {
    const markers = [
            ["viewport", VIEWPORT_MARKER],
            ["hotkeys", HOTKEY_MARKER],
            ["food hotkey", FOOD_HOTKEY_MARKER],
            ["food keyup", FOOD_KEYUP_MARKER],
            ["movement keydown", MOVEMENT_KEYDOWN_MARKER],
            ["movement keyup", MOVEMENT_KEYUP_MARKER],
            ["backdrop", BACKDROP_GRID_MARKER],
            ["player-stat update", PLAYER_STAT_UPDATE_MARKER],
            ["chat display", CHAT_DISPLAY_MARKER],
            ["insta player lookup", INSTA_PLAYER_LOOKUP_MARKER],
            ["insta player attack", INSTA_PLAYER_ATTACK_MARKER]
        ];
        return markers
            .filter(([, marker]) => !source.includes(marker))
            .map(([name]) => name);
    }
 
    async function loadPatchedBundle(originalUrl) {
        try {
            const originalSource = await fetchBundleSource(originalUrl);
            const missingMarkers = findMissingPatchMarkers(originalSource);
            if (missingMarkers.length) {
                throw new Error("the game client changed; missing patch markers: " + missingMarkers.join(", "));
            }
 
            const bundleUrl = new URL(originalUrl, location.href);
            const patchedSource = originalSource
                .replace(BACKDROP_GRID_MARKER, "k.globalAlpha=1,")
                .replace(VIEWPORT_MARKER, patchedViewportCode())
                .replace(HOTKEY_MARKER, patchedHotkeyCode())
                .replace(FOOD_HOTKEY_MARKER, patchedFoodHotkeyCode())
                .replace(FOOD_KEYUP_MARKER, patchedFoodKeyupCode())
                .replace(MOVEMENT_KEYDOWN_MARKER, patchedMovementKeydownCode())
                .replace(MOVEMENT_KEYUP_MARKER, patchedMovementKeyupCode())
                .replace(/from"\.\/vendor-[^"]+\.js"/, (specifier) => {
                    const path = specifier.slice(5, -1);
                    return `from"${new URL(path, bundleUrl).href}"`;
                });
            // The site's original module is parser-deferred. Our replacement is
            // dynamically appended, so preserve the same ordering explicitly;
            // otherwise a cached bundle can run before MooMoo's body exists.
            await waitForDocumentParsed();
            let lastError;
            for (let attempt = 1; attempt <= PATCHED_MODULE_RETRY_LIMIT; attempt += 1) {
                try {
                    await loadPatchedModule(patchedSource);
                    return;
                } catch (error) {
                    lastError = error;
                    if (attempt < PATCHED_MODULE_RETRY_LIMIT) {
                        console.warn(`[MooMoo Scroll Zoom] patched bundle attempt ${attempt} failed; retrying.`);
                        await wait(BUNDLE_RETRY_DELAY_MS * attempt);
                    }
                }
            }
 
            throw lastError || new Error("patched game bundle could not load");
        } catch (error) {
            console.error("[MooMoo Scroll Zoom] could not patch the game bundle; loading the original bundle.", error);
            loadOriginalBundle(originalUrl);
        }
    }
 
    function gameBundleUrl(value) {
        if (!value) return null;
        try {
            const url = new URL(String(value), location.href);
            return GAME_BUNDLE.test(url.pathname) ? url.href : null;
        } catch {
            return null;
        }
    }

    function claimGameBundle(script, originalUrl, removeConnected = true) {
        if (gameScriptHijacked || !script || !originalUrl) return false;
        gameScriptHijacked = true;
        restoreBundleInsertionGuards();
        script.type = "application/x-kitty-klient-blocked";
        script.removeAttribute("src");
        if (removeConnected && script.isConnected) script.remove();
        // Start the replacement fetch during the same turn that blocked the
        // original module. No observer/microtask gap is left for it to execute.
        loadPatchedBundle(originalUrl);
        return true;
    }

    function interceptGameBundle(script, removeConnected = true) {
        if (gameScriptHijacked || !script || script.tagName !== "SCRIPT") return false;
        const originalUrl = gameBundleUrl(script.src || script.getAttribute("src"));
        return claimGameBundle(script, originalUrl, removeConnected);
    }

    function installSynchronousBundleGuards() {
        const nodePrototype = Node.prototype;
        const elementPrototype = Element.prototype;
        const scriptPrototype = HTMLScriptElement.prototype;
        const originalAppendChild = nodePrototype.appendChild;
        const originalInsertBefore = nodePrototype.insertBefore;
        const originalReplaceChild = nodePrototype.replaceChild;
        const originalAppend = elementPrototype.append;
        const originalPrepend = elementPrototype.prepend;
        const originalSetAttribute = elementPrototype.setAttribute;
        const originalSrc = Object.getOwnPropertyDescriptor(scriptPrototype, "src");
        let restored = false;

        const restore = () => {
            if (restored) return;
            restored = true;
            nodePrototype.appendChild = originalAppendChild;
            nodePrototype.insertBefore = originalInsertBefore;
            nodePrototype.replaceChild = originalReplaceChild;
            if (originalAppend) elementPrototype.append = originalAppend;
            if (originalPrepend) elementPrototype.prepend = originalPrepend;
            elementPrototype.setAttribute = originalSetAttribute;
            if (originalSrc) Object.defineProperty(scriptPrototype, "src", originalSrc);
        };
        restoreBundleInsertionGuards = restore;

        const captureNode = (node) => {
            if (
                gameScriptHijacked ||
                !node ||
                node.nodeType !== Node.ELEMENT_NODE ||
                node.tagName !== "SCRIPT"
            ) return false;
            const originalUrl = gameBundleUrl(node.src || node.getAttribute("src"));
            return claimGameBundle(node, originalUrl, false);
        };

        nodePrototype.appendChild = function (node) {
            if (captureNode(node)) return node;
            return originalAppendChild.call(this, node);
        };
        nodePrototype.insertBefore = function (node, reference) {
            if (captureNode(node)) return node;
            return originalInsertBefore.call(this, node, reference);
        };
        nodePrototype.replaceChild = function (node, previous) {
            if (captureNode(node)) return previous;
            return originalReplaceChild.call(this, node, previous);
        };
        if (originalAppend) {
            elementPrototype.append = function (...nodes) {
                const remaining = nodes.filter((node) => !captureNode(node));
                if (remaining.length) return originalAppend.apply(this, remaining);
            };
        }
        if (originalPrepend) {
            elementPrototype.prepend = function (...nodes) {
                const remaining = nodes.filter((node) => !captureNode(node));
                if (remaining.length) return originalPrepend.apply(this, remaining);
            };
        }
        elementPrototype.setAttribute = function (name, value) {
            if (
                !gameScriptHijacked &&
                this instanceof HTMLScriptElement &&
                String(name).toLowerCase() === "src"
            ) {
                const originalUrl = gameBundleUrl(value);
                if (claimGameBundle(this, originalUrl, false)) return;
            }
            return originalSetAttribute.call(this, name, value);
        };
        if (originalSrc && originalSrc.get && originalSrc.set) {
            Object.defineProperty(scriptPrototype, "src", {
                configurable: originalSrc.configurable,
                enumerable: originalSrc.enumerable,
                get: originalSrc.get,
                set(value) {
                    if (!gameScriptHijacked) {
                        const originalUrl = gameBundleUrl(value);
                        if (claimGameBundle(this, originalUrl, false)) return;
                    }
                    return originalSrc.set.call(this, value);
                }
            });
        }
    }

})();