OnPhoneDialFail
OnPhoneDialFail is called when a telephone call fails to connect, right before the game resets the phone to idle and tells the client why the dial failed.
object OnPhoneDialFail(PhoneController phoneController, Telephone.DialFailReason reason, BasePlayer currentPlayer)Parameters
| Parameter | Type | Description |
|---|---|---|
phoneController | PhoneController | The PhoneController of the telephone handset that attempted the call. Use it to reach the owning entity via phoneController.baseEntity and to inspect activeCallTo or the dialed number. |
reason | Telephone.DialFailReason | A Telephone.DialFailReason value explaining why the call could not be placed, such as no answer, busy, or a blocked/invalid number. Compare it against the enum members to branch on the cause. |
currentPlayer | BasePlayer | The BasePlayer holding the phone when the dial failed. May be null if the controller has no player owner, so null-check it before using player APIs. |
Return value
Returning null lets the game proceed: the phone is set to Idle, the client is told the dial failed with the given reason, the active call is cleared, and timeouts are cancelled. Returning any non-null value skips that entire block, so the phone stays in its current call state and the client receives no failure RPC.
How it works
This hook fires inside PhoneController.OnDialFailed, which the game runs when a dial attempt cannot be completed, for example an unanswered call, a busy line, or a rejected number. It is the single place where a failed call is handled, so it runs once per failed dial.
The phoneController parameter is the controller instance and gives access to baseEntity and activeCallTo. reason is a Telephone.DialFailReason you can compare against the enum members to distinguish causes. currentPlayer is the player who placed the call; it can be null, so check it before reading player data or sending messages.
The hook is dispatched normally, so declaring currentPlayer as a more specific type only narrows calls where the argument is that type. Since the argument is a plain BasePlayer, keep the declared type as-is unless you intentionally want to skip non-matching owners. Return a value to suppress the default failure handling. Because the hook fires rarely, it is safe to log or notify here, but avoid expensive work that could stall the network thread.
Example plugin: Log and notify players when a phone call fails
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Phone Dial Fail Notifier", "RustPluginGenerator", "1.0.0")]
[Description("Sends a localized chat message to a player when their telephone call fails to connect")]
public class PhoneDialFailNotifier : RustPlugin
{
private PluginConfig config;
public class PluginConfig
{
[JsonProperty("Notify the caller on failure")]
public bool NotifyCaller { get; set; } = true;
[JsonProperty("Prefix")]
public string Prefix { get; set; } = "[Phone]";
}
protected override void LoadDefaultConfig() => config = new PluginConfig();
protected override void LoadConfig()
{
base.LoadConfig();
try
{
config = Config.ReadObject<PluginConfig>();
if (config == null) throw new Exception();
}
catch
{
PrintWarning("Configuration file is invalid, using defaults");
LoadDefaultConfig();
}
SaveConfig();
}
protected override void SaveConfig() => Config.WriteObject(config);
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["Fail.NoAnswer"] = "The call went unanswered.",
["Fail.Busy"] = "The line is busy.",
["Fail.Blocked"] = "That number cannot be reached.",
["Fail.Generic"] = "The call failed to connect ({0}).",
["Reply"] = "{0} {1}"
}, this);
}
private string Msg(string key, string userId = null, params object[] args) =>
string.Format(lang.GetMessage(key, this, userId), args);
private object OnPhoneDialFail(PhoneController phoneController, Telephone.DialFailReason reason, BasePlayer currentPlayer)
{
if (!config.NotifyCaller || currentPlayer == null) return null;
string text;
switch (reason.ToString())
{
case "NoAnswer":
case "TimeOut":
text = Msg("Fail.NoAnswer", currentPlayer.UserIDString);
break;
case "Busy":
text = Msg("Fail.Busy", currentPlayer.UserIDString);
break;
case "Blocked":
case "InvalidNumber":
text = Msg("Fail.Blocked", currentPlayer.UserIDString);
break;
default:
text = Msg("Fail.Generic", currentPlayer.UserIDString, reason);
break;
}
currentPlayer.ChatMessage(Msg("Reply", currentPlayer.UserIDString, config.Prefix, text));
return null;
}
}
}The plugin listens to OnPhoneDialFail and, when the hook fires, builds a short message from the Telephone.DialFailReason value using a switch statement and localized strings. It checks currentPlayer != null and the NotifyCaller config option before sending the message. The message is prefixed with the configurable Prefix and sent only to the caller via ChatMessage. The hook always returns null so the game continues its normal failure handling; the plugin only adds context on top of the vanilla behavior.
Common use cases
Explain why a call failed
Send the caller a localized chat message that maps the dial fail reason to plain language, such as busy or unreachable.
Log phone activity for admins
Write failed dial attempts to the data folder with the player name, controller ID and reason so admins can review abuse.
Custom rate limiting messages
When your own dial-tracking logic rejects a call and forces a failure, use this hook to tell the player the specific limit they hit.
Pitfalls
Returning non-null suppresses reset
Any non-null return from the hook skips the phone reset and the client failure RPC, leaving the phone stuck in its call state. Only return a value if you deliberately take over recovery.
currentPlayer can be null
Controllers without an owning player hand back null for
currentPlayer. Always guard before reading UserIDString or sending chat.Do not assume every failure is player-driven
The dial can fail for reasons unrelated to the caller's intent, such as line state changes. Branch on
reasonrather than assuming a specific cause.
Build a plugin with OnPhoneDialFail
Describe what should happen and get a compiled plugin that uses this hook.
Edit the prompt on the next screen. 2 free plugins a month, no card.
Last updated Oct 26, 2026. Found a mistake? Email support@rustplugingenerator.com.
Build a plugin with OnPhoneDialFail
Generate