Skip to content

Integrating Everyday Animations ​

This is the route most servers take, and the one the pack is shaped for.

The resource streams animations and ships a list of them. It is fxmanifest.lua, a data table in clips.lua, a one-line server.lua, and 38 .ycd files in stream/. There is no client script, so nothing inside the pack plays an animation — players reach these through the emote menu your server already runs, or through code of your own.

That turns out to be the easy case, because an emote menu asks for exactly what this pack is made of.

What an emote menu needs from you ​

Every emote system reduces a custom animation to the same small set of values. Whatever the fields are called in your resource, these are what to put in them:

What the menu asks forWhat to give it
DictionaryThe dictionary from the animation list — one of 19
Clip nameThe id. On all 94 rows the clip name is the id
Flag1 to loop. See Flags below
DurationWhatever the resource uses for "run until stopped", normally -1
Loop settingOn for the 46 loop rows, off for the 48 once rows
Label and categoryYours to choose

Two properties of the data make this mechanical rather than fiddly, and they hold on every row with no exceptions:

clip          == id
bodies.male   == dict
bodies.female == dict .. '@f'

So one line in the list gives you both strings for a male row and both for a female row. There is nothing to look up twice and nothing to cross-reference. The proof per row is in Every dictionary ships twice.

A row in a generic emote resource therefore looks like this, with your resource's own field names:

lua
{
    label    = 'Salute',
    command  = 'salute',
    dict     = 'rm@salute',
    clip     = 'salute',
    duration = -1,
}

Ninety-three more rows differ from that one in three strings.

Do not build the dictionary from the id

'rm@' .. id is correct for the 15 Greetings & Social animations, which each have a dictionary of their own, and wrong for the other 79, which live in four shared dictionaries — rm@communication_gestures, rm@reactions_expressions, rm@standing_idle and rm@casual_actions.

'rm@' .. 'salute' is rm@salute and plays. 'rm@' .. 'yawn' is rm@yawn, which does not exist, and a clip asked for from a dictionary that never loaded fails silently — no console error, no warning, the character stands there. Read dict off the row instead of constructing it.

Flags ​

RedM has its own animation flag values, and they are not GTA V's. A flag word copied out of a FiveM emote resource will not mean here what it meant there, which is the single most common reason a row that looks right behaves oddly.

Flag 1 — loop — is the known-good value for this pack and the one to start from. If your menu exposes other flag values, set one animation up with them and watch it in game before you apply it to the rest; guessing from a FiveM number is how a whole category ends up subtly wrong. Playing an animation covers the native call, where RDR3's TaskPlayAnim takes thirteen arguments.

Duration -1 means no time limit. Combined with the loop flag, the animation runs until something stops it.

Do not pass the duration figure to the menu as a play time

The numbers in the list are metadata the pack author wrote into clips.lua. Nothing reads them, and a 1.967-second gesture given a 1.967-second play time is over before the player has let go of the key. Use the figure to sort or label your menu, and let the loop flag and your stop control decide when the animation ends. GET_ANIM_DURATION is the authority on what the game thinks a clip's length actually is.

The 15 greetings ship as loop, and they are one-shot gestures

Every row in Greetings & Social carries mode = 'loop' in the list, but a 0.533-second waving on repeat reads as a twitch rather than a wave. Set your menu's loop setting off for those 15 unless you specifically want them repeating. The split across all 94 is 48 once and 46 loop — see Lengths.

Handling both bodies ​

Every animation ships twice: a version fitted to the male body and one fitted to the female body, under an identical clip name. Both versions play on either body. Neither one breaks. The matching one fits better — a male-fitted gesture on a female character reads as slightly off rather than wrong.

If your menuThen
Supports a per-body dictionaryPoint female characters at dict .. '@f'
Does notAdd each animation twice, labelled "(M)" and "(F)", or pick one version for everyone

Adding each one twice turns 94 rows into 188 and puts the choice on the player, which is honest but doubles the list. Using the male version for everyone is a legitimate choice if your menu cannot branch, and most of these animations are gestures where the difference is small.

If your menu hands the animation to a function of yours, pick the dictionary there:

lua
-- isFemale comes from your own character data. On this pack the female
-- dictionary is always the male one with '@f' appended, so there is nothing
-- to look up.
local function dictFor(row, isFemale)
    if isFemale then
        return row.dict .. '@f'
    end
    return row.dict
end

Prefer your server's own character-sex field over IsPedMale

