Jump to content

[AJUDA] Criação de loop


Recommended Posts

Olá! Tudo bom com vocês?

Eu ainda sou amador, e utilizo alguns loops prontos, mas nunca montei um, na verdade, nem sequer sei como ele funciona.

Alguém poderia me explicar como eu poderia utilizá-lo para obter a lista de jogadores, ou como utilizá-lo em uma tabela, ou seja, como utilizá-lo de maneira geral. 

Obrigado! ❤️

Link to comment
  • Other Languages Moderators

Para obter a lista de jogadores online, vc só precisa obter todos os elementos do tipo "player". Para isso você usa getElementsByType ("player")

Se você quiser acessar cada jogador obtido por meio de um loop, por exemplo, pra dar um jetpack á cada um deles. Dai você faz assim:

function jetPraGeral (thePlayer, cmd)
	local todoMundo = getElementsByType ("player") -- todoMundo é uma table com todos os jogadores conectados ao server.
	for i, jogador in ipairs (todoMundo) do -- Para cada elemento dessa table, faça o seguinte:
		setPedWearingJetpack (jogador, true) -- Dá um jetpack pra esse elemento.
	end
end
addCommandHandler ("todosJet", jetPraGeral)

A table acima seria tipo assim:

local todoMundo = {player1, player2, player3} -- player1 não é o nick do jogador, e sim um elemento do tipo "player".
-- Supondo que só tenham 3 jogadores no server.

Ali naquele loop do FOR:

  • i se refere ao índice de cada elemento dessa table. No entanto ela não está indexada, então o MTA considera índices inteiros em ordem. Se você quer obter o player2, você pode acessá-lo com todoMundo[2], pois o 2 é o índice que o MTA deu pra ele.
  • jogador se refere a cada elemento em si.
  • ipairs indica que o loop percorre os elementos com índices inteiros numa tabela, em ordem.

Obs: Se você quer que o i comece a partir do 0 em vez de 1, use pairs em vez de ipairs. Por exemplo em casos onde você quer contar quantos players estão dentro de um veículo. Porém você deve considerar o assento 0, que é do motorista.

function meusOcupantes (thePlayer, cmd)
	local myVehicle = getPedOccupiedVehicle (thePlayer) -- myVehicle recebe o veículo que o jogador que executou o comando está.
	if not myVehicle then return end -- Se o jogador que executou o comando não está em um veículo, nada acontece.
	
	local counter = 0 -- Contador de ocupantes começa em 0.
	local ocupantes = getVehicleOccupants(myVehicle) -- ocupantes recebe uma table com todos os jogadores que estão dentro do veículo. Indexada com os assentos ocupados.
	for seat, player in pairs(ocupantes) do
		counter = counter + 1
		outputChatBox ("Assento "..seat..": "..getPlayerName(player), thePlayer, 255, 255, 255, true)
	end
	outputChatBox ("Ocupantes: "..counter, thePlayer)
end

A table acima é tipo assim:

local ocupantes = {
	[0] = motorista;
	[1] = player2;
	[3] = player3
}
-- Supondo que não tenha jogador no assento 2.

Note que ela está indexada com o assento em que cada jogador está. No entanto se usar ipairs, o motorista seria ignorado, pois o loop começaria a partir do 1, ignorando o índice 0. Então o loop deve ser feito com pairs, que considera todos os elementos independente de seu índice. Porém o loop pairs percorre a table de maneira aleatória, e não em ordem como o ipairs. Outra coisa a ser levada em consideração entre os dois tipos de loop, é que se você estiver usando uma table com índices não-inteiros, o ipairs não pegará nenhum dos elementos, pois ela só funciona com índices inteiros ou com tabelas que não estão indexadas.

Faça o seguinte teste entre eles: client-side (recomendável)

tabelaNaoIndexada = { -- O próprio MTA irá indexar isso automaticamente em ordem inteira.
	" ",
	"Um",
	2,
	"ABC",
	0.15
}

