Skip to content

Instantly share code, notes, and snippets.

@androksi
Last active February 8, 2023 23:05
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save androksi/9370db5ff8fb0f46937aab570576d196 to your computer and use it in GitHub Desktop.
Save androksi/9370db5ff8fb0f46937aab570576d196 to your computer and use it in GitHub Desktop.

Tabelas

Ah... como não falar dessa coisinha maravilhosa? Pois bem, passarei um pouco da minha experiência com elas neste documento.

Tabela, objeto, array, seja lá como você nomeia, é praticamente a mesma coisa. Aqui neste tutorial, irei me referir a elas como tabelas. Ademais, trabalharemos em cima da linguagem Lua. Sei que em outras, como JavaScript, por exemplo, a comunidade costuma padronizar como objeto ou array.

Por que usar?

As tabelas são como um local na memória onde você pode armazenar centenas de dados ao mesmo tempo, assim como variáveis. Todavia, optar por variáveis pode não ser a melhor opção. Por quê? Pois bem, vamos lá.

Primeiramente, definir centenas de variáveis para algo que pode ser simples, é totalmente contra as boas práticas de programação e contra-intuitivo. Devemos escrever o código não só para nós, mas também para outros desenvolvedores que possam usar nosso código como exemplo.

Segundamente, elas irão facilitar a sua vida. E muito. Usando-as, abre-te infinitas possibilidades para chegar ao seu objetivo com muito menos código.

Concluindo, tabela é vida.

Primeiros passos...

Bom, não estou aqui para falar de algoritmo, programação em geral ou seja lá o que você espera. Falarei sobre tabelas. Ponto. Então, você deve saber definir uma variável, atribuir valores, entre outras coisas que envolve o ambiente de desenvolvimento.

Começaremos definindo uma variável, que irá carregar uma tabela vazia. Oh, meu Deus! Como faço isso? É bem fácil!

local nossaTabela = {}

Para atribuir uma tabela a uma variável, nós usamos chaves. Abrimos e fechamos. Dessa forma: {}.

Feito isso, agora a nossa variável nossaTabela leva uma tabela. Dentro dela, nós podemos ter muitos valores, de diferentes tipos; seja uma string, seja um número, seja outra tabela, uma função, seja um valor boleano, isto é, valores verdadeiros e falsos.

Índices

Os índices são identificadores de algum valor dentro de uma tabela. Eles podem ser muitas coisas: números, strings, funções, elementos e afins. E, também, eles podem ou não estar presentes visivelmente. Veja este exemplo:

local nossaTabela = { 5, "olá", false }

Na tabela acima, os índices não foram definidos, porém eles existem, mesmo não vendo-os. Em Lua, o começo de um índice sempre será 1. Embora em outras linguagem, se não a maioria, começa em 0.

Sendo assim, então, os índices daquela tabela estão dessa forma:

  • Índice 1: 5
  • Índice 2: "olá"
  • Índice 3: false

Perceba que eles estão em ordem, e sempre irão estar, se nós, em momento algum, definirmos um índice para algum valor. Você pode estar se perguntando: ué, como assim não entendi.

Vamos lá. Considerando a mesma tabela do exemplo acima, eu apenas coloquei valores, como quem não quer nada. Portanto, a linguagem Lua irá facilitar minha vida e deixar os índices em ordem. Porém, se eu fizer isto:

local nossaTabela = { cinco = 5, mensagem = "olá", boleano = false }

Os índices ordenados já não existem mais, pois nós mesmos substituímos por outra coisa. Eles também poderiam ser números diferentes, assim:

local nossaTabela = { [10] = 5, [99] = "olá", [666] = false }

Preste bastante atenção no código acima... eu não coloquei simplesmente um número, envelopei eles com colchetes. Caso não faça isso, dará um erro.

Uma outra coisinha sobre índices

Não sei se você percebeu algo neste exemplo:

local nossaTabela = { cinco = 5, mensagem = "olá", boleano = false }

Os índices estão sendo definidos como variáveis, pois bem, é exatamente isso. Falando sobre nomes, e não números, nós podemos definir um índice de duas maneiras.

