From aa7b4f8e7b3daee364105002fb2793a20260a222 Mon Sep 17 00:00:00 2001 From: 0xFEEDC0DE64 Date: Sun, 6 Sep 2026 16:48:20 +0200 Subject: [PATCH] Ignore full coop pickups --- gamemode/weaponsystem.lua | 59 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/gamemode/weaponsystem.lua b/gamemode/weaponsystem.lua index 157d0f1..c412b34 100644 --- a/gamemode/weaponsystem.lua +++ b/gamemode/weaponsystem.lua @@ -26,6 +26,39 @@ local persistentItemClasses = { item_suitcharger = true } +local itemAmmoTypes = { + item_ammo_357 = "357", + item_ammo_357_large = "357", + item_ammo_ar2 = "AR2", + item_ammo_ar2_altfire = "AR2AltFire", + item_ammo_ar2_large = "AR2", + item_ammo_crossbow = "XBowBolt", + item_ammo_pistol = "Pistol", + item_ammo_pistol_large = "Pistol", + item_ammo_smg1 = "SMG1", + item_ammo_smg1_grenade = "SMG1_Grenade", + item_ammo_smg1_large = "SMG1", + item_box_buckshot = "Buckshot", + item_rpg_round = "RPG_Round" +} + +local function CanReceiveAmmo(ply, ammoType) + if ammoType == nil or ammoType < 0 then return false end + + local maximum + local maxAmmoOverride = GetConVar("gmod_maxammo") + if maxAmmoOverride and maxAmmoOverride:GetInt() > 0 then + maximum = maxAmmoOverride:GetInt() + else + maximum = game.GetAmmoMax(ammoType) + end + + -- Unknown/custom ammo types are left to their own pickup implementation. + if maximum == nil or maximum < 0 then return true end + + return ply:GetAmmoCount(ammoType) < maximum +end + local function IsRespawnable(ent) if not IsValid(ent) then return false end @@ -146,6 +179,32 @@ hook.Add("WeaponEquip", "CustomCoopRespawnCollectedWeapon", function(weapon) ScheduleRespawn(template) end) +-- A duplicate weapon is removed through WEAPON:EquipAmmo even when the player +-- cannot accept more ammo. Refusing only the useless attempt leaves the pickup +-- available and silent until this player spends ammunition (or someone else +-- who needs it touches it). +hook.Add("PlayerCanPickupWeapon", "CustomCoopIgnoreFullDuplicateWeapons", function(ply, weapon) + if not trackedItems[weapon] or not ply:HasWeapon(weapon:GetClass()) then return end + + if not CanReceiveAmmo(ply, weapon:GetPrimaryAmmoType()) + and not CanReceiveAmmo(ply, weapon:GetSecondaryAmmoType()) then + return false + end +end) + +-- Stock ammo items normally reject a full player themselves. Checking here as +-- well avoids pickup effects from engine branches or addons that remove the +-- item even when GiveAmmo accepted zero rounds. +hook.Add("PlayerCanPickupItem", "CustomCoopIgnoreFullAmmoItems", function(ply, item) + if not trackedItems[item] then return end + + local ammoName = itemAmmoTypes[item:GetClass()] + if not ammoName then return end + + local ammoType = game.GetAmmoID(ammoName) + if not CanReceiveAmmo(ply, ammoType) then return false end +end) + -- Prevent +use from dragging a map pickup away. Touch pickup still works, and -- duplicate weapons are left to the engine's EquipAmmo path so they correctly -- replenish reserve ammo and disappear only when ammo was actually accepted.