Status Behaviors let your character apply a lasting gameplay change to another Rival — a burn that ticks damage, a cooldown that blocks a special, a mark that changes what your next hit does. They are written in Lua and registered through a Blueprint asset.
When to use a Status Behavior
Before making a status behavior, consider whether it couldn’t be better implemented by logic directly on your character. The two criteria below work as a good rule of thumb for when a status makes sense:
- The behavior should be applied to a character other than the one who inflicts it — If you need a persistent effect that can only apply to your own character, handling the behavior inside your character and using a NetProp for timer/stacks/etc is probably the right move
- The behavior is persistent — One-time effects can simply be executed immediately and don’t need to go through the status effect system.
RivalsStatusEffect vs RivalsCustomStatusState
Statuses come in two varieties, both of which will inherit from RivalsStatusBehaviorBase:
- Status Effect (RivalsLuaStatusEffectBase): This represents an arbitrary status effect. A Rival can have many of them at a time, and they don’t force any specific custom behavior. Used for thins like Ranno’s poison, Zetterburn’s burn, etc.
- Custom Status State (RivalsLuaCustomStatusState): This represents a custom state tied to a status. A Rival can only be in one Custom Status State at a time, and it will override their action state (walk/run/etc). Custom Status States have custom animations and movement behavior. Used for things like Ranno’s bubble, Etalus’ Freeze, etc.
In general: if the Rival can keep acting during the state, it’s a Status Effect. If not, it’s a Custom Status State.
Creating a Status Effect
1: Create the Blueprint
In your mod’s UnrealAssets folder, create a Blueprint whose parent class is RivalsLuaStatusEffectBase. Open it and set three properties on the Class Defaults:
- Effect Name: The short name of your effect, for example Burn.
- Lua Script Path: The path to your script, starting with your ModID, eg
1234567890/Scripts/MyStatusEffect.lua - Lua Metatable Name: The name of the global table your script defines. It must be a valid Lua name.
2: Write the Script
Create the Lua file at the path you entered. The script defines one global table, named exactly the same as your Lua Metatable Name.
MyStatusEffect = {}
-- Runs every frame while the effect is active.
-- Return true to remove the effect.
function MyStatusEffect.Update( StatusEffect, Target )
local value = StatusEffect.StatusEffectValue:GetValue()
value = value - 1
StatusEffect.StatusEffectValue:SetValue( value )
if ( value <= 0 ) then
return true
end
return false
end
There are numerous functions that Status Effects can implement, check the Lua documentation for more info. Note that StatusEffectValues are NetProps, and thus must be accessed with GetValue/SetValue.
3. Register the effect
Your effect can’t be used until something registers it. Open your CharacterData or ArticleData asset and add your new Blueprint class to the Status Effect Behavior Classes array.
Using an Effect
Manipulating status effects is mostly done via 3 self-explanatory functions:
- Target:AddStatusEffect( inflictor, “EffectName”, stacks)
- local stacks = Target:GetStatusEffectValue( “EffectName” )
- Target:RemoveStatusEffects( “EffectName” )
Note that status effects do not inherently have a duration. If you want a duration-based status effect, you’ll typically use the stack counter as a timer and tick it down in the effect’s Update function.
Multiple instances of the same status will be resolved differently depending on whether Is Exclusive is set on the effect’s Blueprint. When true, the status will remove any prior instances before being applied. When false, multiple instances will coexist simultaneously, tick their functions seperately, and GetStatusEffectValue will return the value of the first instance found.
Naming and Mod Namespaces
Every effect is stored under a namespaced key, <YourModID>.<EffectName>. This allows two mods to both ship an effect called Burn without conflict. Base game effects have no prefix.
You do not have to type this prefix. When your script passes in a plain name like “Burn”, the game automatically prefixes your own ModID. You only need to think about this when invoking a status effect defined outside your own mod.
- For your own burn effect, write “Burn”
- For a base game effect (eg Zetterburn’s), write “base.Burn”
- For another mod’s burn effect write “OtherModID.Burn”
You can only ever register an effect in your own mod’s namespace.
Visuals
There are two ways to implement a status effect visual.
1. Status Visual Definition
On your Blueprint, add an entry to the Status Visual Definitions map using your effect’s short-name as a key. The properties on this allow you to manipulate the affected Rival’s tint, outline, and aura.
Colors in a Status Visual Definition are palette slot names, not raw color values. Default Color Palette provides fallback values when the inflictor has no matching palette of their own.
You can also implement GetVisual on your status effect to programatically provide a status effect at runtime, allowing you to change the values dynamically.
2. Visual Renderer Class
For effects that can’t be easily expressed with a Status Visual Definition, you can create your own renderer Actor and assign it to Visual Renderer Class on the Status Effect Blueprint.
SFX and VFX
To play SFX or VFX, you can set up the SFX Container Class and VFX Container Class and then invoke them from scripts:
self:PlaySFX( Target, "MySound" )
self:SpawnVfx( Target, "MyEffect" )
The inflictor can also be supplied as an optional third parameter. If the named effects are defined on the inflictor’s skin, it will use those instead of the ones on the Status Effect.
Custom Status States
Authoring a Custom Status State follows the same shape as a Status Effect, with three differences:
- The parent class is RivalsLuaCustomStatusState
- The name property is State Name
- The effect is registered in Custom Status State Behavior Classes
Custom Status States can be applied via SetCustomStatusState:
Target:SetCustomStatusState( ERivalsCharacterState.CustomStatus1, self:GetEntityIndex(), "MyState" )
The important element here is the last parameter, which is the State Name on your Blueprint. The type will always be CustomStatus1.
Your script then drives the state by implementing various functions in its script, see the Lua documentation for more details.
Function Reference
Status Effect Hooks:
Return true from any of these functions to remove the effect.
| Hook | Runs when |
|---|---|
Update | Every frame |
UpdatePostMovement | Every frame, after movement resolves |
UpdateInHitpause | Every frame during hitpause |
UpdateOnHitboxImpact | The Rival is struck. Also receives the hitbox |
UpdateOnHitRival | The Rival hits someone. Also receives the Rival hit |
UpdateOnHitShield | The Rival hits a shield. Also receives the shielding Rival |
UpdateOnInitState | The Rival changes state |
UpdateOnKnockback | The Rival takes knockback |
UpdateOnTechableHitstunEnd | Techable hitstun ends |
Additional Status Effect Hooks:
Hook | Runs when |
|---|---|
OnOwnerHitBlastzone | Fires when the player this the blast zone. Returning true prevents death instead of removing the effect — it must be removed manually instead. |
OnRemoved | Runs when the effect ends. No return value. |
Custom Status State Hooks
| Hook | Purpose |
|---|---|
Start, End, EndNaturally | Lifecycle. EndNaturally runs when the state times out rather than being cut short |
Update, UpdatePostMovement, UpdateTimer | Per frame |
GetLength | How many frames the state lasts |
GetIasaFrame | When the Rival can act again |
GetOverlays | Visual overlays |
GetVisual | Visual treatment |
CanHitboxHitTarget | Whether a given hitbox can connect |
ApplyKnockbackToTarget | Custom knockback response |
TakeDamage | Custom damage response |