DNF90 服务端与启动器完整源码(含 GM 工具功能增强)

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

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

No files matched your search

@@ -0,0 +1,115 @@
package dnfbridge
// ============================================================================
// 神秘异次元遗迹「双组计数下发」—— 已定位通道,但本树格式对不上,未实施
//
// 【本树真正的"计数器表"通道】dungeon_tower_settlement.go:
//
// currentAdventureTowerCountsMsgID = 1294 // 计数器表(class-0 通知)
// currentTowerCharacterEntryMsgID = 546 // 角色侧条目
//
// op1294 的 body 恰好 4 个 u8,由 writeCurrentAdventureTowerCounters 写出:
//
// TowerRemaining[绝望], TowerLimits[绝望], TowerRemaining[悲叹], TowerLimits[悲叹]
//
// op546 的 body 是 `u32 道具ID + u8 剩余`(11008 绝望塔 / 5115 悲叹塔),
// 每次发两条。op1294 重建 tooltip 时会清掉不在表里的行 —— 这正是报告里
// "原塔类行一并保留,避免替换整张计数表时清除原值"所指的那张表。
//
// 目前 op1294 只在**塔类通关**时发送(dungeon_settlement_result_send.go:139
// 的 `plan.TowerRewardMsgID != 0` 分支),所以进入 107/0 时客户端从未收到过
// 任何计数表。
//
// 【为什么没有实施】三处与报告不一致,凭猜下发会写坏客户端 UI 状态:
//
// 1. 报告说「按当前 EXE 的 op1331 读取器」发送;但本树
// dnfenum.CmdPacketAtPriest2Awakening = 1331,且**全代码库没有任何发送
// op1331 的代码**,客户端抓包也从未发出过 1331。
// 2. 报告要下发的是"账号总用量 + 各角色各图用量"两组;而 op1294 的 4 字节
// 结构放的是"塔类剩余/上限 × 2 座塔",**结构上装不下**另一组。
// 3. op16(选图请求,dungeoncmd.SelectDungeonRequest)字段已全部核对:
// DungeonID/Difficulty/EntryOption/SelectionMode/RuntimeState/RuntimeToken/
// Reserved/PartyState/LeaderObjectKey/SpecialMode,**没有次数字段** ——
// 说明次数只能是服务端单向下发,客户端不回报。
//
// 【下一步需要的证据】只要用户确认"进 107/0 停在选图页时界面上是否显示剩余
// 次数",就能判定:不显示 => 该客户端不需要这项,服务端计数已经生效(超额入场
// 会被 Preflight/Commit 拒绝);显示 => 确为 op1294 那张表,再按"追加两组字节"
// 试发并用明文探针观测界面变化。在拿到这个观察前不写猜测格式。
// ============================================================================
// ============================================================================
// 神秘异次元遗迹「保底奖励」—— 已查清:现有独立掉落机制已经覆盖,无需改动
//
// 五件奖励道具(PVF 实测,均在库):
//
// 490006024 闪耀的次元精华 stackable/490006001/chn_490006024.stk
// 490004769 绿色次元精华 stackable/490004001/chn_490004769.stk
// 490004770 红色次元精华 stackable/490004001/chn_490004770.stk
// 490004771 黄色次元精华 stackable/490004001/chn_490004771.stk
// 490004772 蓝色次元精华 stackable/490004001/chn_490004772.stk
//
// 【来源】etc/independent_drop.etc(服务端常量 currentDungeonIndependentDropPath
// = "Etc/Independent_Drop.etc",大小写不敏感)。该表的记录格式已由
// parseCurrentDungeonIndependentDrops 解析为 17 个字段:
//
// values[0] 记录类型(0=怪物, 1=APC)
// values[1] 对象代码(怪物号)
// values[2] 道具 ID
// values[3..7] 五档难度的概率
// values[8..12] 五档难度的判定次数
// values[13..15] 等级下限/上限/难度过滤
// values[16] list 标志
//
// 表里与本活动相关的条目(概率 1000000,恰好等于
// currentDungeonIndependentDropDenominator):
//
// 62040 490004769 概率 1000000×5 次数 1×5
// 110889 490004769 概率 1000000×5 次数 2×5
// 110890 490004769 概率 1000000×5 次数 1×5
// 110891 490004769 概率 1000000×5 次数 1×5
// 110880 490006024 概率 1000000×5 次数 1×5
// 110881 490006024 概率 1000000×5 次数 1×5
// 110920 490004770 概率 1000000×5 次数 4×5
// 110921 490004770 概率 1000000×5 次数 8×5
// 110925 490004771 概率 1000000×5 次数 10×5
// 110926 490004771 概率 1000000×5 次数 10×5
// 110927 490004771 概率 1000000×5 次数 40×5
// 110936 490004772 概率 1000000×5 次数 3×5 ← 现场实测属于副本 4910
// 110938 490004772 概率 1000000×5 次数 6×5
//
// 【为什么这就是"保底"而无需改代码】rollCurrentDungeonIndependentDropEntries
// 对 type 0 的判定是:
//
// probability := currentDungeonIndependentDropProbability(Probability[difficulty], bonusPercent)
// for attempt := 0; attempt < attempts; attempt++ {
// if probability <= rng.Next(currentDungeonIndependentDropDenominator) { continue }
// result = append(result, entry.ItemID)
// }
//
// rng.Next(1000000) 取值区间是 [0,999999],所以 probability == 1000000 时
// `probability <= rng.Next(...)` **恒为假**,每次判定都命中 —— 即 attempts 次
// 全部掉落。这些条目因此每次击杀都稳定产出固定数量,正是"保底奖励"。
//
// 现场佐证:探针曾记录 MOBLEVEL dungeon=4910 ... code=110936 ——
// 110936 正是掉落 490004772(蓝色次元精华)的那只怪,且它确实出现在 4910。
//
// 结论:**不需要为保底奖励新增任何服务端发放逻辑**(可继续遵守报告要求的
// "不新增自定义掉率或奖励")。此前"五图 dgn 无 reward/drop 段"的观察是对的,
// 但精华并不写在 dgn 里,而写在独立掉落表里 —— 这一点已在本次纠正。
// ============================================================================
// currentAbisGuaranteeRewardItemIDs 是五件保底奖励道具的 PVF 身份,以及它们在
// etc/independent_drop.etc 中对应的怪物掉落者。仅供核对,不参与任何发放路径
// (发放由既有的独立掉落链路完成)。
var currentAbisGuaranteeRewardItemIDs = [...]struct {
ItemID uint32
Name string
MonsterID int64
}{
{490006024, "闪耀的次元精华", 110880},
{490004769, "绿色次元精华", 110889},
{490004770, "红色次元精华", 110920},
{490004771, "黄色次元精华", 110925},
{490004772, "蓝色次元精华", 110936},
}