Files
90CNServer/launcher/index.html
T
hanfuit 645b64fe21 DNF90 服务端与启动器完整源码(含 GM 工具功能增强)
服务端(Go):
- GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面
- GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新
- 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新)
- 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍
- 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0)
- 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算

启动器(Python/JS):
- 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭
- GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐)
- 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
2026-11-04 14:31:55 +08:00

249 lines
19 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>90轮回</title>
<link rel="stylesheet" href="/style.css">
<link rel="stylesheet" href="/shell.css">
</head>
<body>
<!-- 兼容旧 app.js 的隐藏控件 -->
<div id="launcherView" class="hidden" aria-hidden="true">
<div id="logBody"></div>
<span id="statusBadge"><span id="statusText"></span></span>
<span id="footInfo"></span>
<button id="btnStart"></button><button id="btnGm"></button><button id="btnStop"></button>
<button id="btnSponsor"></button><button id="btnWinLoadout"></button><button id="btnWinSetting"></button>
<button id="btnClearLog"></button>
</div>
<div id="appShell">
<header class="shell-topnav">
<div class="shell-brand">
<div class="shell-logo">90</div>
<div><b>90轮回</b><span>启动器 <em>v2.1.0</em></span></div>
</div>
<nav class="shell-nav">
<button class="shell-nav-item active" data-shell-page="start"><span class="nav-ico">▶</span>开始</button>
<button class="shell-nav-item" data-shell-page="gm"><span class="nav-ico">⚙</span>GM工具</button>
<button class="shell-nav-item" data-shell-page="loadout"><span class="nav-ico">🔄</span>一键换装</button>
<button class="shell-nav-item" data-shell-page="servertool"><span class="nav-ico">🧰</span>服务端工具</button>
<button class="shell-nav-item" data-shell-page="companion"><span class="nav-ico">👥</span>支援兵</button>
<button class="shell-nav-item" data-shell-page="plugins"><span class="nav-ico">🧩</span>插件</button>
<div class="shell-nav-gap"></div>
<button class="shell-nav-item" data-shell-page="settings"><span class="nav-ico">⚙</span>设置</button>
<button class="shell-nav-item" data-shell-page="changelog"><span class="nav-ico">📜</span>更新日志</button>
</nav>
<div class="shell-win-controls">
<button class="tb-btn" id="shellWinMin" title="最小化">—</button>
<button class="tb-btn tb-close" id="shellWinClose" title="关闭">×</button>
</div>
</header>
<main class="shell-main">
<header class="shell-topbar">
<div class="shell-crumb" id="shellCrumb">开始 / 本地服务端</div>
</header>
<section class="shell-page active" id="page-start">
<div class="hero">
<div class="hero-bg"></div>
<div class="hero-content">
<div class="hero-kicker">DNF · 90级 · 本地服务端</div>
<h1 id="shellServerName">Server90轮回</h1>
<div class="hero-status">
<span class="live-dot" id="shellStatusDot"></span>
<span id="shellStatusText">检测中…</span>
<span class="muted" id="shellPid">PID —</span>
</div>
<div class="hero-actions">
<button class="start-btn" id="shellStart"><span>▶</span> 开始游戏</button>
<button class="start-menu" id="shellStartMenu">▾</button>
<div class="start-menu-pop hidden" id="shellStartPop">
<button data-shell-action="start">启动服务端并登录</button>
<button data-shell-action="launch">仅启动客户端</button>
<button data-shell-action="stop">关闭服务端</button>
</div>
<button class="account-login" id="shellAccount" title="管理并选择游戏账号">
<span class="account-ico">👤</span>
<span><b>账号管理</b><small id="shellAccountName">加载中…</small></span>
</button>
<div class="account-picker">
<span class="account-picker-label">当前登录账号</span>
<select id="shellAccountSelect" title="选择登录账号"></select>
</div>
<button class="stop-server-btn" id="shellStop"><span>■</span> 关闭服务端</button>
</div>
<div class="hero-hint">服务端和客户端会一起启动,首次约 10 秒;切换账号后再点“开始游戏”可多开。</div>
</div>
<div class="hero-clock" id="shellClock">检查于 --:--:--</div>
</div>
<div class="stat-grid">
<div class="stat-card"><div class="stat-label">版本</div><div class="stat-row"><span>本地</span><b id="statVersion">v2026.11.03</b></div><div class="stat-row"><span>远程最新</span><b class="green" id="statRemote">检查中</b></div><div class="stat-row"><span>状态</span><b class="green" id="statState">—</b></div></div>
<div class="stat-card"><div class="stat-label">运行</div><div class="stat-row"><span>客户端</span><b id="statClient">—</b></div><div class="stat-row"><span>游戏端口</span><b id="statPorts">—</b></div><div class="stat-row"><span>资源</span><b id="statResource">—</b></div></div>
<div class="stat-card"><div class="stat-label">数据</div><div class="stat-row"><span>PVF 文件</span><b id="statPvf">—</b></div><div class="stat-row"><span>客户端目录</span><b class="small" id="statClientDir">—</b></div><div class="stat-row"><span>版本记录</span><b id="statDb">—</b></div></div>
<div class="stat-card"><div class="stat-label">工具</div><div class="stat-row"><span>内置 GM</span><b class="green">已开启</b></div><div class="stat-row"><span>GM 端口</span><b id="statGmPort">18111</b></div><div class="stat-row"><span>接口端口</span><b id="statApiPort">19527</b></div></div>
</div>
</section>
<section class="shell-page" id="page-loadout">
<div class="page-pad">
<div class="page-heading"><div><h2>一键换装</h2><p class="muted">方案保存在 LoadoutTool/config.json;全局热键由启动器后端注册。</p></div><button class="shell-btn primary" id="loSaveConfig">保存配置</button></div>
<div class="loadout-layout">
<div class="loadout-side">
<div class="lo-pages" id="loPages"></div>
<div class="lo-list" id="loList"></div>
<div class="lo-side-actions"><button class="shell-btn" id="loAddPage">新增换装页</button><button class="shell-btn" id="loAddScheme">新增方案</button><button class="shell-btn" id="loDeleteScheme">删除方案</button></div>
</div>
<div class="loadout-main">
<div class="lo-form">
<label>方案名称<input id="loName" class="shell-input"></label>
<label>绑定角色<input id="loCharacter" class="shell-input" placeholder="角色游戏内名称"></label>
<label>热键<input id="loHotkey" class="shell-input" placeholder="例如 Ctrl+F1"></label>
<button class="shell-btn" id="loCaptureHotkey">录制热键</button>
</div>
<div class="lo-toolbar"><button class="shell-btn" id="loRefreshChars">刷新角色</button><button class="shell-btn" id="loSaveCurrent">保存当前装备</button><button class="shell-btn primary" id="loApply">应用方案</button><span id="loStatus" class="muted"></span><span id="loCooldown" class="lo-cooldown"></span></div>
<div class="lo-slots" id="loSlots"><div class="empty-box">选择方案后显示装备快照</div></div>
</div>
</div>
</div>
</section>
<section class="shell-page" id="page-servertool">
<div class="page-pad">
<div class="page-heading"><div><h2>服务端工具</h2><p class="muted">按原 ServerTool 页签组织,配置写入 server-features.json / activity.json。</p></div><span class="tag" id="stSource">文件配置</span></div>
<div class="st-tabs" id="stTabs">
<button class="st-tab active" data-st="global">全局游戏参数</button>
<button class="st-tab" data-st="activity">在线活动</button>
<button class="st-tab" data-st="gameplay">游戏参数</button>
<button class="st-tab" data-st="growth">疲劳/成长</button>
<button class="st-tab" data-st="raid">团本配置</button>
<button class="st-tab" data-st="launch">启动控制</button>
</div>
<div class="st-subtabs" id="stSubTabs"></div>
<div class="st-toolbar"><button class="shell-btn primary" id="stSave">保存当前页</button><button class="shell-btn" id="stReload">重新读取</button><span id="stStatus" class="muted"></span></div>
<div class="st-body" id="stBody"></div>
</div>
</section>
<section class="shell-page" id="page-companion">
<div class="page-pad">
<div class="page-heading"><div><h2>支援兵</h2><p class="muted">按账号配置支援兵;配置只影响下一次进入副本。</p></div><button class="shell-btn primary" id="cpSave">保存配置</button></div>
<div class="cp-toolbar">
<label>账号<select id="cpAccount" class="shell-input"></select></label>
<label>出战角色<select id="cpOwner" class="shell-input"></select></label>
<button class="shell-btn" id="cpReload">刷新</button>
<span id="cpStatus" class="muted"></span>
</div>
<div class="cp-flags">
<label class="st-check"><input type="checkbox" id="cpEnabled">启用支援兵</label>
<label class="st-check"><input type="checkbox" id="cpBalance">读取佩戴装备</label>
<label class="st-check"><input type="checkbox" id="cpProgression">启用成长推进</label>
<label class="st-check"><input type="checkbox" id="cpRandom">随机武器装备</label>
<label class="st-check"><input type="checkbox" id="cpBasicAttack">允许支援兵普攻</label>
</div>
<h3 class="cp-title">选择支援兵角色</h3>
<div class="cp-grid" id="cpGrid"><div class="empty-box">选择出战角色后加载支援兵列表</div></div>
<div class="cp-ai">
<div class="cp-ai-head"><h3>AI 策略</h3><select id="cpAISource" class="shell-input"></select></div>
<div class="st-form">
<label>行为模式<select id="cpAIBehavior"><option value="assist">辅助</option><option value="aggressive">好战</option></select></label>
<label>BUFF 优先级<select id="cpAIBuff"><option value="leader_first">优先队长</option><option value="assist_only">仅辅助</option><option value="off">关闭</option></select></label>
<label>职业连招<select id="cpAIComboPreset"><option value="auto">按职业自动</option><option value="sword_guard">鬼剑士:控制连招</option><option value="fighter_chain">格斗家:近身连招</option><option value="gunner_burst">神枪手:远程爆发</option><option value="mage_control">魔法师:范围控制</option><option value="priest_support">圣职者:辅助连招</option></select></label>
<label>范围技能最少目标<input id="cpAIAoe" type="number" min="2" max="6" step="1"></label>
<label class="st-check"><input type="checkbox" id="cpAIComboEnabled">启用连招</label>
<label class="st-check"><input type="checkbox" id="cpAIProtect">保护队长</label>
</div>
<details class="st-json">
<summary>高级调参:距离、追击、视野、重试和治疗阈值</summary>
<div class="st-form" id="cpAITuning">
<label>思考间隔(ms)<input data-cp-tuning="think_interval_ms" type="number" min="50" max="2000"></label>
<label>辅助攻击间隔(ms)<input data-cp-tuning="assist_attack_interval_ms" type="number" min="200" max="10000"></label>
<label>辅助横向范围<input data-cp-tuning="assist_leash_x" type="number" min="30" max="500"></label>
<label>辅助纵向范围<input data-cp-tuning="assist_leash_y" type="number" min="20" max="300"></label>
<label>追击范围<input data-cp-tuning="chase_range" type="number" min="20" max="1000"></label>
<label>视野范围<input data-cp-tuning="vision_range" type="number" min="100" max="20000"></label>
<label>目标黏性(ms)<input data-cp-tuning="target_stickiness_ms" type="number" min="0" max="10000"></label>
<label>队长治疗阈值(%)<input data-cp-tuning="heal_leader_percent" type="number" min="0" max="100"></label>
<label>自身治疗阈值(%)<input data-cp-tuning="heal_self_percent" type="number" min="0" max="100"></label>
<label>重试间隔(ms)<input data-cp-tuning="retry_ms" type="number" min="50" max="5000"></label>
<label>辅助重试(ms)<input data-cp-tuning="support_retry_ms" type="number" min="100" max="10000"></label>
<label>忙碌移动(ms)<input data-cp-tuning="busy_move_ms" type="number" min="100" max="10000"></label>
<label>卡住判定(ms)<input data-cp-tuning="stuck_ms" type="number" min="100" max="5000"></label>
<label>绕行等待(ms)<input data-cp-tuning="detour_ms" type="number" min="100" max="5000"></label>
<label>放弃目标(ms)<input data-cp-tuning="give_up_ms" type="number" min="500" max="20000"></label>
<label>跟随距离<input data-cp-tuning="follow_distance" type="number" min="20" max="300"></label>
</div>
</details>
<div class="st-note">AI 策略按角色保存;保存后下一次进入副本生效。</div>
</div>
<div class="st-note" id="cpHint">支援兵按账号隔离,只能选择同一账号下的其他角色。</div>
</div>
</section>
<section class="shell-page" id="page-plugins">
<div class="page-pad"><h2>插件</h2><div class="empty-box">插件目录:启动器扩展位,后续接入 LoadoutTool / ServerTool 之外的模块。</div></div>
</section>
<section class="shell-page" id="page-settings">
<div class="page-pad">
<div class="page-heading"><div><h2>设置</h2><p class="muted">当前启动器实际绑定的服务端、数据库和游戏端。</p></div><button class="shell-btn" id="setRefresh">刷新</button></div>
<div class="settings-grid">
<div class="settings-card"><div class="settings-label">服务端根目录</div><div class="settings-value" id="setServerRoot">—</div></div>
<div class="settings-card"><div class="settings-label">服务端控制</div><div class="settings-value" id="setControl">—</div></div>
<div class="settings-card"><div class="settings-label">数据库</div><div class="settings-value" id="setDb">—</div></div>
<div class="settings-card"><div class="settings-label">游戏客户端</div><div class="settings-value" id="setClient">—</div></div>
<div class="settings-card"><div class="settings-label">服务端状态</div><div class="settings-value" id="setRun">—</div></div>
<div class="settings-card"><div class="settings-label">Native API</div><div class="settings-value" id="setNative">—</div></div>
</div>
</div>
</section>
<section class="shell-page" id="page-changelog">
<div class="page-pad"><h2>更新日志</h2><p class="muted">启动器与工具集成记录。</p><div class="empty-box">2.1.0 · 单窗口整合启动器、GM、一键换装、服务端工具</div></div>
</section>
<section class="shell-page" id="page-gm">
<div id="gmView" class="gm-app">
<aside class="gm-sidebar">
<div class="gm-logo"><div class="gm-logo-mark">D</div><div><div class="gm-logo-title">DNF90 GM</div><div class="gm-logo-sub">九零轮回 · 管理工具</div></div></div>
<div class="gm-nav-group">总览</div>
<div class="gm-nav-item active" data-page="dashboard"><span class="ico">📊</span>控制台</div>
<div class="gm-nav-item" data-page="characters"><span class="ico">👥</span>角色管理</div>
<div class="gm-nav-group">资源</div>
<div class="gm-nav-item" data-page="items"><span class="ico">🎁</span>道具发放</div>
<div class="gm-nav-item" data-page="mail"><span class="ico">✉️</span>邮件系统</div>
<div class="gm-nav-item" data-page="inventory"><span class="ico">🎒</span>背包装备</div>
<div class="gm-nav-item" data-page="auction"><span class="ico">🏷️</span>拍卖行</div>
<div class="gm-nav-group">进度</div>
<div class="gm-nav-item" data-page="quests"><span class="ico">📜</span>任务管理</div>
<div class="gm-nav-item" data-page="dungeons"><span class="ico">⚔️</span>副本控制</div>
<div class="gm-nav-group">系统</div>
<div class="gm-nav-item" data-page="wallet"><span class="ico">💰</span>钱包点券</div>
<div class="gm-nav-item" data-page="wipe"><span class="ico">🗑️</span>删档管理</div>
<div class="gm-nav-item" data-page="settings"><span class="ico">⚙️</span>连接设置</div>
<div class="gm-sidebar-foot"><div><span class="conn-dot off" id="gmConnDot"></span><span class="conn-text" id="gmConnText">数据源:SQLite</span></div><button class="gm-back" id="btnBackLauncher">← 返回启动器</button></div>
</aside>
<div class="gm-main"><header class="gm-topbar"><h1 id="gmPageTitle">控制台</h1><span class="gm-crumb" id="gmPageCrumb">/ 服务端总览</span><div class="topbar-spacer"></div><button class="gm-btn gm-btn-sm gm-btn-ghost" id="gmBtnRefresh">↻ 刷新</button><button class="gm-win-btn gm-win-min" id="gmWinMin" title="最小化">—</button><button class="gm-win-btn gm-win-close" id="gmWinClose" title="关闭">×</button></header><div class="gm-content" id="gmContent"></div></div>
</div>
</section>
</main>
</div>
<div class="shell-statusbar"><span><i class="live-dot"></i> <b id="shellBottomStatus">运行中</b></span><span>端口 <b id="shellBottomPort">—</b></span><span>内存 <b id="shellBottomMem">—</b></span><span>CPU <b>0.0%</b></span><span class="grow"></span><span id="shellBottomLog">日志 就绪</span></div>
<div class="win-resize n" data-edge="top"></div><div class="win-resize s" data-edge="bottom"></div>
<div class="win-resize w" data-edge="left"></div><div class="win-resize e" data-edge="right"></div>
<div class="win-resize nw" data-edge="topleft"></div><div class="win-resize ne" data-edge="topright"></div>
<div class="win-resize sw" data-edge="bottomleft"></div><div class="win-resize se" data-edge="bottomright"></div>
<div class="modal-mask hidden" id="sponsorModal"><div class="modal"><div class="modal-head"><span>赞助我们</span><button class="modal-close" id="btnCloseSponsor">×</button></div><div class="modal-body"><p class="sponsor-tip">感谢支持 DNF90 单机模拟器!</p><div class="qrcode-box" id="qrcodeBox"></div></div></div></div>
<div class="modal-mask hidden" id="accountsModal"><div class="modal" style="width:520px"><div class="modal-head"><span>账号管理</span><button class="modal-close" id="btnCloseAccounts" onclick="document.getElementById('accountsModal').classList.add('hidden')">×</button></div><div class="modal-body" style="text-align:left"><div id="accountsList" style="margin-bottom:16px"></div><div class="accounts-add"><div class="accounts-add-title">添加新账号</div><div class="gm-form-row"><div class="gm-field"><label>用户名</label><input class="gm-input" id="newAccUser"></div><div class="gm-field"><label>密码</label><input class="gm-input" id="newAccPass" type="password"></div></div><button class="gm-btn gm-btn-primary" id="btnAddAccount">+ 添加账号</button></div></div></div></div>
<script src="/app.js"></script>
<script src="/shell.js"></script>
</body>
</html>