Venha conhecer o Xtibia!

Bem Vindo ao XTibia - Sua comunidade de Otserv e Tibia

Registre-se para utilizar nossas ferramentas e baixar conteúdos. Quando registrado e logado em sua conta, lhe garantimos uma experiência incrível em nossa comunidade!


Poccnn

tfs 0.3 Tutorial SPOO Lua.


Fala Xtibianos.
Vim passar um pouco do que aprendi como programar usando SPOO lua. 


SPOO > Simulação de programação orientada a objeto. 

Lua, não é uma linguagem orientada a objeto, ela apenas simula isso. 

 

Vamos ao que interessa

Para criar um objeto, primeiro cria-se uma estrutura: 
 

Citar

_veiculo = {} -- estrutura (tabela); estou usando uma variavel apenas para dar um nome a essa estrutura. 

 

A estrutura pode ter valores inseridos nela. 

Citar

_veiculo.nome = "sem nome" 
_veiculo.cor = "sem cor" 

 

Agora vamos criar metodos (function) para manipular os valores dentro da estrutura. 

Citar

 

function _veiculo:getName() 
   return self.nome 
end 

function _veiculo:setName(name) 
   self.nome = name 
end 

function _veiculo:getCor() 
   return self.cor 
end 

function _veiculo:setCor(cor) 
   self.cor = cor 
end 

 

 

Agora voce pode usar os metodos para manipular os dados 

Citar

 

_veiculo:setName('poccnn') 
_veiculo:setCor('preto') 

print(_veiculo:getName(),_veiculo:getCor()) 
Saida gerada por esse codigo >> poccnn, preto 

 

 

Mas há um problema, só existe um objeto para ser manipulado; e se eu quiser maanipular mais obejtos do mesmo tipo? 

para isso, lua dispõe de uma função que cria uma metatabela, ou seja, uma tabela que contem os dados originais dessa tabela e mais algumas peculiaridades proprias desse sistema. 

 

Se voce quiser se aprofundar em saber como funciona a herança em spoo lua, veja esse tutorial.

Para criar um novo objeto; vamos criar um metodo que faça isso usando a função setmetatable: 

setmetatable(table,metatable) 

 

Citar

 

function _veiculo:newObjeto(obj) 
   obj.__index = _veiculo -- determinação de indice; mesmo tendo como padrao de indice o proprio objeto, ao ser passado como valor, fica requisitado que seja declarado o indice para o mesmo. 
   return setmetatable({},obj) -- usei uma tabela vazia. 
end 

 

Dois objetos criados com esse metodo.

Citar

local opala = _veiculo:newObjeto(_veiculo) 
local fusca = _veiculo:newObjeto(_veiculo) 

 

 

 dessa forma, esse novo objeto que foi criado e atribuido as variaveis de nomes opala e fusca, pode usar os metametodos já criados para o objeto principal (_veiculo). 

 

Citar

opala:setName('opala') 
opala:setCor('preto') 
fusca:setName('fusca') 
print(opala:getName(),opala:getCor()) 
print(fusca:getName(),fusca:getCor()) 

 

Saida gerada por esse codigo >> 
   opala,   preto 
   fusca,   sem cor 

 

 

Veja que a cor não foi definida para o objeto fusca, então ele retorna o valor padrão que foi declarado na estrutura principal >> _veiculo.cor = "sem cor". 

 

Lua dispõe de varios elementos (variaveis) chaves para manipulação de metatabelas; aqui vou comentar sobre algumas delas: 

Citar

 

__index >> voce declara qual o indice que o sistema vai procurar os valores declarados para o objeto utilizar. 
__metatable >> voce determina qual o objeto que será retornado quando for chamado pela função getmetatable(object). 
__call >> toda vez que usa um metodo no objeto, esse elemento é chamado e aparti dai voce pode determinar o que vai fazer essa chamada. 
__newindex >> declara um novo caminho para inserção de dados ou chamadas de dados. 
__tostring >> caso voce queira imprimir os dados de um objeto, esse elemento sera chamado para obter a string para ser imprimida. 

eu não vou comentar os demais elementos, devido minha ignorancia dos mesmo. 

 

 

