--3组3v3异步竞技场,是单机关卡 -- 在战斗开始后,销毁当前组的6武将;在展示胜负结果时,创建下一组战斗的entity local EventSystem = require('Event/EventSystem') local Base = require("Battle/Logic/Level/LevelFunction/LevelFunction") local NineVsNineLevelFunction = class("NineVsNineLevelFunction",Base) local SkillMissileSystem = require"Battle/Logic/Entity/System/SkillMissileSystem" local Const_FirstStartFrame = 80 -- 80帧后开始自动战斗 local SlowMotionFrame = 80 -- 慢镜头时长4秒(80帧) local SlowMotionID = "heroMatch1v1" -- 慢镜头的id function NineVsNineLevelFunction:InitLevel() self.player1AwakenInfoDic = {} --己方觉醒信息字典,key为characterID,value为该character是否觉醒 self.player2AwakenInfoDic = {} --敌方觉醒信息字典,key为characterID,value为该character是否觉醒 Base.InitLevel(self) self.SwitchHeroInheritSA = false LevelPlayerManager.SetCanSwitchHeroByCommand(false) --本玩法禁止手动切将 self.isForbidPlayerInput = true --本玩法禁止玩家输入 self.roundResultList = {} -- 战斗记录 self.isShowingUI = false -- 正在战斗结果展示阶段 self.curRound = 1 self:SendBILog(true) end function NineVsNineLevelFunction:CreatePlayers(pos, dir) Base.CreatePlayers(self, pos, dir) self:CreateEnemyHeroes() --保存觉醒信息 因为每回合都会丢弃之前的entity,系统又要访问之前的entity信息,所以这里保存这些信息,不然拿不到 self:CollectAwakenInfo(LuaConst.STANDALONE_PLAYER_PlayID, self.player1AwakenInfoDic) self:CollectAwakenInfo(LuaConst.STANDALONE_ENEMYPLAYER1_PLAYID, self.player2AwakenInfoDic) self:SetAutoFight(false) -- 先不自动战斗,等UI关闭后再开始 end function NineVsNineLevelFunction:OnUpdate() Base.OnUpdate(self) if LogicUpdateManager._clientHandleFrame == Const_FirstStartFrame then -- 第一场开始自动战斗 self:SetAutoFight(true) end if self.slowMotionEndFrame then self:UpdateSlowMotion() end end -- 当场的某玩家所有武将死亡 function NineVsNineLevelFunction:OnPlayerAllHeroDead(entity) Base.OnPlayerAllHeroDead(self, entity) if self.isShowingUI == false then --刷新积分 self:RecordRoundResult(entity) self.isShowingUI = true self:EnterSlowMotion() end self.exp:SetCameraGray(false) -- 相机恢复正常色 end -- 记录战斗结果 function NineVsNineLevelFunction:RecordRoundResult(deadEntity) local result = {isWin = deadEntity._logicInitData.PlayerIDInRoom == LuaConst.STANDALONE_ENEMYPLAYER1_PLAYID, frame = LogicUpdateManager._clientHandleFrame} table.insert(self.roundResultList, result) self:SendBILog(false) end function NineVsNineLevelFunction:ShouldFinish() return self.curRound == 3 or (#self.roundResultList == 2 and self.roundResultList[1].isWin == self.roundResultList[2].isWin) end -- 收到系统信息进入下一场战斗 function NineVsNineLevelFunction:SwitchHeroStart() self.curRound = self.curRound + 1 self:BeginNextRound() self.isShowingUI = false self:SendBILog(true) end function NineVsNineLevelFunction:BeginNextRound() self:ClearBattleInfo(true) LevelPlayerManager.UseReserveArmy(LuaConst.STANDALONE_ENEMYPLAYER1_PLAYID, self.curRound) LevelPlayerManager.UseReserveArmy(LuaConst.STANDALONE_PLAYER_PlayID, self.curRound) self:CreatePlayers() self:SetAutoFight(true) EventSystem.Dispatch(EventID.NineVsNine_RoundStart, self.curRound) end function NineVsNineLevelFunction:CollectAwakenInfo(playerID, infoDic) --保存觉醒信息 因为每回合都会丢弃之前的entity,系统又要访问之前的entity信息,所以这里保存这些信息,不然拿不到 local entityList = LevelPlayerManager.GetPlayerEntitysByPlayerIDInRoom(playerID) if entityList then for _, entity in ipairs(entityList) do local armyData = LevelPlayerManager.GetPlayerArmyData(playerID, entity) infoDic[entity:GetCharacterID()] = armyData.mainHeroAwaken local adjutantEntity = entity.components.adjutant.AdjutantEntity if adjutantEntity then infoDic[adjutantEntity:GetCharacterID()] = armyData.viceHeroAwaken end end end end function NineVsNineLevelFunction:GetHeroIsAwaken(playerID, heroId) if playerID == LuaConst.STANDALONE_ENEMYPLAYER1_PLAYID then return self.player2AwakenInfoDic[heroId] else return self.player1AwakenInfoDic[heroId] end end --region roundEnd和结算慢镜头 -- 进入慢镜头 function NineVsNineLevelFunction:EnterSlowMotion() self.slowMotionEndFrame = LogicUpdateManager._clientHandleFrame + SlowMotionFrame -- 慢镜头结束的帧号 LevelItemManager.Global:DoAction(LuaConst.LevelActionType.Global_SlowMotion,SlowMotionID) logging.crit(LTAG.CRIT, "GWS : 9v9进入慢镜头,当前结束的round = ", self.curRound, "curFrame = ",LogicUpdateManager._clientHandleFrame, ",endFrame = ", self.slowMotionEndFrame) end -- 检测慢镜头结束 function NineVsNineLevelFunction:UpdateSlowMotion() if self.slowMotionEndFrame == LogicUpdateManager._clientHandleFrame then self.slowMotionEndFrame = nil self:SlowMotionFinish() end end -- 慢镜头结束 function NineVsNineLevelFunction:SlowMotionFinish() if self:ShouldFinish() then self:_LevelFinish() else self:_RoundEnd() end end --endregion roundEnd和结算慢镜头 --去结算 function NineVsNineLevelFunction:_RoundEnd() logging.crit(LTAG.CRIT, "GWS : 9v9慢镜头结束,当前结束的round = ", self.curRound, "curFrame = ",LogicUpdateManager._clientHandleFrame, ",endFrame = ", self.slowMotionEndFrame) EventSystem.Dispatch(EventID.NineVsNine_RoundOver, self.curRound, self.roundResultList[self.curRound].isWin) end --去结算 function NineVsNineLevelFunction:_LevelFinish() LevelManager.AddSummaryTime(LevelItemManager.Global:GetPassTime()) --这个玩法得自己设置一下,不然拿不到SummeryTime local winCount = 0 for i, info in ipairs(self.roundResultList) do if info.isWin then winCount = winCount + 1 end end if winCount >= 2 then LevelItemManager.Global:DoAction(LuaConst.LevelActionType.Global_LevelSucceed) else LevelItemManager.Global:DoAction(LuaConst.LevelActionType.Global_LevelFail) end end --region 创建entity --创建敌方玩家的英雄 function NineVsNineLevelFunction:CreateEnemyHeroes() local heroEntityTable = {} repeat local army = LevelPlayerManager.GetPlayerArmyByPlayerIDInRoom(LuaConst.STANDALONE_ENEMYPLAYER1_PLAYID) if not army then logging.error(LTAG.ERROR, "HYW : army nil Error @NineVsNineLevelFunction:CreateEnemyHeroes!!") break end local playerInfo = LevelPlayerManager.GetPlayerInfoByPlayerIDInRoom(LuaConst.STANDALONE_ENEMYPLAYER1_PLAYID) for i,v in ipairs(army) do local armyPos = LevelPlayerManager.GetHeroArmyPos(LuaConst.STANDALONE_ENEMYPLAYER1_PLAYID,v.HeroID) -- 前-中-后军 0-2-4 armyPos = armyPos / 2 + 1 local bornItem = self:GetBornItemByIndex(armyPos + 3) local pos = LogicRandom.GetRandomPointInLevelItem(nil, bornItem.ItemData, 8238236) local bornItemID = bornItem.LevelItemID EntityFactory.SetParams("BornItemID", bornItemID, "InitHP", v.HP, "Name", playerInfo.name) EntityFactory.SetParams("CampID", LuaConst.STANDALONE_ENEMY_CAMP) EntityFactory.SetParams("StratagemSkill", playerInfo.stratagemSkill) EntityFactory.SetType_ID(LuaConst.CharacterType.Hero, v.HeroID) EntityFactory.SetAttrTable_ID(v.Attr) EntityFactory.SetPos_Dir(pos, bornItem.ItemData.ItemDir) EntityFactory.SetSelf_Sync(false, false) EntityFactory.SetEffectBreak_Weapon(v.mainHeroBreakNums,v.isMagicWeaponActive,v.mainHeroWeaponLevels) EntityFactory.SetHorse_ID(v.horseID, v.horseAppearanceId) EntityFactory.SetPet_Info(v.petInfo.petId, v.petInfo.stage, v.petInfo.petName, v.petInfo.petSkill) EntityFactory.SetHeroAppearance_ID(v.heroAppearanceId) EntityFactory.SetWeaponAppearance_ID(v.weaponAppearanceId) EntityFactory.SetDyeAppearanceList(v.mainDyeCurPartList) EntityFactory.SetLightEffect_ID(v.lightEffectIds) EntityFactory.SetWeaponSoulInfo(v.weaponSoulInfo) EntityFactory.SetParams("PlayerID", LuaConst.STANDALONE_ENEMYPLAYER1_PLAYID) local entity = EntityFactory.DoCreatePlayerEntity() entity._logicInitData.OfficialPosition = playerInfo.officialPosition entity:SetGs(self:GetGsByArmyData(v.heroGs, v)) table.insert(heroEntityTable, entity) local adjutantID = v.AdjutantID if adjutantID and adjutantID > 0 then EntityFactory.SetType_ID(LuaConst.CharacterType.Adjutant, adjutantID) EntityFactory.SetAttrTable_ID(v.Attr) EntityFactory.SetEffectBreak_Weapon(v.viceHeroBreakNums,v.isViceMagicWeaponActive,v.viceHeroWeaponLevels) EntityFactory.SetHeroAppearance_ID(v.viceHeroAppearanceId) EntityFactory.SetWeaponAppearance_ID(v.viceWeaponAppearanceId) EntityFactory.SetDyeAppearanceList(v.viceDyeCurPartList) EntityFactory.DoCreateAdjutantEntity(entity) end end self:TryAddPlayerBuff(LuaConst.STANDALONE_ENEMYPLAYER1_PLAYID) LevelPlayerManager.SetPlayerEntityTable(heroEntityTable, LuaConst.STANDALONE_ENEMYPLAYER1_PLAYID) for i,entity in ipairs(heroEntityTable) do SystemManager.Active(entity) end until true end --endregion function NineVsNineLevelFunction:SetAutoFight(val) local heroEntityTable = LevelPlayerManager.GetPlayerEntitysByPlayerIDInRoom(LuaConst.STANDALONE_PLAYER_PlayID) for i,entity in ipairs(heroEntityTable) do if val then self:StartAutoFight(entity) else self:StopAutoFight(entity) end SystemManager.PausePetAttack(entity, not val) -- 宠物可否攻击 end heroEntityTable = LevelPlayerManager.GetPlayerEntitysByPlayerIDInRoom(LuaConst.STANDALONE_ENEMYPLAYER1_PLAYID) for i,entity in ipairs(heroEntityTable) do if val then self:StartAutoFight(entity) else self:StopAutoFight(entity) end SystemManager.PausePetAttack(entity, not val) -- 宠物可否攻击 end end --region 重写配置 function NineVsNineLevelFunction:ClearBattleInfo(clearMonster) -- 不用base if clearMonster then local normalCount = #LogicUpdateManager.EntityList_Normal for i = normalCount, 1, -1 do local entity = LogicUpdateManager.EntityList_Normal[i] SystemManager.DeadQuit(entity) --SystemManager.OnUnload(entity,true) end end --玩家 local heroCount = #LogicUpdateManager.EntityList_Sync for i = heroCount, 1, -1 do local entity = LogicUpdateManager.EntityList_Sync[i] SystemManager.DeadQuit(entity) end SkillMissileSystem.Clear() MissileManager.Clear() end function NineVsNineLevelFunction:OnPlayerOneHeroDead(entity) -- 不用base ,需要特殊的处理 local alldead,autoIndex = LevelPlayerManager.IsAllDead(entity) if alldead then self:OnPlayerAllHeroDead(entity) end end --armyData是LevelPlayerManager.GetPlayerArmyByPlayerIDInRoom返回的list里的元素 function NineVsNineLevelFunction:GetGsByArmyData(wholeArmyGs, armyData) return armyData.heroGs end function NineVsNineLevelFunction:ShouldShowVictoryPose() return false end function NineVsNineLevelFunction:IsMusouShowOpen() return false --不播无双小黑屋动画 end function NineVsNineLevelFunction:GetRobotAI(entity) return LuaConst.PveRobotAIID end --是否三军武将同时上场 function NineVsNineLevelFunction:IsAllHeroJoinBattle() return true end function NineVsNineLevelFunction:IsIndividualSa() return true end function NineVsNineLevelFunction:IsAutoUseMusou() return true end function NineVsNineLevelFunction:GetBornPosAndDirByArmyIndex(i, originBornPos, bornDir, heroID) local armyPos = LevelPlayerManager.GetHeroArmyPos(LuaConst.STANDALONE_PLAYER_PlayID, heroID) -- 前-中-后军 0-2-4 armyPos = armyPos / 2 + 1 local bornItem = self:GetBornItemByIndex(armyPos) return LogicRandom.GetRandomPointInLevelItem(nil, bornItem.ItemData, 8238236), bornItem.ItemData.ItemDir end --endregion --region 埋点 function NineVsNineLevelFunction:SendBILog(isStart) local myAllBattleList = LevelPlayerManager.GetPlayerReserveArmyInfo(LuaConst.STANDALONE_PLAYER_PlayID) local enemyAllBattleList = LevelPlayerManager.GetPlayerReserveArmyInfo(LuaConst.STANDALONE_ENEMYPLAYER1_PLAYID) local myBattleList = myAllBattleList["heroLineUpInfos" .. self.curRound] local enemyBattleList = enemyAllBattleList["heroLineUpInfos" .. self.curRound] local lineHeroID = {} for i,heroFightInfo in ipairs(myBattleList) do table.insert(lineHeroID, tostring(heroFightInfo.heroId)) table.insert(lineHeroID, tostring(heroFightInfo.ViceHeroId)) end local enemyHeroID = {} for i,heroFightInfo in ipairs(enemyBattleList) do table.insert(enemyHeroID, tostring(heroFightInfo.heroId)) table.insert(enemyHeroID, tostring(heroFightInfo.ViceHeroId)) end local myGsList = LevelPlayerManager.GetPlayerInfoByPlayerIDInRoom(LuaConst.STANDALONE_PLAYER_PlayID).fightScores local enemyGsList = LevelPlayerManager.GetPlayerInfoByPlayerIDInRoom(LuaConst.STANDALONE_ENEMYPLAYER1_PLAYID).fightScores local myHeroGS = myGsList[self.curRound] local enemyHeroGS = enemyGsList[self.curRound] local isWin = isStart and 0 or (self.roundResultList[self.curRound].isWin and 1 or 0) local btime = 0 if not isStart then local lastWinInfo = self.roundResultList[self.curRound-1] local lastOverFrame = lastWinInfo and lastWinInfo.frame or 0 btime = math.floor( (LogicUpdateManager._clientHandleFrame - lastOverFrame) * LuaConst.TimeSpan ) end EventSystem.Dispatch(EventID.BI_LevelHigh,BIManager.BIType.OffLine1v1, self.curRound, 1, lineHeroID, myHeroGS, enemyHeroID ,enemyHeroGS,isStart,0, btime ,isWin) end --endregion 埋点 return NineVsNineLevelFunction