iPollo Posted March 5, 2020 Share Posted March 5, 2020 (edited) Hello everyone, I recently started with Lua programming at MTA, for studies, I started to develop a small system, whose goal is to create items on the map. So far everything worked perfectly, so I decided to implement an event, so that I know when the player goes through an item, but it didn't work (there are no errors in the console or in the debugscript) REMEMBERING: I started recently, so anything I have done wrong besides said, or that can be improved, let me know, please. For item creation I have this, at first, everything is working here, this is on ServerSide -- Count VARS local definirItem_Count = 0; local criarItemNoMapa_Count = 0; -- Table which stores the defined items item_ID = {} item_NOME = {} -- Table which stores spawned items on the map spawnedItem_ID = {} spawnedItem_NOME = {} spawnedItem_X = {} spawnedItem_Y = {} spawnedItem_Z = {} -- Function that defines the items function definirItem(item, nome) definirItem_Count = definirItem_Count + 1 table.insert(item_ID, definirItem_Count, item) table.insert(item_NOME, definirItem_Count, nome) end -- Function that creates the items on the map function criarItemNoMapa(item, nome, x, y, z) criarItemNoMapa_Count = criarItemNoMapa_Count + 1 createObject(item, x, y, z) table.insert(spawnedItem_ID, criarItemNoMapa_Count, item) table.insert(spawnedItem_NOME, criarItemNoMapa_Count, nome) table.insert(spawnedItem_X, criarItemNoMapa_Count, X) table.insert(spawnedItem_Y, criarItemNoMapa_Count, Y) table.insert(spawnedItem_Z, criarItemNoMapa_Count, Z) end -- Item definition definirItem(1853, "Chave de Fenda") definirItem(1577, "Mala Verde") definirItem(1580, "Mala Vemelha") definirItem(1579, "Mala Azul") I believe the problem arises in clientSide, because I have this -- Timer that repeats setTimer(verificarPositition, 500, 0) -- Function called by the timer to check if the player is in the range of an item -- For that I looped up to the highest value in the table of spawned items -- And I took the X, Y and Z values from certain tables -- And if the player is in this range, trigger the event function verificarPosition() for i = 0, table.maxn(spawnedItem_ID), 1 do local x, y, z = getElementPosition(getLocalPlayer()) if(isElementInRange(getLocalPlayer(), spawnedItem_X[i], spawnedItem_Y[i], spawnedItem_Z[i], 5)) triggerEvent("onPlayerEnterItemArea", getLocalPlayer()) end end end -- Event (its not been called) addEvent("onPlayerEnterItemArea", false) addEventHandler("onPlayerEnterItemArea", getRootElement(), function() outputChatBox("CALLED") end) Any help and improvement in the code will be a great help Edited March 5, 2020 by iPollo Link to comment
The_GTA Posted March 5, 2020 Share Posted March 5, 2020 Dear iPollo, let's get your script working before we get to the improvements. So let me ask some questions 1) how do you create the "spawnedItem_ID" array, plus the other related ones, on the clientside? variables that you create in serverside scripts are not automatically visible on the clientside. variable synchronization is usually done through events. 2) did you enter debugscript after starting your resource? then you might have missed the warning that the first argument to setTimer is "nil" (bad argument). So to fix your clientside script multiple changes are required. First you have to move the call to setTimer after the definition of your verificarPosition Lua function (for example into line 16). Then we have to do the following steps: 1) add a new event called "onClientReceiveSpawnedItems" as remote-event on the clientside 2) add an event handler for "onClientReceiveSpawnedItems" in which we receive the spawnedItems array 3) add a new event "onPlayerReady" as remote-event on the serverside 4) add an event handler for "onPlayerReady" in which we send the spawnedItems array to the ready client only. 5) at the end of your clientside script trigger the server event "onPlayerReady" We need this event interlock because we have to make sure that the client is initialized before he can receive the spawnedItems array. There are alternatives to this approach like initializing the array on both the clientside and the serverside so that both have their own copy. Link to comment
iPollo Posted March 5, 2020 Author Share Posted March 5, 2020 (edited) 26 minutes ago, The_GTA said: Dear iPollo, let's get your script working before we get to the improvements. So let me ask some questions 1) how do you create the "spawnedItem_ID" array, plus the other related ones, on the clientside? variables that you create in serverside scripts are not automatically visible on the clientside. variable synchronization is usually done through events. 2) did you enter debugscript after starting your resource? then you might have missed the warning that the first argument to setTimer is "nil" (bad argument). So to fix your clientside script multiple changes are required. First you have to move the call to setTimer after the definition of your verificarPosition Lua function (for example into line 16). Then we have to do the following steps: 1) add a new event called "onClientReceiveSpawnedItems" as remote-event on the clientside 2) add an event handler for "onClientReceiveSpawnedItems" in which we receive the spawnedItems array 3) add a new event "onPlayerReady" as remote-event on the serverside 4) add an event handler for "onPlayerReady" in which we send the spawnedItems array to the ready client only. 5) at the end of your clientside script trigger the server event "onPlayerReady" We need this event interlock because we have to make sure that the client is initialized before he can receive the spawnedItems array. There are alternatives to this approach like initializing the array on both the clientside and the serverside so that both have their own copy. 1) I didn't create it on ClientSide, because I thought that if it were "global" it would be accessible there. 2) Fixed And I made the other five points, but I still don't understand how to access array on the other side Edited March 5, 2020 by iPollo Link to comment
The_GTA Posted March 5, 2020 Share Posted March 5, 2020 (edited) I decided to give you a sample implementation on how it could be implemented. Take a look at this code: client.Lua -- Variables that have been transfered from the server to us. local spawnedItem_ID = false; local spawnedItem_NOME = false; local spawnedItem_X = false; local spawnedItem_Y = false; local spawnedItem_Z = false; -- Function called by the timer to check if the player is in the range of an item -- For that I looped up to the highest value in the table of spawned items -- And I took the X, Y and Z values from certain tables -- And if the player is in this range, trigger the event function verificarPosition() for i = 1, table.maxn(spawnedItem_ID), 1 do local x, y, z = getElementPosition(getLocalPlayer()) if(getDistanceBetweenPoints3D(x, y, z, spawnedItem_X[i], spawnedItem_Y[i], spawnedItem_Z[i]) <= 5) then triggerEvent("onPlayerEnterItemArea", getLocalPlayer()) end end end -- Timer that repeats setTimer(verificarPosition, 500, 0) -- Event (its not been called) addEvent("onPlayerEnterItemArea", false) addEventHandler("onPlayerEnterItemArea", getRootElement(), function() outputChatBox("CALLED") end) -- Receiving server data event. addEvent("onClientReceiveSpawnedItems", true); addEventHandler("onClientReceiveSpawnedItems", root, function(_spawnedItem_ID, _spawnedItem_NOME, _spawnedItem_X, _spawnedItem_Y, _spawnedItem_Z) outputDebugString( "received spawned items on client" ); spawnedItem_ID = _spawnedItem_ID; spawnedItem_NOME = _spawnedItem_NOME; spawnedItem_X = _spawnedItem_X; spawnedItem_Y = _spawnedItem_Y; spawnedItem_Z = _spawnedItem_Z; end ); -- Tell the server that the client is ready. triggerServerEvent("onPlayerReady", root); server.Lua -- Count VARS local definirItem_Count = 0; local criarItemNoMapa_Count = 0; -- Table which stores the defined items item_ID = {} item_NOME = {} -- Table which stores spawned items on the map spawnedItem_ID = {} spawnedItem_NOME = {} spawnedItem_X = {} spawnedItem_Y = {} spawnedItem_Z = {} -- Function that defines the items function definirItem(item, nome) definirItem_Count = definirItem_Count + 1 table.insert(item_ID, definirItem_Count, item) table.insert(item_NOME, definirItem_Count, nome) end -- Function that creates the items on the map function criarItemNoMapa(item, nome, x, y, z) criarItemNoMapa_Count = criarItemNoMapa_Count + 1 createObject(item, x, y, z) table.insert(spawnedItem_ID, criarItemNoMapa_Count, item) table.insert(spawnedItem_NOME, criarItemNoMapa_Count, nome) table.insert(spawnedItem_X, criarItemNoMapa_Count, x) table.insert(spawnedItem_Y, criarItemNoMapa_Count, y) table.insert(spawnedItem_Z, criarItemNoMapa_Count, z) end -- Item definition definirItem(1853, "Chave de Fenda") definirItem(1577, "Mala Verde") definirItem(1580, "Mala Vemelha") definirItem(1579, "Mala Azul") -- TEST. criarItemNoMapa(4855, "Chave de Fenda", 0, 0, 5); addEvent("onPlayerReady", true); addEventHandler("onPlayerReady", root, function() triggerClientEvent(client, "onClientReceiveSpawnedItems", root, spawnedItem_ID, spawnedItem_NOME, spawnedItem_X, spawnedItem_Y, spawnedItem_Z ); end ); Changes to the script: 1) added missing "then" after if-condition inside verificarPosition 2) moved setTimer to after function declaration 3) added the events for sending arrays from server to client 4) fixed typo in the setTimer call (you wrote "verificarPositition" instead of "verificarPosition") 5) replaced isElementInRange with getDistanceBetweenPoints3D 6) fixed typo in the criarItemNoMapa function (uppercase X, Y, Z changed to lowercase x, y, z) 7) for-loop inside verificarPosition now starts from index 1 because by convention index-based arrays in Lua start at number 1 Is this what you want? Please compare this script with what you have fixed so far. If you have any questions then just ask. Do you want me to suggest improvements for your script? Edited March 5, 2020 by The_GTA Link to comment
iPollo Posted March 5, 2020 Author Share Posted March 5, 2020 39 minutes ago, The_GTA said: I decided to give you a sample implementation on how it could be implemented. Take a look at this code: client.Lua -- Variables that have been transfered from the server to us. local spawnedItem_ID = false; local spawnedItem_NOME = false; local spawnedItem_X = false; local spawnedItem_Y = false; local spawnedItem_Z = false; -- Function called by the timer to check if the player is in the range of an item -- For that I looped up to the highest value in the table of spawned items -- And I took the X, Y and Z values from certain tables -- And if the player is in this range, trigger the event function verificarPosition() for i = 1, table.maxn(spawnedItem_ID), 1 do local x, y, z = getElementPosition(getLocalPlayer()) if(getDistanceBetweenPoints3D(x, y, z, spawnedItem_X[i], spawnedItem_Y[i], spawnedItem_Z[i]) <= 5) then triggerEvent("onPlayerEnterItemArea", getLocalPlayer()) end end end -- Timer that repeats setTimer(verificarPosition, 500, 0) -- Event (its not been called) addEvent("onPlayerEnterItemArea", false) addEventHandler("onPlayerEnterItemArea", getRootElement(), function() outputChatBox("CALLED") end) -- Receiving server data event. addEvent("onClientReceiveSpawnedItems", true); addEventHandler("onClientReceiveSpawnedItems", root, function(_spawnedItem_ID, _spawnedItem_NOME, _spawnedItem_X, _spawnedItem_Y, _spawnedItem_Z) outputDebugString( "received spawned items on client" ); spawnedItem_ID = _spawnedItem_ID; spawnedItem_NOME = _spawnedItem_NOME; spawnedItem_X = _spawnedItem_X; spawnedItem_Y = _spawnedItem_Y; spawnedItem_Z = _spawnedItem_Z; end ); -- Tell the server that the client is ready. triggerServerEvent("onPlayerReady", root); server.Lua -- Count VARS local definirItem_Count = 0; local criarItemNoMapa_Count = 0; -- Table which stores the defined items item_ID = {} item_NOME = {} -- Table which stores spawned items on the map spawnedItem_ID = {} spawnedItem_NOME = {} spawnedItem_X = {} spawnedItem_Y = {} spawnedItem_Z = {} -- Function that defines the items function definirItem(item, nome) definirItem_Count = definirItem_Count + 1 table.insert(item_ID, definirItem_Count, item) table.insert(item_NOME, definirItem_Count, nome) end -- Function that creates the items on the map function criarItemNoMapa(item, nome, x, y, z) criarItemNoMapa_Count = criarItemNoMapa_Count + 1 createObject(item, x, y, z) table.insert(spawnedItem_ID, criarItemNoMapa_Count, item) table.insert(spawnedItem_NOME, criarItemNoMapa_Count, nome) table.insert(spawnedItem_X, criarItemNoMapa_Count, x) table.insert(spawnedItem_Y, criarItemNoMapa_Count, y) table.insert(spawnedItem_Z, criarItemNoMapa_Count, z) end -- Item definition definirItem(1853, "Chave de Fenda") definirItem(1577, "Mala Verde") definirItem(1580, "Mala Vemelha") definirItem(1579, "Mala Azul") -- TEST. criarItemNoMapa(4855, "Chave de Fenda", 0, 0, 5); addEvent("onPlayerReady", true); addEventHandler("onPlayerReady", root, function() triggerClientEvent(client, "onClientReceiveSpawnedItems", root, spawnedItem_ID, spawnedItem_NOME, spawnedItem_X, spawnedItem_Y, spawnedItem_Z ); end ); Changes to the script: 1) added missing "then" after if-condition inside verificarPosition 2) moved setTimer to after function declaration 3) added the events for sending arrays from server to client 4) fixed typo in the setTimer call (you wrote "verificarPositition" instead of "verificarPosition") 5) replaced isElementInRange with getDistanceBetweenPoints3D 6) fixed typo in the criarItemNoMapa function (uppercase X, Y, Z changed to lowercase x, y, z) 7) for-loop inside verificarPosition now starts from index 1 because by convention index-based arrays in Lua start at number 1 Is this what you want? Please compare this script with what you have fixed so far. If you have any questions then just ask. Do you want me to suggest improvements for your script? Okay, you literally opened my mind, now it's much clearer, and thanks for all the corrections. But for some reason it gives an error: attempt to call global 'client' <a user data value> on here: addEvent("onPlayerReady", true); addEventHandler("onPlayerReady", root, function() triggerClientEvent(client "onClientRecebeItemVar", root, item_ID, item_NOME, spawnedItem_ID, spawnedItem_NOME, spawnedItem_X, spawnedItem_Y, spawnedItem_Z) end) Link to comment
The_GTA Posted March 5, 2020 Share Posted March 5, 2020 Just now, iPollo said: attempt to call global 'client' <a user data value> You forgot to put a comma after "client" in line 3, like this: addEvent("onPlayerReady", true); addEventHandler("onPlayerReady", root, function() triggerClientEvent(client, "onClientRecebeItemVar", root, item_ID, item_NOME, spawnedItem_ID, spawnedItem_NOME, spawnedItem_X, spawnedItem_Y, spawnedItem_Z) end) No problem. I am glad to help you! 1 Link to comment
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now