Skip to content

Female Poses Developer API ​

The pack is usable two ways: through its own exports, or as a plain asset pack you drive with natives.

Everything here is client-side. There are no server scripts.

Exports ​

lua
exports['rm_30-custom-female-pose']:Play(id, opts)
exports['rm_30-custom-female-pose']:Stop()
exports['rm_30-custom-female-pose']:IsPlaying()
exports['rm_30-custom-female-pose']:GetClips()
exports['rm_30-custom-female-pose']:OpenMenu()
ExportReturns
Play(id, opts)true if the pose existsLooks the pose up and plays it. false means no such id
Stop()nothingStops the current pose, blending out
IsPlaying()boolean, idWhether a pose is playing, and which
GetClips()tableEvery pose, with id, label, dict, clip, category, duration, mode, walk, rootMotion
OpenMenu()nothingOpens the pose menu

opts is optional:

lua
exports['rm_30-custom-female-pose']:Play('pose5', {
    mode  = 'loop',   -- 'once' | 'loop' | 'hold'
    walk  = true,     -- upper body only; keep moving
    speed = 1.0,      -- clamped to Config.MinSpeed..MaxSpeed
})

Use Play rather than natives if you can

It resolves the dictionary for you, which means the two odd pairs — hatsdown_clip and pose29 — just work. It also applies the guards, the holster and the speed clamp.

Play returns true as soon as the pose is found, not when it starts — the actual playback runs in a thread so your caller is not blocked while the dictionary streams.

Guard it if the pack is optional ​

lua
if GetResourceState('rm_30-custom-female-pose') == 'started' then
    exports['rm_30-custom-female-pose']:Play('pose5')
end

A photo-mode script ​

lua
RegisterCommand('photopose', function(_, args)
    local id = args[1] or 'pose5'
    local ok = exports['rm_30-custom-female-pose']:Play(id, { mode = 'hold', speed = 0.5 })
    if not ok then
        print(('no such pose: %s'):format(id))
    end
end, false)

hold freezes on the final frame, which is usually a cleaner photograph than a point in the loop.

Building your own picker ​

lua
for _, c in ipairs(exports['rm_30-custom-female-pose']:GetClips()) do
    print(c.id, c.label, c.category, c.dict, c.clip, c.duration, c.mode)
end

That is the same list the built-in menu draws, so a custom picker and the shipped one can never disagree.

Natives directly ​

If you would rather not depend on the resource's exports:

lua
local ped  = PlayerPedId()
local dict = 'redmorrow_com@pose5'
local clip = 'pose5'

RequestAnimDict(dict)
while not HasAnimDictLoaded(dict) do Wait(0) end

TaskPlayAnim(ped, dict, clip, 4.0, -4.0, -1, 1, 0.0, false, 0, false, 0, false)

Always wait for the dictionary

Calling TaskPlayAnim before HasAnimDictLoaded returns true is what produces a T-pose flash, or nothing at all. Give the wait a timeout so a missing dictionary reports itself instead of spinning forever.

RedM's TaskPlayAnim takes 13 parameters:

lua
TaskPlayAnim(
    ped,        -- entity
    dict,       -- animation dictionary
    clip,       -- clip name inside it
    blendIn,    -- 4.0
    blendOut,   -- -4.0
    duration,   -- -1 = the clip's own length
    flags,      -- see below
    startPhase, -- 0.0
    p8,         -- false
    ikFlags,    -- 0
    p10,        -- false
    taskFilter, -- 0
    p12         -- false
)

RDR3 animation flags ​

RDR3 flag values are not GTA V's

Copying a flag number out of a FiveM resource will do something other than what you expect.

FlagValue
LOOPING1
HOLD_LAST_FRAME2
NOT_INTERRUPTABLE4
UPPERBODY8
SECONDARY16
ABORT_ON_PED_MOVEMENT32
ADDITIVE64
OVERRIDE_PHYSICS128
EXTRACT_INITIAL_OFFSET256
FORCE_START8192
USE_MOVER_EXTRACTION32768
DONT_SUPPRESS_LOCO65536

The combinations the pack itself uses:

WantFlags
Play once0No loop, no hold
Loop1What every shipped pose uses
Hold the last frame2Best for screenshots
Upper body while moving25LOOPING + UPPERBODY + SECONDARY

