Jump to content

[HELP] Passing an Element using a Global Variable


ReZurrecti0n

Recommended Posts

I don't see why this is not working as it should, I must be overlooking a small detail somewhere...

local PlayerVisible={}

function ClientResourceStart(resource)
	setTimer(Seconds,1000,0)
	collectgarbage()-- Will remove ALL of these from code in the near future, will cost speed in the long run, Lua is good with recyling on its own anyway
end

function ClientRender()-- This event is constantly called, it's not wise to add anything here unless you have NO other choice... You were warned!
	for l,t in ipairs(PlayerVisible)do -- I suspect this line is the problem?!
		if(PlayerVisible[t])then -- If this "statement" is removed, Point Z is reached...
			outputChatBox("TM: #FFFFFFPoint Z!",255,150,50,true)-- Not reaching this point...
		end
	end
end

function Seconds()
	local f1,f2,f3=getCameraMatrix()
	for l,t in ipairs(getElementsByType("ped"))do
		local f4,f5,f6=getElementPosition(t)
		if(getDistanceBetweenPoints3D(f1,f2,f3,f4,f5,f6)<=25.0)then
			if(isLineOfSightClear(f4,f5,f6,f1,f2,f3+2))then
				local f7,f8=getScreenFromWorldPosition(f4,f5,f6+1)
				if(f7)and(f8)then
					outputChatBox("TM: #FFFFFFPoint D!",255,150,50,true)-- This point IS reached...
					PlayerVisible[t]=true-- Still working this... !!!
					--PlayerVisible[t][id]="NPC" -- Once point Z is reached, then I'll worry about this stuff
					--PlayerVisible[t][name]="Bill" -- Once point Z is reached, then I'll worry about this stuff
				end
			elseif(PlayerVisible[t])then-- Ped no longer in L.O.S.
				outputChatBox("TM: #FFFFFFPoint 1!",255,0,0,true)
				--PlayerVisible[t]=nil -- Removed for now in case Point 1 was triggered
			end
		elseif(PlayerVisible[t])then-- Ped no longer in Range
			outputChatBox("TM: #FFFFFFPoint 2!",255,0,0,true)
			--PlayerVisible[t]=nil -- Removed for now in case Point 2 was triggered
		end
	end
	collectgarbage()
end

addEventHandler("onClientRender",getRootElement(),ClientRender)

Not great with tables yet as I am just learning them, but I don't know... Anyway, the whole idea in the above code is to reach Point Z when the PlayerVisible has anything in it

Does anyone see what may be wrong in the code? Or why Point Z is not being reached anyways...? (Might be the ipairs loop under ClientRender?)

Link to comment
  • Moderators
2 hours ago, ReZurrecti0n said:

Does anyone see what may be wrong in the code? Or why Point Z is not being reached anyways...? (Might be the ipairs loop under ClientRender?)

 

This

for l,t in ipairs(PlayerVisible)do 

will only loop through items, BUT only items that are stored as an array.

{[1] = player, [2] = player, [3] = player} -- array structure

-- OR

{player, player, player} 

 

To solve that issue we can use pairs, instead of ipairs. This function doesn't care if items are stored as an array.

{[player] = true, [player] = true, [player] = true} -- your structure

 

So do this instead:

for l,t in pairs(PlayerVisible)do 

 

 

 

  • Thanks 1
Link to comment

Thanks for pointing that out, did not notice there was both a "pair" and "ipair".

So I did switch from:

for l,t in ipairs(PlayerVisible)do

to:

for l,t in pairs(PlayerVisible)do

But still unable to reach Point Z...

I'm struggling to understand tables inside of tables and its structure, Im going to have to take some time to read over a few Lua Wiki Tuts on it again. Until the table structures click in my head. Then after that I may want to look more into: for, while, pairs and ipairs (Loop Stuff)

Edited by ReZurrecti0n
Addition
Link to comment

I figured it out, I did need to use pairs and not ipairs, thx IIYama

But I was also pointing at the t var when I needed to be pointing at the l var

