Anti-ban Autohit 🎯 + Real Self Hitbox

Autohit + real tracked hitbox for YOUR player only (toggle H)

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Anti-ban Autohit 🎯 + Real Self Hitbox
// @version      1.3
// @description  Autohit + real tracked hitbox for YOUR player only (toggle H)
// @author       anshu bihari
// @match        https://evoworld.io/
// @icon         https://www.google.com/s2/favicons?sz=64&domain=evoworld.io
// @license      MIT
// @grant        none
// @namespace https://greasyfork.org/users/1536224
// ==/UserScript==
(function() {
    'use strict';

    // ---------- config ----------
    const Height = {'grimReaper':150, 'pumpkinGhost':150, 'ghostlyReaper':150}; // fallback heights
    const ReaperList = new Set(['grimReaper', 'pumpkinGhost', 'ghostlyReaper']);

    // Display and control
    let SHOW_SELF_HITBOX = true; // default visible
    const SHOW_SELF_LABEL = 'HITBOX'; // label for button

    // ---------- overlay ----------
    let overlayCanvas = null;
    let overlayCtx = null;
    function createOverlay() {
        if (overlayCanvas) return;
        overlayCanvas = document.createElement('canvas');
        overlayCanvas.id = 'evoworld-hitbox-overlay';
        overlayCanvas.style.position = 'fixed';
        overlayCanvas.style.left = '0';
        overlayCanvas.style.top = '0';
        overlayCanvas.style.width = '100%';
        overlayCanvas.style.height = '100%';
        overlayCanvas.style.pointerEvents = 'none';
        overlayCanvas.style.zIndex = 9998;
        overlayCanvas.width = window.innerWidth;
        overlayCanvas.height = window.innerHeight;
        document.body.appendChild(overlayCanvas);
        overlayCtx = overlayCanvas.getContext('2d');

        window.addEventListener('resize', () => {
            overlayCanvas.width = window.innerWidth;
            overlayCanvas.height = window.innerHeight;
        });
    }

    // ---------- small toggle button for hitbox ----------

    const hbButton = document.createElement('div');
    hbButton.id = 'hitbox-toggle';
    hbButton.style.position = 'fixed';
    hbButton.style.top = '410px';
    hbButton.style.right = '20px';
    hbButton.style.backgroundColor = '#2196F3';
    hbButton.style.color = 'white';
    hbButton.style.padding = '8px 12px';
    hbButton.style.zIndex = 10000;
    hbButton.style.cursor = 'pointer';
    hbButton.style.borderRadius = '10px';
    hbButton.style.fontFamily = 'Arial, sans-serif';
    hbButton.style.fontSize = '12px';
    hbButton.style.boxShadow = '0 0 6px rgba(0,0,0,0.2)';
    hbButton.innerText = `${SHOW_SELF_LABEL}: ${SHOW_SELF_HITBOX ? 'ON' : 'OFF'}`;
    document.body.appendChild(hbButton);
    hbButton.addEventListener('click', () => {
        SHOW_SELF_HITBOX = !SHOW_SELF_HITBOX;
        hbButton.innerText = `${SHOW_SELF_LABEL}: ${SHOW_SELF_HITBOX ? 'ON' : 'OFF'}`;
        if (SHOW_SELF_HITBOX) startOverlayLoop(); else stopOverlayLoop();
    });

    // also toggle with 'H' key
    document.addEventListener('keydown', (e) => {
        if (e.key && e.key.toLowerCase() === 'h') {
            SHOW_SELF_HITBOX = !SHOW_SELF_HITBOX;
            hbButton.innerText = `${SHOW_SELF_LABEL}: ${SHOW_SELF_HITBOX ? 'ON' : 'OFF'}`;
            if (SHOW_SELF_HITBOX) startOverlayLoop(); else stopOverlayLoop();
            console.log('Self hitbox toggled:', SHOW_SELF_HITBOX);
        }
    });

    // ---------- world -> screen helper (supports camera if available) ----------
    function worldToScreen(pos) {
        try {
            if (!overlayCanvas) createOverlay();

            // Prefer any game-provided camera transform
            if (typeof game !== 'undefined') {
                if (game.camera && typeof game.camera.toScreen === 'function') {
                    const p = game.camera.toScreen(pos);
                    return { x: Math.round(p.x), y: Math.round(p.y) };
                }
                if (game.camera && typeof game.camera.x === 'number' && typeof game.camera.y === 'number') {
                    const zoom = (typeof game.camera.zoom === 'number') ? game.camera.zoom : ((typeof game.camera.scale === 'number') ? game.camera.scale : 1);
                    const screenX = (pos.x - game.camera.x) * zoom + overlayCanvas.width / 2;
                    const screenY = (pos.y - game.camera.y) * zoom + overlayCanvas.height / 2;
                    return { x: Math.round(screenX), y: Math.round(screenY) };
                }
            }

            // fallback: center on player if available
            if (game && game.me && game.me.position) {
                const cx = overlayCanvas.width / 2;
                const cy = overlayCanvas.height / 2;
                const dx = pos.x - game.me.position.x;
                const dy = pos.y - game.me.position.y;
                const zoom = (game && game.renderer && typeof game.renderer.scale === 'number') ? game.renderer.scale : 1;
                return { x: Math.round(cx + dx * zoom), y: Math.round(cy + dy * zoom) };
            }

            // last fallback: raw coords
            return { x: Math.round(pos.x), y: Math.round(pos.y) };
        } catch (e) {
            return { x: pos.x, y: pos.y };
        }
    }

    // ---------- get real box size for an entity (world-space) ----------
    function getEntityBoxSize(ent) {
        if (!ent) return { w: 40, h: 80 };
        if (typeof ent.hitboxWidth === 'number' && typeof ent.hitboxHeight === 'number') {
            return { w: ent.hitboxWidth, h: ent.hitboxHeight };
        }
        if (typeof ent.width === 'number' && typeof ent.height === 'number') {
            return { w: ent.width, h: ent.height };
        }
        if (ent.size && typeof ent.size.x === 'number' && typeof ent.size.y === 'number') {
            return { w: ent.size.x, h: ent.size.y };
        }
        if (ent.name && Height[ent.name]) {
            const h = Height[ent.name];
            return { w: Math.max(30, h * 0.6), h: h };
        }
        return { w: 40, h: 80 };
    }

    // ---------- draw only YOUR hitbox ----------
    function drawMyHitbox() {
        if (!overlayCtx || !game || !game.me || !game.me.position) return;
        if (!SHOW_SELF_HITBOX) return;

        const me = game.me;
        const screen = worldToScreen(me.position);
        const size = getEntityBoxSize(me);

        // try to get scale from camera/renderer to draw correct pixel size
        let scale = 1;
        try {
            if (game && game.camera && typeof game.camera.zoom === 'number') scale = game.camera.zoom;
            else if (game && game.renderer && typeof game.renderer.scale === 'number') scale = game.renderer.scale;
        } catch (e) { scale = 1; }

        const w = size.w * scale;
        const h = size.h * scale;
        const x = screen.x - w / 2;
        const y = screen.y - h / 2;

        overlayCtx.beginPath();
        overlayCtx.rect(x, y, w, h);
        overlayCtx.fillStyle = 'rgba(255,0,0,0.14)';
        overlayCtx.fill();
        overlayCtx.lineWidth = Math.max(1, 2 * scale);
        overlayCtx.strokeStyle = 'rgba(255,0,0,0.95)';
        overlayCtx.stroke();

        // label
        overlayCtx.font = `${12 * Math.max(1, scale)}px Arial`;
        overlayCtx.fillStyle = 'rgba(255,0,0,0.95)';
        overlayCtx.textAlign = 'center';
        overlayCtx.fillText('YOU', screen.x, y - 6 * scale);
    }

    // ---------- draw loop only for self hitbox ----------
    function drawAllHitboxes() {
        if (!overlayCtx) return;
        overlayCtx.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height);
        drawMyHitbox();
    }

    let overlayRAF = null;
    function startOverlayLoop() {
        if (!overlayCanvas) createOverlay();
        if (overlayRAF) return;
        function loop() {
            try { drawAllHitboxes(); } catch (e) {}
            overlayRAF = requestAnimationFrame(loop);
        }
        loop();
    }
    function stopOverlayLoop() {
        if (overlayRAF) cancelAnimationFrame(overlayRAF);
        overlayRAF = null;
        if (overlayCtx && overlayCanvas) {
            overlayCtx.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height);
        }
    }

    // ---------- HIT DETECTION: use entity box extents for real overlap ----------
    function getHalfExtents(ent) {
        const s = getEntityBoxSize(ent);
        return { halfW: s.w / 2, halfH: s.h / 2 };
    }

    // Updated X-range check: we compare box edges rather than center-to-center only.
    function isWithinXRange(attacker, target, rangeTable, distAdjustment = 0) {
        if (!attacker || !target) return false;
        const aX = attacker.position.x;
        const bX = target.position.x;

        const aHalf = getHalfExtents(attacker).halfW;
        const bHalf = getHalfExtents(target).halfW;

        var relativeSpeed = Math.abs((attacker.moveSpeed && attacker.moveSpeed.x) ? attacker.moveSpeed.x : 0 - ((target.moveSpeed && target.moveSpeed.x) ? target.moveSpeed.x : 0));
        const frameTime = (typeof lastFps === 'number' && lastFps > 0) ? (1000 / lastFps) : 16;
        const serverDelay = (typeof latency === 'number') ? latency : 0;
        const totalDelay = frameTime + serverDelay;

        // distance between box edges along X (0 or negative means overlap)
        var centerDist = Math.abs(bX - aX);
        var edgeGap = centerDist - (aHalf + bHalf);
        var effectiveDist = edgeGap - totalDelay * relativeSpeed / 1000 + distAdjustment;

        // fallback to name-based range if table exists
        let allowedRange = 0;
        try {
            if (rangeTable && attacker.name && target.name && rangeTable[attacker.name] && typeof rangeTable[attacker.name][target.name] !== 'undefined') {
                allowedRange = rangeTable[attacker.name][target.name];
            }
        } catch (e) { allowedRange = 0; }

        return effectiveDist <= allowedRange;
    }

    // Updated Y-range check: use box extents vertically
    function isWithinYRange(attacker, target, heights, distAdjustment = 0) {
        if (!attacker || !target) return false;
        const aY = attacker.position.y;
        const bY = target.position.y;

        const aHalf = getHalfExtents(attacker).halfH;
        const bHalf = getHalfExtents(target).halfH;

        var relativeSpeed = Math.abs((attacker.moveSpeed && attacker.moveSpeed.y) ? attacker.moveSpeed.y : 0 - ((target.moveSpeed && target.moveSpeed.y) ? target.moveSpeed.y : 0));
        const frameTime = (typeof lastFps === 'number' && lastFps > 0) ? (1000 / lastFps) : 16;
        const serverDelay = (typeof latency === 'number') ? latency : 0;
        const totalDelay = frameTime + serverDelay;

        var centerDist = Math.abs(bY - aY);
        var edgeGap = centerDist - (aHalf + bHalf);
        var effectiveDist = edgeGap - totalDelay * relativeSpeed / 1000 + distAdjustment;

        // heights table fallback
        let allowedRangeY = 0;
        try {
            if (heights && attacker.name && target.name) {
                allowedRangeY = heights[target.name] || heights[attacker.name] || 0;
            }
        } catch (e) { allowedRangeY = 0; }

        return effectiveDist <= allowedRangeY;
    }

    // ---------- preserved autohit logic (calls new isWithinXRange/YRange) ----------
    // NOTE: uses HitRangeX, HitBackRangeX, Height from your previous code. Keep them defined above to match old behavior.
    const HitRangeX = {'grimReaper':{'grimReaper':140, 'pumpkinGhost':140, 'ghostlyReaper':140},
                      'pumpkinGhost':{'grimReaper':140, 'pumpkinGhost':140, 'ghostlyReaper':140},
                      'ghostlyReaper':{'grimReaper':140, 'pumpkinGhost':140, 'ghostlyReaper':140}
    };
    const HitBackRangeX = {'grimReaper':{'grimReaper':141, 'pumpkinGhost':141, 'ghostlyReaper':141},
                          'pumpkinGhost':{'grimReaper':141, 'pumpkinGhost':141, 'ghostlyReaper':141},
                          'ghostlyReaper':{'grimReaper':141, 'pumpkinGhost':141, 'ghostlyReaper':141}
    };

    function simulateQuickRightArrowKeyWithDelay() {
        const keyDownEvent = new KeyboardEvent('keydown', {
            key: 'ArrowRight',
            code: 'ArrowRight',
            keyCode: 39,
            which: 39,
            bubbles: true,
            cancelable: true
        });
        document.dispatchEvent(keyDownEvent);

        setTimeout(() => {
            const keyUpEvent = new KeyboardEvent('keyup', {
                key: 'ArrowRight',
                code: 'ArrowRight',
                keyCode: 39,
                which: 39,
                bubbles: true,
                cancelable: true
            });
            document.dispatchEvent(keyUpEvent);
        }, 35);
    }

    function simulateQuickLeftArrowKeyWithDelay() {
        const keyDownEvent = new KeyboardEvent('keydown', {
            key: 'ArrowLeft',
            code: 'ArrowLeft',
            keyCode: 37,
            which: 37,
            bubbles: true,
            cancelable: true
        });
        document.dispatchEvent(keyDownEvent);

        setTimeout(() => {
            const keyUpEvent = new KeyboardEvent('keyup', {
                key: 'ArrowLeft',
                code: 'ArrowLeft',
                keyCode: 37,
                which: 37,
                bubbles: true,
                cancelable: true
            });
            document.dispatchEvent(keyUpEvent);
        }, 35);
    }

    function getMagnitude(objPos) {
        var myPos = game.me.position;
        var xDifference = Math.abs(myPos.x - objPos.x);
        var yDifference = Math.abs(myPos.y - objPos.y);
        return xDifference + yDifference;
    }

    function getClosestReaper() {
        if (gameServer == 'undefined' || game.me == 'undefined' || imDead || !joinedGame) {
            return;
        }

        let list = game.sortToDraw(game.hashMap.retrieveVisibleByClient(game));
        let reaperInVision = [];
        for(let i=0; i < list.length; i++) {
            var curEntity = list[i];
            if (curEntity.hp != null && curEntity.deleted == false) {
                if (curEntity.level != null) {
                    if (!ReaperList.has(curEntity.name)) continue;
                    if (curEntity == game.me) { continue;
                    }

                    reaperInVision.push(curEntity);
                }
            }
        }

        var closestReaper = 'undefined';
        var closestMagn = 'undefined';
        for(var i = 0; i < reaperInVision.length; i++) {
            var curEntry = reaperInVision[i];
            if (closestReaper === 'undefined') {
                closestReaper = curEntry;
                closestMagn = getMagnitude(curEntry.position);
            } else {
                var checkingMagn = getMagnitude(curEntry.position);
                if (checkingMagn < closestMagn) {
                    closestReaper = curEntry;
                    closestMagn = checkingMagn;
                }
            }
        }
        return closestReaper;
    };

    function autoHit(){
        let enemy=getClosestReaper();
        if (typeof enemy != 'object' || typeof game.me != 'object' || !ReaperList.has(game.me.name)){
            return;
        }

        let onLeftSide = (game.me.position.x<=enemy.position.x);
        let enemyFlicking = (onLeftSide && enemy.direction===1) || (!onLeftSide && enemy.direction===-1);
        let facingEnemy = (onLeftSide && game.me.direction===1) || (!onLeftSide && game.me.direction===-1);

        if (!flicking){
            facingEnemy=true;
        }

        if (facingEnemy){
            if (enemyFlicking){
                if (isWithinXRange(game.me, enemy, HitBackRangeX) && isWithinYRange(game.me, enemy, Height)){
                    skillUse();
                    setTimeout(skillStop,100);
                }
            } else if (!enemyFlicking){
                if (isWithinXRange(game.me, enemy, HitRangeX) && isWithinYRange(game.me, enemy, Height)){
                    skillUse();
                    setTimeout(skillStop,100);
                }
            }
        } else if (!facingEnemy){
            if (enemyFlicking){
                if (isWithinXRange(game.me, enemy, HitBackRangeX, -25) && isWithinYRange(game.me, enemy, Height)){
                    if (onLeftSide){
                        simulateQuickRightArrowKeyWithDelay();
                        skillUse();
                        setTimeout(skillStop,100);
                    } else if (!onLeftSide){
                        simulateQuickLeftArrowKeyWithDelay();
                        skillUse();
                        setTimeout(skillStop,100);
                    }
                }
            } else if (!enemyFlicking){
                if (isWithinXRange(game.me, enemy, HitRangeX ,-5) && isWithinYRange(game.me, enemy, Height)){
                    if (onLeftSide){
                        simulateQuickRightArrowKeyWithDelay();
                        skillUse();
                        setTimeout(skillStop,100);
                    } else if (!onLeftSide){
                        simulateQuickLeftArrowKeyWithDelay();
                        skillUse();
                        setTimeout(skillStop,100);
                    }
                }
            }
        }
    }

    // ---------- UI toggle for autohit (existing) ----------
    let autoHitting = false;
    let flicking = false;
    const button = document.createElement("div");
    button.id = "autohit-toggle";
    button.style.position = "fixed";
    button.style.top = "450px";
    button.style.right = "20px";
    button.style.backgroundColor = "#f44336";
    button.style.color = "white";
    button.style.padding = "15px 25px";
    button.style.zIndex = 9999;
    button.style.cursor = "pointer";
    button.style.borderRadius = "15px";
    button.style.fontFamily = "Arial, sans-serif";
    button.style.fontWeight = "bold";
    button.style.boxShadow = "0 0 10px rgba(0,0,0,0.3)";
    button.innerHTML = `<div style="text-align:center;">AUTOHIT: OFF<br><span style="font-weight:normal;">Made by ANSHU BIHARI</span></div>`;
    document.body.appendChild(button);
    button.addEventListener("click", () => {
        autoHitting = !autoHitting;
        flicking = autoHitting;
        button.style.backgroundColor = autoHitting ? "#4CAF50" : "#f44336";
        button.innerHTML = `<div style="text-align:center;">AUTOHIT: ${autoHitting ? "ON" : "OFF"}<br><span style="font-weight:normal;">Made by Business</span></div>`;
        console.log('Autohitting:', autoHitting, 'Flicking:', flicking);
        if (autoHitting) startOverlayLoop();
        else if (!SHOW_SELF_HITBOX) stopOverlayLoop();
    });

    document.addEventListener("keyup", (event) => {
        if (event.keyCode === 73) {
            let closest = getClosestReaper();
            if (closest) {
                console.log(game.me.position.x-getClosestReaper().position.x);
                console.log(game.me.position.y-getClosestReaper().position.y);
            }
        } else if (event.keyCode === 32) {
            console.log('time to start/stop');
            skillStop();
        } else if (event.keyCode === 40) {
            autoHitting = !autoHitting;
            flicking = autoHitting;
            button.style.backgroundColor = autoHitting ? "#4CAF50" : "#f44336";
            button.innerHTML = `<div style="text-align:center;">AUTOHIT: ${autoHitting ? "ON" : "OFF"}<br><span style="font-weight:normal;">Made by Business</span></div>`;
            console.log('Toggled Autohitting by Arrow Down:', autoHitting);
            if (button.style.display === "none") button.style.display = "block";
            if (autoHitting) startOverlayLoop();
            else if (!SHOW_SELF_HITBOX) stopOverlayLoop();
        } else if (event.keyCode === 82) {
            autoHitting = !autoHitting;
            flicking = autoHitting;
            button.style.backgroundColor = autoHitting ? "#4CAF50" : "#f44336";
            button.innerHTML = `<div style="text-align:center;">AUTOHIT: ${autoHitting ? "ON" : "OFF"}<br><span style="font-weight:normal;">Made by Business</span></div>`;
            console.log('Toggled Autohitting by R:', autoHitting);
            if (button.style.display === "none") button.style.display = "block";
            if (autoHitting) startOverlayLoop();
            else if (!SHOW_SELF_HITBOX) stopOverlayLoop();
        }
    });

    // ---------- init and server hooks ----------
    try {
        console.log("Trying to make whole script work!!");
    } catch (bananamelon) {
        console.error("Trying to make whole script work!!");
    }

    function initialize() {
        createOverlay();
        if (SHOW_SELF_HITBOX || autoHitting) startOverlayLoop();

        gameServer['on']('disconnect', function() {
            gameServer = undefined;
            WaitForGameServer();
        });

        if (typeof gameServer.on === 'function') {
            gameServer['on'](socketMsgType.SYNC, function(data) {
                if (autoHitting) autoHit();
                try { if (SHOW_SELF_HITBOX) drawAllHitboxes(); } catch (e) {}
            });
        } else {
            console.error('gameServerOn is not a function');
        }
    };

    function WaitForGameServer() {
        if (typeof gameServer === 'undefined' || typeof gameServer['on'] === 'undefined') {
            setTimeout(WaitForGameServer, 1000);
        } else {
            initialize();
        }
    }

    WaitForGameServer();
})();