2025-11-11 05:54:24 +00:00
|
|
|
|
package fight
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"blazing/cool"
|
|
|
|
|
|
"blazing/logic/service/common"
|
|
|
|
|
|
"blazing/logic/service/fight/action"
|
|
|
|
|
|
"blazing/logic/service/fight/info"
|
|
|
|
|
|
"blazing/logic/service/fight/input"
|
|
|
|
|
|
"context"
|
|
|
|
|
|
"math/rand"
|
|
|
|
|
|
"sort"
|
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/jinzhu/copier"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
type FightC struct {
|
|
|
|
|
|
Info info.NoteReadyToFightInfo
|
|
|
|
|
|
IsReady bool
|
|
|
|
|
|
ownerID uint32 // 战斗发起者ID
|
|
|
|
|
|
Our *input.Input //始终等于房主ID
|
|
|
|
|
|
Opp *input.Input //对手ID
|
|
|
|
|
|
Switch []*action.ActiveSwitchAction
|
|
|
|
|
|
|
|
|
|
|
|
rand *rand.Rand
|
|
|
|
|
|
StartTime time.Time
|
|
|
|
|
|
actionChan chan action.BattleActionI // 所有操作统一从这里进入
|
|
|
|
|
|
Round int //回合数
|
2025-11-11 11:45:09 +00:00
|
|
|
|
quit chan struct{}
|
2025-11-11 05:54:24 +00:00
|
|
|
|
First *input.Input
|
|
|
|
|
|
Second *input.Input
|
|
|
|
|
|
closefight bool
|
|
|
|
|
|
info.FightOverInfo
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (f *FightC) CanEscape() bool {
|
|
|
|
|
|
|
|
|
|
|
|
return f.Info.Status != info.BattleStatus.FIGHT_WITH_PLAYER
|
|
|
|
|
|
}
|
|
|
|
|
|
func (f *FightC) Ownerid() uint32 {
|
|
|
|
|
|
|
|
|
|
|
|
return f.ownerID
|
|
|
|
|
|
}
|
|
|
|
|
|
func (f *FightC) GetInputByPlayer(c common.PlayerI, isOpposite bool) *input.Input {
|
|
|
|
|
|
// 判断当前玩家是否为我方玩家
|
|
|
|
|
|
isOurPlayer := c.GetInfo().UserID == f.ownerID
|
|
|
|
|
|
|
|
|
|
|
|
// 当isOurPlayer与isOpposite值不同时返回我方,相同时返回对方
|
|
|
|
|
|
if isOurPlayer != isOpposite {
|
|
|
|
|
|
return f.Our
|
|
|
|
|
|
}
|
|
|
|
|
|
return f.Opp
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (f *FightC) GetInputByAction(c action.BattleActionI, isOpposite bool) *input.Input {
|
|
|
|
|
|
// 判断动作所属玩家是否为我方
|
|
|
|
|
|
isOurAction := c.GetPlayerID() == f.Our.Player.GetInfo().UserID
|
|
|
|
|
|
|
|
|
|
|
|
// 根据isOpposite决定是否返回相反方向的输入
|
|
|
|
|
|
if isOurAction == !isOpposite {
|
|
|
|
|
|
return f.Our
|
|
|
|
|
|
}
|
|
|
|
|
|
return f.Opp
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 玩家使用技能
|
|
|
|
|
|
func (f *FightC) GetCurrPET(c common.PlayerI) *info.BattlePetEntity {
|
|
|
|
|
|
if f.Our.Player.GetInfo().UserID == c.GetInfo().UserID {
|
|
|
|
|
|
return f.Our.CurrentPet
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return f.Opp.CurrentPet
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
func (f *FightC) GetOpp(c common.PlayerI) *input.Input {
|
|
|
|
|
|
return f.GetInputByPlayer(c, true)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取随机数
|
|
|
|
|
|
func (f *FightC) GetRand() *rand.Rand {
|
|
|
|
|
|
|
|
|
|
|
|
return f.rand
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取随机数
|
|
|
|
|
|
func (f *FightC) IsFirst(play common.PlayerI) bool {
|
|
|
|
|
|
|
|
|
|
|
|
return f.First.Player == play
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 加载进度
|
|
|
|
|
|
func (f *FightC) LoadPercent(c common.PlayerI, percent int32) {
|
|
|
|
|
|
f.GetInputByPlayer(c, true).Player.SendLoadPercent(info.LoadPercentOutboundInfo{
|
|
|
|
|
|
Id: c.GetInfo().UserID,
|
|
|
|
|
|
Percent: uint32(percent),
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (f *FightC) initplayer(c common.PlayerI, opp bool) bool {
|
|
|
|
|
|
if len(c.GetInfo().PetList) == 0 {
|
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
temp := input.NewInput(f, c)
|
|
|
|
|
|
temp.AllPet = make([]*info.BattlePetEntity, 0)
|
|
|
|
|
|
temp.InitAttackValue()
|
|
|
|
|
|
for i := 0; i < len(c.GetInfo().PetList); i++ {
|
|
|
|
|
|
temp.AllPet = append(temp.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
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
switch f.Info.Mode {
|
|
|
|
|
|
case info.BattleMode.SINGLE_MODE:
|
|
|
|
|
|
temp.AllPet = temp.AllPet[:1]
|
|
|
|
|
|
default:
|
|
|
|
|
|
}
|
|
|
|
|
|
if opp {
|
|
|
|
|
|
f.Opp = temp //这里是对方的
|
|
|
|
|
|
|
|
|
|
|
|
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++ {
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
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++ {
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
f.Opp.SetOPP(f.Our)
|
|
|
|
|
|
f.Our.SetOPP(f.Opp)
|
|
|
|
|
|
temp.CurrentPet = temp.AllPet[0]
|
|
|
|
|
|
return true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建新战斗,邀请方和被邀请方,或者玩家和野怪方
|
|
|
|
|
|
func NewFight(mode, status info.EnumBattleMode, p1 common.PlayerI, p2 common.PlayerI) *FightC {
|
|
|
|
|
|
f := &FightC{}
|
|
|
|
|
|
f.ownerID = p1.GetInfo().UserID
|
2025-11-11 11:45:09 +00:00
|
|
|
|
f.quit = make(chan struct{})
|
2025-11-11 05:54:24 +00:00
|
|
|
|
f.StartTime = time.Now()
|
|
|
|
|
|
seed := f.StartTime.UnixNano() ^ int64(p1.GetInfo().UserID) ^ int64(p2.GetInfo().UserID) // ^ int64(f.Round) // 用异或运算混合多维度信息
|
|
|
|
|
|
f.rand = rand.New(rand.NewSource(seed))
|
|
|
|
|
|
f.Info = info.NoteReadyToFightInfo{
|
|
|
|
|
|
|
|
|
|
|
|
Status: status,
|
|
|
|
|
|
}
|
|
|
|
|
|
f.Info.Status = status //房主
|
|
|
|
|
|
f.Info.Mode = mode
|
|
|
|
|
|
ok := f.initplayer(p1, false)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ok = f.initplayer(p2, true)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
i := Fightpool.Free()
|
|
|
|
|
|
if i <= 0 {
|
|
|
|
|
|
Fightpool.Tune(Fightpool.Cap() + 1)
|
|
|
|
|
|
cool.Loger.Error(context.Background(), "Fightpool is full")
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
rr := Fightpool.Submit(f.battleLoop)
|
|
|
|
|
|
if rr != nil {
|
|
|
|
|
|
panic(rr)
|
|
|
|
|
|
}
|
|
|
|
|
|
f.Broadcast(func(ff *input.Input) {
|
|
|
|
|
|
|
|
|
|
|
|
ff.Player.SendNoteReadyToFightInfo(f.Info)
|
|
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
return f
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 被击败的ID
|
|
|
|
|
|
func (b *FightC) IsWin(c *input.Input, cache uint32) bool {
|
|
|
|
|
|
|
|
|
|
|
|
var tt []*info.BattlePetEntity
|
|
|
|
|
|
bbb := b.Our.AllPet
|
|
|
|
|
|
|
|
|
|
|
|
if c.Player.GetInfo().UserID == b.ownerID { //如果是房主
|
|
|
|
|
|
bbb = b.Opp.AllPet
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for _, v := range bbb {
|
|
|
|
|
|
if v.Info.CatchTime == cache {
|
|
|
|
|
|
v.NotAlive = true
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
tt = append(tt, v)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for _, v := range tt {
|
|
|
|
|
|
if !v.NotAlive { //如果存活
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 广播,并是否结束回合
|
|
|
|
|
|
func (f *FightC) Broadcast(t func(ff *input.Input)) {
|
|
|
|
|
|
|
|
|
|
|
|
t(f.Our)
|
|
|
|
|
|
t(f.Opp)
|
|
|
|
|
|
|
|
|
|
|
|
}
|