Adding the Dances to an Emote Menu
This is the route most servers take, and the one the pack is built for.
rm_dance_24 streams animations and does nothing else. The whole resource is fxmanifest.lua, a data table in clips.lua, a one-line server.lua that prints a startup message, and eight .ycd files in stream/. There is no menu, no command, no key binding, no events and no exports — and no config options either. Players reach the dances through the emote menu your server already runs, or through a script of your own.
The pack's own docs/ folder says the same thing, and in this pack those guides are accurate.
Nothing is missing from your download
All 27 rows in clips.lua are live, nothing is commented out, and every dictionary a row names is present in stream/. "24+" means 24 main dances plus 3 bonus ones. The count is not short — see the dance list.
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 for | What to give it |
|---|---|
| Dictionary | redmorrow_dance_24@dance for the 24 main dances, or that name plus @f for the female version |
| Clip name | The clip from the dance list |
| Flag | 1 — loop |
| Duration | Whatever the resource uses for "run until stopped", normally -1 |
| Loop setting | On. All 27 dances are loops |
| Label and category | Yours to choose. The shipped ones are rough — see below |
Do not pass the figure from the duration column to the menu as a play time. That number is metadata the pack author wrote into clips.lua; nothing in the resource reads it, and a 2.467 s dance given a 2.467 s duration ends before the player has let go of the key. Use it to sort or label your menu, and let the loop flag decide when the dance stops.
Flags
RedM has its own eScriptedAnimFlags values. They are not GTA V's, so a flag word copied out of a FiveM emote resource will not mean here what it meant there.
| Use | Flag |
|---|---|
| Loop the dance | 1 |
| Play once | 0 |
| Play once and hold the last frame | 2 |
| Loop upper body only, so the player can walk | 1 + 8 + 16 = 25 |
For dances, 1 is almost always what you want. Full value table in Playing a dance.
The 24 main dances
One dictionary pair covers all 24:
| Body | Dictionary |
|---|---|
| Male | redmorrow_dance_24@dance |
| Female | redmorrow_dance_24@dance@f |
The clip name is identical in both. Take the 24 clip names from The 24 main dances. In all 24 of these rows the id and the clip name are the same string, so either column works. The one row in the pack where they differ is a bonus dance, below.
A row in a generic emote resource therefore looks like this, with your resource's own field names:
{
label = 'Samba Dancing',
command = 'samba',
dict = 'redmorrow_dance_24@dance',
clip = 'samba_dancing',
duration = -1,
loop = true,
}The 3 bonus dances
These are the exception. Each one has its own pair of dictionaries, not the main pair:
| Dance | Male dictionary | Female dictionary | Clip | Length |
|---|---|---|---|---|
| Chicken Dance | dnac@chicken_dance | dnac@chicken_dance@f | chicken_dance | 4.767 s |
| Jazz Dancing (2) | dnac@jazz_dancing | dnac@jazz_dancing@f | jazz_dancing | 2.033 s |
| Dancing Twerk | dnac@dancing_twerk | dnac@dancing_twerk@f | dancing_twerk | 15.2 s |
Same flag, same duration handling as the other 24. The only difference is the dictionary string.
Two different dances use the clip name jazz_dancing
This is exactly the place where it bites.
- The row with id
jazz_dancing_2is the clipjazz_dancinginsidednac@jazz_dancing. - The row with id
jazz_dancingis a different dance: the clipjazz_dancinginsideredmorrow_dance_24@dance.
A menu that keys its rows on the clip name alone will collide, and one of the two dances will quietly disappear from your list or overwrite the other. Key on the id, or on the dictionary and clip name together.
This is the only row in the pack whose id differs from its clip, and the only clip name used twice. Every other row has id == clip.
Handling both bodies
Every dance ships twice: a version fitted to the male body and one fitted to the female body. The female dictionary is always the male name plus @f, with the same clip names inside. That holds for all 27 rows without exception — in every row bodies.male is the dict field and bodies.female is that string plus @f.
Both versions play on either body. Neither one breaks. The matching one fits better.
| If your menu | Then |
|---|---|
| Supports a per-body dictionary | Point female characters at the @f dictionary |
| Does not | Add each dance twice, labelled "(M)" and "(F)", or use the male version for everyone |
Adding each dance twice turns 27 rows into 54 and puts the choice on the player, which is honest but noisy. Using the male version for everyone is a legitimate choice if your menu cannot branch; it looks slightly off on female characters rather than wrong.
If your menu hands the dance to a function of yours, pick the dictionary there:
-- GET_META_PED_TYPE returns 0 for male and 1 for female.
-- Compare the number: 0 is truthy in Lua, so testing it as a boolean is wrong.
-- IsPedMale may come back as 0/1 rather than true/false on RedM, so handle both.
local function isFemale(ped)
if GetMetaPedType then
local ok, t = pcall(GetMetaPedType, ped)
if ok and t == 1 then return true end
if ok and t == 0 then return false end
end
local male = IsPedMale(ped)
return not (male == true or (type(male) == 'number' and male ~= 0))
end
local function dictFor(row, ped)
if isFemale(ped) then return row.dict .. '@f' end
return row.dict
endAppending @f is safe in this pack precisely because the pairing is mechanical in all 27 rows. That is not true of every RedMorrow pack — in 100+ Female Poses, seven dictionaries are named after a different pose than their id, so names there must be read from the table rather than built.
Groups, if your menu uses them
The category field in clips.lua is lopsided:
| Category | Rows |
|---|---|
dance | 24 |
Chicken Dance | 1 |
Jazz Dancing | 1 |
Dancing Twerk | 1 |
Grouping straight from that field gets you one group of 24 and three groups of one, with inconsistent capitalisation between them. Put all 27 in a single Dances group in your menu instead, or rewrite the field — category is one of the fields you are allowed to change. Details in Categories.
With RedM Emotes
RedM Emotes stores its library as rows, and each row carries a dictionary and a clip name. That is all these dances need, so they drop in like any other custom dictionary: one row per dance, with the dictionary and clip from the tables above, the loop setting on, 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.
Start the pack before your emote menu
The dictionaries have to exist on the client before a player opens the menu and picks a dance. Order in server.cfg is the simplest way to guarantee that:
ensure rm_dance_24
ensure your_emote_menuThe ensure line follows the folder name, not the manifest
In CFX the resource name is the directory name. The folder is rm_dance_24, so ensure rm_dance_24 is the correct line.
The name field inside fxmanifest.lua is redmorrow_dance_24, and that is metadata — it renames nothing. It is also why the startup message reads:
[redmorrow_dance_24] Dance animation pack started.Do not copy that bracketed name into your server.cfg. More in Installation.
Generating the rows instead of typing 27
Twenty-seven rows is past the point where hand-typing is a good use of an evening, and hand-typing is where the jazz_dancing collision turns into a bug. Generate them from the pack's own table.
clips.lua sets a global called Config inside rm_dance_24's own Lua state. CFX gives every resource its own state, so your emote resource cannot read Config.Clips directly and there are no exports to hand it over. There are two ways round that: copy the rows, or load the file and read it in a sandbox of your own.
clips.lua is listed in escrow_ignore, so it ships readable on disk, which is what makes the second option work:
-- Reads rm_dance_24's own clip list. Returns an empty table if the pack is
-- not installed or the file will not parse.
local function getDanceClips()
local src = LoadResourceFile('rm_dance_24', 'clips.lua')
if not src then return {} end
local env = { Config = {} }
local chunk = load(src, '@rm_dance_24/clips.lua', 't', env)
if not chunk or not pcall(chunk) then return {} end
return env.Config.Clips or {}
endThe sandboxed env is the point: the file assigns to Config, and running it inside env keeps that assignment out of your own globals while still giving you the table.
Then print the rows in whatever shape your menu's config wants, and copy them out of the console:
RegisterCommand('dancedump', function()
local clips = getDanceClips()
for _, c in ipairs(clips) do
print((" { id = '%s', label = '%s', dict = '%s', clip = '%s', duration = -1, loop = true },")
:format(c.id, c.label, c.dict, c.clip))
end
print(('-- %d rows'):format(#clips))
end, false)Change the format string to emit your resource's field names, or a SQL INSERT, or a JSON array. Add c.dict .. '@f' to the line if you want the female dictionary in the same row. The output lands in the console of whichever side you ran the command on.
#clips is 27 and the array is contiguous
Nothing in clips.lua is commented out, so there is no filtering to do and no gap to skip. If you get a number other than 27, the folder name in LoadResourceFile does not match what is on disk — it takes the folder name, rm_dance_24, not the manifest name.
Read dict off the row — do not build it from the id
'redmorrow_dance_24@dance' is right for 24 of the 27 rows and wrong for the three bonus dances, which live in dnac@... dictionaries. A clip requested from a dictionary that never loaded fails silently: no error in the server console, nothing in F8, the character just stands there. Those three would look like broken menu entries with no clue as to why.
Check one dance before you add all 27
Confirm the pack streamed. In the F8 client console:
luaDoesAnimDictExist('redmorrow_dance_24@dance')truemeans the dictionaries reached the client.falsemeans the resource is not started, theensureline does not match the folder, or the asset-pack entitlement check failed. See Troubleshooting.Add one row to your emote menu's config —
samba_dancingout ofredmorrow_dance_24@dance, flag1.Restart the emote resource, not just the pack. Most emote menus read their config once at start and will not see your edit until they do.
Play it, then play it on a female character with the
@fdictionary, so you have seen both bodies work before you paste in the other 26.Add the rest, generated rather than typed.
Editing clips.lua does not change your emote menu
The two lists are separate, and this is the single most common misunderstanding about packs shaped like this one.
clips.lua is a reference list that ships with the pack. Your emote menu has its own config, its own database table or its own file. Renaming a dance in clips.lua renames it in clips.lua and nowhere else — the names have to be copied into the menu's own config as well. Equally, nothing in rm_dance_24 reads your menu, so the pack cannot break it.
What you may and may not change in that file is covered in The clips.lua table. The short version: label, category, mode and walk are yours; dict and clip are not, because an RDR2 dictionary stores its own name inside the .ycd file.
Next
- Playing a dance — the native call, the dictionary wait, stopping cleanly
- Dance list — all 27 with dictionary, clip and length
- The clips.lua table — every field in the row
- Installation — download, upload,
ensure, entitlement - Troubleshooting — symptom, cause, fix
- FAQ — the short answers
- Animation Basics — how two resources end up fighting over one character
- 30+ Female Poses — a sibling pack that ships its own menu, so none of this page applies to it
Still stuck? Ask in Discord.