Skip to content
RustPluginGenerator

OnMlrsFiringEnded

OnMlrsFiringEnded is called when an MLRS finishes its firing sequence, right after the vehicle's internal MLRS.EndFiring method clears its broken/firing flags and sends a network update.

Signature
void OnMlrsFiringEnded(MLRS mLRS)

Parameters

Hook parameters
ParameterTypeDescription
mLRSMLRSThe MLRS vehicle entity whose firing sequence just ended. It is the same BaseEntity instance spawned in the world, so you can read its net.ID, position, OwnerID and mounted occupants.

Return value

The return value is ignored. The hook is patched with continue behavior and MLRS.EndFiring returns void, so returning null, true or any other value has no effect on the firing sequence.

How it works

The hook fires once per firing cycle, at the end of MLRS.EndFiring. That method runs when the launcher has finished launching its salvo and is transitioning back to a usable state; the injected call sits after the flags Reserved6 and Broken are cleared, timeSinceBroken is reset to zero and the flags are networked to clients. Because it fires after the state change, the vehicle you receive is already back in its idle configuration, so reading HasFlag(BaseEntity.Flags.Broken) or Flags.Reserved6 here returns the post-firing values.

The only argument is the MLRS entity itself. Use mLRS.net.ID.Value as a stable key for tracking, mLRS.transform.position for the launch site, mLRS.OwnerID to identify the placing player, and mLRS.GetMounted() if you need to know whether an operator is still seated. You do not need to narrow the parameter type; declaring MLRS is already specific, and declaring a broader type such as BaseEntity would not change which calls arrive because the game always passes an MLRS instance.

The hook is a good place for cooldown bookkeeping, admin logging of salvo completions, or map markers, since it fires once per sequence rather than per rocket.

Example plugin: Enforce a per-player MLRS salvo cooldown

MlrsSalvoCooldown.cs
using System;
using System.Collections.Generic;
using Newtonsoft.Json;

namespace Oxide.Plugins
{
    [Info("Mlrs Salvo Cooldown", "RustPluginGenerator", "1.0.0")]
    [Description("Tracks when a player's MLRS finishes a salvo and reports the next allowed launch time.")]
    public class MlrsSalvoCooldown : RustPlugin
    {
        private const string PermUse = "mlrssalvocooldown.use";

        private PluginConfig config;
        private readonly Dictionary<ulong, DateTime> lastSalvo = new Dictionary<ulong, DateTime>();

        private class PluginConfig
        {
            [JsonProperty("Salvo cooldown in seconds")]
            public int CooldownSeconds { get; set; } = 600;
        }

        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>
            {
                ["SalvoEnded"] = "Your MLRS salvo ended. Next salvo allowed in {0} seconds.",
                ["Ready"] = "Your MLRS is ready to fire.",
                ["OnCooldown"] = "Your MLRS is on cooldown for another {0} seconds.",
                ["NoPermission"] = "You do not have permission to use this command."
            }, 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 OnMlrsFiringEnded(MLRS mLRS)
        {
            if (mLRS == null) return;

            ulong ownerId = mLRS.OwnerID;
            if (ownerId == 0) return;

            lastSalvo[ownerId] = DateTime.UtcNow;

            var player = BasePlayer.FindAwakeOrSleeping(ownerId.ToString());
            if (player != null && player.IsConnected)
            {
                player.ChatMessage(Msg("SalvoEnded", player.UserIDString, config.CooldownSeconds));
            }
        }

        [ChatCommand("canfire")]
        private void CmdCanFire(BasePlayer player, string command, string[] args)
        {
            if (player == null) return;
            if (!permission.UserHasPermission(player.UserIDString, PermUse))
            {
                player.ChatMessage(Msg("NoPermission", player.UserIDString));
                return;
            }

            int remaining = GetRemainingSeconds(player.userID.Get());
            if (remaining <= 0)
            {
                player.ChatMessage(Msg("Ready", player.UserIDString));
                return;
            }

            player.ChatMessage(Msg("OnCooldown", player.UserIDString, remaining));
        }

        private int GetRemainingSeconds(ulong ownerId)
        {
            DateTime last;
            if (!lastSalvo.TryGetValue(ownerId, out last)) return 0;

            double elapsed = (DateTime.UtcNow - last).TotalSeconds;
            double left = config.CooldownSeconds - elapsed;
            return left > 0 ? (int)Math.Ceiling(left) : 0;
        }

        private void Unload()
        {
            lastSalvo.Clear();
        }
    }
}

The plugin records the time each player last finished an MLRS salvo, keyed by OwnerID. When the salvo ends, it stamps the current time and, if the owner is online, messages them how many seconds remain before the next allowed salvo. A canfire chat command checks the stored timestamp against the configured cooldown and tells the player whether they can launch again, including the remaining time. Data lives in memory only and is cleared on unload, which is enough for a soft advisory cooldown; combine it with a weapon or entity restriction elsewhere if you need hard enforcement. The config exposes the cooldown length in seconds.

Common use cases

  • Post-salvo admin audit

    Record owner, position and timestamp each time a salvo finishes and write it to a data file, giving staff a history of MLRS usage without hooking every rocket.

  • Cooldown or usage limits

    Track the last completion per owner or team and deny further launches (through a separate restriction hook) until the configured interval has passed.

  • Map and team notifications

    Broadcast a chat notice to the owning team when their launcher finishes firing, or drop a temporary marker at mLRS.transform.position.

Pitfalls

  • Fires after the state reset

    The call sits after Flags.Broken and Flags.Reserved6 are cleared, so checking those flags inside the hook will not tell you the launcher was just firing. Track state yourself if you need to know a sequence started.

  • OwnerID may be stale or zero

    If the launcher was placed via admin command or its building was destroyed, OwnerID can be 0 or point to a player who is offline. Resolve with BasePlayer.FindAwakeOrSleeping(ownerId.ToString()) before messaging.

  • One call per sequence, not per rocket

    Use the OnMlrsRocketFired family if you need a callback for each individual launch; this hook only marks the end of the whole salvo.

Build a plugin with OnMlrsFiringEnded

Describe what should happen and get a compiled plugin that uses this hook.

Prompt: Post-salvo admin audit using the OnMlrsFiringEnded hook, with a config file and a permission
Generate this plugin

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 OnMlrsFiringEnded

Generate