2026-04-14 17:41:39 +02:00

499 lines
14 KiB
Lua

local Blips, JobBlips, isInMarker, hintToDisplay, onDuty, spawner, myPlate, vehicleObjInCaseofDrop, vehicleInCaseofDrop, vehicleMaxHealth =
{}, {}, false, "no hint to display", false, 0, {}, nil, nil, nil
local PlayerPedId = PlayerPedId
local IsPedInAnyVehicle = IsPedInAnyVehicle
local GetVehiclePedIsIn = GetVehiclePedIsIn
local GetVehicleNumberPlateText = GetVehicleNumberPlateText
local GetPedInVehicleSeat = GetPedInVehicleSeat
local GetVehicleEngineHealth = GetVehicleEngineHealth
RegisterNetEvent('esx:playerLoaded', function(xPlayer)
ESX.PlayerLoaded = true
refreshBlips()
end)
RegisterNetEvent('esx:onPlayerLogout', function()
ESX.PlayerLoaded = false
end)
function OpenMenu()
local elements = {
{ unselectable = true, icon = "fas fa-shirt", title = TranslateCap('cloakroom') },
{ icon = "fas fa-shirt", title = TranslateCap('job_wear'), value = "job_wear" },
{ icon = "fas fa-shirt", title = TranslateCap('citizen_wear'), value = "citizen_wear" },
}
ESX.OpenContext("right", elements, function(menu, element)
if element.value == "citizen_wear" then
onDuty = false
ESX.ShowNotification(TranslateCap('offduty'), "success")
ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin)
local isMale = skin.sex == 0
TriggerEvent('skinchanger:loadDefaultModel', isMale, function()
ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin)
TriggerEvent('skinchanger:loadSkin', skin)
end)
end)
end)
elseif element.value == "job_wear" then
onDuty = true
ESX.ShowNotification(TranslateCap('onduty'), "success")
ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin)
if skin.sex == 0 then
if ESX.Table.SizeOf(jobSkin.skin_male) >= 1 then
TriggerEvent('skinchanger:loadClothes', skin, jobSkin.skin_male)
else
ESX.ShowNotification(TranslateCap('no_male_clothing'), "error")
end
else
if ESX.Table.SizeOf(jobSkin.skin_female) >= 1 then
TriggerEvent('skinchanger:loadClothes', skin, jobSkin.skin_female)
else
ESX.ShowNotification(TranslateCap('no_female_clothing'), "error")
end
end
end)
end
end)
end
AddEventHandler('esx_jobs:action', function(job, zone, zoneKey)
menuIsShowed = true
local playerJob = ESX.PlayerData.job.name
if zone.Type == "cloakroom" then
OpenMenu()
elseif zone.Type == "work" then
local playerPed = PlayerPedId()
if IsPedInAnyVehicle(playerPed, false) then
ESX.ShowNotification(TranslateCap('foot_work'))
else
TriggerServerEvent('esx_jobs:startWork', zone.Item, zoneKey)
end
elseif zone.Type == "vehspawner" then
local spawnPoint = nil
local vehicle = nil
for k, v in pairs(Config.Jobs) do
if playerJob == k then
for l, w in pairs(v.Zones) do
if w.Type == "vehspawnpt" and w.Spawner == zone.Spawner then
spawnPoint = w
spawner = w.Spawner
end
end
for m, x in pairs(v.Vehicles) do
if x.Spawner == zone.Spawner then
vehicle = x
end
end
end
end
if ESX.Game.IsSpawnPointClear(spawnPoint.Pos, 5.0) then
spawnVehicle(spawnPoint, vehicle, zone.Caution)
else
ESX.ShowNotification(TranslateCap('spawn_blocked'))
end
elseif zone.Type == "vehdelete" then
local looping = true
for k, v in pairs(Config.Jobs) do
if playerJob == k then
for l, w in pairs(v.Zones) do
if w.Type == "vehdelete" and w.Spawner == zone.Spawner then
local playerPed = PlayerPedId()
if IsPedInAnyVehicle(playerPed, false) then
local vehicle = GetVehiclePedIsIn(playerPed, false)
local plate = GetVehicleNumberPlateText(vehicle)
plate = string.gsub(plate, " ", "")
local driverPed = GetPedInVehicleSeat(vehicle, -1)
local vehicleMaxHealth = GetVehicleEngineHealth(vehicle)
if playerPed == driverPed then
for i = 1, #myPlate, 1 do
if myPlate[i] == plate then
local vehicleHealth = GetVehicleEngineHealth(vehicleInCaseofDrop)
local giveBack = ESX.Math.Round(vehicleHealth / vehicleMaxHealth, 2)
TriggerServerEvent('esx_jobs:caution', "give_back", giveBack, 0, 0)
DeleteVehicle(GetVehiclePedIsIn(playerPed, false))
if w.Teleport ~= 0 then
ESX.Game.Teleport(playerPed, w.Teleport)
end
table.remove(myPlate, i)
if vehicleObjInCaseofDrop.HasCaution then
vehicleInCaseofDrop = nil
vehicleObjInCaseofDrop = nil
vehicleMaxHealth = nil
end
break
end
end
else
ESX.ShowNotification(TranslateCap('not_your_vehicle'))
end
end
looping = false
break
end
if looping == false then
break
end
end
end
if looping == false then
break
end
end
elseif zone.Type == "delivery" then
if Blips['delivery'] ~= nil then
RemoveBlip(Blips['delivery'])
Blips['delivery'] = nil
end
TriggerServerEvent('esx_jobs:startWork', zone.Item, zoneKey)
end
--nextStep(zone.GPS)
end)
function nextStep(gps)
if gps == 0 then return end
if Blips['delivery'] ~= nil then
RemoveBlip(Blips['delivery'])
Blips['delivery'] = nil
end
Blips['delivery'] = AddBlipForCoord(gps.x, gps.y, gps.z)
SetBlipRoute(Blips['delivery'], true)
ESX.ShowNotification(TranslateCap('next_point'))
end
AddEventHandler('esx_jobs:hasExitedMarker', function(zone)
TriggerServerEvent('esx_jobs:stopWork')
menuIsShowed = false
isInMarker = false
end)
RegisterNetEvent('esx:setJob', function(job)
ESX.PlayerData.job = job
onDuty = false
myPlate = {} -- loosing vehicle caution in case player changes job.
spawner = 0
deleteBlips()
refreshBlips()
end)
function deleteBlips()
if JobBlips[1] ~= nil then
for i = 1, #JobBlips, 1 do
RemoveBlip(JobBlips[i])
JobBlips[i] = nil
end
end
end
function refreshBlips()
local zones = {}
local blipInfo = {}
while not ESX.PlayerLoaded do
Wait(500)
end
local playerJob = ESX.PlayerData.job?.name
for jobKey, jobValues in pairs(Config.Jobs) do
if jobKey == playerJob then
for zoneKey, zoneValues in pairs(jobValues.Zones) do
if not zoneValues.Blip then goto continue end
local _Pos = {}
if not (zoneValues.Zone) then
_Pos = zoneValues.Pos
end
TriggerEvent("izone:getZoneCenter", zoneValues.Zone, function(_center)
if (_center) then
_Pos = _center
end
end)
local blip = AddBlipForCoord(_Pos.x, _Pos.y, _Pos.z)
SetBlipSprite(blip, jobValues.BlipInfos.Sprite)
SetBlipDisplay(blip, 4)
SetBlipScale(blip, 0.8)
SetBlipCategory(blip, 3)
SetBlipColour(blip, jobValues.BlipInfos.Color)
SetBlipAsShortRange(blip, true)
BeginTextCommandSetBlipName("STRING")
AddTextComponentSubstringPlayerName(zoneValues.Name)
EndTextCommandSetBlipName(blip)
table.insert(JobBlips, blip)
::continue::
end
end
end
end
function spawnVehicle(spawnPoint, vehicle, vehicleCaution)
hintIsShowed = false
TriggerServerEvent('esx_jobs:caution', 'take', vehicleCaution, spawnPoint, vehicle)
end
RegisterNetEvent('esx_jobs:spawnJobVehicle', function(spawnPoint, vehicle)
local playerPed = PlayerPedId()
ESX.Game.SpawnVehicle(vehicle.Hash, spawnPoint.Pos, spawnPoint.Heading, function(spawnedVehicle)
if vehicle.Trailer ~= "none" then
ESX.Game.SpawnVehicle(vehicle.Trailer, spawnPoint.Pos, spawnPoint.Heading, function(trailer)
AttachVehicleToTrailer(spawnedVehicle, trailer, 1.1)
end)
end
-- save & set plate
local plate = 'WORK' .. math.random(100, 900)
SetVehicleNumberPlateText(spawnedVehicle, plate)
table.insert(myPlate, plate)
plate = string.gsub(plate, " ", "")
TaskWarpPedIntoVehicle(playerPed, spawnedVehicle, -1)
if not vehicle.HasCaution then return end
vehicleInCaseofDrop = spawnedVehicle
vehicleObjInCaseofDrop = vehicle
vehicleMaxHealth = GetVehicleEngineHealth(spawnedVehicle)
end)
end)
-- Display markers (only if on duty and the player's job ones)
CreateThread(function()
while true do
local Sleep = 1500
local zones = {}
if ESX.PlayerLoaded then
local playerJob = ESX.PlayerData.job.name
if playerJob then
for k, v in pairs(Config.Jobs) do
if playerJob == k then
Sleep = 0
zones = v.Zones
end
end
local coords = GetEntityCoords(PlayerPedId())
for k, v in pairs(zones) do
if onDuty or v.Type == "cloakroom" then
if (v.Zone) then
TriggerEvent("izone:getZoneCenter", v.Zone, function(center)
if (not (center == nil)) then
if (v.Marker ~= -1 and #(coords - center) < Config.DrawDistance) then
Sleep = 0
DrawMarker(v.Marker, center.x, center.y, center.z - 1, 0.0, 0.0, 0.0, 0, 0.0, 0.0,
v.Size.x, v.Size.y, v.Size.z, v.Color.r, v.Color.g, v.Color.b, 100, false,
true,
2, false, false, false, false)
end
end
end)
else
local Pos = vector3(v.Pos.x, v.Pos.y, v.Pos.z)
if (v.Marker ~= -1 and #(coords - Pos) < Config.DrawDistance) then
Sleep = 0
DrawMarker(v.Marker, v.Pos.x, v.Pos.y, v.Pos.z, 0.0, 0.0, 0.0, 0, 0.0, 0.0, v.Size.x,
v.Size.y, v.Size.z, v.Color.r, v.Color.g, v.Color.b, 100, false, true, 2, false,
false,
false, false)
end
end
end
end
end
end
Wait(Sleep)
end
end)
-- Display public markers
CreateThread(function()
while true do
local Sleep = 1500
local coords = GetEntityCoords(PlayerPedId())
for k, v in pairs(Config.PublicZones) do
if (v.Marker ~= -1 and #(coords - v.Pos) < Config.DrawDistance) then
Sleep = 0
DrawMarker(v.Marker, v.Pos.x, v.Pos.y, v.Pos.z, 0.0, 0.0, 0.0, 0, 0.0, 0.0, v.Size.x, v.Size.y, v.Size.z,
v.Color.r, v.Color.g, v.Color.b, 100, false, true, 2, false, false, false, false)
end
end
Wait(Sleep)
end
end)
-- Activate public marker
CreateThread(function()
while true do
local Sleep = 1500
local coords = GetEntityCoords(PlayerPedId())
for k, v in pairs(Config.PublicZones) do
if #(coords - v.Pos) < v.Size.x / 2 then
Sleep = 0
ESX.ShowHelpNotification(v.Hint)
hintIsShowed = true
if IsControlJustReleased(0, 38) then
ESX.Game.Teleport(PlayerPedId(), v.Teleport)
end
end
end
Wait(Sleep)
end
end)
-- Activate menu when player is inside marker
CreateThread(function()
while true do
local Sleep = 500
if ESX.PlayerLoaded then
local playerJob = ESX.PlayerData.job.name
if playerJob and playerJob ~= 'unemployed' then
local zones = nil
local job = nil
for k, v in pairs(Config.Jobs) do
if playerJob == k then
Sleep = 0
job = v
zones = v.Zones
end
end
if zones then
local coords = GetEntityCoords(PlayerPedId())
local currentZone = nil
local zone = nil
local lastZone = nil
for k, v in pairs(zones) do
-- If we defined a zone from iZone
if v.Zone then
TriggerEvent("izone:isPlayerInZone", v.Zone, function(isIn)
if isIn then
Sleep = 0
isInMarker = true
currentZone = k
zone = v
return
else
isInMarker = false
end
end)
-- Because we were in a routine
if isInMarker then
break
end
-- Else use radius defined from center
else
local Pos = vector3(v.Pos.x, v.Pos.y, v.Pos.z)
if #(coords - Pos) < v.Size.x then
Sleep = 0
isInMarker = true
currentZone = k
zone = v
break
else
isInMarker = false
end
end
end
if IsControlJustReleased(0, 38) and not menuIsShowed and isInMarker then
if onDuty or zone.Type == "cloakroom" then
TriggerEvent('esx_jobs:action', job, zone, currentZone)
end
end
-- hide or show top left zone hints
if isInMarker and not menuIsShowed then
hintIsShowed = true
if (onDuty or zone.Type == "cloakroom") and zone.Type ~= "vehdelete" then
if zone.Hint then
hintToDisplay = zone.Hint
ESX.ShowHelpNotification(hintToDisplay)
end
elseif zone.Type == "vehdelete" and (onDuty) then
local playerPed = PlayerPedId()
if IsPedInAnyVehicle(playerPed, false) then
local vehicle = GetVehiclePedIsIn(playerPed, false)
local driverPed = GetPedInVehicleSeat(vehicle, -1)
local plate = GetVehicleNumberPlateText(vehicle)
plate = string.gsub(plate, " ", "")
if playerPed == driverPed then
for i = 1, #myPlate, 1 do
if myPlate[i] == plate then
hintToDisplay = zone.Hint
break
end
end
else
hintToDisplay = TranslateCap('not_your_vehicle')
ESX.ShowHelpNotification(hintToDisplay)
end
else
hintToDisplay = TranslateCap('in_vehicle')
ESX.ShowHelpNotification(hintToDisplay)
end
hintIsShowed = true
elseif onDuty and zone.Spawner ~= spawner then
hintToDisplay = TranslateCap('wrong_point')
ESX.ShowHelpNotification(hintToDisplay)
end
end
if isInMarker and not hasAlreadyEnteredMarker then
hasAlreadyEnteredMarker = true
end
if not isInMarker and hasAlreadyEnteredMarker then
hasAlreadyEnteredMarker = false
TriggerEvent('esx_jobs:hasExitedMarker', zone)
end
end
end
end
Wait(Sleep)
end
end)
if Config.RequestIPL then
CreateThread(function()
-- Slaughterer
RemoveIpl("CS1_02_cf_offmission")
RequestIpl("CS1_02_cf_onmission1")
RequestIpl("CS1_02_cf_onmission2")
RequestIpl("CS1_02_cf_onmission3")
RequestIpl("CS1_02_cf_onmission4")
-- Tailor
RequestIpl("id2_14_during_door")
RequestIpl("id2_14_during1")
end)
end
if ESX.PlayerLoaded then refreshBlips() end