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: 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.

נכון ליום 21-08-2026. ראה הגרסה האחרונה.

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

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

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

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         kitty klient
// @version      3.11.8
// @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: 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 HUD_DEFAULTS = Object.freeze({
        autoHeal: true,
        soldierAuto: true,
        movementGear: true,
        trapEscape: true,
        antiBoost: true,
        threatTrap: true,
        reloadSpike: true,
        shieldDefense: true,
        musketRecharge: true,
        autoPurchase: false,
        esp: true,
        predictionGhost: true,
        bullHelmet: true,
        tankRightClick: true,
        instaKill: false,
        boostBreak: true,
        boostChat: true,
        syncLeader: false,
        syncFollower: false,
        soldierRange: 400,
        combatRange: 400,
        antiBoostRange: 200,
        killMessageEnabled: true,
        killMessage: "gg"
    });
    const HUD_BOOLEAN_KEYS = Object.freeze([
        "autoHeal",
        "soldierAuto",
        "movementGear",
        "trapEscape",
        "antiBoost",
        "threatTrap",
        "reloadSpike",
        "shieldDefense",
        "musketRecharge",
        "autoPurchase",
        "esp",
        "predictionGhost",
        "bullHelmet",
        "tankRightClick",
        "instaKill",
        "boostBreak",
        "boostChat",
        "syncLeader",
        "syncFollower",
        "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 }),
        antiBoostRange: Object.freeze({ min: 80, max: 500, step: 10 })
    });
    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(";
    // __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 hudMounted = false;
    let hudSettingsSent = false;
    let hudState = { ...HUD_DEFAULTS };
    const hudControls = new Map();
    window.__MooMooScrollZoomMultiplier = viewMultiplier;

    // 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);
        }
        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 status = document.querySelector("#" + HUD_ID + " [data-hud-status]");
        if (!status) return;
        const enabled = [
            hudState.autoHeal && "heal",
            hudState.soldierAuto && "soldier",
            hudState.movementGear && "speed",
            hudState.antiBoost && "spikes",
            hudState.syncLeader && "sync leader",
            hudState.syncFollower && "sync follower"
        ].filter(Boolean);
        status.textContent = enabled.length ? "Active: " + enabled.join(" · ") : "Automation paused";
    }
 
    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(15,19,29,.94);--mm-surface:rgba(255,255,255,.07);--mm-line:rgba(255,255,255,.13);--mm-text:#f5f7ff;--mm-muted:#aab4ca;--mm-accent:#71e6ab;position:fixed;z-index:2147483646;top:72px;left:16px;width:min(336px,calc(100vw - 32px));font:13px/1.25 system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;color:var(--mm-text);pointer-events:auto}",
            "#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-launcher{width:100%;border:1px solid var(--mm-line);border-radius:10px;background:var(--mm-bg);color:var(--mm-text);padding:10px 12px;display:flex;justify-content:space-between;align-items:center;font-weight:800;letter-spacing:.02em;cursor:pointer;box-shadow:0 8px 30px rgba(0,0,0,.28)}#moomoo-op-hud .mm-hud-launcher b{color:var(--mm-accent);font-size:11px}",
            "#moomoo-op-hud .mm-hud-panel{margin-top:7px;max-height:calc(100vh - 140px);overflow:auto;border:1px solid var(--mm-line);border-radius:12px;background:var(--mm-bg);box-shadow:0 14px 44px rgba(0,0,0,.34);padding:12px}#moomoo-op-hud.mm-hud-collapsed .mm-hud-panel{display:none}",
            "#moomoo-op-hud .mm-hud-status{margin:0 0 10px;color:var(--mm-accent);font-size:11px;font-weight:700}#moomoo-op-hud .mm-hud-section{border-top:1px solid var(--mm-line);padding:10px 0 2px}#moomoo-op-hud .mm-hud-section:first-of-type{border-top:0;padding-top:0}#moomoo-op-hud h3{margin:0 0 7px;font-size:11px;text-transform:uppercase;letter-spacing:.09em;color:var(--mm-muted)}",
            "#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}#moomoo-op-hud small{color:var(--mm-muted);font-size:10px}",
            "#moomoo-op-hud input[type='checkbox']{appearance:none;width:34px;height:19px;margin:0;border:1px solid var(--mm-line);border-radius:999px;background:#465068;position:relative;flex:0 0 auto;cursor:pointer}#moomoo-op-hud input[type='checkbox']:after{content:'';position:absolute;top:2px;left:2px;width:13px;height:13px;border-radius:50%;background:white;transition:transform .14s ease}#moomoo-op-hud input[type='checkbox']:checked{background:#198f60}#moomoo-op-hud input[type='checkbox']:checked:after{transform:translateX(15px)}",
            "#moomoo-op-hud input[type='number']{width:62px;border:1px solid var(--mm-line);border-radius:6px;background:var(--mm-surface);color:var(--mm-text);padding:5px 6px;text-align:right}#moomoo-op-hud .mm-hud-message{width:100%;border:1px solid var(--mm-line);border-radius:7px;background:var(--mm-surface);color:var(--mm-text);padding:7px 8px;margin:3px 0 7px}",
            "#moomoo-op-hud .mm-hud-actions{display:grid;grid-template-columns:1fr;gap:6px}#moomoo-op-hud .mm-hud-actions button,#moomoo-op-hud .mm-hud-reset{border:1px solid var(--mm-line);border-radius:7px;background:var(--mm-surface);color:var(--mm-text);padding:7px;cursor:pointer}#moomoo-op-hud .mm-hud-actions button:hover,#moomoo-op-hud .mm-hud-reset:hover{border-color:var(--mm-accent)}#moomoo-op-hud .mm-hud-keys{margin:0;padding-left:16px;color:var(--mm-muted);font-size:11px;display:grid;gap:3px}",
            "@media (max-width:600px){#moomoo-op-hud{top:12px;left:10px;width:min(320px,calc(100vw - 20px))}#moomoo-op-hud .mm-hud-panel{max-height:calc(100vh - 82px)}}"
        ].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 launcher = document.createElement("button");
        launcher.className = "mm-hud-launcher";
        launcher.type = "button";
        launcher.textContent = "kitty klient";
        const launcherState = document.createElement("b");
        launcherState.textContent = "OPEN HUD";
        launcher.appendChild(launcherState);
        launcher.addEventListener("click", () => {
            root.classList.toggle("mm-hud-collapsed");
            launcherState.textContent = root.classList.contains("mm-hud-collapsed") ? "OPEN HUD" : "HIDE HUD";
        });
        const panel = document.createElement("div");
        panel.className = "mm-hud-panel";
        panel.addEventListener("keydown", (event) => event.stopPropagation(), true);
        panel.addEventListener("keyup", (event) => event.stopPropagation(), true);
 
        const status = document.createElement("p");
        status.className = "mm-hud-status";
        status.dataset.hudStatus = "";
        panel.appendChild(status);
 
        const automation = addHudSection(panel, "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 hat and adaptive tail");
        addHudToggle(automation, "trapEscape", "Trap escape", "Build behind you while continuously breaking the locking trap");
        addHudToggle(automation, "antiBoost", "Anti-boost spikes", "React to a boosted enemy");
        addHudToggle(automation, "threatTrap", "Threat trap", "Place one pit trap between you and a nearby enemy or hostile animal");
        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", "Musket recharge", "Selects a reloading Musket unless another action needs control");
        addHudToggle(automation, "autoPurchase", "Auto purchase", "Monkey Tail → Soldier → Stick/Bull path → gear → wings");

        const tabSync = addHudSection(panel, "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(panel, "Visuals");
        addHudToggle(visuals, "esp", "Player & animal markers", "Blue friends, red foes, green animals, and player lines");
        addHudToggle(visuals, "predictionGhost", "Prediction ghost", "A translucent copy projects ahead by half your live ping");
 
        const actions = addHudSection(panel, "Gear & boost controls");
        addHudToggle(actions, "bullHelmet", "Bull helmet", "Tick-paced primary attack; swaps Monkey Tail for Corrupt X Wings");
        addHudToggle(actions, "tankRightClick", "Tank right-click", "Tick-paced Tank swap for the right-click weapon");
        addHudToggle(actions, "instaKill", "R insta", "Bull primary + Turret Gear secondary combo");
        addHudToggle(actions, "boostBreak", "Shift + F boost-break", "Place, break, and move on cooldown");
        addHudToggle(actions, "boostChat", "Shift + F chat", "Send shuffled speed messages");
        const tuning = addHudSection(panel, "Distance tuning");
        addHudNumber(tuning, "soldierRange", "Soldier radius", "Pixels");
        addHudNumber(tuning, "combatRange", "Combat radius", "Tail behavior cutoff");
        addHudNumber(tuning, "antiBoostRange", "Spike radius", "Pixels");
 
        const messages = addHudSection(panel, "Death message");
        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(panel, "Hotkeys");
        const keyList = document.createElement("ul");
        keyList.className = "mm-hud-keys";
        ["P autoheal", "Q food · F trap · V spikes · Z 3 windmills behind · H selected build", "Shift + F boost-break · 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.append(launcher, panel);
        document.body.appendChild(root);
        renderHud();
    }
 
    function scheduleHudMount() {
        if (document.body) mountHud();
        else document.addEventListener("DOMContentLoaded", mountHud, { once: true });
    }
 
    window.addEventListener("MooMooOPHudState", (event) => {
        if (!event.detail || typeof event.detail !== "object") return;
        hudState = normalizeHudSettings({ ...hudState, ...event.detail });
        if (!hudSettingsSent) {
            hudSettingsSent = true;
            sendHudCommand({ type: "hydrate", settings: readHudSettings() });
        }
        saveHudSettings();
        renderHud();
    });
 
    scheduleHudMount();
 
    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,
  __mmAntiBoostRange = 200,
  __mmSoldierAutoEnabled = !0,
  __mmMovementGearEnabled = !0,
  __mmTrapEscapeEnabled = !0,
  __mmAntiBoostEnabled = !0,
  __mmThreatTrapEnabled = !0,
  __mmReloadSpikeEnabled = !0,
  __mmShieldDefenseEnabled = !0,
  __mmMusketRechargeEnabled = !0,
  __mmAutoPurchaseEnabled = !1,
  __mmEspEnabled = !0,
  __mmPredictionGhostEnabled = !0,
  __mmBullHelmetEnabled = !0,
  __mmTankRightClickEnabled = !0,
  __mmInstaUiEnabled = !1,
  __mmBoostBreakEnabled = !0,
  __mmBoostChatEnabled = !0,
  __mmSyncLeaderEnabled = !1,
  __mmSyncFollowerEnabled = !1,
  __mmKillMessageEnabled = !0,
  __mmKillMessage = "gg";
const __mmShieldWeapon = 11,
  __mmShortSword = 3,
  __mmPolearmWeapon = 5,
  __mmTurretGear = 53,
  __mmTurretGearRange = 700,
  __mmThreatTrapRange = 450,
  __mmThreatTrapCooldownMs = 650,
  __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 __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 }),
  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,
  __mmAutoHealLastSendAt = 0,
  __mmAutoHealLastDamageAt = 0,
  __mmAutoHealLastObservedHealth = null,
  __mmLastWeapon = null,
  __mmLastBuildItem = null,
  __mmAutoHealWeapon = null;
