Jump to content

[Help] Events


iPollo

Recommended Posts

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 by iPollo
Link to comment

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
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 by iPollo
Link to comment

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 by The_GTA
Link to comment
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
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!

  • 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...