feat(fight): 添加擂台系统相关功能与协议支持

新增了擂台系统相关的消息结构体和处理逻辑,包括:
- 添加了多个与擂台交互的命令结构体(如 ARENA_SET_OWENR、ARENA_FIGHT_OWENR 等)
- 实现了玩家发送擂台信息的方法 Send_ARENA_GET_INFO
- 在 Space 结构中增加了擂台相关信息及操作方法 Can_ARENA 和 UP_ARENA
- 修复了一个伤害计算公式错误,将乘法修正为除法
- 当
This commit is contained in:
2025-11-15 19:11:23 +08:00
parent 79ca4ace98
commit 135419a99e
10 changed files with 169 additions and 4 deletions

View File

@@ -0,0 +1,73 @@
package controller
import (
"blazing/common/socket/errorcode"
"blazing/logic/service/fight"
"blazing/logic/service/fight/info"
"blazing/logic/service/player"
"blazing/logic/service/space"
)
// public static const ARENA_SET_OWENR:uint = 2417;
// 如果星际擂台上无人,站到星际擂台的包
// 前端到后端无数据内容 空包
// 后端到前端无数据内容 空包
// 都需要通过2419包广播更新擂台状态
func (h Controller) ARENA_SET_OWENR(data *fight.ARENA_SET_OWENR, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
if c.CanFight() {
space.GetSpace(c.Info.MapID).UP_ARENA(c, 1)
}
return
}
// public static const ARENA_FIGHT_OWENR:uint = 2418;
// 挑战擂台的包
// 前端到后端无数据内容 空包
// 后端到前端无数据内容 空包
// 还是后端主动发送2503的包给双方前端后 等待前端加载完毕 主动发送2404包通知后端开始战斗
// 并不会通知对方是否接受挑战。只要有人挑战就直接进入对战
func (h Controller) ARENA_FIGHT_OWENR(data *fight.ARENA_FIGHT_OWENR, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
if !c.CanFight() {
return
}
t := space.GetSpace(c.Info.MapID).Can_ARENA(c)
if t != nil {
fight.NewFight(info.BattleMode.SINGLE_MODE, info.BattleStatus.FIGHT_WITH_PLAYER, t, c) ///开始对战,房主方以及被邀请方
}
return
}
// 获取星际擂台信息的包 进入空间站地图前端会发送请求包 或者 有人站到星际擂台上后 广播回包
// 前端到后端无数据内容
// 后端到前端
func (h Controller) ARENA_GET_INFO(data *fight.ARENA_GET_INFO, c *player.Player) (result *info.S2C_ARENA_GET_INFO, err errorcode.ErrorCode) {
result = &space.GetSpace(c.Info.MapID).ARENA
return
}
// public static const ARENA_UPFIGHT:uint = 2420;
// 放弃擂台挑战的包
// 前端到后端无数据内容
// 后端到前端无数据内容
// 都需要通过2419包广播更新擂台状态
func (h Controller) ARENA_UPFIGHT(data *fight.ARENA_UPFIGHT, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
space.GetSpace(c.Info.MapID).UP_ARENA(c, 0)
//result = &info.S2C_ARENA_GET_INFO{}
return
}
func (h Controller) ARENA_OWENR_ACCE(data *fight.ARENA_OWENR_ACCE, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
space.GetSpace(c.Info.MapID).UP_ARENA(c, 3)
//result = &info.S2C_ARENA_GET_INFO{}
return
}
// public static const ARENA_OWENR_ACCE:uint = 2422;
// 此包为擂台战对战结束后 胜方前端会发送给后端 具体作用为通知后端发送2419包更新擂台信息。
// 前端到后端无数据内容
// 后端到前端无数据内容
// public static const ARENA_OWENR_OUT:uint = 2423;
// 此包不清楚具体怎么触发 但已知此包为后端主动发送。不清楚什么情况下回用到

View File

