local SmallContainers = {
    "Base.Bag_ProtectiveCaseSmall",
    "Base.Bag_ProtectiveCaseSmallMilitary",
    "Base.Bag_ProtectiveCaseSmall",
    "Base.Bag_ProtectiveCaseSmallMilitary",
    "Base.HollowBook",
    "Base.HollowBook",
    "Base.PistolCase1",
    "Base.PistolCase1",
    "Base.PistolCase1",
    "Base.Cashbox",
    "Base.CigarBox",
    "Base.Shoebox",
    "Base.Shoebox",
    "Base.Suitcase",
    "Base.Handbag",
    "Base.Purse",
    "Base.Bag_BowlingBallBag",
    "Base.Hatbox",
    "Base.Tacklebox"
}

local LargeContainers = {
    "Base.Flightcase",
    "Base.Guitarcase",
    "Base.Bag_RifleCase",
    "Base.Bag_RifleCaseGreen",
    "Base.Bag_RifleCaseCloth",
    "Base.Bag_RifleCaseClothCamo"
}

SpawnPistolCommon = {}
SpawnPistolUncommon = {}
SpawnPistolRare = {}
SpawnPistolVaryRare = {}

SpawnBUGCommon = {}
SpawnBUGUncommon = {}
SpawnBUGRare = {}
SpawnBUGVaryRare = {}

SpawnRevolverCommon = {}
SpawnRevolverUncommon = {}
SpawnRevolverRare = {}
SpawnRevolverVaryRare = {}

SpawnSportShotgunCommon = {}
SpawnSportShotgunUncommon = {}
SpawnSportShotgunRare = {}
SpawnSportShotgunVaryRare = {}

SpawnTacShotgunCommon = {}
SpawnTacShotgunUncommon = {}
SpawnTacShotgunRare = {}
SpawnTacShotgunVaryRare = {}

SpawnSportRifleCommon = {}
SpawnSportRifleUncommon = {}
SpawnSportRifleRare = {}
SpawnSportRifleVaryRare = {}

SpawnTacRifleCommon = {}
SpawnTacRifleUncommon = {}
SpawnTacRifleRare = {}
SpawnTacRifleVaryRare = {}

SpawnPoliceHandgunCommon = {}
SpawnPoliceHandgunUncommon = {}
SpawnPoliceHandgunRare = {}
SpawnPoliceHandgunVaryRare = {}

SpawnPoliceLongGunCommon = {}
SpawnPoliceLongGunUncommon = {}
SpawnPoliceLongGunRare = {}
SpawnPoliceLongGunVaryRare = {}

SpawnSWATLongGunCommon = {}
SpawnSWATLongGunUncommon = {}
SpawnSWATLongGunRare = {}
SpawnSWATLongGunVaryRare = {}

SpawnMilitaryHandgunCommon = {}
SpawnMilitaryHandgunUncommon = {}
SpawnMilitaryHandgunRare = {}
SpawnMilitaryHandgunVaryRare = {}

SpawnMilitaryLongGunCommon = {}
SpawnMilitaryLongGunUncommon = {}
SpawnMilitaryLongGunRare = {}
SpawnMilitaryLongGunVaryRare = {}

SpawnMilitarySniperCommon = {}
SpawnMilitarySniperUncommon = {}
SpawnMilitarySniperRare = {}
SpawnMilitarySniperVaryRare = {}

SpawnStoreHandgunCommon = {}
SpawnStoreHandgunUncommon = {}
SpawnStoreHandgunRare = {}
SpawnStoreHandgunVaryRare = {}

SpawnStoreRifleCommon = {}
SpawnStoreRifleUncommon = {}
SpawnStoreRifleRare = {}
SpawnStoreRifleVaryRare = {}

SpawnStoreShotgunCommon = {}
SpawnStoreShotgunUncommon = {}
SpawnStoreShotgunRare = {}
SpawnStoreShotgunVaryRare = {}

SpawnCnRGunCommon = {}
SpawnCnRGunUncommon = {}
SpawnCnRGunRare = {}
SpawnCnRGunVaryRare = {}

SpawnNFAGunCommon = {}
SpawnNFAGunUncommon = {}
SpawnNFAGunRare = {}
SpawnNFAGunVaryRare = {}

