Playing a Pose
This pack has no menu, no chat command, no key binding and no exports. Unzipped and started, it streams 104 .ycd files into the game and prints one line in the server console. Nothing plays a pose until your own code asks for one.
That is the whole job of this page.
What you are driving
Each pose is two strings — a dictionary and a clip — and clips.lua is where both come from.
| Poses | 99 live entries in clips.lua |
| Mode | Every one is loop. There are no once or hold entries |
| Root motion | None. No pose moves the character off its spot |
| Body | Female only. No male variant ships anywhere in the pack |
| Prefix | redmorrow@ … @f |
99, not 100
clips.lua holds 105 rows and six of them are commented out, leaving 99 you can play. Their .ycd files are still in stream/, so nothing is missing from your download — deleting the -- in front of a row brings it back. See The clips.lua table.
The resource's own README describes a build this is not
README.md and the comment header at the top of clips.lua both mention an in-game menu, a /redmorrow command, exports['redmorrow']:Play(), a Config.ForceBody option, and files called config.lua, client.lua and html/. None of those exist in this download — the only files are fxmanifest.lua, clips.lua, a one-line server.lua, README.md and stream/.
The README is stale, not wrong about the clips. Its dictionary and clip names are accurate; its instructions are for a version with a client script. Treat clips.lua as the authority and this page as the instructions.
The minimal working script
local function PlayPose(dict, clip)
local ped = PlayerPedId()
RequestAnimDict(dict)
local deadline = GetGameTimer() + 5000
while not HasAnimDictLoaded(dict) do
if GetGameTimer() > deadline then
print(('[pose] dictionary never loaded: %s'):format(dict))
return false
end
Wait(0)
end
TaskPlayAnim(ped, dict, clip, 4.0, -4.0, -1, 1, 0.0, false, 0, false, 0, false)
return true
endThree steps, in this order every time: ask for the dictionary, wait until the game confirms it is loaded, then start the task. Skipping the middle step is the single most common reason a pose does nothing.
Where the code goes
Config.Clips is a global inside the redmorrow resource. CFX gives every resource its own Lua state, so another resource cannot read it — there is no GetClips() here and no shared table to require. You have two options:
Put a client script in your own resource and copy the dictionary/clip pairs you need into it. This is the normal choice: your code stays yours, and a pack update cannot overwrite it.
Add a client script to this resource. Drop a
client.luabesideclips.lua, add it toclient_scriptsinfxmanifest.luaafterclips.lua, and it will seeConfig.Clipsdirectly. Both files are outside escrow, so this works — but remember you are editing a file the next version of the pack will replace.
Either way the pack itself must be started, or the dictionaries do not exist in the game at all. The ensure line has to match the folder name on disk — see Installation.
The thirteen arguments
RDR3's TaskPlayAnim takes thirteen parameters, and its flag values are not GTA V's.
| # | Argument | Above | What it does |
|---|---|---|---|
| 1 | ped | PlayerPedId() | Who plays it |
| 2 | dict | from clips.lua | The dictionary |
| 3 | clip | from clips.lua | The clip name inside it |
| 4 | blendIn | 4.0 | How fast the pose blends on. Higher is snappier |
| 5 | blendOut | -4.0 | How fast it blends off when it ends. Negative is the normal form |
| 6 | duration | -1 | Milliseconds, or -1 for no time limit |
| 7 | flags | 1 | The flag word |
| 8 | startPhase | 0.0 | Where in the clip to begin. 0.0 is the first frame |
| 9 | — | false | Leave it |
| 10 | ikFlags | 0 | Leave it |
| 11 | — | false | Leave it |
| 12 | taskFilter | 0 | Leave it |
| 13 | — | false | Leave it |
Three of those are worth understanding and the rest you can copy.
Blend in and blend out. 4.0 and -4.0 give a quick, clean transition into and out of the pose. Lower the blend-in to around 1.0 for a slow settle into the pose; that reads better on the long idles and worse on the one-frame poses, which have nothing to blend toward.
Duration -1. No time limit — the task runs until something stops it. A fixed number here is a millisecond count, so 5000 holds the pose for five seconds and then releases the character.
The flag word. 1 is what the pack's own header documents, and it is the loop behaviour these poses are built for.
RDR3 flag values are not GTA V's
A flag number copied out of a FiveM resource will do something other than what you expect here. If you need behaviour beyond the documented call, read the values from the RedM platform notes rather than a FiveM snippet.
Why the wait is not optional
A clip requested from a dictionary that has not loaded fails silently. No console error, no warning, no T-pose. The character stands there, and your code has no idea anything went wrong because TaskPlayAnim returns nothing either way.
This is cause number one of "the pose does nothing".
The timeout in the script above exists so the failure reports itself. Without it, while not HasAnimDictLoaded(dict) do Wait(0) end spins forever on a typo and the pose never arrives — which looks exactly like the silent failure it was meant to prevent.
If a specific pose refuses to come up, check the dictionary name before anything else:
print(DoesAnimDictExist('redmorrow@pose5@f'))false means the name is wrong or the resource is not started. true with a dead character means the clip name is wrong — the dictionary loaded, and the clip you asked for is not in it. More symptoms in Troubleshooting.
Looping is the only mode these ship as
All 99 entries carry mode = 'loop', and that is not an oversight. These are poses, not actions — they have no beginning and no end to play through.
Eight of them are 0.033 s long, which is one frame at 30 fps. Played once, a one-frame clip is over before the blend finishes and you see nothing. Looped, it is a static pose held indefinitely, which is the point of a pose pack. Another 47 run under two seconds and would be gone almost as fast. Four more run 3.7 s and 21 run 9 s, which is long enough to carry visible movement; the single 59 s entry and the eighteen 89 s ones are full idles.
The duration field in clips.lua is metadata the author wrote. Nothing in the pack reads it, and it is not what you pass as argument 6 — leave that at -1 and let the clip loop. Full breakdown in the animation list.
The character stays put
rootMotion = false on all 99. No pose walks, turns or drifts the character, so wherever you stand when the pose starts is where you remain. That makes these safe to play in tight interiors and on a photo mark without the ped wandering out of frame.
Female only
Every row's bodies table has a female key and nothing else. There is no male variant anywhere in the pack, and no body switching to configure.
A male ped handed one of these dictionaries will play it. RDR2's skeletons are close enough that it does not error — it reads as a female pose on a male character, which is usually not what you want. If your server has mixed characters, gate the command on the player's model yourself.
Stopping
ClearPedTasks(PlayerPedId())That cancels what the ped is doing and returns it to idle. If you started the clip with a flag that puts it in the secondary task slot, clear that slot too:
local ped = PlayerPedId()
ClearPedSecondaryTask(ped)
ClearPedTasks(ped)Calling both is harmless when only one applies, which makes it the safe default for a stop command.
Another script's animation will clear yours
Starting an animation clears the ped's tasks. If an emote resource is also running, its next play wipes your pose and yours wipes its emote. Stop the other one deliberately rather than letting the two fight — see Animations.
A worked example
A /pose command inside your own resource, reading the id from the player:
-- client.lua in your own resource
local Poses = {
pose5 = { dict = 'redmorrow@pose5@f', clip = 'pose5' },
lean = { dict = 'redmorrow@lean@f', clip = 'lean' },
smoke = { dict = 'redmorrow@smoke@f', clip = 'smoke' },
hatsdown_clip = { dict = 'redmorrow@pose7@f', clip = 'hatsdown_clip' },
}
RegisterCommand('pose', function(_, args)
local ped = PlayerPedId()
local id = args[1]
if not id or id == 'stop' then
ClearPedSecondaryTask(ped)
ClearPedTasks(ped)
return
end
local pose = Poses[id]
if not pose then
print(('[pose] no such pose: %s'):format(id))
return
end
PlayPose(pose.dict, pose.clip)
end, false)/pose lean plays it, /pose stop clears it, /pose nonsense says so in the F8 console instead of failing quietly. PlayPose is the function from the top of this page.
Four poses are listed there and the pack has 99. Copy the rows you want out of clips.lua rather than typing them from the list — it ships readable for exactly this reason.
Where the two strings come from
The dictionary and clip for every pose are in The clips.lua table, and tabulated with their durations in the animation list.
Never derive a dictionary from an id
'redmorrow@' .. id .. '@f' is correct for 92 of the 99 poses and wrong for seven. pose1 is in redmorrow@regard7@f. pose28 is in redmorrow@pose27@f. hatsdown_clip is in redmorrow@pose7@f. And pose47_pose47 is in redmorrow@pose47@f — the one whose clip name saves you and whose id does not.
Code that builds the name instead of reading it hits the silent failure above on those seven, and nothing in the console tells you why. The full list is at seven ids that do not match their dictionary.
Once you have the pairs, dropping them into an emote system is usually less work than maintaining your own command — Integrating with an emote system covers that, and RedM Emotes takes a dictionary and clip per row.