Skip to content
RustPluginGenerator

OnBoatGroupSpawned

OnBoatGroupSpawned is called after BoatGroupSpawner.SpawnBoatGroup has finished creating a group of RHIBs. It fires once per spawned group, after the boats exist in the world.

Signature
void OnBoatGroupSpawned(BoatGroupSpawner boatGroupSpawner, UnityEngine.Vector2 position, UnityEngine.Quaternion quaternion, HashSet<RHIB> list, bool flag, bool spawnsPT)

Parameters

Hook parameters
ParameterTypeDescription
boatGroupSpawnerBoatGroupSpawnerThe BoatGroupSpawner component that produced the group. Use it to read its transform, its protection area settings or to compare against a known spawner reference.
positionUnityEngine.Vector2The 2D (X/Z) world position the group was spawned at. RHIBs use sea level height, so a Vector2 is enough; convert with new Vector3(position.x, 0f, position.y) when you need a world point.
quaternionUnityEngine.QuaternionThe rotation applied to the spawned boats. Useful when you want to place a marker or effect aligned with the group's facing direction.
listHashSet<RHIB>The set of RHIB entities created for this group. Can be empty if spawning failed; iterate it to inspect, tag, modify or remove individual boats.
flagboolA boolean passed through from the spawner. It reflects the spawner's internal state at the time of the call rather than anything you control through this hook.
spawnsPTboolA boolean indicating whether this group spawns the patrol boat variant. When true, the group is intended for the larger naval patrol behavior rather than plain RHIBs.

Return value

This hook is fired with a continue injection, so the return value is ignored entirely. Whether you return null or any other value has no effect on BoatGroupSpawner.SpawnBoatGroup; the original code path always proceeds as if the hook had not run.

How it works

This hook fires at the very end of BoatGroupSpawner.SpawnBoatGroup, after the spawner has moved, protected and configured the boats it created. That means every RHIB in list is already spawned and positioned, so you can safely read and change their state. The hook is raised for each group, not for each boat.

The list parameter is the most useful: iterate it to write to each RHIB's metadata, apply skins, buff health, attach custom behavior, or kill the whole group. position and quaternion give you the group origin on the water plane, which is handy for broadcasting a chat warning, playing an effect, or recording a spawn point. spawnsPT lets you tell patrol-boat groups apart from regular ones if you only want to act on one kind. boatGroupSpawner lets you read or compare the owning component.

Oxide dispatches the hook by parameter type, so you can narrow the list element type only if you keep the declared signature intact. Narrowing boatGroupSpawner to a subclass would skip calls whenever the runtime instance is a different type, so keep it as BoatGroupSpawner unless you know the server only uses one subclass. The hook runs on the main thread during the spawner's own tick, so avoid heavy work; schedule delayed actions with timer.Once.

Example plugin: Announce and tag new naval boat groups

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

namespace Oxide.Plugins
{
    [Info("BoatGroupAnnouncer", "RustPluginGenerator", "1.0.0")]
    [Description("Announces new naval boat groups and applies a server skin and health bonus to spawned RHIBs")]
    public class BoatGroupAnnouncer : RustPlugin
    {
        private const string PermSeeCount = "boatgroupannouncer.seecount";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Broadcast to chat")]
            public bool BroadcastToChat = true;

            [JsonProperty("Boat skin id")]
            public ulong BoatSkin = 0UL;

            [JsonProperty("Boat health multiplier")]
            public float HealthMultiplier = 1.5f;
        }

        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>
            {
                ["Heard"] = "A naval boat group has appeared near {0}.",
                ["HeardCount"] = "A naval boat group of {0} boats has appeared near {1}.",
                ["Count"] = "Spawned {0} RHIB(s) at {1}."
            }, 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(PermSeeCount, this);
        }

        private void OnBoatGroupSpawned(BoatGroupSpawner boatGroupSpawner, Vector2 position, Quaternion quaternion, HashSet<RHIB> list, bool flag, bool spawnsPT)
        {
            if (list == null || list.Count == 0) return;

            Vector3 worldPos = new Vector3(position.x, 0f, position.y);
            string location = $"({Mathf.RoundToInt(worldPos.x)}, {Mathf.RoundToInt(worldPos.z)})";

            foreach (RHIB boat in list)
            {
                if (boat == null || boat.IsDestroyed) continue;
                if (config.BoatSkin != 0UL) boat.skinID = config.BoatSkin;
                boat.InitializeHealth(boat.MaxHealth() * config.HealthMultiplier, boat.MaxHealth() * config.HealthMultiplier);
                boat.SendNetworkUpdate();
            }

            if (config.BroadcastToChat)
            {
                foreach (BasePlayer player in BasePlayer.activePlayerList)
                {
                    if (player == null || !player.IsConnected) continue;
                    string text = permission.UserHasPermission(player.UserIDString, PermSeeCount)
                        ? Msg("HeardCount", player.UserIDString, list.Count, location)
                        : Msg("Heard", player.UserIDString, location);
                    player.ChatMessage(text);
                }
            }

            Puts(Msg("Count", null, list.Count, location));
        }
    }
}

The plugin listens for OnBoatGroupSpawned, converts the 2D spawn position into a world point at sea level, and broadcasts a localized chat notice to every connected player. It then walks the spawned RHIB set and applies a skin, a small health boost and a custom name so admins can tell dynamic naval groups apart from manually placed boats. A permission gate limits the feature to players who should see the detailed count, while the config exposes the health multiplier and the skin id so server owners can tune them without recompiling. Timer references are kept so Unload can clean up any pending work.

Common use cases

  • Warn players about new naval groups

    Broadcast a chat message or play an effect at the spawn position so coastal players know a new group of RHIBs has appeared nearby.

  • Buff or skin spawned RHIBs

    Iterate the spawned set and adjust health, apply a server skin or rename each boat to make AI-driven groups visually distinct from player-owned boats.

  • Cap or cancel crowded naval spawns

    Count existing RHIBs on the map and kill the new group immediately if the server is over a configured limit.

Pitfalls

  • Fires per group, not per boat

    Do not assume one call equals one boat. A single invocation can deliver several RHIBs in list, and the set can be empty if the spawner failed to create any.

  • Returning a value does nothing

    This injection ignores the return value, so you cannot stop the spawn from this hook. If you need to prevent boats appearing you have to remove them after the fact.

  • Position is a Vector2

    The position parameter holds only X and Z. Building a world point with new Vector3(position.x, 0f, position.y) keeps you at sea level; do not treat the second component as altitude.

Build a plugin with OnBoatGroupSpawned

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

Prompt: Warn players about new naval groups using the OnBoatGroupSpawned 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 OnBoatGroupSpawned

Generate