Agora vamos por em pratica esses elementos para entendermos melhor seu funcionamento: 


Usando o parametro __index 
ao ser declarado o indice, é usado os valores apontado pelo mesmo. 
 

Citar

local novoCarro = setmetatable(_veiculo,{__index = _veiculo}) 
print(novoCarro:getName(),novoCarro:getCor()) -- usando os metametodos declarados em _veiculo.

 


Usando o parametro __metatable 
Usando esse parametro, voce apenas declara qual sera o objeto retornado. 
 

Citar

 

local corcel = setmetatable({},{__index = _veiculo, __metatable = opala}) --determinei que a metatabela seja o objeto opala descrito acima 
corcel:setName('corcel') -- nesse novo objeto criado, marquei o nome dele como corcel. 
print(getmetatable(corcel):getName()) -- ao ser chamado o objeto, ele retorna o objeto opala, por isso o nome pego, veio do objeto opala e nao desse novo objeto criado acima. 

Saida gerada por esse codigo >> opala. 


Usando o parametro __call 
Toda a chamada que for feita a esse objeto, pode ser processada usando o parametro call. 
 

Citar

 

function _veiculo:getNameByobjName(name) 
   setmetatable({},_veiculo) 
   self.__index = _veiculo 
   self.__call = function(self,value) 
   local lfor = value == 'opala' and opala or value == 'fusca' and fusca or _veiculo 
      if(lfor:getName() == "sem nome")then 
         return "Insira um nome no veiculo..." 
      else 
         return lfor:getName() 
      end 
   end 
   return self.__call(self,name) 
end 
print(corcel:getNameByobjName('opala'),corcel:getNameByobjName('fusca'),corcel:getNameByobjName('monza')) 

 

Saida gerada por esse codigo >> 
opala 
fusca 
Insira um nome no veiculo... 

 


Usando o parametro __newindex

Ao usar esse parametro, voce declara para onde vai ou onde vai buscar os valores do objeto.

 

Citar

 

local impala = setmetatable({},{__index = _veiculo, __newindex = opala}) 
-- todos os elementos declarados para esse objeto impala, não ficam nesse objeto e sim, vão para o objeto declarado em __newindex. 

 

impala.combustivel = "gasolina" -- declarado uma varivel. 
function impala:setPower(power) -- declarado novos metametodos. 
   self.power = power 
end 

function impala:getPower() 
   return self.power 
end 

opala:setPower(200) -- somente o objeto declarado em __newindex é que pode se fazer do uso dos elementos adicionados. 

print(opala.combustivel,opala:getPower()) -- pegando os elementos dentro do objeto opala. 

 

Saida gerado por esse codigo >> gasolina,   200 

 

 

E por ultimo o elemento __tostring 
__tostring serve como elemento para receber uma string para outros fins que não sejam metametodos. 
 

Citar

 

local marverick = setmetatable({},{__index = _veiculo, __tostring = function() return "Essa é uma super-maquina!!!" end}) 
print(marverick) 

 

Saida gerada por esse codigo >> Essa é uma super-maquina!!! 

 

 

Bem é isso pessoal espero que tenham entendido. 

Me corrijam caso tenha errado algo.

Editado por Poccnn
Inserção de informações/formatação

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!


Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.


