You’re checking for coords below ground already, so the closest is of course 0.
This whole ‘step upwards’ thing is just silly, slow, and misguided, and even in cases where you would need to get the lowest ground (say, an underpass) it’s best to start at 1000 downwards, then take every hit, - 0.5 or so, until you don’t hit anything anymore, and then get the result from the last hit.
Same for the post linked above, the thing solving it there is that the code teleports (without freezing the ped, good job!) to the target coords and then does a few random Wait calls (with 5 being worrying too → anyone with over 200 FPS will be screwed there) and usually getting lucky with the collision mesh for the area having loaded by that time. That still doesn’t make the part where you ‘loop upwards’ fix it, it rather shows it was a case of 1. from the list above.
All the positions I copied using the qb-core admin menu with the player standing at the locations. I’ve ended up subtracting 0.99 from all the z positions and they all appear fine, so none of them are below the terrain.
Given I can walk on all the locations where the values end up as 0, could the collision data still not be loaded? … although given I’m not in the region, it’s a waypoint being calculated for an area that may not be loaded… hmm.
So is GetGroundZFor_3dCoord considered an expensive operation? I’m thinking that if I put it in my
loop when I’m displaying the marker on the ground with the Wait(0), that maybe calcluating it everything is a waste. Could leave a groundZ variable as nil and if nill going around the loop once it’s being displayed, calculate once then ignore every other iteration.
Make me cringe frankly. I recall doing this in Win32 programming to find windows with th specific “class” name. Eww. Just because someone thinks of something and it works doesn’t mean it should be done.
Thanks d-bubble, that definitely got me thinking about the problem at hand. Becuase my waypoints are potentionally a long way away from the player the mesh isn’t loaded in, so of course me calculating it before I arrive can only result in 0. So I decided to do the call when I’m displaying the marker once I’m in range and only calculate when the marker comes into range and reset it to nil when I’m no longer in range, then when I new point is generated it can repeat fo rthe new co-ordinates. No looping in order to get there the way people hav been suggesting. Just takes a little “architecture”. This is my new marker drawing thread:
Citizen.CreateThread(function()
local waitTime = 500
local zGround = nil
while true do
Citizen.Wait(waitTime)
if jobBlip and currentJobLocation then
local playerPos = GetEntityCoords(PlayerPedId())
local distance = #(playerPos - currentJobLocation)
if distance <= 15 then
waitTime = 0
if not zGround then
local val, ground = GetGroundZFor_3dCoord(currentJobLocation.x, currentJobLocation.y, currentJobLocation.z, true)
zGround = ground
end
DrawMarker(
27,
currentJobLocation.x, currentJobLocation.y, zGround, -- x, y, z
0, 0, 0, -- Direction vector x, y, z
0, 0, 0, -- Rotation x, y, z
5.0, 5.0, 5.0, -- Scale
10, 10, 255, 255, -- Red, Green, Blue, Alph
false, -- Slowly bob up and down?
false, -- Constantly face camera?
2, -- P19. Other values don't seem to do anything
false, -- Rotate
nil, -- textureDict [[ string ]]
nil, -- textureName [[ string ]]
false -- Draw on intesecting entities?
)
if distance <= 2.5 then
if not listen then
StartListeningForInput()
end
else
listen = false
end
else
zGround = nil
waitTime = 500
end
end
end
end)
That’s a lot easier to get direct ground positions then: peds in GTA have a script height of ~2 units so if you ended up with centered coordinates of the ped just ‘- 1’.