Files
esx_core-esx-framework/esx_ambulancejob/client/job.lua
T
EbenSantuy 5b591a94b5 This I made for people who cant configure the esx_kashacters and to fix all the issue ! thanks to KASH to make this nice Feature
Thanks You KASH (github.com/KASHZIN)Who The Original Develop This ESX_KASHACTERS RELEASE And To for the tutorial XxFri3ndlyxX (github.com/XxFri3ndlyxX)

this tutorial i made little bit use XxFri3ndlyxX tutorial

1.Step One [ essentialmode\client\main.lua ]

Delete Or Replace This !
--[[Citizen.CreateThread(function()
	while true do
		Citizen.Wait(0)

		if NetworkIsSessionStarted() then
			TriggerServerEvent('es:firstJoinProper')
			TriggerEvent('es:allowedToSpawn')
			return
		end
	end
end)]]--

2.Step Two [ es_extended [ LINE : 457 ] client/main.lua ]
This To Fix Cant Open Inventory When You Die And Get Revived

Change You Menu interactions to this !
``` ---Menu interactions
Citizen.CreateThread(function()
	while true do
		
		Citizen.Wait(0)

		if IsControlJustReleased(0, 289) and IsInputDisabled(0) and not ESX.UI.Menu.IsOpen('default', 'es_extended', 'inventory') then
			ESX.ShowInventory()
		end

	end
end)```

3. Step Three 
To Get Your esx_kashacters work you need do this on your database

SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = 'owner'
And This
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = 'indentifier'
Credit @Xnubil

6. Step Six [Fix Datastore]
Duplicate Your esx_datastore or add This line on your esx_datastore server\main.lua

-- Fix was taken from this link --
-- https://forum.fivem.net/t/release-esx-kashacters-multi-character/251613/448?u=xxfri3ndlyxx --
AddEventHandler('esx:playerLoaded', function(source)

  local result = MySQL.Sync.fetchAll('SELECT * FROM datastore')

	for i=1, #result, 1 do
		local name   = result[i].name
		local label  = result[i].label
		local shared = result[i].shared

		local result2 = MySQL.Sync.fetchAll('SELECT * FROM datastore_data WHERE name = @name', {
			['@name'] = name
		})

		if shared == 0 then

			table.insert(DataStoresIndex, name)
			DataStores[name] = {}

			for j=1, #result2, 1 do
				local storeName  = result2[j].name
				local storeOwner = result2[j].owner
				local storeData  = (result2[j].data == nil and {} or json.decode(result2[j].data))
				local dataStore  = CreateDataStore(storeName, storeOwner, storeData)

				table.insert(DataStores[name], dataStore)
			end
		end
	end

	local _source = source
	local xPlayer = ESX.GetPlayerFromId(_source)
  	local dataStores = {}
  
	for i=1, #DataStoresIndex, 1 do
		local name      = DataStoresIndex[i]
		local dataStore = GetDataStore(name, xPlayer.identifier)

		if dataStore == nil then
			MySQL.Async.execute('INSERT INTO datastore_data (name, owner, data) VALUES (@name, @owner, @data)',
			{
				['@name']  = name,
				['@owner'] = xPlayer.identifier,
				['@data']  = '{}'
			})

			dataStore = CreateDataStore(name, xPlayer.identifier, {})
			table.insert(DataStores[name], dataStore)
		end

		table.insert(dataStores, dataStore)
	end

	xPlayer.set('dataStores', dataStores)
end)

Download Link : https://github.com/XxFri3ndlyxX/esx_datastore
Credits : https://github.com/XxFri3ndlyxX

5. Step Five [ Fix Ambulance ]
This To Fix Die Tele And When Your Get Revived You Cant Open any Menu only F2

Download My File the esx_ambulancejob (or download the lastest version esx_ambulancejob :v)

6. Step Six [ Fix your esx_kashacters identifier ]
Download My mysql-async And start on your server.cfg

7. Step Seven [ Fix Your Identifier And Spawn] 
Download My esx_kashacters Modified And start on your server.cfg
Thats All Identifier [esx_kashacters\server\main.lua] maybe thats all
you need in Roleplay Server if you wan to change just change it 

===--------------------------------------------------------------------===

Okey Thats All Make My esx_kashacters work properly if you wanna ask
My Discord : Blue.#5108

Thank you Again to KASH And XxFri3ndlyxX ! :)
ENJOY YOUR ESX_KASHACTERS
2019-07-17 15:26:07 +07:00

919 lines
28 KiB
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-left',
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-left',
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-left',
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)
local playerPed = PlayerPedId()
DoScreenFadeOut(800)
while not IsScreenFadedOut() do
Citizen.Wait(500)
end
ESX.Game.Teleport(playerPed, coords, function()
DoScreenFadeIn(800)
if heading then
SetEntityHeading(playerPed, heading)
end
end)
end
-- Draw markers & Marker logic
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
local playerCoords = GetEntityCoords(PlayerPedId())
local letSleep, 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)
letSleep = 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)
letSleep = 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)
letSleep = 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)
letSleep = 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)
letSleep = 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)
letSleep = false
end
if distance < v.Marker.x then
isInMarker, currentHospital, currentPart, currentPartNum = true, hospitalNum, 'FastTravelsPrompt', k
end
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
if letSleep then
Citizen.Wait(500)
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-left',
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-left',
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-left',
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())
ESX.PlayerData = ESX.GetPlayerData()
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-left',
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-left',
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-left',
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-left',
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)
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-left',
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, quiet)
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
if not quiet then
ESX.ShowNotification(_U('healed'))
end
end)