[Release-Archived] Cops FiveM

Here is the updated cops system to work with the weashop that i converted to couchdb :slight_smile:
(this is the server.lua)

local couchFunctions = {}

if(db.driver == "mysql") then
	require "resources/essentialmode/lib/MySQL"
	MySQL:open(db.sql_host, db.sql_database, db.sql_user, db.sql_password)
elseif(db.driver == "mysql-async") then
	require "resources/mysql-async/lib/MySQL"
	TriggerEvent('es:exposeDBFunctions', function(dbExposed)
		couchFunctions = dbExposed
		dbExposed.createDatabase("police", function()end)
	end)

	
end

local inServiceCops = {}

function addCop(identifier)
	
	if(db.driver == "mysql") then
		local result = "nil"
		local query = MySQL:executeQuery("SELECT * FROM police WHERE identifier = '@identifier'", { ['@identifier'] = identifier})
		local resultq = MySQL:getResults(query, {'rank'}, "identifier")
		
		if(not resultq[1]) then
			result = "nil"
		else
			result = resultq[1].rank
		end
		
		if(result == "nil") then
			MySQL:executeQuery("INSERT INTO police (`identifier`) VALUES ('@identifier')", { ['@identifier'] = identifier})
		end
		
	elseif(db.driver == "mysql-async") then
		MySQL.Async.fetchAll("SELECT * FROM police WHERE identifier = @identifier", { ['@identifier'] = identifier}, function (result)
			if(result[1] == nil) then
				MySQL.Async.execute("INSERT INTO police (`identifier`) VALUES @identifier", { ['@identifier'] = identifier})
			end
		end)
	
		couchFunctions.getDocumentByRow("police", "identifier", identifier, function(document)
			if(document == false) then
				couchFunctions.createDocument("police", {
					identifier = identifier,
					rank = "Recruit"
				}, function()end)
			end
		end)
	end
end

function remCop(identifier)
	if(db.driver == "mysql") then
		MySQL:executeQuery("DELETE FROM police WHERE identifier = '@identifier'", { ['@identifier'] = identifier})
	elseif(db.driver == "mysql-async") then
		MySQL.Async.execute("DELETE FROM police WHERE identifier = @identifier", { ['@identifier'] = identifier})
	
		couchFunctions.getDocumentByRow("police", "identifier", identifier, function(document)
			if(document ~= false) then
				couchFunctions.updateDocument("police", document._id, {
					identifier = document.identifier .. "/"
				}, function()end)
			end
		end)
	end
end

function checkIsCop(identifier)
	if(db.driver == "mysql") then
		local query = MySQL:executeQuery("SELECT * FROM police WHERE identifier = '@identifier'", { ['@identifier'] = identifier})
		local result = MySQL:getResults(query, {'rank'}, "identifier")
		
		if(not result[1]) then
			TriggerClientEvent('police:receiveIsCop', source, "unknown")
		else
			TriggerClientEvent('police:receiveIsCop', source, result[1].rank)
		end
	elseif(db.driver == "mysql-async") then
		MySQL.Async.fetchAll("SELECT * FROM police WHERE identifier = @identifier", { ['@identifier'] = identifier}, function (result)
			if(result[1] == nil) then
				TriggerClientEvent('police:receiveIsCop', source, "unknown")
			else
				TriggerClientEvent('police:receiveIsCop', source, result[1].rank)
			end
		end)
	
		couchFunctions.getDocumentByRow("police", "identifier", identifier, function(document)
			if(document == false) then
				TriggerClientEvent('police:receiveIsCop', source, "unknown")
			else
				TriggerClientEvent('police:receiveIsCop', source, document.rank)
			end
		end)
	end
end

AddEventHandler('playerDropped', function()
	if(inServiceCops[source]) then
		inServiceCops[source] = nil
		
		if(config.useJobSystem == true) then
			TriggerEvent("jobssystem:disconnectReset", source, config.job.officer_not_on_duty_job_id)
		end
		
		for i, c in pairs(inServiceCops) do
			TriggerClientEvent("police:resultAllCopsInService", i, inServiceCops)
		end
	end
end)

if(config.useCopWhitelist == true) then
	RegisterServerEvent('police:checkIsCop')
	AddEventHandler('police:checkIsCop', function()
		local identifier = getPlayerID(source)
		checkIsCop(identifier)
	end)