function ClientRender()-- This event is constantly called, it's not wise to add anything here unless you have NO other choice... You were warned!
	for l,t in pairs(PlayerVisible)do -- I suspect this line is the problem?! ((( I just needed to change from ipairs to pairs, thx IIYama )))
		if(PlayerVisible[l])then -- If this "statement" is removed, Point Z is reached... ((( I just had to change the [t] to [l] and now it works )))
			outputChatBox("TM: #FFFFFFPoint Z!",255,150,50,true)-- Not reaching this point... ((( With the noted changes, I now reach Point Z )))
		end
	end
end

 

Link to comment
  • Moderators
4 hours ago, ReZurrecti0n said:

But I was also pointing at the t var when I needed to be pointing at the l var

Currently you are looping through the selecting of players that only have the statement.

 

Are the once that are removed also players that didn't even have the statement in the first place?

Depending on that answer I can give you the right solutions.

Link to comment

I'll explain what exactly I'm trying to make here in order to better understand what I want the code to do:

The "Seconds" function will trigger every second to check for Players/Peds (Currently only testing Peds though) that are in range of the player and also have a L.O.S. This is because I don't want to put all these loops and checks under the ClientRender Event since it is constantly called. Anyway, the Player/Ped is then marked with PlayerVisible while/when still in range and has a L.O.S., if that Player/Ped loses either, then that is when it is removed.

Although not shown in any of the code above, once a Player/Ped is marked with PlayerVisible (Point Z), DX Draws are used on the marked element to create ID, Playername, Health Bar, Armor Bar and Local Text which would come from saying anything in the local chat.

So basically, this can just be thought of something like a simple nametag, if a player is close enough with a L.O.S. then it'll be seen by that player (Peds too)

DrawDXTextOnElement(l,"LOCAL: OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",1.12,25.0,255,255,255,255,1.3)

I have always thought that the l position in loops were always numbers(1st Var), but in this case it must be the stored element because it draws it on the Ped it found

(But also keep in mind, I'm currently only testing on Peds as other players will need to be handled slightly different I'm sure)

So far, it is working, next I will test on 3 different Peds all at the same time to be sure, then finally add in support for other players and whatnot

Short Answer: Only players who fall out of range or lose L.O.S. lose the statement

Link to comment
  • Moderators
13 minutes ago, ReZurrecti0n said:

Short Answer: Only players who fall out of range or lose L.O.S. lose the statement

So there is just one state ON and OFF? Or are the more states in visibility?

 

Like:

  • On map showing
  • Tag showing

 

In order to make it easier.

  1. Set a default state: visibility = false
  2. Do your checks, if YES do:
    1. visibility = true
    2. add the ped to the table
       
  3. If visibility == false, remove the ped from the table.
     

 

function Seconds()
	local f1, f2, f3= getCameraMatrix()
	for l,t in ipairs(getElementsByType("ped"))do
		local f4,f5,f6=getElementPosition(t)
		
		local visible = false -- by default the ped is not visible
		
		-- Do your checks.
		if(getDistanceBetweenPoints3D(f1,f2,f3,f4,f5,f6)<=25.0)then
			if(isLineOfSightClear(f4,f5,f6,f1,f2,f3+2))then
				local f7,f8=getScreenFromWorldPosition(f4,f5,f6+1)
				if(f7)and(f8)then
					
					-- Ped is visible
					visible = true -- set the state
					
					-- Add the ped to the table if not added yet.
					if not PlayerVisible[t] then
						outputChatBox("TM: #FFFFFFPoint D!",255,150,50,true)-- This point IS reached...
						PlayerVisible[t] = true-- Still working this... !!!
					end
					--PlayerVisible[t][id]="NPC" -- Once point Z is reached, then I'll worry about this stuff
					--PlayerVisible[t][name]="Bill" -- Once point Z is reached, then I'll worry about this stuff
				end
			elseif(PlayerVisible[t])then-- Ped no longer in L.O.S.
				outputChatBox("TM: #FFFFFFPoint 1!",255,0,0,true)
			end
		elseif(PlayerVisible[t])then-- Ped no longer in Range
			outputChatBox("TM: #FFFFFFPoint 2!",255,0,0,true)
		end
		
		-- Clear the ped from the table if not visible and in the table
		if not visible and PlayerVisible[t] then
			PlayerVisible[t] = nil
		end
	end
	

	
	-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	--collectgarbage() -- < REMOVE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	
end

 

And remove destroyed elements from the table. Lua does not know if an element exist or is destroyed.

