diff --git a/resources/[jobs]/[crime]/nordi_containerheist/client/main.lua b/resources/[jobs]/[crime]/nordi_containerheist/client/main.lua index 79acc1147..6ae1c6983 100644 --- a/resources/[jobs]/[crime]/nordi_containerheist/client/main.lua +++ b/resources/[jobs]/[crime]/nordi_containerheist/client/main.lua @@ -1,7 +1,5 @@ local QBCore = exports['qb-core']:GetCoreObject() local isRobbing = false -local currentZone = nil -local containerBlip = nil local inZone = false local currentZoneId = nil @@ -12,23 +10,6 @@ local function Debug(msg) end end --- Function to draw 3D text -function DrawText3D(x, y, z, text) - -- Set the text properties - SetTextScale(0.35, 0.35) - SetTextFont(4) - SetTextProportional(1) - SetTextColour(255, 255, 255, 215) - SetTextEntry("STRING") - SetTextCentre(1) - AddTextComponentString(text) - SetDrawOrigin(x, y, z, 0) - DrawText(0.0, 0.0) - local factor = (string.len(text)) / 370 - DrawRect(0.0, 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75) - ClearDrawOrigin() -end - -- Function to check if a point is inside a polygon local function IsPointInPolygon(point, polygon) local x, y = point.x, point.y @@ -61,196 +42,47 @@ local function GetCurrentZone() return nil end --- Function to create a blip at the robbery location -local function CreateRobberyBlip(coords) - if containerBlip then - RemoveBlip(containerBlip) - end +-- Simple command to test if the script is working +RegisterCommand('containertest', function() + local playerCoords = GetEntityCoords(PlayerPedId()) + print("Player coords: " .. playerCoords.x .. ", " .. playerCoords.y .. ", " .. playerCoords.z) - 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 + local zone = GetCurrentZone() + if zone then + QBCore.Functions.Notify("You are in zone: " .. zone.id, "success") + print("In zone: " .. zone.id) else - SetBlipColour(containerBlip, Config.Blip.color) -- Default color for regular police + QBCore.Functions.Notify("You are not in any container zone", "error") + print("Not in any zone") 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 +end, false) --- Function to play container robbery animation -local function PlayRobberyAnimation(containerType) - local playerPed = PlayerPedId() - local animDict = containerType.animation.dict - local animName = containerType.animation.name +-- Command to start robbery (for testing) +RegisterCommand('robcontainer', function() + local zone = GetCurrentZone() - RequestAnimDict(animDict) - while not HasAnimDictLoaded(animDict) do - Wait(10) + if zone then + QBCore.Functions.Notify("Starting robbery in zone: " .. zone.id, "success") + TriggerServerEvent('container_heist:server:testRobbery', zone.id, zone.type) + else + QBCore.Functions.Notify("You are not in any container zone", "error") 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 +end, false) --- Function to start container robbery -local function StartContainerRobbery(zone) - if isRobbing then return end - - isRobbing = true - currentZone = zone - - -- Get container type from zone - local containerType = Config.ContainerTypes[zone.type] - if not containerType then - QBCore.Functions.Notify("Invalid container type!", "error") - isRobbing = false - currentZone = nil - return - end - - -- Check if player has required tools - QBCore.Functions.TriggerCallback('container_heist:server:checkRequiredItems', function(hasTools) - if not hasTools then - QBCore.Functions.Notify(Config.Notifications.noTools, "error") - isRobbing = false - currentZone = nil - return - end - - -- Check cooldowns - QBCore.Functions.TriggerCallback('container_heist:server:checkCooldown', function(cooldownCheck) - if not cooldownCheck.success then - QBCore.Functions.Notify(cooldownCheck.message, "error") - isRobbing = false - currentZone = nil - return - end - - -- Check police count - QBCore.Functions.TriggerCallback('container_heist:server:getPoliceCount', function(policeCount) - if policeCount < Config.PoliceRequired then - QBCore.Functions.Notify(Config.Notifications.notEnoughPolice, "error") - isRobbing = false - currentZone = nil - return - end - - -- Alert police if configured - if containerType.policeAlert then - 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 - PlayRobberyAnimation(containerType) - - 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', zone.id, zone.type) - QBCore.Functions.Notify(Config.Notifications.success, "success") - isRobbing = false - currentZone = nil - end, function() -- Cancel - -- Cancelled - QBCore.Functions.Notify(Config.Notifications.failed, "error") - isRobbing = false - currentZone = nil - end) - end) - end, zone.id) - end) -end - --- Register usable item event handler - FIXED VERSION +-- Register usable item event handler RegisterNetEvent('container_heist:client:useFlexItem', function() - Debug("useFlexItem event triggered") + print("useFlexItem event triggered") local zone = GetCurrentZone() if zone then - Debug("Player is in zone: " .. zone.id) - StartContainerRobbery(zone) + print("Player is in zone: " .. zone.id) + QBCore.Functions.Notify("Starting robbery with flex tool in zone: " .. zone.id, "success") + TriggerServerEvent('container_heist:server:testRobbery', zone.id, zone.type) else QBCore.Functions.Notify(Config.Notifications.notInZone, "error") end end) --- Alternative method to handle item use -RegisterNetEvent('inventory:client:UseItem', function(item) - if item.name == Config.RequiredItems.flex.name then - Debug("Used item via inventory:client:UseItem: " .. item.name) - TriggerEvent('container_heist:client:useFlexItem') - end -end) - --- Command to test the robbery (for debugging) -RegisterCommand('testcontainerrob', function() - local zone = GetCurrentZone() - - if zone then - Debug("Testing robbery in zone: " .. zone.id) - StartContainerRobbery(zone) - else - QBCore.Functions.Notify(Config.Notifications.notInZone, "error") - end -end, false) - --- Command to toggle debug mode -RegisterCommand('containerdebug', function() - Config.Debug = not Config.Debug - - if Config.Debug then - QBCore.Functions.Notify("Container Debug mode enabled", "primary") - else - QBCore.Functions.Notify("Container Debug mode disabled", "primary") - end -end, false) - -- Main thread for checking if player is in a zone CreateThread(function() while true do @@ -262,14 +94,14 @@ CreateThread(function() inZone = true currentZoneId = zone.id QBCore.Functions.Notify("You entered " .. zone.label .. ". Use your flex tool to break in.", "primary") - Debug("Entered zone: " .. zone.id) + print("Entered zone: " .. zone.id) end sleep = 500 else if inZone then inZone = false currentZoneId = nil - Debug("Left zone") + print("Left zone") end end @@ -280,8 +112,6 @@ end) -- Debug thread for visualizing zones CreateThread(function() while true do - Wait(0) - if Config.Debug then local playerPed = PlayerPedId() local playerCoords = GetEntityCoords(playerPed) @@ -299,21 +129,7 @@ CreateThread(function() 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 - ) - } + end -- Calculate center of zone for label local centerX, centerY = 0, 0 @@ -326,52 +142,35 @@ CreateThread(function() -- Draw zone label local centerZ = (zone.minZ + zone.maxZ) / 2 - DrawText3D(centerX, centerY, centerZ, zone.id .. " (" .. zone.type .. ")") - } + DrawTextOnCoord(centerX, centerY, centerZ, zone.id .. " (" .. zone.type .. ")") + end + Wait(0) 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 - local alertTitle = Config.Notifications.policeTitle - - -- Customize alert based on job - if playerJob == "marshal" then - alertTitle = "MARSHAL SERVICE ALERT" - elseif playerJob == "sheriff" then - alertTitle = "SHERIFF DEPARTMENT ALERT" +-- Function to draw text in 3D space +function DrawTextOnCoord(x, y, z, text) + local onScreen, _x, _y = World3dToScreen2d(x, y, z) + if onScreen then + SetTextScale(0.35, 0.35) + SetTextFont(4) + SetTextProportional(1) + SetTextColour(255, 255, 255, 215) + SetTextEntry("STRING") + SetTextCentre(1) + AddTextComponentString(text) + DrawText(_x, _y) + local factor = (string.len(text)) / 370 + DrawRect(_x, _y + 0.0125, 0.015 + factor, 0.03, 0, 0, 0, 75) end - - -- Create alert for police officers - QBCore.Functions.Notify(alertTitle .. ": " .. string.format(Config.Notifications.policeMessage, streetName), "police", 10000) - - -- 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 then - StopAnimTask(PlayerPedId(), "amb@world_human_welding@male@base", "base", 1.0) - end - end -end) +end -- Print message when resource starts AddEventHandler('onClientResourceStart', function(resourceName) if (GetCurrentResourceName() == resourceName) then - Debug("Client script started successfully") + print("^2[Container Heist]^7: Client script started successfully") end end) diff --git a/resources/[jobs]/[crime]/nordi_containerheist/config.lua b/resources/[jobs]/[crime]/nordi_containerheist/config.lua index 1c0bb6d06..79899a50c 100644 --- a/resources/[jobs]/[crime]/nordi_containerheist/config.lua +++ b/resources/[jobs]/[crime]/nordi_containerheist/config.lua @@ -8,7 +8,6 @@ Config.PoliceRequired = 1 -- Minimum police required Config.PoliceJobs = { "police", -- Regular police "marshal", -- Marshal service - "sheriff" -- Sheriff department } -- Required Items diff --git a/resources/[jobs]/[crime]/nordi_containerheist/server/main.lua b/resources/[jobs]/[crime]/nordi_containerheist/server/main.lua index b33b3c346..d980b6d1a 100644 --- a/resources/[jobs]/[crime]/nordi_containerheist/server/main.lua +++ b/resources/[jobs]/[crime]/nordi_containerheist/server/main.lua @@ -1,7 +1,4 @@ local QBCore = exports['qb-core']:GetCoreObject() -local zoneCooldowns = {} -local playerCooldowns = {} -local globalCooldowns = {} -- Debug function local function Debug(msg) @@ -10,226 +7,30 @@ local function Debug(msg) end end --- Register usable item - FIXED VERSION -QBCore.Functions.CreateUseableItem(Config.RequiredItems.flex.name, function(source, item) - local src = source - Debug("Player " .. src .. " used item: " .. Config.RequiredItems.flex.name) - TriggerClientEvent('container_heist:client:useFlexItem', src) +-- Register usable item +QBCore.Functions.CreateUseableItem(Config.RequiredItems.flex.name, function(source) + print("Player " .. source .. " used item: " .. Config.RequiredItems.flex.name) + 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 - local Player = QBCore.Functions.GetPlayer(src) - if not Player then return cb(false) end - - -- Check for required flex tool - local hasItem = exports['tgiann-inventory']:HasItem(src, Config.RequiredItems.flex.name, Config.RequiredItems.flex.amount) - Debug("Player " .. src .. " has required item: " .. tostring(hasItem)) - cb(hasItem) -end) - --- Check cooldowns -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 - - local citizenId = Player.PlayerData.citizenid - local currentTime = os.time() - - -- Check player cooldown - if playerCooldowns[citizenId] and (currentTime - playerCooldowns[citizenId]) < (Config.CooldownTime * 60) then - local timeLeft = math.ceil(((playerCooldowns[citizenId] + (Config.CooldownTime * 60)) - currentTime) / 60) - return cb({success = false, message = "You need to wait " .. timeLeft .. " more minutes before attempting another heist!"}) - end - - -- Check zone cooldown - if zoneCooldowns[zoneId] and (currentTime - zoneCooldowns[zoneId]) < (Config.CooldownTime * 60) then - return cb({success = false, message = Config.Notifications.alreadyRobbed}) - end - - -- 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 zoneType then - return cb({success = false, message = "Invalid zone!"}) - end - - -- Check global cooldown for container type - 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 - - cb({success = true}) -end) - --- Get police count -QBCore.Functions.CreateCallback('container_heist:server:getPoliceCount', function(source, cb) - local policeCount = 0 - local players = QBCore.Functions.GetPlayers() - - for _, playerId in ipairs(players) do - local Player = QBCore.Functions.GetPlayer(playerId) - if Player then - -- Check if player's job is in the list of police jobs - for _, jobName in ipairs(Config.PoliceJobs) do - if Player.PlayerData.job.name == jobName and Player.PlayerData.job.onduty then - policeCount = policeCount + 1 - break -- No need to check other job names for this player - end - end - end - end - - cb(policeCount) -end) - --- Alert police -RegisterNetEvent('container_heist:server:alertPolice', function(coords, streetName, containerLabel) - local src = source - local players = QBCore.Functions.GetPlayers() - - for _, playerId in ipairs(players) do - local Player = QBCore.Functions.GetPlayer(playerId) - if Player then - -- Check if player's job is in the list of police jobs - for _, jobName in ipairs(Config.PoliceJobs) do - if Player.PlayerData.job.name == jobName and Player.PlayerData.job.onduty then - TriggerClientEvent('container_heist:client:policeAlert', playerId, coords, streetName, containerLabel) - break -- No need to send multiple alerts to the same player - end - end - end - end -end) - --- Finish robbery and give rewards -RegisterNetEvent('container_heist:server:finishRobbery', function(zoneId, containerTypeName) +-- Test robbery event +RegisterNetEvent('container_heist:server:testRobbery', function(zoneId, zoneType) local src = source local Player = QBCore.Functions.GetPlayer(src) if not Player then return end - local citizenId = Player.PlayerData.citizenid - local currentTime = os.time() + print("Player " .. src .. " started robbery in zone: " .. zoneId .. " of type: " .. zoneType) + TriggerClientEvent('QBCore:Notify', src, "Robbery started in zone: " .. zoneId, "success") - -- Set cooldowns - playerCooldowns[citizenId] = currentTime - zoneCooldowns[zoneId] = 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 - local itemData = exports['tgiann-inventory']:GetItemByName(src, Config.RequiredItems.flex.name) - if itemData and itemData.info then - local newDurability = math.max(0, (itemData.info.durabilityPercent or 100) - Config.RequiredItems.flex.durabilityDecrease) - exports['tgiann-inventory']:UpdateItemMetadata(src, Config.RequiredItems.flex.name, itemData.slot, { - durabilityPercent = newDurability, - serie = itemData.info.serie or "TOOL-" .. math.random(100000, 999999), - usedTotalAmmo = itemData.info.usedTotalAmmo or 0, - ammo = itemData.info.ammo or 0 - }) - - -- Remove item if durability reaches 0 - if newDurability <= 0 and Config.RequiredItems.flex.remove then - exports['tgiann-inventory']:RemoveItem(src, Config.RequiredItems.flex.name, 1) - TriggerClientEvent('QBCore:Notify', src, "Your " .. Config.RequiredItems.flex.label .. " broke!", "error") - end - end - elseif Config.RequiredItems.flex.remove then - -- Remove item if configured - exports['tgiann-inventory']:RemoveItem(src, Config.RequiredItems.flex.name, Config.RequiredItems.flex.amount) - end - - -- Give rewards based on chances - local rewardsGiven = 0 - for _, reward in pairs(containerType.rewards) do - if math.random(1, 100) <= reward.chance then - local amount = math.random(reward.min, reward.max) - - if reward.item == "cash" then - Player.Functions.AddMoney("cash", amount) - TriggerClientEvent('QBCore:Notify', src, "Found $" .. amount, "success") - else - -- Add item with proper metadata for weapons - if string.match(reward.item, "weapon_") then - exports['tgiann-inventory']:AddItem(src, reward.item, amount, nil, { - serie = "HEIST-" .. math.random(100000, 999999), - durabilityPercent = 100, - usedTotalAmmo = 0, - ammo = 0 - }) - else - exports['tgiann-inventory']:AddItem(src, reward.item, amount) - end - - TriggerClientEvent('QBCore:Notify', src, "Found " .. amount .. "x " .. reward.label, "success") - end - - rewardsGiven = rewardsGiven + 1 - end - end - - if rewardsGiven == 0 then - TriggerClientEvent('QBCore:Notify', src, "The container was empty!", "error") - end -end) - --- Clean up cooldowns periodically -CreateThread(function() - while true do - Wait(60000) -- Check every minute - local currentTime = os.time() - - -- Clean up player cooldowns - for citizenId, cooldownTime in pairs(playerCooldowns) do - if (currentTime - cooldownTime) > (Config.CooldownTime * 60) then - playerCooldowns[citizenId] = nil - end - end - - -- Clean up zone cooldowns - for zoneId, cooldownTime in pairs(zoneCooldowns) do - if (currentTime - cooldownTime) > (Config.CooldownTime * 60) then - zoneCooldowns[zoneId] = nil - end - end - - -- Clean up global cooldowns - for containerType, cooldownTime in pairs(globalCooldowns) do - if (currentTime - cooldownTime) > (Config.GlobalCooldown * 60) then - globalCooldowns[containerType] = nil - end - end - end -end) - --- Alternative method to register usable item for tgiann-inventory -RegisterNetEvent('QBCore:Server:UseItem', function(source, item) - if item.name == Config.RequiredItems.flex.name then - Debug("Player " .. source .. " used item via QBCore:Server:UseItem: " .. item.name) - TriggerClientEvent('container_heist:client:useFlexItem', source) - end + -- Give a test reward + exports['tgiann-inventory']:AddItem(src, "cash", 1000) + TriggerClientEvent('QBCore:Notify', src, "You found $1000!", "success") end) -- Print message when resource starts AddEventHandler('onResourceStart', function(resourceName) if (GetCurrentResourceName() == resourceName) then - print('^2[Container Heist]^7: Script started successfully') - print('^2[Container Heist]^7: Registered usable item: ' .. Config.RequiredItems.flex.name) + print("^2[Container Heist]^7: Server script started successfully") + print("^2[Container Heist]^7: Registered usable item: " .. Config.RequiredItems.flex.name) end end)