2025-09-04 02:00:57 +08:00
|
|
|
package service
|
|
|
|
|
|
|
|
|
|
import (
|
2025-09-05 22:40:36 +08:00
|
|
|
"blazing/common/data/xmlres"
|
2025-09-04 02:00:57 +08:00
|
|
|
"blazing/logic/service/fight/info"
|
2025-09-06 00:31:08 +08:00
|
|
|
"blazing/modules/blazing/model"
|
2025-09-04 03:14:43 +08:00
|
|
|
"fmt"
|
2025-09-07 00:23:28 +08:00
|
|
|
"math"
|
2025-09-04 23:57:22 +08:00
|
|
|
"math/rand"
|
2025-09-04 03:14:43 +08:00
|
|
|
"time"
|
2025-09-04 02:00:57 +08:00
|
|
|
|
2025-09-05 22:40:36 +08:00
|
|
|
"github.com/gogf/gf/v2/util/gconv"
|
2025-09-04 02:00:57 +08:00
|
|
|
"github.com/jinzhu/copier"
|
2025-09-06 00:31:08 +08:00
|
|
|
"github.com/mohae/deepcopy"
|
2025-09-07 00:23:28 +08:00
|
|
|
"github.com/panjf2000/ants/v2"
|
2025-09-04 02:00:57 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type PlayerI interface {
|
|
|
|
|
ID() uint32
|
|
|
|
|
MapID() uint32
|
2025-09-05 22:40:36 +08:00
|
|
|
GetAction()
|
2025-09-08 01:23:12 +08:00
|
|
|
GetPetInfo() []model.PetInfo
|
2025-09-04 02:00:57 +08:00
|
|
|
SendPack(b []byte) error
|
|
|
|
|
SendReadyToFightInfo(info.FightStartOutboundInfo)
|
|
|
|
|
SendNoteReadyToFightInfo(info.NoteReadyToFightInfo)
|
2025-09-05 22:40:36 +08:00
|
|
|
SendFightEndInfo(info.FightOverInfo)
|
2025-09-06 01:47:08 +08:00
|
|
|
SendAttackValue(info.AttackValueS)
|
2025-09-07 00:23:28 +08:00
|
|
|
SendChangePet(info.ChangePetInfo)
|
2025-09-08 01:23:12 +08:00
|
|
|
SetFightC(*FightC)
|
|
|
|
|
}
|
|
|
|
|
type Input struct {
|
|
|
|
|
CanChange bool //是否可以死亡切换CanChange
|
|
|
|
|
CurrentPet *info.BattlePetEntity //当前精灵
|
|
|
|
|
AllPet []*info.BattlePetEntity
|
|
|
|
|
Player PlayerI
|
|
|
|
|
Finished bool //是否加载完成
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (i *Input) GetPetInfo() *info.BattlePetEntity {
|
|
|
|
|
|
|
|
|
|
return i.CurrentPet
|
|
|
|
|
|
2025-09-04 02:00:57 +08:00
|
|
|
}
|
2025-09-04 23:57:22 +08:00
|
|
|
|
2025-09-04 02:00:57 +08:00
|
|
|
type FightC struct {
|
2025-09-08 01:23:12 +08:00
|
|
|
Info info.NoteReadyToFightInfo
|
2025-09-07 05:58:47 +08:00
|
|
|
|
|
|
|
|
OwnerID uint32 // 战斗发起者ID
|
2025-09-08 01:23:12 +08:00
|
|
|
Our *Input //始终等于房主ID
|
|
|
|
|
Opp *Input //对手ID
|
|
|
|
|
rand *rand.Rand
|
2025-09-04 23:57:22 +08:00
|
|
|
StartTime time.Time
|
2025-09-05 22:40:36 +08:00
|
|
|
actionChan chan info.BattleActionI // 所有操作统一从这里进入
|
|
|
|
|
Round int //回合数
|
|
|
|
|
EffectS info.NodeManager //effects容器
|
2025-09-08 01:23:12 +08:00
|
|
|
First *BPET
|
|
|
|
|
Second *BPET
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *FightC) GetInputByPlayer(c PlayerI, isOpposite bool) *Input {
|
|
|
|
|
// 判断当前玩家是否为我方玩家
|
|
|
|
|
isOurPlayer := c == f.Our.Player
|
|
|
|
|
|
|
|
|
|
// 逻辑简化:当"是否为我方玩家"与"是否需要对方"状态一致时,返回对方输入,否则返回我方输入
|
|
|
|
|
if isOurPlayer == isOpposite {
|
|
|
|
|
return f.Opp
|
|
|
|
|
}
|
|
|
|
|
return f.Our
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *FightC) GetInputByAction(c info.BattleActionI, isOpposite bool) *Input {
|
|
|
|
|
// 判断动作所属玩家是否为我方
|
|
|
|
|
isOurAction := c.GetPlayerID() == f.Our.Player.ID()
|
|
|
|
|
|
|
|
|
|
// 根据isOpposite决定是否返回相反方向的输入
|
|
|
|
|
if isOurAction == !isOpposite {
|
|
|
|
|
return f.Our
|
|
|
|
|
}
|
|
|
|
|
return f.Opp
|
2025-09-05 22:40:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 玩家逃跑
|
|
|
|
|
func (f *FightC) Escape(c PlayerI) {
|
|
|
|
|
ret := &info.EscapeAction{
|
|
|
|
|
PlayerID: c.ID(),
|
|
|
|
|
Reason: info.FightOverInfo{
|
|
|
|
|
|
|
|
|
|
Reason: uint32(info.BattleOverReason.PlayerEscape),
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f.actionChan <- ret
|
2025-09-04 02:00:57 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-07 00:23:28 +08:00
|
|
|
// 切换精灵 主动和被驱逐
|
|
|
|
|
func (f *FightC) ChangePet(c PlayerI, id int32) {
|
|
|
|
|
ret := &info.ActiveSwitchAction{
|
|
|
|
|
PlayerID: c.ID(),
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
rett := func(t *Input) *info.BattlePetEntity {
|
|
|
|
|
for _, v := range t.AllPet {
|
|
|
|
|
if v.Info.CatchTime == uint32(id) {
|
2025-09-07 00:23:28 +08:00
|
|
|
copier.Copy(&ret.Reason, &v)
|
|
|
|
|
ret.Reason.UserId = c.ID()
|
2025-09-08 01:23:12 +08:00
|
|
|
return v
|
2025-09-07 00:23:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2025-09-07 05:58:47 +08:00
|
|
|
return nil
|
2025-09-07 00:23:28 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
f.GetInputByPlayer(c, false).CurrentPet = rett(f.GetInputByPlayer(c, false))
|
2025-09-07 00:23:28 +08:00
|
|
|
|
|
|
|
|
f.actionChan <- ret
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-04 23:57:22 +08:00
|
|
|
// 玩家使用技能
|
2025-09-06 00:31:08 +08:00
|
|
|
func (f *FightC) UseSkill(c PlayerI, id int32) {
|
2025-09-08 23:17:42 +08:00
|
|
|
|
|
|
|
|
if id == 0 {
|
|
|
|
|
f.actionChan <- &info.SystemGiveUpAction{PlayerID: c.ID()}
|
|
|
|
|
return
|
|
|
|
|
}
|
2025-09-05 22:40:36 +08:00
|
|
|
ret := &info.SelectSkillAction{
|
2025-09-04 23:57:22 +08:00
|
|
|
PlayerID: c.ID(),
|
2025-09-05 22:40:36 +08:00
|
|
|
}
|
2025-09-08 01:23:12 +08:00
|
|
|
ret.PetInfo = f.GetInputByPlayer(c, false).CurrentPet
|
2025-09-04 23:57:22 +08:00
|
|
|
|
2025-09-06 00:31:08 +08:00
|
|
|
for _, v := range ret.PetInfo.Skills {
|
|
|
|
|
|
|
|
|
|
if v != nil && v.ID == int(id) {
|
|
|
|
|
ret.Skill = v
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2025-09-04 23:57:22 +08:00
|
|
|
f.actionChan <- ret
|
2025-09-04 03:05:37 +08:00
|
|
|
}
|
2025-09-04 02:00:57 +08:00
|
|
|
|
2025-09-04 23:57:22 +08:00
|
|
|
// 战斗准备
|
|
|
|
|
func (f *FightC) ReadyFight(c PlayerI) {
|
2025-09-04 02:00:57 +08:00
|
|
|
rett := info.FightStartOutboundInfo{}
|
|
|
|
|
|
2025-09-04 23:57:22 +08:00
|
|
|
copier.Copy(&rett.Info1, &f.Info.OurPetList[0]) // 复制自己的信息
|
2025-09-05 22:40:36 +08:00
|
|
|
copier.Copy(&rett.Info2, &f.Info.OpponentPetList[0])
|
|
|
|
|
rett.Info1.UserID = f.Info.OurInfo.UserID //
|
|
|
|
|
rett.Info2.UserID = f.Info.OpponentInfo.UserID
|
|
|
|
|
|
|
|
|
|
rrsult := func() { //传回函数
|
|
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
f.Our.Player.SendReadyToFightInfo(rett)
|
|
|
|
|
f.Opp.Player.SendReadyToFightInfo(rett)
|
2025-09-05 22:40:36 +08:00
|
|
|
}
|
2025-09-04 02:00:57 +08:00
|
|
|
|
2025-09-04 23:57:22 +08:00
|
|
|
switch f.Info.FightId {
|
|
|
|
|
case 1: // 1v1
|
2025-09-05 22:42:11 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
f.GetInputByPlayer(c, false).Finished = true
|
|
|
|
|
if f.GetInputByPlayer(c, true).Finished {
|
|
|
|
|
rrsult()
|
2025-09-04 02:00:57 +08:00
|
|
|
}
|
2025-09-08 01:23:12 +08:00
|
|
|
|
2025-09-04 23:57:22 +08:00
|
|
|
case 3: // 野怪战斗
|
2025-09-06 00:31:08 +08:00
|
|
|
|
2025-09-05 22:40:36 +08:00
|
|
|
//判断捕捉率大于0
|
|
|
|
|
if gconv.Int(xmlres.PetMAP[int(f.Info.OpponentPetList[0].ID)].CatchRate) > 0 {
|
|
|
|
|
rett.Info2.Catchable = 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rrsult()
|
2025-09-04 02:00:57 +08:00
|
|
|
}
|
2025-09-04 23:57:22 +08:00
|
|
|
}
|
2025-09-07 00:23:28 +08:00
|
|
|
|
|
|
|
|
var Fightpool *ants.Pool
|
2025-09-04 02:00:57 +08:00
|
|
|
|
2025-09-07 00:23:28 +08:00
|
|
|
func init() {
|
|
|
|
|
Fightpool, _ = ants.NewPool(math.MaxInt32)
|
|
|
|
|
//defer p.Release()
|
2025-09-04 02:00:57 +08:00
|
|
|
}
|
2025-09-04 23:57:22 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
// 创建新战斗,邀请方和被邀请方,或者玩家和野怪方
|
|
|
|
|
func NewFight(i info.NoteReadyToFightInfo, p1 PlayerI, p2 PlayerI) *FightC {
|
|
|
|
|
f := &FightC{}
|
|
|
|
|
f.OwnerID = p1.ID()
|
|
|
|
|
f.Info = i //房主
|
|
|
|
|
seed := f.StartTime.UnixNano() ^ int64(p1.ID()) ^ int64(p2.ID()) // ^ int64(f.Round) // 用异或运算混合多维度信息
|
|
|
|
|
f.rand = rand.New(rand.NewSource(seed))
|
|
|
|
|
|
|
|
|
|
f.Our = &Input{
|
|
|
|
|
CurrentPet: info.CreateBattlePetEntity(p1.GetPetInfo()[0], f.rand),
|
|
|
|
|
Player: p1,
|
|
|
|
|
}
|
|
|
|
|
for k, v := range p1.GetPetInfo() {
|
2025-09-08 01:25:48 +08:00
|
|
|
if i.MAXPET == 0 || k < int(i.MAXPET) { //todo 待测试
|
2025-09-08 01:23:12 +08:00
|
|
|
f.Our.AllPet = append(f.Our.AllPet, info.CreateBattlePetEntity(v, f.rand))
|
|
|
|
|
}
|
2025-09-04 23:57:22 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
}
|
2025-09-07 05:58:47 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
f.Opp = &Input{
|
|
|
|
|
CurrentPet: info.CreateBattlePetEntity(p2.GetPetInfo()[0], f.rand),
|
|
|
|
|
Player: p2,
|
2025-09-07 05:58:47 +08:00
|
|
|
}
|
2025-09-08 01:23:12 +08:00
|
|
|
for k, v := range p2.GetPetInfo() {
|
2025-09-08 01:25:48 +08:00
|
|
|
if i.MAXPET == 0 || k < int(i.MAXPET) {
|
2025-09-08 01:23:12 +08:00
|
|
|
f.Opp.AllPet = append(f.Opp.AllPet, info.CreateBattlePetEntity(v, f.rand))
|
|
|
|
|
}
|
2025-09-06 00:31:08 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
p1.SetFightC(f) //给我方追加战斗容器
|
|
|
|
|
p2.SetFightC(f) //给对方增加战斗容器
|
|
|
|
|
defer func() {
|
|
|
|
|
rr := Fightpool.Submit(f.battleLoop)
|
|
|
|
|
if rr != nil {
|
|
|
|
|
panic(rr)
|
|
|
|
|
}
|
|
|
|
|
f.Broadcast(func(ff *Input) {
|
2025-09-04 03:14:43 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
ff.Player.SendNoteReadyToFightInfo(i)
|
|
|
|
|
})
|
|
|
|
|
}()
|
2025-09-07 00:23:28 +08:00
|
|
|
//go f.battleLoop() // 起战斗循环
|
2025-09-08 01:23:12 +08:00
|
|
|
return f
|
2025-09-04 03:14:43 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-05 22:40:36 +08:00
|
|
|
// 广播,并是否结束回合
|
2025-09-08 01:23:12 +08:00
|
|
|
func (f *FightC) Broadcast(t func(ff *Input)) {
|
2025-09-07 05:58:47 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
t(f.Our)
|
2025-09-07 05:58:47 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
t(f.Opp)
|
2025-09-07 05:58:47 +08:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-04 23:57:22 +08:00
|
|
|
// 战斗回合循环
|
2025-09-04 03:14:43 +08:00
|
|
|
func (f *FightC) battleLoop() {
|
2025-09-08 01:23:12 +08:00
|
|
|
f.StartTime = time.Now()
|
|
|
|
|
f.actionChan = make(chan info.BattleActionI, 2) // 初始化全局操作通道
|
|
|
|
|
fmt.Println("战斗开始精灵", f.Our.Player.GetPetInfo()[0].CatchTime)
|
|
|
|
|
//战斗开始前操作
|
|
|
|
|
|
2025-09-04 23:57:22 +08:00
|
|
|
for {
|
2025-09-07 05:58:47 +08:00
|
|
|
|
2025-09-07 00:23:28 +08:00
|
|
|
f.Round++ //回合数自增
|
2025-09-07 05:58:47 +08:00
|
|
|
|
2025-09-10 00:41:09 +08:00
|
|
|
if f.Round > 250 || f.actionChan == nil { //回合数超过250,战斗平局结束
|
|
|
|
|
break
|
2025-09-05 22:40:36 +08:00
|
|
|
}
|
|
|
|
|
actions := make(map[uint32]info.BattleActionI) // 每个玩家一条记录
|
2025-09-04 23:57:22 +08:00
|
|
|
timeout := time.After(60 * time.Second)
|
|
|
|
|
|
|
|
|
|
for len(actions) < 2 {
|
2025-09-04 03:14:43 +08:00
|
|
|
select {
|
2025-09-04 23:57:22 +08:00
|
|
|
case action := <-f.actionChan:
|
2025-09-08 01:23:12 +08:00
|
|
|
// 只接受有效玩家 ID\
|
|
|
|
|
if action == nil {
|
2025-09-04 23:57:22 +08:00
|
|
|
continue
|
|
|
|
|
}
|
2025-09-08 01:23:12 +08:00
|
|
|
|
|
|
|
|
if action.GetPlayerID() != f.Our.Player.ID() && action.GetPlayerID() != f.Opp.Player.ID() {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-07 00:23:28 +08:00
|
|
|
if a, isExpelled := action.(*info.ActiveSwitchAction); isExpelled {
|
2025-09-07 05:58:47 +08:00
|
|
|
//fmt.Println("对方死亡切换")
|
2025-09-08 01:23:12 +08:00
|
|
|
f.Broadcast(func(ff *Input) {
|
|
|
|
|
|
|
|
|
|
ff.Player.SendChangePet(a.Reason)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if f.GetInputByAction(action, false).CanChange {
|
|
|
|
|
//如果是被动切换,不计入回合结算
|
|
|
|
|
f.GetInputByAction(action, false).CanChange = false
|
2025-09-07 00:23:28 +08:00
|
|
|
continue
|
2025-09-08 01:23:12 +08:00
|
|
|
|
2025-09-07 00:23:28 +08:00
|
|
|
}
|
2025-09-05 22:40:36 +08:00
|
|
|
|
2025-09-07 00:23:28 +08:00
|
|
|
}
|
2025-09-05 22:40:36 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
if action.GetPlayerID() != 0 && f.Info.FightId == 3 {
|
|
|
|
|
|
|
|
|
|
f.GetInputByAction(action, true).Player.GetAction()
|
2025-09-05 22:40:36 +08:00
|
|
|
|
|
|
|
|
}
|
2025-09-08 01:23:12 +08:00
|
|
|
|
2025-09-04 23:57:22 +08:00
|
|
|
// 如果该玩家已经提交过,就忽略重复动作
|
2025-09-05 22:40:36 +08:00
|
|
|
if _, exists := actions[uint32(action.GetPlayerID())]; exists {
|
|
|
|
|
fmt.Printf("玩家%d 已经提交过动作,忽略重复\n", action.GetPlayerID())
|
2025-09-04 23:57:22 +08:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-05 22:40:36 +08:00
|
|
|
actions[uint32(action.GetPlayerID())] = action
|
2025-09-07 00:23:28 +08:00
|
|
|
fmt.Println("玩家%d 执行动作", action.GetPlayerID())
|
2025-09-04 23:57:22 +08:00
|
|
|
|
2025-09-04 03:14:43 +08:00
|
|
|
case <-timeout:
|
2025-09-04 23:57:22 +08:00
|
|
|
fmt.Println("回合操作超时")
|
2025-09-08 01:23:12 +08:00
|
|
|
|
|
|
|
|
if _, exists := actions[f.Our.Player.ID()]; !exists {
|
|
|
|
|
actions[f.Our.Player.ID()] = &info.SystemGiveUpAction{PlayerID: f.Our.Player.ID()} //系统选择出手
|
2025-09-04 03:14:43 +08:00
|
|
|
}
|
2025-09-08 01:23:12 +08:00
|
|
|
if _, exists := actions[f.Opp.Player.ID()]; !exists {
|
|
|
|
|
actions[f.Opp.Player.ID()] = &info.SystemGiveUpAction{PlayerID: f.Opp.Player.ID()} //系统选择出手
|
2025-09-04 03:14:43 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-04 23:57:22 +08:00
|
|
|
// 双方动作齐了,取出来结算
|
2025-09-08 23:17:42 +08:00
|
|
|
//todo 如果一方没有选择,实际上就是后端判断PP是否还有,前端是直接发的
|
2025-09-08 01:23:12 +08:00
|
|
|
p1Action := actions[f.Our.Player.ID()]
|
|
|
|
|
p2Action := actions[f.Opp.Player.ID()]
|
2025-09-05 22:40:36 +08:00
|
|
|
fmt.Println("开始结算回合")
|
2025-09-06 01:47:08 +08:00
|
|
|
var BattleActionI [2]info.BattleActionI
|
|
|
|
|
BattleActionI[0], BattleActionI[1] = info.Compare(p1Action, p2Action)
|
2025-09-05 22:40:36 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
switch faction := BattleActionI[0].(type) {
|
|
|
|
|
case *info.EscapeAction: //优先逃跑
|
2025-09-05 22:40:36 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
f.Broadcast(func(ff *Input) {
|
|
|
|
|
ff.Player.SendFightEndInfo(faction.Reason) //广播逃跑原因
|
|
|
|
|
})
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
case *info.PlayerOfflineAction: //单方掉线
|
2025-09-06 00:31:08 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
f.Broadcast(func(ff *Input) {
|
|
|
|
|
ff.Player.SendFightEndInfo(faction.Reason) //广播逃跑原因
|
|
|
|
|
})
|
2025-09-06 00:31:08 +08:00
|
|
|
break
|
2025-09-08 01:23:12 +08:00
|
|
|
case *info.ActiveSwitchAction: //切换上场的
|
|
|
|
|
f.enterturn(BattleActionI[1], nil) //切换,相当于后手直接出手
|
|
|
|
|
|
|
|
|
|
case *info.SelectSkillAction: //选择技能
|
|
|
|
|
//回合前操作,比如挂载buff
|
|
|
|
|
|
2025-09-10 00:41:09 +08:00
|
|
|
f.enterturn(BattleActionI[0], BattleActionI[1])
|
2025-09-08 01:23:12 +08:00
|
|
|
//回合后操作
|
2025-09-06 00:31:08 +08:00
|
|
|
|
|
|
|
|
}
|
2025-09-07 00:23:28 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2025-09-06 01:47:08 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
type BPET struct {
|
|
|
|
|
*Input
|
2025-09-07 05:58:47 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
//*info.SelectSkillAction //技能实体
|
|
|
|
|
*info.BattlePetEntity //精灵实体
|
|
|
|
|
*info.AttackValue
|
|
|
|
|
*FightC
|
|
|
|
|
Damage uint32 //造成伤害
|
|
|
|
|
}
|
2025-09-07 05:58:47 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
// 被击败的ID
|
|
|
|
|
func (b *BPET) IsWin(cache uint32) bool {
|
2025-09-04 02:00:57 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
fmt.Println("当前回合", b.FightC.Round, "开始检查战斗是否结束")
|
2025-09-05 22:40:36 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
var tt []info.ReadyFightPetInfo
|
|
|
|
|
bbb := b.FightC.Info.OurPetList
|
2025-09-06 00:31:08 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
if b.Input.Player.ID() == b.FightC.OwnerID { //如果是房主
|
|
|
|
|
bbb = b.FightC.Info.OpponentPetList
|
|
|
|
|
} else {
|
|
|
|
|
bbb = b.FightC.Info.OurPetList
|
|
|
|
|
}
|
2025-09-05 22:40:36 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
for _, v := range bbb {
|
|
|
|
|
if v.CatchTime == cache {
|
|
|
|
|
v.NotAlive = true
|
2025-09-06 01:47:08 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
}
|
|
|
|
|
tt = append(tt, v)
|
|
|
|
|
}
|
2025-09-05 22:40:36 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
for _, v := range tt {
|
|
|
|
|
if !v.NotAlive { //如果存活
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 解析并 施加effect
|
|
|
|
|
func (f *FightC) parseskill(id *info.SelectSkillAction) {
|
|
|
|
|
temparg := id.Skill.SideEffectArgS
|
|
|
|
|
for _, v := range id.Skill.SideEffectS {
|
|
|
|
|
|
|
|
|
|
t, ok := info.NodeM[v]
|
|
|
|
|
|
|
|
|
|
if ok { //获取成功
|
2025-09-05 22:40:36 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
args := t.GetArgSize()
|
|
|
|
|
t.SetArgs(temparg[:args]) //设置入参
|
|
|
|
|
//如果不是是房主方,说明施加的对象是反的,比如本来是false,实际上是给邀请方施加的
|
|
|
|
|
//所以这里要对target取反
|
|
|
|
|
if id.GetPlayerID() != f.OwnerID {
|
2025-09-08 23:17:42 +08:00
|
|
|
t.SetOwner(!t.GetOwner())
|
2025-09-05 22:40:36 +08:00
|
|
|
}
|
2025-09-08 01:23:12 +08:00
|
|
|
temparg = temparg[args:]
|
|
|
|
|
f.EffectS.AddEffect(deepcopy.Copy(t).(info.Effect))
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-08 02:51:21 +00:00
|
|
|
// 创建BPET实例的辅助函数
|
|
|
|
|
func (f *FightC) newBPET(input *Input) *BPET {
|
|
|
|
|
return &BPET{
|
|
|
|
|
FightC: f,
|
|
|
|
|
Input: input,
|
|
|
|
|
BattlePetEntity: input.CurrentPet,
|
|
|
|
|
AttackValue: info.NewAttackValue(input.Player.ID()),
|
|
|
|
|
Damage: 0,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
func (f *FightC) initAttackers(fattack, sattack info.BattleActionI) {
|
2025-09-08 01:23:12 +08:00
|
|
|
// 伤害值
|
|
|
|
|
|
|
|
|
|
// 根据攻击方归属设置当前战斗的主/次攻击方属性
|
|
|
|
|
var first, second *Input // 定义临时变量存储主/次攻击方
|
|
|
|
|
if fattack.GetPlayerID() == f.OwnerID {
|
|
|
|
|
first = f.Our // 攻击方为我方时,主攻击方是我方
|
|
|
|
|
second = f.Opp // 次攻击方是对方
|
|
|
|
|
} else {
|
|
|
|
|
first = f.Opp // 攻击方为对方时,主攻击方是对方
|
|
|
|
|
second = f.Our // 次攻击方是我方
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 统一赋值,减少重复代码
|
2025-09-08 02:51:21 +00:00
|
|
|
f.First = f.newBPET(first)
|
|
|
|
|
f.Second = f.newBPET(second)
|
2025-09-08 01:23:12 +08:00
|
|
|
|
|
|
|
|
fmt.Println("先手", f.First.CurrentPet.Info.CatchTime, "后手", f.Second.CurrentPet.Info.CatchTime)
|
|
|
|
|
|
|
|
|
|
// TODO: 在这里调用技能结算逻辑
|
2025-09-08 02:51:21 +00:00
|
|
|
}
|
2025-09-08 01:23:12 +08:00
|
|
|
|
2025-09-08 02:51:21 +00:00
|
|
|
// 处理技能攻击逻辑
|
|
|
|
|
func (f *FightC) processSkillAttack(attacker, defender *BPET, skill *info.SelectSkillAction) {
|
2025-09-08 01:23:12 +08:00
|
|
|
f.parseskill(skill)
|
2025-09-08 02:51:21 +00:00
|
|
|
spower := skill.Skill.CalculatePower(defender.Type().ID)
|
|
|
|
|
attacker.Damage = spower
|
|
|
|
|
|
|
|
|
|
// 记录技能信息
|
|
|
|
|
attacker.AttackValue.SkillID = uint32(skill.Skill.ID)
|
|
|
|
|
attacker.AttackValue.AttackTime = skill.Skill.AttackTime()
|
|
|
|
|
// 判断是否暴击
|
|
|
|
|
if _, ok := skill.Skill.IsCritical(); ok {
|
|
|
|
|
attacker.AttackValue.IsCritical = 1
|
|
|
|
|
}
|
2025-09-08 01:23:12 +08:00
|
|
|
|
2025-09-08 02:51:21 +00:00
|
|
|
// 扣减防御方血量
|
|
|
|
|
if attacker.Damage > defender.CurrentPet.Info.Hp {
|
|
|
|
|
defender.CurrentPet.Info.Hp = 0
|
|
|
|
|
} else {
|
|
|
|
|
defender.CurrentPet.Info.Hp -= attacker.Damage
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-08 01:23:12 +08:00
|
|
|
|
2025-09-08 02:51:21 +00:00
|
|
|
// 检查战斗是否结束
|
|
|
|
|
func (f *FightC) winner(winner *BPET) func() {
|
2025-09-08 01:23:12 +08:00
|
|
|
|
2025-09-08 02:51:21 +00:00
|
|
|
return func() {
|
|
|
|
|
f.Broadcast(func(ff *Input) {
|
|
|
|
|
ff.Player.SendFightEndInfo(info.FightOverInfo{
|
|
|
|
|
WinnerId: winner.Player.ID(),
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
close(f.actionChan)
|
2025-09-10 00:41:09 +08:00
|
|
|
//f.actionChan = nil
|
2025-09-08 01:23:12 +08:00
|
|
|
}
|
2025-09-08 02:51:21 +00:00
|
|
|
}
|
|
|
|
|
func (f *FightC) enterturn(fattack, sattack info.BattleActionI) {
|
|
|
|
|
f.initAttackers(fattack, sattack) //初始化先后手
|
|
|
|
|
skill, _ := fattack.(*info.SelectSkillAction)
|
2025-09-08 01:23:12 +08:00
|
|
|
|
2025-09-08 02:51:21 +00:00
|
|
|
f.processSkillAttack(f.First, f.Second, skill)
|
|
|
|
|
fmt.Printf("先手技能伤害: %v, 先手剩余血量: %v\n", f.First.Damage, f.First.CurrentPet.Info.Hp)
|
|
|
|
|
fmt.Printf("%v 先手出招结束\n", f.First.CurrentPet.Info.CatchTime)
|
2025-09-08 01:23:12 +08:00
|
|
|
if f.Second.CurrentPet.Info.Hp > 0 { //如果后手方没被打死
|
|
|
|
|
skill, ok := sattack.(*info.SelectSkillAction)
|
|
|
|
|
if ok {
|
|
|
|
|
|
2025-09-08 02:51:21 +00:00
|
|
|
f.processSkillAttack(f.Second, f.First, skill)
|
|
|
|
|
fmt.Printf("后手技能伤害: %v, 后手剩余血量: %v\n", f.Second.Damage, f.Second.CurrentPet.Info.Hp)
|
|
|
|
|
fmt.Printf("%v 后手出招结束\n", f.Second.CurrentPet.Info.CatchTime)
|
2025-09-07 05:58:47 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
} //还有系统选择放弃出手的
|
|
|
|
|
|
|
|
|
|
if f.First.CurrentPet.Info.Hp == 0 {
|
|
|
|
|
f.First.CanChange = true //被打死就可以切精灵了
|
|
|
|
|
if f.Second.IsWin(f.First.CurrentPet.Info.CatchTime) { //然后检查是否战斗结束
|
2025-09-10 00:41:09 +08:00
|
|
|
defer f.Broadcast(func(ff *Input) {
|
|
|
|
|
ff.Player.SendFightEndInfo(info.FightOverInfo{
|
|
|
|
|
WinnerId: f.Second.Player.ID(),
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
defer close(f.actionChan)
|
2025-09-07 05:58:47 +08:00
|
|
|
|
|
|
|
|
}
|
2025-09-07 00:23:28 +08:00
|
|
|
}
|
2025-09-06 01:47:08 +08:00
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
} else {
|
2025-09-08 02:51:21 +00:00
|
|
|
f.Second.AttackValue = info.NewAttackValue(f.Second.Player.ID()) //已经被打死了,直接将后手方输出归0
|
|
|
|
|
f.Second.CanChange = true //被打死就可以切精灵了
|
|
|
|
|
if f.First.IsWin(f.Second.CurrentPet.Info.CatchTime) { //然后检查是否战斗结束
|
2025-09-10 00:41:09 +08:00
|
|
|
defer f.Broadcast(func(ff *Input) {
|
|
|
|
|
ff.Player.SendFightEndInfo(info.FightOverInfo{
|
|
|
|
|
WinnerId: f.First.Player.ID(),
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
defer close(f.actionChan)
|
2025-09-08 01:23:12 +08:00
|
|
|
|
|
|
|
|
}
|
2025-09-04 03:14:43 +08:00
|
|
|
}
|
2025-09-08 01:23:12 +08:00
|
|
|
|
|
|
|
|
f.Broadcast(func(ff *Input) {
|
|
|
|
|
ret := info.AttackValueS{
|
|
|
|
|
FAttack: *f.First.AttackValue,
|
|
|
|
|
SAttack: *f.Second.AttackValue,
|
|
|
|
|
}
|
|
|
|
|
ret.FAttack.RemainHp = int32(f.First.CurrentPet.Info.Hp)
|
|
|
|
|
|
|
|
|
|
ret.FAttack.LostHp = uint32(f.First.Damage) //先手方造成血量
|
|
|
|
|
ret.SAttack.RemainHp = int32(f.Second.CurrentPet.Info.Hp)
|
|
|
|
|
ret.SAttack.LostHp = uint32(f.Second.Damage) //后手方造成血量
|
2025-09-10 00:41:09 +08:00
|
|
|
//ret.SAttack.Status.Poisoned_1 = 1
|
2025-09-08 01:23:12 +08:00
|
|
|
ff.Player.SendAttackValue(ret)
|
|
|
|
|
})
|
2025-09-08 02:51:21 +00:00
|
|
|
|
2025-09-04 03:14:43 +08:00
|
|
|
}
|