From 5c3a360b7059b65ed6b8321de6ccd77c320faf19 Mon Sep 17 00:00:00 2001 From: wtclaude Date: Mon, 2 Nov 2026 04:24:14 -0600 Subject: [PATCH] fix(kit): find a kit's extra by its item definition when it has no held entity (#20) Rust's November 2026 build (staging 26344826) adds the server variable ItemModEntity.playerOnlyEntityBeltOnly, on by default: an item Rust marks player-only, the medical syringe among them, has a held entity only while it is in the belt. A kit puts its syringes in the main inventory, so the heal (D260) found no item whose held entity is a MedicalTool and never healed (s5.kit.heal on the staging drill: heals 0, health 75). FindHeld now asks the item definition's entity prefab when an item has no held entity, for every extra (heal, melee, flamethrower, grenade, rocket), and HasFuel reads the flamethrower's fuel type the same way. Holding the item moves it to the belt, where Rust makes its entity. A heal that cannot hold the item (a full belt) is now no heal, not a heal of an item never held (D331). On rust-staging: s5.kit.heal PASS, heals 2, syringes left 0, health 145. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY --- plugin/RunicNPC.cs | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/plugin/RunicNPC.cs b/plugin/RunicNPC.cs index 90b1d1c..aa69d14 100644 --- a/plugin/RunicNPC.cs +++ b/plugin/RunicNPC.cs @@ -2784,13 +2784,29 @@ namespace Oxide.Plugins if (container == null) continue; foreach (Item item in container.itemList) - if (item != null && item.GetHeldEntity() is T) + if (item != null && HeldAs(item) != null) return item; } return null; } + /// + /// The item's held entity as a , or, when it has none, its definition's + /// entity prefab's. Since Rust's November 2026 build a "player-only" item (a syringe) has a held + /// entity only in the belt (ItemModEntity.playerOnlyEntityBeltOnly), and an extra waits in + /// the main inventory until moves it (issue #20). + /// + private static T HeldAs(Item item) where T : HeldEntity + { + BaseEntity held = item.GetHeldEntity(); + if (held != null) + return held as T; + ItemModEntity mod = item.info.GetComponent(); + GameObject prefab = mod != null && mod.entityPrefab != null && mod.entityPrefab.isValid ? mod.entityPrefab.Get() : null; + return prefab != null ? prefab.GetComponent() : null; + } + /// Puts an item in its hands; only the belt can be held, so it is moved there first. private static bool Hold(RunicNpcPlayer npc, Item item) { @@ -2914,7 +2930,8 @@ namespace Oxide.Plugins if (amount <= 0f) return false; - Hold(npc, item); + if (!Hold(npc, item)) + return false; // a full belt: nowhere to hold it. npc.SignalBroadcast(BaseEntity.Signal.Attack); item.UseItem(1); npc.Heal(amount); @@ -3011,8 +3028,10 @@ namespace Oxide.Plugins private static bool HasFuel(RunicNpcPlayer npc, Item flameItem) { - FlameThrower f = flameItem.GetHeldEntity() as FlameThrower; - return f != null && (f.ammo > 0 || (f.fuelType != null && npc.inventory.FindItemByItemName(f.fuelType.shortname) != null)); + // Off the belt it may have no held entity, so no tank (HeldAs): only the kit's fuel counts then. + FlameThrower held = flameItem.GetHeldEntity() as FlameThrower; + FlameThrower f = HeldAs(flameItem); + return f != null && ((held != null && held.ammo > 0) || (f.fuelType != null && npc.inventory.FindItemByItemName(f.fuelType.shortname) != null)); } ///