Se você não deseja utilizar espaços, caracteres especiais, então aquela é a forma mais adequada. Se por ventura seja necessário usar espaços ou qualquer símbolo, então nós também precisamos colocar o índice envelopado por colchetes, e também como sendo uma string. Desta maneira:

local nossaTabela = { ["número cinco"] = 5, mensagem = "olá", ["verdadeiro ou falso"] = false }

Contudo, isso deve ser algo bem raro em seu código. Evite essa nomeação. Prefira usar apenas uma variável normal, sem frufrufru.

Trabalhando com tabelas

Agora que já sabemos o básico delas, vamos para a parte que realmente importa no final das contas.

Para obter o valor, nós usamos os índices. Por favor, leia acima para entender mais sobre índices.

Trazendo aquele nosso primeiro exemplo, no tópico de índices:

local nossaTabela = { 5, "olá", false }

Aqui, nós podemos obter o valor usando apenas uma maneira: através dos índices numéricos!

print(nossaTabela[1]) -- Irá mostrar 5.
print(nossaTabela[2]) -- Irá mostrar "olá".
print(nossaTabela[3]) -- Irá mostrar false.

Também, podemos adicionar mais um valor dentro da tabela, sem nem mesmo tocar na original, definida no princípio.

nossaTabela[4] = 10
nossaTabela[5] = "sou o índice número 5"
nossaTabela[6] = true

Sempre seguindo a ordem dos números. Caso contrário, você terá problemas futuros. Por hora, iremos manter dessa forma.

Bom, obviamente, nós podemos remover valores também!

nossaTabela[5] = nil

Basta atribuir o valor para nil. Mas aí que pega agora... nós acabamos de quebrar a tabela. 😂 Bom... ela ainda está funcionando, mas perdeu completamente a ordem, isto é, agora ela está: 1, 2, 3, 4, 6. O índice 5 já não existe mais. E se você for espertinho(a), já sabe como recuperar a ordem. 👌

Mas... e se o índice não for um número?

Temos duas formas de obter o valor, caso o índice não seja um número. Vamos ver o exemplo:

local nossaTabela = { cinco = 5, mensagem = "olá", boleano = false }

Nós podemos obter usando notação ponto ou com colchetes, dessa forma:

print(nossaTabela.cinco)
print(nossaTabela.mensagem)
print(nossaTabela.boleano)

ou...

print(nossaTabela["cinco"])
print(nossaTabela["mensagem"])
print(nossaTabela["boleano"])

Eu sei... pode parecer um pouco confuso, mas é a mesma coisa. Bom, é a mesma coisa nesse exemplo, mas usando colchetes, quando necessário, pode ser bem útil.

Ah, e claro, nós podemos definir valores na tabela dessa forma também. Vamos dar uma olhadinha abaixo:

nossaTabela.texto = "Não tem texto nenhum não!"
nossaTabela["saudações"] = "Seja bem-vindo(a)!"

Espero que você saiba o porquê de saudações estar entre colchetes. 😊

Ainda sobre índices...

Iremos definir 20 índices numéricos de uma só vez numa tabela. Para isso, é necessário um pouco mais de conhecimento sobre programação em geral. Vejamos o código abaixo:

local tabela = {}

for i = 1, 20 do
    tabela[i] = i
end

Em resumo, seria a mesma coisa que isto:

local tabela = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }

Nada muito novo aqui, se você for esperto(a). O que mudou é que geramos 20 índices numa tabela de uma maneira muito mais rápida. Poderia ser 100, 200, 500, 1000 índices. Nem imagine como seria ter que escrever tudo à mão...

Fiz o exemplo acima para que nós possamos entrar no tópico seguinte, que são os loops. Em Lua, além daquele que está no exemplo acima, temos dois tipos: pairs e ipairs.

O primeiro, pairs, irá retornar o índice e valor, respectivamente, independente de como o índice seja; string ou número. Entretanto, a ordem não é garantida.

