local CountryNightBoss_Controller = {} local EventSystem = require('Event/EventSystem') local ColliderManager = require("Battle/Logic/Level/ColliderManager") CountryNightBoss_Controller.SceneMapID = 8 -- 长安汉中 CountryNightBoss_Controller.CurInteractBossID = 0 local COUNTRY_NIGHT_BOSS_EFFECT_PATH = "Public/FunctionEffect/PT_GuoZhan_Boss" local INTERACT_DIS = DataSheetManager.ConstData:GetDataByID("CountryBossNPCLightEffectRadius").FloatValue:Square() local RECRUIT_PERMISSION = DataSheetManager.ConstData:GetDataByID("CountryBossCallTogetherJobLmt").IntListValue local COUNTRY_FIRST_LINEUP_REDPOINT = "COUNTRY_FIRST_LINEUP_REDPOINT" local private = {} CountryNightBoss_Controller.SortFieldEnum = { Damage = "damage", Kill = "kill", Help = "help", Death = "death", } local function IncrSort(a, b) return a[private.sortTargetField] > b[private.sortTargetField] end local function DecSort(a, b) return a[private.sortTargetField] < b[private.sortTargetField] end local function SortByMaxValue(a, b) if a[private.sortTargetField] == b[private.sortTargetField] then return a.acid < b.acid else return a[private.sortTargetField] > b[private.sortTargetField] end end function CountryNightBoss_Controller.OnStartup() EventSystem.Regist(EventID.FunctionUnlockUpdate, private.RefreshByFunctionUnlock) EventSystem.Regist(EventID.Update_CountryNightBoss_SceneInfo, private.SyncBossSceneInfo) EventSystem.Regist(EventID.TimerWheelStartTimeOver, private.OnCountryNightBossStart) EventSystem.Regist(EventID.Country_OnGetFoundCountry, private.OnCountryNightBossStart) private.hasShowRemind = false private.bossModelDic = {} -- k: BossId - v: entity映射 private.onBossClickEventList = {} private.activeColliderIDDic = {} private.sortTargetField = "" -- 排序需要的字段 end -- 活动时间弹出提示 function private.OnCountryNightBossStart(timeId, activityId, timeIndex) if not activityId then private.OpenRemind() else if activityId == LuaConst.ActivityType.CountryNightBoss then private.OpenRemind() end end EventSystem.Dispatch(EventID.UI_CountryNightBoss_ActivityNotice, true) private.RefreshRedPoint() end --- 在场景中活动结束 function CountryNightBoss_Controller.OnEndActivityView() -- 弹出活动战斗统计界面 if not UIManager.IsViewOpened(Const_UI_Lua.UIEnum.UICountryNightBossRecord) then UIManager.OpenView(Const_UI_Lua.UIEnum.UICountryNightBossRecord) end private.hasShowRemind = false EventSystem.Dispatch(EventID.UI_CountryNightBoss_ActivityNotice, false) CountryNightBoss_Controller.ClearCountryNightBossModelInfo() end function private.OpenRemind() if private.hasShowRemind then return end if CountryNightBoss_Controller.IsOpen() then if CTL.Activities.IsInActivitySpecificLevel() then UIManager.OpenView(Const_UI_Lua.UIEnum.UIActivitiesRemind, {LuaConst.ActivityType.CountryNightBoss}) else CTL.HomeMain.AddTownHomeDelayView(Const_UI_Lua.UIEnum.UIActivitiesRemind, {LuaConst.ActivityType.CountryNightBoss}) end private.hasShowRemind = true end end function CountryNightBoss_Controller.IsChangAnLevel() return BattleDataGetter.GetCurLevelID() == CountryNightBoss_Controller.SceneMapID end ---@return bool 是否在活动开放时间内 function CountryNightBoss_Controller.IsOpen() return MDL.Unlock.IsUnlock(MDL.Unlock.FunctionType.CountryNightBoss) and CTL.Activities.IsOpeningTime(LuaConst.ActivityType.CountryNightBoss) and MDL.Country.GetCurStage() ~= MDL.Country.Stage.CountryReset end --- GMS开关 function private.RefreshByFunctionUnlock(funcId, isUnlock) if funcId == MDL.Unlock.FunctionType.CountryNightBoss then if isUnlock == false then CountryNightBoss_Controller.CloseAllCountryNightBossView() private.RemoveAllModel() private.RefreshRedPoint() end end end function private.DeSelectBossModel() CountryNightBoss_Controller.CurInteractBossID = 0 EventSystem.Dispatch(EventID.UI_UpdateRebelStrike_Select, nil) end function CountryNightBoss_Controller.OpenBattleSummaryPanel(bossId) if UIManager.IsViewOpened(Const_UI_Lua.UIEnum.UICountryNightBossBattleBase) then UIManager.CloseView(Const_UI_Lua.UIEnum.UICountryNightBossBattleBase) end if UIManager.IsViewOpened(Const_UI_Lua.UIEnum.UISwitchHeroReviveView) then UIManager.CloseView(Const_UI_Lua.UIEnum.UISwitchHeroReviveView) end UIManager.OpenView(Const_UI_Lua.UIEnum.UICountryNightBossSummary, { bossID = bossId, isBattleSummary = true }) end function CountryNightBoss_Controller.CloseAllCountryNightBossView() UIManager.CloseView(Const_UI_Lua.UIEnum.UICountryNightBossReward) UIManager.CloseView(Const_UI_Lua.UIEnum.UICountryNightBossDamageRank) UIManager.CloseView(Const_UI_Lua.UIEnum.UICountryNightBossBattleRank) UIManager.CloseView(Const_UI_Lua.UIEnum.UICountryNightBossBattleList) UIManager.CloseView(Const_UI_Lua.UIEnum.UICountryNightBossMain) UIManager.CloseView(Const_UI_Lua.UIEnum.UICountryNightBossRecord) UIManager.CloseView(Const_UI_Lua.UIEnum.UICountryNightBossSummary) end --- 进入战斗 ---@param bossId CountryNightBoss主键 function CountryNightBoss_Controller.EnterBattle(bossId) if not CountryNightBoss_Controller.IsOpen() then CTL.Tips.AddTipsMsg(Const_IDS["IDS_ActivityItem_NotAtActivityTime"]) return end private.DeSelectBossModel() MDL.CountryNightBoss.CountryBossEnterFightReq(bossId) end ---@return bool 是否有战斗中招募队友的权利 function CountryNightBoss_Controller.HasRecruitPermission() for _, jobID in ipairs(RECRUIT_PERMISSION) do if jobID == MDL.Country.GetMyJobId() then return true end end return false end --- 群里前往boss所在坐标 ---@param positionID CountryNightBossPoint主键BossPoint function CountryNightBoss_Controller.GoToBossPos(positionID) if not BattleDataGetter.IsNoBattleLevel() then CTL.Tips.AddTipsMsg(Const_IDS["IDS_CountryNightBoss_UnableToGo"]) return end -- 关闭晚间boss主界面 UIManager.CloseView(Const_UI_Lua.UIEnum.UICountryNightBossMain) UIManager.CloseView(Const_UI_Lua.UIEnum.UIActivitiesMain) EventSystem.Dispatch(EventID.UI_CloseAndRecoverView, Const_UI_Lua.UIEnum.UICountryBase) UIManager.RecoverView() SystemManager.StopAutoFightPathInTown(LogicUpdateManager._curEntity) local pointData = DataSheetManager.CountryNightBossPoint:GetDataByBossPoint(positionID) local levelItem = BattleDataGetter.GetLevelItemByMapID_LevelItemID(CTL.CountryNightBoss.SceneMapID, pointData.LevelItemID) if levelItem then NotSyncBattleSetter.FindPathByLevelItem(CTL.CountryNightBoss.SceneMapID, levelItem, NotSyncBattleSetter.OffHorse, nil, true) end return true end --- @return string 血量百分比字符串 local PERCENT_FORMAT = "%s%%" function CountryNightBoss_Controller.GetHpPercentValStr(hp, totalHp) local val = CountryNightBoss_Controller.GetHpPercentVal(hp, totalHp) return string.format(PERCENT_FORMAT, string.format("%0.2f", val * 100)) end --- @return float 血量真实比值 function CountryNightBoss_Controller.GetHpPercentVal(hp, totalHp) return hp <= 0 and 0 or (hp / totalHp) end --- @param seconds 秒数 --- @return string 格式化boss剩余时间,小于2分钟为红色字体 function CountryNightBoss_Controller.GetBossTimerStrBySeconds(seconds) local min = math.floor(seconds / UTL.Time.TotalSecondsOneMinute) local mod_seconds = seconds % UTL.Time.TotalSecondsOneMinute local showStr if seconds >= UTL.Time.TotalSecondsOneMinute then showStr = string.format("%02d:%02d", min, mod_seconds) else showStr = string.format("00:%02d", mod_seconds) end if seconds >= UTL.Time.TotalSecondsOneMinute * 2 then return UTL.Color.FormatGreenColor(showStr) else return UTL.Color.FormatRedColor(showStr) end end --- Boss设置头像 function CountryNightBoss_Controller.SetBossHeadUI(compCollection, bossId) local isEmptyBoss = not bossId or bossId <= 0 UIUtils.SetActive(compCollection.img_PlayerHead, not isEmptyBoss) UIUtils.SetActive(compCollection.img_Empty.gameObject, isEmptyBoss) if isEmptyBoss then return end local bossData = DataSheetManager.CountryNightBoss:GetDataByID(bossId) local heroData = DataSheetManager.HeroNum:GetDataByID(bossData.HeroID) UTL.Item.ItemCircleIcon(compCollection.img_PlayerHead, compCollection.img_PlayerAvatarBg, heroData.HeroItem) end --- Boss设置半身像 -- Boss半身图片路径更新 local BossHalfImgPathPrefix = ConstAssetPathConfig.BossHalfImgPathPrefix function CountryNightBoss_Controller.SetHalfBossImg(img, imgPath) UIUtils.SetImageByAssetBundle(img, string.format(BossHalfImgPathPrefix, imgPath)) end --- 根据指定字段排序列表 --- @param rawDataArr list 待排序列表 --- @param sortOrder int 1由大到小,0由小到大 --- @param sortField string 排序根据的字段 function CountryNightBoss_Controller.SortDataBySortConfigAndField(rawDataArr, sortOrder, sortField) private.sortTargetField = sortField if sortOrder > 0 then table.sort(rawDataArr, IncrSort) else table.sort(rawDataArr, DecSort) end return rawDataArr end function CountryNightBoss_Controller.SetMaxValByDamage_Kill_Help(rankList, damageData, killData, helpData) local damageSortArray = {} local killSortArray = {} local helpSortArray = {} local curMaxDamage = -1 local curMaxKill = -1 local curMaxHelp = -1 damageData.val = curMaxDamage killData.val = curMaxKill helpData.val = curMaxHelp -- 存储各项数据最大值 for _, v in ipairs(rankList) do if v.damage >= curMaxDamage then curMaxDamage = v.damage table.insert(damageSortArray, v) end if v.kill >= curMaxKill then curMaxKill = v.kill table.insert(killSortArray, v) end if v.help >= curMaxHelp then curMaxHelp = v.help table.insert(helpSortArray, v) end end private.sortTargetField = CountryNightBoss_Controller.SortFieldEnum.Damage table.sort(damageSortArray, SortByMaxValue) private.sortTargetField = CountryNightBoss_Controller.SortFieldEnum.Kill table.sort(killSortArray, SortByMaxValue) private.sortTargetField = CountryNightBoss_Controller.SortFieldEnum.Help table.sort(helpSortArray, SortByMaxValue) damageData.val = curMaxDamage damageData.acid = damageSortArray[1].acid killData.val = curMaxKill killData.acid = killSortArray[1].acid helpData.val = curMaxHelp helpData.acid = helpSortArray[1].acid end function CountryNightBoss_Controller.ShowCountryNightBossNoteView() local activityData = DataSheetManager.ActivityData:GetDataByID(LuaConst.ActivityType.CountryNightBoss) local date, time, extra = CTL.Activities.GetDetailsTimeDesc(activityData, true) local levelID = DataSheetManager.CountryNightBoss:GetDataByID(1).LevelID local levelDurationTime = DataSheetManager.LevelInfoData:GetDataByLevelID(levelID).Timer local previewTime = DataSheetManager.ConstData:GetDataByID("CountryBossInformationStorageTime").IntValue UIManager.OpenView(Const_UI_Lua.UIEnum.UICommonNoteView, { id = LuaConst.NoteID.CountryNightBoss, params = {date..time , math.ceil(FP.tonumberV1(levelDurationTime) / UTL.Time.TotalSecondsOneMinute), previewTime} } ) end --region 布阵相关 function CountryNightBoss_Controller.SetCurSelectKingdom() private.curSelectKingdomId = CountryNightBoss_Controller.GetCurLimitKingdom() end function CountryNightBoss_Controller.IsKindDomChanged() return private.curSelectKingdomId ~= CountryNightBoss_Controller.GetCurLimitKingdom() end --组合国别 -- 比如魏国1、蜀国2 ==> curKingdom为12; 魏国1、蜀国2、吴国3 ==> curKingdom为123 function CountryNightBoss_Controller.GetCurLimitKingdom() local lineUpCountryLimits = MDL.CountryNightBoss.GetLineUpCountryLimits() return MDL.FreeLineUp.GetMultiCountryId(lineUpCountryLimits) end --endregion --region 模型生成相关 local function OnEnterCollider(ownerEntity, entity) if entity == LogicUpdateManager._curEntity then local bossID = ownerEntity.components.record:GetVariable("countryNightBossID") CountryNightBoss_Controller.CurInteractBossID = bossID if bossID and bossID > 0 then EventSystem.Dispatch(EventID.UI_UpdateRebelStrike_Select, true) end end end local function OnExitCollider(ownerEntity, entity) if entity == LogicUpdateManager._curEntity then private.DeSelectBossModel() end end -- 靠近点击 function private.OnClickBossEntityModel(entity) --主视角调用 SystemManager.StopAutoFightPathInTown(LogicUpdateManager._curEntity) local pos = entity.components.move.LogicPos SystemManager.AutoFindPathInTown(LogicUpdateManager._curEntity, pos, LuaConst.NpcAutoFindDistance) end function private.SyncBossSceneInfo(activityType, bossInfoList) if IsServerDataNotNil(bossInfoList) then for _, bossInfo in ipairs(bossInfoList) do local entity = BattleDataGetter.GetEntityByEntityID(private.bossModelDic[bossInfo.bossId]) if not MDL.CountryNightBoss.IsBossOver(bossInfo.bossId) then if not entity then -- 生成指定模型 private.BornBossModel(bossInfo.bossId) else -- 已生成,更新信息 private.UpdateEntityShowInfo(entity, bossInfo) end else -- boss已经死亡 if entity then private.OnBossDead(entity, bossInfo) end if bossInfo.bossId == CountryNightBoss_Controller.CurInteractBossID then -- 当前展开了进入战斗选中,取消选中 EventSystem.Dispatch(EventID.UI_UpdateRebelStrike_Select, nil) end end end end end function private.BornBossModel(bossID) local v = MDL.CountryNightBoss.GetBossInfoByID(bossID) -- 创建模型 local levelItem = BattleDataGetter.GetLevelItemByID(v.levelItemID) if levelItem then local data = levelItem.ItemData local npcID = DataSheetManager.CountryNightBoss:GetDataByID(v.bossId).MonsterID local positionV2 = data.ItemPos local forwardV2 = data.ItemDir EntityFactory.SetParams("BornItemID", v.levelItemID, "CampID", LuaConst.STANDALONE_ENEMY_CAMP) EntityFactory.SetPos_Dir(positionV2, forwardV2) EntityFactory.SetType_ID(LuaConst.CharacterType.NPC, npcID) local entity = EntityFactory.DoCreateEntity() -- 播放NPC常驻特效 SystemManager.ShowPSEffect(entity, COUNTRY_NIGHT_BOSS_EFFECT_PATH, true) -- 注册Entity点击事件 EventSystem.Regist(entity.Event_EntityVisited, private.OnClickBossEntityModel) private.onBossClickEventList[entity.Event_EntityVisited] = true -- 创建名字、倒计时、血量 private.UpdateEntityShowInfo(entity, v) -- 保存 countryNightBossID至Entity entity.components.record:VariableSet("countryNightBossID", v.bossId) private.bossModelDic[v.bossId] = entity.EntityID --添加碰撞 local colliderID = ColliderManager.CreateCircleCollider(positionV2, INTERACT_DIS) private.activeColliderIDDic[entity.EntityID] = colliderID ColliderManager.AddEnterEvent(colliderID, OnEnterCollider, entity) ColliderManager.AddExitEvent(colliderID, OnExitCollider, entity) ColliderManager.ActiveCollider(colliderID, LogicUpdateManager.ValidSyncEntityIter) end end function private.OnBossDead(entity, bossInfo) SystemManager.DeadQuit(entity) local colliderID = private.activeColliderIDDic[entity.EntityID] if colliderID then ColliderManager.DeActiveCollider(colliderID) end EventSystem.UnRegist(entity.Event_EntityVisited, private.OnClickBossEntityModel) private.onBossClickEventList[entity.Event_EntityVisited] = nil private.bossModelDic[bossInfo.bossId] = nil private.activeColliderIDDic[entity.EntityID] = nil end function private.UpdateEntityShowInfo(entity, info) entity.ExpEntity:SetModelUIVisible(true) local bossName = DataSheetManager.CountryNightBoss:GetDataByID(info.bossId).WordBossName entity.ExpEntity:SetModelUI_Name(UIUtils.GetLocalizedTxt(Const_IDS[bossName])) entity.ExpEntity:SetModelUI_HP(info.bossHp, 0, info.totalBossHp, false) entity.ExpEntity:SetModelCDTimerVisible(true, MDL.CountryNightBoss.GetBossLeftTimeByID(info.bossId)) -- 单位:秒 end --- 退出场景删除所有模型状态 function CountryNightBoss_Controller.ClearCountryNightBossModelInfo() for eventID, v in pairs(private.onBossClickEventList) do EventSystem.UnRegist(eventID, private.OnClickBossEntityModel) end -- 退出长安的时候清理 table.clear(private.onBossClickEventList) -- 清除模型缓存 table.clear(private.bossModelDic) -- 清除碰撞器模型 table.clear(private.activeColliderIDDic) private.DeSelectBossModel() end --- 清除所有模型 function private.RemoveAllModel() for i, entityID in pairs(private.bossModelDic) do local entity = BattleDataGetter.GetEntityByEntityID(entityID) SystemManager.DeadQuit(entity) end CountryNightBoss_Controller.ClearCountryNightBossModelInfo() end --endregion --红点 function private.RefreshRedPoint() if CountryNightBoss_Controller.IsOpen() then local time = MDL.RedPoint.GetRedPointTimeByType(MDL.RedPoint.RedPointType.CountryNightBoss) if time and time > 0 and UTL.Time.IsTimestampSameDay(time) then EventSystem.Dispatch(EventID.UI_Activity_Refresh_Single_RedPoint, LuaConst.ActivityType.CountryNightBoss, false) else EventSystem.Dispatch(EventID.UI_Activity_Refresh_Single_RedPoint, LuaConst.ActivityType.CountryNightBoss, true) end else EventSystem.Dispatch(EventID.UI_Activity_Refresh_Single_RedPoint, LuaConst.ActivityType.CountryNightBoss, false) end end function CountryNightBoss_Controller.GetLineUpRedPoint() local dict = PersistentData.PlayerData:Get(COUNTRY_FIRST_LINEUP_REDPOINT) if dict == nil or dict[CountryNightBoss_Controller.GetCurLimitKingdom()] == nil or CTL.RedPoint.GetRedPointActive(CTL.RedPoint.RedPointKey.CountryNightBossLineUp) then return true end return dict[CountryNightBoss_Controller.GetCurLimitKingdom()] end function CountryNightBoss_Controller.SetLineUpRedPoint(flag) local dict = PersistentData.PlayerData:Get(COUNTRY_FIRST_LINEUP_REDPOINT) if dict == nil then dict = {} end dict[CountryNightBoss_Controller.GetCurLimitKingdom()] = flag or false PersistentData.PlayerData:Set(COUNTRY_FIRST_LINEUP_REDPOINT, dict, true) if not flag then CTL.RedPoint.RemoveRedPoint(CTL.RedPoint.RedPointKey.CountryNightBossLineUp) end end return CountryNightBoss_Controller