From 2fa4d9bdcaea3193d07bc1ba1e39d4c64963b93f Mon Sep 17 00:00:00 2001 From: Nordi98 Date: Sun, 20 Jul 2025 03:18:58 +0200 Subject: [PATCH] ed --- .../nordi_containerheist/client/main.lua | 268 ++++++- .../[crime]/nordi_containerheist/config.lua | 657 +++++++++++++++++- .../nordi_containerheist/server/main.lua | 28 +- 3 files changed, 920 insertions(+), 33 deletions(-) diff --git a/resources/[jobs]/[crime]/nordi_containerheist/client/main.lua b/resources/[jobs]/[crime]/nordi_containerheist/client/main.lua index 7015aac1b..ad164ca1d 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 containerCooldowns = {} local isRobbing = false local currentContainer = nil local containerBlip = nil +local addedEntities = {} -- Debug function local function Debug(msg) @@ -11,12 +11,25 @@ local function Debug(msg) end 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() local playerPed = PlayerPedId() local playerCoords = GetEntityCoords(playerPed) + local foundEntity = nil + local foundType = nil + local closestDistance = 999.0 - -- Check for containers in the area + -- 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 @@ -24,17 +37,20 @@ local function IsNearValidContainer() local objectCoords = GetEntityCoords(object) local distance = #(playerCoords - objectCoords) - if distance <= 5.0 then + if distance <= 5.0 and distance < closestDistance then for _, containerType in pairs(Config.ContainerTypes) do if model == GetHashKey(containerType.model) then - return object, containerType + foundEntity = object + foundType = containerType + closestDistance = distance + break end end end end end - -- Check for trailers in the area + -- 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 @@ -42,17 +58,20 @@ local function IsNearValidContainer() local vehicleCoords = GetEntityCoords(vehicle) local distance = #(playerCoords - vehicleCoords) - if distance <= 5.0 then + if distance <= 5.0 and distance < closestDistance then for _, containerType in pairs(Config.ContainerTypes) do if model == GetHashKey(containerType.model) then - return vehicle, containerType + foundEntity = vehicle + foundType = containerType + closestDistance = distance + break end end end end end - return nil, nil + return foundEntity, foundType end -- Function to create a blip at the robbery location @@ -62,8 +81,18 @@ local function CreateRobberyBlip(coords) end containerBlip = AddBlipForCoord(coords) + + -- Set blip color based on job + local playerJob = QBCore.Functions.GetPlayerData().job.name + if playerJob == "marshal" then + SetBlipColour(containerBlip, 38) -- Purple for Marshal + elseif playerJob == "sheriff" then + SetBlipColour(containerBlip, 16) -- Orange for Sheriff + else + SetBlipColour(containerBlip, Config.Blip.color) -- Default color for regular police + end + SetBlipSprite(containerBlip, Config.Blip.sprite) - SetBlipColour(containerBlip, Config.Blip.color) SetBlipScale(containerBlip, Config.Blip.scale) SetBlipAsShortRange(containerBlip, true) BeginTextCommandSetBlipName("STRING") @@ -215,6 +244,85 @@ local function StartContainerRobbery(container, containerType) currentContainer = nil 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) + + if not addedEntities[object] then + for _, containerType in pairs(Config.ContainerTypes) do + if model == GetHashKey(containerType.model) then + exports['qb-target']:AddTargetEntity(object, { + 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[object] = true + count = count + 1 + break + end + 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) + + if not addedEntities[vehicle] then + for _, containerType in pairs(Config.ContainerTypes) do + if model == GetHashKey(containerType.model) then + exports['qb-target']:AddTargetEntity(vehicle, { + 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[vehicle] = true + count = count + 1 + break + end + end + end + end + end + end + + return count +end + -- Command to start container robbery RegisterCommand('robcontainer', function() local container, containerType = IsNearValidContainer() @@ -229,6 +337,123 @@ RegisterCommand('robcontainer', function() 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) + +-- 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 @@ -267,6 +492,14 @@ CreateThread(function() end end) +-- Automatically scan for containers periodically +CreateThread(function() + while true do + ScanAndAddContainersToTarget() + Wait(30000) -- Scan every 30 seconds + end +end) + -- Event handler for target interaction RegisterNetEvent('container_heist:client:startRobbery', function(data) local container, _ = IsNearValidContainer() @@ -277,13 +510,26 @@ end) -- Event to show police alert RegisterNetEvent('container_heist:client:policeAlert', function(coords, streetName, containerType) + 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 = Config.Notifications.policeTitle, + title = alertTitle, description = string.format(Config.Notifications.policeMessage, streetName), type = 'inform', position = 'top', - icon = 'fas fa-exclamation-triangle', + icon = alertIcon, iconColor = '#ff0000' }) diff --git a/resources/[jobs]/[crime]/nordi_containerheist/config.lua b/resources/[jobs]/[crime]/nordi_containerheist/config.lua index fff8f9dd9..9a5a8223d 100644 --- a/resources/[jobs]/[crime]/nordi_containerheist/config.lua +++ b/resources/[jobs]/[crime]/nordi_containerheist/config.lua @@ -2,10 +2,13 @@ Config = {} -- General Settings 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.CooldownTime = 1 -- Minutes between heists (per player) +Config.GlobalCooldown = 1 -- Minutes between heists (server-wide) Config.PoliceRequired = 1 -- Minimum police required -Config.PoliceJobName = "police" -- Police job name +Config.PoliceJobs = { + "police", -- Regular police + "marshal", -- Marshal service +} -- Required Items Config.RequiredItems = { @@ -39,34 +42,35 @@ Config.Blip = { sprite = 67, color = 1, scale = 0.8, - label = "Container Robbery", + label = "Container Einbruch", duration = 180, -- seconds flash = true, } +-- Container Types +Config.ContainerTypes = { + -- Regular shipping containers -- Container Types Config.ContainerTypes = { -- Regular shipping containers { - model = "prop_container_01a", -- Container model + model = "prop_container_01a", type = "shipping", label = "Shipping Container", - offset = vector3(0.0, -4.0, 0.0), -- Player position offset for interaction - heading = 180.0, -- Player heading for interaction + 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, -- milliseconds + duration = 30000, }, rewards = { - -- Each reward has a chance (total should be <= 100) - {item = "phone_black", label = "Phone", min = 1, max = 3, chance = 30}, + {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, @@ -92,7 +96,334 @@ Config.ContainerTypes = { }, policeAlert = true, }, - -- Trailer containers + { + 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", @@ -132,11 +463,309 @@ Config.ContainerTypes = { {item = "firstaid", label = "First Aid Kit", min = 1, max = 3, chance = 30}, {item = "cash", label = "Cash", min = 500, max = 3000, chance = 20}, }, - policeAlert = false, -- No police alert for food trailers + policeAlert = false, }, - -- Add more container types as needed + { + 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 = { { diff --git a/resources/[jobs]/[crime]/nordi_containerheist/server/main.lua b/resources/[jobs]/[crime]/nordi_containerheist/server/main.lua index 3701af14d..488e20cd1 100644 --- a/resources/[jobs]/[crime]/nordi_containerheist/server/main.lua +++ b/resources/[jobs]/[crime]/nordi_containerheist/server/main.lua @@ -59,8 +59,14 @@ lib.callback.register('container_heist:server:getPoliceCount', function() for _, playerId in ipairs(players) do local Player = QBCore.Functions.GetPlayer(playerId) - if Player and Player.PlayerData.job.name == Config.PoliceJobName and Player.PlayerData.job.onduty then - policeCount = policeCount + 1 + 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 @@ -74,8 +80,14 @@ RegisterNetEvent('container_heist:server:alertPolice', function(coords, streetNa for _, playerId in ipairs(players) do local Player = QBCore.Functions.GetPlayer(playerId) - if Player and Player.PlayerData.job.name == Config.PoliceJobName and Player.PlayerData.job.onduty then - TriggerClientEvent('container_heist:client:policeAlert', playerId, coords, streetName, containerType) + 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) @@ -97,11 +109,11 @@ RegisterNetEvent('container_heist:server:finishRobbery', function(containerId, c -- 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 and itemData.info.durabilityPercent then - local newDurability = math.max(0, itemData.info.durabilityPercent - Config.RequiredItems.flex.durabilityDecrease) + 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, + serie = itemData.info.serie or "TOOL-" .. math.random(100000, 999999), usedTotalAmmo = itemData.info.usedTotalAmmo or 0, ammo = itemData.info.ammo or 0 }) @@ -158,7 +170,7 @@ RegisterNetEvent('container_heist:server:finishRobbery', function(containerId, c rewardsGiven = rewardsGiven + 1 end - end + } if rewardsGiven == 0 then TriggerClientEvent('QBCore:Notify', src, "The container was empty!", "error")