Skip to content
RustPluginGenerator

OnVehicleModulesAssigned

OnVehicleModulesAssigned is called after a ModularCar finishes spawning the modules defined by its preset configuration. It fires once per vehicle spawn, right before the admin bonus invoke.

Signature
void OnVehicleModulesAssigned(ModularCar modularCar, Rust.Modular.ItemModVehicleModule[] socketItemDefs)

Parameters

Hook parameters
ParameterTypeDescription
modularCarModularCarThe ModularCar entity whose modules were just spawned from a preset. Use it to read position, OwnerID, prefab or existing module layout right after the assignment.
socketItemDefsRust.Modular.ItemModVehicleModule[]Array of Rust.Modular.ItemModVehicleModule item definitions describing the modules the preset applied. Each entry corresponds to a socket and can be used to identify engine, seats, storage or armor modules.

Return value

The original method returns void, so any value you return is ignored and the spawn sequence continues normally. Return null or nothing; there is no way to cancel the assignment from this hook.

How it works

The hook fires inside ModularCar.SpawnPreassignedModules, after the preset's modules have been created and placed into the car's sockets and immediately before HandleAdminBonus is invoked. That means it runs when the game spawns a modular car that has a preassigned preset, such as vehicles spawned from the spawn menu, admin commands or anything else that assigns a preset before spawn.

The modularCar parameter gives you the entity itself: its position, OwnerID, PrefabName and current module layout. The socketItemDefs array holds the ItemModVehicleModule definitions the preset used, one per socket, so you can tell which engine, cockpit, storage or armor modules were installed without walking the sockets yourself.

Because the method returns void, the return value is ignored; you can only observe here. If you want to change modules, do it from a timer or from a hook that fires after spawn completes. A more specific parameter type narrows dispatch, but both parameters already match the exact types used at this site. Avoid heavy work here: it runs at spawn time and can fire many times on a busy server.

Example plugin: Log preset modules assigned to spawned modular cars

VehicleModuleAssignmentLog.cs
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
using Rust.Modular;

namespace Oxide.Plugins
{
    [Info("Vehicle Module Assignment Log", "RustPluginGenerator", "1.0.0")]
    [Description("Logs module presets applied to modular cars and notifies online admins.")]
    public class VehicleModuleAssignmentLog : RustPlugin
    {
        private const string PermAdmin = "vehiclemoduleassignmentlog.admin";

        private PluginConfig config;

        public class PluginConfig
        {
            [JsonProperty("Log to server console")]
            public bool LogToConsole { get; set; } = true;

            [JsonProperty("Notify online admins in chat")]
            public bool LogToChat { get; set; } = true;
        }

        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>
            {
                ["Spawn"] = "Car {0} spawned at {1} with {2} preset module(s): {3}",
                ["None"] = "unknown"
            }, 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(PermAdmin, this);
        }

        private void OnVehicleModulesAssigned(ModularCar modularCar, ItemModVehicleModule[] socketItemDefs)
        {
            if (modularCar == null || modularCar.IsDestroyed) return;

            int count = socketItemDefs?.Length ?? 0;
            var names = new List<string>();
            if (socketItemDefs != null)
            {
                foreach (var mod in socketItemDefs)
                {
                    if (mod == null) continue;
                    ItemDefinition def = mod.GetComponent<ItemDefinition>();
                    if (def == null || def.shortname == null) continue;
                    names.Add(def.shortname);
                }
            }

            string moduleList = names.Count > 0 ? string.Join(", ", names) : Msg("None");
            Vector3 pos = modularCar.transform.position;
            string line = Msg("Spawn", null, modularCar.net.ID.Value, pos.ToString("F0"), count, moduleList);

            if (config.LogToConsole) Puts(line);

            if (!config.LogToChat) return;
            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player == null || !player.IsConnected) continue;
                if (player.IsAdmin || permission.UserHasPermission(player.UserIDString, PermAdmin))
                {
                    player.ChatMessage(line);
                }
            }
        }
    }
}

The plugin listens for OnVehicleModulesAssigned and records the preset modules that were installed on each spawned car. It builds a readable list from socketItemDefs by reading each module's ItemDefinition.shortname, skipping entries with missing definitions, and logs a single line with the car's net ID, position and module count. If LogToChat is enabled in the config, it sends that summary to online admins (and to players granted vehiclemoduleassignmentlog.admin) so they can see vehicle spawns live. Console logging is controlled by LogToConsole.

Common use cases

  • Audit vehicle presets

    Log which modules each preset applies so admins can verify that custom presets place the intended engines and seating before players use them.

  • Post-spawn adjustments

    Use the module list to schedule a delayed tweak, such as changing health or adding a marker, once the vehicle has fully spawned.

  • Spawn statistics

    Count how many modular cars with a given module combination spawn per session to tune loot tables or preset availability.

Pitfalls

  • Hook runs once per spawn

    Players adding or swapping modules later do not trigger this hook. Use the module selection and movement hooks for those cases.

  • Cannot cancel the spawn

    The return value is ignored, so returning false or a value does nothing. Despawn the car from a timer if you need to reject a preset.

  • Timer timing

    The car entity exists, but seating and other flags may not be final at hook time. Run layout checks on a short NextTick or timer.Once delay.

Build a plugin with OnVehicleModulesAssigned

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

Prompt: Audit vehicle presets using the OnVehicleModulesAssigned 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 OnVehicleModulesAssigned

Generate