Pokeultion 1 Postado Junho 2, 2018 Share Postado Junho 2, 2018 Olá pessoa, boa noite. Seguinte, estou tentando fazer uma janela de task no otc, e como em otc comecei agora não manjo nada, principalmente de opcode. Minha principal dúvida é, como fazer o opcode retornar Nome do pokémon da task e quantidade ? Segue oque eu tentei fazer: Código lua do servidor: Spoiler function sendTasksInfo() local pokes = { easy = {"Horsea", "Oddish", "Krabby"}, medium = {"Charmander", "Bulbasaur", "Squirtle"}, hard = {"Charizard", "Venusaur", "Blastoise"} } if getPlayerLevel(cid) < 20 then poke = pokes.easy[math.random(1, #pokes.easy)] quant = math.random(1, 50) doSendPlayerExtendedOpcode(cid, 80, poke..'@'..quant) elseif getPlayerLevel(cid) > 21 and getPlayerLevel(cid) < 70 then poke = pokes.medium[math.random(1, #pokes.medium)] quant = math.random(1, 100) doSendPlayerExtendedOpcode(cid, 80, poke..'@'..quant) elseif getPlayerLevel(cid) > 71 and getPlayerLevel(cid) < 502 then poke = pokes.hard[math.random(1, #pokes.hard)] quant = math.random(1, 300) doSendPlayerExtendedOpcode(cid, 80, poke..'@'..quant) return true end end Código LUA do client: Spoiler function tasksInfo(protocol, opcode, buffer) local param = buffer:split('@') taskWindow:getChildById('labelPoke'):setText(param[1]) taskWindow:getChildById('labelQuant'):setText(param[2]) end Lembrando que também registrei a função ProtocolGame.registerExtendedOpcode(80, tasksInfo) na função init(). Depois disso, apenas usei Labels comuns com ID labelPoke e labelQuant. Mas mesmo assim, não aparece nada no texto ta label. Mas também não da erro no terminal. Então gostaria de saber oque eu estou fazendo errado e se possível uma breve explicação de como funciona o opcode certinho e tal, pois estou começando agora na parte de otc. Obrigado e boa noite a todos! Link para o comentário Compartilhar em outros sites More sharing options...
BananaFight 196 Postado Junho 4, 2018 Share Postado Junho 4, 2018 Ja tentou printar o local param = buffer:split('@') para ver se esta chegando as informações ? Link para o comentário Compartilhar em outros sites More sharing options...
Pokeultion 1 Postado Junho 6, 2018 Autor Share Postado Junho 6, 2018 (editado) Em 03/06/2018 em 23:16, BananaFight disse: Ja tentou printar o local param = buffer:split('@') para ver se esta chegando as informações ? Ainda não. Do jeito que eu tentei fazer, eu queria que as informações chegassem quando eu abrisse a janela, vou tentar printar pra ver se ta acontecendo desse jeito. #edit: tentei printar igual faço com lua no servidor, n sei se é assim: function tasksInfo(protocol, opcode, buffer) local param = buffer:split('@') print(param[1]) print(param[2]) taskWindow:getChildById('labelPoke'):setText(param[1]) taskWindow:getChildById('labelQuant'):setText(param[2]) end E o resultado é: feijoada, nada acontece. Editado Junho 6, 2018 por Pokeultion Link para o comentário Compartilhar em outros sites More sharing options...
Pokeultion 1 Postado Junho 10, 2018 Autor Share Postado Junho 10, 2018 Alguém ? Link para o comentário Compartilhar em outros sites More sharing options...
Administrador PoRaI 99 Postado Junho 22, 2018 Administrador Share Postado Junho 22, 2018 ProtocolGame.registerExtendedOpcode(80, tasksInfo) já tentou usar fora do init? Pokeultion reagiu a isso 1 Link para o comentário Compartilhar em outros sites More sharing options...
Pokeultion 1 Postado Junho 22, 2018 Autor Share Postado Junho 22, 2018 22 horas atrás, PoRaI disse: ProtocolGame.registerExtendedOpcode(80, tasksInfo) já tentou usar fora do init? Agora que você falou, tentei colocar na função show(), mas nada acontece. Caso faça alguma diferença, olha o script.lua inteiro: Spoiler function init() connect(g_game, { onGameEnd = onGameEnd }) taskWindow = g_ui.displayUI('tasks') taskWindow:hide() shopTabBar = taskWindow:getChildById('shopTabBar') shopTabBar:setContentWidget(taskWindow:getChildById('shopTabContent')) marketPanel = g_ui.loadUI('market') shopTabBar:addTab('Market', marketPanel, '/images/game/shop/market') taskButton = modules.client_topmenu.addRightGameButton('taskButton', tr('Tasks'), '/images/topbuttons/emerald_shop', toggle) taskButton:setWidth(36) end function terminate() disconnect(g_game, { onGameEnd = onGameEnd }) taskWindow:destroy() taskButton:destroy() end function onGameEnd() if taskWindow:isVisible() then taskWindow:hide() end end function show() taskWindow:show() taskWindow:raise() taskWindow:focus() addEvent(function() g_effects.fadeIn(taskWindow, 250) end) ProtocolGame.registerExtendedOpcode(85, tasksInfo) end function hide() addEvent(function() g_effects.fadeOut(taskWindow, 250) end) scheduleEvent(function() taskWindow:hide() end, 250) end function toggle() if taskWindow:isVisible() then hide() else show() end end function tasksInfo(protocol, opcode, buffer) local param = buffer:split('@') print(param[1]) print(param[2]) taskWindow:getChildById('labelPoke'):setText(param[1]) taskWindow:getChildById('labelQuant'):setText(param[2]) end Obrigado. Link para o comentário Compartilhar em outros sites More sharing options...
PostadorHunter 99 Postado Junho 24, 2018 Share Postado Junho 24, 2018 ja tentou printar alguma coisa pra ver se a função está sendo executada ? (no servidor você colocou opcode 80 e no client 85) Pokeultion reagiu a isso 1 Link para o comentário Compartilhar em outros sites More sharing options...
Administrador PoRaI 99 Postado Junho 24, 2018 Administrador Share Postado Junho 24, 2018 (editado) Em 22/06/2018 em 15:59, Pokeultion disse: Agora que você falou, tentei colocar na função show(), mas nada acontece. Caso faça alguma diferença, olha o script.lua inteiro: Ocultar conteúdo function init() connect(g_game, { onGameEnd = onGameEnd }) taskWindow = g_ui.displayUI('tasks') taskWindow:hide() shopTabBar = taskWindow:getChildById('shopTabBar') shopTabBar:setContentWidget(taskWindow:getChildById('shopTabContent')) marketPanel = g_ui.loadUI('market') shopTabBar:addTab('Market', marketPanel, '/images/game/shop/market') taskButton = modules.client_topmenu.addRightGameButton('taskButton', tr('Tasks'), '/images/topbuttons/emerald_shop', toggle) taskButton:setWidth(36) end function terminate() disconnect(g_game, { onGameEnd = onGameEnd }) taskWindow:destroy() taskButton:destroy() end function onGameEnd() if taskWindow:isVisible() then taskWindow:hide() end end function show() taskWindow:show() taskWindow:raise() taskWindow:focus() addEvent(function() g_effects.fadeIn(taskWindow, 250) end) ProtocolGame.registerExtendedOpcode(85, tasksInfo) end function hide() addEvent(function() g_effects.fadeOut(taskWindow, 250) end) scheduleEvent(function() taskWindow:hide() end, 250) end function toggle() if taskWindow:isVisible() then hide() else show() end end function tasksInfo(protocol, opcode, buffer) local param = buffer:split('@') print(param[1]) print(param[2]) taskWindow:getChildById('labelPoke'):setText(param[1]) taskWindow:getChildById('labelQuant'):setText(param[2]) end Obrigado. É fora, não dentro de funções. taskWindow = nil ProtocolGame.registerExtendedOpcode(80, function(protocol, opcode, buffer) local param = buffer:split('@') print(param[1]) print(param[2]) taskWindow:getChildById('labelPoke'):setText(param[1]) taskWindow:getChildById('labelQuant'):setText(param[2]) end) function init() connect(g_game, { onGameEnd = onGameEnd }) taskWindow = g_ui.displayUI('tasks') taskWindow:hide() shopTabBar = taskWindow:getChildById('shopTabBar') shopTabBar:setContentWidget(taskWindow:getChildById('shopTabContent')) marketPanel = g_ui.loadUI('market') shopTabBar:addTab('Market', marketPanel, '/images/game/shop/market') taskButton = modules.client_topmenu.addRightGameButton('taskButton', tr('Tasks'), '/images/topbuttons/emerald_shop', toggle) taskButton:setWidth(36) end function terminate() disconnect(g_game, { onGameEnd = onGameEnd }) taskWindow:destroy() taskButton:destroy() end function onGameEnd() if taskWindow:isVisible() then taskWindow:hide() end end function show() taskWindow:show() taskWindow:raise() taskWindow:focus() addEvent(function() g_effects.fadeIn(taskWindow, 250) end) end function hide() addEvent(function() g_effects.fadeOut(taskWindow, 250) end) scheduleEvent(function() taskWindow:hide() end, 250) end function toggle() if taskWindow:isVisible() then hide() else show() end end Editado Junho 25, 2018 por PoRaI Link para o comentário Compartilhar em outros sites More sharing options...
Pokeultion 1 Postado Junho 25, 2018 Autor Share Postado Junho 25, 2018 (editado) 20 horas atrás, PostadorHunter disse: ja tentou printar alguma coisa pra ver se a função está sendo executada ? (no servidor você colocou opcode 80 e no client 85) Notei isso, já arrumei mas da na mesmsa jaisjsaije. Na function show() se eu printar a ProtocolGame.registerExtendedOpcode(255, tasksInfo) aparece isso: Spoiler ERROR: protected lua call failed: LUA ERROR: /gamelib/protocolgame.lua:43: Opcode is already taken. stack traceback: [C]: ? [C]: in function 'error' /gamelib/protocolgame.lua:43: in function 'registerExtendedOpcode' /game_tasks/tasks.lua:54: in function 'show' /game_tasks/tasks.lua:67: in function 'callback' /client_topmenu/topmenu.lua:31: in function </client_topmenu/topmenu.lua:29> OBS: Aparece isso independente do numero que eu coloque no opcode. 13 horas atrás, PoRaI disse: É fora, não dentro de funções. function tasksInfo(protocol, opcode, buffer) local param = buffer:split('@') print(param[1]) print(param[2]) taskWindow:getChildById('labelPoke'):setText(param[1]) taskWindow:getChildById('labelQuant'):setText(param[2]) end ProtocolGame.registerExtendedOpcode(80, tasksInfo) function init() connect(g_game, { onGameEnd = onGameEnd }) taskWindow = g_ui.displayUI('tasks') taskWindow:hide() shopTabBar = taskWindow:getChildById('shopTabBar') shopTabBar:setContentWidget(taskWindow:getChildById('shopTabContent')) marketPanel = g_ui.loadUI('market') shopTabBar:addTab('Market', marketPanel, '/images/game/shop/market') taskButton = modules.client_topmenu.addRightGameButton('taskButton', tr('Tasks'), '/images/topbuttons/emerald_shop', toggle) taskButton:setWidth(36) end function terminate() disconnect(g_game, { onGameEnd = onGameEnd }) taskWindow:destroy() taskButton:destroy() end function onGameEnd() if taskWindow:isVisible() then taskWindow:hide() end end function show() taskWindow:show() taskWindow:raise() taskWindow:focus() addEvent(function() g_effects.fadeIn(taskWindow, 250) end) end function hide() addEvent(function() g_effects.fadeOut(taskWindow, 250) end) scheduleEvent(function() taskWindow:hide() end, 250) end function toggle() if taskWindow:isVisible() then hide() else show() end end Nada Acontece. @TOPIC Tentei colocar isso dentro da function show() só pra testar, e nada acontece também: taskWindow:getChildById('labelPoke'):setText('texto') Label id: labelPoke !text: tr('Teste') estou usando o Label desse jeito, acho que essa parte n tem mt segredo Editado Junho 25, 2018 por Pokeultion Link para o comentário Compartilhar em outros sites More sharing options...
Administrador PoRaI 99 Postado Junho 25, 2018 Administrador Share Postado Junho 25, 2018 7 horas atrás, Pokeultion disse: Notei isso, já arrumei mas da na mesmsa jaisjsaije. Na function show() se eu printar a ProtocolGame.registerExtendedOpcode(255, tasksInfo) aparece isso: Mostrar conteúdo oculto ERROR: protected lua call failed: LUA ERROR: /gamelib/protocolgame.lua:43: Opcode is already taken. stack traceback: [C]: ? [C]: in function 'error' /gamelib/protocolgame.lua:43: in function 'registerExtendedOpcode' /game_tasks/tasks.lua:54: in function 'show' /game_tasks/tasks.lua:67: in function 'callback' /client_topmenu/topmenu.lua:31: in function </client_topmenu/topmenu.lua:29> OBS: Aparece isso independente do numero que eu coloque no opcode. Nada Acontece. @TOPIC Tentei colocar isso dentro da function show() só pra testar, e nada acontece também: taskWindow:getChildById('labelPoke'):setText('texto') Label id: labelPoke !text: tr('Teste') estou usando o Label desse jeito, acho que essa parte n tem mt segredo Tenta novamente, atualizei o código ali em cima. Se não der, provavelmente algo vc está fazendo algo de errado. Pokeultion reagiu a isso 1 Link para o comentário Compartilhar em outros sites More sharing options...
Pokeultion 1 Postado Junho 26, 2018 Autor Share Postado Junho 26, 2018 (editado) 17 horas atrás, PoRaI disse: Tenta novamente, atualizei o código ali em cima. Se não der, provavelmente algo vc está fazendo algo de errado. Agora sim, está retornando esse erro: ERROR: protected lua call failed: LUA ERROR: /game_tasks/tasks.lua:7: attempt to index a nil value stack traceback: [C]: ? /game_tasks/tasks.lua:7: in function 'callback' /gamelib/protocolgame.lua:17: in function </gamelib/protocolgame.lua:14> OBS: Os prints estão retornando O nome do pokémon e a quantidade. #EDIT: Dei uma saida, agora que voltei estava fazendo uns testes. Coloquei o taskWindow:getChildById('labelPoke'):setText(param[1]) em outro lugar de outra forma. Coloquei o seguinte dentro da função show(): taskWindow:getChildById('labelPoke'):setText('eoq') só pra testar. E gerou o mesmo erro: ERROR: protected lua call failed: LUA ERROR: /game_tasks/tasks.lua:44: attempt to index a nil value stack traceback: [C]: ? /game_tasks/tasks.lua:44: in function 'show' /game_tasks/tasks.lua:56: in function 'callback' /client_topmenu/topmenu.lua:31: in function </client_topmenu/topmenu.lua:29> Editado Junho 26, 2018 por Pokeultion Link para o comentário Compartilhar em outros sites More sharing options...
Administrador PoRaI 99 Postado Junho 26, 2018 Administrador Share Postado Junho 26, 2018 12 horas atrás, Pokeultion disse: Agora sim, está retornando esse erro: ERROR: protected lua call failed: LUA ERROR: /game_tasks/tasks.lua:7: attempt to index a nil value stack traceback: [C]: ? /game_tasks/tasks.lua:7: in function 'callback' /gamelib/protocolgame.lua:17: in function </gamelib/protocolgame.lua:14> OBS: Os prints estão retornando O nome do pokémon e a quantidade. #EDIT: Dei uma saida, agora que voltei estava fazendo uns testes. Coloquei o taskWindow:getChildById('labelPoke'):setText(param[1]) em outro lugar de outra forma. Coloquei o seguinte dentro da função show(): taskWindow:getChildById('labelPoke'):setText('eoq') só pra testar. E gerou o mesmo erro: ERROR: protected lua call failed: LUA ERROR: /game_tasks/tasks.lua:44: attempt to index a nil value stack traceback: [C]: ? /game_tasks/tasks.lua:44: in function 'show' /game_tasks/tasks.lua:56: in function 'callback' /client_topmenu/topmenu.lua:31: in function </client_topmenu/topmenu.lua:29> Provavelmente ele não está encontrando o labelPoke (retornando nil value) como filho da taskWindow, posta o arquivo .otui aí. Ou também você pode usar no lugar do getChildById a função: recursiveGetChildById. Só cuidado com conflito de ids, rs. taskWindow:recursiveGetChildById('labelPoke'):setText('eoq') Pokeultion reagiu a isso 1 Link para o comentário Compartilhar em outros sites More sharing options...
Pokeultion 1 Postado Junho 26, 2018 Autor Share Postado Junho 26, 2018 (editado) 1 hora atrás, PoRaI disse: Provavelmente ele não está encontrando o labelPoke (retornando nil value) como filho da taskWindow, posta o arquivo .otui aí. Ou também você pode usar no lugar do getChildById a função: recursiveGetChildById. Só cuidado com conflito de ids, rs. taskWindow:recursiveGetChildById('labelPoke'):setText('eoq') Sim, tava fuçando aqui ontem e consegui dessa forma: taskWindow:recursiveGetChildById('labelPoke'):setText(param[1]). A unica coisa que não está acontecendo é que ele não ta executando o opcode quando abre a janela não sei pq kk, mas isso acho que fuçando eu vejo aqui, fiz uma gambiarrinha de executar uma talk pra executar o opcode pra atualizar quando abrir a janela kk. poderia só me explicar por favor, qual a importancia e função de declarar no começo taskWindow = nil ? E se tem alguma diferença em fazer função separada ou fazer a função direto no opcode como vc fez, ou se era algo errado na minha função ? Obrigado Porai, ajudou muito mano. Obrigado Pela ajuda também PostadorHunter e Bananafight, me ajudaram mt também, obrigado pela atenção de todos! Fuçando aqui também já consegui fazer a task trocar automaticamente a cada determinado tempo, toda vez que abrir a janela caso não tenha passado o tempo, o player não podera trocar XD. Agora falta fazer a parte de "rank" das tasks, como rank a,b,c etc... poderia me dizer teoricamente como devo proceder ? pra ver se consigo aplicar a teoria na pratica aqui... Obrigado pessoal ❤️ Editado Junho 26, 2018 por Pokeultion Link para o comentário Compartilhar em outros sites More sharing options...
Administrador PoRaI 99 Postado Junho 26, 2018 Administrador Share Postado Junho 26, 2018 4 minutos atrás, Pokeultion disse: Sim, tava fuçando aqui ontem e consegui dessa forma: taskWindow:recursiveGetChildById('labelPoke'):setText(param[1]). A unica coisa que não está acontecendo é que ele não ta executando o opcode quando abre a janela não sei pq kk, mas isso acho que fuçando eu vejo aqui, fiz uma gambiarrinha de executar uma talk pra executar o opcode pra atualizar quando abrir a janela kk. poderia só me explicar por favor, qual a importancia e função de declarar no começo taskWindow = nil ? E se tem alguma diferença em fazer função separada ou fazer a função direto no opcode como vc fez, ou se era algo errado na minha função ? Obrigado Porai, ajudou muito mano. Obrigado Pela ajuda também PostadorHunter e Bananafight, me ajudaram mt também, obrigado pela atenção de todos! Fuçando aqui também já consegui fazer a task trocar automaticamente a cada determinado tempo, toda vez que abrir a janela caso não tenha passado o tempo, o player não podera trocar XD. Agora falta fazer a parte de "rank" das tasks, como rank a,b,c etc... poderia me dizer teoricamente como devo proceder ? pra ver se consigo aplicar a teoria na pratica aqui... Obrigado pessoal ❤️ Em Lua faço isso por padronização. Saber quais variáveis estou utilizando no módulo e caso eu queira iniciar com um valor diferente de nil, a declaração vai para todo o código. A única coisa que influenciaria mesmo era se você chamasse a variável como local. Sobre a função ser ou não separada, acredito que não tem problemas, rs. Deve ter sido problema a forma como você implementou. Uma das coisas erradas que notei foi inicializar o opcode TODAS as vezes que executasse o show, é super errado, afinal, você só taria inicializando os opcodes quando clicasse no SHOW e não receberia eles por isso nunca iria funcionar além de dar conflito de usar o mesmo opcode várias vezes. Você só inicializa o opcode uma vez, fora de outras chamadas. Ue, é relativo como o seu sistema de task funciona, kk. Eu fiz uma vez pra um servidor chamado World of Piece só que era uma gambiarra enorme, pq eu só reaproveitei um código de task que o servidor usava e já estava online e eu não tinha muita liberdade em melhorar. Lá o cliente envia uma mensagem pro servidor "pedindo" as informações da outra aba de task, fazendo as verificações se tá liberado ou não. Link para o comentário Compartilhar em outros sites More sharing options...
Pokeultion 1 Postado Junho 26, 2018 Autor Share Postado Junho 26, 2018 (editado) 24 minutos atrás, PoRaI disse: Em Lua faço isso por padronização. Saber quais variáveis estou utilizando no módulo e caso eu queira iniciar com um valor diferente de nil, a declaração vai para todo o código. A única coisa que influenciaria mesmo era se você chamasse a variável como local. Sobre a função ser ou não separada, acredito que não tem problemas, rs. Deve ter sido problema a forma como você implementou. Uma das coisas erradas que notei foi inicializar o opcode TODAS as vezes que executasse o show, é super errado, afinal, você só taria inicializando os opcodes quando clicasse no SHOW e não receberia eles por isso nunca iria funcionar além de dar conflito de usar o mesmo opcode várias vezes. Você só inicializa o opcode uma vez, fora de outras chamadas. Ue, é relativo como o seu sistema de task funciona, kk. Eu fiz uma vez pra um servidor chamado World of Piece só que era uma gambiarra enorme, pq eu só reaproveitei um código de task que o servidor usava e já estava online e eu não tinha muita liberdade em melhorar. Lá o cliente envia uma mensagem pro servidor "pedindo" as informações da outra aba de task, fazendo as verificações se tá liberado ou não. Acho que vou fazer o opcode retornar a permissão se o player pode ou não abrir a proxima aba de task, se não puder manda uma viso se puder abre a aproxima janela. Acho que ai não tem segredo. Então acho que temos um problema kkkk como eu disse, não estava executando direito. Oque eu fiz foi criar uma talkaction executando a função e no client coloquei um g_game.talk('talk') que executa o opcode pra poder atualizar toda vez que abre a janela, no caso do mesmo jeito eu to chamando o opcode toda vez que abre a janela, pq coloquei o game.talk na function show() pra executar toda vez que abrir e atualizar a task asjeiajisej, pq será que sozinho ele n manda a informação automaticamente já ? No caso, o código todo ficou assim: Spoiler taskWindow = nil ProtocolGame.registerExtendedOpcode(255, function(protocol, opcode, buffer) local param = buffer:split('@') print(param[1]) print(param[2]) taskWindow:recursiveGetChildById('labelPoke'):setText(param[1]) --taskWindow:recursiveGetChildById('labelPoke'):setImageSource('/game_tasks/pokes/'..param[1]) end) function init() connect(g_game, { onGameEnd = onGameEnd }) taskWindow = g_ui.displayUI('tasks') taskWindow:hide() shopTabBar = taskWindow:getChildById('shopTabBar') shopTabBar:setContentWidget(taskWindow:getChildById('shopTabContent')) marketPanel = g_ui.loadUI('market') shopTabBar:addTab('Market', marketPanel, '/images/game/shop/market') taskButton = modules.client_topmenu.addRightGameButton('taskButton', tr('Tasks'), '/images/topbuttons/emerald_shop', toggle) taskButton:setWidth(36) end function terminate() disconnect(g_game, { onGameEnd = onGameEnd }) taskWindow:destroy() taskButton:destroy() end function onGameEnd() if taskWindow:isVisible() then taskWindow:hide() end end function show() taskWindow:show() taskWindow:raise() taskWindow:focus() addEvent(function() g_effects.fadeIn(taskWindow, 250) end) --g_game.talk('tst') end function hide() addEvent(function() g_effects.fadeOut(taskWindow, 250) end) scheduleEvent(function() taskWindow:hide() end, 250) end function toggle() if taskWindow:isVisible() then hide() else show() end end Desse jeito ai nem os prints mostram quando eu abro a janela, agora se eu deixar executando a talk que executa o opcode ai funciona, mas como vc disse é errado, pois está chamando o opcode toda vez que abre a janela. #EDIT Estava aqui pensando... pra fazer esse código eu tava olhando como base o do npcDialog de um server ai... e no caso, tem alguma coisa no servidor que "ativa" esse opcode, que no caso é o npc. Sempre que vc fala com o npc o npc executa a função que ta na lib executando o opcode pelo servidor pode ser que o erro esteja ai, e também o motivo de só funcionar se eu executar a função dentro do servidor pra mandar o opcode, então provavelmente o problema ta no meu código lua do servidor, vou continuar dando uma olhada aqui Editado Junho 26, 2018 por Pokeultion Link para o comentário Compartilhar em outros sites More sharing options...
Posts Recomendados