EmirClientLite

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

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да инсталирате разширение, като например Tampermonkey .

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

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

})();