Skip to content
RustPluginGenerator

OnScientistRecalled

OnScientistRecalled is called when the Bradley APC removes one of its mounted scientists, right after the NPC is taken off the active list and the vehicle's spawn counter is reset.

Signature
void OnScientistRecalled(BradleyAPC bradleyAPC, ScientistNPC scientist)

Parameters

Hook parameters
ParameterTypeDescription
bradleyAPCBradleyAPCThe Bradley APC entity whose mounted scientist is being recalled. Use it to read position, health or owner, or to compare against a tracked vehicle.
scientistScientistNPCThe ScientistNPC that was riding the APC and is now removed from the active scientist list. It is no longer associated with the vehicle when the hook fires.

Return value

The return value is ignored. The original method is a void and continues normally whichever value your hook returns; return nothing and treat this as a notification-only hook.

How it works

The hook fires from BradleyAPC.OnScientistMounted, which is the method the APC uses both for mounting and for removing a scientist. Before the call the game adds the NPC prefab to mountedScientistPrefabs, removes the scientist from activeScientists and increments numberOfScientistsToSpawn, so by the time OnScientistRecalled runs the scientist has already been detached from the vehicle and the APC is free to spawn a replacement. Typical triggers are a scientist dying on the APC, a scientist being dismounted during Bradley damage handling, or the vehicle resetting its crew after being killed.

Use bradleyAPC for position, health or identity checks and scientist to inspect the NPC, its health or its UserIDString. Both arguments are non-null when the hook arrives, but the scientist may already be dead or marked for destruction. Declaring BradleyAPC for the first parameter is normally enough to know which vehicle was affected; you cannot narrow the call further by declaring another entity type, since Oxide skips calls where the argument is not an instance of the parameter type.

Example plugin: Reward the killer when a Bradley crew scientist dies

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

namespace Oxide.Plugins
{
    [Info("Bradley Scientist Reward", "RustPluginGenerator", "1.0.0")]
    [Description("Rewards players who kill scientists riding the Bradley APC.")]
    public class BradleyScientistReward : RustPlugin
    {
        private const string PermReward = "bradleyscientistreward.use";

        private PluginConfig config;
        private readonly Dictionary<ulong, float> cooldowns = new Dictionary<ulong, float>();

        private class PluginConfig
        {
            [JsonProperty("Item shortname")]
            public string Shortname = "scrap";

            [JsonProperty("Amount per reward")]
            public int Amount = 25;

            [JsonProperty("Cooldown seconds per player")]
            public float Cooldown = 120f;
        }

        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>
            {
                ["Reward"] = "You destroyed a Bradley crew scientist and received {0} x {1}.",
                ["NoItem"] = "Bradley scientist reward skipped: unknown item shortname {0}."
            }, 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(PermReward, this);
        }

        private void Unload()
        {
            cooldowns.Clear();
        }

        // Called when a scientist NPC is recalled (e.g. despawned by the Bradley logic).
        // Kept for hook compatibility; no reward is given here.
        private void OnScientistRecalled(ScientistNPC scientist, BasePlayer player)
        {
            if (scientist == null) return;
        }

        private void OnEntityDeath(BaseCombatEntity entity, HitInfo hitInfo)
        {
            var scientist = entity as ScientistNPC;
            if (scientist == null || hitInfo == null) return;

            var player = hitInfo.InitiatorPlayer;
            if (player == null || player.IsNpc || !player.IsConnected) return;
            if (!permission.UserHasPermission(player.UserIDString, PermReward)) return;

            ulong userId = player.userID.Get();
            float now = Time.realtimeSinceStartup;
            float last;
            if (cooldowns.TryGetValue(userId, out last) && now - last < config.Cooldown) return;
            cooldowns[userId] = now;

            var item = ItemManager.CreateByName(config.Shortname, config.Amount, 0);
            if (item == null)
            {
                PrintWarning(string.Format(lang.GetMessage("NoItem", this), config.Shortname));
                return;
            }

            player.GiveItem(item);
            player.ChatMessage(Msg("Reward", player.UserIDString, config.Amount, item.info.displayName.english));
        }
    }
}

The plugin listens for OnEntityDeath, casts the dead entity to ScientistNPC, and resolves the killer through hitInfo.InitiatorPlayer. It only proceeds when a player is connected, is not an NPC, and has the bradleyscientistreward.use permission. A per-player cooldown dictionary keyed on the player's ID blocks repeat rewards within the configured number of seconds. When the reward is allowed, it creates the configured item with ItemManager.CreateByName, gives it via GiveItem, and sends the Reward chat message. If the shortname is unknown, it logs the NoItem warning instead. Configuration exposes the item shortname, amount per reward and cooldown in seconds.

Common use cases

  • Track Bradley crew losses

    Keep a counter per APC in a data file to record how many scientists were recalled, which helps admins measure how often Bradley events happen on their map.

  • Reward players who destroy Bradley crew

    Give the player credited with the scientist's death a small loot drop or currency, using the recall hook as a reliable moment to detect that a crew member left the vehicle.

  • Trigger a broadcast when Bradley resets

    Fire a chat announcement or console command when the Bradley recalls a scientist after its own destruction, so the server can mark the end of a Bradley run.

Pitfalls

  • The scientist may already be dead

    The hook fires after the NPC is removed from the vehicle, so scientist.IsDead() can be true. Check health and lastDamage before awarding anything based on a kill.

  • Do not spam chat from this hook

    A single Bradley can recall several scientists in quick succession. Rate-limit any player-facing message so a burst does not flood chat.

  • Return value does nothing

    The injection ignores the return value. Do not try to cancel or redirect the recall by returning a value from the hook.

Build a plugin with OnScientistRecalled

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

Prompt: Track Bradley crew losses using the OnScientistRecalled 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 OnScientistRecalled

Generate