forked from endernon/PGRData
485 lines
No EOL
14 KiB
Lua
485 lines
No EOL
14 KiB
Lua
---@class XSignBoardPlayer
|
||
local XSignBoardPlayer = {}
|
||
|
||
local PlayerState = {
|
||
IDLE = 0,
|
||
PLAYING = 1,
|
||
CHANGING = 2,
|
||
PAUSE = 3,
|
||
STOP = 4
|
||
}
|
||
|
||
--创建一个播放器
|
||
function XSignBoardPlayer.New(playUi, coolTime, delay)
|
||
if playUi == nil then
|
||
return nil
|
||
end
|
||
|
||
local player = {}
|
||
setmetatable(player, { __index = XSignBoardPlayer })
|
||
player:Init(playUi, coolTime, delay)
|
||
return player
|
||
end
|
||
|
||
--初始化
|
||
function XSignBoardPlayer:Init(playUi, coolTime, delay)
|
||
|
||
self.CoolTime = coolTime --冷却时间
|
||
self.PlayUi = playUi --执行Ui
|
||
self:SetStatus(PlayerState.IDLE)
|
||
self.DelayStart = XTime.GetServerNowTimestamp() + delay
|
||
self.LastPlayTime = -1
|
||
self.Delay = delay
|
||
self.Time = XTime.GetServerNowTimestamp()
|
||
self.AutoPlay = true
|
||
self.PlayOne = false
|
||
end
|
||
|
||
|
||
-- self.PlayerData.PlayerList = {} --播放列表
|
||
-- self.PlayerData..PlayingElement = nil --播放对象
|
||
-- self.PlayerData.PlayedList = {} --播放过的列表
|
||
-- self.LastPlayTime = -1 --上次播放时间
|
||
function XSignBoardPlayer:SetPlayerData(data)
|
||
self.PlayerData = data
|
||
end
|
||
|
||
--设置播放队列
|
||
function XSignBoardPlayer:SetPlayList(playList)
|
||
if not playList or #playList <= 0 then
|
||
return
|
||
end
|
||
self.PlayerData.PlayerList = {}
|
||
self.PlayerData.LastPlayTime = -1
|
||
self.DelayStart = self.Time + self.Delay
|
||
|
||
for _, element in ipairs(playList) do
|
||
table.insert(self.PlayerData.PlayerList, element)
|
||
end
|
||
end
|
||
|
||
--清空播放队列
|
||
function XSignBoardPlayer:ClearPlayList()
|
||
if not self.PlayerData then
|
||
return
|
||
end
|
||
self.PlayerData.PlayerList = {}
|
||
end
|
||
|
||
--播放
|
||
function XSignBoardPlayer:Play(tab, cvType)
|
||
if not tab then
|
||
return false
|
||
end
|
||
|
||
if not self:IsActive() then
|
||
return false
|
||
end
|
||
|
||
if self.PlayerData.PlayingElement and self.PlayerData.PlayingElement.Id == tab.Id then
|
||
return false
|
||
end
|
||
|
||
local element = {}
|
||
element.Id = tab.Id --Id
|
||
element.AddTime = self.Time -- 添加事件
|
||
element.StartTime = -1 --开始播放的时间
|
||
element.EndTime = -1 --结束时间
|
||
|
||
-- 获取相应语言的动作持续时间
|
||
local duration
|
||
local defaultCvType = 1
|
||
local curElementCvType = cvType or CS.UnityEngine.PlayerPrefs.GetInt("CV_TYPE", defaultCvType)
|
||
|
||
if tab.Duration[curElementCvType] == nil then
|
||
if tab.Duration[defaultCvType] == nil then
|
||
XLog.Error(string.format("XSignBoardPlayer:Play函数错误,配置表SignboardFeedback.tab没有配置Id:%s的Duration数据", tostring(element.Id)))
|
||
return false
|
||
end
|
||
duration = tab.Duration[defaultCvType]
|
||
else
|
||
duration = tab.Duration[curElementCvType]
|
||
end
|
||
|
||
element.Duration = duration
|
||
element.Validity = tab.Validity --有效期
|
||
element.CoolTime = 0--tab.CoolTime --冷却时间
|
||
element.Weight = tab.Weight --权重
|
||
element.SignBoardConfig = tab
|
||
element.CvType = cvType
|
||
table.insert(self.PlayerData.PlayerList, 1, element)
|
||
|
||
return true
|
||
end
|
||
|
||
--播放下一个
|
||
--isRecord决定是否要保存当前动作播放记录
|
||
function XSignBoardPlayer:PlayNext(isRecord)
|
||
if not self:IsActive() then
|
||
return
|
||
end
|
||
|
||
if not self.PlayerData.PlayerList or #self.PlayerData.PlayerList == 0 then
|
||
return
|
||
end
|
||
|
||
--获取第一个在有限期之类的动画
|
||
local head = nil
|
||
--只播放权重最高的动画模式,同权限动画,只随机播放其中一个
|
||
if self.PlayOne then
|
||
local highestWeight = 0
|
||
local randomList = {}
|
||
for index, element in ipairs(self.PlayerData.PlayerList) do
|
||
if element.Weight > highestWeight and self:CheckAnimValidity(element) then
|
||
highestWeight = element.Weight --记录最高权重
|
||
end
|
||
end
|
||
for index, element in ipairs(self.PlayerData.PlayerList) do
|
||
if element.Weight == highestWeight and self:CheckAnimValidity(element) then
|
||
table.insert(randomList,element)
|
||
end
|
||
end
|
||
if #randomList > 0 then
|
||
local index = math.random(1, #randomList)
|
||
head = randomList[index]
|
||
end
|
||
else --顺序播放动画
|
||
while #self.PlayerData.PlayerList > 0 and not head do
|
||
|
||
local element = table.remove(self.PlayerData.PlayerList, 1)
|
||
-- local lastPlayTime = self.PlayerData.PlayedList[temp.Id]
|
||
-- --如果还在冷却中
|
||
-- if lastPlayTime and self.Time < lastPlayTime then
|
||
-- if #self.PlayerData.PlayerList <= 0 then
|
||
-- break
|
||
-- end
|
||
-- temp = table.remove(self.PlayerData.PlayerList, 1)
|
||
-- end
|
||
--检测是否过期
|
||
if self:CheckAnimValidity(element) then
|
||
head = element
|
||
end
|
||
end
|
||
end
|
||
|
||
|
||
--如果找不到合适的动画
|
||
if not head then
|
||
return
|
||
end
|
||
|
||
head.StartTime = self.Time
|
||
|
||
self.PlayerData.PlayingElement = head
|
||
self:SetStatus(PlayerState.PLAYING)
|
||
self.PlayerData.LastPlayTime = head.StartTime + head.Duration
|
||
|
||
if isRecord then
|
||
-- 记录播放过的动作
|
||
XDataCenter.SignBoardManager.RecordSignBoard(head.SignBoardConfig)
|
||
end
|
||
|
||
self.PlayUi:Play(head)
|
||
self:PlayActionAnim(head)
|
||
|
||
if self.PlayOne then
|
||
-- 清空播放列表,只播放当前权重最高的动画(head)
|
||
self.PlayerData.PlayerList = {}
|
||
end
|
||
end
|
||
|
||
function XSignBoardPlayer:PlayNextCross(isRecord)
|
||
if not self:IsActive() then
|
||
return
|
||
end
|
||
|
||
if not self.PlayerData.PlayerList or #self.PlayerData.PlayerList == 0 then
|
||
return
|
||
end
|
||
|
||
--获取第一个在有限期之类的动画
|
||
local head = nil
|
||
--只播放权重最高的动画模式,同权限动画,只随机播放其中一个
|
||
if self.PlayOne then
|
||
local highestWeight = 0
|
||
local randomList = {}
|
||
for index, element in ipairs(self.PlayerData.PlayerList) do
|
||
if element.Weight > highestWeight and self:CheckAnimValidity(element) then
|
||
highestWeight = element.Weight --记录最高权重
|
||
end
|
||
end
|
||
for index, element in ipairs(self.PlayerData.PlayerList) do
|
||
if element.Weight == highestWeight and self:CheckAnimValidity(element) then
|
||
table.insert(randomList,element)
|
||
end
|
||
end
|
||
if #randomList > 0 then
|
||
local index = math.random(1, #randomList)
|
||
head = randomList[index]
|
||
end
|
||
else --顺序播放动画
|
||
while #self.PlayerData.PlayerList > 0 and not head do
|
||
|
||
local element = table.remove(self.PlayerData.PlayerList, 1)
|
||
-- local lastPlayTime = self.PlayerData.PlayedList[temp.Id]
|
||
-- --如果还在冷却中
|
||
-- if lastPlayTime and self.Time < lastPlayTime then
|
||
-- if #self.PlayerData.PlayerList <= 0 then
|
||
-- break
|
||
-- end
|
||
-- temp = table.remove(self.PlayerData.PlayerList, 1)
|
||
-- end
|
||
--检测是否过期
|
||
if self:CheckAnimValidity(element) then
|
||
head = element
|
||
end
|
||
end
|
||
end
|
||
|
||
--如果找不到合适的动画
|
||
if not head then
|
||
return
|
||
end
|
||
|
||
head.StartTime = self.Time
|
||
|
||
self.PlayerData.PlayingElement = head
|
||
self:SetStatus(PlayerState.PLAYING)
|
||
self.PlayerData.LastPlayTime = head.StartTime + head.Duration
|
||
|
||
if isRecord then
|
||
-- 记录播放过的动作
|
||
XDataCenter.SignBoardManager.RecordSignBoard(head.SignBoardConfig)
|
||
end
|
||
|
||
self.PlayUi:PlayCross(head)
|
||
self:PlayActionAnim(head)
|
||
|
||
if self.PlayOne then
|
||
-- 清空播放列表,只播放当前权重最高的动画(head)
|
||
self.PlayerData.PlayerList = {}
|
||
end
|
||
end
|
||
|
||
--检查动画是否过期(时效性)
|
||
function XSignBoardPlayer:CheckAnimValidity(Element)
|
||
if Element.Validity < 0 then
|
||
return true
|
||
else
|
||
local validity = Element.Validity + Element.AddTime
|
||
if validity > self.Time then
|
||
return true
|
||
end
|
||
end
|
||
return false
|
||
end
|
||
|
||
--停止
|
||
function XSignBoardPlayer:Stop(force)
|
||
if self.PlayerData.PlayingElement == nil then
|
||
return
|
||
end
|
||
self.PlayerData.PlayedList[self.PlayerData.PlayingElement.Id] = XTime.GetServerNowTimestamp() + self.PlayerData.PlayingElement.CoolTime
|
||
self:SetStatus(PlayerState.IDLE)
|
||
self.PlayUi:OnStop(self.PlayerData.PlayingElement, force)
|
||
self:StopActionAnim()
|
||
self.PlayerData.PlayingElement = nil
|
||
self.LastPlayTime = XTime.GetServerNowTimestamp()
|
||
end
|
||
|
||
--暂停
|
||
function XSignBoardPlayer:Pause()
|
||
self:SetStatus(PlayerState.PAUSE)
|
||
self:PauseActionAnim()
|
||
end
|
||
|
||
function XSignBoardPlayer:Freeze()
|
||
self:SetStatus(PlayerState.STOP)
|
||
self:PauseActionAnim()
|
||
end
|
||
|
||
function XSignBoardPlayer:Resume()
|
||
self.LastPlayTime = XTime.GetServerNowTimestamp()
|
||
local status = self.PlayerData.PlayingElement == nil and PlayerState.IDLE or PlayerState.PLAYING
|
||
self:SetStatus(status)
|
||
self:ResumeActionAnim()
|
||
end
|
||
|
||
--更新
|
||
function XSignBoardPlayer:Update(deltaTime)
|
||
if not self:IsActive() then
|
||
return
|
||
end
|
||
|
||
if (not self.PlayerData.PlayerList or #self.PlayerData.PlayerList == 0) and self.PlayerData.PlayingElement == nil then
|
||
return
|
||
end
|
||
|
||
if self.Status == PlayerState.STOP then
|
||
return
|
||
end
|
||
|
||
if self.Status == PlayerState.PAUSE then
|
||
return
|
||
end
|
||
|
||
self.Time = self.Time + deltaTime
|
||
|
||
if self.Time < self.DelayStart then
|
||
return
|
||
end
|
||
|
||
local nextElementTime = self.PlayerData.LastPlayTime + self.CoolTime
|
||
|
||
--存在播放中的动作
|
||
if self.PlayerData.PlayingElement ~= nil and self.PlayerData.PlayingElement.Duration > 0 then
|
||
local deadline = self.PlayerData.PlayingElement.StartTime + self.PlayerData.PlayingElement.Duration
|
||
if deadline < self.Time then
|
||
if self.PlayUi.Parent.SetWhetherPlayChangeActionEffect then
|
||
--动作生命周期正常结束,不用播放打断特效
|
||
self.PlayUi.Parent:SetWhetherPlayChangeActionEffect(false)
|
||
end
|
||
self:SetInterruptDetection(false)
|
||
self:Stop()
|
||
return
|
||
end
|
||
end
|
||
|
||
--冷却时间
|
||
if nextElementTime < self.Time and self.Status ~= PlayerState.PLAYING and self.AutoPlay then
|
||
self:PlayNextCross(true)
|
||
end
|
||
end
|
||
|
||
function XSignBoardPlayer:SetInterruptDetection(boolValue)
|
||
self.IsInInterruptDetection = boolValue
|
||
end
|
||
|
||
function XSignBoardPlayer:GetInterruptDetection()
|
||
return self.IsInInterruptDetection
|
||
end
|
||
|
||
--强制运行
|
||
function XSignBoardPlayer:ForcePlay(tab, cvType, isRecord)
|
||
if self.Status == PlayerState.STOP then
|
||
return
|
||
end
|
||
|
||
if self:Play(tab, cvType) then
|
||
self:PlayNext(isRecord)
|
||
end
|
||
end
|
||
|
||
function XSignBoardPlayer:ForcePlayCross(tab, cvType, isRecord)
|
||
if self.Status == PlayerState.STOP then
|
||
return
|
||
end
|
||
|
||
if self:Play(tab, cvType) then
|
||
self:PlayNextCross(isRecord)
|
||
end
|
||
end
|
||
|
||
function XSignBoardPlayer:IsPlaying()
|
||
return self.Status == PlayerState.PLAYING
|
||
end
|
||
|
||
--设置自动播放
|
||
function XSignBoardPlayer:SetAutoPlay(bAutoPlay)
|
||
self.AutoPlay = bAutoPlay
|
||
end
|
||
|
||
-- 播放队列是否只播放权重最高的动画
|
||
function XSignBoardPlayer:SetPlayOne(bPlayOne)
|
||
self.PlayOne = bPlayOne
|
||
end
|
||
|
||
---生命周期----------------------------------------------
|
||
function XSignBoardPlayer:IsActive()
|
||
return self.Active
|
||
end
|
||
|
||
function XSignBoardPlayer:OnEnable()
|
||
self.Active = true
|
||
self:Resume()
|
||
end
|
||
|
||
function XSignBoardPlayer:OnDisable()
|
||
self.Active = false
|
||
self:Stop()
|
||
self:ClearPlayList()
|
||
end
|
||
|
||
function XSignBoardPlayer:OnDestroy()
|
||
self:Stop()
|
||
end
|
||
|
||
-- v1.32 角色特殊动作
|
||
--===================================================================
|
||
|
||
-- 当前播放的动作是否有特殊场景动画
|
||
function XSignBoardPlayer:IsPlayingElementHaveSceneAnim()
|
||
if self.PlayerData.PlayingElement == nil then
|
||
return false
|
||
end
|
||
return XSignBoardConfigs.CheckIsHaveSceneAnim(self.PlayerData.PlayingElement.SignBoardConfig.Id)
|
||
end
|
||
|
||
-- 当前播放的动作是否有特殊Ui动画
|
||
function XSignBoardPlayer:IsPlayingElementHaveUiAnim()
|
||
if self.PlayerData.PlayingElement == nil then
|
||
return false
|
||
end
|
||
return XSignBoardConfigs.CheckIsShowHideUi(self.PlayerData.PlayingElement.SignBoardConfig.Id)
|
||
end
|
||
|
||
-- 开始播放
|
||
function XSignBoardPlayer:PlayActionAnim(head)
|
||
-- Ui动画
|
||
if XSignBoardConfigs.CheckIsShowHideUi(head.SignBoardConfig.Id) then
|
||
if self.PlayUi.PlayUiAnim then
|
||
self.PlayUi:PlayUiAnim()
|
||
end
|
||
XEventManager.DispatchEvent(XEventId.EVENT_ROLE_ACTION_UIANIM_START, head.SignBoardConfig.Id, head.Duration)
|
||
end
|
||
-- 镜头动画
|
||
if XSignBoardConfigs.CheckIsHaveSceneAnim(head.SignBoardConfig.Id) and self.PlayUi.PlaySceneAnim then
|
||
self.PlayUi:PlaySceneAnim(head)
|
||
else -- 避免本次播放没有镜头动画而上个动作有镜头动画且其处于被打断暂停状态时的镜头残留
|
||
XDataCenter.SignBoardManager.SceneAnimStop()
|
||
end
|
||
end
|
||
|
||
function XSignBoardPlayer:PauseActionAnim()
|
||
if self:IsPlayingElementHaveSceneAnim() then
|
||
XDataCenter.SignBoardManager.SceneAnimPause()
|
||
end
|
||
end
|
||
|
||
function XSignBoardPlayer:ResumeActionAnim()
|
||
if self:IsPlayingElementHaveSceneAnim() then
|
||
XDataCenter.SignBoardManager.SceneAnimResume()
|
||
end
|
||
end
|
||
|
||
-- 结束播放
|
||
function XSignBoardPlayer:StopActionAnim()
|
||
-- Ui动画处理
|
||
if self:IsPlayingElementHaveUiAnim() then
|
||
local signBoardid = self.PlayerData.PlayingElement ~= nil and self.PlayerData.PlayingElement.SignBoardConfig.Id
|
||
XEventManager.DispatchEvent(XEventId.EVENT_ROLE_ACTION_UIANIM_END, signBoardid)
|
||
end
|
||
if self:IsPlayingElementHaveSceneAnim() then
|
||
XDataCenter.SignBoardManager.SceneAnimStop()
|
||
end
|
||
-- 取消打断监听
|
||
XDataCenter.SignBoardManager.StopBreakTimer()
|
||
end
|
||
|
||
function XSignBoardPlayer:SetStatus(status)
|
||
self.Status = status
|
||
end
|
||
|
||
--===================================================================
|
||
|
||
return XSignBoardPlayer |