function ClientRender()-- This event is constantly called, it's not wise to add anything here unless you have NO other choice... You were warned!
	for l,t in pairs(PlayerVisible)do 
		if isElement(t) then
			outputChatBox("TM: #FFFFFFPoint Z!",255,150,50,true)-- Not reaching this point... ((( With the noted changes, I now reach Point Z )))
		else
			PlayerVisible[t] = nil -- if the element is destroyed, clear the data
		end
	end
end

 

  • Like 1
Link to comment

Since I got it to work, I've been changing the code and decided it's probably best I update what I have atm. Especially now that you have an idea of what I'm trying to do:

-- Clientside Script:

local PlayerVisible={}

function ClientResourceStart(resource)

	PED=createPed(271,-1641.0,-2248.0,31.5,0.0)-- !!! TEMP !!!
	PED2=createPed(241,-1640.0,-2248.0,31.5,0.0)-- !!! TEMP !!! (These are the 3 Peds I'm testing with)
	PED3=createPed(158,-1642.0,-2248.0,31.5,0.0)-- !!! TEMP !!!
	setPedArmor(PED,100.0)
	setTimer(Seconds,1000,0)
	collectgarbage()-- I will be removing ALL of these found throughout my scripts shortly...
end

function ClientRender()-- This event is constantly called, it's not wise to add anything here unless you have to
	for l,t in pairs(PlayerVisible)do
		if(PlayerVisible[l])then -- Now Works !!!
			--outputChatBox("TM: #FFFFFFPoint Z!",255,150,50,true)
			-- The following line is what I'm now trying to figure out (Working with Tables) [Currently not working correctly]
      		DrawDXTextOnElement(l,"(#A0A0A0"..PlayerVisible[l].id.."#808080) #C0C0C0"..PlayerVisible[l].name.."",0.95,25.0,128,128,128,255,1.3)
      		-- ^ If the above line were to be removed, everything else would work as it should... ^
			DrawDXBoxOnElement(l,102,7,1.01,25.0,0,0,0)-- Black Outline Box for Health
			DrawDXBoxOnElement(l,100,5,1.009,25.0,64,0,0)-- Damage Box for Health
			DrawDXBoxOnElement(l,getElementHealth(l),5,1.009,25.0,255,0,0)-- Amount Box for Health
			DrawDXBoxOnElement(l,102,7,1.06,25.0,0,0,0)-- Black Outline Box for Armor
			DrawDXBoxOnElement(l,100,5,1.059,25.0,64,64,64)-- Damage Box for Armor
			DrawDXBoxOnElement(l,getPedArmor(l),5,1.059,25.0,255,255,255)-- Amount Box for Armor
			DrawDXTextOnElement(l,"LOCAL: OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",1.12,25.0,255,255,255,255,1.3)
		end
	end
end

function Seconds()
	local f1,f2,f3=getCameraMatrix()
-- There is another loop for type "players" here, but removed for the time being as it needs updating and only testing on Peds atm
	for l,t in ipairs(getElementsByType("ped"))do
		local f4,f5,f6=getElementPosition(t)
		if(getDistanceBetweenPoints3D(f1,f2,f3,f4,f5,f6)<=25.0)then
			if(isLineOfSightClear(f4,f5,f6+2,f1,f2,f3))then
				local f7,f8=getScreenFromWorldPosition(f4,f5,f6+1)
				if(f7)and(f8)and(not PlayerVisible[t])then
					PlayerVisible[t]=true -- Works, but need to make this a table of some kind
					PlayerVisible[t].id="NPC" -- This can't be right
					PlayerVisible[t].name="Bill" -- This also doesn't seem to work
					outputChatBox("TM: #00FF00Point A!",255,150,50,true)
				end
			elseif(PlayerVisible[t])then -- Ped no longer in L.O.S.
				PlayerVisible[t]=nil -- This where I was destroying the "table"
			end
		elseif(PlayerVisible[t])then -- Ped no longer in Range
			PlayerVisible[t]=nil -- This is also where I was destroying the "table"
		end
	end
end

I think what I need to do now is create a table that contains elements with various keys to store data such as: Element, "Name", "ID" and so on...

Problem is, I'm not yet familiar with how to create such a table and then use it correctly. The On/Off statement was more or less for testing before going onwards

So... In order for me to finish this, I have to find out how these table structures work exactly... To make the ID and NAME along with the ELEMENT itself all work

Link to comment

Figuring out how tables work in Lua was... Rather challenging, but did manage to figure out the very basics. For those who read this thread in hoping of an example of tables, this is what my final code turned out to be and now everything works as it was intended:

local Element={} -- The simplest form of declaring a table, I decided not to get fancy with it

function ClientResourceStart(resource)
	PED=createPed(271,-1641.0,-2248.0,31.5,0.0) -- 1st Test Ped
	Element[PED]={Name="Zach"} -- Giving 1st Test Ped a Name in the table
	setPedArmor(PED,100.0)
	PED=createPed(241,-1639.0,-2248.0,31.5,0.0) -- 2nd Test Ped
	Element[PED]={Name="Bill"}
	PED=createPed(158,-1643.0,-2248.0,31.5,0.0) -- 3rd Test Ped
	Element[PED]={Name="Mary"}
	setTimer(Seconds,1000,0) -- Will run the Seconds Function every second to check if player is in Range and has a LOS
end

function Seconds()
	local f1,f2,f3=getCameraMatrix()
-- Another loop for players, currently only testing with Peds though
	for l,t in ipairs(getElementsByType("ped"))do
		local f4,f5,f6=getElementPosition(t)
		if(getDistanceBetweenPoints3D(f1,f2,f3,f4,f5,f6)<=25.0)then
			if(isLineOfSightClear(f4,f5,f6+2,f1,f2,f3))then
				local f7,f8=getScreenFromWorldPosition(f4,f5,f6+1)
				if(f7)and(f8)and(not Element[t]["Visible"])then -- Checks to make sure this Ped isn't already marked with "Visible"
					Element[t]["Visible"]=true -- Adds a new entry to the table, Visible
					Element[t]["ID"]="NPC" -- Adds yet another new entry to the table
				end
			elseif(Element[t]["Visible"])then -- Ped no longer in L.O.S.
				Element[t]["Visible"]=nil -- Removes the entry from the table
				Element[t]["ID"]=nil -- Removes the entry from the table
			end
		elseif(Element[t]["Visible"])then -- Ped no longer in Range
			Element[t]["Visible"]=nil -- Removes the entry from the table
			Element[t]["ID"]=nil -- Removes the entry from the table
		end
	end
end

function ClientRender()-- This event is constantly called, it's not wise to add anything here unless you have NO other choice... You were warned!
	for l,t in pairs(Element)do
		if(Element[l]["Visible"])then -- Checks if the element in this loop has "Visible" marked (Or exist even)
			DrawDXTextOnElement(l,"(#A0A0A0"..Element[l]["ID"].."#808080) #C0C0C0"..Element[l]["Name"].."",0.95,25.0,128,128,128,255,1.3)
      		-- ^ The line above displays the Peds ID and Name above the head ^
			DrawDXBoxOnElement(l,102,7,1.01,25.0,0,0,0,75)-- Black Outline Box for Health
			DrawDXBoxOnElement(l,100,5,1.009,25.0,64,0,0,75)-- Damage Box for Health
			DrawDXBoxOnElement(l,getElementHealth(l),5,1.009,25.0,255,0,0)-- Amount Box for Health
			if(getPedArmor(l)>0)then -- If no armor, don't bother showing an empty armor bar...
				DrawDXBoxOnElement(l,102,7,1.06,25.0,0,0,0,75)-- Black Outline Box for Armor
				DrawDXBoxOnElement(l,100,5,1.059,25.0,64,64,64,75)-- Damage Box for Armor
				DrawDXBoxOnElement(l,getPedArmor(l),5,1.059,25.0,255,255,255)-- Amount Box for Armor
			end
			DrawDXTextOnElement(l,"LOCAL: OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",1.12,25.0,255,255,255,255,1.3) -- Just a positioning test, this needs updating
		end
	end
end

Thanx again IIYama :)

Everything in this thread has now been resolved XD

  • Like 1
Link to comment
  • Moderators
3 hours ago, ReZurrecti0n said:

Thanx again IIYama :)

No problem, enjoy

 

Once you have mastered the table completely, serverside scripting will become less of a challenge.

One last tip: be more consistent with locals. (Line 4)

Those keep things clean and tidy.

 

  • Thanks 1
Link to comment

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.
×
×
  • Create New...