@@ -11,6 +11,7 @@ type PlayerI interface {
SendPack(b []byte) error
SendReadyToFightInfo(info.FightStartOutboundInfo)
SendNoteReadyToFightInfo(info.NoteReadyToFightInfo)
Send_ARENA_GET_INFO(b info.S2C_ARENA_GET_INFO)
SendFightEndInfo(info.FightOverInfo)
GetInfo() *model.PlayerInfo
SendAttackValue(info.AttackValueS)

View File

@@ -35,6 +35,24 @@ type StartPetWarInboundInfo struct {
Head player.TomeeHeader `cmd:"2431" struc:"[0]pad"`
}
type ARENA_SET_OWENR struct {
Head player.TomeeHeader `cmd:"2417" struc:"[0]pad"`
}
type ARENA_FIGHT_OWENR struct {
Head player.TomeeHeader `cmd:"2418" struc:"[0]pad"`
}
type ARENA_GET_INFO struct {
Head player.TomeeHeader `cmd:"2419" struc:"[0]pad"`
}
type ARENA_UPFIGHT struct {
Head player.TomeeHeader `cmd:"2420" struc:"[0]pad"`
}
type ARENA_OWENR_ACCE struct {
Head player.TomeeHeader `cmd:"2422" struc:"[0]pad"`
}
// 表示"宠物王加入"的入站消息数据
type PetKingJoinInboundInfo struct {
Head player.TomeeHeader `cmd:"2413" struc:"[0]pad"`

View File

@@ -37,7 +37,7 @@ func (e *Effect89) Skill_Useed() bool {
return true
}
e.Ctx().Our.Heal(e.Ctx().Our, &action.SelectSkillAction{}, e.Ctx().Our.DamageZone.Damage.Mul(decimal.NewFromInt(int64(e.Args()[1]))))
e.Ctx().Our.Heal(e.Ctx().Our, &action.SelectSkillAction{}, e.Ctx().Our.DamageZone.Damage.Div(decimal.NewFromInt(int64(e.Args()[1]))))
return true
}

View File

@@ -177,7 +177,13 @@ type NoteUseSkillOutboundInfo struct {
FirstAttackInfo AttackValue // 本轮先手的精灵在释放技能结束后的状态
SecondAttackInfo AttackValue // 本轮后手的精灵在释放技能结束后的状态
}
type S2C_ARENA_GET_INFO struct {
Flag uint32 // 0=清除ArenaInfoflag为0时其他字段全为空 1=站上擂台的信息 2=挑战中的信息
Id uint32
Nick string `struc:"[16]byte"`
HostWins uint32 // 应该是擂台人的连胜数
ChallengerID uint32 // 挑战者的userid
}
type FightStartOutboundInfo struct {
// @UInt long类型
IsCanAuto uint32 `fieldDesc:"是否自动 默认给0 怀疑是自动战斗器使用的" `

View File

@@ -51,3 +51,6 @@ func (p *AI_player) SendChangePet(info.ChangePetInfo) {
func (lw *AI_player) SendLoadPercent(info.LoadPercentOutboundInfo) {
}
func (p *AI_player) Send_ARENA_GET_INFO(b info.S2C_ARENA_GET_INFO) {
}

View File

@@ -21,6 +21,10 @@ func (p *Player) SendReadyToFightInfo(b info.FightStartOutboundInfo) {
t1 := NewTomeeHeader(2504, p.Info.UserID)
p.SendPack(t1.Pack(&b))
}
func (p *Player) Send_ARENA_GET_INFO(b info.S2C_ARENA_GET_INFO) {
t1 := NewTomeeHeader(2419, p.Info.UserID)
p.SendPack(t1.Pack(&b))
}
func (p *Player) SendNoteReadyToFightInfo(b info.NoteReadyToFightInfo) {
t1 := NewTomeeHeader(2503, p.Info.UserID)

View File

@@ -309,8 +309,9 @@ func LeaveMap(c common.PlayerI) {
if c.GetInfo().MapID == 0 {
return
}
t := NewTomeeHeader(2002, c.GetInfo().UserID)
t := NewTomeeHeader(2002, c.GetInfo().UserID)
space.GetSpace(c.GetInfo().MapID).UP_ARENA(c, 0) //退出擂台
space.GetSpace(c.GetInfo().MapID).User.Range(func(k uint32, v common.PlayerI) (stop bool) {
if k != c.GetInfo().UserID {

View File

@@ -0,0 +1 @@
package space

View File

@@ -4,6 +4,7 @@ import (
"blazing/common/data/xmlres"
"blazing/common/utils"
"blazing/logic/service/common"
"blazing/logic/service/fight/info"
csmap "github.com/mhmtszr/concurrent-swiss-map"
)
@@ -13,12 +14,69 @@ type Space struct {
User *csmap.CsMap[uint32, common.PlayerI] // 存储玩家数据的map键为玩家ID
CanRefresh bool //是否能够刷怪
//ID uint32 // 地图ID
Name string //地图名称
Name string //地图名称
ARENA info.S2C_ARENA_GET_INFO
ARENA_Player common.PlayerI
// DefaultPos model.Pos //默认位置DefaultPos
//Positions map[uint32]model.Pos //从上一个地图跳转后默认位置 无任何写操作
}
func (s *Space) Can_ARENA(c common.PlayerI) common.PlayerI {
if s.ARENA.Flag != 3 {
s.ARENA.Flag = 3
s.ARENA.ChallengerID = c.GetInfo().UserID
return s.ARENA_Player
}
return nil
}
// flag 0 取消 1为加入 3 为挑战
func (s *Space) UP_ARENA(c common.PlayerI, FLAG uint32) {
switch FLAG {
case 0:
if s.ARENA.Id != c.GetInfo().UserID { //说明不是自己退出
return
}
s.ARENA = info.S2C_ARENA_GET_INFO{}
case 1:
if s.ARENA.Id != 0 { //说明已经有人了
return
}
s.ARENA.Flag = 1
s.ARENA.Id = c.GetInfo().UserID //添加用户ID
s.ARENA.Nick = c.GetInfo().Nick
s.ARENA_Player = c //添加用户
case 3: //胜利替换
if s.ARENA.Flag != 3 { //说明没进入挑战
return
}
if s.ARENA.Id != c.GetInfo().UserID && c.GetInfo().UserID != s.ARENA.ChallengerID { //说明已经有人了
return
}
if c.GetInfo().UserID == s.ARENA.Id {
s.ARENA.HostWins += 1 //连胜+1
}
s.ARENA.Flag = 1
s.ARENA.Id = c.GetInfo().UserID //添加用户ID
s.ARENA.Nick = c.GetInfo().Nick
s.ARENA_Player = c //添加用户
}
s.User.Range(func(playerID uint32, p common.PlayerI) bool {
p.Send_ARENA_GET_INFO(s.ARENA)
return false
})
}
// NewSyncMap 创建一个新的玩家同步map
func NewSpace() *Space {
return &Space{