Files
bl/logic/service/fight/loop.go
昔念 2b3c4b6ccd ```
refactor(nono): 优化非诺相关结构体字段命名与初始化方式

将 nono 包中多个结构体的字段初始化方式改为键值对形式,提升可读性。
同时统一字段命名风格,增强代码一致性。

feat(fight): 移除冗余战斗循环逻辑并调整部分依赖引用

删除 fightc.go 中的 battleLoop 方法及相关逻辑,简化战斗流程控制。
移除未使用的包引用,并调整结构体成员顺序以提高清晰度。

refactor(player): 修改数据库字段类型为 jsonb 提升灵活性

将 Player 结构体中的 Data 字段由 text 类型修改为 jsonb 类型,
便于后续进行更灵活的数据存储与查询操作。
```
2025-11-01 18:36:21 +08:00

197 lines
4.8 KiB
Go

package fight
import (
"blazing/logic/service/common"
"blazing/logic/service/fight/action"
"blazing/logic/service/fight/info"
"blazing/logic/service/fight/input"
"blazing/logic/service/player"
"fmt"
"time"
)
func (f *FightC) battleLoop() {
f.actionChan = make(chan action.BattleActionI, 2)
fmt.Println("战斗开始精灵", f.Our.Player.GetInfo().PetList[0].CatchTime)
ourID := f.Our.Player.GetInfo().UserID
oppID := f.Opp.Player.GetInfo().UserID
for {
if f.closefight {
close(f.actionChan)
break
}
f.Round++
fmt.Printf("—— 第 %d 回合开始 ——\n", f.Round)
actions := f.collectPlayerActions(ourID, oppID)
if f.closefight {
break
}
f.resolveRound(actions[ourID], actions[oppID])
}
fmt.Println("战斗循环结束")
}
// 收集玩家动作(含超时判定)
func (f *FightC) collectPlayerActions(ourID, oppID uint32) map[uint32]action.BattleActionI {
actions := make(map[uint32]action.BattleActionI)
timeout := time.After(60 * time.Second)
for len(actions) < 2 {
select {
case paction, ok := <-f.actionChan:
if !ok || f.closefight {
return actions
}
if paction == nil {
continue
}
pid := paction.GetPlayerID()
if pid != ourID && pid != oppID {
continue
}
// 避免重复提交
if _, exists := actions[pid]; exists {
fmt.Printf("玩家%d 已经提交过动作,忽略重复\n", pid)
continue
}
// 被动切换处理(不计入本回合)
if as, ok := paction.(*action.ActiveSwitchAction); ok {
if f.GetInputByAction(as, false).CanChange {
f.GetInputByAction(as, false).CanChange = false
continue
}
}
// AI自动技能
if pid != 0 && (f.Info.Status == info.BattleStatus.FIGHT_WITH_BOSS ||
f.Info.Status == info.BattleStatus.FIGHT_WITH_NPC) {
f.GetInputByAction(paction, true).GetAction(f.Our)
}
actions[pid] = paction
fmt.Println("玩家执行动作:", pid, paction.Priority())
case <-timeout:
f.handleTimeout(ourID, oppID, actions)
return actions
}
}
return actions
}
// 超时处理逻辑
func (f *FightC) handleTimeout(ourID, oppID uint32, actions map[uint32]action.BattleActionI) {
for _, pid := range []uint32{ourID, oppID} {
if _, exists := actions[pid]; exists {
continue
}
fmt.Printf("玩家%d 超时\n", pid)
player := f.GetInputByPlayer(f.getPlayerByID(pid), true).Player
if !f.GetInputByPlayer(f.getPlayerByID(pid), false).Finished {
f.UseSkill(player, 0) //卡加载,给对方也一个action
}
f.Over(f.getPlayerByID(pid), info.BattleOverReason.PlayerOVerTime)
}
}
// 根据动作类型执行一回合结算
func (f *FightC) resolveRound(p1Action, p2Action action.BattleActionI) {
if p1Action == nil || p2Action == nil {
fmt.Println("某方未选择动作,自动跳过结算")
return
}
fmt.Println("开始结算回合")
// 动作优先级排序
b1, b2 := f.Compare(p1Action, p2Action)
switch a := b1.(type) {
case *action.EscapeAction:
f.Broadcast(func(ff *input.Input) {
ff.Player.SendFightEndInfo(a.Reason)
})
f.closefight = true
case *action.ActiveSwitchAction:
if _, ok := b2.(*action.SelectSkillAction); ok {
f.enterturn(b2.(*action.SelectSkillAction), nil)
} else {
f.enterturn(nil, nil)
}
case *action.UseItemAction:
f.handleItemAction(a, b2)
default:
f.handleSkillActions(b1, b2)
}
}
// 使用道具的逻辑封装
func (f *FightC) handleItemAction(a *action.UseItemAction, other action.BattleActionI) {
switch {
case a.ItemID >= 30001 && a.ItemID <= 300010:
our, ok1 := f.Our.Player.(*player.Player)
opp, ok2 := f.Opp.Player.(*player.AI_player)
if ok1 && ok2 && opp.CanCapture {
ok, res := f.Our.Capture(f.Opp.CurrentPet, a.ItemID, -1)
if ok {
fmt.Println(res)
our.Service.PetAdd(*f.Opp.CurrentPet.Info)
our.CatchPetInfo(info.CatchMonsterOutboundInfo{
CatchTime: uint32(f.Opp.CurrentPet.Info.CatchTime),
PetId: uint32(f.Opp.CurrentPet.ID),
})
our.SendFightEndInfo(info.FightOverInfo{WinnerId: f.ownerID})
f.closefight = true
} else {
our.CatchPetInfo(info.CatchMonsterOutboundInfo{})
}
}
case a.ItemID == 300001:
fmt.Println("ItemID 是 300001")
default:
fmt.Println("ItemID 不在指定范围内")
}
if _, ok := other.(*action.SelectSkillAction); ok {
f.enterturn(other.(*action.SelectSkillAction), nil)
} else {
f.enterturn(nil, nil)
}
}
// 双方都是技能时的结算逻辑
func (f *FightC) handleSkillActions(a1, a2 action.BattleActionI) {
s1, _ := a1.(*action.SelectSkillAction)
s2, _ := a2.(*action.SelectSkillAction)
switch {
case s1 == nil || s1.SkillEntity == nil:
f.enterturn(s2, nil)
case s2 == nil || s2.SkillEntity == nil:
f.enterturn(s1, nil)
default:
f.enterturn(s1, s2)
}
}
// 根据玩家ID返回对应对象
func (f *FightC) getPlayerByID(id uint32) common.PlayerI {
if id == f.Our.Player.GetInfo().UserID {
return f.Our.Player
}
return f.Opp.Player
}