walk ORs UPPERBODY | SECONDARY onto the mode flag rather than replacing it — loop plus walk is 25, hold plus walk is 26, and only mode = 'once' plus walk gives 24.

lua
-- loop
TaskPlayAnim(ped, dict, clip, 4.0, -4.0, -1, 1, 0.0, false, 0, false, 0, false)

-- hold the final frame
TaskPlayAnim(ped, dict, clip, 4.0, -4.0, -1, 2, 0.0, false, 0, false, 0, false)

-- upper body, keep walking (every shipped pose is mode 'loop', so the pack passes 25)
TaskPlayAnim(ped, dict, clip, 4.0, -4.0, -1, 25, 0.0, false, 0, false, 0, false)

Stopping, checking and speed ​

lua
-- normal stop, with a blend-out
StopAnimTask(ped, dict, clip, 2.0)

-- a clip started with SECONDARY (flags 25 or 26) also occupies the ped's
-- secondary task slot: clear that slot as well
ClearPedSecondaryTask(ped)
StopAnimTask(ped, dict, clip, 2.0)

-- last resort: cancels everything the ped is doing, no blend
ClearPedTasks(ped, true, false)

IsEntityPlayingAnim(ped, dict, clip, 3)

The pack's own stop does the same: for a clip it started with the SECONDARY flag it calls ClearPedSecondaryTask before StopAnimTask, and it falls back to ClearPedTasks only if a clip is still playing after the blend-out.

Speed is a separate native, and one call will not hold it:

lua
-- _SET_ENTITY_ANIM_SPEED does not stick — one call will not hold the multiplier.
-- Wait for the task to actually start, then re-apply it for as long as the clip runs.
CreateThread(function()
    for _ = 1, 60 do -- TaskPlayAnim only begins on a later frame
        if IsEntityPlayingAnim(ped, dict, clip, 3) then break end
        Wait(0)
    end
    while IsEntityPlayingAnim(ped, dict, clip, 3) do
        Citizen.InvokeNative(0xEAA885BA3CEA4E4A, ped, dict, clip, 1.5)
        Wait(0)
    end
end)

Let the pack hold the speed for you

The pack runs a watcher thread per pose that waits for the task to start and then re-applies the speed every frame for as long as the speed is not 1.0 — at exactly 1.0 it skips the native entirely and just polls for the clip ending. Play's speed option and the menu's speed slider both rely on that thread, so prefer them over driving the native yourself.

Adding them to an emote system ​

Every emote system needs the same two values — the dictionary and the clip. Take them from the animation list or read them out of clips.lua.

A generic entry:

lua
{
    name     = 'Leaning on the rail',
    command  = 'fpose5',
    dict     = 'redmorrow_com@pose5',
    clip     = 'pose5',
    flag     = 1,
    duration = -1,
}

Copy the pairs; do not generate them

'redmorrow_com@' .. id is right for twenty-seven poses and wrong for two. hatsdown_clip is in redmorrow_com@pose7 and pose29 is in redmorrow_com@pose26.

With RedM Emotes ​

RedM Emotes is database-driven, so each pose is a row — dict, name (the clip), a display name, and is_loop = 1:

sql
INSERT INTO `rm_emotes` (dict, name, custom_name, duration, category, is_loop, emote_type)
VALUES ('redmorrow_com@pose5', 'pose5', 'Leaning on the rail', -1, 'position', 1, 'anim');

Then rebuild its library, or the row stays invisible until a restart:

lua
exports.rm_emotes:Rebuild()

Start this pack before or alongside your emote resource so the dictionaries exist when a player opens the menu.

Two scripts, one character ​

Starting an animation clears the ped's tasks, and another resource's TaskPlayAnim will clear yours right back. If you drive a pose from your own script while an emote menu is also running, stop the other one deliberately:

lua
exports.rm_emotes:Stop()
exports['rm_30-custom-female-pose']:Play('pose5')

More on that in Animations.

On resource stop ​

The pack clears the pose off the character and releases its dictionaries when it stops. That ordering matters: an animation left playing from a dictionary that has been unloaded underneath it is the usual cause of a frozen or T-posing character.

If you hold a reference to one of these dictionaries in your own resource, release it on your own onResourceStop too.

Documentation for RedMorrow. Scripts are licensed per server — redistribution is not permitted.