local Infrast = require("Infrast/Infrast") local EventSystem = require('Event/EventSystem') local Base = require("Battle/Logic/Level/LevelFunction/SyncLevelFunction") local SyncTeamPVELevelFunction = class("SyncTeamPVELevelFunction",Base) function SyncTeamPVELevelFunction:InitLevel() self.DamageDic = {}--key是playerID,value是伤害值 self.RecordPlayerEntitys = {}--记录玩家们开始时的entity顺序 self.HeroArmyList = nil self.showVictoryPoseFrame = nil self.sendResultFrame = nil --以所有玩家的最低等级作为自适应参数 self.formulaAdaptiveVar = 99999 for k,v in pairs(LevelPlayerManager.PlayersArmyTable) do --pairs safe if v.playerInfo.teamLevel < self.formulaAdaptiveVar then self.formulaAdaptiveVar = v.playerInfo.teamLevel end end if not LevelManager.IsSyncRebelStrike() then --以所有玩家的最低战力作为服务器战力 self:SetServerGsByLowestPlayerGs() --else --围剿叛军要求不用最低战力,服务器会发,这里 do nothing end Base.InitLevel(self) end function SyncTeamPVELevelFunction:InitLevelDifficulty() if LevelManager.IsSyncTeamDifficult() then local data = DataSheetManager.MultiplayerDungeon:GetDataByID(LevelManager.GetCurLevelID()) if data then self.LevelGs = data.Power self.SubjugateDataPVEID = data.SubjugateDataPVE end end end --获取公式自适应变量,基础规则是以主玩家的等级为变量来自适应。仅可用于单机副本,联机副本需要重写 function SyncTeamPVELevelFunction:GetFormulaAdaptiveVariable() return self.formulaAdaptiveVar end function SyncTeamPVELevelFunction:CreatePlayers() --不调用Base --LevelPlayerManager.MyPlayerIDInRoom --自己的playerID local heroArmyList = {} local heroArmyDataSet for k,v in pairs(LevelPlayerManager.PlayersArmyTable) do --pairs safe,下面会排序 heroArmyDataSet = {army = v,playerID = k} table.insert(heroArmyList,heroArmyDataSet) end table.sort(heroArmyList,function(a,b) return a.playerID < b.playerID end) self.HeroArmyList = heroArmyList for i,heroArmyDataSet in ipairs(heroArmyList) do self:CreatePlayerEntitys(heroArmyDataSet.playerID,heroArmyDataSet.army,i) --check↓ 稳定后可以删除 if heroArmyDataSet.playerID ~= i then logging.error(LTAG.ERROR, "HYW : playerID值有问题,预期是从1开始递增,1、2、3这样的。但是实际上不是。需要联系服务器解决") end --check↑ self.DamageDic[heroArmyDataSet.playerID] = FP.newV1(0) local entitys = LevelPlayerManager.GetPlayerEntitysByPlayerIDInRoom(heroArmyDataSet.playerID) self.RecordPlayerEntitys[heroArmyDataSet.playerID] = {} for _ ,entity in ipairs(entitys) do table.insert(self.RecordPlayerEntitys[heroArmyDataSet.playerID] ,entity) end self:TryCreatePlayerStatistic(heroArmyDataSet.playerID) self:TryAddPlayerBuff(heroArmyDataSet.playerID) end self:InitEntityByClientIntermediateParamsBytes() EventSystem.Dispatch(EventID.Battle_SyncPVE_CreatePlayerFinished) end function SyncTeamPVELevelFunction:CreatePlayerEntitys(playerIDInRoom ,playerHeroArmy,index) local heroEntityTable = {} local army = playerHeroArmy.army local playerInfo = playerHeroArmy.playerInfo local isPlayerSelf = playerInfo.playerID == LevelPlayerManager.MyPlayerIDInRoom local gs = 0 for i,v in ipairs(army) do gs = gs + (v.heroGs or 0) end for i,heroArmyData in ipairs(army) do local entity = self:CreatePlayerEntity(playerInfo,heroArmyData,isPlayerSelf,index) entity:SetGs(gs) table.insert(heroEntityTable,entity) end LevelPlayerManager.SetPlayerEntityTable(heroEntityTable ,playerIDInRoom) local firstEntity = heroEntityTable[1] if firstEntity == nil then logging.error(LTAG.ERROR, "HYW : firstEntity为空Error! #army : " .. tostring(#army) .. " 是否是机器人:" .. tostring(self:IsRobotPlayerInfo(playerInfo)) .. " acid : " .. tostring(playerInfo.acid)) end local levelInfo = BattleDataGetter.GetLevelInfoData() if levelInfo.AutoBattle then -- 策划要求根据levelInfo的配置来决定是否开启自动战斗 2021年7月15日 SystemManager.StartAutoFight(firstEntity)-- ×策划要求默认开启自动战斗(已撤销) --2021年1月11日(策划已撤销这个需求 2021年7月15日) end if playerIDInRoom == LevelPlayerManager.MyPlayerIDInRoom then LevelPlayerManager.SetCurEntity(firstEntity ,false , LevelPlayerManager.GetPlayerSetting(playerIDInRoom ,LuaConst.BattleSettingEnum.AutoRide)) --LevelPlayerManager.MainEntityCampID = firstEntity:GetCampID() gws 多余了,在initfuben的时候统计army时就统计了 else if self:IsRobotPlayerInfo(playerInfo) then for i,v in ipairs(heroEntityTable) do table.insert(self.RobotList,v) end end SystemManager.Active(firstEntity,LevelPlayerManager.GetPlayerSetting(playerIDInRoom ,LuaConst.BattleSettingEnum.AutoRide))-- 可以不用设置,因为后续在kcp通知battlebegin的时候会把所有玩家的第一个entity都显示出来 end EventSystem.Dispatch(EventID.Battle_SyncPVE_CreatePlayerFinished) end function SyncTeamPVELevelFunction:IsRobotPlayerInfo(playerInfo) if playerInfo.fighterType == LuaConst.BattleMemberType.Robot_Hero or string.find(playerInfo.acid, "Robot") then return true end return false end function SyncTeamPVELevelFunction:IsRobotEntity(entity) for i,v in ipairs(self.RobotList) do if v == entity then return true end end return false end function SyncTeamPVELevelFunction:BeginLevel() Base.BeginLevel(self) end function SyncTeamPVELevelFunction:GetRobotAI(entity) return LuaConst.PveRobotAIID --现在pveRobotAIID可以同时支持组队和单机pve副本 end function SyncTeamPVELevelFunction:GetDamageNo1PlayerID() local biggest = nil local playerID = nil for k,v in pairs(self.DamageDic) do --pairs safe if biggest == nil or v > biggest then biggest = v playerID = k end end return playerID end function SyncTeamPVELevelFunction:SwitchAutoFight(entity) Base.SwitchAutoFight(self,entity) entity.components.target:SetForceTarget(nil) end -- ↓ 提到基类了,因为其他玩法也要用 ↓ -- function SyncTeamPVELevelFunction:QuitRoom(entity) -- if entity == LogicUpdateManager._curEntity then -- if not LogicUpdateManager.IsReplayOrServerCheck then --客户端重播或服务器校验的话, -- EventSystem.Dispatch(EventID.Level_SendRoleLeaveFuben) -- self:StopLevel() -- end -- else -- self:OnOffLine(entity) -- end -- end -- ↑↑↑↑↑↑↑↑↑↑↑↑↑ function SyncTeamPVELevelFunction:OnUpdate() Base.OnUpdate(self) if self.showVictoryPoseFrame == LogicUpdateManager._clientHandleFrame then self:ShowVictoryPose() end if self.sendResultFrame == LogicUpdateManager._clientHandleFrame then self:SendResult(true) end end function SyncTeamPVELevelFunction:GetVictoryPoseEntity() return LevelPlayerManager.GetPlayerEntitysByPlayerIDInRoom(self:GetDamageNo1PlayerID())[1] or LogicUpdateManager._curEntity end function SyncTeamPVELevelFunction:ShowVictoryPose() for playerID,_ in pairs(LevelPlayerManager.PlayersArmyTable) do --pairs safe LevelPlayerManager.GetPlayerEntitysByPlayerIDInRoom(playerID)[1].ExpEntity:SetModelUIVisible(false) end Base.ShowVictoryPose(self) EventSystem.Dispatch(EventID.TeamPVEShowVictoryPose) end function SyncTeamPVELevelFunction:OnHpChange(entity,caster,delta,op) if op == "sub" and delta < FP.Const.Zero then if caster and caster:IsActive() then if entity:IsMonster() then local sourceEntity = caster:GetMasterEntity() or caster if sourceEntity._logicInitData.PlayerIDInRoom > 0 then self.DamageDic[sourceEntity._logicInitData.PlayerIDInRoom]:Sub(delta) end --不需要Dispatch出去 end end end end function SyncTeamPVELevelFunction:OnPlayerAllHeroDead(entity) if not LevelManager.IsSyncTeamPVENotRevive() then --不调用Base --目前策划没有需求,所以所有entity死亡都直接复活,不走cmd --以后如果加复活按钮,到时候hero得用cmd复活,robot走一个默认延迟后复活 --if self:IsRobotEntity(entity) then local heroEntitys = LevelPlayerManager.GetPlayerEntitysByPlayerIDInRoom(entity._logicInitData.PlayerIDInRoom) if heroEntitys then for i,heroEntity in ipairs(heroEntitys) do SystemManager.OnRevive(heroEntity,true)-- 需要在出生点复活 end local firstEntity = heroEntitys[1] if firstEntity then local ctrlParam = RuntimeDataManager.New_BuffCtrl() ctrlParam.ForceDuration:Reset(1) firstEntity.components.skillBase.NeedReleaseGetInSkill = true SystemManager.AddBuff(firstEntity,500000, entity, nil, ctrlParam) --ugly 复活后强行加一个无敌buff,防止被眩晕打断入场技 --临时代码,之后会改掉 end else logging.error(LTAG.ERROR, "GWS:组队副本中,死亡后复活 ,发现没有这个play的所有entity ,playerid =" , entity._logicInitData.PlayerIDInRoom) end -- elseif entity:IsPlayerSelf() then -- LuaInputManager.SetSpecialCommand(specialCommand) -- end if entity:IsPlayerSelf() then EventSystem.Dispatch(EventID.UI_MainShowTips, UIUtils.GetLocalizedTxt(Const_IDS.IDS_TeamDungeon1_DeathAndRelive)) end else -- do nothing --多人难度副本、悬赏等不能复活 end end function SyncTeamPVELevelFunction:OnReconnect(playerID) --Reconnect的时候只会有1个Entity,所以这里要GetPlayerEntitysByPlayerIDInRoom local entities = LevelPlayerManager.GetPlayerEntitysByPlayerIDInRoom(playerID) for i,_entity in ipairs(entities) do for i,v in ipairs(self.RobotList) do if v == _entity then SystemManager.StopAutoFight(_entity) table.remove(self.RobotList,i) break end end end end function SyncTeamPVELevelFunction:OnLevelSucceed(withShow) if LevelManager.HasNextLevel() then self.sendResultFrame = LogicUpdateManager._clientHandleFrame + 40 else self.showVictoryPoseFrame = LogicUpdateManager._clientHandleFrame + 40 self.sendResultFrame = LogicUpdateManager._clientHandleFrame + 80 end end function SyncTeamPVELevelFunction:SendResult(isWin) local team_pve_pb = require 'Proto/team_pve_pb' local msg = team_pve_pb.C2GUploadTeamPVEResult() msg.isWin = isWin for playerID,damageFP in pairs(self.DamageDic) do --pairs safe local fighterTeamPVEResult = team_pve_pb.FighterTeamPVEResult() fighterTeamPVEResult.playerID = playerID fighterTeamPVEResult.damage = FP.tonumberV1(self.DamageDic[fighterTeamPVEResult.playerID]) fighterTeamPVEResult.playerName = LevelPlayerManager.GetPlayerName(playerID) fighterTeamPVEResult.playerACID = LevelPlayerManager.GetPlayerInfoByPlayerIDInRoom(playerID).acid --fighterTeamPVEResult.serverID 这个不传,因为战斗拿不到 local biHeroHP = "" for i,entity in ipairs(self.RecordPlayerEntitys[playerID]) do biHeroHP = biHeroHP ..tostring(FP.tonumberV1(entity.components.attr:HitPointPercents())) .. "|" end fighterTeamPVEResult.biHeroHP = biHeroHP table.insert(msg.allFighterRes,fighterTeamPVEResult) end msg.clientIntermediateParams = self:GetClientIntermediateParamsBytes() --msg.checkInfo = self:GetBattleResultCheckInfo(msg.clientIntermediateParams) --checkInfo不再附加msg.clientIntermediateParams,因为msg.clientIntermediateParams已经被改为了byte数组,这样附加的话proto扛不住,因为proto不支持UTF-8 msg.checkInfo = self:GetBattleResultCheckInfo() --new checkInfo不再附加msg.clientIntermediateParams msg.passTime = self:GetPassTimeOfPrevious() + BattleDataGetter.GetSummaryTime() if USE_LUA_STANDALONE then BattleSimulator.SetCheckResult(msg.checkInfo , msg:SerializeToString()) end if LogicUpdateManager.IsReplayOrServerCheck then -- 客户端重播或服务器校验的话,不要发送TCP logging.log(LTAG.LOG, "[GWS]SyncTeamPVE BattleCheckStr = :",msg.checkInfo) self:StopLevel() BattleSimulator.EndPlay() else NetManager.SendMessage(MessageEnums.MessageC2GUploadTeamPVEResult,msg) self:StopLevel() end end --↓↓↓↓↓↓↓↓↓↓↓中间关参数处理↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ function SyncTeamPVELevelFunction:GetClientIntermediateParamsBytes() --不调用Base if LevelManager.HasNextLevel() then if self.HeroArmyList then local info = {} --把每个玩家的血量、无双值、传送点等信息按照顺序拼成字符串传给服务器。服务器会在下一关转发回来 for i,heroArmyDataSet in ipairs(self.HeroArmyList) do self:FillIntermediateInfoOfPlayer(heroArmyDataSet.playerID, info) end --附上每一小关的通关耗时 self:FillTimeCostInfo(info) return Infrast.EncodeToBytes(info) else logging.error(LTAG.ERROR, "HYW : 致命错误!self.HeroArmyList 为空! LevelID : ", LevelManager.GetCurLevelID()) end end return "" end function SyncTeamPVELevelFunction:GetBattleResultCheckInfo(appendInfo) -- old↓ 提了一个方法到基类去了,直接使用基类提供的方法 -- local result = "" -- for i,entity in ipairs(LogicUpdateManager.EntityList_Sync) do -- local moveComp = entity.components.move -- local str = string.format("%d,f:%d, px:%d,pz:%d,fx:%d,fz:%d,Anim:%s,hp:%d|" -- , entity._logicInitData.EntityID,BattleDataGetter.GetCurFrameIndex() ,moveComp.LogicPos.x[1], moveComp.LogicPos.z[1],moveComp.LogicRotateDir.x[1], moveComp.LogicRotateDir.z[1],tostring(entity.components.anim.CurAnimID),entity.components.attr.hp[1]) -- result = result .. str -- end -- old↑ -- new↓ 直接使用基类提供的方法 local result = self:GetBattleResultCheckStr() -- new 直接使用基类提供的方法 -- new↑ if appendInfo then result = result .. appendInfo end return result end --↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ -- function SyncTeamPVELevelFunction:ShowVictoryPose() -- --隐藏血条 -- for playerID,_ in pairs(LevelPlayerManager.PlayersArmyTable) do --pairs safe -- LevelPlayerManager.GetPlayerEntitysByPlayerIDInRoom(playerID)[1].ExpEntity:SetModelUIVisible(false) -- end -- local entity = LevelPlayerManager.GetPlayerEntitysByPlayerIDInRoom(self:GetDamageNo1PlayerID())[1] or LogicUpdateManager._curEntity -- if not LevelManager.CheckCurLevelType(LuaConst.LevelType.Planes) then -- --播放胜利动画 -- ExpSystemManager.StopAllPsCamera() -- local victoryID = DataSheetManager.ConstData:GetDataByID("ScenesVictoryShowPoint").IntValue -- local itemData = LevelItemManager.GetItemByID(victoryID).ItemData -- local heroData = DataSheetManager.HeroNum:GetDataByID(entity._logicInitData.CharacterID) -- local winEffect = "Public/Win/"..heroData.VictoryPose -- SystemManager.OnWinBattle(entity, itemData.ItemPos, itemData.ItemDir,winEffect) -- end -- end function SyncTeamPVELevelFunction:OnLevelFail() self:SendResult(false) end return SyncTeamPVELevelFunction