Skip to content
RustPluginGenerator

OnVehicleModulesAssign

OnVehicleModulesAssign is called when a ModularCar is about to receive its preset vehicle module loadout from spawn settings, before the modules are actually spawned and attached.

Signature
object OnVehicleModulesAssign(ModularCar modularCar, Rust.Modular.ItemModVehicleModule[] socketItemDefs)

Parameters

Hook parameters
ParameterTypeDescription
modularCarModularCarThe ModularCar entity whose preassigned modules are about to be spawned. Use it to inspect position, owner, skin or flags before the preset loadout is applied.
socketItemDefsRust.Modular.ItemModVehicleModule[]Array of ItemModVehicleModule definitions from the randomly picked ModularCarPresetConfig, one entry per socket that would be filled. Read-only in practice: mutating it affects the loop only if you let the original code run.

Return value

Returning a non-null value makes the game skip the preset module loop entirely, leaving the car spawned without its configured modules. Returning null lets the original code continue and spawn the preset modules as normal.

How it works

The hook fires inside ModularCar.SpawnPreassignedModules after the game has picked a random ModularCarPresetConfig from the spawn settings but before it loops over socketItemDefs to create and mount the module items. This path only runs when the spawn settings have useSpawnSettings enabled and a non-empty configurationOptions list, so it covers spawned modular cars from configured spawn points rather than cars assembled by players with the hammer or a vehicle lift.

modularCar is the live entity; it has no modules yet at this point. socketItemDefs is the preset's socket definition array; each element describes an ItemModVehicleModule that the loop would install. You can read its length to know how many modules the car would get.

Declaring modularCar as a more specific type such as BaseEntity is pointless but harmless; Oxide only calls your method when the argument is an instance of the declared parameter type, so a stricter type narrows calls rather than widening them. Decorating the hook to be skipped for some cars means the original preset assignment still runs.

Example plugin: Strip modules from a share of spawned cars

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

namespace Oxide.Plugins
{
    [Info("VehicleModulesAssign", "RustPluginGenerator", "1.0.0")]
    [Description("Skips preset module assignment for a configurable share of spawned modular cars.")]
    public class VehicleModulesAssign : RustPlugin
    {
        private const string PermAdmin = "vehiclemodulesassign.admin";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Skip chance (0-100)")]
            public float SkipChance { get; set; } = 25f;

            [JsonProperty("Minimum preset modules to affect")]
            public int MinModules { get; set; } = 2;
        }

        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 Init()
        {
            permission.RegisterPermission(PermAdmin, this);
        }

        private object OnVehicleModulesAssign(ModularCar modularCar, Rust.Modular.ItemModVehicleModule[] socketItemDefs)
        {
            if (modularCar == null || socketItemDefs == null) return null;
            if (config.SkipChance <= 0f) return null;
            if (socketItemDefs.Length < config.MinModules) return null;

            int roll = UnityEngine.Random.Range(0, 100);
            if (roll >= config.SkipChance) return null;

            NotifyAdmins(modularCar);
            return true;
        }

        private void NotifyAdmins(ModularCar car)
        {
            string position = car.transform.position.ToString("0");
            foreach (BasePlayer player in BasePlayer.activePlayerList)
            {
                if (player == null || !player.IsConnected) continue;
                if (!player.IsAdmin && !permission.UserHasPermission(player.UserIDString, PermAdmin)) continue;
                player.ChatMessage($"A spawned modular car at {position} was left without preset modules.");
            }
        }
    }
}

The plugin reads a configurable chance and, when it triggers, returns a value from OnVehicleModulesAssign to skip the preset module loop, so the car spawns as a bare chassis. It only affects cars whose preset socket count meets the configured minimum, so small cheap cars keep their loadout. A message is sent to admins online so they know which car was stripped. Null checks guard the entity before any work, and the config falls back to defaults when the file is invalid. No timers or UI are needed, so unload is trivial.

Common use cases

  • Randomize spawned car quality

    Use the hook to skip modules on a configurable percentage of spawned cars so the server produces varied vehicle quality without editing preset assets.

  • Restrict premium cars by location

    Inspect modularCar.transform.position and cancel assignment when the spawn is inside a restricted zone, keeping high-tier cars out of safe areas.

  • Log preset spawns for balancing

    Count how many modules each preset would install and record the totals in oxide/data to tune spawn settings over time.

Pitfalls

  • Only fires for configured spawns

    This hook runs in SpawnPreassignedModules, which only exists when spawn settings have useSpawnSettings and configuration options. Player-built and lift-spawned cars never reach it.

  • Editing the array does nothing by itself

    socketItemDefs belongs to a shared preset config object. Changing it in place does not change which modules spawn unless you also understand the loop, and it can corrupt later spawns.

  • Not a player-facing event

    Do not send chat or console messages here for every call; it runs on map-wide vehicle spawns and can flood output. Only notify when a specific condition is met.

Build a plugin with OnVehicleModulesAssign

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

Prompt: Randomize spawned car quality using the OnVehicleModulesAssign 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 OnVehicleModulesAssign

Generate