From 52d35119c804fee556a9d32da8b83fcc9a241930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <1@72wo.cn> Date: Fri, 5 Sep 2025 22:40:36 +0800 Subject: [PATCH] =?UTF-8?q?feat(fight):=20=E9=87=8D=E6=9E=84=E6=88=98?= =?UTF-8?q?=E6=96=97=E6=A8=A1=E5=9D=97=E5=B9=B6=E6=B7=BB=E5=8A=A0=E6=96=B0?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重构了战斗动作处理逻辑,增加了新的战斗动作类型 - 新增了逃跑、使用药剂、系统放弃等战斗动作 - 优化了战斗回合循环和动作执行顺序 - 增加了战斗结束处理逻辑 - 调整了玩家和AI的战斗行为 -增加精灵捕捉 --- logic/controller/fight.go | 15 +- logic/service/ai.go | 15 +- logic/service/fight/battle/node/node.go | 11 +- logic/service/fight/cmd.go | 11 -- logic/service/fight/info/BattleAction.go | 209 ++++++++++++++++---- logic/service/fight/info/BattlePetEntity.go | 23 ++- logic/service/fight/info/info.go | 11 ++ logic/service/fight/info/nodemanger.go | 17 +- logic/service/fightc.go | 186 ++++++++++++----- logic/service/player.go | 14 ++ 10 files changed, 386 insertions(+), 126 deletions(-) diff --git a/logic/controller/fight.go b/logic/controller/fight.go index f893bf29a..8914219e1 100644 --- a/logic/controller/fight.go +++ b/logic/controller/fight.go @@ -44,6 +44,10 @@ func (h Controller) OnPlayerFightNpcMonster(data *fight.FightNpcMonsterInboundIn if err1 != nil { panic(err) } + + if c.FightC != nil { + return nil, -1 + } c.FightC = &service.FightC{} c.FightC.NewFight(&ttt, c) //把两个玩家都传进去 c.FightC.OwnerID = c.Info.UserID @@ -72,15 +76,6 @@ func (h Controller) UseSkill(data *fight.UseSkillInboundInfo, c *service.Player) // 战斗逃跑 func (h Controller) Escape(data *fight.EscapeFightInboundInfo, c *service.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) { - defer func() { - //战斗结束Escape - ttt := service.NewTomeeHeader(2506, c.Info.UserID) - - c.SendPack(ttt.Pack(&fight.FightOverInfo{ - Reason: 0, - })) - c.FightC = nil - }() - + c.FightC.Escape(c) return nil, 0 } diff --git a/logic/service/ai.go b/logic/service/ai.go index 99b07b239..39daf3acc 100644 --- a/logic/service/ai.go +++ b/logic/service/ai.go @@ -33,10 +33,23 @@ func (f *AI_player) SendPack(b []byte) error { func (f *AI_player) SendReadyToFightInfo(gg info.FightStartOutboundInfo) { fmt.Println(gg) - f.FightC.UseSkill(f, f.fightinfo.OpponentPetList[0].SkillList[0].ID) //使用1#技能,实际上要按照四个技能权重去使用 + // f.FightC.UseSkill(f, f.fightinfo.OpponentPetList[0].SkillList[0].ID) //使用1#技能,实际上要按照四个技能权重去使用 //这时候给个出招 } func (f *AI_player) SendNoteReadyToFightInfo(_ info.NoteReadyToFightInfo) { panic("not implemented") // TODO: Implement } + +func (f *AI_player) SendFightEndInfo(_ info.FightOverInfo) { + fmt.Println("战斗结束") + +} +func (f *AI_player) GetAction() { + f.FightC.UseSkill(f, f.fightinfo.OpponentPetList[0].SkillList[0].ID) //使用1#技能,实际上要按照四个技能权重去使用 +} +func (p *AI_player) End() { + p.FightC = nil + + return +} diff --git a/logic/service/fight/battle/node/node.go b/logic/service/fight/battle/node/node.go index 2bb4d7258..e0687eb32 100644 --- a/logic/service/fight/battle/node/node.go +++ b/logic/service/fight/battle/node/node.go @@ -19,7 +19,7 @@ type EffectNode struct { SideEffectArgs []int // 附加效果参数 Success bool // 是否执行成功 成功XXX,失败XXX - efftype int // 传出作用对象,默认0是自身,1是作用于对面 + target int // 传出作用对象,默认0是自身,1是作用于对面 Flag int //过滤掉的战斗类型 pvp pve boss战斗,野怪全部生效 //增加owner target,如果owner target都为自身,就回合效果结束后再使用回合效果 } @@ -31,9 +31,14 @@ func (this *EffectNode) ID() int { } // 传出作用对象,默认0是自身,1是作用于对面 -func (this *EffectNode) Type() int { +func (this *EffectNode) Target() int { - return this.efftype + return this.target + +} +func (this *EffectNode) SetTarget(t int) { + + this.target = t } func (this *EffectNode) Stack(t int) int { diff --git a/logic/service/fight/cmd.go b/logic/service/fight/cmd.go index f98df33b4..4f10263ff 100644 --- a/logic/service/fight/cmd.go +++ b/logic/service/fight/cmd.go @@ -25,17 +25,6 @@ type EscapeFightInboundInfo struct { Head service.TomeeHeader `cmd:"2410" struc:"[0]pad"` } -// FightOverInfo 战斗结束信息结构体 2506 -type FightOverInfo struct { - Reason uint32 // 固定值0 - WinnerId uint32 // 胜者的米米号 野怪为0 - TwoTimes uint32 // 双倍经验剩余次数 - ThreeTimes uint32 // 三倍经验剩余次数 - AutoFightTimes uint32 // 自动战斗剩余次数 - EnergyTimes uint32 // 能量吸收器剩余次数 - LearnTimes uint32 // 双倍学习器剩余次数 -} - // HandleFightInviteInboundInfo 处理战斗邀请的入站消息 // 回空包就行 type HandleFightInviteInboundInfo struct { diff --git a/logic/service/fight/info/BattleAction.go b/logic/service/fight/info/BattleAction.go index 8136f78b7..e7416fae9 100644 --- a/logic/service/fight/info/BattleAction.go +++ b/logic/service/fight/info/BattleAction.go @@ -1,6 +1,9 @@ package info import ( + "fmt" + "time" + "github.com/tnnmigga/enum" ) @@ -9,54 +12,178 @@ type EnumPlayerOperation int // 定义读秒倒计时期间玩家可执行的操作枚举 var PlayerOperations = enum.New[struct { - SystemGiveUp EnumPlayerOperation `enum:"-1"` //`enum:"系统选择放弃出手"`比如没有PP, - SelectSkill EnumPlayerOperation `enum:"0"` //`enum:"选择技能"` - - ActiveSwitch EnumPlayerOperation `enum:"2"` //`enum:"主动切换(中切)"` - - UsePotion EnumPlayerOperation `enum:"3"` //`enum:"使用药剂"` 捕捉 逃跑 - Escape EnumPlayerOperation `enum:"4"` //`enum:"使用药剂"` 逃跑 等级最高 ,以及掉线 - - //DeathSwitch EnumPlayerOperation `enum:"4"` //`enum:"死亡切换"` 这两个本质上还是对action的比较 - // ExpelledSwitch EnumPlayerOperation `enum:"5"` //`enum:"(被)驱逐切换"` + SystemGiveUp EnumPlayerOperation `enum:"-1"` // 系统选择放弃出手(比如没有PP) + SelectSkill EnumPlayerOperation `enum:"0"` // 选择技能-6到6 + ActiveSwitch EnumPlayerOperation `enum:"2"` // 主动切换(中切) + UsePotion EnumPlayerOperation `enum:"3"` // 使用药剂(捕捉、逃跑等) + Escape EnumPlayerOperation `enum:"4"` // 逃跑(等级最高,以及掉线) + PlayerOffline EnumPlayerOperation `enum:"5"` // 玩家掉线 }]() -type BattleAction struct { - PlayerID uint32 - Priority EnumPlayerOperation //优先级本质上是action的itoa - Skill BattleSkillEntity - PetInfo BattlePetEntity - //ctx context.Context -} - // Compare 比较两个1v1战斗动作的执行优先级(核心逻辑) -func (c *BattleAction) Compare(a *BattleAction) *BattleAction { - //player, _ := a.ctx.Value("player").(*BattleInputSourceEntity) - // 动作本身的优先级 技能的优先级是0, - p1 := a.Priority - c.Priority - if p1 > 0 { //说明对手快 - return a +func Compare(a, b BattleActionI) BattleActionI { + // 动作本身的优先级比较 + p1 := b.Priority() - a.Priority() + if p1 > 0 { // 对手优先级更高 + return b } else if p1 < 0 { - return c + return a } - if a.Priority == 0 { - - p2 := a.Skill.Priority - c.Skill.Priority //对方减自己 - if p2 > 0 { - return a - } else if p2 < 0 { - return c - } - - p2 = int(a.PetInfo.Value(4)) - int(c.PetInfo.Value(4)) // 假设 Use1v1SkillAction 有 SkillPriority() 方法 - if p2 > 0 { - return a - } else if p2 < 0 { - return c - } + bskill := b.(*SelectSkillAction) + askill := a.(*SelectSkillAction) + // 如果是选择技能操作,进一步比较技能优先级和宠物属性 + p2 := bskill.Skill.Priority - askill.Skill.Priority + if p2 > 0 { + return b + } else if p2 < 0 { + return a } - return c // 3.3 速度相同时 ,发起方优先 + // 比较宠物相关属性(假设Value(4)返回速度相关值) + p2 = int(bskill.PetInfo.Value(4)) - int(askill.PetInfo.Value(4)) + if p2 > 0 { + return b + } else if p2 < 0 { + return a + } + + return a // 速度相同时,发起方优先 +} + +// BattleActionI 战斗动作接口 +type BattleActionI interface { + GetPlayerID() uint32 + Priority() int // 优先级 + +} + +// SelectSkillAction 选择技能的战斗动作 +type SelectSkillAction struct { + PlayerID uint32 // 玩家ID + Skill *BattleSkillEntity // 使用的技能 + PetInfo *BattlePetEntity // 使用技能的宠物 +} + +func (s *SelectSkillAction) GetPlayerID() uint32 { + return s.PlayerID +} + +// Priority 返回动作优先级 +func (s *SelectSkillAction) Priority() int { + return int(PlayerOperations.SelectSkill) +} + +// Broadcast 广播选择技能的动作信息 +func (s *SelectSkillAction) Broadcast() { + fmt.Printf("玩家[%d]选择使用技能:%s(ID:%d),执行者:%s\n", + s.PlayerID, s.Skill.Name, s.Skill.ID, s.PetInfo.ID) +} + +// ActiveSwitchAction 主动切换宠物的战斗动作 +type ActiveSwitchAction struct { + PlayerID uint32 // 玩家ID + CurrentPet BattlePetEntity // 当前在场宠物 + TargetPet BattlePetEntity // 要切换上场的宠物 + SwitchReason string // 切换原因 +} + +// Priority 返回动作优先级 +func (a *ActiveSwitchAction) Priority() int { + return int(PlayerOperations.ActiveSwitch) +} + +// Broadcast 广播切换宠物的动作信息 +func (a *ActiveSwitchAction) Broadcast() { + // fmt.Printf("玩家[%d]主动切换宠物:从%s切换到%s(原因:%s)\n", + // // a.PlayerID, a.CurrentPet.Name, a.TargetPet.Name, a.SwitchReason) +} + +// UsePotionAction 使用药剂的战斗动作 +type UsePotionAction struct { + PlayerID uint32 // 玩家ID + PotionID uint32 // 药剂ID + PotionName string // 药剂名称 + TargetPet BattlePetEntity // 药剂作用目标宠物 +} +type PlayerI interface { + SendPack(b []byte) error +} + +// Priority 返回动作优先级 +func (u *UsePotionAction) Priority() int { + return int(PlayerOperations.UsePotion) +} + +// Broadcast 广播使用药剂的动作信息 +func (u *UsePotionAction) Broadcast() { + // fmt.Printf("玩家[%d]使用药剂:%s(ID:%d),目标:%s\n", + // u.PlayerID, u.PotionName, u.PotionID, u.TargetPet.Name) +} + +// EscapeAction 逃跑的战斗动作 +type EscapeAction struct { + PlayerID uint32 // 玩家ID + Reason FightOverInfo + Our PlayerI + Opp PlayerI +} + +func (e *EscapeAction) GetPlayerID() uint32 { + return e.PlayerID +} +func (e *EscapeAction) GetInfo() FightOverInfo { + return e.Reason +} + +// Priority 返回动作优先级 +func (e *EscapeAction) Priority() int { + return int(PlayerOperations.Escape) +} + +// SystemGiveUpAction 系统强制放弃出手的动作 +type SystemGiveUpAction struct { + PlayerID uint32 // 玩家ID + Reason string // 放弃原因(如没有PP值、宠物全部倒下等) + LastPet BattlePetEntity // 最后在场的宠物 +} + +func (s *SystemGiveUpAction) GetPlayerID() uint32 { + return s.PlayerID +} + +// Priority 返回动作优先级 +func (s *SystemGiveUpAction) Priority() int { + return int(PlayerOperations.SystemGiveUp) +} + +// Broadcast 广播系统放弃的动作信息 +func (s *SystemGiveUpAction) Broadcast() { + // fmt.Printf("玩家[%d]被系统强制放弃出手,原因:%s(最后在场宠物:%s)\n", + // s.PlayerID, s.Reason, s.LastPet.Name) +} + +// PlayerOfflineAction 玩家掉线的战斗动作 +type PlayerOfflineAction struct { + PlayerID uint32 // 掉线玩家ID + OfflineTime time.Time // 掉线时间 + CurrentPet BattlePetEntity // 掉线时在场的宠物 + IsReconnect bool // 是否后续重连(预留字段) +} + +// Priority 返回动作优先级 +func (p *PlayerOfflineAction) Priority() int { + return int(PlayerOperations.PlayerOffline) +} + +// Broadcast 广播玩家掉线信息 +func (p *PlayerOfflineAction) Broadcast() { + // /status := "未重连" + // if p.IsReconnect { + // status = "已重连" + // } + // fmt.Printf("玩家[%d]在[%s]掉线,当前在场宠物:%s,状态:%s\n", + // p.PlayerID, p.OfflineTime.Format("2006-01-02 15:04:05"), + // p.CurrentPet.Name, status) } diff --git a/logic/service/fight/info/BattlePetEntity.go b/logic/service/fight/info/BattlePetEntity.go index ca9375262..7de404ef0 100644 --- a/logic/service/fight/info/BattlePetEntity.go +++ b/logic/service/fight/info/BattlePetEntity.go @@ -4,7 +4,6 @@ import ( element "blazing/common/data/Element" "blazing/common/data/xmlres" "blazing/modules/blazing/model" - "context" "sync" "unsafe" ) @@ -36,16 +35,26 @@ func (a *BattlePetEntity) Value(tt uint32) uint32 { type BattlePetEntity struct { xmlres.PetInfo - info model.PetInfo //通过偏移赋值 - ctx context.Context - Capturable bool // 是否可捕获 - statusConditions sync.Map // key: StatusCondition, value: int (剩余回合) - skills [4]*BattleSkillEntity // 技能槽(最多4个技能) - Status StatusDict //精灵的状态 + info model.PetInfo //通过偏移赋值 + + Capturable bool // 是否可捕获 + statusConditions sync.Map // key: StatusCondition, value: int (剩余回合) + Skills [4]BattleSkillEntity // 技能槽(最多4个技能) + Status StatusDict //精灵的状态 //能力提升属性 Prop PropDict } +// 创建精灵实例 +func CreateBattlePetEntity(info ReadyFightPetInfo) *BattlePetEntity { + ret := &BattlePetEntity{} + + ret.PetInfo = xmlres.PetMAP[int(info.ID)] //注入精灵信息 + + return ret + +} + // calculateRealValue 计算实际属性值根据状态变化计算实际值 // value 基础属性值 // stat 状态变化值(可正可负) diff --git a/logic/service/fight/info/info.go b/logic/service/fight/info/info.go index cfaf753e7..8a80b0005 100644 --- a/logic/service/fight/info/info.go +++ b/logic/service/fight/info/info.go @@ -179,3 +179,14 @@ type ReadyFightPetInfo struct { SkinID uint32 `fieldDesc:"精灵皮肤ID" ` Shiny uint32 `fieldDesc:"精灵是否闪" ` } + +// FightOverInfo 战斗结束信息结构体 2506 +type FightOverInfo struct { + Reason uint32 // 固定值0 + WinnerId uint32 // 胜者的米米号 野怪为0 + TwoTimes uint32 // 双倍经验剩余次数 + ThreeTimes uint32 // 三倍经验剩余次数 + AutoFightTimes uint32 // 自动战斗剩余次数 + EnergyTimes uint32 // 能量吸收器剩余次数 + LearnTimes uint32 // 双倍学习器剩余次数 +} diff --git a/logic/service/fight/info/nodemanger.go b/logic/service/fight/info/nodemanger.go index 81e592172..671ade1c6 100644 --- a/logic/service/fight/info/nodemanger.go +++ b/logic/service/fight/info/nodemanger.go @@ -13,16 +13,18 @@ type Effect interface { PreDamage() bool // 技能伤害计算前触发(增伤 / 减伤等) OnBeforeCalculateDamage() bool // 最终伤害计算前触发 OnDamage() bool // 造成伤害时触发 - - Shield() bool // 护盾值变化时触发 - PostDamage() bool // 伤害结算后触发(血量扣除后) + SetParam(param []int) //设置参数 + GetParam() int //获取参数 + Shield() bool // 护盾值变化时触发 + PostDamage() bool // 伤害结算后触发(血量扣除后) OnCritPostDamage() bool // 暴击伤害结算后触发 OnHit() bool // 技能命中时触发 OnMiss() bool // 技能未命中时触发 AfterAttacked() bool // 被攻击后触发(受击判定) - Type() int // 技能效果类型 + Target() bool // 技能效果类型 + SetTarget(bool) // 技能效果类型 OnDefeat() bool // 精灵被击败时触发 TurnEnd() bool // 回合结束 @@ -71,6 +73,7 @@ type NodeManager struct { var NodeM = &NodeManager{} func (c *NodeManager) AddEffect(e Effect) { + // 如果已有同 ID 的效果,尝试叠加 for _, eff := range c.Effects { if eff.ID() == e.ID() { @@ -115,12 +118,12 @@ func (c *NodeManager) Exec(fn func(Effect) bool) bool { return results } -// 消除回合类效果 efftype 输入是消对方的还是自己的 -func (c *NodeManager) CancelTurn(efftype int) { +// 消除回合类效果 efftype 输入是消对方的还是自己的,false是自己,true是对方 +func (c *NodeManager) CancelTurn(efftype bool) { var remain []Effect for _, eff := range c.Effects { - if eff.Duration(0) <= 0 && eff.Type() != efftype { + if eff.Duration(0) <= 0 && eff.Target() == efftype { //false是自身,true是对方,反转后为真就是自己的 remain = append(remain, eff) } } diff --git a/logic/service/fightc.go b/logic/service/fightc.go index a3a8ecacc..0856ea570 100644 --- a/logic/service/fightc.go +++ b/logic/service/fightc.go @@ -1,44 +1,72 @@ package service import ( + "blazing/common/data/xmlres" + "blazing/common/utils" "blazing/logic/service/fight/info" "fmt" "math/rand" "time" + "github.com/gogf/gf/v2/util/gconv" "github.com/jinzhu/copier" ) type PlayerI interface { ID() uint32 MapID() uint32 - //GetInfo() info.BattlePetEntity + GetAction() + End() //结束战斗 SendPack(b []byte) error SendReadyToFightInfo(info.FightStartOutboundInfo) SendNoteReadyToFightInfo(info.NoteReadyToFightInfo) + SendFightEndInfo(info.FightOverInfo) } type FightC struct { - Info *info.NoteReadyToFightInfo - Our PlayerI - Opp PlayerI - MAXPET uint32 // 最大精灵数 - OwnerID uint32 // 战斗发起者ID - AFinished bool - BFinished bool + Info *info.NoteReadyToFightInfo + Our PlayerI + OurCurrentPet *info.BattlePetEntity //我方精灵 + Opp PlayerI + OppCurrentPet *info.BattlePetEntity //对方当前精灵 + MAXPET uint32 // 最大精灵数 + OwnerID uint32 // 战斗发起者ID + AFinished bool + BFinished bool //random *rand.Rand //随机数种子 StartTime time.Time - actionChan chan info.BattleAction // 所有操作统一从这里进入 - Round int //回合数 + actionChan chan info.BattleActionI // 所有操作统一从这里进入 + Round int //回合数 + EffectS info.NodeManager //effects容器 +} + +// 玩家逃跑 +func (f *FightC) Escape(c PlayerI) { + ret := &info.EscapeAction{ + PlayerID: c.ID(), + Reason: info.FightOverInfo{ + + Reason: uint32(info.BattleOverReason.PlayerEscape), + }, + } + + f.actionChan <- ret } // 玩家使用技能 func (f *FightC) UseSkill(c PlayerI, id uint32) { - - ret := info.BattleAction{ + ret := &info.SelectSkillAction{ PlayerID: c.ID(), - Priority: info.PlayerOperations.SelectSkill, - // Skill: info.CreateBattleSkillWithInfinity(id), + + Skill: info.CreateBattleSkillWithInfinity(id), + } + + if c == f.Our { + ret.PetInfo = f.OurCurrentPet //存入自己的精灵信息 + + } else { + + ret.PetInfo = f.OppCurrentPet } f.actionChan <- ret @@ -49,30 +77,40 @@ func (f *FightC) ReadyFight(c PlayerI) { rett := info.FightStartOutboundInfo{} copier.Copy(&rett.Info1, &f.Info.OurPetList[0]) // 复制自己的信息 + copier.Copy(&rett.Info2, &f.Info.OpponentPetList[0]) + rett.Info1.UserID = f.Info.OurInfo.UserID // + rett.Info2.UserID = f.Info.OpponentInfo.UserID + + rrsult := func() { //传回函数 + + f.Our.SendReadyToFightInfo(rett) + f.Opp.SendReadyToFightInfo(rett) + } switch f.Info.FightId { case 1: // 1v1 if c == f.Our { f.AFinished = true + f.OurCurrentPet = info.CreateBattlePetEntity(f.Info.OurPetList[0]) if f.BFinished { - copier.Copy(&rett.Info2, &f.Info.OpponentPetList[0]) - f.Our.SendReadyToFightInfo(rett) - f.Opp.SendReadyToFightInfo(rett) + + rrsult() } } else { f.Opp = c f.BFinished = true if f.AFinished { - copier.Copy(&rett.Info2, &f.Info.OurPetList[0]) - f.Our.SendReadyToFightInfo(rett) - f.Opp.SendReadyToFightInfo(rett) + rrsult() } } case 3: // 野怪战斗 - copier.Copy(&rett.Info2, &f.Info.OpponentPetList[0]) - rett.Info1.UserID = f.Info.OurInfo.UserID - f.Our.SendReadyToFightInfo(rett) - f.Opp.SendReadyToFightInfo(rett) + + //判断捕捉率大于0 + if gconv.Int(xmlres.PetMAP[int(f.Info.OpponentPetList[0].ID)].CatchRate) > 0 { + rett.Info2.Catchable = 1 + } + + rrsult() } } func (f *FightC) Random() { @@ -90,49 +128,74 @@ func (f *FightC) NewFight(i *info.NoteReadyToFightInfo, plays PlayerI) { f.Our = plays f.Info = i f.StartTime = time.Now() - f.actionChan = make(chan info.BattleAction, 2) // 初始化全局操作通道 + f.actionChan = make(chan info.BattleActionI, 2) // 初始化全局操作通道 switch i.FightId { case 1: // 1v1,等双方进入 case 3: // 野怪战斗 - plays.SendNoteReadyToFightInfo(*i) + f.Opp = &AI_player{fightinfo: *i, FightC: f} // 创建虚拟对手 + plays.SendNoteReadyToFightInfo(*i) } go f.battleLoop() // 起战斗循环 } +// 广播,并是否结束回合 +func (f *FightC) Broadcast(t info.BattleActionI) bool { + switch ff := t.(type) { + case *info.SelectSkillAction: + case *info.EscapeAction: + + f.Our.SendFightEndInfo(ff.Reason) + f.Opp.SendFightEndInfo(ff.Reason) + return true + default: + } + + return false +} + // 战斗回合循环 func (f *FightC) battleLoop() { for { - f.Round++ //回合数自增 - actions := make(map[uint32]info.BattleAction) // 每个玩家一条记录 + f.Round++ //回合数自增 + if f.Round > 250 { //回合数超过250,战斗平局结束 + + } + actions := make(map[uint32]info.BattleActionI) // 每个玩家一条记录 timeout := time.After(60 * time.Second) for len(actions) < 2 { select { case action := <-f.actionChan: // 只接受有效玩家 ID - if action.PlayerID != f.Our.ID() && action.PlayerID != f.Opp.ID() { - continue - } - // 如果该玩家已经提交过,就忽略重复动作 - if _, exists := actions[uint32(action.PlayerID)]; exists { - fmt.Printf("玩家%d 已经提交过动作,忽略重复\n", action.PlayerID) + if action.GetPlayerID() != f.Our.ID() && action.GetPlayerID() != f.Opp.ID() { continue } - actions[uint32(action.PlayerID)] = action - fmt.Printf("玩家%d 执行动作", action.PlayerID) + if action.GetPlayerID() == f.Our.ID() && f.Info.FightId == 3 { + + go f.Opp.GetAction() //获取AI的动作 + + } + // 如果该玩家已经提交过,就忽略重复动作 + if _, exists := actions[uint32(action.GetPlayerID())]; exists { + fmt.Printf("玩家%d 已经提交过动作,忽略重复\n", action.GetPlayerID()) + continue + } + + actions[uint32(action.GetPlayerID())] = action + fmt.Printf("玩家%d 执行动作", action.GetPlayerID()) case <-timeout: fmt.Println("回合操作超时") if _, exists := actions[f.Our.ID()]; !exists { - actions[f.Our.ID()] = info.BattleAction{PlayerID: f.Our.ID(), Priority: info.PlayerOperations.SystemGiveUp} //系统选择出手 + actions[f.Our.ID()] = &info.SystemGiveUpAction{PlayerID: f.Our.ID()} //系统选择出手 } if _, exists := actions[f.Opp.ID()]; !exists { - actions[f.Opp.ID()] = info.BattleAction{PlayerID: f.Our.ID(), Priority: info.PlayerOperations.SystemGiveUp} //系统选择出手 + actions[f.Opp.ID()] = &info.SystemGiveUpAction{PlayerID: f.Our.ID()} //系统选择出手 } } } @@ -140,19 +203,50 @@ func (f *FightC) battleLoop() { // 双方动作齐了,取出来结算 p1Action := actions[f.Our.ID()] p2Action := actions[f.Opp.ID()] - fmt.Printf("开始结算回合") + fmt.Println("开始结算回合") fmt.Println(p1Action) fmt.Println(p2Action) + + firstaction := info.Compare(p1Action, p2Action) + + if firstaction.Priority() > 0 { //如果优先级大于0,说明是在技能之上的 + t := f.Broadcast(firstaction) + if t { + + break + } + } // TODO: 在这里调用技能结算逻辑 - if isBattleEnd() { - fmt.Println("战斗结束") - return + firstskill, _ := firstaction.(*info.SelectSkillAction) + temparg := firstskill.Skill.SideEffectArgS + for _, v := range firstskill.Skill.SideEffectS { + + t, ok := effectmap[v] + + if ok { + + args := t.GetParam() + t.SetParam(temparg[:args]) //设置入参 + //如果不是是房主方,说明施加的对象是反的,比如本来是false,实际上是给邀请方施加的 + //所以这里要对target取反 + if firstaction.GetPlayerID() != f.OwnerID { + t.SetTarget(!t.Target()) + } + temparg = temparg[args:] + + } + } + } + close(f.actionChan) //关闭战斗通道 + //取消战斗信息 + f.Our.End() + f.Opp.End() } -// 判断战斗是否结束 -func isBattleEnd() bool { - return false -} +var effectmap = utils.ToMap[info.Effect, int](info.NodeM.Effects, + func(t info.Effect) int { + return t.ID() + }) diff --git a/logic/service/player.go b/logic/service/player.go index a97032243..0b8c16b5a 100644 --- a/logic/service/player.go +++ b/logic/service/player.go @@ -124,6 +124,15 @@ func (p *Player) GetInfo() model.PlayerInfo { return *p.Info } +func (p *Player) GetAction() { + + return +} +func (p *Player) End() { + p.FightC = nil + + return +} func (p *Player) ID() uint32 { return p.Info.UserID @@ -154,6 +163,11 @@ func (p *Player) SendNoteReadyToFightInfo(b info.NoteReadyToFightInfo) { p.SendPack(t1.Pack(&b)) //准备包由各自发,因为协议不一样 } +func (p *Player) SendFightEndInfo(b info.FightOverInfo) { + t1 := NewTomeeHeader(2506, p.Info.UserID) + + p.SendPack(t1.Pack(&b)) +} // Save 保存玩家数据 func (p *Player) Save() {