Get Closest Coords

Hey everyone,

I’m trying to get the closest coords to the player and have them spawn their vehicle at that location.

config.lua:

-- Company Locations
Config.Locations = {
	[1] = { 
		workSpawn = {
			coords = vector3(-208.75, -1168.79, 23.04),
			heading = 87.63,
		},
	},
	[2] = { 
		workSpawn = { 
			coords = vector3(-214.63, 6197.11, 31.49),
			heading = 134.72,
		},
	},
}

I have tried literally everything I could think of for the last 5 hours but could never get it. I managed to get the values of the distances between the coords and the player, but could never narrow it down to just one distance - I’d always get two results.

I’ve also removed any irrelevant code from the configuration file, for the example above.

Any help would be greatly appreciated :slight_smile:

The code in which I manage to get the distance values from:

client.lua

	local ClosestLocation = {}
	local _ClosestCoord = nil
	local _ClosestDistance = 10000
	local pos = GetEntityCoords(PlayerPedId())
	local vehicleInfo = vehicleProperties
	for _, loc in pairs(Config.Locations) do
			local _Distance = #(loc.workSpawn.coords - pos)
			if _Distance <= _ClosestDistance then
				_ClosestDistance = _Distance
				_ClosestCoord = loc.workSpawn.coords
				_ClosestHeading = loc.workSpawn.heading
				
				ClosestLocation.D = _ClosestDistance
				ClosestLocation.C = _ClosestCoord
				ClosestLocation.H = _ClosestHeading
				
				 print(ClosestLocation.D .. ' - ' .. ClosestLocation.C)
			end
		end
		local vehicle = CreateVehicle(vehicleProperties.model, ClosestLocation.C.x, ClosestLocation.C.y, ClosestLocation.C.z, ClosestLocation.H, true)

This returns the following in the console:

script:example - 7387.6196289063 - vec3(-208.750000, -1168.790039, 23.040001)
script:example - 21.713495254517 - vec3(-214.630005, 6197.109863, 31.490000)

And it also creates two vehicles, one at each location.

I’ve tried math.min and table.sort but that doesn’t work. If I use print(type(ClosestLocation.D)) it returns:

script:example - number
script:example - number
local closestDist = 10000
local closestSpawn = nil
local pcoords = GetEntityCoords(PlayerPedId())

for i, v in ipairs(Config.Locations) do
    local dist = #(v.workSpawn.coords - pcoords)

    if dist < closestDist then
        closestDist = dist
        closestSpawn = v.workSpawn
    end
end

Once the loop is done you should have the closest spawn point stored in the closestSpawn variable.


EDIT
Just noticed your follow up post which will correctly get the closest spawn, but shouldn’t spawn a vehicle at each location. Have you accdentally put the CreateVehicle call in a loop somehow?

I believe I have, here is the full function:

local function loadVehicle(vehicleProperties, workVehicle)
	local closestDist = 10000
	local closestSpawn = nil
	local pos = GetEntityCoords(PlayerPedId())
	local vehicleInfo = vehicleProperties
	for i, v in ipairs(Config.Locations) do
		if workVehicle then -- Determine whether a work vehicle or impound vehicle is being spawned
			local dist = #(v.workSpawn.coords - pos)
			if dist < closestDist then
				closestDist = dist
				closestSpawn = v.workSpawn
				print(v.workSpawn)
			end
		else -- The below will get changed upon figuring out the above
			local _Distance = #(loc.impoundSpawn.coords - pos)
			if _Distance <= _ClosestDistance then
				_ClosestDistance = _Distance
				_ClosestCoord = loc.impoundSpawn.coords
				_ClosestHeading = loc.impoundSpawn.heading
			end
		end
		MenuV:CloseAll()
		RequestModel(vehicleProperties.model)
		while not HasModelLoaded(vehicleProperties.model) do
			Wait(10)
		end
		local vehicle = CreateVehicle(vehicleProperties.model, v.workSpawn.x, v.workSpawn.y, v.workSpawn.z, v.workSpawn.heading, true)
		local netid = NetworkGetNetworkIdFromEntity(vehicle)
		if workVehicle then
			SetVehicleNumberPlateText(vehicle, QBCore.Shared.RandomStr(3) .. QBCore.Shared.RandomInt(3))
			for a, b in pairs(vehicleProperties.extras) do
				SetVehicleExtra(vehicle, a, b)
			end
			exports['LegacyFuel']:SetFuel(vehicle, 100.0)
			SetVehRadioStation(vehicle, 'OFF')
		end
		if Config.VehicleSpawnProtection then
			SetEntityInvincible(vehicle, true)
			SetEntityAlpha(vehicle, 100, false)
			SetTimeout(Config.VehicleSpawnProtectionTime * 1000, function()
				SetEntityInvincible(vehicle, false)
				SetEntityAlpha(vehicle, 255, false)
			end)
		end
		SetVehicleHasBeenOwnedByPlayer(vehicle, true)
		SetEntityAsMissionEntity(vehicle, true, true)
		SetNetworkIdCanMigrate(netid, true)
		SetVehicleNeedsToBeHotwired(vehicle, false)
		SetModelAsNoLongerNeeded(vehicleProperties.model)
		Wait(100)
		TaskWarpPedIntoVehicle(PlayerPedId(), vehicle, -1)
		Wait(100)
		TriggerEvent("vehiclekeys:client:SetOwner", QBCore.Functions.GetPlate(GetVehiclePedIsIn(PlayerPedId(), false)))
	end