Já o segundo, ipairs, irá retornar o índice e valor, respectivamente, de forma ordenada, isto é, a tabela não pode estar... é... como podemos dizer, "corrompida" por índices não-ordenados. Eles devem ser 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11...

Usando o primeiro tipo, pairs:

local tabela = {}

for i = 1, 20 do
    tabela[i] = i
end

for indice, valor in pairs(tabela) do
    print(indice, valor)
end

No exemplo acima, irá mostrar o mesmo índice e valor, pois o índice carrega o mesmo valor. (Só printei até o 8)

pairs

Usando o segundo tipo, ipairs:

O resultado seria o mesmo para o ipairs, nesse caso. Porém, se nós removermos, por exemplo, o índice 7, só irá printar até o 6, usando o ipairs, pois como já dito anteriormente, eles precisam estar ordenados. Uma vez que essa ordem é quebrada, o ipairs mostra até onde há ordenação, isto é, removendo o número 7, ficaria um espaço entre o 6 e o 8.

local tabela = {}

for i = 1, 20 do
    tabela[i] = i
end

tabela[7] = nil

for indice, valor in ipairs(tabela) do
    print(indice, valor)
end

ipairs

Vamos trazer o MTA para o uso de tabelas!

Agora que você já se familiarizou com índices, valores e loops. Nada melhor que temperar com exemplos mais complexos envolvendo o MTA, nosso jogo tão amado.

Começaremos com algo bem simples, porém bem importante. Digamos que cada player pode pegar um veículo para andar pelo mapa. Para isso, nós precisamos de algo para identificar qual player pegou o veículo - e é claro que usaremos tabelas!

local vehicles = {}

Como boa prática de programação, iremos nomear a partir de agora usando nomes em Inglês, e no plural.

Mas... por que no plural? Isso depende do contexto no qual você está, é claro que nem sempre será necessário, mas aqui, serão vários carros, para diferentes players.

A questão agora é: como vamos referenciar o carro do player? É simples! Usaremos o índice para isso. Criando um comando básico para pegar o carro:

function createPlayerVehicle(player)
    local px, py, pz = getElementPosition(player)
    vehicles[player] = createVehicle(411, px, py, pz + 1)
    warpPedIntoVehicle(player, vehicles[player])
end

function destroyPlayerVehicle(player)
    if vehicles[player] then
        if isElement(vehicles[player]) then
            destroyElement(vehicles[player])
        end
        vehicles[player] = nil
    end
end

addCommandHandler("carro", function(player)
    destroyPlayerVehicle(player) -- Destrói o carro antigo, se houver.
    createPlayerVehicle(player) -- Cria o veículo para o player.
end)

addEventHandler("onPlayerQuit", root, function()
    destroyPlayerVehicle(source)
end)

Usei boas práticas de programação, criando funções para criar o veículo e também para destruí-lo. Perceba que aqui:

vehicles[player] = createVehicle(411, px, py, pz + 1)

...eu deixei o elemento do player sendo o índice, e o valor dele é um elemento do tipo veículo. Não tem nenhuma surpresa aqui, eu espero. Além disso, tenha em mente de que player não é uma string, é um elemento, ou seja, nós podemos pegar o carro do player de qualquer lugar do nosso código. Perceba que aqui nesta parte do código:

addEventHandler("onPlayerQuit", root, function()
    destroyPlayerVehicle(source)
end)

Usei um evento para que, quando o player sair do servidor, o carro dele seja destruído e removido da memória. Veja que não usei o mesmo nome (player), pois o nosso elemento dentro desse evento vem pela variável source. Então, lembrando: o que temos no índice é o elemento.

Preste um pouco de atenção neste trecho do código, onde o veículo é destruído e removido da memória:

function destroyPlayerVehicle(player)
    if vehicles[player] then
        if isElement(vehicles[player]) then
            destroyElement(vehicles[player])
        end
        vehicles[player] = nil
    end
end

É DE SUMA IMPORTÂNCIA que você sempre verifique se o índice realmente existe, senão erros no /debugscript podem aparecer. Além do mais, faz bastante sentido. Alguns players podem não ter pego o carro. Nós só iremos executar o código caso para aqueles que possuem algo ocupando espaço na memória.