IsPedMale is reliable on standard multiplayer and story peds and can be wrong on heavily customised ones. If your framework already stores a sex on the character — and in a roleplay server it almost always does — read that instead. It is the value the player picked, which is also the value they expect their animations to follow.

Appending @f is safe here precisely because the pairing is mechanical on all 94 rows. All 38 files are present: 19 dictionaries times two bodies, none missing and none left over.

With RedM Emotes ​

RedM Emotes stores its library as rows, and each row carries a dictionary and a clip name. That is all these animations need, so they drop in like any other custom dictionary: one row per animation, the dictionary from the list, the clip name equal to the id, the loop setting to taste, and a label of your choosing.

The three supported ways to add a row, the exact column names, and the cache rebuild you need afterwards are documented at Three ways to add an emote. Nothing about this pack changes that procedure.

Two things are worth deciding before you start inserting rows, because both are cheaper to settle up front than to unpick in a library of a few thousand entries:

  • The label and the category are yours. Several ids in this pack read as filenames rather than as names — idle_clip, good_by, hand_in_back — and the two long ones read as sentences. The id has to match the clip; the label a player sees does not.
  • Two ids appear twice. pointing and pointing_gesture each exist in two different dictionaries, so two of your rows will want distinct names. See Generating the rows below.

Generating the rows instead of typing 94 ​

Ninety-four rows is past the point where hand-typing is a good use of an evening, and hand-typing is exactly where a wrong dictionary gets introduced as a bug you then have to find.

Because the clip name equals the id on every row, a row is fully determined by two strings — the id and the dictionary. Take those from the animation list, then emit whatever shape your menu wants:

lua
local rows = {
    { id = 'salute',        dict = 'rm@salute' },
    { id = 'yawn',          dict = 'rm@communication_gestures' },
    { id = 'laughing',      dict = 'rm@reactions_expressions' },
    -- ... 91 more
}

for _, r in ipairs(rows) do
    print(("    { label = '%s', dict = '%s', clip = '%s', duration = -1 },")
        :format(r.id, r.dict, r.id))
end

Change the format string to emit your resource's field names, a SQL INSERT, or a JSON array. Add a second line using r.dict .. '@f' if you want the female rows generated in the same pass.

Three things need handling before you run a generated list past a player.

The two duplicate ids ​

pointing and pointing_gesture each appear twice — once in rm@communication_gestures, once in a standalone dictionary of their own. A generator keyed on id writes one of each pair and silently loses the other, or produces two menu rows with the same name that players cannot tell apart.

Key on the dictionary and the clip together, or rename one side. Full detail, including the lengths that differ, is in Duplicate ids.

The two very long ids ​

Two ids were generated from source filenames and run past sixty characters. They work, but they are awkward in a command and ugly in a menu row. Rename the id and the label in your own menu — yoga_tree_pose and reading_map read far better — and leave the clip string alone, because an RDR2 dictionary stores its own name inside the .ycd file. The pair is listed in Two very long ids.

Copying out of clips.lua gives you 15 rows, not 94 ​

This is the trap worth knowing about before you point a script at the file.

clips.lua contains five Config.Clips blocks. One is live — the 15 Greetings & Social rows — and four are commented out. A script that loads the file and reads the table gets 15 entries and no indication that anything else exists.

Nothing is missing from your download

All 38 .ycd files ship, and every one of the 94 clip names resolves inside them. An emote menu given a dictionary and a clip name plays any of the 94 today. The commented blocks are a state of one text file, not a gap in the assets.

Two consequences, depending on how you work:

  • In a text editor, all 94 rows are in the file. clips.lua is listed in escrow_ignore, so it ships readable; stripping the leading comment markers from the four blocks gives you every row as data, which a find-and-replace can reshape into your menu's format.
  • In a script, uncommenting the blocks is not enough. Config.Clips assigns rather than appends, so five live blocks leave only the last one and silently discard the other four. Merge all 94 into a single table, and resolve the duplicate ids while you are in there. More on the file in The clips.lua file.

The animation list on this site is generated from all 94 rows, which makes it the easier source of the two.

Which animations suit which use ​

The pack covers a wide spread of lengths and behaviours, and the groups are not interchangeable. Deciding where each kind belongs is most of the design work.