end
RegisterServerEvent('bank:withdrawAmende')
AddEventHandler('bank:withdrawAmende', function(amount)
    TriggerEvent('es:getPlayerFromId', source, function(user)
        local player = user.identifier
        local bankbalance = bankBalance(player)
		withdraw(player, amount)
		local new_balance = bankBalance(player)
		TriggerClientEvent("es_freeroam:notify", source, "CHAR_BANK_MAZE", 1, "Maze Bank", false, "New Balance: ~g~$" .. new_balance)
		TriggerClientEvent("banking:updateBalance", source, new_balance)
		TriggerClientEvent("banking:removeBalance", source, amount)
		CancelEvent()
    end)
end)
RegisterServerEvent('police:takeService')
AddEventHandler('police:takeService', function()

	if(not inServiceCops[source]) then
		inServiceCops[source] = GetPlayerName(source)
		
		for i, c in pairs(inServiceCops) do
			TriggerClientEvent("police:resultAllCopsInService", i, inServiceCops)
		end
	end
end)

RegisterServerEvent('police:breakService')
AddEventHandler('police:breakService', function()

	if(inServiceCops[source]) then
		inServiceCops[source] = nil
		
		for i, c in pairs(inServiceCops) do
			TriggerClientEvent("police:resultAllCopsInService", i, inServiceCops)
		end
	end
end)

RegisterServerEvent('police:getAllCopsInService')
AddEventHandler('police:getAllCopsInService', function()
	TriggerClientEvent("police:resultAllCopsInService", source, inServiceCops)
end)

RegisterServerEvent('police:checkingPlate')
AddEventHandler('police:checkingPlate', function(plate)

	if(db.driver == "mysql") then
		local executed_query = MySQL:executeQuery("SELECT Nom FROM user_vehicle JOIN users ON user_vehicle.identifier = users.identifier WHERE vehicle_plate = '@plate'", { ['@plate'] = plate })
		local result = MySQL:getResults(executed_query, { 'Nom' }, "identifier")
		if (result[1]) then
			for _, v in ipairs(result) do
				TriggerClientEvent("police:notify", source, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, txt[config.lang]["vehicle_checking_plate_part_1"]..plate..txt[config.lang]["vehicle_checking_plate_part_2"] .. v.Nom..txt[config.lang]["vehicle_checking_plate_part_3"])
			end
		else
			TriggerClientEvent("police:notify", source, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, txt[config.lang]["vehicle_checking_plate_part_1"]..plate..txt[config.lang]["vehicle_checking_plate_not_registered"])
		end
	elseif(db.driver == "mysql-async") then
		MySQL.Async.fetchAll("SELECT Nom FROM user_vehicle JOIN users ON user_vehicle.identifier = users.identifier WHERE vehicle_plate = '"..plate.."'", { ['@plate'] = plate }, function (result)
			if(result[1]) then
				for _, v in ipairs(result) do
					TriggerClientEvent("police:notify", source, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, txt[config.lang]["vehicle_checking_plate_part_1"]..plate..txt[config.lang]["vehicle_checking_plate_part_2"] .. v.Nom..txt[config.lang]["vehicle_checking_plate_part_3"])
				end
			else
				TriggerClientEvent("police:notify", source, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, txt[config.lang]["vehicle_checking_plate_part_1"]..plate..txt[config.lang]["vehicle_checking_plate_not_registered"])
			end
		end)
	end
end)
-- jail addon
RegisterServerEvent('jail:teleportToJail')
AddEventHandler('jail:teleportToJail', function(t, amount)
	TriggerClientEvent('jail:teleportPlayer', t, amount)
end)
-- jail addon end
RegisterServerEvent('police:confirmUnseat')
AddEventHandler('police:confirmUnseat', function(t)
	TriggerClientEvent("police:notify", source, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, txt[config.lang]["unseat_sender_notification_part_1"] .. GetPlayerName(t) .. txt[config.lang]["unseat_sender_notification_part_2"])
	TriggerClientEvent('police:unseatme', t)
end)

RegisterServerEvent('police:dragRequest')
AddEventHandler('police:dragRequest', function(t)
	TriggerClientEvent("police:notify", source, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, txt[config.lang]["drag_sender_notification_part_1"] .. GetPlayerName(t) .. txt[config.lang]["drag_sender_notification_part_2"])
	TriggerClientEvent('police:toggleDrag', t, source)
end)

