OnLiquidWeaponFiringStopped
OnLiquidWeaponFiringStopped is called on the server after a LiquidWeapon (flamethrower) finishes its firing sequence in LiquidWeapon.StopFiring, before control returns to the caller.
void OnLiquidWeaponFiringStopped(LiquidWeapon liquidWeapon)Parameters
| Parameter | Type | Description |
|---|---|---|
liquidWeapon | LiquidWeapon | The LiquidWeapon entity (flamethrower) that has just stopped firing. Use it to read its owner, position, mounted state and short prefab name. |
Return value
The original method returns void, and Oxide ignores whatever your hook returns, so return nothing. The game's StopFiring logic always completes regardless of your return value.
How it works
The hook fires inside LiquidWeapon.StopFiring on the server, immediately after the method has applied its firing-state changes and sent the network update. Any action that reaches StopFiring triggers it: a player releasing the fire button, running out of fuel, the weapon being unequipped or dropped, or the parent entity being destroyed.
The single parameter is the LiquidWeapon entity itself. From it you can read OwnerID, GetOwnerPlayer(), transform.position, ShortPrefabName and the mounted state of the holder. That is enough to attribute the stop event to a player, a position and a weapon type without extra lookups.
Declaring the parameter as LiquidWeapon (or a base type such as BaseEntity) keeps Oxide's dispatch working; a narrower type would simply skip calls where the argument does not match. This is Oxide hook dispatch, not patcher behavior.
The hook is informational: the method returns void, so any value you return is ignored and the game continues normally. It fires once per stop, not per frame, so it is safe for short-lived logic such as cooldown tracking or statistics, but it can still fire for NPC or server-spawned liquid weapons, so filter on OwnerID when you only care about players.
No state is exposed about how long the weapon fired or how much fuel was consumed, so record that separately in CanFireLiquidWeapon or OnLiquidWeaponFired if you need it.
Example plugin: Cooldown flamethrower users with a chat warning
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("LiquidWeaponCooldown", "RustPluginGenerator", "1.0.0")]
[Description("Enforces a per-player cooldown after a flamethrower stops firing")]
public class LiquidWeaponCooldown : RustPlugin
{
private const string PermShortCooldown = "liquidweaponcooldown.vip";
private PluginConfig config;
private readonly Dictionary<string, float> lastStop = new Dictionary<string, float>();
private Timer cleanupTimer;
private class PluginConfig
{
[JsonProperty("Default cooldown in seconds")]
public float DefaultCooldown = 3f;
[JsonProperty("VIP cooldown in seconds")]
public float VipCooldown = 1f;
}
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>
{
["Cooldown"] = "Flamethrower cooling down. Wait {0}s.",
["Ready"] = "Flamethrower ready."
}, 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(PermShortCooldown, this);
cleanupTimer = timer.Every(120f, Cleanup);
}
private void Unload()
{
cleanupTimer?.Destroy();
lastStop.Clear();
}
private void OnLiquidWeaponFiringStopped(LiquidWeapon liquidWeapon)
{
if (liquidWeapon == null) return;
BasePlayer player = liquidWeapon.GetOwnerPlayer();
if (player == null || player.IsNpc) return;
float cooldown = GetCooldown(player);
lastStop[player.UserIDString] = Time.realtimeSinceStartup;
if (player.IsConnected)
{
player.ChatMessage(Msg("Cooldown", player.UserIDString, cooldown.ToString("0.#")));
}
}
private object CanFireLiquidWeapon(LiquidWeapon liquidWeapon, BasePlayer player)
{
if (liquidWeapon == null || player == null) return null;
float stoppedAt;
if (!lastStop.TryGetValue(player.UserIDString, out stoppedAt)) return null;
float cooldown = GetCooldown(player);
float elapsed = Time.realtimeSinceStartup - stoppedAt;
if (elapsed >= cooldown) return null;
player.ChatMessage(Msg("Cooldown", player.UserIDString, (cooldown - elapsed).ToString("0.#")));
return false;
}
private float GetCooldown(BasePlayer player)
{
return permission.UserHasPermission(player.UserIDString, PermShortCooldown)
? Mathf.Max(0f, config.VipCooldown)
: Mathf.Max(0f, config.DefaultCooldown);
}
private void Cleanup()
{
float now = Time.realtimeSinceStartup;
List<string> stale = null;
foreach (KeyValuePair<string, float> entry in lastStop)
{
if (now - entry.Value > 300f)
{
if (stale == null) stale = new List<string>();
stale.Add(entry.Key);
}
}
if (stale == null) return;
foreach (string id in stale) lastStop.Remove(id);
}
}
}The plugin puts a configurable cooldown on flamethrowers per player. OnLiquidWeaponFiringStopped looks up the owner of the stopped LiquidWeapon, records Time.realtimeSinceStartup in a dictionary, and sends a localized chat message telling the player when they can fire again. CanFireLiquidWeapon checks the same dictionary and returns false while the cooldown is active, which prevents the next firing attempt. The dictionary is keyed by the player's userID string so it survives reconnects within the session. Unload clears the timers and the dictionary, and permissions (liquidweaponcooldown.vip) allow a shorter cooldown for selected groups. All player-facing text goes through the language file, so server owners can translate it.
Common use cases
Per-player flamethrower cooldowns
Record the stop time and reject the next
CanFireLiquidWeaponattempt until a configured cooldown elapses. This curbs sustained flame spam on PvP servers without disabling the weapon.Usage statistics
Accumulate a per-player counter and persist it with
Interface.Oxide.DataFileSystemon a timer or onOnServerSave. Compare counts to find players who lean on flamethrowers in raids.Event logging for admins
Write a line with the owner's name, weapon prefab and world position to a data file or console output so staff can review suspicious flamethrower activity around a base.
Pitfalls
NPC and server liquid weapons also fire this hook
OwnerIDcan be zero for weapons spawned by the server. CheckGetOwnerPlayer()for null before treating the event as player-driven.Not every stop is a release of the fire button
Running out of fuel, unequipping and destroying the weapon all reach
StopFiring. If you only want manual releases, compare ammo or inventory state before and after rather than assuming intent.The hook cannot cancel the stop
The return value is discarded, so you cannot keep the weapon firing from here. Prevent firing earlier through
CanFireLiquidWeaponinstead.
Build a plugin with OnLiquidWeaponFiringStopped
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 OnLiquidWeaponFiringStopped
Generate