Skip to Content
ScriptingScaleform
Report an error
Open in ChatGPTOpen in Claude

Use an existing or custom Scaleform movie

Scaleform is GTA V’s Flash-derived native interface system. FiveM can use existing movies and custom .gfx assets. It is not restricted to a fixed list of built-in messages, and rendering it is not free: load only what the feature needs, draw it while visible and release the handle.

For browser-based layouts and ordinary web tooling, compare NUI. For a game movie or a specific native HUD integration, use the contracts below. The reference is the pinned Cfx.re Scaleform guide .

Authoring custom GFx

The documented authoring pipeline uses ActionScript 2, targeting Flash Player 8, with Adobe Flash Pro CS6. ActionScript 3 uses a different VM and is not supported by this GTA Scaleform implementation. Convert the authored .swf to .gfx with a legitimately available gfxexport.exe from the Scaleform GFx SDK; the official guide names SDK 4.0 as suitable. This project does not distribute those proprietary tools or imply that they are freely downloadable.

The game expects a global TIMELINE object. Public functions called by game natives must be members of that object. A file that opens in a Flash player but exposes no matching TIMELINE method is not a working native interface.

Use the official Scaleform boilerplate download  as an upstream reference, not as a fixture claimed to have been built here. Put your owned exported movie in the resource’s streaming files and request it by its movie name without .gfx. Keep authoring files outside the client download pack unless intentionally distributing them.

Feature limits

The documented implementation does not support shape filters, ordinary Flash masking or embedded raster graphics. Text blur is also unsupported; a glow-based approximation is not the same effect. Texture loading and masking use the game-specific mechanisms described below. Do not assume a SWF feature survives conversion because it works in the editor.

Loading, calling and drawing

RequestScaleformMovie(name) gives a handle. Wait for HasScaleformMovieLoaded(handle) with a timeout and a yield. Then begin a method, push arguments with the correct types and end it. Movie-specific method names are not universal: inspect the target movie’s public interface.

StepNative family
Start methodBeginScaleformMovieMethod(handle, methodName)
Numeric/boolean argumentsScaleformMovieMethodAddParamInt, ScaleformMovieMethodAddParamFloat, ScaleformMovieMethodAddParamBool
Short identifiers, such as texture namesThe string-parameter native, also documented under _PUSH_SCALEFORM_MOVIE_METHOD_PARAMETER_STRING.
Normal display textBeginTextCommandScaleformString, AddTextComponentSubstringPlayerName, EndTextCommandScaleformString.
Complete a no-return methodEndScaleformMovieMethod()
Draw at a 2D positionDrawScaleformMovie(...)
Draw across the screenDrawScaleformMovieFullscreen(...)
Draw in world spaceDrawScaleformMovie_3d(...); inspect the native signature and target track.
Release ownershipSetScaleformMovieAsNoLongerNeeded(handle)

The official manual warns about a color shift when a 3D movie is drawn under blackout. The native reference  remains the parameter authority. C# also has a higher-level Scaleform wrapper .

A client example with interruption-safe cleanup

Create a resource with client_script 'client.lua' in its manifest. The docscaleform command displays a known built-in movie for three seconds. A second invocation replaces the first rather than leaking another draw loop.

-- client.lua local generation = 0 local activeHandle = nil local function release(handle) if handle ~= nil then SetScaleformMovieAsNoLongerNeeded(handle) end end local function cancel() generation = generation + 1 release(activeHandle) activeHandle = nil end RegisterCommand('docscaleform', function() cancel() local request = generation local handle = RequestScaleformMovie('mp_big_message_freemode') activeHandle = handle CreateThread(function() local started = GetGameTimer() while request == generation and not HasScaleformMovieLoaded(handle) do if GetGameTimer() - started >= 5000 then if activeHandle == handle then release(activeHandle) activeHandle = nil end print('Scaleform load timed out.') return end Wait(0) end -- Cancellation already released this request's handle. if request ~= generation then return end if BeginScaleformMovieMethod(handle, 'SHOW_SHARD_WASTED_MP_MESSAGE') then BeginTextCommandScaleformString('STRING') AddTextComponentSubstringPlayerName('Preview') EndTextCommandScaleformString() BeginTextCommandScaleformString('STRING') AddTextComponentSubstringPlayerName('This message closes automatically.') EndTextCommandScaleformString() ScaleformMovieMethodAddParamInt(5) EndScaleformMovieMethod() end local shown = GetGameTimer() while request == generation and GetGameTimer() - shown < 3000 do DrawScaleformMovieFullscreen(handle, 255, 255, 255, 255, 0) Wait(0) end if request == generation and activeHandle == handle then release(activeHandle) activeHandle = nil end end) end, false) RegisterCommand('docscaleformstop', cancel, false) AddEventHandler('onResourceStop', function(name) if name == GetCurrentResourceName() then cancel() end end)

This example is source-reviewed teaching code, not a claim of executed game rendering. Test successful display, timeout, rapid repeated commands and a resource stop during loading and drawing. In Lua, use nil to represent no owned handle; do not accidentally release a newer request from an old coroutine. For return-valued methods, use the appropriate return-value native path rather than treating EndScaleformMovieMethod() as the returned application value.

Textures and masks

Game textures use img://textureDictionary/textureName, for example img://mpcarhud/albany. A normal HTTP image URL or an embedded bitmap in the authoring file is not interchangeable with that mechanism. Load the intended dictionary and use exact texture names.

DrawScaleformMovieFullscreenMasked(movie, maskMovie, ...) takes a second movie as its mask. The documented mask is hard-edged: a nontransparent mask pixel reveals the underlying pixel, without smooth alpha masking or antialiasing. Do not design an interface that depends on Flash-style feathered masks and assume this native implements them.

Some movies accept limited markup such as <b>, <br>, <FONT FACE='$Font2'>, <FONT SIZE='24'> and <img src='img://dictionary/texture'>. Support belongs to the individual movie/text field. Treat untrusted player text as text, not as a source of arbitrary markup.

The upstream font list is: $Font2, $Font2_cond, $Font2_cond_NOT_GAMERNAME, $Font5, $Machine, $Stencil, $Lubalin, $Bookman, $Stenberg, $Mistral, $HelveticaBLK, $HelveticaBLKI, $Times, $TradeGothic, $AnnaSC, $EngraversOldEnglish, $Bauhaus, and $Redemption. Not every movie supports every font.

Diagnose the failing layer

FailureCheck
Movie never loadsExact exported movie name, streaming resource, game track, timeout logs and collisions with another asset name.
Movie loads but method does nothingGlobal TIMELINE member, spelling, argument types and argument order.
Text is truncated or malformedUse the text-command path for display text, not the short-identifier string helper.
Texture absentDictionary/texture spelling and img:// URL; do not substitute a web image URL.
Flickering or duplicate outputMultiple resources/threads drawing the same UI, stale command requests or missing cleanup.
Works until a resource restartLeaked handles, old callbacks, dependency startup order or stale streamed exports.

Continue with Lua scheduling, resource cleanup, instructional buttons, and NUI alternatives.