FiveM animations and props: TaskPlayAnim flags, attach to bone, delete

Play animations and attach props in FiveM Lua: RequestAnimDict, TaskPlayAnim flags 1, 16, 32 and 49, ClearPedTasks, AttachEntityToEntity to a bone, scenarios and cleanup.

You want a player to drink a coffee, hold a phone or use a tool: an animation, often with a prop in the hand. Done wrong, the animation does nothing, the prop floats at the player's feet or stays in the world forever. This guide shows the working sequence and the cleanup.

Load, play, clear

An animation lives in a dictionary. The dictionary must be loaded before you play from it:

lua
local function playAnim(ped, dict, anim, flag, duration)
    RequestAnimDict(dict)
    while not HasAnimDictLoaded(dict) do
        Wait(0)
    end
    TaskPlayAnim(ped, dict, anim, 8.0, -8.0, duration or -1, flag or 0, 0.0, false, false, false)
end

If HasAnimDictLoaded is never true, the dictionary name is wrong and this loop hangs, so add a timeout when the name comes from config. With ox_lib, one line replaces the loop:

lua
lib.requestAnimDict('mp_player_inteat@burger')

TaskPlayAnim takes the ped, dictionary, animation, blend in, blend out, duration in ms (-1 = until stopped), the flag, and a playback rate. Release the dictionary when you are done with RemoveAnimDict(dict).

The animation flags

The flag is a bitmask, so values add up. The ones you will use:

Flag Effect
0 Play once, player cannot move
1 Loop
16 Upper body only, legs keep walking
32 Player keeps control
49 1 + 16 + 32: loop, upper body, controllable

For a hold-in-hand animation (phone, drink, cigarette), 49 is the usual choice: it loops, only the upper body is animated, and the player can still walk. For a one-shot action where the player should stand still, use 0, or 1 if it should loop.

Stopping the animation

lua
local ped = PlayerPedId()
ClearPedTasks(ped)                 -- stop and let the ped blend out
-- or, if it is stuck:
ClearPedTasksImmediately(ped)      -- cut instantly, can look abrupt
StopAnimTask(ped, dict, anim, 1.0) -- stop only that animation

Use StopAnimTask when several things run on the ped, as ClearPedTasks also cancels the walking or scenario underneath. ClearPedTasksImmediately fixes a stuck ped but also snaps them out of vehicles, so keep it for recovery.

A prop in the hand

A prop is an object you create and attach to a bone of the ped. The sequence: load the model, create the object, attach it, play the animation.

lua
local prop

local function attachProp(ped, model, bone, x, y, z, rx, ry, rz)
    local hash = joaat(model)
    RequestModel(hash)
    while not HasModelLoaded(hash) do Wait(0) end

    local coords = GetEntityCoords(ped)
    prop = CreateObject(hash, coords.x, coords.y, coords.z + 0.2, true, true, false)

    AttachEntityToEntity(
        prop, ped, GetPedBoneIndex(ped, bone),
        x, y, z, rx, ry, rz,
        true, true, false, true, 1, true
    )
    SetModelAsNoLongerNeeded(hash)
    return prop
end

The pieces:

  • CreateObject(model, x, y, z, isNetwork, netMissionEntity, doorFlag): pass isNetwork = true if other players should see the prop, which is normally what you want for something in a hand.
  • GetPedBoneIndex(ped, boneId) converts a bone id such as 28422 (right hand placement) or 18905 (left hand) to an index. Look up the bone id list for others.
  • x, y, z and rx, ry, rz are the offsets and rotation relative to the bone. These need tuning per prop; there is no shortcut, so change a value and test.
  • The booleans after the rotation are soft pinning, collision and similar flags. Collision false prevents the prop pushing the ped around.

Put it together

lua
local function eatBurger()
    local ped = PlayerPedId()
    attachProp(ped, 'prop_cs_burger_01', 28422, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
    lib.requestAnimDict('mp_player_inteat@burger')
    TaskPlayAnim(ped, 'mp_player_inteat@burger', 'mp_player_int_eat_burger', 8.0, -8.0, 3000, 49, 0.0, false, false, false)
    Wait(3000)
    ClearPedTasks(ped)
    deleteProp()
end

If the prop looks wrong in the hand, fix the offsets first, then the bone. If another animation name does not exist in a dictionary, TaskPlayAnim silently does nothing, so double check the pair (the exact dictionary and animation names, in lowercase as written).

Delete the prop

Always clean up. A prop that is not deleted stays in the world, still attached to a ped that no longer holds it:

lua
function deleteProp()
    if prop and DoesEntityExist(prop) then
        DetachEntity(prop, true, true)
        DeleteEntity(prop)
    end
    prop = nil
end

AddEventHandler('onResourceStop', function(resource)
    if resource ~= GetCurrentResourceName() then return end
    deleteProp()
    ClearPedTasks(PlayerPedId())
end)

Also delete the prop on death and when the player leaves the animation, not only on the happy path. Leaked props are a classic source of "objects everywhere" and a slow server; see resmon high ms.

Scenarios

For standing animations that include their own props, such as leaning, smoking or writing on a clipboard, use a scenario instead:

lua
local ped = PlayerPedId()
TaskStartScenarioInPlace(ped, 'WORLD_HUMAN_CLIPBOARD', 0, true)

-- later
ClearPedTasks(ped)

The arguments are the ped, the scenario name, a delay in ms (0 for none) and whether to play the entry animation. Scenarios attach and clean up their prop for you, and they are the easiest option when the animation does not need to be held while walking.

For a ready-made version of animation plus prop plus progress bar, ox_lib's lib.progressBar accepts anim and prop options; see notifications and progress bars and Wait and threads for the waiting habits behind the loops above.

Checklist

Symptom Fix
Animation does nothing Request the dictionary and wait for HasAnimDictLoaded first
Loop hangs at load The dictionary name is wrong; add a timeout
Player frozen in place Flag 0 or 1 blocks movement; use 49 to keep control
Prop at the feet, not the hand Wrong bone or no AttachEntityToEntity; check GetPedBoneIndex
Prop crooked in the hand Tune the x, y, z and rotation offsets
Props left in the world DeleteEntity(prop) on end, death and resource stop
Ped stuck in a pose ClearPedTasks or, as a last resort, ClearPedTasksImmediately

Quick answers

Why does my animation not play?

The animation dictionary was not loaded yet. Call RequestAnimDict, wait until HasAnimDictLoaded is true, and only then call TaskPlayAnim. With ox_lib, lib.requestAnimDict(dict) does this for you.

Which TaskPlayAnim flag should I use?

Use 1 to loop, 16 to play on the upper body only, 32 to let the player keep control, and 49 for loop plus upper body plus controllable. These are the common combinations for animations you hold while walking.

How do I remove a prop after the animation?

Call DeleteEntity(prop) when the animation ends or the script stops, and release the model with SetModelAsNoLongerNeeded. Props left behind pile up in the world.

Scripts that skip this problem

Hookah SystemPlaceable hookahs and lounge furniture with 50+ flavours and effects.View script →Vape System50+ vapes with flavours, smoke and effects — from mango to super speed.View script →Super Leaf BlowerA leaf blower that pushes players, cars, NPCs and props. Works on any framework.View script →

Keep reading