OnFireworkStarted
OnFireworkStarted is called on the server right after a BaseFirework entity is lit and switches on its On/OnFire flags, before its exhaustion timer is scheduled. It marks the moment the rocket begins its upward flight.
void OnFireworkStarted(BaseFirework firework)Parameters
| Parameter | Type | Description |
|---|---|---|
firework | BaseFirework | The BaseFirework entity that just transitioned into its active flight state. Use it to read position, OwnerID, or to attach follow-up logic such as timers keyed to net.ID.Value. |
Return value
The return value is ignored. The original code continues and always schedules the exhaustion timer via Invoke(OnExhausted, activityLength), regardless of what the hook returns. Return nothing (or null) and rely on other hooks such as OnFireworkExhausted or OnFireworkDamage to alter behavior.
How it works
The hook fires inside BaseFirework.Begin, after the entity's flags are updated to On and OnFire (with a network update queued) and just before Invoke(OnExhausted, activityLength) schedules the end of the flight. Anything that puts a firework into its active phase runs through Begin, so this covers a player igniting a placed firework with a held ignition source as well as anything else that calls the same method on the server.
The only parameter is the firework entity itself. Read firework.net.ID.Value to correlate the start and the later exhaustion, firework.transform.position for the launch point, or firework.OwnerID to find the player who placed it. If you only care about fireworks (not every BaseFirework subclass), declaring BaseFirework is already as specific as it gets here; declaring anything narrower would never match.
Because the hook runs synchronously inside Begin, keep the body cheap: record state, start a timer.Once, or send an effect. Do not call Kill() on the firework here unless you deliberately want the scheduled exhaustion to fire against a dead entity.
Example plugin: Broadcast and track firework launches per player
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Firework Launch Announcer", "RustPluginGenerator", "1.0.0")]
[Description("Tracks firework launches per player and broadcasts permitted launches to the server.")]
public class FireworkLaunchAnnouncer : RustPlugin
{
private const string PermAnnounce = "fireworklaunchannouncer.announce";
private PluginConfig config;
private readonly Dictionary<ulong, int> launchesByPlayer = new Dictionary<ulong, int>();
private class PluginConfig
{
[JsonProperty("Broadcast launched fireworks to all players")]
public bool Broadcast { get; set; } = true;
[JsonProperty("Broadcast format ({0} = player name, {1} = absolute position)")]
public string BroadcastFormat { get; set; } = "{0} lit a firework at {1}";
}
private void Init()
{
permission.RegisterPermission(PermAnnounce, this);
}
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);
private void OnFireworkStarted(BaseFirework firework)
{
if (firework == null) return;
ulong ownerId = firework.OwnerID;
BasePlayer owner = ownerId != 0 ? BasePlayer.FindByID(ownerId) : null;
if (owner == null || !permission.UserHasPermission(owner.UserIDString, PermAnnounce)) return;
launchesByPlayer.TryGetValue(ownerId, out int count);
launchesByPlayer[ownerId] = count + 1;
if (!config.Broadcast) return;
Vector3 pos = firework.transform.position;
string coords = $"{Mathf.RoundToInt(pos.x)}, {Mathf.RoundToInt(pos.z)}";
Server.Broadcast(string.Format(config.BroadcastFormat, owner.displayName, coords));
}
private void Unload()
{
launchesByPlayer.Clear();
}
}
}The plugin keeps a small in-memory counter of how many fireworks each player has launched during the current server session and stores the launch time keyed by the firework's network ID. When OnFireworkStarted fires, it reads firework.OwnerID, resolves the player with BasePlayer.FindByID, and checks the fireworklaunchannouncer.announce permission. Authorized players get a broadcast to the whole server and a counter update. The in-memory dictionary is cleared in Unload so a reload starts fresh, which keeps the example free of disk I/O while still demonstrating the hook's natural data flow.
Common use cases
Zone-based restrictions
Cancel or counteract launches inside no-build zones by killing the firework in
OnFireworkStartedwhen its position falls within a monitored area, then informing the owner via chat.Event signaling
Use launched fireworks as a trigger for server events: start a countdown, spawn a supply drop nearby, or sound a siren for all connected players.
Statistics tracking
Log how many fireworks each player launches per wipe by incrementing a counter keyed on
OwnerIDand persisting it withInterface.Oxide.DataFileSystemon save.
Pitfalls
OwnerID is zero for non-player sources
Fireworks spawned by plugins or admin commands may carry
OwnerID0. Always guard againstBasePlayer.FindByID(0) == nullbefore using the player object.Killing here leaves a dangling invoke
The exhaustion timer is already scheduled at the time the hook runs, so destroying the entity does not cancel that invoke. Expect
OnFireworkExhaustedto still fire and code defensively there.Fires once per firework, not per volley
A multi-shot firework still invokes
Beginonce when lit. Do not design logic that assumes one hook call per visible burst; useOnFireworkExhaustedfor the flight completion.
Build a plugin with OnFireworkStarted
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 OnFireworkStarted
Generate