TaskPlayAnim

Hello everyone!

I’m trying to use TaskPlayAnim to play the ATM enter animation but it seems that isn’t working well…
The game block the commands for the local player but the in-game ped doesn’t move.

Here is my code:

function PlayTask(dict, name, loop)
    local lockX, lockY, lockZ, flag = 0, 0, 0, 0
    
    if name == "rcmepsilonism8" or name == "rcmpaparazzo_3" then lockX = 1
    elseif name == "mini@sprunk" then lockX = 2 end
    
    if name == "missfam5_yoga" or name == "missfra1mcs_2_crew_react" then lockY = 1 end
    if PlayAnyTask.MP then lockZ = 1 end
    if stringtoboolean[loop] then flag = 1 end

    ClearPedTasks(ped)
    Wait(1) -- just giving some time for ped to actually stop any anim
    RequestAnimDict(dict)
    while not HasAnimDictLoaded(dict) do Wait(500) end
    TaskPlayAnim(ped, dict, name, 8.0, 8.0, -1, flag, 1.0, lockX, lockY, lockZ)
    while IsEntityPlayingAnim(ped, dict, name, 3) do Wait(500) end
    RemoveAnimDict(dict)
end

NOTE: This is just a function that is being called in a thread when a certain code is triggered, i.e, it doesn’t run every ms.

I’ve debugged everything and everything seems to work fine. The only thing that doesn’t work is the in-game animation.
There aren’t errors on either client or server consoles.

Thanks for reading! :smile:

Check that the dictionary name is correct, the animation name is accurate,
the ped outside of this function is correctly declared and not null,
lock in most cases is false

function PlayTask(dict, name, loop)
    local lockX, lockY, lockZ, flag = 0, 0, 0, 0
    
    if name == "rcmepsilonism8" or name == "rcmpaparazzo_3" then lockX = 1
    elseif name == "mini@sprunk" then lockX = 2 end
    
    if name == "missfam5_yoga" or name == "missfra1mcs_2_crew_react" then lockY = 1 end
    if PlayAnyTask.MP then lockZ = 1 end
    if stringtoboolean[loop] then flag = 1 end

    if dict == "amb@prop_human_atm@male@enter" and name == "enter" then print("dict and name are both right") end
    if ped and ped == PlayerPedId() then print("ped is right") end

    ClearPedTasks(ped)
    Wait(1) -- just giving some time for ped to actually stop any anim
    RequestAnimDict(dict)
    while not HasAnimDictLoaded(dict) do Wait(500) end
    TaskPlayAnim(ped, dict, name, 8.0, 8.0, -1, flag, 1.0, lockX, lockY, lockZ)
    while IsEntityPlayingAnim(ped, dict, name, 3) do Wait(500) end
    RemoveAnimDict(dict)
end

Hello @minguez , thanks for your answer!
As you can see, i’ve debugged the dict, name and ped variables and everything is right.

About the lockX, lockY and lockZ variables, they aren’t always false. In most cases they are and that’s why I’ve declared them as false but in some specific cases they can be integer numbers.
You can check that information in the native reference: TaskPlayAnim

lockX:
0 in most cases
1 for rcmepsilonism8 and rcmpaparazzo_3
more than 1 for mini@sprunk
lockY:
0 in most cases
1 for missfam5_yoga, missfra1mcs_2_crew_react
lockZ:
0 for single player
Can be 1 but only for MP

I’ve figured it out!
It seems that the playbackRate variable needs to be between 0.0 and 1.0 and it depends on what task you are trying to play. Check out TaskPlayAnim for more information.

playbackRate:
values are between 0.0 and 1.0

The same seem to happen for the animTime variable in the TaskPlayAnimAdvanced

animTime: Value between 0.0 and 1.0, lets you start an animation from the given point

For those who are interested, here is my current working code with both normal and advanced functions.
I’ve used the ATM animations for this test.
NOTE: this is just functions. To make it work you need to adapt to your own code.

local PlayAnyTask = {
    MP = true # true if game mode is MultiPlayer (example: FiveM) | false if game mode is SinglePlayer
}

local function LoadAnimDict(dict)
    RequestAnimDict(dict)
    while not HasAnimDictLoaded(dict) do Wait(500) end
    #  You can also decrease this waiting time to 0 if you want.
    # I use 500ms so it doesn't have a chance to crash your game if the task/anim gets too much time to load..
end

# This is just a function I've made to easly transform a string to boolean.
# I don't know why but when you pass a variable to a function with the value true/false,
# that variable transforms the boolean into a string.
local function StringToBoolean(str)
    if string.upper(tostring(str)) == "TRUE" then return true end
    return false
end

function PlayTask(dict, name, loop, playbackRate)
    local lockX, lockY, lockZ, flag = 0, 0, 0, 0
    playbackRate = playbackRate or 0.0

    if name == "rcmepsilonism8" or name == "rcmpaparazzo_3" then lockX = 1
    elseif name == "mini@sprunk" then lockX = 2 end
    
    if name == "missfam5_yoga" or name == "missfra1mcs_2_crew_react" then lockY = 1 end
    if PlayAnyTask.MP then lockZ = 1 end
    if StringToBoolean(loop) then flag = 1 end

    ClearPedTasks(ped)
    LoadAnimDict(dict)
    TaskPlayAnim(ped, dict, name, 8.0, 8.0, -1, flag, playbackRate, lockX, lockY, lockZ)
    RemoveAnimDict(dict)
end

function PlayAdvancedTask(dict, name, loop, animTime, coords)
    local lockX, lockY, lockZ, flag = 0, 0, 0, 0
    animTime = animTime or 0.0
    
    if name == "rcmepsilonism8" or name == "rcmpaparazzo_3" then lockX = 1
    elseif name == "mini@sprunk" then lockX = 2 end
    
    if name == "missfam5_yoga" or name == "missfra1mcs_2_crew_react" then lockY = 1 end
    if PlayAnyTask.MP then lockZ = 1 end
    if StringToBoolean(loop) then flag = 1 end
    
    ClearPedTasks(ped)
    LoadAnimDict(dict)
    TaskPlayAnimAdvanced(ped, dict, name, coords.x, coords.y, coords.z, 0.0, 0.0, coords.heading, 8.0, 8.0, -1, flag, animTime, false, false)
    RemoveAnimDict(dict)
end

In case you want to use 2 animations, one after the other, i got it to work with this code

local ped = PlayerPedId()

PlayAdvancedTask(ped, "amb@prop_human_atm@male@enter", "enter", false, 0.0, atmCoords)
Wait(0) # time to load the task/anim

local taskWaitTime = GetEntityAnimTotalTime(ped, "amb@prop_human_atm@male@enter", "enter") - GetEntityAnimCurrentTime(ped, "amb@prop_human_atm@male@enter", "enter")
Wait(taskWaitTime)
# You can either do this way or the following way
while IsEntityPlayingAnim(ped, "amb@prop_human_atm@male@enter", "enter", 3) do Wait(0) end
# This way seems to work smoothly and the code appears cleaner but I can't really tell which way is faster..
# You still need the Wait(0) to give time for the animation to fully load

PlayTask("amb@prop_human_atm@male@base", "base", true, 0.0)
# This task/anim needs to be stopped since it's in an infinite loop.
# To do that you just need to run the following line of code.
ClearPedTasks(ped) # this one will stop any animation that the ped is doing
StopAnimTask(ped, "amb@prop_human_atm@male@base", "base", 8.0) # this one will stop the anim given.
# I do recommend to use this last one with the IsEntityPlayingAnim native to check if the anim is currently playing

Thanks to @minguez that tried to help!

Thank you all for reading this! :smile: