```
feat(fight): 实现精灵大乱斗模式并优化对战逻辑 新增大乱斗模式(PET_MELEE)支持,重构原有精灵王之战相关逻辑。 更新战斗初始化流程,添加随机精灵选择机制。 调整玩家匹配与取消邀请接口实现方式。 完善战斗结束处理函数,移除未实现异常抛出。 ```
This commit is contained in:
@@ -3,14 +3,24 @@ package controller
|
|||||||
import (
|
import (
|
||||||
"blazing/common/socket/errorcode"
|
"blazing/common/socket/errorcode"
|
||||||
"blazing/logic/service/fight"
|
"blazing/logic/service/fight"
|
||||||
|
"blazing/logic/service/fight/info"
|
||||||
"blazing/logic/service/player"
|
"blazing/logic/service/player"
|
||||||
)
|
)
|
||||||
|
|
||||||
//精灵王之战
|
//大乱斗
|
||||||
|
|
||||||
func (h Controller) PvpKingFight(data *fight.StartPetWarInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
func (h Controller) PET_MELEE(data *fight.StartPetWarInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||||
if !c.CanFight() {
|
if !c.CanFight() {
|
||||||
return nil, errorcode.ErrorCodes.ErrPokemonNotEligible
|
return nil, errorcode.ErrorCodes.ErrPokemonNotEligible
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.PVPinfo = &info.PVPinfo{
|
||||||
|
Mode: info.BattleMode.PET_MELEE,
|
||||||
|
Status: info.BattleStatus.FIGHT_WITH_PLAYER}
|
||||||
|
g := c.PET_MELEE()
|
||||||
|
if g != nil {
|
||||||
|
fight.NewFight(info.BattleMode.PET_MELEE, info.BattleStatus.FIGHT_WITH_PLAYER, c.PET_MELEE(), c) ///开始对战,房主方以及被邀请方
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ func (h Controller) OnPlayerInviteOtherFight(data *fight.InviteToFightInboundInf
|
|||||||
|
|
||||||
// 取消和他人战斗
|
// 取消和他人战斗
|
||||||
func (h Controller) OnPlayerCanceledOtherInviteFight(data *fight.InviteFightCancelInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
func (h Controller) OnPlayerCanceledOtherInviteFight(data *fight.InviteFightCancelInboundInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||||
c.CancelBattle()
|
c.PVPinfo = nil
|
||||||
|
|
||||||
return nil, 0
|
return nil, 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,11 +26,13 @@ import (
|
|||||||
type EnumBattleMode int
|
type EnumBattleMode int
|
||||||
|
|
||||||
var BattleMode = enum.New[struct {
|
var BattleMode = enum.New[struct {
|
||||||
|
PET_MELEE EnumBattleMode `enum:"3"` //乱斗模式
|
||||||
SINGLE_MODE EnumBattleMode `enum:"1"` // 单人模式
|
SINGLE_MODE EnumBattleMode `enum:"1"` // 单人模式
|
||||||
MULTI_MODE EnumBattleMode `enum:"2"` // 多人模式
|
MULTI_MODE EnumBattleMode `enum:"2"` // 多人模式
|
||||||
}]()
|
}]()
|
||||||
var BattleStatus = enum.New[struct {
|
var BattleStatus = enum.New[struct {
|
||||||
// 原ActionScript中的常量映射
|
// 原ActionScript中的常量映射
|
||||||
|
|
||||||
FIGHT_WITH_NPC EnumBattleMode `enum:"3"` // 与NPC战斗
|
FIGHT_WITH_NPC EnumBattleMode `enum:"3"` // 与NPC战斗
|
||||||
FIGHT_WITH_BOSS EnumBattleMode `enum:"2"` // 与BOSS战斗
|
FIGHT_WITH_BOSS EnumBattleMode `enum:"2"` // 与BOSS战斗
|
||||||
FIGHT_WITH_PLAYER EnumBattleMode `enum:"1"` // 与玩家战斗(PVP)
|
FIGHT_WITH_PLAYER EnumBattleMode `enum:"1"` // 与玩家战斗(PVP)
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import (
|
|||||||
"blazing/logic/service/fight/action"
|
"blazing/logic/service/fight/action"
|
||||||
"blazing/logic/service/fight/info"
|
"blazing/logic/service/fight/info"
|
||||||
"blazing/logic/service/fight/input"
|
"blazing/logic/service/fight/input"
|
||||||
|
"blazing/modules/blazing/model"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"sort"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"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 {
|
if len(c.GetInfo().PetList) == 0 {
|
||||||
return false
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
temp := input.NewInput(f, c)
|
in := input.NewInput(f, c)
|
||||||
temp.AllPet = make([]*info.BattlePetEntity, 0)
|
in.AllPet = make([]*info.BattlePetEntity, 0)
|
||||||
temp.InitAttackValue()
|
in.InitAttackValue()
|
||||||
for i := 0; i < len(c.GetInfo().PetList); i++ {
|
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 {
|
in.SortPet()
|
||||||
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
|
|
||||||
})
|
|
||||||
|
|
||||||
switch f.Info.Mode {
|
switch f.Info.Mode {
|
||||||
case info.BattleMode.SINGLE_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:
|
default:
|
||||||
}
|
}
|
||||||
if opp {
|
|
||||||
switch f.Info.Status {
|
|
||||||
case info.BattleStatus.FIGHT_WITH_PLAYER:
|
|
||||||
|
|
||||||
default:
|
in.CurrentPet = in.AllPet[0]
|
||||||
temp.Finished = true //PVE 默认boss数据直接加载完成
|
return in
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandomElfIDs 从1-2000中随机抽取n个不重复的精灵ID
|
||||||
|
func RandomElfIDs(n int) []int {
|
||||||
|
if n <= 0 || n > 2000 {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
f.Opp = temp //这里是对方的
|
|
||||||
|
|
||||||
copier.Copy(&f.Info.OpponentInfo, f.Opp.Player.GetInfo())
|
// 用map记录已抽取的ID,避免重复
|
||||||
f.Info.OpponentPetList = make([]info.ReadyFightPetInfo, len(temp.AllPet))
|
used := make(map[int]struct{}, n)
|
||||||
for i := 0; i < len(temp.AllPet); i++ {
|
ids := make([]int, 0, n)
|
||||||
|
|
||||||
err := copier.CopyWithOption(&f.Info.OpponentPetList[i], &temp.AllPet[i].Info, copier.Option{IgnoreEmpty: true, DeepCopy: true})
|
for len(ids) < n {
|
||||||
|
// 生成1-2000的随机数
|
||||||
|
id := rand.Intn(2000) + 1 // rand.Intn(2000)生成0-1999,+1后为1-2000
|
||||||
|
|
||||||
|
// 检查是否已抽取
|
||||||
|
if _, exists := used[id]; !exists {
|
||||||
|
used[id] = struct{}{}
|
||||||
|
ids = append(ids, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
f.Our = temp
|
|
||||||
|
|
||||||
copier.Copy(&f.Info.OurInfo, f.Our.Player.GetInfo())
|
return userindo, t
|
||||||
f.Info.OurPetList = make([]info.ReadyFightPetInfo, len(temp.AllPet))
|
|
||||||
for i := 0; i < len(temp.AllPet); i++ {
|
|
||||||
|
|
||||||
err := copier.CopyWithOption(&f.Info.OurPetList[i], &temp.AllPet[i].Info, copier.Option{IgnoreEmpty: true, DeepCopy: true})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range temp.AllPet {
|
|
||||||
if v.Info.Hp == 0 {
|
|
||||||
v.NotAlive = true
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
temp.CurrentPet = temp.AllPet[0]
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建新战斗,邀请方和被邀请方,或者玩家和野怪方
|
// 创建新战斗,邀请方和被邀请方,或者玩家和野怪方
|
||||||
@@ -192,15 +191,18 @@ func NewFight(mode, status info.EnumBattleMode, p1 common.PlayerI, p2 common.Pla
|
|||||||
}
|
}
|
||||||
f.Info.Status = status //房主
|
f.Info.Status = status //房主
|
||||||
f.Info.Mode = mode
|
f.Info.Mode = mode
|
||||||
ok := f.initplayer(p1, false)
|
f.Our, f.Opp = f.initplayer(p1), f.initplayer(p2)
|
||||||
if !ok {
|
|
||||||
return nil
|
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.Our.SetOPP(f.Opp)
|
||||||
f.Opp.SetOPP(f.Our)
|
f.Opp.SetOPP(f.Our)
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package input
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"blazing/common/data/xmlres"
|
"blazing/common/data/xmlres"
|
||||||
|
"sort"
|
||||||
|
|
||||||
"blazing/logic/service/common"
|
"blazing/logic/service/common"
|
||||||
"blazing/logic/service/fight/action"
|
"blazing/logic/service/fight/action"
|
||||||
@@ -56,6 +57,29 @@ func NewInput(c common.FightI, p common.PlayerI) *Input {
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (our *Input) SortPet() {
|
||||||
|
sort.Slice(our.AllPet, func(i, j int) bool {
|
||||||
|
x, y := our.AllPet[i], our.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
|
||||||
|
})
|
||||||
|
for _, v := range our.AllPet {
|
||||||
|
if v.Info.Hp == 0 {
|
||||||
|
v.NotAlive = true
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
func (our *Input) GetPetInfo() *info.BattlePetEntity {
|
func (our *Input) GetPetInfo() *info.BattlePetEntity {
|
||||||
|
|
||||||
return our.CurrentPet
|
return our.CurrentPet
|
||||||
@@ -66,6 +90,7 @@ func (our *Input) SetOPP(t *Input) {
|
|||||||
our.Opp = t
|
our.Opp = t
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (our *Input) GenSataus() {
|
func (our *Input) GenSataus() {
|
||||||
our.Status = [20]int8{}
|
our.Status = [20]int8{}
|
||||||
for i := 0; i < 20; i++ { //堆叠状态剩余回合
|
for i := 0; i < 20; i++ { //堆叠状态剩余回合
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ func (e *EffectNode) PreBattleEnd() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *EffectNode) OnBattleEnd() bool {
|
func (e *EffectNode) OnBattleEnd() bool {
|
||||||
panic("not implemented") // TODO: Implement
|
// panic("not implemented") // TODO: Implement
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EffectNode) EFFect_Befer(in *input.Input, effEffect input.Effect) bool {
|
func (e *EffectNode) EFFect_Befer(in *input.Input, effEffect input.Effect) bool {
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ package player
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"blazing/logic/service/common"
|
"blazing/logic/service/common"
|
||||||
|
|
||||||
"blazing/logic/service/fight/info"
|
"blazing/logic/service/fight/info"
|
||||||
"blazing/logic/service/space"
|
"blazing/logic/service/space"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 邀请玩家加入战斗 邀请者,被邀请者,邀请模式
|
// 邀请玩家加入战斗 邀请者,被邀请者,邀请模式
|
||||||
func (lw *Player) InvitePlayerToBattle() {
|
func (lw *Player) InvitePlayerToBattle() {
|
||||||
|
|
||||||
pinfo := lw.PVPinfo
|
pinfo := lw.PVPinfo
|
||||||
space.GetSpace(lw.Info.MapID).User.IterCb(func(key uint32, v common.PlayerI) {
|
space.GetSpace(lw.Info.MapID).User.IterCb(func(key uint32, v common.PlayerI) {
|
||||||
|
|
||||||
@@ -28,11 +30,25 @@ func (lw *Player) InvitePlayerToBattle() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
func (p *Player) PET_MELEE() *Player {
|
||||||
|
var lw *Player
|
||||||
|
//pinfo := lw.PVPinfo
|
||||||
|
space.GetSpace(p.Info.MapID).User.IterCb(func(key uint32, v common.PlayerI) {
|
||||||
|
|
||||||
// 取消对战邀请
|
value := v.(*Player)
|
||||||
func (lw *Player) CancelBattle() {
|
|
||||||
|
|
||||||
lw.PVPinfo = nil
|
if value.PVPinfo != nil && value != p {
|
||||||
|
//确认是乱斗模式
|
||||||
|
|
||||||
|
if value.PVPinfo.Mode == info.BattleMode.PET_MELEE {
|
||||||
|
lw = value
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
return lw
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) SendLoadPercent(b info.LoadPercentOutboundInfo) {
|
func (p *Player) SendLoadPercent(b info.LoadPercentOutboundInfo) {
|
||||||
|
|||||||
Reference in New Issue
Block a user