forked from Simnation/Main
155 lines
No EOL
5.3 KiB
Lua
155 lines
No EOL
5.3 KiB
Lua
Anim = Anim or {}
|
|
Ids = Ids or Require("lib/utility/shared/ids.lua")
|
|
Anim.Active = Anim.Active or {}
|
|
Anim.isUpdateLoopRunning = Anim.isUpdateLoopRunning or false
|
|
|
|
--- This will request the animation dictionary.
|
|
--- @param animDict string
|
|
--- @return boolean
|
|
function Anim.RequestDict(animDict)
|
|
if not animDict or type(animDict) ~= "string" then
|
|
return false
|
|
end
|
|
|
|
if HasAnimDictLoaded(animDict) then
|
|
return true
|
|
end
|
|
|
|
RequestAnimDict(animDict)
|
|
local timeout = GetGameTimer() + 2000
|
|
while not HasAnimDictLoaded(animDict) and GetGameTimer() < timeout do
|
|
Wait(50)
|
|
end
|
|
|
|
return HasAnimDictLoaded(animDict)
|
|
end
|
|
|
|
--- This will start the animation update loop.
|
|
function Anim.Start()
|
|
if Anim.isUpdateLoopRunning then return end
|
|
Anim.isUpdateLoopRunning = true
|
|
CreateThread(function()
|
|
while Anim.isUpdateLoopRunning do
|
|
local idsToProcess = {}
|
|
for idKey, _ in pairs(Anim.Active) do
|
|
table.insert(idsToProcess, idKey)
|
|
end
|
|
|
|
if #idsToProcess == 0 then
|
|
Wait(750)
|
|
else
|
|
for _, id in ipairs(idsToProcess) do
|
|
local animData = Anim.Active[id]
|
|
if animData then
|
|
local entity = animData.entity
|
|
local onComplete = animData.onComplete
|
|
if not DoesEntityExist(entity) then
|
|
if onComplete then onComplete(false, "despawned") end
|
|
Anim.Active[id] = nil
|
|
elseif animData.status == "pending_task" then
|
|
TaskPlayAnim(entity, animData.animDict, animData.animName, animData.blendIn, animData.blendOut, animData.duration, animData.flag, animData.playbackRate, false, false, false)
|
|
animData.startTime = GetGameTimer()
|
|
animData.animEndTime = animData.duration > 0 and (animData.startTime + animData.duration) or -1
|
|
animData.status = "playing"
|
|
elseif animData.status == "playing" then
|
|
local animationCompletedNaturally = false
|
|
if animData.duration == -1 then
|
|
if not IsEntityPlayingAnim(entity, animData.animDict, animData.animName, 3) and GetEntityAnimCurrentTime(entity, animData.animDict, animData.animName) > 0.8 then
|
|
animationCompletedNaturally = true
|
|
end
|
|
elseif animData.animEndTime ~= -1 and GetGameTimer() >= animData.animEndTime then
|
|
animationCompletedNaturally = true
|
|
end
|
|
if animationCompletedNaturally then
|
|
if onComplete then onComplete(true, "completed") end
|
|
Anim.Active[id] = nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
Wait(100)
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
--- This will play an animation on the specified ped.
|
|
--- @param id string | nil
|
|
--- @param entity number
|
|
--- @param animDict string
|
|
--- @param animName string
|
|
--- @param blendIn number | nil
|
|
--- @param blendOut number | nil
|
|
--- @param duration number | nil
|
|
--- @param flag number | nil
|
|
--- @param playbackRate number | nil
|
|
--- @param onComplete function | nil
|
|
--- @return string | nil
|
|
function Anim.Play(id, entity, animDict, animName, blendIn, blendOut, duration, flag, playbackRate, onComplete)
|
|
local newId = id or Ids.CreateUniqueId(Anim.Active)
|
|
if Anim.Active[newId] then
|
|
if onComplete then
|
|
onComplete(false, "id_in_use")
|
|
end
|
|
return newId
|
|
end
|
|
|
|
if not entity or not DoesEntityExist(entity) or not IsEntityAPed(entity) then
|
|
if onComplete then
|
|
onComplete(false, "invalid_entity")
|
|
end
|
|
return nil
|
|
end
|
|
|
|
if not Anim.RequestDict(animDict) then
|
|
if onComplete then
|
|
onComplete(false, "dict_load_failed")
|
|
end
|
|
return nil
|
|
end
|
|
|
|
Anim.Active[newId] = {
|
|
entity = entity,
|
|
animDict = animDict,
|
|
animName = animName,
|
|
blendIn = blendIn or 8.0,
|
|
blendOut = blendOut or -8.0,
|
|
duration = duration or -1,
|
|
flag = flag or 1,
|
|
playbackRate = playbackRate or 0.0,
|
|
onComplete = onComplete,
|
|
status = "pending_task",
|
|
startTime = 0,
|
|
animEndTime = 0
|
|
}
|
|
|
|
Anim.Start()
|
|
return newId
|
|
end
|
|
|
|
function Anim.Stop(id)
|
|
if not id or not Anim.Active or not Anim.Active[id] then
|
|
return false
|
|
end
|
|
|
|
local animData = Anim.Active[id]
|
|
|
|
if animData.entity and DoesEntityExist(animData.entity) and IsEntityAPed(animData.entity) then
|
|
if animData.status == "playing" or animData.status == "pending_task" then
|
|
StopAnimTask(animData.entity, animData.animDict, animData.animName, 1.0)
|
|
end
|
|
end
|
|
|
|
if animData.onComplete then
|
|
animData.onComplete(false, "stopped_by_id")
|
|
end
|
|
|
|
Anim.Active[id] = nil
|
|
local anyLeft = Anim.Active and next(Anim.Active) ~= nil
|
|
if not anyLeft then
|
|
Anim.isUpdateLoopRunning = false
|
|
end
|
|
return true
|
|
end
|
|
|
|
return Anim |