Anti-ban Autohit 🎯 + Real Self Hitbox

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

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 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();
})();