Effect Components
CrowdControlEffectComponent is the recommended way to implement effects. Instead of registering every effect manually and routing all triggers through the subsystem's global delegates, you add one component per effect to any actor. The component:
- carries the effect's menu metadata (ID, name, description, price, categories, duration),
- registers itself with Crowd Control on BeginPlay,
- receives its own trigger callback when a viewer buys the effect,
- automatically sends the success/failure response based on your callback's return value,
- self-manages timed effects (duration countdown, pause/resume, stop).
Setting Up an Effect
Add a CrowdControlEffectComponent to an actor (or create a Blueprint subclass of it per effect) and fill in the details panel:
| Property | Meaning |
|---|---|
| Effect ID | Unique ID, lowercase with no spaces - must match your effect pack. |
| Display Name | Name shown to viewers. |
| Description | Description shown to viewers. |
| Price | Default price in coins. |
| Categories | Menu categories. |
| Duration | Seconds. 0 makes it an instant effect; greater than 0 makes it a timed effect. |
| Auto Register | Registers the effect on BeginPlay (default on). Turn off to call Register yourself. |
Handling Triggers
Override OnEffectTriggered (Blueprint: Event On Effect Triggered; C++: OnEffectTriggered_Implementation). It receives the request ID, quantity, any parameters, and the viewer's display name, and returns how the effect was handled:
| Return value | What happens |
|---|---|
| Success | Success is reported; timed effects begin their countdown. |
| FailTemporary | Reported as a temporary failure - the viewer is refunded and the effect may be retried. |
| FailPermanent | Reported as a permanent failure - the effect will not be retried. |
| Pending | Nothing is sent. Respond later with CompleteSuccess, CompleteFailTemporary(Message), or CompleteFailPermanent(Message) - use this for asynchronous handling. |
A minimal instant effect in Blueprint is just: override On Effect Triggered → apply your gameplay change → return Success.
Timed Effects
When Duration > 0, a successful trigger starts a local countdown on the component:
- OnEffectStopped fires when the time expires (or the effect is stopped early with
Stop). Undo the effect's gameplay state here. - Pause / Resume pause and resume the countdown, notify Crowd Control (
timedPause/timedResume), and fire the overridable OnEffectPaused / OnEffectResumed events. Use these when your game enters a state where the effect shouldn't tick down (cutscenes, menus, loading). IsRunning,IsPaused, andGetTimeRemainingexpose the current state.
While a timed effect is running, additional triggers of the same effect are automatically answered with a temporary failure.
Menu Visibility & Availability
Components can report their effect's menu state directly:
- SetVisibility(bVisible) - show or hide the effect in the menu.
- SetAvailability(bAvailable) - mark the effect purchasable or not.
Visibility and availability are independent states on the Crowd Control side - when changing availability, remember visibility stays whatever you last reported. Use these from your game state logic, e.g. hide a "Kill Boss" effect outside of boss fights.
The same functionality is available on the subsystem for effects without components: ReportEffectStatus, SetEffectVisibility, SetEffectAvailability.
Effect Notifications
To show on-screen notifications like "Viewer sent Spawn Zombies!", bind a widget to the subsystem's OnEffectRequestReceived event. It fires for every incoming effect - whether it is handled by a component or by the global trigger delegates - with the request ID, effect ID, display name, viewer name, duration, and quantity. It is purely informational and does not replace responding to the effect.
Reporting Game State (Pack Metadata)
To report live game state to Crowd Control (used by packs that surface game state to viewers), call the subsystem's SendPackMetadata(Key, Value) - or SendPackMetadataJson with a JSON object string for multiple values at once.