Entrar Agora

  • Conteúdo Similar

    • Nova livraria lua para xml
      Por Poccnn
      Fala XTibianos!
      Vim disponibilizar e ensinar como usar a livraria xml em lua, desenvolvida por mim. 
       
      Ela foi desenvolvida para substituir a livraria padrão disponibilizada por lua para trabalhar com dados xml.
      Essa livraria não requer a dll-xml necessária para a livraria padrão lua.
       
      Aqui tem o tutorial criado por mim para demonstrar as funções e suas implementações da livraria luaxml.

      Registre-se para ver link(s).
       
      Vamos lá.
      Primeiro, a livraria: 
      --[=[ ################################################################################################################# ## LibXml desenvolvida por Marcryzius ## ## Terminado na data: 23 de Julho de 2016 ## ## Ultima modificação: 7 de setembro de 2016 ## ## Livre para quem queira usa-la ou modifica-la (caso modifique, favor postar suas modificações para ajudar outros). ## ################################################################################################################# ]=] xml = {} -- carrega o arquivo e retornar um objeto para os metametodos ou uma string para outros fins. function xml:load(dir) local open,read_open = io.open(dir,'r') if(open)then read_open = open:read(-1) open:close() else read_open = "<?xml version=\"1.0\"?>\n<!-- file \"",dir, "\", criado por LuaXML system desenvolvido por Marcryzius -->\n\n" end return setmetatable({},{__index = xml, __tostring = function() return read_open end}) end -- Converte strings formatadas em xml para tabelas com parametros validos em lua. retornar uma tabela. function xml:eval(tag,head) local tab,index,tag = {},0,type(tag) == 'string' and tag or tostring(self) if(string.match(tag,'<.-/>'))then --<tag name="carrot" quant="914"/> for head,corpser in string.gmatch(tag,'<(%a+) (.-)/>') do if not(tab[index+1])then tab[index+1] = { head = head, _M = 'tag' } end for k,v in string.gmatch(corpser,'(%a+).-"(.-)"') do tab[index+1][k] = v end index = index+1 end elseif(string.match(tag,'<.->'))then if(string.match(tag,'<(%a+)>'))then --<bloco> </bloco> tab.head = string.match(tag,'<(%a+)>') tab._M = 'bloco' for ke,v in pairs(xml:eval(head)) do tab[ke] = v end elseif(string.match(tag,'<(%a+).->'))then --<string id="author"> Corpo com string </string> tab.head = string.match(tag,'<(%a+).->') tab._M = 'tagBloco' for ke,v in string.gmatch(string.match(tag,'<%a+ (.-)>'),'(%a+).-"(.-)"') do tab[ke] = v end for ke,v in pairs(xml:eval(head)) do tab[ke] = v end end end return tab end -- converte tabelas e parametros com argumentos pre-determinados para xml, em uma string formatada em xml. retornar uma string. function xml:str() local str = '' if(self._M == 'tag')then --<tag name="carrot" quant="914"/> str = '\n<'..(self.tag or '')..' ' for k,v in pairs(self) do if not(k == '_M') and not(k == 'head') and not(k == 'tag') and not(type(v) == 'table') and not(tonumber(k)) then str = str..k..'="'..v..'" ' end end str = str..'/>' elseif(self._M == 'tagBloco')then local taghead,corpo = '','' --<string id="author"> Corpo com string </string> for k,v in pairs(self) do if not(type(v) == 'table')then if not(k == '_M') and not(k == 'head') and not(tonumber(k)) then taghead = taghead..' '..k..'="'..v..'"' elseif(k == '_string')then corpo = corpo..' '..v end elseif(type(v) == 'table')then corpo = corpo..xml.str(v) end end str = '\n<'..(self.head or 'tag')..taghead..'>'..corpo..'\n</'..(self.head or 'tag')..'>' elseif(self._M == 'bloco')then --<bloco> </bloco> local corpo = '' str = '<'..self.head..'>' for k,v in pairs(self) do if(tonumber(k) and type(v) == 'table')then corpo = corpo..xml.str(v) end end str = str..corpo..'\n</'..self.head..'>' end return str end -- Busca um bloco xml atraves dos argumentos fornecidos. retornar um objeto para os metametodos ou uma string para outros fins. function xml:find(headTag,param,value) local tab = {} local tag,head = nil,nil if not(headTag) or type(headTag) ~= 'string' then return false elseif not(string.find(tostring(self),'<?xml version="1.0".-?>'))then --<?xml version="1.0" encoding="UTF-8"?> return false,'Versao do arquivo xml nao aceita ou desconhecida - use versao 1.0' elseif not(param and value)then tag,head = string.match(tostring(self),'(<'..headTag..'>)(.-)</'..headTag..'>') if not(tag)then tag,head = string.match(tostring(self),'(<'..headTag..'.->)(.-)</'..headTag..'>') end elseif tostring(param) then for tg,hd in string.gmatch(tostring(self),'(<'..headTag..'.->)(.-)</'..headTag..'>') do if(string.find(tg,param..'="'..value..'"'))then tag,head = tg,hd end end end if(tag and head)then tab = xml:eval(tag,head) end return setmetatable(tab,{__index = xml, __tostring = xml.str}) end -- Cria um novo objeto xml com o nome da taghead inserido. function xml:new(arg) return setmetatable({head = arg or 'xmltag', _M = 'bloco'},{__index = xml, __tostring = xml.str}) end -- Essa função não é equivalente a da libluaxml que modificar o nome da taghead. -- Essa função cria uma tag do tipo >> <tagExemplo valor="1" novo="new"/> function xml:tag(arg,param) -- arg, seria o nome da tag (<tagExemplo .../>) -- param, seria uma tabela contendo todos os valores que serão postos na tag ({valor=1,novo="new"}). if(type(arg) ~= 'string')then return print(type(param) == 'string' and param or type(param)) end local tab = {tag=arg,_M='tag'} if(type(param) == 'table')then for k,v in pairs(param) do tab[k] = v end end table.insert(self,tab) end -- Essa função não é equivalente a da libluaxml. -- Essa função cria uma tag do tipo >> <tagExemplo pode="ter" valores="aqui" opcional=":)">valores inseridos aqui tambem (obs. com uso de metametodos)</tagExemplo> function xml:append(arg,param) -- arg, seria o nome da tag (<tagExemplo .../>) -- param, seria uma tabela contendo todos os valores que serão postos na tag ({valor=1,novo="new"}). local tab = {head=arg,_M='tagBloco'} if(type(param) == 'table')then for k,v in pairs(param) do tab[k] = v end end if(type(param) == 'string')then table.insert(tab,param) end table.insert(self,tab) return setmetatable(tab,{__index = xml, __tostring = xml.str}) end -- salva os dados em um arquivo xml -- Se, já existir o arquivo, ele será substituido. function xml:save(dir) local dir = type(dir) == 'string' and #dir > 6 and dir or 'newFileByXmlGenerator.xml' if not(string.find(dir,'.xml'))then dir = dir..'.xml' end local file = io.open(dir,"w") file:write("<?xml version=\"1.0\"?>\n<!-- file \"",dir, "\", criado por LuaXML system desenvolvido por Marcryzius -->\n\n") file:write(self:str()) file:close() end  
       
      Vou ensinar como usar ela. 
      Vou usar como exemplo uma parte do arquivo vocations.xml: 
         
      Registre-se para ver spoiler(s).
       
      Obs. Os codigos estão codificados em utf8, converta para ansi antes de usa-los.
       
      É isso ae pessoal, espero que gostem.
       
    • Script de npc função de "wait"
      Por Zync
      Eu tenho um script de um npc que luta contra o jogador, e tenho ele a dizer umas frases antes do duelo, só que da forma que tenho ele fala tudo de uma vez e solta logo o pokemon, o que não da tempo ao player der ler as mensagens, eu queria uma função que fizesse o npc esperar x segundos entre cada mensagem
      Eu tentei usar esta função:
      local function wait(seconds) local start = os.time() repeat until os.time() > start + seconds end (...) selfSay("O meu nome é X, eu quero duelar com vc!") wait(2) selfSay("Espero que esteja preparado mlk!") wait(2) selfSay("Vamos a isso!") (...) Mas não teve o resultado que eu esperava, o npc fica calado durante algum tempo e depois fala as msgs e solta logo o pokemon tupo no mesmo instante, tem alguma forma que funcione de fazer isso?
    • Bloquear e Desbloquear Comando
      Por Justiceiro751
      Alguém poderia me ajudar a criar um script para GM e ADM que bloqueia e desbloqueia um comando ?
      Ex GM/ADM: /abrirevento 15 -- aqui iria abrir o evento por 15 segundos, então o player teria que digitar /irevento dentro de 15 segundos.
      após passar 15 segundos, o player não iria conseguir mais entrar no evento, ou seja, não irá conseguir usar o comando /irevento.
       
      Pergunta: Mas como seria o evento ?
      Resposta: O player seria movido para uma determinada localização no mapa definida pelo criador do script.
      @UP.
    • Sistema de Ferreiro - inovador.
      Por Poccnn
      Hail Xtibianos.
      Eu estava/estou atualizando alguns scripts meus bem antigos, então resolvi compartilhar para vocês que priorizam um jogo mais ao estilo: segunda vida na idade média. 
       
      Bom... tu terás que fazer uma sala parecida como essa e com esses ids (pois já foram implementados no código).

       
      Agora vamos implementar os códigos:
      Vá em data/actions.xml e insira essas tags:
       
      Em data/actions/scripts/tools; insira todos esses códigos cada um com seus respectivos nomes:
       
      ferreiro.lua
       
      wood.lua
       
      bellow.lua
       
      Pronto. Instalados os scripts; agora irei explicar como funciona o sistema.
       
      Para acender o crucible, você precisa usar o fire bug (5468) no crucible (8642) até ele acender.

       
      Agora você põe a arma em cima da bancada e clica no bellow para ele 'aquecer' a arma para forja.

       
      Depois de 'esquentar' a arma, voce forja ela no anvil (bigorna de id 2555) por um tempo (tempo esse determinado pelo uso do crucible).

       
      Se o crucible 'apagar', voce clica no bellow até ele voltar a 'acender', mas isso só pode ser feito algumas vezes.
       

       
      Se você clicar muitas vezes e ele não 'acender', então tu terás que usar o fire bug de novo no crucible.
       
      É isso pessoal, depois posto mais scripts atualizados meu; espero que gostem; qualquer erro ou dúvida deixem no comentário abaixo.
    • Tutorial Coroutine Lua
      Por Poccnn
      Fala Xtibianos. 
      Nesse tutorial, gostaria de explicar um pouco sobre coroutine e seu uso. 
       
      Irei começar com uma lista de funções da coroutine. 
       
      Irei começa falando sobre a principal função da coroutine. 
       
      No corpo dessa função, voce precisa declarar pontos para "suspender" a execução da coroutine. 
       
      Ao criar a coroutine, ela se encontra no estado "suspended", ou seja, parada/pausada. 

      para iniciar a coroutine, voce precisa ativar ela usando a função: 
       
      Além de ativar/reativar a coroutine, você passa valores para a função da coroutine. 
      A primeira ativação da coroutine, os argumentos passados não poderão ser modificados, ficam estáticos nos parâmetros da função. 
       
       
      Veja que o resultado da segunda chamada não coincidem com os valores passados. Isso se dá devido aos parâmetros da função impregada na coroutine, não modificar seus valores. uma vez declarados os valores, eles não poderão ser modificados. 
       
      uma chamada de coroutine a mais da quantidade de yield's existente na coroutine.
       
      Como demonstrado acima, ao exceder a quantidade de yield's, ela retorna essa mensagem (sem disparar erro no console). 
       
      Agora você deva estar se perguntando: Então como fazer para pegar os valores que são passados em cada ativação? 

      Vou explicar agora: 
      a função yield pega os valores fornecidos e retorna-os; então você pode pegar esses valores usando variaveis para armazena-los. 
       
       
      Mas, no corpo da função criada para a coroutine, você pode fazer chamadas a funções, pegar valores de variaveis globais, etc; sempre usando a função yield para "suspender" a coroutine. 
       
       
      Agora só falta comentar sobre a função: 
       
      Assim como coroutine.create, a função auxiliar coroutine.wrap cria uma nova co-rotina, mas ao invés de retornar uma referência para a co-rotina, retorna uma função que, quando chamada, (re)invoca a co- rotina. 

      De forma geral, a função coroutine.wrap oferece uma maior conveniência que coroutine.create; ela provê exatamente o que é usualmente necessario: uma função para reativar uma co-rotina. Por outro lado, o uso das funções coroutine.create e coroutine.resume permite o gerenciamento de erros (funções estas que não podem ser usada por wrap). 
       

      A função retornada por coroutine.wrap não captura erros; qualquer erro provocado pela execução da co-rotina é propagado a seu chamador. 
       
      É isso ai pessoal, espero que tenham gostado. qualquer duvida, sugestão ou critica, deixem nos comentários. 
       

Anuncie no Xtibia!

Anuncie para obter mais acessos em seu servidor, entre em contato conosco: [email protected].