PokeRogue - Autoplay (basic)

Autoplay helper for PokeRogue: auto-progress and basic auto-battle. Use responsibly (single-player / local saves only).

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

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

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         PokeRogue - Autoplay (basic)
// @namespace    http://tampermonkey.net/
// @version      0.9
// @description  Autoplay helper for PokeRogue: auto-progress and basic auto-battle. Use responsibly (single-player / local saves only).
// @author       Generated with ChatGPT
// @match        https://pokerogue.net/*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    // CONFIG
    const CONFIG = {
        pollInterval: 300,        // ms between checks
        thinkDelay: 300,          // delay before making a move (ms)
        preferHighestPower: true, // choose move with highest power if data available
        autoUseItems: false,      // whether to try to auto-use items from menu
        stopOnLevelUp: false,     // pause autoplay if party levels up
    };

    // internal state
    let running = false;
    let loopHandle = null;

    function log(...args){ console.log('[ARBOT]',...args); }

    // try to safely find the main scene/game object
    function findScene(){
        // common places found by community scripts
        if (window.scene) return window.scene;
        if (window.game && window.game.scene) return window.game.scene;
        if (globalThis?.pokerogue?.getScene) return globalThis.pokerogue.getScene();
        // scan globals for an object that looks like starterData/dexData
        for (const k of Object.keys(window)){
            try{
                const v = window[k];
                if (v && typeof v === 'object'){
                    if ('starterData' in v && 'dexData' in v) return v;
                }
            }catch(e){}
        }
        return null;
    }

    // helpers to simulate clicks on UI elements (buttons that appear in the DOM)
    function clickElement(el){ if(!el) return false; el.dispatchEvent(new MouseEvent('mousedown',{bubbles:true})); el.dispatchEvent(new MouseEvent('mouseup',{bubbles:true})); el.click(); return true; }

    // try to advance dialogue / continue screens
    function tryAdvanceUI(){
        // Usually the game shows "Next" or continues on space/enter; try to click primary button
        const primary = document.querySelector('.dialogue-button, .primary, button.primary, button');
        if(primary){ clickElement(primary); return true; }
        // fallback: press space
        const evt = new KeyboardEvent('keydown', { key: ' ', code: 'Space', bubbles: true });
        document.dispatchEvent(evt);
        return false;
    }

    // basic battle decision logic - best-effort: inspect party and active battle object
    function autoBattle(scene){
        try{
            // community scripts expose scene.fight or scene.battle or scene.battleData
            const battle = scene.fight || scene.battle || scene.battleData || (scene.scene && (scene.scene.fight||scene.scene.battle));
            if(!battle) return false;

            // find active pokemon and available moves
            const active = battle.activePokemon || battle.activePoke || (battle.player && battle.player.active);
            const options = battle.moves || active?.moves || (battle.moveOptions);

            // if there are DOM buttons for moves, try to click best one
            const moveButtons = Array.from(document.querySelectorAll('.move-button, .battle-move, button.move')).filter(Boolean);
            if(moveButtons.length>0){
                // choose button index using simple heuristic
                let bestIndex = 0;
                if(options && options.length === moveButtons.length){
                    let bestScore = -Infinity;
                    for(let i=0;i<options.length;i++){
                        const m = options[i];
                        // estimate power from fields 'power' 'damage' or 'basePower'
                        const power = Number(m?.power ?? m?.damage ?? m?.basePower ?? 0);
                        const acc = Number(m?.accuracy ?? 100);
                        let score = power * (acc/100);
                        // prefer non-damaging moves less
                        if(m?.category === 'status') score *= 0.5;
                        if(score>bestScore){ bestScore = score; bestIndex = i; }
                    }
                }
                // click chosen move after small delay
                setTimeout(()=> clickElement(moveButtons[bestIndex]), CONFIG.thinkDelay);
                return true;
            }

            // fallback: if battle has a method to choose move, call it
            if(typeof battle.chooseMove === 'function'){
                // try to select by highest power
                const moves = battle.moves || active?.moves || [];
                let idx = 0;
                if(moves.length){
                    let best = -Infinity;
                    for(let i=0;i<moves.length;i++){
                        const m = moves[i];
                        const p = Number(m?.power ?? m?.damage ?? 0);
                        if(p>best){ best = p; idx = i; }
                    }
                }
                setTimeout(()=> { try{ battle.chooseMove(idx); }catch(e){/*ignore*/} }, CONFIG.thinkDelay);
                return true;
            }

        }catch(e){ /* ignore */ }
        return false;
    }

    function mainLoop(){
        const scene = findScene();
        if(!scene){ return; }

        // If currently in battle/selection, try to auto-battle
        if(autoBattle(scene)){ return; }

        // otherwise try to advance UI (menus, dialogue, shop screens)
        tryAdvanceUI();
    }

    // public controls (exposed on window for quick toggling)
    function start(){ if(running) return; running = true; log('autoplay started'); loopHandle = setInterval(mainLoop, CONFIG.pollInterval); }
    function stop(){ if(!running) return; running = false; clearInterval(loopHandle); loopHandle = null; log('autoplay stopped'); }

    // expose controls
    globalThis.PokeRogueAutoplay = { start, stop, running: () => running, CONFIG };

    // small UI hint on page
    const badge = document.createElement('div');
    badge.textContent = 'AR-BOT';
    Object.assign(badge.style, {position:'fixed',right:'8px',bottom:'8px',padding:'6px 8px',background:'#111',color:'#fff',zIndex:99999,fontSize:'12px',borderRadius:'6px',opacity:0.6,cursor:'pointer'});
    badge.title = 'Click to toggle autoplay (or use PokeRogueAutoplay.start()/stop() in console)';
    badge.onclick = ()=>{ running? stop():start(); badge.style.background = running? '#a00' : '#111'; };
    document.body.appendChild(badge);

    log('Autoplay helper injected. Use PokeRogueAutoplay.start() to begin.');

})();