end

After testing, this time around it spawns two vehicles (1 per location) and some how places the player in the middle of the map.

Yeah, you’re spawning the vehicle on each iteration. You need to spawn the vehicle after the for loop is done - the spawn data will be stored in closestSpawn variable when the loop is done that you can use to spawn the vehicle.

After a tidy up, I’ve managed to get it to spawn only one vehicle however it is spawning the vehicle under the map and in the very middle of it.

local function loadVehicle(vehicleProperties, workVehicle)
	local closestDist = 10000
	local closestSpawn = nil
	local pos = GetEntityCoords(PlayerPedId())
	for i, v in ipairs(Config.Locations) do
		if workVehicle then
			local dist = #(v.workSpawn.coords - pos)
			if dist < closestDist then
				closestDist = dist
				closestSpawn = v.workSpawn
				print(closestSpawn.coords)
			end
		else -- The below will get changed upon figuring out the above
			local dist = #(v.impoundSpawn.coords - pos)
			if dist < closestDist then
				closestDist = dist
				closestSpawn = v.impoundSpawn
				print(closestSpawn.coords)
			end
		end
	end
		MenuV:CloseAll()
		RequestModel(vehicleProperties.model)
		while not HasModelLoaded(vehicleProperties.model) do
			Wait(10)
		end
		local vehicle = CreateVehicle(vehicleProperties.model, closestSpawn.x, closestSpawn.y, closestSpawn.z, closestSpawn.heading, true)
		local netid = NetworkGetNetworkIdFromEntity(vehicle)
		if workVehicle then
			SetVehicleNumberPlateText(vehicle, QBCore.Shared.RandomStr(3) .. QBCore.Shared.RandomInt(3))
			for a, b in pairs(vehicleProperties.extras) do
				SetVehicleExtra(vehicle, a, b)
			end
			exports['LegacyFuel']:SetFuel(vehicle, 100.0)
			SetVehRadioStation(vehicle, 'OFF')
		end
		if Config.VehicleSpawnProtection then
			SetEntityInvincible(vehicle, true)
			SetEntityAlpha(vehicle, 100, false)
			SetTimeout(Config.VehicleSpawnProtectionTime * 1000, function()
				SetEntityInvincible(vehicle, false)
				SetEntityAlpha(vehicle, 255, false)
			end)
		end
		SetVehicleHasBeenOwnedByPlayer(vehicle, true)
		SetEntityAsMissionEntity(vehicle, true, true)
		SetNetworkIdCanMigrate(netid, true)
		SetVehicleNeedsToBeHotwired(vehicle, false)
		SetModelAsNoLongerNeeded(vehicleProperties.model)
		Wait(100)
		TaskWarpPedIntoVehicle(PlayerPedId(), vehicle, -1)
		Wait(100)
		TriggerEvent("vehiclekeys:client:SetOwner", QBCore.Functions.GetPlate(GetVehiclePedIsIn(PlayerPedId(), false)))
end

When I get the print, it shows:
script:example - vec3(-214.630005, 6197.109863, 31.490000)
which is a correct location.

And I’ve got it :slight_smile: I just had to change the line:

local vehicle = CreateVehicle(vehicleProperties.model, closestSpawn.x, closestSpawn.y, closestSpawn.z, closestSpawn.heading, true)

to:

local vehicle = CreateVehicle(vehicleProperties.model, closestSpawn.coords.x, closestSpawn.coords.y, closestSpawn.coords.z, closestSpawn.heading, true)

I think the lack of sleep isn’t helping and I just need a fresh set of eyes as I’m starting to see all my mistakes now haha. Thank you and I really appreciate your help!

local vehicle = CreateVehicle(vehicleProperties.model, closestSpawn.x, closestSpawn.y, closestSpawn.z, closestSpawn.heading, true)

should be

local vehicle = CreateVehicle(vehicleProperties.model, closestSpawn.coords.x, closestSpawn.coords.y, closestSpawn.coords.z, closestSpawn.heading, true)

Glad I could help!