tabelaIndexadaInt = { -- Funciona com ipairs, mas ignora o 0.
	[0] = " ",
	[1] = "Um",
	[2] = 2,
	[3] = "ABC",
	[4] = 0.15
}

tabelaIndexadaQualquer = { -- Não funciona com ipairs, pois não é possível determinar a ordem dos índices, pois eles não são todos inteiros.
  [0] = " ",
  ["1"] = "Um",
  ["dois"] = 2,
  [3.3] = "ABC",
  [4] = 0.15
}

tabelaIndexadaIntQualquer = { -- Só funciona com ipairs até onde existe o índice seguinte. Se não encontrar o índice seguinte, o resto será ignorado.
	[1] = " ",
	[2] = "Um",
	[4] = 2,
	[5] = "ABC",
	[6] = 0.15 -- Se substituir o 6 pelo 3 que está faltando, essa table funcionará perfeitamente no ipairs. Pois não terá índice faltando na sequência.
}

for index, valor in ipairs (tabelaNaoIndexada) do -- Substitua o tabelaNaoIndexada pelas outras tables para testar. Tente também usando o pairs.
	outputChatBox (index.." = "..valor)
end
outputChatBox ("Tamanho: "..#tabelaNaoIndexada) -- Tente verificar o tamanho das tables com isso e observe os bugs.

A função #table serve para mostrar o tamanho de uma table. No entanto ela não conta os elementos e irá bugar em tables indexadas como os 2 últimos exemplos.
Na verdade ela apenas mostra o maior índice inteiro da sequência. No caso do último exemplo, onde o maior índice é 6. Ele vai dizer que o tamanho dela é 6, quando na verdade é 5.

Qualquer dúvida que você ainda tiver sobre as tables e os loops, estarei aqui pra ajudar.

  • Thanks 3
Link to comment

Muito obrigado a todos!

Entendi perfeitamente, e aprendi ❤️

@brunob22, agradeço, mas não faz muito sentido essa explicação, o que o @Lord Henry fez por exemplo, é explicar, dando exemplos, e com isso compreendi.

Mas se puderem me tirar uma dúvida, eu usei este loop com while, para caso a data esteja negativa, ele definir como 0, mas não da nada, o que fiz de errado?

(Os loops não estão dentro de uma function.

for index, p in ipairs(getElementsByType("player")) do
    while getElementData(p, "fome") < 0 do
        setElementData(p, "fome", 0)
    end
end

 

Link to comment

Na realidade pode, só que você implementou ele de maneira incorreta kkk. Ali não existe necessidade de colocar um loop, um simples if já resolveria:

for index, p in ipairs(getElementsByType("player")) do
    outputChatBox(tostring(getElementData(p, "fome"))) -- debug
    if getElementData(p, "fome") < 0 then
        setElementData(p, "fome", 0)
    end
end

Obs: Mesmo assim era para o seu código funcionar, provavelmente o elementdata não esteja setado corretamente.

  • Thanks 1
Link to comment
  • Other Languages Moderators
11 hours ago, VazErn said:

Eu fiz isto, mas não sabia disso, por que não pode ser utilizado?

 

Pois o While é um loop que ocorre enquanto a condição dele for atendida, não existe um número limitando as repetições. No entanto, vc já está dentro de um loop For. Dessa forma a estrutura de repetição fica eterna, pois o MTA não consegue executar a segunda repetição do For pois o While ainda está sendo repetido eternamente. E supondo que o MTA mantenha a execução do While e tente fazer a segunda repetição do For, isso daria um problema maior ainda, pois o While seria repetido eternamente 2x ao mesmo tempo, e cada For faria um novo While e assim sucessivamente. O sistema inteiro entraria em colapso.

No entanto eu sei que o MTA tem um sistema de segurança que cancela a execução do script quando detecta loops infinitos.

O que é possível fazer, é usar um For dentro de um While. Pois assim que as repetições do For forem concluídas, o While pode continuar sua repetição sem problemas.

Link to comment

voce entendeu porque ele mando o codigo pronto como sempre. eu te mostrei onde procurar

que e diferene. voce nao vai na escola eo professor te entraga a prova ja com respostas?

 

eu dei a direção poderia simplesmente estudar sobre ou espera alguem trazer codigo pronto

escolheu a segunda opção

Edited by brunob22
Link to comment
4 hours ago, Lord Henry said:

Pois o While é um loop que ocorre enquanto a condição dele for atendida, não existe um número limitando as repetições. No entanto, vc já está dentro de um loop For. Dessa forma a estrutura de repetição fica eterna, pois o MTA não consegue executar a segunda repetição do For pois o While ainda está sendo repetido eternamente. E supondo que o MTA mantenha a execução do While e tente fazer a segunda repetição do For, isso daria um problema maior ainda, pois o While seria repetido eternamente 2x ao mesmo tempo, e cada For faria um novo While e assim sucessivamente. O sistema inteiro entraria em colapso.

No entanto eu sei que o MTA tem um sistema de segurança que cancela a execução do script quando detecta loops infinitos.

O que é possível fazer, é usar um For dentro de um While. Pois assim que as repetições do For forem concluídas, o While pode continuar sua repetição sem problemas.

Pelo que entendi um for pode dentro de um while, porém não o contrário ?

Não existe qualquer impedimento quanto a isto, uma coisa é implementar um código incorreto gerando loop infinito, outra é dizer que em qualquer circunstância um while dentro do for geraria esse loop sem fim. A linguagem LUA assim como diversas outras é procedual e executa uma instrução por vez, sendo assim, não é possível a execução dos dois loops (while/for) ao mesmo tempo. No código acima ele roda o for (1x) e então começa a execução do while, e uma nova execução do for ocorreria só depois de ter finalizado o andamento do segundo loop(while). E caso o while entre em um loop infinito a segunda execução do for nunca chegaria.

No while não é claro a quantidade de repetições e como já comentado ele é executada enquanto a condição de verificação for verdadeira, e por não ter um fim “claro” a lógica de saída (tornar a verificação falsa) do while deve ser sempre implementada em seu bloco (se não o fizer resultará em um loop infinito).

O código que ele expôs está correto*, no while ele define a condição de saída do loop (tornando o elementdata-fome igual a zero)

* Na realidade não está totalmente correto, mas o código dele é funcional. O while assim como qualquer outra estrutura de repetição deve ser usado apenas quando existe a necessidade ou possibilidade de re-executar o código mais de uma vez, sendo que ali no código usou-se um while que sempre rodará apenas uma vez, e nesse caso uma simples estrutura de condição “if” já satisfaz as necessidade.

Abaixo uma adaptação do código para a necessidade de utilização do while:

for index, p in ipairs(getElementsByType("player")) do
    local fome = getElementData(p, "fome") -- suponha que o valor seja -10
    while fome < 0 do -- while seria executado 10 vezes
    	fome = fome + 1
        setElementData(p, "fome", fome)
    end
end

 

Edited by MaligNos
Correção código
  • Thanks 1
Link to comment
On 28/11/2018 at 12:22, brunob22 said:

voce entendeu porque ele mando o codigo pronto como sempre. eu te mostrei onde procurar

que e diferene. voce nao vai na escola eo professor te entraga a prova ja com respostas?

 

eu dei a direção poderia simplesmente estudar sobre ou espera alguem trazer codigo pronto

escolheu a segunda opção

Amigo, isto aí cabe a quem está aprendendo, ele me deu o código, mas acha que eu utilizei sem nem sequer aprender? 

Com a explicação eu aprendi perfeitamente, e graças ao código, entendi como posso aplicar, e assim fazer meus loops sem nenhuma consulta.

Acho que você deveria rever seus métodos-críticos.

E obrigado pela ajuda!

Se dar código juntamente com a explicação, então a Wiki, e os sites de tutoriais em Lua estão errados?

Link to comment
  • Other Languages Moderators

Olha... eu não iria comentar nada, mesmo sabendo que já é o terceiro post dele criticando sobre postar códigos prontos, mas como o próprio autor deste tópico entrou no assunto, acho válido deixar minha sincera opinião, bom vamos lá.

Eu entendo a crítica dele e concordo em partes. Quando vc posta o código pronto, vc desestimula o cara a pesquisar por conta própria, pois é só o cara dar Ctrl+C e Ctrl+V e o problema está resolvido. No entanto eu observo os usuários do fórum para ver quem está tentando e quem só está copiando código. Posso contar nos dedos quantos usuários realmente estão tentando aprender. Eu posto o código comentado e estimulo os outros a comentarem seus códigos pois quando vc comenta seu próprio código em cada linha, vc sabe exatamente como ele funciona e você não se perde, pois é muito mais fácil de estudar um código funcionando diretamente com o que ele estava tentando fazer do que estudar uma sintaxe e sair chutando os valores.

No caso de usuários novos, eu só posto código se ele já vem com uma parte feita, e que claramente não foi baixado da internet, caso contrário eu só indico links por onde ele pode começar, pois não vejo motivos pra começar por ele.

Eu entendo que a maioria do pessoal aqui não é fluente no inglês (o que é um grande obstáculo, pois tudo na informática é em inglês) e por esse motivo possuem muita dificuldade com a Wiki. Mas isso não significa que ela seja descartável, aliás muito pelo contrário, pois ela explica o que cada função faz. Nas minhas respostas eu tento sempre manter as funções linkadas em suas páginas da Wiki, para estimular o usuário a clicar e descobrir por si mesmo como ela funciona.

É claro que todos nós preferimos os autodidatas, que saem buscando na Wiki, testando as coisas, errando, consertando e aprendendo. Porém existem coisas que não se aprendem em documentações, como por exemplo as boas práticas de programação. Eu por exemplo fico incomodado quando vejo um parâmetro de função declarado como source, pois isso remove o source original da função. É uma coisa besta, mas me incomoda. Outra coisa que me irrita muito é código não indentado. Na maioria das vezes me recuso ativamente a ler o código enquanto ele não estiver indentado.

Mas devo lembrá-los, que estamos em uma comunidade, e para isso devemos nos ajudar e não nos explorar e nem nos atacar. Se fosse pra mandar só links, seria mais fácil ir direto no google em vez de perder tempo criando um tópico.

Já me estressei algumas vezes com varios usuários deste fórum, o que considero falha minha, pois eu deveria ser sempre neutro. Nem todos os novatos sabem lidar com as críticas, e nem todos os experts sabem criticar sem ser de maneira agressiva. A questão é: Qual será sua resposta quanto a isso? Ela será construtiva? Ela é necessária? Ela ajuda alguém? A discussão vale a pena?

É tudo questão de bom senso e auto-controle. Aprender nem sempre é fácil, mas ensinar também não é.

Eis meu desabafo.

 

Edited by Lord Henry
  • Like 2
Link to comment
  • Moderators

@VazErn Posso até estar sendo chato em falar isso, mas te dando um bom conselho: sempre pesquise pelo fórum antes; Na seção Scripting tem muitos tópicos assim e até aqui no nosso sub-fórum. Aqui por exemplo, um bom tutorial:

Se você não conseguir entender o tutorial, até porque está em inglês, então nesse caso sem problemas, só postar aqui. Mas de qualquer forma, espero que entenda isso como algo útil pra você, visto que para realmente avançar na programação é importante você ler tutoriais em inglês pois em PT tem pouquíssimos e você também mostra seu esforço em aprender por garimpar o fórum - eu digo isso por mim, só aprendi mesmo depois que busquei tudo por conta própria, eu nunca fui de pedir algo a alguém - estou falando de mim mesmo, não é nenhuma indireta pra você.

Quanto ao nosso membro brunob22, realmente não vejo nenhum problema em fazer o código pro pessoal, na verdade, quem vai te impedir? Se eu quiser começo dar scripts pronto pra todo mundo aqui, e aí?

Minha opinião é que criar códigos de forma didática aos outros pode até ser um pouco bom pra você mesmo evoluir, mas isso vai até certo ponto, desgasta mais a pessoa e sempre tem aqueles que se aproveitam da boa vontade e começam a te encher o saco via privado, ficam mal acostumados e ficam spamando tópicos com "dúvidas" sempre dependendo de scripters.

Concordo em certa parte do que ele disse, cada um tem que correr atrás e fazer seu código. Enfim, se ele não usasse essa forma ofensiva pra se expressar e atacar outros de forma indireta todos aqui entenderia o ponto dele.

Edited by DNL291
  • Like 1
Link to comment
  • Other Languages Moderators
52 minutes ago, DNL291 said:

sempre tem aqueles que se aproveitam da boa vontade e começam a te encher o saco via privado, ficam mal acostumados

Pensei em falar sobre as mensagens privadas, mas alguns iriam ficar muito chateados comigo, pois fazem isso direto. xD

  • Like 1
  • Haha 1
Link to comment
3 hours ago, DNL291 said:

@VazErn Posso até estar sendo chato em falar isso, mas te dando um bom conselho: sempre pesquise pelo fórum antes; Na seção Scripting tem muitos tópicos assim e até aqui no nosso sub-fórum. Aqui por exemplo, um bom tutorial:

Se você não conseguir entender o tutorial, até porque está em inglês, então nesse caso sem problemas, só postar aqui. Mas de qualquer forma, espero que entenda isso como algo útil pra você, visto que para realmente avançar na programação é importante você ler tutoriais em inglês pois em PT tem pouquíssimos e você também mostra seu esforço em aprender por garimpar o fórum - eu digo isso por mim, só aprendi mesmo depois que busquei tudo por conta própria, eu nunca fui de pedir algo a alguém - estou falando de mim mesmo, não é nenhuma indireta pra você.

Quanto ao nosso membro brunob22, realmente não vejo nenhum problema em fazer o código pro pessoal, na verdade, quem vai te impedir? Se eu quiser começo dar scripts pronto pra todo mundo aqui, e aí?

Minha opinião é que criar códigos de forma didática aos outros pode até ser um pouco bom pra você mesmo evoluir, mas isso vai até certo ponto, desgasta mais a pessoa e sempre tem aqueles que se aproveitam da boa vontade e começam a te encher o saco via privado, ficam mal acostumados e ficam spamando tópicos com "dúvidas" sempre dependendo de scripters.

Concordo em certa parte do que ele disse, cada um tem que correr atrás e fazer seu código. Enfim, se ele não usasse essa forma ofensiva pra se expressar e atacar outros de forma indireta todos aqui entenderia o ponto dele.

Primeiramente, obrigado @DNL291.

Sim, eu sabia que havia tutoriais assim, mas não observei nenhum em português, por isto, abri este tópico, para ser útil tanto para mim, quanto para outros usuários.

Link to comment
  • Moderators
On 30/11/2018 at 20:33, Lord Henry said:

Pensei em falar sobre as mensagens privadas, mas alguns iriam ficar muito chateados comigo, pois fazem isso direto. xD

Eu nem ligo em ajudar por privado, mas as coisas tem um limite.

Desculpem a mensagem fora do assunto aqui, mas a propósito queria falar uma coisa, no caso pra você Lord. Percebi que você tem vários posts bem elaborados (como o do loop/ipairs/pairs), você poderia postar mais na seção Tutoriais, seria bem útil pra mais pessoas encontrarem e além do mais é mais "tutorial" do que alguns posts de lá...

Link to comment

Bruno acho ignorância de sua parte pensar dessa maneira, Lord não deu o Código pronto, ele apenas deu exemplos de diferentes maneiras de ser utilizado. Qualquer um pode chegar aqui e dizer oque precisa para montar um loop de for perfeito. Porém a explicação da própria wiki nem sempre satisfaz o carinha que quer montar o loop. No caso o meu. Eu Não tinha noção nenhum sobre for, agora já tenho uma noção de como funciona porque o lord deu uma explicação muito boa e entrando em detalhes.

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