🧪 Status Effects System — Public API¶
This page defines the supported, stable public API for the RevFramework Status Effects System.
If something is not listed here, it is not supported as a public integration point — even if it appears accessible in code.
Audience: Developers integrating Status Effects into gameplay, tools, UI, or other systems
Scope: Runtime public API and supported runtime components
Stability: Breaking changes to items listed on this page are avoided or clearly versioned
API Stability Policy
Items listed on this page are considered stable.
New public APIs and components may be added over time.
Internals may change without notice.
RevFramework guarantees stability only for documented public APIs and components.
Usage of internal or undocumented code is unsupported and may break without notice.
📌 Core Concepts¶
- StatusEffectController is the runtime orchestration root.
- Status effects are controller-driven — effects do not self-register, self-tick, or self-remove.
- The controller is the sole owner of effect lifecycle.
- Effects are passive runtime objects and do not manage their own execution.
- Effect behaviour lives in effect instances implementing
IStatusEffect. - Construction is flexible: direct code construction, definition assets, or id-based registry creation.
- Optional behaviour is layered through metadata, potency, resistance, authority, and timing seams.
- The system avoids global state and does not require singletons.
🧠 Runtime Guarantees¶
- Effects are always driven by the controller (never self-driven)
- Authority gating blocks both ticking and mutation
- Effects can exist without their target integrations
- Potency and duration are computed independently
🧱 Core Runtime Controller¶
StatusEffectController¶
The central runtime component responsible for applying, ticking, refreshing, querying, and removing status effects.
Responsibilities¶
- Apply and remove effect instances
- Advance active effects over time
- Enforce stacking behaviour
- Respect immunity and resistance
- Recompute potency and duration modifiers
- Gate ticking and mutation through authority (when enabled)
- Emit runtime events for gameplay, diagnostics, and UI
Gameplay systems typically interact with Status Effects through this controller.
▶️ Applying and Refreshing Effects¶
ApplyStatus¶
void ApplyStatus(IStatusEffect effect)
void ApplyStatus(IStatusEffect effect, StatusContext context)
Applies a concrete effect instance to the controller owner.
Supported behaviour includes:
- replace / refresh / stack handling
- immunity checks
- potency scaling
- duration scaling
- source attribution via
StatusContext
Use the overload with StatusContext when you want item / ability / instigator attribution.
ApplyOrRefresh¶
void ApplyOrRefresh(Func<IStatusEffect> build, StatusContext context)
Builds and applies an effect through a factory delegate.
Useful for:
- centralised refresh flows
- lazy construction
- code-driven ability effects
- integrations that want one apply path without pre-constructing the effect
❌ Removal / Cleanse / Dispel¶
void RemoveStatus(StatusId id)
void RemoveStatusAt(int index)
void ClearAll()
Removes active effects from the controller.
Dispel / Cleanse¶
int Dispel(DispelType type, int minTier = 0)
int CleanseByTag(StatusTag tagMask)
Removes active effects matching the requested dispel bucket or tag mask.
🔍 Runtime Queries¶
bool HasStatus(StatusId id)
int GetStackCount(StatusId id)
IReadOnlyList<IStatusEffect> Active { get; }
bool TryGetFirst(StatusId id, out IStatusEffect effect)
IStatusEffect GetFirstOrNull(StatusId id)
int TryGetAll(StatusId id, List<IStatusEffect> buffer)
bool TryGetFirstContext(StatusId id, out StatusContext context)
StatusContext GetContext(IStatusEffect effect)
These methods provide the supported runtime query surface for gameplay, UI, and tools.
Notes:
Activeis a live, read-only view- Do not modify the collection externally
- Ordering is implementation-defined and should not be relied upon
⚙️ Runtime Policy Controls¶
void SetStackCap(StatusId id, int max)
void ClearStackCap(StatusId id)
void SetPerSourceStacks(StatusId id, bool enabled = true)
void SetTimeMode(StatusTimeMode mode, MonoBehaviour custom = null)
void RecomputePotencyForAll()
void RecomputeDurationsForAll(bool pulseFx = true)
These methods modify controller behaviour at runtime.
📣 Lifecycle Events¶
event Action<StatusId> StatusApplied
event Action<StatusId> StatusRefreshed
event Action<StatusId> StatusRemoved
event Action<StatusId> StatusExpired
These events provide the primary gameplay / UI event surface.
🧩 Effect Model¶
IStatusEffect¶
Core runtime contract representing a single status effect instance.
StatusId Id { get; }
float Duration { get; }
float TimeRemaining { get; }
bool IsExpired { get; }
StatusStackingRule Stacking { get; }
void Apply(GameObject target)
void Tick(GameObject target, float deltaTime)
void Remove(GameObject target)
void Refresh(float? newDuration = null)
Effects are runtime instances controlled by StatusEffectController.
TimedStatusEffect¶
Recommended base class for most custom effects.
Provides:
- duration handling
- expiry logic
- refresh behaviour
- FX seam integration
🏗️ Effect Construction Paths¶
RevFramework supports three official construction paths.
1. Direct Runtime Construction¶
controller.ApplyStatus(new PoisonStatus(5f, 10f));
Used for code-driven gameplay.
2. Definition Assets¶
abstract class StatusEffectDefinitionBase : ScriptableObject
{
IStatusEffect BuildEffect();
}
Used for data-driven authoring.
Designers create ScriptableObject assets which build runtime effects.
Intended Usage of StatusEffectDefinitionBase¶
Definitions are recommended when:
- designers configure status behaviour
- abilities/items reference reusable effect data
- status configuration should live in assets
Direct construction is recommended when:
- gameplay logic creates effects directly in code
- effects are dynamic or procedurally generated
Both workflows are fully supported.
3. Registry Construction¶
StatusRegistry.TryBuild(StatusId id, float duration, float magnitudeOrMult, out IStatusEffect effect)
Used when:
- systems create effects by id
- integrations require decoupled construction
- plugins register new effect types
Note:
The registry is optional and primarily intended for:
- decoupled systems
- id-driven construction
- plugin registration
It is not required for normal gameplay usage.
🏷️ Status Identity and Tags¶
StatusId¶
Strongly typed identifier used throughout the system.
Prefer StatusId over raw strings for gameplay code.
StatusTag¶
Bit flags describing effect categories such as:
- Buff / Debuff
- DOT / HOT
- CC
- Movement
- Poison / Fire / Magic
Used by:
- immunity
- resistance
- UI filtering
- dispel logic
🔌 Extension Seams¶
Effect Capability Interfaces¶
Optional effect interfaces:
IAdjustableMagnitudeIStatusMetadataIDispellable
Receiver‑Side Modifier Interfaces¶
Attach to actors:
IStatusPotencyIStatusResistanceIStatusImmunity
These influence how incoming effects behave.
Math Service¶
IStatusMathService
Allows custom potency / duration calculation pipelines.
Time Source¶
ITimeSource
Custom time provider for the controller.
Authority¶
IStatusAuthority
Used for multiplayer or restricted mutation rules.
When authority is enabled:
- effects do not tick
- effects do not apply
- effects do not mutate
unless authority resolves successfully
🧰 Utility Helpers¶
StatusUtility¶
Supported helpers:
ComputeFinalPotency()
ComputeFinalDurationScale()
Apply()
Useful for previews, diagnostics, or convenience application.
🧾 Built‑In Effect Types¶
- PoisonStatus
- BurnStatus
- SlowStatus
- HasteStatus
- StunStatus
- VulnerabilityStatus
- ThornsStatus
🔗 Integration Effects (Health Module)¶
When the Health integration module is present, additional effects become available:
RegenStatusShieldStatus
These live in:
RevFramework > Integrations > StatusEffects > HealthIntegration
They integrate the Status Effects system with the Health pipeline.
🎨 Supported UI Components¶
Optional UI helpers:
StatusBuffBarStatusIconViewStatusIconLibrary
These provide a simple UGUI status bar implementation.
TL;DR¶
If it appears on this page, it is a supported public API.
Anything not listed should be treated as internal implementation detail.