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.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

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

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==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);
})();