Animations and scenarios
An emote is an animation played on your character: a wave, a dance, sitting on the ground. The game does not keep every animation in memory, so before you can play one you have to ask for it, wait for it to load, then play it. This lesson builds that exact sequence as a resource you can run, and shows the two ways to move a ped: a single animation clip and a built-in scenario.
Build it
Make the resource folder
Inside your server's resources folder, create this folder:
resources/qu_emotes
Create the files
Create this exact file layout. Emotes run on the player's machine, so this is a client-only resource.
resources/qu_emotes/
fxmanifest.lua
client.lua
Write fxmanifest.lua
Open fxmanifest.lua and paste this:
fx_version 'cerulean'
game 'gta5'
client_script 'client.lua'
Older tutorials add a lua54 'yes' line here. As of June 2025 that setting is deprecated and ignored: Lua 5.4 is now the only Lua runtime, so you leave it out.
Write the dance command
Open client.lua and paste this. The playAnim helper is the whole pattern in one place: request, wait, play.
-- Request a dictionary, wait until it streams in, then play the clip on the player.
local function playAnim(dict, name, duration, flags)
RequestAnimDict(dict)
while not HasAnimDictLoaded(dict) do
Wait(0)
end
local ped = PlayerPedId()
TaskPlayAnim(ped, dict, name, 8.0, 8.0, duration, flags, 0.0, false, false, false)
-- We have the data now, so let the engine free the memory when it can.
RemoveAnimDict(dict)
end
RegisterCommand('dance', function()
-- flags = 1 means the animation loops until something stops it.
playAnim('anim@amb@nightclub@dancers@crowddance_facedj@hi_intensity', 'hi_dance_facedj_09_v2_female', -1, 1)
print('[qu_emotes] dancing - run /stop to cancel')
end, false)
Add the sit scenario and a stop command
Add these to the bottom of client.lua. A scenario is a packaged behaviour the game already ships, so it needs no dict and no flags.
RegisterCommand('sit', function()
local ped = PlayerPedId()
-- Scenarios are built-in behaviours; no dict to request, no flags to pass.
TaskStartScenarioInPlace(ped, 'PROP_HUMAN_SEAT_CHAIR_MP_PLAYER', 0, true)
print('[qu_emotes] sitting - run /stop to cancel')
end, false)
RegisterCommand('stop', function()
local ped = PlayerPedId()
-- ClearPedTasks ends whatever animation or scenario is currently running.
ClearPedTasks(ped)
print('[qu_emotes] stopped')
end, false)
Start and test it
Open server.cfg and add this line:
ensure qu_emotes
Save, then run:
restart qu_emotes
Join the server, open F8, and run these one at a time, watching your character each time:
/dance
/sit
/stop
/dance makes your character dance in a loop. /sit drops them into a seated scenario. /stop clears whichever one is running and your character stands back up to idle. If the dance fires but your character never moves on the first try, that is the streaming gap the next section is built to explain.
Keep reading the full lesson
Sign in to start, then unlock every step of this lesson and the full FiveM School with a membership.
- How it works
- If something went wrong
- What you can do now
- Try it yourself
The remainder of Animations and scenarios is available to FiveM School members.