Removed

Here to remove old posts

This can be done a number of ways. Given you mentioned the job was called “cardealer” I am going to make some assumptions. Like you using the ESX framework. But in future, please provide as much information as possible. If anybody wants support, they should be giving EVERYTHING they know, so people can get straight to solving the issue, not figuring out stuff you already know and could have shared with those helping.

Anyway, all of these solutions assume you are using ESX and require something similar to the following added to the script, if it isn’t already (it probably is, though). These 2 event handlers can go anywhere in the client file;

RegisterNetEvent("esx:playerLoaded")
AddEventHandler("esx:playerLoaded", function(xPlayer)
	ESX.PlayerData = xPlayer
end)

RegisterNetEvent("esx:setJob")
AddEventHandler("esx:setJob", function(job)
	ESX.PlayerData.job = job
end)

The above code is not the only way to ensure the player’s job is always set, but it’s one of the best ways to avoid calling slow ESX functions in a loop. Basically, with ESX, once you have set the player’s job on load and updated on setJob, you can access the name with ESX.PlayerData.job.name and use that for checks. Without something like this, you will get an error that you are trying to reference a nil property “job” of PlayerData, if you use my solutions. Anyway, now that we know what job the player has and it’s updated each time they set a new job, we can proceed. Let’s choose a solution.

Solution 1:
Edit the line for the key press check and add a check for the player’s job. This however, does mean that the marker and the 3D text are displayed despite not being a car dealer.

if IsControlJustPressed(0, 38) and ESX.PlayerData.job.name == "cardealer" then
	OpenVehicleShop()
end

Solution 2:
Wrap the whole vehicleshopCoords loop inside a check for the job, so that no marker or text will display unless they have the car dealer job.

if ESX.PlayerData.job.name == "cardealer" then
	for i = 1, #vehicleshopCoords do
		-- etc
	end
end

Solution 3:
If you want to compare it to multiple jobs, not just “cardealer”, you can replace ESX.PlayerData.job.name == "cardealer" with a function that loops a table and checks against all approved jobs. I called mine HasApprovedJob.

local approvedJobs = {
	"cardealer",
	"pdm",
	"vapid"
}

function HasApprovedJob()
	for i = 1, #approvedJobs do
		if ESX.PlayerData.job.name == approvedJobs[i] then
			return true
		end
	end
	return false
end

Then you just use solution 1 or 2 with this function call, instead of the single job check. For example;

if HasApprovedJob() then
	for i = 1, #vehicleshopCoords do
		-- etc
	end
end

Completed Example:

local approvedJobs = {
	"cardealer",
	"pdm",
	"vapid"
}

function HasApprovedJob()
	for i = 1, #approvedJobs do
		if ESX.PlayerData.job.name == approvedJobs[i] then
			return true
		end
	end
	return false
end

RegisterNetEvent('esx:playerLoaded')
AddEventHandler('esx:playerLoaded', function(xPlayer)
	ESX.PlayerData = xPlayer
end)

RegisterNetEvent("esx:setJob")
AddEventHandler("esx:setJob", function(job)
	ESX.PlayerData.job = job
end)

Citizen.CreateThread(function()
	while true do
		Citizen.Wait(3)
		local ped = PlayerPedId()
		if HasApprovedJob() then
			for i = 1, #vehicleshopCoords do
				local actualShop = vehicleshopCoords[i]
				local dist = #(actualShop - GetEntityCoords(ped))
				if dist <= 50.0 then
					DrawMarker(23, actualShop.x, actualShop.y, actualShop.z - 0.97, 0, 0, 0, 0, 0, 0, 1.0, 1.0, 0.7, 200, 10, 10, 100, 0, 0, 0, 0, 0, 0, 0)
					if dist <= 10.0 then
						DrawText3Ds(actualShop.x, actualShop.y, actualShop.z,"PRESS ~r~E~w~ TO OPEN VEHICLE SHOP")
						if dist <= 5.0 then
							if IsControlJustPressed(0, 38) then
								OpenVehicleShop()
							end
						end
					end
				end
			end
		end
	end
end)