diff --git a/resources/[jobs]/[crime]/nordi_containerheist/client/main.lua b/resources/[jobs]/[crime]/nordi_containerheist/client/main.lua index 725225f35..05ec0b6fa 100644 --- a/resources/[jobs]/[crime]/nordi_containerheist/client/main.lua +++ b/resources/[jobs]/[crime]/nordi_containerheist/client/main.lua @@ -1,8 +1,8 @@ local QBCore = exports['qb-core']:GetCoreObject() local isRobbing = false -local currentContainer = nil +local currentPoint = nil local containerBlip = nil -local addedEntities = {} +local nearbyPoint = nil -- Debug function local function Debug(msg) @@ -28,92 +28,22 @@ function DrawText3D(x, y, z, text) DrawRect(_x, _y + 0.0125, 0.015 + factor, 0.03, 41, 11, 41, 68) end --- Function to get model name from hash -local function GetModelNameFromHash(hash) - for _, containerType in pairs(Config.ContainerTypes) do - if GetHashKey(containerType.model) == hash then - return containerType.model - end - end - return "Unknown" -end - --- Function to check if player is near a valid container -local function IsNearValidContainer() +-- Function to find the nearest container point +local function GetNearestContainerPoint() local playerPed = PlayerPedId() local playerCoords = GetEntityCoords(playerPed) - local foundEntity = nil - local foundType = nil - local closestDistance = 5.0 -- Maximum detection distance + local closestPoint = nil + local minDistance = 3.0 -- Maximum interaction distance - -- First check: Use raycast to detect what player is looking at - local rayHandle = StartExpensiveSynchronousShapeTestLosProbe( - playerCoords.x, playerCoords.y, playerCoords.z, - playerCoords.x + (GetEntityForwardX(playerPed) * 5.0), - playerCoords.y + (GetEntityForwardY(playerPed) * 5.0), - playerCoords.z, - 16, playerPed, 4 - ) - local _, hit, endCoords, _, entity = GetShapeTestResult(rayHandle) - - if hit and DoesEntityExist(entity) then - local model = GetEntityModel(entity) - local entityType = GetEntityType(entity) - local distance = #(playerCoords - GetEntityCoords(entity)) - - -- Check if this entity is a valid container or trailer - for _, containerType in pairs(Config.ContainerTypes) do - if model == GetHashKey(containerType.model) then - return entity, containerType - end + for _, point in pairs(Config.ContainerPoints) do + local distance = #(playerCoords - point.coords) + if distance < minDistance then + minDistance = distance + closestPoint = point end end - -- Second check: Check all objects in area - local objects = GetGamePool('CObject') - for _, object in ipairs(objects) do - if DoesEntityExist(object) and not IsEntityDead(object) then - local model = GetEntityModel(object) - local objectCoords = GetEntityCoords(object) - local distance = #(playerCoords - objectCoords) - - if distance <= closestDistance then - for _, containerType in pairs(Config.ContainerTypes) do - if model == GetHashKey(containerType.model) then - if distance < closestDistance then - foundEntity = object - foundType = containerType - closestDistance = distance - end - end - end - end - end - end - - -- Third check: Check all vehicles in area (for trailers) - local vehicles = GetGamePool('CVehicle') - for _, vehicle in ipairs(vehicles) do - if DoesEntityExist(vehicle) and not IsEntityDead(vehicle) then - local model = GetEntityModel(vehicle) - local vehicleCoords = GetEntityCoords(vehicle) - local distance = #(playerCoords - vehicleCoords) - - if distance <= closestDistance then - for _, containerType in pairs(Config.ContainerTypes) do - if model == GetHashKey(containerType.model) then - if distance < closestDistance then - foundEntity = vehicle - foundType = containerType - closestDistance = distance - end - end - end - end - end - end - - return foundEntity, foundType + return closestPoint, minDistance end -- Function to create a blip at the robbery location @@ -187,511 +117,163 @@ local function PlayRobberyAnimation(containerType) end) end --- Function to add target to specific entity -local function AddTargetToEntity(entity, containerType) - if not DoesEntityExist(entity) or not containerType then return false end - - -- Check if we've already added this entity - if addedEntities[entity] then return false end - - -- Add target to this specific entity - exports['qb-target']:AddTargetEntity(entity, { - options = { - { - type = "client", - event = "container_heist:client:startRobbery", - icon = "fas fa-angle-double-right", - label = "Break into " .. containerType.label, - containerType = containerType, - } - }, - distance = 3.0 - }) - - addedEntities[entity] = true - return true -end - --- Function to scan and add all nearby containers to target system -local function ScanAndAddContainersToTarget() - local playerPed = PlayerPedId() - local playerCoords = GetEntityCoords(playerPed) - local count = 0 - - -- Check for containers in the area (objects) - local objects = GetGamePool('CObject') - for _, object in ipairs(objects) do - if DoesEntityExist(object) and not IsEntityDead(object) then - local objectCoords = GetEntityCoords(object) - local distance = #(playerCoords - objectCoords) - - if distance <= 50.0 then - local model = GetEntityModel(object) - - for _, containerType in pairs(Config.ContainerTypes) do - if model == GetHashKey(containerType.model) then - if AddTargetToEntity(object, containerType) then - count = count + 1 - Debug("Added target to container: " .. containerType.model .. " at distance: " .. distance) - end - break - end - end - end - end - end - - -- Check for trailers in the area (vehicles) - local vehicles = GetGamePool('CVehicle') - for _, vehicle in ipairs(vehicles) do - if DoesEntityExist(vehicle) and not IsEntityDead(vehicle) then - local vehicleCoords = GetEntityCoords(vehicle) - local distance = #(playerCoords - vehicleCoords) - - if distance <= 50.0 then - local model = GetEntityModel(vehicle) - - for _, containerType in pairs(Config.ContainerTypes) do - if model == GetHashKey(containerType.model) then - if AddTargetToEntity(vehicle, containerType) then - count = count + 1 - Debug("Added target to trailer: " .. containerType.model .. " at distance: " .. distance) - end - break - end - end - end - end - end - - return count -end - --- Function to visualize containers for debugging -local function VisualizeContainers() - if not Config.Debug then return end - - CreateThread(function() - while Config.Debug do - local playerPed = PlayerPedId() - local playerCoords = GetEntityCoords(playerPed) - - -- Check for containers in the area (objects) - local objects = GetGamePool('CObject') - for _, object in ipairs(objects) do - if DoesEntityExist(object) and not IsEntityDead(object) then - local objectCoords = GetEntityCoords(object) - local distance = #(playerCoords - objectCoords) - - if distance <= 20.0 then - local model = GetEntityModel(object) - - for _, containerType in pairs(Config.ContainerTypes) do - if model == GetHashKey(containerType.model) then - -- Draw a marker at the container - DrawMarker(1, objectCoords.x, objectCoords.y, objectCoords.z + 2.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 1.0, 1.0, 1.0, 255, 0, 0, 100, false, true, 2, false, nil, nil, false) - - -- Draw text with container type - DrawText3D(objectCoords.x, objectCoords.y, objectCoords.z + 2.5, containerType.label) - break - end - end - end - end - end - - -- Check for trailers in the area (vehicles) - local vehicles = GetGamePool('CVehicle') - for _, vehicle in ipairs(vehicles) do - if DoesEntityExist(vehicle) and not IsEntityDead(vehicle) then - local vehicleCoords = GetEntityCoords(vehicle) - local distance = #(playerCoords - vehicleCoords) - - if distance <= 20.0 then - local model = GetEntityModel(vehicle) - - for _, containerType in pairs(Config.ContainerTypes) do - if model == GetHashKey(containerType.model) then - -- Draw a marker at the trailer - DrawMarker(1, vehicleCoords.x, vehicleCoords.y, vehicleCoords.z + 2.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 1.0, 1.0, 1.0, 0, 0, 255, 100, false, true, 2, false, nil, nil, false) - - -- Draw text with trailer type - DrawText3D(vehicleCoords.x, vehicleCoords.y, vehicleCoords.z + 2.5, containerType.label) - break - end - end - end - end - end - - Wait(0) - end - end) -end - -- Function to start container robbery -local function StartContainerRobbery(container, containerType) +local function StartContainerRobbery(point) if isRobbing then return end isRobbing = true - currentContainer = container + currentPoint = point + + -- Get container type from point + local containerType = Config.ContainerTypes[point.type] + if not containerType then + QBCore.Functions.Notify("Invalid container type!", "error") + isRobbing = false + currentPoint = nil + return + end -- Check if player has required tools local hasTools = lib.callback.await('container_heist:server:checkRequiredItems', false) if not hasTools then - lib.notify({ - title = Config.Notifications.title, - description = Config.Notifications.noTools, - type = 'error' - }) + QBCore.Functions.Notify(Config.Notifications.noTools, "error") isRobbing = false - currentContainer = nil + currentPoint = nil return end -- Check cooldowns - local cooldownCheck = lib.callback.await('container_heist:server:checkCooldown', false, NetworkGetNetworkIdFromEntity(container)) + local cooldownCheck = lib.callback.await('container_heist:server:checkCooldown', false, point.id) if not cooldownCheck.success then - lib.notify({ - title = Config.Notifications.title, - description = cooldownCheck.message, - type = 'error' - }) + QBCore.Functions.Notify(cooldownCheck.message, "error") isRobbing = false - currentContainer = nil + currentPoint = nil return end -- Check police count local policeCount = lib.callback.await('container_heist:server:getPoliceCount', false) if policeCount < Config.PoliceRequired then - lib.notify({ - title = Config.Notifications.title, - description = Config.Notifications.notEnoughPolice, - type = 'error' - }) + QBCore.Functions.Notify(Config.Notifications.notEnoughPolice, "error") isRobbing = false - currentContainer = nil + currentPoint = nil return end -- Position player for animation - local containerCoords = GetEntityCoords(container) - local containerHeading = GetEntityHeading(container) - local offsetCoords = GetOffsetFromEntityInWorldCoords(container, containerType.offset.x, containerType.offset.y, containerType.offset.z) - - -- Set player position and heading - SetEntityCoords(PlayerPedId(), offsetCoords.x, offsetCoords.y, offsetCoords.z) - SetEntityHeading(PlayerPedId(), containerHeading + containerType.heading) + SetEntityCoords(PlayerPedId(), point.coords.x, point.coords.y, point.coords.z) + SetEntityHeading(PlayerPedId(), point.heading) -- Alert police if configured if containerType.policeAlert then - local streetName = GetStreetNameFromHashKey(GetStreetNameAtCoord(containerCoords.x, containerCoords.y, containerCoords.z)) - TriggerServerEvent('container_heist:server:alertPolice', containerCoords, streetName, containerType.label) + local streetName = GetStreetNameFromHashKey(GetStreetNameAtCoord(point.coords.x, point.coords.y, point.coords.z)) + TriggerServerEvent('container_heist:server:alertPolice', point.coords, streetName, containerType.label) end -- Start robbery progress bar PlayRobberyAnimation(containerType) - if lib.progressBar({ - duration = containerType.animation.duration, - label = 'Breaking into ' .. containerType.label, - useWhileDead = false, - canCancel = true, - disable = { - car = true, - move = true, - combat = true, - }, - anim = { - dict = containerType.animation.dict, - clip = containerType.animation.name, - }, - }) then + QBCore.Functions.Progressbar("container_robbery", 'Breaking into ' .. containerType.label, containerType.animation.duration, false, true, { + disableMovement = true, + disableCarMovement = true, + disableMouse = false, + disableCombat = true, + }, {}, {}, {}, function() -- Done -- Success - TriggerServerEvent('container_heist:server:finishRobbery', NetworkGetNetworkIdFromEntity(container), containerType.type) - lib.notify({ - title = Config.Notifications.title, - description = Config.Notifications.success, - type = 'success' - }) - else + TriggerServerEvent('container_heist:server:finishRobbery', point.id, point.type) + QBCore.Functions.Notify(Config.Notifications.success, "success") + isRobbing = false + currentPoint = nil + end, function() -- Cancel -- Cancelled - lib.notify({ - title = Config.Notifications.title, - description = Config.Notifications.failed, - type = 'error' - }) - end - - isRobbing = false - currentContainer = nil + QBCore.Functions.Notify(Config.Notifications.failed, "error") + isRobbing = false + currentPoint = nil + end) end -- Command to start container robbery RegisterCommand('robcontainer', function() - local container, containerType = IsNearValidContainer() - if container and containerType then - StartContainerRobbery(container, containerType) + local point, distance = GetNearestContainerPoint() + + if point then + StartContainerRobbery(point) else - lib.notify({ - title = Config.Notifications.title, - description = "No valid container nearby!", - type = 'error' - }) + QBCore.Functions.Notify("No container nearby!", "error") end end, false) --- Command to scan and add all nearby containers to target system -RegisterCommand('scancontainers', function() - local count = ScanAndAddContainersToTarget() - lib.notify({ - title = "Container Scanner", - description = "Added " .. count .. " containers/trailers to target system", - type = 'success', - position = 'top', - duration = 3000 - }) -end, false) - --- Command to force refresh all targets -RegisterCommand('refreshcontainers', function() - -- Clear existing targets - addedEntities = {} - - -- Force a new scan - local count = ScanAndAddContainersToTarget() - - lib.notify({ - title = "Container Refresh", - description = "Refreshed " .. count .. " containers/trailers", - type = 'success', - position = 'top', - duration = 3000 - }) -end, false) - -- Command to toggle debug mode RegisterCommand('containerdebug', function() Config.Debug = not Config.Debug + if Config.Debug then - lib.notify({ - title = "Container Debug", - description = "Debug mode enabled", - type = 'inform', - position = 'top', - duration = 3000 - }) - VisualizeContainers() + QBCore.Functions.Notify("Container Debug mode enabled", "primary") else - lib.notify({ - title = "Container Debug", - description = "Debug mode disabled", - type = 'inform', - position = 'top', - duration = 3000 - }) + QBCore.Functions.Notify("Container Debug mode disabled", "primary") end end, false) --- Debug command to show all nearby containers and trailers -RegisterCommand('containersdebug', function() - if not Config.Debug then return end - - local playerPed = PlayerPedId() - local playerCoords = GetEntityCoords(playerPed) - local foundContainers = 0 - - -- Check for containers in the area (objects) - local objects = GetGamePool('CObject') - for _, object in ipairs(objects) do - if DoesEntityExist(object) and not IsEntityDead(object) then - local objectCoords = GetEntityCoords(object) - local distance = #(playerCoords - objectCoords) - - if distance <= 20.0 then - local model = GetEntityModel(object) - local modelName = "Unknown" - - for _, containerType in pairs(Config.ContainerTypes) do - if model == GetHashKey(containerType.model) then - modelName = containerType.model - break - end - end - - print("Found container object: " .. modelName .. " (Hash: " .. model .. ") at distance: " .. distance) - foundContainers = foundContainers + 1 - end - end - end - - -- Check for trailers in the area (vehicles) - local vehicles = GetGamePool('CVehicle') - for _, vehicle in ipairs(vehicles) do - if DoesEntityExist(vehicle) and not IsEntityDead(vehicle) then - local vehicleCoords = GetEntityCoords(vehicle) - local distance = #(playerCoords - vehicleCoords) - - if distance <= 20.0 then - local model = GetEntityModel(vehicle) - local modelName = "Unknown" - - for _, containerType in pairs(Config.ContainerTypes) do - if model == GetHashKey(containerType.model) then - modelName = containerType.model - break - end - end - - print("Found trailer vehicle: " .. modelName .. " (Hash: " .. model .. ") at distance: " .. distance) - foundContainers = foundContainers + 1 - end - end - end - - print("Total containers/trailers found: " .. foundContainers) -end, false) - --- Command to identify the model of what you're looking at -RegisterCommand('identifycontainer', function() - local playerPed = PlayerPedId() - local success, entity = GetEntityPlayerIsFreeAimingAt(PlayerId()) - - if success and DoesEntityExist(entity) then - local model = GetEntityModel(entity) - local modelName = GetModelNameFromHash(model) - local entityType = GetEntityType(entity) - local entityTypeStr = "Unknown" - - if entityType == 1 then - entityTypeStr = "Ped" - elseif entityType == 2 then - entityTypeStr = "Vehicle" - elseif entityType == 3 then - entityTypeStr = "Object" - end - - print("Entity Type: " .. entityTypeStr) - print("Model Hash: " .. model) - print("Model Name: " .. modelName) - - -- Add visual indicator - local coords = GetEntityCoords(entity) - DrawMarker(0, coords.x, coords.y, coords.z + 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 255, 0, 0, 100, false, true, 2, false, nil, nil, false) - - -- Show notification - lib.notify({ - title = "Container Identification", - description = "Type: " .. entityTypeStr .. "\nModel: " .. modelName .. "\nHash: " .. model, - type = 'inform', - position = 'top', - duration = 5000 - }) - else - lib.notify({ - title = "Container Identification", - description = "No entity found. Aim at a container or trailer.", - type = 'error', - position = 'top', - duration = 3000 - }) - end -end, false) - --- Setup target interactions for containers -CreateThread(function() - -- Wait for target system to be ready - Wait(1000) - - -- Add target for all container types - for _, containerType in pairs(Config.ContainerTypes) do - exports['qb-target']:AddTargetModel(containerType.model, { - options = { - { - type = "client", - event = "container_heist:client:startRobbery", - icon = "fas fa-angle-double-right", - label = "Break into " .. containerType.label, - containerType = containerType, - } - }, - distance = 3.0 - }) - end - - -- Spawn containers at fixed locations if configured - for _, location in pairs(Config.ContainerLocations) do - if location.spawnContainer then - local hash = GetHashKey(location.model) - RequestModel(hash) - while not HasModelLoaded(hash) do - Wait(10) - end - - local container = CreateObject(hash, location.coords.x, location.coords.y, location.coords.z, true, false, false) - SetEntityHeading(container, location.heading) - FreezeEntityPosition(container, true) - SetModelAsNoLongerNeeded(hash) - end - end -end) - --- Initial scan when resource starts -CreateThread(function() - Wait(2000) -- Wait for everything to load - ScanAndAddContainersToTarget() - - -- If debug mode is enabled, start visualizing containers - if Config.Debug then - VisualizeContainers() - end -end) - --- Automatically scan for containers periodically +-- Main thread for checking nearby container points CreateThread(function() while true do - ScanAndAddContainersToTarget() - Wait(10000) -- Scan every 10 seconds + local playerPed = PlayerPedId() + local playerCoords = GetEntityCoords(playerPed) + local wait = 1000 + local point, distance = GetNearestContainerPoint() + + if point and distance < 3.0 then + wait = 0 + nearbyPoint = point + + -- Draw marker + DrawMarker(1, point.coords.x, point.coords.y, point.coords.z - 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.8, 0.8, 0.8, 0, 255, 0, 100, false, true, 2, false, nil, nil, false) + + -- Draw text + DrawText3D(point.coords.x, point.coords.y, point.coords.z, point.label .. " [E]") + + -- Check for interaction + if IsControlJustReleased(0, 38) and distance < 1.5 then -- E key + StartContainerRobbery(point) + end + else + nearbyPoint = nil + end + + Wait(wait) end end) --- Event handler for target interaction -RegisterNetEvent('container_heist:client:startRobbery', function(data) - local container, _ = IsNearValidContainer() - if container then - StartContainerRobbery(container, data.containerType) +-- Debug thread for showing all container points +CreateThread(function() + while true do + Wait(0) + + if Config.Debug then + for _, point in pairs(Config.ContainerPoints) do + DrawMarker(1, point.coords.x, point.coords.y, point.coords.z - 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 255, 0, 0, 100, false, true, 2, false, nil, nil, false) + DrawText3D(point.coords.x, point.coords.y, point.coords.z + 0.5, point.id .. " (" .. point.type .. ")") + end + else + Wait(1000) + end end end) -- Event to show police alert -RegisterNetEvent('container_heist:client:policeAlert', function(coords, streetName, containerType) +RegisterNetEvent('container_heist:client:policeAlert', function(coords, streetName, containerLabel) local playerJob = QBCore.Functions.GetPlayerData().job.name local alertTitle = Config.Notifications.policeTitle - local alertIcon = 'fas fa-exclamation-triangle' -- Customize alert based on job if playerJob == "marshal" then alertTitle = "MARSHAL SERVICE ALERT" - alertIcon = 'fas fa-star' -- Marshal badge icon elseif playerJob == "sheriff" then alertTitle = "SHERIFF DEPARTMENT ALERT" - alertIcon = 'fas fa-shield-alt' -- Sheriff badge icon end -- Create alert for police officers - lib.notify({ - title = alertTitle, - description = string.format(Config.Notifications.policeMessage, streetName), - type = 'inform', - position = 'top', - icon = alertIcon, - iconColor = '#ff0000' - }) + QBCore.Functions.Notify(alertTitle .. ": " .. string.format(Config.Notifications.policeMessage, streetName), "police", 10000) -- Add blip to map CreateRobberyBlip(coords) @@ -707,7 +289,7 @@ AddEventHandler('onResourceStop', function(resourceName) RemoveBlip(containerBlip) end - if isRobbing and currentContainer then + if isRobbing then StopAnimTask(PlayerPedId(), "amb@world_human_welding@male@base", "base", 1.0) end end diff --git a/resources/[jobs]/[crime]/nordi_containerheist/config.lua b/resources/[jobs]/[crime]/nordi_containerheist/config.lua index 6a9a01c40..1df0fbdcc 100644 --- a/resources/[jobs]/[crime]/nordi_containerheist/config.lua +++ b/resources/[jobs]/[crime]/nordi_containerheist/config.lua @@ -1,13 +1,14 @@ -Config = {} +weapon_combatpistoConfig = {} -- General Settings -Config.Debug = true -- Set to true for debug prints -Config.CooldownTime = 1 -- Minutes between heists (per player) -Config.GlobalCooldown = 1 -- Minutes between heists (server-wide) -Config.PoliceRequired = 1 -- Minimum police required +Config.Debug = false -- Set to true for debug prints +Config.CooldownTime = 30 -- Minutes between heists (per player) +Config.GlobalCooldown = 15 -- Minutes between heists (server-wide) +Config.PoliceRequired = 2 -- Minimum police required Config.PoliceJobs = { "police", -- Regular police "marshal", -- Marshal service + "sheriff" -- Sheriff department } -- Required Items @@ -42,42 +43,38 @@ Config.Blip = { sprite = 67, color = 1, scale = 0.8, - label = "Container Einbruch", + label = "Container Robbery", duration = 180, -- seconds flash = true, } - +-- Container Types (for rewards and animations) Config.ContainerTypes = { -- Regular shipping containers - { - model = "prop_container_01a", - type = "shipping", + shipping = { label = "Shipping Container", - offset = vector3(0.0, -4.0, 0.0), - heading = 180.0, animation = { dict = "amb@world_human_welding@male@base", name = "base", flag = 1, - duration = 30000, + duration = 30000, -- milliseconds }, rewards = { + -- Each reward has a chance (total should be <= 100) {item = "phone", label = "Phone", min = 1, max = 3, chance = 30}, {item = "rolex", label = "Rolex Watch", min = 1, max = 2, chance = 20}, {item = "goldchain", label = "Gold Chain", min = 1, max = 3, chance = 25}, {item = "diamond", label = "Diamond", min = 1, max = 1, chance = 5}, {item = "laptop", label = "Laptop", min = 1, max = 1, chance = 15}, + -- Cash reward {item = "cash", label = "Cash", min = 1000, max = 5000, chance = 40}, }, policeAlert = true, }, - { - model = "prop_container_01b", - type = "shipping", - label = "Shipping Container", - offset = vector3(0.0, -4.0, 0.0), - heading = 180.0, + + -- Weapons container + weapons = { + label = "Weapons Container", animation = { dict = "amb@world_human_welding@male@base", name = "base", @@ -93,340 +90,10 @@ Config.ContainerTypes = { }, policeAlert = true, }, - { - model = "prop_container_01c", - type = "shipping", - label = "Shipping Container", - offset = vector3(0.0, -4.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 30000, - }, - rewards = { - {item = "phone", label = "Phone", min = 1, max = 3, chance = 30}, - {item = "rolex", label = "Rolex Watch", min = 1, max = 2, chance = 20}, - {item = "goldchain", label = "Gold Chain", min = 1, max = 3, chance = 25}, - {item = "diamond", label = "Diamond", min = 1, max = 1, chance = 5}, - {item = "laptop", label = "Laptop", min = 1, max = 1, chance = 15}, - {item = "cash", label = "Cash", min = 1000, max = 5000, chance = 40}, - }, - policeAlert = true, - }, - { - model = "prop_container_01d", - type = "shipping", - label = "Shipping Container", - offset = vector3(0.0, -4.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 30000, - }, - rewards = { - {item = "phone", label = "Phone", min = 1, max = 3, chance = 30}, - {item = "rolex", label = "Rolex Watch", min = 1, max = 2, chance = 20}, - {item = "goldchain", label = "Gold Chain", min = 1, max = 3, chance = 25}, - {item = "diamond", label = "Diamond", min = 1, max = 1, chance = 5}, - {item = "laptop", label = "Laptop", min = 1, max = 1, chance = 15}, - {item = "cash", label = "Cash", min = 1000, max = 5000, chance = 40}, - }, - policeAlert = true, - }, - { - model = "prop_container_01e", - type = "shipping", - label = "Shipping Container", - offset = vector3(0.0, -4.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 30000, - }, - rewards = { - {item = "phone", label = "Phone", min = 1, max = 3, chance = 30}, - {item = "rolex", label = "Rolex Watch", min = 1, max = 2, chance = 20}, - {item = "goldchain", label = "Gold Chain", min = 1, max = 3, chance = 25}, - {item = "diamond", label = "Diamond", min = 1, max = 1, chance = 5}, - {item = "laptop", label = "Laptop", min = 1, max = 1, chance = 15}, - {item = "cash", label = "Cash", min = 1000, max = 5000, chance = 40}, - }, - policeAlert = true, - }, - { - model = "prop_container_01f", - type = "shipping", - label = "Shipping Container", - offset = vector3(0.0, -4.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 30000, - }, - rewards = { - {item = "phone", label = "Phone", min = 1, max = 3, chance = 30}, - {item = "rolex", label = "Rolex Watch", min = 1, max = 2, chance = 20}, - {item = "goldchain", label = "Gold Chain", min = 1, max = 3, chance = 25}, - {item = "diamond", label = "Diamond", min = 1, max = 1, chance = 5}, - {item = "laptop", label = "Laptop", min = 1, max = 1, chance = 15}, - {item = "cash", label = "Cash", min = 1000, max = 5000, chance = 40}, - }, - policeAlert = true, - }, - { - model = "prop_container_01g", - type = "shipping", - label = "Shipping Container", - offset = vector3(0.0, -4.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 30000, - }, - rewards = { - {item = "phone", label = "Phone", min = 1, max = 3, chance = 30}, - {item = "rolex", label = "Rolex Watch", min = 1, max = 2, chance = 20}, - {item = "goldchain", label = "Gold Chain", min = 1, max = 3, chance = 25}, - {item = "diamond", label = "Diamond", min = 1, max = 1, chance = 5}, - {item = "laptop", label = "Laptop", min = 1, max = 1, chance = 15}, - {item = "cash", label = "Cash", min = 1000, max = 5000, chance = 40}, - }, - policeAlert = true, - }, - { - model = "prop_container_01h", - type = "shipping", - label = "Shipping Container", - offset = vector3(0.0, -4.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 30000, - }, - rewards = { - {item = "phone", label = "Phone", min = 1, max = 3, chance = 30}, - {item = "rolex", label = "Rolex Watch", min = 1, max = 2, chance = 20}, - {item = "goldchain", label = "Gold Chain", min = 1, max = 3, chance = 25}, - {item = "diamond", label = "Diamond", min = 1, max = 1, chance = 5}, - {item = "laptop", label = "Laptop", min = 1, max = 1, chance = 15}, - {item = "cash", label = "Cash", min = 1000, max = 5000, chance = 40}, - }, - policeAlert = true, - }, - { - model = "prop_container_02a", - type = "shipping", - label = "Shipping Container", - offset = vector3(0.0, -4.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 30000, - }, - rewards = { - {item = "phone", label = "Phone", min = 1, max = 3, chance = 30}, - {item = "rolex", label = "Rolex Watch", min = 1, max = 2, chance = 20}, - {item = "goldchain", label = "Gold Chain", min = 1, max = 3, chance = 25}, - {item = "diamond", label = "Diamond", min = 1, max = 1, chance = 5}, - {item = "laptop", label = "Laptop", min = 1, max = 1, chance = 15}, - {item = "cash", label = "Cash", min = 1000, max = 5000, chance = 40}, - }, - policeAlert = true, - }, - { - model = "prop_container_03a", - type = "shipping", - label = "Shipping Container", - offset = vector3(0.0, -2.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 30000, - }, - rewards = { - {item = "phone", label = "Phone", min = 1, max = 3, chance = 30}, - {item = "rolex", label = "Rolex Watch", min = 1, max = 2, chance = 20}, - {item = "goldchain", label = "Gold Chain", min = 1, max = 3, chance = 25}, - {item = "diamond", label = "Diamond", min = 1, max = 1, chance = 5}, - {item = "laptop", label = "Laptop", min = 1, max = 1, chance = 15}, - {item = "cash", label = "Cash", min = 1000, max = 5000, chance = 40}, - }, - policeAlert = true, - }, - { - model = "prop_container_03b", - type = "shipping", - label = "Shipping Container", - offset = vector3(0.0, -2.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 30000, - }, - rewards = { - {item = "phone", label = "Phone", min = 1, max = 3, chance = 30}, - {item = "rolex", label = "Rolex Watch", min = 1, max = 2, chance = 20}, - {item = "goldchain", label = "Gold Chain", min = 1, max = 3, chance = 25}, - {item = "diamond", label = "Diamond", min = 1, max = 1, chance = 5}, - {item = "laptop", label = "Laptop", min = 1, max = 1, chance = 15}, - {item = "cash", label = "Cash", min = 1000, max = 5000, chance = 40}, - }, - policeAlert = true, - }, - { - model = "prop_container_03mb", - type = "shipping", - label = "Shipping Container", - offset = vector3(0.0, -2.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 30000, - }, - rewards = { - {item = "phone", label = "Phone", min = 1, max = 3, chance = 30}, - {item = "rolex", label = "Rolex Watch", min = 1, max = 2, chance = 20}, - {item = "goldchain", label = "Gold Chain", min = 1, max = 3, chance = 25}, - {item = "diamond", label = "Diamond", min = 1, max = 1, chance = 5}, - {item = "laptop", label = "Laptop", min = 1, max = 1, chance = 15}, - {item = "cash", label = "Cash", min = 1000, max = 5000, chance = 40}, - }, - policeAlert = true, - }, - { - model = "prop_container_04a", - type = "shipping", - label = "Shipping Container", - offset = vector3(0.0, -2.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 30000, - }, - rewards = { - {item = "phone", label = "Phone", min = 1, max = 3, chance = 30}, - {item = "rolex", label = "Rolex Watch", min = 1, max = 2, chance = 20}, - {item = "goldchain", label = "Gold Chain", min = 1, max = 3, chance = 25}, - {item = "diamond", label = "Diamond", min = 1, max = 1, chance = 5}, - {item = "laptop", label = "Laptop", min = 1, max = 1, chance = 15}, - {item = "cash", label = "Cash", min = 1000, max = 5000, chance = 40}, - }, - policeAlert = true, - }, - { - model = "prop_container_04mb", - type = "shipping", - label = "Shipping Container", - offset = vector3(0.0, -2.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 30000, - }, - rewards = { - {item = "phone", label = "Phone", min = 1, max = 3, chance = 30}, - {item = "rolex", label = "Rolex Watch", min = 1, max = 2, chance = 20}, - {item = "goldchain", label = "Gold Chain", min = 1, max = 3, chance = 25}, - {item = "diamond", label = "Diamond", min = 1, max = 1, chance = 5}, - {item = "laptop", label = "Laptop", min = 1, max = 1, chance = 15}, - {item = "cash", label = "Cash", min = 1000, max = 5000, chance = 40}, - }, - policeAlert = true, - }, - { - model = "prop_container_05mb", - type = "shipping", - label = "Shipping Container", - offset = vector3(0.0, -2.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 30000, - }, - rewards = { - {item = "phone", label = "Phone", min = 1, max = 3, chance = 30}, - {item = "rolex", label = "Rolex Watch", min = 1, max = 2, chance = 20}, - {item = "goldchain", label = "Gold Chain", min = 1, max = 3, chance = 25}, - {item = "diamond", label = "Diamond", min = 1, max = 1, chance = 5}, - {item = "laptop", label = "Laptop", min = 1, max = 1, chance = 15}, - {item = "cash", label = "Cash", min = 1000, max = 5000, chance = 40}, - }, - policeAlert = true, - }, - { - model = "prop_container_ld", - type = "shipping", - label = "Shipping Container", - offset = vector3(0.0, -2.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 30000, - }, - rewards = { - {item = "phone", label = "Phone", min = 1, max = 3, chance = 30}, - {item = "rolex", label = "Rolex Watch", min = 1, max = 2, chance = 20}, - {item = "goldchain", label = "Gold Chain", min = 1, max = 3, chance = 25}, - {item = "diamond", label = "Diamond", min = 1, max = 1, chance = 5}, - {item = "laptop", label = "Laptop", min = 1, max = 1, chance = 15}, - {item = "cash", label = "Cash", min = 1000, max = 5000, chance = 40}, - }, - policeAlert = true, - }, - { - model = "prop_container_door_mb", - type = "shipping", - label = "Container Door", - offset = vector3(0.0, -1.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 20000, - }, - rewards = { - {item = "phone", label = "Phone", min = 1, max = 1, chance = 20}, - {item = "cash", label = "Cash", min = 500, max = 2000, chance = 30}, - }, - policeAlert = false, - }, - -- Trailer models - { - model = "trailers", - type = "trailer", + -- Cargo trailer + cargo = { label = "Cargo Trailer", - offset = vector3(0.0, -5.0, 0.0), - heading = 180.0, animation = { dict = "amb@world_human_welding@male@base", name = "base", @@ -442,12 +109,10 @@ Config.ContainerTypes = { }, policeAlert = true, }, - { - model = "trailers2", - type = "trailer", - label = "Box Trailer", - offset = vector3(0.0, -5.0, 0.0), - heading = 180.0, + + -- Food trailer + food = { + label = "Food Trailer", animation = { dict = "amb@world_human_welding@male@base", name = "base", @@ -462,320 +127,73 @@ Config.ContainerTypes = { }, policeAlert = false, }, - { - model = "trailers3", - type = "trailer", - label = "Transport Trailer", - offset = vector3(0.0, -5.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 40000, - }, - rewards = { - {item = "phone", label = "Phone", min = 1, max = 3, chance = 30}, - {item = "rolex", label = "Rolex Watch", min = 1, max = 2, chance = 20}, - {item = "goldchain", label = "Gold Chain", min = 1, max = 3, chance = 25}, - {item = "diamond", label = "Diamond", min = 1, max = 1, chance = 5}, - {item = "laptop", label = "Laptop", min = 1, max = 1, chance = 15}, - {item = "cash", label = "Cash", min = 1000, max = 5000, chance = 40}, - }, - policeAlert = true, - }, - { - model = "trailers4", - type = "trailer", - label = "Car Trailer", - offset = vector3(0.0, -5.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 40000, - }, - rewards = { - {item = "carparts", label = "Car Parts", min = 3, max = 8, chance = 60}, - {item = "toolbox", label = "Toolbox", min = 1, max = 2, chance = 40}, - {item = "cash", label = "Cash", min = 1000, max = 3000, chance = 30}, - }, - policeAlert = true, - }, - { - model = "trailerlogs", - type = "trailer", - label = "Logging Trailer", - offset = vector3(0.0, -5.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 40000, - }, - rewards = { - {item = "wood", label = "Wood", min = 10, max = 20, chance = 80}, - {item = "cash", label = "Cash", min = 500, max = 2000, chance = 20}, - }, - policeAlert = false, - }, - { - model = "tanker", - type = "trailer", - label = "Fuel Tanker", - offset = vector3(0.0, -5.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 50000, - }, - rewards = { - {item = "petrol", label = "Petrol", min = 10, max = 20, chance = 70}, - {item = "cash", label = "Cash", min = 2000, max = 5000, chance = 30}, - }, - policeAlert = true, - }, - { - model = "tanker2", - type = "trailer", - label = "Chemical Tanker", - offset = vector3(0.0, -5.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 50000, - }, - rewards = { - {item = "chemicals", label = "Chemicals", min = 5, max = 15, chance = 60}, - {item = "cash", label = "Cash", min = 3000, max = 8000, chance = 40}, - }, - policeAlert = true, - }, - { - model = "docktrailer", - type = "trailer", - label = "Dock Trailer", - offset = vector3(0.0, -5.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 40000, - }, - rewards = { - {item = "electronics", label = "Electronics", min = 3, max = 8, chance = 40}, - {item = "plastic", label = "Plastic", min = 10, max = 20, chance = 60}, - {item = "aluminum", label = "Aluminum", min = 10, max = 20, chance = 50}, - {item = "copper", label = "Copper", min = 5, max = 15, chance = 30}, - {item = "cash", label = "Cash", min = 3000, max = 10000, chance = 25}, - }, - policeAlert = true, - }, - { - model = "tr2", - type = "trailer", - label = "Car Carrier Trailer", - offset = vector3(0.0, -5.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 40000, - }, - rewards = { - {item = "carparts", label = "Car Parts", min = 3, max = 8, chance = 60}, - {item = "toolbox", label = "Toolbox", min = 1, max = 2, chance = 40}, - {item = "cash", label = "Cash", min = 1000, max = 3000, chance = 30}, - }, - policeAlert = true, - }, - { - model = "tr3", - type = "trailer", - label = "Large Trailer", - offset = vector3(0.0, -5.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 40000, - }, - rewards = { - {item = "electronics", label = "Electronics", min = 3, max = 8, chance = 40}, - {item = "plastic", label = "Plastic", min = 10, max = 20, chance = 60}, - {item = "aluminum", label = "Aluminum", min = 10, max = 20, chance = 50}, - {item = "copper", label = "Copper", min = 5, max = 15, chance = 30}, - {item = "cash", label = "Cash", min = 3000, max = 10000, chance = 25}, - }, - policeAlert = true, - }, - { - model = "tr4", - type = "trailer", - label = "Training Trailer", - offset = vector3(0.0, -5.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 40000, - }, - rewards = { - {item = "electronics", label = "Electronics", min = 3, max = 8, chance = 40}, - {item = "plastic", label = "Plastic", min = 10, max = 20, chance = 60}, - {item = "aluminum", label = "Aluminum", min = 10, max = 20, chance = 50}, - {item = "copper", label = "Copper", min = 5, max = 15, chance = 30}, - {item = "cash", label = "Cash", min = 3000, max = 10000, chance = 25}, - }, - policeAlert = true, - }, - { - model = "tvtrailer", - type = "trailer", - label = "TV Trailer", - offset = vector3(0.0, -5.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 40000, - }, - rewards = { - {item = "electronics", label = "Electronics", min = 5, max = 10, chance = 70}, - {item = "wires", label = "Wires", min = 5, max = 15, chance = 60}, - {item = "cash", label = "Cash", min = 2000, max = 6000, chance = 30}, - }, - policeAlert = true, - }, - { - model = "armytanker", - type = "trailer", - label = "Military Tanker", - offset = vector3(0.0, -5.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 50000, - }, - rewards = { - {item = "weapon_pistol", label = "Pistol", min = 1, max = 1, chance = 15}, - {item = "pistol_ammo", label = "Pistol Ammo", min = 10, max = 30, chance = 30}, - {item = "armor", label = "Body Armor", min = 1, max = 3, chance = 25}, - {item = "cash", label = "Cash", min = 5000, max = 15000, chance = 20}, - }, - policeAlert = true, - }, - { - model = "armytrailer", - type = "trailer", - label = "Military Trailer", - offset = vector3(0.0, -5.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 50000, - }, - rewards = { - {item = "weapon_pistol", label = "Pistol", min = 1, max = 1, chance = 15}, - {item = "pistol_ammo", label = "Pistol Ammo", min = 10, max = 30, chance = 30}, - {item = "armor", label = "Body Armor", min = 1, max = 3, chance = 25}, - {item = "cash", label = "Cash", min = 5000, max = 15000, chance = 20}, - }, - policeAlert = true, - }, - { - model = "freighttrailer", - type = "trailer", - label = "Freight Trailer", - offset = vector3(0.0, -5.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 45000, - }, - rewards = { - {item = "electronics", label = "Electronics", min = 3, max = 8, chance = 40}, - {item = "plastic", label = "Plastic", min = 10, max = 20, chance = 60}, - {item = "aluminum", label = "Aluminum", min = 10, max = 20, chance = 50}, - {item = "copper", label = "Copper", min = 5, max = 15, chance = 30}, - {item = "cash", label = "Cash", min = 3000, max = 10000, chance = 25}, - }, - policeAlert = true, - }, - { - model = "graintrailer", - type = "trailer", - label = "Grain Trailer", - offset = vector3(0.0, -5.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 40000, - }, - rewards = { - {item = "grain", label = "Grain", min = 10, max = 20, chance = 80}, - {item = "cash", label = "Cash", min = 500, max = 2000, chance = 20}, - }, - policeAlert = false, - }, - { - model = "proptrailer", - type = "trailer", - label = "Prop Trailer", - offset = vector3(0.0, -5.0, 0.0), - heading = 180.0, - animation = { - dict = "amb@world_human_welding@male@base", - name = "base", - flag = 1, - duration = 40000, - }, - rewards = { - {item = "electronics", label = "Electronics", min = 3, max = 8, chance = 40}, - {item = "plastic", label = "Plastic", min = 10, max = 20, chance = 60}, - {item = "aluminum", label = "Aluminum", min = 10, max = 20, chance = 50}, - {item = "copper", label = "Copper", min = 5, max = 15, chance = 30}, - {item = "cash", label = "Cash", min = 3000, max = 10000, chance = 25}, - }, - policeAlert = true, - }, - } - - --- Locations where containers can be found (optional, for target setup) -Config.ContainerLocations = { +-- Container Points (specific locations for container robberies) +Config.ContainerPoints = { + -- Port area shipping containers { - coords = vector3(1000.0, -3000.0, 5.0), - heading = 0.0, - model = "prop_container_01a", - spawnContainer = true, -- Whether to spawn a container at this location + id = "port_container_1", + type = "shipping", -- References the container type above for rewards + coords = vector3(895.7916, -2968.3140, 5.9008), + heading = 269.5337, + label = "Break into Container" }, { - coords = vector3(980.0, -3000.0, 5.0), - heading = 0.0, - model = "prop_container_01b", - spawnContainer = true, + id = "port_container_2", + type = "shipping", + coords = vector3(990.23, -3050.34, 5.90), + heading = 90.0, + label = "Break into Container" }, - -- Add more fixed locations as needed + + -- Weapons containers + { + id = "weapons_container_1", + type = "weapons", + coords = vector3(905.45, -3200.67, 5.90), + heading = 0.0, + label = "Break into Weapons Container" + }, + { + id = "weapons_container_2", + type = "weapons", + coords = vector3(910.34, -3195.23, 5.90), + heading = 270.0, + label = "Break into Weapons Container" + }, + + -- Cargo trailers + { + id = "cargo_trailer_1", + type = "cargo", + coords = vector3(825.34, -3125.45, 5.90), + heading = 270.0, + label = "Break into Cargo Trailer" + }, + { + id = "cargo_trailer_2", + type = "cargo", + coords = vector3(830.56, -3130.78, 5.90), + heading = 180.0, + label = "Break into Cargo Trailer" + }, + + -- Food trailers + { + id = "food_trailer_1", + type = "food", + coords = vector3(765.23, -3165.34, 5.90), + heading = 180.0, + label = "Break into Food Trailer" + }, + { + id = "food_trailer_2", + type = "food", + coords = vector3(770.45, -3170.56, 5.90), + heading = 90.0, + label = "Break into Food Trailer" + }, + + -- Add more points as needed } diff --git a/resources/[jobs]/[crime]/nordi_containerheist/fxmanifest.lua b/resources/[jobs]/[crime]/nordi_containerheist/fxmanifest.lua index 2a8e5aa50..dbc2d0566 100644 --- a/resources/[jobs]/[crime]/nordi_containerheist/fxmanifest.lua +++ b/resources/[jobs]/[crime]/nordi_containerheist/fxmanifest.lua @@ -11,16 +11,16 @@ shared_scripts { } client_scripts { - 'client/main.lua' + 'client.lua' } server_scripts { - 'server/main.lua' + 'server.lua' } lua54 'yes' dependencies { 'ox_lib', - 'tgiann-inventory' + 'qb-core' } diff --git a/resources/[jobs]/[crime]/nordi_containerheist/server/main.lua b/resources/[jobs]/[crime]/nordi_containerheist/server/main.lua index 18f863861..138445a4a 100644 --- a/resources/[jobs]/[crime]/nordi_containerheist/server/main.lua +++ b/resources/[jobs]/[crime]/nordi_containerheist/server/main.lua @@ -1,5 +1,5 @@ local QBCore = exports['qb-core']:GetCoreObject() -local containerCooldowns = {} +local pointCooldowns = {} local playerCooldowns = {} local globalCooldowns = {} @@ -22,7 +22,7 @@ lib.callback.register('container_heist:server:checkRequiredItems', function(sour end) -- Check cooldowns -lib.callback.register('container_heist:server:checkCooldown', function(source, containerId) +lib.callback.register('container_heist:server:checkCooldown', function(source, pointId) local src = source local Player = QBCore.Functions.GetPlayer(src) if not Player then return {success = false, message = "Player not found"} end @@ -36,19 +36,30 @@ lib.callback.register('container_heist:server:checkCooldown', function(source, c 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 + -- Check point cooldown + if pointCooldowns[pointId] and (currentTime - pointCooldowns[pointId]) < (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)"} + -- Find point type + local pointType = nil + for _, point in pairs(Config.ContainerPoints) do + if point.id == pointId then + pointType = point.type + break end end + if not pointType then + return {success = false, message = "Invalid point!"} + end + + -- Check global cooldown for container type + if globalCooldowns[pointType] and (currentTime - globalCooldowns[pointType]) < (Config.GlobalCooldown * 60) then + local timeLeft = math.ceil(((globalCooldowns[pointType] + (Config.GlobalCooldown * 60)) - currentTime) / 60) + return {success = false, message = Config.Notifications.globalCooldown .. " (" .. timeLeft .. " minutes left)"} + end + return {success = true} end) @@ -74,7 +85,7 @@ lib.callback.register('container_heist:server:getPoliceCount', function() end) -- Alert police -RegisterNetEvent('container_heist:server:alertPolice', function(coords, streetName, containerType) +RegisterNetEvent('container_heist:server:alertPolice', function(coords, streetName, containerLabel) local src = source local players = QBCore.Functions.GetPlayers() @@ -84,7 +95,7 @@ RegisterNetEvent('container_heist:server:alertPolice', function(coords, streetNa -- 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) + TriggerClientEvent('container_heist:client:policeAlert', playerId, coords, streetName, containerLabel) break -- No need to send multiple alerts to the same player end end @@ -93,7 +104,7 @@ RegisterNetEvent('container_heist:server:alertPolice', function(coords, streetNa end) -- Finish robbery and give rewards -RegisterNetEvent('container_heist:server:finishRobbery', function(containerId, containerType) +RegisterNetEvent('container_heist:server:finishRobbery', function(pointId, containerTypeName) local src = source local Player = QBCore.Functions.GetPlayer(src) if not Player then return end @@ -103,8 +114,15 @@ RegisterNetEvent('container_heist:server:finishRobbery', function(containerId, c -- Set cooldowns playerCooldowns[citizenId] = currentTime - containerCooldowns[containerId] = currentTime - globalCooldowns[containerType] = currentTime + pointCooldowns[pointId] = currentTime + globalCooldowns[containerTypeName] = currentTime + + -- Get container type + local containerType = Config.ContainerTypes[containerTypeName] + if not containerType then + Debug("Container type not found: " .. containerTypeName) + return + end -- Decrease durability of flex tool if configured if Config.RequiredItems.flex.durability then @@ -129,23 +147,9 @@ RegisterNetEvent('container_heist:server:finishRobbery', function(containerId, c 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 + for _, reward in pairs(containerType.rewards) do if math.random(1, 100) <= reward.chance then local amount = math.random(reward.min, reward.max) @@ -190,10 +194,10 @@ CreateThread(function() end end - -- Clean up container cooldowns - for containerId, cooldownTime in pairs(containerCooldowns) do + -- Clean up point cooldowns + for pointId, cooldownTime in pairs(pointCooldowns) do if (currentTime - cooldownTime) > (Config.CooldownTime * 60) then - containerCooldowns[containerId] = nil + pointCooldowns[pointId] = nil end end @@ -205,4 +209,3 @@ CreateThread(function() end end end) -