UseReach forWhy
A long scene — sitting in a saloon, waiting on a porch, an NPC on a shop floorThe five 89-second idles, and batter_on_deck at 37.333 sLong enough that nothing visibly repeats while a conversation happens
A social moment — a greeting, a laugh, a shrug, an insultThe 48 one-shot rows in Communication Gestures and Reactions & ExpressionsThey have a beginning and an end, so they read as a single action and release
A screenshotThe five single-frame poses, plus the standing and leaning idlesA held position, framed on purpose
Anything with space around itThe four root-motion clipsThey move the character, so they need room

The five 89-second idles — idle_clip, idle_2_clip, idle_3_clip, idle_6_clip and idle_8_clip — are the longest things in the pack by a wide margin. Set them to loop and they hold a scene indefinitely without the loop point being obvious.

The one-shot gestures are the 32 Communication Gestures and the 16 Reactions & Expressions, all 48 of them mode = 'once' in the list. Setting aside male_sitting_pose, which is a single-frame pose sitting in that group, the shortest is clapping at 1.167 s and the longest one-shot in the pack is terrified at 20.000 s. These are the rows to put behind a quick-access wheel or a chat command, because a player triggers one and gets on with the scene.

The five single-frame poses carry duration = 0.033 — one frame at 30 fps. They are poses, not animations: they need loop or hold-last-frame behaviour to be usable, and played once they flash and vanish. Which five, and which way each one ships, is in Single-frame poses.

The four root-motion clips move the character across the ground rather than animating in place. Play them full body, and keep them off a porch edge, a rooftop or a crowded saloon floor, where a character drifting off its mark is the difference between a nice moment and a player wedged in a wall. The four are named in Root-motion clips.

Nine rows start seated or kneeling

Nine animations carry a blendIn of 2.0 in the list — roughly half a second, slower than the default — because they begin on the ground. If your menu exposes a blend-in setting, use that figure on those nine and leave the rest at the default. If it does not, they still play; they arrive hard, which is a cosmetic problem rather than a broken row. The nine are listed in Special cases.

Start the pack before your emote menu ​

The dictionaries have to exist on the client before a player opens the menu and picks something:

cfg
ensure rm_everyday_v1
ensure your_emote_menu

Streaming does not strictly depend on start order — CFX collects stream/ whenever the resource starts — so position in server.cfg is not critical. Putting the pack first is a habit worth keeping anyway, because it rules the question out when you are debugging something else.

The ensure line follows the folder, not the manifest

In CFX the resource name is the directory name on disk. The name field in fxmanifest.lua is metadata and renames nothing, so whatever the folder is called is what ensure has to say. If you rename the folder, change the ensure line to match in the same sitting.

The dictionary names are baked into the .ycd files either way, so your menu rows never change when the folder does. Download and entitlement are on Installation.

Check one animation before you add all 94 ​

  1. Confirm the pack streamed. In the F8 client console:

    lua
    DoesAnimDictExist('rm@salute')

    true means the dictionaries reached the client. false means the resource is not started, the ensure line does not match the folder name, or the asset-pack entitlement check failed — see Troubleshooting.

  2. Add one row to your emote menu: salute out of rm@salute, flag 1, duration -1.

  3. Restart the emote resource, not only the pack. Most emote menus read their config once at start and will not see your edit until they do.

  4. Play it, then play it on a female character with rm@salute@f, so you have seen both bodies work before you paste in the other 93.

  5. Try one row from a shared dictionary — yawn out of rm@communication_gestures — so you have proved the four big dictionaries work as well as the single-animation ones.

  6. Try one single-frame pose and one root-motion clip, which are the two kinds most likely to need a setting your menu may or may not expose.

  7. Add the rest, generated rather than typed.

That first check is worth the ten seconds

A clip from a dictionary that never loaded produces no error in the server console and nothing in F8. The character stands there, which is also what a wrong clip name looks like, and what a menu row with a typo looks like. Confirming the dictionary exists separates "the pack is not reaching the client" from "my row is wrong", and those two have nothing in common except the symptom.

The pack has no menu of its own ​

Worth saying plainly at the end, because it decides what your players actually experience.

This resource makes 94 animations available on the client and stops there. Everything a player sees or does — the menu, the labels, the grouping, the stop control, the key binding, who is allowed to use which animation, whether a gesture loops — belongs to whatever you wire it into. Rename good_by to "Farewell" in your menu and that is the name of the animation on your server. Hide the root-motion clips behind a photo mode and nobody will ever trip over them.

The pack's job is to put the clip on the client. The rest is yours, and the list is the only thing you have to be faithful to.

Next ​

Still stuck? Ask in Discord.

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