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.
void OnVehicleModulesAssigned(ModularCar modularCar, Rust.Modular.ItemModVehicleModule[] socketItemDefs)Parameters
| Parameter | Type | Description |
|---|---|---|
modularCar | ModularCar | The 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. |
socketItemDefs | Rust.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
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
NextTickortimer.Oncedelay.
Build a plugin with OnVehicleModulesAssigned
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 OnVehicleModulesAssigned
Generate