Skip to content

ParticleFxPlayer ​

Plays particle effects (PTFX) at a world position or attached to an entity. Supports one-shot, looped, infinite, and timed playback. Effects can be rendered locally or over the network.

WARNING

Synced particle fx are restricted by missing natives. For example it is not possible to set the color or alpha of a synced particle fx. If you want that you have to create the particle on each client individually.


Example ​

Play particle fx on position for one second looped over network ​

lua
---@type NssLibsParticleFxPlayerControllerApi
local pfx_api = exports.nss_libs:getParticleFxPlayerApi(GetCurrentResourceName())

---@type NssLibsParticleFxPlayerApi
local pfx_player = pfx_api.create()

local duration_in_ms = 1000 -- One second
local interval_in_ms = 100 -- 10 times per second

-- non-looped asset
local asset_dictionary = 'scr_crackpot'
local asset_name = 'scr_crackpot_tesla_fail'

-- false if non-looped asset: https://github.com/femga/rdr3_discoveries/blob/f729ba03f75a591ce5c841642dc873345242f612/graphics/ptfx/ptfx_assets_non_looped.lua
-- true looped asset: https://github.com/femga/rdr3_discoveries/blob/f729ba03f75a591ce5c841642dc873345242f612/graphics/ptfx/ptfx_assets_looped.lua
local is_looped_asset = false

pfx_player
        .setAsset(asset_dictionary, asset_name, is_looped_asset)
        .setPosition(0.0, 0.0, 0.0)
        .useNetwork()
        .play(duration_in_ms, interval_in_ms)
lua
---@type NssLibsParticleFxPlayerControllerApi
local pfx_api = exports.nss_libs:getParticleFxPlayerApi(GetCurrentResourceName())

---@type NssLibsParticleFxPlayerApi
local pfx_player = pfx_api.create()

local duration_in_ms = 1000 -- One second

-- non-looped asset
local asset_dictionary = 'scr_crackpot'
local asset_name = 'scr_crackpot_tesla_fail'

-- false if non-looped asset: https://github.com/femga/rdr3_discoveries/blob/f729ba03f75a591ce5c841642dc873345242f612/graphics/ptfx/ptfx_assets_non_looped.lua
-- true looped asset: https://github.com/femga/rdr3_discoveries/blob/f729ba03f75a591ce5c841642dc873345242f612/graphics/ptfx/ptfx_assets_looped.lua
local is_looped_asset = false

local random_interval = { 100, 500 } -- Random value between 100 and 500 ms each wait loop

pfx_player
        .setAsset(asset_dictionary, asset_name, is_looped_asset)
        .setPosition(0.0, 0.0, 0.0)
        .useNetwork()
        .play(duration_in_ms, random_interval)

Commands / Objects ​

exports.nss_libs:getParticleFxPlayerApi(resource_name) ​

ParamTypeDefaultDescription
resource_namestring—The name of the resource that uses the ParticleFxPlayer API. Pass GetCurrentResourceName()

Returns NssLibsParticleFxPlayerControllerApi — object scoped to the calling resource


NssLibsParticleFxPlayerControllerApi ​

.create() ​

Creates and registers a new particle fx player instance. The instance is tracked by the controller and can be cleaned up via destroy().

Returns NssLibsParticleFxPlayerApi — the player instance


NssLibsParticleFxPlayerApi ​

Builder-pattern API. All setter methods return self to allow method chaining. Call play() to start the effect.

.setAsset(pfx_dictionary, pfx_name, is_looped_asset?) ​

Sets the PTFX asset to use.

ParamTypeDefaultDescription
pfx_dictionarystring—The particle fx dictionary name
pfx_namestring—The particle fx name within the dictionary
is_looped_assetboolean?falsetrue for looped assets, false for non-looped assets

Returns self — chainable


.setPosition(x, y, z) ​

Sets the world position where the effect will be played. Each axis supports an exact value or a random range table {min, max}.

ParamTypeDefaultDescription
xnumber|table—World X coordinate, or {min, max} for a random value
ynumber|table—World Y coordinate, or {min, max} for a random value
znumber|table—World Z coordinate, or {min, max} for a random value

Returns self — chainable


.attachToEntity(entity) ​

Binds the effect to an entity. The effect follows the entity's position. Use setEntityOffset() to define an offset relative to the entity.

ParamTypeDefaultDescription
entitynumber—The entity handle to attach to

Returns self — chainable


.setEntityOffset(x, y, z) ​

Sets the positional offset relative to the attached entity. Each axis supports an exact value or a random range table {min, max}. Only used when attachToEntity() has been called.

ParamTypeDefaultDescription
xnumber|table—X offset, or {min, max} for a random value
ynumber|table—Y offset, or {min, max} for a random value
znumber|table—Z offset, or {min, max} for a random value

Returns self — chainable


.setRotation(rot_x, rot_y, rot_z) ​

Sets the rotation of the effect in degrees.

ParamTypeDefaultDescription
rot_xnumber—Rotation around the X axis
rot_ynumber—Rotation around the Y axis
rot_znumber—Rotation around the Z axis

Returns self — chainable


.setAxis(axis_x, axis_y, axis_z) ​

Sets the axis values for the effect.

ParamTypeDefaultDescription
axis_xnumber—X axis value
axis_ynumber—Y axis value
axis_znumber—Z axis value

Returns self — chainable


.setScale(scale) ​

Sets the scale of the effect. Supports an exact value or a random range table.

ParamTypeDefaultDescription
scalenumber|table—Scale multiplier, or {min, max} for a random value per play cycle

Returns self — chainable


.setInterval(interval_in_ms) ​

Sets the interval between repetitions when playing with a duration. Supports an exact value or a random range table.

ParamTypeDefaultDescription
interval_in_msnumber|table—Interval in milliseconds, or {min, max} for a random value per loop iteration

Returns self — chainable


.useNetwork() ​

Renders the effect over the network so it is visible to all players. Must be called before play().

Returns self — chainable


.useLocal() ​

Renders the effect locally only (visible to the local client). This is the default behavior.

Returns self — chainable


.play(duration_in_ms, interval_in_ms?, on_finished?, on_error?) ​

Starts playback of the effect. Loads the required assets automatically before spawning the effect.

ParamTypeDefaultDescription
duration_in_msnumber?—Total playback duration in ms. -1 for infinite, 0 or nil for one-shot
interval_in_msnumber|table?—Interval between repetitions in ms, or {min, max} for random. Only relevant when duration_in_ms > 0 or -1
on_finishedfunction?—Callback invoked when playback ends naturally
on_errorfunction?—Callback invoked if an error occurs (e.g. asset could not be loaded). Receives (error_msg)

.stop() ​

Stops the effect immediately. Does not remove the player instance from the controller.


.destroy() ​

Stops the effect, removes the PFX handle, and unregisters the player instance from the controller. Use this for full cleanup.


.isPlaying() ​

Returns boolean — true if the effect is currently active


.isInfinite() ​

Returns boolean — true if the effect was started with duration_in_ms = -1 (infinite playback)


.getHandle() ​

Returns number — the internal PFX handle ID assigned by the game engine


.getId() ​

Returns string — the unique identifier for this player instance

NIGHTSHIFT STUDIO Documentation