SpawnSBSCommon = {}
SpawnSBSUncommon = {}
SpawnSBSRare = {}
SpawnSBSVaryRare = {}

SpawnSawedRifleCommon = {}
SpawnSawedRifleUncommon = {}
SpawnSawedRifleRare = {}
SpawnSawedRifleVaryRare = {}

SpawnCrimeHandgunCommon = {}
SpawnCrimeHandgunUncommon = {}
SpawnCrimeHandgunRare = {}
SpawnCrimeHandgunVaryRare = {}

SpawnCrimeLongGunCommon = {}
SpawnCrimeLongGunUncommon = {}
SpawnCrimeLongGunRare = {}
SpawnCrimeLongGunVaryRare = {}

local COUNTER_KEY = "Guns93_ItemSpawnCounts"

local MAX_SPAWNS = {
    ["SPAS12"] = 3,
    ["HK91"] = 5,
}

local function GetSpawnCounters()
    local data = ModData.getOrCreate(COUNTER_KEY)
    if not data.counts then data.counts = {} end
    return data.counts
end

local function CanSpawnItem(fullType)
    if not MAX_SPAWNS[fullType] then return true end 
    local counts = GetSpawnCounters()
    return (counts[fullType] or 0) < MAX_SPAWNS[fullType]
end

local function IncrementSpawnCount(fullType)
    if not MAX_SPAWNS[fullType] then return end
    local counts = GetSpawnCounters()
    counts[fullType] = (counts[fullType] or 0) + 1
    ModData.transmit(COUNTER_KEY)
end

