00:06 [Error] NPCDropGun v2.0.8: Failed to call hook OnCorpsePopulate(BasePlayer, PlayerCorpse):
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at Oxide.Plugins.NPCDropGun.OnCorpsePopulate (BasePlayer player, PlayerCorpse corpse) [0x00092] in <2677e8a3d5044ff894f31f5a0b71d5b1>:0
at Oxide.Plugins.NPCDropGun.DirectCallHook (System.String name, System.Object& ret, System.Object[] args) [0x000de] in <2677e8a3d5044ff894f31f5a0b71d5b1>:0
at OxidePerfCounter.main.HookPerformance (Oxide.Core.Plugins.HookMethod method, System.Object[] args, Oxide.Plugins.CSharpPlugin __instance, System.Object& __result) [0x0009c] in <b3fa7a63aa764ffb9f048e13be62c298>:0 This is the message I get in my console.
the plugin might be 'out of date' to the barrage of Rust updates of late.
Thats what I thought I was doing here?
WOW no one has found a solution yet?? Author not maintaining it anymore??
@Wulf do you know how we can get this mod activated again??
Here is the message I keep getting; I assume it is because this has not been updated in 4 years:
Failed to call internal hook 'OnCorpsePopulate'on plugin 'NPCDropGun v2.0.8' [338615359] (Index was outside the bounds of the array.) at void Oxide.Plugins.NPCDropGun.OnCorpsePopulate(BasePlayer player, PlayerCorpse corpse) in /home/container/carbon/plugins/NPCDropGun.cs:line 61 at object Oxide.Plugins.NPCDropGun.InternalCallHook(uint hook, object[] args) in NPCDropGun.cs/Internal:line 76
I haven't tested this, but I hope it patches and fixes the issue until the update comes out.
FIX #1 — Safe default-loot removal
Replace this block:
for (int i = 0; i < corpse.containers.Length; i++)
{
corpse.containers[i].Clear();
}WITH:
if (corpse.containers != null)
{
for (int i = 0; i < corpse.containers.Length; i++)
{
if (corpse.containers[i] != null)
corpse.containers[i].Clear();
}
}
Whole Plugin:
using System;
using System.Collections.Generic;
using System.Linq;
using Facepunch;
using Newtonsoft.Json;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Oxide.Plugins
{
[Info("NPC Drop Gun", "2CHEVSKII", "2.0.9")]
[Description("Forces NPC to drop used gun and other items after death")]
public class NPCDropGun : RustPlugin
{
private Settings settings;
private Dictionary<BasePlayer, List<Item>> delayedItems;
void Init()
{
delayedItems = new Dictionary<BasePlayer, List<Item>>();
}
void OnServerInitialized()
{
if ((bool)Manager.GetPlugin("BotSpawn"))
PrintWarning("BotSpawn plugin found! Some ammo and loot might not be handled correctly!");
}
void OnEntityDeath(BasePlayer player)
{
if (player is NPCPlayer)
DoSpawns(player);
}
void OnCorpsePopulate(BasePlayer player, PlayerCorpse corpse)
{
if (player == null || corpse == null)
return;
if (!delayedItems.TryGetValue(player, out var list))
return;
if (corpse.containers == null || corpse.containers.Length == 0)
{
Pool.FreeList(ref list);
delayedItems.Remove(player);
return;
}
if (settings.RemoveDefault)
{
foreach (var container in corpse.containers)
container?.Clear();
}
foreach (var item in list)
{
bool moved = false;
foreach (var container in corpse.containers)
{
if (container != null && item.MoveToContainer(container))
{
moved = true;
break;
}
}
if (!moved)
{
if (settings.DropNearFull)
ApplyVelocity(DropNearPosition(item, corpse.transform.position + new Vector3(0, 0.3f)));
else
item.Remove();
}
}
Pool.FreeList(ref list);
delayedItems.Remove(player);
}
void DoSpawns(BasePlayer player)
{
var list = Pool.GetList<Item>();
delayedItems[player] = list;
if (Random.Range(0f, 1f) <= settings.Meds.DropChance)
{
var meds = SpawnMeds();
if (meds != null)
list.Add(meds);
}
var def = player.inventory?.containerBelt?.FindItemByUID(player.svActiveItemID)?.info;
if (def == null)
return;
var weapon = ItemManager.Create(
def,
1,
settings.Guns.RandomSkin ? GetRandomSkin(def) : 0UL
);
if (weapon == null)
return;
float cond = Random.Range(
(int)settings.Guns.Condition.Min,
(int)settings.Guns.Condition.Max
);
weapon.conditionNormalized = cond / 100f;
var held = weapon.GetHeldEntity();
if (held is BaseProjectile proj && Random.Range(0f, 1f) <= settings.Ammo.DropChance)
{
var ammo = SpawnAmmo(proj);
if (ammo != null)
list.Add(ammo);
}
if (Random.Range(0f, 1f) <= settings.Guns.DropChance)
{
SetAttachments(weapon);
if (settings.GunIntoCorpse || player.eyes == null || held == null)
list.Add(weapon);
else
ApplyVelocity(DropNearPosition(weapon, player.eyes.position));
}
}
Item SpawnMeds()
{
int amount = Random.Range(
(int)settings.Meds.Amount.Min,
(int)settings.Meds.Amount.Max
);
return amount < 1 ? null : ItemManager.CreateByName("syringe.medical", amount);
}
Item SpawnAmmo(BaseProjectile weapon)
{
if (weapon?.primaryMagazine?.ammoType == null)
return null;
int amount = Random.Range(
(int)settings.Ammo.Amount.Min,
(int)settings.Ammo.Amount.Max
);
return amount < 1 ? null : ItemManager.Create(weapon.primaryMagazine.ammoType, amount);
}
void SetAttachments(Item item)
{
if (settings.Guns.Attachments.Length == 0 || item.contents == null)
return;
int count = Random.Range(
(int)settings.Guns.AttachmentCount.Min,
(int)settings.Guns.AttachmentCount.Max
);
for (int i = 0; i < count; i++)
{
var name = settings.Guns.Attachments.GetRandom();
var att = ItemManager.CreateByPartialName(name);
if (att != null && item.contents.CanAccept(att))
att.MoveToContainer(item.contents);
}
}
BaseEntity DropNearPosition(Item item, Vector3 pos)
=> item.CreateWorldObject(pos);
BaseEntity ApplyVelocity(BaseEntity ent)
{
ent.SetVelocity(new Vector3(
Random.Range(-4f, 4f),
Random.Range(-0.3f, 2f),
Random.Range(-4f, 4f)
));
ent.SetAngularVelocity(new Vector3(
Random.Range(-10f, 10f),
Random.Range(-10f, 10f),
Random.Range(-10f, 10f)
));
ent.SendNetworkUpdateImmediate();
return ent;
}
ulong GetRandomSkin(ItemDefinition idef)
{
if (idef == null)
return 0;
var skins = Pool.GetList<int>();
if (idef.skins != null)
skins.AddRange(idef.skins.Select(s => s.id));
if (idef.skins2 != null)
skins.AddRange(idef.skins2.Where(s => s != null).Select(s => s.DefinitionId));
int skin = skins.Count > 0 ? skins.GetRandom() : 0;
Pool.FreeList(ref skins);
return skin == 0 ? 0 : ItemDefinition.FindSkin(idef.itemid, skin);
}
protected override void LoadDefaultConfig()
{
settings = Settings.Default;
SaveConfig();
}
protected override void LoadConfig()
{
base.LoadConfig();
settings = Config.ReadObject<Settings>() ?? Settings.Default;
}
protected override void SaveConfig()
{
Config.WriteObject(settings);
}
public class Settings
{
public GunSettings Guns { get; set; }
public OtherSettings Ammo { get; set; }
public OtherSettings Meds { get; set; }
public bool GunIntoCorpse { get; set; }
public bool RemoveDefault { get; set; }
public bool DropNearFull { get; set; }
public static Settings Default => new Settings
{
Guns = new GunSettings
{
DropChance = 1f,
RandomSkin = true,
Condition = new RangeSettings { Min = 5, Max = 95 },
AttachmentCount = new RangeSettings { Min = 0, Max = 2 },
Attachments = new[]
{
"weapon.mod.8x.scope",
"weapon.mod.flashlight",
"weapon.mod.holosight",
"weapon.mod.lasersight",
"weapon.mod.muzzleboost",
"weapon.mod.muzzlebrake",
"weapon.mod.silencer",
"weapon.mod.simplesight",
"weapon.mod.small.scope"
}
},
Ammo = new OtherSettings
{
DropChance = 0.8f,
Amount = new RangeSettings { Min = 10, Max = 55 }
},
Meds = new OtherSettings
{
DropChance = 0.4f,
Amount = new RangeSettings { Min = 1, Max = 3 }
},
GunIntoCorpse = false,
RemoveDefault = false,
DropNearFull = true
};
public class GunSettings : DropChanceSettings
{
public RangeSettings Condition { get; set; }
public RangeSettings AttachmentCount { get; set; }
public string[] Attachments { get; set; }
public bool RandomSkin { get; set; }
}
public class OtherSettings : DropChanceSettings
{
public RangeSettings Amount { get; set; }
}
public class DropChanceSettings
{
public float DropChance { get; set; }
}
public class RangeSettings
{
public uint Min { get; set; }
public uint Max { get; set; }
}
}
}
}