Files
bl/logic/controller/fight_boss.go
昔念 dd28d48ca4 ```
feat(build): 更新构建脚本添加资源打包和proto编译

更新build.bat脚本,添加proto文件编译和资源打包功能,调整资源打包顺序。

BREAKING CHANGE: 构建流程发生变化,需要重新生成proto文件和打包资源。

---

refactor(xmlres): 使用gres替换gfile读取资源文件

将xmlres模块中文件读取方式从gfile.GetBytes改为gres.GetContent,
使
2026-01-01 19:57:39 +08:00

240 lines
6.0 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"
"blazing/common/data/xmlres"
"blazing/common/socket/errorcode"
"strings"
"blazing/logic/service/fight"
"blazing/logic/service/fight/info"
"blazing/logic/service/player"
"blazing/modules/blazing/model"
"blazing/modules/config/service"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/grand"
"github.com/samber/lo"
)
// processMonID 处理怪物ID字符串如果是多个ID则随机选择一个
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 := grand.Intn(len(monid))
selected = monid[randomIdx]
}
return selected
}
// PlayerFightBoss 挑战地图boss
// data: 包含挑战Boss信息的输入数据
// player: 当前玩家对象
// 返回: 战斗结果和错误码
func (h Controller) PlayerFightBoss(data *fight.ChallengeBossInboundInfo, p *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
if !p.CanFight() {
return nil, errorcode.ErrorCodes.ErrSystemError
}
var monster *model.PetInfo
monsterInfo := &model.PlayerInfo{}
var taskID int
var canCapture int
mdata, ok := xmlres.MonsterMap[int(p.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
}
for i, bm := range bc.BossMon {
monster = model.GenPetInfo(
gconv.Int(processMonID(bm.MonID)), 24, //24个体
-1,
0, //野怪没特性
bm.Lv, nil)
monster.CatchTime = uint32(i)
if bm.Hp != 0 {
monster.Hp = uint32(bm.Hp)
monster.MaxHp = uint32(bm.Hp)
}
for _, v := range strings.Split(bm.NewSeIdxs, " ") {
idx := gconv.Uint16(v)
if idx == 0 {
continue
}
EID, args := service.NewEffectService().Args(uint32(idx))
monster.EffectInfo = append(monster.EffectInfo, model.PetEffectInfo{
Idx: idx,
EID: gconv.Uint16(EID),
Args: gconv.Ints(args),
})
}
monsterInfo.PetList = append(monsterInfo.PetList, *monster)
}
if bc.BossCatchable == 1 {
canCapture = xmlres.PetMAP[int(monster.ID)].CatchRate
if grand.Meet(1, 100) {
r := monsterInfo.PetList[0]
r.RandShiny()
monsterInfo.PetList[0] = r
}
}
monsterInfo.Nick = bc.Name //xmlres.PetMAP[int(monster.ID)].DefName
break
}
}
if len(monsterInfo.PetList) == 0 {
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
}
p.Fightinfo.Status = info.BattleMode.FIGHT_WITH_NPC
p.Fightinfo.Mode = info.BattleMode.MULTI_MODE
ai := player.NewAI_player(monsterInfo)
ai.CanCapture = canCapture
ai.Prop[0] = 2
fight.NewFight(p, ai, func(foi *info.FightOverInfo) {
if taskID != 0 {
if foi.Reason == 0 && foi.WinnerId == p.Info.UserID {
p.CompletedTask(taskID, 0)
}
}
p.Done.Exec(model.MilestoneMode.BOSS, []uint32{p.Info.MapID, data.BossId, uint32(foi.Reason)}, nil)
})
return nil, -1
}
// OnPlayerFightNpcMonster 战斗野怪
// data: 包含战斗野怪信息的输入数据
// player: 当前玩家对象
// 返回: 战斗结果和错误码
func (h Controller) OnPlayerFightNpcMonster(data1 *fight.FightNpcMonsterInboundInfo, p *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
if !p.CanFight() {
return nil, errorcode.ErrorCodes.ErrSystemError
}
refPet := p.OgreInfo.Data[data1.Number]
if refPet.Id == 0 {
return nil, errorcode.ErrorCodes.ErrPokemonNotExists
}
if refPet.Ext != 0 {
refPet.Id = refPet.Ext
}
monster := model.GenPetInfo(
int(refPet.Id), -1,
-1,
0, //野怪没特性
int(refPet.Lv),
refPet.ShinyInfo)
if refPet.Ext != 0 {
if grand.Meet(3, 100) {
monster.RandShiny()
}
}
monsterInfo := &model.PlayerInfo{}
monsterInfo.Nick = xmlres.PetMAP[int(monster.ID)].DefName
monsterInfo.PetList = append(monsterInfo.PetList, *monster)
ai := player.NewAI_player(monsterInfo)
ai.CanCapture = handleNPCFightSpecial(monster.ID)
p.Fightinfo.Status = info.BattleMode.FIGHT_WITH_NPC //打野怪
p.Fightinfo.Mode = info.BattleMode.MULTI_MODE //多人模式
fight.NewFight(p, ai, func(foi *info.FightOverInfo) {
p.Done.Exec(model.MilestoneMode.Moster, []uint32{p.Info.MapID, monsterInfo.PetList[0].ID, uint32(foi.Reason)}, nil)
if foi.Reason == 0 && foi.WinnerId == p.Info.UserID {
if !p.CanGetExp() {
return
}
exp := uint32(xmlres.PetMAP[int(monster.ID)].YieldingExp) * monster.Level / 7
items := &info.S2C_GET_BOSS_MONSTER{
//EV: 45,
EXP: exp * 2,
}
if refPet.Item != 0 {
p.ItemAdd(refPet.Item, uint32(grand.Intn(2)+1))
items.ItemList = append(items.ItemList, data.ItemInfo{
ItemId: refPet.Item,
ItemCnt: uint32(grand.Intn(2) + 1),
})
}
evs := gconv.Uint32s(strings.Split(xmlres.PetMAP[int(monster.ID)].YieldingEV, " "))
items.EV = lo.Sum(evs) - 1
p.Info.EVPool += lo.Sum(evs) //给予累计学习力
foi.Winpet.AddEV(evs)
p.Info.ExpPool += exp * 4
p.AddPetExp(foi.Winpet, uint32(exp)*2)
p.SendPackCmd(8004, items)
}
})
return nil, -1
}
// handleNPCFightSpecial 处理NPC战斗特殊情况
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
}