RevFramework – Pickups • Core¶
Folder: Runtime/Systems/Pickups/Core
The Core folder contains the foundation of the entire pickup-effect pipeline.
These files define how effects are created, decorated, validated, cooldown-gated, and executed at runtime.
✔ Base class for all pickup effects
✔ Global cooldown system
✔ Null-damageable support
✔ Context-aware effect API
✔ Factory-driven decorator pipeline
✔ No reflection in the hot path
✔ Fully deterministic and multiplayer-safe (ownership rules live in Authority)
🎯 Purpose (accurate)¶
This folder provides:
PickupEffect— base class with cooldown gating, decorator traversal, and null-damageable checksIEffectAllowsNullDamageable— marker enabling execution without anIDamageablePickupEffectStaticCooldowns— global(ownerID, effectID) → expiryTimemapPickupEffectFactory— constructs a full decorated effect chain from a definitionIPickupEffectWithContext+ItemUseContext— richer API for item / inventory-driven effects- Decorator registration via
IPickupDecoratorRegistry PickupEffectRunner— unified dispatcher (context-aware and classic paths)
This folder deliberately does not handle:
- triggers or colliders
- authority or ownership
- world pickups or interactables
- inventory usage logic
- UI or feedback
- networking or replication
Those responsibilities live in other folders.
🧩 Key Types (truth-aligned)¶
PickupEffect¶
The abstract base for all pickup effects — including decorators.
Capabilities:
- Built-in cooldown gating
- Enforces null-damageable policy by walking the decorator chain
- Applies cooldowns per owner, resolved as:
- The
ComponentbackingIDamageable(if present) - Fallback to the
contextGameObject - Skips cooldown enforcement if no valid owner exists
- Calls
OnApplyonly after all policy checks succeed
Runtime entry point:
public void ApplyTo(IDamageable target, GameObject context)
Implement effect logic in:
protected abstract void OnApply(IDamageable target, GameObject context);
Decorator chains are traversed correctly at runtime to determine policy and execution order.
IEffectAllowsNullDamageable¶
A simple marker interface.
If any effect or decorator in the chain implements this interface,
the effect may execute without an IDamageable.
Utility access:
effect.AllowsNullDamageable();
Internally this walks the decorator chain via PickupEffect logic.
PickupEffectStaticCooldowns¶
Global, per-session cooldown storage.
Important (post-refactor):
This class is pure runtime — there is no editor-only pruning or editor dependency.
Behaviour:
- Keys are
(ownerInstanceID, effectInstanceID) - Expired entries are removed lazily during lookup
- Cooldowns are never persisted (session-only)
- Zero allocations on the hot path
Public API:
bool IsOnCooldown(Object owner, int key);
void StartCooldown(Object owner, int key, float duration);
void ClearFor(Object owner);
void ClearAll();
PickupEffectFactory¶
Builds a fully decorated PickupEffect from a ScriptableObject definition.
Construction process:
- Create the core effect via
def.CreateCoreEffect() - Sort decorators ascending by priority
- For each decorator:
- Resolve a creator from
IPickupDecoratorRegistry - Instantiate the decorator ScriptableObject
- Wrap the previous effect
- Return the outermost decorated effect
Key guarantees:
- Default registry includes Sound, VFX, PersistentVFX, Conditional, and DebugLog creators
- Registry is pluggable via:
SetRegistry(...)RegisterCreator(...)UnregisterCreator(...)- No reflection is used during construction
ItemUseContext + IPickupEffectWithContext¶
Used when effects originate from inventory or item usage, rather than world pickups.
ItemUseContext fields:
itemDef— originating item definition (optional)owner— GameObject owning the inventory (optional)slotIndex— slot index or-1when not applicable
If an effect implements:
IPickupEffectWithContext
then the runner routes execution to:
ApplyTo(IDamageable damageable, GameObject target, ItemUseContext ctx);
Otherwise, it falls back to the classic PickupEffect.ApplyTo path.
This routing logic lives in PickupEffectRunner, not in PickupEffect itself.
DecoratorType¶
Enum mapping definition entries to concrete decorator creators:
VFXSoundDebugLogConditionalPersistentVFX
Creators live in Decorators/Creators.
PickupEffectRunner¶
Single, unified API for executing pickup effects.
Responsibilities:
- Detects whether the effect implements
IPickupEffectWithContext - Routes to the context-aware overload when available
- Otherwise invokes
PickupEffect.ApplyTo - Provides a convenience overload for world pickups:
PickupEffectRunner.Apply(effect, dmg, target);
🔁 Runtime Flow (exact to code)¶
- A pickup effect definition is selected
PickupEffectFactory.BuildEffect(def)constructs the decorated effect instance- Caller invokes
PickupEffectRunner.Apply(...) - Runner selects:
- context-aware path (
IPickupEffectWithContext), or - classic
ApplyTopath PickupEffect.ApplyToperforms:- decorator-chain walk to compute null-damageable policy
- enforcement of that policy
IHealthReadonly.IsDeadcheck when applicable- cooldown owner resolution
- cooldown check and early-out if active
- cooldown registration when applicable
- invocation of
OnApply - Decorators execute in order:
BeforeApply→ wrapped effect →AfterApply
This sequence exactly mirrors the runtime implementation.
🧱 Extending Core (supported paths)¶
| Goal | Action |
|---|---|
| Add a new effect type | Subclass PickupEffect and override OnApply |
Allow execution without IDamageable |
Implement IEffectAllowsNullDamageable |
| Add item-use context logic | Implement IPickupEffectWithContext |
| Add a new decorator | Subclass PickupEffectDecorator + implement IPickupDecoratorCreator |
| Replace decorator registry | PickupEffectFactory.SetRegistry(...) |
| Register additional decorators | PickupEffectFactory.RegisterCreator(...) |
📘 See Also¶
- Definitions — effect authoring ScriptableObjects
- Decorators — wrappers providing pre/post behaviour
- Effects — built-in effect implementations
- Runtime — triggers, interactables, authority, world pickups