Pickups → Currency Integration¶
This folder provides an optional integration bridge between the Pickups system and the RevFramework Currency system.
It allows pickup effects to modify currency without the Pickups runtime assembly depending on Currency. The dependency lives here instead, in an assembly gated on REV_CURRENCY_PRESENT that calls ICurrencyService directly.
This integration is built and supported for RevFramework systems only.
It is not intended as a general integration layer for third-party currency solutions.
What This Integration Does¶
The GiveCurrencyEffect allows pickups to:
- Grant currency — a positive
amountcredits the actor - Remove currency — a negative
amountdebits them - Report whether the change actually happened, so a pickup can decline to consume itself
👉 This keeps the Pickups runtime assembly fully decoupled from Currency: the dependency lives here, in a separate assembly that only compiles when Currency is present.
How It Works¶
GiveCurrencyEffect.TryApply(...) does three things, in order:
- Guard. Returns
falseimmediately if there is no context object, ifcurrencyIdis blank, or ifamountis zero. Nothing is applied and nothing is logged as an error. - Resolve.
CurrencyResolve.ServiceFrom(ctx)returns the activeICurrencyServicefor the context object's scene. This is a typed call, not a search:CurrencyResolveprefers a service published throughCurrencyBootstrap.Publish(...), then a per-scene cached lookup ofSceneCurrencyService. If it finds nothing it returnsnull, this effect returnsfalse, and in the Editor it logs a warning naming both fixes. - Apply. Calls
ICurrencyService.Credit(ctx, currency, money)for a positiveamountorDebit(ctx, currency, money)for a negative one, and returns the service'sSuccessflag.
There is no reflection, no duck-typed method-name search, and no relay step.
There used to be
An earlier version resolved the service by reflecting over assembly-qualified type names and then hunting for a (string, int) method called Add, Adjust, Credit or Deposit. It never worked: the assembly names were wrong, one candidate was the placeholder "MyGame.CurrencyService, MyGame", and the real contract is Credit(GameObject, CurrencyId, Money). It failed silently on every path, so the effect had always done nothing. Calling ICurrencyService directly turns that whole class of failure into a compile error. CurrencyServiceRelay is not part of this path and never was — no runtime code here references it.
Important¶
This is optional¶
- Pickups do not require Currency
- This assembly is gated on
REV_CURRENCY_PRESENTand simply does not compile without it
The dependency is isolated, not hidden¶
- The Pickups runtime assembly does not reference Currency
- This integration assembly does, directly and by type
- You can remove this folder without affecting Pickups
Behaviour depends on the Currency system¶
- A debit larger than the balance is refused by the service and leaves the balance untouched — this effect never partially applies
- Caps, authority and other policies composed onto the scene service apply here like anywhere else
- Any refusal is returned as
falseand logged as a warning in the Editor
It reports refusal¶
GiveCurrencyEffect implements IPickupEffectReportsDelivery, so PickupEffect.TryApplyTo(...) and PickupEffectRunner.TryApply(...) return the service's real answer.
That matters for the caller: TriggerPickup reads it and does not destroy itself when the payload was refused. Without it, a missing service, a cap refusal and a clean credit are indistinguishable — which is how a toll plate built as a pickup with amount = -50 lets an under-funded player through and removes the obstacle permanently.
It also implements IEffectAllowsNullDamageable: a currency change does not require the actor to be damageable.
Example Usage¶
- Create a
GiveCurrencyPickupDefinition -
Set:
-
currencyId = "Gold" -
amount = 10 -
Assign the definition to a pickup
- Put a
SceneCurrencyServicein the scene, or publish one withCurrencyBootstrap.Publish(...)
👉 When the pickup is consumed, the currency change is applied if a service resolves and accepts it. If either fails, the effect reports false and the pickup is left in the world.
Design Intent¶
This integration demonstrates:
- How Pickups can interact with other RevFramework systems
- How an optional dependency is isolated in its own gated assembly rather than reflected around
- How to keep systems modular and optional
- Why an effect that can be refused should say so, through
IPickupEffectReportsDelivery
Third-Party / Custom System Use¶
This integration is built for RevFramework Currency systems only.
If you are using a different currency system:
- Treat this as a reference example
- Implement your own pickup effect
- Use your own service layer
👉 Custom or third-party currency integrations are not supported by this adapter.
Safe to Remove¶
This folder is completely optional.
Removing it will:
- Not affect the Pickups runtime
- Not break existing pickup behaviour
- Only remove currency-related functionality
Summary¶
This integration answers:
“How can pickups affect currency without coupling systems?”
It provides:
- A currency effect that calls
ICurrencyServicedirectly, from an assembly that only exists when Currency does - A safe, optional extension point
- A clear integration pattern
Use it as a reference, extend it, or replace it entirely.