Files
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

73 lines
3.5 KiB
Go
Raw Permalink 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.
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
}