RegisterServerEvent('police:targetCheckInventory')
AddEventHandler('police:targetCheckInventory', function(target)

	local identifier = getPlayerID(target)
	
	if(config.useVDKInventory == true) then
		if(db.driver == "mysql") then
			local strResult = txt[config.lang]["checking_inventory_part_1"] .. GetPlayerName(target) .. txt[config.lang]["checking_inventory_part_2"]
			local executed_query = MySQL:executeQuery("SELECT * FROM `user_inventory` JOIN items ON items.id = user_inventory.item_id WHERE user_id = '@username'", { ['@username'] = identifier })
			local result = MySQL:getResults(executed_query, { 'quantity', 'libelle', 'item_id', 'isIllegal' }, "item_id")
			if (result) then
				for _, v in ipairs(result) do
					if(v.quantity ~= 0) then
						strResult = strResult .. v.quantity .. "*" .. v.libelle .. ", "
					end
					if(v.isIllegal == "1" or v.isIllegal == "True" or v.isIllegal == 1 or v.isIllegal == true) then
						TriggerClientEvent('police:dropIllegalItem', target, v.item_id)
					end
				end
			end
			
			TriggerClientEvent("police:notify", source, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, strResult)
			
		elseif(db.driver == "mysql-async") then
			MySQL.Async.fetchAll("SELECT * FROM `user_inventory` JOIN items ON items.id = user_inventory.item_id WHERE user_id = @username", { ['@username'] = identifier }, function (result)
				local strResult = txt[config.lang]["checking_inventory_part_1"] .. GetPlayerName(target) .. txt[config.lang]["checking_inventory_part_2"]
				
				for _, v in ipairs(result) do
					if(v.quantity ~= 0) then
						strResult = strResult .. v.quantity .. "*" .. v.libelle .. ", "
					end
					
					if(v.isIllegal == "1" or v.isIllegal == "True" or v.isIllegal == 1 or v.isIllegal == true) then
						TriggerClientEvent('police:dropIllegalItem', target, v.item_id)
					end
				end
				
				TriggerClientEvent("police:notify", source, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, strResult)
			end)
		end
	end
	
	if(config.useWeashop == true) then
	
		if(db.driver == "mysql") then
			local strResult = txt[config.lang]["checking_weapons_part_1"] .. GetPlayerName(target) .. txt[config.lang]["checking_weapons_part_2"]
		
			local executed_query = MySQL:executeQuery("SELECT * FROM user_weapons WHERE identifier = '@username'", { ['@username'] = identifier })
			local result = MySQL:getResults(executed_query, { 'weapon_model' }, 'identifier' )
			if (result) then
				for _, v in ipairs(result) do
					strResult = strResult .. v.weapon_model .. ", "
				end
			end
			
			TriggerClientEvent("police:notify", source, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, strResult)
			
		elseif(db.driver == "mysql-async") then
				local del = {}
			
				local strResult = txt[config.lang]["checking_weapons_part_1"] .. GetPlayerName(target) .. txt[config.lang]["checking_weapons_part_2"]
				TriggerEvent('es:getPlayerFromId', target, function(user)
					TriggerEvent('es:exposeDBFunctions', function(db)
						db.getDocumentByRow('es_weashop', 'identifier', user.identifier, function(dbuser)
							for i=1, #dbuser.weapons do
								strResult = strResult .. dbuser.weapons[i] .. ", "
							end
							RemoveAllPedWeapons(target, true)
							TriggerClientEvent("police:notify", source, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, strResult)
							db.updateDocument('es_weashop', dbuser._id, {weapons = del, cost = del})
						end)
					end)
				end)
				
				
				
			
		end
	end	
end)

RegisterServerEvent('police:finesGranted')
AddEventHandler('police:finesGranted', function(target, amount)
	TriggerClientEvent('police:payFines', target, amount, source)
	TriggerClientEvent("police:notify", source, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, txt[config.lang]["send_fine_request_part_1"]..amount..txt[config.lang]["send_fine_request_part_2"]..GetPlayerName(target))
end)

RegisterServerEvent('police:finesETA')
AddEventHandler('police:finesETA', function(officer, code)
	if(code==1) then
		TriggerClientEvent("police:notify", officer, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, GetPlayerName(source)..txt[config.lang]["already_have_a_pendind_fine_request"])
	elseif(code==2) then
		TriggerClientEvent("police:notify", officer, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, GetPlayerName(source)..txt[config.lang]["request_fine_timeout"])
	elseif(code==3) then
		TriggerClientEvent("police:notify", officer, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, GetPlayerName(source)..txt[config.lang]["request_fine_refused"])
	elseif(code==0) then
		TriggerClientEvent("police:notify", officer, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, GetPlayerName(source)..txt[config.lang]["request_fine_accepted"])
	end
end)

