richup.io Advanced Cheat Suite

Socket interceptor + Vue state reader + auto-play bot + HUD overlay

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

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.

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

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

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         richup.io Advanced Cheat Suite
// @namespace    http://tampermonkey.net/
// @version      2.0.0
// @description  Socket interceptor + Vue state reader + auto-play bot + HUD overlay
// @author       Fox
// @match        *://www.richup.io/*
// @match        *://richup.io/*
// @grant        GM_addStyle
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    // ─────────────────────────────────────────────
    //  CONFIG
    // ─────────────────────────────────────────────
    const CFG = {
        botEnabled:        false,
        hudEnabled:        true,
        autoBuy:           true,   // buy every unowned property landed on
        autoBuildHotels:   true,   // build houses → hotels on complete sets
        autoAcceptTrade:   false,  // auto-accept ALL incoming trades (risky)
        rollDelay:         1200,   // ms between bot actions
        logPackets:        true,   // dump socket events to console
    };

    // ─────────────────────────────────────────────
    //  STYLES — floating HUD
    // ─────────────────────────────────────────────
    GM_addStyle(`
        #ru-hud {
            position: fixed;
            top: 10px;
            right: 10px;
            z-index: 999999;
            background: rgba(10,10,20,0.92);
            color: #e0e0e0;
            font: 12px/1.5 'Consolas', monospace;
            padding: 10px 14px;
            border-radius: 8px;
            border: 1px solid #444;
            min-width: 260px;
            max-height: 80vh;
            overflow-y: auto;
            box-shadow: 0 4px 24px #000a;
            user-select: none;
        }
        #ru-hud h3 {
            margin: 0 0 6px;
            color: #7ecfff;
            font-size: 13px;
            letter-spacing: 1px;
        }
        #ru-hud .ru-player {
            border-bottom: 1px solid #333;
            padding: 4px 0;
        }
        #ru-hud .ru-player:last-child { border: none; }
        #ru-hud .ru-name  { color: #ffd700; font-weight: bold; }
        #ru-hud .ru-money { color: #4cff91; }
        #ru-hud .ru-pos   { color: #aaa; font-size: 11px; }
        #ru-hud .ru-props { color: #c8a0ff; font-size: 11px; }
        #ru-hud .ru-status { color: #ff6b6b; font-size: 11px; }
        #ru-hud .ru-controls {
            margin-top: 8px;
            display: flex;
            gap: 6px;
            flex-wrap: wrap;
        }
        #ru-hud button {
            background: #1a2a3a;
            color: #7ecfff;
            border: 1px solid #7ecfff44;
            border-radius: 4px;
            padding: 2px 8px;
            cursor: pointer;
            font: 11px monospace;
        }
        #ru-hud button:hover { background: #2a4a6a; }
        #ru-hud button.active { background: #0a4a2a; color: #4cff91; border-color: #4cff91; }
    `);

    // ─────────────────────────────────────────────
    //  SOCKET.IO INTERCEPTOR
    //  Hooks into the io() constructor before the
    //  game's own code calls it, wrapping emit/on
    //  so we can sniff every packet in both dirs.
    // ─────────────────────────────────────────────
    const _interceptedSocket = { ref: null };
    const _socketListeners   = {}; // event → [callbacks]

    function hookSocketIO() {
        // Poll until socket.io client lib is loaded
        const poll = setInterval(() => {
            if (typeof window.io !== 'function') return;
            clearInterval(poll);

            const origIO = window.io;
            window.io = function (...args) {
                const sock = origIO.apply(this, args);
                _interceptedSocket.ref = sock;
                patchSocket(sock);
                return sock;
            };
            // copy static props (managers etc.)
            Object.assign(window.io, origIO);
            console.log('[RU-CHEAT] socket.io hooked');
        }, 50);
    }

    function patchSocket(sock) {
        // ── Outgoing: wrap emit ──
        const origEmit = sock.emit.bind(sock);
        sock.emit = function (event, ...args) {
            if (CFG.logPackets)
                console.log(`[RU→SRV] ${event}`, ...args);
            return origEmit(event, ...args);
        };

        // ── Incoming: wrap onevent (socket.io v4 internal) ──
        const origOnevent = sock.onevent.bind(sock);
        sock.onevent = function (packet) {
            const [event, ...data] = packet.data || [];
            if (CFG.logPackets)
                console.log(`[SRV→RU] ${event}`, ...data);

            // dispatch to our own listeners
            (_socketListeners[event] || []).forEach(cb => {
                try { cb(...data); } catch(e) {}
            });

            return origOnevent(packet);
        };
    }

    // Register a listener for an incoming socket event
    function onSock(event, cb) {
        if (!_socketListeners[event]) _socketListeners[event] = [];
        _socketListeners[event].push(cb);
    }

    // Emit to server through the hooked socket
    function sockEmit(event, ...args) {
        if (_interceptedSocket.ref)
            _interceptedSocket.ref.emit(event, ...args);
    }

    // ─────────────────────────────────────────────
    //  VUE STATE READER
    //  richup.io uses Vue 3. __vue_app__ is on #app.
    //  We walk the component tree to find the root
    //  game store / component state.
    // ─────────────────────────────────────────────
    function getVueRoot() {
        const el = document.querySelector('#app') ||
                   document.querySelector('[data-v-app]');
        if (!el || !el.__vue_app__) return null;
        return el.__vue_app__;
    }

    // Walk component tree, collect all component instances
    function collectComponents(vnode, out = []) {
        if (!vnode) return out;
        if (vnode.component) {
            out.push(vnode.component);
            collectComponents(vnode.component.subTree, out);
        }
        if (vnode.shapeFlag & 16) { // ARRAY_CHILDREN
            vnode.children?.forEach(c => collectComponents(c, out));
        }
        return out;
    }

    // Find a component whose data/props contain a key
    function findComponentWith(key) {
        const app = getVueRoot();
        if (!app) return null;
        const comps = collectComponents(app._instance?.subTree);
        return comps.find(c =>
            c.data?.[key] !== undefined ||
            c.props?.[key] !== undefined ||
            c.setupState?.[key] !== undefined
        );
    }

    // Get the full game state object — tries common key names
    function getGameState() {
        for (const key of ['game', 'gameState', 'state', 'room', 'gameData']) {
            const comp = findComponentWith(key);
            if (comp) {
                return comp.data?.[key] ??
                       comp.setupState?.[key] ??
                       comp.props?.[key];
            }
        }
        // Fallback: scan all components for a 'players' array
        const app = getVueRoot();
        if (!app) return null;
        const comps = collectComponents(app._instance?.subTree);
        for (const c of comps) {
            const src = c.setupState ?? c.data ?? {};
            if (Array.isArray(src.players) && src.players.length > 0)
                return src;
        }
        return null;
    }

    // ─────────────────────────────────────────────
    //  DOM HELPERS — click the right buttons
    // ─────────────────────────────────────────────
    function clickButton(selector) {
        const btn = document.querySelector(selector);
        if (btn && !btn.disabled) { btn.click(); return true; }
        return false;
    }

    // Finds a visible, enabled button whose text matches a regex
    function clickButtonByText(regex) {
        const btns = [...document.querySelectorAll('button')];
        const btn  = btns.find(b =>
            regex.test(b.textContent.trim()) &&
            !b.disabled &&
            b.offsetParent !== null
        );
        if (btn) { btn.click(); return true; }
        return false;
    }

    // ─────────────────────────────────────────────
    //  AUTO-PLAY BOT
    // ─────────────────────────────────────────────
    let botTimer = null;

    function botTick() {
        if (!CFG.botEnabled) return;

        // Priority order:
        // 1. Roll dice if it's our turn and dice haven't been rolled
        // 2. Buy property if prompt is visible
        // 3. Build houses/hotels
        // 4. Handle card draw (OK/Close)
        // 5. End turn

        // Roll dice
        if (clickButtonByText(/roll|throw|dice/i)) return;

        // Buy property
        if (CFG.autoBuy && clickButtonByText(/buy|purchase/i)) return;

        // Build — look for 'Build' or 'House' or 'Hotel' buttons
        if (CFG.autoBuildHotels && clickButtonByText(/build|house|hotel/i)) return;

        // Dismiss card / OK / Close
        if (clickButtonByText(/^ok$|^close$|^got it$|^continue$/i)) return;

        // Mortgage decision — never mortgage, click 'No' if asked
        if (clickButtonByText(/^no$|^cancel$/i)) return;

        // End turn
        if (clickButtonByText(/end turn|next turn|finish/i)) return;
    }

    function startBot() {
        if (botTimer) clearInterval(botTimer);
        botTimer = setInterval(botTick, CFG.rollDelay);
    }

    function stopBot() {
        clearInterval(botTimer);
        botTimer = null;
    }

    // ─────────────────────────────────────────────
    //  TRADE SNIPER
    //  Listens for incoming trade offer packets and
    //  auto-accepts if the offer is in our favor.
    // ─────────────────────────────────────────────
    onSock('trade:offer', (offer) => {
        console.log('[RU-CHEAT] Trade offer received:', offer);
        if (!CFG.autoAcceptTrade) return;

        // Simple heuristic: accept if we receive more money than we give
        const weGet  = (offer.toMoney   || 0);
        const weGive = (offer.fromMoney || 0);
        if (weGet >= weGive) {
            console.log('[RU-CHEAT] Auto-accepting trade (favorable)');
            sockEmit('trade:accept', { tradeId: offer.id });
        }
    });

    // Also try common event names
    ['tradeOffer', 'trade_offer', 'offer'].forEach(ev => {
        onSock(ev, (data) => {
            console.log(`[RU-CHEAT] Trade event '${ev}':`, data);
        });
    });

    // ─────────────────────────────────────────────
    //  HUD OVERLAY
    // ─────────────────────────────────────────────
    let hudEl = null;

    function createHUD() {
        hudEl = document.createElement('div');
        hudEl.id = 'ru-hud';
        hudEl.innerHTML = `
            <h3>RU-CHEAT v2.0</h3>
            <div id="ru-hud-players">Waiting for game state...</div>
            <div class="ru-controls">
                <button id="ru-btn-bot">BOT: OFF</button>
                <button id="ru-btn-buy">AUTO-BUY: ON</button>
                <button id="ru-btn-build">AUTO-BUILD: ON</button>
                <button id="ru-btn-trade">AUTO-TRADE: OFF</button>
                <button id="ru-btn-dump">DUMP STATE</button>
            </div>
        `;
        document.body.appendChild(hudEl);

        document.getElementById('ru-btn-bot').onclick = () => {
            CFG.botEnabled = !CFG.botEnabled;
            CFG.botEnabled ? startBot() : stopBot();
            updateHUDControls();
        };
        document.getElementById('ru-btn-buy').onclick = () => {
            CFG.autoBuy = !CFG.autoBuy;
            updateHUDControls();
        };
        document.getElementById('ru-btn-build').onclick = () => {
            CFG.autoBuildHotels = !CFG.autoBuildHotels;
            updateHUDControls();
        };
        document.getElementById('ru-btn-trade').onclick = () => {
            CFG.autoAcceptTrade = !CFG.autoAcceptTrade;
            updateHUDControls();
        };
        document.getElementById('ru-btn-dump').onclick = () => {
            const state = getGameState();
            console.log('[RU-CHEAT] Full game state dump:', state);
            alert('Game state dumped to console (F12)');
        };
    }

    function updateHUDControls() {
        const botBtn   = document.getElementById('ru-btn-bot');
        const buyBtn   = document.getElementById('ru-btn-buy');
        const buildBtn = document.getElementById('ru-btn-build');
        const tradeBtn = document.getElementById('ru-btn-trade');
        if (!botBtn) return;
        botBtn.textContent   = `BOT: ${CFG.botEnabled ? 'ON' : 'OFF'}`;
        botBtn.className     = CFG.botEnabled ? 'active' : '';
        buyBtn.textContent   = `AUTO-BUY: ${CFG.autoBuy ? 'ON' : 'OFF'}`;
        buyBtn.className     = CFG.autoBuy ? 'active' : '';
        buildBtn.textContent = `AUTO-BUILD: ${CFG.autoBuildHotels ? 'ON' : 'OFF'}`;
        buildBtn.className   = CFG.autoBuildHotels ? 'active' : '';
        tradeBtn.textContent = `AUTO-TRADE: ${CFG.autoAcceptTrade ? 'ON' : 'OFF'}`;
        tradeBtn.className   = CFG.autoAcceptTrade ? 'active' : '';
    }

    function updateHUDPlayers() {
        const el = document.getElementById('ru-hud-players');
        if (!el) return;

        const state = getGameState();
        if (!state || !state.players) {
            el.textContent = 'Game state not found yet...';
            return;
        }

        el.innerHTML = state.players.map(p => {
            const props = (p.properties || p.ownedProperties || []);
            const propNames = props.map(pr => pr.name || pr.id || pr).join(', ') || 'none';
            const bankrupt  = p.bankrupt || p.isBankrupt ? '<span class="ru-status"> [BANKRUPT]</span>' : '';
            const isTurn    = (state.currentPlayer === p.id || state.currentPlayerId === p.id)
                              ? ' ◀ TURN' : '';
            return `
                <div class="ru-player">
                    <span class="ru-name">${p.name || p.username || 'Player'}</span>${bankrupt}
                    <span style="color:#aaa">${isTurn}</span><br>
                    <span class="ru-money">$${(p.money ?? p.balance ?? '?').toLocaleString()}</span>
                    <span class="ru-pos"> · Pos: ${p.position ?? p.pos ?? '?'}</span><br>
                    <span class="ru-props">Props: ${propNames}</span>
                </div>
            `;
        }).join('');
    }

    // ─────────────────────────────────────────────
    //  HOTKEYS
    // ─────────────────────────────────────────────
    document.addEventListener('keydown', (e) => {
        if (e.key === 'F2') {
            e.preventDefault();
            CFG.botEnabled = !CFG.botEnabled;
            CFG.botEnabled ? startBot() : stopBot();
            updateHUDControls();
            console.log(`[RU-CHEAT] Bot ${CFG.botEnabled ? 'ENABLED' : 'DISABLED'}`);
        }
        if (e.key === 'F3') {
            e.preventDefault();
            console.log('[RU-CHEAT] State dump:', getGameState());
        }
        if (e.key === 'F4') {
            e.preventDefault();
            CFG.hudEnabled = !CFG.hudEnabled;
            if (hudEl) hudEl.style.display = CFG.hudEnabled ? '' : 'none';
        }
    });

    // ─────────────────────────────────────────────
    //  INIT
    // ─────────────────────────────────────────────
    hookSocketIO(); // must run before page JS loads (run-at: document-start)

    // Wait for DOM to be ready, then build HUD and start polling
    window.addEventListener('DOMContentLoaded', () => {
        createHUD();
        // Refresh HUD every second
        setInterval(() => {
            if (CFG.hudEnabled) updateHUDPlayers();
            updateHUDControls();
        }, 1000);
    });

    console.log('[RU-CHEAT] Loaded. F2=bot, F3=dump state, F4=toggle HUD');

})();