Greasy Fork

Greasy Fork is available in English.

moomoo.io esp

gives you magical powers

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         moomoo.io esp
// @description  gives you magical powers
// @version      1
// @author       Wealthy
// @match        *://*.moomoo.io/*
// @grant        none
// @icon         https://moomoo.io/img/animals/cow_1.png
// @namespace http://greasyfork.icu/users/1347888
// ==/UserScript==

localStorage.setItem("moofoll", true);

const players = [], animals = [];

const property = "team";

Object.defineProperty(Object.prototype, property, {
    get: function() {
        if(this.isPlayer) {
            const player = players.find(player => player.id === this.id);

            !player && players.push(this);
        } else {
            const animal = animals.find(animal => animal.sid === this.sid && animal.src === this.src);

            !animal && animals.push(this);
        }

        return this[`_${property}`];
    },
    set: function(value) {
        this[`_${property}`] = value;
    },
    configurable: true
});

const check = {
    tribe: (owner, { team, sid }) => (owner.sid !== sid && owner.team && owner.team === team),
    owner: ({ wood, stone, food, points }) => (wood || stone || food || points)
}

let ctx, camX, camY, xOffset, yOffset;

const showHealth = (x, y, health, maxHealth) => {
    const text = `HP:${Math.round(health)}/${maxHealth}`;

    ctx.fillStyle = "#fff";
    ctx.lineJoin = "round";
    ctx.font = "20px Hammersmith One";
    ctx.lineWidth = 6;
    ctx.strokeText(text, x - xOffset, y - yOffset);
    ctx.fillText(text, x - xOffset, y - yOffset);
}

const showLine = (x1, y1, x2,y2, stroke = "black", width = 3) => {
    ctx.lineCap = "round";
    ctx.strokeStyle = stroke;
    ctx.lineWidth = width;
    ctx.beginPath();
    ctx.moveTo(x1 - xOffset, y1 - yOffset);
    ctx.lineTo(x2 - xOffset, y2 - yOffset);
    ctx.stroke();
}

const getDistance = (x1, y1, x2, y2) => Math.hypot(x2 - x1, y2 - y1);
const getDirection = (x1, y1, x2, y2) => Math.atan2(y1 - y2, x1 - x2);

const checked = (name) => document.getElementById(`${name}Box`)?.checked;

let owner, tribe, enemies;

const esp = (delta) => {
    if(!players.length) return;

    if(!ctx) {
        const gameCanvas = document.getElementById("gameCanvas");
        ctx = gameCanvas.getContext("2d");
    }

    if(!ctx) return;

    owner = null;
    tribe = [];
    enemies = [];

    for(let player of players) {
        if(player.visible) {
            if(check.owner(player)) {
                owner = player;
            } else if(owner && check.tribe(owner, player)) {
                tribe.push(player);
            } else enemies.push(player);
        }
    }

    if(!owner) return;

    let tmpDist = getDistance(camX, camY, owner.x, owner.y);
    let tmpDir = getDirection(owner.x, owner.y, camX, camY);
    let camSpd = Math.min(tmpDist * 0.01 * delta, tmpDist);

    if (tmpDist > 0.05) {
        camX += camSpd * Math.cos(tmpDir);
        camY += camSpd * Math.sin(tmpDir);
    } else {
        camX = owner.x;
        camY = owner.y;
    }

    xOffset = camX - (1920 / 2);
    yOffset = camY - (1080 / 2);

    if(checked("health")) {
        showHealth(owner.x, owner.y + owner.scale + 66.5, owner.health, owner.maxHealth);

        for(let animal of animals) animal.visible && showHealth(animal.x, animal.y + animal.scale + 66.5, animal.health, animal.maxHealth);
        for(let enemy of enemies) showHealth(enemy.x, enemy.y + enemy.scale + 66.5, enemy.health, enemy.maxHealth);
    }

    if(checked("animal")) for(let animal of animals) animal.visible && showLine(owner.x, owner.y, animal.x, animal.y, "#221abf");
    if(checked("enemy")) for(let enemy of enemies) showLine(owner.x, owner.y, enemy.x, enemy.y, "#000000");
}

let lastUpdate;

const frame = () => {
    requestAnimationFrame(frame);

    let delta = Date.now() - lastUpdate;
    lastUpdate = Date.now();

    esp(delta);
}

frame()

let html = document.createElement("div");
html.innerHTML = `<div class=modal id=simpleModal><div class=modal-content><div class=modal-header><span class=closeBtn>×</span><h2 style=font-size:17px>Settings</h2></div><div class=modal-body style=font-size:15px><div class=flexControl><label class=container>Enemy Radar <input id=enemyBox type=checkbox> <span class=checkmark></span></label> <label class=container>Animal Radar <input id=animalBox type=checkbox> <span class=checkmark></span></label> <label class=container>Show HP <input id=healthBox type=checkbox> <span class=checkmark></span></label></div></div><div class=modal-footer></div></div></div>`
document.body.appendChild(html);

let style = document.createElement("style");
style.type = "text/css";
style.appendChild(document.createTextNode(`.keyPressLow,.menuPrompt{color:#4a4a4a;text-align:center}.keyPressLow{margin-left:8px;font-size:16px;margin-right:8px;height:25px;width:50px;background-color:#fcfcfc;border-radius:3.5px;border:.5px solid #f2f2f2}.menuPrompt{font-size:17px;font-family:"Hammersmith One";flex:0.2;margin-top:10px;display:inline-block}.modal{display:none;position:fixed;z-index:1;left:0;top:0;overflow:auto;height:100%;width:100%}.container,.container input:checked~.checkmark:after{display:block}.modal-content{margin:10% auto;width:40%;box-shadow:0 5px 8px 0 rgba(0,0,0,.2),0 7px 20px 0 rgba(0,0,0,.17);font-size:14px;line-height:1.6}.modal-footer h3,.modal-header h2{margin:0}.modal-header{background:#000;padding:15px;color:#fff;border-top-left-radius:5px;border-top-right-radius:5px}.modal-body{padding:10px 20px;background:#fff}.modal-footer{background:#000;padding:10px;color:#fff;text-align:center;border-bottom-left-radius:5px;border-bottom-right-radius:5px}.closeBtn{float:right;font-size:30px;color:red}.closeBtn:focus,.closeBtn:hover{color:#000;text-decoration:none;cursor:pointer}.container{position:relative;padding-left:35px;margin-bottom:12px;cursor:pointer;font-size:16px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.container input{position:absolute;opacity:0;cursor:pointer;height:0;width:0}.checkmark{position:absolute;top:0;left:0;height:25px;width:25px;background-color:#000}.container:hover input~.checkmark{background-color:#ccc}.container input:checked~.checkmark{background-color:#000}.checkmark:after{content:"";position:absolute;display:none}.container .checkmark:after{left:9px;top:5px;width:5px;height:10px;border:solid #fff;border-width:0 3px 3px 0;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}`))
document.head.appendChild(style);

document.addEventListener("keydown", function(e) {
    if ([113, 27].includes(e.keyCode)){
        if (modal.style.display === "none") {
            modal.style.display = "block";
        } else modal.style.display = "none";
    }
});

let modal = document.getElementById("simpleModal");
let closeBtn = document.getElementsByClassName("closeBtn")[0];

closeBtn.addEventListener("click", () => {
    modal.style.display = "none";
});

window.addEventListener("click", (event) => {
    if(event.target == modal) modal.style.display = "none";
});