RegisterServerEvent('police:cuffGranted')
AddEventHandler('police:cuffGranted', function(t)
	TriggerClientEvent("police:notify", source, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, txt[config.lang]["toggle_cuff_player_part_1"]..GetPlayerName(t)..txt[config.lang]["toggle_cuff_player_part_2"])
	TriggerClientEvent('police:getArrested', t)
end)

RegisterServerEvent('police:forceEnterAsk')
AddEventHandler('police:forceEnterAsk', function(t, v)
	TriggerClientEvent("police:notify", source, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, txt[config.lang]["force_player_get_in_vehicle_part_1"]..GetPlayerName(t)..txt[config.lang]["force_player_get_in_vehicle_part_2"])
	TriggerClientEvent('police:forcedEnteringVeh', t, v)
end)

-----------------------------------------------------------------------
----------------------EVENT SPAWN POLICE VEH---------------------------
-----------------------------------------------------------------------
RegisterServerEvent('CheckPoliceVeh')
AddEventHandler('CheckPoliceVeh', function(vehicle)
	TriggerClientEvent('FinishPoliceCheckForVeh',source)
	TriggerClientEvent('policeveh:spawnVehicle', source, vehicle)
end)

-----------------------------------------------------------------------
---------------------COMMANDE ADMIN AJOUT / SUPP COP-------------------
-----------------------------------------------------------------------
if(config.useCopWhitelist) then

	TriggerEvent('es:addGroupCommand', 'copadd', "admin", function(source, args, user)
		 if(not args[2]) then
			TriggerClientEvent('chatMessage', source, txt[config.lang]["title_notification"], {255, 0, 0}, txt[config.lang]["usage_command_copadd"])	
		else
			if(GetPlayerName(tonumber(args[2])) ~= nil)then
				local player = tonumber(args[2])
				addCop(getPlayerID(player))
				TriggerClientEvent('chatMessage', source, txt[config.lang]["title_notification"], {255, 0, 0}, txt[config.lang]["command_received"])
				TriggerClientEvent("police:notify", player, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, txt[config.lang]["become_cop_success"])
				TriggerClientEvent('police:nowCop', player)
			else
				TriggerClientEvent('chatMessage', source, txt[config.lang]["title_notification"], {255, 0, 0}, txt[config.lang]["no_player_with_this_id"])
			end
		end
	end, function(source, args, user) 
		TriggerClientEvent('chatMessage', source, txt[config.lang]["title_notification"], {255, 0, 0}, txt[config.lang]["not_enough_permission"])
	end)

	TriggerEvent('es:addGroupCommand', 'coprem', "admin", function(source, args, user) 
		 if(not args[2]) then
			print("nein")
			TriggerClientEvent('chatMessage', source, txt[config.lang]["title_notification"], {255, 0, 0}, txt[config.lang]["usage_command_coprem"])	
		else
			if(GetPlayerName(tonumber(args[2])) ~= nil)then
				local player = tonumber(args[2])
				remCop(getPlayerID(player))
				TriggerClientEvent("police:notify", player, "CHAR_ANDREAS", 1, txt[config.lang]["title_notification"], false, txt[config.lang]["remove_from_cops"])
				TriggerClientEvent('chatMessage', source, txt[config.lang]["title_notification"], {255, 0, 0}, txt[config.lang]["command_received"])
				TriggerClientEvent('police:noLongerCop', player)
			else
				TriggerClientEvent('chatMessage', source, txt[config.lang]["title_notification"], {255, 0, 0}, txt[config.lang]["no_player_with_this_id"])
			end
		end
	end, function(source, args, user) 
		TriggerClientEvent('chatMessage', source, txt[config.lang]["title_notification"], {255, 0, 0}, txt[config.lang]["not_enough_permission"])
	end)
	
end

-- get's the player id without having to use bugged essentials
function getPlayerID(source)
    local identifiers = GetPlayerIdentifiers(source)
    local player = getIdentifiant(identifiers)
    return player
end

-- gets the actual player id unique to the player,
-- independent of whether the player changes their screen name
function getIdentifiant(id)
    for _, v in ipairs(id) do
        return v
    end
end

3 Likes

This doesn’t give weapons back when finishing shift?

Also pasting this into police/server.lua meant i had to add myself to police everytime i joined the server as i couldn’t see the marker.

For those having problems with this remember everytime you add something that creates a database you need to remove essentialsmode database and let it recreate with the new one.

Is it possible for me to change it so when you fine someone it comes out of the cash but not bank?

I deleted essentialmode DB and police DB, your version didn’t create a police DB i had to use the original version, and it’s the same when i paste yours in a need to add myself to the police each time i connect.

