forked from Simnation/Main
298 lines
10 KiB
Lua
298 lines
10 KiB
Lua
local QBCore = exports['qb-core']:GetCoreObject()
|
|
local isRobbing = false
|
|
local currentPoint = nil
|
|
local containerBlip = nil
|
|
|
|
-- Debug function
|
|
local function Debug(msg)
|
|
if Config.Debug then
|
|
print("[Container Heist] " .. msg)
|
|
end
|
|
end
|
|
|
|
-- Completely rewritten DrawText3D function
|
|
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 find the nearest container point
|
|
local function GetNearestContainerPoint()
|
|
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
|
|
end
|
|
end
|
|
|
|
return closestPoint, minDistance
|
|
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(point)
|
|
if isRobbing then return end
|
|
|
|
isRobbing = true
|
|
currentPoint = point
|
|
|
|
-- Get container type from point
|
|
local containerType = Config.ContainerTypes[point.type]
|
|
if not containerType then
|
|
QBCore.Functions.Notify("Invalid container type!", "error")
|
|
isRobbing = false
|
|
currentPoint = nil
|
|
return
|
|
end
|
|
|
|
-- Check if player has required tools
|
|
QBCore.Functions.TriggerCallback('container_heist:server:checkRequiredItems', function(hasTools)
|
|
if not hasTools then
|
|
QBCore.Functions.Notify(Config.Notifications.noTools, "error")
|
|
isRobbing = false
|
|
currentPoint = 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
|
|
currentPoint = 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
|
|
currentPoint = 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)
|
|
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', point.id, point.type)
|
|
QBCore.Functions.Notify(Config.Notifications.success, "success")
|
|
isRobbing = false
|
|
currentPoint = nil
|
|
end, function() -- Cancel
|
|
-- Cancelled
|
|
QBCore.Functions.Notify(Config.Notifications.failed, "error")
|
|
isRobbing = false
|
|
currentPoint = nil
|
|
end)
|
|
end)
|
|
end, point.id)
|
|
end)
|
|
end
|
|
|
|
-- Command to start container robbery
|
|
RegisterCommand('robcontainer', function()
|
|
local point, distance = GetNearestContainerPoint()
|
|
|
|
if point then
|
|
StartContainerRobbery(point)
|
|
else
|
|
QBCore.Functions.Notify("No container nearby!", "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 nearby container points and drawing text
|
|
CreateThread(function()
|
|
while true do
|
|
local sleep = 1000
|
|
local playerPed = PlayerPedId()
|
|
local playerCoords = GetEntityCoords(playerPed)
|
|
|
|
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
|
|
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 .. ")")
|
|
end
|
|
sleep = 0
|
|
end
|
|
|
|
Wait(sleep)
|
|
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"
|
|
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)
|