Files
StellaSora_DataLua/lua/game/ui/mainlineex/chapterlinectrl.lua
T
SL1900 8a2a0f2a29 Update - 1.10.1.110
EN: 1.10.1.110
CN: 1.10.1.111
JP: 1.10.1.115
KR: 1.10.1.115
2026-05-26 15:30:00 +09:00

950 lines
35 KiB
Lua

local LocalData = require("GameCore.Data.LocalData")
local ChapterLineCtrl = class("ChapterLineCtrl", BaseCtrl)
local AvgData = PlayerData.Avg
local WwiseAudioMgr = CS.WwiseAudioManager.Instance
local RectTransformUtility = CS.UnityEngine.RectTransformUtility
local GameCameraStackManager = CS.GameCameraStackManager
ChapterLineCtrl._mapNodeConfig = {
tranContent = {
sNodeName = "Content",
sComponentName = "RectTransform"
},
scrollRect = {
sNodeName = "Scroll View",
sComponentName = "ScrollRect"
},
imgMask = {
sNodeName = "ImgMask",
sComponentName = "RectTransform"
},
goImgMaskRoot = {},
layoutContent = {
sNodeName = "Content",
sComponentName = "HorizontalLayoutGroup"
}
}
ChapterLineCtrl._mapEventConfig = {
Story_RewardClosed = "OnEvent_Story_RewardClosed",
Story_Done = "OnEvent_Story_Done"
}
local UnlockConditionPriority = {
[1] = "MustStoryIds",
[2] = "OneofStoryIds",
[3] = "MustEvIds",
[4] = "OneofEvIds",
[5] = "WorldLevel",
[6] = "MustAchievementIds",
[7] = "TimeUnlock"
}
function ChapterLineCtrl:Awake()
self.bCanClick = true
local callback = function()
self.bHasAchievementData = true
end
PlayerData.Achievement:SendAchievementInfoReq(callback)
local tbParam = self:GetPanelParam()
self.curChapter = tbParam[1]
self.curTimeStamp = 0
self.curNodeDepth = 1
self.tbImgFocusNode = {}
self.tbLockedPlayedAnim = {}
self.lineAnimTime = 0.14
self.tbBranchGrid = {}
self.tbLockedBranchGrid = {}
self.bFocusNotReadNode = true
self.Rect = self._mapNode.tranContent:GetComponent("RectTransform")
self:CacheCurChapterConfig()
self:CacheChapterBranchNode()
self:Refresh()
self:AddTimer(1, 0.5, function()
if self.bNeedPlayUnlockAnim or self.bNeedPlayBranchAnim then
if self.bNeedPlayBranchAnim and self.tbNeedPlayUnlockAnimGird[1] ~= nil then
self.curShouldPlayDepth = self.tbNeedPlayUnlockAnimGird[1].depth
end
self:DoPlayUnlockAnim(self.curShouldPlayDepth)
end
end, true, true, true)
end
function ChapterLineCtrl:RefreshFocusNode()
self.tbFocusNode = {}
self.bFocusLastNode = false
local tbNewNodes = AvgData:CheckNewStory(self.curChapter)
for k, v in pairs(tbNewNodes) do
if v == true then
table.insert(self.tbFocusNode, k)
end
end
if #self.tbFocusNode == 0 then
local firstNode = self._mapNode.tranContent:GetChild(1):Find("goGrid"):GetChild(0)
local avgId = firstNode.name
local storyConfig = AvgData:GetStoryCfgData(avgId)
if not AvgData:IsStoryReaded(storyConfig.Id) then
table.insert(self.tbFocusNode, storyConfig.Id)
else
self.bFocusLastNode = true
table.insert(self.tbFocusNode, AvgData:GetRecentStoryId(self.curChapter))
end
end
self.bNeedPlayUnlockAnim = false
self.bNeedPlayBranchAnim = false
for k, v in ipairs(self.tbFocusNode) do
local storyConfig = ConfigTable.GetData_Story(v)
local bHasPlayedAnim = LocalData.GetPlayerLocalData("MainlineUnlock_" .. v)
if bHasPlayedAnim == nil or tonumber(bHasPlayedAnim) == 0 then
if storyConfig.IsBranch == true then
self.bNeedPlayBranchAnim = true
break
end
self.bNeedPlayUnlockAnim = true
break
end
local avgId = storyConfig.StoryId
if 0 < table.indexof(self.tbLockedBranchGrid, avgId) and self.tbBranch[avgId] ~= nil then
for _, branchGrid in ipairs(self.tbBranch[avgId]) do
local bUnlock = AvgData:IsUnlock(branchGrid.ConditionId, branchGrid.StoryId)
if bUnlock then
self.bNeedPlayBranchAnim = true
break
end
end
end
end
end
function ChapterLineCtrl:Refresh()
self._mapNode.goImgMaskRoot.transform:SetParent(self._mapNode.tranContent)
self._mapNode.goImgMaskRoot.transform:SetAsFirstSibling()
self:RefreshFocusNode()
self.tbGridList = {}
self.tbTimeStampList = {}
self.tbDepthLockCount = {}
self.maxUnlockDepth = 1
self.maxStoryDepth = 1
for i = 1, self._mapNode.tranContent.childCount - 1 do
local gridRoot = self._mapNode.tranContent:GetChild(i):Find("goGrid")
local goTimeStamp = self._mapNode.tranContent:GetChild(i):Find("goTimeStamp")
self.tbDepthLockCount[i] = {
Node = self._mapNode.tranContent:GetChild(i),
ChildCount = gridRoot.childCount,
DisableCount = 0
}
for j = 1, gridRoot.childCount do
local goGrid = gridRoot:GetChild(j - 1)
local avgId = goGrid.name
table.insert(self.tbGridList, {
avgId = avgId,
grid = goGrid,
depth = i
})
local storyConfig = AvgData:GetStoryCfgData(avgId)
local bUnlock = AvgData:IsUnlock(storyConfig.ConditionId, storyConfig.StoryId)
if i > self.maxStoryDepth then
self.maxStoryDepth = i
end
if bUnlock and i > self.maxUnlockDepth then
self.maxUnlockDepth = i
end
end
table.insert(self.tbTimeStampList, goTimeStamp)
end
table.sort(self.tbGridList, function(a, b)
return a.depth < b.depth
end)
self:RefreshCurNodeDepthByNewUnlock()
self:RefreshUnlockAnimList()
self.tbBranchOverflowDepths = {}
self.maxLockRootDepth = 0
for k, v in ipairs(self.tbGridList) do
self:RefreshGrid(v.grid, v.depth)
end
self:ApplyLayoutContentRightPadding()
local isComplete = self:IsAllStoryCompleted()
self.curTimeStamp = isComplete and self.curTimeStamp or self.maxUnlockDepth
for i = 1, #self.tbTimeStampList do
self:RefreshTimeStamp(self.tbTimeStampList[i], i)
end
self:AddTimer(1, 0.1, function()
local posX = self.curNodeDepth < 4 and 0 or (self.curNodeDepth - 1) * -512
self._mapNode.tranContent.anchoredPosition = Vector2(posX, 0)
end, true, true, true)
CS.UnityEngine.UI.LayoutRebuilder.ForceRebuildLayoutImmediate(self._mapNode.tranContent)
for k, v in ipairs(self.tbGridList) do
self:RecordGridBorderPos(v.grid)
end
for k, v in ipairs(self.tbGridList) do
self:CheckLineReasonable(v.grid)
end
if self.curTimeStamp - 1 < 0 then
self._mapNode.imgMask.gameObject:SetActive(false)
else
self._mapNode.imgMask.gameObject:SetActive(true)
local node = self._mapNode.tranContent:Find(tostring(self.curNodeDepth))
local layout = self._mapNode.tranContent:GetComponent("HorizontalLayoutGroup")
local pos = node.localPosition.x - layout.padding.left
self._mapNode.imgMask.anchoredPosition = Vector2(pos, -6)
end
end
function ChapterLineCtrl:RefreshGrid(goGrid, gridDepth)
local avgId = goGrid.name
local storyConfig = AvgData:GetStoryCfgData(avgId)
local bUnlock = AvgData:IsUnlock(storyConfig.ConditionId, avgId)
local goLeftBorder = goGrid:Find("goLeftBorder")
local bAllLock = 1 < gridDepth and true or false
for i = 1, #storyConfig.ParentStoryId do
local parentConfig = AvgData:GetStoryCfgData(storyConfig.ParentStoryId[i])
local parentUnlock = AvgData:IsUnlock(parentConfig.ConditionId, parentConfig.StoryId)
if parentUnlock then
bAllLock = false
end
end
if bAllLock then
self.tbDepthLockCount[gridDepth].DisableCount = self.tbDepthLockCount[gridDepth].DisableCount + 1
end
self.tbDepthLockCount[gridDepth].Node.gameObject:SetActive(self.tbDepthLockCount[gridDepth].DisableCount < self.tbDepthLockCount[gridDepth].ChildCount)
local allParentDepthLock = true
if self.tbDepthLockCount[gridDepth - 1] ~= nil and self.tbDepthLockCount[gridDepth - 1] ~= nil then
allParentDepthLock = self.tbDepthLockCount[gridDepth - 1].DisableCount == self.tbDepthLockCount[gridDepth - 1].ChildCount
end
local bNeedPlayUnlockAnim = false
for k, v in ipairs(self.tbNeedPlayUnlockAnimGird) do
if v.avgId == avgId then
bNeedPlayUnlockAnim = true
break
end
end
local bPlayedLockAnim = table.indexof(self.tbLockedPlayedAnim, avgId) > 0
local bShowGrid = (not bAllLock or not allParentDepthLock) and not bNeedPlayUnlockAnim or bPlayedLockAnim
goGrid.gameObject:SetActive(bShowGrid)
local bReaded = AvgData:IsStoryReaded(storyConfig.Id)
local btnEnter = goGrid:Find("btnEnter"):GetComponent("UIButton")
local NormalRoot = btnEnter.transform:Find("AnimRoot/NormalRoot")
local BattleRoot = btnEnter.transform:Find("AnimRoot/BattleRoot")
local BranchRoot = goGrid:Find("BranchRoot")
local LockRoot = btnEnter.transform:Find("AnimRoot/LockRoot")
local imgClue = goGrid:Find("imgClue")
local lineContinue = goGrid:Find("lineContinue")
local goRightBorder = goGrid:Find("goRightBorder")
local txtUnlock = LockRoot:Find("txtUnlock"):GetComponent("TMP_Text")
local cgComp = storyConfig.IsBattle and NormalRoot:GetComponent("CanvasGroup") or BattleRoot:GetComponent("CanvasGroup")
NovaAPI.SetCanvasGroupAlpha(cgComp, bUnlock and 1 or 0.5)
local bShowLockRoot = not bUnlock or bPlayedLockAnim
LockRoot.gameObject:SetActive(bShowLockRoot)
if bShowLockRoot and gridDepth > (self.maxLockRootDepth or 0) then
if bShowGrid then
if self.tbDepthLockCount[gridDepth].Node.gameObject.activeInHierarchy then
self.maxLockRootDepth = gridDepth
end
elseif bNeedPlayUnlockAnim then
self.maxLockRootDepth = gridDepth
end
end
imgClue.gameObject:SetActive(storyConfig.HasEvidence and bUnlock and not bReaded)
local bShowLineContinue = not bUnlock and gridDepth > self.maxUnlockDepth
lineContinue.gameObject:SetActive(bShowLineContinue)
local rootTrans = storyConfig.IsBattle and BattleRoot or NormalRoot
rootTrans.gameObject:SetActive(bUnlock)
local imgFocus = rootTrans:Find("imgFocus")
local RedDot = rootTrans:Find("RedDot")
local bFocus = 0 < table.indexof(self.tbFocusNode, storyConfig.Id) and (not bReaded or self.bFocusLastNode)
imgFocus.gameObject:SetActive(bFocus and not bPlayedLockAnim)
RedDot.gameObject:SetActive(bFocus and not bReaded and not bPlayedLockAnim)
if self.tbBranch[avgId] ~= nil then
for k, v in ipairs(self.tbBranch[avgId]) do
if 0 < table.indexof(self.tbFocusNode, v.Id) then
bFocus = true
break
end
end
end
if bUnlock then
local nodeTimeStampIndex = tonumber(goGrid.transform.parent.parent.name)
if nodeTimeStampIndex > self.curTimeStamp then
if self.tbImgFocusNode[self.curTimeStamp] ~= nil then
for k, v in ipairs(self.tbImgFocusNode[self.curTimeStamp]) do
v.gameObject:SetActive(false)
end
end
self.curTimeStamp = nodeTimeStampIndex
end
if self.tbImgFocusNode[self.curTimeStamp] == nil then
self.tbImgFocusNode[self.curTimeStamp] = {}
end
table.insert(self.tbImgFocusNode[self.curTimeStamp], imgFocus)
end
if bUnlock then
local goReaded = rootTrans:Find("goReaded")
local goNotRead = rootTrans:Find("goNotRead")
local txtNotRead = goNotRead:Find("txtNotRead"):GetComponent("TMP_Text")
local txtLevelName = goReaded:Find("txtLevelName"):GetComponent("TMP_Text")
local txtLevelIndex = goReaded:Find("txtLevelIndex"):GetComponent("TMP_Text")
local txtNewUnlock = goNotRead:Find("txtNewUnlock"):GetComponent("TMP_Text")
goReaded.gameObject:SetActive(bReaded)
goNotRead.gameObject:SetActive(not bReaded)
NovaAPI.SetTMPText(txtNotRead, storyConfig.Index)
NovaAPI.SetTMPText(txtLevelName, storyConfig.Title)
NovaAPI.SetTMPText(txtLevelIndex, storyConfig.Index)
NovaAPI.SetTMPText(txtNewUnlock, ConfigTable.GetUIText("Story_NewStory_Unlock"))
if not storyConfig.IsBattle then
local imgClueReaded = goReaded:Find("imgClueReaded")
imgClueReaded.gameObject:SetActive(storyConfig.HasEvidence)
end
self:PlayUnlockAnim(rootTrans, "Empty")
end
NovaAPI.SetTMPText(txtUnlock, ConfigTable.GetUIText("Story_Unkown_Chapter"))
for i = 1, goRightBorder.childCount do
goRightBorder:GetChild(i - 1).gameObject:SetActive(not bShowLineContinue)
end
if self.tbBranch[avgId] ~= nil then
if bNeedPlayUnlockAnim == false and 0 < table.indexof(self.tbLockedBranchGrid, avgId) then
bNeedPlayUnlockAnim = true
end
self:RefreshBranchGrid(BranchRoot, avgId, gridDepth, bNeedPlayUnlockAnim)
end
btnEnter.onClick:RemoveAllListeners()
btnEnter.onClick:AddListener(function()
self:OnClickGrid(avgId)
end)
end
function ChapterLineCtrl:RecordGridBorderPos(goGrid)
local avgId = goGrid.name
if self.tbGridBorderPos == nil then
self.tbGridBorderPos = {}
end
local uiCamera = GameCameraStackManager.Instance.uiCamera
local imgLeftPoint_1 = goGrid:Find("imgLeftPoint_1"):GetComponent("RectTransform")
local imgRightPoint_1 = goGrid:Find("imgRightPoint_1"):GetComponent("RectTransform")
local leftScreenPos = imgLeftPoint_1 and RectTransformUtility.WorldToScreenPoint(uiCamera, imgLeftPoint_1.position) or nil
local rightScreenPos = imgRightPoint_1 and RectTransformUtility.WorldToScreenPoint(uiCamera, imgRightPoint_1.position) or nil
self.tbGridBorderPos[avgId] = {
left = leftScreenPos,
right = rightScreenPos,
grid = goGrid
}
end
function ChapterLineCtrl:RefreshBranchGrid(root, avgId, depth, isNeedPlayUnlockAnim)
local nUnlockBranchCount = 0
table.sort(self.tbBranch[avgId], function(a, b)
local aUnlock = AvgData:IsUnlock(a.ConditionId, a.StoryId)
local bUnlock = AvgData:IsUnlock(b.ConditionId, b.StoryId)
if aUnlock ~= bUnlock then
return aUnlock
end
return a.StoryId < b.StoryId
end)
for k, v in ipairs(self.tbBranch[avgId]) do
if AvgData:IsUnlock(v.ConditionId, v.StoryId) then
nUnlockBranchCount = nUnlockBranchCount + 1
end
end
local index = 1
local bHasUnlockBranch = false
local bHasUnReadBranch = false
for k, v in ipairs(self.tbBranch[avgId]) do
local bUnlock = AvgData:IsUnlock(v.ConditionId, v.StoryId)
local bReaded = AvgData:IsStoryReaded(v.Id)
local branchGrid = root:Find("BranchGrid_" .. k)
local storyConfig = AvgData:GetStoryCfgData(v.StoryId)
if bUnlock then
bHasUnlockBranch = true
end
if bUnlock and not bReaded then
local hasPlay = LocalData.GetPlayerLocalData("MainlineUnlock_" .. storyConfig.Id)
if hasPlay == nil or tonumber(hasPlay) == 0 then
bHasUnReadBranch = true
end
end
if 0 >= table.indexof(self.tbLockedBranchGrid, avgId) then
table.insert(self.tbLockedBranchGrid, avgId)
end
if bUnlock and 0 < table.indexof(self.tbLockedBranchGrid, avgId) then
table.removebyvalue(self.tbLockedBranchGrid, avgId)
end
if isNeedPlayUnlockAnim and bUnlock then
if not bReaded then
root.gameObject:SetActive(false)
end
table.insert(self.tbNeedPlayUnlockAnimGird, {
grid = root,
avgId = storyConfig.StoryId,
depth = depth,
index = index,
totalCount = nUnlockBranchCount
})
end
if branchGrid ~= nil then
local goUnlock = branchGrid:Find("AnimRoot/goUnlock")
local goLock = branchGrid:Find("AnimRoot/goLock")
local goLevelIndex = branchGrid:Find("AnimRoot/goUnlock/txtLevelIndex")
local txtLevelIndex = goLevelIndex:GetComponent("TMP_Text")
local txtLevelName = txtLevelIndex.transform:Find("txtLevelName"):GetComponent("TMP_Text")
local cgLevelIndex = goLevelIndex:GetComponent("CanvasGroup")
local imgNewUnlockBg = branchGrid:Find("AnimRoot/goUnlock/imgNewUnlockBg")
local imgNewUnlock = branchGrid:Find("AnimRoot/goUnlock/imgNewUnlock")
NovaAPI.SetCanvasGroupAlpha(cgLevelIndex, 1)
NovaAPI.SetTMPText(txtLevelIndex, storyConfig.Index)
goUnlock.gameObject:SetActive(bUnlock)
goLock.gameObject:SetActive(not bUnlock)
txtLevelIndex.gameObject:SetActive(bUnlock)
if bReaded then
NovaAPI.SetTMPText(txtLevelName, storyConfig.Title)
else
NovaAPI.SetTMPText(txtLevelName, ConfigTable.GetUIText("Story_NewEnd_Unlock"))
end
if #self.tbBranch[avgId] == 1 then
end
local imgLockBg = branchGrid:Find("AnimRoot/goLock/imgBranchGridBgLock")
imgLockBg.gameObject:SetActive(not bUnlock)
local txtUnlock = branchGrid:Find("AnimRoot/goUnlock/txtUnlock"):GetComponent("TMP_Text")
txtUnlock.gameObject:SetActive(false)
NovaAPI.SetTMPText(txtUnlock, ConfigTable.GetUIText("Story_Unkown_End"))
local imgLock = branchGrid:Find("AnimRoot/goLock/imgLock")
imgLock.gameObject:SetActive(not bUnlock)
local RedDot = branchGrid:Find("AnimRoot/RedDot")
local bNew = 0 < table.indexof(self.tbFocusNode, v.Id) and not bReaded
RedDot.gameObject:SetActive(bNew)
imgNewUnlock.gameObject:SetActive(bNew)
imgNewUnlockBg.gameObject:SetActive(bNew)
local btnEnter = branchGrid:GetComponent("UIButton")
btnEnter.onClick:RemoveAllListeners()
btnEnter.onClick:AddListener(function()
self:OnClickGrid(v.StoryId)
end)
end
index = index + 1
end
root.gameObject:SetActive(bHasUnlockBranch)
if bHasUnlockBranch then
if not isNeedPlayUnlockAnim or not bHasUnReadBranch then
self:PlayUnlockAnim(root, "BranchRoot_loop" .. nUnlockBranchCount)
else
self:PlayUnlockAnim(root, "BranchRoot_Empty")
end
end
if 2 < nUnlockBranchCount then
if self.tbBranchOverflowDepths == nil then
self.tbBranchOverflowDepths = {}
end
table.insert(self.tbBranchOverflowDepths, depth)
end
end
function ChapterLineCtrl:ApplyLayoutContentRightPadding()
local maxLockDepth = self.maxLockRootDepth or 0
local bWide = false
local tbOverflow = self.tbBranchOverflowDepths or {}
for _, branchDepth in ipairs(tbOverflow) do
if branchDepth >= maxLockDepth then
bWide = true
break
end
end
local targetRight = bWide and 400 or 200
local layoutContent = self._mapNode.layoutContent
if layoutContent.padding.right ~= targetRight then
local padding = layoutContent.padding
NovaAPI.SetLayoutGroupPadding(layoutContent.gameObject, padding.left, targetRight, padding.top, padding.bottom)
end
end
function ChapterLineCtrl:RefreshTimeStamp(goTimeStamp, index)
local timeStampName
local nId = self.curChapter * 100 + index
local config = ConfigTable.GetData("StoryChapterTimeStamp", nId)
if config == nil then
return
end
timeStampName = config.TimeStamp
if timeStampName == nil then
goTimeStamp.gameObject:SetActive(false)
return
end
local tranTimeStamp = goTimeStamp:GetChild(0)
local imgFocus = tranTimeStamp:Find("imgFocus")
imgFocus.gameObject:SetActive(index == self.curTimeStamp)
local imgBg = tranTimeStamp:Find("imgBg")
imgBg.gameObject:SetActive(index ~= self.curTimeStamp)
local txtTimeTitle = tranTimeStamp:Find("imgFocus/txtTimeTitle"):GetComponent("TMP_Text")
local imgStage = txtTimeTitle.transform:Find("imgStage")
imgStage.gameObject:SetActive(index == self.curTimeStamp)
if index > self.maxUnlockDepth and 0 < self.curTimeStamp then
timeStampName = ConfigTable.GetUIText("No_Arrived_Future")
end
NovaAPI.SetTMPText(txtTimeTitle, timeStampName)
local txtTimeTitle = tranTimeStamp:Find("imgBg/txtTimeTitle"):GetComponent("TMP_Text")
NovaAPI.SetTMPText(txtTimeTitle, timeStampName)
end
function ChapterLineCtrl:CheckLineReasonable(grid)
local avgId = grid.name
local storyConfig = AvgData:GetStoryCfgData(avgId)
local goLeftBorder = grid:Find("goLeftBorder")
local uiCamera = GameCameraStackManager.Instance.uiCamera
if grid.gameObject.activeInHierarchy == false then
return
end
if self.tbShortenedLines == nil then
self.tbShortenedLines = {}
end
for i = 1, goLeftBorder.childCount do
local line = goLeftBorder:GetChild(i - 1)
local lineRect = line:GetComponent("RectTransform")
for index = 1, #storyConfig.ParentStoryId do
local parentAvgId = storyConfig.ParentStoryId[index]
local curBorderPos = self.tbGridBorderPos and self.tbGridBorderPos[avgId]
local parentBorderPos = self.tbGridBorderPos and self.tbGridBorderPos[parentAvgId]
if parentBorderPos.grid ~= nil and parentBorderPos.grid.gameObject.activeInHierarchy ~= false and curBorderPos ~= nil and curBorderPos.left ~= nil and parentBorderPos ~= nil and parentBorderPos.right ~= nil then
local isHitA, worldPosA = RectTransformUtility.ScreenPointToWorldPointInRectangle(grid, parentBorderPos.right, uiCamera)
local isHitB, worldPosB = RectTransformUtility.ScreenPointToWorldPointInRectangle(grid, curBorderPos.left, uiCamera)
local localPosA = grid:InverseTransformPoint(worldPosA)
local localPosB = grid:InverseTransformPoint(worldPosB)
local dir = parentBorderPos.right - curBorderPos.left
local expectedAngle = math.deg(math.atan(dir.y, dir.x))
local lineAngle = lineRect.eulerAngles.z
local angleDiff = ((expectedAngle - lineAngle) % 180 + 180) % 180
if 90 < angleDiff then
angleDiff = 180 - angleDiff
end
if not (5 < angleDiff) then
local screenDist = (localPosA - localPosB).magnitude
local lineWidthScreen = lineRect.sizeDelta.x
local newSizeDelta = screenDist
if not (math.abs(screenDist - lineWidthScreen) <= 18) then
if screenDist > lineWidthScreen then
lineRect.sizeDelta = Vector2(newSizeDelta, lineRect.sizeDelta.y)
print("拉伸线段", grid.name, "原宽度", lineWidthScreen, "新宽度", newSizeDelta)
print("点A屏幕坐标", parentBorderPos.right, "点B屏幕坐标", curBorderPos.left)
elseif screenDist < lineWidthScreen then
lineRect.sizeDelta = Vector2(newSizeDelta, lineRect.sizeDelta.y)
self.tbShortenedLines[avgId] = {
lineIndex = i,
parentAvgId = parentAvgId,
originalWidth = newSizeDelta
}
end
end
end
end
end
end
end
function ChapterLineCtrl:RefreshCurNodeDepthByNewUnlock()
local tbGridList = self.tbGridList or {}
local snapshotKey = "MainlineUnlockSnapshot_" .. tostring(self.curChapter)
local depthKey = "MainlineCurNodeDepth_" .. tostring(self.curChapter)
local prevUnlockSet = {}
local snapshotRaw = LocalData.GetPlayerLocalData(snapshotKey)
if type(snapshotRaw) == "string" and snapshotRaw ~= "" then
for storyId in string.gmatch(snapshotRaw, "([^,]+)") do
prevUnlockSet[storyId] = true
end
end
local deepestDepth
local curUnlockIds = {}
local parentDepthMap = {}
for _, v in ipairs(tbGridList) do
parentDepthMap[v.avgId] = v.depth
local storyConfig = AvgData:GetStoryCfgData(v.avgId)
if storyConfig ~= nil then
local bUnlock = AvgData:IsUnlock(storyConfig.ConditionId, storyConfig.StoryId)
if bUnlock then
local storyIdKey = tostring(storyConfig.Id)
table.insert(curUnlockIds, storyIdKey)
if not prevUnlockSet[storyIdKey] and (deepestDepth == nil or deepestDepth < v.depth) then
deepestDepth = v.depth
end
end
end
end
local tbBranch = self.tbBranch or {}
for parentAvgId, branchList in pairs(tbBranch) do
local parentDepth = parentDepthMap[parentAvgId]
for _, branchData in ipairs(branchList) do
local bUnlock = AvgData:IsUnlock(branchData.ConditionId, branchData.StoryId)
if bUnlock then
local branchIdKey = tostring(branchData.Id)
table.insert(curUnlockIds, branchIdKey)
if not prevUnlockSet[branchIdKey] and parentDepth ~= nil and (deepestDepth == nil or deepestDepth < parentDepth) then
deepestDepth = parentDepth
end
end
end
end
if deepestDepth ~= nil then
self.curNodeDepth = deepestDepth
LocalData.SetPlayerLocalData(depthKey, deepestDepth)
else
local savedDepth = LocalData.GetPlayerLocalData(depthKey)
local nSavedDepth = tonumber(savedDepth)
if nSavedDepth ~= nil and 0 < nSavedDepth then
self.curNodeDepth = nSavedDepth
end
end
LocalData.SetPlayerLocalData(snapshotKey, table.concat(curUnlockIds, ","))
end
function ChapterLineCtrl:RefreshUnlockAnimList()
self.tbNeedPlayUnlockAnimGird = {}
self.curShouldPlayDepth = 9999
if not self.bNeedPlayUnlockAnim and not self.bNeedPlayBranchAnim then
return
end
local cachedGird = {}
for k, v in ipairs(self.tbGridList) do
local storyConfig = AvgData:GetStoryCfgData(v.avgId)
if table.indexof(self.tbFocusNode, storyConfig.Id) > 0 then
local bHasPlayedAnim = LocalData.GetPlayerLocalData("MainlineUnlock_" .. storyConfig.Id)
if (bHasPlayedAnim == nil or bHasPlayedAnim == 0) and cachedGird[v.avgId] == nil then
table.insert(self.tbNeedPlayUnlockAnimGird, v)
cachedGird[v.avgId] = v
if self.curShouldPlayDepth > v.depth then
self.curShouldPlayDepth = v.depth
end
end
else
for _, parentNode in pairs(storyConfig.ParentStoryId) do
if cachedGird[parentNode] ~= nil then
local parentStoryConfig = AvgData:GetStoryCfgData(parentNode)
local bHasPlayedAnim = LocalData.GetPlayerLocalData("MainlineUnlock_" .. storyConfig.Id)
local parentUnlock = AvgData:IsUnlock(parentStoryConfig.ConditionId, parentStoryConfig.StoryId)
if cachedGird[v.avgId] == nil and (bHasPlayedAnim == nil or bHasPlayedAnim == 0) and parentUnlock then
table.insert(self.tbNeedPlayUnlockAnimGird, v)
cachedGird[v.avgId] = v
if self.curShouldPlayDepth > v.depth then
self.curShouldPlayDepth = v.depth
end
end
elseif table.indexof(self.tbFocusNode, parentNode) > 0 then
local parentStoryConfig = AvgData:GetStoryCfgData(parentNode)
local bHasPlayedAnim = LocalData.GetPlayerLocalData("MainlineUnlock_" .. parentStoryConfig.Id)
if bHasPlayedAnim == nil or bHasPlayedAnim == 0 then
bHasPlayedAnim = LocalData.GetPlayerLocalData("MainlineUnlock_" .. storyConfig.Id)
if cachedGird[v.avgId] == nil and (bHasPlayedAnim == nil or bHasPlayedAnim == 0) then
table.insert(self.tbNeedPlayUnlockAnimGird, v)
cachedGird[v.avgId] = v
if self.curShouldPlayDepth > v.depth then
self.curShouldPlayDepth = v.depth
end
end
end
end
end
end
end
end
function ChapterLineCtrl:DoPlayUnlockAnim(depth)
local nodes = {}
for _, node in ipairs(self.tbNeedPlayUnlockAnimGird) do
if node.depth == depth then
table.insert(nodes, node)
end
end
for _, node in pairs(nodes) do
self:PlayGridUnlockAnim(node, depth)
end
end
function ChapterLineCtrl:PlayGridUnlockAnim(nodeInfo, depth)
local storyConfig = AvgData:GetStoryCfgData(nodeInfo.avgId)
if storyConfig.IsBranch then
nodeInfo.grid.gameObject:SetActive(true)
self:PlayBranchNodeUnlockAnim(nodeInfo, depth)
else
self:PlayNormalNodeUnlockAnim(nodeInfo, depth)
end
end
function ChapterLineCtrl:PlayNormalNodeUnlockAnim(nodeInfo, depth)
local grid = nodeInfo.grid.transform
local storyConfig = AvgData:GetStoryCfgData(nodeInfo.avgId)
local imgLeftPoint_1 = grid:Find("imgLeftPoint_1")
local imgRightPoint_1 = grid:Find("imgRightPoint_1")
local goLeftBorder = grid:Find("goLeftBorder")
local goRightBorder = grid:Find("goRightBorder")
local allLine = {}
for i = 0, goLeftBorder.transform.childCount - 1 do
table.insert(allLine, goLeftBorder.transform:GetChild(i))
end
grid.gameObject:SetActive(true)
local bLeftActived = imgLeftPoint_1.gameObject.activeInHierarchy
local bRightActived = imgRightPoint_1.gameObject.activeInHierarchy
local goLineContinue = grid:Find("lineContinue")
imgRightPoint_1.gameObject:SetActive(false)
imgLeftPoint_1.gameObject:SetActive(false)
goLineContinue.gameObject:SetActive(false)
local bUnlock = AvgData:IsUnlock(storyConfig.ConditionId, storyConfig.StoryId)
local batteleNode = grid:Find("btnEnter/AnimRoot/BattleRoot")
local normalNode = grid:Find("btnEnter/AnimRoot/NormalRoot")
local lockNode = grid:Find("btnEnter/AnimRoot/LockRoot")
batteleNode.gameObject:SetActive(false)
normalNode.gameObject:SetActive(false)
lockNode.gameObject:SetActive(false)
local rootNode
local bNewUnlock = 0 < table.indexof(self.tbLockedPlayedAnim, nodeInfo.avgId)
if bNewUnlock then
lockNode.gameObject:SetActive(true)
table.removebyvalue(self.tbLockedPlayedAnim, nodeInfo.avgId)
end
if bUnlock then
rootNode = storyConfig.IsBattle == true and batteleNode or normalNode
else
rootNode = lockNode
table.insert(self.tbLockedPlayedAnim, nodeInfo.avgId)
end
local PlayLineAnimTime = 0.01
if 0 < #allLine and not bNewUnlock then
PlayLineAnimTime = self.lineAnimTime
for k, v in ipairs(allLine) do
self:PlayLineAnim(v)
end
self:AddTimer(1, self.lineAnimTime, function()
imgLeftPoint_1.gameObject:SetActive(bLeftActived)
end, true, true, true)
elseif bNewUnlock then
imgLeftPoint_1.gameObject:SetActive(bLeftActived)
end
local DoAfterAnim = function(time)
self:AddTimer(1, time, function()
imgRightPoint_1.gameObject:SetActive(bRightActived)
if not bUnlock then
if bRightActived then
goLineContinue.gameObject:SetActive(true)
self:PlayLineAnim(goLineContinue)
end
else
local imgFocus = rootNode:Find("imgFocus")
local bReaded = AvgData:IsStoryReaded(storyConfig.Id)
local RedDot = rootNode:Find("RedDot")
local bFocus = table.indexof(self.tbFocusNode, storyConfig.Id) > 0 and (not bReaded or self.bFocusLastNode)
imgFocus.gameObject:SetActive(bFocus)
RedDot.gameObject:SetActive(bFocus and not bReaded)
self:DoPlayUnlockAnim(depth + 1)
end
end, true, true, true)
end
self:AddTimer(1, PlayLineAnimTime, function()
lockNode.gameObject:SetActive(false)
rootNode.gameObject:SetActive(true)
local animName = bUnlock and "BattleRoot_in" or "LockRoot_in"
if bUnlock then
LocalData.SetPlayerLocalData("MainlineUnlock_" .. storyConfig.Id, 1)
CS.WwiseAudioManager.Instance:PostEvent("ui_mainline_level")
end
local animTime = self:PlayUnlockAnim(rootNode, animName)
DoAfterAnim(animTime)
end, true, true, true)
end
function ChapterLineCtrl:PlayBranchNodeUnlockAnim(nodeInfo, depth)
self:PlayUnlockAnim(nodeInfo.grid, "BranchRoot_in" .. nodeInfo.totalCount)
WwiseAudioMgr:PostEvent("ui_mainline_newending")
local storyConfig = AvgData:GetStoryCfgData(nodeInfo.avgId)
LocalData.SetPlayerLocalData("MainlineUnlock_" .. storyConfig.Id, 1)
end
function ChapterLineCtrl:PlayUnlockAnim(go, animName)
local animator = go:GetComponent("Animator")
animator.enabled = true
animator:Play(animName)
local nAnimLength = NovaAPI.GetAnimClipLength(animator, {animName})
return nAnimLength
end
function ChapterLineCtrl:PlayLineAnim(goLine)
local lineRect = goLine:GetComponent("RectTransform")
if lineRect.pivot.x > 0 then
lineRect.pivot = Vector2(0, 0.5)
local Pos = lineRect.localPosition
local angle = math.rad(lineRect.localEulerAngles.z)
lineRect.localPosition = Vector3(Pos.x - lineRect.rect.width * math.cos(angle), Pos.y - lineRect.rect.width * math.sin(angle), Pos.z)
end
lineRect.localScale = Vector3(0, 1, 1)
lineRect:DOScaleX(1, self.lineAnimTime)
end
function ChapterLineCtrl:OnClickGrid(avgId)
if self.bCanClick == false then
return
end
local storyConfig = AvgData:GetStoryCfgData(avgId)
local bUnlock, tbResult = AvgData:IsUnlock(storyConfig.ConditionId, avgId)
if not bUnlock then
WwiseAudioMgr:PostEvent("ui_systerm_locked")
if tbResult ~= nil then
local lockTxt = ""
for i = 1, #tbResult do
local value = tbResult[i]
if value[1] == false then
if UnlockConditionPriority[i] == "MustStoryIds" then
do
local tbStoryIds = value[2]
for k, v in pairs(tbStoryIds) do
if v == false then
local storyData = ConfigTable.GetData_Story(AvgData.CFG_Story[k])
lockTxt = orderedFormat(ConfigTable.GetUIText("Story_UnlockPreId") or "", storyData.Title)
break
end
end
end
break
end
if UnlockConditionPriority[i] == "OneofStoryIds" then
do
local tbStoryIds = value[2]
for k, v in pairs(tbStoryIds) do
if v == false then
local storyData = ConfigTable.GetData_Story(AvgData.CFG_Story[k])
lockTxt = orderedFormat(ConfigTable.GetUIText("Story_UnlockPreId") or "", storyData.Title)
break
end
end
end
break
end
if UnlockConditionPriority[i] == "MustEvIds" then
lockTxt = ConfigTable.GetUIText("Story_UnlockClueCondition")
break
end
if UnlockConditionPriority[i] == "OneofEvIds" then
lockTxt = ConfigTable.GetUIText("Story_UnlockClueCondition")
break
end
if UnlockConditionPriority[i] == "WorldLevel" then
do
local level = value[2]
lockTxt = orderedFormat(ConfigTable.GetUIText("Story_UnlockWorldLv") or "", level)
end
break
end
if UnlockConditionPriority[i] == "MustAchievementIds" then
if self.bHasAchievementData == true then
local tbAchievementList = value[2]
for k, v in pairs(tbAchievementList) do
if v == false then
local achievementId = k
local achievement = ConfigTable.GetData("Achievement", achievementId)
lockTxt = orderedFormat(ConfigTable.GetUIText("Story_UnlockAchievement") or "", achievement.Title) .. "\n" .. "(" .. achievement.Desc .. ")"
break
end
end
end
break
end
if UnlockConditionPriority[i] == "TimeUnlock" then
local curTime = CS.ClientManager.Instance.serverTimeStamp
local openTime = value[2]
local remainTime = openTime - curTime
if remainTime <= 60 then
do
local sec = math.floor(remainTime)
lockTxt = orderedFormat(ConfigTable.GetUIText("Mainline_Open_Time_Sec") or "", sec)
end
break
end
if 60 < remainTime and remainTime <= 3600 then
do
local min = math.floor(remainTime / 60)
local sec = math.floor(remainTime - min * 60)
if sec == 0 then
min = min - 1
sec = 60
end
lockTxt = orderedFormat(ConfigTable.GetUIText("Mainline_Open_Time_Min") or "", min, sec)
end
break
end
if 3600 < remainTime and remainTime <= 86400 then
do
local hour = math.floor(remainTime / 3600)
local min = math.floor((remainTime - hour * 3600) / 60)
if min == 0 then
hour = hour - 1
min = 60
end
lockTxt = orderedFormat(ConfigTable.GetUIText("Mainline_Open_Time_Hour") or "", hour, min)
end
break
end
if 86400 < remainTime then
local day = math.floor(remainTime / 86400)
local hour = math.floor((remainTime - day * 86400) / 3600)
if hour == 0 then
day = day - 1
hour = 24
end
lockTxt = orderedFormat(ConfigTable.GetUIText("Mainline_Open_Time_Day") or "", day, hour)
end
end
break
end
end
local msg = {
nType = AllEnum.MessageBox.Alert,
sContent = lockTxt
}
EventManager.Hit(EventId.OpenMessageBox, msg)
end
return
end
WwiseAudioMgr:PostEvent("ui_common_menu3")
local nRecentStoryId = AvgData:GetRecentStoryId(self.curChapter)
local recentStoryAvgId = ConfigTable.GetData_Story(nRecentStoryId).StoryId
local findCount = 0
local recentStoryDepth = 0
local curDepth = 0
for k, v in ipairs(self.tbGridList) do
local gridName = v.grid.name
if gridName == avgId then
findCount = findCount + 1
curDepth = v.depth
end
if gridName == recentStoryAvgId then
findCount = findCount + 1
recentStoryDepth = v.depth
end
if findCount == 2 then
break
end
end
self.curChosenStory = avgId
EventManager.Hit(EventId.ChoseMainlineStory, avgId, curDepth >= recentStoryDepth)
end
function ChapterLineCtrl:OnEvent_Story_RewardClosed()
if self.bNeedPlayUnlockAnim or self.bNeedPlayBranchAnim then
if self.bNeedPlayBranchAnim and self.tbNeedPlayUnlockAnimGird[1] ~= nil then
self.curShouldPlayDepth = self.tbNeedPlayUnlockAnimGird[1].depth
end
self:DoPlayUnlockAnim(self.curShouldPlayDepth)
end
end
function ChapterLineCtrl:OnEvent_Story_Done(bHasReward)
if not bHasReward and (self.bNeedPlayUnlockAnim or self.bNeedPlayBranchAnim) then
if self.bNeedPlayBranchAnim and self.tbNeedPlayUnlockAnimGird[1] ~= nil then
self.curShouldPlayDepth = self.tbNeedPlayUnlockAnimGird[1].depth
end
self:AddTimer(1, 1.5, function()
self:DoPlayUnlockAnim(self.curShouldPlayDepth)
end, true, true, true)
end
end
function ChapterLineCtrl:CacheCurChapterConfig()
self.tbChapterStoryNumIds = AvgData:GetChapterStoryNumIds(self.curChapter)
end
function ChapterLineCtrl:CacheChapterBranchNode()
self.tbBranch = {}
for i, v in ipairs(self.tbChapterStoryNumIds) do
local data = ConfigTable.GetData_Story(v)
if data.IsBranch then
if self.tbBranch[data.ParentStoryId[1]] == nil then
self.tbBranch[data.ParentStoryId[1]] = {}
end
table.insert(self.tbBranch[data.ParentStoryId[1]], data)
end
end
end
function ChapterLineCtrl:IsAllStoryCompleted()
for k, v in ipairs(self.tbGridList) do
if self.maxStoryDepth == v.depth and self.curChosenStory == v.grid.name then
local avgId = v.grid.name
local nStoryId = AvgData.CFG_Story[avgId]
return AvgData:IsStoryReaded(nStoryId)
end
end
return false
end
function ChapterLineCtrl:ForbidClick()
self.bCanClick = false
self:AddTimer(1, 1.5, function()
self.bCanClick = true
end, true, true, true)
end
return ChapterLineCtrl