your doing this in couchdb right, because mine creates it fine…

yeah couchDB
20 characters

Only issue I seem to be having now is that it is spawning two cars. Everything is working properly (minus plate check I am just guessing that is cause ES Garages seems to be not sending enough to couchdb) but Yeah when we select say police2, it will spawn two of them, one you get into the other sits pretty much underneath you.

Found a pretty nasty bug. If a cop grabs and forces a suspect into a vehicle and then that cop dies, and the suspect also dies, that suspect will be attached to the cop player once respawned. I couldn’t find any way to get detached other than relogging.

@Kevin_Helium : I’ll look at your issue later today :slight_smile:

@Hampus_Thilen : Some changes are needed to be done in client.lua but yes it is possible, I let you do theses modifications

@rjross2013 : thanks, I’ll look at that later today to intergrate weashop couchdb version

@risenagain : Some changes are needed to be done on client.lua but yes it is possible, I let you do theses modifications

@Wes187inc : I haven’t this problem, have you modified the script ? Have you the latest version ?

@ImDylan93 : Ohhh, please open a ticket on github

I have the latest version, only thing I have modded is changed around the vehicles on my testing server

https://gyazo.com/4e816797e0e7633bd2f0fa95f1bdeed0

Hello there ! I got a bug when i add a new garage in garage list, i can’t spawn veh, they go under the map … how can i do ?

@Wes187inc : I don’t know why it’s spawning 2 vehicles. Can you send me your script version please ?

@Boulouk_22 : multiple location isn’t support yet : https://github.com/Kyominii/Cops_FiveM/issues/44

Hello ! I would like to know why the car is not spawning … i see the car when i want to spawn it and im selecting it and its just not spawning … i dont have any errors in console !

Have you any error on client ? Have you the last version of Cops_FiveM ?

I modified the code myself and fixed an issue where people that were whitelisted as cops couldn’t be cuffed even when off duty.

Not 100% sure what you mean by script version but I just downloaded it 2 days ago, here is this:

– Manifest
resource_manifest_version ‘77731fab-63ca-442c-a67b-abc70f28dfa5’

And this is my vehicle script

local policeveh = {
	opened = false,
	title = txt[config.lang]["garage_global_title"],
	currentmenu = "main",
	lastmenu = nil,
	currentpos = nil,
	selectedbutton = 0,
	marker = { r = 0, g = 155, b = 255, a = 200, type = 1 }, -- ???
	menu = {
		x = 0.11,
		y = 0.25,
		width = 0.2,
		height = 0.04,
		buttons = 10,
		from = 1,
		to = 10,
		scale = 0.4,
		font = 0,
		["main"] = {
			title = txt[config.lang]["menu_categories_title"],
			name = "main",
			buttons = {
				{name = "Police1", costs = 0, description = {}, model = "police"},
				{name = "Police2", costs = 0, description = {}, model = "police2"},
				{name = "Police3", costs = 0, description = {}, model = "police3"},
				{name = "Police4", costs = 0, description = {}, model = "police4"},
				--{name = "Police5", costs = 0, description = {}, model = "police5"},
				{name = "Police6", costs = 0, description = {}, model = "police6"},
				{name = "Police7", costs = 0, description = {}, model = "police7"},
				{name = "Police Mustang", costs = 0, description = {}, model = "2015polstang"},
				{name = "Offroad Police Tahoe", costs = 0, description = {}, model = "offpol"},
				--{name = "FBI2", costs = 0, description = {}, model = "fbi2"},
				{name = "BMW Police Bike", costs = 0, description = {}, model = "policeb"},
			
			}
		},
	}
}

local fakecar = {model = '', car = nil}
local boughtcar = false
local vehicle_price = 0

function LocalPed()
return GetPlayerPed(-1)
end

-------------------------------------------------
----------------CONFIG SELECTION-----------------
-------------------------------------------------

function ButtonSelected(button)
	local ped = GetPlayerPed(-1)
	local this = policeveh.currentmenu
	if this == "main" then
		TriggerServerEvent('CheckPoliceVeh',button.model)
	end
end

-------------------------------------------------
------------------FINISH AND CLOSE---------------
-------------------------------------------------

RegisterNetEvent('FinishPoliceCheckForVeh')
AddEventHandler('FinishPoliceCheckForVeh', function()
	boughtcar = true
	CloseVeh()
end)

-------------------------------------------------
-------------------PLAYER HAVE VEH---------------
-------------------------------------------------

function DoesPlayerHaveVehicle(model,button,y,selected)
		local t = false
		if t then
			drawMenuRight("OWNED",policeveh.menu.x,y,selected)
		end
