OnPhoneDialTimeout
OnPhoneDialTimeout is called on the server when a player's phone stops ringing without being answered. It runs inside PhoneController.TimeOutDialing and lets you suppress the answering-machine message.
object OnPhoneDialTimeout(PhoneController activeCallTo, PhoneController phoneController, BasePlayer currentPlayer)Parameters
| Parameter | Type | Description |
|---|---|---|
activeCallTo | PhoneController | The PhoneController the caller is trying to reach; it holds the dialing state and its currentPlayer is who would pick up. |
phoneController | PhoneController | The PhoneController of the phone that is dialing out (the caller's phone). |
currentPlayer | BasePlayer | The player the ringing phone is assigned to, i.e. activeCallTo.currentPlayer. Can be null if the target phone lost its owner. |
Return value
Returning null lets the original code continue, so the answering message is played to the caller. Returning any non-null value stops the remainder of TimeOutDialing, so no answering message is sent and the call ends silently.
How it works
The hook fires in PhoneController.TimeOutDialing, which the game runs after a dialed phone has rung for the full timeout period without anyone picking up. At that point the answering message (the recorded greeting on the target phone) is about to be sent to the caller through ServerPlayAnsweringMessage. You get both ends of the attempt: phoneController is the dialing phone, activeCallTo is the target PhoneController, and currentPlayer is the player the target belongs to. All three can be inspected, and null checks are necessary because a phone may have been destroyed or its owner disconnected during the ring. Declaring a more specific type is not possible here since the parameters are already concrete classes. Return something non-null to skip the answering message entirely, which turns a missed call into a silent drop; return null to let the normal behavior run.
Example plugin: Silence missed-call greetings on a PvE server
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("Phone Timeout Control", "RustPluginGenerator", "1.0.0")]
[Description("Suppresses the answering-machine greeting on dial timeouts and notifies the caller.")]
public class PhoneTimeoutControl : RustPlugin
{
private const string PermKeepGreeting = "phonetimeoutcontrol.keepgreeting";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Suppress answering message on timeout")]
public bool SuppressGreeting { get; set; } = true;
[JsonProperty("Notify caller about the missed call")]
public bool NotifyCaller { get; set; } = true;
}
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>
{
["MissedCall"] = "Your call was not answered. The phone stopped ringing.",
["GreetingKept"] = "Your call timed out and the greeting played."
}, this);
}
private string Msg(string key, string userId = null, params object[] args) =>
string.Format(lang.GetMessage(key, this, userId), args);
private void Init()
{
permission.RegisterPermission(PermKeepGreeting, this);
}
private object OnPhoneDialTimeout(PhoneController activeCallTo, PhoneController phoneController, BasePlayer currentPlayer)
{
if (phoneController == null) return null;
BasePlayer caller = phoneController.currentPlayer;
if (caller == null || !caller.IsConnected) return null;
if (!config.SuppressGreeting) return null;
if (permission.UserHasPermission(caller.UserIDString, PermKeepGreeting)) return null;
if (config.NotifyCaller)
{
caller.ChatMessage(Msg("MissedCall", caller.UserIDString));
}
return true;
}
}
}The plugin watches for dial timeouts and decides whether the answering machine should play. A config flag turns the feature on, and a permission lets staff keep the vanilla greeting. It also counts timeouts per player and pushes a short chat note to the caller, so players know the target simply did not answer instead of hearing a recording. activeCallTo.currentPlayer is read defensively because the phone owner may be null or disconnected at timeout. Returning a non-null object blocks ServerPlayAnsweringMessage; returning null keeps vanilla behavior.
Common use cases
Serve a custom greeting instead of the recorded one
Block the default answering message and broadcast your own notice so every unanswered call is handled uniformly across the server.
End calls silently on roleplay servers
Skip the answering machine entirely so a missed call just stops ringing, which suits servers that treat voice messages as out of character.
Log unanswered dial attempts
Record who called whom at timeout for staff review of harassment reports, while still letting the normal greeting play.
Pitfalls
Owner may be gone
activeCallTo.currentPlayercan be null if the target disconnected or the phone was destroyed mid-ring; always null-check before reading player data.Returning a value cancels the greeting
Any non-null return short-circuits the rest of TimeOutDialing, including the play-answering-message call — return null whenever you want vanilla behavior.
The call is already closing
The timeout means the connection is being torn down; do not try to re-dial or keep the call alive from this hook, the call state is already finishing.
Build a plugin with OnPhoneDialTimeout
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 OnPhoneDialTimeout
Generate