From 491ceff534098abf3ebef2d1ae1f992522d3eded Mon Sep 17 00:00:00 2001 From: Nordi98 Date: Sun, 20 Jul 2025 17:07:46 +0200 Subject: [PATCH] ed --- .../nordi_containerheist/client/main.lua | 190 +++++++++++------- .../[crime]/nordi_containerheist/config.lua | 91 ++++----- .../nordi_containerheist/fxmanifest.lua | 16 -- .../nordi_containerheist/server/main.lua | 41 ++-- 4 files changed, 186 insertions(+), 152 deletions(-) diff --git a/resources/[jobs]/[crime]/nordi_containerheist/client/main.lua b/resources/[jobs]/[crime]/nordi_containerheist/client/main.lua index c2032605b..949aa7cef 100644 --- a/resources/[jobs]/[crime]/nordi_containerheist/client/main.lua +++ b/resources/[jobs]/[crime]/nordi_containerheist/client/main.lua @@ -1,7 +1,9 @@ local QBCore = exports['qb-core']:GetCoreObject() local isRobbing = false -local currentPoint = nil +local currentZone = nil local containerBlip = nil +local inZone = false +local currentZoneId = nil -- Debug function local function Debug(msg) @@ -10,7 +12,7 @@ local function Debug(msg) end end --- Completely rewritten DrawText3D function +-- Function to draw 3D text function DrawText3D(x, y, z, text) -- Set the text properties SetTextScale(0.35, 0.35) @@ -27,22 +29,36 @@ function DrawText3D(x, y, z, text) ClearDrawOrigin() end --- Function to find the nearest container point -local function GetNearestContainerPoint() +-- Function to check if a point is inside a polygon +local function IsPointInPolygon(point, polygon) + local x, y = point.x, point.y + local inside = false + local j = #polygon + + for i = 1, #polygon do + if (polygon[i].y > y) ~= (polygon[j].y > y) and + x < (polygon[j].x - polygon[i].x) * (y - polygon[i].y) / (polygon[j].y - polygon[i].y) + polygon[i].x then + inside = not inside + end + j = i + end + + return inside +end + +-- Function to check if player is in any container zone +local function GetCurrentZone() local playerPed = PlayerPedId() local playerCoords = GetEntityCoords(playerPed) - local closestPoint = nil - local minDistance = 3.0 -- Maximum interaction distance - for _, point in pairs(Config.ContainerPoints) do - local distance = #(playerCoords - point.coords) - if distance < minDistance then - minDistance = distance - closestPoint = point + for _, zone in pairs(Config.ContainerZones) do + if IsPointInPolygon(playerCoords, zone.points) and + playerCoords.z >= zone.minZ and playerCoords.z <= zone.maxZ then + return zone end end - return closestPoint, minDistance + return nil end -- Function to create a blip at the robbery location @@ -117,18 +133,18 @@ local function PlayRobberyAnimation(containerType) end -- Function to start container robbery -local function StartContainerRobbery(point) +local function StartContainerRobbery(zone) if isRobbing then return end isRobbing = true - currentPoint = point + currentZone = zone - -- Get container type from point - local containerType = Config.ContainerTypes[point.type] + -- Get container type from zone + local containerType = Config.ContainerTypes[zone.type] if not containerType then QBCore.Functions.Notify("Invalid container type!", "error") isRobbing = false - currentPoint = nil + currentZone = nil return end @@ -137,7 +153,7 @@ local function StartContainerRobbery(point) if not hasTools then QBCore.Functions.Notify(Config.Notifications.noTools, "error") isRobbing = false - currentPoint = nil + currentZone = nil return end @@ -146,7 +162,7 @@ local function StartContainerRobbery(point) if not cooldownCheck.success then QBCore.Functions.Notify(cooldownCheck.message, "error") isRobbing = false - currentPoint = nil + currentZone = nil return end @@ -155,18 +171,15 @@ local function StartContainerRobbery(point) if policeCount < Config.PoliceRequired then QBCore.Functions.Notify(Config.Notifications.notEnoughPolice, "error") isRobbing = false - currentPoint = nil + currentZone = nil return end - -- Position player for animation - 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(point.coords.x, point.coords.y, point.coords.z)) - TriggerServerEvent('container_heist:server:alertPolice', point.coords, streetName, containerType.label) + local playerCoords = GetEntityCoords(PlayerPedId()) + local streetName = GetStreetNameFromHashKey(GetStreetNameAtCoord(playerCoords.x, playerCoords.y, playerCoords.z)) + TriggerServerEvent('container_heist:server:alertPolice', playerCoords, streetName, containerType.label) end -- Start robbery progress bar @@ -179,31 +192,31 @@ local function StartContainerRobbery(point) disableCombat = true, }, {}, {}, {}, function() -- Done -- Success - TriggerServerEvent('container_heist:server:finishRobbery', point.id, point.type) + TriggerServerEvent('container_heist:server:finishRobbery', zone.id, zone.type) QBCore.Functions.Notify(Config.Notifications.success, "success") isRobbing = false - currentPoint = nil + currentZone = nil end, function() -- Cancel -- Cancelled QBCore.Functions.Notify(Config.Notifications.failed, "error") isRobbing = false - currentPoint = nil + currentZone = nil end) end) - end, point.id) + end, zone.id) end) end --- Command to start container robbery -RegisterCommand('robcontainer', function() - local point, distance = GetNearestContainerPoint() +-- Register usable item +RegisterNetEvent('container_heist:client:useFlexItem', function() + local zone = GetCurrentZone() - if point then - StartContainerRobbery(point) + if zone then + StartContainerRobbery(zone) else - QBCore.Functions.Notify("No container nearby!", "error") + QBCore.Functions.Notify(Config.Notifications.notInZone, "error") end -end, false) +end) -- Command to toggle debug mode RegisterCommand('containerdebug', function() @@ -216,52 +229,87 @@ RegisterCommand('containerdebug', function() end end, false) --- Main thread for checking nearby container points and drawing text +-- Main thread for checking if player is in a zone CreateThread(function() while true do local sleep = 1000 - local playerPed = PlayerPedId() - local playerCoords = GetEntityCoords(playerPed) + local zone = GetCurrentZone() - for _, point in pairs(Config.ContainerPoints) do - local distance = #(playerCoords - point.coords) - - if distance < 10.0 then - sleep = 0 - - -- Draw marker at the container point - 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, 0.2, 0, 255, 0, 100, false, true, 2, false, nil, nil, false) - - -- Draw 3D text above the marker when close enough - if distance < 3.0 then - DrawText3D(point.coords.x, point.coords.y, point.coords.z + 0.5, point.label .. " [E]") - - -- Check for interaction - if IsControlJustReleased(0, 38) and distance < 1.5 then -- E key - StartContainerRobbery(point) - end - end + if zone then + if not inZone or currentZoneId ~= zone.id then + inZone = true + currentZoneId = zone.id + QBCore.Functions.Notify("You entered " .. zone.label .. ". Use your flex tool to break in.", "primary") end - end - - -- Debug mode - show all container points - 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, 0.2, 255, 0, 0, 100, false, true, 2, false, nil, nil, false) - DrawText3D(point.coords.x, point.coords.y, point.coords.z + 1.0, - point.id .. " (" .. point.type .. ")") + sleep = 500 + else + if inZone then + inZone = false + currentZoneId = nil end - sleep = 0 end Wait(sleep) end end) +-- Debug thread for visualizing zones +CreateThread(function() + while true do + Wait(0) + + if Config.Debug then + local playerPed = PlayerPedId() + local playerCoords = GetEntityCoords(playerPed) + + for _, zone in pairs(Config.ContainerZones) do + -- Draw lines connecting the points to visualize the zone + for i = 1, #zone.points do + local j = i % #zone.points + 1 + local point1 = zone.points[i] + local point2 = zone.points[j] + + -- Draw line at ground level + DrawLine( + point1.x, point1.y, zone.minZ, + point2.x, point2.y, zone.minZ, + 255, 0, 0, 255 + ) + + -- Draw line at max height + DrawLine( + point1.x, point1.y, zone.maxZ, + point2.x, point2.y, zone.maxZ, + 255, 0, 0, 255 + ) + + -- Connect min and max height + DrawLine( + point1.x, point1.y, zone.minZ, + point1.x, point1.y, zone.maxZ, + 255, 0, 0, 255 + ) + } + + -- Calculate center of zone for label + local centerX, centerY = 0, 0 + for _, point in ipairs(zone.points) do + centerX = centerX + point.x + centerY = centerY + point.y + end + centerX = centerX / #zone.points + centerY = centerY / #zone.points + + -- Draw zone label + local centerZ = (zone.minZ + zone.maxZ) / 2 + DrawText3D(centerX, centerY, centerZ, zone.id .. " (" .. zone.type .. ")") + end + else + Wait(1000) + end + end +end) + -- Event to show police alert RegisterNetEvent('container_heist:client:policeAlert', function(coords, streetName, containerLabel) local playerJob = QBCore.Functions.GetPlayerData().job.name diff --git a/resources/[jobs]/[crime]/nordi_containerheist/config.lua b/resources/[jobs]/[crime]/nordi_containerheist/config.lua index 61a16286d..e1904d6e0 100644 --- a/resources/[jobs]/[crime]/nordi_containerheist/config.lua +++ b/resources/[jobs]/[crime]/nordi_containerheist/config.lua @@ -36,6 +36,7 @@ Config.Notifications = { notEnoughPolice = "Not enough police in the city!", policeMessage = "Container robbery in progress at %s", alreadyRobbed = "This container has already been robbed recently!", + notInZone = "You need to be in a container area to use this tool!", } -- Blip Settings @@ -129,71 +130,67 @@ Config.ContainerTypes = { }, } --- Container Points (specific locations for container robberies) -Config.ContainerPoints = { +-- Container Zones (defined by 4 points) +Config.ContainerZones = { -- Port area shipping containers { - id = "port_container_1", + id = "port_containers", type = "shipping", -- References the container type above for rewards - coords = vector3(896.4, -2967.91, 5.9), - heading = 90.0, - label = "Break into Container" - }, - { - id = "port_container_2", - type = "shipping", - coords = vector3(990.23, -3050.34, 5.90), - heading = 90.0, - label = "Break into Container" + label = "Port Containers", + points = { + vector3(896.4, -2967.91, 5.9), -- Point 1 + vector3(896.4, -2957.91, 5.9), -- Point 2 + vector3(886.4, -2957.91, 5.9), -- Point 3 + vector3(886.4, -2967.91, 5.9) -- Point 4 + }, + minZ = 4.0, + maxZ = 15.0, }, -- Weapons containers { - id = "weapons_container_1", + id = "weapons_containers", 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" + label = "Weapons Containers", + points = { + vector3(905.45, -3200.67, 5.90), -- Point 1 + vector3(905.45, -3190.67, 5.90), -- Point 2 + vector3(895.45, -3190.67, 5.90), -- Point 3 + vector3(895.45, -3200.67, 5.90) -- Point 4 + }, + minZ = 4.0, + maxZ = 15.0, }, -- Cargo trailers { - id = "cargo_trailer_1", + id = "cargo_trailers", 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" + label = "Cargo Trailers", + points = { + vector3(825.34, -3125.45, 5.90), -- Point 1 + vector3(825.34, -3115.45, 5.90), -- Point 2 + vector3(815.34, -3115.45, 5.90), -- Point 3 + vector3(815.34, -3125.45, 5.90) -- Point 4 + }, + minZ = 4.0, + maxZ = 15.0, }, -- Food trailers { - id = "food_trailer_1", + id = "food_trailers", 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" + label = "Food Trailers", + points = { + vector3(765.23, -3165.34, 5.90), -- Point 1 + vector3(765.23, -3155.34, 5.90), -- Point 2 + vector3(755.23, -3155.34, 5.90), -- Point 3 + vector3(755.23, -3165.34, 5.90) -- Point 4 + }, + minZ = 4.0, + maxZ = 15.0, }, - -- Add more points as needed + -- Add more zones as needed } diff --git a/resources/[jobs]/[crime]/nordi_containerheist/fxmanifest.lua b/resources/[jobs]/[crime]/nordi_containerheist/fxmanifest.lua index dbc2d0566..40283c2a5 100644 --- a/resources/[jobs]/[crime]/nordi_containerheist/fxmanifest.lua +++ b/resources/[jobs]/[crime]/nordi_containerheist/fxmanifest.lua @@ -6,21 +6,5 @@ author 'Your Name' version '1.0.0' shared_scripts { - '@ox_lib/init.lua', 'config.lua' } - -client_scripts { - 'client.lua' -} - -server_scripts { - 'server.lua' -} - -lua54 'yes' - -dependencies { - 'ox_lib', - 'qb-core' -} diff --git a/resources/[jobs]/[crime]/nordi_containerheist/server/main.lua b/resources/[jobs]/[crime]/nordi_containerheist/server/main.lua index 6fae7d1a8..7b2a4be1c 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 pointCooldowns = {} +local zoneCooldowns = {} local playerCooldowns = {} local globalCooldowns = {} @@ -10,6 +10,11 @@ local function Debug(msg) end end +-- Register usable item +QBCore.Functions.CreateUseableItem(Config.RequiredItems.flex.name, function(source) + TriggerClientEvent('container_heist:client:useFlexItem', source) +end) + -- Check if player has required items QBCore.Functions.CreateCallback('container_heist:server:checkRequiredItems', function(source, cb) local src = source @@ -22,7 +27,7 @@ QBCore.Functions.CreateCallback('container_heist:server:checkRequiredItems', fun end) -- Check cooldowns -QBCore.Functions.CreateCallback('container_heist:server:checkCooldown', function(source, cb, pointId) +QBCore.Functions.CreateCallback('container_heist:server:checkCooldown', function(source, cb, zoneId) local src = source local Player = QBCore.Functions.GetPlayer(src) if not Player then return cb({success = false, message = "Player not found"}) end @@ -36,27 +41,27 @@ QBCore.Functions.CreateCallback('container_heist:server:checkCooldown', function return cb({success = false, message = "You need to wait " .. timeLeft .. " more minutes before attempting another heist!"}) end - -- Check point cooldown - if pointCooldowns[pointId] and (currentTime - pointCooldowns[pointId]) < (Config.CooldownTime * 60) then + -- Check zone cooldown + if zoneCooldowns[zoneId] and (currentTime - zoneCooldowns[zoneId]) < (Config.CooldownTime * 60) then return cb({success = false, message = Config.Notifications.alreadyRobbed}) end - -- Find point type - local pointType = nil - for _, point in pairs(Config.ContainerPoints) do - if point.id == pointId then - pointType = point.type + -- Find zone type + local zoneType = nil + for _, zone in pairs(Config.ContainerZones) do + if zone.id == zoneId then + zoneType = zone.type break end end - if not pointType then - return cb({success = false, message = "Invalid point!"}) + if not zoneType then + return cb({success = false, message = "Invalid zone!"}) 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) + if globalCooldowns[zoneType] and (currentTime - globalCooldowns[zoneType]) < (Config.GlobalCooldown * 60) then + local timeLeft = math.ceil(((globalCooldowns[zoneType] + (Config.GlobalCooldown * 60)) - currentTime) / 60) return cb({success = false, message = Config.Notifications.globalCooldown .. " (" .. timeLeft .. " minutes left)"}) end @@ -104,7 +109,7 @@ RegisterNetEvent('container_heist:server:alertPolice', function(coords, streetNa end) -- Finish robbery and give rewards -RegisterNetEvent('container_heist:server:finishRobbery', function(pointId, containerTypeName) +RegisterNetEvent('container_heist:server:finishRobbery', function(zoneId, containerTypeName) local src = source local Player = QBCore.Functions.GetPlayer(src) if not Player then return end @@ -114,7 +119,7 @@ RegisterNetEvent('container_heist:server:finishRobbery', function(pointId, conta -- Set cooldowns playerCooldowns[citizenId] = currentTime - pointCooldowns[pointId] = currentTime + zoneCooldowns[zoneId] = currentTime globalCooldowns[containerTypeName] = currentTime -- Get container type @@ -194,10 +199,10 @@ CreateThread(function() end end - -- Clean up point cooldowns - for pointId, cooldownTime in pairs(pointCooldowns) do + -- Clean up zone cooldowns + for zoneId, cooldownTime in pairs(zoneCooldowns) do if (currentTime - cooldownTime) > (Config.CooldownTime * 60) then - pointCooldowns[pointId] = nil + zoneCooldowns[zoneId] = nil end end