1
0
Fork 0
forked from Simnation/Main
This commit is contained in:
Nordi98 2025-07-20 04:10:11 +02:00
parent d3f4114333
commit 5cb18574a7
2 changed files with 268 additions and 181 deletions

View file

@ -1,7 +1,7 @@
local QBCore = exports['qb-core']:GetCoreObject()
local pointCooldowns = {}
local playerCooldowns = {}
local globalCooldowns = {}
local isRobbing = false
local currentPoint = nil
local containerBlip = nil
-- Debug function
local function Debug(msg)
@ -10,202 +10,289 @@ local function Debug(msg)
end
end
-- Check if player has required items
lib.callback.register('container_heist:server:checkRequiredItems', function(source)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return false end
-- Check for required flex tool
local hasItem = exports['tgiann-inventory']:HasItem(src, Config.RequiredItems.flex.name, Config.RequiredItems.flex.amount)
return hasItem
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
-- Check cooldowns
lib.callback.register('container_heist:server:checkCooldown', function(source, pointId)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return {success = false, message = "Player not found"} 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
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 {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
return {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
break
local distance = #(playerCoords - point.coords)
if distance < minDistance then
minDistance = distance
closestPoint = point
end
end
if not pointType then
return {success = false, message = "Invalid point!"}
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)
return {success = false, message = Config.Notifications.globalCooldown .. " (" .. timeLeft .. " minutes left)"}
end
return {success = true}
end)
return closestPoint, minDistance
end
-- Get police count
lib.callback.register('container_heist:server:getPoliceCount', function()
local policeCount = 0
local players = QBCore.Functions.GetPlayers()
-- Function to create a blip at the robbery location
local function CreateRobberyBlip(coords)
if containerBlip then
RemoveBlip(containerBlip)
end
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
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
return policeCount
end)
-- Alert police
RegisterNetEvent('container_heist:server:alertPolice', function(coords, streetName, containerLabel)
local src = source
local players = QBCore.Functions.GetPlayers()
TaskPlayAnim(playerPed, animDict, animName, 8.0, -8.0, containerType.animation.duration, containerType.animation.flag, 0, false, false, false)
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
-- 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
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
-- Finish robbery and give rewards
RegisterNetEvent('container_heist:server:finishRobbery', function(pointId, containerTypeName)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
-- Function to start container robbery
local function StartContainerRobbery(point)
if isRobbing then return end
local citizenId = Player.PlayerData.citizenid
local currentTime = os.time()
isRobbing = true
currentPoint = point
-- Set cooldowns
playerCooldowns[citizenId] = currentTime
pointCooldowns[pointId] = currentTime
globalCooldowns[containerTypeName] = currentTime
-- Get container type
local containerType = Config.ContainerTypes[containerTypeName]
-- Get container type from point
local containerType = Config.ContainerTypes[point.type]
if not containerType then
Debug("Container type not found: " .. containerTypeName)
QBCore.Functions.Notify("Invalid container type!", "error")
isRobbing = false
currentPoint = nil
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
-- 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
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)
-- 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
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)
-- 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
TriggerClientEvent('QBCore:Notify', src, "Found " .. amount .. "x " .. reward.label, "success")
end
rewardsGiven = rewardsGiven + 1
end
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 rewardsGiven == 0 then
TriggerClientEvent('QBCore:Notify', src, "The container was empty!", "error")
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)
-- 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
-- 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
-- Clean up point cooldowns
for pointId, cooldownTime in pairs(pointCooldowns) do
if (currentTime - cooldownTime) > (Config.CooldownTime * 60) then
pointCooldowns[pointId] = 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
if isRobbing then
StopAnimTask(PlayerPedId(), "amb@world_human_welding@male@base", "base", 1.0)
end
end
end)

View file

@ -11,21 +11,21 @@ local function Debug(msg)
end
-- Check if player has required items
lib.callback.register('container_heist:server:checkRequiredItems', function(source)
QBCore.Functions.CreateCallback('container_heist:server:checkRequiredItems', function(source, cb)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return false end
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)
return hasItem
cb(hasItem)
end)
-- Check cooldowns
lib.callback.register('container_heist:server:checkCooldown', function(source, pointId)
QBCore.Functions.CreateCallback('container_heist:server:checkCooldown', function(source, cb, pointId)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return {success = false, message = "Player not found"} end
if not Player then return cb({success = false, message = "Player not found"}) end
local citizenId = Player.PlayerData.citizenid
local currentTime = os.time()
@ -33,12 +33,12 @@ lib.callback.register('container_heist:server:checkCooldown', function(source, p
-- 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 {success = false, message = "You need to wait " .. timeLeft .. " more minutes before attempting another heist!"}
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
return {success = false, message = Config.Notifications.alreadyRobbed}
return cb({success = false, message = Config.Notifications.alreadyRobbed})
end
-- Find point type
@ -51,20 +51,20 @@ lib.callback.register('container_heist:server:checkCooldown', function(source, p
end
if not pointType then
return {success = false, message = "Invalid point!"}
return cb({success = false, message = "Invalid point!"})
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)
return {success = false, message = Config.Notifications.globalCooldown .. " (" .. timeLeft .. " minutes left)"}
return cb({success = false, message = Config.Notifications.globalCooldown .. " (" .. timeLeft .. " minutes left)"})
end
return {success = true}
cb({success = true})
end)
-- Get police count
lib.callback.register('container_heist:server:getPoliceCount', function()
QBCore.Functions.CreateCallback('container_heist:server:getPoliceCount', function(source, cb)
local policeCount = 0
local players = QBCore.Functions.GetPlayers()
@ -81,7 +81,7 @@ lib.callback.register('container_heist:server:getPoliceCount', function()
end
end
return policeCount
cb(policeCount)
end)
-- Alert police