2025-09-14 01:35:16 +08:00
|
|
|
|
package fight
|
2025-09-04 02:00:57 +08:00
|
|
|
|
|
|
|
|
|
|
import (
|
2025-09-23 17:34:58 +00:00
|
|
|
|
"blazing/common/data/xmlres"
|
2025-09-14 01:35:16 +08:00
|
|
|
|
"blazing/logic/service/common"
|
2025-09-04 02:00:57 +08:00
|
|
|
|
"blazing/logic/service/fight/info"
|
2025-09-14 01:35:16 +08:00
|
|
|
|
"blazing/logic/service/fight/input"
|
|
|
|
|
|
"blazing/logic/service/player"
|
2025-09-04 03:14:43 +08:00
|
|
|
|
"fmt"
|
2025-09-04 23:57:22 +08:00
|
|
|
|
"math/rand"
|
2025-09-14 01:35:16 +08:00
|
|
|
|
"sort"
|
2025-09-04 03:14:43 +08:00
|
|
|
|
"time"
|
2025-09-04 02:00:57 +08:00
|
|
|
|
|
|
|
|
|
|
"github.com/jinzhu/copier"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
type FightC struct {
|
2025-09-08 01:23:12 +08:00
|
|
|
|
Info info.NoteReadyToFightInfo
|
2025-09-07 05:58:47 +08:00
|
|
|
|
|
2025-09-19 06:58:42 +00:00
|
|
|
|
ownerID uint32 // 战斗发起者ID
|
|
|
|
|
|
Our *input.Input //始终等于房主ID
|
|
|
|
|
|
Opp *input.Input //对手ID
|
|
|
|
|
|
Switch []*ActiveSwitchAction
|
|
|
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
|
rand *rand.Rand
|
2025-09-04 23:57:22 +08:00
|
|
|
|
StartTime time.Time
|
2025-09-14 01:35:16 +08:00
|
|
|
|
actionChan chan BattleActionI // 所有操作统一从这里进入
|
|
|
|
|
|
Round int //回合数
|
2025-09-14 03:36:26 +08:00
|
|
|
|
|
2025-09-14 19:59:58 +08:00
|
|
|
|
First *input.Input
|
|
|
|
|
|
Second *input.Input
|
|
|
|
|
|
closefight bool
|
2025-09-08 01:23:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-14 01:35:16 +08:00
|
|
|
|
func (f *FightC) Ownerid() uint32 {
|
|
|
|
|
|
|
|
|
|
|
|
return f.ownerID
|
|
|
|
|
|
}
|
|
|
|
|
|
func (f *FightC) GetInputByPlayer(c common.PlayerI, isOpposite bool) *input.Input {
|
2025-09-08 01:23:12 +08:00
|
|
|
|
// 判断当前玩家是否为我方玩家
|
2025-09-24 12:40:13 +08:00
|
|
|
|
isOurPlayer := c.GetInfo().UserID == f.ownerID
|
2025-09-08 01:23:12 +08:00
|
|
|
|
|
2025-09-23 13:24:40 +08:00
|
|
|
|
// 当isOurPlayer与isOpposite值不同时返回我方,相同时返回对方
|
|
|
|
|
|
if isOurPlayer != isOpposite {
|
|
|
|
|
|
return f.Our
|
2025-09-08 01:23:12 +08:00
|
|
|
|
}
|
2025-09-23 13:24:40 +08:00
|
|
|
|
return f.Opp
|
2025-09-08 01:23:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-14 01:35:16 +08:00
|
|
|
|
func (f *FightC) GetInputByAction(c BattleActionI, isOpposite bool) *input.Input {
|
2025-09-08 01:23:12 +08:00
|
|
|
|
// 判断动作所属玩家是否为我方
|
2025-09-21 14:56:37 +00:00
|
|
|
|
isOurAction := c.GetPlayerID() == f.Our.Player.GetInfo().UserID
|
2025-09-08 01:23:12 +08:00
|
|
|
|
|
|
|
|
|
|
// 根据isOpposite决定是否返回相反方向的输入
|
|
|
|
|
|
if isOurAction == !isOpposite {
|
|
|
|
|
|
return f.Our
|
|
|
|
|
|
}
|
|
|
|
|
|
return f.Opp
|
2025-09-05 22:40:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-14 01:35:16 +08:00
|
|
|
|
// 玩家使用技能
|
|
|
|
|
|
func (f *FightC) GetCurrPET(c common.PlayerI) *info.BattlePetEntity {
|
2025-09-21 14:56:37 +00:00
|
|
|
|
if f.Our.Player.GetInfo().UserID == c.GetInfo().UserID {
|
2025-09-14 01:35:16 +08:00
|
|
|
|
return f.Our.CurrentPet
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return f.Opp.CurrentPet
|
|
|
|
|
|
}
|
2025-09-11 02:44:21 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-14 03:36:26 +08:00
|
|
|
|
// 获取随机数
|
|
|
|
|
|
func (f *FightC) GetRand() *rand.Rand {
|
2025-09-04 02:00:57 +08:00
|
|
|
|
|
2025-09-14 03:36:26 +08:00
|
|
|
|
return f.rand
|
2025-09-05 22:40:36 +08:00
|
|
|
|
|
2025-09-04 23:57:22 +08:00
|
|
|
|
}
|
2025-09-07 00:23:28 +08:00
|
|
|
|
|
2025-09-14 01:35:16 +08:00
|
|
|
|
func (f *FightC) initplayer(c common.PlayerI, opp bool) {
|
2025-09-04 23:57:22 +08:00
|
|
|
|
|
2025-09-14 04:48:38 +08:00
|
|
|
|
temp := input.NewInput(f, c)
|
2025-09-14 01:35:16 +08:00
|
|
|
|
temp.AllPet = make([]*info.BattlePetEntity, 0)
|
2025-09-24 12:40:13 +08:00
|
|
|
|
temp.InitAttackValue()
|
2025-09-21 14:56:37 +00:00
|
|
|
|
for i := 0; i < len(c.GetInfo().PetList); i++ {
|
2025-09-14 01:35:16 +08:00
|
|
|
|
if f.Info.MAXPET == 0 || i < int(f.Info.MAXPET) {
|
|
|
|
|
|
|
2025-09-21 14:56:37 +00:00
|
|
|
|
temp.AllPet = append(temp.AllPet, info.CreateBattlePetEntity(&c.GetInfo().PetList[i], f.rand))
|
2025-09-08 01:23:12 +08:00
|
|
|
|
}
|
2025-09-04 23:57:22 +08:00
|
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
|
}
|
2025-09-14 01:35:16 +08:00
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
})
|
|
|
|
|
|
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)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-07 05:58:47 +08:00
|
|
|
|
}
|
2025-09-14 01:35:16 +08:00
|
|
|
|
|
|
|
|
|
|
for _, v := range temp.AllPet {
|
|
|
|
|
|
if v.Info.Hp == 0 {
|
|
|
|
|
|
v.NotAlive = true
|
|
|
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
|
}
|
2025-09-14 01:35:16 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
temp.CurrentPet = temp.AllPet[0]
|
2025-09-14 04:48:38 +08:00
|
|
|
|
|
2025-09-14 01:35:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建新战斗,邀请方和被邀请方,或者玩家和野怪方
|
|
|
|
|
|
func NewFight(i info.EnumBattleMode, p1 common.PlayerI, p2 common.PlayerI) *FightC {
|
|
|
|
|
|
f := &FightC{}
|
2025-09-21 14:56:37 +00:00
|
|
|
|
f.ownerID = p1.GetInfo().UserID
|
2025-09-20 00:17:29 +08:00
|
|
|
|
f.Info.FightId = i //房主
|
|
|
|
|
|
switch i {
|
|
|
|
|
|
case info.BattleMode.PVP_6V6:
|
|
|
|
|
|
f.Info.MAXPET = 6
|
|
|
|
|
|
case info.BattleMode.PVP_1V1:
|
|
|
|
|
|
f.Info.MAXPET = 1
|
|
|
|
|
|
}
|
2025-09-21 14:56:37 +00:00
|
|
|
|
seed := f.StartTime.UnixNano() ^ int64(p1.GetInfo().UserID) ^ int64(p2.GetInfo().UserID) // ^ int64(f.Round) // 用异或运算混合多维度信息
|
2025-09-14 01:35:16 +08:00
|
|
|
|
f.rand = rand.New(rand.NewSource(seed))
|
|
|
|
|
|
f.Info = info.NoteReadyToFightInfo{
|
|
|
|
|
|
|
|
|
|
|
|
FightId: i,
|
2025-09-06 00:31:08 +08:00
|
|
|
|
}
|
2025-09-14 01:35:16 +08:00
|
|
|
|
f.initplayer(p1, false)
|
|
|
|
|
|
|
|
|
|
|
|
f.initplayer(p2, true)
|
2025-09-06 00:31:08 +08:00
|
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
|
defer func() {
|
|
|
|
|
|
rr := Fightpool.Submit(f.battleLoop)
|
|
|
|
|
|
if rr != nil {
|
|
|
|
|
|
panic(rr)
|
|
|
|
|
|
}
|
2025-09-14 01:35:16 +08:00
|
|
|
|
f.Broadcast(func(ff *input.Input) {
|
2025-09-04 03:14:43 +08:00
|
|
|
|
|
2025-09-14 01:35:16 +08:00
|
|
|
|
ff.Player.SendNoteReadyToFightInfo(f.Info)
|
2025-09-08 01:23:12 +08:00
|
|
|
|
})
|
|
|
|
|
|
}()
|
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-14 01:35:16 +08:00
|
|
|
|
// 被击败的ID
|
|
|
|
|
|
func (b *FightC) IsWin(c *input.Input, cache uint32) bool {
|
|
|
|
|
|
|
|
|
|
|
|
var tt []*info.BattlePetEntity
|
|
|
|
|
|
bbb := b.Our.AllPet
|
|
|
|
|
|
|
2025-09-21 14:56:37 +00:00
|
|
|
|
if c.Player.GetInfo().UserID == b.ownerID { //如果是房主
|
2025-09-14 01:35:16 +08:00
|
|
|
|
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
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-05 22:40:36 +08:00
|
|
|
|
// 广播,并是否结束回合
|
2025-09-14 01:35:16 +08:00
|
|
|
|
func (f *FightC) Broadcast(t func(ff *input.Input)) {
|
2025-09-07 05:58:47 +08:00
|
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
|
t(f.Our)
|
|
|
|
|
|
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()
|
2025-09-14 01:35:16 +08:00
|
|
|
|
f.actionChan = make(chan BattleActionI, 2) // 初始化全局操作通道
|
2025-09-21 14:56:37 +00:00
|
|
|
|
fmt.Println("战斗开始精灵", f.Our.Player.GetInfo().PetList[0].CatchTime)
|
2025-09-08 01:23:12 +08:00
|
|
|
|
//战斗开始前操作
|
|
|
|
|
|
|
2025-09-04 23:57:22 +08:00
|
|
|
|
for {
|
2025-09-07 05:58:47 +08:00
|
|
|
|
|
2025-09-14 19:59:58 +08:00
|
|
|
|
if f.closefight { //回合数超过250,战斗平局结束f.Round > 250 ||
|
|
|
|
|
|
close(f.actionChan)
|
2025-09-10 00:41:09 +08:00
|
|
|
|
break
|
2025-09-05 22:40:36 +08:00
|
|
|
|
}
|
2025-09-14 19:59:58 +08:00
|
|
|
|
|
|
|
|
|
|
f.Round++ //回合数自增
|
2025-09-14 01:35:16 +08:00
|
|
|
|
actions := make(map[uint32]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-14 19:59:58 +08:00
|
|
|
|
case action, ok := <-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-14 19:59:58 +08:00
|
|
|
|
if !ok {
|
|
|
|
|
|
fmt.Println("战斗结束")
|
|
|
|
|
|
break
|
|
|
|
|
|
}
|
2025-09-08 01:23:12 +08:00
|
|
|
|
|
2025-09-21 14:56:37 +00:00
|
|
|
|
if action.GetPlayerID() != f.Our.Player.GetInfo().UserID && action.GetPlayerID() != f.Opp.Player.GetInfo().UserID {
|
2025-09-08 01:23:12 +08:00
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-14 01:35:16 +08:00
|
|
|
|
if a, isExpelled := action.(*ActiveSwitchAction); isExpelled {
|
2025-09-19 06:58:42 +00:00
|
|
|
|
|
2025-09-14 01:35:16 +08:00
|
|
|
|
f.Broadcast(func(ff *input.Input) {
|
2025-09-21 14:56:37 +00:00
|
|
|
|
if ff.Player.GetInfo().UserID == a.PlayerID { //先给自身广播
|
2025-09-19 06:58:42 +00:00
|
|
|
|
ff.Player.SendChangePet(a.Reason)
|
|
|
|
|
|
}
|
2025-09-08 01:23:12 +08:00
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
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 {
|
|
|
|
|
|
|
2025-09-23 20:53:47 +00:00
|
|
|
|
f.GetInputByAction(action, true).GetAction(f.Our)
|
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-24 12:40:13 +08:00
|
|
|
|
fmt.Println("玩家 执行动作", action.GetPlayerID(), action.Priority())
|
2025-09-04 23:57:22 +08:00
|
|
|
|
|
2025-09-04 03:14:43 +08:00
|
|
|
|
case <-timeout:
|
2025-09-08 01:23:12 +08:00
|
|
|
|
|
2025-09-21 14:56:37 +00:00
|
|
|
|
if _, exists := actions[f.Our.Player.GetInfo().UserID]; !exists {
|
2025-09-23 16:42:10 +00:00
|
|
|
|
f.Over(f.Opp.Player, info.BattleOverReason.PlayerOVerTime)
|
2025-09-04 03:14:43 +08:00
|
|
|
|
}
|
2025-09-21 14:56:37 +00:00
|
|
|
|
if _, exists := actions[f.Opp.Player.GetInfo().UserID]; !exists {
|
2025-09-14 03:36:26 +08:00
|
|
|
|
|
2025-09-23 16:42:10 +00:00
|
|
|
|
f.Over(f.Opp.Player, info.BattleOverReason.PlayerOVerTime)
|
2025-09-04 03:14:43 +08:00
|
|
|
|
}
|
2025-09-14 19:59:58 +08:00
|
|
|
|
|
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-21 14:56:37 +00:00
|
|
|
|
p1Action := actions[f.Our.Player.GetInfo().UserID]
|
|
|
|
|
|
p2Action := actions[f.Opp.Player.GetInfo().UserID]
|
2025-09-05 22:40:36 +08:00
|
|
|
|
fmt.Println("开始结算回合")
|
2025-09-24 12:40:13 +08:00
|
|
|
|
// 统一赋值,减少重复代码
|
2025-09-14 03:36:26 +08:00
|
|
|
|
|
2025-09-14 01:35:16 +08:00
|
|
|
|
var BattleActionI [2]BattleActionI
|
2025-09-16 23:58:03 +08:00
|
|
|
|
BattleActionI[0], BattleActionI[1] = f.Compare(p1Action, p2Action)
|
2025-09-05 22:40:36 +08:00
|
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
|
switch faction := BattleActionI[0].(type) {
|
2025-09-23 16:42:10 +00:00
|
|
|
|
case *PlayerOfflineAction: //单方掉线
|
2025-09-05 22:40:36 +08:00
|
|
|
|
|
2025-09-14 01:35:16 +08:00
|
|
|
|
f.Broadcast(func(ff *input.Input) {
|
2025-09-08 01:23:12 +08:00
|
|
|
|
ff.Player.SendFightEndInfo(faction.Reason) //广播逃跑原因
|
|
|
|
|
|
})
|
2025-09-14 19:59:58 +08:00
|
|
|
|
f.closefight = true
|
2025-09-23 16:42:10 +00:00
|
|
|
|
case *EscapeAction: //优先逃跑
|
2025-09-06 00:31:08 +08:00
|
|
|
|
|
2025-09-14 01:35:16 +08:00
|
|
|
|
f.Broadcast(func(ff *input.Input) {
|
2025-09-08 01:23:12 +08:00
|
|
|
|
ff.Player.SendFightEndInfo(faction.Reason) //广播逃跑原因
|
|
|
|
|
|
})
|
2025-09-14 19:59:58 +08:00
|
|
|
|
f.closefight = true
|
|
|
|
|
|
|
2025-09-14 03:36:26 +08:00
|
|
|
|
case *ActiveSwitchAction: //切换上场的,切换方放弃出手
|
|
|
|
|
|
f.enterturn(BattleActionI[1], &SystemGiveUpAction{BaseAction: NewBaseAction(BattleActionI[0].GetPlayerID())}) //切换,相当于后手直接出手
|
2025-09-08 01:23:12 +08:00
|
|
|
|
|
2025-09-14 01:35:16 +08:00
|
|
|
|
case *UseItemAction: //使用道具
|
2025-09-14 03:36:26 +08:00
|
|
|
|
//fmt.Println(faction.ItemID)
|
2025-09-11 02:44:21 +08:00
|
|
|
|
|
|
|
|
|
|
switch {
|
|
|
|
|
|
case faction.ItemID >= 30001 && faction.ItemID <= 300010: //胶囊
|
|
|
|
|
|
|
2025-09-23 13:24:40 +08:00
|
|
|
|
//todo 将血量和技能pp传回enterturn
|
|
|
|
|
|
tt, ok := f.Our.Player.(*player.Player)
|
|
|
|
|
|
mo, ism := f.Opp.Player.(*player.AI_player)
|
|
|
|
|
|
|
|
|
|
|
|
if ok && ism && mo.CanCapture { //如果获取玩家
|
|
|
|
|
|
|
|
|
|
|
|
ok, _ := f.Our.Capture(f.Opp.CurrentPet, faction.ItemID, -1)
|
|
|
|
|
|
if ok { //todo 待补充
|
|
|
|
|
|
tt.Service.PetAdd(*f.Opp.CurrentPet.Info)
|
|
|
|
|
|
tt.CatchPetInfo(info.CatchMonsterOutboundInfo{
|
|
|
|
|
|
CatchTime: uint32(f.Opp.CurrentPet.Info.CatchTime),
|
|
|
|
|
|
PetId: uint32(f.Opp.CurrentPet.ID),
|
|
|
|
|
|
})
|
|
|
|
|
|
tt.SendFightEndInfo(info.FightOverInfo{
|
|
|
|
|
|
|
|
|
|
|
|
WinnerId: f.ownerID,
|
|
|
|
|
|
})
|
|
|
|
|
|
f.closefight = true
|
|
|
|
|
|
} else {
|
2025-09-21 17:01:31 +00:00
|
|
|
|
tt.CatchPetInfo(info.CatchMonsterOutboundInfo{})
|
2025-09-11 02:44:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-23 13:24:40 +08:00
|
|
|
|
} else { //说明不是可以捕捉的
|
|
|
|
|
|
tt.CatchPetInfo(info.CatchMonsterOutboundInfo{})
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-11 02:44:21 +08:00
|
|
|
|
// 当 ItemID 在 30001-300010 之间时执行的逻辑
|
|
|
|
|
|
fmt.Println("ItemID 在范围内")
|
|
|
|
|
|
case faction.ItemID == 300001:
|
|
|
|
|
|
// 原来的单个值判断(如果还需要保留)
|
|
|
|
|
|
fmt.Println("ItemID 是 300001")
|
|
|
|
|
|
default:
|
|
|
|
|
|
// 其他情况
|
|
|
|
|
|
fmt.Println("ItemID 不在指定范围内")
|
|
|
|
|
|
}
|
2025-09-14 03:36:26 +08:00
|
|
|
|
f.enterturn(BattleActionI[1], &SystemGiveUpAction{BaseAction: NewBaseAction(BattleActionI[0].GetPlayerID())}) //切换,相当于后手直接出手
|
2025-09-19 07:34:19 +00:00
|
|
|
|
default: //选择技能或者放弃出手
|
2025-09-08 01:23:12 +08:00
|
|
|
|
//回合前操作,比如挂载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
|
|
|
|
// 解析并 施加effect
|
2025-09-14 03:36:26 +08:00
|
|
|
|
func (f *FightC) parseskill(attacker, defender *input.Input, id *SelectSkillAction) {
|
2025-09-08 01:23:12 +08:00
|
|
|
|
temparg := id.Skill.SideEffectArgS
|
|
|
|
|
|
for _, v := range id.Skill.SideEffectS {
|
|
|
|
|
|
|
2025-09-24 16:36:32 +00:00
|
|
|
|
t := input.Geteffect(input.EffectType.Skill, v)
|
2025-09-08 01:23:12 +08:00
|
|
|
|
|
2025-09-24 19:46:42 +08:00
|
|
|
|
args := xmlres.EffectArgs[v]
|
2025-09-05 22:40:36 +08:00
|
|
|
|
|
2025-09-24 19:46:42 +08:00
|
|
|
|
if t.Effect.GetOwner() { //如果取反,说明是给对方添加的回合效果
|
|
|
|
|
|
//实际上,owner永远为反,说明是对方给我添加的
|
2025-09-24 16:36:32 +00:00
|
|
|
|
t.Effect.SetArgs(attacker, temparg[:args]...) //设置入参,施加方永远是我方
|
2025-09-08 01:23:12 +08:00
|
|
|
|
|
2025-09-24 19:46:42 +08:00
|
|
|
|
defender.AddEffect(t)
|
|
|
|
|
|
} else {
|
2025-09-24 16:36:32 +00:00
|
|
|
|
t.Effect.SetArgs(attacker, temparg[:args]...) //设置入参
|
2025-09-24 19:46:42 +08:00
|
|
|
|
attacker.AddEffect(t)
|
2025-09-08 01:23:12 +08:00
|
|
|
|
}
|
2025-09-24 16:36:32 +00:00
|
|
|
|
temparg = temparg[args:]
|
2025-09-08 01:23:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-21 17:18:22 +00:00
|
|
|
|
func (f *FightC) initAttackers(fattack BattleActionI) {
|
2025-09-08 01:23:12 +08:00
|
|
|
|
// 伤害值
|
|
|
|
|
|
|
|
|
|
|
|
// 根据攻击方归属设置当前战斗的主/次攻击方属性
|
2025-09-14 01:35:16 +08:00
|
|
|
|
|
|
|
|
|
|
if fattack.GetPlayerID() == f.ownerID {
|
|
|
|
|
|
f.First, f.Second = f.Our, f.Opp // 攻击方为我方时,主攻击方是我方
|
2025-09-10 01:35:08 +08:00
|
|
|
|
|
2025-09-08 01:23:12 +08:00
|
|
|
|
} else {
|
2025-09-14 01:35:16 +08:00
|
|
|
|
f.First, f.Second = f.Opp, f.Our // 攻击方为对方时,主攻击方是对方
|
2025-09-10 01:35:08 +08:00
|
|
|
|
|
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
|
|
|
|
// 处理技能攻击逻辑
|
2025-09-15 00:40:19 +08:00
|
|
|
|
func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *SelectSkillAction) {
|
2025-09-08 02:51:21 +00:00
|
|
|
|
|
|
|
|
|
|
// 记录技能信息
|
2025-09-15 00:40:19 +08:00
|
|
|
|
attacker.AttackValue.SkillID = uint32(a.Skill.ID) //获取技能ID
|
2025-09-08 01:23:12 +08:00
|
|
|
|
|
2025-09-15 00:40:19 +08:00
|
|
|
|
attacker.Exec(func(t input.Effect) bool { //计算命中
|
2025-09-10 02:16:47 +00:00
|
|
|
|
|
2025-09-15 00:40:19 +08:00
|
|
|
|
t.IsHit(defender, a.Skill) //相当于先调整基础命中
|
2025-09-14 16:56:31 +08:00
|
|
|
|
|
2025-09-14 03:36:26 +08:00
|
|
|
|
return attacker.AttackTime == 0 //等于0,继续处理
|
2025-09-12 00:27:49 +08:00
|
|
|
|
})
|
2025-09-15 00:40:19 +08:00
|
|
|
|
defender.Exec(func(t input.Effect) bool { //计算闪避
|
|
|
|
|
|
t.TakeHit(attacker, a.Skill)
|
2025-09-14 03:36:26 +08:00
|
|
|
|
|
|
|
|
|
|
return attacker.AttackTime > 0 //
|
|
|
|
|
|
})
|
2025-09-15 00:40:19 +08:00
|
|
|
|
attacker.AttackValue.AttackTime = a.Skill.AttackTime
|
2025-09-14 03:36:26 +08:00
|
|
|
|
if attacker.AttackValue.AttackTime > 0 { //如果命中
|
2025-09-15 00:40:19 +08:00
|
|
|
|
f.parseskill(attacker, defender, a) //命中后解析effect
|
2025-09-23 17:34:58 +00:00
|
|
|
|
|
2025-09-23 22:30:01 +00:00
|
|
|
|
attacker.Exec(func(t input.Effect) bool {
|
2025-09-24 12:40:13 +08:00
|
|
|
|
|
2025-09-23 18:35:23 +00:00
|
|
|
|
t.OnSkill(defender, a.Skill) //调用伤害计算
|
|
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
|
})
|
2025-09-08 01:23:12 +08:00
|
|
|
|
|
2025-09-24 12:40:13 +08:00
|
|
|
|
attacker.Exec(func(t input.Effect) bool {
|
|
|
|
|
|
|
|
|
|
|
|
t.SkillUseEnd(defender)
|
|
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
|
})
|
2025-09-12 00:27:49 +08:00
|
|
|
|
// 扣减防御方血量
|
|
|
|
|
|
} //todo 处理未命中效果
|
2025-09-08 01:23:12 +08:00
|
|
|
|
|
2025-09-08 02:51:21 +00:00
|
|
|
|
}
|
2025-09-10 22:59:10 +08:00
|
|
|
|
|
2025-09-14 04:48:38 +08:00
|
|
|
|
//回合有先手方和后手方,同时有攻击方和被攻击方
|
|
|
|
|
|
|
2025-09-14 01:35:16 +08:00
|
|
|
|
func (f *FightC) enterturn(fattack, sattack BattleActionI) {
|
2025-09-14 03:36:26 +08:00
|
|
|
|
|
2025-09-23 13:24:40 +08:00
|
|
|
|
if f.closefight { //战斗结束
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2025-09-21 17:18:51 +00:00
|
|
|
|
f.initAttackers(fattack) //初始化先后手
|
2025-09-14 01:35:16 +08:00
|
|
|
|
var attacker, defender *input.Input
|
2025-09-14 03:36:26 +08:00
|
|
|
|
|
|
|
|
|
|
//开始回合操作
|
2025-09-10 01:35:08 +08:00
|
|
|
|
for i := 0; i < 2; i++ {
|
2025-09-14 03:36:26 +08:00
|
|
|
|
|
2025-09-14 04:48:38 +08:00
|
|
|
|
var attackeraction BattleActionI
|
2025-09-10 01:35:08 +08:00
|
|
|
|
if i == 0 { //
|
|
|
|
|
|
attacker, defender = f.First, f.Second
|
2025-09-14 01:35:16 +08:00
|
|
|
|
attackeraction = fattack
|
2025-09-14 04:48:38 +08:00
|
|
|
|
attacker.First = true //先手技能
|
2025-09-10 01:35:08 +08:00
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
attacker, defender = f.Second, f.First
|
2025-09-14 01:35:16 +08:00
|
|
|
|
attackeraction = sattack
|
2025-09-14 04:48:38 +08:00
|
|
|
|
attacker.First = false //先手技能
|
2025-09-08 01:23:12 +08:00
|
|
|
|
|
2025-09-10 01:35:08 +08:00
|
|
|
|
}
|
2025-09-14 04:48:38 +08:00
|
|
|
|
skill, ok := attackeraction.(*SelectSkillAction)
|
|
|
|
|
|
|
|
|
|
|
|
if !ok || attacker.CurrentPet.Info.Hp <= 0 { //还有系统选择放弃出手的
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2025-09-23 20:53:47 +00:00
|
|
|
|
attacker.Exec(func(t input.Effect) bool { //回合开始前
|
2025-09-14 04:48:38 +08:00
|
|
|
|
|
|
|
|
|
|
//结算状态
|
2025-09-15 00:40:19 +08:00
|
|
|
|
t.OnTurnStart(defender)
|
2025-09-14 04:48:38 +08:00
|
|
|
|
return true
|
|
|
|
|
|
})
|
2025-09-15 00:40:19 +08:00
|
|
|
|
canuseskill := attacker.Exec(func(t input.Effect) bool { //这个是能否使用技能
|
2025-09-14 03:36:26 +08:00
|
|
|
|
//结算状态
|
2025-09-15 00:40:19 +08:00
|
|
|
|
return t.UseSkill(defender) //返回本身结算,如果false,说明不能使用技能了
|
2025-09-08 01:23:12 +08:00
|
|
|
|
|
2025-09-14 03:36:26 +08:00
|
|
|
|
})
|
2025-09-07 05:58:47 +08:00
|
|
|
|
|
2025-09-14 03:36:26 +08:00
|
|
|
|
if canuseskill { //可以使用技能
|
2025-09-15 00:40:19 +08:00
|
|
|
|
|
2025-09-14 03:36:26 +08:00
|
|
|
|
f.processSkillAttack(attacker, defender, skill)
|
2025-09-10 02:11:16 +00:00
|
|
|
|
|
2025-09-14 03:36:26 +08:00
|
|
|
|
skill.Skill.Info.PP-- //减少PP
|
2025-09-10 02:16:47 +00:00
|
|
|
|
}
|
2025-09-10 01:35:08 +08:00
|
|
|
|
fmt.Println(i,
|
2025-09-24 16:36:32 +00:00
|
|
|
|
"玩家技能伤害:", attacker.GetEffect(input.EffectType.Damage, 0).Stack(),
|
2025-09-10 01:35:08 +08:00
|
|
|
|
"自身剩余血量:", attacker.CurrentPet.Info.Hp,
|
|
|
|
|
|
"对手剩余血量:", defender.CurrentPet.Info.Hp,
|
|
|
|
|
|
)
|
|
|
|
|
|
if defender.CurrentPet.Info.Hp == 0 {
|
2025-09-14 01:35:16 +08:00
|
|
|
|
defender.CanChange = true //被打死就可以切精灵了
|
|
|
|
|
|
if f.IsWin(attacker, defender.CurrentPet.Info.CatchTime) { //然后检查是否战斗结束
|
2025-09-10 01:35:08 +08:00
|
|
|
|
var WinnerId uint32
|
|
|
|
|
|
if i == 0 {
|
2025-09-21 14:56:37 +00:00
|
|
|
|
WinnerId = f.First.Player.GetInfo().UserID
|
2025-09-10 01:35:08 +08:00
|
|
|
|
} else {
|
2025-09-21 14:56:37 +00:00
|
|
|
|
WinnerId = f.Second.Player.GetInfo().UserID
|
2025-09-10 01:35:08 +08:00
|
|
|
|
}
|
2025-09-14 01:35:16 +08:00
|
|
|
|
defer f.Broadcast(func(ff *input.Input) {
|
2025-09-10 22:59:10 +08:00
|
|
|
|
//todo 将血量和技能pp传回enterturn
|
|
|
|
|
|
|
2025-09-10 00:41:09 +08:00
|
|
|
|
ff.Player.SendFightEndInfo(info.FightOverInfo{
|
2025-09-10 01:35:08 +08:00
|
|
|
|
WinnerId: WinnerId,
|
2025-09-10 00:41:09 +08:00
|
|
|
|
})
|
|
|
|
|
|
})
|
2025-09-14 19:59:58 +08:00
|
|
|
|
defer func() {
|
|
|
|
|
|
f.closefight = true
|
|
|
|
|
|
}()
|
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-04 03:14:43 +08:00
|
|
|
|
}
|
2025-09-23 19:11:03 +00:00
|
|
|
|
|
2025-09-24 16:36:32 +00:00
|
|
|
|
f.First.Exec(func(t input.Effect) bool { //这个是能否使用技能
|
2025-09-23 19:11:03 +00:00
|
|
|
|
//结算状态
|
2025-09-24 16:36:32 +00:00
|
|
|
|
t.TurnEnd(f.Second) //返回本身结算,如果false,说明不能使用技能了
|
2025-09-23 19:11:03 +00:00
|
|
|
|
return true
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2025-09-24 16:36:32 +00:00
|
|
|
|
f.Second.Exec(func(t input.Effect) bool { //这个是能否使用技能
|
2025-09-23 22:20:52 +00:00
|
|
|
|
//结算状态
|
2025-09-24 16:36:32 +00:00
|
|
|
|
t.TurnEnd(f.First) //返回本身结算,如果false,说明不能使用技能了
|
2025-09-23 22:20:52 +00:00
|
|
|
|
return true
|
|
|
|
|
|
})
|
2025-09-14 19:59:58 +08:00
|
|
|
|
ret := info.AttackValueS{
|
|
|
|
|
|
FAttack: *f.First.AttackValue,
|
|
|
|
|
|
SAttack: *f.Second.AttackValue,
|
|
|
|
|
|
}
|
2025-09-17 00:50:37 +08:00
|
|
|
|
|
|
|
|
|
|
for i := 0; i < 20; i++ { //堆叠状态剩余回合
|
2025-09-19 00:29:55 +08:00
|
|
|
|
|
2025-09-24 16:36:32 +00:00
|
|
|
|
ret.FAttack.Status[i] = int8(f.First.GetEffect(input.EffectType.Status, i).Duration())
|
|
|
|
|
|
|
|
|
|
|
|
ret.SAttack.Status[i] = int8(f.Second.GetEffect(input.EffectType.Status, i).Duration())
|
2025-09-19 00:29:55 +08:00
|
|
|
|
|
2025-09-17 00:50:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-14 01:35:16 +08:00
|
|
|
|
f.Broadcast(func(ff *input.Input) {
|
2025-09-19 06:58:42 +00:00
|
|
|
|
for _, v := range f.Switch {
|
2025-09-21 14:56:37 +00:00
|
|
|
|
if ff.Player.GetInfo().UserID != v.PlayerID {
|
2025-09-19 06:58:42 +00:00
|
|
|
|
ff.Player.SendChangePet(v.Reason)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2025-09-19 06:59:30 +00:00
|
|
|
|
f.Switch = []*ActiveSwitchAction{}
|
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
|
|
|
|
}
|