Files
bl/logic/controller/fight_boss.go
昔念 1dbd4169e9 feat(xmlres): 更新 BOSS 配置结构并优化字段注释
新增多个 BOSS 相关配置字段,包括任务关联、奖励机制与挑战限制等,
增强 BOSS 精灵的可配置性与业务表达能力。同时完善字段注释以对齐 XML
实际使用情况,并保留原有部分字段用于兼容历史配置。

fix(fight): 调整战斗胜利回调执行顺序以确保数据一致性

将战斗结束回调移至广播之前执行,保证在发送战斗结果前已完成所有状态
更新,尤其是针对胜利宠物的信息同步
2025-11-22 22:57:32 +08:00

200 lines
4.8 KiB
Go
Raw 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 controller
import (
"blazing/common/data/xmlres"
"blazing/common/socket/errorcode"
"math/rand"
"strings"
"blazing/logic/service/fight"
"blazing/logic/service/fight/info"
"blazing/logic/service/player"
"blazing/modules/blazing/model"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/grand"
)
func processMonID(bm string) string {
// 按空格分割字符串
monid := strings.Split(bm, " ")
// 过滤分割后可能的空字符串(如连续空格导致的空元素)
filtered := make([]string, 0, len(monid))
for _, m := range monid {
if m != "" {
filtered = append(filtered, m)
}
}
monid = filtered
var selected string
switch len(monid) {
case 0:
// 无元素时,可返回空或默认值(根据业务需求调整)
selected = ""
case 1:
// 长度为1时取第一个唯一的元素
selected = monid[0]
default:
// 长度大于1时随机选取一个
randomIdx := rand.Intn(len(monid))
selected = monid[randomIdx]
}
return selected
}
// 挑战地图boss
func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
var mo *model.PetInfo
moinfo := &model.PlayerInfo{}
var taskid int
var cancpet int
mdata, ok := xmlres.MonsterMap[int(c.Info.MapID)]
if !ok {
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
}
if len(mdata.Bosses) == 0 {
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
}
for _, bc := range mdata.Bosses {
if bc.Id == nil {
bc.Id = gconv.PtrInt(0)
}
if (bc.Id == nil && data.BossId == 0) || uint32(*bc.Id) == data.BossId { //打默认第一个boss
if bc.TaskID != nil {
taskid = *bc.TaskID
}
if bc.BossCatchable == 1 {
cancpet = xmlres.PetMAP[int(mo.ID)].CatchRate
}
for _, bm := range bc.BossMon {
mo = c.GenPetInfo(
gconv.Int(processMonID(bm.MonID)), 24, //24个体
-1,
0, //野怪没特性
0,
bm.Lv)
mo.Hp = uint32(bm.Hp)
mo.MaxHp = uint32(bm.Hp)
moinfo.PetList = append(moinfo.PetList, *mo)
}
moinfo.Nick = xmlres.PetMAP[int(mo.ID)].DefName
break
}
}
c.Fightinfo.Status = info.BattleMode.FIGHT_WITH_NPC
c.Fightinfo.Mode = info.BattleMode.MULTI_MODE
ai := player.NewAI_player(moinfo)
ai.CanCapture = cancpet
fight.NewFight(c, ai, func(foi *info.FightOverInfo) {
c.Done.Exec(model.MilestoneMode.BOSS, []uint32{c.Info.MapID, data.BossId, uint32(foi.Reason)}, func(results *model.MilestoneEX) uint32 {
if foi.Reason == 0 && foi.WinnerId == c.Info.UserID {
if results.CheakNoNumber(1) && taskid != 0 { //触发3次奖励
c.Info.TaskList[taskid-1] = 3
moinfo.PetList[0].Downgrade(1)
PetID := moinfo.PetList[0].ID
newm1 := model.GenPetInfo(int(PetID), -1, -1, 0, 0, 1)
c.Service.Pet.PetAdd(*newm1)
c.SendPackCmd(8004, &info.S2C_GET_BOSS_MONSTER{
BonusID: uint32(taskid),
PetID: PetID,
CaptureTm: newm1.CatchTime,
})
return 1
}
}
return 0
})
})
return nil, -1
}
// 战斗野怪
func (h Controller) OnPlayerFightNpcMonster(data *fight.FightNpcMonsterInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
refpet := c.OgreInfo.Data[data.Number]
if refpet.Id == 0 {
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
}
mo := c.GenPetInfo(
int(refpet.Id), -1,
-1,
0, //野怪没特性
int(refpet.Shiny),
int(refpet.Lv))
moinfo := &model.PlayerInfo{}
moinfo.Nick = xmlres.PetMAP[int(mo.ID)].DefName
moinfo.PetList = append(moinfo.PetList, *mo)
ai := player.NewAI_player(moinfo)
ai.CanCapture = handleNPCFightSpecial(mo.ID)
c.Fightinfo.Status = info.BattleMode.FIGHT_WITH_NPC //打野怪
c.Fightinfo.Mode = info.BattleMode.MULTI_MODE //多人模式
fight.NewFight(c, ai, func(foi *info.FightOverInfo) {
c.Done.Exec(model.MilestoneMode.Moster, []uint32{c.Info.MapID, moinfo.PetList[0].ID, uint32(foi.Reason)}, func(results *model.MilestoneEX) uint32 {
if foi.Reason == 0 && foi.WinnerId == c.Info.UserID {
if refpet.Item != 0 {
c.SendPackCmd(8004, &info.S2C_GET_BOSS_MONSTER{
ItemList: c.ItemAdd(model.ItemInfo{
ItemId: refpet.Item,
ItemCnt: uint32(grand.Intn(2) + 1),
}),
})
}
foi.Winpet.ADD_EV(gconv.Uint32s(strings.Split(xmlres.PetMAP[int(mo.ID)].YieldingEV, " ")))
exp := uint32(xmlres.PetMAP[int(mo.ID)].YieldingExp) * mo.Level / 7
c.Info.ExpPool += exp * 4
c.AddPetExp(foi.Winpet, uint32(exp)*2)
c.SendPackCmd(2509, &info.PET_WAR_EXP_NOTICE{
EXP: exp * 2,
})
}
return 0
})
})
return nil, -1
}
func handleNPCFightSpecial(petid uint32) int {
npcPetID := int(petid)
petCfg, ok := xmlres.PetMAP[npcPetID]
if !ok {
// log.Error(context.Background(), "NPC宠物配置不存在", "petID", npcPetID)
return 0
}
catchRate := gconv.Int(petCfg.CatchRate)
return catchRate
}