OnMlrsRocketFired
OnMlrsRocketFired is called on the server right after an MLRS successfully launches a single rocket and before the launcher moves on to its next rocket in the salvo.
void OnMlrsRocketFired(MLRS mLRS, ServerProjectile projectile)Parameters
| Parameter | Type | Description |
|---|---|---|
mLRS | MLRS | The MLRS launcher entity that fired the rocket. Use it for position checks, ownership (OwnerID), or to inspect the rocket container inside it. |
projectile | ServerProjectile | The ServerProjectile that was just spawned for this rocket. You can read and change its velocity, speed, gravity modifier, and position before it travels. |
Return value
Returning a value has no effect; Oxide ignores the return value for this hook, and the original method always continues to decrement nextRocketIndex after the hook returns.
How it works
This hook fires inside MLRS.FireNextRocket, after the game has created the rocket projectile, assigned its gravity modifier, and before it decrements nextRocketIndex. Because FireNextRocket is called once per rocket in a salvo, the hook fires once for every individual rocket launched, not once for the whole volley. The mLRS parameter gives you the launcher entity itself, useful for checking its position, OwnerID, or whether it is owned by a particular player or team. The projectile parameter is the live ServerProjectile that will fly toward the target; you can read its velocity, position, and gravity modifier, or adjust them to change the trajectory. Declaring mLRS as a more specific type will not narrow anything since MLRS is already the concrete type. Declaring projectile as ServerProjectile is required; there is no broader type that still receives the call. Do not call Puts or PrintWarning here because MLRS salvos fire many rockets quickly. Keep the handler cheap: read values, mutate the projectile, and return. The hook is ideal for logging, trajectory tweaks, announcing incoming rockets, or counting rockets per launcher.
Example plugin: Log and announce incoming MLRS rockets to the server
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Mlrs Rocket Alert", "RustPluginGenerator", "1.0.0")]
[Description("Notifies the server or subscribers when an MLRS fires each rocket in a salvo.")]
public class MlrsRocketAlert : RustPlugin
{
private const string PermSubscribe = "mlrsrocketalert.subscribe";
private PluginConfig config;
private readonly Dictionary<ulong, int> rocketsFired = new Dictionary<ulong, int>();
private class PluginConfig
{
[JsonProperty("Broadcast to all players")]
public bool BroadcastToAll { get; set; } = true;
[JsonProperty("Only announce once per salvo")]
public bool OncePerSalvo { get; set; } = false;
[JsonProperty("Seconds between salvo announcements")]
public float SalvoCooldown { get; set; } = 5f;
}
protected override void LoadDefaultConfig() => config = new PluginConfig();
protected override void LoadConfig()
{
base.LoadConfig();
try
{
config = Config.ReadObject<PluginConfig>();
if (config == null) throw new System.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>
{
["Broadcast"] = "An MLRS rocket is inbound from {0} ({1} fired).",
["Admin"] = "MLRS rocket fired from {0} by {1}. Speed {2:F1}, total {3}.",
["Subscribed"] = "Alerts enabled: /mlrsalert off to disable.",
["Unsubscribed"] = "Alerts disabled."
}, 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(PermSubscribe, this);
}
[ChatCommand("mlrsalert")]
private void CmdMlrsAlert(BasePlayer player, string command, string[] args)
{
if (player == null) return;
if (!permission.UserHasPermission(player.UserIDString, PermSubscribe))
{
SendReply(player, "You do not have permission to subscribe to MLRS alerts.");
return;
}
bool currently = permission.UserHasPermission(player.UserIDString, PermSubscribe + ".on");
if (currently)
{
permission.RevokeUserPermission(player.UserIDString, PermSubscribe + ".on");
SendReply(player, Msg("Unsubscribed", player.UserIDString));
}
else
{
permission.GrantUserPermission(player.UserIDString, PermSubscribe + ".on", this);
SendReply(player, Msg("Subscribed", player.UserIDString));
}
}
private void OnMlrsRocketFired(MLRS mLrs, ServerProjectile projectile)
{
if (mLrs == null || projectile == null || mLrs.IsDestroyed) return;
ulong launcherId = mLrs.net != null ? mLrs.net.ID.Value : 0UL;
int count;
rocketsFired.TryGetValue(launcherId, out count);
rocketsFired[launcherId] = ++count;
if (config.OncePerSalvo && count > 1) return;
Vector3 origin = mLrs.transform.position;
string ownerName = "unknown";
var owner = BasePlayer.FindByID(mLrs.OwnerID);
if (owner != null)
ownerName = owner.displayName;
string originText = $"{origin.x:F0},{origin.z:F0}";
float speed = projectile.initialVelocity.magnitude;
if (config.BroadcastToAll)
{
string broadcast = Msg("Broadcast", null, originText, count);
foreach (var player in BasePlayer.activePlayerList)
{
if (player == null || player.IsNpc) continue;
player.ChatMessage(broadcast);
}
return;
}
string detail = Msg("Admin", null, originText, ownerName, speed, count);
foreach (var player in BasePlayer.activePlayerList)
{
if (player == null || !player.IsAdmin) continue;
if (permission.UserHasPermission(player.UserIDString, PermSubscribe + ".on"))
player.ChatMessage(detail);
}
}
private void Unload()
{
rocketsFired.Clear();
}
}
}The plugin registers a chat and console command, /mlrsalert on|off, which toggles whether that admin receives MLRS notifications. When OnMlrsRocketFired fires, it looks up the launcher's owner and resolves a display name, reads the rocket's speed and position, and builds a summary string. If alerts are enabled for the calling admin's console toggle it prints the detail to chat, otherwise it sends a broadcast depending on config. A per-launcher counter (kept in a dictionary keyed by the MLRS entity's net ID) tracks how many rockets that launcher has fired since plugin load. Every hook parameter is null-checked before use, and the handler avoids heavy work because salvos fire rockets in quick succession.
Common use cases
Warn the server of incoming rocket salvos
Broadcast a short chat notice each time a rocket leaves the launcher, or only on the first rocket of a salvo, so players know an MLRS strike is inbound.
Adjust rocket trajectory
Read and modify the projectile's velocity, gravity modifier, or position in the hook to bend shots, shorten range, or limit maximum speed for balance purposes.
Attribute MLRS usage to the launcher owner
Combine
mLRS.OwnerIDwith a per-owner counter to track how many rockets each player fires, then feed those counts into a leaderboard or stats store.
Pitfalls
Fires once per rocket, not per salvo
A single
/firecommand launches multiple rockets, and this hook runs for each of them. If you want one notice per salvo, dedupe using the launcher's net ID and a short cooldown or tracknextRocketIndex-style sequencing yourself.Avoid heavy logging in the hook
MLRS salvos fire rockets within a single frame or across a handful of frames. Calling Puts, PrintWarning, or iterating BasePlayer.activePlayerList inside the handler can spam logs and stall the server during a full salvo.
ServerProjectile may be destroyed shortly after
Do not store the
projectilereference for later use. It dies on impact. Capture only simple values like position, velocity, or the launcher entity's net ID if you need data later.
Build a plugin with OnMlrsRocketFired
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 OnMlrsRocketFired
Generate