From 2f0ea2052a2bcb3c8f17e88721f74e1491754a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20SAVA=C5=9E?= Date: Sat, 28 Feb 2026 21:52:26 +0300 Subject: [PATCH 1/8] Fix major memory leaks in Items and optimize custom item spawning --- .../DamageHandlers/GenericDamageHandler.cs | 80 ++++++++++++------- EXILED/Exiled.API/Features/Items/Item.cs | 14 +++- EXILED/Exiled.API/Features/Player.cs | 21 ++++- .../API/Features/CustomArmor.cs | 2 +- .../API/Features/CustomGrenade.cs | 36 ++++++--- .../API/Features/CustomItem.cs | 5 +- .../API/Features/CustomWeapon.cs | 17 +++- .../Exiled.Events/Handlers/Internal/Round.cs | 4 +- 8 files changed, 130 insertions(+), 49 deletions(-) diff --git a/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs b/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs index d55324798e..34a2b81f9b 100644 --- a/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs +++ b/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs @@ -10,19 +10,31 @@ namespace Exiled.API.Features.DamageHandlers using System; using Enums; + + using Exiled.API.Extensions; using Exiled.API.Features.Pickups.Projectiles; using Footprinting; + + using InventorySystem; + using InventorySystem.Items; + using InventorySystem.Items.Firearms.ShotEvents; using InventorySystem.Items.Scp1509; + using Items; + using PlayerRoles; using PlayerRoles.PlayableScps.Scp096; using PlayerRoles.PlayableScps.Scp1507; using PlayerRoles.PlayableScps.Scp3114; using PlayerRoles.PlayableScps.Scp939; + using PlayerStatsSystem; + using UnityEngine; + using Object = UnityEngine.Object; + /// /// Allows generic damage to a player. /// @@ -59,7 +71,7 @@ public GenericDamageHandler(Player player, Player attacker, float damage, Damage if (customCassieAnnouncement is not null) customCassieAnnouncement.Announcement ??= $"{player.Nickname} killed by {attacker.Nickname} utilizing {damageType}"; - Attacker = attacker.Footprint; + Attacker = attacker != null ? attacker.Footprint : Server.Host.Footprint; AllowSelfDamage = true; Damage = damage; ServerLogsText = $"GenericDamageHandler damage processing"; @@ -123,55 +135,57 @@ public GenericDamageHandler(Player player, Player attacker, float damage, Damage Base = new GrayCandyDamageHandler(Attacker.Hub, damage); break; case DamageType.MicroHid: - InventorySystem.Items.MicroHID.MicroHIDItem microHidOwner = new(); - microHidOwner.Owner = attacker.ReferenceHub; + InventorySystem.Items.MicroHID.MicroHIDItem microHidOwner = new() + { + Owner = attacker.ReferenceHub, + }; Base = new MicroHidDamageHandler(damage, microHidOwner); break; case DamageType.Explosion: - Base = new ExplosionDamageHandler(attacker.Footprint, UnityEngine.Vector3.zero, damage, 0, ExplosionType.Grenade); + Base = new ExplosionDamageHandler(attacker.Footprint, Vector3.zero, damage, 0, ExplosionType.Grenade); break; case DamageType.Firearm: case DamageType.AK: - GenericFirearm(player, attacker, damage, damageType, ItemType.GunAK); + GenericFirearm(damage, damageType, ItemType.GunAK); break; case DamageType.Crossvec: - GenericFirearm(player, attacker, damage, damageType, ItemType.GunCrossvec); + GenericFirearm(damage, damageType, ItemType.GunCrossvec); break; case DamageType.Logicer: - GenericFirearm(player, attacker, damage, damageType, ItemType.GunLogicer); + GenericFirearm(damage, damageType, ItemType.GunLogicer); break; case DamageType.Revolver: - GenericFirearm(player, attacker, damage, damageType, ItemType.GunRevolver); + GenericFirearm(damage, damageType, ItemType.GunRevolver); break; case DamageType.Shotgun: - GenericFirearm(player, attacker, damage, damageType, ItemType.GunShotgun); + GenericFirearm(damage, damageType, ItemType.GunShotgun); break; case DamageType.Com15: - GenericFirearm(player, attacker, damage, damageType, ItemType.GunCOM15); + GenericFirearm(damage, damageType, ItemType.GunCOM15); break; case DamageType.Com18: - GenericFirearm(player, attacker, damage, damageType, ItemType.GunCOM18); + GenericFirearm(damage, damageType, ItemType.GunCOM18); break; case DamageType.Fsp9: - GenericFirearm(player, attacker, damage, damageType, ItemType.GunFSP9); + GenericFirearm(damage, damageType, ItemType.GunFSP9); break; case DamageType.E11Sr: - GenericFirearm(player, attacker, damage, damageType, ItemType.GunE11SR); + GenericFirearm(damage, damageType, ItemType.GunE11SR); break; case DamageType.Com45: - GenericFirearm(player, attacker, damage, damageType, ItemType.GunCom45); + GenericFirearm(damage, damageType, ItemType.GunCom45); break; case DamageType.Frmg0: - GenericFirearm(player, attacker, damage, damageType, ItemType.GunFRMG0); + GenericFirearm(damage, damageType, ItemType.GunFRMG0); break; case DamageType.A7: - GenericFirearm(player, attacker, damage, damageType, ItemType.GunA7); + GenericFirearm(damage, damageType, ItemType.GunA7); break; case DamageType.Scp127: - GenericFirearm(player, attacker, damage, damageType, ItemType.GunSCP127); + GenericFirearm(damage, damageType, ItemType.GunSCP127); break; case DamageType.ParticleDisruptor: - Base = new DisruptorDamageHandler(new (Item.Create(ItemType.ParticleDisruptor, attacker).Base as InventorySystem.Items.Firearms.Firearm, InventorySystem.Items.Firearms.Modules.DisruptorActionModule.FiringState.FiringSingle), Vector3.up, damage); + Base = new DisruptorDamageHandler(new DisruptorShotEvent(default, Attacker, InventorySystem.Items.Firearms.Modules.DisruptorActionModule.FiringState.FiringSingle), Vector3.up, damage); break; case DamageType.Scp096: Scp096Role curr096 = attacker.ReferenceHub.roleManager.CurrentRole as Scp096Role ?? new Scp096Role(); @@ -193,9 +207,12 @@ public GenericDamageHandler(Player player, Player attacker, float damage, Damage Base = new PlayerStatsSystem.ScpDamageHandler(attacker.ReferenceHub, damage, DeathTranslations.Unknown); break; case DamageType.Scp018: - Scp018Projectile scp018Projectile = Projectile.Create(ProjectileType.Scp018); - scp018Projectile.PreviousOwner = attacker; - Base = new Scp018DamageHandler(scp018Projectile.Base, damage, true); + InventorySystem.Items.ThrowableProjectiles.Scp018Projectile dummy018 = new() + { + PreviousOwner = Attacker, + }; + + Base = new Scp018DamageHandler(dummy018, damage, true); break; case DamageType.Scp207: Base = new PlayerStatsSystem.ScpDamageHandler(attacker.ReferenceHub, damage, DeathTranslations.Scp207); @@ -303,21 +320,24 @@ public override HandlerOutput ApplyDamage(ReferenceHub ply) /// /// Generic firearm path for handle type. /// - /// Current player. - /// Current attacker. /// Damage amount. /// Damage type. /// ItemType. - private void GenericFirearm(Player player, Player attacker, float amount, DamageType damageType, ItemType itemType) + private void GenericFirearm(float amount, DamageType damageType, ItemType itemType) { - Firearm firearm = new(itemType) + ItemType ammoType = ItemType.None; + + ItemBase firearmIntance = itemType.GetTemplate(); + if (Item.Get(firearmIntance) is Firearm firearm) + ammoType = firearm.PrimaryMagazine.AmmoType.GetItemType(); + + Base = new PlayerStatsSystem.FirearmDamageHandler { - Base = - { - Owner = attacker.ReferenceHub, - }, + Damage = amount, + Attacker = Attacker, + WeaponType = itemType, + AmmoType = ammoType, }; - Base = new PlayerStatsSystem.FirearmDamageHandler() { Firearm = firearm.Base, Damage = amount }; } } } diff --git a/EXILED/Exiled.API/Features/Items/Item.cs b/EXILED/Exiled.API/Features/Items/Item.cs index 89bb189c42..6e9a20d66f 100644 --- a/EXILED/Exiled.API/Features/Items/Item.cs +++ b/EXILED/Exiled.API/Features/Items/Item.cs @@ -414,7 +414,19 @@ public static T Create(ItemType type, Player owner = null) /// /// Destroy this item. /// - public void Destroy() => Owner.RemoveItem(this); + public void Destroy() + { + if (Owner.RemoveItem(this)) + return; + + if (Base != null) + { + BaseToItem.Remove(Base); + + if (Base.gameObject != null) + Object.Destroy(Base.gameObject); + } + } /// /// Creates the that based on this . diff --git a/EXILED/Exiled.API/Features/Player.cs b/EXILED/Exiled.API/Features/Player.cs index 522a0a2113..90ea90f180 100644 --- a/EXILED/Exiled.API/Features/Player.cs +++ b/EXILED/Exiled.API/Features/Player.cs @@ -2324,7 +2324,23 @@ public void Heal(float amount, bool overrideMaxHealth = false) /// /// The ItemType to be used. /// if item was used successfully. Otherwise, . - public bool UseItem(ItemType usableItem) => UseItem(Item.Create(usableItem)); + public bool UseItem(ItemType usableItem) + { + if (usableItem.GetTemplate() is not UsableItem) + return false; + + Item item = Item.Create(usableItem); + + if (item is not Usable usable) + { + item.Destroy(); + return false; + } + + UseItem(usable); + item.Destroy(); + return true; + } /// /// Forces the player to use an item. @@ -2388,7 +2404,8 @@ public void Vaporize(Player attacker = null, string cassieAnnouncement = "") if ((Role.Side != Side.Scp) && !string.IsNullOrEmpty(cassieAnnouncement)) Cassie.Message(cassieAnnouncement); - Kill(new DisruptorDamageHandler(new DisruptorShotEvent(Item.Create(ItemType.ParticleDisruptor, attacker).Base as InventorySystem.Items.Firearms.Firearm, DisruptorActionModule.FiringState.FiringSingle), Vector3.up, -1)); + Footprint footprint = attacker != null ? attacker.Footprint : Server.Host.Footprint; + Kill(new DisruptorDamageHandler(new DisruptorShotEvent(default, footprint, DisruptorActionModule.FiringState.FiringSingle), Vector3.up, -1)); } /// diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomArmor.cs b/EXILED/Exiled.CustomItems/API/Features/CustomArmor.cs index e6f1932905..c1a77f6351 100644 --- a/EXILED/Exiled.CustomItems/API/Features/CustomArmor.cs +++ b/EXILED/Exiled.CustomItems/API/Features/CustomArmor.cs @@ -82,7 +82,7 @@ public override void Give(Player player, bool displayMessage = true) if (AmmoLimits.Count != 0) armor.AmmoLimits = AmmoLimits; - if (AmmoLimits.Count != 0) + if (CategoryLimits.Count != 0) armor.CategoryLimits = CategoryLimits; player.AddItem(armor); diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomGrenade.cs b/EXILED/Exiled.CustomItems/API/Features/CustomGrenade.cs index 48d725ce7e..feafdae9c2 100644 --- a/EXILED/Exiled.CustomItems/API/Features/CustomGrenade.cs +++ b/EXILED/Exiled.CustomItems/API/Features/CustomGrenade.cs @@ -19,10 +19,14 @@ namespace Exiled.CustomItems.API.Features using Exiled.Events.EventArgs.Player; using Footprinting; + + using InventorySystem; using InventorySystem.Items; using InventorySystem.Items.Pickups; using InventorySystem.Items.ThrowableProjectiles; + using Mirror; + using UnityEngine; using Object = UnityEngine.Object; @@ -70,31 +74,43 @@ public override ItemType Type /// The spawned. public virtual Pickup Throw(Vector3 position, float force, float weight, float fuseTime = 3f, ItemType grenadeType = ItemType.GrenadeHE, Player? player = null) { - if (player is null) - player = Server.Host; + player ??= Server.Host; - player.Role.Is(out FpcRole fpcRole); - Vector3 velocity = fpcRole.FirstPersonController.FpcModule.Motor.Velocity; + Vector3 velocity = Vector3.zero; + Quaternion rotation = Quaternion.identity; - Throwable throwable = (Throwable)Item.Create(grenadeType, player); + if (player != Server.Host) + { + if (player.Role.Is(out FpcRole fpcRole)) + velocity = fpcRole.FirstPersonController.FpcModule.Motor.Velocity; + + if (player.CameraTransform != null) + rotation = player.CameraTransform.rotation; + } - ThrownProjectile thrownProjectile = Object.Instantiate(throwable.Base.Projectile, position, throwable.Owner.CameraTransform.rotation); + InventoryItemLoader.TryGetItem(grenadeType, out ThrowableItem template); + + ThrownProjectile thrownProjectile = Object.Instantiate(template.Projectile, position, rotation); PickupSyncInfo newInfo = new() { - ItemId = throwable.Type, - Locked = !throwable.Base._repickupable, + ItemId = grenadeType, + Locked = !template._repickupable, Serial = ItemSerialGenerator.GenerateNext(), WeightKg = weight, }; + if (thrownProjectile is TimeGrenade time) time._fuseTime = fuseTime; + thrownProjectile.NetworkInfo = newInfo; - thrownProjectile.PreviousOwner = new Footprint(throwable.Owner.ReferenceHub); + thrownProjectile.PreviousOwner = player.Footprint; NetworkServer.Spawn(thrownProjectile.gameObject); thrownProjectile.InfoReceivedHook(default, newInfo); + if (thrownProjectile.TryGetComponent(out Rigidbody component)) - throwable.Base.PropelBody(component, throwable.Base.FullThrowSettings.StartTorque, ThrowableNetworkHandler.GetLimitedVelocity(velocity)); + template.PropelBody(component, template.FullThrowSettings.StartTorque, ThrowableNetworkHandler.GetLimitedVelocity(velocity)); + thrownProjectile.ServerActivate(); return Pickup.Get(thrownProjectile); diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs b/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs index 789fd25ceb..d38825617b 100644 --- a/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs +++ b/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs @@ -540,7 +540,7 @@ public static IEnumerable UnregisterItems(IEnumerable targetTy Pickup? pickup = Spawn(position, item, previousOwner); - UnityEngine.Object.Destroy(item.Base); + item.Destroy(); return pickup; } @@ -554,6 +554,8 @@ public static IEnumerable UnregisterItems(IEnumerable targetTy public virtual Pickup? Spawn(Vector3 position, Item item, Player? previousOwner = null) { Pickup? pickup = item.CreatePickup(position); + + item.Destroy(); pickup.Scale = Scale; pickup.Weight = Weight; @@ -663,6 +665,7 @@ public virtual void Give(Player player, Item item, bool displayMessage = true) } catch (Exception e) { + item.Destroy(); Log.Error($"{nameof(Give)}: {e}"); } } diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs b/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs index 9053cf2d66..df0896ed97 100644 --- a/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs +++ b/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs @@ -18,9 +18,11 @@ namespace Exiled.CustomItems.API.Features using Exiled.API.Features.Pickups; using Exiled.Events.EventArgs.Item; using Exiled.Events.EventArgs.Player; + using InventorySystem.Items.Firearms.Attachments; using InventorySystem.Items.Firearms.Attachments.Components; using InventorySystem.Items.Firearms.Modules; + using UnityEngine; using Firearm = Exiled.API.Features.Items.Firearm; @@ -69,16 +71,19 @@ public override ItemType Type /// public override Pickup? Spawn(Vector3 position, Player? previousOwner = null) { - if (Item.Create(Type) is not Firearm firearm) + Item item = Item.Create(Type); + if (item is not Firearm firearm) { Log.Debug($"{nameof(Spawn)}: Item is not Firearm."); + item.Destroy(); return null; } if (!Attachments.IsEmpty()) firearm.AddAttachment(Attachments); - Pickup? pickup = firearm.CreatePickup(position); + FirearmPickup? pickup = (FirearmPickup?)firearm.CreatePickup(position, spawn: false); + item.Destroy(); if (pickup is null) { @@ -87,14 +92,18 @@ public override ItemType Type } if (ClipSize > 0) - firearm.MagazineAmmo = ClipSize; + pickup.MaxAmmo = pickup.Ammo = ClipSize; pickup.Weight = Weight; pickup.Scale = Scale; + if (previousOwner is not null) pickup.PreviousOwner = previousOwner; + pickup.Spawn(); + TrackedSerials.Add(pickup.Serial); + return pickup; } @@ -108,9 +117,11 @@ public override ItemType Type if (ClipSize > 0) firearm.MagazineAmmo = ClipSize; + int ammo = firearm.MagazineAmmo; Log.Debug($"{nameof(Name)}.{nameof(Spawn)}: Spawning weapon with {ammo} ammo."); Pickup? pickup = firearm.CreatePickup(position); + item.Destroy(); pickup.Scale = Scale; if (previousOwner is not null) diff --git a/EXILED/Exiled.Events/Handlers/Internal/Round.cs b/EXILED/Exiled.Events/Handlers/Internal/Round.cs index cebcffa749..49bfc21b88 100644 --- a/EXILED/Exiled.Events/Handlers/Internal/Round.cs +++ b/EXILED/Exiled.Events/Handlers/Internal/Round.cs @@ -145,9 +145,11 @@ private static void GenerateAttachments() if (firearmType == FirearmType.None) continue; - if (Item.Create(firearmType.GetItemType()) is not Firearm firearm) + if (!InventoryItemLoader.TryGetItem(firearmType.GetItemType(), out InventorySystem.Items.Firearms.Firearm firearmTemplate)) continue; + Firearm firearm = new(firearmTemplate); + Firearm.ItemTypeToFirearmInstance[firearmType] = firearm; List attachmentIdentifiers = ListPool.Pool.Get(); From 020f18bfefcc278b7ab9151bc4ba83f0327dd78b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20SAVA=C5=9E?= Date: Sat, 28 Feb 2026 22:39:58 +0300 Subject: [PATCH 2/8] fix armors to --- EXILED/Exiled.Events/Patches/Generic/StaminaRegenArmor.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/EXILED/Exiled.Events/Patches/Generic/StaminaRegenArmor.cs b/EXILED/Exiled.Events/Patches/Generic/StaminaRegenArmor.cs index 96441e17e9..38ad7536e2 100644 --- a/EXILED/Exiled.Events/Patches/Generic/StaminaRegenArmor.cs +++ b/EXILED/Exiled.Events/Patches/Generic/StaminaRegenArmor.cs @@ -16,14 +16,17 @@ namespace Exiled.Events.Patches.Generic /// /// Patches . - /// Implements . + /// Implements . /// [HarmonyPatch(typeof(BodyArmor), nameof(BodyArmor.StaminaRegenMultiplier), MethodType.Getter)] internal class StaminaRegenArmor { private static void Postfix(BodyArmor __instance, ref float __result) { - if(Item.Get(__instance) is Armor armor) + if (__instance.ItemSerial == 0) + return; + + if (Item.Get(__instance) is Armor armor) __result *= armor.StaminaRegenMultiplier; } } From 7445f0201b607b7c331561b8ecc9776ffe94f7ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20SAVA=C5=9E?= Date: Sat, 28 Feb 2026 22:59:47 +0300 Subject: [PATCH 3/8] more --- .../DamageHandlers/GenericDamageHandler.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs b/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs index 34a2b81f9b..82a6c87eeb 100644 --- a/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs +++ b/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs @@ -18,6 +18,7 @@ namespace Exiled.API.Features.DamageHandlers using InventorySystem; using InventorySystem.Items; + using InventorySystem.Items.Firearms.Modules; using InventorySystem.Items.Firearms.ShotEvents; using InventorySystem.Items.Scp1509; @@ -327,9 +328,17 @@ private void GenericFirearm(float amount, DamageType damageType, ItemType itemTy { ItemType ammoType = ItemType.None; - ItemBase firearmIntance = itemType.GetTemplate(); - if (Item.Get(firearmIntance) is Firearm firearm) - ammoType = firearm.PrimaryMagazine.AmmoType.GetItemType(); + if (InventoryItemLoader.TryGetItem(itemType, out InventorySystem.Items.Firearms.Firearm firearmTemplate)) + { + foreach (ModuleBase module in firearmTemplate.Modules) + { + if (module is IPrimaryAmmoContainerModule ammoModule) + { + ammoType = ammoModule.AmmoType; + break; + } + } + } Base = new PlayerStatsSystem.FirearmDamageHandler { From 844e25d6e7c21cb952e8d491a49c7f0100a17102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20SAVA=C5=9E?= Date: Sat, 28 Feb 2026 23:00:58 +0300 Subject: [PATCH 4/8] ,. --- .../Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs b/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs index 82a6c87eeb..ca685c610e 100644 --- a/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs +++ b/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs @@ -322,9 +322,8 @@ public override HandlerOutput ApplyDamage(ReferenceHub ply) /// Generic firearm path for handle type. /// /// Damage amount. - /// Damage type. /// ItemType. - private void GenericFirearm(float amount, DamageType damageType, ItemType itemType) + private void GenericFirearm(float amount, ItemType itemType) { ItemType ammoType = ItemType.None; From 014f4a0fac528ee385c1cc05eb8e7590b24e12b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20SAVA=C5=9E?= Date: Sat, 28 Feb 2026 23:13:40 +0300 Subject: [PATCH 5/8] f'x f'x --- .../DamageHandlers/GenericDamageHandler.cs | 40 +++++++++---------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs b/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs index ca685c610e..4ea1909b72 100644 --- a/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs +++ b/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs @@ -18,6 +18,7 @@ namespace Exiled.API.Features.DamageHandlers using InventorySystem; using InventorySystem.Items; + using InventorySystem.Items.Firearms; using InventorySystem.Items.Firearms.Modules; using InventorySystem.Items.Firearms.ShotEvents; using InventorySystem.Items.Scp1509; @@ -147,43 +148,43 @@ public GenericDamageHandler(Player player, Player attacker, float damage, Damage break; case DamageType.Firearm: case DamageType.AK: - GenericFirearm(damage, damageType, ItemType.GunAK); + GenericFirearm(damage, ItemType.GunAK); break; case DamageType.Crossvec: - GenericFirearm(damage, damageType, ItemType.GunCrossvec); + GenericFirearm(damage, ItemType.GunCrossvec); break; case DamageType.Logicer: - GenericFirearm(damage, damageType, ItemType.GunLogicer); + GenericFirearm(damage, ItemType.GunLogicer); break; case DamageType.Revolver: - GenericFirearm(damage, damageType, ItemType.GunRevolver); + GenericFirearm(damage, ItemType.GunRevolver); break; case DamageType.Shotgun: - GenericFirearm(damage, damageType, ItemType.GunShotgun); + GenericFirearm(damage, ItemType.GunShotgun); break; case DamageType.Com15: - GenericFirearm(damage, damageType, ItemType.GunCOM15); + GenericFirearm(damage, ItemType.GunCOM15); break; case DamageType.Com18: - GenericFirearm(damage, damageType, ItemType.GunCOM18); + GenericFirearm(damage, ItemType.GunCOM18); break; case DamageType.Fsp9: - GenericFirearm(damage, damageType, ItemType.GunFSP9); + GenericFirearm(damage, ItemType.GunFSP9); break; case DamageType.E11Sr: - GenericFirearm(damage, damageType, ItemType.GunE11SR); + GenericFirearm(damage, ItemType.GunE11SR); break; case DamageType.Com45: - GenericFirearm(damage, damageType, ItemType.GunCom45); + GenericFirearm(damage, ItemType.GunCom45); break; case DamageType.Frmg0: - GenericFirearm(damage, damageType, ItemType.GunFRMG0); + GenericFirearm(damage, ItemType.GunFRMG0); break; case DamageType.A7: - GenericFirearm(damage, damageType, ItemType.GunA7); + GenericFirearm(damage, ItemType.GunA7); break; case DamageType.Scp127: - GenericFirearm(damage, damageType, ItemType.GunSCP127); + GenericFirearm(damage, ItemType.GunSCP127); break; case DamageType.ParticleDisruptor: Base = new DisruptorDamageHandler(new DisruptorShotEvent(default, Attacker, InventorySystem.Items.Firearms.Modules.DisruptorActionModule.FiringState.FiringSingle), Vector3.up, damage); @@ -329,22 +330,17 @@ private void GenericFirearm(float amount, ItemType itemType) if (InventoryItemLoader.TryGetItem(itemType, out InventorySystem.Items.Firearms.Firearm firearmTemplate)) { - foreach (ModuleBase module in firearmTemplate.Modules) - { - if (module is IPrimaryAmmoContainerModule ammoModule) - { - ammoType = ammoModule.AmmoType; - break; - } - } + Items.Firearm firearm = new(firearmTemplate); + ammoType = firearm.AmmoType.GetItemType(); } Base = new PlayerStatsSystem.FirearmDamageHandler { Damage = amount, Attacker = Attacker, - WeaponType = itemType, AmmoType = ammoType, + WeaponType = itemType, + Firearm = firearmTemplate, }; } } From bc7c56377941ce0d4a8f03fa14bae28274c00891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20SAVA=C5=9E?= Date: Sat, 28 Feb 2026 23:33:24 +0300 Subject: [PATCH 6/8] =?UTF-8?q?=C3=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs b/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs index df0896ed97..97188b643c 100644 --- a/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs +++ b/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs @@ -92,7 +92,7 @@ public override ItemType Type } if (ClipSize > 0) - pickup.MaxAmmo = pickup.Ammo = ClipSize; + pickup.Ammo = ClipSize; pickup.Weight = Weight; pickup.Scale = Scale; From 9efd69869801faab6f0bf4a7711d69ec55122d24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20SAVA=C5=9E?= Date: Sun, 1 Mar 2026 15:26:05 +0300 Subject: [PATCH 7/8] , --- EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs b/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs index 97188b643c..e889ec3f90 100644 --- a/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs +++ b/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs @@ -82,6 +82,9 @@ public override ItemType Type if (!Attachments.IsEmpty()) firearm.AddAttachment(Attachments); + if (ClipSize > 0) + firearm.MagazineAmmo = ClipSize; + FirearmPickup? pickup = (FirearmPickup?)firearm.CreatePickup(position, spawn: false); item.Destroy(); @@ -91,9 +94,6 @@ public override ItemType Type return null; } - if (ClipSize > 0) - pickup.Ammo = ClipSize; - pickup.Weight = Weight; pickup.Scale = Scale; From 92b361ba7ea234ee1bb40468c777bee9b25c1f8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20SAVA=C5=9E?= Date: Mon, 2 Mar 2026 01:18:43 +0300 Subject: [PATCH 8/8] someonefix --- EXILED/Exiled.CustomItems/API/Features/CustomItem.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs b/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs index d38825617b..e131db7086 100644 --- a/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs +++ b/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs @@ -555,7 +555,6 @@ public static IEnumerable UnregisterItems(IEnumerable targetTy { Pickup? pickup = item.CreatePickup(position); - item.Destroy(); pickup.Scale = Scale; pickup.Weight = Weight; @@ -665,7 +664,6 @@ public virtual void Give(Player player, Item item, bool displayMessage = true) } catch (Exception e) { - item.Destroy(); Log.Error($"{nameof(Give)}: {e}"); } }