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
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()| Export | Returns | |
|---|---|---|
Play(id, opts) | true if the pose exists | Looks the pose up and plays it. false means no such id |
Stop() | nothing | Stops the current pose, blending out |
IsPlaying() | boolean, id | Whether a pose is playing, and which |
GetClips() | table | Every pose, with id, label, dict, clip, category, duration, mode, walk, rootMotion |
OpenMenu() | nothing | Opens the pose menu |
opts is optional:
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
if GetResourceState('rm_30-custom-female-pose') == 'started' then
exports['rm_30-custom-female-pose']:Play('pose5')
endA photo-mode script
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
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)
endThat 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:
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:
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.
| Flag | Value |
|---|---|
LOOPING | 1 |
HOLD_LAST_FRAME | 2 |
NOT_INTERRUPTABLE | 4 |
UPPERBODY | 8 |
SECONDARY | 16 |
ABORT_ON_PED_MOVEMENT | 32 |
ADDITIVE | 64 |
OVERRIDE_PHYSICS | 128 |
EXTRACT_INITIAL_OFFSET | 256 |
FORCE_START | 8192 |
USE_MOVER_EXTRACTION | 32768 |
DONT_SUPPRESS_LOCO | 65536 |
The combinations the pack itself uses:
| Want | Flags | |
|---|---|---|
| Play once | 0 | No loop, no hold |
| Loop | 1 | What every shipped pose uses |
| Hold the last frame | 2 | Best for screenshots |
| Upper body while moving | 25 | LOOPING + 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.
-- 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
-- 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:
-- _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:
{
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:
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:
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:
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.