-
Quem Está Navegando 0 membros estão online
Nenhum usuário registrado visualizando esta página.
-
Conteúdo Similar
-
Por Underewar
Tutorial: Criando um Sistema de Enviar efeito com OTClient.
Neste tutorial, vamos criar um sistema simples de Enviar efeito no OTClient.
Este sistema permitirá que os jogadores ativem um efeito especial e vejam uma janela ao clicar em um botão específico.
Pré-requisitos:
Ambiente de Desenvolvimento:
Certifique-se de ter um ambiente de desenvolvimento configurado com OTClient Edubart. Conhecimento Básico em Lua:
Familiaridade com a linguagem de script Lua.
Passo 1: Estrutura do projeto
Organize seu projeto conforme abaixo:
OTC / MODS
Passo 2: Criando a Interface Gráfica (OTUI)
game_pass.otui
Repare que em nossa interface nossos botões de ação entram no caminho do module e iniciam uma função que esta disponivel em nosso game_pass.lua (Client-Side)
Passo 3: Criando funções Client-Side
Agora com as funções criada podemos chamar elas de acordo com a necessidade em nosso arquivo de interface.
Por exemplo a função effect() que foi chamada em nosso arquivo de interface.otui agora é criada aqui para mostrar o efeito ao jogador.
game_pass.lua
Passo 4: Registrando o novo Mod
Agora podemos registrar e iniciar nosso modulo usando o arquivo de configuração
game_pass.otmod
Feito isso ja podemos ver nosso module no client e enviar opcodes através do gameprotocol e também receber o buffer para manipular os dados podemos utilizar :
protocolGame:sendExtendedOpcode(14, "1")
Basicamente oque estamos fazendo é armazenando o valor 1 na variaval 14 do ExtendedOpcode e futuramente podemos recuperar esse valor.
Recuperamos esse valor em nosso server side data/creatuerscript/otc/game_pass.lua
Verificando se o opcode é 14 se for 14 então fazemos x ação.
Show, tendo isso em mente para que o nosso client-side consiga receber com sucesso o efeito enviado ao jogador então utilizamos
Passo 5: Criando o Server-side responsavel por enviar o efeito correto ao jogador dependendo do opcode selecionado no nosso cliente.
data/creaturescripts/otc/game_pass.lua
Passo 6: Registrando o evento para evitar erros futuros!
Para que tudo funcione corretamente sem erros é necessário registrar o evento no creaturescript.xml / login.lua
creaturescript.xml
<event type="extendedopcode" name="GamePass" script="otc/game_pass.lua" />
login.lua
player:registerEvent("GamePass")
Ótimo agora ao selecionar o menu recompensa o jogador recebera um efeito.
Espero que tenha ficado claro como usar Opcodes/ExetendedOpcodes.
Arquivos usados no tutorrial:
OTC MODULE
game_pass.rar
Creaturescript
game_pass.lua
Vi muitos tutoriais desatualizado então resolvi trazer esse!
Reparem que nesse caso passamos creature como parametro do buffer isso porque precisamos enviar um efeito no player.
Melhorando a formatação com JSON Encoder
-
Por Codex NG
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.cpp
Look 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.h
Look 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.cpp
Find 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.h
Look 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; }
-
Por Mateus Robeerto
este é um tutorial de como usar um cliente com spr/dat estendido e protegido pelo CAB.
fiz um video mostrando como usar um client com spr/dat estendido sem o error, basta seguir passo a passo o que eu fiz, em resumo voce precisara copiar seu dat estendido pra outro local para poder editar ele, salvando ele como não estendido e dps renomeando para poder usar junto com o original e compilando tudo com o programa cab...
A DLL ajuda o cliente a ler as 2 dat (compilada pelo programa cab) , sem ela o cliente não abre, caso o teu cliente tenha o bug do ctrl+n ou alguns outros bugs que eu vi em alguns casos, a DLL tem a função de arrumar a maioria deles.
LINK DOWNLOAD
https://www.mediafire.com/file/kxqkywxeijk8hn2/programa_para_oldclient.rar/file
ou
creator cab
https://drive.google.com/file/d/19b-EqpS-RmOQ_1o7ubb2a7j6RKcijjUa/view?usp=sharing
scan https://www.virustotal.com/gui/file/4398e414d680ac26addbedc1f20bd59a82b546a1633abbb02b13d2f7150e950e/detection
DLL
https://drive.google.com/file/d/1T8XgwgHJAO9sgw5WR809GjMfej2NvP3n/view?usp=sharing
SCAN https://www.virustotal.com/gui/file/539f0f7187c668457a14d87603e075ab5d1b6f6ac6a17aabf2b591fc3c177741/detection
stup-pe hoohar o client
https://drive.google.com/file/d/1cwR1wj3M8IsvxmIt5pQhZ4-DlFSMQVal/view?usp=sharing
scan https://www.virustotal.com/gui/file/d06889d61474ee9480947956e52916fb997a3717e9f59d3ed830b5c780e81340/detection
-
Por DeCarvalho
Bem procurei aqui na comunidade um VIP System mais informativo e nada, além de ter tido problema com os que estão aqui e acabei achando em outro lugar um que funcionou perfeitamente para mim.
Usando tfs disponibilizado neste tópico http://www.tibiaking.com/forum/topic/53099-1078-tfs-12-cast-system-novos-outfits-mounts/
Só estou trazendo o conteúdo e por não conhecer bem não posso dar suporte mas do jeito que está é só 'instalar' e vai funcionar.
Creditos.: Summ
Sistema Vip
Talkaction !checkvip para todos os players
Talkaction /vip para membros da staff
- /vip adddays, NomedoPlayer, 5 --> Adiciona 5 dias vip para o Player. - /vip removedays, NomedoPlayer, 5 --> Remove 5 dias vip do Player. - /vip remove, PlayerName --> Remove todos os dias vip do Player. - /vip check, NomedoPlayer --> Checa quantos dias vip o Player tem. - /vip addinfinite, NomedoPlayer --> Adiciona tempo vip infinito para o Player.
Tiles VIP
Portas VIP / Actions
Items que adicionam dias VIP
ItemId 10135 adiciona 10 dias vip. ItemId 10134 adiciona 30 dias vip. ItemId 10133 adiciona 90 dias vip.
Imagens
Comando !checkvip mas sem ter vip
Comando /vip adddays, dracoknight, 5
Comando !checkvip após adicionar 5 dias
Comando /vip addinfinite, dracoknight
Comando !checkvip após usar infinite
Comando /vip remove, dracoknight
-
Por Diego767
Boa tarde, nao sei se estou no lugar certo para fazer a pergunta, mas vamos tentar...
Meu ot esta rodando bem, porem os itens e monstros mais novos nao tem (cobra sword, terra helmet, e nem os monstros que dropam isso)
O que eu poderia fazer para add eles, os itens e os monstros?
-