Ir para conteúdo
  • Cadastre-se

c++ [C++] TFS 1.2 / OTX Server 3 New Npc Currency System


Posts Recomendados

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;
}

 

Editado por Codex NG (veja o histórico de edições)
Link para o post
Compartilhar em outros sites
  • 2 weeks later...
  • Respostas 5
  • Created
  • Última resposta

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

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.

Parabéns, seu tópico de conteúdo foi aprovado!
Muito obrigado pela sua contribuição, nós do Tibia King agradecemos.
Seu conteúdo com certeza ajudará à muitos outros, você recebeu +1 REP.

  Mostrar conteúdo oculto

 

Link para o post
Compartilhar em outros sites
  • 2 weeks later...

  @Codex NG  Hiho men if im using otx 2.x and i edit these sources files i will upgrade my otx 2 to 3 npc system?wait for u reply nice tuto

 

Link para o post
Compartilhar em outros sites
  • 4 weeks later...
  Em 18/10/2016 em 05:43, Pastabase disse:

  @Codex NG  Hiho men if im using otx 2.x and i edit these sources files i will upgrade my otx 2 to 3 npc system?wait for u reply nice tuto

 

Expand   Mostrar mais  

If it works on otx2 then yes it will work on otx3, it also works on TFS 1.2/1.3

 

Some aspects of the sources haven't changed since 0.3, so you might even be able to use this code as far back as then of course you will need to make code adjustments. But i don't see why it can't be done.

Editado por Codex NG (veja o histórico de edições)
Link para o post
Compartilhar em outros sites

Participe da conversa

Você pode postar agora e se cadastrar mais tarde. Se você tem uma conta, faça o login para postar com sua conta.

Visitante
Responder

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emojis são permitidos.

×   Seu link foi automaticamente incorporado.   Mostrar como link

×   Seu conteúdo anterior foi restaurado.   Limpar o editor

