Draw marker when player is near

I am having an issue where after so many markers have been placed they start to not show up, how would I be able to only draw a marker when someone is near it?

Check the distance between the player and the marker.
If the marker is close enough to be seen, draw it. If not, don’t.

Thanks, I am pretty new to coding / lua could give me an example?

Firstly you probably should show the code snippet, you use for drawing the markers.

At the end of the day though, the pseudo-code should look like this:

-- 1. get marker coords
-- 2. get player coords
-- compare them
-- if smaller than x (the draw distance you want, let's say 20), draw
-- else don't draw

local markerCoords = { x: '123.0', y: '123.0', z: '123.0' } -- this can be taken from the config for example
local playerCoords = GetEntityCoords(PlayerId()) -- not sure if that's the correct syntax though
local distance = GetDistanceBetweenCoords(table.unpack(markerCoords), table.unpack(playerCoords), true) -- comparing the values

if distance < 20 then
    DrawMarker('blablabla', 1, 2, 3) -- draw the marker
end

Above code is totally from the top of my head, so it naturally won’t work, but I just wanted to show you the steps. Read more about the methods here: https://runtime.fivem.net/doc/natives/

EDIT: changed the if statement

I would have used Lua vector math to get the distance, and the distance > 20 check seems to be reversed, but other than that I am in full agreement with Mentozz.

Citizen.CreateThread(function()
    while true do
        Citizen.Wait(0)

        local ped = GetPlayerPed(-1)
        local playerPos = GetEntityCoords(ped, true)

        for i,pos in pairs(INTERIORS) do
            DrawMarker(1, pos.x, pos.y, pos.z-1.02, 0, 0, 0, 0, 0, 0, 0.7,0.7,0.8, 255,255,255, 200, 0, 0, 2, 0, 0, 0, 0)
            if (Vdist(playerPos.x, playerPos.y, playerPos.z, pos.x, pos.y, pos.z) < 1.0) and (not PED_hasBeenTeleported) then
                POS_actual = pos.id
                if not gui_interiors.opened then
                    gui_interiors_OpenMenu()
                end
            end
        end
    end
end)

This is where I am drawing the marker.
How would I make it work with this?

Move the Vdist call to before drawing the marker, and store the value it returns.
Then compare that to whatever you want the draw range to be. If it’s nearer than that, do the draw.
In the existing if check for the distance, put in the same variable.

Sorry, still a little confused.

local distance = Vdist(playerPos.x, playerPos.y, playerPos.z, pos.x, pos.y, pos.z)

Does this look right?

Yes, so far so good.
(I mean, I wouldn’t use Vdist at all, but let’s not confuse the issue!)

		if distance > 20 then
			for i,pos in pairs(INTERIORS) do
				DrawMarker(1, pos.x, pos.y, pos.z-1.02, 0, 0, 0, 0, 0, 0, 0.7,0.7,0.8, 255,255,255, 200, 0, 0, 2, 0, 0, 0, 0)
					if (Vdist(playerPos.x, playerPos.y, playerPos.z, pos.x, pos.y, pos.z) < 1.0) and (not PED_hasBeenTeleported) then
					POS_actual = pos.id
                if not gui_interiors.opened then
                    gui_interiors_OpenMenu()
                end
            end
        end
    end
end)

This is most definitely wrong help me out with this here.

Hey, thanks for your help! After some playing around I got it to work! Here is the final code.

Citizen.CreateThread(function()
    while true do
        Citizen.Wait(0)
		
		local ped = GetPlayerPed(-1)
        local playerPos = GetEntityCoords(ped, true)
		
		for i,pos in pairs(INTERIORS) do
		local distance = Vdist(playerPos.x, playerPos.y, playerPos.z, pos.x, pos.y, pos.z)
		
			if distance < 500 then
				DrawMarker(1, pos.x, pos.y, pos.z-1.02, 0, 0, 0, 0, 0, 0, 0.7,0.7,0.8, 255,255,255, 200, 0, 0, 2, 0, 0, 0, 0)
				if (Vdist(playerPos.x, playerPos.y, playerPos.z, pos.x, pos.y, pos.z) < 1.0) and (not PED_hasBeenTeleported) then
					POS_actual = pos.id
					if not gui_interiors.opened then
						gui_interiors_OpenMenu()
					end
                end
            end
        end
    end
end)

I didn’t test this, so don’t use it as a solution. It’s just an illustration of what I mean.

Citizen.CreateThread(function()
    while true do
        Citizen.Wait(0)

        local ped = PlayerPedId()
        local playerPos = GetEntityCoords(ped, true)

        for i,pos in pairs(INTERIORS) do
            local distance = Vdist(playerPos.x, playerPos.y, playerPos.z, pos.x, pos.y, pos.z)
            if distance < 20 then
                DrawMarker(1, pos.x, pos.y, pos.z-1.02, 0, 0, 0, 0, 0, 0, 0.7,0.7,0.8, 255,255,255, 200, 0, 0, 2, 0, 0, 0, 0)
                if distance < 1.0 and not PED_hasBeenTeleported then
                    POS_actual = pos.id
                    if not gui_interiors.opened then
                        gui_interiors_OpenMenu()
                    end
                end
            end
        end
    end
end)

See how I re-use the distance variable so I don’t have to do a second Vdist?
Also, PlayerPedId() returns the same as GetPlayerPed(-1), but is way way way faster.

Depending on how you store INTERIORS, you can also move distance over to using CfxLua vector math, and replace Vdist entirely. That will also speed it up by a lot.

Having the marker visible at 500 meters is perhaps a little overkill? Draw one in an open, visible place and measure your distance from it, and you’ll see it becomes largely irrelevant as far as on-screen information goes, before 150 meters. Add buildings in the way to that, and I’m sure 100m is fine.

This is really nitpicking, though. Congratulations on solving it!

The only thing I would say can be improved, it not initializing the distance variable inside of the loop, but rather outside of it and then just changing the value, like this:

local distance = nil
for i,pos in pairs(INTERIORS) do
        distance = Vdist(playerPos.x, playerPos.y, playerPos.z, pos.x, pos.y, pos.z)
        ...
end

It’s a free memory optimization right here

1 Like

Measured against the native overhead of the Vdist, I’d say that’s not going to be noticeable, but you are technically correct, and that is the best kind of correct!