Nós podemos também destruir todos os veículos de uma só vez! Usando um loop de repetição. Farei um exemplo no qual somente pessoas com permissão poderiam destruir todos eles.

function destroyAllVehicles()
    for player, vehicle in pairs(vehicles) do
        if isElement(vehicle) then
            destroyElement(vehicle)
        end
        vehicles[player] = nil
    end
end

addCommandHandler("secreto", function(player)
    if hasObjectPermissionTo(player, "command.mute") then
        destroyAllVehicles()
    end
end)

Eita... agora lascou, androksi. Entendi nadinha daquela função destroyAllVehicles. Bem, vamos lá então...

Primeiro, espero que você saiba o motivo de eu ter usado pairs.

Segundo, felizmente não há supresas no código. Como explicado no tópico sobre índices, é exatamente isso que fiz ali. A tabela vehicles armazena o player no índice, e o valor é o carro. O que está acontecendo é basicamente isto daqui:

vehicles

Temos uma tabela. Ela possui índices e valores. Nesse caso, o índice é o player e o valor é o carro. Lembrando novamente: o nome não é importante ali. Usei player apenas para facilitar a leitura. Entretanto, eu usei vehicle para referenciar o elemento.

Se você está prestando atenção neste documento, percebeu que naquela função (destroyAllVehicles) eu não verifiquei se realmente o índice existe. O motivo é simples: nós estamos buscando os valores diretamente na tabela, e não acessando-a de fora, como na função destroyPlayerVehicle, isto é, o índice sempre irá existir.

Todavia, ainda apliquei uma condicional para ver se o veículo realmente existe, pois usando destroyElement sem ter um elemento, resultaria em um erro. Em um cenário hipotético, digamos que o veículo (elemento) tenha sido destruído através do painel admin.

Bora para mais um exemplo!

Criaremos um sistema de loteria, bem simples. Os possíveis números serão apenas de 1 a 100.

local lotteryNumbers = {}

addCommandHandler("loteria", function(player, command, number)
    number = tonumber(number)
    if not number or number <= 0 or number > 100 then
        return false
    end

    -- Para validar com segurança, usaremos o serial do player como índice.
    local playerSerial = getPlayerSerial(player)

    -- Iremos checar se ele já possui um índice na tabela, ou seja, se ele tiver, é porque já jogou na loteria.
    if lotteryNumbers[playerSerial] then
        return outputChatBox("* ERRO: Você já jogou na loteria. O seu número é: " .. lotteryNumbers[playerSerial][2], player, 255, 0, 0)
    end

    -- Caso não tenha, então vamos atribuir!
    lotteryNumbers[playerSerial] = { player, number }
    outputChatBox("* Você jogou na loteria. Número da sorte: " .. number, player, 0, 255, 0)
end)

-- Vamos criar um comando para administradores realizar o sorteio.
addCommandHandler("sortear", function(player)
    if hasObjectPermissionTo(player, "command.mute") then
        local luckyNumber = math.random(1, 100)
        local totalWinners = 0

        outputChatBox("* NÚMERO DA SORTE ACABOU DE SAIR: " .. luckyNumber, root, 255, 255, 0)

        for serial, data in pairs(lotteryNumbers) do
            local lotteryPlayer = data[1]
            local lotteryNumber = data[2]

            if lotteryNumber == luckyNumber then
                if isElement(lotteryPlayer) then
                    outputChatBox("* " .. getPlayerName(lotteryPlayer) .. " ganhou na loteria!", root, 0, 255, 0)
                    givePlayerMoney(lotteryPlayer, 50000)
                    totalWinners = totalWinners + 1
                end
            end
        end

        outputChatBox("* Total de ganhadores: " .. totalWinners, root, 255, 255, 0)
    end
end)

Uff... tenho coisas a esclarecer nesse exemplo. Primeiro de tudo, quero que você se atente bastante ao código, exclusivamente nesta linha:

lotteryNumbers[playerSerial] = { player, number }