local function Guns93GunPicker(Gun, Guns)
    if not Guns then return nil end
    local fullType = Guns:getFullType()
    local name = fullType:gsub("Base%.Guns93", ""):gsub("Spawner", "")
    local common   = _G["Spawn" .. name .. "Common"]   or {}
    local uncommon = _G["Spawn" .. name .. "Uncommon"] or {}
    local rare     = _G["Spawn" .. name .. "Rare"]     or {}
    local varyRare = _G["Spawn" .. name .. "VaryRare"] or {}
    local attempts = 0
    local maxAttempts = 5
    while attempts < maxAttempts do
        local GunSpawnD100 = ZombRand(0, 100)
        local candidate
        if GunSpawnD100 > 65 and #common > 0 then
            candidate = common[ZombRand(#common) + 1]
        elseif GunSpawnD100 > 35 and #uncommon > 0 then
            candidate = uncommon[ZombRand(#uncommon) + 1]
        elseif GunSpawnD100 > 5 and #rare > 0 then
            candidate = rare[ZombRand(#rare) + 1]
        elseif #varyRare > 0 then
            candidate = varyRare[ZombRand(#varyRare) + 1]
        end
        if candidate and CanSpawnItem(candidate) then
            local altAmmo = ""
            if ZombRand(1, 10) > 7 and ScriptManager.instance:getItem(candidate .. "_Alt") then
                altAmmo = "_Alt"
            end
            return candidate .. altAmmo
        end
        attempts = attempts + 1
    end
    return nil
end

local function applyAutoParts(gun)
    if isClient() then return end
    if not gun:getFireModePossibilities() then return end
    local md = gun:getModData()
    local partToUse
    if md.hasAutoTrigger and md.hasAutoPart then
        local trigger = gun:getWeaponPart("Trigger")
        if ZombRand(10) > 5 and not (trigger:hasTag(Gun93Registries.guns93.Fullauto) or trigger:hasTag(Gun93Registries.guns93.Burst)) then
            partToUse = md.hasAutoPart
        else
            partToUse = md.hasAutoTrigger
        end
    else
        partToUse = md.hasAutoTrigger or md.hasAutoPart
    end
    if partToUse then
        local partItem = instanceItem(partToUse)
        gun:detachWeaponPart(partItem:getPartType())
        gun:attachWeaponPart(partItem)
        if md.hasSpcPart then
            local spcItem = instanceItem(md.hasSpcPart)
            gun:detachWeaponPart(spcItem:getPartType())
        end
    end
end

local function Guns93ZombieGunSpawns(zombie)
    if not zombie or zombie:isDead() then return end
    if isClient() then return end
--    print("Zombie............................", zombie)
    local ZomID = zombie:getPersistentOutfitID()
    for i = zombie:getAttachedItems():size() - 1, 0, -1 do
        local zomGun = zombie:getAttachedItems():get(i)
        if zomGun ~= nil then
            local Guns = zomGun:getItem()
            if Guns and Guns:hasTag(Gun93Registries.guns93.Guns93Spawner) then
                local Gun = nil
                local GunLocation = zomGun:getLocation()
                Gun = Guns93GunPicker(nil, Guns)
                if Gun ~= nil then
                    zombie:setAttachedItem(GunLocation, nil)
                    local spawn = instanceItem(Gun)
                    IncrementSpawnCount(spawn:getFullType())
                    if spawn:getAttachmentType() == "Rifle" then
                        spawn:attachWeaponPart(instanceItem("Base.Sling"))
                    end
                    zombie:setAttachedItem(GunLocation, spawn)
                    if spawn then
                        local partsData = {}
                        local allParts = spawn:getAllWeaponParts()
                        for i = 0, allParts:size() - 1 do
                            local part = allParts:get(i)
                            if part then
                                table.insert(partsData, part:getFullType())
                            end
                        end
--                        print("Read to send ............................")
                        sendServerCommand("zombie", "attachgun", {
                            zombieID = ZomID,
                            weaponID = spawn:getFullType(),
                            gunLoc = GunLocation,
                            sprite = spawn:getWeaponSprite(),
                            attachedParts = partsData
                        })
 --                       print("Send complete ............................")
                    end
                end
                zombie:transmitModData()
                zombie:resetModel()
            elseif not SandboxVars.Guns93.Guns93VanillaGuns then
                for _, badItem in ipairs(Guns93RemoveItems) do
                    if Guns:getFullType() == badItem then
                        zombie:setAttachedItem(zomGun:getLocation(), nil)
                    end
                end
            end
        end
    end
end

local function setGunCondition(gun, spawner)
    if isClient() then return end
    if not gun then return end
    local isNew = spawner:hasTag(Gun93Registries.guns93.NewGun)
    if isNew then
        gun:setCondition(ZombRand(1,10) > 5 and ZombRand(15,20) or 20)
    else
        gun:setCondition(ZombRand(7,20))
    end
end

local function loadedGun(gun, spawner)
    if isClient() then return end
    if not spawner:hasTag(Gun93Registries.guns93.GunLoaded) then return end
    local roll = ZombRand(11)
    if roll <= 5 then return end
    gun:setCurrentAmmoCount(ZombRand(1, gun:getMaxAmmo()))
    if roll > 7 and gun:haveChamber() then
        gun:setRoundChambered(true)
    end
    if gun:isManuallyRemoveSpentRounds() then
        local spent = gun:getMaxAmmo() - gun:getCurrentAmmoCount()
        gun:setSpentRoundCount(spent)
    end
end

local function createCase(spawner)
    if isClient() then return end
    if ZombRand(11) <= 5 then return nil end
    local hasSmall  = spawner:hasTag(Gun93Registries.guns93.SmallContainer)
    local hasLarge  = spawner:hasTag(Gun93Registries.guns93.LargeContainer)
    if not hasSmall and not hasLarge then return nil end
    local pool = hasLarge and LargeContainers or SmallContainers
    if #pool == 0 then return nil end
    local case = instanceItem(pool[ZombRand(#pool) + 1])
    return case, case:getInventory()
end

local function finalizeGun(gun, spawner, targetContainer)
    if isClient() then return end
    if not targetContainer or not targetContainer.AddItem then
        return
    end
    IncrementSpawnCount(gun)
    if spawner:hasTag(Gun93Registries.guns93.MGun) then
        applyAutoParts(gun)
    end
    setGunCondition(gun, spawner)
    loadedGun(gun, spawner)
    if targetContainer then
        local isLoadedMags = spawner:hasTag(Gun93Registries.guns93.LoadedMags)
        local refItem = instanceItem(gun:getScriptItem())
        if gun:getMagazineType() then
            local magType = gun:getMagazineType()
            local fallbackMagType = refItem:getMagazineType()
            local mag1 = instanceItem(magType)
            local mag2 = instanceItem(fallbackMagType)
            local rareMag = mag1:hasTag(Gun93Registries.guns93.RareMag)
            local rareMag2 = mag2:hasTag(Gun93Registries.guns93.RareMag)
            local roll = ZombRand(11)
            if magType == "Base.EblocClip" then
                for _ = 1, ZombRand(10,25) do
                    local clip = instanceItem(magType)
                    if isLoadedMags then clip:setCurrentAmmoCount(clip:getMaxAmmo()) end
                    DynamicMagClip(clip)
                    targetContainer:AddItem(clip)
                end
            else
                if roll > 3 or spawner:hasTag(Gun93Registries.guns93.SmallContainer) or spawner:hasTag(Gun93Registries.guns93.LargeContainer) then
                    if isLoadedMags then mag1:setCurrentAmmoCount(mag1:getMaxAmmo()) end
                    DynamicMagClip(mag1)
                    targetContainer:AddItem(mag1)
                end
                if roll > 5 and not rareMag2 then
                    if isLoadedMags then mag2:setCurrentAmmoCount(mag2:getMaxAmmo()) end
                    DynamicMagClip(mag2)
                    targetContainer:AddItem(mag2)
                end
                if spawner:hasTag(Gun93Registries.guns93.MoreMags) then
                    if roll > 2 and not rareMag then
                        local extra1 = instanceItem(magType)
                        if isLoadedMags then extra1:setCurrentAmmoCount(extra1:getMaxAmmo()) end
                        DynamicMagClip(extra1)
                        targetContainer:AddItem(extra1)
                    end
                    if roll > 3 and not rareMag2 then
                        local extra2 = instanceItem(fallbackMagType)
                        if isLoadedMags then extra2:setCurrentAmmoCount(extra2:getMaxAmmo()) end
                        DynamicMagClip(extra2)
                        targetContainer:AddItem(extra2)
                    end
                end
            end
        end
        if gun:getModData().hasClip then
            local clipType = gun:getModData().hasClip
            local clipCount = ZombRand(1,3)
            if instanceItem(clipType):hasTag(Gun93Registries.guns93.StripperClip) then
                clipCount = ZombRand(4,10)
            end
            for _ = 1, clipCount do
                local clip = instanceItem(clipType)
                if isLoadedMags then clip:setCurrentAmmoCount(clip:getMaxAmmo()) end
                DynamicMagClip(clip)
                targetContainer:AddItem(clip)
            end
        end
        if gun:getModData().hasLoader then
            if ZombRand(0,11) > 8 then 
                local loaderType = gun:getModData().hasLoader
            elseif ZombRand(0,11) > 9 and gun:getModData().hasLoader2 then 
                loaderType = gun:getModData().hasLoader2 
            elseif ZombRand(0,11) > 9 and gun:getModData().hasLoader3 then 
                loaderType = gun:getModData().hasLoader3 
            end
            if loaderType then
                for _ = 1, ZombRand(1,3) do
                    local loader = instanceItem(loaderType)
                    if isLoadedMags and ZombRand(11) > 5 then loader:setCurrentAmmoCount(loader:getMaxAmmo()) end
                    DynamicMagClip(loader)
                    targetContainer:AddItem(loader)
                end
            end
        end
        if gun:hasTag(Gun93Registries.guns93.SurplusAmmo) then
            local box = gun:getAmmoBox():gsub("Box$", "Carton")
            targetContainer:AddItem(instanceItem(box))
        end
        if not spawner:hasTag(Gun93Registries.guns93.NoAmmo) then
            local roll = ZombRand(11)
            if roll > 2 then targetContainer:AddItem(instanceItem(gun:getAmmoBox())) end
            if roll > 4 then
                local ammoBox = gun:getAmmoBox()
                if ammoBox then targetContainer:AddItem(instanceItem(ammoBox)) end
                if gun:hasTag(Gun93Registries.guns93.AmmoSwitch) then
                    local altGunType = gun:hasTag(Gun93Registries.guns93.AltAmmo) and gun:getFullType():gsub("_Alt$", "") or (gun:getFullType() .. "_Alt")
                    local altItem = instanceItem(altGunType)
                    if altItem and altItem:getAmmoBox() then
                        if roll > 5 then targetContainer:AddItem(instanceItem(altItem:getAmmoBox())) end
                        if roll > 6 then targetContainer:AddItem(instanceItem(altItem:getAmmoBox())) end
                    end
                end
            end
            if spawner:hasTag(Gun93Registries.guns93.MoreAmmo) then
                if roll > 5 then targetContainer:AddItem(instanceItem(gun:getAmmoBox())) end
                if roll > 6 then targetContainer:AddItem(instanceItem(gun:getAmmoBox())) end
            end
        end
        targetContainer:AddItem(gun)
    end
end

local function Guns93ItemPickerContainer(roomType, containerType, container, spawner)
    if isClient() then return end
    if not container or not container.AddItem then
        return
    end
    local fullType = spawner:getFullType()
    local isMilitary = fullType:match("MilitaryHandgunSpawner") or fullType:match("MilitaryLongGunSpawner") or fullType:match("MilitarySniperSpawner")
    if isMilitary and roomType ~= "armystorage" then
        container:Remove(spawner)
        sendRemoveItemFromContainer(container, spawner)
        container:setDirty(true)
        container:setExplored(true)
        local replacement = "Base.Guns93SBSSpawner"
        if ZombRand(10) > 3 then
            replacement = "Base.Guns93NFAGunSpawner"
        end
        spawner = instanceItem(replacement)
    end
    local pickedType = Guns93GunPicker(nil, spawner)
    if not pickedType then return end
    local gun = instanceItem(pickedType)
    local target = container
    local case, caseInv = createCase(spawner)
    if case and caseInv and caseInv.AddItem then
        target = caseInv
        container:AddItem(case)
    end
    finalizeGun(gun, spawner, target)
    container:Remove(spawner)
    sendRemoveItemFromContainer(container, spawner)
    container:setDirty(true)
    container:setExplored(true)
end

local function Guns93ItemPickerFloor(roomType, square, spawner)
    if isClient() then return end
    local fullType = spawner:getFullType()
    local isMilitary = fullType:match("MilitaryHandgunSpawner") or fullType:match("MilitaryLongGunSpawner") or fullType:match("MilitarySniperSpawner")
    if isMilitary and roomType ~= "armystorage" then
        local replacement = "Base.Guns93SBSSpawner"
        if ZombRand(10) > 3 then
            replacement = "Base.Guns93NFAGunSpawner"
        end
        spawner = instanceItem(replacement)
    end
    local pickedType = Guns93GunPicker(nil, spawner)
    if not pickedType then return end
    local gun = instanceItem(pickedType)
    finalizeGun(gun, spawner, nil)
    local zHeight = 0
    local objects = square:getObjects()
    for i = 0, objects:size() - 1 do
        local obj = objects:get(i)
        local props = obj:getProperties()
        if props and props:getSurface() then
            local isTall = (props:getSurface() * 0.01) + 0.01
            if isTall > zHeight then
                zHeight = isTall
            end
        end
    end
    square:AddWorldInventoryItem(gun, ZombRandFloat(0.2, 0.8), ZombRandFloat(0.2, 0.8), zHeight)
end

local function Guns93VanillaReplacerFloor(roomType, square, spawner)
    if isClient() then return end
    local fullType = spawner:getFullType()
    local pickedType = nil
    if fullType == "Base.Pistol" or fullType == "Base.Pistol2" or fullType == "Base.Pistol3" then
        pickedType = "Base.Guns93PistolSpawner"
    elseif fullType == "Base.Revolver" or fullType == "Base.Revolver_Short" or fullType == "Base.Revolver_Long" then
        pickedType = "Base.Guns93RevolverSpawner"
    elseif fullType == "Base.TrapperCarbine" or fullType == "Base.L94_Rifle" or fullType == "Base.L92_Carbine" or fullType == "Base.VarmintRifle" or fullType == "Base.HuntingRifle" or fullType == "Base.JS14_Rifle" then
        pickedType = "Base.Guns93SportRifleSpawner"
    elseif fullType == "Base.MSR7T_Rifle" or fullType == "Base.AssaultRifle" or fullType == "Base.AssaultRifle2" then
        if roomType ~= "armystorage" then
            if ZombRand(10) > 3 then
                pickedType = "Base.Guns93NFAGunSpawner"
            else
                pickedType = "Base.Guns93TacRifleSpawner"
            end
        end
    elseif fullType == "Base.Shotgun" or fullType == "Base.ShotgunSawnoff" or fullType == "Base.DoubleBarrelShotgun" or fullType == "Base.DoubleBarrelShotgunSawnoff" then
        pickedType = "Base.Guns93SportShotgunSpawner"
    elseif fullType == "Base.JS3T_Shotgun" then
        pickedType = "Base.Guns93TacShotgunSpawner"
    end
    if not pickedType then return end
    local gun = instanceItem(pickedType)
    local zHeight = 0
    local objects = square:getObjects()
    for i = 0, objects:size() - 1 do
        local obj = objects:get(i)
        local props = obj:getProperties()
        if props and props:getSurface() then
            local isTall = (props:getSurface() * 0.01) + 0.01
            if isTall > zHeight then
                zHeight = isTall
            end
        end
    end
    square:AddWorldInventoryItem(gun, ZombRandFloat(0.2, 0.8), ZombRandFloat(0.2, 0.8), zHeight)
    return true
end

local function Guns93SpawnerItem(roomType, containerType, container)
    if isClient() then return end
    if not instanceof(container, "ItemContainer") then return end
    local items = container:getItems()
    local toRemove = {}
    for i = 0, items:size() - 1 do
        local item = items:get(i)
        if item then
            if item:getFullType() == "Base.Guns93Junk" then
                table.insert(toRemove, item)
            elseif instanceof(item, "HandWeapon") and item:hasTag(Gun93Registries.guns93.Guns93Spawner) then
                Guns93ItemPickerContainer(roomType, containerType, container, item)
                table.insert(toRemove, item)
            elseif not SandboxVars.Guns93.Guns93VanillaGuns then
                for _, badItem in ipairs(Guns93RemoveItems or {}) do
                    if item:getFullType() == badItem then
                        table.insert(toRemove, item)
                        break
                    end
                end
            end
        end
    end
    for _, item in ipairs(toRemove) do
        if container:contains(item) then
            container:Remove(item)
            sendRemoveItemFromContainer(container, item)
            container:setDirty(true)
            container:setExplored(true)
        end
    end
end

Events.OnFillContainer.Add(Guns93SpawnerItem)

local function Guns93ProcessInventory(roomType, inventory)
    if isClient() then return end
    if not inventory then return end
    local items = inventory:getItems()
    local toRemove = {}
    for i = 0, items:size() - 1 do
        local item = items:get(i)
        if item then
            if item:hasTag(Gun93Registries.guns93.Guns93Spawner) and instanceof(item, "HandWeapon") then
                Guns93ItemPickerContainer(roomType, nil, inventory, item)
                table.insert(toRemove, item)
            elseif item:getFullType() == "Base.Guns93Junk" then
                table.insert(toRemove, item)
            elseif instanceof(item, "InventoryContainer") and item:getInventory() then
                Guns93ProcessInventory(roomType, item:getInventory())
            elseif not SandboxVars.Guns93.Guns93VanillaGuns then
                for _, badItem in ipairs(Guns93RemoveItems or {}) do
                    if item:getFullType() == badItem then
                        table.insert(toRemove, item)
                        break
                    end
                end
            end
        end
    end
    for _, item in ipairs(toRemove) do
        if inventory:contains(item) then
            inventory:Remove(item)
            sendRemoveItemFromContainer(inventory, item)
            inventory:setDirty(true)
            inventory:setExplored(true)
        end
    end
end

local function Guns93SpawnerItemScanner()
    if isClient() then return end
    local playersToCheck = {}
    if getPlayer() then
        table.insert(playersToCheck, getPlayer())
    end
    if getOnlinePlayers() then
        local onlinePlayers = getOnlinePlayers()
        if onlinePlayers and onlinePlayers:size() > 0 then
            for i = 0, onlinePlayers:size() - 1 do
                table.insert(playersToCheck, onlinePlayers:get(i))
            end
        end
    end
    for _, player in ipairs(playersToCheck) do
        local playerSquare = player:getSquare()
        if playerSquare == nil then return end
        local cell = getCell()
        local z = playerSquare:getZ()
        local SEARCH_RADIUS = 10
        for dx = -SEARCH_RADIUS, SEARCH_RADIUS do
            for dy = -SEARCH_RADIUS, SEARCH_RADIUS do
                local x = math.floor(player:getX() + dx)
                local y = math.floor(player:getY() + dy)
                local square = cell:getGridSquare(x, y, z)
                if square then
                    local roomType = square:getRoom() and square:getRoom():getName() or nil
                    local worldObjects = square:getWorldObjects()
                    local toProcess = {}
                    local toRemove = {}
                    for j = 0, worldObjects:size() - 1 do
                        local worldItem = worldObjects:get(j)
                        if worldItem then
                            local item = worldItem:getItem()
                            table.insert(toProcess, {worldItem = worldItem, item = item})
                        end
                    end
                    for _, entry in ipairs(toProcess) do
                        local item = entry.item
                        local worldItem = entry.worldItem
                        if item:hasTag(Gun93Registries.guns93.Guns93Spawner) then
                            Guns93ItemPickerFloor(roomType, square, item)
                            table.insert(toRemove, worldItem)
                        elseif item:getFullType() == "Base.Guns93Junk" then
                            table.insert(toRemove, worldItem)
                        elseif instanceof(item, "InventoryContainer") and item:getInventory() then
                            Guns93ProcessInventory(roomType, item:getInventory())
                        elseif not SandboxVars.Guns93.Guns93VanillaGuns then
                            if instanceof(item, "HandWeapon") and item:isRanged() and not item:hasTag(Gun93Registries.guns93.Guns93) then
                                Guns93VanillaReplacerFloor(roomType, square, item)
                                table.insert(toRemove, worldItem)
                            else
                                for _, badItem in ipairs(Guns93RemoveItems) do
                                    if item:getFullType() == badItem then
                                        table.insert(toRemove, worldItem)
                                    end
                                end
                            end
                        end
                    end
                    for _, worldItem in ipairs(toRemove) do
                        if worldItem and square then
                            square:removeWorldObject(worldItem)
                        end
                    end
                    local objects = square:getObjects()
                    for i = 0, objects:size() - 1 do
                        local obj = objects:get(i)
                        local container = obj:getContainer() or (obj.getItemContainer and obj:getItemContainer())
                        if container then
                            Guns93ProcessInventory(roomType, container)
                        end
                    end
                    local corpse = square:getDeadBody()
                    if corpse and corpse:getContainer() then
                        Guns93ProcessInventory(roomType, corpse:getContainer())
                    end
                    local movingObjects = square:getMovingObjects()
                    if movingObjects then
                        for i = 0, movingObjects:size() - 1 do
                            local mover = movingObjects:get(i)
                            if mover then
                                if instanceof(mover, "BaseVehicle") then
                                    for p = 0, mover:getPartCount() - 1 do
                                        local part = mover:getPartByIndex(p)
                                        if part and part:getItemContainer() then
                                            Guns93ProcessInventory(roomType, part:getItemContainer())
                                        end
                                    end
                                elseif instanceof(mover, "IsoZombie") then
                                    Guns93ZombieGunSpawns(mover)
                                end
                            end
                        end
                    end
                end
            end
        end
    end
end

local TICK_DELAY = 180
local tickTimer = TICK_DELAY or 180

local function Guns93SpawnerOnTickDelay()
    if isClient() then return end
    tickTimer = tickTimer - 1
    if tickTimer <= 0 then
        Guns93SpawnerItemScanner()
        tickTimer = TICK_DELAY
    end
end

Events.OnTick.Add(Guns93SpawnerOnTickDelay)

local function Guns93ZombieDrops(zombie)
    if isClient() then return end
    for i = zombie:getAttachedItems():size() - 1, 0, -1 do
        local zomGun = zombie:getAttachedItems():get(i)
        local Gun = zomGun:getItem()
        if Gun:hasTag(Gun93Registries.guns93.Guns93) then
            Gun:setCondition(ZombRand(5, 20))
            Gun:setCurrentAmmoCount(ZombRand(0, Gun:getMaxAmmo()))
            if Gun:haveChamber() then
                if Gun:getCurrentAmmoCount() > 0 then
                    if ZombRand(0, 10) > 6 then
                        Gun:setJammed(true)
                        Gun:setSpentRoundChambered(true)
                    else
                        Gun:setRoundChambered(true)
                    end
                end
            end
            if Gun:isManuallyRemoveSpentRounds() then
                local spent = Gun:getMaxAmmo() - Gun:getCurrentAmmoCount()
                Gun:setSpentRoundCount(spent)
            end
            if Gun:getMagazineType() then
                local refItem = instanceItem(Gun:getScriptItem())
                local RareMag2 = false
                local GunMag = instanceItem(Gun:getMagazineType())
                local GunMag2 = instanceItem(refItem:getMagazineType())
                if Gun:getMagazineType() == "Base.EblocClip" then
                    local clipNum = ZombRand(10,25)
                    for _ = 0, clipNum - 1 do
                        local clip = instanceItem(Gun:getMagazineType())
                        clip:setCurrentAmmoCount(clip:getMaxAmmo())
                        DynamicMagClip(clip)
                        zombie:getInventory():AddItem(clip)
                    end
                else
                    if GunMag2:hasTag(Gun93Registries.guns93.RareMag) then
                        RareMag2 = true
                    end
                    local magsD10 = ZombRand(0,10)
                    if magsD10 > 2 then
                        local newMag = instanceItem(GunMag2:getFullType())
                        local ammo = ZombRand(0, Gun:getMaxAmmo())
                        newMag:setCurrentAmmoCount(ammo)
                        DynamicMagClip(newMag)
                        zombie:getInventory():AddItem(newMag)
                        if not RareMag2 then
                            for _ = 0, ZombRand(1,3)-1 do
                                local newMag = instanceItem(GunMag2:getFullType())
                                local ammo = ZombRand(0, Gun:getMaxAmmo())
                                newMag:setCurrentAmmoCount(ammo)
                                DynamicMagClip(newMag)
                                zombie:getInventory():AddItem(newMag)
                            end
                        end
                    end
                end
            else
                local looseCount = ZombRand(20)
                local ammoType = Gun:getAmmoType()
                if ammoType and ammoType:getItemKey() then
                    for _ = 1, looseCount do
                        local ammo = instanceItem(ammoType:getItemKey())
                        if ammo then
                            zombie:getInventory():AddItem(ammo)
                        end
                    end
                end
            end
            if Gun:getModData().hasClip then
                local clip = Gun:getModData().hasClip
                local clipNum = ZombRand(1,3)
                if instanceItem(clip):hasTag(Gun93Registries.guns93.StripperClip) then
                    clipNum = ZombRand(4,10)
                end
                if clip then
                    for _ = 0, clipNum-1 do
                        local newClip = instanceItem(clip)
                        local ammo = ZombRand(0, newClip:getMaxAmmo())
                        newClip:setCurrentAmmoCount(ammo)
                        DynamicMagClip(newClip)
                        zombie:getInventory():AddItem(newClip)
                    end
                end
            end
            if Gun:getModData().hasLoader then
                local loader = nil
                if ZombRand(0,10) > 7 then
                    loader = Gun:getModData().hasLoader
                elseif ZombRand(0,10) > 8 and Gun:getModData().hasLoader2 then
                    loader = Gun:getModData().hasLoader2
                elseif ZombRand(0,10) > 8 and Gun:getModData().hasLoader3 then
                    loader = Gun:getModData().hasLoader3
                end
                if loader then
                    for _ = 0, ZombRand(1,3)-1 do
                        local newLoader = instanceItem(loader)
                        if ZombRand(0,10) > 5 then
                            newLoader:setCurrentAmmoCount(newLoader:getMaxAmmo())
                        end
                        DynamicMagClip(newLoader)
                        zombie:getInventory():AddItem(newLoader)
                    end
                end
            end
        end
    end
end

Events.OnZombieDead.Add(Guns93ZombieDrops)
Events.OnZombieUpdate.Add(Guns93ZombieGunSpawns)
---Events.OnZombieCreate.Add(Guns93ZombieGunSpawns)