Recycling
The bottle recycling machine takes bottles and cans from the player and owes them coins for it. The player collects the coins from the machine’s screen. This API lists the machines in the scene you are in, reads and changes how many OC (Open Sewer Coins) a machine owes the player, and tells your mod when the player returns bottles. It does not hand the coins out. See the limits below.
When to use it
- Show or log how much a recycling machine owes the player.
- Add a bonus to what a machine owes, or reset it to zero.
- React when the player returns bottles, for example to count them or give a reward.
Quick example
This mod logs each bottle return: how many items the player returned and how many OC that added to what the machine owes.
using ObenseuerCore;
[ModInfo("example.recyclingwatch", "Recycling Watch", "0.1.0")]
[ModDependency("obenseuer.moddingframework", "0.11.0")]
public sealed class RecyclingWatch : FrameworkMod
{
protected override void OnLoad()
{
Recycling.Recycled += args => Log.Info("Machine " + args.Id + ": " + args.Amount + " returned, +" + args.Money + " OC owed");
}
}
Recycled is an event: the framework calls your code each time it happens. See Using events for more on events.
Common tasks
Log how much each machine in the scene owes the player.
foreach (string id in Recycling.All())
Log.Info(id + " owes " + Recycling.Owed(id) + " OC");
Add a 50 OC bonus to what a machine owes. Owed gives -1 when the machine is not found, so check that first.
string id = "put an id from All() here";
int owed = Recycling.Owed(id);
if (owed >= 0) Recycling.SetOwed(id, owed + 50);
Reset what a machine owes to zero.
string id = "put an id from All() here";
Recycling.SetOwed(id, 0);
Reference
This is the full list of what the API gives you. A machine is named by an id, a text name for that machine in the scene. You get the ids from Recycling.All() and pass them to the other members.
Recycling recycling machines in the scene
Use it to list the machines in the scene, read and set what a machine owes the player, and hear when bottles are returned.
public static class Recycling
{
public static event Action<RecycledArgs> Recycled;
public static bool IsAvailable { get; }
public static List<string> All();
public static int Owed(string id);
public static bool SetOwed(string id, int owed);
}
| Property | Type | What it means |
|---|---|---|
IsAvailable | bool | false when the Recycled event could not be set up. |
| Method | Returns | What it does |
|---|---|---|
All() | List<string> | The id of every machine in the scene you are in. |
Owed(id) | int | The OC the machine owes the player. -1 when no machine has that id or no save is loaded. |
SetOwed(id, owed) | bool | Sets what the machine owes. true when it was set. |
| Event | Gives you | When it fires |
|---|---|---|
Recycled | RecycledArgs | The player returned bottles to a machine. |
RecycledArgs one bottle return
Recycling.Recycled hands you one of these for each return the machine accepts. Money is the OC that return really added, and Amount is the number of items.
public sealed class RecycledArgs
{
public string Id { get; }
public int Amount { get; }
public int Money { get; }
}
| Property | Type | What it means |
|---|---|---|
Id | string | The id of the machine. |
Amount | int | How many items were returned. |
Money | int | The OC this return added to what the machine owes. |
Things to know
- The id is the machine’s saved name, or its place in the scene when it has none. The place looks like
SceneName:Root[0]/Child[2]and changes if objects in the scene are reordered. (It is the object’sGUIDwhen it has one, otherwise the scene path.) All()lists the machines in the scene you are in, and it is slow, so do not call it every frame. It searches the scene each time. A machine that is switched off in the scene is not listed. An empty list means there are none, or that something went wrong. (It lists the scene id of every activeBottleRecyclingwithFindObjectsByType. A machine with no id is skipped.)Owed(id)is the OC the player can still collect from that machine. It gives-1when no machine has that id or no save is loaded. (It readsBottleRecycling.bottleRecyclingMoney.)SetOwed(id, owed)sets that amount directly. A negative amount returnsfalseand changes nothing. It also returnsfalsewhen no machine has that id, and while a save is loading or being written.- Otherwise
SetOwedreturnstrue. It does not pay out anything and does not make the machine’s screen show a payout. (It writesbottleRecyclingMoney. The panel adds to this field when bottles are returned and pays it out one OC at a time, so a change made here is used the next time the panel counts.SetOweddoes not fire the machine’sonGiveMoneyrelay, which belongs to the payout.) Recycledfires once for each return the machine accepts.Amountis how many items were in that return.Moneyis how many OC the return really added. A mushroom return, which the game gives a random value, reports the value the game actually added. (It is raised after the game has added the value tobottleRecyclingMoney.Moneyis the change in that field across the game’s call.)Recycleddoes not fire when the machine refuses an item, and it does not fire when your mod callsSetOwed. A save loading or being written does not raise it either.- A
Recycledhandler that throws an error does not stop the others. The framework logs the error and still runs the other handlers. - If the player returns bottles while the machine is paying out, that payout stops. The rest of what the machine owes stays on it.
Moneystill counts only the new return. ChangingSetOwedwhile a payout is running changes how much is paid. (The payout is a coroutine that countsbottleRecyclingMoneydown while it runs.)
Limits
- You can’t make a machine pay out. The game only pays out while the machine’s screen is open, and a mod can’t open that screen without opening the game menu. To change what the player gets, use
OwedandSetOwed. (BottleRecyclingPanel.GiveCoinsis public, but it pays throughStartGiveMoney, which reads the panel’scurrentBottleRecyclingfield. The game sets that field only inOpen, which also opens the game menu, and clears it inClose. The game never sets it by itself with the menu closed.) - You can’t read or change what each kind of bottle is worth.
Recycledtells you what the game added, and that is all. (The panel’s category table inBottleAddhas no framework call to read or change it.) - You can’t trigger the machine’s payout relay. (The framework has no call for the machine’s
onGiveMoneyrelay.)
Details
Target: Obenseuer 0.5.08 (buildid 25969064), Unity 6000.0.77f1 Mono, BepInEx 6 Unity.Mono (be.788, the tested build) or BepInEx 5 (5.4.23 or later). Namespace: ObenseuerCore. Logs go to BepInEx\logs\obenseuer.moddingframework.recycling.log.
Everything not listed in this reference is internal and may change without notice.
The framework changes one game method when it starts, so it can tell your mod when bottles are returned. This page calls that a feature group: its name is obenseuer.moddingframework.recycling, the name you will see in the log.
When you can call it
- Call everything from your mod’s normal code (
OnLoad, event handlers,Update), not from a background thread you started. The game and Unity only work safely on one thread, the main thread (see the glossary). - It is safe to call any of it at any time, even on the main menu or while a save is loading. If there is nothing to read yet,
All()gives an empty list andOwedgives-1. Anullor empty id finds nothing, and nothing is thrown to you.
What to check for and what comes back
Recycling.IsAvailabletells you whetherRecycledworks. It isfalsewhen the framework could not set up the event, or when the feature group was turned off.All,OwedandSetOwedkeep working when it isfalse.
If something fails to set up
The framework changes some of the game’s methods when it starts. If a game update breaks one of them, the framework removes all the changes of the feature group that depends on it, turns the group off, and writes error lines and a warning to the group’s log file in BepInEx\logs. The rest of the framework keeps working.
- If the framework cannot change the game’s bottle return step,
Recycledstops and the rest keeps working. One warning goes to the log, andIsAvailablebecomesfalse. (The framework adds a prefix and a postfix toBottleRecyclingPanel.BottleAdd, the private method the panel runs for each returned item.)