Líderes
-
-
-
.HuRRiKaNe
MembroPontos701Total de itens -
Conteúdo Popular
Exibindo conteúdo com a maior reputação em 09/16/18 em todas áreas
-
Pack Sprites
1 ponto
-
[show-off] Classic Yurots
1 pontoClassic Yurots v8.60 Eu estou desenvolvendo um novo Yurots! O mapa é exclusivo para o servidor e foi modificado para relembrar os tempos Old's. A versão da distro utilizada para o servidor é uma customização da OTX2 - 2.8 "LEZICK". A datapack foi completamente modificada e se tornou única, removendo todos os problemas encontrados da versão. Em breve irei atualizar este tópico e também adicionar atualizações sobre o projeto. Imagens Patch (basta clicar na versão para ser redirecionado até o post específico) - v0.10 (17/08/2018) - v0.20 (22/08/2018) - v0.25 (22/08/2018) - v0.30 (26/08/2018) Quer me ajudar? Poste sua sugestão para este projeto.1 ponto
-
Fortbay City | Cidade Completa | 11.40
Fortbay City Version: 11.40 Brief infos: *63 houses *01 guildhall *01 depot *01 boat(s) *02 usable hunt places Download: Type: .Rar Size: 677KB Temple position: [X: 1028 Y: 1025 Z: 7] File password: tibiaking Scan: OBSERVAÇÕES: O mapa não foi implantado em qualquer otserver para teste, então pode haver pequenos erros no mapa (e.g: ausencia de pz tiles, portas que não abrem, blank tiles, etc). Images:1 ponto
-
[C++] TFS 1.2 / OTX Server 3 New Npc Currency System
Sorry I don't speak spanish so you will have to bare with me. This is a new way for people to create npc's which use different types of currency, rather than a coming up with different items to trade with the npc or trying to edit the npc modules this method simplifies everything by providing the npc with a npc currency id. All this npc currency id is, is a storage value.. pretty simple eh? If the npc doesn't have a currency id then it will use the normal currency e.g. gold, plat, cc etc.. I originally posted this on otland, but fuck them xD Using Lailene here you can see she has a currency attribute with id of 123456 <?xml version="1.0" encoding="UTF-8"?> <npc name="Lailene" currency="123456" script="lailene.lua" walkinterval="2000" floorchange="0" speechbubble="2"> <health now="100" max="100"/> <look type="279" head="114" body="94" legs="113" feet="114" addons="0"/> </npc> Now any player who has a storage value of 123456 can purchase things from her shop provided they have enough value stored within the storage, similar to having money in the bank. The money or in this case the storage value is added and removed from the player in real time. Lets get to the code game.cpp Find this bool Game::removeMoney(Cylinder* cylinder, uint64_t money, uint32_t flags /*= 0*/) Replace the whole function with this. bool Game::removeMoney(Cylinder* cylinder, uint64_t money, uint32_t flags /*= 0*/) { if (cylinder == nullptr) { return false; } if (money == 0) { return true; } uint32_t currencyId = 0; Player* player; if (Creature* creature = cylinder->getCreature()) { if (Player* p = creature->getPlayer()) { currencyId = p->getNpcCurrencyId(); player = p; } } if (!currencyId) { std::vector<Container*> containers; std::multimap<uint32_t, Item*> moneyMap; uint64_t moneyCount = 0; for (size_t i = cylinder->getFirstIndex(), j = cylinder->getLastIndex(); i < j; ++i) { Thing* thing = cylinder->getThing(i); if (!thing) { continue; } Item* item = thing->getItem(); if (!item) { continue; } Container* container = item->getContainer(); if (container) { containers.push_back(container); } else { const uint32_t worth = item->getWorth(); if (worth != 0) { moneyCount += worth; moneyMap.emplace(worth, item); } } } size_t i = 0; while (i < containers.size()) { Container* container = containers[i++]; for (Item* item : container->getItemList()) { Container* tmpContainer = item->getContainer(); if (tmpContainer) { containers.push_back(tmpContainer); } else { const uint32_t worth = item->getWorth(); if (worth != 0) { moneyCount += worth; moneyMap.emplace(worth, item); } } } } if (moneyCount < money) { return false; } for (const auto& moneyEntry : moneyMap) { Item* item = moneyEntry.second; if (moneyEntry.first < money) { internalRemoveItem(item); money -= moneyEntry.first; } else if (moneyEntry.first > money) { const uint32_t worth = moneyEntry.first / item->getItemCount(); const uint32_t removeCount = (money / worth) + 1; addMoney(cylinder, (worth * removeCount) - money, flags); internalRemoveItem(item, removeCount); break; } else { internalRemoveItem(item); break; } } } else { int32_t value; player->getStorageValue(currencyId, value); if (value < money) { return false; } player->addStorageValue(currencyId, value - money); } return true; } Next find this void Game::addMoney(Cylinder* cylinder, uint64_t money, uint32_t flags /*= 0*/) Replace the whole function with this void Game::addMoney(Cylinder* cylinder, uint64_t money, uint32_t flags /*= 0*/) { if (money == 0) { return; } if (Creature* creature = cylinder->getCreature()) { if (Player* player = creature->getPlayer()) { if(uint32_t currencyId = player->getNpcCurrencyId()){ int32_t value; player->getStorageValue(currencyId, value); player->addStorageValue(currencyId, value + money); return; } } } uint32_t crystalCoins = money / 10000; money -= crystalCoins * 10000; while (crystalCoins > 0) { const uint16_t count = std::min<uint32_t>(100, crystalCoins); Item* remaindItem = Item::CreateItem(ITEM_CRYSTAL_COIN, count); ReturnValue ret = internalAddItem(cylinder, remaindItem, INDEX_WHEREEVER, flags); if (ret != RETURNVALUE_NOERROR) { internalAddItem(cylinder->getTile(), remaindItem, INDEX_WHEREEVER, FLAG_NOLIMIT); } crystalCoins -= count; } uint16_t platinumCoins = money / 100; if (platinumCoins != 0) { Item* remaindItem = Item::CreateItem(ITEM_PLATINUM_COIN, platinumCoins); ReturnValue ret = internalAddItem(cylinder, remaindItem, INDEX_WHEREEVER, flags); if (ret != RETURNVALUE_NOERROR) { internalAddItem(cylinder->getTile(), remaindItem, INDEX_WHEREEVER, FLAG_NOLIMIT); } money -= platinumCoins * 100; } if (money != 0) { Item* remaindItem = Item::CreateItem(ITEM_GOLD_COIN, money); ReturnValue ret = internalAddItem(cylinder, remaindItem, INDEX_WHEREEVER, flags); if (ret != RETURNVALUE_NOERROR) { internalAddItem(cylinder->getTile(), remaindItem, INDEX_WHEREEVER, FLAG_NOLIMIT); } } } npc.cppLook for this pugi::xml_attribute attr; if ((attr = npcNode.attribute("speed"))) { baseSpeed = pugi::cast<uint32_t>(attr.value()); } else { baseSpeed = 100; } Right underneath that you are going to place this. if ((attr = npcNode.attribute("currency"))) { currency = pugi::cast<uint32_t>(attr.value()); } npc.hLook for this bool isPushable() const final { return walkTicks > 0; } Place this right underneath uint32_t getCurrencyId() const { return currency; } Look for this uint32_t walkTicks; Place this right underneath uint32_t currency; player.cppFind this void Player::openShopWindow(Npc* npc, const std::list<ShopInfo>& shop) Replace that function with this void Player::openShopWindow(Npc* npc, const std::list<ShopInfo>& shop) { shopItemList = shop; sendShop(npc); sendSaleItemList(npc); } Next find this bool Player::updateSaleShopList(const Item* item) Replace that function with this bool Player::updateSaleShopList(const Item* item) { uint16_t itemId = item->getID(); if (itemId != ITEM_GOLD_COIN && itemId != ITEM_PLATINUM_COIN && itemId != ITEM_CRYSTAL_COIN) { auto it = std::find_if(shopItemList.begin(), shopItemList.end(), [itemId](const ShopInfo& shopInfo) { return shopInfo.itemId == itemId && shopInfo.sellPrice != 0; }); if (it == shopItemList.end()) { const Container* container = item->getContainer(); if (!container) { return false; } const auto& items = container->getItemList(); return std::any_of(items.begin(), items.end(), [this](const Item* containerItem) { return updateSaleShopList(containerItem); }); } } if (client) { client->sendSaleItemList(shopOwner, shopItemList); } return true; } Next you are going to look for uint64_t Player::getMoney() const Now right underneath that function you are going to place these. uint64_t Player::getMoney(Npc* npc) const { uint64_t cash; setNpcCurrencyId(npc); uint32_t currencyId = getNpcCurrencyId(); if (currencyId) { int32_t value; getStorageValue(currencyId, value); cash = (uint64_t)value; } else { cash = getMoney(); } return cash; } void Player::setNpcCurrencyId(Npc* npc) const{ currencyId = npc->getCurrencyId(); } uint32_t Player::getNpcCurrencyId() const { return currencyId; } player.hLook for this uint64_t getMoney() const; Place this right underneath uint64_t getMoney(Npc*) const; void setNpcCurrencyId(Npc*) const; uint32_t getNpcCurrencyId() const; Find this void sendShop(Npc* npc) const { if (client) { client->sendShop(npc, shopItemList); } } Place this right underneath void sendSaleItemList(Npc* npc) const { if (client) { client->sendSaleItemList(npc, shopItemList); } } Find this uint32_t manaMax; Place this right underneath mutable uint32_t currencyId; protocolgame.cpp Now find this function void ProtocolGame::sendSaleItemList(const std::list<ShopInfo>& shop) Place this right underneath void ProtocolGame::sendSaleItemList(Npc* npc, const std::list<ShopInfo>& shop) { NetworkMessage msg; msg.addByte(0x7B); msg.add<uint64_t>(player->getMoney(npc)); std::map<uint16_t, uint32_t> saleMap; if (shop.size() <= 5) { // For very small shops it's not worth it to create the complete map for (const ShopInfo& shopInfo : shop) { if (shopInfo.sellPrice == 0) { continue; } int8_t subtype = -1; const ItemType& itemType = Item::items[shopInfo.itemId]; if (itemType.hasSubType() && !itemType.stackable) { subtype = (shopInfo.subType == 0 ? -1 : shopInfo.subType); } uint32_t count = player->getItemTypeCount(shopInfo.itemId, subtype); if (count > 0) { saleMap[shopInfo.itemId] = count; } } } else { // Large shop, it's better to get a cached map of all item counts and use it // We need a temporary map since the finished map should only contain items // available in the shop std::map<uint32_t, uint32_t> tempSaleMap; player->getAllItemTypeCount(tempSaleMap); // We must still check manually for the special items that require subtype matches // (That is, fluids such as potions etc., actually these items are very few since // health potions now use their own ID) for (const ShopInfo& shopInfo : shop) { if (shopInfo.sellPrice == 0) { continue; } int8_t subtype = -1; const ItemType& itemType = Item::items[shopInfo.itemId]; if (itemType.hasSubType() && !itemType.stackable) { subtype = (shopInfo.subType == 0 ? -1 : shopInfo.subType); } if (subtype != -1) { uint32_t count; if (!itemType.isFluidContainer() && !itemType.isSplash()) { count = player->getItemTypeCount(shopInfo.itemId, subtype); // This shop item requires extra checks } else { count = subtype; } if (count > 0) { saleMap[shopInfo.itemId] = count; } } else { std::map<uint32_t, uint32_t>::const_iterator findIt = tempSaleMap.find(shopInfo.itemId); if (findIt != tempSaleMap.end() && findIt->second > 0) { saleMap[shopInfo.itemId] = findIt->second; } } } } uint8_t itemsToSend = std::min<size_t>(saleMap.size(), std::numeric_limits<uint8_t>::max()); msg.addByte(itemsToSend); uint8_t i = 0; for (std::map<uint16_t, uint32_t>::const_iterator it = saleMap.begin(); i < itemsToSend; ++it, ++i) { msg.addItemId(it->first); msg.addByte(std::min<uint32_t>(it->second, std::numeric_limits<uint8_t>::max())); } writeToOutputBuffer(msg); } protocolgame.h Find this void sendSaleItemList(const std::list<ShopInfo>& shop); Place this right underneath void sendSaleItemList(Npc* npc, const std::list<ShopInfo>& shop); luascript.cpp Find int LuaScriptInterface::luaPlayerAddMoney(lua_State* L) Replace that whole function with this int LuaScriptInterface::luaPlayerAddMoney(lua_State* L) { // player:addMoney(money[, currencyId]) uint64_t money = getNumber<uint64_t>(L, 2); uint32_t currencyId = getNumber<uint32_t>(L, 3); Player* player = getUserdata<Player>(L, 1); if (player) { if (currencyId) { int32_t value; player->getStorageValue(currencyId, value); player->addStorageValue(currencyId, value + money); } else { g_game.addMoney(player, money); } pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } Next find this function which should be right below it. int LuaScriptInterface::luaPlayerRemoveMoney(lua_State* L) Replace that whole function with this int LuaScriptInterface::luaPlayerRemoveMoney(lua_State* L) { // player:removeMoney(money[, currencyId]) Player* player = getUserdata<Player>(L, 1); if (player) { uint64_t money = getNumber<uint64_t>(L, 2); uint32_t currencyId = getNumber<uint32_t>(L, 3); if (currencyId) { int32_t value; player->getStorageValue(currencyId, value); if (value < money) { pushBoolean(L, false); return 1; } player->addStorageValue(currencyId, value - money); pushBoolean(L, true); } else { pushBoolean(L, g_game.removeMoney(player, money)); } } else { lua_pushnil(L); } return 1; }1 ponto
-
GLOBAL 100% 7.40 Cliente Proprio, Port Hope 7.4, POI, Demon OaK, War System, Shared Exp, Cast System, Anti Clone, Task System.
Download Scan1 ponto
-
(Resolvido)[Creaturescript] Como travar um player se tiver tal storage?
doCreatureSetNoMove(cid, true)1 ponto
-
(Resolvido)Script de efeito
(Resolvido)Script de efeito
iury alves potter reagiu a Kramer por uma resposta no tópico
1 pontoNão consegui ter um entendimento maior, esse script é para ser usado quando ? Assim que o player falar isso ou quando usar tal frase ? Pois tenho um quando ele pisar em X tile com ID ele ficaria com N storage ignorando o anti idle assim burlando o otservlist e soltando M efeito e rodando o char por X período que você programar, quanto maior o intervalo maior será a verificação do script causando mais lag.1 ponto -
(Resolvido)Quest Que Precisa de um Item pra funcionar
@Thiphone ActionID - É uma identidade, assim como pessoas tem números de Identidades(RG) diferentes para facilitar o acesso aos nossos dados. A actionID não é diferente, ela nada mais é que a identidade do Bau ou outro Item. Ah, mas o que ela faz? Simples. Se você criar um arquivo .lua com o nome de BAU, e outro arquivo com o nome de BAU2, cada um vai dar item diferente. Então terão identidades (actionID) diferentes um do outro. Exemplo: <action actionid="2240" event="script" value="bau.lua"/> <action actionid="2241" event="script" value="bau2.lua"/> Agora, respondendo a sua pergunta, "a action ID eu posso coloca qual eu quiser, ou posso colocar a 2000?" Sim, desde que ela não exista. Exemplo: Se o bau1 tem actionID = 1000, o bau2 NÃO pode ter actionID = 1000. Pode ser 1001, 1002, 1003.... Storage - Storages também NÃO PODEM SER IGUAIS. Se você usou no arquivo BAU a storage 2508, então no BAU2 você não poderá usar a mesma storage. (mentira pode usar sim, mas com algumas exceções). Pensa assim: É páscoa na sua escola, então estão distribuindo chocolates, doces.... Quando você ganhar seu chocolate e suas balinhas, você não poderá pegar de novo, por que você já pegou uma vez. Porém na escola você tem as professoras que veem quem recebeu ou não o chocolate e as balas, já no tibia "as professoras" são as storages. Ou seja, se você abrir um bau ele vai te dar a storage 1, se você tentar abrir o mesmo bau depois você não vai conseguir, por que você já ganhou o chocolate e as balas . Em poucas palavras, ao abrir o bau1, automaticamente você vai ganhar uma storage e se tentar abrir o mesmo bau não vai conseguir, pois você já abriu o bau uma vez e recebeu o prêmio.1 ponto
-
(Resolvido)Lista Pokemon
1 pontoda uma olhada nesse tópico talvez possa ajuda você. https://www.xtibia.com/forum/topic/242237-tutorial-otc-pokemon-bar/1 ponto
-
Vamos melhorar o TK!
1 pontoHello membros do Tibia King, vocês puderam notar que recentemente tivemos algumas melhorias em nossa comunidade, como por exemplo o nossa nova seção de Classificados, um novo visual para o site, entre outras novidades que vocês podem conferir clicando aqui. Aah! Vale lembrar também que está acontecendo neste momento o evento "Mapper King" organizado pelo membro @Daniel, participe e acompanhe clicando aqui. Neste tópico gostaria de abordar um assunto importantíssimo a respeito de nossa comunidade: a participação vocês na comunidade! Ou seja, alguns dos membros da comunidade ajudam aos outros, postam conteúdos e contribuem bastante. assim como eu, mas como todos, também tenho minhas ocupações, projetos pessoais e o mais importante, vida pessoal. Por isso digo que é essencial o agradecimento e a retribuição de todos que usufruem de tudo que nossa comunidade oferece, mas eu vejo que muitos esquecem de fazer isso, agem como "leechers", apenas sugam o conteúdo e até mesmo pedem ajuda em nossas seções de suporte, é ajudado pelos membros do fórum e nem se quer agradecem pela atenção. O reconhecimento é muito gratificante, as vezes receber um simples "obrigado" já é muita coisa, isso incentiva que as pessoas continuarem ajudando, publicando e criando novos conteúdos para todos. Tente também contribuir com a comunidade, as vezes alguém está com um problema que você já resolveu alguma vez ou até mesmo você já sabe a solução, não custa nada ajudar e compartilhar o seu conhecimento! Então é isso galera, vamos tentar sempre evoluir e fazer com que essa comunidade maravilhosa seja ainda melhor. Nós da equipe do TK continuaremos fazendo nossa parte, ajudando sempre da melhor maneira. Vale lembrar que estamos com novas ideias para valorizar ainda mais os membros que são realmente ativos, portanto aguardem que novidades surgirão! E você? O que acha, concorda ou descorda? Deixe sua opinião aqui e vamos juntos em busca de uma comunidade melhor!1 ponto
-
[8.60] DBRelated 1.2 Site + Data + Sources
[8.60] DBRelated 1.2 Site + Data + Sources
Ackerzin reagiu a .HuRRiKaNe por uma resposta no tópico
1 pontoInformações: Diversas Transformações como Goku GodMode, Golden Freeza, Bills entre outras! Novos sistemas! Mapa próprio! Reborn System! Diversas Quests! Diversos Items! E mais! Imagens: Download: Mediafire Scan: https://www.virustotal.com/pt/file/82bf4689784c5459e240d0ba7fd15e28b5ab8f2253c885d43aeaa875b07ded11/analysis/1437840718/ Distro(Executavel + DLL's) By Animal Pak: Download Scan: https://www.virustotal.com/pt/file/ffd037b5dfa3c6e5529490e460d075da3b4c24e8a230671a7d0c11f0dbc6d8d4/analysis/1438323955/ Créditos: DBRelated Team Animal Pak1 ponto -
Criando um mod simples
Criando um mod simples
gmstrikker reagiu a Snowsz por uma resposta no tópico
1 pontoNeste tutorial espero ensina-los a criar um mod simples, composto por uma janela e um botão, para ativa-la e desativá-la. O mod deve ficar mais ou menos assim: • Entre na pasta mods do seu otclient, e crie um arquivo com um nome quaisquer, como por exemplo, o nome que quer para seu mod, o meu, vou chamar de "tutorial". • Dentro da pasta criada, crie um novo arquivo com extensão "otmod", coloque o nome do seu mod nele, eu vou colocar o nome de "tutorial", ficando "tutorial.otmod": • Dentro do seu arquivo de extensão "otmod" adicione o seguinte código: Module name: description: author: website: version: autoload: autoload-priority: scripts: [ ] @onLoad: @onUnload: • Explicando Dai você me pergunta por que isso está identado dessa forma? Module name: Com dois espaços antes de "name:"? Porque "Module" é uma declaração do tipo de arquivo que está sendo utilizado, já o "name:", é um componente do "Module", por isso, ele deve estar dentro de "Module", caso contrário, poderá ocorrer erros. Nesta linha: Module Ele está declarando que este arquivo é um modulo, uma modificação para seu client. Nesta linha: name: Aqui, estará sendo declarado o nome do seu módulo, eu vou colocar o nome "Tutorial": name: Tutorial Ao clicar no gerenciador de módulos, ele irá mostrar o seu mod com o nome escolhido: Nesta linha: description: Aqui, entrará a descrição do seu mod, por exemplo: description: Um mod simples. Irá mostrar mais ou menos assim: Nesta linha: author: Entrará o seu nome, ou seja, o nome de quem criou o mod(autor óbvio), por exemplo: author: Snowsz Ficaria mais ou menos assim: Nesta linha: website: Você pode declarar o seu site, por exemplo: website: tibiaking.com Ficaria mais ou menos assim: Nesta linha: version: Você pode colocar a versão do seu mod, por exemplo: version: 1.0 Ficaria mais ou menos assim: A parte com explicação gráfica terminou ! Nesta linha: autoload: Será determinado se o seu mod irá ser carregado automaticamente, por exemplo: Exemplo 1: autoload: false Assim, seu mod só irá ser carregado manualmente, você terá que ir no gerenciador de módulos e clicar em carregar para inciar seu mod. Exemplo 2: autoload: true Assim, seu mod só irá ser carregado automaticamente, sem a necessidade de clicar para ser carregado. Nesta linha: autoload-priority: Será determinada a prioridade de carregamento do seu mod, "Como assim?", é simples, ele irá carregar antes ou depois de outro mod, isso determina em que posição de carregamento seu mod deve estar, como por exemplo, em primeiro lugar , um exemplo de prioridade: autoload-priority: 1000 Acho que não tem nenhum mod com essa prioridade? Hehe, será um dos primeiros a carregar! Nesta linha: scripts: [ ] Será determinado os scripts carregados pelo seu módulo, os scripts usado por ele, por exemplo: scripts: [ tutorial ] Ele irá busca um arquivo com o nome tutorial.lua na mesma pasta que ele estiver, e carregará tudo que tem dentro daquele arquivo. Nesta linha: @onLoad: Será determinado que função o seu mod irá chamar ao iniciar, por exemplo: @onLoad: print("Hello World!") Irá mostrar uma mensagem no seu terminal do otclient. Por fim, nesta linha: @onUnload: Será determinado que função o seu mod irá chamar ao ser descarregado, ao se desligar, por exemplo: @onUnload: print("Bye World! ;(") Irá mostrar uma mensagem no seu terminal do otclient. Bom, a configuração que usaremos no nosso mod simples será essa: Module name: Tutorial description: Um mod simples. author: Snowsz website: tibiaking.com version: 1.0 autoload: true autoload-priority: 1000 scripts: [ tutorial ] @onLoad: init() @onUnload: terminate() Mexa apenas no que souber Na pasta do seu mod, crie um novo arquivo, com o nome "tutorial", ele deverá conter a extensão "lua", ficando "tutorial.lua", que é o arquivo de script setado no nosso "tutorial.otmod": scripts: [ tutorial ] Dentro dele, coloque o seguinte código: function init() tutorialWindow = g_ui.displayUI('tutorial.otui') tutorialWindow:hide() tutorialButton = modules.client_topmenu.addRightButton('tutorialButton', tr('Exemplo'), 'icone', onoff, true) end function terminate() tutorialWindow:hide() end function onoff() if tutorialWindow:isVisible() then tutorialWindow:hide() else tutorialWindow:show() end end A função "init()" é a função chamada pelo seu mod, ao iniciar, a função "terminate()", é chamada pelo seu mod, ao ser desligado. Na função "init()", em uma de suas linhas podemos encontrar isso: tutorialWindow = g_ui.displayUI('tutorial.otui') Onde tem "tutorialWindow", está sendo declarado uma variável global, um iniciante em lua deve saber o que é, então não vou explicar. Dentro de tal variável, há uma função, "O que essa função faz?", ela executa os elementos contidos em um arquivo, que seria os arquivos de extensão "otui", nela, estaremos executando o "tutorial.otui". Nesta linha: tutorialWindow:hide() Ele executa uma função na variável "tutorialWindow", que seria uma função para esconder a janela, pois, o que estava contido no "tutorial.otui" seria uma janela que criaremos logo logo. Nesta linha: tutorialButton = modules.client_topmenu.addRightButton('tutorialButton', tr('Exemplo'), 'icone', onoff, true) Está sendo declarado uma variável global, nela, está contido a referencia de uma função, que seria um botão adicionado ao lado direito do menu, exemplo: Utilizei a imagem de ícone do otclient para demonstração. Explicando a função: Sua base é essa: modules.client_topmenu.addRightButton(id, description, icon, callback, front) • Id: Será o id dado ao botão, para melhorar o acesso. • Description: É a descrição do botão, ao passar o mouse em cima, aparecerá um texto. • Icon: É a imagem do botão, como a que eu utilizei no exemplo, usei o ícone do otclient. • Callback: É uma função chamada ao clicar nele. • Front: Define se o botão será adicionado na frente ou atrás dos demais botões do seu menu. Explicando a função "terminate()", na sua única linha podemos encontrar isso: tutorialWindow:hide() É o seguinte, ao seu mod descarregar, ele irá esconder sua janela criada. Explicando a função "onoff()", nas suas linhas podemos encontrar isso: if tutorialWindow:isVisible() then tutorialWindow:hide() else tutorialWindow:show() end Mas bem, o que isso faz? Simples, "tutorialWindow:isVisible()", ele checa se a janela está visível, se estiver, ele irá esconde-la "tutorialWindow:hide()", caso a janela não esteja visível, ele irá mostra-la "tutorialWindow:show()", essa é a utilidade da função utilizada no botão do menu. Agora, na pasta do seu mod, crie um novo arquivo, com o nome de "tutorial", a extensão dele deve ser "otui", ficando "tutorial.otui", dentro desse arquivo, adicione isso: MainWindow id: tutorialwindow height: 255 width: 438 !text: tr("Mod simples") Explicando: • "MainWindow", seria o objeto que irá ser utilizado pelo arquivo, no caso, uma janela. • "id", o id, estaria setando um id para a sua janela. • "height", seria a altura da sua janela, do "MainWindow". • "width", seria a largura da sua janela, do "MainWindow". • "!text", seria o texto inserido como título de sua janela, a função chamada nele "tr()", chama uma tradução para aquela frase, caso não tenha ficaria aquilo mesmo, caso tenha, iria mudar para outro texto traduzido. Bom gente, espero que tenham gostado do tutorial, eu não sou bom com tutoriais... Se tiver me perdido peço desculpas, qualquer erro podem postar aqui que irei corrigir, se eu tiver me enrolado em algo, me desculpem, dei várias pausas enquanto fazia isso kk', espero que tenham entendido tudo. Créditos: Snowsz1 ponto
Líderes está configurado para São Paulo/GMT-03:00