local XUiPanelRoleModel = require("XUi/XUiCharacter/XUiPanelRoleModel") local XPlanetRunningExploreEntity = require("XUi/XUiPlanet/Explore/XPlanetRunningExploreEntity") local XPlanetRunningComponentAttr = require("XUi/XUiPlanet/Explore/Component/XPlanetRunningComponentAttr") local XPlanetRunningComponentMove = require("XUi/XUiPlanet/Explore/Component/XPlanetRunningComponentMove") local XPlanetRunningComponentLeaderMove = require("XUi/XUiPlanet/Explore/Component/XPlanetRunningComponentLeaderMove") local XPlanetRunningComponentCamp = require("XUi/XUiPlanet/Explore/Component/XPlanetRunningComponentCamp") local XPlanetRunningComponentData = require("XUi/XUiPlanet/Explore/Component/XPlanetRunningComponentData") local XPlanetRunningComponentRotation = require("XUi/XUiPlanet/Explore/Component/XPlanetRunningComponentRotation") local XPlanetRunningSystemMove = require("XUi/XUiPlanet/Explore/System/XPlanetRunningSystemMove") local XPlanetRunningSystemRotate = require("XUi/XUiPlanet/Explore/System/XPlanetRunningSystemRotate") local XPlanetRunningSystemLeaderMove = require("XUi/XUiPlanet/Explore/System/XPlanetRunningSystemLeaderMove") local XPlanetBubbleManager = require("XUi/XUiPlanet/Explore/Bubble/XPlanetBubbleManager") local XPlanetRunningSystemAnimation = require("XUi/XUiPlanet/Explore/System/XPlanetRunningSystemAnimation") local XPlanetRunningComponentAnimation = require("XUi/XUiPlanet/Explore/Component/XPlanetRunningComponentAnimation") local XPlanetMovieManager = require("XUi/XUiPlanet/Explore/Movie/XPlanetMovieManager") local CAMP = XPlanetExploreConfigs.CAMP local EXPLORE_STATUS = { NONE = 0, START = 1, WALK = 2, END = 3, PAUSE = 4, } local TIME_SCALE = XPlanetExploreConfigs.TIME_SCALE ---@class XPlanetRunningExplore local XPlanetRunningExplore = XClass(nil, "XPlanetRunningExplore") function XPlanetRunningExplore:Ctor() ---@type XPlanetMainScene|XPlanetStageScene self.Scene = false ---@type XPlanetRunningSystemMove self.SystemMove = XPlanetRunningSystemMove.New() ---@type XPlanetRunningSystemRotate self.SystemRotate = XPlanetRunningSystemRotate.New() ---@type XPlanetRunningSystemLeaderMove self.SystemLeaderMove = XPlanetRunningSystemLeaderMove.New() ---@type XPlanetRunningSystemAnimation self.SystemAnimation = XPlanetRunningSystemAnimation.New() ---@type XPlanetMovieManager self.MovieManager = XPlanetMovieManager.New(self) ---@type XPlanetRunningExploreEntity[] self.Entities = {} ---@type XPlanetRunningExploreEntity[] self._DictEntities = {} self.LeaderId = false self._Data = { CharacterData = {}, MonsterData = {} } self._RootUi = nil self._RootCharacter = false self._InStart = false -- 初始化锁 ---@type XUiPanelRoleModel[] self._Model = {} self._Status = EXPLORE_STATUS.NONE self._IncId = 0 self._IndexCaptain = 1 self._Vector3Zero = Vector3() self._SkipFight = false self._PauseReason = XPlanetExploreConfigs.PAUSE_REASON.NONE self._TimeScale = TIME_SCALE.NORMAL self._GridInBuildingRange = {} ---@type XPlanetRunningDataDelayCreateModel[] self._ModelDelay2Create = {} self._GapModelDelay = 10 self._DurationModelDelay = 0 end function XPlanetRunningExplore:SetRootUi(rootUi) self._RootUi = rootUi end function XPlanetRunningExplore:SetBubbleManager() if not self._RootUi then return end ---@type XPlanetBubbleManager self.PlanetBubbleManager = XPlanetBubbleManager.New(self, self._RootUi, self._RootUi.BubbleRoot, self.Scene:GetCamera()) end function XPlanetRunningExplore:IsRunning() return self._Status == EXPLORE_STATUS.WALK or self._Status == EXPLORE_STATUS.START end function XPlanetRunningExplore:_GetUid() self._IncId = self._IncId + 1 return self._IncId end function XPlanetRunningExplore:StartSync() self._Status = EXPLORE_STATUS.START self:Update(0) end function XPlanetRunningExplore:Pause(reason, notSyncPosition) if reason then self._PauseReason = self._PauseReason | reason end self._Status = EXPLORE_STATUS.PAUSE XEventManager.DispatchEvent(XEventId.EVENT_PLANET_UPDATE_PAUSE) self.SystemAnimation:LetCharacterAction(self, XPlanetExploreConfigs.ACTION.STAND) if reason == XPlanetExploreConfigs.PAUSE_REASON.RESULT then return end if notSyncPosition then return end -- 在暂停时, 可能进行建筑或退出操作, 影响角色属性和存档, 需要同步坐标 self.SystemLeaderMove:SyncPosition(self) end function XPlanetRunningExplore:Resume(reason) if reason then self._PauseReason = self._PauseReason & (~reason) end if self._PauseReason ~= XPlanetExploreConfigs.PAUSE_REASON.NONE then return end if self._Status == EXPLORE_STATUS.PAUSE then self._Status = EXPLORE_STATUS.WALK XEventManager.DispatchEvent(XEventId.EVENT_PLANET_UPDATE_PAUSE) end self.SystemAnimation:LetCharacterAction(self, XPlanetExploreConfigs.ACTION.WALK) end function XPlanetRunningExplore:IsPauseNotByPlayer() return self._PauseReason ~= XPlanetExploreConfigs.PAUSE_REASON.PLAYER end function XPlanetRunningExplore:IsPause(reason) if reason then return self._PauseReason & reason ~= XPlanetExploreConfigs.PAUSE_REASON.NONE end return self._PauseReason ~= XPlanetExploreConfigs.PAUSE_REASON.NONE end function XPlanetRunningExplore:SetData(data) self._Data = data end function XPlanetRunningExplore:UpdateDataBoss(data) if not data then local stageData = XDataCenter.PlanetManager.GetStageData() data = stageData:GetMonsterData() end self._Data.MonsterData = data end function XPlanetRunningExplore:UpdateDataCharacter(data) if not data then local stageData = XDataCenter.PlanetManager.GetStageData() data = stageData:GetCharacterData() end self._Data.CharacterData = data end function XPlanetRunningExplore:SetScene(scene) self.Scene = scene end function XPlanetRunningExplore:Update(deltaTime) deltaTime = deltaTime * self:GetTimeScale() self:UpdateModelDelayCreate() if self._Status == EXPLORE_STATUS.START then self._Status = EXPLORE_STATUS.WALK self._InStart = true self:CreateLeader() self:InitRootModel() self:UpdateCharacters() self:UpdateBoss() self:HideFollowers() self.SystemAnimation:Update(self) -- 入场剧情播放 self:CheckAndPlayMovie() self._InStart = false return end if self._Status == EXPLORE_STATUS.WALK then self.SystemLeaderMove:Update(self, deltaTime) self.SystemRotate:Update(self, deltaTime) self.SystemAnimation:Update(self) return end if self._Status == EXPLORE_STATUS.PAUSE then self.SystemAnimation:Update(self) -- 暂停时也要更新动作 return end end ---@return XPlanetRunningExploreEntity function XPlanetRunningExplore:GetEntity(entityId) return self._DictEntities[entityId] end function XPlanetRunningExplore:GetModel(entityId) return self._Model[entityId] end function XPlanetRunningExplore:UpdateCharacters(characterDataList) -- 创建玩家角色 characterDataList = characterDataList or self._Data.CharacterData local dict = {} for i = 1, #characterDataList do local data = characterDataList[i] local characterId = data.Id dict[characterId] = data end for i = #self.Entities, 1, -1 do local entity = self.Entities[i] if entity.Camp.CampType == CAMP.PLAYER and entity.Data then local characterId = entity.Data.IdFromConfig if not dict[characterId] then self:RemoveEntity(entity, i) dict[characterId] = nil end end end for characterId, data in pairs(dict) do local entity = self:FindCharacter(characterId) if data then if not entity then entity = self:CreateCharacter(data) else self:UpdateCharacterAttr(entity, data) end self:UpdateModel(entity) end end -- 设置队长 for i = 1, #characterDataList do local data = characterDataList[i] if data.Life > 0 then self:SetCaptainByCharacterId(data.Id) break end end XEventManager.DispatchEvent(XEventId.EVENT_PLANET_UPDATE_CHARACTER_ENTITY) end function XPlanetRunningExplore:CreateMovieEntity(characterId) ---@type XPlanetRunningExploreEntity local entity = XPlanetRunningExploreEntity.New() entity.Id = self:_GetUid() entity.Data = XPlanetRunningComponentData.New() entity.Data.IdFromConfig = characterId local modelName = nil if XPlanetCharacterConfigs.CheckHasCharacter(characterId) then modelName = XPlanetCharacterConfigs.GetCharacterModel(characterId) else modelName = XPlanetStageConfigs.GetBossModel(characterId) end entity.Data.ModelName = modelName -- entity.Attr = XPlanetRunningComponentAttr.New() entity.Attr.Life = 1 -- camp entity.Camp = XPlanetRunningComponentCamp.New() entity.Camp.CampType = CAMP.MOVIE -- entity.Move = entity.Move or XPlanetRunningComponentMove.New() entity.Rotation = XPlanetRunningComponentRotation.New() entity.Animation = XPlanetRunningComponentAnimation.New() entity.Animation.Action = XPlanetExploreConfigs.ACTION.STAND self:AddEntity(entity) self:UpdateModel(entity) return entity end function XPlanetRunningExplore:CreateCharacter(characterData) ---@type XPlanetRunningExploreEntity local entity = XPlanetRunningExploreEntity.New() entity.Id = self:_GetUid() entity.Data = XPlanetRunningComponentData.New() entity.Data.IdFromConfig = characterData.Id -- 属性 属性都要动态计算 entity.Attr = XPlanetRunningComponentAttr.New() self:UpdateCharacterAttr(entity, characterData) -- 移动 entity.Move = XPlanetRunningComponentMove.New() entity.Move.Status = XPlanetExploreConfigs.MOVE_STATUS.START -- 起点 local stageData = XDataCenter.PlanetManager.GetStageData() local gridId = stageData:GetGridId() local tileId = self.Scene:CheckIsTalentPlanet() and self.Scene:GetRoadMapStartPoint() or gridId self:UpdatePositionCurrent(entity, tileId) -- camp entity.Camp = XPlanetRunningComponentCamp.New() entity.Camp.CampType = CAMP.PLAYER -- rotation entity.Rotation = XPlanetRunningComponentRotation.New() -- animation entity.Animation = XPlanetRunningComponentAnimation.New() self:AddEntity(entity) return entity end ---@param entity XPlanetRunningExploreEntity function XPlanetRunningExplore:CreateModel(entity, delay) if self:GetModel(entity.Id) then return end -- boss不能重叠多个模型 if entity.Camp.CampType == CAMP.BOSS then if self:IsBossModelOnGrid(entity.Move.TileIdCurrent) then return end end local rootCharacter = self._RootCharacter local modelName if not entity then return end if not entity.Data then return end local idFromConfig = entity.Data.IdFromConfig if entity.Camp.CampType == CAMP.PLAYER then modelName = XPlanetCharacterConfigs.GetCharacterModel(idFromConfig) elseif entity.Camp.CampType == CAMP.BOSS then modelName = XPlanetStageConfigs.GetBossModel(idFromConfig) elseif entity.Camp.CampType == CAMP.MOVIE then modelName = entity.Data.ModelName end if modelName then local nodeCharacter = CS.UnityEngine.GameObject("Role") nodeCharacter.transform:SetParent(rootCharacter.transform, false) nodeCharacter.gameObject:SetLayerRecursively(CS.UnityEngine.LayerMask.NameToLayer(HomeSceneLayerMask.HomeCharacter)) ---@type XUiPanelRoleModel local panelModel = XUiPanelRoleModel.New(nodeCharacter) local entityId = entity.Id self._Model[entityId] = panelModel if delay then ---@class XPlanetRunningDataDelayCreateModel local dataDelay2Create = { EntityId = entity.Id, ModelName = modelName } self._ModelDelay2Create[#self._ModelDelay2Create + 1] = (dataDelay2Create) else self:LoadModel(entity, panelModel, modelName) end local position = entity.Move.PositionCurrent if position then panelModel:SetLocalPosition(position) end -- 初始化时, 更新坐标和旋转 self:UpdateTransform(entity) end end ---@param entity XPlanetRunningExploreEntity ---@param panelModel XUiPanelRoleModel function XPlanetRunningExplore:LoadModel(entity, panelModel, modelName, updateTransform) panelModel:UpdateRoleModel(modelName, nil, nil, function(model) self:OnModelCreate(entity, panelModel, updateTransform) end, false, true) end ---@param entity XPlanetRunningExploreEntity ---@param panelModel XUiPanelRoleModel function XPlanetRunningExplore:OnModelCreate(entity, panelModel, updateTransform) if self.PlanetBubbleManager then self.PlanetBubbleManager:UpdateFollowTransform(entity) end -- 先关掉根节点动画 panelModel:CloseRootMotion(panelModel) local scale = 1.5 panelModel:GetTransform().localScale = CS.UnityEngine.Vector3(scale, scale, scale) local componentXInput = XUiHelper.TryGetComponent(panelModel:GetTransform(), "", "XGoInputHandler") if componentXInput then componentXInput.enabled = false end if updateTransform then self:UpdateTransform(entity) end --非Boss出生时播放特效 if entity.Camp.CampType ~= CAMP.BOSS or not XPlanetStageConfigs.IsSpecialBoss(entity.Data.IdFromConfig) then self:PlayBornEffect(entity) end -- Boss出现 if self._Status ~= EXPLORE_STATUS.START then if entity.Camp.CampType == CAMP.BOSS and XPlanetStageConfigs.IsSpecialBoss(entity.Data.IdFromConfig) and not self._InStart then local model = self:GetModel(entity.Id) if model and model:GetTransform() then model:HideRoleModel() XLuaUiManager.SafeClose("UiPlanetDetail02") XEventManager.DispatchEvent(XEventId.EVENT_PLANET_HIDE_EXPLORE_UI) XDataCenter.PlanetExploreManager.OpenUiPlanetEncounter(function() XEventManager.DispatchEvent(XEventId.EVENT_PLANET_ON_BOSS_MODEL_CREATE, entity.Id) end, XPlanetConfigs.TipType.BossBorn) end end end end function XPlanetRunningExplore:FindBoss(bossId) for _, entity in pairs(self.Entities) do if entity.Camp.CampType == CAMP.BOSS and entity.Data.IdFromConfig == bossId then return entity end end return false end function XPlanetRunningExplore:FindCharacter(characterId) for i = 1, #self.Entities do local entity = self.Entities[i] if entity.Camp.CampType == CAMP.PLAYER and entity.Data.IdFromConfig == characterId then return entity, i end end return false end function XPlanetRunningExplore:FindBossByIdFromServer(idFromServer) for _, entity in pairs(self.Entities) do if entity.Camp.CampType == CAMP.BOSS and entity.Data.IdFromServer == idFromServer then return entity end end return false end function XPlanetRunningExplore:FindEntityByTransform(transform) for entityId, model in pairs(self._Model) do if model and model:GetTransform() == transform then return self:GetEntity(entityId) end end return false end -- 创建boss function XPlanetRunningExplore:UpdateBoss(data) local bossList = data or self._Data.MonsterData local dict = {} for i = 1, #bossList do local bossData = bossList[i] local idFromServer = bossData.Id local count = bossData.Count or 1 ---@type XPlanetRunningExploreEntity local entity = self:FindBossByIdFromServer(idFromServer) if not entity then entity = XPlanetRunningExploreEntity.New() entity.Data = entity.Data or XPlanetRunningComponentData.New() entity.Id = self:_GetUid() self:AddEntity(entity) end dict[entity.Id] = true entity.Data.IdFromConfig = bossData.CfgId entity.Data.IdFromServer = idFromServer -- 属性 属性都要动态计算 客户端取不到了 entity.Attr = entity.Attr or XPlanetRunningComponentAttr.New() entity.Attr.Attack = 0 entity.Attr.MaxLife = bossData.MaxLife or 1 entity.Attr.Defense = 0 entity.Attr.Life = bossData.Life or 1 entity.Attr.CriticalPercent = 0 entity.Attr.CriticalDamageAdded = 0 entity.Attr.Speed = 0 entity.Data.Amount = count -- 移动 entity.Move = entity.Move or XPlanetRunningComponentMove.New() entity.Move.Status = XPlanetExploreConfigs.MOVE_STATUS.START -- 起点 local tileId = bossData.NodeId self:UpdatePositionCurrent(entity, tileId) entity.Camp = entity.Camp or XPlanetRunningComponentCamp.New() entity.Camp.CampType = CAMP.BOSS entity.Rotation = XPlanetRunningComponentRotation.New() -- animation entity.Animation = XPlanetRunningComponentAnimation.New() end for i = #self.Entities, 1, -1 do local entity = self.Entities[i] if entity.Camp.CampType == CAMP.BOSS then if not dict[entity.Id] then self:RemoveEntity(entity, i) else self:UpdateModel(entity, true) end end end self:UpdateBossBubbleAmount() XEventManager.DispatchEvent(XEventId.EVENT_PLANET_UPDATE_BOSS_ENTITY) self:SortModelDelay() end ---@param entity XPlanetRunningExploreEntity function XPlanetRunningExplore:RemoveEntity(entity, index) self:RemoveModel(entity) if not index then for i = 1, #self.Entities do if self.Entities[i] == entity then index = i break end end end if index then table.remove(self.Entities, index) end if entity then self._DictEntities[entity.Id] = nil end end ---@param entity XPlanetRunningExploreEntity function XPlanetRunningExplore:RemoveModel(entity) local entityId = entity.Id local model = self:GetModel(entityId) self:StopBubbleText(entity) self:StopBubble(entity) if model then model:RemoveRoleModelPool() self._Model[entityId] = nil end end function XPlanetRunningExplore:FindBossOnGrid(gridId) for i = 1, #self.Entities do local entity = self.Entities[i] if entity.Camp.CampType == CAMP.BOSS then local entityGridId = entity.Move.TileIdCurrent if entityGridId == gridId then return entity end end end end function XPlanetRunningExplore:IsBossOnGrid(gridId) local boss = self:FindBossOnGrid(gridId) return boss and true or false end function XPlanetRunningExplore:IsSkipFight() --return self._SkipFight return XDataCenter.PlanetManager.GetStageSkipFight() end function XPlanetRunningExplore:SetSkipFight(value) --self._SkipFight = value XDataCenter.PlanetManager.SetStageSkipFight(value) end ---@return XPlanetRunningExploreEntity[] function XPlanetRunningExplore:GetBossListByGrid(gridId) local result = {} for i = 1, #self.Entities do local entity = self.Entities[i] if entity.Move.TileIdCurrent == gridId and entity.Camp.CampType == CAMP.BOSS then result[#result + 1] = entity end end return result end ---@return XPlanetRunningExploreEntity[] function XPlanetRunningExplore:GetCharacterAlive() local result = {} for i = 1, #self.Entities do local entity = self.Entities[i] if entity.Camp.CampType == CAMP.PLAYER and entity.Attr.Life > 0 then result[#result + 1] = entity end end return result end ---@return XPlanetRunningExploreEntity[] function XPlanetRunningExplore:GetCharacter() local result = {} for i = 1, #self.Entities do local entity = self.Entities[i] if entity.Camp.CampType == CAMP.PLAYER then result[#result + 1] = entity end end return result end ---@return XPlanetRunningExploreEntity[] function XPlanetRunningExplore:GetBoss() local result = {} for i = 1, #self.Entities do local entity = self.Entities[i] if entity.Camp.CampType == CAMP.BOSS then result[#result + 1] = entity end end return result end function XPlanetRunningExplore:GetCaptain() for i = 1, #self.Entities do local entity = self.Entities[i] if entity.Camp.CampType == CAMP.PLAYER and entity.Attr.Life > 0 then return entity end end end function XPlanetRunningExplore:GetCaptainTransform() local entity = self:GetCaptain() if not entity then return false end local model = self:GetModel(entity.Id) if not model then return false end return model:GetTransform() end function XPlanetRunningExplore:UpdateFollowerPosition() -- 更新一下坐标 local leader = self:GetLeader() self.SystemLeaderMove:MoveFollower(self, leader, 0) -- 更新一下角度 self.SystemRotate:UpdateEntity(self, leader, math.huge) end -- 更换队长 function XPlanetRunningExplore:SetCaptainByCharacterId(characterId) local entity, index = self:FindCharacter(characterId) if entity and index ~= self._IndexCaptain then table.remove(self.Entities, index) table.insert(self.Entities, self._IndexCaptain, entity) --self:SaveTeamCharacterIndex() -- 更换队长后, 更新坐标和旋转 self:UpdateFollowerPosition() if self:IsRunning() and self._Status == EXPLORE_STATUS.WALK then self.SystemAnimation:LetCharacterAction(self, XPlanetExploreConfigs.ACTION.WALK) else self.SystemAnimation:LetCharacterAction(self, XPlanetExploreConfigs.ACTION.STAND) end XEventManager.DispatchEvent(XEventId.EVENT_PLANET_UPDATE_CHARACTER_ENTITY) end end function XPlanetRunningExplore:SetCaptainByEntityId(entityId) local entity, index = self:GetEntity(entityId) if entity then table.remove(self.Entities, index) table.insert(self.Entities, 1, entity) end end function XPlanetRunningExplore:UpdateTeam(characterIdList) local characterData = {} for i, characterId in pairs(characterIdList) do local data = { Id = characterId, Life = 1, MaxLife = 1, } characterData[#characterData + 1] = data end self:UpdateCharacters(characterData) end function XPlanetRunningExplore:CreateLeader() ---@type XPlanetRunningExploreEntity local entity = XPlanetRunningExploreEntity.New() entity.Id = self:_GetUid() self.LeaderId = entity.Id entity.LeaderMove = XPlanetRunningComponentLeaderMove.New() -- 移动 entity.Move = XPlanetRunningComponentMove.New() entity.Move.Status = XPlanetExploreConfigs.MOVE_STATUS.START -- 起点 local stageData = XDataCenter.PlanetManager.GetStageData() local gridId = stageData:GetGridId() local tileId = self.Scene:CheckIsTalentPlanet() and self.Scene:GetRoadMapStartPoint() or gridId self:UpdatePositionCurrent(entity, tileId) entity.LeaderMove.TileIdOnServer = tileId entity.Camp = XPlanetRunningComponentCamp.New() entity.Camp.CampType = CAMP.LEADER entity.Rotation = XPlanetRunningComponentRotation.New() self:AddEntity(entity) end function XPlanetRunningExplore:IsCaptain(entityId) local captain = self:GetCaptain() if not captain then return false end return captain.Id == entityId end function XPlanetRunningExplore:InitRootModel() if not self._RootCharacter then local transformPlanet = self.Scene._Planet._Transform local rootCharacter = CS.UnityEngine.GameObject("CharacterRoot") rootCharacter.transform:SetParent(transformPlanet, false) rootCharacter.gameObject:SetLayerRecursively(CS.UnityEngine.LayerMask.NameToLayer(HomeSceneLayerMask.HomeCharacter)) self._RootCharacter = rootCharacter end end function XPlanetRunningExplore:Destroy() self:OnDestroy() for i = 1, #self.Entities do local entity = self.Entities[i] entity.Id = 0 entity.Attr = nil entity.Move = nil entity.LeaderMove = nil entity.Camp = nil entity.Rotation = nil entity.Data = nil entity.Animation = nil end self.Entities = nil self._RootUi = nil self._RootCharacter = nil self._Model = nil self.Scene = nil self._Data = nil self.SystemMove = nil self.SystemRotate = nil self.SystemLeaderMove = nil self.SystemAnimation = nil self.MovieManager = nil self.LeaderId = nil self._Status = nil self._IncId = nil self._SkipFight = nil self._PauseReason = nil self._TimeScale = nil self._Vector3Zero = nil if self.PlanetBubbleManager then self.PlanetBubbleManager:OnDestroy() self.PlanetBubbleManager = nil end end function XPlanetRunningExplore:IsDestroy() return not self.Scene end function XPlanetRunningExplore:UpdateByStageData() local stageData = XDataCenter.PlanetManager.GetStageData() self:UpdateDataCharacter(stageData:GetCharacterData()) self:UpdateDataBoss(stageData:GetMonsterData()) self:UpdateCharacters() self:UpdateBoss() end function XPlanetRunningExplore:OnStart() XEventManager.AddEventListener(XEventId.EVENT_PLANET_PLAY_ANIMATION_ON_RESULT, self.PlayAnimationWhenResult, self) end function XPlanetRunningExplore:OnEnable() XEventManager.AddEventListener(XEventId.EVENT_PLANET_UPDATE_STAGE, self.UpdateByStageData, self) XEventManager.AddEventListener(XEventId.EVENT_PLANET_UPDATE_CHARACTER, self.OnCharacterUpdate, self) XEventManager.AddEventListener(XEventId.EVENT_PLANET_NEW_EFFECT, self.OnEffectAdd, self) XEventManager.AddEventListener(XEventId.EVENT_PLANET_RESUME, self.Resume, self) XEventManager.AddEventListener(XEventId.EVENT_PLANET_UPDATE_BUILDING, self.UpdateBuildingRange, self) XEventManager.AddEventListener(XEventId.EVENT_PLANET_PLAY_BUBBLE, self.PlayBubbleFromEvent, self) XEventManager.AddEventListener(XEventId.EVENT_PLANET_PLAY_BUBBLE_ID, self.PlayBubble2Captain, self) self:UpdateDataCharacter() self:UpdateCharacters() end function XPlanetRunningExplore:OnDisable() XEventManager.RemoveEventListener(XEventId.EVENT_PLANET_UPDATE_STAGE, self.UpdateByStageData, self) XEventManager.RemoveEventListener(XEventId.EVENT_PLANET_UPDATE_CHARACTER, self.OnCharacterUpdate, self) XEventManager.RemoveEventListener(XEventId.EVENT_PLANET_NEW_EFFECT, self.OnEffectAdd, self) XEventManager.RemoveEventListener(XEventId.EVENT_PLANET_RESUME, self.Resume, self) XEventManager.RemoveEventListener(XEventId.EVENT_PLANET_UPDATE_BUILDING, self.UpdateBuildingRange, self) XEventManager.RemoveEventListener(XEventId.EVENT_PLANET_PLAY_BUBBLE, self.PlayBubbleFromEvent, self) XEventManager.RemoveEventListener(XEventId.EVENT_PLANET_PLAY_BUBBLE_ID, self.PlayBubble2Captain, self) end function XPlanetRunningExplore:OnDestroy() XEventManager.RemoveEventListener(XEventId.EVENT_PLANET_PLAY_ANIMATION_ON_RESULT, self.PlayAnimationWhenResult, self) end ---@param entity XPlanetRunningExploreEntity function XPlanetRunningExplore:UpdateCharacterAttr(entity, characterData) XDataCenter.PlanetExploreManager.UpdateCharacterAttrByClient(entity) local life = entity.Attr.Life local lifeCurrent = characterData.Life or 1 entity.Attr.Life = lifeCurrent -- 首次掉血引导 if life > lifeCurrent and lifeCurrent > 0 and XDataCenter.PlanetManager.SetGuideFirstHunt(true) and XDataCenter.PlanetManager.CheckGuideOpen() then self:Pause(XPlanetExploreConfigs.PAUSE_REASON.GUIDE) end end ---@param entity XPlanetRunningExploreEntity function XPlanetRunningExplore:UpdateModel(entity, delay) if entity.Attr.Life <= 0 then self:RemoveModel(entity) else local model = self:GetModel(entity.Id) if not model then self:CreateModel(entity, delay) end end end function XPlanetRunningExplore:OnCharacterUpdate() self:UpdateDataCharacter() self:UpdateCharacters() XEventManager.DispatchEvent(XEventId.EVENT_PLANET_ON_CHARACTER_ENTITY_UPDATE) end function XPlanetRunningExplore:OnEffectAdd(effectIdList) for i = 1, #effectIdList do local effectId = effectIdList[i] local entity = self:GetCaptain() local effect = XPlanetStageConfigs.GetBuffEffect2Model(effectId) if not string.IsNilOrEmpty(effect) then self:PlayEffect2Model(entity, effect) end self:PlayBubble(entity, effectId) end end function XPlanetRunningExplore:PlayBubbleFromEvent(effectId) local entity = self:GetCaptain() local effect = XPlanetStageConfigs.GetBuffEffect2Model(effectId) if not string.IsNilOrEmpty(effect) then self:PlayEffect2Model(entity, effect) end self:PlayBubble(entity, effectId) end function XPlanetRunningExplore:PlayBubble2Captain(bubbleId) local captain = self:GetCaptain() if self.PlanetBubbleManager then self.PlanetBubbleManager:PlayBubble(bubbleId, captain.Id) end end ---@param entity XPlanetRunningExploreEntity function XPlanetRunningExplore:PlayBubble(entity, effectId) local bubbleControllerId = XPlanetStageConfigs.GetBuffBubbleControllerId(effectId) if bubbleControllerId and bubbleControllerId ~= 0 then if self.PlanetBubbleManager then self.PlanetBubbleManager:PlayBubble(bubbleControllerId, entity.Id) end end end function XPlanetRunningExplore:StopBubble(entity) if self.PlanetBubbleManager then self.PlanetBubbleManager:StopBubble(entity.Id) end end ---@param entity XPlanetRunningExploreEntity function XPlanetRunningExplore:UpdatePositionCurrent(entity, tileId) entity.Move.TileIdCurrent = tileId local position = self.Scene:GetTileHeightPosition(tileId) entity.Move.PositionCurrent = position end function XPlanetRunningExplore:HideFollowers() local characterList = self:GetCharacter() for i = 2, #characterList do local entity = characterList[i] self:HideModel(entity) end end ---@param entity XPlanetRunningExploreEntity function XPlanetRunningExplore:HideModel(entity) local model = self:GetModel(entity.Id) if model then model:SetLocalPosition(self._Vector3Zero) end entity.Data.IsHideModel = true end ---@param entity XPlanetRunningExploreEntity function XPlanetRunningExplore:ShowModel(entity) if entity.Data.IsHideModel then entity.Data.IsHideModel = false self:PlayBornEffect(entity) end end function XPlanetRunningExplore:GetTimeScale() return self._TimeScale end function XPlanetRunningExplore:SetTimeScale(value) self._TimeScale = value end function XPlanetRunningExplore:IsDoubleTimeScale() return self._TimeScale == TIME_SCALE.X2 end function XPlanetRunningExplore:IsNormalTimeScale() return self._TimeScale == TIME_SCALE.NORMAL end function XPlanetRunningExplore:ReplayModelAnimation() self.SystemAnimation:ReplayModelAnimation(self) end ---@param entity XPlanetRunningExploreEntity function XPlanetRunningExplore:PlayEffect2Model(entity, effectPath, isOnScene, callback) local model = self:GetModel(entity.Id) if model then if isOnScene then local transform = model:GetTransform() if transform then local up = transform.localRotation * Vector3.up local position if isOnScene then local height = 1 position = up.normalized * height + transform.localPosition else position = transform.localPosition end local rotation = transform.localRotation self.Scene:PlayEffect(effectPath, position, rotation, callback) end else model:LoadEffect(effectPath, nil, nil, nil, true) end return end if not entity.Move.PositionCurrent then return end if not entity.Rotation.RotationCurrent then return end self.Scene:PlayEffect(effectPath, entity.Move.PositionCurrent, entity.Rotation.RotationCurrent, callback) end function XPlanetRunningExplore:UpdateBossBubbleAmount() local dictGrid = {} for i = 1, #self.Entities do local entity = self.Entities[i] if entity.Camp.CampType == CAMP.BOSS then local gridId = entity.Move.TileIdCurrent local dataGrid = dictGrid[gridId] if not dataGrid then dataGrid = { Amount = 0, Entity = false } dictGrid[gridId] = dataGrid end dataGrid.Amount = dataGrid.Amount + entity.Data.Amount if not dataGrid.Entity then local model = self:GetModel(entity.Id) if model then dataGrid.Entity = entity end end end end for gridId, dataGrid in pairs(dictGrid) do local amount = dataGrid.Amount if amount > 1 then self:PlayBubbleText(dataGrid.Entity, "X" .. amount) else self:StopBubbleText(dataGrid.Entity) end end end function XPlanetRunningExplore:IsBossModelOnGrid(gridId) for entityId, model in pairs(self._Model) do local entity = self:GetEntity(entityId) if entity.Camp.CampType == CAMP.BOSS then if entity.Move.TileIdCurrent == gridId then return true end end end return false end function XPlanetRunningExplore:ResetLeaderPosition() local entity = self:GetLeader() local tileId = self.Scene:GetRoadMapStartPoint() self:UpdatePositionCurrent(entity, tileId) entity.Move.TileIdStart = false entity.Move.TileIdEnd = false entity.Move.Status = XPlanetExploreConfigs.MOVE_STATUS.START entity.LeaderMove.Path = {} self:HideFollowers() self:ReplayModelAnimation() end ---@param entity XPlanetRunningExploreEntity function XPlanetRunningExplore:PlayBubbleText(entity, text) if self.PlanetBubbleManager then self.PlanetBubbleManager:PlayBubbleText(entity.Id, text) end end ---@param entity XPlanetRunningExploreEntity function XPlanetRunningExplore:StopBubbleText(entity) if self.PlanetBubbleManager then self.PlanetBubbleManager:StopBubbleText(entity.Id) end end function XPlanetRunningExplore:PlayMovie(movieId, fininshCb) -- 检测缓存。当通关了且没勾重播按钮则不能播放剧情 local stageId = XDataCenter.PlanetManager.GetStageData():GetStageId() local isPlayCache = XDataCenter.PlanetManager.GetBtnStoryCache() local checkIsPass = XDataCenter.PlanetManager.GetViewModel():CheckStageIsPass(stageId) if checkIsPass then local resultFromServer = XDataCenter.PlanetExploreManager.GetResult() if resultFromServer and resultFromServer:GetFirstPass() then checkIsPass = false end end if not isPlayCache and checkIsPass then if fininshCb then fininshCb() end return end -- 剧情播放、暂停玩法 self:Pause(XPlanetExploreConfigs.PAUSE_REASON.MOVIE) -- 剧情镜头 self.Scene:UpdateCamInMovie(self:GetCaptainTransform()) -- 隐藏非剧情Ui if self._RootUi then self._RootUi:HideUi() end -- 隐藏正在播放的气泡 if self.PlanetBubbleManager then self.PlanetBubbleManager:StopAllBubble() self.PlanetBubbleManager:HideAllBubbleText() end -- 隐藏其他小人 for k, entity in pairs(self.Entities) do local model = self:GetModel(entity.Id) if model and not XTool.UObjIsNil(model.GameObject) then model.GameObject:SetActiveEx(false) end end -- 生成剧情专用小人 local movieInfo = XPlanetExploreConfigs.GetMovieInfoById(movieId) local movieEntitys = {} local charIds = {} for k, v in pairs(movieInfo) do if not movieEntitys[v.PlanetCharacterId] and XTool.IsNumberValid(v.PlanetCharacterId) then local entity = self:CreateMovieEntity(v.PlanetCharacterId) local model = self:GetModel(entity.Id) model:GetTransform().name = model:GetTransform().name .. "Story" movieEntitys[v.PlanetCharacterId] = entity end end for charId, v in pairs(movieEntitys) do table.insert(charIds, charId) end -- 队长坐标 local firstEntity = movieEntitys[charIds[1]] if firstEntity then local modelF = self:GetModel(firstEntity.Id) local pos, rotation = self:GetEntityBeforePosAndRot(self:GetLeader()) modelF:SetLocalPosition(pos) modelF:GetTransform().rotation = rotation -- local modelCaptain = self:GetModel(self:GetCaptain().Id) -- modelF:GetTransform():LookAt(modelCaptain:GetTransform().position, Vector3.back) end -- boss坐标 local secondEntity = movieEntitys[charIds[2]] if secondEntity then local modelS = self:GetModel(secondEntity.Id) local pos, rotation = self:GetEntityNextPosAndRot(self:GetLeader()) modelS:SetLocalPosition(pos) modelS:GetTransform().rotation = rotation -- 互相看着对方 local modelF = self:GetModel(firstEntity.Id) local v3 = modelS:GetTransform().position - self.Scene:GetPlanetPosition() -- 需要以一个轴旋转人物、该轴是圆心指向角色的向量 modelS:GetTransform():LookAt(modelF:GetTransform().position, v3) end if self.MovieManager then local doFinCb = function() if self._RootUi then -- 播放剧情关闭过度黑幕 self._RootUi:PlayAnimation("DarkDisable") -- 恢复非剧情Ui self._RootUi:ShowUi() end if not self.Scene then return end -- 恢复场景镜头 self.Scene:UpdateCameraInStage() if fininshCb then fininshCb() end -- 恢复其他小人 for k, entity in pairs(self.Entities) do local model = self:GetModel(entity.Id) if model and not XTool.UObjIsNil(model.GameObject) then model.GameObject:SetActiveEx(true) end end -- 恢复text if self.PlanetBubbleManager then self.PlanetBubbleManager:ShowAllBubbleText() end -- 删除剧情专用小人 for k, entity in pairs(movieEntitys) do self:RemoveEntity(entity) end self:Resume(XPlanetExploreConfigs.PAUSE_REASON.MOVIE) end self.MovieManager:Play(movieId, movieEntitys, doFinCb) end end function XPlanetRunningExplore:SkipMovie() if self.MovieManager then self.MovieManager:Skip() end end function XPlanetRunningExplore:IsPlayingMovie() if self._PauseReason & XPlanetExploreConfigs.PAUSE_REASON.MOVIE > 0 then return true end end function XPlanetRunningExplore:PlayBornEffect(entity) -- 初始创造和主界面的不播放音效 if XLuaUiManager.IsUiShow("UiPlanetLoading") or XLuaUiManager.IsUiShow("UiPlanetMain") then return end local effectPath = XPlanetConfigs.GetEffectChangeRole() self:PlayEffect2Model(entity, effectPath, true) end function XPlanetRunningExplore:PlayAnimationWhenResult(isWin) self:Pause(XPlanetExploreConfigs.PAUSE_REASON.RESULT) local bossList = self:GetBoss() for i = 1, #bossList do local boss = bossList[i] local model = self:GetModel(boss.Id) if model then model:HideRoleModel() end end local characterList = self:GetCharacterAlive() for i = 1, #characterList do local entity = characterList[i] if isWin then entity.Animation.ActionOnce = XPlanetExploreConfigs.ACTION.WIN else entity.Animation.Action = XPlanetExploreConfigs.ACTION.FAIL end end end ---@param entity XPlanetRunningExploreEntity ---@return Vector3,Quaternion 下一格表面坐标,下一格子朝向本格方向 function XPlanetRunningExplore:GetEntityNextPosAndRot(entity) if not entity then XLog.Error("XPlanetRunningExplore:GetEntityBeforePosAndRot Error! entity is Null!") return false end local position = entity.Move.PositionTarget local rotation = entity.Rotation.RotationCurrent local curTile = entity.Move.TileIdCurrent local nextPosition = self.Scene:GetTileHeightPosition(self.Scene:GetNextRoadTileId(curTile)) rotation = CS.UnityEngine.Quaternion.LookRotation(nextPosition - position, self.Scene:GetTileUp(curTile)) position = nextPosition return position, rotation end ---@param entity XPlanetRunningExploreEntity ---@return Vector3,Quaternion 上一格表面坐标,上一格子朝向本格方向 function XPlanetRunningExplore:GetEntityBeforePosAndRot(entity) if not entity then XLog.Error("XPlanetRunningExplore:GetEntityBeforePosAndRot Error! entity is Null!") return false end local position = entity.Move.PositionTarget local rotation = entity.Rotation.RotationCurrent local curTile = entity.Move.TileIdCurrent local beforePosition = self.Scene:GetTileHeightPosition(self.Scene:GetBeforeRoadTileId(curTile)) rotation = CS.UnityEngine.Quaternion.LookRotation(position - beforePosition, self.Scene:GetTileUp(curTile)) position = beforePosition return position, rotation end ---@return XPlanetRunningExploreEntity function XPlanetRunningExplore:GetLeader() return self._DictEntities[self.LeaderId] end ---@param entity XPlanetRunningExploreEntity function XPlanetRunningExplore:AddEntity(entity) self.Entities[#self.Entities + 1] = entity self._DictEntities[entity.Id] = entity end function XPlanetRunningExplore:UpdateBuildingRange() self._GridInBuildingRange = {} local buildingList = self.Scene:GetBuildingList() for _, building in pairs(buildingList) do local range2Cycle = building:GetRangeTileList() for cycle, listGrid in pairs(range2Cycle) do for i = 1, #listGrid do local gridId = listGrid[i] self._GridInBuildingRange[gridId] = true end end end end function XPlanetRunningExplore:IsGridInBuildingRange(gridId) return self._GridInBuildingRange[gridId] end function XPlanetRunningExplore:CheckAndPlayMovie() if self.Scene:CheckIsTalentPlanet() then return end local stageId = XDataCenter.PlanetManager.GetStageData():GetStageId() local movieId = XPlanetExploreConfigs.GetMovieIdByCheckControllerStage(XPlanetExploreConfigs.MOVIE_CONDITION.ENTER_STAGE, stageId) if movieId and XDataCenter.PlanetManager.GetIsNotCountinueEnterGame() then self:PlayMovie(movieId, function() self.Scene:UpdateCameraInStage(true, true) XEventManager.DispatchEvent(XEventId.EVENT_PLANET_STAGE_MOVIE_STOP) end) end end function XPlanetRunningExplore:IsOnStartPoint(gridId) return self.Scene:GetRoadMapStartPoint() == gridId end -- 本来应该写个system, 但是临近上线, 就不提交新文件了 function XPlanetRunningExplore:UpdateModelDelayCreate() self._DurationModelDelay = self._DurationModelDelay + 1 if self._DurationModelDelay > self._GapModelDelay then self._DurationModelDelay = 0 if #self._ModelDelay2Create > 0 then ---@type XPlanetRunningDataDelayCreateModel local data = self._ModelDelay2Create[1] table.remove(self._ModelDelay2Create, 1) local entityId = data.EntityId local entity = self:GetEntity(entityId) if entity and entity.Attr.Life > 0 then local model = self:GetModel(entityId) if model then local modelName = data.ModelName self:LoadModel(entity, model, modelName, true) end end end end end function XPlanetRunningExplore:UpdateTransform(entity) if entity.Move.Status == XPlanetExploreConfigs.MOVE_STATUS.START then self.SystemMove:Update(self, entity, 0, true) self.SystemRotate:UpdateEntity(self, entity, math.huge) entity.Move.Status = XPlanetExploreConfigs.MOVE_STATUS.START end end function XPlanetRunningExplore:SortModelDelay() local dictGrid = {} local startTileId = self:GetLeader().Move.TileIdCurrent local nextTileId = startTileId for i = 1, 999 do nextTileId = self.Scene:GetNextRoadTileId(nextTileId) dictGrid[nextTileId] = i if nextTileId == startTileId then break end end for i = #self._ModelDelay2Create, 1, -1 do local data = self._ModelDelay2Create[i] local entityId = data.EntityId local entity = self:GetEntity(entityId) if not entity then table.remove(self._ModelDelay2Create, i) end end ---@param a XPlanetRunningDataDelayCreateModel ---@param b XPlanetRunningDataDelayCreateModel table.sort(self._ModelDelay2Create, function(a, b) local entityIdB = b.EntityId local entityB = self:GetEntity(entityIdB) local tileIdB = entityB.Move.TileIdCurrent local entityIdA = a.EntityId local entityA = self:GetEntity(entityIdA) local tileIdA = entityA.Move.TileIdCurrent local priorityB = dictGrid[tileIdB] local priorityA = dictGrid[tileIdA] return priorityA < priorityB end) end return XPlanetRunningExplore