24+ Dances
27 dance animations for RedM, streamed as native RDR2 .ycd dictionaries: 24 main dances plus 3 bonus ones, each with a male version and a female version, listed in a readable clips.lua.
It is an asset pack. It streams the animations and tells you what they are called. It does not play them for you — there is no menu, no chat command, no keybind and no export. The dances reach your players through an emote menu you already run, or through your own script.
No framework No database 27 dances Male and female All looping Asset pack — no menuThe 60-second version
Unzip into
resources, keeping the folder namerm_dance_24:textresources/[animations]/rm_dance_24Add one line to
server.cfg:cfgensure rm_dance_24Position does not matter. Before your emote menu is a good habit.
Restart, or from the server console:
textrefresh ensure rm_dance_24Check the server console.
server.luaprints one line, and that line is the whole of its server-side behaviour:text[redmorrow_dance_24] Dance animation pack started.
No framework, no database, no SQL, no build step. One ensure line and nothing else.
The console line says redmorrow_dance_24, the ensure line says rm_dance_24
Both are correct. redmorrow_dance_24 is the name field in fxmanifest.lua, which is metadata the print statement quotes. rm_dance_24 is the folder on disk, which is what CFX actually calls the resource. The ensure line must match the folder.
Nothing happens in game yet, and that is correct
That console line is the only confirmation the pack gives you. There is no key to press and no command to type. Until an emote menu or your own code calls TaskPlayAnim, the 8 dictionaries sit on the client unused.
Go to Emote menus or Playing a dance next.
Your server key needs asset packs enabled
The manifest declares dependency '/assetpacks', a Cfx.re licence-key entitlement check. Without it the resource refuses to start, and nothing in the resource can work around it. See Installation.
This is an asset pack, not an emote menu
This is the thing most worth knowing before you install it. The resource is a manifest, a data file, a one-line server script and eight animation files:
fxmanifest.lua | cerulean, rdr3, lua54 'yes'. Loads clips.lua as a client script and server.lua as a server script. Declares dependency '/assetpacks' |
clips.lua | A data table and nothing else. Sets the global Config.Clips — 27 rows, all 27 live |
server.lua | One line. A print that confirms the resource started |
stream/ | 8 .ycd dictionaries, 4.0 MB total |
README.md, CHANGELOG.md, LICENSE.md, docs/*.md | Readable, and accurate for this build |
There is no client.lua, no config.lua and no html/ folder. So:
| Not in this pack | Consequence |
|---|---|
No client.lua | Nothing requests a dictionary or calls TaskPlayAnim. No dance can play on its own |
| No menu, no NUI | Players have nothing to open |
No RegisterCommand | There is no chat command |
| No key binding | There is no key to press |
| No exports | exports['rm_dance_24'] has no methods on it |
| No events | Nothing to trigger from the server or from another client script |
No config.lua | There are no settings to change. Everything tunable lives in clips.lua |
The sibling 30+ Female Poses pack does ship a menu, a command and five exports, and can be handed to players as-is. This one cannot. Owning both is not the same experience, so if you were expecting the same shape, that is the difference. The other sibling, 100+ Female Poses, is assets-only like this one.
There are two routes to actually using it:
| Route | Page |
|---|---|
| Feed the 27 dictionary and clip pairs into an emote menu you already run | Emote menus |
| Write a few lines of Lua that play a clip by dictionary and clip name | Playing a dance |
The minimum that puts a dance on screen, in a client script of your own:
local dict, clip = 'redmorrow_dance_24@dance', 'samba_dancing'
CreateThread(function()
RequestAnimDict(dict)
local timeout = GetGameTimer() + 5000
while not HasAnimDictLoaded(dict) do
if GetGameTimer() > timeout then
print('dictionary did not load — is rm_dance_24 started?')
return
end
Wait(0)
end
TaskPlayAnim(PlayerPedId(), dict, clip, 4.0, -4.0, -1, 1, 0.0, false, 0, false, 0, false)
end)Stop it with StopAnimTask(ped, dict, clip, 2.0) — the blend-out speed has to be greater than 0 — or ClearPedTasks(ped, true, false). Release the dictionary with RemoveAnimDict(dict) when you are finished with it, for example in onResourceStop.
RDR3's TaskPlayAnim takes thirteen arguments
Its flag values are different numbers meaning different things from GTA V's, so a flag word copied from a FiveM script will not do what it says there. 1 is LOOPING here. Duration -1 means no time limit, so with the loop flag the dance runs until something stops it.
A clip requested from a dictionary that never loaded fails silently — the character stands there doing nothing, with no error anywhere. Always wait on HasAnimDictLoaded with a timeout, as above. Full argument list and flag table on Playing a dance.
Config.Clips is not readable from another resource
CFX gives every resource its own Lua state, so a global set inside rm_dance_24 does not exist in yours. Two ways round it: copy the rows into your own resource, or read the file off disk and evaluate it in a sandbox.
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 {}
endThat works because clips.lua is in escrow_ignore and therefore still plain text on disk. LoadResourceFile takes the folder name, so it is rm_dance_24 here too. More on this in The clips.lua table.
What is actually in it
| Dances | 27 — 24 main, 3 bonus |
Rows in clips.lua | 27, all live. Nothing is commented out |
| Stream files | 8 .ycd, 4.0 MB total |
| Format | Native RDR2 .ycd (RSC8 v58) |
| Bodies | A male and a female version of every dance |
| Mode | Every row is loop |
| Root motion | None. No dance moves the character |
| Total runtime | 299.3 s across all 27 |
| Server scripts | One print |
Every dictionary a row names is present in stream/, and every file in stream/ belongs to a live row — nothing missing, nothing orphaned. The full table, with the clip name and length of all 27, is on the dance list.
The count on the label is honest
"24+" means 24 main dances plus 3 bonus ones, and all 27 play. This pack is not one short of its name: clips.lua has no commented-out rows and no dead entries.
Requirements
| Required | ||
|---|---|---|
| RedM server | Yes | A current build. Old builds cannot load escrow-protected resources |
| Asset packs | Yes | The manifest declares dependency '/assetpacks' |
| An emote menu, or your own code | Yes | The pack cannot play a dance by itself |
| Framework | No | VORP, RSG, RedEM:RP or none — it looks for nothing |
| Database | No | No SQL, no server-side state |
| OneSync | No | Nothing is synchronised by the pack |
Every dance loops, holds its position, and ships in both bodies
All 27 rows agree on two things, which keeps the integration simple:
mode = 'loop'. There is not one once or hold row. Play them with duration -1 and flag 1, and clear the task to stop. mode maps to flags as 'loop' = 1, 'hold' = 2, 'once' = 0.
rootMotion = false. No dance walks, turns or slides the character. Where you start the clip is where the character stays.
Each row carries id, label, dict, clip, category, duration, mode, rootMotion and bodies. The comment header at the top of clips.lua also documents optional walk, flags and blendIn keys; no row in this build uses any of them. label, category and mode are yours to rename — dict and clip are not, because they have to match the names stored inside the .ycd files.
Both bodies, every dance
The female dictionary is always the male name plus @f, with identical clip names inside. That holds for all 27 rows without exception: bodies.male equals dict, and bodies.female equals dict with @f appended.
| Body | Main dictionary |
|---|---|
| Male | redmorrow_dance_24@dance |
| Female | redmorrow_dance_24@dance@f |
The 3 bonus dances each have their own pair instead — dnac@chicken_dance, dnac@jazz_dancing and dnac@dancing_twerk, plus the @f form of each. They are listed on the dance list.
Both versions play on either body; the matching one fits better. Picking between them in code has one trap worth knowing up front:
-- true when the ped uses the female body.
-- GET_META_PED_TYPE: 0 = male, 1 = female. Compare the NUMBER — 0 is truthy in Lua.
-- Falls back to IS_PED_MALE, which RedM may return as 0/1 rather than a boolean.
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))
endIf your emote menu cannot pick a dictionary per body, add the dance twice (for example "Samba (M)" and "Samba (F)"), or use the male version for everyone. See Emote menus.
One naming collision to design around
Twenty-six of the 27 rows have id equal to clip. One does not, and it causes the only real integration hazard in the pack:
| ID | Dictionary | Clip |
|---|---|---|
jazz_dancing_2 | dnac@jazz_dancing | jazz_dancing |
jazz_dancing | redmorrow_dance_24@dance | jazz_dancing |
The clip name jazz_dancing belongs to two different dances
They are two separate animations in two separate dictionaries. A menu that keys its rows on the clip name alone collides on these two and will show one dance twice. Key on id, or on dictionary and clip together.
This is the only row whose id differs from its clip, and the only clip name used twice. Details on the dance list.
The categories are lopsided
clips.lua groups rows with a category field, and the grouping is not useful as shipped:
| Category | Rows |
|---|---|
dance | 24 |
Chicken Dance | 1 |
Jazz Dancing | 1 |
Dancing Twerk | 1 |
A menu built straight from category gets one group of 24 and three groups of one, with lowercase on the big group and title case on the three singletons. Rewriting the field is explicitly allowed and is the most worthwhile edit in the file — see The clips.lua table and the category breakdown.
Durations
The duration field spans 0.5 s to 27.867 s, with a median of 8.833 s and 299.3 s of animation in total.
| Shortest | breakdance_1990_2 at 0.5 s |
| Longest | samba_dancing_1 at 27.867 s |
| Median | 8.833 s |
breakdance_1990_2 is half a second long
It is the only row under a second — the next shortest is 2.033 s. Looped, half a second reads as a fast repeating twitch rather than a dance you would leave running. Worth looking at on screen before you put it in a player-facing menu.
duration is metadata, and nothing reads it
It is a number written into clips.lua by hand. No code in the pack consults it, and it is not read out of the .ycd. If a dance looks like it runs longer or shorter than the table says, trust the game — GET_ANIM_DURATION gives the real figure. Full list on the dance list.
The folder name is the resource name
In CFX the resource name is the directory name on disk. The name 'redmorrow_dance_24' line in fxmanifest.lua is metadata and renames nothing — it is only why the startup print says [redmorrow_dance_24].
The folder is rm_dance_24, so the line is ensure rm_dance_24. Strip any version suffix like rm_dance_24-1.0.0 before adding it, and remove the extra folder level that unzipping sometimes leaves behind: resources/rm_dance_24/fxmanifest.lua has to exist.
Never rename a .ycd file
An RDR2 dictionary stores its own name inside the file. Renaming the file does not rename the dictionary — it only makes the two disagree, and that dictionary becomes unreachable.
Escrow, and what you can edit
The resource is protected with Cfx.re Asset Escrow. It starts only on a server whose sv_licenseKey belongs to the Cfx.re account that bought it; a key from another account cannot start it. Download it from portal.cfx.re under Assets then Granted Assets, and if you upload over FTP, use binary mode — ASCII mode corrupts the protected files.
escrow_ignore covers clips.lua and all the markdown, so those ship readable and stay editable after escrow.
| Editable | Leave alone |
|---|---|
clips.lua — label, category, mode, and adding walk or flags | dict and clip, which must match the names inside the .ycd |
README.md, CHANGELOG.md, LICENSE.md, docs/*.md | server.lua, stream/*.ycd and the .fxap file |
Editing a protected file stops the resource starting
Escrow refuses to start a changed protected file, with Failed to verify protected resource in the console. If you hit that, download the folder again and re-upload in binary mode.
Editing clips.lua does not change your emote menu, either. It is a reference list: whatever you rename there also has to be renamed in your menu's own config.
Runtime cost
Nothing. The pack registers no loops and no threads, so it reads 0.00 ms on both the client and the server resource monitor. Players download about 4 MB of animation files the first time they join and the files are cached after that, and a dictionary only occupies memory once someone plays a dance from it.
Where to go next
| Page | What's in it |
|---|---|
| Installation | Requirements, folder name, the asset-pack check, verifying the dictionaries streamed |
| Playing a dance | The 13-argument TaskPlayAnim call, loading a dictionary safely, RDR3 flags, stopping cleanly |
| Dance list | All 27 with dictionary, clip and length |
| Emote menus | Getting the 27 pairs into the menu you already run, including both bodies |
| The clips.lua table | Every field, what is safe to change, reading the list from your own resource |
| Troubleshooting | Symptom to cause to fix, including the silent failures |
| FAQ | The questions that come up first |
Related reading: Animation Basics for how RedM streams .ycd dictionaries, RedM Emotes if you want a menu to put these in — its three ways to add an emote applies directly — and RedM platform notes for how RDR3 differs from FiveM.
Support
RedMorrow Discord. Bring your server console output and whether DoesAnimDictExist('redmorrow_dance_24@dance') returns true on your client.
Version 1.0.0.