end

-------------------------------------------------
----------------CONFIG OPEN MENU-----------------
-------------------------------------------------

function OpenMenuVeh(menu)
	fakecar = {model = '', car = nil}
	policeveh.lastmenu = policeveh.currentmenu
	if menu == "main" then
		policeveh.lastmenu = "main"
	end
	policeveh.menu.from = 1
	policeveh.menu.to = 10
	policeveh.selectedbutton = 0
	policeveh.currentmenu = menu
end

-------------------------------------------------
------------------DRAW NOTIFY--------------------
-------------------------------------------------

function drawNotification(text)
	SetNotificationTextEntry("STRING")
	AddTextComponentString(text)
	DrawNotification(false, false)
end

-------------------------------------------------
------------------DRAW TITLE MENU----------------
-------------------------------------------------

function drawMenuTitle(txt,x,y)
local menu = policeveh.menu
	SetTextFont(2)
	SetTextProportional(0)
	SetTextScale(0.5, 0.5)
	SetTextColour(255, 255, 255, 255)
	SetTextEntry("STRING")
	AddTextComponentString(txt)
	DrawRect(x,y,menu.width,menu.height,0,0,0,150)
	DrawText(x - menu.width/2 + 0.005, y - menu.height/2 + 0.0028)
end

-------------------------------------------------
------------------DRAW MENU BOUTON---------------
-------------------------------------------------

function drawMenuButton(button,x,y,selected)
	local menu = policeveh.menu
	SetTextFont(menu.font)
	SetTextProportional(0)
	SetTextScale(menu.scale, menu.scale)
	if selected then
		SetTextColour(0, 0, 0, 255)
	else
		SetTextColour(255, 255, 255, 255)
	end
	SetTextCentre(0)
	SetTextEntry("STRING")
	AddTextComponentString(button.name)
	if selected then
		DrawRect(x,y,menu.width,menu.height,255,255,255,255)
	else
		DrawRect(x,y,menu.width,menu.height,0,0,0,150)
	end
	DrawText(x - menu.width/2 + 0.005, y - menu.height/2 + 0.0028)
end

-------------------------------------------------
------------------DRAW MENU INFO-----------------
-------------------------------------------------

function drawMenuInfo(text)
	local menu = policeveh.menu
	SetTextFont(menu.font)
	SetTextProportional(0)
	SetTextScale(0.45, 0.45)
	SetTextColour(255, 255, 255, 255)
	SetTextCentre(0)
	SetTextEntry("STRING")
	AddTextComponentString(text)
	DrawRect(0.675, 0.95,0.65,0.050,0,0,0,150)
	DrawText(0.365, 0.934)
end

-------------------------------------------------
----------------DRAW MENU DROIT------------------
-------------------------------------------------

function drawMenuRight(txt,x,y,selected)
	local menu = policeveh.menu
	SetTextFont(menu.font)
	SetTextProportional(0)
	SetTextScale(menu.scale, menu.scale)
	--SetTextRightJustify(1)
	if selected then
		SetTextColour(0, 0, 0, 255)
	else
		SetTextColour(255, 255, 255, 255)
	end
	SetTextCentre(0)
	SetTextEntry("STRING")
	AddTextComponentString(txt)
	DrawText(x + menu.width/2 - 0.03, y - menu.height/2 + 0.0028)
end

-------------------------------------------------
-------------------DRAW TEXT---------------------
-------------------------------------------------

function drawTxt(text,font,centre,x,y,scale,r,g,b,a)
	SetTextFont(font)
	SetTextProportional(0)
	SetTextScale(scale, scale)
	SetTextColour(r, g, b, a)
	SetTextDropShadow(0, 0, 0, 0,255)
	SetTextEdge(1, 0, 0, 0, 255)
	SetTextDropShadow()
	SetTextOutline()
	SetTextCentre(centre)
	SetTextEntry("STRING")
	AddTextComponentString(text)
	DrawText(x , y)
end

-------------------------------------------------
----------------CONFIG BACK MENU-----------------
-------------------------------------------------

function Back()
	if backlock then
		return
	end
	backlock = true
	if policeveh.currentmenu == "main" then
		CloseVeh()
	elseif vehshop.currentmenu == "main" then
		if DoesEntityExist(fakecar.car) then
			Citizen.InvokeNative(0xEA386986E786A54F, Citizen.PointerValueIntInitialized(fakecar.car))
		end
		fakecar = {model = '', car = nil}
	else
		OpenMenuVeh(policeveh.lastmenu)
	end
