client/job.lua:
local CurrentAction, CurrentActionMsg, CurrentActionData = nil, '', {}
local HasAlreadyEnteredMarker, LastHospital, LastPart, LastPartNum
local IsBusy = false
local spawnedVehicles, isInShopMenu = {}, false
function OpenAmbulanceActionsMenu()
local elements = {
{label = _U('cloakroom'), value = 'cloakroom'}
}
if Config.EnablePlayerManagement and ESX.PlayerData.job.grade_name == 'boss' then
table.insert(elements, {label = _U('boss_actions'), value = 'boss_actions'})
end
ESX.UI.Menu.CloseAll()
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'ambulance_actions',
{
title = _U('ambulance'),
align = 'top-right',
elements = elements
}, function(data, menu)
if data.current.value == 'cloakroom' then
OpenCloakroomMenu()
elseif data.current.value == 'boss_actions' then
TriggerEvent('esx_society:openBossMenu', 'ambulance', function(data, menu)
menu.close()
end, {wash = false})
end
end, function(data, menu)
menu.close()
end)
end
function OpenMobileAmbulanceActionsMenu()
ESX.UI.Menu.CloseAll()
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'mobile_ambulance_actions',
{
title = _U('ambulance'),
align = 'top-right',
elements = {
{label = _U('ems_menu'), value = 'citizen_interaction'}
}
}, function(data, menu)
if data.current.value == 'citizen_interaction' then
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'citizen_interaction',
{
title = _U('ems_menu_title'),
align = 'top-right',
elements = {
{label = _U('ems_menu_revive'), value = 'revive'},
{label = _U('ems_menu_small'), value = 'small'},
{label = _U('ems_menu_big'), value = 'big'},
{label = _U('ems_menu_putincar'), value = 'put_in_vehicle'}
}
}, function(data, menu)
if IsBusy then return end
local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer()
if closestPlayer == -1 or closestDistance > 1.0 then
ESX.ShowNotification(_U('no_players'))
else
if data.current.value == 'revive' then
IsBusy = true
ESX.TriggerServerCallback('esx_ambulancejob:getItemAmount', function(quantity)
if quantity > 0 then
local closestPlayerPed = GetPlayerPed(closestPlayer)
if IsPedDeadOrDying(closestPlayerPed, 1) then
local playerPed = PlayerPedId()
ESX.ShowNotification(_U('revive_inprogress'))
local lib, anim = 'mini@cpr@char_a@cpr_str', 'cpr_pumpchest'
for i=1, 15, 1 do
Citizen.Wait(900)
ESX.Streaming.RequestAnimDict(lib, function()
TaskPlayAnim(PlayerPedId(), lib, anim, 8.0, -8.0, -1, 0, 0, false, false, false)
end)
end
TriggerServerEvent('esx_ambulancejob:removeItem', 'medikit')
TriggerServerEvent('esx_ambulancejob:revive', GetPlayerServerId(closestPlayer))
-- Show revive award?
if Config.ReviveReward > 0 then
ESX.ShowNotification(_U('revive_complete_award', GetPlayerName(closestPlayer), Config.ReviveReward))
else
ESX.ShowNotification(_U('revive_complete', GetPlayerName(closestPlayer)))
end
else
ESX.ShowNotification(_U('player_not_unconscious'))
end
else
ESX.ShowNotification(_U('not_enough_medikit'))
end
IsBusy = false
end, 'medikit')
elseif data.current.value == 'small' then
ESX.TriggerServerCallback('esx_ambulancejob:getItemAmount', function(quantity)
if quantity > 0 then
local closestPlayerPed = GetPlayerPed(closestPlayer)
local health = GetEntityHealth(closestPlayerPed)
if health > 0 then
local playerPed = PlayerPedId()
IsBusy = true
ESX.ShowNotification(_U('heal_inprogress'))
TaskStartScenarioInPlace(playerPed, 'CODE_HUMAN_MEDIC_TEND_TO_DEAD', 0, true)
Citizen.Wait(10000)
ClearPedTasks(playerPed)
TriggerServerEvent('esx_ambulancejob:removeItem', 'bandage')
TriggerServerEvent('esx_ambulancejob:heal', GetPlayerServerId(closestPlayer), 'small')
ESX.ShowNotification(_U('heal_complete', GetPlayerName(closestPlayer)))
IsBusy = false
else
ESX.ShowNotification(_U('player_not_conscious'))
end
else
ESX.ShowNotification(_U('not_enough_bandage'))
end
end, 'bandage')
elseif data.current.value == 'big' then
ESX.TriggerServerCallback('esx_ambulancejob:getItemAmount', function(quantity)
if quantity > 0 then
local closestPlayerPed = GetPlayerPed(closestPlayer)
local health = GetEntityHealth(closestPlayerPed)
if health > 0 then
local playerPed = PlayerPedId()
IsBusy = true
ESX.ShowNotification(_U('heal_inprogress'))
TaskStartScenarioInPlace(playerPed, 'CODE_HUMAN_MEDIC_TEND_TO_DEAD', 0, true)
Citizen.Wait(10000)
ClearPedTasks(playerPed)
TriggerServerEvent('esx_ambulancejob:removeItem', 'medikit')
TriggerServerEvent('esx_ambulancejob:heal', GetPlayerServerId(closestPlayer), 'big')
ESX.ShowNotification(_U('heal_complete', GetPlayerName(closestPlayer)))
IsBusy = false
else
ESX.ShowNotification(_U('player_not_conscious'))
end
else
ESX.ShowNotification(_U('not_enough_medikit'))
end
end, 'medikit')
elseif data.current.value == 'put_in_vehicle' then
TriggerServerEvent('esx_ambulancejob:putInVehicle', GetPlayerServerId(closestPlayer))
end
end
end, function(data, menu)
menu.close()
end)
end
end, function(data, menu)
menu.close()
end)
end
function FastTravel(coords, heading)
TeleportFadeEffect(PlayerPedId(), coords, heading)
end
function TeleportFadeEffect(entity, coords, heading)
Citizen.CreateThread(function()
DoScreenFadeOut(800)
while not IsScreenFadedOut() do
Citizen.Wait(0)
end
ESX.Game.Teleport(entity, coords, function()
DoScreenFadeIn(800)
if heading then
SetEntityHeading(entity, heading)
end
end)
end)
end
-- Draw markers & Marker logic
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
local playerCoords = GetEntityCoords(PlayerPedId())
local canSleep, isInMarker, hasExited = true, false, false
local currentHospital, currentPart, currentPartNum
for hospitalNum,hospital in pairs(Config.Hospitals) do
-- Ambulance Actions
for k,v in ipairs(hospital.AmbulanceActions) do
local distance = GetDistanceBetweenCoords(playerCoords, v, true)
if distance < Config.DrawDistance then
DrawMarker(Config.Marker.type, v, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Config.Marker.x, Config.Marker.y, Config.Marker.z, Config.Marker.r, Config.Marker.g, Config.Marker.b, Config.Marker.a, false, false, 2, Config.Marker.rotate, nil, nil, false)
canSleep = false
end
if distance < Config.Marker.x then
isInMarker, currentHospital, currentPart, currentPartNum = true, hospitalNum, 'AmbulanceActions', k
end
end
-- Pharmacies
for k,v in ipairs(hospital.Pharmacies) do
local distance = GetDistanceBetweenCoords(playerCoords, v, true)
if distance < Config.DrawDistance then
DrawMarker(Config.Marker.type, v, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Config.Marker.x, Config.Marker.y, Config.Marker.z, Config.Marker.r, Config.Marker.g, Config.Marker.b, Config.Marker.a, false, false, 2, Config.Marker.rotate, nil, nil, false)
canSleep = false
end
if distance < Config.Marker.x then
isInMarker, currentHospital, currentPart, currentPartNum = true, hospitalNum, 'Pharmacy', k
end
end
-- Vehicle Spawners
for k,v in ipairs(hospital.Vehicles) do
local distance = GetDistanceBetweenCoords(playerCoords, v.Spawner, true)
if distance < Config.DrawDistance then
DrawMarker(v.Marker.type, v.Spawner, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, v.Marker.x, v.Marker.y, v.Marker.z, v.Marker.r, v.Marker.g, v.Marker.b, v.Marker.a, false, false, 2, v.Marker.rotate, nil, nil, false)
canSleep = false
end
if distance < v.Marker.x then
isInMarker, currentHospital, currentPart, currentPartNum = true, hospitalNum, 'Vehicles', k
end
end
-- Helicopter Spawners
for k,v in ipairs(hospital.Helicopters) do
local distance = GetDistanceBetweenCoords(playerCoords, v.Spawner, true)
if distance < Config.DrawDistance then
DrawMarker(v.Marker.type, v.Spawner, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, v.Marker.x, v.Marker.y, v.Marker.z, v.Marker.r, v.Marker.g, v.Marker.b, v.Marker.a, false, false, 2, v.Marker.rotate, nil, nil, false)
canSleep = false
end
if distance < v.Marker.x then
isInMarker, currentHospital, currentPart, currentPartNum = true, hospitalNum, 'Helicopters', k
end
end
-- Fast Travels
for k,v in ipairs(hospital.FastTravels) do
local distance = GetDistanceBetweenCoords(playerCoords, v.From, true)
if distance < Config.DrawDistance then
DrawMarker(v.Marker.type, v.From, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, v.Marker.x, v.Marker.y, v.Marker.z, v.Marker.r, v.Marker.g, v.Marker.b, v.Marker.a, false, false, 2, v.Marker.rotate, nil, nil, false)
canSleep = false
end
if distance < v.Marker.x then
FastTravel(v.To.coords, v.To.heading)
end
end
-- Fast Travels (Prompt)
for k,v in ipairs(hospital.FastTravelsPrompt) do
local distance = GetDistanceBetweenCoords(playerCoords, v.From, true)
if distance < Config.DrawDistance then
DrawMarker(v.Marker.type, v.From, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, v.Marker.x, v.Marker.y, v.Marker.z, v.Marker.r, v.Marker.g, v.Marker.b, v.Marker.a, false, false, 2, v.Marker.rotate, nil, nil, false)
canSleep = false
end
if distance < v.Marker.x then
isInMarker, currentHospital, currentPart, currentPartNum = true, hospitalNum, 'FastTravelsPrompt', k
end
end
-- Logic for exiting & entering markers
if isInMarker and not HasAlreadyEnteredMarker or (isInMarker and (LastHospital ~= currentHospital or LastPart ~= currentPart or LastPartNum ~= currentPartNum)) then
if
(LastHospital ~= nil and LastPart ~= nil and LastPartNum ~= nil) and
(LastHospital ~= currentHospital or LastPart ~= currentPart or LastPartNum ~= currentPartNum)
then
TriggerEvent('esx_ambulancejob:hasExitedMarker', LastHospital, LastPart, LastPartNum)
hasExited = true
end
HasAlreadyEnteredMarker, LastHospital, LastPart, LastPartNum = true, currentHospital, currentPart, currentPartNum
TriggerEvent('esx_ambulancejob:hasEnteredMarker', currentHospital, currentPart, currentPartNum)
end
if not hasExited and not isInMarker and HasAlreadyEnteredMarker then
HasAlreadyEnteredMarker = false
TriggerEvent('esx_ambulancejob:hasExitedMarker', LastHospital, LastPart, LastPartNum)
end
end
end
end)
AddEventHandler('esx_ambulancejob:hasEnteredMarker', function(hospital, part, partNum)
if ESX.PlayerData.job and ESX.PlayerData.job.name == 'ambulance' then
if part == 'AmbulanceActions' then
CurrentAction = part
CurrentActionMsg = _U('actions_prompt')
CurrentActionData = {}
elseif part == 'Pharmacy' then
CurrentAction = part
CurrentActionMsg = _U('open_pharmacy')
CurrentActionData = {}
elseif part == 'Vehicles' then
CurrentAction = part
CurrentActionMsg = _U('garage_prompt')
CurrentActionData = {hospital = hospital, partNum = partNum}
elseif part == 'Helicopters' then
CurrentAction = part
CurrentActionMsg = _U('helicopter_prompt')
CurrentActionData = {hospital = hospital, partNum = partNum}
elseif part == 'FastTravelsPrompt' then
local travelItem = Config.Hospitals[hospital][part][partNum]
CurrentAction = part
CurrentActionMsg = travelItem.Prompt
CurrentActionData = {to = travelItem.To.coords, heading = travelItem.To.heading}
end
end
end)
AddEventHandler('esx_ambulancejob:hasExitedMarker', function(hospital, part, partNum)
if not isInShopMenu then
ESX.UI.Menu.CloseAll()
end
CurrentAction = nil
end)
-- Key Controls
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
if CurrentAction then
ESX.ShowHelpNotification(CurrentActionMsg)
if IsControlJustReleased(0, Keys['E']) then
if CurrentAction == 'AmbulanceActions' then
OpenAmbulanceActionsMenu()
elseif CurrentAction == 'Pharmacy' then
OpenPharmacyMenu()
elseif CurrentAction == 'Vehicles' then
OpenVehicleSpawnerMenu(CurrentActionData.hospital, CurrentActionData.partNum)
elseif CurrentAction == 'Helicopters' then
OpenHelicopterSpawnerMenu(CurrentActionData.hospital, CurrentActionData.partNum)
elseif CurrentAction == 'FastTravelsPrompt' then
FastTravel(CurrentActionData.to, CurrentActionData.heading)
end
CurrentAction = nil
end
elseif ESX.PlayerData.job ~= nil and ESX.PlayerData.job.name == 'ambulance' and not IsDead then
if IsControlJustReleased(0, Keys['F6']) then
OpenMobileAmbulanceActionsMenu()
end
else
Citizen.Wait(500)
end
end
end)
RegisterNetEvent('esx_ambulancejob:putInVehicle')
AddEventHandler('esx_ambulancejob:putInVehicle', function()
local playerPed = PlayerPedId()
local coords = GetEntityCoords(playerPed)
if IsAnyVehicleNearPoint(coords, 5.0) then
local vehicle = GetClosestVehicle(coords, 5.0, 0, 71)
if DoesEntityExist(vehicle) then
local maxSeats, freeSeat = GetVehicleMaxNumberOfPassengers(vehicle)
for i=maxSeats - 1, 0, -1 do
if IsVehicleSeatFree(vehicle, i) then
freeSeat = i
break
end
end
if freeSeat then
TaskWarpPedIntoVehicle(playerPed, vehicle, freeSeat)
end
end
end
end)
function OpenCloakroomMenu()
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'cloakroom',
{
title = _U('cloakroom'),
align = 'top-right',
elements = {
{label = _U('ems_clothes_civil'), value = 'citizen_wear'},
{label = _U('ems_clothes_ems'), value = 'ambulance_wear'},
}
}, function(data, menu)
if data.current.value == 'citizen_wear' then
ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin)
TriggerEvent('skinchanger:loadSkin', skin)
end)
elseif data.current.value == 'ambulance_wear' then
ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin)
if skin.sex == 0 then
TriggerEvent('skinchanger:loadClothes', skin, jobSkin.skin_male)
else
TriggerEvent('skinchanger:loadClothes', skin, jobSkin.skin_female)
end
end)
end
menu.close()
end, function(data, menu)
menu.close()
end)
end
function OpenVehicleSpawnerMenu(hospital, partNum)
local playerCoords = GetEntityCoords(PlayerPedId())
local elements = {
{label = _U('garage_storeditem'), action = 'garage'},
{label = _U('garage_storeitem'), action = 'store_garage'},
{label = _U('garage_buyitem'), action = 'buy_vehicle'}
}
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle', {
title = _U('garage_title'),
align = 'top-right',
elements = elements
}, function(data, menu)
if data.current.action == 'buy_vehicle' then
local shopCoords = Config.Hospitals[hospital].Vehicles[partNum].InsideShop
local shopElements = {}
local authorizedVehicles = Config.AuthorizedVehicles[ESX.PlayerData.job.grade_name]
if #authorizedVehicles > 0 then
for k,vehicle in ipairs(authorizedVehicles) do
table.insert(shopElements, {
label = ('%s - <span style="color:green;">%s</span>'):format(vehicle.label, _U('shop_item', ESX.Math.GroupDigits(vehicle.price))),
name = vehicle.label,
model = vehicle.model,
price = vehicle.price,
type = 'car'
})
end
else
return
end
OpenShopMenu(shopElements, playerCoords, shopCoords)
elseif data.current.action == 'garage' then
local garage = {}
ESX.TriggerServerCallback('esx_vehicleshop:retrieveJobVehicles', function(jobVehicles)
if #jobVehicles > 0 then
for k,v in ipairs(jobVehicles) do
local props = json.decode(v.vehicle)
local vehicleName = GetLabelText(GetDisplayNameFromVehicleModel(props.model))
local label = ('%s - <span style="color:darkgoldenrod;">%s</span>: '):format(vehicleName, props.plate)
if v.stored then
label = label .. ('<span style="color:green;">%s</span>'):format(_U('garage_stored'))
else
label = label .. ('<span style="color:darkred;">%s</span>'):format(_U('garage_notstored'))
end
table.insert(garage, {
label = label,
stored = v.stored,
model = props.model,
vehicleProps = props
})
end
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_garage', {
title = _U('garage_title'),
align = 'top-right',
elements = garage
}, function(data2, menu2)
if data2.current.stored then
local foundSpawn, spawnPoint = GetAvailableVehicleSpawnPoint(hospital, 'Vehicles', partNum)
if foundSpawn then
menu2.close()
ESX.Game.SpawnVehicle(data2.current.model, spawnPoint.coords, spawnPoint.heading, function(vehicle)
ESX.Game.SetVehicleProperties(vehicle, data2.current.vehicleProps)
TriggerServerEvent('esx_vehicleshop:setJobVehicleState', data2.current.vehicleProps.plate, false)
ESX.ShowNotification(_U('garage_released'))
end)
end
else
ESX.ShowNotification(_U('garage_notavailable'))
end
end, function(data2, menu2)
menu2.close()
end)
else
ESX.ShowNotification(_U('garage_empty'))
end
end, 'car')
elseif data.current.action == 'store_garage' then
StoreNearbyVehicle(playerCoords)
end
end, function(data, menu)
menu.close()
end)
end
function StoreNearbyVehicle(playerCoords)
local vehicles, vehiclePlates = ESX.Game.GetVehiclesInArea(playerCoords, 30.0), {}
if #vehicles > 0 then
for k,v in ipairs(vehicles) do
-- Make sure the vehicle we're saving is empty, or else it wont be deleted
if GetVehicleNumberOfPassengers(v) == 0 and IsVehicleSeatFree(v, -1) then
table.insert(vehiclePlates, {
vehicle = v,
plate = ESX.Math.Trim(GetVehicleNumberPlateText(v))
})
end
end
else
ESX.ShowNotification(_U('garage_store_nearby'))
return
end
ESX.TriggerServerCallback('esx_ambulancejob:storeNearbyVehicle', function(storeSuccess, foundNum)
if storeSuccess then
local vehicleId = vehiclePlates[foundNum]
local attempts = 0
ESX.Game.DeleteVehicle(vehicleId.vehicle)
IsBusy = true
Citizen.CreateThread(function()
while IsBusy do
Citizen.Wait(0)
drawLoadingText(_U('garage_storing'), 255, 255, 255, 255)
end
end)
-- Workaround for vehicle not deleting when other players are near it.
while DoesEntityExist(vehicleId.vehicle) do
Citizen.Wait(500)
attempts = attempts + 1
-- Give up
if attempts > 30 then
break
end
vehicles = ESX.Game.GetVehiclesInArea(playerCoords, 30.0)
if #vehicles > 0 then
for k,v in ipairs(vehicles) do
if ESX.Math.Trim(GetVehicleNumberPlateText(v)) == vehicleId.plate then
ESX.Game.DeleteVehicle(v)
break
end
end
end
end
IsBusy = false
ESX.ShowNotification(_U('garage_has_stored'))
else
ESX.ShowNotification(_U('garage_has_notstored'))
end
end, vehiclePlates)
end
function GetAvailableVehicleSpawnPoint(hospital, part, partNum)
local spawnPoints = Config.Hospitals[hospital][part][partNum].SpawnPoints
local found, foundSpawnPoint = false, nil
for i=1, #spawnPoints, 1 do
if ESX.Game.IsSpawnPointClear(spawnPoints[i].coords, spawnPoints[i].radius) then
found, foundSpawnPoint = true, spawnPoints[i]
break
end
end
if found then
return true, foundSpawnPoint
else
ESX.ShowNotification(_U('garage_blocked'))
return false
end
end
function OpenHelicopterSpawnerMenu(hospital, partNum)
local playerCoords = GetEntityCoords(PlayerPedId())
local elements = {
{label = _U('helicopter_garage'), action = 'garage'},
{label = _U('helicopter_store'), action = 'store_garage'},
{label = _U('helicopter_buy'), action = 'buy_helicopter'}
}
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'helicopter_spawner', {
title = _U('helicopter_title'),
align = 'top-right',
elements = elements
}, function(data, menu)
if data.current.action == 'buy_helicopter' then
local shopCoords = Config.Hospitals[hospital].Helicopters[partNum].InsideShop
local shopElements = {}
local authorizedHelicopters = Config.AuthorizedHelicopters[ESX.PlayerData.job.grade_name]
if #authorizedHelicopters > 0 then
for k,helicopter in ipairs(authorizedHelicopters) do
table.insert(shopElements, {
label = ('%s - <span style="color:green;">%s</span>'):format(helicopter.label, _U('shop_item', ESX.Math.GroupDigits(helicopter.price))),
name = helicopter.label,
model = helicopter.model,
price = helicopter.price,
type = 'helicopter'
})
end
else
ESX.ShowNotification(_U('helicopter_notauthorized'))
return
end
OpenShopMenu(shopElements, playerCoords, shopCoords)
elseif data.current.action == 'garage' then
local garage = {}
ESX.TriggerServerCallback('esx_vehicleshop:retrieveJobVehicles', function(jobVehicles)
if #jobVehicles > 0 then
for k,v in ipairs(jobVehicles) do
local props = json.decode(v.vehicle)
local vehicleName = GetLabelText(GetDisplayNameFromVehicleModel(props.model))
local label = ('%s - <span style="color:darkgoldenrod;">%s</span>: '):format(vehicleName, props.plate)
if v.stored then
label = label .. ('<span style="color:green;">%s</span>'):format(_U('garage_stored'))
else
label = label .. ('<span style="color:darkred;">%s</span>'):format(_U('garage_notstored'))
end
table.insert(garage, {
label = label,
stored = v.stored,
model = props.model,
vehicleProps = props
})
end
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'helicopter_garage', {
title = _U('helicopter_garage_title'),
align = 'top-right',
elements = garage
}, function(data2, menu2)
if data2.current.stored then
local foundSpawn, spawnPoint = GetAvailableVehicleSpawnPoint(hospital, 'Helicopters', partNum)
if foundSpawn then
menu2.close()
ESX.Game.SpawnVehicle(data2.current.model, spawnPoint.coords, spawnPoint.heading, function(vehicle)
ESX.Game.SetVehicleProperties(vehicle, data2.current.vehicleProps)
TriggerServerEvent('esx_vehicleshop:setJobVehicleState', data2.current.vehicleProps.plate, false)
ESX.ShowNotification(_U('garage_released'))
end)
end
else
ESX.ShowNotification(_U('garage_notavailable'))
end
end, function(data2, menu2)
menu2.close()
end)
else
ESX.ShowNotification(_U('garage_empty'))
end
end, 'helicopter')
elseif data.current.action == 'store_garage' then
StoreNearbyVehicle(playerCoords)
end
end, function(data, menu)
menu.close()
end)
end
function OpenShopMenu(elements, restoreCoords, shopCoords)
local playerPed = PlayerPedId()
isInShopMenu = true
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_shop', {
title = _U('vehicleshop_title'),
align = 'top-right',
elements = elements
}, function(data, menu)
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'vehicle_shop_confirm',
{
title = _U('vehicleshop_confirm', data.current.name, data.current.price),
align = 'top-right',
elements = {
{ label = _U('confirm_no'), value = 'no' },
{ label = _U('confirm_yes'), value = 'yes' }
}
}, function(data2, menu2)
if data2.current.value == 'yes' then
local newPlate = exports['esx_vehicleshop']:GeneratePlate()
local vehicle = GetVehiclePedIsIn(playerPed, false)
local props = ESX.Game.GetVehicleProperties(vehicle)
props.plate = newPlate
ESX.TriggerServerCallback('esx_ambulancejob:buyJobVehicle', function (bought)
if bought then
ESX.ShowNotification(_U('vehicleshop_bought', data.current.name, ESX.Math.GroupDigits(data.current.price)))
isInShopMenu = false
ESX.UI.Menu.CloseAll()
DeleteSpawnedVehicles()
FreezeEntityPosition(playerPed, false)
SetEntityVisible(playerPed, true)
ESX.Game.Teleport(playerPed, restoreCoords)
else
ESX.ShowNotification(_U('vehicleshop_money'))
menu2.close()
end
end, props, data.current.type)
else
menu2.close()
end
end, function(data2, menu2)
menu2.close()
end)
end, function(data, menu)
isInShopMenu = false
ESX.UI.Menu.CloseAll()
DeleteSpawnedVehicles()
FreezeEntityPosition(playerPed, false)
SetEntityVisible(playerPed, true)
ESX.Game.Teleport(playerPed, restoreCoords)
end, function(data, menu)
DeleteSpawnedVehicles()
WaitForVehicleToLoad(data.current.model)
ESX.Game.SpawnLocalVehicle(data.current.model, shopCoords, 0.0, function(vehicle)
table.insert(spawnedVehicles, vehicle)
TaskWarpPedIntoVehicle(playerPed, vehicle, -1)
FreezeEntityPosition(vehicle, true)
end)
end)
WaitForVehicleToLoad(elements[1].model)
ESX.Game.SpawnLocalVehicle(elements[1].model, shopCoords, 0.0, function(vehicle)
table.insert(spawnedVehicles, vehicle)
TaskWarpPedIntoVehicle(playerPed, vehicle, -1)
FreezeEntityPosition(vehicle, true)
end)
end
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
if isInShopMenu then
DisableControlAction(0, 75, true) -- Disable exit vehicle
DisableControlAction(27, 75, true) -- Disable exit vehicle
else
Citizen.Wait(500)
end
end
end)
function DeleteSpawnedVehicles()
while #spawnedVehicles > 0 do
local vehicle = spawnedVehicles[1]
ESX.Game.DeleteVehicle(vehicle)
table.remove(spawnedVehicles, 1)
end
end
function WaitForVehicleToLoad(modelHash)
modelHash = (type(modelHash) == 'number' and modelHash or GetHashKey(modelHash))
if not HasModelLoaded(modelHash) then
RequestModel(modelHash)
while not HasModelLoaded(modelHash) do
Citizen.Wait(0)
DisableControlAction(0, Keys['TOP'], true)
DisableControlAction(0, Keys['DOWN'], true)
DisableControlAction(0, Keys['LEFT'], true)
DisableControlAction(0, Keys['RIGHT'], true)
DisableControlAction(0, 176, true) -- ENTER key
DisableControlAction(0, Keys['BACKSPACE'], true)
drawLoadingText(_U('vehicleshop_awaiting_model'), 255, 255, 255, 255)
end
end
end
function drawLoadingText(text, red, green, blue, alpha)
SetTextFont(4)
SetTextProportional(0)
SetTextScale(0.0, 0.5)
SetTextColour(red, green, blue, alpha)
SetTextDropShadow(0, 0, 0, 0, 255)
SetTextEdge(1, 0, 0, 0, 255)
SetTextDropShadow()
SetTextOutline()
SetTextCentre(true)
BeginTextCommandDisplayText("STRING")
AddTextComponentSubstringPlayerName(text)
EndTextCommandDisplayText(0.5, 0.5)
end
function OpenPharmacyMenu()
ESX.UI.Menu.CloseAll()
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'pharmacy',
{
title = _U('pharmacy_menu_title'),
align = 'top-right',
elements = {
{label = _U('pharmacy_take', _U('medikit')), value = 'medikit'},
{label = _U('pharmacy_take', _U('bandage')), value = 'bandage'}
}
}, function(data, menu)
TriggerServerEvent('esx_ambulancejob:giveItem', data.current.value)
end, function(data, menu)
menu.close()
end)
end
function WarpPedInClosestVehicle(ped)
local coords = GetEntityCoords(ped)
local vehicle, distance = ESX.Game.GetClosestVehicle(coords)
if distance ~= -1 and distance <= 5.0 then
local maxSeats, freeSeat = GetVehicleMaxNumberOfPassengers(vehicle)
for i=maxSeats - 1, 0, -1 do
if IsVehicleSeatFree(vehicle, i) then
freeSeat = i
break
end
end
if freeSeat then
TaskWarpPedIntoVehicle(ped, vehicle, freeSeat)
end
else
ESX.ShowNotification(_U('no_vehicles'))
end
end
RegisterNetEvent('esx_ambulancejob:heal')
AddEventHandler('esx_ambulancejob:heal', function(healType)
local playerPed = PlayerPedId()
local maxHealth = GetEntityMaxHealth(playerPed)
if healType == 'small' then
local health = GetEntityHealth(playerPed)
local newHealth = math.min(maxHealth, math.floor(health + maxHealth / 8))
SetEntityHealth(playerPed, newHealth)
elseif healType == 'big' then
SetEntityHealth(playerPed, maxHealth)
end
ESX.ShowNotification(_U('healed'))
end)