2025-11-01 18:36:21 +08:00
|
|
|
|
package fight
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2025-11-08 16:38:41 +08:00
|
|
|
|
"blazing/common/data/xmlres"
|
2026-01-26 14:12:12 +00:00
|
|
|
|
"blazing/common/socket/errorcode"
|
2025-12-18 10:57:59 +00:00
|
|
|
|
"blazing/common/utils"
|
2025-11-15 23:02:46 +00:00
|
|
|
|
"blazing/cool"
|
2026-03-04 22:47:21 +08:00
|
|
|
|
"blazing/modules/player/model"
|
2025-11-15 23:02:46 +00:00
|
|
|
|
"context"
|
2026-04-08 01:28:55 +08:00
|
|
|
|
"runtime/debug"
|
2026-04-04 05:44:02 +08:00
|
|
|
|
"sort"
|
2026-02-16 02:30:26 +08:00
|
|
|
|
"sync/atomic"
|
2025-11-15 22:17:43 +00:00
|
|
|
|
|
2025-11-01 18:36:21 +08:00
|
|
|
|
"blazing/logic/service/common"
|
|
|
|
|
|
"blazing/logic/service/fight/action"
|
|
|
|
|
|
"blazing/logic/service/fight/info"
|
|
|
|
|
|
"blazing/logic/service/fight/input"
|
|
|
|
|
|
"blazing/logic/service/player"
|
2025-11-11 05:54:24 +00:00
|
|
|
|
|
2025-11-01 18:36:21 +08:00
|
|
|
|
"fmt"
|
|
|
|
|
|
"time"
|
2025-11-08 16:38:41 +08:00
|
|
|
|
|
2025-12-05 00:24:02 +08:00
|
|
|
|
"github.com/alpacahq/alpacadecimal"
|
2025-11-08 16:38:41 +08:00
|
|
|
|
"github.com/gogf/gf/v2/util/gconv"
|
2026-02-14 08:01:34 +08:00
|
|
|
|
"github.com/jinzhu/copier"
|
2025-11-01 18:36:21 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
2026-04-06 02:06:11 +08:00
|
|
|
|
func consumeLimitedPetEffects(pet *model.PetInfo) {
|
|
|
|
|
|
if pet == nil || len(pet.EffectInfo) == 0 {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
next := pet.EffectInfo[:0]
|
|
|
|
|
|
for _, eff := range pet.EffectInfo {
|
|
|
|
|
|
if eff.Status == 2 {
|
|
|
|
|
|
if eff.LeftCount > 0 {
|
|
|
|
|
|
eff.LeftCount--
|
|
|
|
|
|
}
|
|
|
|
|
|
if eff.LeftCount == 0 {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
next = append(next, eff)
|
|
|
|
|
|
}
|
|
|
|
|
|
pet.EffectInfo = next
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-01 18:36:21 +08:00
|
|
|
|
func (f *FightC) battleLoop() {
|
2026-01-26 14:12:12 +00:00
|
|
|
|
defer func() {
|
|
|
|
|
|
if err := recover(); err != nil { // 恢复 panic,err 为 panic 错误值
|
|
|
|
|
|
// 1. 打印错误信息
|
2026-02-02 01:01:01 +08:00
|
|
|
|
var ctx = context.Background()
|
2026-02-02 18:32:41 +08:00
|
|
|
|
cool.Logger.Error(ctx, f.ownerID, err)
|
2026-01-26 14:12:12 +00:00
|
|
|
|
f.Broadcast(func(ff *input.Input) {
|
|
|
|
|
|
if p, ok := ff.Player.(*player.Player); ok {
|
|
|
|
|
|
head := common.NewTomeeHeader(1001, p.Info.UserID)
|
|
|
|
|
|
|
|
|
|
|
|
head.Result = uint32(errorcode.ErrorCodes.ErrSystemBusyTryLater)
|
|
|
|
|
|
|
|
|
|
|
|
p.SendPack(head.Pack(nil))
|
2026-02-12 00:49:18 +08:00
|
|
|
|
|
|
|
|
|
|
p.Service.Info.Save(*p.Info)
|
2026-01-26 14:12:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}()
|
2026-04-04 04:28:04 +08:00
|
|
|
|
//fmt.Println("战斗开始精灵", f.Our[0].Player.GetInfo().PetList[0].CatchTime)
|
2025-11-01 18:36:21 +08:00
|
|
|
|
|
2025-12-16 02:50:10 +08:00
|
|
|
|
//fmt.Println("开始收集玩家动作", waitr)
|
2025-11-12 01:19:24 +08:00
|
|
|
|
for !f.closefight {
|
2025-11-01 18:36:21 +08:00
|
|
|
|
|
|
|
|
|
|
f.Round++
|
|
|
|
|
|
|
2026-04-08 01:28:55 +08:00
|
|
|
|
if !f.sideHasActionableSlots(SideOur) {
|
|
|
|
|
|
if player := f.primaryOppPlayer(); player != nil {
|
|
|
|
|
|
f.WinnerId = player.GetInfo().UserID
|
|
|
|
|
|
}
|
2026-04-14 00:38:50 +08:00
|
|
|
|
f.Reason = normalizeFightOverReason(model.BattleOverReason.DefaultEnd)
|
2026-04-08 01:28:55 +08:00
|
|
|
|
f.FightOverInfo.WinnerId = f.WinnerId
|
|
|
|
|
|
f.FightOverInfo.Reason = f.Reason
|
|
|
|
|
|
f.closefight = true
|
|
|
|
|
|
break
|
|
|
|
|
|
}
|
|
|
|
|
|
if !f.sideHasActionableSlots(SideOpp) {
|
|
|
|
|
|
if player := f.primaryOurPlayer(); player != nil {
|
|
|
|
|
|
f.WinnerId = player.GetInfo().UserID
|
|
|
|
|
|
}
|
2026-04-14 00:38:50 +08:00
|
|
|
|
f.Reason = normalizeFightOverReason(model.BattleOverReason.DefaultEnd)
|
2026-04-08 01:28:55 +08:00
|
|
|
|
f.FightOverInfo.WinnerId = f.WinnerId
|
|
|
|
|
|
f.FightOverInfo.Reason = f.Reason
|
|
|
|
|
|
f.closefight = true
|
|
|
|
|
|
break
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-04 05:44:02 +08:00
|
|
|
|
expectedSlots := f.expectedActionSlots()
|
|
|
|
|
|
actions := f.collectPlayerActions(expectedSlots)
|
2025-11-11 01:10:26 +08:00
|
|
|
|
if f.closefight {
|
|
|
|
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
}
|
2026-01-20 02:25:02 +08:00
|
|
|
|
|
2026-04-04 05:44:02 +08:00
|
|
|
|
f.resolveRound(actions)
|
2025-11-11 11:45:09 +00:00
|
|
|
|
|
2025-11-01 18:36:21 +08:00
|
|
|
|
}
|
2025-11-11 01:10:26 +08:00
|
|
|
|
f.Broadcast(func(ff *input.Input) {
|
|
|
|
|
|
|
2025-11-15 00:15:09 +08:00
|
|
|
|
//todo 将血量和技能pp传回enterturn
|
|
|
|
|
|
ff.Exec(func(tt input.Effect) bool {
|
|
|
|
|
|
tt.OnBattleEnd()
|
|
|
|
|
|
tt.Alive(false) //将所有属性变化失效掉
|
|
|
|
|
|
return true
|
|
|
|
|
|
})
|
2026-04-06 02:06:11 +08:00
|
|
|
|
for i := 0; i < len(ff.AllPet); i++ {
|
|
|
|
|
|
consumeLimitedPetEffects(&ff.AllPet[i].Info)
|
|
|
|
|
|
for j := 0; j < len(ff.Player.GetInfo().PetList); j++ {
|
|
|
|
|
|
if ff.Player.GetInfo().PetList[j].CatchTime != ff.AllPet[i].Info.CatchTime {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
2025-11-22 22:57:32 +08:00
|
|
|
|
|
2026-04-06 02:06:11 +08:00
|
|
|
|
ff.Player.GetInfo().PetList[j].EffectInfo = ff.AllPet[i].Info.EffectInfo
|
|
|
|
|
|
if f.Info.Mode == info.BattleMode.PET_MELEE {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
2025-12-18 23:57:17 +08:00
|
|
|
|
|
2026-04-06 02:06:11 +08:00
|
|
|
|
if ff.UserID == f.WinnerId {
|
|
|
|
|
|
currentPet := ff.CurrentPet()
|
|
|
|
|
|
if currentPet != nil && currentPet.Info.CatchTime == ff.Player.GetInfo().PetList[j].CatchTime {
|
|
|
|
|
|
f.Winpet = &ff.Player.GetInfo().PetList[j]
|
2025-11-15 23:02:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-06 02:06:11 +08:00
|
|
|
|
ff.Player.GetInfo().PetList[j].Hp = utils.Min(ff.Player.GetInfo().PetList[j].MaxHp, ff.AllPet[i].Info.Hp)
|
|
|
|
|
|
ff.Player.GetInfo().PetList[j].SkillList = ff.AllPet[i].Info.SkillList
|
|
|
|
|
|
}
|
2025-11-15 23:02:46 +00:00
|
|
|
|
}
|
2025-11-20 21:37:37 +08:00
|
|
|
|
|
2025-11-23 00:06:14 +08:00
|
|
|
|
})
|
2026-01-03 02:18:31 +08:00
|
|
|
|
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC {
|
2026-03-07 00:26:05 +08:00
|
|
|
|
|
2026-04-04 04:28:04 +08:00
|
|
|
|
addpet := f.Opp[0].Player.GetInfo().PetList[0]
|
2026-03-04 22:47:21 +08:00
|
|
|
|
if f.Reason == model.BattleOverReason.Cacthok {
|
2026-01-03 02:18:31 +08:00
|
|
|
|
f.WinnerId = f.ownerID
|
2026-02-22 21:46:36 +08:00
|
|
|
|
|
|
|
|
|
|
addpet.EffectInfo = nil //清空特性信息
|
2026-04-04 04:28:04 +08:00
|
|
|
|
f.Our[0].Player.(*player.Player).Service.Pet.PetAdd(&addpet, 0)
|
2026-01-03 02:18:31 +08:00
|
|
|
|
|
2026-04-04 22:13:42 +08:00
|
|
|
|
oppPet := f.Opp[0].CurrentPet()
|
|
|
|
|
|
petID := uint32(0)
|
|
|
|
|
|
if oppPet != nil {
|
|
|
|
|
|
petID = uint32(oppPet.ID)
|
|
|
|
|
|
}
|
2026-04-04 04:28:04 +08:00
|
|
|
|
f.Our[0].Player.SendPackCmd(2409, &info.CatchMonsterOutboundInfo{
|
2026-02-22 21:46:36 +08:00
|
|
|
|
CatchTime: uint32(addpet.CatchTime),
|
2026-04-04 22:13:42 +08:00
|
|
|
|
PetId: petID,
|
2026-01-03 02:18:31 +08:00
|
|
|
|
})
|
2026-01-31 19:10:36 +08:00
|
|
|
|
|
2026-04-04 04:28:04 +08:00
|
|
|
|
defer f.Our[0].Player.(*player.Player).Service.Done.UpdatePet(addpet, 0, 1)
|
2026-01-03 02:18:31 +08:00
|
|
|
|
//f.Reason = 0 //清空
|
|
|
|
|
|
}
|
|
|
|
|
|
if f.Reason == 0 {
|
2026-01-31 19:10:36 +08:00
|
|
|
|
|
2026-04-04 04:28:04 +08:00
|
|
|
|
defer f.Our[0].Player.(*player.Player).Service.Done.UpdatePet(addpet, 1, 0)
|
2025-12-03 22:05:28 +08:00
|
|
|
|
|
2026-01-03 02:18:31 +08:00
|
|
|
|
}
|
2026-04-04 04:28:04 +08:00
|
|
|
|
// f.Our[0].Player.(*player.Player).MapNPC.Reset(7 * time.Second)
|
2026-02-13 03:04:04 +08:00
|
|
|
|
|
2026-04-04 04:28:04 +08:00
|
|
|
|
copier.Copy(&f.FightOverInfo, f.Our[0].Player.(*player.Player).Info)
|
|
|
|
|
|
atomic.StoreUint32(&f.Our[0].Player.(*player.Player).Canmon, 2)
|
|
|
|
|
|
f.Our[0].Player.(*player.Player).MapNPC.Reset(10 * time.Second)
|
|
|
|
|
|
// f.Our[0].Player.(*player.Player).Info.FightTime = f.Our[0].Player.(*player.Player).Info.FightTime + time.Now().Unix() - f.StartTime.Unix()
|
2025-12-03 22:05:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-01 01:45:19 +08:00
|
|
|
|
//大乱斗,给个延迟
|
|
|
|
|
|
//<-time.After(1000)
|
2026-04-09 02:14:09 +08:00
|
|
|
|
f.BroadcastPlayers(func(p common.PlayerI) {
|
|
|
|
|
|
if f.LegacyGroupProtocol {
|
|
|
|
|
|
f.sendLegacyGroupOver(p, &f.FightOverInfo)
|
|
|
|
|
|
} else {
|
2026-04-12 13:27:39 +08:00
|
|
|
|
f.sendFightPacket(p, fightPacketOver, buildFightOverPayload(f.FightOverInfo))
|
2026-04-09 02:14:09 +08:00
|
|
|
|
}
|
2025-11-19 16:11:02 +08:00
|
|
|
|
|
2026-04-09 02:14:09 +08:00
|
|
|
|
p.QuitFight()
|
2025-11-18 22:16:55 +00:00
|
|
|
|
|
2025-11-18 20:52:04 +00:00
|
|
|
|
//待退出玩家战斗状态
|
2025-11-11 01:10:26 +08:00
|
|
|
|
})
|
2025-11-15 00:15:09 +08:00
|
|
|
|
|
2026-01-03 02:18:31 +08:00
|
|
|
|
//f.Reason = info.BattleOverReason.PlayerCaptureSuccess
|
|
|
|
|
|
//f.WinnerId = 0 //捕捉成功不算胜利
|
|
|
|
|
|
if f.callback != nil {
|
|
|
|
|
|
|
|
|
|
|
|
f.callback(f.FightOverInfo) //先执行回调,再执行返回信息,在回调内修改战斗判断
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2026-01-20 02:25:02 +08:00
|
|
|
|
|
2025-11-12 01:19:24 +08:00
|
|
|
|
close(f.over)
|
2025-11-12 21:44:56 +08:00
|
|
|
|
|
2025-11-01 18:36:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 收集玩家动作(含超时判定)
|
2026-04-04 05:44:02 +08:00
|
|
|
|
func (f *FightC) collectPlayerActions(expectedSlots map[actionSlotKey]struct{}) []action.BattleActionI {
|
|
|
|
|
|
actions := make(map[actionSlotKey]action.BattleActionI, len(expectedSlots))
|
2026-04-02 23:05:18 +08:00
|
|
|
|
f.openActionWindow()
|
|
|
|
|
|
defer f.closeActionWindow()
|
|
|
|
|
|
|
|
|
|
|
|
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC {
|
2026-04-08 01:28:55 +08:00
|
|
|
|
f.triggerNPCActions()
|
2026-04-02 23:05:18 +08:00
|
|
|
|
}
|
2025-11-01 18:36:21 +08:00
|
|
|
|
|
2026-02-05 23:44:07 +08:00
|
|
|
|
waitr := time.Duration(f.waittime)*time.Millisecond*10 + 30*time.Second
|
2025-12-16 02:50:10 +08:00
|
|
|
|
|
2026-04-05 21:59:22 +08:00
|
|
|
|
timeout := time.NewTimer(waitr)
|
|
|
|
|
|
defer timeout.Stop()
|
2026-04-04 05:44:02 +08:00
|
|
|
|
for len(actions) < len(expectedSlots) {
|
2025-11-13 05:05:05 +08:00
|
|
|
|
|
2025-11-01 18:36:21 +08:00
|
|
|
|
select {
|
2025-11-11 11:45:09 +00:00
|
|
|
|
case <-f.quit:
|
|
|
|
|
|
f.closefight = true
|
2026-04-04 05:44:02 +08:00
|
|
|
|
return flattenActionMap(actions)
|
2025-11-11 11:45:09 +00:00
|
|
|
|
|
2026-04-02 23:05:18 +08:00
|
|
|
|
case <-f.actionNotify:
|
|
|
|
|
|
paction := f.nextAction()
|
2025-11-01 18:36:21 +08:00
|
|
|
|
if paction == nil {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-04 05:44:02 +08:00
|
|
|
|
key := actionSlotKeyFromAction(paction)
|
|
|
|
|
|
if _, ok := expectedSlots[key]; !ok {
|
2025-11-01 18:36:21 +08:00
|
|
|
|
continue
|
|
|
|
|
|
}
|
2026-01-07 02:30:21 +08:00
|
|
|
|
|
2025-12-10 16:42:23 +00:00
|
|
|
|
selfinput := f.GetInputByAction(paction, false)
|
2026-04-04 05:44:02 +08:00
|
|
|
|
if selfinput == nil {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
2025-12-10 16:03:45 +00:00
|
|
|
|
if ret, ok := paction.(*action.ActiveSwitchAction); ok {
|
2026-02-07 01:36:43 +08:00
|
|
|
|
|
2025-12-11 13:31:20 +08:00
|
|
|
|
//正常结束可以切换,以及死切后还能再切一次
|
2025-12-10 16:42:23 +00:00
|
|
|
|
if selfinput.CanChange == 0 {
|
2026-04-04 05:44:02 +08:00
|
|
|
|
currentPet := selfinput.PrimaryCurPet()
|
|
|
|
|
|
if currentPet != nil && currentPet.Info.Hp > 0 { //非死亡切换
|
2025-12-10 16:42:23 +00:00
|
|
|
|
selfinput.CanChange = 1
|
2025-12-25 20:49:54 +08:00
|
|
|
|
f.Broadcast(func(ff *input.Input) {
|
|
|
|
|
|
|
|
|
|
|
|
ff.Exec(func(t input.Effect) bool {
|
|
|
|
|
|
|
|
|
|
|
|
t.SwitchOut(selfinput)
|
|
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
2025-12-10 16:42:23 +00:00
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
|
|
selfinput.CanChange = 2
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2026-04-04 04:34:43 +08:00
|
|
|
|
// oldpet := selfinput.CurPet[0]
|
2025-12-25 20:49:54 +08:00
|
|
|
|
// InitAttackValue := *selfinput.AttackValue
|
2026-04-04 05:44:02 +08:00
|
|
|
|
nextPet, reason := selfinput.GetPet(ret.Cid)
|
|
|
|
|
|
if nextPet == nil {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
selfinput.SetCurPetAt(0, nextPet)
|
|
|
|
|
|
ret.Reason = reason
|
|
|
|
|
|
ret.Reason.ActorIndex = uint32(ret.ActorIndex)
|
2026-02-05 23:44:07 +08:00
|
|
|
|
|
2026-04-09 02:14:09 +08:00
|
|
|
|
if f.LegacyGroupProtocol {
|
|
|
|
|
|
f.sendLegacyGroupChangePetSuccess(selfinput.Player, selfinput, &ret.Reason)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
f.sendFightPacket(selfinput.Player, fightPacketChangePetSuccess, &ret.Reason)
|
|
|
|
|
|
}
|
2025-12-18 23:57:17 +08:00
|
|
|
|
|
2026-04-04 05:44:02 +08:00
|
|
|
|
f.Switch[key] = ret
|
2025-12-10 16:03:45 +00:00
|
|
|
|
|
|
|
|
|
|
selfinput.InitAttackValue() //切换精灵消除能力提升
|
|
|
|
|
|
//这时候精灵已经切换过了,可以直接给新精灵加效果
|
|
|
|
|
|
|
|
|
|
|
|
f.Broadcast(func(ff *input.Input) {
|
|
|
|
|
|
|
|
|
|
|
|
ff.Exec(func(t input.Effect) bool {
|
|
|
|
|
|
|
2025-12-25 20:49:54 +08:00
|
|
|
|
t.SwitchIn(selfinput)
|
2025-12-10 16:03:45 +00:00
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
2025-12-11 13:31:20 +08:00
|
|
|
|
if selfinput.CanChange == 2 {
|
2025-12-16 02:50:10 +08:00
|
|
|
|
|
2025-12-11 13:31:20 +08:00
|
|
|
|
selfinput.CanChange = 0
|
2026-04-04 05:44:02 +08:00
|
|
|
|
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC && paction.GetPlayerID() == 0 {
|
|
|
|
|
|
f.Switch = make(map[actionSlotKey]*action.ActiveSwitchAction)
|
2026-04-09 02:14:09 +08:00
|
|
|
|
if f.LegacyGroupProtocol {
|
|
|
|
|
|
f.sendLegacyGroupChangePetSuccess(f.Our[0].Player, selfinput, &ret.Reason)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
f.sendFightPacket(f.Our[0].Player, fightPacketChangePetSuccess, &ret.Reason)
|
|
|
|
|
|
}
|
2026-02-07 01:12:46 +08:00
|
|
|
|
//println("AI出手死切")
|
2026-04-08 01:28:55 +08:00
|
|
|
|
f.triggerNPCActions() // boss出手后获取出招
|
2026-01-20 02:25:02 +08:00
|
|
|
|
|
2025-12-16 07:42:45 +00:00
|
|
|
|
}
|
2025-12-11 13:31:20 +08:00
|
|
|
|
continue
|
|
|
|
|
|
}
|
2026-02-05 23:44:07 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
continue
|
2025-11-01 18:36:21 +08:00
|
|
|
|
}
|
2025-12-01 23:31:48 +08:00
|
|
|
|
|
2025-12-10 16:42:23 +00:00
|
|
|
|
} else {
|
2026-02-07 03:09:43 +08:00
|
|
|
|
// println("玩家执行释放技能动作:", pid, paction.(*action.SelectSkillAction).Info.ID)
|
2026-04-04 05:44:02 +08:00
|
|
|
|
currentPet := selfinput.PrimaryCurPet()
|
|
|
|
|
|
if currentPet == nil || currentPet.Info.Hp <= 0 { //0血执行非切换动作
|
2025-12-10 16:42:23 +00:00
|
|
|
|
//todo 记录异常操作
|
2026-04-04 05:44:02 +08:00
|
|
|
|
cool.Logger.Print(context.TODO(), "玩家执行了异常操作,当前精灵血量为0,不能执行非切换动作", paction.GetPlayerID())
|
2025-12-10 16:42:23 +00:00
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
if selfinput.CanChange == 1 { //非被动死亡情况下,不能执行额外动作,0允许切,2是死亡,可以额外动作
|
2026-04-04 05:44:02 +08:00
|
|
|
|
cool.Logger.Print(context.TODO(), "玩家执行了异常操作,切换后二次释放技能,不能执行非切换动作", paction.GetPlayerID())
|
2025-12-10 16:42:23 +00:00
|
|
|
|
continue
|
|
|
|
|
|
}
|
2026-02-02 12:36:43 +08:00
|
|
|
|
|
2025-11-01 18:36:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-04 05:44:02 +08:00
|
|
|
|
actions[key] = paction
|
2025-11-03 03:59:59 +08:00
|
|
|
|
//fmt.Println("玩家执行动作:", pid, paction.Priority())
|
2025-11-01 18:36:21 +08:00
|
|
|
|
|
2026-04-05 21:59:22 +08:00
|
|
|
|
case <-timeout.C:
|
2026-04-04 05:44:02 +08:00
|
|
|
|
r := f.handleTimeout(expectedSlots, actions)
|
2026-02-09 01:29:33 +08:00
|
|
|
|
if r {
|
2026-04-04 05:44:02 +08:00
|
|
|
|
return flattenActionMap(actions)
|
2026-02-09 01:29:33 +08:00
|
|
|
|
}
|
2026-04-05 21:59:22 +08:00
|
|
|
|
timeout.Reset(waitr)
|
2026-02-09 01:29:33 +08:00
|
|
|
|
|
2025-11-01 18:36:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-04 05:44:02 +08:00
|
|
|
|
return flattenActionMap(actions)
|
2025-11-01 18:36:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 超时处理逻辑
|
2026-04-04 05:44:02 +08:00
|
|
|
|
func (f *FightC) handleTimeout(expectedSlots map[actionSlotKey]struct{}, actions map[actionSlotKey]action.BattleActionI) bool {
|
2025-11-11 11:45:09 +00:00
|
|
|
|
|
2026-02-08 15:18:50 +08:00
|
|
|
|
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC {
|
2026-04-04 05:44:02 +08:00
|
|
|
|
for key := range expectedSlots {
|
|
|
|
|
|
if _, exists := actions[key]; exists || !f.isOurPlayerID(key.PlayerID) {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
player := f.getPlayerByID(key.PlayerID)
|
|
|
|
|
|
if player != nil {
|
2026-04-08 01:28:55 +08:00
|
|
|
|
targetIndex := 0
|
|
|
|
|
|
if self := f.getInputByUserID(key.PlayerID, key.ActorIndex, false); self != nil {
|
|
|
|
|
|
targetIndex = self.RandomOpponentSlotIndex()
|
|
|
|
|
|
}
|
|
|
|
|
|
f.UseSkillAt(player, 0, key.ActorIndex, targetIndex)
|
2026-04-04 05:44:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-02-09 01:29:33 +08:00
|
|
|
|
return false
|
2026-02-08 15:18:50 +08:00
|
|
|
|
} else {
|
2026-04-04 05:44:02 +08:00
|
|
|
|
missingOur := false
|
|
|
|
|
|
missingOpp := false
|
|
|
|
|
|
for key := range expectedSlots {
|
|
|
|
|
|
if _, exists := actions[key]; exists {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
if f.isOurPlayerID(key.PlayerID) {
|
|
|
|
|
|
missingOur = true
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
missingOpp = true
|
|
|
|
|
|
}
|
|
|
|
|
|
switch {
|
|
|
|
|
|
case missingOur && !missingOpp:
|
|
|
|
|
|
if player := f.primaryOppPlayer(); player != nil {
|
|
|
|
|
|
f.WinnerId = player.GetInfo().UserID
|
|
|
|
|
|
}
|
|
|
|
|
|
case missingOpp && !missingOur:
|
|
|
|
|
|
if player := f.primaryOurPlayer(); player != nil {
|
|
|
|
|
|
f.WinnerId = player.GetInfo().UserID
|
|
|
|
|
|
}
|
|
|
|
|
|
default:
|
|
|
|
|
|
for _, act := range actions {
|
|
|
|
|
|
f.WinnerId = act.GetPlayerID()
|
2026-02-08 15:18:50 +08:00
|
|
|
|
break
|
|
|
|
|
|
}
|
2026-04-04 05:44:02 +08:00
|
|
|
|
if f.WinnerId == 0 {
|
|
|
|
|
|
f.WinnerId = f.ownerID
|
|
|
|
|
|
}
|
2026-02-08 15:18:50 +08:00
|
|
|
|
}
|
2026-03-04 22:47:21 +08:00
|
|
|
|
f.Reason = model.BattleOverReason.PlayerOVerTime
|
2026-02-08 15:18:50 +08:00
|
|
|
|
f.closefight = true
|
2026-02-09 01:29:33 +08:00
|
|
|
|
return true
|
2025-11-01 18:36:21 +08:00
|
|
|
|
}
|
2026-02-08 15:18:50 +08:00
|
|
|
|
|
2025-11-01 18:36:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-08 01:28:55 +08:00
|
|
|
|
func (f *FightC) triggerNPCActions() {
|
|
|
|
|
|
for slot, opponent := range f.Opp {
|
|
|
|
|
|
if opponent == nil {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
go func(slot int, opponent *input.Input) {
|
|
|
|
|
|
defer func() {
|
|
|
|
|
|
if err := recover(); err != nil {
|
|
|
|
|
|
cool.Logger.Error(context.Background(), "fight npc action panic", f.ownerID, slot, err, string(debug.Stack()))
|
|
|
|
|
|
}
|
|
|
|
|
|
}()
|
|
|
|
|
|
opponent.GetAction()
|
|
|
|
|
|
}(slot, opponent)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-04 05:44:02 +08:00
|
|
|
|
func flattenActionMap(actions map[actionSlotKey]action.BattleActionI) []action.BattleActionI {
|
|
|
|
|
|
flattened := make([]action.BattleActionI, 0, len(actions))
|
|
|
|
|
|
for _, act := range actions {
|
|
|
|
|
|
if act != nil {
|
|
|
|
|
|
flattened = append(flattened, act)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return flattened
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (f *FightC) actionSpeed(act action.BattleActionI) alpacadecimal.Decimal {
|
|
|
|
|
|
if act == nil {
|
|
|
|
|
|
return alpacadecimal.Zero
|
|
|
|
|
|
}
|
|
|
|
|
|
attacker := f.GetInputByAction(act, false)
|
|
|
|
|
|
if attacker == nil {
|
|
|
|
|
|
return alpacadecimal.Zero
|
|
|
|
|
|
}
|
|
|
|
|
|
return attacker.GetProp(4)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (f *FightC) sortActions(actions []action.BattleActionI) {
|
|
|
|
|
|
sort.SliceStable(actions, func(i, j int) bool {
|
|
|
|
|
|
a, b := actions[i], actions[j]
|
|
|
|
|
|
if a == nil || b == nil {
|
|
|
|
|
|
return a != nil
|
|
|
|
|
|
}
|
|
|
|
|
|
if a.Priority() != b.Priority() {
|
|
|
|
|
|
return a.Priority() > b.Priority()
|
|
|
|
|
|
}
|
|
|
|
|
|
if speedA, speedB := f.actionSpeed(a), f.actionSpeed(b); speedA.Cmp(speedB) != 0 {
|
|
|
|
|
|
return speedA.Cmp(speedB) > 0
|
|
|
|
|
|
}
|
|
|
|
|
|
if a.GetActorIndex() != b.GetActorIndex() {
|
|
|
|
|
|
return a.GetActorIndex() < b.GetActorIndex()
|
|
|
|
|
|
}
|
|
|
|
|
|
if a.GetTargetIndex() != b.GetTargetIndex() {
|
|
|
|
|
|
return a.GetTargetIndex() < b.GetTargetIndex()
|
|
|
|
|
|
}
|
|
|
|
|
|
return a.GetPlayerID() < b.GetPlayerID()
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-04 22:13:42 +08:00
|
|
|
|
func sortActionsByActor(actions []action.BattleActionI) {
|
|
|
|
|
|
sort.SliceStable(actions, func(i, j int) bool {
|
|
|
|
|
|
a, b := actions[i], actions[j]
|
|
|
|
|
|
if a == nil || b == nil {
|
|
|
|
|
|
return a != nil
|
|
|
|
|
|
}
|
|
|
|
|
|
if a.GetActorIndex() != b.GetActorIndex() {
|
|
|
|
|
|
return a.GetActorIndex() < b.GetActorIndex()
|
|
|
|
|
|
}
|
|
|
|
|
|
if a.GetTargetIndex() != b.GetTargetIndex() {
|
|
|
|
|
|
return a.GetTargetIndex() < b.GetTargetIndex()
|
|
|
|
|
|
}
|
|
|
|
|
|
return a.GetPlayerID() < b.GetPlayerID()
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
2026-04-04 05:44:02 +08:00
|
|
|
|
|
2026-04-04 22:13:42 +08:00
|
|
|
|
func (f *FightC) splitRoundActions(actions []action.BattleActionI) ([]action.BattleActionI, []action.BattleActionI) {
|
|
|
|
|
|
our := make([]action.BattleActionI, 0, len(actions))
|
|
|
|
|
|
opp := make([]action.BattleActionI, 0, len(actions))
|
|
|
|
|
|
for _, act := range actions {
|
|
|
|
|
|
if act == nil {
|
2026-04-04 05:44:02 +08:00
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
if f.isOurPlayerID(act.GetPlayerID()) {
|
2026-04-04 22:13:42 +08:00
|
|
|
|
our = append(our, act)
|
2026-04-04 05:44:02 +08:00
|
|
|
|
} else {
|
2026-04-04 22:13:42 +08:00
|
|
|
|
opp = append(opp, act)
|
2026-04-04 05:44:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-04 22:13:42 +08:00
|
|
|
|
sortActionsByActor(our)
|
|
|
|
|
|
sortActionsByActor(opp)
|
|
|
|
|
|
return our, opp
|
2026-04-04 05:44:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-01 18:36:21 +08:00
|
|
|
|
// 根据动作类型执行一回合结算
|
2026-04-04 05:44:02 +08:00
|
|
|
|
func (f *FightC) resolveRound(actions []action.BattleActionI) {
|
|
|
|
|
|
if len(actions) == 0 {
|
|
|
|
|
|
cool.Logger.Debug(context.Background(), "当前回合没有可执行动作,自动跳过结算")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-04 22:13:42 +08:00
|
|
|
|
ourActions, oppActions := f.splitRoundActions(actions)
|
|
|
|
|
|
roundLen := len(ourActions)
|
|
|
|
|
|
if len(oppActions) > roundLen {
|
|
|
|
|
|
roundLen = len(oppActions)
|
|
|
|
|
|
}
|
|
|
|
|
|
for i := 0; i < roundLen; i++ {
|
2026-04-04 05:44:02 +08:00
|
|
|
|
if f.closefight {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2026-04-04 22:13:42 +08:00
|
|
|
|
var ourAct action.BattleActionI
|
|
|
|
|
|
var oppAct action.BattleActionI
|
|
|
|
|
|
if i < len(ourActions) {
|
|
|
|
|
|
ourAct = ourActions[i]
|
|
|
|
|
|
}
|
|
|
|
|
|
if i < len(oppActions) {
|
|
|
|
|
|
oppAct = oppActions[i]
|
|
|
|
|
|
}
|
|
|
|
|
|
f.resolveActionPair(ourAct, oppAct)
|
2026-04-04 05:44:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (f *FightC) resolveActionPair(p1Action, p2Action action.BattleActionI) {
|
|
|
|
|
|
if p1Action == nil && p2Action == nil {
|
2025-11-01 18:36:21 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 动作优先级排序
|
|
|
|
|
|
b1, b2 := f.Compare(p1Action, p2Action)
|
|
|
|
|
|
|
2026-01-03 01:35:32 +08:00
|
|
|
|
switch actionType := b1.(type) {
|
2025-11-01 18:36:21 +08:00
|
|
|
|
case *action.ActiveSwitchAction:
|
2026-01-03 01:35:32 +08:00
|
|
|
|
f.handleActiveSwitchAction(actionType, b2)
|
2025-11-13 21:36:18 +08:00
|
|
|
|
|
2026-01-03 01:35:32 +08:00
|
|
|
|
case *action.UseItemAction:
|
|
|
|
|
|
f.handleUseItemAction(actionType, b2)
|
2025-11-08 16:38:41 +08:00
|
|
|
|
|
2026-01-03 01:35:32 +08:00
|
|
|
|
default:
|
|
|
|
|
|
f.handleSkillActions(b1, b2)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-01 18:36:21 +08:00
|
|
|
|
|
2026-01-03 01:35:32 +08:00
|
|
|
|
// handleActiveSwitchAction 处理主动切换精灵动作
|
2026-02-23 21:50:57 +08:00
|
|
|
|
func (f *FightC) handleActiveSwitchAction(_ *action.ActiveSwitchAction, otherAction action.BattleActionI) {
|
2026-01-03 01:35:32 +08:00
|
|
|
|
|
|
|
|
|
|
if skillAction, ok := otherAction.(*action.SelectSkillAction); ok {
|
2026-03-09 18:49:51 +08:00
|
|
|
|
if skillAction.SkillEntity != nil && skillAction.XML.CD != nil {
|
|
|
|
|
|
f.waittime = *skillAction.XML.CD
|
2025-11-13 21:36:18 +08:00
|
|
|
|
}
|
2026-01-03 01:35:32 +08:00
|
|
|
|
f.enterturn(skillAction, nil)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
f.enterturn(nil, nil)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-25 18:25:52 +08:00
|
|
|
|
|
2026-01-03 01:35:32 +08:00
|
|
|
|
// handleUseItemAction 处理使用道具动作
|
|
|
|
|
|
func (f *FightC) handleUseItemAction(itemAction *action.UseItemAction, otherAction action.BattleActionI) {
|
2026-04-04 05:44:02 +08:00
|
|
|
|
f.setActionAttackValue(itemAction)
|
2026-01-03 01:35:32 +08:00
|
|
|
|
f.handleItemAction(itemAction)
|
2026-01-03 02:18:31 +08:00
|
|
|
|
|
2026-01-03 01:35:32 +08:00
|
|
|
|
input := f.GetInputByAction(itemAction, false)
|
2026-04-04 05:44:02 +08:00
|
|
|
|
if input == nil {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if currentPet := input.PrimaryCurPet(); currentPet != nil && currentPet.Info.Hp <= 0 {
|
|
|
|
|
|
currentPet.Info.Hp = 1
|
2026-01-03 01:35:32 +08:00
|
|
|
|
}
|
2025-11-08 16:38:41 +08:00
|
|
|
|
|
2026-01-03 01:35:32 +08:00
|
|
|
|
if skillAction, ok := otherAction.(*action.SelectSkillAction); ok {
|
2026-03-09 18:49:51 +08:00
|
|
|
|
if skillAction.SkillEntity != nil && skillAction.XML.CD != nil {
|
|
|
|
|
|
f.waittime = *skillAction.XML.CD
|
2025-11-08 16:38:41 +08:00
|
|
|
|
}
|
2026-01-03 01:35:32 +08:00
|
|
|
|
f.enterturn(skillAction, nil)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if otherItemAction, ok := otherAction.(*action.UseItemAction); ok {
|
|
|
|
|
|
f.handleItemAction(otherItemAction)
|
|
|
|
|
|
}
|
|
|
|
|
|
f.enterturn(nil, nil)
|
2025-11-01 18:36:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 使用道具的逻辑封装
|
2025-11-08 16:38:41 +08:00
|
|
|
|
func (f *FightC) handleItemAction(a *action.UseItemAction) {
|
2026-04-04 05:44:02 +08:00
|
|
|
|
source := f.GetInputByAction(a, false)
|
|
|
|
|
|
target := f.GetInputByAction(a, true)
|
|
|
|
|
|
if source == nil {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2025-11-08 16:38:41 +08:00
|
|
|
|
|
|
|
|
|
|
item, ok := xmlres.ItemsMAP[int(a.ItemID)]
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2026-04-04 05:44:02 +08:00
|
|
|
|
r := source.Player.(*player.Player).Service.Item.CheakItem(uint32(a.ItemID))
|
2026-02-22 19:33:17 +08:00
|
|
|
|
if r <= 0 {
|
2025-11-25 12:29:50 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
2026-04-04 05:44:02 +08:00
|
|
|
|
source.Player.(*player.Player).Service.Item.UPDATE(a.ItemID, -1)
|
2025-11-20 21:37:37 +08:00
|
|
|
|
|
2025-11-01 18:36:21 +08:00
|
|
|
|
switch {
|
2025-11-08 16:38:41 +08:00
|
|
|
|
case gconv.Int(item.Bonus) != 0:
|
2026-04-04 05:44:02 +08:00
|
|
|
|
if target != nil && target.CanCapture > 0 && target.PrimaryCurPet() != nil { //可以捕捉
|
|
|
|
|
|
target.PrimaryCurPet().CatchRate = target.CanCapture
|
|
|
|
|
|
ok, _ := source.Capture(target.PrimaryCurPet(), a.ItemID, -1)
|
|
|
|
|
|
our := source.Player.(*player.Player)
|
2025-11-01 18:36:21 +08:00
|
|
|
|
if ok {
|
2026-03-27 17:06:18 +08:00
|
|
|
|
r := input.GetFunc(int64(item.ID))
|
|
|
|
|
|
if r != nil {
|
2026-04-04 05:44:02 +08:00
|
|
|
|
r.Exec(f, &target.Player.GetInfo().PetList[0])
|
2026-03-27 17:06:18 +08:00
|
|
|
|
}
|
2026-03-04 22:47:21 +08:00
|
|
|
|
f.Reason = model.BattleOverReason.Cacthok
|
2025-11-01 18:36:21 +08:00
|
|
|
|
f.closefight = true
|
|
|
|
|
|
} else {
|
2025-11-20 21:37:37 +08:00
|
|
|
|
our.SendPack(common.NewTomeeHeader(2409, f.ownerID).Pack(&info.CatchMonsterOutboundInfo{}))
|
2025-11-19 16:11:02 +08:00
|
|
|
|
|
2025-11-01 18:36:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-08 16:38:41 +08:00
|
|
|
|
case gconv.Int(item.HP) != 0:
|
|
|
|
|
|
addhp := item.HP
|
2026-04-04 05:44:02 +08:00
|
|
|
|
source.Heal(source, a, alpacadecimal.NewFromInt(int64(addhp)))
|
2026-04-09 02:14:09 +08:00
|
|
|
|
f.BroadcastPlayers(func(p common.PlayerI) {
|
2026-04-04 05:44:02 +08:00
|
|
|
|
currentPet := source.PrimaryCurPet()
|
|
|
|
|
|
if currentPet == nil {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2026-04-09 02:14:09 +08:00
|
|
|
|
f.sendFightPacket(p, fightPacketUseItem, &info.UsePetIteminfo{
|
2026-04-04 05:44:02 +08:00
|
|
|
|
UserID: source.UserID,
|
2025-11-08 16:38:41 +08:00
|
|
|
|
ChangeHp: int32(addhp),
|
|
|
|
|
|
ItemID: uint32(item.ID),
|
2026-04-04 05:44:02 +08:00
|
|
|
|
UserHp: uint32(currentPet.Info.Hp),
|
2025-11-08 16:38:41 +08:00
|
|
|
|
})
|
2025-11-19 16:11:02 +08:00
|
|
|
|
|
2025-11-08 16:38:41 +08:00
|
|
|
|
})
|
|
|
|
|
|
case gconv.Int(item.PP) != 0:
|
2026-04-04 05:44:02 +08:00
|
|
|
|
source.HealPP(item.PP)
|
2026-04-09 02:14:09 +08:00
|
|
|
|
f.BroadcastPlayers(func(p common.PlayerI) {
|
2026-04-04 05:44:02 +08:00
|
|
|
|
currentPet := source.PrimaryCurPet()
|
|
|
|
|
|
if currentPet == nil {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2026-04-09 02:14:09 +08:00
|
|
|
|
f.sendFightPacket(p, fightPacketUseItem, &info.UsePetIteminfo{
|
2026-04-04 05:44:02 +08:00
|
|
|
|
UserID: source.UserID,
|
2025-11-08 16:38:41 +08:00
|
|
|
|
|
|
|
|
|
|
ItemID: uint32(item.ID),
|
2026-04-04 05:44:02 +08:00
|
|
|
|
UserHp: uint32(currentPet.Info.Hp),
|
2025-11-08 16:38:41 +08:00
|
|
|
|
})
|
2025-11-19 16:11:02 +08:00
|
|
|
|
|
2025-11-08 16:38:41 +08:00
|
|
|
|
})
|
2025-11-08 00:47:45 +08:00
|
|
|
|
|
2025-11-01 18:36:21 +08:00
|
|
|
|
default:
|
|
|
|
|
|
|
2025-11-08 16:38:41 +08:00
|
|
|
|
fmt.Println(a.ItemID, "ItemID 不在指定范围内")
|
2025-11-01 18:36:21 +08:00
|
|
|
|
}
|
2025-11-08 16:38:41 +08:00
|
|
|
|
|
2025-11-01 18:36:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 双方都是技能时的结算逻辑
|
|
|
|
|
|
func (f *FightC) handleSkillActions(a1, a2 action.BattleActionI) {
|
|
|
|
|
|
s1, _ := a1.(*action.SelectSkillAction)
|
|
|
|
|
|
s2, _ := a2.(*action.SelectSkillAction)
|
|
|
|
|
|
|
|
|
|
|
|
switch {
|
|
|
|
|
|
case s1 == nil || s1.SkillEntity == nil:
|
2026-04-08 01:28:55 +08:00
|
|
|
|
if s2 != nil && s2.SkillEntity != nil {
|
2026-03-09 18:49:51 +08:00
|
|
|
|
if s2.XML.CD != nil {
|
|
|
|
|
|
f.waittime = *s2.XML.CD
|
2025-11-26 18:39:23 +08:00
|
|
|
|
}
|
2025-11-15 16:27:59 +08:00
|
|
|
|
}
|
2025-11-26 18:39:23 +08:00
|
|
|
|
|
2025-11-01 18:36:21 +08:00
|
|
|
|
f.enterturn(s2, nil)
|
2025-11-26 18:39:23 +08:00
|
|
|
|
// fmt.Println("1 空过 2玩家执行技能:", s2.PlayerID, s2.Info.ID)
|
2025-11-01 18:36:21 +08:00
|
|
|
|
case s2 == nil || s2.SkillEntity == nil:
|
2026-04-08 01:28:55 +08:00
|
|
|
|
if s1 != nil && s1.SkillEntity != nil {
|
2026-03-09 18:49:51 +08:00
|
|
|
|
if s1.XML.CD != nil {
|
|
|
|
|
|
f.waittime = *s1.XML.CD
|
2025-11-26 18:39:23 +08:00
|
|
|
|
}
|
2025-11-15 16:27:59 +08:00
|
|
|
|
}
|
2025-11-01 18:36:21 +08:00
|
|
|
|
f.enterturn(s1, nil)
|
2025-11-26 18:39:23 +08:00
|
|
|
|
//fmt.Println("2 空过 玩家执行技能:", s1.PlayerID, s1.Info.ID)
|
2025-11-01 18:36:21 +08:00
|
|
|
|
default:
|
2026-03-09 18:49:51 +08:00
|
|
|
|
if s1.XML.CD != nil {
|
|
|
|
|
|
f.waittime = *s1.XML.CD
|
2025-11-15 16:27:59 +08:00
|
|
|
|
}
|
2026-03-09 18:49:51 +08:00
|
|
|
|
if s2.XML.CD != nil {
|
|
|
|
|
|
f.waittime += *s2.XML.CD
|
2025-11-15 16:27:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-01 18:36:21 +08:00
|
|
|
|
f.enterturn(s1, s2)
|
2026-01-20 02:25:02 +08:00
|
|
|
|
|
2025-11-01 18:36:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 根据玩家ID返回对应对象
|
|
|
|
|
|
func (f *FightC) getPlayerByID(id uint32) common.PlayerI {
|
2026-04-04 05:44:02 +08:00
|
|
|
|
for _, player := range f.OurPlayers {
|
|
|
|
|
|
if player != nil && player.GetInfo().UserID == id {
|
|
|
|
|
|
return player
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
for _, player := range f.OppPlayers {
|
|
|
|
|
|
if player != nil && player.GetInfo().UserID == id {
|
|
|
|
|
|
return player
|
|
|
|
|
|
}
|
2025-11-01 18:36:21 +08:00
|
|
|
|
}
|
2026-04-04 05:44:02 +08:00
|
|
|
|
return nil
|
2025-11-01 18:36:21 +08:00
|
|
|
|
}
|