Por mais que não tenha segredo nenhum aqui, pode ficar um pouco confuso à primeira vista. Mas sinceramente, é bem simples! Lembra um dos nossos primeiros exemplos? Deixe-me refrescar sua memória:

local nossaTabela = { 5, "olá", false }

Pois então, é exatamente a mesma coisa! 😊 A diferença, é que agora nós temos esses valores referenciados por um índice da tabela. Nós poderíamos fazer a mesma coisa, com um player e número aleatório. Desta forma:

local nossaTabela = { getRandomPlayer(), math.random(50) }

ou seja... agora aqueles valores estão atrelados a um serial, que fica no índice da tabela. Cada índice é um serial diferente, com valores diferentes. Seria algo dessa forma, se houvesse 5 players apostando na loteria, por exemplo:

local lotteryNumbers = {
    ["98DGSA89DSAGDAG8DG8DDGSAGBBBV9"] = { player, number },
    ["G98GSAD7FG9NBVCVAS76C159YH0SAA"] = { player, number },
    ["EEE76543F67CBNAVOIHOOFA784109G"] = { player, number },
    ["9J009NVBUBUAVYXASVCVFAAHF89HAS"] = { player, number },
    ["00GF0ASG818278F5321VDIUBCAVXST"] = { player, number }
}

Porém, nós estamos fazendo isso de forma automática! Veja que sensacional. Deixando a lógica do código abaixo de lado, quero que veja com atenção o que está acontecendo aqui:

for serial, data in pairs(lotteryNumbers) do
    local lotteryPlayer = data[1]
    local lotteryNumber = data[2]

    if lotteryNumber == luckyNumber then
        if isElement(lotteryPlayer) then
            outputChatBox("* " .. getPlayerName(lotteryPlayer) .. " ganhou na loteria!", root, 0, 255, 0)
            givePlayerMoney(lotteryPlayer, 50000)
            totalWinners = totalWinners + 1
        end
    end
end

👀 Rum... espero que você saiba o motivo de eu ter colocado desta maneira:

for serial, data in pairs(lotteryNumbers) do

Mas enfim, vamos entender. Dê uma olhada em como isso se parece em um desenho:

lottery

Relembrando, então, nós estamos inserindo os dados de forma automática aqui nesta parte:

lotteryNumbers[playerSerial] = { player, number }

...isto é, agora cada índice da tabela, também leva outra tabela. Veja que, nessa nova tabela, nós NÃO definimos os índices, então eles estão ordenados!

Seria totalmente diferente se nós quisessemos nomear, para ficar mais fácil. Assim, desta maneira:

lotteryNumbers[playerSerial] = { player = player, number = number }

Por mais que os nomes estejam iguais, lembre-se que um é índice e o outro é valor. Agora nós teríamos que alterar isso em dois lugares no código.

Aqui:

if lotteryNumbers[playerSerial] then
    return outputChatBox("* ERRO: Você já jogou na loteria. O seu número é: " .. lotteryNumbers[playerSerial][2], player, 255, 0, 0)
end

onde

lotteryNumbers[playerSerial][2]

passaria a ser

lotteryNumbers[playerSerial].number

E também aqui:

local lotteryPlayer = data[1]
local lotteryNumber = data[2]

onde passaria a ser

local lotteryPlayer = data.player
local lotteryNumber = data.number

De qualquer forma, isso foi apenas um adendo que quis deixar, mostrando as possibilidades.

Eu ouvi mais um exemplo?

Iremos utilizar agora a função table.insert e table.remove. O exemplo, assim como os outros anteriores, será bem simples.

Criaremos um cenário onde os jogadores que digitarem /fila entrarão na fila para receber vida e colete.

local playersToHeal = {}

function healPlayers()
    local totalPlayers = 0

    for index, player in pairs(playersToHeal) do
        if isElement(player) then
            setElementHealth(player, 100)
            setPedArmor(player, 100)
            outputChatBox("* Você recebeu vida e colete.", player, 0, 255, 0)
            totalPlayers = totalPlayers + 1
        end
    end

    outputChatBox("* Total de players curados: " .. totalPlayers, root, 0, 255, 0)
