// ==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 https://greasyfork.org/users/1455240 // @icon https://raw.githubusercontent.com/enorsona/thirdparty/refs/heads/master/sherurotes_carrybag.ico // @downloadURL none // ==/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); } }); } })();