Greasy Fork is available in English.

moomoo.io esp

gives you magical powers

// ==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 https://greasyfork.org/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";
});