kieran

[Question] using math.min to get smallest x,y,z distance

Recommended Posts

I want to make a script that will get distance between player and locations in a table, I have done this, but... I want to get the minimum distance and targets x, y, z. 

Basically, get distance between player and hospital, get the smallest distance only, then get the x, y, z of the targets distance from the table and output the x,y,z, so if I'm closest to all saints, it outputs those coordinates only.

hosp_loc = { --Table of hospitals
	-- x, y, z, rot
	{ 1173, -1323, 15, 270}, -- All Saints
	{ 2038, -1411, 17, 130}, --Jefferson
	{ 1242, 327, 19, 340}, -- Red County
	{ 1609, 1816, 12, 360}, -- Las Venturas
	{ -2655, 635, 14, 180}, -- San Fierro
	{ -2200, -2311, 30, 320} -- Angel Pine
}


function getDistance(thePlayer)
	for i=1,#hosp_loc do 
        local hx,hy,hz = hosp_loc[i][1],hosp_loc[i][2],hosp_loc[i][3] --Hospital locations
        local px,py,pz = getElementPosition( thePlayer ) --Player location
		distance = getDistanceBetweenPoints3D (hx, hy, hz, px, py, pz) --Get the distance between player and hospitals
		output = math.min(distance) --Trying to get the minimum distance of one hospital
		outputChatBox(""..output, thePlayer, 255, 170, 85) --Ouput the x,y,z of that specific hospital to the chat
	end
end

addCommandHandler( "loc", getDistance, false ) --To get the distance

Anyone know how to do this? xD was one of the first things I tried to script and trying to come back to do it now I know a little more (just not enough to do it). Thanks.

Share this post


Link to post

You need to give it atleast two values.

output = math.min(distance, output)

You can also fill in 3 or 100 values.

 

Share this post


Link to post

Thanks @IIYAMA, but do you know of a way to get the x y z position though?  So instead of output being distance, it would be the closest 3D point x,y,z in table? instead of meters to point...

Also is there any other way of getting minimum number?  I can only use one value :/ it will do it for all locations, I just want the closest locations x y z to be returned so I can use it on spawn...

Edited by kieran
  • Like 1

Share this post


Link to post

The most simplest way is this:

function getDistance(thePlayer)
	-- get the player position
	local px,py,pz = getElementPosition( thePlayer ) --Player location

	-- prepare 2 variables, but do not give them a value yet.
	local closestDistance 
	local closestPoint

	-- loop through the tables
	for i=1,#hosp_loc do 
		local hx, hy, hz = hosp_loc[i][1], hosp_loc[i][2], hosp_loc[i][3] --Hospital locations
        
		local distance = getDistanceBetweenPoints3D (hx, hy, hz, px, py, pz) --Get the distance between player and hospitals
		if not closestDistance or distance < closestDistance then -- If the closestDistance is nil/(false) OR the distance is smaller than the closestDistance. 
			closestDistance = distance -- save the distance in closestDistance, which is located outside of the loop.
			closestPoint = hosp_loc[i] -- save the point in closestPoint, which is located outside of the loop.
		end
	end
	outputChatBox(inspect(closestPoint), thePlayer, 255, 170, 85) -- debug the closestPoint variable, should be a table!
	
end

 

Edited by IIYAMA

Share this post


Link to post

@IIYAMA Thanks, but um, final question on this...  How can I get it to show only the numbers?  Sorry... never used inspect before, and I can't think of a way to get length or use sub/gsub

Edited by kieran
  • Like 1

Share this post


Link to post
closestPoint[4]

 

This is what closestPoint is now:


{ 1173, -1323, 15, 270}
{[1] = 1173, [2] = -1323, [3] = 15, [4] = 270}

This is how the table index works, when the keys are not defined.

 

The inspect function will convert all data types to a string, please study: https://wiki.multitheftauto.com/wiki/Inspect

So a boolean will look like something like this: "true" / "false"

A number will look like something like this: "1323435"

A table will look like something like this: "{123, 5656}"

ETC.

 

 

  • Thanks 1

Share this post


Link to post

Thanks :D came up with the code below and works great! 

function getDistance(thePlayer)
	-- get the player position
	local px,py,pz = getElementPosition( thePlayer ) --Player location

	-- prepare 2 variables, but do not give them a value yet.
	local closestDistance 
	local closestPoint

	-- loop through the tables
	for i=1,#hosp_loc do 
		local hx, hy, hz = hosp_loc[i][1], hosp_loc[i][2], hosp_loc[i][3] --Hospital locations
        --if site:sub(0, 7)  ~= "http://"  then
		local distance = getDistanceBetweenPoints3D (hx, hy, hz, px, py, pz) --Get the distance between player and hospitals
		if not closestDistance or distance < closestDistance then -- If the closestDistance is nil/(false) OR the distance is smaller than the closestDistance. 
			closestDistance = distance -- save the distance in closestDistance, which is located outside of the loop.
			closestPoint = hosp_loc[i] -- save the point in closestPoint, which is located outside of the loop.
		end
	end
  
	x = (inspect(closestPoint[1])) -- debug the closestPoint variable, should be a table!
	y = (inspect(closestPoint[2]))
	z = (inspect(closestPoint[3]))
	r = (inspect(closestPoint[4]))
	spawn = x..", "..y..", "..z..", "..r
	outputChatBox(spawn, thePlayer, 255, 170, 85)
	
end

addCommandHandler( "loc", getDistance, false )

 

  • Like 1

Share this post


Link to post

Nice but keep in mind that inspect is actually for debugging.

I recommend you to use tostring to convert numbers to strings. Because inspect does a lot more in the background than tostring does. Which is probably using a lot more cpu then needed.

local numberToString = tostring(123) -- "123"

 

 

local x = tostring(closestPoint[1])
local y = tostring(closestPoint[2])
local z = tostring(closestPoint[3])
local r = tostring(closestPoint[4])
local spawn = x..", "..y..", "..z..", "..r

Also it is very important to use locals, to improve atleast the hierarchy of the code. In my opinion the most important thing about using locals, is that you as code writer know when data shouldn't be saved for a longer period. It must be GONE, because you don't need it any more.

 

https://wiki.multitheftauto.com/wiki/Local

https://www.lua.org/pil/4.2.html

 

 

Whaaahaha brings back memories, when I started with lua.

 

  • Thanks 1

Share this post


Link to post

Thanks @IIYAMA, this helps, I need to learn C# and Python, so this is why I find lua so confusing at times, especially on MTA.  Some things seem a little, backwards. xD

Also I noticed a big problem, if I die miles out at sea off the map, I can't re-spawn. :/

Edited by kieran

Share this post


Link to post
5 hours ago, kieran said:

Thanks @IIYAMA, this helps, I need to learn C# and Python, so this is why I find lua so confusing at times, especially on MTA.  Some things seem a little, backwards. xD

Also I noticed a big problem, if I die miles out at sea off the map, I can't re-spawn. :/

Lua is one of the easiest languages you can learn.

Share this post


Link to post
22 hours ago, Tails said:

Lua is one of the easiest languages you can learn.

Yes but I am beginning to learn 3 alongside it, so it just gets confusing :)

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.