From 465cd1d99d239dac408c96bb72a83851901676f8 Mon Sep 17 00:00:00 2001 From: Nordi98 Date: Sun, 20 Jul 2025 18:21:09 +0200 Subject: [PATCH] Update main.lua --- .../nordi_containerheist/client/main.lua | 676 ++---------------- 1 file changed, 49 insertions(+), 627 deletions(-) diff --git a/resources/[jobs]/[crime]/nordi_containerheist/client/main.lua b/resources/[jobs]/[crime]/nordi_containerheist/client/main.lua index ff6071d9a..75178bd53 100644 --- a/resources/[jobs]/[crime]/nordi_containerheist/client/main.lua +++ b/resources/[jobs]/[crime]/nordi_containerheist/client/main.lua @@ -1,632 +1,54 @@ -local QBCore = exports['qb-core']:GetCoreObject() -local isRobbing = false -local currentContainer = nil -local containerBlip = nil -local addedEntities = {} - --- Debug function -local function Debug(msg) - if Config.Debug then - print("[Container Heist] " .. 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 at the correct position (rear for trailers, door for containers) -local function IsPlayerAtCorrectPosition(entity, containerType) - local playerPos = GetEntityCoords(PlayerPedId()) - local entityPos = GetEntityCoords(entity) - local entityHeading = GetEntityHeading(entity) - local entityForwardVector = GetEntityForwardVector(entity) - - -- Get vector from entity to player - local toPlayerVector = vector3( - playerPos.x - entityPos.x, - playerPos.y - entityPos.y, - 0.0 - ) - - -- Normalize the vector - local length = math.sqrt(toPlayerVector.x^2 + toPlayerVector.y^2) - if length > 0 then - toPlayerVector = vector3(toPlayerVector.x / length, toPlayerVector.y / length, 0.0) - else - return false - end - - -- Calculate dot product with forward vector - local forwardDot = toPlayerVector.x * entityForwardVector.x + toPlayerVector.y * entityForwardVector.y - - if string.match(containerType.type, "trailer") then - -- For trailers, player should be at the rear (negative dot product) - return forwardDot < -0.7 -- Threshold to ensure player is behind the trailer - else - -- For containers, player should be at the door (positive dot product) - return forwardDot > 0.7 -- Threshold to ensure player is in front of the container - end -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 (objects) - 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 <= 5.0 and distance < closestDistance then - for _, containerType in pairs(Config.ContainerTypes) do - if model == GetHashKey(containerType.model) then - -- Check if player is at the door for containers - if IsPlayerAtCorrectPosition(object, containerType) then - foundEntity = object - foundType = containerType - closestDistance = distance - break - else - lib.notify({ - title = Config.Notifications.title, - description = "You need to stand at the door of the container!", - type = 'error' - }) - 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 model = GetEntityModel(vehicle) - local vehicleCoords = GetEntityCoords(vehicle) - local distance = #(playerCoords - vehicleCoords) - - if distance <= 5.0 and distance < closestDistance then - for _, containerType in pairs(Config.ContainerTypes) do - if model == GetHashKey(containerType.model) then - -- Check if player is at the rear for trailers - if IsPlayerAtCorrectPosition(vehicle, containerType) then - foundEntity = vehicle - foundType = containerType - closestDistance = distance - break - else - lib.notify({ - title = Config.Notifications.title, - description = "You need to stand at the rear of the trailer!", - type = 'error' - }) - end - end - end - end - end - end - - return foundEntity, foundType -end - --- Function to create a blip at the robbery location -local function CreateRobberyBlip(coords) - if containerBlip then - RemoveBlip(containerBlip) - 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) - SetBlipScale(containerBlip, Config.Blip.scale) - SetBlipAsShortRange(containerBlip, true) - BeginTextCommandSetBlipName("STRING") - AddTextComponentString(Config.Blip.label) - EndTextCommandSetBlipName(containerBlip) - - if Config.Blip.flash then - SetBlipFlashes(containerBlip, true) - end - - -- Remove blip after duration - SetTimeout(Config.Blip.duration * 1000, function() - if containerBlip then - RemoveBlip(containerBlip) - containerBlip = nil - end - end) -end - --- Function to play container robbery animation -local function PlayRobberyAnimation(containerType) - local playerPed = PlayerPedId() - local animDict = containerType.animation.dict - local animName = containerType.animation.name - - RequestAnimDict(animDict) - while not HasAnimDictLoaded(animDict) do - Wait(10) - end - - TaskPlayAnim(playerPed, animDict, animName, 8.0, -8.0, containerType.animation.duration, containerType.animation.flag, 0, false, false, false) - - -- Add particle effects for welding - local boneIndex = GetPedBoneIndex(playerPed, 28422) - local particleDict = "core" - local particleName = "ent_amb_welding" - - RequestNamedPtfxAsset(particleDict) - while not HasNamedPtfxAssetLoaded(particleDict) do - Wait(10) - end - - UseParticleFxAssetNextCall(particleDict) - local particleHandle = StartParticleFxLoopedOnPedBone(particleName, playerPed, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, boneIndex, 0.5, false, false, false) - - -- Clean up after animation - SetTimeout(containerType.animation.duration, function() - StopParticleFxLooped(particleHandle, 0) - StopAnimTask(playerPed, animDict, animName, 1.0) - end) -end - --- Function to start container robbery -local function StartContainerRobbery(container, containerType) - if isRobbing then return end - - isRobbing = true - currentContainer = container - - -- 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' - }) - isRobbing = false - currentContainer = nil - return - end - - -- Check cooldowns - local cooldownCheck = lib.callback.await('container_heist:server:checkCooldown', false, NetworkGetNetworkIdFromEntity(container)) - if not cooldownCheck.success then - lib.notify({ - title = Config.Notifications.title, - description = cooldownCheck.message, - type = 'error' - }) - isRobbing = false - currentContainer = 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' - }) - isRobbing = false - currentContainer = nil - return - end - - -- Get container dimensions - local containerModel = GetEntityModel(container) - local min, max = GetModelDimensions(containerModel) - local containerLength = max.y - min.y - - -- Position player for animation - local containerCoords = GetEntityCoords(container) - local containerHeading = GetEntityHeading(container) - local offsetCoords - local playerHeading - - -- Check if this is a trailer type - if string.match(containerType.type, "trailer") then - -- For trailers, position at the rear - offsetCoords = GetOffsetFromEntityInWorldCoords(container, 0.0, -(containerLength/2 + 1.0), 0.0) - playerHeading = containerHeading + 180.0 -- Face the rear of the trailer - else - -- For containers, position at the door (front) - offsetCoords = GetOffsetFromEntityInWorldCoords(container, 0.0, containerLength/2 + 1.0, 0.0) - playerHeading = containerHeading -- Face the front of the container - end - - -- Set player position and heading - SetEntityCoords(PlayerPedId(), offsetCoords.x, offsetCoords.y, offsetCoords.z) - SetEntityHeading(PlayerPedId(), playerHeading) - - -- 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) - 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 - -- Success - TriggerServerEvent('container_heist:server:finishRobbery', NetworkGetNetworkIdFromEntity(container), containerType.type) - lib.notify({ - title = Config.Notifications.title, - description = Config.Notifications.success, - type = 'success' - }) - else - -- Cancelled - lib.notify({ - title = Config.Notifications.title, - description = Config.Notifications.failed, - type = 'error' - }) - end - - isRobbing = false - 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 = { +['hafenarbeiter'] = { + label = 'Red mit dem Hafenarbeiter', + icon = 'fa-solid fa-hard-hat', + model = "s_m_m_dockwork_01", + coords = vector3(1234.56, -3210.45, 5.9), -- Koordinaten anpassen + heading = 90, + data = { + firstname = 'Kalle', + lastname = 'Kutter', + text = "Moin... du wirkst nich wie jemand, der hier offiziell was abholen will.", + buttons = { + { + text = "Kommt drauf an, was es hier so gibt...", + data = { + text = "Hehehe... naja, sagen wir mal so: Manche Container stehen nachts ein bisschen... unbeaufsichtigt rum.", + buttons = { + { + text = "Ach ja? Und dann?", + data = { + text = "Na, wenn einer wüsste, wie man da *rein* kommt... bräuchte er sicher was mit Zähne oder Strom, verstehste?", + buttons = { { - type = "client", - event = "container_heist:client:startRobbery", - icon = "fas fa-angle-double-right", - label = "Break into " .. containerType.label, - containerType = containerType, - canInteract = function(entity) - return IsPlayerAtCorrectPosition(entity, containerType) - end - } - }, - 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 = { + text = "Klar. Ich versteh schon.", + data = { + text = "Gut. Dann hab ich dir ja nix gesagt, oder?", + buttons = { + { + text = "Du hast mich nie gesehen.", + close = true + } + } + } + }, { - type = "client", - event = "container_heist:client:startRobbery", - icon = "fas fa-angle-double-right", - label = "Break into " .. containerType.label, - containerType = containerType, - canInteract = function(entity) - return IsPlayerAtCorrectPosition(entity, containerType) - end + text = "Klingt mir zu heiß...", + close = true } - }, - 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() - if container and containerType then - StartContainerRobbery(container, containerType) - else - lib.notify({ - title = Config.Notifications.title, - description = "No valid container nearby!", - type = '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) - --- 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, - canInteract = function(entity) - return IsPlayerAtCorrectPosition(entity, containerType) - end + } + } + }, + { + text = "Ich glaub, ich hab mich verlaufen...", + close = true + } + } } }, - 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) - --- 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() - if container then - StartContainerRobbery(container, data.containerType) - end -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 = alertTitle, - description = string.format(Config.Notifications.policeMessage, streetName), - type = 'inform', - position = 'top', - icon = alertIcon, - iconColor = '#ff0000' - }) - - -- Add blip to map - CreateRobberyBlip(coords) - - -- Play alert sound - PlaySound(-1, "Lose_1st", "GTAO_FM_Events_Soundset", 0, 0, 1) -end) - --- Clean up on resource stop -AddEventHandler('onResourceStop', function(resourceName) - if resourceName == GetCurrentResourceName() then - if containerBlip then - RemoveBlip(containerBlip) - end - - if isRobbing and currentContainer then - StopAnimTask(PlayerPedId(), "amb@world_human_welding@male@base", "base", 1.0) - end - end -end) + { + text = "Nur mal umschauen, Chef.", + close = true + } + } + } +}