let __mmAutoPurchaseTimer = 0,
  __mmAutoPurchasePending = null;
let __mmMovementGearTimer = 0,
  __mmMovementGearPreviousHat = null,
  __mmMovementGearPreviousTail = null,
  __mmProximityTailPrevious = 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;
let __mmThreatTrapTimer = 0,
  __mmThreatTrapLastAt = 0,
  __mmThreatTrapLastKey = 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,
  __mmSyncStatus = "off";
let __mmBuildSpamTimer = 0,
  __mmBuildSpamKey = 0;
let __mmWindmillRowTimer = 0,
  __mmWindmillHoldTimer = 0,
  __mmWindmillHeld = !1,
  __mmWindmillRowWeapon = null;
let __mmMusketRechargeTimer = 0,
  __mmMusketRechargePreviousWeapon = null;
let __mmPredictionLastX = null,
  __mmPredictionLastY = null,
  __mmPredictionLastAt = 0;
let __mmPrimaryHeld = !1,
  __mmSecondaryHeld = !1,
  __mmHeldAttackTimer = 0,
  __mmPrimaryBullArmTimer = 0,
  __mmPrimaryBullSwingPending = !1,
  __mmSecondaryTankArmTimer = 0,
  __mmSecondaryTankSwingPending = !1,
  __mmPrimaryClickHat = null,
  __mmPrimaryClickTail = null,
  __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,
  __mmTrapWeapon = null,
  __mmTrapHat = null,
  __mmTrapLastSwingAt = 0,
  __mmTrapBuildTimer = 0,
  __mmTrapBuildAttemptKey = null,
  __mmTrapBuildWeapon = null;
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);
};
const __mmOriginalSocketSend = O.send;
O.send = function () {
  const __mmResult = __mmOriginalSocketSend.apply(this, arguments);
  return (__mmSyncObserveSocketSend(arguments), __mmResult);
};
const __mmOriginalPlayerAttack = Pl;
const __mmOriginalHealthUpdate = $l;
const __mmOriginalPlayerStatUpdate = Kl;
const __mmOriginalRender = Cl;
// 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,
  snapshot: null,
  primaryWeapon: null,
  followupIndex: 0,
  attackHeld: !1,
  cooldowns: Object.create(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() {
    return !!(
      !v ||
      !v.alive ||
      v.lockMove ||
      __mmPrimaryHeld ||
      __mmSecondaryHeld ||
      __mmTrapAttackActive ||
      __mmBoostBreakHeld ||
      __mmBuildSpamTimer ||
      __mmFoodSpamTimer ||
      this.isEmergencyHealth()
    );
  },
  capture() {
    this.snapshot = {
      weapon: __mmSelectedWeapon(),
      hat: v.skinIndex,
      tail: v.tailIndex,
      primaryHeld: __mmPrimaryHeld,
      secondaryHeld: __mmSecondaryHeld,
      heldPulse: !!__mmHeldAttackTimer,
      movementGear: __mmMovementGearEnabled,
      soldierAuto: __mmSoldierAutoEnabled,
      autoHeal: __mmAutoHealEnabled,
    };
  },
  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) &&
      Number.isFinite(Number(__mmTarget.x)) &&
      Number.isFinite(Number(__mmTarget.y))
      ? __mmTarget
      : null;
  },
  weaponData(__mmWeapon) {
    return b && b.weapons && __mmWeapon != null ? b.weapons[__mmWeapon] : null;
  },
  weaponCooldown(__mmWeapon) {
    const __mmData = this.weaponData(__mmWeapon);
    const __mmSpeed = __mmData && Number(__mmData.speed);
    return Math.max(this.tick(), Number.isFinite(__mmSpeed) && __mmSpeed > 0 ? __mmSpeed : this.tick());
  },
  weaponReady(__mmWeapon) {
    return !!(
      v &&
      v.alive &&
      v.weapons &&
      v.weapons.includes(__mmWeapon) &&
      this.weaponData(__mmWeapon) &&
      __mmWeaponReady(__mmWeapon) &&
      Date.now() >= (this.cooldowns[__mmWeapon] || 0)
    );
  },
  markWeaponCooldown(__mmWeapon) {
    this.cooldowns[__mmWeapon] = Date.now() + this.weaponCooldown(__mmWeapon);
  },
  supportedPrimary(__mmRequireReady = !0) {
    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 &&
      (!__mmRequireReady || this.weaponReady(__mmWeapon))
      ? __mmWeapon
      : null;
  },
  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);
    return Math.hypot(__mmTarget.x - v.x, __mmTarget.y - v.y) <= __mmReach;
  },
  aim(__mmTarget) {
    return __mmTarget
      ? Math.atan2(__mmTarget.y - v.y, __mmTarget.x - v.x)
      : Ci();
  },
  context(__mmRequireRange, __mmRequirePrimaryReady = !0) {
    if (
      !__mmInstaUiEnabled ||
      !this.runtimeReady() ||
      this.isPriorityConflict()
    )
      return null;
    const __mmPrimary = this.supportedPrimary(__mmRequirePrimaryReady);
    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;
    // Both selections are independently ownership-checked by the helpers.
    v.skins && v.skins[7] && __mmEquipHatNow(7);
    v.tails && v.tails[__mmCorruptXWings] &&
      __mmEquipTailNow(__mmCorruptXWings);
  },
  selectSecondaryDamageGear() {
    // The second strike uses Turret Gear when it is owned. It is sent before
    // the secondary selection/attack, preserving the ordered tick sequence.
    v && v.alive && v.skins && v.skins[__mmTurretGear] &&
      __mmEquipHatNow(__mmTurretGear);
  },
  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() || !this.turretInRange(__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) {}
    // Keep the hat through two server ticks: one to apply the equip packet and
    // one for the loaded turret shot, then cleanup restores the snapshot.
    this.schedule(() => {
      this.state === "turretPoke" &&
        this.schedule(() => this.finishTurretPoke());
    });
    return !0;
  },
  start(__mmOptions = {}) {
    if (this.state !== "idle") return !1;
    this.state = "validate";
    this.targetOptional = !!__mmOptions.targetOptional;
    this.followupIndex = 0;
    this.cooldowns = Object.create(null);
    if (!this.runtimeReady()) return (this.cleanup("runtime-unavailable"), !1);
    this.capture();
    const __mmTarget = this.nearestEnemy();
    if (__mmTarget) this.targetSid = __mmTarget.sid;
    const __mmContext = this.context(!1, !1);
    if (!__mmContext) return (this.cleanup("validation-failed"), !1);
    this.primaryWeapon = __mmContext.primary;
    this.state = "arm";
    this.arm();
    return !0;
  },
  arm() {
    const __mmContext = this.context(!1, !1);
    if (!__mmContext) return void this.cleanup("arm-invalid");
    this.primaryWeapon = __mmContext.primary;
    // Do not put on Bull gear merely because an enemy is nearby. Arming only
    // snapshots state; gear is selected after the target is truly in reach.
    this.state = "waitForRange";
    this.waitForRange();
  },
  waitForRange() {
    if (this.state !== "waitForRange") return;
    const __mmContext = this.context(!1, !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")
      );
    if (!this.weaponReady(__mmContext.primary))
      return void this.schedule(() => this.waitForRange());
    this.selectDamageGear();
    // Socket messages are ordered, so send Bull gear, selection, and the
    // attack-down state as one sequence. The attack stays down until the next
    // server tick; releasing it in this same turn only showed Bull Helmet.
    this.state = "executeBurst";
    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 || !this.weaponReady(__mmContext.primary))
      return void this.cleanup("primary-unavailable");
    if (!this.sendAttack(__mmContext.primary, !0, __mmContext.target))
      return void this.cleanup("primary-send-failed");
    this.markWeaponCooldown(__mmContext.primary);
    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 &&
      this.weaponReady(__mmWeapon)
      ? __mmWeapon
      : null;
  },
  spikeFollowup() {
    const __mmSpike = __mmSpikeItem();
    return __mmSpike != null &&
      v &&
      v.items &&
      v.items.includes(__mmSpike) &&
      __mmCanUseBuildItem(__mmSpike)
      ? __mmSpike
      : null;
  },
  nextFollowup() {
    const __mmSteps = ["secondary", "spike"];
    while (this.followupIndex < __mmSteps.length) {
      const __mmStep = __mmSteps[this.followupIndex++];
      if (__mmStep === "secondary") {
        const __mmSecondary = this.secondaryFollowup();
        if (__mmSecondary != null)
          return { type: "weapon", item: __mmSecondary };
      } else {
        const __mmSpike = this.spikeFollowup();
        if (__mmSpike != null) return { type: "item", item: __mmSpike };
      }
    }
    return 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, !1);
    if (!__mmContext) return void this.cleanup("followup-invalid");
    const __mmFollowup = this.nextFollowup();
    if (!__mmFollowup) return void this.cleanup("complete");
    if (
      (__mmFollowup.type === "weapon" && !this.weaponReady(__mmFollowup.item)) ||
      (__mmFollowup.type === "item" && !this.spikeFollowup())
    )
      return void this.schedule(() => this.executeFollowup());
    __mmFollowup.type === "weapon" && this.selectSecondaryDamageGear();
    if (!this.sendAttack(
      __mmFollowup.item,
      __mmFollowup.type === "weapon",
      __mmContext.target,
    ))
      return void this.cleanup("followup-send-failed");
    __mmFollowup.type === "weapon" && this.markWeaponCooldown(__mmFollowup.item);
    this.schedule(() => this.executeFollowup());
  },
  cleanup(__mmReason) {
    const __mmSnapshot = this.snapshot;
    this.state = "cleanup";
    this.timer && clearTimeout(this.timer);
    this.timer = 0;
    this.releaseAttack();
    if (v && v.alive && __mmSnapshot) {
      __mmSnapshot.tail != null && __mmEquipTailNow(__mmSnapshot.tail);
      __mmSnapshot.hat != null && __mmEquipHatNow(__mmSnapshot.hat);
      __mmSnapshot.weapon != null && __mmRestoreWeapon(__mmSnapshot.weapon);
      (__mmSnapshot.primaryHeld || __mmSnapshot.secondaryHeld) &&
        (__mmPrimaryHeld || __mmSecondaryHeld) &&
        __mmResumeHeldAttack();
    }
    this.snapshot = null;
    this.targetSid = null;
    this.targetOptional = !1;
    this.primaryWeapon = null;
    this.followupIndex = 0;
    this.cooldowns = Object.create(null);
    this.reason = __mmReason || "cancelled";
    this.state = "idle";
    // 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) {
      __mmUpdateMovementGear();
      __mmUpdateSoldier();
      __mmUpdateMusketRecharge();
      __mmAutoHeal();
    }
  },
  cancel(__mmReason) {
    this.cleanup(__mmReason || "cancelled");
  },
};
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 __mmSameTeam(__mmPlayer) {
  const __mmOwnTeam = __mmTeamKey(v),
    __mmOtherTeam = __mmTeamKey(__mmPlayer);
  return (
    __mmOwnTeam != null &&
    __mmOtherTeam != null &&
    __mmOwnTeam === __mmOtherTeam
  );
}
function __mmIsEnemyPlayer(__mmPlayer) {
  if (
    !__mmPlayer ||
    !__mmPlayer.alive ||
    !v ||
    !v.alive ||
    __mmPlayer === v ||
    __mmPlayer.sid === v.sid ||
    __mmSameTeam(__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 !== "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 __mmSyncObserveSocketSend(__mmArguments) {
  if (!__mmSyncLeaderEnabled || !v || !v.alive) return;
  if (__mmArguments[0] === "c") {
    __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, __mmServerTickMs())));
}
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 || !Array.isArray(E) || !Array.isArray(N)) return;
    const __mmOwnX = v.x - __mmLeft,
      __mmOwnY = v.y - __mmTop;
    (k.save(), (k.lineWidth = 1.5), (k.globalAlpha = 0.72));
    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 = __mmSameTeam(__mmPlayer) ? "#43a5ff" : "#ff4d5d",
        __mmX = __mmPlayer.x - __mmLeft,
        __mmY = __mmPlayer.y - __mmTop;
      ((k.strokeStyle = __mmColor),
        k.beginPath(),
        k.moveTo(__mmOwnX, __mmOwnY),
        k.lineTo(__mmX, __mmY),
        k.stroke());
    }
    ((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 = __mmSameTeam(__mmPlayer) ? "#43a5ff" : "#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) {}
  }
}
Cl = function () {
  const __mmResult = __mmOriginalRender.apply(this, arguments);
  return (__mmDrawEsp(), __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.turret,
        __mmEntries.tank,
        __mmEntries.shadow,
        __mmEntries.angel,
        __mmEntries.blood,
        __mmEntries.corrupt,
      ]
    : [
        __mmEntries.monkeyTail,
        __mmEntries.soldier,
        __mmEntries.bull,
        __mmEntries.booster,
        __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,
      __mmServerTickMs(),
    ));
}
function __mmStopAutoPurchase() {
  (__mmAutoPurchaseTimer && clearInterval(__mmAutoPurchaseTimer),
    (__mmAutoPurchaseTimer = 0),
    (__mmAutoPurchasePending = null));
}
function __mmEnemyWithinCombatRange() {
  if (!v || !v.alive) return !1;
  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;
}
function __mmHudState() {
  return {
    autoHeal: __mmAutoHealEnabled,
    soldierAuto: __mmSoldierAutoEnabled,
    movementGear: __mmMovementGearEnabled,
    trapEscape: __mmTrapEscapeEnabled,
    antiBoost: __mmAntiBoostEnabled,
    threatTrap: __mmThreatTrapEnabled,
    reloadSpike: __mmReloadSpikeEnabled,
    shieldDefense: __mmShieldDefenseEnabled,
    musketRecharge: __mmMusketRechargeEnabled,
    autoPurchase: __mmAutoPurchaseEnabled,
    esp: __mmEspEnabled,
    predictionGhost: __mmPredictionGhostEnabled,
    bullHelmet: __mmBullHelmetEnabled,
    tankRightClick: __mmTankRightClickEnabled,
    instaKill: __mmInstaUiEnabled,
    boostBreak: __mmBoostBreakEnabled,
    boostChat: __mmBoostChatEnabled,
    syncLeader: __mmSyncLeaderEnabled,
    syncFollower: __mmSyncFollowerEnabled,
    soldierRange: __mmSoldierRange,
    combatRange: __mmCombatRange,
    antiBoostRange: __mmAntiBoostRange,
    killMessageEnabled: __mmKillMessageEnabled,
    killMessage: __mmKillMessage,
  };
}
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 === "antiBoostRange" &&
        (__mmAntiBoostRange = Math.max(80, Math.min(500, __mmNumber))),
    __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 === "trapEscape")
    ((__mmTrapEscapeEnabled = __mmEnabled),
      __mmEnabled ? __mmStartTrapEscape() : __mmStopTrapEscape());
  else if (__mmKey === "antiBoost") __mmAntiBoostEnabled = __mmEnabled;
  else if (__mmKey === "threatTrap") __mmThreatTrapEnabled = __mmEnabled;
  else if (__mmKey === "reloadSpike") __mmReloadSpikeEnabled = __mmEnabled;
  else if (__mmKey === "shieldDefense") __mmShieldDefenseEnabled = __mmEnabled;
  else if (__mmKey === "musketRecharge")
    ((__mmMusketRechargeEnabled = __mmEnabled),
      !__mmEnabled && (__mmMusketRechargePreviousWeapon = null));
  else if (__mmKey === "autoPurchase")
    ((__mmAutoPurchaseEnabled = __mmEnabled),
      __mmEnabled ? (__mmStartAutoPurchase(), __mmUpdateAutoPurchase()) : __mmStopAutoPurchase());
  else if (__mmKey === "esp") __mmEspEnabled = __mmEnabled;
  else if (__mmKey === "predictionGhost")
    __mmPredictionGhostEnabled = __mmEnabled;
  else if (__mmKey === "bullHelmet") {
    __mmBullHelmetEnabled = __mmEnabled;
    if (!__mmEnabled && v && __mmPrimaryClickHat != null) {
      const __mmHat = __mmPrimaryClickHat;
      ((__mmPrimaryClickHat = null),
        v.skinIndex === 7 && __mmCanEquipHat(__mmHat) && __mmEquipHatNow(__mmHat));
    }
  } else if (__mmKey === "tankRightClick")
    ((__mmTankRightClickEnabled = __mmEnabled),
      !__mmEnabled && __mmStopSecondary());
  else if (__mmKey === "instaKill") {
    ((__mmInstaUiEnabled = __mmEnabled),
      !__mmEnabled && __mmInsta.cancel("hud-disabled"));
  }
  else if (__mmKey === "boostBreak") {
    ((__mmBoostBreakEnabled = __mmEnabled),
      !__mmEnabled && __mmStopBoostBreak());
  } else if (__mmKey === "boostChat") {
    ((__mmBoostChatEnabled = __mmEnabled), !__mmEnabled && __mmStopBoostChat());
  } else if (__mmKey === "syncLeader") {
    __mmSetSyncLeader(__mmEnabled);
    return;
  } else if (__mmKey === "syncFollower") {
    __mmSetSyncFollower(__mmEnabled);
    return;
  } 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 === "antiBoostRange"
    ? __mmSetHudNumber(__mmKey, __mmValue)
    : __mmSetHudToggle(__mmKey, __mmValue);
}
function __mmApplyHudSettings(__mmSettings) {
  if (!__mmSettings || typeof __mmSettings !== "object") return;
  const __mmKeys = [
    "autoHeal",
    "soldierAuto",
    "movementGear",
    "trapEscape",
    "antiBoost",
    "threatTrap",
    "reloadSpike",
    "shieldDefense",
    "musketRecharge",
    "autoPurchase",
    "esp",
    "predictionGhost",
    "bullHelmet",
    "tankRightClick",
    "instaKill",
    "boostBreak",
    "boostChat",
    "syncLeader",
    "syncFollower",
    "killMessageEnabled",
    "killMessage",
    "soldierRange",
    "combatRange",
    "antiBoostRange",
  ];
  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);
  __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) {
  if (
    !v ||
    !v.alive ||
    __mmHat == null ||
    (__mmHat !== 0 && !(v.skins && v.skins[__mmHat]))
  )
    return !1;
  if (v.skinIndex === __mmHat) {
    __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) {
  if (
    !v ||
    !v.alive ||
    __mmTail == null ||
    (__mmTail !== 0 && !(v.tails && v.tails[__mmTail]))
  )
    return !1;
  if (v.tailIndex === __mmTail) {
    __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) {
  if (!v || !v.alive) return;
  (__mmHat != null && __mmEquipHatNow(__mmHat),
    __mmTail != null && __mmEquipTailNow(__mmTail));
}
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() {
  __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 __mmWeapon = __mmSelectedWeapon();
  (je(v.items[0]),
    O.send("F", 1, Ci()),
    O.send("F", 0, Ci()),
    __mmWeapon != null && __mmRestoreWeapon(__mmWeapon),
    __mmResumeHeldAttack());
}
function __mmUseFoodBurst(__mmCount) {
  const __mmBites = Math.min(Math.max(0, __mmCount | 0), __mmFoodCharges());
  if (!__mmBites) return;
  const __mmFood = v.items[0],
    __mmAngle = Ci(),
    __mmWeapon = __mmSelectedWeapon();
  for (let __mmBite = 0; __mmBite < __mmBites; __mmBite++)
    (je(__mmFood), O.send("F", 1, __mmAngle), O.send("F", 0, __mmAngle));
  (__mmWeapon != null && __mmRestoreWeapon(__mmWeapon), __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 __mmRestoreWeapon(__mmWeapon) {
  v && v.alive && v.weapons.includes(__mmWeapon) && je(__mmWeapon, !0);
}
function __mmMusketIsReloading() {
  if (!v || !v.alive || !v.weapons || !v.weapons.includes(__mmMusket))
    return !1;
  const __mmReload = v.reloads && Number(v.reloads[__mmMusket]);
  return Number.isFinite(__mmReload) && __mmReload > 0;
}
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 __mmMusketRechargeOverridden() {
  return (
    !v ||
    !v.alive ||
    __mmInsta.isActive() ||
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmTrapAttackActive ||
    __mmBoostBreakHeld ||
    __mmBuildSpamTimer ||
    __mmFoodSpamTimer ||
    __mmAutoHealWasHealing ||
    __mmShieldDefenseTimer ||
    __mmTankGearActive() ||
    __mmPrimaryClickHat != null ||
    __mmRightClickHat != null ||
    __mmTrapHat != null
  );
}
function __mmUpdateMusketRecharge() {
  if (
    !__mmMusketRechargeEnabled ||
    __mmSyncFollowerEnabled ||
    !v ||
    !v.alive ||
    !v.weapons ||
    !v.weapons.includes(__mmMusket)
  )
    return void (__mmMusketRechargePreviousWeapon = null);
  if (!__mmMusketIsReloading()) {
    const __mmPreviousWeapon = __mmMusketRechargePreviousWeapon;
    return (
      (__mmMusketRechargePreviousWeapon = null),
      void (
        __mmPreviousWeapon != null &&
        !__mmMusketRechargeOverridden() &&
        __mmSelectedWeapon() === __mmMusket &&
        __mmRestoreWeapon(__mmPreviousWeapon)
      )
    );
  }
  if (__mmMusketRechargeOverridden()) return;
  const __mmSelected = __mmSelectedWeapon();
  __mmSelected !== __mmMusket &&
    (__mmMusketRechargePreviousWeapon == null &&
      (__mmMusketRechargePreviousWeapon = __mmSelected),
    je(__mmMusket, !0));
}
function __mmStartMusketRecharge() {
  __mmMusketRechargeTimer ||
    (__mmMusketRechargeTimer = setInterval(
      __mmUpdateMusketRecharge,
      __mmServerTickMs(),
    ));
}
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 __mmAutoHealCooldown() {
  // Send the first food immediately on a health update, then pace follow-up
  // food to the server tick with only a small ping allowance.
  const __mmPing = Number(window.pingTime);
  return Math.max(
    75,
    Math.min(
      135,
      __mmServerTickMs() - 12 +
        (Number.isFinite(__mmPing) ? Math.max(0, __mmPing) * 0.12 : 0),
    ),
  );
}
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;
  if (
    __mmAutoHealLastObservedHealth != null &&
    __mmCurrentHealth < __mmAutoHealLastObservedHealth
  )
    __mmAutoHealLastDamageAt = Date.now();
  __mmAutoHealLastObservedHealth = __mmCurrentHealth;
}
function __mmResetAutoHeal() {
  ((__mmAutoHealWasHealing = !1),
    (__mmAutoHealLastSendAt = 0),
    (__mmAutoHealLastDamageAt = 0),
    (__mmAutoHealLastObservedHealth = v && v.alive ? Number(v.health) : null),
    __mmRestoreAutoHealWeapon());
}
function __mmAutoHealIsEmergency() {
  if (!v || !v.alive) return !1;
  const __mmCriticalHealth = Math.max(20, v.maxHealth * 0.2);
  const __mmFoodValue = __mmAutoHealFoodValue();
  const __mmMissingHealth = Math.max(0, v.maxHealth - v.health);
  return (
    v.health <= __mmCriticalHealth ||
    ((__mmEnemyWithinCombatRange() || v.lockMove || __mmTrapAttackActive) &&
      __mmMissingHealth >= __mmFoodValue)
  );
}
function __mmAutoHeal() {
  if (!__mmAutoHealEnabled || !v || !v.alive)
    return void __mmResetAutoHeal();
  __mmObserveAutoHealHealth(v.health);
  if (v.health >= v.maxHealth || !__mmCanEat()) return void __mmResetAutoHeal();

  const __mmNow = Date.now();
  const __mmCooldown = __mmAutoHealCooldown();
  // A health update can call this immediately. Every later food use waits for
  // the short server-tick cadence, rather than adding a second post-hit wait.
  if (__mmNow - __mmAutoHealLastSendAt < __mmCooldown) return;

  ((__mmAutoHealWasHealing = !0),
    (__mmAutoHealLastSendAt = __mmNow),
    __mmUseFood());
}
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));
  if (__mmShiftPreviousTail != null) {
    const __mmTail = __mmShiftPreviousTail;
    ((__mmShiftPreviousTail = null),
      v.tailIndex !== __mmTail &&
        (__mmTail === 0 || (v.tails && v.tails[__mmTail])) &&
        __mmEquipTailNow(__mmTail));
  }
  if (__mmTemporaryHatOverlay())
    return void (
      __mmShiftRestoreTimer ||
      (__mmShiftRestoreTimer = setTimeout(function () {
        ((__mmShiftRestoreTimer = 0), __mmRestoreShiftSpeed());
      }, __mmServerTickMs()))
    );
  const __mmHat = __mmShiftPreviousHat;
  ((__mmShiftPreviousHat = null),
    __mmHat != null &&
      v.skinIndex !== __mmHat &&
      __mmCanEquipHat(__mmHat) &&
      __mmEquipHatNow(__mmHat));
}
function __mmStartShiftSpeedGear() {
  if (!v || !v.alive || !__mmShiftHasSpeedGear()) return;
  ((__mmShiftMode = 1),
    (__mmShiftPreviousHat = __mmShiftBaseHat()),
    (__mmShiftPreviousTail = v.tailIndex),
    __mmShiftSpeedTimer ||
      (__mmShiftSpeedTimer = setInterval(
        __mmUpdateShiftSpeed,
        __mmServerTickMs(),
      )),
    __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",
        }),
      ));
  }, __mmServerTickMs());
}
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 (__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) {
    __mmRestoreMovementGear();
    if (v.tails && v.tails[__mmAngelWings])
      return void __mmEquipTailNow(__mmAngelWings);
    return void __mmClearIdleMonkeyTail();
  }
  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,
      __mmServerTickMs(),
    )),
    __mmUpdateMovementGear());
}
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;
  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;
  }
  return null;
}
function __mmThreatTrapAnimalAllowed(__mmAnimal) {
  if (
    !__mmAnimal ||
    !__mmAnimal.active ||
    !__mmAnimal.alive ||
    !__mmAnimal.visible ||
    !__mmAnimal.hostile
  )
    return !1;
  const __mmName = String(__mmAnimal.name || "").trim().toLowerCase();
  return __mmName !== "moostafa" && __mmName !== "moofie";
}
function __mmThreatTrapTarget() {
  if (!v || !v.alive) return null;
  let __mmClosest = null,
    __mmClosestDistance = Infinity;
  const __mmConsider = function (__mmTarget, __mmType) {
    if (
      !__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 > __mmThreatTrapRange || __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,
      distance: __mmDistance,
    }),
      (__mmClosestDistance = __mmDistance));
  };
  if (Array.isArray(E))
    for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
      const __mmPlayer = E[__mmIndex];
      __mmIsEnemyPlayer(__mmPlayer) && __mmConsider(__mmPlayer, "player");
    }
  if (Array.isArray(N))
    for (let __mmIndex = 0; __mmIndex < N.length; __mmIndex++) {
      const __mmAnimal = N[__mmIndex];
      __mmThreatTrapAnimalAllowed(__mmAnimal) &&
        __mmConsider(__mmAnimal, "animal");
    }
  return __mmClosest;
}
function __mmPlaceThreatTrap() {
  if (
    !__mmThreatTrapEnabled ||
    !v ||
    !v.alive ||
    v.lockMove ||
    __mmInsta.isActive() ||
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmTrapAttackActive ||
    __mmBoostBreakHeld ||
    __mmBuildSpamTimer ||
    __mmFoodSpamTimer
  )
    return !1;
  const __mmTrap = __mmThreatTrapItem(),
    __mmThreat = __mmThreatTrapTarget(),
    __mmNow = Date.now();
  if (
    __mmTrap == null ||
    !__mmThreat ||
    (__mmThreat.key === __mmThreatTrapLastKey &&
      __mmNow - __mmThreatTrapLastAt < __mmThreatTrapCooldownMs)
  )
    return !1;
  // Build placement is angle-based and always occurs at the player's placement
  // radius, so aiming at the threat puts the pit trap directly between us.
  const __mmAngle = Math.atan2(
      __mmThreat.target.y - v.y,
      __mmThreat.target.x - v.x,
    ),
    __mmWeapon = __mmSelectedWeapon();
  try {
    (je(__mmTrap),
      O.send("F", 1, __mmAngle),
      O.send("F", 0, __mmAngle),
      __mmWeapon != null && __mmRestoreWeapon(__mmWeapon),
      (__mmThreatTrapLastAt = __mmNow),
      (__mmThreatTrapLastKey = __mmThreat.key));
    return !0;
  } catch (__mmThreatTrapError) {
    return !1;
  }
}
function __mmStartThreatTrap() {
  __mmThreatTrapTimer ||
    (__mmThreatTrapTimer = setInterval(
      __mmPlaceThreatTrap,
      __mmServerTickMs(),
    ));
}
function __mmNearestEnemy() {
  if (!v || !v.alive) return null;
  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));
}
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();
  (!__mmEnemyNearby &&
    v.tails &&
    v.tails[11] &&
    v.tailIndex !== 11 &&
    __mmEquipTailNow(11),
    __mmEnemyNearby && !__mmHasStick() && v.tailIndex === 11 && __mmEquipTailNow(0));
  const __mmHat = __mmSpeedHat();
  if (!__mmEnemyNearby && v.skins && v.skins[__mmHat]) __mmEquipHatNow(__mmHat);
  else if (
    __mmBoostTankPreviousHat != null &&
    v.skinIndex === 40 &&
    __mmCanEquipHat(__mmBoostTankPreviousHat)
  )
    __mmEquipHatNow(__mmBoostTankPreviousHat);
  else if (
    __mmInSnowBiome() &&
    v.skins &&
    v.skins[__mmBoosterHat] &&
    v.skinIndex !== __mmBoosterHat
  )
    __mmEquipHatNow(__mmBoosterHat);
}
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();
  (__mmPauseSoldierForBreaking(),
    !__mmEnemyWithinCombatRange() &&
      v.tails &&
      v.tails[11] &&
      v.tailIndex !== 11 &&
      __mmEquipTailNow(11),
    je(__mmPad),
    O.send("F", 1, __mmAngle),
    O.send("F", 0, __mmAngle),
    __mmStartBoostForward(__mmAngle),
    __mmBoostTankPreviousHat == null &&
      (__mmBoostTankPreviousHat = v.skinIndex),
    __mmEquipHatNow(40),
    (__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;
  ((__mmBoostBreakHeld = !0),
    __mmBoostBreakTimer ||
      (__mmBoostBreakTimer = setInterval(
        __mmBoostBreakTick,
        __mmServerTickMs(),
      )),
    __mmStartBoostChat(),
    __mmBoostBreakTick());
}
function __mmStopBoostBreak() {
  ((__mmBoostBreakHeld = !1),
    __mmBoostBreakTimer &&
      (clearInterval(__mmBoostBreakTimer), (__mmBoostBreakTimer = 0)),
    __mmBoostBreakStrikeTimer &&
      (clearTimeout(__mmBoostBreakStrikeTimer),
      (__mmBoostBreakStrikeTimer = 0)),
    (__mmBoostBreakStriking = !1),
    __mmBoostBreakPreviousWeapon != null &&
      __mmRestoreWeapon(__mmBoostBreakPreviousWeapon),
    (__mmBoostBreakPreviousWeapon = null),
    __mmStopBoostChat(),
    (__mmBoostBreakCooldownWeapon = null),
    (__mmBoostBreakReadyAt = 0));
  if (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)),
    __mmUpdateMovementGear());
}
function __mmStartAutoHeal() {
  __mmAutoHealTimer || (__mmAutoHealTimer = setInterval(__mmAutoHeal, 10));
}
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 __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];
  if (__mmCount === 2) return [__mmAngle - 0.48, __mmAngle + 0.48];
  if (__mmCount === 3)
    return [__mmAngle - 0.48, __mmAngle + 0.48, __mmAngle + Math.PI];
  return [
    __mmAngle - 0.48,
    __mmAngle + 0.48,
    __mmAngle + Math.PI - 0.48,
    __mmAngle + Math.PI + 0.48,
  ];
}
function __mmPlaceAntiBoostSpikes(__mmAngle) {
  const __mmSpike = __mmSpikeItem(),
    __mmCount = Math.min(4, __mmMaxBuildCount(__mmSpike));
  if (__mmSpike == null || __mmCount < 1) return;
  const __mmWeapon = __mmSelectedWeapon(),
    __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]));
  __mmRestoreWeapon(__mmWeapon);
}
function __mmUpdateAntiBoostSpikes() {
  if (__mmInsta.isActive()) return void __mmInsta.cancel("anti-boost");
  if (
    !__mmAntiBoostEnabled ||
    !v ||
    !v.alive ||
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmTrapAttackActive ||
    __mmBoostBreakHeld
  )
    return;
  const __mmNow = Date.now();
  if (__mmNow - __mmAntiBoostLast < 350) return;
  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
    ) {
      (__mmPlaceAntiBoostSpikes(Math.atan2(__mmToPlayerY, __mmToPlayerX)),
        (__mmAntiBoostLast = __mmNow),
        (__mmTrail.boostAt = 0));
      return;
    }
  }
}
function __mmStartAntiBoostSpikes() {
  __mmAntiBoostTimer ||
    (__mmAntiBoostTimer = setInterval(__mmUpdateAntiBoostSpikes, 50));
}
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) {
  const __mmSpike = __mmSpikeItem();
  if (
    !__mmTarget ||
    __mmSpike == null ||
    !__mmCanUseBuildItem(__mmSpike)
  )
    return !1;
  const __mmWeapon = __mmSelectedWeapon();
  const __mmAngle = Math.atan2(__mmTarget.y - v.y, __mmTarget.x - v.x);
      (je(__mmSpike),
    O.send("F", 1, __mmAngle),
    O.send("F", 0, __mmAngle),
    __mmRestoreWeapon(__mmWeapon));
  return !0;
}
function __mmUpdateReloadSpike() {
  const __mmReloading = __mmMusketIsReloading() || __mmTurretGearIsReloading();
  if (!__mmReloading) return void (__mmReloadSpikePlaced = !1);
  if (
    !__mmReloadSpikeEnabled ||
    __mmReloadSpikePlaced ||
    !v ||
    !v.alive ||
    __mmInsta.isActive() ||
    __mmPrimaryHeld ||
    __mmSecondaryHeld ||
    __mmTrapAttackActive ||
    __mmBoostBreakHeld ||
    __mmFoodSpamTimer ||
    __mmAutoHealWasHealing ||
    __mmBuildSpamTimer
  )
    return;
  const __mmTarget = __mmReloadSpikeTarget();
  __mmTarget && __mmPlaceReloadSpike(__mmTarget) && (__mmReloadSpikePlaced = !0);
}
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 __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;
  const __mmGrids = X.getGridArrays(v.x, v.y, Math.max(140, v.scale * 4));
  let __mmClosest = null,
    __mmClosestDistance = Infinity;
  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.trap) continue;
      const __mmDistance =
        (__mmObject.x - v.x) ** 2 + (__mmObject.y - v.y) ** 2;
      __mmDistance < __mmClosestDistance &&
        ((__mmClosestDistance = __mmDistance), (__mmClosest = __mmObject));
    }
  return __mmClosest;
}
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 __mmFacing = Math.atan2(__mmTrap.y - v.y, __mmTrap.x - v.x),
    __mmBehind = __mmFacing + Math.PI,
    __mmSpike = __mmSpikeItem(),
    __mmSpikeCount = 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 = __mmTrapBuildWeapon;
  ((__mmTrapBuildTimer && clearTimeout(__mmTrapBuildTimer),
    (__mmTrapBuildTimer = 0),
    (__mmTrapBuildWeapon = null),
    __mmClearAttempt && (__mmTrapBuildAttemptKey = null),
    __mmWeapon != null && __mmRestoreWeapon(__mmWeapon)));
}
function __mmStartTrapBuildEscape(__mmTrap) {
  if (!v || !v.alive || !v.lockMove || !__mmTrap || __mmTrapBuildTimer) return;
  const __mmTrapKey = __mmTrapBuildKey(__mmTrap);
  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 ||
      !v.lockMove ||
      __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));
    if (__mmIndex < __mmPlan.length) {
      __mmTrapBuildTimer = setTimeout(__mmPlaceNext, __mmServerTickMs());
      return;
    }
    __mmStopTrapBuildEscape(!1);
  };
  __mmTrapBuildTimer = setTimeout(__mmPlaceNext, __mmServerTickMs());
}
function __mmEquipTankForTrap() {
  if (!v || !v.alive || !v.skins || !v.skins[40] || __mmRightClickHat != null)
    return;
  (__mmTrapHat == null && (__mmTrapHat = v.skinIndex),
    v.skinIndex !== 40 && __mmEquipHatNow(40));
}
function __mmRestoreTrapHat() {
  if (__mmTrapHat == null) return;
  if (!v || !v.alive) return void (__mmTrapHat = null);
  if (__mmPrimaryHeld || __mmSecondaryHeld || __mmRightClickHat != null) return;
  const __mmHat = __mmTrapHat;
  ((__mmTrapHat = null),
    v.skinIndex !== __mmHat &&
      __mmCanEquipHat(__mmHat) &&
      __mmEquipHatNow(__mmHat));
}
function __mmStopTrapAttack() {
  (__mmStopTrapBuildEscape(),
    __mmTrapAttackActive &&
    (O.send("F", 0, Ci()),
    (__mmTrapAttackActive = !1),
    __mmRestoreWeapon(__mmTrapWeapon),
    (__mmTrapWeapon = null)),
    (__mmTrapLastSwingAt = 0),
    __mmRestoreTrapHat());
}
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) ||
      !__mmWeaponReady(__mmWeapon) ||
      __mmDistance > __mmTrapWeaponRange(__mmWeapon, __mmTrap)
    )
      continue;
    return __mmWeapon;
  }
  return null;
}
function __mmBreakTrap() {
  if (__mmInsta.isActive()) return void __mmInsta.cancel("trap-escape");
  if (
    !__mmTrapEscapeEnabled ||
    !v ||
    !v.alive ||
    !v.lockMove
  )
    return void __mmStopTrapAttack();
  __mmAutoHeal();
  const __mmTrap = __mmNearestLockingTrap();
  if (__mmTrap == null) return void __mmStopTrapAttack();
  __mmStartTrapBuildEscape(__mmTrap);
  (__mmTrapAttackActive ||
    (__mmPauseSoldierForBreaking(),
    (__mmTrapAttackActive = !0),
    (__mmTrapWeapon = __mmSelectedWeapon()),
    __mmEquipTankForTrap()));
  const __mmWeapon = __mmTrapBreakWeapon(__mmTrap);
  if (__mmWeapon == null) return;
  const __mmNow = Date.now();
  const __mmWeaponData = b.weapons[__mmWeapon];
  const __mmDelay = Math.max(50, Number(__mmWeaponData.speed) || 400);
  if (__mmNow - __mmTrapLastSwingAt < __mmDelay) return;
  const __mmAngle = Math.atan2(__mmTrap.y - v.y, __mmTrap.x - v.x);
  (je(__mmWeapon, !0),
    O.send("F", 1, __mmAngle),
    O.send("F", 0, __mmAngle),
    (__mmTrapLastSwingAt = __mmNow));
}
function __mmStartTrapEscape() {
  __mmTrapAttackTimer ||
    (__mmTrapAttackTimer = setInterval(__mmBreakTrap, __mmServerTickMs()));
}
function __mmStopTrapEscape() {
  (__mmTrapAttackTimer &&
    (clearInterval(__mmTrapAttackTimer), (__mmTrapAttackTimer = 0)),
    __mmStopTrapAttack());
}
function __mmCanAutoSoldier() {
  return (
    __mmSoldierAutoEnabled &&
    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;
  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, __mmServerTickMs()));
}
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 ||
      (__mmPlayer.team && v.team && __mmPlayer.team === v.team)
    )
      continue;
    __mmEnemies.push(__mmAiEnemySnapshot(__mmPlayer));
  }
  __mmEnemies.sort(function (__mmFirst, __mmSecond) {
    return __mmFirst.distance - __mmSecond.distance;
  });
  const __mmAngle = __mmTrapAngle();
  return {
    available: !0,
    modVersion: "3.8.4",
    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: !!v.lockMove,
      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 &&
    v &&
    v.alive &&
    v.weapons.includes(__mmShieldWeapon) &&
    !__mmInsta.isActive() &&
    !__mmPrimaryHeld &&
    !__mmSecondaryHeld &&
    !__mmTrapAttackActive
  );
}
function __mmUseShieldDefense(__mmPlayer) {
  if (!__mmCanUseShieldDefense()) return;
  const __mmDistance = (__mmPlayer.x - v.x) ** 2 + (__mmPlayer.y - v.y) ** 2;
  if (__mmDistance > __mmShieldDefenseRange * __mmShieldDefenseRange) 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 () {
      const __mmWeaponToRestore = __mmShieldDefenseWeapon;
      ((__mmShieldDefenseTimer = 0),
        (__mmShieldDefenseWeapon = null),
        !__mmPrimaryHeld &&
          !__mmSecondaryHeld &&
          !__mmTrapAttackActive &&
          __mmWeaponToRestore != null &&
          __mmWeaponToRestore !== __mmShieldWeapon &&
          __mmRestoreWeapon(__mmWeaponToRestore));
    }, __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 !Number.isFinite(__mmReload) || __mmReload <= 0;
}
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 __mmEquipBullTailForPrimary() {
  if (!v || !v.alive) return;
  if (v.tails && v.tails[__mmCorruptXWings]) {
    (__mmPrimaryClickTail == null && (__mmPrimaryClickTail = v.tailIndex),
      __mmEquipTailNow(__mmCorruptXWings));
  } else
    v.tailIndex === 11 &&
      ((__mmPrimaryClickTail = v.tailIndex), __mmEquipTailNow(0));
}
function __mmEquipBullForPrimary() {
  if (!__mmBullPrimaryAvailable() || !__mmPrimaryWeaponReady()) return;
  (__mmPrimaryClickHat == null && (__mmPrimaryClickHat = v.skinIndex),
    __mmEquipHatNow(7),
    __mmEquipBullTailForPrimary());
}
function __mmRestoreBullForPrimary() {
  if (__mmSecondaryHeld || __mmRightClickHat != null) return;
  if (!v || !v.alive)
    return void ((__mmPrimaryClickHat = null), (__mmPrimaryClickTail = null));
  const __mmHat = __mmPrimaryClickHat,
    __mmTail = __mmPrimaryClickTail;
  ((__mmPrimaryClickHat = null),
    (__mmPrimaryClickTail = null),
    __mmTail != null &&
      v.tailIndex !== __mmTail &&
      (__mmTail === 0 || (v.tails && v.tails[__mmTail])) &&
      __mmEquipTailNow(__mmTail),
    __mmHat != null &&
      v.skinIndex !== __mmHat &&
      (__mmHat === 0 || (v.skins && v.skins[__mmHat])) &&
      __mmEquipHatNow(__mmHat));
}
function __mmFirePrimaryBullWeapon() {
  __mmPrimaryBullArmTimer = 0;
  const __mmWeapon = v && v.weapons ? v.weapons[0] : null;
  if (!__mmPrimaryHeld || !__mmBullPrimaryAvailable() || __mmWeapon == null)
    return (
      (__mmPrimaryBullSwingPending = !1),
      void __mmRestoreBullForPrimary()
    );
  (je(__mmWeapon, !0),
    __mmSendWeaponAttack(1),
    // Hold Bull Helmet across the full left-click for a stable tick macro.
    (__mmPrimaryBullSwingPending = !1));
}
function __mmPulsePrimaryBullWeapon() {
  if (
    !__mmPrimaryHeld ||
    !__mmBullPrimaryAvailable() ||
    !__mmPrimaryWeaponReady() ||
    __mmPrimaryBullSwingPending
  )
    return;
  const __mmWasBull = v.skinIndex === 7;
  __mmEquipBullForPrimary();
  if (__mmPrimaryClickHat == null) return void __mmSendWeaponAttack(1);
  if (__mmWasBull) return (je(v.weapons[0], !0), 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;
  ((__mmPrimaryHeld = !0),
    __mmStartHeldAttackPulse(),
    __mmAtFullHealth() && __mmStopFoodSpam());
}
function __mmStopPrimaryInput() {
  ((__mmPrimaryHeld = !1),
    __mmPrimaryBullArmTimer &&
      (clearTimeout(__mmPrimaryBullArmTimer), (__mmPrimaryBullArmTimer = 0)),
    (__mmPrimaryBullSwingPending = !1),
    __mmStopHeldAttackPulse(),
    __mmSecondaryHeld && __mmPulseHeldAttack(),
    __mmRestoreBullForPrimary(),
    __mmRestoreTrapHat());
}
document.addEventListener(
  "mousedown",
  function (__mmEvent) {
    if (!__mmIsGameClick(__mmEvent) || __mmEvent.button !== 0) return;
    // 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");
    (__mmEvent.preventDefault(),
      __mmEvent.stopImmediatePropagation(),
      __mmStartPrimaryInput());
  },
  !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 __mmSecondary = __mmSecondaryWeapon(),
    __mmData =
      __mmSecondary == null ? null : b && b.weapons && b.weapons[__mmSecondary];
  return __mmSecondary == null
    ? null
    : __mmData && __mmData.projectile != null && v.weapons[0] != null
      ? v.weapons[0]
      : __mmSecondary;
}
function __mmRightClickWeaponReady() {
  const __mmWeapon = __mmRightClickWeapon();
  return __mmWeapon != null && __mmWeaponReady(__mmWeapon);
}
function __mmServerTickMs() {
  return Math.max(
    60,
    Math.ceil(1e3 / Math.max(1, Number(y && y.serverUpdateRate) || 9)),
  );
}
function __mmEquipTankForSecondary() {
  if (
    !__mmTankRightClickEnabled ||
    !v ||
    !v.alive ||
    !__mmRightClickWeaponReady() ||
    !v.skins ||
    !v.skins[40]
  )
    return;
  (__mmRememberNormalHat(),
    __mmRightClickHat == null &&
      (__mmRightClickHat =
        v.skinIndex === 40 ? __mmLastNormalHat : v.skinIndex),
    __mmEquipHatNow(40));
}
function __mmRestoreRightClickHat() {
  if (__mmRightClickHat == null) return;
  if (!v || !v.alive) return void (__mmRightClickHat = null);
  const __mmHat =
    __mmRightClickHat === 40 ? __mmLastNormalHat : __mmRightClickHat;
  ((__mmRightClickHat = null), __mmEquipHatNow(__mmHat));
}
function __mmFireSecondaryTankWeapon() {
  __mmSecondaryTankArmTimer = 0;
  if (!__mmSecondaryHeld || !__mmRightClickWeaponReady())
    return (
      (__mmSecondaryTankSwingPending = !1),
      void __mmRestoreRightClickHat()
    );
  const __mmWeapon = __mmRightClickWeapon();
  if (__mmWeapon == null)
    return (
      (__mmSecondaryTankSwingPending = !1),
      void __mmRestoreRightClickHat()
    );
  (je(__mmWeapon, !0),
    __mmSendWeaponAttack(1),
    // Keep Tank Gear on for the held right-click. Restoring it after every
    // swing caused a tick-by-tick Tank/normal-hat flicker.
    (__mmSecondaryTankSwingPending = !1));
}
function __mmPulseSecondaryWeapon() {
  if (
    !__mmSecondaryHeld ||
    !__mmRightClickWeaponReady() ||
    __mmSecondaryTankSwingPending
  )
    return;
  const __mmWeapon = __mmRightClickWeapon(),
    __mmUseTank = !!(__mmTankRightClickEnabled && v && v.skins && v.skins[40]),
    __mmWasTank = __mmTankGearActive();
  if (__mmWeapon == null) return;
  if (!__mmUseTank)
    return (je(__mmWeapon, !0), void __mmSendWeaponAttack(1));
  __mmEquipTankForSecondary();
  if (__mmRightClickHat == null)
    return (je(__mmWeapon, !0), void __mmSendWeaponAttack(1));
  if (__mmWasTank) 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());
}
function __mmFinishSecondaryInput() {
  (__mmStopSecondary(), __mmRestoreBullForPrimary());
}
document.addEventListener(
  "mousedown",
  function (__mmEvent) {
    if (__mmEvent.button !== 2 || !__mmIsGameClick(__mmEvent))
      return void __mmRestoreRightClickHat();
    __mmInsta.isActive() && __mmInsta.cancel("manual-secondary");
    if (!__mmTankRightClickEnabled || __mmRightClickWeapon() == null)
      return void __mmRestoreRightClickHat();
    (__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) {
    __mmEvent.button === 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(),
    __mmStopWindmillHold(),
    __mmInsta.cancel("window-blur"),
    __mmRestoreBullForPrimary(),
    __mmStopShiftSpeed(),
    __mmRestoreMovementGear());
});
document.addEventListener("visibilitychange", function () {
  document.hidden &&
    (__mmStopPrimaryInput(),
    __mmStopSecondary(),
    __mmStopWindmillHold(),
    __mmInsta.cancel("document-hidden"),
    __mmStopShiftSpeed(),
    __mmRestoreMovementGear());
});
function __mmSendKillMessage() {
  if (!__mmKillMessageEnabled || !__mmKillMessage || !v || !v.alive) return;
  __mmSendChat(__mmKillMessage);
}
__mmStartAutoHeal();
__mmStartTrapEscape();
__mmStartSoldierAuto();
__mmStartMovementGear();
__mmStartMusketRecharge();
__mmStartAutoPurchase();
__mmStartAntiBoostSpikes();
__mmStartThreatTrap();
__mmStartReloadSpike();
$l = function (__mmPlayerSid, __mmHealth) {
  const __mmResult = __mmOriginalHealthUpdate.apply(this, arguments);
  if (v && __mmPlayerSid === v.sid) {
    __mmObserveAutoHealHealth(__mmHealth);
    // R owns a very short attack window. Routine food changes selection and
    // can erase the queued strike, so defer it until cleanup. Critical health
    // still wins and immediately cancels the burst.
    if (__mmInsta.isActive()) {
      __mmInsta.isEmergencyHealth() &&
        __mmInsta.cancel("health-emergency");
    } else __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
  );
};
Pl = function (__mmPlayerSid, __mmAngle, __mmWeapon) {
  __mmTrackTurretGearReload(__mmPlayerSid);
  __mmHandleEnemyPolearmSwing(__mmPlayerSid, __mmWeapon);
  return __mmOriginalPlayerAttack.apply(this, arguments);
};
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 "t==67?void 0: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 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 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],
            ["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(/from"\.\/vendor-[^"]+\.js"/, (specifier) => {
                    const path = specifier.slice(5, -1);
                    return `from"${new URL(path, bundleUrl).href}"`;
                });
            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 interceptGameBundle(script) {
        if (gameScriptHijacked || !script.src || !GAME_BUNDLE.test(new URL(script.src, location.href).pathname)) return;
 
        gameScriptHijacked = true;
        const originalUrl = script.src;
        script.type = "application/x-moomoo-scroll-zoom-blocked";
        script.removeAttribute("src");
        script.remove();
        loadPatchedBundle(originalUrl);
    }
 
    const observer = 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);
                }
            }
        }
    });
 
    observer.observe(document, { childList: true, subtree: true });
    document.querySelectorAll("script[src]").forEach(interceptGameBundle);
    document.addEventListener("readystatechange", () => {
        if (!gameScriptHijacked && document.readyState === "interactive") {
            document.querySelectorAll("script[src]").forEach(interceptGameBundle);
        }
    }, { once: true });
})();