CowzHacks

Auto farm, zoom, xray and other

Du musst eine Erweiterung wie Tampermonkey, Greasemonkey oder Violentmonkey installieren, um dieses Skript zu installieren.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

Sie müssten eine Skript Manager Erweiterung installieren damit sie dieses Skript installieren können

(Ich habe schon ein Skript Manager, Lass mich es installieren!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name        CowzHacks
// @namespace   Violentmonkey Scripts
// @match       *://cowz.io/*
// @icon        https://cowz.io/favicon.ico
// @grant       unsafeWindow
// @version     0.2
// @author      Drik
// @description Auto farm, zoom, xray and other
// @run-at      document-start
// @license     MIT
// ==/UserScript==

// version 0.2: better auto farm, new auto loot, better aimbot, upraged all functions

(() => {
    'use strict';

    const uw = typeof unsafeWindow !== 'undefined' ? unsafeWindow : window;

    const MIN_Z = 0x0,
        MAX_Z = 0x14,
        STEP = 0x1 / 0x2;

    const CELL = 0x18;
    const WORLD = 0x400;
    const GRID_N = Math.ceil(WORLD / CELL);

    const ARRIVE_DIST = 0xC;
    const REPLAN_TICKS = 0x5A;
    const STUCK_FRAMES = 0x96;
    const NAV_STUCK_MOVE = 0x4;
    const PHASE_TIMEOUT = 0x3C;
    const ATTACK_TIMEOUT = 0x258;
    const LOOT_TIMEOUT = 0xC8;
    const WANDER_TIMEOUT = 0x190;
    const DROP_WAIT = 0xA;
    const LOOT_REFRESH = 0x28;

    const LOOT_BLACKLIST = new Set([
        'club_01', 'club_02', 'club_03',
        'padded_armor_01', 'padded_armor_02', 'padded_armor_03',
        'leather_gloves_01', 'leather_gloves_02', 'leather_gloves_03',
    ]);

    let tZ = 1;
    let xOn = false,
        mOn = false,
        fcOn = false;
    let farmOn = false,
        lootOn = false,
        AimBotOn = false;
    let menuVisible = true;
    let ba = null,
        bv = null;
    const fcPos = {
        x: 0,
        y: 0
    };
    const keys = {};
    let last = performance.now();

    let navPath = [],
        navWpIdx = 0,
        navDrag = null;
    let navReplan = 0,
        navGoal = null;
    let navStuckTk = 0,
        navStuckX = 0,
        navStuckY = 0;

    const FS = {
        IDLE: 0,
        ATTACK: 1,
        DROP_WAIT: 2,
        LOOT: 3,
        WANDER: 4
    };
    let fState = FS.IDLE;
    let fMob = null;
    let fPhase = 0,
        fDrag = null;
    let fStuckCk = 0,
        fStuckCnt = 0,
        fLx = 0,
        fLy = 0;
    let lastMobZone = null,
        wanderGoalPos = null;
    let phaseTimer = 0,
        attackTimer = 0,
        wanderTimer = 0;
    let dropWaitTimer = 0;
    let clickConfirmed = false;


    let lootQueue = [];
    let lootItem = null;
    let lootTimer = 0;
    let lootRefresh = 0;

    const lootDone = new Set();

    const walkCache = new Map();

    const clamp = (n, a, b) => Math.min(b, Math.max(a, n));
    const vlen = v => Math.hypot(v.x, v.y);
    const vsub = (a, b) => ({
        x: a.x - b.x,
        y: a.y - b.y
    });
    const vdist = (a, b) => vlen(vsub(a, b));
    const lerp = (a, b, t) => a + (b - a) * t;

    const getCam = () => {
        try {
            return uw.game?.camera || null;
        } catch {
            return null;
        }
    };
    const getVis = () => {
        try {
            return uw.game?.visibility || null;
        } catch {
            return null;
        }
    };
    const getPlayer = () => {
        try {
            return uw.game?.playerBarn?.getLocalPlayer() || null;
        } catch {
            return null;
        }
    };
    const getMobs = () => {
        try {
            return uw.game?.mobBarn?.mobs || [];
        } catch {
            return [];
        }
    };
    const getItems = () => {
        try {
            return uw.game?.itemBarn?.items || [];
        } catch {
            return [];
        }
    };
    const getInput = () => {
        try {
            return uw.game?.input || null;
        } catch {
            return null;
        }
    };
    const getGeo = () => {
        try {
            return uw.game?.geoBarn || null;
        } catch {
            return null;
        }
    };
    const getSel = () => {
        try {
            return uw.game?.selection || null;
        } catch {
            return null;
        }
    };

    function hasWall(a, b) {
        const geo = getGeo();
        if (!geo) return false;
        try {
            const dx = b.x - a.x,
                dy = b.y - a.y,
                dist = Math.hypot(dx, dy);
            if (dist < 1) return false;
            return !!geo.raycast(a, {
                x: dx / dist,
                y: dy / dist
            }, dist, {
                colMask: 2
            });
        } catch {
            return false;
        }
    }

    function ci(gx, gy) {
        return gy * GRID_N + gx;
    }

    function cellCenter(gx, gy) {
        return {
            x: gx * CELL + CELL / 2,
            y: gy * CELL + CELL / 2
        };
    }

    function worldToGrid(wx, wy) {
        return {
            gx: Math.floor(wx / CELL),
            gy: Math.floor(wy / CELL)
        };
    }

    function isWalkable(gx, gy) {
        if (gx < 0 || gy < 0 || gx >= GRID_N || gy >= GRID_N) return false;
        const k = ci(gx, gy);
        if (walkCache.has(k)) return walkCache.get(k);
        const c = cellCenter(gx, gy),
            r = CELL * 0.45;
        const blocked = hasWall(c, {
                x: c.x + r,
                y: c.y
            }) || hasWall(c, {
                x: c.x - r,
                y: c.y
            }) ||
            hasWall(c, {
                x: c.x,
                y: c.y + r
            }) || hasWall(c, {
                x: c.x,
                y: c.y - r
            });
        walkCache.set(k, !blocked);
        return !blocked;
    }

    function heuristic(ax, ay, bx, by) {
        const dx = Math.abs(ax - bx),
            dy = Math.abs(ay - by);
        return (dx + dy) + (Math.SQRT2 - 2) * Math.min(dx, dy);
    }

    function astar(from, to) {
        const sg = worldToGrid(from.x, from.y),
            eg = worldToGrid(to.x, to.y);
        const open = new Map(),
            closed = new Set();
        const start = ci(sg.gx, sg.gy),
            goal = ci(eg.gx, eg.gy);
        open.set(start, {
            g: 0,
            f: heuristic(sg.gx, sg.gy, eg.gx, eg.gy),
            gx: sg.gx,
            gy: sg.gy,
            _p: null
        });
        const dirs = [
            [1, 0],
            [-1, 0],
            [0, 1],
            [0, -1],
            [1, 1],
            [1, -1],
            [-1, 1],
            [-1, -1]
        ];
        let iters = 0;
        while (open.size > 0 && iters++ < 2000) {
            let bestK = null,
                bestF = Infinity;
            for (const [k, v] of open) {
                if (v.f < bestF) {
                    bestF = v.f;
                    bestK = k;
                }
            }
            const cur = open.get(bestK);
            open.delete(bestK);
            closed.add(bestK);
            if (bestK === goal) {
                const path = [];
                let node = cur;
                while (node) {
                    path.unshift(cellCenter(node.gx, node.gy));
                    node = node._p;
                }
                path[0] = from;
                path.push(to);
                return stringPull(path);
            }
            for (const [dx, dy] of dirs) {
                const nx = cur.gx + dx,
                    ny = cur.gy + dy,
                    nk = ci(nx, ny);
                if (closed.has(nk) || !isWalkable(nx, ny)) continue;
                const cost = (Math.abs(dx) + Math.abs(dy) === 2) ? Math.SQRT2 : 1;
                const g = cur.g + cost;
                if (!open.has(nk) || g < open.get(nk).g)
                    open.set(nk, {
                        g,
                        f: g + heuristic(nx, ny, eg.gx, eg.gy),
                        gx: nx,
                        gy: ny,
                        _p: cur
                    });
            }
        }
        return null;
    }

    function stringPull(path) {
        if (!path || path.length < 3) return path || [];
        const result = [path[0]];
        let i = 0;
        while (i < path.length - 1) {
            let j = path.length - 1;
            while (j > i + 1 && hasWall(path[i], path[j])) j--;
            result.push(path[j]);
            i = j;
        }
        return result;
    }

    function planPath(from, to) {
        if (!hasWall(from, to)) return [from, to];
        const raw = astar(from, to);
        return (raw && raw.length > 0) ? raw : null;
    }

    function navStart(goal) {
        const p = getPlayer();
        if (!p?.pos) return false;
        const path = planPath({
            x: p.pos.x,
            y: p.pos.y
        }, goal);
        if (!path || path.length < 2) return false;
        navPath = path;
        navWpIdx = 1;
        navGoal = goal;
        navReplan = 0;
        navStuckTk = 0;
        navStuckX = p.pos.x;
        navStuckY = p.pos.y;
        navDragTo(navPath[1]);
        return true;
    }

    function navDragTo(wp) {
        const c = getCam(),
            i = getInput();
        if (!c || !i) return;
        const sc = c.worldToScreen(wp);
        const sx = Math.round(sc.x),
            sy = Math.round(sc.y);
        if (navDrag && !navDrag.isDead) {
            navDrag.pos.x = sx;
            navDrag.pos.y = sy;
            navDrag.posStart.x = sx;
            navDrag.posStart.y = sy;
            i.mousePos.x = sx;
            i.mousePos.y = sy;
        } else {
            closeNavDrag();
            i.mousePos.x = sx;
            i.mousePos.y = sy;
            const pos = {
                    x: sx,
                    y: sy
                },
                now = performance.now();
            navDrag = {
                pos: {
                    ...pos
                },
                posOld: {
                    ...pos
                },
                posStart: {
                    ...pos
                },
                isNew: true,
                isDead: false,
                button: 0,
                clickCount: 1,
                startTime: now,
                captureId: 0,
                groupId: 0,
                ownerId: 0,
                hoverId: 0,
                tags: []
            };
            i.mouseButtons[0] = true;
            i.mouseDragEvents.push(navDrag);
            const cl = i.mouseButtonClicks[0] || {
                pos: {
                    ...pos
                },
                time: now,
                count: 0
            };
            cl.count = 1;
            cl.time = now;
            cl.pos = {
                ...pos
            };
            navDrag.clickCount = cl.count;
            i.mouseButtonClicks[0] = cl;
        }
    }

    function closeNavDrag() {
        const i = getInput();
        if (navDrag) {
            navDrag.isDead = true;
            navDrag.isNew = false;
            navDrag = null;
        }
        if (i) i.mouseButtons[0] = false;
    }

    function navStop() {
        closeNavDrag();
        navPath = [];
        navWpIdx = 0;
        navGoal = null;
        navReplan = 0;
    }

    function tickNav() {
        if (!navGoal || !farmOn) return;
        const p = getPlayer();
        if (!p?.pos) return;
        const pos = p.pos;
        navStuckTk++;
        if (navStuckTk % STUCK_FRAMES === 0) {
            const moved = vdist(pos, {
                x: navStuckX,
                y: navStuckY
            });
            if (moved < NAV_STUCK_MOVE) {
                walkCache.clear();
                const jitter = {
                    x: clamp(navGoal.x + (Math.random() - 0.5) * CELL * 3, 10, WORLD - 10),
                    y: clamp(navGoal.y + (Math.random() - 0.5) * CELL * 3, 10, WORLD - 10)
                };
                navStart(jitter);
                return;
            }
            navStuckX = pos.x;
            navStuckY = pos.y;
        }
        if (navWpIdx >= navPath.length) {
            navStop();
            return;
        }
        const wp = navPath[navWpIdx];
        if (vdist(pos, wp) < ARRIVE_DIST) {
            navWpIdx++;
            if (navWpIdx >= navPath.length) {
                navStop();
                return;
            }
            navDragTo(navPath[navWpIdx]);
            return;
        }
        navReplan++;
        if (navReplan >= REPLAN_TICKS) {
            navReplan = 0;
            const fresh = stringPull([{
                x: pos.x,
                y: pos.y
            }, ...navPath.slice(navWpIdx)]);
            if (fresh && fresh.length > 1) {
                navPath = [{
                    x: pos.x,
                    y: pos.y
                }, ...fresh.slice(1)];
                navWpIdx = 1;
            }
        }
        navDragTo(navPath[navWpIdx] || navGoal);
    }

    function checkClick(id) {
        const sel = getSel();
        if (!sel) return false;
        return sel.targetEntityId === id || sel.selectEntityId === id;
    }

    function mobValid(m) {
        return !!(m && m.entityActive && !m.dead && m.pos?.x != null);
    }

    function farmStuck() {
        const p = getPlayer();
        if (!p?.pos) return false;
        fStuckCk++;
        if (fStuckCk < 120) return false;
        fStuckCk = 0;
        const d = vdist(p.pos, {
            x: fLx,
            y: fLy
        });
        fLx = p.pos.x;
        fLy = p.pos.y;
        if (d < 2) {
            fStuckCnt++;
            if (fStuckCnt >= 3) {
                fStuckCnt = 0;
                return true;
            }
        } else fStuckCnt = 0;
        return false;
    }

    function nearestMob(ignoreWalls) {
        const p = getPlayer();
        if (!p?.pos) return null;
        const px = p.pos.x,
            py = p.pos.y;
        let best = null,
            bestScore = -Infinity;
        for (const m of getMobs()) {
            if (!mobValid(m)) continue;
            if (!ignoreWalls && hasWall({
                    x: px,
                    y: py
                }, {
                    x: m.pos.x,
                    y: m.pos.y
                })) continue;
            const dist = Math.hypot(m.pos.x - px, m.pos.y - py);
            const hpPct = m.lifeMax > 0 ? m.life / m.lifeMax : 1;
            const s = -dist * 0.8 - hpPct * 50;
            if (s > bestScore) {
                bestScore = s;
                best = m;
            }
        }
        return best;
    }


    function scanAllLoot() {
        const p = getPlayer();
        const px = p?.pos?.x ?? 0,
            py = p?.pos?.y ?? 0;
        return getItems()
            .filter(it => {
                if (!it.entityActive || it.dead) return false;
                if (LOOT_BLACKLIST.has(it.item?.type)) return false;
                if (it.pos?.x == null) return false;
                if (lootDone.has(it.entityId)) return false;
                return true;
            })
            .sort((a, b) => {
                const rDiff = (b.item?.rarity ?? 0) - (a.item?.rarity ?? 0);
                if (rDiff !== 0) return rDiff;
                const da = Math.hypot(a.pos.x - px, a.pos.y - py);
                const db = Math.hypot(b.pos.x - px, b.pos.y - py);
                return da - db;
            });
    }


    function refreshLootQueue() {
        const fresh = scanAllLoot();

        lootQueue = lootQueue.filter(q => q.entityActive && !q.dead);

        const inQueue = new Set(lootQueue.map(q => q.entityId));
        for (const it of fresh) {
            if (!inQueue.has(it.entityId)) lootQueue.push(it);
        }

        const px = getPlayer()?.pos?.x ?? 0,
            py = getPlayer()?.pos?.y ?? 0;
        lootQueue.sort((a, b) => {
            const rDiff = (b.item?.rarity ?? 0) - (a.item?.rarity ?? 0);
            if (rDiff !== 0) return rDiff;
            return Math.hypot(a.pos.x - px, a.pos.y - py) - Math.hypot(b.pos.x - px, b.pos.y - py);
        });
    }

    function setTarget(id) {
        const g = uw.game;
        if (!g) return;
        g.selection.targetEntityId = id;
        g.selection.setTarget = true;
    }

    function makeDrag(wx, wy) {
        const c = getCam(),
            i = getInput();
        if (!c || !i) return null;
        const sc = c.worldToScreen({
            x: wx,
            y: wy
        });
        const sx = Math.round(sc.x),
            sy = Math.round(sc.y);
        i.mousePos.x = sx;
        i.mousePos.y = sy;
        const pos = {
                x: sx,
                y: sy
            },
            now = performance.now();
        const evt = {
            pos: {
                ...pos
            },
            posOld: {
                ...pos
            },
            posStart: {
                ...pos
            },
            isNew: true,
            isDead: false,
            button: 0,
            clickCount: 1,
            startTime: now,
            captureId: 0,
            groupId: 0,
            ownerId: 0,
            hoverId: 0,
            tags: []
        };
        i.mouseButtons[0] = true;
        i.mouseDragEvents.push(evt);
        const cl = i.mouseButtonClicks[0] || {
            pos: {
                ...pos
            },
            time: now,
            count: 0
        };
        cl.count = 1;
        cl.time = now;
        cl.pos = {
            ...pos
        };
        evt.clickCount = cl.count;
        i.mouseButtonClicks[0] = cl;
        return evt;
    }

    function fakeClick(e) {
        const mx = e.pos?.x,
            my = e.pos?.y;
        if (mx == null) return null;
        return makeDrag(mx, my);
    }

    function closeClick(evt) {
        const i = getInput();
        if (!i || !evt) return;
        evt.isDead = true;
        evt.isNew = false;
        i.mouseButtons[0] = false;
    }

    function wanderGoal() {
        const p = getPlayer();
        if (!p?.pos) return null;
        const base = lastMobZone || {
            x: p.pos.x,
            y: p.pos.y
        };
        for (let a = 0; a < 16; a++) {
            const angle = Math.random() * Math.PI * 2,
                dist = 80 + Math.random() * 300;
            const tx = clamp(base.x + Math.cos(angle) * dist, 20, WORLD - 20);
            const ty = clamp(base.y + Math.sin(angle) * dist, 20, WORLD - 20);
            if (!hasWall(p.pos, {
                    x: tx,
                    y: ty
                })) return {
                x: tx,
                y: ty
            };
            const mid = {
                x: lerp(p.pos.x, tx, 0.5) + (Math.random() - 0.5) * CELL,
                y: lerp(p.pos.y, ty, 0.5) + (Math.random() - 0.5) * CELL
            };
            if (!hasWall(p.pos, mid) && !hasWall(mid, {
                    x: tx,
                    y: ty
                })) return {
                x: tx,
                y: ty
            };
        }
        return null;
    }

    function resetFarm() {
        closeClick(fDrag);
        fDrag = null;
        navStop();
        fMob = null;
        fPhase = 0;
        fStuckCk = 0;
        fStuckCnt = 0;
        phaseTimer = 0;
        attackTimer = 0;
        wanderTimer = 0;
        dropWaitTimer = 0;
        lootQueue = [];
        lootItem = null;
        lootTimer = 0;
        lootRefresh = 0;
        lootDone.clear();
        clickConfirmed = false;
        setTarget(0);
        fState = FS.IDLE;
    }

    function setFS(s) {
        fState = s;
        phaseTimer = 0;
    }


    function tickLoot() {
        if (!lootOn || !farmOn) return;
        const p = getPlayer();
        if (!p || p.dead) return;


        if (fState === FS.ATTACK) return;

        lootRefresh++;
        if (lootRefresh >= LOOT_REFRESH) {
            lootRefresh = 0;
            refreshLootQueue();
        }


        if (lootItem && (!lootItem.entityActive || lootItem.dead)) {
            lootDone.add(lootItem.entityId);
            lootItem = null;
            lootQueue = lootQueue.filter(q => q.entityId !== lootItem?.entityId);
            closeClick(fDrag);
            fDrag = null;
            lootTimer = 0;
        }

        if (lootQueue.length === 0) {

            if (fState === FS.DROP_WAIT || fState === FS.LOOT) {
                setFS(FS.IDLE);
            }
            return;
        }


        while (lootQueue.length > 0 && (!lootQueue[0].entityActive || lootQueue[0].dead)) {
            lootDone.add(lootQueue[0].entityId);
            lootQueue.shift();
        }
        if (lootQueue.length === 0) return;

        const it = lootQueue[0];
        if (lootItem?.entityId !== it.entityId) {
            closeClick(fDrag);
            fDrag = null;
            lootItem = it;
            lootTimer = 0;
        }

        lootTimer++;


        if (lootTimer > LOOT_TIMEOUT) {
            lootDone.add(it.entityId);
            lootQueue.shift();
            lootItem = null;
            lootTimer = 0;
            closeClick(fDrag);
            fDrag = null;
            return;
        }


        if (lootTimer === 1 || lootTimer % 30 === 0) {
            setTarget(it.entityId);
            closeClick(fDrag);
            fDrag = fakeClick(it);
            requestAnimationFrame(() => {
                closeClick(fDrag);
                fDrag = null;
            });
        }
    }

    function tickFarm() {
        if (!farmOn) return;
        const p = getPlayer();
        if (!p || p.dead) return;
        const pos = p.pos;
        phaseTimer++;

        if (fState === FS.IDLE) {

            if (lootOn) {
                refreshLootQueue();
                if (lootQueue.length > 0) {
                    setFS(FS.LOOT);
                    return;
                }
            }
            fMob = nearestMob(false);
            if (fMob) {
                lastMobZone = {
                    x: fMob.pos.x,
                    y: fMob.pos.y
                };
                navStop();
                fLx = pos.x;
                fLy = pos.y;
                fPhase = 0;
                attackTimer = 0;
                clickConfirmed = false;
                setFS(FS.ATTACK);
                return;
            }
            wanderGoalPos = wanderGoal();
            wanderTimer = 0;
            if (wanderGoalPos) navStart(wanderGoalPos);
            setFS(FS.WANDER);
        } else if (fState === FS.WANDER) {
            wanderTimer++;

            if (lootOn && wanderTimer % LOOT_REFRESH === 0) {
                refreshLootQueue();
                if (lootQueue.length > 0) {
                    navStop();
                    setFS(FS.LOOT);
                    return;
                }
            }
            fMob = nearestMob(false);
            if (fMob) {
                navStop();
                wanderGoalPos = null;
                setFS(FS.IDLE);
                return;
            }
            const arrived = wanderGoalPos && vdist(pos, wanderGoalPos) < ARRIVE_DIST;
            if (arrived || wanderTimer > WANDER_TIMEOUT || !navGoal) {
                navStop();
                wanderGoalPos = wanderGoal();
                wanderTimer = 0;
                if (wanderGoalPos) navStart(wanderGoalPos);
                return;
            }
            if (wanderTimer % 60 === 0) {
                const any = nearestMob(true);
                if (any && !hasWall(pos, any.pos)) {
                    navStop();
                    setFS(FS.IDLE);
                    return;
                }
            }
            if (!navGoal && wanderGoalPos) navStart(wanderGoalPos);
        } else if (fState === FS.ATTACK) {
            attackTimer++;
            if (!mobValid(fMob)) {
                closeClick(fDrag);
                fDrag = null;
                setTarget(0);
                fMob = null;
                fPhase = 0;
                dropWaitTimer = 0;
                setFS(FS.DROP_WAIT);
                return;
            }
            if (attackTimer > ATTACK_TIMEOUT) {
                closeClick(fDrag);
                fDrag = null;
                setTarget(0);
                fMob = null;
                fPhase = 0;
                walkCache.clear();
                setFS(FS.IDLE);
                return;
            }
            if (phaseTimer > PHASE_TIMEOUT && fPhase !== 2) {
                closeClick(fDrag);
                fDrag = null;
                fPhase = 0;
                phaseTimer = 0;
                return;
            }
            if (farmStuck()) {
                resetFarm();
                return;
            }

            if (!fMob.dead) {
                if (attackTimer % 60 === 0 && hasWall(pos, fMob.pos)) {
                    closeClick(fDrag);
                    fDrag = null;
                    setTarget(0);
                    const path = planPath(pos, fMob.pos);
                    if (path && path.length > 1) {
                        navPath = path;
                        navWpIdx = 1;
                        navGoal = fMob.pos;
                        navReplan = 0;
                        navDragTo(navPath[1]);
                    } else {
                        fMob = null;
                        fPhase = 0;
                        setFS(FS.IDLE);
                    }
                    return;
                }
                navStop();
                if (fPhase === 0) {
                    setTarget(fMob.entityId);
                    fDrag = fakeClick(fMob);
                    clickConfirmed = false;
                    fPhase = 1;
                    phaseTimer = 0;
                } else if (fPhase === 1) {
                    if (!clickConfirmed) {
                        clickConfirmed = checkClick(fMob.entityId);
                        if (!clickConfirmed && phaseTimer > PHASE_TIMEOUT) {
                            closeClick(fDrag);
                            fDrag = null;
                            setTarget(fMob.entityId);
                            fDrag = fakeClick(fMob);
                            phaseTimer = 0;
                            return;
                        }
                    }
                    closeClick(fDrag);
                    fDrag = null;
                    fPhase = 2;
                    phaseTimer = 0;
                } else {
                    setTarget(fMob.entityId);
                    if (attackTimer % 30 === 0 && !checkClick(fMob.entityId)) {
                        setTarget(fMob.entityId);
                        fDrag = fakeClick(fMob);
                        requestAnimationFrame(() => {
                            closeClick(fDrag);
                            fDrag = null;
                        });
                    }
                }
            } else {
                closeClick(fDrag);
                fDrag = null;
                setTarget(0);
                attackTimer = 0;
                dropWaitTimer = 0;
                setFS(FS.DROP_WAIT);
            }
        } else if (fState === FS.DROP_WAIT) {
            dropWaitTimer++;
            if (dropWaitTimer >= DROP_WAIT) {
                if (lootOn) {
                    refreshLootQueue();
                    if (lootQueue.length > 0) {
                        fMob = null;
                        fPhase = 0;
                        setFS(FS.LOOT);
                        return;
                    }
                }
                fMob = null;
                fPhase = 0;
                setFS(FS.IDLE);
            }
        } else if (fState === FS.LOOT) {
            if (lootQueue.length === 0 && lootItem == null) {
                setFS(FS.IDLE);
            }
        }
    }

    function updateLabel() {
        const el = document.getElementById('zlbl');
        if (el) el.textContent = tZ.toFixed(1).replace(/\.0$/, '');
    }

    function applyZ() {
        const c = getCam();
        if (c) try {
            c.z = tZ;
        } catch {}
    }

    function zoomBy(d) {
        tZ = clamp(+(tZ + d).toFixed(2), MIN_Z, MAX_Z);
        updateLabel();
    }

    function nudgeZoom() {
        const c = getCam();
        if (!c) return;
        try {
            c.z = tZ + 0.01;
            requestAnimationFrame(() => {
                try {
                    c.z = tZ;
                } catch {}
            });
        } catch {}
    }

    function applyV() {
        const v = getVis();
        if (!v) return;
        if (!ba) {
            ba = v.cellGameAlpha.slice();
            bv = v.cellVis.slice();
        }
        if (xOn) v.cellGameAlpha.fill(-Infinity);
        if (mOn) v.cellVis.fill(-Infinity);
    }

    function restoreA() {
        const v = getVis();
        if (v && ba) v.cellGameAlpha.fill(ba);
    }

    function restoreM() {
        const v = getVis();
        if (v && bv) v.cellVis.fill(bv);
    }

    const ARROW_KEYS = ['arrowup', 'arrowdown', 'arrowleft', 'arrowright'];

    function enableFreeCam() {
        const p = getPlayer(),
            c = getCam();
        if (p?.bodyPos) {
            fcPos.x = p.bodyPos.x;
            fcPos.y = p.bodyPos.y;
        } else if (c) {
            fcPos.x = c.pos.x;
            fcPos.y = c.pos.y;
        }
        updateFcHint();
    }

    function updateFcHint() {
        const el = document.getElementById('fc-hint');
        if (!el) return;
        el.textContent = fcOn ? '↑↓←→' : '';
        el.style.color = fcOn ? '#82aaff' : 'rgba(255,255,255,0.35)';
    }

    function tickFreeCam() {
        if (!fcOn) return;
        const p = getPlayer(),
            c = getCam();
        if (!p || !c) return;
        const sp = 0.7 * tZ;
        if (keys['arrowup']) fcPos.y += sp;
        if (keys['arrowdown']) fcPos.y -= sp;
        if (keys['arrowleft']) fcPos.x -= sp;
        if (keys['arrowright']) fcPos.x += sp;
        try {
            if (p.bodyPos) {
                p.bodyPos.x = fcPos.x;
                p.bodyPos.y = fcPos.y;
            }
            c.pos.x = fcPos.x;
            c.pos.y = fcPos.y;
        } catch {}
    }

    function tickAimBot() {
        if (!AimBotOn) return;
        const p = getPlayer();
        if (!p?.pos) return;
        let best = null,
            bd = Infinity;
        for (const m of getMobs()) {
            if (!m.entityActive || m.dead) continue;
            if (hasWall({
                    x: p.pos.x,
                    y: p.pos.y
                }, {
                    x: m.pos?.x ?? 0,
                    y: m.pos?.y ?? 0
                })) continue;
            const d = Math.hypot((m.pos?.x ?? 0) - p.pos.x, (m.pos?.y ?? 0) - p.pos.y);
            if (d < bd) {
                bd = d;
                best = m;
            }
        }
        if (!best) return;
        const c = getCam(),
            i = getInput();
        if (!c || !i) return;
        const sc = c.worldToScreen({
            x: best.pos.x,
            y: best.pos.y
        });
        i.mousePos.x = Math.round(sc.x);
        i.mousePos.y = Math.round(sc.y);
    }

    function toggleMenu() {
        menuVisible = !menuVisible;
        const box = document.getElementById('zm');
        if (box) box.style.display = menuVisible ? 'flex' : 'none';
    }

    function setLootVisible(v) {
        const row = document.getElementById('loot-row');
        if (row) row.style.display = v ? 'flex' : 'none';
        if (!v) {
            lootOn = false;
            const cb = document.getElementById('lt');
            if (cb) cb.checked = false;
        }
    }

    function handleZoomWheel(e) {
        if (!e.ctrlKey || e.__zmHandled) return;
        e.__zmHandled = true;
        if (e.cancelable) e.preventDefault();
        e.stopPropagation();
        e.stopImmediatePropagation();
        zoomBy(e.deltaY < 0 ? -STEP : STEP);
    }

    window.addEventListener('keydown', e => {
        const k = e.key.toLowerCase();
        if (e.key === 'F10') {
            e.preventDefault();
            toggleMenu();
            return;
        }
        if (e.ctrlKey) {
            const plus = e.key === '+' || e.key === '=' || e.code === 'Equal';
            const minus = e.key === '-' || e.code === 'Minus';
            if (plus || minus) {
                e.preventDefault();
                e.stopImmediatePropagation();
                zoomBy(plus ? STEP : -STEP);
                return;
            }
        }
        if (fcOn && ARROW_KEYS.includes(k)) {
            e.preventDefault();
            e.stopImmediatePropagation();
        }
        keys[k] = true;
    }, true);
    window.addEventListener('keyup', e => {
        keys[e.key.toLowerCase()] = false;
    }, true);
    document.addEventListener('wheel', handleZoomWheel, {
        capture: true,
        passive: false
    });
    window.addEventListener('wheel', handleZoomWheel, {
        capture: true,
        passive: false
    });
    document.addEventListener('mousewheel', handleZoomWheel, {
        capture: true,
        passive: false
    });

    const st = document.createElement('style');
    st.textContent = `#zm {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 99999;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 238px;
  padding: 10px;
  border-radius: 12px;
  background: rgba(20, 20, 28, 0.96);
  border: 1px solid rgba(255, 255, 255, 0.12);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.35);
  backdrop-filter: blur(10px);
  font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
  color: #e6edf3;
  user-select: none;
}
#zm,
#zm * {
  box-sizing: border-box;
}
#zm .toprow {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  align-items: center;
}
#zm .stat {
  color: #7ee787;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
}
#zm .stat span {
  display: inline-block;
  min-width: 34px;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: #fff;
  font-weight: 600;
}
#zm .zrow {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
}
#zm .zhint {
  color: rgba(255, 255, 255, 0.55);
  font-size: 11px;
}
#zm .zval {
  color: #58a6ff;
  font-size: 13px;
  font-weight: 600;
  min-width: 40px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
#zm .sep {
  width: 100%;
  height: 1px;
  background: rgba(255, 255, 255, 0.12);
}
#zm .controls {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
#zm label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 13px;
  cursor: pointer;
  color: #f0f6fc;
  padding: 6px 8px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.04);
}
#zm label:hover {
  background: rgba(255, 255, 255, 0.07);
}
#zm label .left {
  display: flex;
  align-items: center;
  gap: 8px;
}
#zm input[type="checkbox"] {
  accent-color: #58a6ff;
  margin: 0;
}
#zm #fc-hint {
  font-size: 12px;
  min-width: 42px;
  text-align: right;
}
#zm label.farm-label {
  color: #ff7b72;
}
#zm label.farm-label.active {
  color: #ff3b3b;
  text-shadow: 0 0 8px rgba(255, 60, 60, 0.8);
}
#zm label.loot-label {
  color: #f0a040;
  padding-left: 24px;
}
#zm label.loot-label.active {
  color: #ffb84d;
  text-shadow: 0 0 8px rgba(255, 180, 60, 0.7);
}
#zm-hint {
  position: fixed;
  bottom: 60px;
  left: 8px;
  z-index: 99999;
  font-family: system-ui, -apple-system, sans-serif;
  font-size: 15px;
  color: red;
  pointer-events: none;
  user-select: none;
}
`;
    document.documentElement.appendChild(st);

    const hint = document.createElement('div');
    hint.id = 'zm-hint';
    hint.textContent = 'F10 - open/close menu';
    document.documentElement.appendChild(hint);

    const box = document.createElement('div');
    box.id = 'zm';
    box.innerHTML = `
    <div class="toprow">
      <span class="stat">FPS: <span id="fps">0</span></span>
      <span class="stat">PING: <span id="ping">0</span></span>
    </div>
    <div class="sep"></div>
    <div class="zrow">
      <span class="zhint">Zoom</span>
      <span class="zhint">Ctrl\xb1 / Scroll</span>
      <span class="zval" id="zlbl">${tZ}</span>
    </div>
    <div class="sep"></div>
    <div class="controls">
      <label><span class="left"><input type="checkbox" id="zx"> xray</span></label>
      <label><span class="left"><input type="checkbox" id="xm"> xray map</span></label>
      <label><span class="left"><input type="checkbox" id="fc"> free camera</span><span id="fc-hint"></span></label>
      <label><span class="left"><input type="checkbox" id="AimBot"> AimBot</span></label>
      <label class="farm-label" id="farm-label"><span class="left"><input type="checkbox" id="fm"> auto farm</span></label>
      <label class="loot-label" id="loot-row" style="display:none"><span class="left"><input type="checkbox" id="lt"> auto loot</span></label>
    </div>
  `;
    document.documentElement.appendChild(box);

    const fpsNode = box.querySelector('#fps'),
        pingNode = box.querySelector('#ping');
    const zx = box.querySelector('#zx'),
        xm = box.querySelector('#xm');
    const fc = box.querySelector('#fc'),
        fm = box.querySelector('#fm');
    const lt = box.querySelector('#lt'),
        aimCb = box.querySelector('#AimBot');
    const farmLabel = box.querySelector('#farm-label'),
        lootLabel = box.querySelector('#loot-row');

    zx.onchange = () => {
        xOn = zx.checked;
        if (!xOn) restoreA();
    };
    xm.onchange = () => {
        mOn = xm.checked;
        if (!mOn) restoreM();
        nudgeZoom();
    };
    fc.onchange = () => {
        fcOn = fc.checked;
        fcOn ? enableFreeCam() : updateFcHint();
    };
    aimCb.onchange = () => {
        AimBotOn = aimCb.checked;
    };
    fm.onchange = () => {
        farmOn = fm.checked;
        farmLabel.classList.toggle('active', farmOn);
        setLootVisible(farmOn);
        if (!farmOn) resetFarm();
    };
    lt.onchange = () => {
        lootOn = lt.checked;
        lootLabel.classList.toggle('active', lootOn);
        if (lootOn) {
            lootDone.clear();
            refreshLootQueue();
        }
    };

    const stop = e => e.stopPropagation();
    ['pointerdown', 'pointerup', 'mousedown', 'mouseup', 'click', 'dblclick', 'contextmenu', 'wheel', 'touchstart', 'touchend', 'touchmove']
    .forEach(ev => box.addEventListener(ev, stop));

    function tickHUD() {
        if (!uw.game?.inGame) return;
        const t = performance.now(),
            dt = t - last;
        last = t;
        if (fpsNode && dt > 0 && dt < 1000) fpsNode.textContent = (1000 / dt).toFixed(1);
        const pings = uw.game?.netGraph?.pings;
        if (pings?.length && pingNode) pingNode.textContent = Number(pings[pings.length - 1]).toFixed(0);
    }

    function loop() {
        applyZ();
        applyV();
        tickFreeCam();
        tickAimBot();
        tickNav();
        tickFarm();
        tickLoot();
        tickHUD();
        requestAnimationFrame(loop);
    }
    updateLabel();
    requestAnimationFrame(loop);
})();

(() => {
    'use strict';

    function apply() {
        const title = document.querySelector("#landing-start-title");
        if (title && !title._edited) {
            title.textContent = "CowzHacks";
            title._edited = true;
        }

        const news = document.querySelector("#landing-news-container");
        if (news && !news._moved) {
            news.style.transform = "translateX(40px)";
            news._moved = true;
        }
    }

    const mo = new MutationObserver(() => apply());

    mo.observe(document.documentElement, {
        childList: true,
        subtree: true
    });

    apply();
})();


(() => {
    'use strict';

    let cached = null;

    try {
        const raw = sessionStorage.getItem('_si');
        if (raw) cached = JSON.parse(raw);
    } catch {}

    const origFetch = unsafeWindow.fetch.bind(unsafeWindow);

    const live = origFetch('/api/site_info', {
            cache: 'no-store',
            priority: 'high'
        })
        .then(r => r.json())
        .then(data => {
            cached = data;
            try {
                sessionStorage.setItem('_si', JSON.stringify(data));
            } catch {}
            return data;
        })
        .catch(() => null);

    unsafeWindow.fetch = function(url, opts) {
        if (typeof url === 'string' && url.includes('/api/site_info')) {
            if (cached) {
                return Promise.resolve(new Response(JSON.stringify(cached), {
                    status: 200,
                    headers: {
                        'Content-Type': 'application/json'
                    }
                }));
            }
            return live.then(data =>
                data ?
                new Response(JSON.stringify(data), {
                    status: 200,
                    headers: {
                        'Content-Type': 'application/json'
                    }
                }) :
                origFetch(url, opts)
            );
        }
        return origFetch(url, opts);
    };
})();