×   Não é possível colar imagens diretamente. Carregar ou inserir imagens do URL.

  • Quem Está Navegando   0 membros estão online

    Nenhum usuário registrado visualizando esta página.

  • Conteúdo Similar

    • Por KekezitoLHP
      Nome: Fist Fighting/Attackspeed
      Tipo: C++
      Autor: Oneshot
       
      Já vi alguns pedidos no fórum sobre a skill Fist Fighting, onde quanto mais você treinasse ela, mais rápido você atacaria no jogo, e parece que isto é um feature do Tibia. Como é uma modificação muito fácil nas sources, resolvi passar aí para a galera.
      Por padrão, o intervalo entre ataques do Tibia é 2000ms, ou seja, um ataque físico a cada dois segundos. Eu fiz uma pequena modificação nas sources onde o Fist Fighting seria inversamente proporcional ao tal intervalo, ou seja, quanto maior o valor da skill, menor seria o intervalo.

      Fiz de um modo que um jogador com Fist Fighting de nível 200, então, teria uma redução de 75% no intervalo de ataque, ou seja, um ataque a cada meio segundo ou dois ataques por segundo

      Leve em consideração que ele pega como base o attackspeed da vocação ou da arma usada, ou seja, se seu servidor já tem o tal chamado "fast attack", de nada adianta adicionar esse código C++.
       
       
      Abra seu player.cpp, procure por isso:
      Player::getAttackSpeed() Substitua toda a função, dependendo da versão de seu servidor:
       
      0.3.6
      uint32_t Player::getAttackSpeed() {     Item* weapon = getWeapon();     if(weapon && weapon->getAttackSpeed() != 0)         return std::ceil(weapon->getAttackSpeed() * (1 - (getSkill(SKILL_FIST, SKILL_LEVEL) * 0.00375)));     return std::ceil(vocation->getAttackSpeed() * (1 - (getSkill(SKILL_FIST, SKILL_LEVEL) * 0.00375))); } 0.4
      uint32_t Player::getAttackSpeed() const {     return std::ceil(((weapon && weapon->getAttackSpeed() != 0) ? weapon->getAttackSpeed() * (1 - (getSkill(SKILL_FIST, SKILL_LEVEL) * 0.00375)) : (vocation->getAttackSpeed() / std::max((size_t)1, getWeapons().size()) * (1 - (getSkill(SKILL_FIST, SKILL_LEVEL) * 0.00375))))); } Isso adiciona uma utilidade para a skill Fist Fighting que em muitos dos servidores é algo deixado de lado e inútil.
    • Por tataboy67
      Dungeon System v1.1

      A pedido de um usuário em meu Discord, resolvi ajuda-lo e desenvolver um sistema totalmente interativo e de qualidade aqui para vocês.
      Bom, o sistema se baseia em uma ActionID que ao clicar, podemos ai entrar em uma dungeon, tendo tempo para finaliza-la e até um cooldown, caso queira entrar novamente.

      Imagens do sistema:
       

      Vamos ao Código:

      Em actions, crie um arquivo com o nome de: Dungeon Actions.lua
       
      Em creaturescripts, crie um arquivo com o nome de: Dungeon Creaturescript.lua
       
      Ainda em creaturescripts, crie outro arquivo com o nome de: Type Dungeon Creaturescript.lua
       
       Na LIB, crie um arquivo com o nome de Dungeon System Lib.lua, e adicione:
       
      Em creaturescripts.xml, adicione:
       
       
      Em actions.xml, adicione:
       Em libs.lua, adicione:
      dofile('data/lib/Dungeon System Lib.lua')  
      v1.1 (Nova atualização, agora pode spawnar mobs dentro da DG, e ao sair, eles são removidos)

      (CREDITOS TOTAIS A MIM: @tataboy67)

      Essa é a primeira versão. Ainda pretendo colocar para nascer mobs, remover mobs ao entrar, etc etc...
       
    • Por Leohige
      The Ruby Server - Base Pokémon
      Ao olhar as diversas bases que podem ser encontradas aqui no fórum e em outros locais da internet, pude ver que todas elas carecem de qualidade. Todas estas bases são feitas utilizando gambiarras para diversos sistemas funcionarem, e com isso vários problemas surgem, como de sistemas que não funcionam direito, e o mais importante, com um desempenho extremamente baixo, gerando apenas servidores instáveis. Com isso eu decidi que iria começar a desenvolver uma base para servidores relacionados a Pokémon, com dois objetivos. Um dos objetivos é ganhar mais conhecimento em cima da linguagem de programação C++, o outro objetivo é disponibilizar uma base completamente estável, funcional e de fácil configuração e desenvolvimento para servidores de Pokémon, para que mais ótimos trabalhos possam surgir. Este projeto também irá incluir um cliente próprio e estável, junto com um website.
       
      Também planejo criar uma espécie de Wiki para o servidor, cliente e website, com o objetivo de auxiliar quem for desenvolver em cima deste servidor, e também aqueles que pouco entendem do assunto relacionando a criação de escripts, Pokémon, spells e etc.
       
      Alguns poucos sistemas foram implementados no servidor por ora. Sistemas como o de catch e de goback serão implementados mais para frente, quando outros sistemas forem completamente implementados, como o sistema de configuração de Pokeballs, criação de Pokémons e sistema de shinys. Estou visando a qualidade do servidor como um todo, por isso algumas coisas irão demorar para aparecer.

      O sistema de Pokeballs e de criação de Pokémon já está bem encaminhado, e um sistema de gêneros também já está pronto com fácil configuração, onde o spawn destes Pokémon com sexo será por % igual aos jogos da franquia. Um sistema de surgimento de Ditto aleatório já está praticamente implementado, onde um Pokémon aleatório pode ser um Ditto disfarçado.
       
      [+] Informações do Servidor
      Baseado em: TFS 1.3
      Protocolo: 10.98
       
      [+] Informações do Client
      Baseado em: otclient 0.6.6

      [+] Informações do Website
      Baseado em: nenhum
      Desenvolvido em: PHP (por ser o mais comum na comunidade)
       
      Como contribuir?
      Eu gostaria muito que a comunidade ajudasse no desenvolvimento deste projeto, pois o mesmo será disponibilizado para todos, e para contribuir não necessariamente é preciso entender de programação. Você pode também ajudar testando e reportando os bugs encontrados no repositório do projeto no GitHub, assim como com sugestões e ideias de mudança/implementação no servidor através do próprio repositório ou através do Discord, ou ajudar na criação de guias para o website do projeto.
       
      Links
       
      [+] RubyServer - GitHub
      https://github.com/rubyserver/rubyserver
       
      [+] RubyClient - GitHub
      https://github.com/rubyserver/rubyclient
       
      [+] RubyServer - Website
      https://rubyserver.github.io/rubyserver/
       
      [+] RubyServer - Discord
      https://discord.gg/XTrZGpy
       
      Algumas Imagens
       
       
       
       
       
    • Por KotZletY
      Salve geral, recentemente fiz um Task System para meu servidor, então gostaria de compartilha ele com vocês, assim como outros scripts que fiz e gostaria de compartilhar. Bom, vamos ao que interessa.
                        
       
                                                                                                               Informações!!
      Task Normal - Você 1x por vez, quantas vezes quiser, repetindo a task se também quiser.
      Task Diaria -  Você faz uma vez por dia, não podendo repeti em quanto as 24 horas não terminar.
      Task Rank - É mostrado na descrição do player qual rank task ele possui.
      Task Rank Quest - Um extra desse task system é o piso task, será explicado na parte do script, leiam com atenção.
      Task Comandos - Comandos task, 1 para ver o progresso das suas task e outro para mostrar informações do seu personagem, como uma consulta, os comandos são: !task que mostra quais task você ta fazendo, tanto diaria quanto normal e !task me que mostrar informações do seu personagem, como rank, quantidade de pontos task e quantidade de pontos task rank.
      Well, o resto é surpresa, cabe você descobrir! xD
       
       
      Para não ficar só nas palavras, mostrarei algumas imagens, várias no caso: Removida, colocarei novas!
       
                                                                                                               Instalação!!
      Muito bem, chega de conversa, como instalar logo essa bagaça. Primeiramente vá em data/lib e abra o arquivo lib.lua e adicione:
      dofile('data/lib/task system.lua') Ainda na pasta lib crie um arquivo.lua chamado task system.lua e adicione esse code dentro:
       
      No final do tópico, ensinarei a configurar a lib. Agora vai em, data/npc e crie um arquivo.xml chamado  task.xml e coloque esse code dentro:
      <?xml version="1.0" encoding="UTF-8"?> <npc name="NPC Task" script="task system.lua" walkinterval="0" floorchange="0"> <health now="150" max="150"/> <look type="430"/> <parameters> <parameter key="message_greet" value="Hello |PLAYERNAME|. I'm in charge of delivering missions to the players. Would you like to do a {normal} task, {daily} task, {receive} your reward from a task or {abandon} a task ? You can also see the {normal task list} and the {daily task list}."/> <parameter key="message_farewell" value="See you later." /> <parameter key="message_walkaway" value="See you later." /> </parameters> </npc> Ainda na pasta npc, entre na pasta scripts e crie um arquivo.lua chamado task system.lua e adicione esse code dentro:
       
      Agora vá em data/talkactions e abra o arquivo talkactions.xml e adicione a seguinte tag:
      <talkaction words="!task" separator=" " script="task system.lua" /> Ainda na pasta talkactions entre na pasta scripts e crie um arquivo.lua chamado task system.lua e adicione esse code dentro dele:
       
      Agora vá em data/creaturescripts e abra o arquivo creaturescripts.xl e adicione a seguinte tag:
      <event type="kill" name="tasksystem" script="task system.lua"/> Ainda na pasta creaturescripts entre na pasta scripts e crie um arquivo.lua chamado task system.lua e adicione esse code dentro dele:
      Ainda na pasta script  abra o login.lua e adicione dentro:
      player:registerEvent("tasksystem") Agora vá em data/events/scripts e abra o arquivo player.lua, depois de aberto, antes de:
      self:sendTextMessage(MESSAGE_INFO_DESCR, description) adicione:
      if thing:isCreature() then if thing:isPlayer() then description = string.format("%s\nTask Rank: "..getRankTask(thing), description) end end  
                                                                                              Extra(Opcional)!!
       
      Extra,  vá em data/movements/scripts e crie um  arquivo chamado tile task.lua, depois de aberto, antes de:
            
      Vá em data/movements/movements.xml adicione: 
      <movevent event="StepIn" actionid="XXXX" script="tile task.lua"/>  
      Explicação: Com esse movements acima, você só poderá passar por o piso caso tenha pontos task necessário para passar, se ativar a opção, removePoints então a mesma quantidade de pontos necessária para passar, será removida, ao passar, caso esteja desativada, então
      apenas será necessário ter os pontos task para passar. Em XXXX coloque o actionid, e o actionid coloque no piso desejado!
       
      New Extra: Vá em data/movements/scripts e crie um arquivo chamado tile task2.lua e adicione o seguinte scripts:
       
      Vá em data/movements/movements.xml adicione:  
      <movevent event="StepIn" actionid="XXXX" script="tile task2.lua"/> Explicação: Ao adicionar esse movements acima, você só poderá passar pelo piso caso seu rank task seja igual ou superior ao rank definido na variável, caso não seja igual e nem superior, não será possível passar.
      Configure na lib, a sequência de ranks de acordo com a sequência de rank da tabela de pontos, assim:
       
      A sequência precisa está igual e numeradas.
                                                                                               Configurando!!
      task_monsters = { [1] = {name = "monster1", mons_list = {"monster_t2", "monster_t3"}, storage = 30000, amount = 20, exp = 5000, pointsTask = {1, 1}, items = {{id = 2157, count = 1}, {id = 2160, count = 3}}}, [2] = {name = "monster2", mons_list = {"", ""}, storage = 30001, amount = 10, exp = 10000, pointsTask = {1, 1}, items = {{id = 10521, count = 1}, {id = 2160, count = 5}}}, [3] = {name = "monster3", mons_list = {"", ""}, storage = 30002, amount = 10, exp = 18000, pointsTask = {1, 1}, items = {{id = 2195, count = 1}, {id = 2160, count = 8}}}, [4] = {name = "monster4", mons_list = {"", ""}, storage = 30003, amount = 10, exp = 20000, pointsTask = {1, 1}, items = {{id = 2520, count = 1}, {id = 2160, count = 10}}} } task_daily = { [1] = {name = "monsterDay1", mons_list = {"monsterDay1_t2", "monsterDay1_t3"}, storage = 40000, amount = 10, exp = 5000, pointsTask = {1, 1}, items = {{id = 2157, count = 1}, {id = 2160, count = 3}}}, [2] = {name = "monsterDay2", mons_list = {"", ""}, storage = 40001, amount = 10, exp = 10000, pointsTask = {1, 1}, items = {{id = 10521, count = 1}, {id = 2160, count = 5}}}, [3] = {name = "monsterDay3", mons_list = {"", ""}, storage = 40002, amount = 10, exp = 18000, pointsTask = {1, 1}, items = {{id = 2195, count = 1}, {id = 2160, count = 8}}}, [4] = {name = "monsterDay4", mons_list = {"", ""}, storage = 40003, amount = 10, exp = 20000, pointsTask = {1, 1}, items = {{id = 2520, count = 1}, {id = 2160, count = 10}}} }                                        
                                                    
      nome - Nome do monstro.
      mons_list - Nome dos monstro que são semelhantes e que matando eles também contará.
      Exemplo:
      name = "troll", mons_list = {"troll","frost troll","island troll"} e assim matando,  troll, frost troll e island troll contará na task também.
      storage - É a storage que salva a quantidade de monstros já matados.
      amount - É a quantidade necessária de monstros matados para finalizar a task.
      exp - É a quantidade de Experiência que vai ganhar ao finalizar a task, caso não queira dar experiência, basta deixar em 0.
      pointsTask = {Task Points Que vai ganhar(Pontos usado no piso e etc..), Pontos Rank, que irá ganhar e aumentar seu rank.}
      items - Itens que o player vai ganhar, devem está tabelados, dentro da tabela item, adicione das tabelas contendo o id do item e count, quantidade de items que irá ganhar.
      Ex: items = {{id = 2157, count = 1}, {id = 2160, count = 3}} -- Aqui contém 2x tipos de itens, o 2157 e o 2160, e suas devidas quantidades que irá ganhar.
      items = {{id = 2157, count = 1}} -- Aqui só tem 1 tipo de item e a quantidade que vai ganhar.
      Adicione quantos itens quiser. O mesmo vale para as task diarias!
       
       
       
      Bom, é isso ae, qualquer duvida, crítica, sugestões, deixem ae, se precisa de suporte na instalação ou está com erro em algo estarei dando suporte, abraços e bom uso do sistema.
      É totalmente proibido leva meu sistema para outro site, blog ou fórum!
    • Por celohere
      Esse é o tfs downgraded pelo Ninja da Otland , eu fiz umas mudanças pra deixar ele mais legal (na minha opinião) . E agora eu quero disponibilizar pra todos esse download , com a intenção de contribuir pelo menos um pouco com a comunidade. Eu apenas quero avisar que não sou um programador profissional , e talvez eu tenha feito alguma ***** , mas até o momento nao encontrei nenhum bug crítico.Eu não sei se esse server é estável pq nao cheguei a por ele online , enfim todos os créditos vão para o Ninja da Otland pelo downgrade ,para o tfs team pelo distro em si e pra mim Celohere por essas alterações.
       
      Changelog
       
      Bugs
       
      algumas fotos do servidor rodando:
       
      EDIT:
      novo link:
      fixed crash on re-login -- credits to danielsalim1 and mattyx14 --
      fixed monster walk dashing -- credits to me --
      EDIT 2:
      fix players login in the same sqm
       
      EDIT 3:
      fixed runes stack on full container bug -- crédits to me --
      eu criei um repositório no github ,se alguem quiser reportar algum bug ou quiser me ajudar com algum fix ,sera muito bem vindo
      https://github.com/celohere/tfs-1.2-8.0
       
      EDIT 4:
      mais algumas modificações
      fixed use of lifefluid on hotkeys -- crédits to me --
      fixed fluid wrong message on hotkeys -- crédits to danielsalim1 --
      added auto recharge ammo ( arrows e bolts recarregam automaticamente agora) -- crédits to Joe Rod and Emilianenko --
      added player ban (agora o ban por excessive player killing esta banindo apenas o jogador, e nao a conta inteira ) -- crédits to Gesior.pl --
       
      EDIT 5:
      Fixed container queryAdd issues -- Crédits to Nekiro --
      Fixed push the last creature from stack -- crédits to Jhon_ and Emilianenko --
      Fixed a crash related to houses -- crédits to DSpeichert --
       
      EDIT 6: 
      novo link atualizado
      as modificações podem ser vista no changelog
       
      tfs_8.0-master.rar
  • Estatísticas dos Fóruns

    96845
    Tópicos
    519598
    Posts



×
×
  • Criar Novo...

Informação Importante

Confirmação de Termo