feat(fight): 实现精灵大乱斗模式并优化对战逻辑

新增大乱斗模式(PET_MELEE)支持,重构原有精灵王之战相关逻辑。
更新战斗初始化流程,添加随机精灵选择机制。
调整玩家匹配与取消邀请接口实现方式。
完善战斗结束处理函数,移除未实现异常抛出。
```
This commit is contained in:
2025-11-15 01:53:51 +08:00
parent d73eb9eb26
commit 0e1860bdf4
7 changed files with 123 additions and 67 deletions

View File

@@ -6,8 +6,8 @@ import (
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"blazing/modules/blazing/model"
"math/rand"
"sort"
"sync"
"time"
@@ -100,81 +100,80 @@ func (f *FightC) LoadPercent(c common.PlayerI, percent int32) {
})
}
func (f *FightC) initplayer(c common.PlayerI, opp bool) bool {
func (f *FightC) initplayer(c common.PlayerI) *input.Input {
if len(c.GetInfo().PetList) == 0 {
return false
return nil
}
temp := input.NewInput(f, c)
temp.AllPet = make([]*info.BattlePetEntity, 0)
temp.InitAttackValue()
in := input.NewInput(f, c)
in.AllPet = make([]*info.BattlePetEntity, 0)
in.InitAttackValue()
for i := 0; i < len(c.GetInfo().PetList); i++ {
temp.AllPet = append(temp.AllPet, info.CreateBattlePetEntity(&c.GetInfo().PetList[i], f.rand))
in.AllPet = append(in.AllPet, info.CreateBattlePetEntity(&c.GetInfo().PetList[i], f.rand))
}
sort.Slice(temp.AllPet, func(i, j int) bool {
x, y := temp.AllPet[i], temp.AllPet[j]
// 若x血量>0且y血量=0则x排在前
if x.Info.Hp > 0 && y.Info.Hp <= 0 {
return true
}
// 若x血量=0且y血量>0则x排在后
if x.Info.Hp <= 0 && y.Info.Hp > 0 {
return false
}
// 同类型(都>0或都=0保持原有顺序
return i < j
})
in.SortPet()
switch f.Info.Mode {
case info.BattleMode.SINGLE_MODE:
temp.AllPet = temp.AllPet[:1]
in.AllPet = in.AllPet[:1]
case info.BattleMode.PET_MELEE:
in.AllPet = make([]*info.BattlePetEntity, 0)
for _, v := range RandomElfIDs(3) {
p := model.GenPetInfo(v, 24, -1, -1, -1, 100)
p.CatchTime = uint32(v)
in.AllPet = append(in.AllPet, info.CreateBattlePetEntity(p, f.rand))
}
//in.AllPet = in.AllPet[:3]
default:
}
if opp {
switch f.Info.Status {
case info.BattleStatus.FIGHT_WITH_PLAYER:
default:
temp.Finished = true //PVE 默认boss数据直接加载完成
}
f.Opp = temp //这里是对方的
in.CurrentPet = in.AllPet[0]
return in
}
copier.Copy(&f.Info.OpponentInfo, f.Opp.Player.GetInfo())
f.Info.OpponentPetList = make([]info.ReadyFightPetInfo, len(temp.AllPet))
for i := 0; i < len(temp.AllPet); i++ {
// RandomElfIDs 从1-2000中随机抽取n个不重复的精灵ID
func RandomElfIDs(n int) []int {
if n <= 0 || n > 2000 {
return nil
}
err := copier.CopyWithOption(&f.Info.OpponentPetList[i], &temp.AllPet[i].Info, copier.Option{IgnoreEmpty: true, DeepCopy: true})
if err != nil {
panic(err)
}
}
} else {
f.Our = temp
// 用map记录已抽取的ID避免重复
used := make(map[int]struct{}, n)
ids := make([]int, 0, n)
copier.Copy(&f.Info.OurInfo, f.Our.Player.GetInfo())
f.Info.OurPetList = make([]info.ReadyFightPetInfo, len(temp.AllPet))
for i := 0; i < len(temp.AllPet); i++ {
for len(ids) < n {
// 生成1-2000的随机数
id := rand.Intn(2000) + 1 // rand.Intn(2000)生成0-1999+1后为1-2000
err := copier.CopyWithOption(&f.Info.OurPetList[i], &temp.AllPet[i].Info, copier.Option{IgnoreEmpty: true, DeepCopy: true})
if err != nil {
panic(err)
}
// 检查是否已抽取
if _, exists := used[id]; !exists {
used[id] = struct{}{}
ids = append(ids, id)
}
}
for _, v := range temp.AllPet {
if v.Info.Hp == 0 {
v.NotAlive = true
}
return ids
}
func initfightready(in *input.Input) (info.FightUserInfo, []info.ReadyFightPetInfo) {
t := make([]info.ReadyFightPetInfo, len(in.AllPet))
userindo := info.FightUserInfo{
UserID: in.UserID,
Nick: in.Player.GetInfo().Nick,
}
temp.CurrentPet = temp.AllPet[0]
return true
for i := 0; i < len(in.AllPet); i++ {
err := copier.CopyWithOption(&t[i], &in.AllPet[i].Info, copier.Option{IgnoreEmpty: true, DeepCopy: true})
if err != nil {
panic(err)
}
}
return userindo, t
}
// 创建新战斗,邀请方和被邀请方,或者玩家和野怪方
@@ -192,15 +191,18 @@ func NewFight(mode, status info.EnumBattleMode, p1 common.PlayerI, p2 common.Pla
}
f.Info.Status = status //房主
f.Info.Mode = mode
ok := f.initplayer(p1, false)
if !ok {
return nil
f.Our, f.Opp = f.initplayer(p1), f.initplayer(p2)
f.Info.OurInfo, f.Info.OurPetList = initfightready(f.Our)
f.Info.OpponentInfo, f.Info.OpponentPetList = initfightready(f.Opp)
switch f.Info.Status {
case info.BattleStatus.FIGHT_WITH_PLAYER:
default:
f.Our.Finished = true //PVE 默认boss数据直接加载完成
}
ok = f.initplayer(p2, true)
if !ok {
return nil
}
f.Our.SetOPP(f.Opp)
f.Opp.SetOPP(f.Our)