Skip to content
RustPluginGenerator

OnFireworkExhausted

OnFireworkExhausted is called when a lit firework finishes burning, right after its fuse timer elapses and before the entity is scheduled for cleanup.

Signature
void OnFireworkExhausted(BaseFirework firework)

Parameters

Hook parameters
ParameterTypeDescription
fireworkBaseFireworkThe BaseFirework entity that just ran out of fuse time. It is still spawned at this point, but its flags are already cleared and it is about to be queued for cleanup.

Return value

The return value is ignored. The original method returns void and continues normally, so the cleanup invoke and active-list removal always run regardless of what you return.

How it works

The hook fires inside BaseFirework.OnExhausted, after the game has switched off the OnFire and On flags, sent a flag network update and disabled global broadcast. It runs before the cleanup invoke and before the firework is removed from the internal active-firework list, so firework is still valid but no longer burning. Use the reference for positional effects, tracking who launched which firework, or awarding something to the owner. firework.OwnerID identifies the player who lit it, and firework.net.ID.Value is a stable identifier for that entity instance. Because the parameter is typed BaseFirework, Oxide only dispatches this hook for actual firework entities, so declaring the type more narrowly gains nothing. The hook gives you no return value control. Do not call Kill() on the firework from inside the hook unless you intend to shorten the normal cleanup path; the game will handle removal itself moments later.

Example plugin: Announce and reward the player who set off a firework

FireworkExhaustedReward.cs
using UnityEngine;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("Firework Exhausted Reward", "RustPluginGenerator", "1.0.0")]
    [Description("Rewards the player who launched a firework once it burns out, with a per-player cooldown.")]
    public class FireworkExhaustedReward : RustPlugin
    {
        private const string PermUse = "fireworkexhaustedreward.use";

        private PluginConfig config;
        private readonly Dictionary<ulong, float> lastReward = new Dictionary<ulong, float>();

        private class PluginConfig
        {
            [JsonProperty("Require permission")]
            public bool RequirePermission { get; set; } = false;

            [JsonProperty("Reward item shortname")]
            public string RewardItem { get; set; } = "scrap";

            [JsonProperty("Reward amount")]
            public int RewardAmount { get; set; } = 5;

            [JsonProperty("Cooldown seconds per player")]
            public float CooldownSeconds { get; set; } = 30f;

            [JsonProperty("Max distance from firework to reward")]
            public float MaxDistance { get; set; } = 50f;
        }

        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>
            {
                ["Reward"] = "Your firework burned out. Here is {0} x{1}.",
                ["NoRoom"] = "Your firework burned out, but there was no room for {0} x{1}."
            }, this);
        }

        private string Msg(string key, string userId = null, params object[] args)
        {
            return string.Format(lang.GetMessage(key, this, userId), args);
        }

        private void Init()
        {
            permission.RegisterPermission(PermUse, this);
        }

        private void OnFireworkExhausted(BaseFirework firework)
        {
            if (firework == null || firework.OwnerID == 0 || config.RewardAmount <= 0)
                return;

            var player = BasePlayer.FindByID(firework.OwnerID);
            if (player == null || !player.IsConnected || player.IsDead())
                return;

            if (config.RequirePermission && !permission.UserHasPermission(player.UserIDString, PermUse))
                return;

            float now = UnityEngine.Time.realtimeSinceStartup;
            float last;
            if (lastReward.TryGetValue(player.userID.Get(), out last) && now - last < config.CooldownSeconds)
                return;

            if (UnityEngine.Vector3.Distance(player.transform.position, firework.transform.position) > config.MaxDistance)
                return;

            var definition = ItemManager.FindItemDefinition(config.RewardItem);
            if (definition == null)
                return;

            lastReward[player.userID.Get()] = now;

            var item = ItemManager.CreateByName(config.RewardItem, config.RewardAmount);
            if (item == null)
                return;

            if (!player.inventory.GiveItem(item))
            {
                item.Remove();
                player.ChatMessage(Msg("NoRoom", player.UserIDString, definition.displayName.english, config.RewardAmount));
                return;
            }

            player.ChatMessage(Msg("Reward", player.UserIDString, definition.displayName.english, config.RewardAmount));
        }

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

The plugin rewards whoever lit a firework once it burns out. OnFireworkExhausted receives the BaseFirework, resolves the owner through OwnerID and BasePlayer.FindByID, and checks the config flag before doing anything. If the owner is online and near the firework position, it grants the configured item amount through inventory.GiveItem and sends a chat line built from the language file with the player name and firework position. A short cooldown per player id prevents chained firework racks from flooding inventory and chat. Config exposes the reward shortname, amount and cooldown in seconds; the cooldown map is cleared in Unload.

Common use cases

  • Reward firework displays

    Grant scrap or a small item to the player who launched the firework as a light server event incentive.

  • Log and count launches

    Record which player used fireworks and how many, then print a server-wide summary of active display areas at the end of an event.

  • Trigger end-of-display effects

    Run a sound or particle effect at the firework position once it burns out to close out a coordinated show.

Pitfalls

  • OwnerID is zero for admin-spawned fireworks

    Fireworks placed through console or by an admin with no player initiator have OwnerID 0, so FindByID returns null. Null-check before giving rewards or sending messages.

  • The entity is not destroyed yet

    The cleanup invoke and active-list removal happen after the hook, so the firework still exists. Do not rely on IsDestroyed being true and do not remove it yourself unless you want to shorten the display.

  • Racks fire many hooks quickly

    A player can light dozens of fireworks in seconds. Without a per-player cooldown, rewards and chat messages will stack up; throttle by OwnerID instead of printing on every call.

Build a plugin with OnFireworkExhausted

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

Prompt: Reward firework displays using the OnFireworkExhausted 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 OnFireworkExhausted

Generate