forked from Simnation/Main
Update main.lua
This commit is contained in:
parent
2a1f7bf95c
commit
465cd1d99d
1 changed files with 49 additions and 627 deletions
|
@ -1,632 +1,54 @@
|
||||||
local QBCore = exports['qb-core']:GetCoreObject()
|
['hafenarbeiter'] = {
|
||||||
local isRobbing = false
|
label = 'Red mit dem Hafenarbeiter',
|
||||||
local currentContainer = nil
|
icon = 'fa-solid fa-hard-hat',
|
||||||
local containerBlip = nil
|
model = "s_m_m_dockwork_01",
|
||||||
local addedEntities = {}
|
coords = vector3(1234.56, -3210.45, 5.9), -- Koordinaten anpassen
|
||||||
|
heading = 90,
|
||||||
-- Debug function
|
data = {
|
||||||
local function Debug(msg)
|
firstname = 'Kalle',
|
||||||
if Config.Debug then
|
lastname = 'Kutter',
|
||||||
print("[Container Heist] " .. msg)
|
text = "Moin... du wirkst nich wie jemand, der hier offiziell was abholen will.",
|
||||||
end
|
buttons = {
|
||||||
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 = {
|
|
||||||
{
|
{
|
||||||
type = "client",
|
text = "Kommt drauf an, was es hier so gibt...",
|
||||||
event = "container_heist:client:startRobbery",
|
data = {
|
||||||
icon = "fas fa-angle-double-right",
|
text = "Hehehe... naja, sagen wir mal so: Manche Container stehen nachts ein bisschen... unbeaufsichtigt rum.",
|
||||||
label = "Break into " .. containerType.label,
|
buttons = {
|
||||||
containerType = containerType,
|
{
|
||||||
canInteract = function(entity)
|
text = "Ach ja? Und dann?",
|
||||||
return IsPlayerAtCorrectPosition(entity, containerType)
|
data = {
|
||||||
end
|
text = "Na, wenn einer wüsste, wie man da *rein* kommt... bräuchte er sicher was mit Zähne oder Strom, verstehste?",
|
||||||
|
buttons = {
|
||||||
|
{
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
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 = {
|
|
||||||
{
|
{
|
||||||
type = "client",
|
text = "Klingt mir zu heiß...",
|
||||||
event = "container_heist:client:startRobbery",
|
close = true
|
||||||
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[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",
|
text = "Ich glaub, ich hab mich verlaufen...",
|
||||||
event = "container_heist:client:startRobbery",
|
close = true
|
||||||
icon = "fas fa-angle-double-right",
|
}
|
||||||
label = "Break into " .. containerType.label,
|
}
|
||||||
containerType = containerType,
|
|
||||||
canInteract = function(entity)
|
|
||||||
return IsPlayerAtCorrectPosition(entity, containerType)
|
|
||||||
end
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
distance = 3.0
|
{
|
||||||
})
|
text = "Nur mal umschauen, Chef.",
|
||||||
end
|
close = true
|
||||||
|
}
|
||||||
-- 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)
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue