Greasy Fork

Greasy Fork is available in English.

榭洛科特的背包

原名GBF周回本胜利跳过。已重构。现支持:1.关闭左侧边栏,2.攻击后刷新,3.胜利跳过,待追加:4.五神复活增益显示。

当前为 2025-07-26 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name                榭洛科特的背包
// @version             1.4
// @author              Alk
// @license             GPL3.0
// @description         原名GBF周回本胜利跳过。已重构。现支持:1.关闭左侧边栏,2.攻击后刷新,3.胜利跳过,待追加:4.五神复活增益显示。
// @match               *.granbluefantasy.jp
// @grant               unsafeWindow
// @grant               GM_registerMenuCommand
// @grant               GM_setValue
// @grant               GM_getValue
// @run-at              document-start
// @namespace           http://greasyfork.icu/users/1455240
// @icon                https://raw.githubusercontent.com/enorsona/thirdparty/refs/heads/master/sherurotes_carrybag.ico
// ==/UserScript==

// ========== 设置项 ==========
const enable_console_log = true; // 控制是否输出调试日志到控制台
const enable_write_log = false;  // 控制是否写入本地日志(localStorage)
const log_key = 'SierokarteLog';

// ========== 状态读取 ==========
const checkEnabledAttackRefresh = () => {
    return GM_getValue('AttackRefresh', true);
};
const checkEnabledHideSidebar = () => {
    return GM_getValue('HideLeftSidebar', true);
};

let ar_enabled = checkEnabledAttackRefresh();

// ========== 切换刷新功能 ==========
const switchEnabledAttackRefresh = () => {
    const current = checkEnabledAttackRefresh();
    GM_setValue('AttackRefresh', !current);
    location.reload();
};
const switchEnabledHideSidebar = () => {
    const current = checkEnabledHideSidebar();
    GM_setValue('HideLeftSidebar', !current);
    location.reload();
};

// ========== 注册菜单 ==========
const registerMenu = () => {
    GM_registerMenuCommand(
        `攻击后自动刷新:${checkEnabledAttackRefresh() ? '已开启' : '已关闭'}`,
        switchEnabledAttackRefresh
    );
    GM_registerMenuCommand(
        `关闭左侧边栏:${checkEnabledHideSidebar() ? '已开启' : '已关闭'}`,
        switchEnabledHideSidebar
    );
};
registerMenu();

// ========== 日志记录函数 ==========
const write_log = (log) => {
    if (enable_console_log) console.log(`[榭洛科特]:`, log);
    if (!enable_write_log) return;

    const raw_logs = localStorage.getItem(log_key);
    const logs = raw_logs === null ? [] : JSON.parse(raw_logs);
    logs.push({
        'date_time': Date.now(),
        'log': log
    });
    localStorage.setItem(log_key, JSON.stringify(logs));
};

// ========== 设备判断 ==========
const detectDeviceType = () => {
    const userAgent = navigator.userAgent.toLowerCase();
    const isMobile = /iphone|ipad|android|mobile|windows phone|blackberry/.test(userAgent);

    const width = window.innerWidth || document.documentElement.clientWidth;
    const height = window.innerHeight || document.documentElement.clientHeight;
    const aspectRatio = width / height;

    if (!isMobile && aspectRatio < 1) {
        return 'mobile';
    }

    return isMobile ? 'mobile' : 'desktop';
};

// ========== URL 与 JSON 解析 ==========
const tryParseJSON = (response) => {
    try {
        return JSON.parse(response);
    } catch (e) {
        return response;
    }
};

const getURL = (base) => {
    const url = new URL(base);
    const parts = url.pathname.split('/');
    return {
        pathname: url.pathname,
        levels: parts,
        url_type: parts[1],
        action_type: parts[3],
    };
};

const detectURL = (action_type) => {
    if (action_type === 'normal_attack_result.json') return 'attack';
    if (action_type === 'ability_result.json') return 'ability';
    if (action_type === 'summon_result.json') return 'summon';
    return 'other';
};

// ========== 页面控制函数 ==========
const reload = () => location.reload(true);
const goback = () => history.go(-1);

const checkWin = (scenario) => {
    const win = scenario.find(s => s.cmd === "win");
    if (win) {
        write_log(win.is_last_raid);
        return win.is_last_raid === 1 ? 1 : 2;
    }
    return 0;
};

// ========== 拦截并处理XHR ==========
const customLoad = (xhr) => {
    const {url_type, action_type} = getURL(xhr.responseURL);
    if (url_type !== 'rest' || !action_type.includes('.json') || action_type.includes('start.json')) return;

    const response = tryParseJSON(xhr.response);
    if (!response.scenario) return;

    const is_attack = detectURL(action_type) === 'attack';
    write_log(`当前操作为普通攻击:${is_attack}`);
    const status = checkWin(response.scenario);
    write_log(`当前状态为:${status}`);

    if (ar_enabled && is_attack) {
        if (status === 0 || status === 2) {
            write_log('执行刷新当前页。');
            reload();
        } else if (status === 1) {
            write_log('执行返回上一页。');
            goback();
        }
    } else {
        if (status === 1) {
            write_log('执行返回上一页。');
            goback();
        } else if (status === 2) {
            write_log('执行刷新当前页。');
            reload();
        }
    }
};

// ========== Hook XMLHttpRequest ==========
const origSend = unsafeWindow.XMLHttpRequest.prototype.send;
unsafeWindow.XMLHttpRequest.prototype.send = function (...args) {
    this.addEventListener('load', () => {
        if (this.status === 200) {
            customLoad(this);
        }
    });
    origSend.apply(this, args);
};

// ========== 隐藏左侧边栏 ==========
(() => {
    if (detectDeviceType() === 'desktop' || checkEnabledHideSidebar()) {
        window.addEventListener('load', () => {
            try {
                const target = document.body.firstElementChild;
                if (target && target.firstElementChild) {
                    target.removeChild(target.firstElementChild);
                    write_log('已移除左侧边栏。');
                }
            } catch (e) {
                console.warn('隐藏左边栏失败:', e);
            }
        });
    }
})();