feat(fight): 添加试炼之塔和勇者之塔战斗功能

- 实现FreshChoiceFightLevel方法,支持试炼之塔(2428)和勇者之塔(2414)的关卡选择
- 添加PetTawor方法,支持宠物对战功能,处理CMD 2429和2415命令
- 集成Boss配置服务,动态获取Boss信息并设置战斗属性
- 重构Boss性别检查字段访问路径,修正战斗逻辑错误
- 移除未使用的xmlres依赖
This commit is contained in:
2026-01-01 05:32:56 +08:00
parent 2081331cbd
commit 71fc6de652
6 changed files with 145 additions and 27 deletions

View File

@@ -4,8 +4,13 @@ import (
"blazing/common/socket/errorcode" "blazing/common/socket/errorcode"
"blazing/common/utils" "blazing/common/utils"
"blazing/logic/service/fight" "blazing/logic/service/fight"
fightinfo "blazing/logic/service/fight/info"
"blazing/logic/service/player" "blazing/logic/service/player"
"blazing/logic/service/space/info" "blazing/logic/service/space/info"
"blazing/modules/blazing/model"
configmodel "blazing/modules/config/model"
"blazing/modules/config/service"
configservice "blazing/modules/config/service"
"sync/atomic" "sync/atomic"
"github.com/jinzhu/copier" "github.com/jinzhu/copier"
@@ -25,17 +30,37 @@ import (
func (h Controller) FreshChoiceFightLevel(data *fight.C2S_FRESH_CHOICE_FIGHT_LEVEL, c *player.Player) (result *fight.S2C_FreshChoiceLevelRequestInfo, err errorcode.ErrorCode) { func (h Controller) FreshChoiceFightLevel(data *fight.C2S_FRESH_CHOICE_FIGHT_LEVEL, c *player.Player) (result *fight.S2C_FreshChoiceLevelRequestInfo, err errorcode.ErrorCode) {
result = &fight.S2C_FreshChoiceLevelRequestInfo{} result = &fight.S2C_FreshChoiceLevelRequestInfo{}
c.Info.CurrentFreshStage = utils.Max(c.Info.CurrentFreshStage, 1)
c.Info.CurrentStage = utils.Max(c.Info.CurrentStage, 1)
if data.Level > 0 {
switch data.Head.CMD {
case 2428: //试炼之塔
c.Info.CurrentFreshStage = uint32((data.Level - 1) * 10)
case 2414: //勇者之塔
c.Info.CurrentStage = uint32((data.Level - 1) * 10)
}
}
switch data.Head.CMD { switch data.Head.CMD {
case 2428: //试炼之塔 case 2428: //试炼之塔
c.Info.CurrentFreshStage = utils.Max(c.Info.CurrentFreshStage, 1)
result.CurFightLevel = uint(c.Info.CurrentFreshStage) result.CurFightLevel = uint(c.Info.CurrentFreshStage)
boss := service.NewTower600Service().Boss(c.Info.CurrentFreshStage)
//next := service.NewTower600Service().Boss(c.Info.CurrentFreshStage + 1)
if boss != nil {
for _, v := range boss.BossIds {
r := configservice.NewBossService().Get(v)
result.BossId = append(result.BossId, uint32(r.MonID))
}
}
case 2414: //勇者之塔 case 2414: //勇者之塔
c.Info.CurrentStage = utils.Max(c.Info.CurrentStage, 1)
result.CurFightLevel = uint(c.Info.CurrentStage) result.CurFightLevel = uint(c.Info.CurrentStage)
} }
// 设置Boss ID为固定值10
result.BossId = []uint32{10}
// 重置玩家的Canmon标志位为0表示可以刷怪 // 重置玩家的Canmon标志位为0表示可以刷怪
atomic.StoreUint32(&c.Canmon, 0) atomic.StoreUint32(&c.Canmon, 0)
// 在函数结束时将玩家传送到对应地图 // 在函数结束时将玩家传送到对应地图
@@ -52,3 +77,81 @@ func (h Controller) FreshLeaveFightLevel(data *fight.FRESH_LEAVE_FIGHT_LEVEL, c
c.SendPackCmd(2001, out) c.SendPackCmd(2001, out)
return result, 0 return result, 0
} }
func (h Controller) PetTawor(data *fight.StartTwarInboundInfo, c *player.Player) (result *fight.S2C_ChoiceLevelRequestInfo, err errorcode.ErrorCode) {
if !c.CanFight() {
return nil, errorcode.ErrorCodes.ErrSystemError
}
c.Fightinfo.Mode = fightinfo.BattleMode.MULTI_MODE
c.Fightinfo.Status = fightinfo.BattleMode.FIGHT_WITH_NPC
monsterInfo := &model.PlayerInfo{}
var boss *configmodel.BaseTowerConfig
result = &fight.S2C_ChoiceLevelRequestInfo{}
switch data.Head.CMD {
case 2429: //试炼之塔
boss = service.NewTower600Service().Boss(c.Info.CurrentFreshStage)
next := service.NewTower600Service().Boss(c.Info.CurrentFreshStage + 1)
if next != nil {
for _, v := range next.BossIds {
r := configservice.NewBossService().Get(v)
result.BossID = append(result.BossID, uint32(r.MonID))
}
}
result.CurFightLevel = uint32(c.Info.CurrentFreshStage)
case 2415: //勇者之塔
result.CurFightLevel = uint32(c.Info.CurrentStage)
}
for i, v := range boss.BossIds {
r := configservice.NewBossService().Get(v)
if r != nil {
monster := model.GenPetInfo(int(r.MonID), int(r.Lv), int(r.Nature), 0, int(r.Lv), nil)
if r.Hp != 0 {
monster.Hp = uint32(r.Hp)
monster.MaxHp = uint32(r.Hp)
}
if len(r.Prop) != 0 {
copy(monster.Prop[:], r.Prop)
}
if len(r.SKill) != 0 {
for i := 0; i < len(monster.SkillList); i++ {
if r.SKill[i] != 0 {
monster.SkillList[i].ID = r.SKill[i]
}
}
}
//todo 特性填装
monster.CatchTime = uint32(i)
monsterInfo.PetList = append(monsterInfo.PetList, *monster)
}
}
ai := player.NewAI_player(monsterInfo)
_, err = fight.NewFight(c, ai, func(foi *fightinfo.FightOverInfo) {
if foi.Reason == 0 && foi.WinnerId == c.Info.UserID { //我放获胜
switch data.Head.CMD {
case 2429: //试炼之塔
c.Info.CurrentFreshStage++
case 2415: //勇者之塔
}
}
}) ///开始对战,房主方以及被邀请方
return
}

View File

@@ -21,7 +21,7 @@ func (e *NewSel69) Damage_ADD(t *info.DamageZone) bool {
} }
// 检查对手性别 // 检查对手性别
if e.Ctx().Opp.CurrentPet.Info.Gender != int(e.Args()[0].IntPart()) { if e.Ctx().Opp.CurrentPet.Gender != int(e.Args()[0].IntPart()) {
return true return true
} }

View File

@@ -20,6 +20,12 @@ type ChallengeBossInboundInfo struct {
type NullOutboundInfo struct { type NullOutboundInfo struct {
} }
type S2C_ChoiceLevelRequestInfo struct {
CurFightLevel uint32 `json:"curFightLevel"` // 当前战斗层数
BossLen uint32 `struc:"sizeof=BossID"`
BossID []uint32 `json:"bossId"` // 下一层的精灵id数组
}
// 准备战斗包 // 准备战斗包
type ReadyToFightInboundInfo struct { type ReadyToFightInboundInfo struct {
Head common.TomeeHeader `cmd:"2404" struc:"skip"` Head common.TomeeHeader `cmd:"2404" struc:"skip"`
@@ -34,7 +40,9 @@ type EscapeFightInboundInfo struct {
type StartPetWarInboundInfo struct { type StartPetWarInboundInfo struct {
Head common.TomeeHeader `cmd:"2431" struc:"skip"` Head common.TomeeHeader `cmd:"2431" struc:"skip"`
} }
type StartTwarInboundInfo struct {
Head common.TomeeHeader `cmd:"2429|2415" struc:"skip"`
}
type ARENA_SET_OWENR struct { type ARENA_SET_OWENR struct {
Head common.TomeeHeader `cmd:"2417" struc:"skip"` Head common.TomeeHeader `cmd:"2417" struc:"skip"`
} }

View File

@@ -2,7 +2,6 @@ package fight
import ( import (
"blazing/common/data" "blazing/common/data"
"blazing/common/data/xmlres"
"blazing/common/socket/errorcode" "blazing/common/socket/errorcode"
"blazing/common/utils" "blazing/common/utils"
"blazing/cool" "blazing/cool"
@@ -132,26 +131,6 @@ func (f *FightC) LoadPercent(c common.PlayerI, percent int32) {
var meetpet = make(map[int]model.PetInfo) var meetpet = make(map[int]model.PetInfo)
func initmeetpet() {
meetpet = make(map[int]model.PetInfo)
for i, v := range xmlres.PetMAP {
if v.EvolvesTo != 0 {
continue
}
if v.EvolvFlag != 0 {
continue
}
if v.ID > 2000 {
continue
}
r := model.GenPetInfo(int(v.ID), 24, -1, -1, 100, nil)
meetpet[i] = *r
}
}
func (f *FightC) initplayer(c common.PlayerI) (*input.Input, errorcode.ErrorCode) { func (f *FightC) initplayer(c common.PlayerI) (*input.Input, errorcode.ErrorCode) {
if !c.CanFight() { if !c.CanFight() {

View File

@@ -3,6 +3,8 @@ package service
import ( import (
"blazing/cool" "blazing/cool"
"blazing/modules/config/model" "blazing/modules/config/model"
"github.com/gogf/gf/v2/database/gdb"
) )
type BossService struct { type BossService struct {
@@ -13,6 +15,25 @@ func NewBossService() *BossService {
return &BossService{ return &BossService{
&cool.Service{ &cool.Service{
Model: model.NewBossConfig(), Model: model.NewBossConfig(),
PageQueryOp: &cool.QueryOp{
KeyWordField: []string{"desc"},
},
}, },
} }
} }
func (s *BossService) Get(id uint32) *model.BossConfig {
if id == 0 {
return nil
}
var item *model.BossConfig
cool.DBM(s.Model).Where("id", id).
Cache(gdb.CacheOption{
// Duration: time.Hour,
Force: false,
}).Scan(&item)
return item
}

View File

@@ -16,3 +16,10 @@ func NewTower600Service() *Tower600Service {
}, },
} }
} }
func (s *Tower600Service) Boss(tower_level uint32) *model.BaseTowerConfig {
var config model.Tower600Config
cool.DBM(s.Model).Where("tower_level = ?", tower_level).Scan(&config)
return &config.BaseTowerConfig
}