EmirClientLite

Simple UI with ESP lines and basic autofarm for diep.io[FULL VERSION IN MY DISCORD]

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

Vous devrez installer une extension telle que Tampermonkey pour installer ce 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         EmirClientLite
// @description  Simple UI with ESP lines and basic autofarm for diep.io[FULL VERSION IN MY DISCORD]
// @version      0.1.0
// @author       EmirtheBoss
// @match        https://diep.io/*
// @run-at       document-start
// @grant        none
// @license      Copyright EmirtheBoss
// @namespace https://greasyfork.org/users/1544163
// ==/UserScript==

(function () {
    "use strict";

    const CONFIG = {
        visuals: {
            esp: true,
            espLines: true,
            lineWidth: 2,
            lineColor: "#af52de",
        },
        autofarm: {
            enabled: false,
            priority: "pentagon",
            fire: true,
        },
        keys: {
            toggleMenu: "KeyM",
            toggleEsp: "KeyL",
            toggleAutofarm: "KeyJ",
        },
    };

    let gameCanvas = null;
    let overlayCanvas = null;
    let overlayCtx = null;

    function createOverlay() {
        if (overlayCanvas) return;
        overlayCanvas = document.createElement("canvas");
        overlayCanvas.style.position = "fixed";
        overlayCanvas.style.top = "0";
        overlayCanvas.style.left = "0";
        overlayCanvas.style.width = "100%";
        overlayCanvas.style.height = "100%";
        overlayCanvas.style.pointerEvents = "none";
        overlayCanvas.style.zIndex = "999998";
        overlayCanvas.id = "emirclientlite-overlay";
        document.body.appendChild(overlayCanvas);
        overlayCtx = overlayCanvas.getContext("2d");
        resizeOverlay();
        window.addEventListener("resize", resizeOverlay);
    }

    function resizeOverlay() {
        if (!overlayCanvas) return;
        overlayCanvas.width = window.innerWidth * window.devicePixelRatio;
        overlayCanvas.height = window.innerHeight * window.devicePixelRatio;
        overlayCtx.setTransform(1, 0, 0, 1, 0, 0);
    }

    let menuContainer = null;

    function createMenu() {
        if (menuContainer) return;

        menuContainer = document.createElement("div");
        menuContainer.id = "emirclientlite-menu";
        Object.assign(menuContainer.style, {
            position: "fixed",
            top: "60px",
            left: "60px",
            width: "230px",
            background: "rgba(15,15,20,0.95)",
            border: "1px solid #2f2f2f",
            borderRadius: "6px",
            boxShadow: "0 0 12px rgba(0,0,0,0.7)",
            color: "#e0e0e0",
            fontFamily: "Segoe UI, Arial, sans-serif",
            fontSize: "13px",
            zIndex: "999999",
            userSelect: "none",
            padding: "8px 10px",
            display: "none",
        });

        const header = document.createElement("div");
        header.textContent = "EmirClientLite Controls";
        Object.assign(header.style, {
            textAlign: "center",
            fontWeight: "600",
            marginBottom: "6px",
            cursor: "move",
            borderBottom: "1px solid #2f2f2f",
            paddingBottom: "4px",
        });
        menuContainer.appendChild(header);

        function addToggle(label, id, hint) {
            const wrap = document.createElement("label");
            Object.assign(wrap.style, {
                display: "flex",
                alignItems: "center",
                margin: "4px 0",
                cursor: "pointer",
            });

            const cb = document.createElement("input");
            cb.type = "checkbox";
            cb.id = id;
            Object.assign(cb.style, {
                marginRight: "8px",
                accentColor: "#00b4ff",
            });

            const text = document.createElement("span");
            text.textContent = label + (hint ? " (" + hint + ")" : "");

            wrap.appendChild(cb);
            wrap.appendChild(text);
            menuContainer.appendChild(wrap);
            return cb;
        }

        const espCheckbox = addToggle("ESP Lines", "emirclientlite-esp", "L");
        const autofarmCheckbox = addToggle("Autofarm", "emirclientlite-autofarm", "J");

        const priorityHeader = document.createElement("div");
        priorityHeader.textContent = "Farming Priority";
        Object.assign(priorityHeader.style, {
            marginTop: "6px",
            marginBottom: "2px",
            fontWeight: "500",
        });
        menuContainer.appendChild(priorityHeader);

        function addRadio(label, value) {
            const wrap = document.createElement("label");
            Object.assign(wrap.style, {
                display: "flex",
                alignItems: "center",
                margin: "2px 0",
                cursor: "pointer",
            });

            const rb = document.createElement("input");
            rb.type = "radio";
            rb.name = "emirclientlite-priority";
            rb.value = value;
            rb.style.marginRight = "6px";
            rb.style.accentColor = "#00b4ff";

            const text = document.createElement("span");
            text.textContent = label;

            wrap.appendChild(rb);
            wrap.appendChild(text);
            menuContainer.appendChild(wrap);
            return rb;
        }

        const rbPenta = addRadio("Pentagons", "pentagon");
        const rbSquare = addRadio("Squares", "square");
        const rbTri = addRadio("Triangles", "triangle");

        document.body.appendChild(menuContainer);

        (function makeDraggable() {
            let dragging = false;
            let offsetX = 0;
            let offsetY = 0;

            header.addEventListener("mousedown", (e) => {
                dragging = true;
                const rect = menuContainer.getBoundingClientRect();
                offsetX = e.clientX - rect.left;
                offsetY = e.clientY - rect.top;
                e.preventDefault();
            });

            window.addEventListener("mousemove", (e) => {
                if (!dragging) return;
                menuContainer.style.left = e.clientX - offsetX + "px";
                menuContainer.style.top = e.clientY - offsetY + "px";
            });

            window.addEventListener("mouseup", () => {
                dragging = false;
            });
        })();

        espCheckbox.checked = CONFIG.visuals.esp && CONFIG.visuals.espLines;
        autofarmCheckbox.checked = CONFIG.autofarm.enabled;
        if (CONFIG.autofarm.priority === "pentagon") rbPenta.checked = true;
        else if (CONFIG.autofarm.priority === "square") rbSquare.checked = true;
        else rbTri.checked = true;

        espCheckbox.addEventListener("change", () => {
            const val = espCheckbox.checked;
            CONFIG.visuals.esp = val;
            CONFIG.visuals.espLines = val;
            console.log("[EmirClientLite] ESP Lines " + (val ? "ON" : "OFF"));
        });

        autofarmCheckbox.addEventListener("change", () => {
            CONFIG.autofarm.enabled = autofarmCheckbox.checked;
            console.log("[EmirClientLite] Autofarm " + (CONFIG.autofarm.enabled ? "ON" : "OFF"));
        });

        [rbPenta, rbSquare, rbTri].forEach((rb) => {
            rb.addEventListener("change", () => {
                if (!rb.checked) return;
                CONFIG.autofarm.priority = rb.value;
                console.log("[EmirClientLite] Priority: " + rb.value);
            });
        });
    }

    function setupKeybinds() {
        window.addEventListener("keydown", (e) => {
            if (e.repeat) return;

            if (e.code === CONFIG.keys.toggleMenu) {
                if (!menuContainer) return;
                const hidden = menuContainer.style.display === "none";
                menuContainer.style.display = hidden ? "block" : "none";
                e.preventDefault();
            }

            if (e.code === CONFIG.keys.toggleEsp) {
                const newVal = !(CONFIG.visuals.esp && CONFIG.visuals.espLines);
                CONFIG.visuals.esp = newVal;
                CONFIG.visuals.espLines = newVal;
                const cb = document.getElementById("emirclientlite-esp");
                if (cb) cb.checked = newVal;
                console.log("[EmirClientLite] ESP Lines " + (newVal ? "ON" : "OFF"));
                e.preventDefault();
            }

            if (e.code === CONFIG.keys.toggleAutofarm) {
                CONFIG.autofarm.enabled = !CONFIG.autofarm.enabled;
                const cb = document.getElementById("emirclientlite-autofarm");
                if (cb) cb.checked = CONFIG.autofarm.enabled;
                console.log("[EmirClientLite] Autofarm " + (CONFIG.autofarm.enabled ? "ON" : "OFF"));
                e.preventDefault();
            }
        });
    }

    const origGetById = Document.prototype.getElementById;
    Document.prototype.getElementById = function (id) {
        const el = origGetById.call(this, id);
        if (id === "canvas" && el && el.tagName === "CANVAS") {
            gameCanvas = el;
            if (document.readyState === "complete" || document.readyState === "interactive") {
                createOverlay();
            } else {
                window.addEventListener("DOMContentLoaded", createOverlay);
            }
        }
        return el;
    };

    const origCreateEl = Document.prototype.createElement;
    Document.prototype.createElement = function (tag) {
        const el = origCreateEl.call(this, tag);
        if (tag === "canvas" && el.id === "canvas") {
            gameCanvas = el;
            if (document.readyState === "complete" || document.readyState === "interactive") {
                createOverlay();
            } else {
                window.addEventListener("DOMContentLoaded", createOverlay);
            }
        }
        return el;
    };

    if (document.readyState === "complete" || document.readyState === "interactive") {
        createMenu();
    } else {
        window.addEventListener("DOMContentLoaded", createMenu);
    }
    setupKeybinds();

    const EntityType = {
        Square: "square",
        Triangle: "triangle",
        Pentagon: "pentagon",
        Player: "player",
        Unknown: "unknown",
    };

    const entities = [];
    let lastFrameTime = performance.now();

    function clearEntities() {
        entities.length = 0;
    }

    function centroid(verts) {
        let sx = 0, sy = 0;
        if (!verts.length) return { x: 0, y: 0 };
        for (const v of verts) {
            sx += v.x;
            sy += v.y;
        }
        return { x: sx / verts.length, y: sy / verts.length };
    }

    const origGetContext = HTMLCanvasElement.prototype.getContext;
    HTMLCanvasElement.prototype.getContext = function (type, ...args) {
        const ctx = origGetContext.call(this, type, ...args);
        if (this.id !== "canvas" || type !== "2d" || !ctx) return ctx;

        let currentVerts = [];
        let collecting = false;

        const origBeginPath = ctx.beginPath;
        const origMoveTo = ctx.moveTo;
        const origLineTo = ctx.lineTo;
        const origFill = ctx.fill;
        const origArc = ctx.arc;

        ctx.beginPath = function (...a) {
            collecting = true;
            currentVerts = [];
            return origBeginPath.apply(this, a);
        };

        ctx.moveTo = function (x, y) {
            if (collecting) currentVerts.push({ x, y });
            return origMoveTo.call(this, x, y);
        };

        ctx.lineTo = function (x, y) {
            if (collecting) currentVerts.push({ x, y });
            return origLineTo.call(this, x, y);
        };

                ctx.fill = function (...a) {
            if (collecting && currentVerts.length >= 3) {
                const c = centroid(currentVerts);
                const t = this.getTransform();
                const worldX = t.a * c.x + t.c * c.y + t.e;
                const worldY = t.b * c.x + t.d * c.y + t.f;

                let type = EntityType.Unknown;
                const n = currentVerts.length;
                if (n === 3) type = EntityType.Triangle;
                else if (n === 4) type = EntityType.Square;
                else if (n === 5) type = EntityType.Pentagon;

                entities.push({
                    type,
                    x: worldX,
                    y: worldY,
                });
            }
            collecting = false;
            currentVerts = [];
            return origFill.apply(this, a);
        };


        ctx.arc = function (x, y, r, ...rest) {
            return origArc.call(this, x, y, r, ...rest);
        };

        return ctx;
    };

    function redrawESP() {
        if (!overlayCtx || !gameCanvas) return;
        const now = performance.now();
        const dt = now - lastFrameTime;
        lastFrameTime = now;

        overlayCtx.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height);

        if (!CONFIG.visuals.esp || !CONFIG.visuals.espLines) return;

        const centerX = overlayCanvas.width / 2;
        const centerY = overlayCanvas.height / 2;

        overlayCtx.save();
        overlayCtx.lineWidth = CONFIG.visuals.lineWidth * window.devicePixelRatio;

        for (const ent of entities) {
            if (
                ent.type !== EntityType.Square &&
                ent.type !== EntityType.Triangle &&
                ent.type !== EntityType.Pentagon
            ) continue;

            // Pick color per shape type
            if (ent.type === EntityType.Square) {
                overlayCtx.strokeStyle = "#ffe869"; // yellow square
            } else if (ent.type === EntityType.Triangle) {
                overlayCtx.strokeStyle = "#fc7677"; // red triangle
            } else if (ent.type === EntityType.Pentagon) {
                overlayCtx.strokeStyle = "#768dfc"; // blue pentagon
            }

            overlayCtx.beginPath();
            overlayCtx.moveTo(centerX, centerY);
            overlayCtx.lineTo(ent.x, ent.y);
            overlayCtx.stroke();
        }

        overlayCtx.restore();

    }

    function sendMouse(x, y) {
        if (!gameCanvas) return;
        const rect = gameCanvas.getBoundingClientRect();
        const clientX = rect.left + x;
        const clientY = rect.top + y;
        const moveEvt = new MouseEvent("mousemove", {
            clientX,
            clientY,
            bubbles: true,
            cancelable: true,
        });
        gameCanvas.dispatchEvent(moveEvt);
    }

    function mouseDown() {
        const down = new MouseEvent("mousedown", {
            button: 0,
            bubbles: true,
            cancelable: true,
        });
        window.dispatchEvent(down);
    }

    function mouseUp() {
        const up = new MouseEvent("mouseup", {
            button: 0,
            bubbles: true,
            cancelable: true,
        });
        window.dispatchEvent(up);
    }

    let autofireTimer = 0;

    function runAutofarm(dt) {
        if (!CONFIG.autofarm.enabled || !gameCanvas) return;
        if (!entities.length) return;

        const canvasCenterX = gameCanvas.clientWidth / 2;
        const canvasCenterY = gameCanvas.clientHeight / 2;

        const targetType = CONFIG.autofarm.priority;
        let candidates = entities.filter((e) => {
            if (targetType === "pentagon") return e.type === EntityType.Pentagon;
            if (targetType === "square") return e.type === EntityType.Square;
            if (targetType === "triangle") return e.type === EntityType.Triangle;
            return false;
        });

        if (!candidates.length) {
            candidates = entities.filter(
                (e) =>
                    e.type === EntityType.Pentagon ||
                    e.type === EntityType.Square ||
                    e.type === EntityType.Triangle
            );
        }
        if (!candidates.length) return;

        let best = null;
        let bestDist = Infinity;
        for (const e of candidates) {
            const dx = e.x - canvasCenterX * window.devicePixelRatio;
            const dy = e.y - canvasCenterY * window.devicePixelRatio;
            const d = Math.hypot(dx, dy);
            if (d < bestDist) {
                bestDist = d;
                best = e;
            }
        }
        if (!best) return;

        const rect = gameCanvas.getBoundingClientRect();
        const targetScreenX = best.x / window.devicePixelRatio;
        const targetScreenY = best.y / window.devicePixelRatio;

        sendMouse(targetScreenX, targetScreenY);

        autofireTimer += dt;
        if (CONFIG.autofarm.fire && autofireTimer >= 120) {
            autofireTimer = 0;
            mouseDown();
            setTimeout(mouseUp, 40);
        }
    }

    function mainLoop() {
        const now = performance.now();
        const dt = now - lastFrameTime;

        redrawESP();
        runAutofarm(dt);
        clearEntities();

        requestAnimationFrame(mainLoop);
    }

    function startLoopWhenReady() {
        if (!overlayCanvas) {
            requestAnimationFrame(startLoopWhenReady);
            return;
        }
        lastFrameTime = performance.now();
        requestAnimationFrame(mainLoop);
    }
    startLoopWhenReady();

})();