服务端(Go): - GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面 - GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新 - 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新) - 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍 - 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0) - 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算 启动器(Python/JS): - 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭 - GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐) - 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
58 lines
2.3 KiB
Go
58 lines
2.3 KiB
Go
package dnfbridge
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"longheng.io/server/internal/modules/dnf/worldmap"
|
|
)
|
|
|
|
// TestCurrentDungeonRandomizedCreatureQueueKeepsNeutralTeamOnly pins the op479
|
|
// queue to NEUTRAL creatures.
|
|
//
|
|
// Dropping the team filter (tried live 2026-09-16T23:3xZ) did not make 218's
|
|
// hostile 托梅尔 appear: his association row already materializes him, and the
|
|
// queue produced a second, *friendly* 托梅尔 next to it -- the op479 descriptor has
|
|
// no faction field, so everything in the queue is team-neutral for the client.
|
|
// 58530 normalizes to team "monster", so it must stay out of this queue and keep
|
|
// riding the op29 association row (fifth value 0).
|
|
func TestCurrentDungeonRandomizedCreatureQueueKeepsNeutralTeamOnly(t *testing.T) {
|
|
room := worldmap.RoomCoordinate{X: 1, Y: 4}
|
|
groups := [][]currentDungeonRandomizedObjectSelection{{
|
|
{
|
|
Room: room, Family: currentDungeonRandomizedMonsterFamily, Team: "monster",
|
|
DefinitionID: 58530, ObjectKey: 402, Level: 114,
|
|
Position: worldmap.Point{X: 459, Y: 256},
|
|
},
|
|
{
|
|
Room: room, Family: currentDungeonRandomizedMonsterFamily, Team: "neutral",
|
|
DefinitionID: 65673, ObjectKey: 403, Level: 114,
|
|
Position: worldmap.Point{X: 459, Y: 256},
|
|
},
|
|
{
|
|
// Passive objects belong to the association rows only.
|
|
Room: room, Family: currentDungeonRandomizedPassiveFamily, Team: "neutral",
|
|
DefinitionID: 18865, ObjectKey: 404, Level: 114,
|
|
Position: worldmap.Point{X: 459, Y: 256},
|
|
},
|
|
}}
|
|
body, count, err := buildCurrentDungeonRandomizedCreatureQueue(room, groups)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if count != 1 || len(body) != 23 {
|
|
t.Fatalf("queue count=%d body=%x", count, body)
|
|
}
|
|
if got := uint32(body[3]) | uint32(body[4])<<8 | uint32(body[5])<<16 | uint32(body[6])<<24; got != 65673 {
|
|
t.Fatalf("queue definition=%d want 65673 (neutral row only) body=%x", got, body)
|
|
}
|
|
if got := uint16(body[7]) | uint16(body[8])<<8; got != 114 {
|
|
t.Fatalf("queue level=%d want 114 body=%x", got, body)
|
|
}
|
|
if body[22] != currentDungeonExplicitPositionMode {
|
|
t.Fatalf("queue position mode=%d want %d", body[22], currentDungeonExplicitPositionMode)
|
|
}
|
|
if other, otherCount, err := buildCurrentDungeonRandomizedCreatureQueue(worldmap.RoomCoordinate{X: 0, Y: 0}, groups); err != nil || otherCount != 0 || other != nil {
|
|
t.Fatalf("foreign room queue=%x count=%d err=%v", other, otherCount, err)
|
|
}
|
|
}
|