end

addCommandHandler("fila", function(player)
    table.insert(playersToHeal, player)
end)

addEventHandler("onResourceStart", resourceRoot, function()
    outputChatBox("*** EM 5 SEGUNDOS, QUEM DIGITAR O COMANDO /fila RECEBERÁ VIDA E COLETE! ****", root, 255, 255, 0)
    setTimer(healPlayers, 5000, 1)
end)

addEventHandler("onPlayerQuit", root, function()
    for index, player in pairs(playersToHeal) do
        if player == source then
            table.remove(playersToHeal, index)
        end
    end
end)

A função table.insert recebe 3 parâmetros. O primeiro, é a tabela cujo os dados serão inseridos. O segundo, é o índice. O terceiro, o valor.

Porém, se nós omitirmos o terceiro parâmetro, ou seja, não colocarmos nada, como foi o caso do exemplo acima, então o índice será numérico e irá armazenar aquele valor no respectivo índice.

Um exemplo sem relação ao anterior:

local tabela = {}

table.insert(tabela, 5)
table.insert(tabela, "olá")
table.insert(tabela, false)

-- Seria a mesma coisa de
local tabela = { 5, "olá", false }

Enfim. Talvez você esteja se debatendo aí no seu conforto: ué, tem uma falha no código!!!!!!!!!!!

Bom, de fato tem. Olhe bem este trecho:

addCommandHandler("fila", function(player)
    table.insert(playersToHeal, player)
end)

O player poderia usar o comando infinitas vezes, o que não é bom para esse cenário. Nós iremos verificar de uma maneira diferente aqui, já que o índice é numérico, ou seja, não temos o elemento do player como índice para simplesmente usar:

if playersToHeal[player] then

Criaremos então uma função para isso.

function isPlayerInQueue(player)
    -- Usei 'p' apenas para não conflitar com o parâmetro.
    for index, p in pairs(playersToHeal) do
        if isElement(p) and p == player then
            return true
        end
    end
    return false
end

👀 E novamente... espero que você saiba o que isto significa:

for index, p in pairs(playersToHeal) do

Agora com essa função implementada no código, nós podemos usá-la para verificar.

addCommandHandler("fila", function(player)
    -- Se o jogador estiver na fila, então iremos parar o código por aqui.
    if isPlayerInQueue(player) then
        return false
    end

    table.insert(playersToHeal, player)
end)

Você deve ter visto que no evento onPlayerQuit, existe a função table.remove. Iremos falar um pouco sobre ela agora. Você vai entender facilmente.

Ela leva dois parâmetros. O primeiro, a tabela. O segundo, o índice que você deseja remover. Sendo assim, nós temos aqui o seguinte:

addEventHandler("onPlayerQuit", root, function()
    for index, player in pairs(playersToHeal) do
        if player == source then
            table.remove(playersToHeal, index)
        end
    end
end)

Sobre o loop, você já deve saber, mas agora preste atenção num fato: nós estamos verificando se aquele player é igual ao player que saiu do servidor. Se passar pela condição, quer dizer que sim, ele é o responsável. Dessa forma, o index, obviamente, será dele.

Nós podemos, então, tranquilamente removê-lo da tabela, pois ele não fará mais parte dela.

Tamanho da tabela ou... último índice

Em meus exemplos, você deve ter notado que usei variáveis para obter quantos players foram curados ou quantos venceram na loteria. Bom, nesse caso, não tem muito o que fazer, é necessário criar as variáveis.

Contudo, nós usamos # para obter o tamanho de uma tabela. Porém, dessa vez não vou explicar, já tem uma resposta muito boa em nosso Discord do MTA:SA. Deixarei a mensagem abaixo em formato de imagem.

Mensagem por @Lord-Henry.

Mensagem do Lord Henry explicando

Sugestão logo abaixo dada por @DNL291.

Você também pode conferir uma alternativa que muitos programadores e scripters usam.

Okay, vai... um pouquinho sobre funções dentro de tabelas

Vamos lembrar primeiro como a gente define uma função padrão.

function somar(a, b)
    return a + b
end

