Files
bl/logic/controller/fight_boss.go
昔念 5c5e5c06ab ```
feat(fight): 优化Boss战奖励发放与经验通知逻辑

- 重构 Boss 怪物掉落物品发放代码,提高可读性与扩展性
- 注释掉宠物经验变化的通知指令(2509),暂不发送给客户端
- 修复战斗模式判断条件,从 Mode 改为 Status 判断 PVE 战斗
- 调整战斗超时逻辑,修改超时原因并增加调试日志输出
- 优化战斗结束回调执行顺序,确保广播前完成状态更新
- 重写 PetInfo.AddEV 方法,支持更安全
2025-11-23 00:06:14 +08:00

198 lines
4.9 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 {
items := &info.S2C_GET_BOSS_MONSTER{}
items.ItemList = c.ItemAdd(model.ItemInfo{
ItemId: refpet.Item,
ItemCnt: uint32(grand.Intn(2) + 1),
})
c.SendPackCmd(8004, items)
}
foi.Winpet.AddEV(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
}