Legit OP hack

A low-key pro-style MooMoo mod: scroll zoom (75% start, 15% minimum), autoheal, food spam, quick builds, and weapon controls. Hotkeys: P autoheal, Q food, F trap, V spike, H selected deployable; hold Q/F/V/H to spam. Left click selects primary; right click uses secondary.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         Legit OP hack
// @namespace    https://eclipse-mod.local/
// @version      3.5.0
// @description  A low-key pro-style MooMoo mod: scroll zoom (75% start, 15% minimum), autoheal, food spam, quick builds, and weapon controls. Hotkeys: P autoheal, Q food, F trap, V spike, H selected deployable; hold Q/F/V/H to spam. Left click selects primary; right click uses secondary.
// @match        *://moomoo.io/*
// @match        *://*.moomoo.io/*
// @grant        none
// @run-at       document-start
// @license MIT
// ==/UserScript==

(() => {
    "use strict";

    const MIN_VIEW_MULTIPLIER = 0.5;
    const MAX_VIEW_MULTIPLIER = 1 / 0.15;
    const ZOOM_STEP = 1.1;
    const INDICATOR_ID = "moomoo-scroll-zoom-indicator";
    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 BUNDLE_RETRY_LIMIT = 3;
    const BUNDLE_RETRY_DELAY_MS = 400;
    let viewMultiplier = 1 / 0.75;
    let hideIndicatorTimer = 0;
    let gameScriptHijacked = false;
    let originalBundleLoaded = false;
    window.__MooMooScrollZoomMultiplier = viewMultiplier;

    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"));
    }

    document.addEventListener("wheel", (event) => {
        if (!isGameSurface(event.target) || event.ctrlKey || event.deltaY === 0) return;

        event.preventDefault();
        event.stopImmediatePropagation();
        viewMultiplier = Math.min(
            MAX_VIEW_MULTIPLIER,
            Math.max(MIN_VIEW_MULTIPLIER, viewMultiplier * (event.deltaY > 0 ? ZOOM_STEP : 1 / ZOOM_STEP))
        );
        applyViewportSize();
        showZoomIndicator();
    }, { capture: true, passive: false });

    window.addEventListener("MooMooScrollZoomAutoheal", (event) => {
        showZoomIndicator(`Autoheal: ${event.detail ? "On" : "Off"}`);
    });

    function patchedViewportCode() {
        return [
            "const __mmZoomBaseWidth=y.maxScreenWidth,__mmZoomBaseHeight=y.maxScreenHeight;",
            "let _=y.maxScreenWidth,L=y.maxScreenHeight;",
            "let __mmFoodSpamTimer=0;",
            "let __mmAutoHealTimer=0,__mmAutoHealEnabled=!0,__mmAutoHealWasHealing=!1,__mmLastWeapon=null,__mmAutoHealWeapon=null;",
            "let __mmBuildSpamTimer=0,__mmBuildSpamKey=0;",
            "let __mmSecondaryHeld=!1;",
            "const __mmOriginalSelect=je;je=function(__mmItem,__mmIsWeapon){return __mmIsWeapon&&(__mmLastWeapon=__mmItem),__mmOriginalSelect(__mmItem,__mmIsWeapon)};",
            "function __mmUseFood(){if(v&&v.alive&&v.items[0]!=null){je(v.items[0]),O.send(\"F\",1,Ci()),O.send(\"F\",0,Ci())}}",
            "function __mmAtFullHealth(){return v&&v.alive&&v.health>=v.maxHealth}",
            "function __mmRestorePrimary(){v&&v.alive&&v.weapons[0]!=null&&je(v.weapons[0],!0)}",
            "function __mmRestoreAutoHealWeapon(){if(!v||!v.alive)return;const __mmWeapon=v.weapons.includes(__mmAutoHealWeapon)?__mmAutoHealWeapon:v.weapons.includes(v.weaponIndex)?v.weaponIndex:v.weapons[0];__mmWeapon!=null&&je(__mmWeapon,!0),__mmAutoHealWeapon=null}",
            "function __mmAutoHeal(){if(!__mmAutoHealEnabled||!v||!v.alive)return;if(v.health<v.maxHealth){__mmAutoHealWasHealing||(__mmAutoHealWasHealing=!0,__mmAutoHealWeapon=__mmLastWeapon),__mmUseFood()}else __mmAutoHealWasHealing&&(__mmAutoHealWasHealing=!1,__mmRestoreAutoHealWeapon())}",
            "function __mmToggleAutoHeal(){__mmAutoHealEnabled=!__mmAutoHealEnabled,!__mmAutoHealEnabled&&__mmAutoHealWasHealing&&(__mmAutoHealWasHealing=!1,__mmRestoreAutoHealWeapon()),window.dispatchEvent(new CustomEvent(\"MooMooScrollZoomAutoheal\",{detail:__mmAutoHealEnabled}))}",
            "function __mmStartAutoHeal(){__mmAutoHealTimer||(__mmAutoHealTimer=setInterval(__mmAutoHeal,1e3/y.serverUpdateRate))}",
            "function __mmStartFoodSpam(){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 __mmItem=__mmItemSlot<0?v.buildIndex:v.items[__mmItemSlot];if(__mmItem==null||__mmItem<0||__mmItemSlot<0&&![17,18,19,20,21,22].includes(__mmItem))return;__mmItemSlot>=0&&je(__mmItem),O.send(\"F\",1,Ci()),O.send(\"F\",0,Ci()),__mmRestorePrimary()}",
            "function __mmStopBuildSpam(__mmKey){(!__mmKey||__mmKey==__mmBuildSpamKey)&&(__mmBuildSpamTimer&&clearInterval(__mmBuildSpamTimer),__mmBuildSpamTimer=0,__mmBuildSpamKey=0)}",
            "function __mmStartBuildSpam(__mmItemSlot,__mmKey){if(__mmBuildSpamTimer&&__mmBuildSpamKey==__mmKey)return;__mmStopBuildSpam(),__mmBuildSpamKey=__mmKey,__mmUseBuild(__mmItemSlot),__mmBuildSpamTimer=setInterval(function(){__mmUseBuild(__mmItemSlot)},1e3/y.serverUpdateRate)}",
            "window.addEventListener(\"blur\",__mmStopFoodSpam);",
            "window.addEventListener(\"blur\",function(){__mmStopBuildSpam()});",
            "function __mmIsGameClick(__mmEvent){return __mmEvent.target instanceof Element&&__mmEvent.target.closest(\"#gameCanvas,#touch-controls-fullscreen\")}",
            "document.addEventListener(\"mousedown\",function(__mmEvent){if(!__mmIsGameClick(__mmEvent)||__mmEvent.button!==0&&__mmEvent.button!==2)return;__mmEvent.button===0&&v&&v.alive&&v.weapons[0]!=null&&je(v.weapons[0],!0),__mmAtFullHealth()&&__mmStopFoodSpam()},!0);",
            "function __mmStopSecondary(){__mmSecondaryHeld&&(O.send(\"F\",0,Ci()),__mmSecondaryHeld=!1)}",
            "document.addEventListener(\"mousedown\",function(__mmEvent){if(__mmEvent.button!==2||!__mmIsGameClick(__mmEvent)||!v||!v.alive||v.weapons[1]==null)return;__mmEvent.preventDefault(),__mmEvent.stopImmediatePropagation(),je(v.weapons[1],!0),O.send(\"F\",1,Ci()),__mmSecondaryHeld=!0},!0);",
            "document.addEventListener(\"mouseup\",function(__mmEvent){__mmEvent.button===2&&__mmSecondaryHeld&&(__mmEvent.preventDefault(),__mmEvent.stopImmediatePropagation(),__mmStopSecondary())},!0);",
            "document.addEventListener(\"contextmenu\",function(__mmEvent){__mmIsGameClick(__mmEvent)&&__mmEvent.preventDefault()},!0);",
            "window.addEventListener(\"blur\",__mmStopSecondary);",
            "__mmStartAutoHeal();",
            "window.__MooMooScrollZoomSetViewport=function(__mmZoomMultiplier){",
            "const __mmMultiplier=Math.max(" + MIN_VIEW_MULTIPLIER + ",Math.min(" + MAX_VIEW_MULTIPLIER + ",Number(__mmZoomMultiplier)||1));",
            "_=y.maxScreenWidth=__mmZoomBaseWidth*__mmMultiplier;",
            "L=y.maxScreenHeight=__mmZoomBaseHeight*__mmMultiplier;",
            "bi();",
            "};",
            "setTimeout(function(){window.__MooMooScrollZoomSetViewport(window.__MooMooScrollZoomMultiplier||1)},0);"
        ].join("");
    }

    function patchedHotkeyCode() {
        // Item slots 2 and 4 are the current spike and pit-trap upgrades.
        return "t==80?__mmToggleAutoHeal():t==72?__mmStartBuildSpam(-1,72):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() {
        return "function pl(e){const __mmFoodKey=e.which||e.keyCode||0;__mmFoodKey==81&&__mmStopFoodSpam();(__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");
    }

    async function loadPatchedBundle(originalUrl) {
        try {
            const originalSource = await fetchBundleSource(originalUrl);
            if (!originalSource.includes(VIEWPORT_MARKER) || !originalSource.includes(HOTKEY_MARKER) || !originalSource.includes(FOOD_HOTKEY_MARKER) || !originalSource.includes(FOOD_KEYUP_MARKER)) {
                throw new Error("the game client changed; a required patch marker was not found");
            }

            const bundleUrl = new URL(originalUrl, location.href);
            const patchedSource = originalSource
                .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}"`;
                });
            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);
            patchedScript.onerror = () => {
                URL.revokeObjectURL(blobUrl);
                console.error("[MooMoo Scroll Zoom] patched game bundle could not load; loading the original bundle.");
                loadOriginalBundle(originalUrl);
            };
            (document.head || document.documentElement).appendChild(patchedScript);
        } 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);
})();