Welcome to 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.

Postado (editado)

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

Interessante o tutorial, não sabia que existia essa possibilidade em LUA.

Obrigado por compartilhar @Poccnn

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

    • Por Poccnn
      Hail Xtibianos.
       
      Eu criei esse sistema para impedir que mages usem magias sem estarem usando o livro. 
      Cada livro libera uma certa quantidade de magias, logo, os mages terão que ter o livro para usarem determinadas magias mesmo eles tendo o level requerido por ela.
       
      Tu irás a precisar usar essa livraria para poder usar esse sistema:
       
      Em movements.xml adicione:
      Registre-se para ver spoiler(s).
       
      Mais realidade para o verdadeiro tibia.
      Qualquer duvida, erro e etc, deixe nos comentários. 
    • Por Poccnn
      MALLEUS MALEFICARUM
       
      O Martelo das Bruxas ou O Martelo das Feiticeiras é um livro que foi escrito e publicado em 1486 ou 1487 pelos dominicanos Heinrich Kraemer (também conhecido por Heinrich Institoris) e James Sprenger, na Alemanha, em cumprimento à bula papal Summis Desiderantis Affectibus de Inocêncio VIII, que os autorizava criar um manual de combate aos praticantes de heresias - e que veio a se tornar o guia dos inquisidores pelo restante do século XV e seguintes; embora outros manuais tenham sido escritos no período, este é dos mais "perversos e cruéis", verdadeiro "manual de ódio, de tortura e morte".
       

       
      Devido a heresia cometidas pelas pessoas que renegaram a fé um dia obtida e pactuando sua vida com o diabo, trouxeram para si a ira de Deus.
      Negaram a fé, negaram a igreja, negaram Deus e prestaram culto ao diabo.

       
       
       
       
      A ARTE DO PENTAGRAMA
       
      As Bruxas são mulheres que praticam culto ao diabo e se satisfazem de seu poder para suas feitiçarias, encantos e adivinhações. 
      Devido a suas capacidade de conhecerem as artes da magia negra, os Bruxos conseguem causar pânico por onde passam e onde atuam.
      O pentagrama é o simbolo chave para a Bruxaria; é dele que dizem que as forças do mal emanam e os Bruxos o usam para suas artes malignas.
       

       
       
      Não era para ser uma quest esse sistema, mas eu adaptei para poder publica-lo.
       
      Inicialmente foi desenvolvido apenas como forma de punição pela sentença dada pela inquisição aos acusados de bruxaria; agora ele se tornou uma quest.
       
      Adicionando o sistema.
       
      data/movements/movements.xml
      Registre-se para ver spoiler(s).
      mapa:

      Registre-se para ver attachment(s).
       

      Registre-se para ver attachment(s).

      Registre-se para ver attachment(s).

      Registre-se para ver attachment(s).

      Registre-se para ver link(s).

      Registre-se para ver attachment(s).

      Registre-se para ver attachment(s).
    • Por leozinpbb
      Esta dando esse probleminha aqui agora , e também não consigo atacar mais ninguém.

      Registre-se para ver attachment(s).

      Registre-se para ver attachment(s).
    • Por Poccnn
      Hail Xtibianos.
       
      Trago a vós uma serie de funções que eu uso no meu servidor e que pode ser úteis ao seu.
      Lembrando que algumas funções podem fazer uso de uma livraria xml criado por mim e posta nesse tópico.
       
       
      Essa função tem por objetivo criar uma data formatada (00:00:00) de um intervalo de tempo.
       
      function intervalClockFormat(ini,fim) --[[( Marcryzius )]]--local ini,fim = tonumber(ini),tonumber(fim)if not(ini or fim)then return "error",print('function intervalClock erro: type de variaveis invalidas') endlocal tienpo = fim-ini-- existe o parametro de dia, mas não está sendo retornado (usado).local day,hour,minu,seco  = tienpo/60/60/23%30,math.floor(tienpo/60/60%23), math.floor(tienpo/60%60),math.floor(tienpo%60)    return (hour < 10 and "0"..hour or hour)..":"..(minu < 10 and "0"..minu or minu)..":"..(seco < 10 and "0"..seco or seco)endEx: print(intervalClockFormat(os.time(),os.time()+98)) >> 00:01:38print(intervalClockFormat(os.time(),os.time()+6598)) >> 01:49:58
      Essas funções tem por objetivo salvar as informações de uma determinada quest e saber se o player tem essa quest salva em seu histórico. 
      function saveQuestsInfor(uid,name,cid,other) --[[( Marcryzius )]]----[[    uid = Item.uid usado no bau(entre outros) para receber o item da Quest    name = nome do item dado ao player ou nome da quest    cid = identificacao do player    other = informacoes adicionais para serem salvas junto a quest]]--if not(db.executeQuery("SELECT * FROM `server_quests`;"))then -- caso a table não exista, será criada    db.executeQuery("CREATE TABLE `server_quests` (`uid` INTEGER, `name` VARCHAR(255), `name_player` VARCHAR(255), `pos` VARCHAR(255), `other` TEXT);")end-- caso o parametro uid seja numero, se pega a posição do item ou, caso não, se pega a posição do player.local other,pos2 = other or '',''local pos = type(uid) == 'number' and getThingPos(uid) or getCreaturePosition(cid)    pos2 = 'x='..pos.x..', y='..pos.y..', z='..pos.z        -- verifica se tudo está correto.    if not(type(name) == 'string') or not(tonumber(cid))then         return false, print('Funcao requer parametros: name,cid')     end        -- salva as informações na database.    db.executeQuery("INSERT INTO `server_quests` (`uid`, `name`, `name_player`,`pos`,`other`) VALUES ("..(uid or tonumber(pos.x..''..pos.y..''..pos.z))..",'"..name.."', '"..getCreatureName(cid).."','"..pos2.."','"..other.."');")    return trueendfunction getSaveQuestsInfor(uid,cid) --[[( Marcryzius )]]--local str = false    if(tonumber(uid))then        str = db.getResult("SELECT * FROM `server_quests` WHERE `uid` = '"..uid.."' AND `name_player` = ".. db.escapeString(getCreatureName(cid))..";")    elseif(type(uid) == 'string')then        str = db.getResult("SELECT * FROM `server_quests` WHERE `name_player` = " ..db.escapeString(getCreatureName(cid)).. " AND `name` = '"..uid.."';")    else        return false,print('getSaveQuestInfor: tipo de uid invalido > '..tostring(type(uid)))    end    return (str:getID() == -1) and true or false end  
      Essa função serve para por a primeira letra de cada palavra da 'msg' em maiúscula.
      function upperPrimer(msg) --[[( Marcryzius )]]--local txt = ''    for k in string.gmatch(msg,'%a+') do        if(#k > 1)then            txt = txt..' '..k:gsub("^%a", function(s) return s:upper() end)        else            txt = txt..' '..k        end    end    return txt:sub(2,-1)endEx:print(upperPrimer("toda primeira letra de cada palavra desse texto foi colocada em maiusculo")) >> Toda Primeira Letra De Cada Palavra Desse Texto Foi Colocada Em Maiusculo  
      Função criada para determinar o valor inteiro mais próximo de uma fração.
      function math.proxInteger(value) --[[( Marcryzius )]]-- local value = tonumber(value)    if not(value)then return 0,print('Function error: math.proxInteger() > valor => '..type(value)) end    return value-math.floor(value) < 0.5 and math.floor(value) or math.ceil(value)end  
      Essa função converte a 'string' em números e devolve a soma de todos os números.
      function getStoreString(str) --[[( Marcryzius )]]--local store = 0    if(type(str) == 'string')then        for pos = 1,#str do            store = store+str:sub(pos,pos):byte()        end    elseif(type(str) == 'number')then        return str    else        print('function getStoreString adverte: tipo de parametro invalido. ('..type(str)..')')    end    return storeendEx:print(getStoreString("lua")) >> 322  
      Pega o level necessário para usar a arma dentro do arquivo weapons.xml
      function getLevelNeedToWeaponById(itemid) --[[( Marcryzius )]]--local xfile = xml:load("data/weapons/weapons.xml"):find('%a+','id',itemid)    return tonumber(xfile and xfile.level) or 0end
      Essa função faz uma verificação se há um town em uma determinada área.
      function getTownInArea(pos, ranger) --[[( Marcryzius )]]--local ranger,townid,bloked = ranger or 200,1,{getTownId('Gods Island'),getTownId('Isle of Destiny')} -- towns suprimidos    while getTownName(townid) do    local get  = getTownTemplePosition(townid)        if not(isInArray(bloked,townid)) and ((pos.x >= get.x-ranger and pos.x <= get.x+ranger)and(pos.y >= get.y-ranger and pos.y <= get.y+ranger))then            return townid        else            townid = townid+1        end    end    return 0 --retorna 0 (zero) para servir como condição.end
      Pega o nome e o level do top
      function getTopLevel() --[[( Marcryzius )]]--local target,name,level = db.getResult("SELECT `name`, `level` FROM `players` WHERE `group_id` <= 2 ORDER BY 'level' DESC;"),"",0    if(target:getID() ~= -1) then         repeat        local glevel = target:getDataInt("level")                if(level < glevel)then                name,level = target:getDataString("name"),    glevel            end        until not(target:next())     end    target:free()    return name,levelend  
      Verifica se existe o nome de um player mesmo ele estando offline.
      function playerExistName(nome) --[[( Marcryzius )]]--local db = db.getResult("SELECT `name` FROM `players` WHERE `id` = " ..getPlayerGUIDByName(nome).. ";")    if not(db:getID() == -1) then        return db:getDataString("name")    end    return falseend  
      Retorna o tempo vigente apenas em segundos
      function HorasParaSegundos() --[[( Marcryzius )]]--    local hour,minu,second = tostring(os.date("%H:%M:%S")):match('(%d+)%d+)%d+)')    return ((tonumber(hour) or 0)*3600)+((tonumber(minu) or 0)*60)+secondend