OnMlrsFired
OnMlrsFired is called when a player launches a salvo from an MLRS vehicle, after the rocket firing sequence has been scheduled. It receives the MLRS entity and the player who fired it.
void OnMlrsFired(MLRS mlrs, BasePlayer owner)Parameters
| Parameter | Type | Description |
|---|---|---|
mlrs | MLRS | The MLRS entity that was fired. Use it to read its position, OwnerID, net.ID or to query nearby entities around the launcher. |
owner | BasePlayer | The BasePlayer that launched the salvo. May be null in edge cases, so always null-check before reading UserIDString or team data. |
Return value
The hook's return value is ignored. Interface.CallHook is called for its side effects only and MLRS.Fire continues its normal sequence regardless of what your plugin returns.
How it works
The hook fires inside MLRS.Fire, right after the launcher stores the firing player and schedules FireNextRocket to run every 0.5 seconds for the remaining rockets. That means it runs once per salvo launch, not once per rocket, and it fires before the first rocket actually leaves a tube.
Use mlrs to identify the launcher: net.ID.Value, transform.position or OwnerID. Use owner to attribute the launch to a player, their team (currentTeam) or their permission group. The owner argument is a BasePlayer; declaring it as something more specific does not help here, but declaring it more narrowly than the game passes would only affect dispatch if a different type were supplied. In practice both arguments are always the expected types, so you can rely on the signature.
Because the hook runs once per salvo, it is a good place to announce MLRS activity, gate player usage via permissions, log launches for admin review, or start a short notice timer. It is not the place to react to individual rockets, which fire separately. The hook is cheap to handle and safe to use for player-facing messaging.
Example plugin: Announce and rate-limit MLRS salvos
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Mlrs Salvo Announcer", "RustPluginGenerator", "1.0.0")]
[Description("Announces MLRS salvos in chat and applies a per-player cooldown")]
public class MlrsSalvoAnnouncer : RustPlugin
{
private const string PermUse = "mlrssalvoannouncer.use";
private PluginConfig config;
private readonly Dictionary<ulong, double> lastLaunch = new Dictionary<ulong, double>();
private class PluginConfig
{
[JsonProperty("Announce salvos in chat")]
public bool Announce { get; set; } = true;
[JsonProperty("Cooldown seconds between salvos")]
public float CooldownSeconds { get; set; } = 60f;
[JsonProperty("Require permission to fire")]
public bool RequirePermission { get; set; } = false;
}
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>
{
["Announce"] = "{0} launched an MLRS salvo from {1}",
["NoPermission"] = "You do not have permission to fire the MLRS.",
["Cooldown"] = "Please wait {0} seconds before firing the MLRS again."
}, 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(PermUse, this);
}
private void OnMlrsFired(MLRS mlrs, BasePlayer owner)
{
if (mlrs == null || owner == null) return;
if (config.RequirePermission && !permission.UserHasPermission(owner.UserIDString, PermUse))
{
owner.ChatMessage(Msg("NoPermission", owner.UserIDString));
return;
}
double now = Time.realtimeSinceStartup;
double last;
if (lastLaunch.TryGetValue(owner.userID, out last))
{
double remaining = config.CooldownSeconds - (now - last);
if (remaining > 0d)
{
owner.ChatMessage(Msg("Cooldown", owner.UserIDString, Math.Ceiling(remaining)));
return;
}
}
lastLaunch[owner.userID] = now;
if (!config.Announce) return;
Vector3 pos = mlrs.transform.position;
string grid = FormatGrid(pos);
Server.Broadcast(Msg("Announce", null, owner.displayName, grid));
}
private static string FormatGrid(Vector3 pos)
{
int x = Mathf.FloorToInt((pos.x + 1024f) / 146.3f);
int z = Mathf.FloorToInt((pos.z + 1024f) / 146.3f);
return string.Concat((char)('A' + Mathf.Clamp(x, 0, 25)), Mathf.Clamp(z, 0, 99).ToString());
}
private void Unload()
{
lastLaunch.Clear();
}
}
}The plugin listens for OnMlrsFired, null-checks both arguments, and enforces a per-player cooldown stored in a Dictionary<ulong, double> keyed against Time.realtimeSinceStartup. A configurable cooldown and message let admins tune noise. When a launch is accepted it broadcasts a localized message with the player's display name and the launcher's map position, then records the timestamp. A CanUseMlrs permission can be required if enabled. The plugin uses no timers and no persistent data, so Unload only clears the dictionary. This gives admins visibility into large-scale MLRS use without polling or external logging.
Common use cases
Broadcast MLRS activity to the server
Send a chat message naming the launcher and the grid reference so players can react to incoming salvos.
Restrict who may fire MLRS
Check
permission.UserHasPermission(owner.UserIDString, "mlrssalvoannouncer.use")and warn or kick players who launch without the permission.Audit large-scale MLRS use
Record the launcher, timestamp and coordinates in oxide data so admins can review coordinated attacks after the fact.
Pitfalls
Fires once per salvo, not per rocket
If you need per-projectile reactions, use
OnMlrsRocketFiredorOnMlrsFireinstead.OnMlrsFiredfires a single time when the sequence is scheduled.The salvo has not landed yet
The hook runs immediately after
InvokeRepeatingis set up, so the first rocket is still in its tube. Do not assume any damage or impact has happened when the hook fires.Null owner on unusual paths
MLRS.Fireaccepts an owner argument that can be null in edge cases (for example, scripted launches). Always guard before readingUserIDStringor sending a chat message.
Build a plugin with OnMlrsFired
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 OnMlrsFired
Generate