Phones and calls
A phone line is one phone in the scene. PhoneLines lists them, rings them, starts calls, and answers or turns down rings.
PhoneLines rings, calls and events
Use it to list the phones in the scene, ring one, start a call from one, answer or decline a ring, and listen for call events.
public static class PhoneLines
{
public static List<PhoneLineInfo> All();
public static bool Ring(string phoneId, string number, int hangupSeconds, Action<bool> answered);
public static bool StartCall(string phoneId, string number);
public static bool IsBusy(string phoneId);
public static bool IsRinging(string phoneId);
public static string RingingNumber(string phoneId);
public static bool Answer(string phoneId);
public static bool Decline(string phoneId);
public static event Action<PhoneCallArgs> CallStarted;
public static event Action<PhoneCallArgs> CallEnded;
public static event Action<PhoneCallArgs> Ringing;
public static bool IsAvailable { get; }
}
| Method | Returns | What it does |
|---|---|---|
All() | List<PhoneLineInfo> | Every phone that is switched on in the scene you are in. |
Ring(phoneId, number, hangupSeconds, answered) | bool | Makes a phone ring, as if the number were calling. Returns true when the phone rings. |
StartCall(phoneId, number) | bool | Starts a call from a phone, as if the player had dialled the number. Returns true when the call started. |
IsBusy(phoneId) | bool | true when the phone cannot take a new ring. |
IsRinging(phoneId) | bool | true when the phone is ringing and nobody has answered. |
RingingNumber(phoneId) | string | The digits of the number that is ringing. null when it is not ringing. |
Answer(phoneId) | bool | Picks up a ringing phone. Returns true when the ring is gone. |
Decline(phoneId) | bool | Turns a ring down without answering. Returns true when it worked. |
| Property | Type | What it means |
|---|---|---|
IsAvailable | bool | false when the phone events could not be set up. |
| Event | Gives you | When it fires |
|---|---|---|
CallStarted | PhoneCallArgs: the phone’s id and the number. | A call has just started on a phone. |
CallEnded | PhoneCallArgs: the phone’s id and the number. | A call has just ended on a phone. |
Ringing | PhoneCallArgs: the phone’s id and the number. | A phone has just started to ring. |
PhoneLineInfo a snapshot of one phone
PhoneLines.All() gives you one of these for each phone that is switched on. Its Id is the phoneId you pass to the other PhoneLines calls. (It is built from the game’s Phone object.)
public sealed class PhoneLineInfo
{
public string Id { get; }
public PhoneNetwork Network { get; }
public bool Busy { get; }
}
| Property | Type | What it means |
|---|---|---|
Id | string | The phone’s id: its save id, or its place in the scene if it has none. |
Network | PhoneNetwork | Which phone network the phone is on. The same values as in Phones. |
Busy | bool | The same answer as IsBusy. |
PhoneCallArgs what the three events tell you
CallStarted, CallEnded and Ringing hand you one of these. Id says which phone it was, and Number is the number that was dialled or is ringing.
public sealed class PhoneCallArgs
{
public string Id { get; }
public string Number { get; }
}
| Property | Type | What it means |
|---|---|---|
Id | string | The id of the phone. |
Number | string | The digits of the number that was dialled or is ringing. "" if there is none. |
Things to know
All()only lists the phones that are switched on in the scene you are in. A phone that is switched off is skipped. (It usesFindObjectsByType, so an inactive phone is skipped. The id is the object’s save GUID (see the glossary), or its scene path when it has none.)Ringmakes the phone ring, as if the number were calling.- Your
answeredcode runs once the ring ends. It runs withtrueif the player picks up (with the key in the game or withAnswer). It runs withfalsewhen the ring times out orDeclineturns it down.hangupSecondscounts in-game seconds, not real seconds. (It is counted onTimeOfDayAzure.Timer.) StartCallstarts a call from the phone, as if the player had dialled the number. It starts the phone’s conversation for that number.IsBusyistruewhen the game menu is open, a call is going on, or the phone is ringing. These are the three things the game checks before it refuses a ring. It isfalsefor an unknown id.- The menu check applies only to
IsBusy.StartCallchecks whether a conversation is running, as the game’s talk does, but not the menu, because the game does not check the menu there either. IsRingingistruewhen the phone has a call coming in that nobody has answered or turned down. It isfalsefor an unknown id.RingingNumbergives the digits of the caller, written the wayPhones.All()writes them. It givesnullwhen the phone is not ringing or the id is unknown.Answerpicks up a ringing phone. It returnstruewhen the ring is gone.Declineturns a ring down without answering. The ring stops, and youranswered(false)code runs, the same as on a timeout. Otherwise it returnstrue. (It callsPhone.ExpireReceivedCall.)- Calls and rings run the game’s own signals, and quests can react to them. Ringing a phone that a quest uses can change that quest. (
Phone.onCallStarted,onCallEnded,onReceivingCallandonReceivedCallAnswetedfire.)
Limits
Ringreturnsfalsewhen the phone is not found, the number is not in the phone book, a save is loading or saving, or the game refuses. (It calls the game’sPhone.ReceiveCall. It learns about a refusal from the game’s own not-answered callback, which the game calls at once when it refuses.)- The game refuses when the game menu is open, a call is going on, or the phone is already ringing. When it refuses, your
answeredcode is not called. Ringthrows anArgumentNullExceptionifansweredisnull, the same asLocks.StartLockpickdoes.- Your
answeredcode is lost when the game is saved and loaded. A ring that was still going when the player saved still exists after the load, andAnswerandDeclinestill work on it, but your code never runs for it. (The ring state (incomingCall,hangupTimer) is anfsPropertyonPhone, but the callback fields are delegates, and the game’s save system (FullSerializer) skips delegate fields.) StartCallreturnsfalsewhen the phone is not found, the number is not in the phone book, a save is loading or saving, a call is going on or ringing, a conversation is already running, or the phone is missing the parts it needs to talk. (It calls the game’sPhone.StartCall. The phone must have its conversation trigger (conversationTrigger) and talk component (interactableTalk), or the game would end the call at once.)- The game’s talk can still turn a call down after
StartCall. That happens when the player is in the air, a contest is running, the player is waiting, the talk is switched off, or the talk’s object is not active. Then the framework undoes the call: the background static stops,CallStartedandCallEndeddo not fire, andStartCallreturnsfalse. - The player’s own calls are not undone like that. A call the player dials, or answers from a ring, goes through the same game method without the undo. If the game turns one of them down in its talk check, the background static keeps playing and the call stays marked as active until the next call.
Answerreturnsfalse, and leaves the phone alone, when the phone is not found, a save is loading or saving, the phone is not ringing, the phone has no hang-up timer, the phone has no talk parts, a call is going on, the game menu is open, or a conversation is running. (It calls the game’sPhone.Interact, which runs the game’s answer path when a ring is pending.Phone.UseandExpireReceivedCallboth use the hang-up timer (hangupTimer) without a null check, so a missing timer makesAnswerrefuse.)Answerdoes the game’s answer steps before the talk can turn the call down. The ring’s enter signal, the “answered” signal, the ringtone stop, the pickup sound and youranswered(true)code have all run by then. If the talk then refuses the call, those steps have already happened and the ring is gone.Answerstill returnstrue, because the ring is gone either way. (The signals arePhone.onReceivedCallAnswetedand the enter relay.)Declinereturnsfalsewhen the phone is not found, a save is loading or saving, the phone is not ringing, or its hang-up timer is missing.- Every call that changes a phone returns
falsewhile a save is loading or saving. (It checksSaveData.Busy.)