local QBCore = exports['qb-core']:GetCoreObject() local containerCooldowns = {} local playerCooldowns = {} local globalCooldowns = {} -- Debug function local function Debug(msg) if Config.Debug then print("[Container Heist] " .. msg) end end -- Check if player has required items lib.callback.register('container_heist:server:checkRequiredItems', function(source) local src = source local Player = QBCore.Functions.GetPlayer(src) if not Player then return false end -- Check for required flex tool local hasItem = exports['tgiann-inventory']:HasItem(src, Config.RequiredItems.flex.name, Config.RequiredItems.flex.amount) return hasItem end) -- Check cooldowns lib.callback.register('container_heist:server:checkCooldown', function(source, containerId) local src = source local Player = QBCore.Functions.GetPlayer(src) if not Player then return {success = false, message = "Player not found"} end local citizenId = Player.PlayerData.citizenid local currentTime = os.time() -- Check player cooldown if playerCooldowns[citizenId] and (currentTime - playerCooldowns[citizenId]) < (Config.CooldownTime * 60) then local timeLeft = math.ceil(((playerCooldowns[citizenId] + (Config.CooldownTime * 60)) - currentTime) / 60) return {success = false, message = "You need to wait " .. timeLeft .. " more minutes before attempting another heist!"} end -- Check container cooldown if containerCooldowns[containerId] and (currentTime - containerCooldowns[containerId]) < (Config.CooldownTime * 60) then return {success = false, message = Config.Notifications.alreadyRobbed} end -- Check global cooldown for container type for containerType, cooldownTime in pairs(globalCooldowns) do if (currentTime - cooldownTime) < (Config.GlobalCooldown * 60) then local timeLeft = math.ceil(((cooldownTime + (Config.GlobalCooldown * 60)) - currentTime) / 60) return {success = false, message = Config.Notifications.globalCooldown .. " (" .. timeLeft .. " minutes left)"} end end return {success = true} end) -- Get police count lib.callback.register('container_heist:server:getPoliceCount', function() local policeCount = 0 local players = QBCore.Functions.GetPlayers() for _, playerId in ipairs(players) do local Player = QBCore.Functions.GetPlayer(playerId) if Player then -- Check if player's job is in the list of police jobs for _, jobName in ipairs(Config.PoliceJobs) do if Player.PlayerData.job.name == jobName and Player.PlayerData.job.onduty then policeCount = policeCount + 1 break -- No need to check other job names for this player end end end end return policeCount end) -- Alert police RegisterNetEvent('container_heist:server:alertPolice', function(coords, streetName, containerType) local src = source local players = QBCore.Functions.GetPlayers() for _, playerId in ipairs(players) do local Player = QBCore.Functions.GetPlayer(playerId) if Player then -- Check if player's job is in the list of police jobs for _, jobName in ipairs(Config.PoliceJobs) do if Player.PlayerData.job.name == jobName and Player.PlayerData.job.onduty then TriggerClientEvent('container_heist:client:policeAlert', playerId, coords, streetName, containerType) break -- No need to send multiple alerts to the same player end end end end end) -- Finish robbery and give rewards RegisterNetEvent('container_heist:server:finishRobbery', function(containerId, containerType) local src = source local Player = QBCore.Functions.GetPlayer(src) if not Player then return end local citizenId = Player.PlayerData.citizenid local currentTime = os.time() -- Set cooldowns playerCooldowns[citizenId] = currentTime containerCooldowns[containerId] = currentTime globalCooldowns[containerType] = currentTime -- Decrease durability of flex tool if configured if Config.RequiredItems.flex.durability then local itemData = exports['tgiann-inventory']:GetItemByName(src, Config.RequiredItems.flex.name) if itemData and itemData.info then local newDurability = math.max(0, (itemData.info.durabilityPercent or 100) - Config.RequiredItems.flex.durabilityDecrease) exports['tgiann-inventory']:UpdateItemMetadata(src, Config.RequiredItems.flex.name, itemData.slot, { durabilityPercent = newDurability, serie = itemData.info.serie or "TOOL-" .. math.random(100000, 999999), usedTotalAmmo = itemData.info.usedTotalAmmo or 0, ammo = itemData.info.ammo or 0 }) -- Remove item if durability reaches 0 if newDurability <= 0 and Config.RequiredItems.flex.remove then exports['tgiann-inventory']:RemoveItem(src, Config.RequiredItems.flex.name, 1) TriggerClientEvent('QBCore:Notify', src, "Your " .. Config.RequiredItems.flex.label .. " broke!", "error") end end elseif Config.RequiredItems.flex.remove then -- Remove item if configured exports['tgiann-inventory']:RemoveItem(src, Config.RequiredItems.flex.name, Config.RequiredItems.flex.amount) end -- Find the container type in config local containerConfig = nil for _, config in pairs(Config.ContainerTypes) do if config.type == containerType then containerConfig = config break end end if not containerConfig then Debug("Container type not found in config: " .. containerType) return end -- Give rewards based on chances local rewardsGiven = 0 for _, reward in pairs(containerConfig.rewards) do if math.random(1, 100) <= reward.chance then local amount = math.random(reward.min, reward.max) if reward.item == "cash" then Player.Functions.AddMoney("cash", amount) TriggerClientEvent('QBCore:Notify', src, "Found $" .. amount, "success") else -- Add item with proper metadata for weapons if string.match(reward.item, "weapon_") then exports['tgiann-inventory']:AddItem(src, reward.item, amount, nil, { serie = "HEIST-" .. math.random(100000, 999999), durabilityPercent = 100, usedTotalAmmo = 0, ammo = 0 }) else exports['tgiann-inventory']:AddItem(src, reward.item, amount) end TriggerClientEvent('QBCore:Notify', src, "Found " .. amount .. "x " .. reward.label, "success") end rewardsGiven = rewardsGiven + 1 end end -- <-- This end statement was missing if rewardsGiven == 0 then TriggerClientEvent('QBCore:Notify', src, "The container was empty!", "error") end end) -- Clean up cooldowns periodically CreateThread(function() while true do Wait(60000) -- Check every minute local currentTime = os.time() -- Clean up player cooldowns for citizenId, cooldownTime in pairs(playerCooldowns) do if (currentTime - cooldownTime) > (Config.CooldownTime * 60) then playerCooldowns[citizenId] = nil end end -- Clean up container cooldowns for containerId, cooldownTime in pairs(containerCooldowns) do if (currentTime - cooldownTime) > (Config.CooldownTime * 60) then containerCooldowns[containerId] = nil end end -- Clean up global cooldowns for containerType, cooldownTime in pairs(globalCooldowns) do if (currentTime - cooldownTime) > (Config.GlobalCooldown * 60) then globalCooldowns[containerType] = nil end end end end)