end

-------------------------------------------------
----------------FONCTION ???????-----------------
-------------------------------------------------

function f(n)
return n + 0.0001
end

function LocalPed()
return GetPlayerPed(-1)
end

function try(f, catch_f)
local status, exception = pcall(f)
if not status then
catch_f(exception)
end
end
function firstToUpper(str)
    return (str:gsub("^%l", string.upper))
end

function tablelength(T)
  local count = 0
  for _ in pairs(T) do count = count + 1 end
  return count
end

function round(num, idp)
  if idp and idp>0 then
    local mult = 10^idp
    return math.floor(num * mult + 0.5) / mult
  end
  return math.floor(num + 0.5)
end

function stringstarts(String,Start)
   return string.sub(String,1,string.len(Start))==Start
end

-------------------------------------------------
----------------FONCTION OPEN--------------------
-------------------------------------------------

function OpenVeh() --OpenCreator
	boughtcar = false
	local ped = LocalPed()
	local pos = {452.115,-1018.106,28.478}
	FreezeEntityPosition(ped,true)
	SetEntityVisible(ped,false)
	local g = Citizen.InvokeNative(0xC906A7DAB05C8D2B,pos[1],pos[2],pos[3],Citizen.PointerValueFloat(),0)
	SetEntityCoords(ped,pos[1],pos[2],g)
	SetEntityHeading(ped,pos[4])
	policeveh.currentmenu = "main"
	policeveh.opened = true
	policeveh.selectedbutton = 0
end

-------------------------------------------------
----------------FONCTION CLOSE-------------------
-------------------------------------------------

function CloseVeh() -- Close Creator
	Citizen.CreateThread(function()
		local ped = LocalPed()
		if not boughtcar then
			FreezeEntityPosition(ped,false)
			SetEntityVisible(ped,true)
		else
			local veh = GetVehiclePedIsUsing(ped)
			local model = GetEntityModel(veh)
			local colors = table.pack(GetVehicleColours(veh))
			local extra_colors = table.pack(GetVehicleExtraColours(veh))
			local plyCoords = GetEntityCoords(ped, 0)

			local mods = {}
			for i = 0,24 do
				mods[i] = GetVehicleMod(veh,i)
			end
			Citizen.InvokeNative(0xEA386986E786A54F, Citizen.PointerValueIntInitialized(veh))

			FreezeEntityPosition(ped,false)
			RequestModel(model)
			while not HasModelLoaded(model) do
				Citizen.Wait(0)
			end
			policevehicle = CreateVehicle(model, plyCoords["x"], plyCoords["y"], plyCoords["z"],90.0,true,false)
			SetModelAsNoLongerNeeded(model)
			
			SetVehicleMod(policevehicle, 11, 2)
			SetVehicleMod(policevehicle, 12, 2)
			SetVehicleMod(policevehicle, 13, 2)
			SetVehicleEnginePowerMultiplier(policevehicle, 35.0)
			
			SetVehicleOnGroundProperly(policevehicle)
			SetVehicleHasBeenOwnedByPlayer(policevehicle,true)
			local id = NetworkGetNetworkIdFromEntity(policevehicle)
			SetNetworkIdCanMigrate(id, true)
			Citizen.InvokeNative(0x629BFA74418D6239,Citizen.PointerValueIntInitialized(policevehicle))
			SetVehicleColours(policevehicle,colors[1],colors[2])
			SetVehicleExtraColours(policevehicle,extra_colors[1],extra_colors[2])
			TaskWarpPedIntoVehicle(GetPlayerPed(-1),policevehicle,-1)
			SetEntityVisible(ped,true)
			
			if DoesEntityExist(fakecar.car) then
				Citizen.InvokeNative(0xEA386986E786A54F, Citizen.PointerValueIntInitialized(fakecar.car))
			end
		end
		
		policeveh.opened = false
		policeveh.menu.from = 1
		policeveh.menu.to = 10
	end)
end

-------------------------------------------------
----------------FONCTION OPEN MENU---------------
-------------------------------------------------

