diff --git a/.gitignore b/.gitignore index 8990de4e5..b86aaa6f3 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,4 @@ public/logic logic/logic2 login/login login/login +logic/logic1 diff --git a/logic/controller/nono.go b/logic/controller/nono.go index 4b3976f8b..ad8c2fc89 100644 --- a/logic/controller/nono.go +++ b/logic/controller/nono.go @@ -13,12 +13,12 @@ func (h *Controller) NonoFollowOrHome(data *nono.NonoFollowOrHomeInInfo, c *play c.Info.NONO.Flag = data.Flag result = &nono.NonoFollowOutInfo{ - data.Head.UserID, - data.Flag, - data.Flag, - "", - 0, - 0, + UserID: data.Head.UserID, + SuperStage: data.Flag, + Flag: data.Flag, + Nick: "", + Color: 0, + Power: 0, } return @@ -43,8 +43,8 @@ func (h *Controller) GetNonoInfo(data *nono.NonoInboundInfo, c *player.Player) ( func (h *Controller) SwitchFlying(data *nono.SwitchFlyingInboundInfo, c *player.Player) (result *nono.SwitchFlyingOutboundInfo, err errorcode.ErrorCode) { //这个时候player应该是空的 result = &nono.SwitchFlyingOutboundInfo{ - data.Head.UserID, - data.Type, + UserId: data.Head.UserID, + Type: data.Type, } return diff --git a/logic/logic1 b/logic/logic1 index ee7d53d21..fa81df56e 100644 Binary files a/logic/logic1 and b/logic/logic1 differ diff --git a/logic/service/fight/action/BattleAction.go b/logic/service/fight/action/BattleAction.go index 57f4ca967..fe15ef582 100644 --- a/logic/service/fight/action/BattleAction.go +++ b/logic/service/fight/action/BattleAction.go @@ -3,7 +3,6 @@ package action import ( "blazing/logic/service/common" "blazing/logic/service/fight/info" - "time" "github.com/tnnmigga/enum" ) @@ -120,15 +119,3 @@ func (e *OverTimeAction) GetInfo() info.FightOverInfo { func (e *OverTimeAction) Priority() int { return int(PlayerOperations.PlayerOffline) } - -// PlayerOfflineAction 玩家掉线的战斗动作 -type PlayerOfflineAction struct { - BaseAction - OfflineTime time.Time // 掉线时间 - Reason info.FightOverInfo -} - -// Priority 返回动作优先级 -func (p *PlayerOfflineAction) Priority() int { - return int(PlayerOperations.PlayerOffline) -} diff --git a/logic/service/fight/fightc.go b/logic/service/fight/fightc.go index 87c51ea65..ee472c754 100644 --- a/logic/service/fight/fightc.go +++ b/logic/service/fight/fightc.go @@ -6,7 +6,6 @@ import ( "blazing/logic/service/fight/action" "blazing/logic/service/fight/info" "blazing/logic/service/fight/input" - "blazing/logic/service/player" "blazing/modules/blazing/model" "fmt" "math/rand" @@ -20,8 +19,8 @@ import ( ) type FightC struct { - Info info.NoteReadyToFightInfo - + Info info.NoteReadyToFightInfo + IsReady bool ownerID uint32 // 战斗发起者ID Our *input.Input //始终等于房主ID Opp *input.Input //对手ID @@ -194,6 +193,7 @@ func NewFight(mode, status info.EnumBattleMode, p1 common.PlayerI, p2 common.Pla f.Broadcast(func(ff *input.Input) { ff.Player.SendNoteReadyToFightInfo(f.Info) + }) }() @@ -234,167 +234,6 @@ func (f *FightC) Broadcast(t func(ff *input.Input)) { } -// 战斗回合循环 -func (f *FightC) battleLoop() { - - f.actionChan = make(chan action.BattleActionI, 2) // 初始化全局操作通道 - fmt.Println("战斗开始精灵", f.Our.Player.GetInfo().PetList[0].CatchTime) - //战斗开始前操作 - - for { - - if f.closefight { //回合数超过250,战斗平局结束f.Round > 250 || - close(f.actionChan) - break - } - - f.Round++ //回合数自增 - actions := make(map[uint32]action.BattleActionI) // 每个玩家一条记录 - timeout := time.After(60 * time.Second) - - for len(actions) < 2 { - select { - case paction, ok := <-f.actionChan: - // 只接受有效玩家 ID\ - if paction == nil { - continue - } - if !ok { - fmt.Println("战斗结束") - break - } - if f.closefight { //回合数超过250,战斗平局结束f.Round > 250 || - - break - } - if paction.GetPlayerID() != f.Our.Player.GetInfo().UserID && paction.GetPlayerID() != f.Opp.Player.GetInfo().UserID { - continue - } - - if _, isExpelled := paction.(*action.ActiveSwitchAction); isExpelled { - - if f.GetInputByAction(paction, false).CanChange { - //如果是被动切换,不计入回合结算 - f.GetInputByAction(paction, false).CanChange = false - continue - - } - - } - - if paction.GetPlayerID() != 0 { - if f.Info.Status == info.BattleStatus.FIGHT_WITH_BOSS || f.Info.Status == info.BattleStatus.FIGHT_WITH_NPC { - //AI的action实质上就是放技能,如果阻止掉,比如中毒,那就也不能逃跑 - f.GetInputByAction(paction, true).GetAction(f.Our) - } - - } - - // 如果该玩家已经提交过,就忽略重复动作 - if _, exists := actions[uint32(paction.GetPlayerID())]; exists { - fmt.Printf("玩家%d 已经提交过动作,忽略重复\n", paction.GetPlayerID()) - continue - } - - actions[uint32(paction.GetPlayerID())] = paction - fmt.Println("玩家 执行动作", paction.GetPlayerID(), paction.Priority()) - - case <-timeout: - - if _, exists := actions[f.Our.Player.GetInfo().UserID]; !exists { - f.Over(f.Opp.Player, info.BattleOverReason.PlayerOVerTime) - } - if _, exists := actions[f.Opp.Player.GetInfo().UserID]; !exists { - - f.Over(f.Our.Player, info.BattleOverReason.PlayerOVerTime) - } - - } - } - - // 双方动作齐了,取出来结算 - //todo 如果一方没有选择,实际上就是后端判断PP是否还有,前端是直接发的 - p1Action := actions[f.Our.Player.GetInfo().UserID] - p2Action := actions[f.Opp.Player.GetInfo().UserID] - fmt.Println("开始结算回合") - // 统一赋值,减少重复代码 - - var BattleActionI [2]action.BattleActionI - BattleActionI[0], BattleActionI[1] = f.Compare(p1Action, p2Action) - - switch faction := BattleActionI[0].(type) { - case *action.PlayerOfflineAction: // 单方掉线 - f.Broadcast(func(ff *input.Input) { - ff.Player.SendFightEndInfo(faction.Reason) // 广播逃跑原因 - }) - f.closefight = true - - case *action.EscapeAction: // 优先逃跑 - f.Broadcast(func(ff *input.Input) { - ff.Player.SendFightEndInfo(faction.Reason) // 广播逃跑原因 - }) - f.closefight = true - - case *action.ActiveSwitchAction: // 切换上场的, 切换方放弃出手 - - // 如果后手不是技能,替换成空技能(放弃出手) - if _, ok := BattleActionI[1].(*action.SelectSkillAction); !ok { - - f.enterturn(nil, nil) //双方都不出手 - - } else { - //后手方先手,先手方放弃出手 - f.enterturn(BattleActionI[1].(*action.SelectSkillAction), nil) - - } - - case *action.UseItemAction: // 使用道具 - switch { - case faction.ItemID >= 30001 && faction.ItemID <= 300010: // 胶囊 - tt, ok := f.Our.Player.(*player.Player) - mo, ism := f.Opp.Player.(*player.AI_player) - - if ok && ism && mo.CanCapture { - ok, res := f.Our.Capture(f.Opp.CurrentPet, faction.ItemID, -1) - if ok { - fmt.Println(res) - 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 { - tt.CatchPetInfo(info.CatchMonsterOutboundInfo{}) - } - } else { - tt.CatchPetInfo(info.CatchMonsterOutboundInfo{}) - } - fmt.Println("ItemID 在范围内") - case faction.ItemID == 300001: - fmt.Println("ItemID 是 300001") - default: - fmt.Println("ItemID 不在指定范围内") - } - - if _, ok := BattleActionI[1].(*action.SelectSkillAction); !ok { - f.enterturn(nil, nil) - } else { - f.enterturn(BattleActionI[1].(*action.SelectSkillAction), nil) - } - - default: // 双方都是技能或者默认情况 - - f.enterturn(BattleActionI[0].(*action.SelectSkillAction), BattleActionI[1].(*action.SelectSkillAction)) - } - - } - -} - // 处理技能攻击逻辑 func (f *FightC) processSkillAttack(attacker, defender *input.Input, a *action.SelectSkillAction) { diff --git a/logic/service/fight/loop.go b/logic/service/fight/loop.go new file mode 100644 index 000000000..9da70f53c --- /dev/null +++ b/logic/service/fight/loop.go @@ -0,0 +1,196 @@ +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 +} diff --git a/logic/service/fight/playeraction.go b/logic/service/fight/playeraction.go index 96f839cc9..9c2f60d8d 100644 --- a/logic/service/fight/playeraction.go +++ b/logic/service/fight/playeraction.go @@ -113,6 +113,7 @@ func (f *FightC) Capture(c common.PlayerI, id uint32) { // 战斗准备 func (f *FightC) ReadyFight(c common.PlayerI) { + rett := info.FightStartOutboundInfo{} copier.Copy(&rett.Info1, &f.Info.OurPetList[0]) // 复制自己的信息 diff --git a/modules/blazing/model/player.go b/modules/blazing/model/player.go index 4825bb9a0..aea7ae032 100644 --- a/modules/blazing/model/player.go +++ b/modules/blazing/model/player.go @@ -12,7 +12,7 @@ const TableNamePlayerInfo = "player_info" type Player struct { *cool.Model PlayerID uint64 `gorm:"not null;index:idx_pet_by_player_id;comment:'所属玩家ID'" json:"player_id"` - Data string `gorm:"type:text;not null;comment:'全部数据'" json:"data"` + Data string `gorm:"type:jsonb;not null;comment:'全部数据'" json:"data"` } type PlayerEX struct { Player