1077 lines
28 KiB
Lua
1077 lines
28 KiB
Lua
local LuaSystemBase = require_ex('LuaSystem/LuaSystemBase')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RadioSystem = HL.Class('RadioSystem', LuaSystemBase.LuaSystemBase)
|
|
|
|
RADIO_DATA_SORT_KEYS = { "priorityKey", "needResumeKey", "addTimeKey" }
|
|
CONTINUE_RADIO_PRIORITY = -1000
|
|
TIMEOUT_TIME = 60
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RadioSystem.s_radioIndexCache = HL.StaticField(HL.Table) << {}
|
|
|
|
|
|
RadioSystem.m_curShow = HL.Field(HL.Any)
|
|
|
|
|
|
RadioSystem.m_waitingQueue = HL.Field(HL.Table)
|
|
|
|
|
|
RadioSystem.m_queueSortFunc = HL.Field(HL.Function)
|
|
|
|
|
|
RadioSystem.m_audioEndFunc = HL.Field(HL.Function)
|
|
|
|
|
|
RadioSystem.m_pauseRefCount = HL.Field(HL.Number) << 0
|
|
|
|
|
|
RadioSystem.inMainHud = HL.Field(HL.Boolean) << true
|
|
|
|
|
|
RadioSystem.m_forcePlayRadio = HL.Field(HL.Boolean) << false
|
|
|
|
|
|
RadioSystem.m_radioOnlySound = HL.Field(HL.Boolean) << false
|
|
|
|
|
|
RadioSystem.m_enableDebugLog = HL.Field(HL.Boolean) << false
|
|
|
|
|
|
RadioSystem.m_globalTagHandle = HL.Field(CS.Beyond.Gameplay.Core.GlobalTagHandle)
|
|
|
|
|
|
|
|
RadioSystem.RadioSystem = HL.Constructor() << function(self)
|
|
|
|
|
|
self:RegisterMessage(MessageConst.ON_SCENE_LOAD_START, function(arg)
|
|
self:_FlushAll()
|
|
end)
|
|
|
|
self:RegisterMessage(MessageConst.ALL_CHARACTER_DEAD, function(arg)
|
|
self:_FlushAll()
|
|
end)
|
|
|
|
self:RegisterMessage(MessageConst.ON_TELEPORT_SQUAD, function(arg)
|
|
self:_FlushAll()
|
|
end)
|
|
|
|
self:RegisterMessage(MessageConst.PLAY_CG, function(arg)
|
|
self:_FlushAll()
|
|
end)
|
|
|
|
self:RegisterMessage(MessageConst.ON_PLAY_CUTSCENE, function(arg)
|
|
if not self.m_forcePlayRadio then
|
|
self:_FlushAll()
|
|
end
|
|
end)
|
|
|
|
self:RegisterMessage(MessageConst.REMOTE_COMM_START, function(arg)
|
|
self:_FlushAll()
|
|
end)
|
|
|
|
self:RegisterMessage(MessageConst.ON_SNS_FORCE_DIALOG_START, function(arg)
|
|
self:_FlushAll()
|
|
end)
|
|
|
|
self:RegisterMessage(MessageConst.ON_DO_CLOSE_MAP, function(arg)
|
|
self:_FlushAll()
|
|
end)
|
|
|
|
|
|
|
|
|
|
self:RegisterMessage(MessageConst.ON_GUIDE_STOPPED, function(arg)
|
|
if arg then
|
|
local isForceGuide = unpack(arg)
|
|
if isForceGuide then
|
|
self:_TryResumeAndShow()
|
|
end
|
|
end
|
|
end)
|
|
|
|
self:RegisterMessage(MessageConst.START_GUIDE_GROUP, function(arg)
|
|
local info = unpack(arg)
|
|
if info.type == CS.Beyond.Gameplay.GuideGroupType.Force then
|
|
self:_TryPauseAndHide()
|
|
end
|
|
end)
|
|
|
|
|
|
self:RegisterMessage(MessageConst.ON_ULTIMATE_SKILL_START, function(arg)
|
|
local info = unpack(arg)
|
|
if info.type == CS.Beyond.Gameplay.GuideGroupType.Force then
|
|
self:_TryPauseAndHide()
|
|
end
|
|
end)
|
|
self:RegisterMessage(MessageConst.ON_ULTIMATE_SKILL_END, function(arg)
|
|
self:_TryResumeAndShow()
|
|
end)
|
|
|
|
|
|
self:RegisterMessage(MessageConst.ON_NARRATIVE_BLACK_SCREEN_END, function(arg)
|
|
self:_TryResumeAndShow()
|
|
end)
|
|
|
|
|
|
self:RegisterMessage(MessageConst.ON_DIALOG_START, function(arg)
|
|
self:_OnDialogStart(arg)
|
|
end)
|
|
|
|
|
|
|
|
|
|
self:RegisterMessage(MessageConst.ON_FORCE_PLAY_RADIO_CHANGED, function(arg)
|
|
local forcePlayRadio = unpack(arg)
|
|
if self.m_forcePlayRadio ~= forcePlayRadio then
|
|
self.m_forcePlayRadio = forcePlayRadio
|
|
|
|
if not forcePlayRadio and not self:_CheckCanPlay() then
|
|
self:_TryPauseAndHide()
|
|
end
|
|
end
|
|
end)
|
|
|
|
self:RegisterMessage(MessageConst.ON_RADIO_ONLY_SOUND_CHANGED, function(arg)
|
|
local onlySound = unpack(arg)
|
|
if self.m_radioOnlySound ~= onlySound then
|
|
self.m_radioOnlySound = onlySound
|
|
|
|
if self.m_curShow then
|
|
local panel = self:_GetUICtrl()
|
|
if onlySound then
|
|
panel:HideSelf()
|
|
else
|
|
panel:ShowSelf()
|
|
panel.animationWrapper:ClearTween(false)
|
|
panel:PlayAnimationIn()
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
self:RegisterMessage(MessageConst.ON_RADIO_EMPTY_SHOW, function(arg)
|
|
self:_TryResumeAndShow()
|
|
end)
|
|
self:RegisterMessage(MessageConst.ON_RADIO_EMPTY_HIDE, function(arg)
|
|
if not self.m_forcePlayRadio then
|
|
self:_TryPauseAndHide()
|
|
end
|
|
end)
|
|
|
|
self:RegisterMessage(MessageConst.ON_IN_MAIN_HUD_CHANGED, function(arg)
|
|
local inMainHud = unpack(arg)
|
|
self.inMainHud = inMainHud
|
|
if inMainHud then
|
|
self:_TryResumeAndShow()
|
|
else
|
|
if not self.m_forcePlayRadio then
|
|
self:_TryPauseAndHide()
|
|
end
|
|
end
|
|
end)
|
|
|
|
self:RegisterMessage(MessageConst.ON_NARRATIVE_STATE_CHANGED, function(arg)
|
|
local inNarrative = unpack(arg)
|
|
|
|
if not inNarrative then
|
|
self:_TryResumeAndShow()
|
|
end
|
|
end)
|
|
|
|
self:RegisterMessage(MessageConst.SHOW_RADIO, function(arg)
|
|
local data = unpack(arg)
|
|
self:_TryPlayRadio(data)
|
|
end)
|
|
self:RegisterMessage(MessageConst.MANUAL_STOP_RADIO, function(arg)
|
|
local radioId = unpack(arg)
|
|
self:ManualStopRadio(radioId)
|
|
end)
|
|
|
|
self:RegisterMessage(MessageConst.FLUSH_RADIO, function(arg)
|
|
local radioId = unpack(arg)
|
|
self:_DoFlushRadio()
|
|
if not string.isEmpty(radioId) then
|
|
self:_TryPlayRadio(radioId)
|
|
else
|
|
self:_Exit()
|
|
end
|
|
end)
|
|
|
|
|
|
self:RegisterMessage(MessageConst.ENABLE_RADIO_QUEUE_LOG, function(enable)
|
|
self.m_enableDebugLog = enable
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
RadioSystem.ManualStopRadio = HL.Method(HL.Any) << function(self, radioId)
|
|
if self.m_curShow == nil then
|
|
return
|
|
end
|
|
|
|
if self.m_curShow.radioId ~= radioId then
|
|
return
|
|
end
|
|
|
|
RadioSystem.s_radioIndexCache[radioId] = self.m_curShow.curIndex - 1
|
|
self:_CutCurRadio(true)
|
|
if not self.m_curShow then
|
|
if not self:_TryShowNextRadio() then
|
|
self:_Exit()
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
RadioSystem._ClearCurTimer = HL.Method() << function(self)
|
|
if self.m_curShow and self.m_curShow.timerId and self.m_curShow.timerId > 0 then
|
|
self:_ClearTimer(self.m_curShow.timerId)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
RadioSystem._AddTimeoutTimer = HL.Method() << function(self)
|
|
self:_ClearCurTimer()
|
|
local timerId = self:_StartTimer(TIMEOUT_TIME, function()
|
|
self:_ShowSingleRadio()
|
|
end)
|
|
self.m_curShow.timerId = timerId
|
|
end
|
|
|
|
|
|
|
|
RadioSystem._TryPauseAndHide = HL.Method() << function(self)
|
|
self:_RemoveGlobalTag()
|
|
|
|
if self.m_curShow then
|
|
if self.m_pauseRefCount == 0 then
|
|
|
|
if self.m_curShow.voiceHandleId and self.m_curShow.voiceHandleId > 0 then
|
|
VoiceManager:PauseVoice(self.m_curShow.voiceHandleId)
|
|
self:_ClearCurTimer()
|
|
elseif self.m_curShow.timerId then
|
|
local triggerTime = TimerManager:GetTimerTriggerTime(self.m_curShow.timerId)
|
|
if triggerTime > 0 then
|
|
self.m_curShow.resumeTime = triggerTime - Time.time
|
|
end
|
|
self:_ClearCurTimer()
|
|
end
|
|
end
|
|
|
|
self.m_pauseRefCount = self.m_pauseRefCount + 1
|
|
end
|
|
NarrativeUtils.SetRadioId("")
|
|
|
|
self:_Exit()
|
|
end
|
|
|
|
|
|
|
|
RadioSystem._IsSoundOnly = HL.Method().Return(HL.Boolean) << function(self)
|
|
return GameWorld.narrativeManager.radioOnlySound
|
|
end
|
|
|
|
|
|
|
|
RadioSystem._TryResumeAndShow = HL.Method() << function(self)
|
|
local panel = self:_GetUICtrl()
|
|
if not panel then
|
|
return
|
|
end
|
|
|
|
local showRadio = true
|
|
local resume = false
|
|
local isShow = panel:IsShow()
|
|
if self.m_curShow and self.m_pauseRefCount > 0 then
|
|
resume = true
|
|
self.m_pauseRefCount = self.m_pauseRefCount - 1
|
|
if self.m_curShow.cacheCallbackVoiceHandleId > 0 and self.m_curShow and self.m_curShow.voiceHandleId and
|
|
self.m_pauseRefCount == 0 then
|
|
if self.m_curShow.cacheCallbackVoiceHandleId == self.m_curShow.voiceHandleId then
|
|
self.m_curShow.voiceHandleId = -1
|
|
self.m_curShow.cacheCallbackVoiceHandleId = -1
|
|
else
|
|
VoiceManager:ResumeVoice(self.m_curShow.voiceHandleId)
|
|
self:_AddTimeoutTimer()
|
|
end
|
|
end
|
|
end
|
|
if self:_CheckCanPlay() then
|
|
local needShow = not self:_IsSoundOnly()
|
|
if needShow then
|
|
panel:ShowSelf()
|
|
if not isShow then
|
|
panel.animationWrapper:ClearTween(false)
|
|
panel:PlayAnimationIn()
|
|
end
|
|
end
|
|
|
|
if resume then
|
|
self:_ContinueCurRadio()
|
|
elseif not self.m_curShow then
|
|
if not self:_TryShowNextRadio() then
|
|
showRadio = false
|
|
self:_Exit()
|
|
end
|
|
elseif not isShow then
|
|
|
|
showRadio = false
|
|
self:_Exit()
|
|
end
|
|
else
|
|
showRadio = false
|
|
self:_Exit()
|
|
end
|
|
|
|
if showRadio then
|
|
self:_AddGlobalTag()
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
RadioSystem._Exit = HL.Method(HL.Opt(HL.Boolean)) << function(self, useAnim)
|
|
self:_RemoveGlobalTag()
|
|
self:_HideUI(useAnim)
|
|
end
|
|
|
|
|
|
|
|
|
|
RadioSystem._HideUI = HL.Method(HL.Opt(HL.Boolean)) << function(self, useAnim)
|
|
local panel = self:_GetUICtrl()
|
|
if panel then
|
|
panel:HideSelf(useAnim)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
RadioSystem._TryPlayRadio = HL.Method(CS.Beyond.Gameplay.Actions.GameAction.RadioRuntimeData) << function(self, data)
|
|
local radioId = data.radioId
|
|
local fromBegin = data.fromBegin
|
|
local index = data.index
|
|
local callback = data.callback
|
|
local entity = data.entity
|
|
|
|
local res, radioData = Tables.radioTable:TryGetValue(radioId)
|
|
if not res then
|
|
logger.error("Radio play fail, no radioId in table: " .. radioId)
|
|
return
|
|
end
|
|
|
|
local extraData = {
|
|
callback = callback,
|
|
entity = entity,
|
|
}
|
|
local tmpIndex
|
|
index = index == nil and 0 or index
|
|
|
|
if not fromBegin then
|
|
if index >= 0 then
|
|
tmpIndex = index
|
|
elseif RadioSystem.s_radioIndexCache[radioId] then
|
|
|
|
tmpIndex = RadioSystem.s_radioIndexCache[radioId]
|
|
RadioSystem.s_radioIndexCache[radioId] = -1
|
|
end
|
|
end
|
|
|
|
if tmpIndex and tmpIndex >= 0 then
|
|
extraData.curIndex = tmpIndex
|
|
end
|
|
|
|
|
|
if not self.m_curShow then
|
|
self:_TryAddRadio2Queue(radioId, extraData)
|
|
self:_TryResumeAndShow()
|
|
else
|
|
local curExtraData = {
|
|
callback = self.m_curShow.callback,
|
|
entity = self.m_curShow.entity,
|
|
curIndex = self.m_curShow.curIndex - 1,
|
|
needResume = true,
|
|
}
|
|
|
|
if self.m_curShow.priority > radioData.priority then
|
|
|
|
if radioData.continueAfterRadio then
|
|
self:_TryAddRadio2Queue(radioId, extraData)
|
|
end
|
|
elseif self.m_curShow.priority < radioData.priority then
|
|
self:_TryAddRadio2Queue(radioId, extraData)
|
|
|
|
if self.m_curShow.continueAfterRadio then
|
|
self:_TryAddRadio2Queue(self.m_curShow.radioId, curExtraData)
|
|
end
|
|
self:_CutCurRadio(true)
|
|
if not self.m_curShow then
|
|
self:_TryShowNextRadio()
|
|
end
|
|
else
|
|
self:_TryAddRadio2Queue(radioId, extraData)
|
|
|
|
if self.m_curShow.radioId ~= radioId and self.m_curShow.continueAfterRadio then
|
|
self:_TryAddRadio2Queue(self.m_curShow.radioId, curExtraData, true)
|
|
end
|
|
self:_CutCurRadio(true)
|
|
if not self.m_curShow then
|
|
self:_TryShowNextRadio()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
RadioSystem._ContinueCurRadio = HL.Method() << function(self)
|
|
if self.m_pauseRefCount == 0 then
|
|
local panel = self:_GetUICtrl()
|
|
local needShow = not self:_IsSoundOnly()
|
|
if self.m_curShow then
|
|
if self.m_curShow.voiceHandleId then
|
|
VoiceManager:ResumeVoice(self.m_curShow.voiceHandleId)
|
|
self:_AddTimeoutTimer()
|
|
if self.m_curShow.cacheCallbackVoiceHandleId <= 0 and self.m_curShow.cacheCallbackVoiceHandleId ==
|
|
self.m_curShow.voiceHandleId then
|
|
self:_ShowSingleRadio()
|
|
end
|
|
elseif self.m_curShow.resumeTime > 0 then
|
|
local timerId = self:_StartTimer(self.m_curShow.resumeTime, function()
|
|
self:_ShowSingleRadio()
|
|
end)
|
|
self.m_curShow.timerId = timerId
|
|
else
|
|
self:_ShowSingleRadio()
|
|
end
|
|
|
|
if needShow then
|
|
panel.view.textTalk:Play()
|
|
panel.view.textTalkCenter:Play()
|
|
end
|
|
|
|
|
|
if self.m_curShow then
|
|
NarrativeUtils.SetRadioId(self.m_curShow.radioId)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
RadioSystem._TryGetContinueExRadio = HL.Method(HL.Table).Return(HL.Any) << function(self, curData)
|
|
local interruptedVoiceId = curData.interruptedVoiceId
|
|
local data
|
|
if not string.isEmpty(interruptedVoiceId) then
|
|
local res, continueRadioId = VoiceUtils.TryGetRadioContinueId(interruptedVoiceId, VoiceUtils.GetDefaultContinueRadioSpeakers())
|
|
if res then
|
|
data = {
|
|
radioId = continueRadioId,
|
|
curIndex = 0,
|
|
priority = CONTINUE_RADIO_PRIORITY,
|
|
addTime = TimeManagerInst.unscaledTime,
|
|
isContinueExRadio = true,
|
|
}
|
|
end
|
|
end
|
|
return data
|
|
end
|
|
|
|
|
|
|
|
RadioSystem._TryShowNextRadio = HL.Method().Return(HL.Boolean) << function(self)
|
|
if #self.m_waitingQueue <= 0 then
|
|
return false
|
|
end
|
|
|
|
local data = self.m_waitingQueue[1]
|
|
local radioId = data.radioId
|
|
|
|
if not self:_CheckCanPlay(radioId) then
|
|
return false
|
|
end
|
|
|
|
|
|
if data.isContinueExRadio then
|
|
table.remove(self.m_waitingQueue, 1)
|
|
data = self.m_waitingQueue[1]
|
|
radioId = data.radioId
|
|
end
|
|
|
|
|
|
local continueRadioData = self:_TryGetContinueExRadio(data)
|
|
if continueRadioData then
|
|
self:_DoShowRadio(continueRadioData)
|
|
|
|
self.m_curShow.interruptedVoiceId = self.m_waitingQueue[1].interruptedVoiceId
|
|
self.m_waitingQueue[1].interruptedVoiceId = nil
|
|
self.m_waitingQueue[1].continuedRadio = continueRadioData.radioId
|
|
return true
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
table.remove(self.m_waitingQueue, 1)
|
|
self:_DoShowRadio(data)
|
|
|
|
if BEYOND_DEBUG then
|
|
self:_UpdateLog()
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
|
|
|
|
|
|
RadioSystem._CheckRadioInQueue = HL.Method(HL.String).Return(HL.Number) << function(self, radioId)
|
|
for index, v in pairs(self.m_waitingQueue) do
|
|
if v.radioId == radioId then
|
|
return index
|
|
end
|
|
end
|
|
return -1
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RadioSystem._TryAddRadio2Queue = HL.Method(HL.String, HL.Opt(HL.Table, HL.Boolean)) << function(self, radioId, extraData, resume)
|
|
if self:_CheckRadioInQueue(radioId) <= 0 then
|
|
local res, radioData = Tables.radioTable:TryGetValue(radioId)
|
|
if res then
|
|
local data = {
|
|
radioId = radioId,
|
|
curIndex = 0,
|
|
priority = radioData.priority,
|
|
addTime = TimeManagerInst.unscaledTime,
|
|
}
|
|
|
|
if extraData then
|
|
for k, v in pairs(extraData) do
|
|
data[k] = v
|
|
end
|
|
end
|
|
|
|
data["priorityKey"] = -radioData.priority
|
|
data["needResumeKey"] = resume and 0 or -1
|
|
data["addTimeKey"] = resume and data.addTime or -data.addTime
|
|
table.insert(self.m_waitingQueue, data)
|
|
|
|
table.sort(self.m_waitingQueue, self.m_queueSortFunc)
|
|
|
|
if BEYOND_DEBUG then
|
|
self:_UpdateLog()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
RadioSystem._CutCurRadio = HL.Method(HL.Opt(HL.Boolean)) << function(self, doCallback)
|
|
local curShow = self.m_curShow
|
|
local callback
|
|
local radioId
|
|
if curShow then
|
|
callback = curShow.callback
|
|
radioId = curShow.radioId
|
|
if curShow.timerId then
|
|
self:_ClearTimer(curShow.timerId)
|
|
end
|
|
|
|
if not string.isEmpty(curShow.voiceId) then
|
|
if curShow.voiceHandleId then
|
|
VoiceManager:StopVoice(curShow.voiceHandleId)
|
|
end
|
|
VoiceCallbackUtil.UnsubscribeOnVoiceEndEvent(self.m_audioEndFunc)
|
|
end
|
|
|
|
end
|
|
self.m_curShow = nil
|
|
self.m_pauseRefCount = 0
|
|
|
|
|
|
if doCallback and callback and not string.isEmpty(radioId) then
|
|
callback(radioId)
|
|
end
|
|
|
|
NarrativeUtils.RadioFinish({ radioId })
|
|
|
|
NarrativeUtils.SetRadioId("")
|
|
end
|
|
|
|
|
|
|
|
RadioSystem._UpdateVoiceInfo = HL.Method() << function(self)
|
|
self.m_curShow.voiceDurations = {}
|
|
self.m_curShow.voiceTotalDuration = 0
|
|
local radioSingleDataList = self.m_curShow.radioSingleDataList
|
|
for i = 1, radioSingleDataList.Count do
|
|
local singleData = radioSingleDataList[CSIndex(i)]
|
|
local voiceId = singleData.audioOverride
|
|
local res, duration = VoiceUtils.TryGetVoiceDuration(voiceId)
|
|
if not res then
|
|
voiceId = ""
|
|
end
|
|
if string.isEmpty(voiceId) then
|
|
self.m_curShow.voiceDurations = {}
|
|
self.m_curShow.voiceTotalDuration = 0
|
|
break
|
|
end
|
|
|
|
table.insert(self.m_curShow.voiceDurations, duration)
|
|
self.m_curShow.voiceTotalDuration = self.m_curShow.voiceTotalDuration + duration
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
RadioSystem._DoShowRadio = HL.Method(HL.Table) << function(self, data)
|
|
local panel = self:_GetUICtrl()
|
|
local needShow = not self:_IsSoundOnly()
|
|
if needShow then
|
|
panel.animationWrapper:ClearTween()
|
|
panel:PlayAnimationIn()
|
|
else
|
|
self:_HideUI()
|
|
end
|
|
local radioId = data.radioId
|
|
local curIndex = data.curIndex
|
|
local callback = data.callback
|
|
local entity = data.entity
|
|
local isContinueExRadio = data.isContinueExRadio
|
|
local res, radioData = Tables.radioTable:TryGetValue(radioId)
|
|
if res then
|
|
local canStop = false
|
|
local radioType = radioData.radioType
|
|
|
|
|
|
if radioType == GEnums.RadioType.Wireless then
|
|
self.m_curShow = {
|
|
radioId = radioId,
|
|
priority = radioData.priority,
|
|
continueAfterRadio = radioData.continueAfterRadio,
|
|
continueAfterDialog = radioData.continueAfterDialog,
|
|
radioSingleDataList = radioData.radioSingleDataList,
|
|
callback = callback,
|
|
curIndex = curIndex,
|
|
timerId = nil,
|
|
voiceHandleId = nil,
|
|
entity = entity,
|
|
icon = nil,
|
|
spriteName = nil,
|
|
cacheCallbackVoiceHandleId = -1,
|
|
resumeTime = -1,
|
|
isContinueExRadio = isContinueExRadio,
|
|
}
|
|
self:_UpdateVoiceInfo()
|
|
self:_ShowSingleRadio()
|
|
NarrativeUtils.SetRadioId(self.m_curShow.radioId)
|
|
else
|
|
logger.error("_DoShowRadio radioType error, only wireless supported, radioId: %s!!!", radioId)
|
|
end
|
|
|
|
else
|
|
logger.error("_DoShowRadio data error, radioId: %s!!!", radioId)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
RadioSystem._ShowSingleRadio = HL.Method() << function(self)
|
|
local panel = self:_GetUICtrl()
|
|
local isShow = panel:IsShow()
|
|
local needShow = not self:_IsSoundOnly()
|
|
if isShow and not needShow then
|
|
self:_HideUI()
|
|
elseif not isShow and needShow then
|
|
panel:ShowSelf()
|
|
end
|
|
if self.m_curShow then
|
|
local nextIndex = self.m_curShow.curIndex + 1
|
|
|
|
if nextIndex <= self.m_curShow.radioSingleDataList.Count then
|
|
panel.view.infoNode:ClearTween()
|
|
local nextSingleData = self.m_curShow.radioSingleDataList[CSIndex(nextIndex)]
|
|
local num = panel:ShowRadioUI(self.m_curShow, nextSingleData, nextIndex)
|
|
num = num / I18nUtils.GetTextSpeedFactor()
|
|
local voiceId = nextSingleData.audioOverride
|
|
local res, _ = VoiceUtils.TryGetVoiceDuration(voiceId)
|
|
if not res then
|
|
voiceId = ""
|
|
end
|
|
|
|
local audioEffect = nextSingleData.audioEffect
|
|
local is3D = nextSingleData.is3D
|
|
|
|
self:_ClearCurTimer()
|
|
|
|
local durationOnText = lume.clamp(num * Tables.cinematicConst.textShowDurationPerWord, Tables.cinematicConst.radioMinWaitTime, Tables.cinematicConst.radioMaxWaitTime)
|
|
|
|
if not string.isEmpty(voiceId) then
|
|
local cfg = CS.Beyond.Gameplay.Audio.NarrativeVoiceConfig(audioEffect, 1)
|
|
local voiceHandleId
|
|
local entity = self.m_curShow.entity
|
|
if is3D and entity then
|
|
voiceHandleId = VoiceManager:SpeakNarrative(voiceId, entity, cfg)
|
|
else
|
|
voiceHandleId = VoiceManager:SpeakNarrative(voiceId, nil, cfg)
|
|
end
|
|
if voiceHandleId > 0 and VoiceManager:IsVoicePlaying(voiceHandleId) then
|
|
self.m_curShow.voiceHandleId = voiceHandleId
|
|
VoiceCallbackUtil.SubscribeOnVoiceEndEvent(self.m_audioEndFunc)
|
|
self.m_curShow.voiceId = voiceId
|
|
self:_AddTimeoutTimer()
|
|
else
|
|
local duration = durationOnText
|
|
self:_ClearCurTimer()
|
|
local timerId = self:_StartTimer(duration, function()
|
|
self:_ShowSingleRadio()
|
|
end)
|
|
self.m_curShow.timerId = timerId
|
|
end
|
|
else
|
|
|
|
local duration = durationOnText
|
|
local minDuration = Tables.cinematicConst.radioTextMinDuration
|
|
local finalTime = math.max(minDuration, duration)
|
|
local timerId = self:_StartTimer(finalTime, function()
|
|
self:_ShowSingleRadio()
|
|
end)
|
|
self.m_curShow.timerId = timerId
|
|
end
|
|
self.m_curShow.curIndex = nextIndex
|
|
self.m_curShow.cacheCallbackVoiceHandleId = -1
|
|
else
|
|
GameWorld.narrativeManager:SetLastFinishRadio(self.m_curShow.radioId)
|
|
self:_CutCurRadio(true)
|
|
if not self.m_curShow then
|
|
if not self:_TryShowNextRadio() then
|
|
local panel = self:_GetUICtrl()
|
|
panel:TryPlayInfoNodeOut()
|
|
self:_Exit()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
RadioSystem._CheckCanPlay = HL.Method(HL.Opt(HL.String)).Return(HL.Boolean) << function(self, radioId)
|
|
|
|
if GameInstance.player.guide.isInForceGuide and not GameInstance.player.guide.isInHelperGuideStep then
|
|
return false
|
|
end
|
|
|
|
if self.m_forcePlayRadio then
|
|
return true
|
|
end
|
|
|
|
if Utils.isInNarrative() then
|
|
return false
|
|
end
|
|
|
|
return self.inMainHud
|
|
end
|
|
|
|
|
|
|
|
RadioSystem._UpdateLog = HL.Method() << function(self)
|
|
if self.m_enableDebugLog then
|
|
local text = ""
|
|
for i, debugData in pairs(self.m_waitingQueue) do
|
|
if i ~= 1 then
|
|
text = text .. "\n"
|
|
end
|
|
text = text .. string.format("{%s : %d}", debugData.radioId, debugData.curIndex)
|
|
end
|
|
Notify(MessageConst.UPDATE_DEBUG_TEXT, text)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
RadioSystem._GetUICtrl = HL.Method().Return(HL.Forward("UICtrl")) << function(self)
|
|
local _, panel = UIManager:IsOpen(PanelId.Radio)
|
|
return panel
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
RadioSystem._AddGlobalTag = HL.Method() << function(self)
|
|
self:_RemoveGlobalTag()
|
|
self.m_globalTagHandle = GameInstance.player.globalTagsSystem:AddGlobalTag(CS.Beyond.Gameplay.Core.GameplayTag(CS.Beyond.GlobalTagConsts.TAG_RADIO_PATH))
|
|
end
|
|
|
|
|
|
|
|
RadioSystem._RemoveGlobalTag = HL.Method() << function(self)
|
|
if self.m_globalTagHandle then
|
|
self.m_globalTagHandle:RemoveTag()
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RadioSystem._OnDialogStart = HL.Method(HL.Opt(HL.Table)) << function(self, data)
|
|
local _, dialogType = unpack(data)
|
|
if dialogType == Const.DialogType.Cinematic then
|
|
self:_FlushAll()
|
|
else
|
|
if self.m_curShow then
|
|
if self.m_curShow.continueAfterDialog then
|
|
local needContinue, nextIndex = self:_TryGetContinueIndex()
|
|
if needContinue then
|
|
local extraData = {
|
|
curIndex = nextIndex - 1,
|
|
interruptedVoiceId = self.m_curShow.voiceId,
|
|
}
|
|
self:_TryAddRadio2Queue(self.m_curShow.radioId, extraData)
|
|
end
|
|
elseif self.m_curShow.isContinueExRadio then
|
|
|
|
if #self.m_waitingQueue > 0 and self.m_waitingQueue[1].continuedRadio == self.m_curShow.radioId then
|
|
self.m_waitingQueue[1].interruptedVoiceId = self.m_curShow.interruptedVoiceId
|
|
end
|
|
end
|
|
end
|
|
self:_CutCurRadio(true)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
RadioSystem._TryGetContinueIndex = HL.Method().Return(HL.Boolean, HL.Number) << function(self)
|
|
local nextIndex = self.m_curShow.curIndex
|
|
if self.m_curShow and self.m_curShow.continueAfterDialog then
|
|
|
|
if self.m_curShow.voiceTotalDuration <= 0 then
|
|
return true, nextIndex
|
|
end
|
|
|
|
local playedTime = 0
|
|
if self.m_curShow.curIndex - 1 > 1 then
|
|
for i = 1, self.m_curShow.curIndex - 1 do
|
|
playedTime = playedTime + self.m_curShow.voiceDurations[i]
|
|
end
|
|
end
|
|
local res, positionMs = VoiceUtils.TryGetVoicePlayPosition(self.m_curShow.voiceHandleId)
|
|
local curVoiceDuration = self.m_curShow.voiceDurations[self.m_curShow.curIndex]
|
|
if res then
|
|
curVoiceDuration = positionMs / 1000
|
|
playedTime = playedTime + curVoiceDuration
|
|
end
|
|
|
|
local totalPercent = playedTime / self.m_curShow.voiceTotalDuration
|
|
|
|
|
|
if totalPercent > 0.9 then
|
|
return false, -1
|
|
end
|
|
|
|
|
|
local singlePercent = curVoiceDuration / self.m_curShow.voiceDurations[self.m_curShow.curIndex]
|
|
if singlePercent > 0.9 then
|
|
nextIndex = self.m_curShow.curIndex + 1
|
|
end
|
|
|
|
|
|
if nextIndex > self.m_curShow.radioSingleDataList.Count then
|
|
return false, -1
|
|
end
|
|
return true, nextIndex
|
|
else
|
|
return false, -1
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RadioSystem._FlushAll = HL.Method(HL.Opt(HL.Any)) << function(self, _)
|
|
self:_DoFlushRadio()
|
|
self:_Exit(true)
|
|
end
|
|
|
|
|
|
|
|
RadioSystem._DoFlushRadio = HL.Method() << function(self)
|
|
|
|
local radioIds = {}
|
|
for _, data in pairs(self.m_waitingQueue) do
|
|
table.insert(radioIds, data.radioId)
|
|
if data.callback then
|
|
data.callback(data.radioId)
|
|
end
|
|
end
|
|
|
|
if #radioIds > 0 then
|
|
NarrativeUtils.RadioFinish(radioIds)
|
|
end
|
|
|
|
self.m_waitingQueue = {}
|
|
if self.m_curShow then
|
|
self:_CutCurRadio(true)
|
|
end
|
|
|
|
if BEYOND_DEBUG then
|
|
self:_UpdateLog()
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RadioSystem._OnAudioEnd = HL.Method(HL.Number) << function(self, voiceHandleId)
|
|
if self.m_curShow and self.m_curShow.voiceHandleId == voiceHandleId then
|
|
if self.m_pauseRefCount > 0 then
|
|
self.m_curShow.cacheCallbackVoiceHandleId = voiceHandleId
|
|
else
|
|
if self.m_curShow.timerId and self.m_curShow.timerId > 0 then
|
|
self:_ClearTimer(self.m_curShow.timerId)
|
|
end
|
|
|
|
local timerId = self:_StartTimer(Tables.cinematicConst.radioAudioWaitTime, function()
|
|
self:_ShowSingleRadio()
|
|
end)
|
|
self.m_curShow.timerId = timerId
|
|
self.m_curShow.cacheCallbackVoiceHandleId = -1
|
|
self.m_curShow.voiceHandleId = nil
|
|
end
|
|
VoiceCallbackUtil.UnsubscribeOnVoiceEndEvent(self.m_audioEndFunc)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
RadioSystem.OnInit = HL.Override() << function(self)
|
|
RadioSystem.s_radioIndexCache = {}
|
|
self.m_waitingQueue = {}
|
|
self.m_queueSortFunc = Utils.genSortFunction(RADIO_DATA_SORT_KEYS, true)
|
|
self.m_curShow = nil
|
|
self.m_audioEndFunc = function(handleId)
|
|
self:_OnAudioEnd(handleId)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
RadioSystem.OnRelease = HL.Override() << function(self)
|
|
self:_CutCurRadio(true)
|
|
RadioSystem.s_radioIndexCache = {}
|
|
self.m_waitingQueue = {}
|
|
self.m_curShow = nil
|
|
self.m_queueSortFunc = nil
|
|
self.m_audioEndFunc = nil
|
|
end
|
|
|
|
HL.Commit(RadioSystem)
|
|
return RadioSystem
|