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,72 @@
package dnfbridge
import (
"context"
dnfrepo "longheng.io/server/internal/modules/dnf/repository"
"longheng.io/server/internal/modules/dnf/statbuff"
)
// 深渊派对史诗掉落率 = GM 全局倍率 × 角色身上的城镇增益药剂窗口。
//
// 服主 2026-10-03 的原话就是这条口径:
//
// "在服务端看来 无非就是决定是否出史诗前 如果使用了药剂并且在持续时间内
// 把决定出史诗的可能性翻一倍"
//
// 所以这里**只做一件事**:把 currentGMHellEpicDropRatePercent() 的结果按药剂倍率放大。
// 决定出史诗的地方仍然只有 dungeon_hell_party_drop.go 里那一次 gmAdjustHellEpicRarity
// 调用,本函数不新增任何掷骰、也不改稀有度权重。
//
// 为什么要在掉落热路径上读角色记录:药剂是"城镇使用、进图生效"的(PVF
// `[action usable place] [village] [seria room]`),而 runtimeDungeonState.Character
// 是进图那一刻的角色快照,正好包含刚落的增益窗口;掉落发生时再回读一次数据库既没必要,
// 也不会让同一次进图的前后掉落用上不同的值。
//
// 窗口是**角色级**的(存在 Character.Stats,不是账号):谁用的药,就只对谁生效;
// 重登、换频道都不影响它 —— 换频道会新建会话并重跑一次"登录/回城"的恢复投影,
// 窗口本身一直躺在角色记录里。过期的窗口由 statbuff.ActiveEpicDropRate 自己判掉
// (它按 now 比较到期时间),所以"10 分钟到了"这件事不需要调用方再管。
func (s *Service) currentHellPartyEpicDropRatePercent(character dnfrepo.CharacterRecord) int {
percent := s.currentGMHellEpicDropRatePercent()
effect, active := statbuff.ActiveEpicDropRate(character, s.gameplayNow())
if !active {
return clampHellEpicDropRatePercent(percent)
}
multiplier := s.currentEpicDropRatePotionMultiplierPercent(int(effect.MultiplierPercent))
return clampHellEpicDropRatePercent(scaleHellEpicDropRateByPotion(percent, multiplier))
}
// currentEpicDropRatePotionMultiplierPercent 返回本次实际使用的药剂倍数。
//
// 正常情况下就是 PVF 表里查出来的值(1136 ⇒ 200 = 2 倍)。GM 把"临时测试倍率"拧成
// 非 0 时改用它 —— 服主要肉眼确认"用了药剂史诗真的掉得更多",2 倍是看不出来的。
//
// ⚠ 它**只替换倍数**:调用方仍然必须先通过 statbuff.ActiveEpicDropRate(窗口没过期),
// 所以这个旋钮测的仍然是"药剂到底有没有用",不是"GM 能不能硬调掉落"。
// 读设置失败时退回 PVF 倍数(fail-safe:宁可少给加成,也不给一个来路不明的倍数)。
func (s *Service) currentEpicDropRatePotionMultiplierPercent(pvfMultiplierPercent int) int {
settings, err := s.GMGameplaySettings(context.Background())
if err != nil || settings.EpicDropRatePotionTestMultiplierPercent <= 0 {
return pvfMultiplierPercent
}
return settings.EpicDropRatePotionTestMultiplierPercent
}
// scaleHellEpicDropRateByPotion 是纯函数版本:percent × multiplier / 100。
func scaleHellEpicDropRateByPotion(percent int, multiplierPercent int) int {
if percent <= 0 || multiplierPercent <= 0 {
return 0
}
return percent * multiplierPercent / 100
}
func clampHellEpicDropRatePercent(percent int) int {
if percent > gmHellEpicDropRateMaximumPercent {
return gmHellEpicDropRateMaximumPercent
}
if percent < gmHellEpicDropRateMinimumPercent {
return gmHellEpicDropRateMinimumPercent
}
return percent
}