The Everyday Animations clips.lua
clips.lua is a readable Lua table of 94 entries. The manifest loads it as a client script, and nothing reads it, because the pack ships no code that would. It is reference data: the dictionary and clip name of every animation in the pack, written down in a file you can open.
That is a smaller claim than the file's size suggests, and it is the right one to start from. The value of the table is the names in it: 19 dictionaries, each shipping in a male and a female version, and the clip name for each of the 94 animations. Those are the two strings RequestAnimDict and TaskPlayAnim ask you for. Everything else in a row is a label for an interface you build.
| Entries | 94 |
| Active in the file as it ships | 15 |
| Commented out | 79 |
Config.Clips statements | 5 — four commented, one live |
| Global it sets | Config.Clips |
| Loaded as | A client script |
| Lines | 140 |
| Size | About 28 KB |
escrow_ignore in the manifest covers clips.lua, stream/*.ycd and stream/**/*.ycd, so the clip list ships as plain editable text and the animation data ships as ordinary assets. Nothing you need to read in this pack is hidden from you.
What reads it
Nothing.
The resource is fxmanifest.lua, clips.lua, server.lua, stream/ with 38 .ycd files, and its Markdown. clips.lua is the only entry under client_scripts, and server.lua is one line:
[rm] Animation pack started.There is no other client file, no menu, no command and no export, so no code in the download consults the table. Every field below is metadata waiting for code you write — see Playing an animation for the native call that uses dict and clip.
Because clips.lua is listed under client_scripts only, the table exists on the client and not on the server. server.lua never sees it.
The header comment describes a build with playback code
The comment block at the top of clips.lua was written against a version of this pack that plays clips for you. This download has no client code at all, so treat that block as notes on the data rather than a description of behaviour. Its opening line also counts "32 animations", which is one block's worth and not the file's 94.
The field names in the header are accurate, because they match the rows. The rest of it is not about the resource you have.
One entry
Every row is a single-line table, flat, with the same keys in the same order:
{ id = 'salute', label = 'Salute', dict = 'rm@salute', clip = 'salute',
category = 'Salute', duration = 2.833, mode = 'loop', rootMotion = false,
bodies = { male = 'rm@salute', female = 'rm@salute@f' } },Config.Clips is a plain array, so ipairs walks it in file order and #Config.Clips counts the rows of whichever block is live. The order is the order the blocks were generated in, not alphabetical. Look rows up by id rather than by position — with the caveat about two ids further down.
Fields
| Field | Type | Means | Safe to change? |
|---|---|---|---|
id | string | The key you look a row up by | Yes, if it stays unique and you update your own references |
label | string | A display name for a menu or a list | Yes |
dict | string | The animation dictionary — the .ycd filename without the extension. The value you pass to RequestAnimDict | No |
clip | string | The clip name inside that dictionary. The value you pass to TaskPlayAnim | No |
category | string | A grouping key for a menu | Yes |
duration | number | Length in seconds | Advisory; nothing reads it |
mode | string | A suggestion about playback. 'once' on 48 rows, 'loop' on 46 | Yes |
rootMotion | boolean | true means the clip moves the character. true on 4 rows | Advisory |
bodies | table | { male = dict, female = dict .. '@f' } | No |
blendIn | number | Optional. 2.0 on 9 rows that start seated or kneeling | Advisory |
Only dict, clip and the two names inside bodies have any mechanical meaning, and that meaning comes from the .ycd files rather than from this table. The rest are strings and numbers the pack author wrote down for whatever interface comes later.
duration is written as the author recorded it, sometimes as an integer — duration = 5 and duration = 2.833 both appear. If a clip plays longer or shorter than the field claims, the field is wrong and the clip is right; GET_ANIM_DURATION returns the real length. The spread across all 94 rows is in the animation list.
The header block names two further optional keys, walk and flags. Neither appears on any row in the file. They are legal to add if you write code that reads them.
bodies holds on all 94 rows
bodies.male == dict
bodies.female == dict .. '@f'No exceptions, and the clip name inside the male and the female dictionary is identical. Choosing a body is therefore a dictionary swap and not a lookup: request dict or dict .. '@f' and pass the same clip either way. All 38 files are on disk — 19 dictionaries times two bodies, none missing and none spare. The per-dictionary breakdown is in the animation list.
Keep both names as they are. They are the asset's names, not yours.
dict and clip fail silently when they are wrong
An RDR2 dictionary stores its own name inside the .ycd file. dict is not a filename you are free to rename, it is a lookup key that has to agree with the asset. Renaming [email protected] does not rename the dictionary inside it, so the clip stops resolving.
| Mistake | What happens |
|---|---|
Wrong dict | The dictionary never loads. No animation, no console error |
Wrong clip | The dictionary loads and the clip is not found. No animation, no console error |
Neither raises anything you can see. This is why a timeout on the HasAnimDictLoaded wait matters — it is the only way to turn a silent failure into a line you can read. Troubleshooting walks through telling that apart from an asset-pack entitlement problem.
Do not build dict from id
'rm@' .. id happens to be correct for the 15 greetings, because each of them has its own dictionary. It is wrong for the other 79, which sit in four shared dictionaries — charge lives in rm@communication_gestures, not in rm@charge. Copy the dict and clip pair out of the table or out of the animation list. Do not generate it.
The file ships partly commented out
clips.lua contains five Config.Clips = { statements. Four of them are commented out and one is live:
| Block | Rows | State in the file |
|---|---|---|
| Communication Gestures | 32 | Commented out |
| Reactions & Expressions | 16 | Commented out |
| Standing & Idle | 18 | Commented out |
| Casual Actions | 13 | Commented out |
| Greetings & Social | 15 | Live |
Three things follow, and they pull in different directions.
All 94 animations are present and usable regardless. The 38 .ycd files are in stream/ and every one of the 94 clip names resolves inside them. The commented rows are commented text in a file nothing reads; they describe no asset that is absent. An emote menu handed rm@casual_actions and reading_book plays that animation today, with the file exactly as it shipped. Nothing is missing from your download.
Anyone copying rows out of the file will only see 15. That is the one place the file's state costs you something real. The animation list carries all 94 rows with their dictionary, clip name, length and mode, uncommented and in tables you can read at a glance. Copy from there.
Uncommenting the four blocks does not give you 94. Config.Clips assigns, it does not append.
Config.Clips = { { id = 'a' } } -- the table now holds one row
Config.Clips = { { id = 'b' } } -- the first table is discarded; still one row, not twoEach statement builds a fresh table and throws the previous one away, with no warning and no error. The live block is the last statement in the file, so uncommenting the four above it changes nothing at all: all four tables are built in turn, each replaces the one before, and then the greetings block replaces the lot. You would end up with the same 15 rows you started with, having edited 79 lines.
Merging them properly
The blocks have to become one table. Delete the four intermediate -- } and -- Config.Clips = { boundaries along with the row comments, so the whole file is a single assignment:
Config = Config or {}
Config.Clips = {
-- Communication Gestures
{ id = 'acknowledging', label = 'Acknowledging', dict = 'rm@communication_gestures', clip = 'acknowledging', category = 'Communication Gestures', duration = 1.933, mode = 'once', rootMotion = false, bodies = { male = 'rm@communication_gestures', female = 'rm@communication_gestures@f' } },
-- ...the other 31, then Reactions & Expressions, Standing & Idle, Casual Actions...
-- Greetings & Social
{ id = 'salute', label = 'Salute', dict = 'rm@salute', clip = 'salute', category = 'Salute', duration = 2.833, mode = 'loop', rootMotion = false, bodies = { male = 'rm@salute', female = 'rm@salute@f' } },
}If you would rather keep the blocks visually separate, append instead of assigning:
Config = Config or {}
Config.Clips = Config.Clips or {}
local function add(rows)
for _, row in ipairs(rows) do
Config.Clips[#Config.Clips + 1] = row
end
end
add {
-- Communication Gestures rows
}
add {
-- Reactions & Expressions rows
}Resolve the two duplicate ids in the same edit
pointing and pointing_gesture each appear once in the Communication Gestures block and once in the live Greetings block, pointing at different dictionaries. While the gesture block is commented out there is no collision. Merge the blocks and the table holds two rows for each of those ids.
Lua will not complain, because the table is an array rather than a set of keys, but a menu keyed on id finds one row and silently loses the other. Rename the standalone pair — pointing_alt and pointing_gesture_alt read well enough — or key your menu on dict and clip together. Both pairs are set out in the animation list.
The leading dashes are not in a consistent column
The commented rows were not switched off uniformly. Most read -- {, several have the dashes pulled left out of the indent or carry extra spaces after them. Search for the id rather than for a fixed prefix, and remove only the two dashes; the leading whitespace does not matter to Lua.
Worth saying plainly: merging the file is only useful if you intend to read Config.Clips from a script you add inside this resource. If your animations are driven from an emote menu or your own resource, copying the pairs you want out of the animation list is less work and survives a re-download of the pack. See Integrating with other resources.
What you may change
label, category, mode, duration and id are yours. These are the edits that pay for themselves.
The 15 greetings ship as loop
Every row in the Greetings block carries mode = 'loop', and all 15 are one-shot social gestures. A 0.533-second waving on a loop reads as a twitch rather than a wave, and quick_formal_bow repeating is a character bobbing at someone. once is the honest value for all 15:
{ id = 'waving', label = 'Waving', dict = 'rm@waving', clip = 'waving',
category = 'Greetings', duration = 0.533, mode = 'once', rootMotion = false,
bodies = { male = 'rm@waving', female = 'rm@waving@f' } },Unchanged, the split across all 94 rows is 48 once and 46 loop.
The five single-frame poses want hold
Five rows have duration = 0.033, one frame at 30 fps. They are poses rather than animations and they need their last frame held to be worth anything:
| Row | Ships as |
|---|---|
male_sitting_pose | once |
female_standing_pose | loop |
hand_in_back | loop |
cross_legged_sitting | loop |
leaning_against_wall | loop |
'hold' is the third value the header's vocabulary allows and no row in the file uses it. These five are where it belongs. mode is advisory either way — a string your own code reads and acts on — so write the value that describes the clip and let your playback decide what to do with it. The list is also in the animation list.
15 of the 19 categories hold one row
category has 19 distinct values across the table, and 15 of them are single-item: each greeting was given a category named after itself, so salute sits in a category called Salute. A menu built straight off the field gets four large groups and fifteen groups of one.
Give the greetings a shared category and the menu gets usable:
category = 'Greetings',The five-group split the documentation uses — Greetings & Social, Communication Gestures, Reactions & Expressions, Standing & Idle, Casual Actions — is a sensible target, and it is a category edit and nothing more.
Two ids are 63 characters long
a_man_stands_on_the_left_leg_in_a_yoga_tree_pose_with_the_hands
a_woman_stands_holding_a_map_open_in_both_hands_and_looks_arounBoth were generated from source filenames, both work, and both are unpleasant to type and worse in a menu. yoga_tree_pose and reading_map carry the same meaning in a fifth of the characters. Alias them:
{ id = 'yoga_tree_pose', label = 'Yoga Tree Pose', dict = 'rm@standing_idle',
clip = 'a_man_stands_on_the_left_leg_in_a_yoga_tree_pose_with_the_hands',
category = 'Standing & Idle', duration = 5, mode = 'loop', rootMotion = true,
bodies = { male = 'rm@standing_idle', female = 'rm@standing_idle@f' } },The id and the label change. The clip does not, and cannot — that string is the name inside the .ycd. Both rows are also root-motion clips, which is the other thing to know about them; see the animation list.
Several labels are raw filenames in the same way — good by, idle_clip, idle_2_clip, hand in back — and are worth a pass if players will ever read them.
After an edit
clips.lua is a client script read at load, so a restart is needed and a refresh on its own is not enough. The resource name in CFX is the folder name, so the restart line follows the folder on disk:
restart rm_everyday_v1The manifest's name 'rm' is metadata and does not rename anything. If you renamed the folder, use the name you gave it — the rule is that the line matches the folder, in server.cfg and in the console alike. Installation covers it.
A syntax error takes the whole resource down
clips.lua is the only client script, and a missing comma or an unclosed brace stops the resource from starting at all. The asset-pack entitlement check declared by dependency '/assetpacks' runs in the same window, so a licence-key problem and a Lua problem can look alike in the console. Troubleshooting separates them.
Your emote menu keeps its own list either way
Whatever you do to this file, it is not the list your players browse.
Config is a Lua global, and CFX gives every resource its own isolated Lua state. A global set inside this pack exists only inside this pack. Your own resource can start it, depend on it and stream its dictionaries, and still see Config.Clips as nil:
-- in your own resource: this is always nil
print(Config and Config.Clips)There is no export to ask through, because the pack registers none. So an emote menu, a photo-mode script or a job resource holds its own copy of the pairs it needs — in its own config file or its own database table — and that copy is what it plays from. Merging the blocks in clips.lua, renaming an id or fixing a category changes this file and leaves your menu exactly as it was. The same edit has to be made on the menu's side.
RedM Emotes shows the three routes for getting a dictionary and clip name into a menu's own list.
See also
| Page | |
|---|---|
| Animation list | All 94 rows, with dictionary, clip name, length and mode |
| Playing an animation | The native call, start to stop |
| Integrating with other resources | Emote menus, your own scripts |
| Installation | The ensure line and the asset-pack requirement |
| Troubleshooting | Symptom, cause, fix |
| FAQ | Short answers about the pack |
| Animation Basics | How RedM animations work in general |
| 100+ Female Poses | The sibling asset pack, same shape, female only |