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 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
      --[[> Marcryzius Devil <]]-- forja = { [2406] = { {5880,2148,2148, result = 2395, fail = 2234}, {5880,5880,5880, result = 2413, fail = 2234}, {5880,2144,5880,2144,5880, result = 7385, fail = 2234} }, [2376] = { {5880, result = 2397, fail = 2234}, }, [2412] = { {2144,2143, result = 2438, fail = 2234}, {5880, 5880, 2149,2149, result = 2419, fail = 2234}, }, [2413] = { {5880,5880,5880,2152, result = 2377, fail = 2234}, }, [2384] = { {5880,5880,7760,5880,7760,7760,7760, result = 2392, fail = 2234}, {5880,5880, 5880, result = 2385, fail = 2234}, }, [2385] = { {5880, 2144, result = 2412, fail = 2234}, }, [2395] = { {2396,2396,2396,2157,2396, result = 2407, fail = 2234}, }, [2383] = { {5880,2145,2145,2145, result = 7449, fail = 2234}, }, [2379] = { {5880, result = 2376, fail = 2234}, {1294,1294,5880, result = 2420, fail = 2234}, {2151,5880,2151,2149, result = 2411, fail = 0}, }, [2420] = { {5880, 5880, result = 2443, fail = 2234}, {5880, 2149,5880,2149, result = 2419, fail = 2234}, }, [2402] = { {5880, result = 2384, fail = 2234}, }, [2403] = { {5880, result = 2406, fail = 0}, {5880,2151,2151, result = 2402, fail = 0}, }, [2404] = { {5880, result = 2395, fail = 2234}, {2143,5880,2143, result = 2379, fail = 0}, }, -- axes [2380] = { {5901,5901,5901, result = 2381, fail = 2559}, {5880, result = 2386, fail = 2559}, {2144, result = 2388, fail = 2559}, }, [2386] = { {5880, 1294, 5880, 1294, result = 8601, fail = 2559}, {2143, 5880, 5880, 2143, result = 2387, fail = 2559}, {2388,2144, 5880, 2144, result = 2430, fail = 2559}, }, [2416] = { {5880,5880,5901, result = 2422, fail = 2416}, }, [2225] = { -- knife {5880,2151, result = 2403, fail = 0}, {5880,2143, result = 2404, fail = 0}, {5880,2144, result = 2379, fail = 0}, -- axe {5880,5901, result = 2380, fail = 0}, -- hammer {5880,1294, result = 2416, fail = 0}, }, } function skill(cid) -- verifica o skill(ferreiro) do player usando store. return (getPlayerStorageValue(cid,getStoreString('_FERREIRO_SKILL')) < 0) and 0 or getPlayerStorageValue(cid,getStoreString('_FERREIRO_SKILL')) end function formatFerreiroLevel(valor) return math.floor(valor/20) end function getPiece(str) local obj = { itemid = str.itemid, actionid = str.actionid, uid = str.uid, type = getItemWeaponType(str.uid), time = 0, extra = getItemAttribute(str.uid,'extraattack') or getItemAttribute(str.uid,'extradefense') or 0, quant = 0, count = 0, max_count = getItemInfo(str.itemid).attack == 0 and getItemInfo(str.itemid).defense or getItemInfo(str.itemid).attack or 5, stack = 0, step = {} } if not(self)then self = setmetatable(obj,self) self.__index = self self.__call = function(self,uid,obj) if uid and not self[uid] then self[uid] = { __index = obj} setmetatable(self[uid], self[uid]) return self[uid] elseif(self[uid])then return self[uid] end end end return self.__call(self,str.actionid == 0 and str.uid or str.actionid,obj) end function onUse(cid, item, fromPosition, itemEx, toPos) local obj = nil local pos_item = {x=toPos.x,y=toPos.y,z=toPos.z,stackpos=1} local get = getThingFromPos(pos_item) local anvil = getThingFromPos({x=toPos.x,y=toPos.y,z=toPos.z,stackpos=2}) -- bigorna if(isCreature(itemEx.uid))then return true elseif not(anvil) or not(anvil.itemid == 2555)then -- bigorna return true,doPlayerSendCancel(cid,"use seu martelo em algum item em cima de uma bigorna.") elseif not(get) or not(isInArray({1,3,4},getItemWeaponType(get.uid)) or get.itemid == 2225) then return true else if(itemEx.actionid == 0)then doItemSetAttribute(itemEx.uid,"aid",itemEx.uid) end obj = getPiece(itemEx) -- pega o item para refinamento. end if(obj.type ~= 4 and obj.time+(obj.count*10) < os.time())then obj.count = 0 doPlayerSendCancel(cid,"Ponha sua arma na fornalha.") elseif((skill(cid)/20)%2 == 0 or (skill(cid)/20)%2 == 1)then doPlayerSendTextMessage(cid,20,"voce avançou para o level "..formatFerreiroLevel(skill(cid)).." na profissao de (Ferreiro).") doSendMagicEffect(toPos,3) else -- Verificações necessarias para adicionar um extraAtaque ou extraDefesa no item. local number = math.random(1,obj.max_count+((obj.extra == 0 and 1 or obj.extra)*10)) if(formatFerreiroLevel(skill(cid)) > number) then if(obj.quant >= obj.max_count)then if(obj.stack > 0)then table.insert(obj.step,obj.stack) obj.stack = 1 local result = nil for _, list in pairs(forja[obj.itemid]) do local parar = nil for k,passo in ipairs(obj.step)do result = not(passo == list[k]) and list.fail or nil if(#obj.step == k and not result)then if(#obj.step == #list)then result = list.result end parar = true end end if(parar)then break end end if(result)then obj.stack = 0 if(result == 0)then doRemoveItem(itemEx.uid) else doItemSetAttribute(itemEx.uid,"aid",itemEx.uid) doTransformItem(itemEx.uid, result) end doSendMagicEffect(toPos,5) return end end if(obj.type == 1 or obj.type == 3)then doItemSetAttribute(itemEx.uid,"extraattack",obj.extra+1) elseif(obj.type == 4)then doItemSetAttribute(itemEx.uid,"extradefense",obj.extra+1) end obj.count = 0 obj.quant = 0 doSendMagicEffect(toPos,14) return end obj.quant = obj.quant+1 doSendMagicEffect(toPos,13) doSendMagicEffect(toPos,3) elseif(formatFerreiroLevel(skill(cid)) < math.random(1,20))then doCreatureAddHealth(cid,-5) doPlayerSendCancel(cid,"você se machucou com seu martelo.") doSendMagicEffect(toPos,2) else doSendMagicEffect(toPos,3) end end return true,setPlayerStorageValue(cid,getStoreString('_FERREIRO_SKILL'),skill(cid)+1) end wood.lua
      --[[> Marcryzius Devil <]]-- function onUse(cid, item, fPos, itemEx, toPos) local number = math.random(1,10) if(itemEx.itemid == 8642)then if (skill(cid)/20 >= number)then doRemoveItem(item.uid, 1) doTransformItem(itemEx.uid,8641) doItemSetAttribute(itemEx.uid,"aid",itemEx.uid) doSendMagicEffect(toPos,6) doSendMagicEffect(toPos,15) doSendMagicEffect(toPos,36) addEvent(function(pos) local item_pos = getThingFromPos(pos) doSendMagicEffect(pos,2) doTransformItem(item_pos.uid,8642) end,60000*math.random(1,2),toPos) else if(math.random(1,10) == 1)then doCreatureSay(cid,"Aaaai!",1) doCreatureAddHealth(cid,-5) doSendMagicEffect(getCreaturePosition(cid),15) doPlayerSendCancel(cid,"você se queimou.") else doSendMagicEffect(toPos,2) doSendMagicEffect(toPos,5) end end setPlayerStorageValue(cid,getStoreString('_FERREIRO_SKILL'),skill(cid)+1) -- cana de açucar elseif(itemEx.itemid == 5471)then if(math.random(1,10) == 10)then doRemoveItem(item.uid) end doTransformItem(itemEx.uid,5465) doDecayItem(itemEx.uid) else doPlayerSendTextMessage(cid,20,"use o fogo na fornalha ou no canavial.") end return true end bellow.lua
      --[[> Marcryzius Devil <]]-- local retardo,effe_index,add = 0, 1,0 local function passEffect(pos,...) local effe = {...} doSendMagicEffect(pos,effe[effe_index] or 15) effe_index = effe_index+1 return coroutine.yield() end local crucible_bellow = function(pos,...) local a = {passEffect(pos,...)} local b = {passEffect(unpack(a))} local c = {passEffect(unpack(b))} passEffect(unpack(c)) effe_index = 1 return end function onUse(cid, item, fpos, itemEx, toPos) local crucible,mesa = nil,fpos for X = -1,1 do for Y = -1,1 do local npos = {x=X+fpos.x,y=Y+fpos.y,z=fpos.z,stackpos=1} local weapon = {x=X+fpos.x,y=Y+fpos.y,z=fpos.z,stackpos=2} local get = assert(getThingFromPos(npos)) if(get and get.itemid == 8641 or get.itemid == 8642)then crucible = getPiece(get) if not(crucible.pos)then crucible.pos = npos end if not(crucible.co)then crucible.co = coroutine.create(crucible_bellow) end elseif(get and get.itemid == 10967)then local get = assert(getThingFromPos(weapon)) if(isInArray({1,3,4},getItemWeaponType(get.uid)) or get.itemid == 2225)then mesa = weapon else add = get.itemid doRemoveItem(get.uid) doSendMagicEffect(weapon,5) end end end end local peg = getThingFromPos(mesa) local attack_item = peg and (getItemInfo(peg.itemid).attack < 5 and 5 or getItemInfo(peg.itemid).attack) or 5 if(crucible and retardo <= os.time())then retardo = os.time()+1 -- intervalo de uso em segundos. if(crucible.itemid == 8642 and crucible.actionid > 0)then local co = coroutine.resume(crucible.co,crucible.pos,6,15,36) if not(co)then local item_pos = getThingFromPos(crucible.pos) crucible.co = coroutine.create(crucible_bellow) doSendMagicEffect(fpos,2) crucible.itemid = 8641 doTransformItem(item_pos.uid,8641) if(crucible.count > math.random(3,5))then doItemSetAttribute(item_pos.uid,"aid",0); crucible.actionid = 0 end addEvent(function(obj) local item_pos = getThingFromPos(obj.pos) obj.count = obj.count+1 obj.itemid = 8642 doSendMagicEffect(obj.pos,CONST_ME_POFF) doTransformItem(item_pos.uid,8642) end,60000*math.random(4,5),crucible) end elseif(crucible.itemid == 8641 and type(mesa) == 'table' and math.random(1,attack_item*3) <= skill(cid))then local get_weapon = getThingFromPos(mesa) if(get_weapon.actionid == 0)then doItemSetAttribute(get_weapon.uid,"aid",get_weapon.uid) end local obj = getPiece(get_weapon) obj.time = os.time() obj.stack = obj.stack > 1 and obj.stack or add if(obj.count <= attack_item)then obj.count = obj.count+1 else doRemoveItem(get_weapon.uid) doSendMagicEffect(toPos,5) return end else doSendMagicEffect(crucible.pos,2) return true end doSendMagicEffect(mesa or crucible.pos,15) doSendMagicEffect(crucible.pos,5) doSendMagicEffect(fpos,67) end return true end 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.
       
      Novo sistema de forja adicionado.
      Agora tu poderás adicionar materiais a forja para obter outros items.
       
      Explicação desse novo sistema:
      Primeiro tu põe a arma base para adição de novos compostos na mesa.
       

      Registre-se para ver attachment(s).
       
      adicione o item em cima da arma.
      Clique no bellow e o item de adição desaparecera.
       

       
      Leve o item "aquecido" para a bigorna.
      Use a marreta nele até sair um efeito verde.
       

       
      Caso ele peça para por de volta na fornalha a arma, não adicione outro item, apenas aqueça-o.
       
      Faça esse mesmo procedimento adicionando compostos até que o item seja criado.
       

       
      aqui um manual de forja feito a parti da tabela forja no script ferreiro.lua
      Registre-se para ver spoiler(s).
       
      Tu poderás adicionar mais compostos para obter outros items a seu critério.
       
      É isso pessoal, depois posto mais scripts atualizados meu; espero que gostem; qualquer erro ou dúvida deixem no comentário abaixo.
    • Por Poccnn
      Hail Xtibianos.
       
      Esse script eu criei a pedido de um membro do fórum e resolvi posta-lo para vocês.
       
      Ele serve para que ao matarem um determinado monstros, somente os players que tiverem uma certa quantidade de participação (em porcentagem) na morte do monstro é que receberam algo (configurável).
       
      Em creaturescripts.xml adicione:
      <event type="statschange" name="stats" script="statsMonster.lua"/> <event type="death" name="deathMonster" script="deathMonster.lua"/>  
      Em creaturescripts/scripts crie um arquivo lua com o nome statsMonster e adicione:
      M = {} function getDamageInMonster(monster,cid) local monster,cid,m_life,p_dano = tonumber(monster),tonumber(cid),0,0 if not(monster or cid)then return 0,error('function getDamageInMonster(): monster or cid, not number') end if not(isCreature(monster))then return 0,error('function getDamageInMonster(): variavel monster nao e monstro.') end for k,v in pairs(M[monster]) do if(k == cid)then p_dano = v end m_life = m_life + v end return math.floor(p_dano/(m_life/100)) end function onStatsChange(cid, attacker, tipo, combat, value) if not(M[cid])then M[cid] = {} end if not(tipo == 1)then return true end if(isPlayer(attacker))then if not(M[cid][attacker])then M[cid][attacker] = 0 end M[cid][attacker] = M[cid][attacker] + value elseif(isMonster(attacker))then -- caso seja um monstro o atacante local get = getCreatureMaster(attacker) -- averigua se não é um summon que está atacando if(tonumber(get) and isPlayer(get))then -- caso o summon seja de um player, adiciona o dano como se fosse o player if not(M[cid][get])then M[cid][get] = 0 end M[cid][get] = M[cid][get] + value end end return true end  
      Agora crie outro arquivo lua na mesma pasta e nomeie para deathMonster e adicione:
      function onDeath(cid, corpse, deathList) --[[> Marcryzius <]]-- if(isCreature(cid))then for _,player in pairs(deathList) do local player = isCreature(player) and getCreatureMaster(player) or player if(isPlayer(player) and isPlayerOn(player))then if(getDamageInMonster(cid,player) >= 50)then --[[ recompensa dada ao jogador Dar um item ao player, enviar ele a algum lugar, setar store etc... ]]-- end if(M[player])then table.remove(M,player) end end end end return true end  
      No monstro que tu queira usar esse sistema, adicione no xml dele essas duas tags:
      <script> <event name = "stats"/> <event name = "deathMonster"/> </script>  
      Pronto.
      Qualquer duvida, erro e etc, deixe nos comentários. 
    • 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:
      <movevent type="Equip" fromid="8905" toid="8909" slot="shield" level="100" event="function" value="onEquipItem"> </movevent> <movevent type="DeEquip" fromid="8905" toid="8909" slot="shield" event="function" value="onDeEquipItem"/> <movevent type="Equip" itemid="8190" slot="shield" level="8" event="script" value="spellbooks.lua"> <vocation id="1"/> <vocation id="5"/> <vocation id="2"/> <vocation id="6"/> <vocation id="9"/> <vocation id="10"/> </movevent> <movevent type="DeEquip" itemid="8190" slot="shield" event="script" value="spellbooks.lua"/> <movevent type="Equip" itemid="8900" slot="shield" level="30" event="script" value="spellbooks.lua"> <vocation id="1"/> <vocation id="5"/> <vocation id="2"/> <vocation id="6"/> <vocation id="9"/> <vocation id="10"/> </movevent> <movevent type="DeEquip" itemid="8900" slot="shield" event="script" value="spellbooks.lua"/> <movevent type="Equip" itemid="8901" slot="shield" level="40" event="script" value="spellbooks.lua"> <vocation id="1"/> <vocation id="5"/> <vocation id="2"/> <vocation id="6"/> <vocation id="9"/> <vocation id="10"/> </movevent> <movevent type="DeEquip" itemid="8901" slot="shield" event="script" value="spellbooks.lua"/> <movevent type="Equip" itemid="8902" slot="shield" level="50" event="script" value="spellbooks.lua"> <vocation id="1"/> <vocation id="2"/> <vocation id="5"/> <vocation id="6"/> <vocation id="9"/> <vocation id="10"/> </movevent> <movevent type="DeEquip" itemid="8902" slot="shield" event="script" value="spellbooks.lua"/> <movevent type="Equip" itemid="8903" slot="shield" level="60" event="script" value="spellbooks.lua"> <vocation id="1"/> <vocation id="5"/> <vocation id="6"/> <vocation id="9"/> <vocation id="10"/> </movevent> <movevent type="DeEquip" itemid="8903" slot="shield" event="script" value="spellbooks.lua"/> <movevent type="Equip" itemid="8904" slot="shield" level="70" event="script" value="spellbooks.lua"> <vocation id="5"/> <vocation id="6"/> <vocation id="9"/> <vocation id="10"/> </movevent> <movevent type="DeEquip" itemid="8904" slot="shield" event="script" value="spellbooks.lua"/> <movevent type="Equip" itemid="8918" slot="shield" level="80" event="script" value="spellbooks.lua"> <vocation id="5"/> <vocation id="6"/> <vocation id="9"/> <vocation id="10"/> </movevent> <movevent type="DeEquip" itemid="8918" slot="shield" event="script" value="spellbooks.lua"/> <movevent type="Equip" itemid="8983" slot="shield" level="120" event="script" value="spellbooks.lua"> <vocation id="5"/> <vocation id="9"/> <vocation id="10"/> </movevent> <movevent type="DeEquip" itemid="8983" slot="shield" event="script" value="spellbooks.lua"/>  
      Em movements/scripts crie um arquivo lua chamado spellbooks e adicione:
      local tab = { [8190] = { "Find Person","Ultimate Healing","Magic Shield","Strong Haste","Antidote pox","Antidote fire","antidote vis","Heal Friend","Cure Friend", "Death Strike" ,"Flame Strike","Energy Strike","Ice Strike","Terra Strike","Fire Wave","Ice Wave","Energy Beam","Great Energy Beam","Creature Illusion", "Ultimate Light","Cancel Invisibility","Invisibility","Summon Creature","Poison Field","Light Magic Missile","Fire Field","Fireball","Energy Field","Stalagmite", "Heavy Magic Missile","Poison Bomb","Firebomb","Soulfire","Poison Wall","Antidote Rune","Ultimate Healing Rune","Animate Dead","Chameleon", "Destroy Field","Desintegrate","Wild Growth","Icicle","Stone Shower","Thunderstorm" }, [8900] = { "Energy Wave","Terra Wave","Mass Healing","Heal Party","Enchant Party","Great Fireball","Explosion","Fire Wall","Energybomb", "Magic Wall","Avalanche","Enchant Tera","Enchant Ice","Enchant Flam","Enchant Vis"},--30 [8901] = {"Enchant Staff","Energy Wall","Sudden Death"},--40 [8902] = {"Rage of the Skies","Wrath of Nature","Paralyze"},--50 [8903] = {"Hells Core","Eternal Winter","Undead Legion","pocion"},--60 [8904] = {"Ultimate Mana Rune"},--70 [8918] = {"wave of fire"},--80 [8983] = {"Death Mort","Apocalypse","Death Wave"}, } local ML1 = createConditionObject(CONDITION_ATTRIBUTES) local ML2 = createConditionObject(CONDITION_ATTRIBUTES) local ML3 = createConditionObject(CONDITION_ATTRIBUTES) local ML4 = createConditionObject(CONDITION_ATTRIBUTES) setConditionParam(ML1, CONDITION_PARAM_TICKS, 24 * 60 * 60 * 1000) setConditionParam(ML2, CONDITION_PARAM_TICKS, 24 * 60 * 60 * 1000) setConditionParam(ML3, CONDITION_PARAM_TICKS, 24 * 60 * 60 * 1000) setConditionParam(ML4, CONDITION_PARAM_TICKS, 24 * 60 * 60 * 1000) setConditionParam(ML1, CONDITION_PARAM_STAT_MAGICLEVEL, 1) setConditionParam(ML2, CONDITION_PARAM_STAT_MAGICLEVEL, 2) setConditionParam(ML3, CONDITION_PARAM_STAT_MAGICLEVEL, 3) setConditionParam(ML4, CONDITION_PARAM_STAT_MAGICLEVEL, 4) setConditionParam(ML1, CONDITION_PARAM_SKILL_SHIELD, -1) setConditionParam(ML2, CONDITION_PARAM_SKILL_SHIELD, -2) setConditionParam(ML3, CONDITION_PARAM_SKILL_SHIELD, -3) setConditionParam(ML4, CONDITION_PARAM_SKILL_SHIELD, -4) local function getItemAttrInFile(id,key) --[[( Marcryzius )]]-- local tipo = (type(id) == 'number') and 'id' or 'name' local file = xml:load('data/items/items.xml') local lerfile = file:find("item",tipo,id) for _,tab in pairs(lerfile) do if(type(tab) == "table")then if(tab.key == key)then return tab.value end end end return false end local function getBookRequirementLevelByVoc(id,voc) --[[( Marcryzius )]]-- local file = xml:load('data/movements/movements.xml') local lerfile = file:find("movevent type=\"Equip\"","itemid",id) for _,tab in pairs(lerfile) do if(type(tab) == "table")then if(tonumber(tab.id) == voc)then return tonumber(lerfile.level) end end end return false end function onEquip(cid, item, slot) local level = getBookRequirementLevelByVoc(item.itemid,getPlayerVocation(cid)) if not(level) or (getPlayerLevel(cid) < level)then return false else for id,tab in pairs(tab) do for _,name in pairs(tab) do if(id <= item.itemid)then playerLearnInstantSpell(cid,name) end end end local attr = tonumber(getItemAttrInFile(item.itemid,"magiclevelpoints")) doAddCondition(cid, (attr == 1) and ML1 or attr == 2 and ML2 or (attr == 3) and ML3 or (attr == 4) == ML4 or nil) end return true end function onDeEquip(cid, item, slot) for _, v in pairs(tab) do for _,name in pairs(v) do doPlayerUnlearnInstantSpell(cid,name) end end doRemoveCondition(cid,CONDITION_ATTRIBUTES) return true end  
      Aconselho substituir o código do spellbook em actions por esse:
      Em actions.xml verifique se existe todos essas tags, caso não, adicione:
      <action itemid="2175" event="script" value="other/spellbook.lua"/> <action itemid="6120" event="script" value="other/spellbook.lua"/> <action itemid="8190" event="script" value="other/spellbook.lua"/> <action fromid="8900" toid="8904" event="script" value="other/spellbook.lua"/> <action itemid="8918" event="script" value="other/spellbook.lua"/> <action itemid="8983" event="script" value="other/spellbook.lua"/> Em actions/scripts/other/spellbooks.lua apague o seu conteúdo e adicione este:
      function onUse(cid, item, fromPosition, itemEx, toPosition) local count = getPlayerInstantSpellCount(cid) local text,plvl = "",getPlayerLevel(cid) local t = {} local ope = xml:load("data/spells/spells.xml") for i = 0, count-1 do local spell = getPlayerInstantSpellInfo(cid, i) local ler = ope:find("%a+","words", spell.words) local check,prem = nil, tonumber(ler.prem) == 1 and true or false for index,tab in pairs(ler) do if(type(tab) == "table")then if(tonumber(tab.id) == getPlayerVocation(cid))then check = true;break end end end if spell.level ~= 0 and check then if not(prem) or prem == isPremium(cid) then if spell.manapercent > 0 then spell.mana = spell.manapercent .. "%" end table.insert(t, spell) check = nil if(spell.level > plvl)then break end end end end table.sort(t, function(a, b) return a.level < b.level end) local prevLevel = -1 for i, spell in ipairs(t) do local line = "" if prevLevel ~= spell.level then if i ~= 1 then line = "\n" end if i == #t and spell.level > plvl then line = line.."Next spell > " end line = line .. "Spells for Level " .. spell.level .. "\n" prevLevel = spell.level end text = text .. line .. " " .. spell.words .. " - " .. spell.name .. " : " .. spell.mana .. "\n" end doShowTextDialog(cid, item.itemid, text) return true end  
      Mais realidade para o verdadeiro tibia.
      Qualquer duvida, erro e etc, deixe nos comentários. 
    • Por Poccnn
      Hail Xtibianos.
      Eu criei esse sistema, não lembro se foi a pedido de um membro ou não, para que seja interessante sempre matar o toplvl do otserver devido ao premio recebido por isso.
       
      Em config.lua adicione:
      huntedTopLevel = 100 -- "false" inibe o sistema; numero é o level minimo necessario para dar hunted ao toplvl. priceForEachLevelTohuntedTopLevel = 100 -- preço pago por cada lvl do toplvl ao mata-lo.  
      Em creaturescripts.xml adicione:
      <event type="death" name="toplvl" script="toplvl.lua"/>  
      Em creaturescripts/scripts/config.lua adicione:
      registerCreatureEvent(cid, "toplvl")  
      Na mesma pasta, crie um arquivo lua com o nome toplvl e adicione:
      function onDeath(cid, corpse, deathList) local top,price = getConfigInfo("huntedTopLevel"),getConfigInfo("priceForEachLevelTohuntedTopLevel") if(isPlayer(cid))then -- hunted top level local _,level = getTopLevel() if(tonumber(level) and top and tonumber(level) >= top and tonumber(level) <= getPlayerLevel(cid))then for _,player in pairs(deathList) do if(isPlayer(player))then doPlayerAddMoney(player, getPlayerLevel(cid)*price) end end end end return true end  
      Agora abra o arquivo lib/050-functions.lua e adicione:
      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,level end  
      No config.lua tu coloca o valor minimo requerido do toplvl para poder ser caçado.
       
      Duvidas, erros e qualquer outra coisa, deixe nos comentários. 
    • Por Poccnn
      Hail Xtibianos.
      Eu fiz esse sistema como pedido de um membro há um bom tempo, mas nunca tinha postado ele e diversos sistemas que uso no meu ot server; agora resolvi postá-los.
       
      Esse é o sistema que impede dos players da mesma party se atacarem ou, também dos membros da mesma guild.
       
      Em config.lua adicione:
      noDamageToGuildMates = false noDamageToPartyMembers = true  
      Em creaturescripts.xml adicione:
      <event type="combat" name="combat" script="combat.lua"/>  
      Em creaturescripts/scripts/login.lua adicione:
      registerCreatureEvent(cid, "combat") Na mesma pasta, crie um arquivo lua chamado combat e adicione isso nele:
      --[[> Marcryzius <]]-- function onCombat(cid, target) if(isPlayer(cid) and isPlayer(target)) then if(getConfigValue("noDamageToGuildMates") and getPlayerGuildId(cid) > 0 and getPlayerGuildId(cid) == getPlayerGuildId(target)) then return false elseif(getConfigValue("noDamageToPartyMembers") and isInParty(target) and getPartyLeader(target) == getPartyLeader(cid)) then return false end end return true end  
      Qualquer duvida ou erro deixe nos comentários.