Files
Endfield-Data/LuaScripts/UI/Panels/Mission/MissionCtrl.lua
2025-12-02 20:37:18 +07:00

1369 lines
52 KiB
Lua

local uiCtrl = require_ex('UI/Panels/Base/UICtrl')
local PANEL_ID = PanelId.Mission
local PHASE_ID = PhaseId.Mission
local CHAPTER_ICON_PATH = "Mission/ChapterIconNew"
local CHAPTER_BG_ICON_PATH = "Mission/ChapterBgIconNew"
local CHAPTER_CHAR_ICON_PATH = "Mission/ChaptCharIconNew"
local OPTIONAL_TEXT_COLOR = "C7EC59"
local QuestState = CS.Beyond.Gameplay.MissionSystem.QuestState
local MissionState = CS.Beyond.Gameplay.MissionSystem.MissionState
local MissionImportance = GEnums.MissionImportance
local ChapterType = CS.Beyond.Gameplay.ChapterType
local MissionExternalSystemType = GEnums.MissionExternalSystemType
local MissionType = CS.Beyond.Gameplay.MissionSystem.MissionType
local MissionViewType = GEnums.MissionViewType
local DomainDepotPackageProgress = GEnums.DomainDepotPackageProgress
local QuestType = GEnums.QuestType
local MissionListCellType_Importance = 0
local MissionListCellType_Chapter = 1
local MissionListCellType_Mission = 2
local MissionSystem = CS.Beyond.Gameplay.MissionSystem
local MissionFilterType_All = -1
local MissionImportanceColorMap = {
[MissionImportance.High] = "Yellow",
[MissionImportance.Mid] = "Green",
[MissionImportance.Low] = "Blue",
}
local BlockConditionListType = CS.System.Collections.Generic.List(CS.Beyond.Gameplay.MissionRuntimeAsset.BlockCondition)
local MissionFilterCellConfig = {
[1] = {
missionFilterType = MissionFilterType_All,
icon = "all_mission_icon_gray",
typeText = Language.ui_mis_panel_tab_all,
},
[2] = {
missionFilterType = MissionViewType.MissionViewMain,
icon = "main_mission_icon_gray",
typeText = Language.ui_mis_panel_tab_main_new,
},
[3] = {
missionFilterType = MissionViewType.MissionViewDiscovery,
icon = "fac_mission_icon_gray",
typeText = Language.ui_mis_panel_tab_discovery,
},
[4] = {
missionFilterType = MissionViewType.MissionViewSide,
icon = "char_mission_icon_gray",
typeText = Language.ui_mis_panel_tab_side,
},
[5] = {
missionFilterType = MissionViewType.MissionViewActivity,
icon = "activity_mission_icon_gray",
typeText = Language.ui_mis_panel_tab_activity,
},
[6] = {
missionFilterType = MissionViewType.MissionViewOther,
icon = "misc_mission_icon_gray",
typeText = Language.ui_mis_panel_tab_other,
},
}
MissionCtrl = HL.Class('MissionCtrl', uiCtrl.UICtrl)
MissionCtrl.s_messages = HL.StaticField(HL.Table) << {
[MessageConst.ON_TRACK_MISSION_CHANGE] = 'OnTrackMissionChange',
[MessageConst.ON_QUEST_OBJECTIVE_UPDATE] = 'OnObjectiveUpdate',
[MessageConst.ON_SYNC_ALL_MISSION] = 'OnSyncAllMission',
[MessageConst.ON_MISSION_STATE_CHANGE] = 'OnMissionStateChange',
[MessageConst.ON_QUEST_STATE_CHANGE] = 'OnQuestStateChange',
}
MissionCtrl.m_missionSystem = HL.Field(HL.Any)
MissionCtrl.m_selectedMissionId = HL.Field(HL.Any) << nil
MissionCtrl.m_lastSelectedMissionId = HL.Field(HL.Any) << nil
MissionCtrl.m_missionViewInfo = HL.Field(HL.Table)
MissionCtrl.m_getMissionCellsFunc = HL.Field(HL.Function)
MissionCtrl.m_questCellCache = HL.Field(HL.Forward("UIListCache"))
MissionCtrl.m_missionTypeCells = HL.Field(HL.Forward("UIListCache"))
MissionCtrl.m_missionFilterType = HL.Field(HL.Any)
MissionCtrl.m_getRewardItemCellsFunc = HL.Field(HL.Function)
MissionCtrl.m_isClosing = HL.Field(HL.Boolean) << false
MissionCtrl.m_willExpire = HL.Field(HL.Boolean) << false
MissionCtrl.m_timeStamp = HL.Field(HL.Any)
MissionCtrl.m_packageNode = HL.Field(HL.Table)
MissionCtrl.m_openMissionFilter = HL.Field(HL.Any) << MissionFilterType_All
MissionCtrl.OnCreate = HL.Override(HL.Any) << function(self, arg)
self.m_missionSystem = GameInstance.player.mission
self.m_packageNode = {
["Hurt"] = self.view.missionInfoNode.packageList.hurtNode,
["Jump"] = self.view.missionInfoNode.packageList.jumpNode,
["Teleport"] = self.view.missionInfoNode.packageList.tpNode,
}
self.m_questCellCache = UIUtils.genCellCache(self.view.missionInfoNode.questCell)
self.view.btnClose.onClick:RemoveAllListeners()
self.view.btnClose.onClick:AddListener(function()
PhaseManager:PopPhase(PHASE_ID)
end)
if arg and arg.missionFilter then
if arg.missionFilter == "MissionViewMain" then
self.m_openMissionFilter = MissionViewType.MissionViewMain
elseif arg.missionFilter == "MissionViewDiscovery" then
self.m_openMissionFilter = MissionViewType.MissionViewDiscovery
elseif arg.missionFilter == "MissionViewSide" then
self.m_openMissionFilter = MissionViewType.MissionViewSide
elseif arg.missionFilter == "MissionViewActivity" then
self.m_openMissionFilter = MissionViewType.MissionViewActivity
elseif arg.missionFilter == "MissionViewOther" then
self.m_openMissionFilter = MissionViewType.MissionViewOther
else
self.m_openMissionFilter = MissionFilterType_All
end
end
self:_InitMissionFilter()
self.m_getMissionCellsFunc = UIUtils.genCachedCellFunction(self.view.missionScrollView)
if arg and arg.autoSelect then
self.m_selectedMissionId = arg.autoSelect
else
self.m_selectedMissionId = self.m_missionSystem.trackMissionId
end
self.view.blackMask.gameObject:SetActive(true)
self:_RefreshMissionList()
self:_AutoSelectMission(true)
self:_RefreshMissionInfo()
self:_ChangeSelectedMission(0)
self:_RefreshNaviSelected()
if DeviceInfo.usingController then
self.view.rewardNaviGroup.onIsFocusedChange:AddListener(function(isFocused)
if not isFocused then
Notify(MessageConst.HIDE_ITEM_TIPS)
end
end)
end
self.view.controllerHintPlaceholder:InitControllerHintPlaceholder({self.view.inputGroup.groupId})
self:BindInputEvent(CS.Beyond.Input.KeyboardKeyCode.J, function()
PhaseManager:PopPhase(PHASE_ID)
end)
self:_StartCoroutine(function()
while true do
coroutine.wait(UIConst.FAC_COMMON_UI_LARGER_UPDATE_INTERVAL)
self:_UpdateShow()
end
end)
end
MissionCtrl._InitMissionFilter = HL.Method() << function(self)
self.view.m_missionTypeCells = UIUtils.genCellCache(self.view.missionTypeTab.tabCell)
self.m_missionFilterType = self.m_openMissionFilter
local currentSelectTab
local currentSelectConfig
self.view.m_missionTypeCells:Refresh(#MissionFilterCellConfig, function(cell, index)
local config = MissionFilterCellConfig[index]
if config.missionFilterType == self.m_openMissionFilter then
currentSelectTab = cell
currentSelectConfig = config
end
if config then
cell.toggle.onValueChanged:AddListener(function(isOn)
if isOn then
self:_SetMissionFilterType(config.missionFilterType)
end
end)
UIUtils.setTabIcons(cell,UIConst.UI_SPRITE_MISSION_TYPE_ICON,config.icon)
end
end)
if currentSelectTab then
currentSelectTab.toggle.isOn = true
self.view.titleTxt.text = currentSelectConfig.typeText
end
end
MissionCtrl._SetMissionFilterType = HL.Method(HL.Any) << function(self, filterType)
if self.m_missionFilterType == filterType then
return
end
self.m_missionFilterType = filterType
for _, missionTypeConfig in pairs(MissionFilterCellConfig) do
if filterType == missionTypeConfig.missionFilterType then
self.view.titleTxt.text = missionTypeConfig.typeText
break
end
end
self:_RefreshMissionList()
self:_AutoSelectMission(false)
self:_ChangeSelectedMission(0)
self:_RefreshNaviSelected()
if not string.isEmpty(self.m_selectedMissionId) then
local missionInfo = self.m_missionSystem:GetMissionInfo(self.m_selectedMissionId)
if self.m_missionFilterType == MissionFilterType_All or self.m_missionFilterType == missionInfo.viewType then
self.view.missionInfoNode.gameObject:SetActive(true)
else
self.view.missionInfoNode.gameObject:SetActive(false)
end
end
end
MissionCtrl._AutoSelectMission = HL.Method(HL.Boolean) << function(self, isFirst)
local trackMissionId = self.m_missionSystem.trackMissionId
local priority = 0
local toBeSelectedMissionId = ""
for _, viewInfo in pairs(self.m_missionViewInfo) do
if viewInfo.type == MissionListCellType_Chapter then
for _, missionViewInfo in pairs(viewInfo.missionList) do
local missionId = missionViewInfo.id
if (not DeviceInfo.usingController or isFirst) and self.m_selectedMissionId and missionId == self.m_selectedMissionId and priority < 3 then
toBeSelectedMissionId = missionId
priority = 3
elseif missionId == trackMissionId and priority < 2 then
toBeSelectedMissionId = missionId
priority = 2
elseif missionId and string.isEmpty(toBeSelectedMissionId) and priority < 1 then
toBeSelectedMissionId = missionId
priority = 1
end
end
else
local missionId = viewInfo.id
if (not DeviceInfo.usingController or isFirst) and self.m_selectedMissionId and missionId == self.m_selectedMissionId and priority < 3 then
toBeSelectedMissionId = missionId
priority = 3
elseif missionId == trackMissionId and priority < 2 then
toBeSelectedMissionId = missionId
priority = 2
elseif missionId and string.isEmpty(toBeSelectedMissionId) and priority < 1 then
toBeSelectedMissionId = missionId
priority = 1
end
end
end
if not isFirst then
self.m_lastSelectedMissionId = self.m_selectedMissionId
end
if self.m_selectedMissionId ~= toBeSelectedMissionId then
self.m_selectedMissionId = toBeSelectedMissionId
self:_RefreshSelectedMission()
self:_RefreshMissionInfo()
end
end
MissionCtrl._TraverseAllMissionCell = HL.Method(HL.Any).Return(HL.Boolean) << function(self, callback)
local hasLastSelectMission = false
for i, viewInfo in ipairs(self.m_missionViewInfo) do
local t = viewInfo.type
if t == MissionListCellType_Mission then
local missionId = viewInfo.id
if missionId == self.m_lastSelectedMissionId then
hasLastSelectMission = true
end
local csIdx = CSIndex(i)
local gameObject = self.view.missionScrollView:Get(csIdx)
if gameObject then
local contentCell = self.m_getMissionCellsFunc(gameObject)
callback(missionId, contentCell.missionCell)
end
elseif t == MissionListCellType_Chapter then
local csIdx = CSIndex(i)
local gameObject = self.view.missionScrollView:Get(csIdx)
if gameObject then
local contentCell = self.m_getMissionCellsFunc(gameObject)
local missionList = viewInfo.missionList
for missionIdx = 1, #missionList do
local missionId = missionList[missionIdx].id
if missionId == self.m_lastSelectedMissionId then
hasLastSelectMission = true
end
local missionCell = contentCell.missionCellCache:GetItem(missionIdx)
callback(missionId, missionCell)
end
end
end
end
return hasLastSelectMission
end
MissionCtrl._RefreshEmptyNode = HL.Method() << function(self)
local noMission = #self.m_missionViewInfo <= 0
if noMission then
self.view.missionListNodeState:SetState("None")
self.view.missionInfoNodeState:SetState("None")
else
self.view.missionListNodeState:SetState("Any")
self.view.missionInfoNodeState:SetState("Any")
end
self.view.emptyNode.gameObject:SetActive(noMission)
local filterCellConfig = nil
for _, c in pairs(MissionFilterCellConfig) do
if self.m_missionFilterType == c.missionFilterType then
filterCellConfig = c
break
end
end
if filterCellConfig then
self.view.emptyIcon.gameObject:SetActive(true)
self.view.emptyIcon:LoadSprite(UIConst.UI_SPRITE_MISSION_TYPE_ICON, filterCellConfig.icon)
else
self.view.emptyIcon.gameObject:SetActive(false)
end
end
MissionCtrl._RefreshMissionList = HL.Method() << function(self)
local missionFilterType = self.m_missionFilterType
if missionFilterType ~= MissionFilterType_All then
missionFilterType = missionFilterType:ToInt()
end
local trackMissionId = self.m_missionSystem.trackMissionId
self.m_missionViewInfo = {}
local viewInfoByImportance = {}
local missionLayout = self.m_missionSystem:GetMissionListLayout_CBT3(missionFilterType)
for importance, subLayout in pairs(missionLayout.importance) do
local subViewInfo = {}
table.insert(viewInfoByImportance, {importance = importance, info = subViewInfo})
table.insert(subViewInfo, {type = MissionListCellType_Importance, importance = importance})
for _, chapter in pairs(subLayout.chapters) do
local missionList = {}
table.insert(subViewInfo,
{ type = MissionListCellType_Chapter,
id = chapter.chapterId, missionList = missionList}
)
for _, missionId in pairs(chapter.missionList) do
table.insert(missionList, {type = MissionListCellType_Mission, id = missionId, importance = importance})
end
table.sort(missionList, function(a, b)
self:_SortMissions(a, b)
end)
end
for _, missionId in pairs(subLayout.standaloneMissions) do
table.insert(subViewInfo, {type = MissionListCellType_Mission, id = missionId, importance = importance})
end
table.sort(subViewInfo, function(a, b)
if a.type == b.type then
local viewType = a.type
if viewType == MissionListCellType_Chapter then
local chapterA = self.m_missionSystem:GetChapterInfo(a.id)
local chapterB = self.m_missionSystem:GetChapterInfo(b.id)
local aType = chapterA.type:ToInt()
local bType= chapterB.type:ToInt()
if aType == bType then
local aMission = a.missionList[1]
local bMission = b.missionList[1]
if aMission ~= nil and bMission ~= nil then
return self:_SortMissions(aMission, bMission)
else
return false
end
else
return aType < bType
end
elseif viewType == MissionListCellType_Mission then
return self:_SortMissions(a, b)
else
return false
end
else
return a.type < b.type
end
end)
end
table.sort(viewInfoByImportance, function(a, b)
return a.importance:ToInt() <= b.importance:ToInt()
end)
for _, infoList in ipairs(viewInfoByImportance) do
for _, info in ipairs(infoList.info) do
table.insert(self.m_missionViewInfo, info)
end
end
self:_RefreshEmptyNode()
self.view.missionScrollView.getCellSize = function(index)
local luaIdx = LuaIndex(index)
local viewInfo = self.m_missionViewInfo[luaIdx]
if viewInfo.type == MissionListCellType_Chapter then
return 219 + 112 * #viewInfo.missionList
elseif viewInfo.type == MissionListCellType_Mission then
return 112
elseif viewInfo.type == MissionListCellType_Importance then
return 87
end
end
local firstImportanceFound = false
for i = 1, #self.m_missionViewInfo do
local viewInfo = self.m_missionViewInfo[i]
if viewInfo.type == MissionListCellType_Importance and (not firstImportanceFound) then
viewInfo.isFirstImportance = true
firstImportanceFound = true
end
end
self.view.missionScrollView.onUpdateCell:RemoveAllListeners()
self.view.missionScrollView.onUpdateCell:AddListener(function(gameObject, index)
local luaIndex = LuaIndex(index)
local content = self.m_getMissionCellsFunc(gameObject)
local viewInfo = self.m_missionViewInfo[luaIndex]
if viewInfo.type == MissionListCellType_Chapter then
content.chapterCell.gameObject:SetActiveIfNecessary(true)
content.missionCell.gameObject:SetActiveIfNecessary(false)
content.importanceNode.gameObject:SetActiveIfNecessary(false)
local chapterCell = content.chapterCell
local chapterId = self.m_missionViewInfo[luaIndex].id
local chapterInfo = self.m_missionSystem:GetChapterInfo(chapterId)
if chapterInfo then
if chapterInfo.type == ChapterType.Main then
chapterCell.episodeName:SetAndResolveTextStyle(chapterInfo.episodeName:GetText())
local chapterNumTxt = chapterInfo.chapterNum:GetText()
local episodeNumTxt = chapterInfo.episodeNum:GetText()
local separator = ""
if not string.isEmpty(chapterNumTxt) and not string.isEmpty(episodeNumTxt) then
separator = " - "
end
chapterCell.chapterNumAndEpisodeNum:SetAndResolveTextStyle(chapterNumTxt .. separator .. episodeNumTxt)
local chapterConfig = UIConst.CHAPTER_ICON_CONFIGS[chapterInfo.type]
if not string.isEmpty(chapterInfo.icon) then
chapterCell.icon.gameObject:SetActive(true)
chapterCell.icon:LoadSprite(CHAPTER_ICON_PATH, chapterInfo.icon)
elseif not string.isEmpty(chapterConfig.icon) then
chapterCell.icon.gameObject:SetActive(true)
chapterCell.icon:LoadSprite(CHAPTER_ICON_PATH, chapterConfig.icon)
else
chapterCell.icon.gameObject:SetActive(false)
chapterCell.icon.sprite = nil
end
if not string.isEmpty(chapterInfo.bgIcon) then
chapterCell.bgIcon.gameObject:SetActive(true)
chapterCell.bgIcon:LoadSprite(CHAPTER_BG_ICON_PATH, chapterInfo.bgIcon)
elseif not string.isEmpty(chapterConfig.bgIcon) then
chapterCell.bgIcon.gameObject:SetActive(true)
chapterCell.bgIcon:LoadSprite(CHAPTER_BG_ICON_PATH, chapterConfig.bgIcon)
else
chapterCell.bgIcon.gameObject:SetActive(false)
chapterCell.bgIcon.sprite = nil
end
chapterCell.titleNode1.gameObject:SetActiveIfNecessary(true)
chapterCell.titleNode2.gameObject:SetActiveIfNecessary(false)
else
chapterCell.titleTxt:SetAndResolveTextStyle(chapterInfo.episodeName:GetText())
chapterCell.titleNode1.gameObject:SetActiveIfNecessary(false)
chapterCell.titleNode2.gameObject:SetActiveIfNecessary(true)
end
local missionList = self.m_missionViewInfo[luaIndex].missionList
content.missionCellCache = content.missionCellCache or UIUtils.genCellCache(chapterCell.missionCell)
content.missionCellCache:Refresh(#missionList, function(missionCell, luaIndex)
local mission = missionList[luaIndex]
local missionId = mission.id
local missionInfo = self.m_missionSystem:GetMissionInfo(missionId)
local importance = mission.importance
if missionInfo then
self:_SetMissionCellContent(missionCell, missionInfo, importance)
end
end)
end
elseif viewInfo.type == MissionListCellType_Mission then
content.chapterCell.gameObject:SetActiveIfNecessary(false)
content.missionCell.gameObject:SetActiveIfNecessary(true)
content.importanceNode.gameObject:SetActiveIfNecessary(false)
local missionCell = content.missionCell
local missionId = self.m_missionViewInfo[luaIndex].id
local missionInfo = self.m_missionSystem:GetMissionInfo(missionId)
local importance = viewInfo.importance
if missionInfo then
self:_SetMissionCellContent(missionCell, missionInfo, importance)
end
elseif viewInfo.type == MissionListCellType_Importance then
content.chapterCell.gameObject:SetActiveIfNecessary(false)
content.missionCell.gameObject:SetActiveIfNecessary(false)
content.importanceNode.gameObject:SetActiveIfNecessary(true)
content.importanceLayout.gameObject:SetActiveIfNecessary(not viewInfo.isFirstImportance)
local importance = viewInfo.importance
local targetState = "Vital"
if importance == MissionImportance.High then
targetState = "Vital"
elseif importance == MissionImportance.Mid then
targetState = "Secondary"
elseif importance == MissionImportance.Low then
targetState = "Normal"
end
content.importanceNodeStateController:SetState(targetState)
end
LayoutRebuilder.ForceRebuildLayoutImmediate(content.transform)
end)
self.view.missionScrollView:UpdateCount(#self.m_missionViewInfo)
end
MissionCtrl._SortMissions = HL.Method(HL.Any, HL.Any).Return(HL.Boolean) << function(self, a, b)
if a.type ~= MissionListCellType_Mission or b.type ~= MissionListCellType_Mission then
return false
end
local missionA = self.m_missionSystem:GetMissionInfo(a.id)
local missionB = self.m_missionSystem:GetMissionInfo(b.id)
local missionDataA = self.m_missionSystem:GetMissionData(a.id)
local missionDataB = self.m_missionSystem:GetMissionData(b.id)
if missionA == nil or missionDataA == nil or missionB == nil or missionDataB == nil then
return false
end
if missionA.sortId ~= missionB.sortId then
return a.sortId > b.sortId
end
if missionA.willUnlockOtherThings ~= missionB.willUnlockOtherThings then
return missionA.willUnlockOtherThings
end
local _, aTypeInfo = Tables.missionTypeInfoTable:TryGetValue(missionA.missionType)
local _, bTypeInfo = Tables.missionTypeInfoTable:TryGetValue(missionB.missionType)
if aTypeInfo ~= nil and bTypeInfo ~= nil then
local missionTypeOrderA = aTypeInfo.typePriority
local missionTypeOrderB = bTypeInfo.typePriority
if missionTypeOrderA == missionTypeOrderB then
if missionDataA.acceptTime == missionDataB.acceptTime then
return missionA.missionId > missionB.missionId
else
return missionDataA.acceptTime > missionDataB.acceptTime
end
else
return missionTypeOrderA > missionTypeOrderB
end
else
return aTypeInfo == nil
end
end
MissionCtrl._RefreshSelectedMission = HL.Method() << function(self)
local hasLastSelectMission = self:_TraverseAllMissionCell(function(missionId, missionCell)
local selected = missionId == self.m_selectedMissionId
if missionId == self.m_lastSelectedMissionId and not selected then
AudioAdapter.PostEvent("Au_UI_Toggle_Common_Off")
end
if missionId ~= self.m_lastSelectedMissionId and selected then
AudioAdapter.PostEvent("Au_UI_Toggle_Common_On")
end
self:_SetMissionCellSelected(missionCell, selected)
end)
if not hasLastSelectMission then
AudioAdapter.PostEvent("Au_UI_Toggle_Common_Off")
end
end
MissionCtrl._RefreshNaviSelected = HL.Method() << function(self)
if not DeviceInfo.usingController then
return
end
self:_TraverseAllMissionCell(function(missionId, missionCell)
local isSelected = missionId == self.m_selectedMissionId
if isSelected then
UIUtils.setAsNaviTarget(missionCell.selectBtn)
end
end)
end
MissionCtrl._SetMissionCellSelected = HL.Method(HL.Any, HL.Boolean) << function(self, missionCell, selected)
missionCell.stateController:SetState(selected and "SelectedBg" or "NormalBg")
end
MissionCtrl._SetMissionCellTrack = HL.Method(HL.Any, HL.Any) << function(self, missionCell, missionInfo)
local missionId = missionInfo.missionId
local track = (missionInfo.missionId == self.m_missionSystem.trackMissionId)
if missionInfo.isConflicted or missionInfo.isBlocked then
missionCell.missionLevelName.color = self.view.config.MISSION_LEVEL_BLOCK_FONT_COLOR
local txt = missionInfo.isConflicted and Language.ui_mis_panel_conflict_list_notice
or Language.ui_mis_panel_block_quest_list_notice
missionCell.missionLevelName:SetAndResolveTextStyle(txt)
else
missionCell.missionLevelName.color = self.view.config.MISSION_LEVEL_NORMAL_FONT_COLOR
if track then
missionCell.missionTrackTip.gameObject:SetActive(true)
local distance = self.m_missionSystem:GetMissionTrackDistance(missionId)
if distance > 0 then
missionCell.missionLevelName.text = tostring(math.floor(distance + 0.5)) .. " m"
else
local levelId = self:_GetLevelId(missionInfo)
local _, levelInfo = Tables.levelDescTable:TryGetValue(levelId)
if levelInfo then
missionCell.missionLevelName:SetAndResolveTextStyle(levelInfo.showName)
else
missionCell.missionLevelName:SetAndResolveTextStyle(Language[levelId])
end
end
else
missionCell.missionTrackTip.gameObject:SetActive(false)
local levelId = self:_GetLevelId(missionInfo)
local _, levelInfo = Tables.levelDescTable:TryGetValue(levelId)
if levelInfo then
missionCell.missionLevelName:SetAndResolveTextStyle(levelInfo.showName)
else
missionCell.missionLevelName:SetAndResolveTextStyle(Language[levelId])
end
end
end
end
MissionCtrl._SetMissionCellContent = HL.Method(HL.Any, HL.Any, HL.Any) << function(self, missionCell, missionInfo, importance)
local missionId = missionInfo.missionId
missionCell.missionNameTxt:SetAndResolveTextStyle(missionInfo.missionName:GetText())
missionCell.selectBtn.onClick:RemoveAllListeners()
missionCell.selectBtn.onClick:AddListener(function()
if self.m_selectedMissionId ~= missionId then
self.m_lastSelectedMissionId = self.m_selectedMissionId
self.m_selectedMissionId = missionId
self:_RefreshSelectedMission()
self.view.missionInfoNode.animation:SkipInAnimation()
self.view.missionInfoNode.animation:PlayInAnimation()
self:_RefreshMissionInfo()
end
end)
local missionViewType = missionInfo.viewType
local icon = UIConst.MISSION_VIEW_TYPE_CONFIG[missionViewType].missionIcon
missionCell.missionIcon:LoadSprite(UIConst.UI_SPRITE_MISSION_TYPE_ICON, icon)
local willExpire, timeStamp = MissionSystem.GetMissionExpireInfo(missionId)
missionCell.redDot.gameObject:SetActive(willExpire)
if willExpire then
missionCell.unlockIcon.gameObject:SetActiveIfNecessary(false)
else
local willUnlock = missionInfo.willUnlockOtherThings
missionCell.unlockIcon.gameObject:SetActiveIfNecessary(willUnlock)
end
missionCell.charaIconImage.gameObject:SetActiveIfNecessary(false)
local chapterId = self.m_missionSystem:GetChapterIdByMissionId(missionId)
if chapterId and chapterId ~= nil then
local chapterInfo = self.m_missionSystem:GetChapterInfo(chapterId)
if chapterInfo and chapterInfo.type == ChapterType.Other then
missionCell.charaIconImage.gameObject:SetActiveIfNecessary(true)
local characterId = missionInfo.charId
local _, characterImgInfo = Tables.actorImageTable:TryGetValue(characterId)
if characterImgInfo then
missionCell.charaIconImage:LoadSprite(CHAPTER_CHAR_ICON_PATH, characterImgInfo.missionPanelChrAvatarPath)
end
end
end
local isMissionSelected = self.m_selectedMissionId == missionId
self:_SetMissionCellTrack(missionCell, missionInfo)
self:_SetMissionCellSelected(missionCell, isMissionSelected)
local importanceState = MissionImportanceColorMap[importance]
missionCell.stateController:SetState(importanceState)
local rightState = "Rightempty"
if missionId == self.m_missionSystem:GetTrackMissionId() then
rightState = "MissionTrack"
elseif missionInfo.isBlocked then
rightState = "Lock"
elseif missionInfo.isConflicted then
rightState = "Forbidder"
end
missionCell.stateController:SetState(rightState)
if missionId == self.m_selectedMissionId then
missionCell.stateController:SetState("SelectedBg")
else
missionCell.stateController:SetState("NormalBg")
end
end
MissionCtrl._RefreshMissionInfo = HL.Method() << function(self)
local bSelectedMissionValid = false
if not string.isEmpty(self.m_selectedMissionId) then
local missionData = self.m_missionSystem:GetMissionData(self.m_selectedMissionId)
local missionInfo = self.m_missionSystem:GetMissionInfo(self.m_selectedMissionId)
if missionData and missionInfo then
local missionInfoNode = self.view.missionInfoNode
bSelectedMissionValid = true
self.view.missionInfoNodeState:SetState("Any")
local missionNameText = missionInfo.missionName:GetText()
missionInfoNode.missionName:SetAndResolveTextStyle(missionNameText)
local missionDescText = missionInfo:GetMissionDesc():GetText()
missionInfoNode.missionDesc:SetAndResolveTextStyle(missionDescText)
local levelId = self:_GetLevelId(missionInfo)
local _, sceneInfo = Tables.levelDescTable:TryGetValue(levelId)
if sceneInfo then
missionInfoNode.missionLevelName:SetAndResolveTextStyle(sceneInfo.showName)
else
missionInfoNode.missionLevelName:SetAndResolveTextStyle(Language[levelId])
end
self.m_willExpire, self.m_timeStamp = MissionSystem.GetMissionExpireInfo(self.m_selectedMissionId)
missionInfoNode.timerNode.gameObject:SetActiveIfNecessary(self.m_willExpire)
self:_UpdateExpireTime()
local willUnlock = missionInfo.willUnlockOtherThings
missionInfoNode.unlockNode.gameObject:SetActiveIfNecessary(willUnlock)
if willUnlock then
local unlockText = missionInfo.missionUnlockText
missionInfoNode.unlockText:SetAndResolveTextStyle(unlockText)
end
missionInfoNode.packageList.gameObject:SetActiveIfNecessary(false)
missionInfoNode.trustBtn.gameObject:SetActiveIfNecessary(false)
missionInfoNode.trustBtn.onClick:RemoveAllListeners()
local externalSysType = missionInfo.externalSystemType
local externalId = missionInfo.externalSystemId
local isPackage = externalSysType == MissionExternalSystemType.DomainDepot
if isPackage then
local packageList = missionInfoNode.packageList
local deliverInfo = GameInstance.player.domainDepotSystem:GetDomainDepotDeliverInfoByInstId(tonumber(externalId))
local inDeliver = deliverInfo.packageProgress == DomainDepotPackageProgress.WaitingRecvPackage or
deliverInfo.packageProgress == DomainDepotPackageProgress.WaitingSendPackage
if deliverInfo ~= nil and inDeliver then
if not deliverInfo.delegateFromOther then
missionInfoNode.trustBtn.gameObject:SetActiveIfNecessary(true)
missionInfoNode.trustBtn.onClick:AddListener(function()
self:Notify(MessageConst.SHOW_POP_UP, {
content = Language.ui_mis_deliver_title,
warningContent = Language.ui_mis_deliver_text_1,
secondWarningContent = Language.ui_mis_deliver_text_2,
onConfirm = function()
DomainDepotUtils.DelegateCurrentDeliver()
PhaseManager:PopPhase(PHASE_ID)
end,
})
end)
end
if deliverInfo.packageProgress == DomainDepotPackageProgress.WaitingSendPackage then
local progress = deliverInfo.cargoIntegrity
local packageTitleState
if progress > 70 then
packageTitleState = "GreaterThan70"
elseif progress > 30 then
packageTitleState = "GreaterThan30"
else
packageTitleState = "GreaterThan0"
end
packageList.titleNode:SetState(packageTitleState)
packageList.packageNumTxt:SetAndResolveTextStyle(progress .. "%")
DomainDepotUtils.UpdateReduceView(self.m_packageNode, deliverInfo.itemType)
packageList.gameObject:SetActiveIfNecessary(true)
end
end
end
self:_RefreshTrackBtn()
missionInfoNode.infoBtn.onClick:RemoveAllListeners()
if missionInfo.isBlocked then
missionInfoNode.lockTipsNode.gameObject:SetActiveIfNecessary(true)
missionInfoNode.leftTipsNode.gameObject:SetActiveIfNecessary(false)
missionInfoNode.mapBtn.gameObject:SetActiveIfNecessary(false)
local cList = BlockConditionListType()
missionInfo:AddBlockConditionDescToList(cList)
local blockCnt = 0
local blockIdx = -1
local conditions = {}
for i = 0, cList.Count - 1 do
local condition = cList[i]
table.insert(conditions, {
jumpId = nil,
desc = condition.desc,
tips = "",
isComplete = condition.isComplete
})
if not condition.isComplete then
blockCnt = blockCnt + 1
blockIdx = i
end
end
if blockCnt == 1 then
missionInfoNode.infoBtn.gameObject:SetActiveIfNecessary(false)
missionInfoNode.tipsTxt:SetAndResolveTextStyle(cList[blockIdx].desc)
elseif blockCnt > 1 then
missionInfoNode.infoBtn.gameObject:SetActiveIfNecessary(true)
missionInfoNode.tipsTxt:SetAndResolveTextStyle(Language.ui_mis_panel_block_quest_notice)
missionInfoNode.infoBtn.onClick:AddListener(function()
UIManager:Open(PanelId.ActivityStartReminderPopup,{
title = Language.ui_mis_block_quest_subtitle,
conditions = conditions,
mainTitle = Language.ui_mis_block_quest_title,
drawMode = ActivityConst.ACTIVITY_REMINDER_DRAW_MODE.NoComplete
})
end)
end
else
missionInfoNode.lockTipsNode.gameObject:SetActiveIfNecessary(false)
missionInfoNode.leftTipsNode.gameObject:SetActiveIfNecessary(missionInfo.isConflicted)
local missionId = missionInfo.missionId
if missionId == self.m_missionSystem.trackMissionId and self.m_missionSystem:HasTrackDataForMap() then
missionInfoNode.mapBtn.gameObject:SetActive(true)
missionInfoNode.mapBtn.onClick:RemoveAllListeners()
missionInfoNode.mapBtn.onClick:AddListener(function()
if not string.isEmpty(self.m_missionSystem.trackMissionId) then
if self.m_missionSystem:HasShowedTrackDataForMap() then
MapUtils.openMapByMissionId(self.m_missionSystem.trackMissionId)
else
Notify(MessageConst.SHOW_TOAST, Language.ui_mis_toast_map_in_challenge)
end
end
end)
else
missionInfoNode.mapBtn.gameObject:SetActive(false)
missionInfoNode.mapBtn.onClick:RemoveAllListeners()
end
end
self:_RefreshObjectiveProgress(self.m_selectedMissionId)
local rewardItemBundles = {}
if not (missionInfo.isWrapperMission and missionInfo.useRewardWrapper) then
local findReward, rewardData = Tables.rewardTable:TryGetValue(missionInfo.rewardId or "")
if findReward then
for _,itemBundle in pairs(rewardData.itemBundles) do
local itemData = Tables.itemTable[itemBundle.id]
table.insert(rewardItemBundles, {
id = itemBundle.id,
count = itemBundle.count,
sortId1 = itemData.sortId1,
sortId2 = itemData.sortId2,
rarity = itemData.rarity,
})
end
end
else
local externalType = missionInfo.externalSystemType
local externalId = missionInfo.externalSystemId
local rewardInfoGot, rewardItemIds, rewardItemNums = CS.Beyond.Gameplay.MissionSystem.TryGetWrapperMissionReward(externalType, externalId)
if rewardInfoGot then
for i = 0, rewardItemIds.Count - 1 do
local itemData = Tables.itemTable[rewardItemIds[i]]
table.insert(rewardItemBundles, {
id = rewardItemIds[i],
count = rewardItemNums[i],
sortId1 = itemData.sortId1,
sortId2 = itemData.sortId2,
rarity = itemData.rarity,
})
end
end
end
table.sort(rewardItemBundles, Utils.genSortFunction(UIConst.COMMON_ITEM_SORT_KEYS))
local hasReward = #rewardItemBundles > 0
self.view.rewardFocusKeyHint.gameObject:SetActive(hasReward)
if hasReward then
self.view.rewardsNode.gameObject:SetActive(true)
self.m_getRewardItemCellsFunc = self.m_getRewardItemCellsFunc or UIUtils.genCachedCellFunction(self.view.rewardScrollList)
self.view.rewardScrollList.onUpdateCell:RemoveAllListeners();
self.view.rewardScrollList.onUpdateCell:AddListener(function(gameObject, index)
local itemCell = self.m_getRewardItemCellsFunc(gameObject)
local luaIdx = LuaIndex(index)
itemCell:InitItem(rewardItemBundles[luaIdx], true)
if DeviceInfo.usingController then
itemCell:SetExtraInfo({
isSideTips = true,
})
end
end)
self.view.rewardScrollList:UpdateCount(#rewardItemBundles)
local firstItemGo = self.view.rewardScrollList:Get(0)
if firstItemGo then
self.view.rewardFocusKeyHint.transform.position = firstItemGo.transform.position
local keyHintPos = self.view.rewardFocusKeyHint.transform.localPosition
keyHintPos.x = keyHintPos.x - 50
keyHintPos.y = keyHintPos.y - 30
self.view.rewardFocusKeyHint.transform.localPosition = keyHintPos
end
else
self.view.rewardsNode.gameObject:SetActive(false)
end
end
end
if not bSelectedMissionValid then
self.view.missionInfoNodeState:SetState("None")
end
end
MissionCtrl._RefreshObjectiveProgress = HL.Method(HL.String) << function(self, missionId)
if string.isEmpty(missionId) then
return
end
local displayQuestIds = self.m_missionSystem:GetDisplayQuestIdsByMissionId(missionId)
local missionInfo = self.m_missionSystem:GetMissionInfo(missionId)
if displayQuestIds and missionInfo then
local displayQuestCount = displayQuestIds.Count
self.m_questCellCache:Refresh(displayQuestCount, function(questCell, luaIdx)
local csIdx = CSIndex(luaIdx)
local questId = displayQuestIds[csIdx]
local questInfo = self.m_missionSystem:GetQuestInfo(questId)
local questData = self.m_missionSystem:GetQuestData(questId)
local objectiveCountInQuest = questInfo.objectiveList.Count
if not missionInfo.isBlocked and objectiveCountInQuest > 0 then
questCell.gameObject:SetActive(true)
local allObjectiveComplete = true
for _, objective in pairs(questInfo.objectiveList) do
if not objective.isCompleted then
allObjectiveComplete = false
break
end
end
questCell.normalIcon.gameObject:SetActive(not allObjectiveComplete)
questCell.completeIcon.gameObject:SetActive(allObjectiveComplete)
questCell.multiObjectiveDeco.gameObject:SetActive(objectiveCountInQuest > 1)
local optional = questInfo.questType == QuestType.Optional
questCell.objectiveCache = questCell.objectiveCache or UIUtils.genCellCache(questCell.objectiveCell)
questCell.objectiveCache:Refresh(objectiveCountInQuest, function(objectiveCell, objectiveLuaIdx)
local objectiveCSIdx = CSIndex(objectiveLuaIdx)
local objective = questInfo.objectiveList[objectiveCSIdx]
local descTxt = nil
if not objective.useStrDesc then
if optional then
descTxt = string.format("<color=#%s>%s</color> %s", OPTIONAL_TEXT_COLOR, Language.ui_optional_quest, objective.runtimeDescription:GetText())
else
descTxt = objective.runtimeDescription:GetText()
end
else
descTxt = objective.descStr
end
if objective.isCompleted then
descTxt = descTxt:gsub("<@qu%.key>", ""):gsub("</>", "")
end
objectiveCell.desc:SetAndResolveTextStyle(descTxt)
if not missionInfo.isConflicted and objective.isShowProgress then
objectiveCell.progress.gameObject:SetActive(true)
if objective.isCompleted then
objectiveCell.progress.text = string.format("%d/%d", objective.progressToCompareForShow, objective.progressToCompareForShow)
else
objectiveCell.progress.text = string.format("%d/%d", objective.progressForShow, objective.progressToCompareForShow)
end
else
objectiveCell.progress.gameObject:SetActive(false)
end
if objective.isCompleted then
objectiveCell.desc.color = self.view.config.OBJECTIVE_COMPLETE_FONT_COLOR
objectiveCell.progress.color = self.view.config.OBJECTIVE_COMPLETE_FONT_COLOR
else
objectiveCell.desc.color = self.view.config.OBJECTIVE_NORMAL_FONT_COLOR
objectiveCell.progress.color = self.view.config.OBJECTIVE_NORMAL_FONT_COLOR
end
end)
else
questCell.gameObject:SetActive(false)
end
end)
end
end
MissionCtrl._RefreshTrackBtn = HL.Method() << function(self)
local missionInfoNode = self.view.missionInfoNode
local trackMissionId = self.m_missionSystem:GetTrackMissionId()
missionInfoNode.trackBtn.onClick:RemoveAllListeners()
missionInfoNode.stopBtn.onClick:RemoveAllListeners()
local missionInfo = self.m_missionSystem:GetMissionInfo(self.m_selectedMissionId)
if missionInfo.isBlocked then
missionInfoNode.stopBtn.gameObject:SetActive(false)
missionInfoNode.trackBtn.gameObject:SetActive(false)
else
if trackMissionId == self.m_selectedMissionId then
missionInfoNode.trackBtn.gameObject:SetActive(false)
missionInfoNode.stopBtn.gameObject:SetActive(true)
else
missionInfoNode.trackBtn.gameObject:SetActive(true)
missionInfoNode.stopBtn.gameObject:SetActive(false)
end
missionInfoNode.trackBtn.onClick:AddListener(function()
local id = self.m_selectedMissionId
local sys = self.m_missionSystem
sys:PushSkipNextTrackInOrOut(self.m_selectedMissionId)
sys:TrackMission(id)
self.m_isClosing = true
self:PlayAnimationOutWithCallback(function()
Notify(MessageConst.RECOVER_PHASE_LEVEL)
end)
end)
missionInfoNode.stopBtn.onClick:AddListener(function()
local sys = self.m_missionSystem
sys:PushSkipNextTrackInOrOut(self.m_selectedMissionId)
self.m_missionSystem:StopTrackMission()
end)
end
end
MissionCtrl._RefreshMissionTrackTip = HL.Method() << function(self)
self:_TraverseAllMissionCell(function(missionId, missionCell)
local missionInfo = self.m_missionSystem:GetMissionInfo(missionId)
self:_SetMissionCellTrack(missionCell, missionInfo)
end)
end
MissionCtrl.OnObjectiveUpdate = HL.Method(HL.Any) << function(self, arg)
local questId = unpack(arg)
local missionId = self.m_missionSystem:GetMissionIdByQuestId(questId)
if not string.isEmpty(self.m_selectedMissionId) and self.m_selectedMissionId == missionId then
self:_RefreshObjectiveProgress(missionId)
end
end
MissionCtrl.OnTrackMissionChange = HL.Method() << function(self)
if self.m_isClosing then
return
end
self:_RefreshTrackBtn()
self:_RefreshMissionTrackTip()
self:_UpdateCurrentDisplayTrackBtn()
end
MissionCtrl._UpdateCurrentDisplayTrackBtn = HL.Method() << function(self)
local missionInfo = self.m_missionSystem:GetMissionInfo(self.m_selectedMissionId)
if not missionInfo then
return
end
local missionId = missionInfo.missionId
local missionInfoNode = self.view.missionInfoNode
if missionId == self.m_missionSystem.trackMissionId and self.m_missionSystem:HasTrackDataForMap() then
missionInfoNode.mapBtn.gameObject:SetActive(true)
missionInfoNode.mapBtn.onClick:RemoveAllListeners()
missionInfoNode.mapBtn.onClick:AddListener(function()
if not string.isEmpty(self.m_missionSystem.trackMissionId) then
if self.m_missionSystem:HasShowedTrackDataForMap() then
MapUtils.openMapByMissionId(self.m_missionSystem.trackMissionId)
else
Notify(MessageConst.SHOW_TOAST, Language.ui_mis_toast_map_in_challenge)
end
end
end)
else
missionInfoNode.mapBtn.gameObject:SetActive(false)
missionInfoNode.mapBtn.onClick:RemoveAllListeners()
end
end
MissionCtrl.OnMissionStateChange = HL.Method(HL.Any) << function(self, arg)
if self.m_selectedMissionId ~= "" and self.m_missionSystem:GetMissionState(self.m_selectedMissionId) == MissionState.None then
self.m_selectedMissionId = ""
end
self:_RefreshMissionList()
self:_RefreshSelectedMission()
self:_RefreshMissionInfo()
self:_RefreshEmptyNode()
self:_AutoSelectMission(false)
self:_RefreshNaviSelected()
end
MissionCtrl.OnQuestStateChange = HL.Method(HL.Any) << function(self, arg)
local questId,questState = unpack(arg)
local missionId = self.m_missionSystem:GetMissionIdByQuestId(questId)
if self.m_missionSystem:GetMissionState(missionId) == MissionState.None then
return
end
if missionId == self.m_selectedMissionId then
self:_RefreshMissionInfo()
end
end
MissionCtrl.OnSyncAllMission = HL.Method(HL.Any) << function(self, arg)
self:_RefreshMissionList()
self:_RefreshSelectedMission()
self:_RefreshMissionInfo()
self:_RefreshNaviSelected()
end
MissionCtrl.OnAnimationInFinished = HL.Override() << function(self)
end
MissionCtrl._ChangeSelectedMission = HL.Method(HL.Number) << function(self, offset)
local selectedIndex
local missionIdInfoList = {}
for k, v in ipairs(self.m_missionViewInfo) do
if v.type == MissionListCellType_Chapter then
for kk, missionViewInfo in pairs(v.missionList) do
table.insert(missionIdInfoList, { cellIndex = k, subIndex = kk, id = missionViewInfo.id, })
if missionViewInfo.id == self.m_selectedMissionId then
selectedIndex = #missionIdInfoList
end
end
else
table.insert(missionIdInfoList, { cellIndex = k, id = v.id, })
if v.id == self.m_selectedMissionId then
selectedIndex = #missionIdInfoList
end
end
end
if not selectedIndex then
return
end
local newInfo = missionIdInfoList[selectedIndex + offset]
if not newInfo then
return
end
self.m_selectedMissionId = newInfo.id
self:_RefreshSelectedMission()
self:_RefreshMissionInfo()
self.view.missionScrollView:ScrollToIndex(CSIndex(newInfo.cellIndex), true)
self:_RefreshNaviSelected()
end
MissionCtrl._GetLevelId = HL.Method(HL.Any).Return(HL.String) << function(self, missionInfo)
if (not missionInfo.isWrapperMission) or (not missionInfo.useLevelIdWrapper) then
return missionInfo.levelId or ""
end
local externalType = missionInfo.externalSystemType
local externalId = missionInfo.externalSystemId
return CS.Beyond.Gameplay.MissionSystem.GetWrapperMissionLevelId(externalType, externalId)
end
MissionCtrl._UpdateShow = HL.Method() << function(self)
self:_UpdateExpireTime()
end
MissionCtrl._UpdateExpireTime = HL.Method() << function(self)
if self.m_willExpire then
local leftTime = (self.m_timeStamp - DateTimeUtils.GetCurrentTimestampByMilliseconds()) / 1000
local timeTxt = UIUtils.getLeftTime(leftTime)
self.view.missionInfoNode.timerTxt:SetAndResolveTextStyle(timeTxt)
end
end
HL.Commit(MissionCtrl)