Nada de interessante aqui. Você já deve fazer isso muito bem. Então, com certeza fará muito bem também dentro da tabela, pois é a mesma coisa. Só vai mudar que o nome da função se transforma no índice!

local tabela = {
    somar = function(a, b)
        return a + b
    end,

    multiplicar = function(a, b)
        return a * b
    end,

    dividir = function(a, b)
        return a / b
    end
}

Usaríamos desta maneira:

print(tabela.somar(1, 2))
print(tabela.multiplicar(2, 27))
print(tabela.dividir(100, 2))

-- Poderíamos também usar com colchetes. Você se lembra? Estranhão, né? 😜
print(tabela["somar"](1, 2))
print(tabela["multiplicar"](2, 27))
print(tabela["dividir"](100, 2))

Sabia que também podemos criar uma função que pega um valor dentro da própria tabela? Confuso, né... mas vou mostrar um pouquinho.

local tabela = {
    valor_escondido = 1,

    pegarValorEscondido = function(self)
        return self.valor_escondido
    end
}

O self ali na função se trata da tabela na qual está sendo chamada. Você vai notar no código abaixo que uma coisa irá mudar.

print(tabela:pegarValorEscondido())

Perceba que utilizei dois pontos (:) para chamar essa função. Se usássemos somente um ponto (.), aquele self não iria fazer sentido ali. Precisamos, nesse contexto, chamar a função como se fosse um método.

Com amor, androksi!

Parabéns por ter chegado até aqui. Agora é com você praticar bastante. Espero ter ajudado de alguma forma. Tabelas não são complicadas, tudo o que você precisa entender é como elas funcionam, como usar os loops e outras coisas além do básico. Creio eu que tenha deixado claro aqui.

Por favor, se ficou alguma dúvida, pode me perguntar à vontade. Caso queira que eu explique algo, também dê o feedback. Estarei disposto a responder quaisquer dúvidas e também aprimorar ainda mais este documento.

💖

@Lord-Henry
Copy link

Excelente tutorial.
Um abraço.

@noonbr
Copy link

noonbr commented Dec 7, 2021

Será de grande ajuda para a comunidade, que tutorial!

@rKing021
Copy link

rKing021 commented Dec 7, 2021

Ai que gozante, tutorial bom dms excelente!!!
Duas palavras
Para Bens 👏👏👏👏

@DNL291
Copy link

DNL291 commented Dec 7, 2021

Muito bom! Queria eu ter essa informação quando estava aprendendo Lua.

Deixando meu feedback:
Em Tamanho da tabela ou... último índice creio que seria melhor deixar uma print da mensagem do Lord Henry em vez do link para o canal do Discord; nada garante que todos leitores utilizam e também por conta do sistema de verificação do DC do MTA poderia tornar isso meio chato pra quem não utiliza o local.
Sobre o uso do operador #, também seria uma boa falar sobre uma alternativa que scripters/programadores usam: https://wiki.multitheftauto.com/wiki/Table.size (recomendo que leitores vejam o código de exemplo da página)

[Off-topic] Sobre a gramática do texto, que por sinal está tão boa quanto o próprio tutorial, quero apenas ressaltar sobre:

  • O emprego incorreto da crase em "referir à elas"
  • Novamente em "à uma variável"
  • Hífen (-) em "- bom... ela ainda" (já que houve um ponto final na frase anterior)
  • "um exemplo cujo" Você pode corrigir mudando para "Um exemplo no qual"
  • "tabela cuja os dados" Aí é só trocar "cuja" para "cujo"
    (Na verdade, eu ia relevar isso já que o foco é o tutorial, e pessoalmente, não sou nenhum expert da nossa linguagem, tanto que posso não ter percebido outros erros. De qualquer modo, único objetivo é ajudar hehe ❤️ )

@androksi
Copy link
Author

androksi commented Dec 7, 2021

Agradeço aos comentários, em especial ao nosso querido @DNL291 por apontar as devidas correções e sugerir mudanças para deixar o documento ainda melhor!

@imfelipedev
Copy link

Ótimo tutorial.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment