Atividades
- Hoje
-
khramers se registrou na comunidade
- Ontem
-
Gabisvaldo se registrou na comunidade
-
gucms se registrou na comunidade
-
leodtrn se registrou na comunidade
-
onder se registrou na comunidade
-
conexaodobiu se registrou na comunidade
-
du dete se registrou na comunidade
-
xupinha se registrou na comunidade
- Última semana
-
Nortino se registrou na comunidade
-
Dkingsito se registrou na comunidade
-
-
-
Formação de equipe global 15+
🚀 RECRUTAMENTO OFICIAL — PROJETO TIBIA GLOBAL 15.30🎮 Estamos construindo um novo projeto e queremos você nessa jornada!Estou em busca de pessoas comprometidas, com visão de futuro e vontade de crescer junto com um projeto de Tibia inspirado na experiência Global 15.30.A ideia é reunir pessoas com diferentes habilidades, experiências e ideias para construir um projeto sólido, organizado e com potencial de crescimento.🤝 Estamos procurando pessoas para diversas áreas:💰 Sócios e investidores — pessoas interessadas em investir no projeto, participar do desenvolvimento do negócio e crescer junto com a equipe.📢 Divulgação e marketing — pessoas que entendam de divulgação, redes sociais, criação de conteúdo, parcerias com criadores e estratégias para atrair jogadores.🛡️ Suporte in-game — pessoas responsáveis, com boa comunicação e disponibilidade para auxiliar jogadores, esclarecer dúvidas e ajudar na organização da comunidade.⚙️ Desenvolvimento e área técnica — profissionais ou entusiastas com conhecimentos em servidores, scripts, programação, configuração e manutenção.🎨 Design e criação de conteúdo — pessoas com habilidades em artes, banners, vídeos, identidade visual e materiais de divulgação.👥 Organização e gestão da comunidade — pessoas interessadas em ajudar a administrar a equipe, organizar eventos e manter uma comunidade ativa e saudável.💡 Tem outra habilidade ou uma ideia que possa contribuir? Também queremos conversar com você!🔥 QUEM PROCURAMOS?Pessoas comprometidas, transparentes, com iniciativa e que entendam que um projeto de qualidade é construído em equipe. Não buscamos apenas pessoas para preencher vagas, mas parceiros que queiram contribuir com ideias, trabalho e crescimento.📩 TEM INTERESSE EM FAZER PARTE?Entre em contato comigo pelo privado e informe:- Seu nome ou nick;- A área em que gostaria de atuar;- Suas experiências e habilidades;- Se tem interesse em parceria, sociedade, investimento ou colaboração.Vamos conversar, alinhar ideias e avaliar como podemos construir algo grande juntos!⚔️ CRIANDO TIBIA BR — Mais do que um servidor, um projeto construído por pessoas que compartilham a mesma paixão pelo Tibia.Interessados em sociedade ou investimento terão a oportunidade de conversar diretamente comigo sobre as possibilidades de parceria e os próximos passos do projeto.https://chat.whatsapp.com/BTeLtU6eDvcDDkmKIMmvXC?s=cl&p=a&mlu=4&ilr=4
-
Quero contratar o serviço de um DEV para trabalhar em um projeto de tibia OT
🚀 OFFICIAL RECRUITMENT — GLOBAL TIBIA PROJECT 15.30 🎮 We are building a brand new project and we want you on this journey! We are looking for committed individuals with a forward-thinking mindset to grow alongside a high-quality Tibia project inspired by the Global 15.30 experience. Our goal is to gather diverse talents to build a solid, organized, and scalable server. 🤝 We are currently looking for partners in the following areas: 💰 Partners & Investors: People interested in funding the project, participating in business development, and sharing future profits. ⚙️ Development & Tech Team: Professionals or enthusiasts with solid knowledge in server management, Lua scripting, C++ programming, website configuration (AAC), and general maintenance. 📢 Marketing & Promotion: People who understand social media growth, content creation, streamer partnerships, and strategies to attract players. 🎨 Design & Content Creation: Talented individuals capable of creating graphics, banners, videos, visual identity, and promotional materials. 🛡️ In-Game Support & Staff: Responsible people with good communication skills to assist players, answer questions, and help moderate the community. 👥 Community Management: People interested in helping manage the team, organizing events, and keeping the community active and healthy. 💡 Do you have another skill or an innovative idea that could contribute? We still want to talk to you! 🔥 WHO ARE WE LOOKING FOR? Transparent, proactive, and committed people who understand that a premium project is built through teamwork. We are not just filling slots; we are looking for long-term partners. 📩 HOW TO APPLY? Send me a PM (Private Message) here on OTLand or join our group directly with the following info: Your name or nickname The area you want to apply for Your previous experience and skills Your expectations (Partnership, Equity/Society, Investment, or Collaboration) 💬 Join our WhatsApp Group directly: 👉 https://chat.whatsapp.com/BTeLtU6eDvcDDkmKIMmvXC?s=cl&p=a&mlu=4&ilr=4 ⚔️ CRIANDO TIBIA BR — More than just a server, a project built by people who share the same passion for Tibia.
-
🔥 RECRUTAMENTO ABERTO | FAÇA PARTE DA NOSSA EQUIPE
🚀 OFFICIAL RECRUITMENT — GLOBAL TIBIA PROJECT 15.30 🎮 We are building a brand new project and we want you on this journey! We are looking for committed individuals with a forward-thinking mindset to grow alongside a high-quality Tibia project inspired by the Global 15.30 experience. Our goal is to gather diverse talents to build a solid, organized, and scalable server. 🤝 We are currently looking for partners in the following areas: 💰 Partners & Investors: People interested in funding the project, participating in business development, and sharing future profits. ⚙️ Development & Tech Team: Professionals or enthusiasts with solid knowledge in server management, Lua scripting, C++ programming, website configuration (AAC), and general maintenance. 📢 Marketing & Promotion: People who understand social media growth, content creation, streamer partnerships, and strategies to attract players. 🎨 Design & Content Creation: Talented individuals capable of creating graphics, banners, videos, visual identity, and promotional materials. 🛡️ In-Game Support & Staff: Responsible people with good communication skills to assist players, answer questions, and help moderate the community. 👥 Community Management: People interested in helping manage the team, organizing events, and keeping the community active and healthy. 💡 Do you have another skill or an innovative idea that could contribute? We still want to talk to you! 🔥 WHO ARE WE LOOKING FOR? Transparent, proactive, and committed people who understand that a premium project is built through teamwork. We are not just filling slots; we are looking for long-term partners. 📩 HOW TO APPLY? Send me a PM (Private Message) here on OTLand or join our group directly with the following info: Your name or nickname The area you want to apply for Your previous experience and skills Your expectations (Partnership, Equity/Society, Investment, or Collaboration) 💬 Join our WhatsApp Group directly: 👉 https://chat.whatsapp.com/BTeLtU6eDvcDDkmKIMmvXC?s=cl&p=a&mlu=4&ilr=4 ⚔️ CRIANDO TIBIA BR — More than just a server, a project built by people who share the same passion for Tibia.
-
RECRUTAMENTO TIME SERVIDOR GLOBAL
🚀 RECRUTAMENTO OFICIAL — PROJETO TIBIA GLOBAL 15.30 🎮 Estamos construindo um novo projeto e queremos você nessa jornada! Estou em busca de pessoas comprometidas, com visão de futuro e vontade de crescer junto com um projeto de Tibia inspirado na experiência Global 15.30. A ideia é reunir pessoas com diferentes habilidades, experiências e ideias para construir um projeto sólido, organizado e com potencial de crescimento. 🤝 Estamos procurando pessoas para diversas áreas: 💰 Sócios e investidores — pessoas interessadas em investir no projeto, participar do desenvolvimento do negócio e crescer junto com a equipe. 📢 Divulgação e marketing — pessoas que entendam de divulgação, redes sociais, criação de conteúdo, parcerias com criadores e estratégias para atrair jogadores. 🛡️ Suporte in-game — pessoas responsáveis, com boa comunicação e disponibilidade para auxiliar jogadores, esclarecer dúvidas e ajudar na organização da comunidade. ⚙️ Desenvolvimento e área técnica — profissionais ou entusiastas com conhecimentos em servidores, scripts, programação, configuração e manutenção. 🎨 Design e criação de conteúdo — pessoas com habilidades em artes, banners, vídeos, identidade visual e materiais de divulgação. 👥 Organização e gestão da comunidade — pessoas interessadas em ajudar a administrar a equipe, organizar eventos e manter uma comunidade ativa e saudável. 💡 Tem outra habilidade ou uma ideia que possa contribuir? Também queremos conversar com você! 🔥 QUEM PROCURAMOS? Pessoas comprometidas, transparentes, com iniciativa e que entendam que um projeto de qualidade é construído em equipe. Não buscamos apenas pessoas para preencher vagas, mas parceiros que queiram contribuir com ideias, trabalho e crescimento. 📩 TEM INTERESSE EM FAZER PARTE? Entre em contato comigo pelo privado e informe: - Seu nome ou nick; - A área em que gostaria de atuar; - Suas experiências e habilidades; - Se tem interesse em parceria, sociedade, investimento ou colaboração. Vamos conversar, alinhar ideias e avaliar como podemos construir algo grande juntos! ⚔️ CRIANDO TIBIA BR — Mais do que um servidor, um projeto construído por pessoas que compartilham a mesma paixão pelo Tibia. Interessados em sociedade ou investimento terão a oportunidade de conversar diretamente comigo sobre as possibilidades de parceria e os próximos passos do projeto. https://chat.whatsapp.com/BTeLtU6eDvcDDkmKIMmvXC?s=cl&p=a&mlu=4&ilr=4
-
kauan16 começou a seguir map tracker
-
map tracker
Salvee rapaziada, estou em busca de um MAPTRACKER para versão mais atual do tibia, estou tentando modificar o codigo fonte do sharpmaptracker mas ainda esta enroscando em algumas coisas, alguém conheça algum que já funcione normalmente?
-
-
Felipe Peixoto alterou sua foto pessoal
-
-
ArielZeRah alterou sua foto pessoal
- Canary EditRL Map By Arquiteto Tibiano *15x Summer Update 2025*
- Anteriormente
-
mabeco1980 começou a seguir xWhiteWolf
-
-
Underewar começou a seguir DrenoxBot | Tibia Bot | Rubinot Bot | OTC Bot | Cipsoft Bot
-
DrenoxBot | Tibia Bot | Rubinot Bot | OTC Bot | Cipsoft Bot
Quero apresentar o DrenoxBot, um bot para Tibia com a interface dentro do próprio cliente. Você não precisa de janela externa nem de navegador aberto. O que tem de diferente Wiki no cliente: monstros, itens, NPCs, quests e mapa com a sua posição, usando os sprites do próprio jogo. Hunt Finder: 131 hunts filtradas por level e vocação, com xp/h e loot/h. Um botão configura targeting, shooter, healing e equipment para a hunt. Set Finder: o set certo para o seu level e elemento, slot por slot. Market Finder: preço de compra, preço de venda e preço do NPC sem abrir o market. Filtra pelo que está no seu depot. Items & Char: depot, stash e inbox numa busca só. Você retira o item direto para a bag. O básico, bem feito Healing por prioridade, respeitando o cooldown real das magias Targeting e Shooter com condições de mana, número de criaturas e alvo CaveBot com biblioteca de rotas, gravação andando ou desenho no mapa, refill e venda Rotas .cb e scripts Lua no formato ZeroBot rodam sem adaptação API Lua própria, com eventos, timers e HUD Painel no site: acompanhe o personagem pelo celular e pause ou ajuste o bot de longe Compatibilidade OTs com o cliente da CipSoft, versão 15.23 ou mais nova. O setup detecta a versão sozinho. Preço Pro a partir de R$ 11,69/mês no plano anual. Paga com PIX, cartão ou boleto, e a licença libera na hora. Teste grátis: toda conta nova ganha 3 dias de Pro. Suporte e comunidade Temos fórum próprio, com uma comunidade para cada OT detectado. Lá ficam suporte, avisos de atualização e scripts compartilhados. Site: drenoxbot.com Fórum: drenoxbot.com/comunidade Dúvidas? Pode responder aqui no tópico!
-
-
[Show Off] Forja sem RNG: upgrade que nunca falha e nunca quebra o item (Eternal Odyssey: Redemption)
A Forja que não quebra seu item No sistema antigo de upgrade tinha porcentagem de sucesso, contador de pena e tudo mais. Você clicava, rolava o dado, e a coisa mais interessante do sistema era o cara ou coroa. Isso acabou. Como funciona agora A raridade do item compra um "pool" de ranks: Rare tem 10, Epic tem 15, Legendary tem 20. Cada atributo rolado no item tem seu próprio rank, de 0 a 10, e cada rank tem um custo em gold e em cristais que você vê antes de gastar qualquer coisa. Os tamanhos não são aleatórios: Rare rola 1 atributo, então 10 ranks maximizam ele. Epic rola 2: 15 ranks maximizam um e levam o outro até a metade. Legendary rola 3: 20 ranks maximizam exatamente dois. Ou seja, um Legendary não é "o mesmo item, só que melhor": é uma decisão de quais dois dos três atributos você vai levar ao máximo. O custo Custo do rank n = unidade x 1,30^(n-1) Unidade por tier do item: 600 / 9.200 / 64.300 / 108.900 / 205.300 gold Cristais por rank: 1 / 1 / 2 / 2 / 3 (os cristais vêm das dungeons do mesmo tier) Não existe multiplicador por raridade no gold: a raridade já comprou mais atributos, cobrar de novo no preço seria cobrar duas vezes pela mesma coisa. A unidade de cada tier foi calibrada com o gold por hora medido em sessões reais de hunt, para que maximizar um Legendary custe um número de horas pensado, que sobe com o tier (de ~8 horas no tier 1 até ~35 no tier 5). A única aposta que sobrou O Overcharge leva um atributo que já está no rank 10 para 11, 12 ou 13, com 70%, 50% e 30% de chance. Custa Stabilizing Cores e gold. Se falhar, você perde só esses materiais: não perde rank, não perde o atributo, não perde o item. Não existe nenhum estado na Forja que destrua algo seu. Por quê Upgrade que destrói o item não é dificuldade, é um imposto sobre quem não pode ter um item reserva. A jogada certa vira "não toque nesse sistema até ficar rico", que é o contrário do que um sistema de upgrade deveria fazer. Com custo determinístico, você planeja a subida em vez de rezar. Isso faz parte do Eternal Odyssey: Redemption, um servidor custom RPG em cima do mapa clássico do Tibia. O Open Alpha está aberto agora e o lançamento é em 23/10 às 13:00 (horário de Brasília). Fica a pergunta para quem desenvolve: 70/50/30 nos ranks 11 a 13 é o formato certo, ou o último rank deveria ser mais raro e bater mais forte?
-
[PokéTibia / OTClient] Fly com sombra e botões de subir/descer — source + Lua
modules https://www.mediafire.com/file/11jl3ug04rp091p/Fly-Com-Sombra.zip/file
-
Zyzz Eternal Odyssey alterou sua foto pessoal
-
[PokéTibia / TFS 0.3.6] Nurse Joy com janela — Curar, Registrar e Fechar
Download: Nurse-Joy.zip (MediaFire)Nurse Joy com janela: Curar, Registrar e Fechar — PokéTibia / TFS 0.3.6Compartilhando a Nurse Joy da minha base com dialogo no OTClient. A janela mostra o nome e outfit da Nurse, mensagem e botoes Curar/Registrar/Fechar. Cura o treinador, Pokemon solto quando permitido, Ball do slot 8 e Balls da mochila; restaura HP, cooldowns move1..move15, felicidade e fome conforme a configuracao da base. O registro libera uma cidade no sistema de Teleport existente. Nao implementa o Teleport completo. E uma aplicacao do sistema de dialogo por clique esquerdo que compartilhei antes. O pacote abaixo inclui os arquivos das duas pontas, para nao depender de baixar outro topico. Edicao publica adaptada: JSON no transporte, registro explicitamente configurado no XML e verificacao de mochila valida. A base em uso nao foi alterada. A imagem de demonstracao corresponde a base original; na edicao publica a fonte usa verdana-11px-rounded e pode mudar ligeiramente a aparencia. O fundo window.png do modulo foi mantido. DEPENDENCIAS: OTClient com extended opcodes, json.decode do corelib, UICreature, estilos Button/Label/ScrollablePanel e fonte verdana-11px-rounded. TFS 0.3.6 / PokexGeneration com NpcSystem, FocusModule, doSendPlayerExtendedOpcode e os helpers/tabelas da sua base. Nao funciona somente copiando heal.lua num TFS puro. Servidor: copie os arquivos server/data para as mesmas pastas de data. A biblioteca npcdialog_lib.lua deve carregar tambem no ambiente dos NPCs. Nurse.xml aponta para heal.lua; se sua Nurse tem outro XML, preserve seu look/nome e altere apenas script e parametros. Configure/coloque a Nurse no mapa/spawn como de costume. O lookType 532 pertence a esta base; use um ID valido no seu DAT. Faça backup antes de substituir heal.lua: todas as Nurses que o usam receberao a mudanca. Registro de cidade: ajuste no XML <parameter key="teleportStorage" value="0"/>. Zero deixa o registro desativado. Use a storage que seu menu de Teleport realmente consulta para aquela cidade; exemplo: 897530 SOMENTE se seu Teleport usa esse numero. Registrar grava 1 nessa storage; nao teleporta, nao muda automaticamente townId e nao adiciona destinos ao menu. Nurses de cidades diferentes devem usar storages diferentes. Na edicao publica, Curar nao cadastra cidade automaticamente. Coordenadas particulares e a busca automatica do templo mais proximo foram retiradas para evitar registrar cidade errada em outro mapa. Cliente: copie os arquivos client/modules/game_npcdialog para modules/game_npcdialog e carregue o modulo depois de corelib/game_interface. Se ja instalou a edicao JSON do meu topico anterior, atualize somente o OTUI/fundo para esta aparencia e use os scripts Nurse do servidor; nao registre o opcode duas vezes. Nao misture o servidor JSON com cliente antigo que usa loadstring/table.serialize. Clique esquerdo: o bloco client/clique_esquerdo.lua vai DENTRO de processMouseAction em game_interface/gameinterface.lua, logo depois de local keyboardModifiers = g_keyboard.getModifiers(). Preserve o restante do arquivo. Ele manda hi quando o clique esquerdo sem modificadores identifica um NPC. NpcSystem cuida do foco/distancia; com dois NPCs juntos o hi pode escolher outro NPC proximo. Use classificacao isNpc correta no protocolo. O jogador tambem pode cumprimentar pela fala. Opcode 80 reservado ao dialogo servidor->cliente: se ja usado nessa direcao, altere nas duas pontas. O modulo fecha ao andar, sair do jogo ou pressionar Escape. Fechar libera o foco no servidor. Botoes usam hifen como separador; nao use hifen dentro do nome de uma opcao. Configuracao de cura: a base precisa definir nurseHealsOnlyInPZ, nurseHealsPokemonOut, baseNurseryHappiness, baseNurseryHunger e pokeballs (entradas all/on). Tambem usa exhaustion.get/set, isPokeball, getPokeballsInContainer, setCD, doCureStatus e opcionalmente doUpdateMoves quando useKpdoDlls=true. Flags false/nil desativam suas respectivas exigencias, mas fome/felicidade precisam de valores numericos. Nao sobrescreva configuration.lua inteira. Exaustao: storage 9211 por 5 segundos; duelo: storage 52480; Fly/Ride/Surf: 17000/17001/63215. Confira conflitos. O HP da Ball e fracao: hp=1 significa cheia. IDs on das Balls precisam ser os seus. Outros atributos como boost, level, held e nick nao sao zerados por este script. Validacao: Lua 5.1/XML e testes simulados de foco, abrir/voltar/fechar, registrar/repetir/desativado, bloqueio em duelo/PZ/exaustao, Pokemon solto proibido, cura de treinador/slot/mochila e mochila ausente. O transporte JSON e clique foram verificados no pacote anterior. Nao foi feito novo teste visual/end-to-end desta edicao no cliente, nem teste de todas as combinacoes de Balls. Teste em copia da base antes de producao. Creditos: modulo original game_npcdialog identificado como Gengo, modificado por Biel; OTClient team e autores do fork; autores do NpcSystem e do sistema de cura/PokéTibia preexistente. Raul compartilha sua integracao, organizada com auxilio do Codex. Nao reivindico autoria de todos os componentes. Nao acompanha executavel, cliente completo, sprites, banco ou mapa. Arquivos completos abaixo. Salve cada bloco no caminho indicado. client/clique_esquerdo.lua -- OTPokemon-style NPC interaction: a plain left click greets the NPC and -- lets the server open the dialog window through the NPC dialog opcode. local clickedNpc = nil if creatureThing and creatureThing:isNpc() then clickedNpc = creatureThing elseif attackCreature and attackCreature:isNpc() then clickedNpc = attackCreature elseif lookThing and lookThing:isCreature() and lookThing:isNpc() then clickedNpc = lookThing end if mouseButton == MouseLeftButton and keyboardModifiers == KeyboardNoModifier and clickedNpc then local player = g_game.getLocalPlayer() if player then player:stopAutoWalk() end g_game.cancelAttack() g_game.talkChannel(MessageModes.NpcTo, 0, 'hi') return true end client/modules/game_npcdialog/npcdialog.lua-- ui widgets local windowDialog local buttonHolder local labelTitle local outfitBox local panelMessage local scrollPanel local labelMessage -- variables local OpcodeDialog = 80 local Actions = { open = 1, closed = 2 } function init() connect(g_game, { onGameEnd = closeDialog }) connect(LocalPlayer, { onPositionChange = onPositionChange }) ProtocolGame.registerExtendedOpcode(OpcodeDialog, function(protocol, opcode, buffer) if type(buffer) ~= 'string' or #buffer > 60000 then return end local ok, result = pcall(json.decode, buffer) if not ok or type(result) ~= 'table' then return end if result.action == Actions.closed then closeDialog() elseif result.action == Actions.open and type(result.data) == 'table' then local data = result.data if type(data.npcId) == 'number' and type(data.message) == 'string' and (data.options == nil or type(data.options) == 'string') then createDialog(data) end end end) windowDialog = g_ui.displayUI('npcdialog') buttonHolder = windowDialog:getChildById('buttonHolder') labelTitle = windowDialog:getChildById('labelTitle') scrollPanel = windowDialog:getChildById('scrollPanel') panelMessage = windowDialog:getChildById('panelMessage') outfitBox = windowDialog:getChildById('outfitBox') labelMessage = g_ui.createWidget('LabelText', panelMessage) end function terminate() disconnect(g_game, { onGameEnd = closeDialog }) disconnect(LocalPlayer, { onPositionChange = onPositionChange }) ProtocolGame.unregisterExtendedOpcode(OpcodeDialog) windowDialog:destroy() end function closeDialog() windowDialog:hide() end function onPositionChange(creature, newPos, oldPos) if creature:isLocalPlayer() then windowDialog:hide() end end function openDialog() windowDialog:raise() windowDialog:show() end function createDialog(value) local Npc = g_map.getCreatureById(value.npcId) if not Npc then return error("game_npcdialog/npcdialog.lua: NPC nao encontrado no mapa visivel.") end labelTitle:setText(Npc:getName()) outfitBox:setOutfit(Npc:getOutfit()) labelMessage:clearText() labelMessage:setText(value.message) -- Evita erro se o limitText não estiver configurado no .otui local limit = panelMessage.limitText or 100 scrollPanel:setVisible(labelMessage:getTextSize().height > limit) buttonHolder:destroyChildren() if value.options and value.options ~= '' then -- Divide os botões pelo caractere '-' vindo do script do NPC local options = {} for option in value.options:gmatch('[^-]+') do table.insert(options, option) end for i = 1, #options do local button = g_ui.createWidget('OptionButton', buttonHolder) button:setText(tr(options[i])) button.onClick = function() g_game.talkChannel(MessageModes.NpcTo, 0, options[i]) end end buttonHolder:setHeight(#options > 6 and 48 or 25) end openDialog() end client/modules/game_npcdialog/npcdialog.otmodModule name: game_npcdialog description: Game NpcDialog author: Gengo Modificado por Biel scripts: [ npcdialog ] sandboxed: true autoload: true autoload-priority: 1001 @onLoad: init() @onUnload: terminate() client/modules/game_npcdialog/npcdialog.otuiLabelText < Label padding-bottom: 5 font: verdana-11px-rounded color: #FFFFFF text-wrap: true text-auto-resize: true OptionButton < Button margin: 3 0 0 2 width: 80 color: #FFFFFF UIWindow size: 620 231 visible: false image-source: window image-border: 12 anchors.centerIn: parent @onEscape: modules.game_npcdialog.closeDialog() Label id: labelTitle font: verdana-11px-rounded anchors.top: parent.top anchors.left: parent.left !text: tr('Title') margin: 18 0 5 25 color: #FFFFFF text-auto-resize: true UICreature id: outfitBox size: 75 75 anchors.top: prev.bottom anchors.left: parent.left margin: 20 0 5 34 VerticalScrollBar id: scrollPanel height: 65 anchors.top: panelMessage.top anchors.left: panelMessage.right anchors.bottom: panelMessage.bottom margin-left: 5 visible: false pixels-scroll: true step: 14 ScrollablePanel id: panelMessage size: 0 120 anchors.top: labelTitle.bottom anchors.left: outfitBox.right anchors.right: parent.right margin: 8 30 10 25 vertical-scrollbar: scrollPanel layout: verticalBox &limitText: 80 ScrollablePanel id: buttonHolder size: 0 24 anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right margin: 15 10 8 10 layout: type: grid cell-size: 99 22 flow: trueserver/data/lib/npcdialog_lib.lua-- Public JSON variant. Use the matching client module; old Lua-table payloads differ. local OpcodeDialog = 80 local function quote(value) return '"' .. value:gsub('[%z\1-\31\\"]', function(c) if c == '"' then return '\\"' end if c == '\\' then return '\\\\' end return string.format('\\u%04x', string.byte(c)) end) .. '"' end function doSendDialogNpc(cid, npc, msg, opc) if type(npc) ~= 'number' or type(msg) ~= 'string' then return false end local buffer = '{"action":1,"data":{"npcId":' .. tostring(npc) .. ',"message":' .. quote(msg) .. ',"options":' .. quote(opc or '') .. '}}' return doSendPlayerExtendedOpcode(cid, OpcodeDialog, buffer) end function doSendDialogNpcClose(cid) return doSendPlayerExtendedOpcode(cid, OpcodeDialog, '{"action":2}') end server/data/npc/Nurse.xml<?xml version="1.0" encoding="UTF-8"?> <npc name="Nurse Joy" script="heal.lua" walkinterval="350000" floorchange="0" speed="0"> <health now="150" max="150"/> <look type="532" head="91" body="102" legs="83" feet="0"/> <parameters> <!-- 0 disables registration. Set your Teleport destination storage. --> <parameter key="teleportStorage" value="0"/> <!-- As mensagens foram movidas para o script em Lua para o sistema de dialogo funcionar corretamente --> <parameter key="message_idletimeout" value="Ate mais treinador!"/> <parameter key="message_walkaway" value="Ate mais treinador!"/> </parameters> </npc> server/data/npc/scripts/heal.lua-- Public adaptation: explicit teleportStorage per NPC; no private map coordinates. local keywordHandler = KeywordHandler:new() local npcHandler = NpcHandler:new(keywordHandler) NpcSystem.parseParameters(npcHandler) local talkState = {} function onThingMove(creature, thing, oldpos, oldstackpos) end function onCreatureAppear(creature) npcHandler:onCreatureAppear(creature) end function onCreatureDisappear(cid) if isPlayer(cid) then doSendDialogNpcClose(cid) end npcHandler:onCreatureDisappear(cid) end function onCreatureTurn(creature) end function msgcontains(txt, str) return (string.find(txt, str) and not string.find(txt, '(%w+)' .. str) and not string.find(txt, str .. '(%w+)')) end function onCreatureSay(cid, type, msg) npcHandler:onCreatureSay(cid, type, msg:lower()) end function onThink() npcHandler:onThink() end function greetCallback(cid) doSendDialogNpc(cid, getNpcId(), "Ola treinador! Bem-vindo ao Centro Pokemon.\nComo posso ajudar voce e seus Pokemons hoje?", "Curar-Registrar-Fechar") return true end function creatureSayCallback(cid, type, msg) if(not npcHandler:isFocused(cid)) then return false end local msg = string.lower(msg) local talkUser = NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT and 0 or cid for a, b in pairs(gobackmsgs or {}) do local gm = string.gsub(b.go, "doka!", "") local bm = string.gsub(b.back, "doka!", "") if string.find(string.lower(msg), string.lower(gm)) or string.find(string.lower(msg), string.lower(bm)) then return true end end -- REGISTRAR CIDADE PARA O SISTEMA DE TELEPORT if msgcontains(msg, 'registrar') or msgcontains(msg, 'registra') then local registeredStorage = tonumber(getNpcParameter("teleportStorage")) if registeredStorage and (registeredStorage <= 0 or registeredStorage ~= math.floor(registeredStorage)) then registeredStorage = nil end if not registeredStorage then doSendDialogNpc(cid, getNpcId(), "Esta Nurse ainda nao possui uma cidade configurada para o Teleport.", "Voltar-Fechar") return true end if getPlayerStorageValue(cid, registeredStorage) >= 1 then doSendDialogNpc(cid, getNpcId(), "Esta cidade ja esta registrada no seu Teleport!", "Curar-Fechar") return true end setPlayerStorageValue(cid, registeredStorage, 1) doSendMagicEffect(getThingPos(cid), CONST_ME_MAGIC_GREEN) doSendDialogNpc(cid, getNpcId(), "Cidade registrada com sucesso! Agora voce pode voltar para ca usando um Pokemon com Teleport.", "Curar-Fechar") return true end -- 1. GATILHO: CLICOU EM CURAR OU FALOU "HEAL/HELP/CURAR" if msgcontains(msg, 'curar') or msgcontains(msg, 'heal') or msgcontains(msg, 'help') then if exhaustion.get(cid, 9211) then selfSay('Por favor, aguarde alguns instantes antes de pedir para curar seus pokemons novamente!', cid) return true end if not getTileInfo(getThingPos(cid)).protection and nurseHealsOnlyInPZ then selfSay("Por favor, entre no centro pokemon para curar seus pokemons!", cid) return true end if getPlayerStorageValue(cid, 52480) >= 1 then selfSay("Voce nao pode fazer isso enquanto estiver em um Duelo!", cid) return true end -- Reject before applying healing/exhaustion when summons must be recalled. if #getCreatureSummons(cid) >= 1 and not nurseHealsPokemonOut then selfSay("Por favor, coloque seu pokemon de volta na bola!", cid) return true end -- Aplica a exaustao e cura o treinador exhaustion.set(cid, 9211, 5) doCreatureAddHealth(cid, getCreatureMaxHealth(cid)-getCreatureHealth(cid)) doCureStatus(cid, "all", true) doSendMagicEffect(getThingPos(cid), 14) local mypb = getPlayerSlotItem(cid, 8) -- Cura Pokemon para fora da bola if #getCreatureSummons(cid) >= 1 then if not nurseHealsPokemonOut then selfSay("Por favor, coloque seu pokemon de volta na bola!", cid) return true end local s = getCreatureSummons(cid)[1] doCreatureAddHealth(s, getCreatureMaxHealth(s)) doSendMagicEffect(getThingPos(s), 14) doCureStatus(s, "all", false) if getPlayerStorageValue(s, 1008) < baseNurseryHappiness then setPlayerStorageValue(s, 1008, baseNurseryHappiness) end if getPlayerStorageValue(s, 1009) > baseNurseryHunger then setPlayerStorageValue(s, 1009, baseNurseryHunger) end else -- Cura o slot principal (Slot 8) if mypb and mypb.uid > 0 and mypb.itemid ~= 0 and isPokeball(mypb.itemid) then doItemSetAttribute(mypb.uid, "hp", 1) if getItemAttribute(mypb.uid, "hunger") and getItemAttribute(mypb.uid, "hunger") > baseNurseryHunger then doItemSetAttribute(mypb.uid, "hunger", baseNurseryHunger) end for c = 1, 15 do local str = "move"..c setCD(mypb.uid, str, 0) end if getItemAttribute(mypb.uid, "happy") and getItemAttribute(mypb.uid, "happy") < baseNurseryHappiness then doItemSetAttribute(mypb.uid, "happy", baseNurseryHappiness) end if getPlayerStorageValue(cid, 17000) <= 0 and getPlayerStorageValue(cid, 17001) <= 0 and getPlayerStorageValue(cid, 63215) <= 0 then for a, b in pairs (pokeballs) do if isInArray(b.all, mypb.itemid) then doTransformItem(mypb.uid, b.on) end end end end end -- Varre a mochila e cura todas as outras pokebolas guardadas local bp = getPlayerSlotItem(cid, CONST_SLOT_BACKPACK) local balls = {} if bp and bp.uid > 0 and isContainer(bp.uid) then balls = getPokeballsInContainer(bp.uid) or {} end if #balls >= 1 then for _, uid in ipairs(balls) do doItemSetAttribute(uid, "hp", 1) for c = 1, 15 do local str = "move"..c setCD(uid, str, 0) end if getItemAttribute(uid, "hunger") and getItemAttribute(uid, "hunger") > baseNurseryHunger then doItemSetAttribute(uid, "hunger", baseNurseryHunger) end if getItemAttribute(uid, "happy") and getItemAttribute(uid, "happy") < baseNurseryHappiness then doItemSetAttribute(uid, "happy", baseNurseryHappiness) end local this = getThing(uid) for a, b in pairs (pokeballs) do if isInArray(b.all, this.itemid) then doTransformItem(uid, b.on) end end end end -- Fecha a janela de dialogo apos a cura concluida com sucesso doSendDialogNpcClose(cid) selfSay('Prontinho! Voce e seus pokemons estao saudaveis novamente.', cid) if useKpdoDlls then doUpdateMoves(cid) end if npcHandler.unGreet then npcHandler:unGreet(cid) else npcHandler:resetNpc(cid) end npcHandler:releaseFocus(cid) return true elseif msgcontains(msg, "voltar") then doSendDialogNpc(cid, getNpcId(), "Ola treinador! Bem-vindo ao Centro Pokemon.\nComo posso ajudar voce e seus Pokemons hoje?", "Curar-Registrar-Fechar") return true -- 2. GATILHO: CLICOU EM FECHAR OU FALOU "SAIR/BYE/FECHAR" elseif msgcontains(msg, "fechar") or msgcontains(msg, 'sair') or msgcontains(msg, 'bye') then doSendDialogNpcClose(cid) selfSay('Ate mais treinador!', cid) if npcHandler.unGreet then npcHandler:unGreet(cid) else npcHandler:resetNpc(cid) end npcHandler:releaseFocus(cid) return true end return true end npcHandler:setCallback(CALLBACK_GREET, greetCallback) npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) npcHandler:addModule(FocusModule:new()) Fundo window.png — recriar sem anexoNa pasta modules/game_npcdialog do cliente, abra PowerShell e execute o bloco abaixo. Ele grava somente window.png nessa pasta. Se preferir outro fundo, ajuste image-source no OTUI. [System.IO.File]::WriteAllBytes((Join-Path (Get-Location) 'window.png'), [Convert]::FromBase64String('iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAACVUlEQVR4nO3dv07yUBiA8bcNXICzW3cTEyMX4O4d6aR35N5dCMTEWTZnZ0MEB77iaVMK8WvNk/D8NnOwad6H0z8TWfwzKfJNJKbLdRYazL5559Xi89tX5z+oP13zzg4NvipnoP9z7BxHhw5UHeDq+qafMztZ5VFf6FFExMPFbevi/etTRGxjzGdlX2d2ktIZds17FBHxuVi0H2X8c6Dlx/hlmFM9EbPysppl17x317W71Xlt7XH8boyeFWerXZS2eU+X62z3aNu82RhjGGmUVHXTr71rpDdwYwynGSV958ubHzbG8JYf45f5rGx9cq1dsozxt9KdUntTF4dBYAwCYxAYg8AYBMYgMAaBMQiMQWAMAmMQGIPAGATGIDAGgTEIjEFgDAJjEBiDwBgExiAwBoExCIxBYAwCYxAYg8AYBMYgMAaBMQiMQWAMAmMQGIPAGATGIDAGgTEIjEFgDAJjEBiDwBgExiAwBoExCIxBYAwCYxAYg8AYBMYgMAaBMQiMQWAMAmMQGIPAGATGIDAGgTEIjEFgDAJjEBiDwBgExiAwBoExCIxBYAwCYxAYg8AYBMYgMFn6h7+p/nfafks9omWHzGdlXF3fRHG2uvzbUzwdaYymXZlJkW/SBXfKMPbFqHZJHrGN8fz2VfuAO6V/aYzmvKsNkTV3RpM7pR9dl6nUwSARP1H0e8fOMJsU+ebh4rZ18f71qXZA/V4ao2veo4iIz8Wi/SjjSB7JyoM7Sd2my3U2KfJN17yziO0N5W51Xlt7HL/Xno/Vn655733sNcaw9s37G4DX+20+pJNdAAAAAElFTkSuQmCC'))
-
[PokéTibia / OTClient] Fly com sombra e botões de subir/descer — source + Lua
Download: Fly-Com-Sombra.zip (MediaFire)Leia as instruções de instalação do pacote.Fly com sombra e botoes — PokéTibia / OTClient Compartilhando os trechos que uso na minha base TFS 0.3.6 / PokexGeneration e no meu fork de OTClient. O jogador montado no Fly recebe uma sombra preta deslocada, e o painel oferece Subir/Descer. A criatura voando e desenhada apos os objetos do andar; a sombra fica no passe do chao. Nao e shader nem sistema completo de montar Fly. Precisa da source do CLIENTE com g_drawQueue, g_adaptiveRenderer, g_sprites.getOffsetFactor e a assinatura de Outfit::draw mostrada no patch. Nao e compativel automaticamente com OTClient classico, v8, Redemption ou qualquer fork. O TFS precisa de extended opcodes e de um sistema Fly existente com storage 17000 e outfits/tiles de voo. Nao substitua order.lua nem login.lua completos. Instalacao: salve o patch como fly_client.patch na raiz da source do cliente. Use git apply --check --ignore-space-change fly_client.patch antes de git apply --ignore-space-change fly_client.patch. Se houver contexto diferente, adapte manualmente os trechos. Nao aplique duas vezes se setFlying/drawShadow ja existem. Recompile o cliente. Copie os tres arquivos de game_fly para modules/game_fly e carregue o modulo depois de game_interface (no bootstrap ou em load-later de interface.otmod). Esta edicao publica usa botoes com texto para nao depender das imagens das setas. Servidor: copie flyup.lua e flydown.lua para data/talkactions/scripts e registre dentro de <talkactions>: <talkaction words="h1" case-sensitive="no" event="script" value="flyup.lua"/> <talkaction words="h2" case-sensitive="no" event="script" value="flydown.lua"/>Integre show/hide nos pontos de montar, desmontar e login conforme o bloco de integracao abaixo. O modulo envia h1/h2 pelo chat; nao envia up/down pelo opcode. O opcode 115 apenas informa show/hide do servidor ao cliente. Se 115 estiver ocupado, troque em todos os locais. Os scripts h1/h2 usam tiles 11675/11676/11677, storage 17000, markPosEff e canWalkOnPos desta familia de bases. Confira seus IDs e helpers; nao sao recursos do TFS puro. Eles mantem as restricoes de teto, obstaculos/PZ e altura desta base (z de 1 a 7). O item de voo deve ser removido pelo movement/sistema existente; nao copie esses IDs para uma base sem os tiles e a limpeza correspondentes. Limites: esta implementacao marca somente o jogador local como flying; outros jogadores nao recebem a sombra automaticamente. Nao modifica pathfinding nem cria voo para qualquer Pokemon. O deslocamento da sombra e 60 * offsetFactor nos dois eixos; ajuste em Creature::drawShadow. O patch foi extraido dos arquivos locais, nao de uma release universal. Revisao de codigo e testes Lua com simulacao realizados; nao foi feita nova compilacao nem teste visual nesta publicacao. Teste montando/desmontando, andando em todas as direcoes, mudando andar, reconectando e com GameMapDrawGroundFirst ligado/desligado antes de usar em producao. Creditos: OTClient team e autores do fork, mantendo a licenca MIT do OTClient. Modulo game_fly identificado como autor raul. Organizacao da edicao publica com auxilio do Codex. Nao reivindico autoria dos sistemas de Fly preexistentes da base. Nao distribuo executavel, sprites, banco, mapa ou configuracoes particulares. client\modules\game_fly\game_fly.luaflyWindow = nil FLY_OPCODE = 115 -- Certifique-se de que nenhum outro modulo use este mesmo numero function init() connect(g_game, { onGameStart = online, onGameEnd = offline }) -- Registra a escuta do Opcode vindo do servidor ProtocolGame.registerExtendedOpcode(FLY_OPCODE, onExtendedOpcode) if g_game.isOnline() then online() end end function terminate() disconnect(g_game, { onGameStart = online, onGameEnd = offline }) ProtocolGame.unregisterExtendedOpcode(FLY_OPCODE) offline() end function online() if not flyWindow then local gameMap = modules.game_interface.getMapPanel() flyWindow = g_ui.displayUI('game_fly.otui', gameMap) end -- Inicia escondido. O servidor vai mandar o comando para exibir ao subir no Fly flyWindow:hide() end function offline() local player = g_game.getLocalPlayer() if player then player:setFlying(false) end if flyWindow then flyWindow:destroy() flyWindow = nil end end -- Funcao que recebe o comando do servidor para ocultar/mostrar function onExtendedOpcode(protocol, opcode, buffer) if not flyWindow then return end if buffer == "show" then local player = g_game.getLocalPlayer() if player then player:setFlying(true) end flyWindow:show() flyWindow:raise() elseif buffer == "hide" then local player = g_game.getLocalPlayer() if player then player:setFlying(false) end flyWindow:hide() end end function flyUp() if g_game.isOnline() then g_game.talk("h1") end end function flyDown() if g_game.isOnline() then g_game.talk("h2") end end client\modules\game_fly\game_fly.otmodModule name: game_fly description: Painel de Fly com botoes de seta estilo OtPokemon author: raul sandboxed: true scripts: [ game_fly ] @onLoad: init() @onUnload: terminate() client\modules\game_fly\game_fly.otuiUIWindow id: flyWindow size: 64 128 anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter focusable: false &draggable: false UIButton id: buttonUp size: 58 32 anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter margin-top: -20 text: 'Subir' focusable: false &phantom: false @onClick: modules.game_fly.flyUp() UIButton id: buttonDown size: 58 32 anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter text: 'Descer' focusable: false &phantom: false @onClick: modules.game_fly.flyDown() fly_client.patch--- a/src/client/creature.h +++ b/src/client/creature.h @@ -47,6 +47,7 @@ virtual ~Creature(); virtual void draw(const Point& dest, bool animate = true, LightView* lightView = nullptr); + void drawShadow(const Point& dest, bool animate = true); virtual void drawOutfit(const Rect& destRect, Otc::Direction direction = Otc::InvalidDirection, const Color& color = Color::white, bool animate = false, bool ui = false, bool oldScaling = false); void drawInformation(const Point& point, bool useGray, const Rect& parentRect, int drawFlags); @@ -74,6 +75,8 @@ void setTypeTexture(const std::string& filename); void setIconTexture(const std::string& filename); void setPassable(bool passable) { m_passable = passable; } + void setFlying(bool flying) { m_flying = flying; } + bool isFlying() { return m_flying; } void setSpeedFormula(double speedA, double speedB, double speedC); void addTimedSquare(uint8 color); @@ -232,6 +235,7 @@ stdext::boolean<true> m_showShieldTexture; stdext::boolean<false> m_shieldBlink; stdext::boolean<false> m_passable; + bool m_flying = false; Color m_timedSquareColor; Color m_staticSquareColor; Color m_nameColor; --- a/src/client/creature.cpp +++ b/src/client/creature.cpp @@ -135,6 +135,23 @@ lightView->addLight(creatureCenter, light); } +void Creature::drawShadow(const Point& dest, bool animate) +{ + if (!m_flying || !canBeSeen()) + return; + + Point animationOffset = animate ? m_walkOffset : Point(0, 0); + if (m_outfit.getCategory() != ThingCategoryCreature) + animationOffset -= getDisplacement(); + + const Point jumpOffset(m_jumpOffset.x, m_jumpOffset.y); + const Point shadowOffset(60 * g_sprites.getOffsetFactor(), 60 * g_sprites.getOffsetFactor()); + const size_t shadowQueueStart = g_drawQueue->size(); + m_outfit.draw(dest - jumpOffset + animationOffset + shadowOffset, + m_walking ? m_walkDirection : m_direction, + m_walkAnimationPhase, true, nullptr); + g_drawQueue->setMark(shadowQueueStart, Color(0, 0, 0, 255)); +} void Creature::drawOutfit(const Rect& destRect, Otc::Direction direction, const Color& color, bool animate, bool ui, bool oldScaling) { --- a/src/client/tile.h +++ b/src/client/tile.h @@ -67,7 +67,9 @@ void drawGround(const Point& dest, LightView* lightView = nullptr); void drawBottom(const Point& dest, LightView* lightView = nullptr); + void drawCreatureShadows(const Point& dest); void drawCreatures(const Point& dest, LightView* lightView = nullptr); + void drawFlyingCreatures(const Point& dest, LightView* lightView = nullptr); void drawTop(const Point& dest, LightView* lightView = nullptr); void drawTexts(Point dest); void drawWidget(Point dest); --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -120,6 +120,31 @@ } } +void Tile::drawCreatureShadows(const Point& dest) +{ + if (m_fill != Color::alpha || m_topDraws < m_topCorrection) + return; + + for (const CreaturePtr& creature : m_walkingCreatures) { + if (creature->isHidden()) + continue; + Point creatureDest(dest.x + ((creature->getPrewalkingPosition().x - m_position.x) * g_sprites.spriteSize() - m_drawElevation * g_sprites.getOffsetFactor()), + dest.y + ((creature->getPrewalkingPosition().y - m_position.y) * g_sprites.spriteSize() - m_drawElevation * g_sprites.getOffsetFactor())); + creature->drawShadow(creatureDest, true); + } + + int limit = g_adaptiveRenderer.creaturesLimit(); + for (auto& thing : m_things) { + if (!thing->isCreature() || thing->isHidden()) + continue; + if (limit-- <= 0) + break; + CreaturePtr creature = thing->static_self_cast<Creature>(); + if (!creature || creature->isWalking()) + continue; + creature->drawShadow(dest - m_drawElevation * g_sprites.getOffsetFactor(), true); + } +} void Tile::drawCreatures(const Point& dest, LightView* lightView) { @@ -130,7 +155,7 @@ // walking creatures for (const CreaturePtr& creature : m_walkingCreatures) { - if (creature->isHidden()) + if (creature->isHidden() || creature->isFlying()) continue; Point creatureDest(dest.x + ((creature->getPrewalkingPosition().x - m_position.x) * g_sprites.spriteSize() - m_drawElevation * g_sprites.getOffsetFactor()), dest.y + ((creature->getPrewalkingPosition().y - m_position.y) * g_sprites.spriteSize() - m_drawElevation * g_sprites.getOffsetFactor())); @@ -146,12 +171,37 @@ if (limit-- <= 0) break; CreaturePtr creature = thing->static_self_cast<Creature>(); - if (!creature || creature->isWalking()) + if (!creature || creature->isWalking() || creature->isFlying()) continue; creature->draw(dest - m_drawElevation * g_sprites.getOffsetFactor(), true, lightView); } } +void Tile::drawFlyingCreatures(const Point& dest, LightView* lightView) +{ + if (m_fill != Color::alpha || m_topDraws < m_topCorrection) + return; + + for (const CreaturePtr& creature : m_walkingCreatures) { + if (creature->isHidden() || !creature->isFlying() || creature->getPrewalkingPosition() != m_position) + continue; + Point creatureDest(dest.x + ((creature->getPrewalkingPosition().x - m_position.x) * g_sprites.spriteSize() - m_drawElevation * g_sprites.getOffsetFactor()), + dest.y + ((creature->getPrewalkingPosition().y - m_position.y) * g_sprites.spriteSize() - m_drawElevation * g_sprites.getOffsetFactor())); + creature->draw(creatureDest, true, lightView); + } + + int limit = g_adaptiveRenderer.creaturesLimit(); + for (auto& thing : m_things) { + if (!thing->isCreature() || thing->isHidden()) + continue; + if (limit-- <= 0) + break; + CreaturePtr creature = thing->static_self_cast<Creature>(); + if (!creature || creature->isWalking() || !creature->isFlying() || creature->getPosition() != m_position) + continue; + creature->draw(dest - m_drawElevation * g_sprites.getOffsetFactor(), true, lightView); + } +} void Tile::drawTop(const Point& dest, LightView* lightView) { --- a/src/client/mapview.cpp +++ b/src/client/mapview.cpp @@ -177,6 +177,11 @@ Point tileDrawPos = transformPositionTo2D(tile->getPosition(), cameraPosition); tile->drawGround(tileDrawPos, m_lightView.get()); } + // Flying shadows stay on the ground and are covered by walls and top items. + for (auto& tile : tiles) { + Point tileDrawPos = transformPositionTo2D(tile->getPosition(), cameraPosition); + tile->drawCreatureShadows(tileDrawPos); + } // bottom, creatures, top for (auto& tile : tiles) { Point tileDrawPos = transformPositionTo2D(tile->getPosition(), cameraPosition); @@ -205,6 +210,7 @@ } tile->drawGround(tileDrawPos, m_lightView.get()); + tile->drawCreatureShadows(tileDrawPos); tile->drawBottom(tileDrawPos, m_lightView.get()); @@ -218,6 +224,11 @@ } } + // Flying creatures remain visible above mountains and other top objects. + for (auto& tile : tiles) { + Point tileDrawPos = transformPositionTo2D(tile->getPosition(), cameraPosition); + tile->drawFlyingCreatures(tileDrawPos, m_lightView.get()); + } for (const MissilePtr& missile : g_map.getFloorMissiles(floor)) { missile->draw(transformPositionTo2D(missile->getPosition(), cameraPosition), true, m_lightView.get()); --- a/src/client/luafunctions_client.cpp +++ b/src/client/luafunctions_client.cpp @@ -509,6 +509,8 @@ g_lua.bindClassMemberFunction<Creature>("setSpeed", &Creature::setSpeed); g_lua.bindClassMemberFunction<Creature>("getBaseSpeed", &Creature::getBaseSpeed); g_lua.bindClassMemberFunction<Creature>("setBaseSpeed", &Creature::setBaseSpeed); + g_lua.bindClassMemberFunction<Creature>("setFlying", &Creature::setFlying); + g_lua.bindClassMemberFunction<Creature>("isFlying", &Creature::isFlying); g_lua.bindClassMemberFunction<Creature>("getSkull", &Creature::getSkull); g_lua.bindClassMemberFunction<Creature>("getShield", &Creature::getShield); g_lua.bindClassMemberFunction<Creature>("getEmblem", &Creature::getEmblem); server\data\talkactions\scripts\flydown.lualocal lower = {460, 11675, 11676, 11677} -- Corrigido para números para evitar falhas de leitura local houses = {'919', '1015', '1590', '1591', '1592', '1593', '1582', '1584', '1586', '1588', '5248', '5189'} local function refreshFlyOutfit(cid, flyOutfit) addEvent(function() if not isCreature(cid) then return end doCreatureChangeOutfit(cid, flyOutfit) end, 80) end function onSay(cid, words, param) if param ~= "" then return false end if getPlayerStorageValue(cid, 17000) <= 0 then return true end -- Impede de descer abaixo do nível do chão (Z=7) if getThingPos(cid).z >= 7 then doPlayerSendCancel(cid, "Voce nao pode descer mais!") return true end local currentTile = getTileInfo(getThingPos(cid)).itemid if currentTile == 11677 then doPlayerSendCancel(cid, "Desculpe, nao e possivel descer mais por aqui.") return true end if currentTile >= 2 and not isInArray(lower, currentTile) then doPlayerSendCancel(cid, "Voce nao pode descer aqui.") return true end local pos = getThingPos(cid) pos.z = pos.z + 1 pos.stackpos = 0 if getTileThingByPos(pos).itemid >= 1 then -- Impede o jogador de descer voando dentro de uma Zone de Proteção (PZ), como um CP if getTilePzInfo(pos) == true then doPlayerSendCancel(cid, "Voce nao pode descer aqui (Zona de Protecao).") return true end -- Impede de descer se houver um obstáculo sólido embaixo (paredes, montanhas, etc.) if not canWalkOnPos(pos, true, true, false, false, true) then doPlayerSendCancel(cid, "Voce nao pode descer aqui, o caminho esta bloqueado.") return true end local flyOutfit = getCreatureOutfit(cid) doTeleportThing(cid, pos) refreshFlyOutfit(cid, flyOutfit) if getCreatureOutfit(cid).lookType == 667 or getCreatureOutfit(cid).lookType == 999 then markPosEff(cid, getThingPos(cid)) end else local flyOutfit = getCreatureOutfit(cid) doCombatAreaHealth(cid, 0, pos, 0, 0, 0, CONST_ME_NONE) doCreateItem(11675, 1, pos) doTeleportThing(cid, pos) refreshFlyOutfit(cid, flyOutfit) if getCreatureOutfit(cid).lookType == 667 or getCreatureOutfit(cid).lookType == 999 then markPosEff(cid, getThingPos(cid)) --edited porygon fly sistem end end return true end server\data\talkactions\scripts\flyup.lualocal function refreshFlyOutfit(cid, flyOutfit) addEvent(function() if not isCreature(cid) then return end doCreatureChangeOutfit(cid, flyOutfit) end, 80) end function onSay(cid, words, param) if param ~= "" then return false end if getPlayerStorageValue(cid, 17000) <= 0 then return true end -- Altere para 0 se o seu mapa suportar o andar 0 sem travar o movimento do Pokémon. local andar_maximo_permitido = 1 if getThingPos(cid).z <= andar_maximo_permitido then doPlayerSendCancel(cid, "Voce ja esta na altura maxima permitida de Fly!") return true end local pos = getThingPos(cid) pos.z = pos.z - 1 pos.stackpos = 0 -- Impede de subir se houver um teto, telhado ou construção sólida logo acima if getTileThingByPos(pos).itemid >= 1 or getTileItemById(getThingPos(cid), 1386).itemid >= 1 then doPlayerSendCancel(cid, "Voce nao pode voar atraves de construcoes.") return true end local flyOutfit = getCreatureOutfit(cid) doCombatAreaHealth(cid, 0, pos, 0, 0, 0, CONST_ME_NONE) doCreateItem(11676, 1, pos) doTeleportThing(cid, pos) refreshFlyOutfit(cid, flyOutfit) if getCreatureOutfit(cid).lookType == 667 or getCreatureOutfit(cid).lookType == 999 then markPosEff(cid, getThingPos(cid)) --edited porygon fly sistem end return true end server\integracao.lua-- Inserir apenas nos pontos correspondentes do sistema de Fly existente. -- Depois de montar e ativar storage 17000: doSendPlayerExtendedOpcode(cid, 115, "show") -- Depois de desmontar e desativar storage 17000: doSendPlayerExtendedOpcode(cid, 115, "hide") -- No login, depois de restaurar o estado de Fly: if getPlayerStorageValue(cid, 17000) > 0 then doSendPlayerExtendedOpcode(cid, 115, "show") else doSendPlayerExtendedOpcode(cid, 115, "hide") end
-
Name Adjustment
o gender no meu servidor mostra do lado do nome (antes), por isso parece que a barra de hp está torta pois não é costume ser assim nos servidores, mas no seu provavelmente estará encaixado. Level também empurra o nick pro lado nessa posição do name adjustment, voce pode simplesmente ajustar como querer a partir do código.
-
Name Adjustment
Salve. Quero compartilhar com vocês um Height adjustment. Ajuste de nome em cima do monstro/player: barra de hp/nome ficam estáticos e centralizados um pouco acima da cabeça player/pokémon, mais precisamente no centro da sprite. Instalação: a alteração é apenas na source (C++), compile o OTclient depois. Primeiro, abre o arquivo src\client\thingtype.h no otc e procure por: encontrará essa linha: cole essa linha em baixo (e salve: ctrl + s): Agora abra o arquivo src\client\thingtype.cpp no otc e procure por: desce um pouquinho até achar essa: antes do 'ThingFlagAttr', cole isso aqui (e salve também): Bom, finalizando essa parte vamos pra src\client\creature.cpp, no otc procure por: logo abaixo tem essas 3 linhas: apague as 3 linhas e no lugar coloque (e salve tudo): Agora basta compilar o otclient e fazer o teste. ANTES nomes desajustados das sprites DEPOIS nomes ajustados no centro da sprite 😈 Editamento: em src\client\creature.cpp, alterando o número você aproxima ou afasta a barra e o nome. Ao editar, salva e compila o otClient novamente. Eu ainda acho que aproximar mais deixa mais bonito. Fica a dica. Esta adaptação é apenas visual, dentro do OTCLIENT (com source) e totalmente funcional. Créditos: Eu por adaptar do 0 e trazer aqui. Não dou suporte, somente freela. Faça bom uso.
-
-
goatboyw alterou sua foto pessoal
-
mito677 reagiu a uma resposta no tópico:
[8.60][OLD Client] Narutibia (NTO HARD) - Servidor Completo
-
-
HSinhori alterou sua foto pessoal
-
OTClient para macOS
Eu tentei compilar o otclient do edubart pra windows e macOS, mas pra windows já está totalmente defasado, muito antigo, aí fui ver o do mehah e do opentibia mas eles não tem informações de como compilar para macOS, alguém por acaso sabe como faço pra compilar a mesma versão de otclient para windows e macOS (tenho ambos os sistemas), ou tenha o otclient já compilado para macOS, já ajuda muito
-
(Sprite pack) Tibia 10.41 (V1.0)
Bom dia! Meu mapa não está carregando. Já tentei de todas as formas. Abro o RME, seleciono meu mapa, aparece uma tela para selecionar a pasta(data/spr) do Tibia 10.41, seleciono e aperto enter, em seguida aparece essa tela e não abre mais nada! OBS: O servidor é 8.60 e está online e com o mapa que quero carregar. (Estou disponibilizando essa informação pois pode ser necessária.)
-
-
🔥 RECRUTAMENTO ABERTO | FAÇA PARTE DA NOSSA EQUIPE
• Nome ou apelido: Julio Cesar/ShakeziiN • Idade: 29 anos. • Cargo pretendido (Mapper ou GM): GM. • Experiência anterior: Já fui proprietario de servidor, coordenador-geral de diversos servidores, responsavel pela staff, etc.. • Quanto tempo possui disponível para o projeto: Pelo menos 8 horas por dia, visto que trabalho home-office e possuo 3 monitores para suporte imediato e efetivo. • Trabalhos/projetos anteriores, caso tenha: Já construi um servidor de War no mapa de Carlin, na época tinha apenas 16 anos e não tinha maturidade pra lidar com a quantidade de players, bateu 130 online mas como o servidor era na minha maquina, sofria diversos ataques DDoS e não tinha poder aquisitivo para investir em uma VPS ou Dedicado. • Por que você gostaria de fazer parte da equipe: Tenho disponibilidade, maturidade e sou apaixonado por Tibia, além de uma otima experiência com pessoas.
-
voncocka alterou sua foto pessoal
-
-
Inferna74 alterou sua foto pessoal
-
Classic-Yurots [8.60] - Push Cruzado + Cast com Setas
desculpa reviver o topico, mas os links para a distro estao indisponiveis? me pode enviar no meu privado por favor? necessito o Tibia.dat/Tibia.spr que estariam disponiveis apenas no client (no lado do servidor esses arquivos nao estao, e nem devem ficar ali) +34691619914 (eu moro fora, o +34 é o digito do pais)
-
Quero contratar o serviço de um DEV para trabalhar em um projeto de tibia OT
QUE TIPO DE TRABALHO PRECISA? CHAMA DISCORD: @Erimyth
-
🔥 RECRUTAMENTO ABERTO | FAÇA PARTE DA NOSSA EQUIPE
Olá meu nobre! Deixo aqui meu interesse em voltar para o mundo dos OTserver personalizados. Envie uma mensagem informando: • Nome ou apelido: Lucas Gomes • Idade: 31 • Cargo pretendido (Mapper ou GM): Sinceramente, eu estou disponível para o cargo que for necessário, sou criativo e sei criar mapas mas também sou um ótimo ouvinte e solucionador. Tenho bastante familiaridade com os arquivos fonte do tibia, sou designer com um pézinho na programação, atuo mais no front-end. • Experiência anterior: Tenho experiência como Mapper, no passado criei sozinho um servidor totalmente customizado com a base do Thyrania OT, que alcançou 470 jogadores simuntâneo, eu tinha 17 anos nao tinha maturidade para tamanho sucesso. • Quanto tempo possui disponível para o projeto: Consigo me dedicar cerca de 2 a 3 Horas por dia, podendo extender no final de semana • Por que você gostaria de fazer parte da equipe: Eu amo o tibia de coração, ja se passaram diversas pessoas e situações na minha vida e a unica coisa boa que ficou de tudo foi o Tibia.
-
TFS 1.5 {8.6} Nekiro Downgrade com montarias e modal window apenas para OTClient.
Não é tão simples. precisei ativar a versão 8.6 Old no features. <client name="8.60 (old)" otb="8.60 (old)" visible="false" data_directory="860"> <otbm version="3"/> <data format="8.6" dat="0x4C2C7993" spr="0x4C220594"/> </client> <client name="8.60" otb="8.60" visible="true" data_directory="860"> <otbm version="3"/> <extensions from="8.20 - 8.31" to="8.60"/> <data format="8.6" dat="0x4C28B721" spr="0x4C220594"/> <!-- ADICIONE ESTA LINHA AQUI --> <data format="8.6" dat="0x4C2C7993" spr="0x4C220594"/> <data format="8.6" dat="0x4C6A4CBC" spr="0x4C63F145"/> ou alterar o visible pra true na versão old, ou copiar o numero da sprt e dat da old para a 8.6 normal.
-
Quero contratar o serviço de um DEV para trabalhar em um projeto de tibia OT
Quero contratar o serviço de um DEV para trabalhar em um projeto de tibia OT, alguem??
-
Cidade de Pitlover [10.98]
Alguém poderia postar um link atualizado? Pois está quebrado. Achei tão bonito o mapa.
- Base Wo-naruto shinobi Returns [WONSR]
-
Kleber Holtz alterou sua foto pessoal
-
Object Builder — Editor de objetos e sprites para OTClient | Windows, Linux e macOS
Fala, pessoal! Quero apresentar o Object Builder, um projeto que estou desenvolvendo para facilitar a edição de objetos e sprites de clientes Tibia/OTClient. A proposta é reunir em uma única ferramenta a edição de itens, outfits, efeitos e projéteis, o gerenciamento de sprites e os ajustes de animações, com uma interface organizada e disponível em português e inglês. O que já dá para fazer: Abrir e salvar DAT/SPR, com configurações de versão e suporte a OTFI. Navegar entre itens, outfits, efeitos e projéteis, usando busca, filtros e ordenação. Editar propriedades dos objetos e visualizar suas camadas, padrões e frames. Editar sprites diretamente no programa, com lápis, borracha e ferramentas de desenho. Ajustar animações, alterando a duração de frames individualmente ou em conjunto. Importar e exportar PNGs e spritesheets, incluindo sequências completas de animação. Compartilhar objetos em arquivos .obd, preservando os dados suportados do objeto. Gerenciar sprites, consultar onde são utilizados e analisar candidatos sem uso ou duplicados. Dividir o SPR em volumes, com tamanhos configuráveis. Trabalhar com desfazer/refazer, atalhos configuráveis, projetos recentes e backups de recuperação. O programa oferece configurações para clientes de 7.40 a 15.25, trabalhando com arquivos DAT/SPR. A compatibilidade depende do formato e dos recursos utilizados pelo cliente. Como começar: Acesse a página de versões e baixe o pacote correspondente ao seu sistema. Abra o programa e escolha Abrir Cliente. Selecione os arquivos DAT/SPR e confira as configurações do cliente. Explore as categorias, faça suas alterações e salve ou exporte os objetos. Links do projeto: Downloads e versões Repositório e documentação Relatar problemas e enviar sugestões Quem testar, deixe aqui suas impressões! Se encontrar algum problema, informe a versão do cliente, o sistema operacional e os passos para reproduzir. Sugestões de quem trabalha com sprites e criação de conteúdo são bem-vindas. Video mostrando algumas funções (sem cortes) https://youtu.be/SPjUujGxrOU
-
[POLAND] [CUSTOM] Dragon Ball World [Anime] dbwots.pl
Dragon Ball World OTS — a different kind of Dragon Ball serverLooking for a Dragon Ball OTS that isn’t all about crazy numbers, instant levels and restarting from zero every few months? Dragon Ball World is a long-term custom Dragon Ball server inspired by the atmosphere of classic games such as Legacy of Goku, with slower progression, meaningful character development and a strong focus on PvE, exploration and custom systems. The idea behind DBW is simple — your character and the time you put into it should actually matter. There are no seasonal editions, no character resets and no wipes. The server has been running continuously for years and is constantly being developed, balanced and expanded with new content. What can you expect?The beginning of the game is focused mainly on PvE progression. You can play solo or together with other players while progressing through: Sagas Quests & Tasks Dungeons Mini Bosses Mazes World Bosses Dragon Ball events Tournaments and many other activities As you progress further, the game gradually introduces more competitive and end-game oriented content. DBW also offers a lot more than regular hunting. You’ll find multiple progression and Life Skill systems such as: Crafting Mining Cooking Gem System for upgrading equipment Training Rooms Item Rarity & Quality, making dropped equipment more unique dozens of equipment sets and progression items and many other custom mechanics built specifically for the server Character progression is intentionally slower than on most Dragon Ball OTS servers. Getting stronger, improving your equipment and reaching new areas is meant to feel like actual progression rather than a race to max level. The server is also designed so that older and higher-level players still have reasons to interact with and help newer players, making it possible to start your adventure even long after the server launch. Constantly evolvingDragon Ball World has been continuously developed for years. Characters, monsters, dungeons and existing systems are regularly rebalanced or completely reworked, while new quests, areas, items and mechanics are constantly being added. The project is currently approaching version 1.0, which will complete the core foundation of the game — but definitely not the development of the server itself. If you’re looking for a long-term Dragon Ball OTS, where progress actually matters and where you can slowly build your character instead of starting over every few months, give DBW a try. Start your adventure and join our community! 🌐 Website: dbwots.pl 💬 Discord: discord.gg/8t5rkpNu2a No resets. No editions. No wipes. Just progression. Update 0.97 Soon! New Client ! New WWW.