服务端(Go): - GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面 - GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新 - 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新) - 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍 - 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0) - 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算 启动器(Python/JS): - 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭 - GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐) - 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
88 lines
3.6 KiB
Go
88 lines
3.6 KiB
Go
package dnfbridge
|
||
|
||
import dnfrepo "longheng.io/server/internal/modules/dnf/repository"
|
||
|
||
const (
|
||
defaultCharacterSlots = dnfrepo.DefaultCharacterSlotLimit
|
||
maxCharacterSlots = dnfrepo.MaxCharacterSlotLimit
|
||
noPackRosterWireSlotLimit = defaultCharacterSlots
|
||
// The account starts with 32 unlocked character slots. The current EXE's
|
||
// roster transport is separate: mode-2 carries slots 0..35 and op679 asks
|
||
// for each following 36-slot batch through an op2 mode-4 body.
|
||
currentRosterExtensionBatchSize = 36
|
||
latestRosterRouteNormal = 0
|
||
latestRosterContextNormal = 0
|
||
currentSceneObjectRoute = 0
|
||
currentSceneObjectContext = 0
|
||
upperMaxCharacter = 0xffff
|
||
latestCharacterStateRoute = 1
|
||
latestCharacterCreateEnabled = 1
|
||
latestCharacterStateActive = 1
|
||
latestCharacterStateNormal = 0
|
||
rosterNameMaxBytes = 30
|
||
rosterWideNameUnits = 31
|
||
noPackRosterPreJobBytes = 2
|
||
noPackRosterPostGrowBytes = 2
|
||
rosterLinkedIDBlockSize = 8
|
||
// Current sub_20026C0 consumes a mandatory type-44 raw block after every
|
||
// equipment item ID. Even an empty block has its u32 length prefix.
|
||
noPackRosterEquipRowBytes = 19
|
||
noPackRosterPostEquipBytes = 38
|
||
noPackRosterEntryTailBytes = noPackRosterPreJobBytes + 1 + 1 + noPackRosterPostGrowBytes + 1 + 4 + 4 + 1 + noPackRosterPostEquipBytes
|
||
rosterDefaultPageCount = 1
|
||
createCodeDuplicated = 0x00
|
||
createCodeSlotFull = 0x04
|
||
createCodeServerError = 0x14
|
||
// Current sub_1CFC9C0 silently returns for check-name failure status 0.
|
||
// Status 0x14 selects its visible duplicate-name prompt; the same value is
|
||
// used by the nearest 90US reference after live status-0/2 responses proved
|
||
// silent on the current client.
|
||
checkNameCodeDuplicated = 0x14
|
||
)
|
||
|
||
// currentSceneActorOwnerServerGroup 返回 actor 记录里那个 "server group" 字节。
|
||
//
|
||
// 移植说明:Server-90 里这个值在 90cn-new-native-v1 profile 下取
|
||
// channelAdvertiseID(),旧 profile 下取 currentSceneObjectRoute。本部署服务端
|
||
// 只有旧 profile(instance.go 硬性校验 90cn-decode-bypass-v1,全库无 new-native
|
||
// 代码),所以这里直接返回 currentSceneObjectRoute,与 Server-90 在旧 profile
|
||
// 下的行为逐字节一致。
|
||
//
|
||
// 支援兵的 mode1 需要这个值:它不能用「本地选中角色」的 server group,
|
||
// 否则客户端会把支援兵和本地 actor 归到同一格。
|
||
func (s *Service) currentSceneActorOwnerServerGroup() byte {
|
||
return currentSceneObjectRoute
|
||
}
|
||
|
||
func currentConnectionTownActorOwnerContext(session *gameSession) byte { if session == nil {
|
||
return currentSceneObjectContext
|
||
}
|
||
return session.connectionTownActorOwnerChannel
|
||
}
|
||
|
||
func currentTownActorOwnerContext(session *gameSession) byte {
|
||
if session == nil {
|
||
return currentSceneObjectContext
|
||
}
|
||
return session.townActorOwnerChannel
|
||
}
|
||
|
||
// currentPartySceneOwnerContext is deliberately separate from the selected
|
||
// actor owner. The local mode0/mode1 actor uses context 0 in the current client,
|
||
// while op9/op11 party records and remote actors are keyed by the connected
|
||
// channel. Test/manual sessions may provide an explicit connection owner; live
|
||
// account-bound sessions retain the channel in session.channel even though the
|
||
// local actor field is zero.
|
||
func currentPartySceneOwnerContext(session *gameSession) byte {
|
||
if session == nil {
|
||
return currentSceneObjectContext
|
||
}
|
||
if session.connectionTownActorOwnerChannel != currentSceneObjectContext {
|
||
return session.connectionTownActorOwnerChannel
|
||
}
|
||
if session.channel.ID > 0 && session.channel.ID <= 0xff {
|
||
return byte(session.channel.ID)
|
||
}
|
||
return session.townActorOwnerChannel
|
||
}
|