if(config.useNativePoliceGarage == true) then
	local backlock = false
	Citizen.CreateThread(function()
		while true do
			Citizen.Wait(0)
			if GetDistanceBetweenCoords(452.115, -1018.106, 28.478,GetEntityCoords(GetPlayerPed(-1))) > 5 then
				if policeveh.opened then
					CloseVeh()
				end
			end
			if policeveh.opened then
				local ped = LocalPed()
				local menu = policeveh.menu[policeveh.currentmenu]
				drawTxt(policeveh.title,1,1,policeveh.menu.x,policeveh.menu.y,1.0, 255,255,255,255)
				drawMenuTitle(menu.title, policeveh.menu.x,policeveh.menu.y + 0.08)
				drawTxt(policeveh.selectedbutton.."/"..tablelength(menu.buttons),0,0,policeveh.menu.x + policeveh.menu.width/2 - 0.0385,policeveh.menu.y + 0.067,0.4, 255,255,255,255)
				local y = policeveh.menu.y + 0.12
				buttoncount = tablelength(menu.buttons)
				local selected = false

				for i,button in pairs(menu.buttons) do
					if i >= policeveh.menu.from and i <= policeveh.menu.to then

						if i == policeveh.selectedbutton then
							selected = true
						else
							selected = false
						end
						drawMenuButton(button,policeveh.menu.x,y,selected)
						y = y + 0.04
						if policeveh.currentmenu == "main" then
							if selected then
									if fakecar.model ~= button.model then
										if DoesEntityExist(fakecar.car) then
											Citizen.InvokeNative(0xEA386986E786A54F, Citizen.PointerValueIntInitialized(fakecar.car))
										end
										local ped = LocalPed()
										local plyCoords = GetEntityCoords(ped, 0)
										local hash = GetHashKey(button.model)
										RequestModel(hash)
										while not HasModelLoaded(hash) do
											Citizen.Wait(0)
											drawTxt(txt[config.lang]["garage_loading"],0,1,0.5,0.5,1.5,255,255,255,255)

										end
										local veh = CreateVehicle(hash,452.115, -1018.106, 28.478,90.0,true,false)
										while not DoesEntityExist(veh) do
											Citizen.Wait(0)
											drawTxt(txt[config.lang]["garage_loading"],0,1,0.5,0.5,1.5,255,255,255,255)
										end
										FreezeEntityPosition(veh,true)
										SetEntityInvincible(veh,true)
										SetVehicleDoorsLocked(veh,4)
										local netid = NetworkGetNetworkIdFromEntity(veh)
										SetNetworkIdCanMigrate(netid, true)
										TaskWarpPedIntoVehicle(LocalPed(),veh,-1)
										for i = 0,24 do
											SetVehicleModKit(veh,0)
											RemoveVehicleMod(veh,i)
										end
										fakecar = { model = button.model, car = veh}
									end
							end
						end
						if selected and IsControlJustPressed(1,201) then
							ButtonSelected(button)
						end
					end
				end
			end
			if policeveh.opened then
				if IsControlJustPressed(1,202) then
					Back()
				end
				if IsControlJustReleased(1,202) then
					backlock = false
				end
				if IsControlJustPressed(1,188) then
					if policeveh.selectedbutton > 1 then
						policeveh.selectedbutton = policeveh.selectedbutton -1
						if buttoncount > 10 and policeveh.selectedbutton < policeveh.menu.from then
							policeveh.menu.from = policeveh.menu.from -1
							policeveh.menu.to = policeveh.menu.to - 1
						end
					end
				end
				if IsControlJustPressed(1,187)then
					if policeveh.selectedbutton < buttoncount then
						policeveh.selectedbutton = policeveh.selectedbutton +1
						if buttoncount > 10 and policeveh.selectedbutton > policeveh.menu.to then
							policeveh.menu.to = policeveh.menu.to + 1
							policeveh.menu.from = policeveh.menu.from + 1
						end
					end
				end
			end

		end
	end)
end

---------------------------------------------------
------------------EVENT SPAWN VEH------------------
---------------------------------------------------

RegisterNetEvent('policeveh:spawnVehicle')
AddEventHandler('policeveh:spawnVehicle', function(v)
	local car = GetHashKey(v)
	local playerPed = GetPlayerPed(-1)
	if playerPed and playerPed ~= -1 then
		RequestModel(car)
		while not HasModelLoaded(car) do
				Citizen.Wait(0)
		end
		local playerCoords = GetEntityCoords(playerPed)

		veh = CreateVehicle(car, playerCoords, 0.0, true, false)
		local netid = NetworkGetNetworkIdFromEntity(veh)
		SetNetworkIdCanMigrate(netid, true)
		TaskWarpPedIntoVehicle(playerPed, veh, -1)
		SetEntityInvincible(veh, true)
	end
end)

@Jordan_Fleetwood : https://github.com/Kyominii/Cops_FiveM/issues/39

@Wes187inc : I’ll look at that when I would have some time ^^

No rush, appreciate it. Just let me know