Listing and sending bills
Invoices lists, sends and cancels the player’s bills, and tells you when one is issued, paid or cancelled. Each bill is an InvoiceInfo, a snapshot of it at the moment you asked, so ask again for fresh values. Text in brackets at the end of a note is extra detail you can skip on a first read.
Invoices list, send and cancel bills
This is the class you start from. All() and Get list the bills, Create sends one, Cancel removes one, and the Issued, Paid and Cancelled events tell you when a bill changes.
public static class Invoices
{
public static List<InvoiceInfo> All();
public static InvoiceInfo Get(int id);
public static bool CanPay(int id);
public static bool Create(string debtor, MoneyCurrency currency, int amount, int days = 7);
public static bool Cancel(int id);
public static bool FireSender(string id);
public static event Action<InvoiceArgs> Issued;
public static event Action<InvoiceArgs> Paid;
public static event Action<InvoiceArgs> Cancelled;
public static bool IsAvailable { get; }
}
| Method | Returns | What it does |
|---|---|---|
All() | List<InvoiceInfo> | Every open invoice the player has. |
Get(id) | InvoiceInfo | The invoice with this id. null when there is none. |
CanPay(id) | bool | true when the invoice can be paid right now. |
Create(debtor, currency, amount, days) | bool | Sends a new invoice. false when it was not sent. |
Cancel(id) | bool | Cancels an invoice. true when it is gone. |
FireSender(id) | bool | Sets off an invoice sender in the level. false when no new invoice was issued. |
| Property | Type | What it means |
|---|---|---|
IsAvailable | bool | false when the three events could not be set up. |
| Event | Gives you | When it fires |
|---|---|---|
Issued | InvoiceArgs | An invoice has just been issued. |
Paid | InvoiceArgs | An invoice has just been paid. |
Cancelled | InvoiceArgs | An invoice has just been cancelled. |
InvoiceInfo a snapshot of one invoice
All() and Get(id) give you this, one for each bill in the game’s list. It is a snapshot taken when you asked. Use its Id with Get, CanPay and Cancel.
public sealed class InvoiceInfo
{
public int Id { get; }
public string Debtor { get; }
public int Amount { get; }
public MoneyCurrency Currency { get; }
public int DueDay { get; }
public int DaysRemaining { get; }
public bool Expired { get; }
public bool NoCrime { get; }
}
| Property | Type | What it means |
|---|---|---|
Id | int | The invoice’s number. Use it with Get, CanPay and Cancel. |
Debtor | string | The name printed on the bill. See The name on the bill. |
Amount | int | The amount, a whole number. |
Currency | MoneyCurrency | OC (Open Sewer Coins) or RM (Real Money). |
DueDay | int | The game day the invoice is due. |
DaysRemaining | int | Days left until it is due. Below 0 when it is overdue. |
Expired | bool | true when the invoice has run out. |
NoCrime | bool | true when not paying it in time is not counted as a crime. |
InvoiceArgs what you are told when an invoice changes
Issued, Paid and Cancelled give you this. Invoice is the bill the event is about. After Cancelled, Get returns null for that id, so keep the bill from the args.
public sealed class InvoiceArgs
{
public InvoiceInfo Invoice { get; }
}
| Property | Type | What it means |
|---|---|---|
Invoice | InvoiceInfo | The invoice as it was when the event fired. |
Things to know
All()lists every invoice that is still open. Invoices that were paid or cancelled are not in it.CanPay(id)istrueonly when the invoice exists, has not run out, and the player has the money right now. It does not take the money. (It asks the game’sInvoiceController.CanPayInvoice, which is the same check the game makes when it pays.)Createsends one invoice each time you call it. It uses the game’s own way of making an invoice, so it is the same item the game sends. The invoice is duedaysgame days from today, and the mail arrives after the game’s usual mail delay.Createreturnstruewhen the player’s invoice count went up. (It callsInvoiceController.CreateInvoiceand compares the count ofinvoicesbefore and after. That way anIssuedhandler that creates a second invoice does not make the first call returnfalse. It uses the game’s private invoice item template.)Cancel(id)removes the invoice and returnstruewhen it is gone. The invoices with a follow-up action are the legal debt ones and the bank debt down payment, and cancelling one would skip that action and leave the game in a wrong state. (It refuses whenonPaidoronExpiredis set. Those callbacks areAddDebt,ClearDebtand the bank debt down payment.)- Cancelling does not take the bill out of the player’s mail or bag. The bill item stays where it is.
Issuedfires when any invoice is created, from your mod or from the game. That covers invoices the game makes itself, such as ones that come from sleep events. It fires before the mail is delivered, so the mail does not exist yet inside your handler. It does not fire when you load a save. (It fires whenCreateInvoiceItemadds the invoice. A loaded list is not made byCreateInvoiceItem, so loading does not fire it.)Paidfires once for each invoice, after the game has run the invoice’s follow-up action. (It fires afterPayInvoicereturnstrue, after the invoice’sonPaidcallback.)Cancelledfires after an invoice is cancelled, but not when the game drops an overdue invoice on its own. (It fires afterCancelInvoiceremoved an invoice. The game’s due-date check (CheckDueDates) removes overdue invoices directly and never callsCancelInvoice.)- Read the details from the event, not from
All(). InPaidandCancelled, the invoice is already gone fromAll(), so useargs.Invoice. - Do not call
All()orGet()every frame. Each call makes a new snapshot for every invoice. Listen toIssued,PaidandCancelledinstead.
Limits
- A wrong argument to
Createthrows anArgumentException.debtormust not be empty.currencymust beOCorRM.amountmust be a whole number from 1 to 16,000,000.daysmust be from 0 to 36,500. (The amount limit isCash.MaxAmount.) Createreturnsfalse, and does nothing, when the game can’t take a new invoice right now. That happens when the game’s invoice controller, game clock or mail controller does not exist yet (for example on the main menu), and while a save is loading or being written. (The checks areInvoiceController.instance,TimeOfDayAzure.instanceandMailController.instancebeingnull(the game adds the invoice before it sends the mail, so the mail controller matters forCreateonly), andSaveGate.Busy.)Cancelreturnsfalsewhen the invoice does not exist, and also when the game has attached a follow-up action to it, as listed above.- If the player puts a cancelled bill in a payment machine afterwards, the payment fails and the machine says the player has not enough money, which is how the game behaves.
IsAvailableisfalsewhen the three events could not be set up.All,Get,CanPay,Create,CancelandFireSenderkeep working when it isfalse. See If something fails to set up.