RevFramework — Status Effects • FAQ¶
This FAQ answers decision questions about the Status Effects system.
It is not a feature list and does not repeat the README content.
Use this when you’re asking:
- “Am I using this correctly?”
- “Is this the right extension point?”
- “Why does this behave like this?”
If you're new to the system, start with the Mental Model page first.
The FAQ assumes you already understand the controller‑driven lifecycle of status effects.
Core Rule (Read This First)¶
Core rule
The StatusEffectController is the only supported mutation entry point.
All status application, refresh, and removal must go through the controller.
If you bypass the controller, behaviour is undefined.
How do I integrate Status Effects into my project?¶
Minimum setup:
- Add
StatusEffectControllerto any actor that should receive statuses - Apply effects via:
ApplyStatus(...), orApplyOrRefresh(...)(preferred)
That’s it.
Everything else — UI, Auras, Authority, Integration bridges — is optional.
| Feature | Required |
|---|---|
| StatusEffectController | ✅ Yes |
| Definitions / Effects | ✅ Yes |
| UI | ❌ No |
| Auras | ❌ No |
| Authority | ❌ No |
| Integration (Health, Shields) | ❌ No |
Should I use ScriptableObject definitions or build effects directly?¶
Both are supported. Choose based on intent:
| Use case | Recommendation |
|---|---|
| Designer‑tuned content | Use Definitions |
| Procedural / code‑driven | Build effects directly |
| Item / Pickup usage | Definitions (via Bridges) |
| Tests / simulations | Direct construction |
Definitions are data blueprints that build runtime effect instances.
They do not change runtime behaviour — they only configure it.
Why does my effect not tick or expire?¶
Almost always one of these:
| Cause | Explanation |
|---|---|
requireAuthority = true with no binder | Effects freeze by design |
Custom ITimeSource returning 0 | Time is paused |
| Effect duration = 0 | Instant or expired effect |
| Effect removed by cleanse/dispels | Working as intended |
If none of these apply, it may be a real issue.
Why doesn’t Status Effects replicate over the network?¶
Because it is not a netcode framework.
Status Effects:
- Applies logic locally
- Exposes authority hooks
- Leaves replication to your netcode
You must replicate:
- Active status IDs
- Remaining time
- Stack counts
- Context (if needed)
This keeps the system netcode‑agnostic by design.
Should I enable requireAuthority?¶
Only if you are doing multiplayer or deterministic simulation.
| Scenario | Setting |
|---|---|
| Single‑player | requireAuthority = false |
| Server‑authoritative multiplayer | true |
| Client‑side prediction | true (with custom binder) |
If enabled without a binder, everything no‑ops by design.
Is it safe to delete folders I don’t use?¶
Not inside the runtime assembly, no. Everything under Runtime/Systems/StatusEffects compiles into one assembly with no define gating inside it, so deleting a folder from it is an unconditional compile error — not a feature that switches off.
| Folder | Safe to delete? | |
|---|---|---|
UI | ✅ | Presentation only; nothing in the runtime references it. |
Auras | ✅ | StatusAuraZone is self-contained. |
Integrations/ (top level, outside the runtime folder) | ✅ | Separate assemblies, define-gated. That is what optionality looks like here. |
Timing | ❌ | StatusEffectController.ResolveTimeSource() constructs UnscaledTimeSource, PausedTimeSource and ScaledTimeSource directly. |
Authority | ❌ | StatusEffectController.HasAuthority() calls StatusAuthority.Resolve. |
Movement | ❌ | SlowStatus references MovementSpeedScaler, and Effects is required by Core. |
This table used to say the opposite
Three of these rows were marked deletable and are not: following the old table produced a project that would not compile. The heading answered "Yes — by design", and the closing line claimed only Abstractions and Core were required. Neither was true.
What optionality actually exists. Whole systems are optional — delete Runtime/Systems/StatusEffects entirely and the rest of RevFramework still compiles, because cross-system code is gated behind REV_*_PRESENT defines. Within a system, the assembly is the unit, not the folder.
Where should stacking rules live?¶
Always in the controller.
Do not:
- Encode stacking inside effects
- Track stacks manually in effects
- Query other effects from an effect
Use:
StatusStackingRuleSetStackCap(...)SetPerSourceStacks(...)
Why doesn’t potency affect my effect?¶
Only effects implementing IAdjustableMagnitude respond to potency changes.
Check:
- Does the effect implement
IAdjustableMagnitude? - Are you recomputing potency via the controller?
- Is a potency provider present on the target?
Potency is absolute, not compounding.
Why does my UI flicker when effects refresh?¶
Replace/Refresh stacking briefly removes and re‑adds effects.
The provided UI:
- Uses a destroy‑grace window
- Coalesces rapid refreshes
- Uses unscaled time for stability
If you write your own UI, replicate this behaviour.
Can I apply statuses without a StatusEffectController?¶
This is a hard requirement
No.
Without a controller:
- No stacking
- No timing
- No authority
- No events
The system will warn (in editor) and safely no‑op.
Where should gameplay rules live?¶
| Concern | Location |
|---|---|
| Behaviour | Effect implementation |
| Rules / stacking | Controller |
| Scaling | Providers + math service |
| UI | UI layer |
| Authority | Authority binder |
| Integration | Bridges / Integration |
If something feels ambiguous, it likely belongs in Core.
How do I create a custom status effect?¶
Create a class derived from TimedStatusEffect.
Steps:
- Define a
StatusId - Choose a
StatusStackingRule - Implement behaviour in
OnTick(...) - Optionally expose metadata via
IStatusMetadata
Example:
public sealed class BleedStatus : TimedStatusEffect, IStatusMetadata
{
public override StatusId Id => "bleed";
public override StatusStackingRule Stacking => StatusStackingRule.Stack;
protected override void OnTick(GameObject target, float dt)
{
// custom behaviour here
}
}
Register in StatusRegistry if needed.
Can I extend this system safely?¶
Yes — that’s the point.
Safe extension points:
- New effects (
TimedStatusEffect) - New definitions
- New potency/resistance providers
- New sinks (movement, mana, stamina)
- Custom authority binders
- Custom math services
Unsafe changes:
- Modifying controller internals
- Adding logic to definitions
- Letting effects mutate global state
Before contacting support¶
Check:
- Is
requireAuthorityenabled without a binder? - Does the target have a
StatusEffectController? - Are you reusing effect instances?
- Are you mutating effect state directly?
- Are you expecting replication that doesn’t exist?
If it still looks wrong after that, it may be a real bug.
Final note¶
Status Effects is intentionally strict about ownership and responsibility.
Why the strictness pays off
That strictness ensures:
- predictable behaviour
- multiplayer safety
- low support overhead
If you work with the system boundaries, it becomes very hard to break.