• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

TFS 1.4.2 more currencies

Dercas

Active Member
Joined
Nov 15, 2008
Messages
88
Reaction score
29
Hi all,

Perhaps someone find this useful... I've made some simple changes in the TFS source that allow players to use more than 1 type of coins at NPC shops. I'm working on LOTR/Middle-earth server & we're planning to make different currencies:
-> Mans
-> Elfs
-> Dwarfs
-> hobbits
->possibly even more...
In the below changes each race currency will be worth the same. 1 Man coin is equal to one Elf coin and one dwarf coin. The only difference will be the rarity.

We've tested this on TFS 1.4.2 at NPC shops only - if you have 100 gold coins and 100 dwarf coins, the NPC will read that you got 200 gold in total and you can purchase things up to 200 gold coins.
If you sell at NPC, for example, a sword (or any other item), you will have 95% chance to get a gold coin and 5% chance to get a dwarf coin.
We have't added Elf coins so far (just Dwarfs for testing) but if someone wants to have more than 2 currencies then you could figure out how to do it, it's not difficult.

Open const.h and look for:
Code:
ITEM_GOLD_COIN = 2148,

Add below whatever currencies you wish, in my case it's Dwarf coin (+ plans for the future already added in the code ;) )
It's obviously
ITEM_ the_name = server Item ID,


Code:
ITEM_GOLD_COIN = 2148,
    ITEM_DWARF_COIN = 26384,

    //ITEM_ELF_COIN =
    //ITEM_MAN_COIN =
    //ITEM_HOBBIT_COIN =


    ITEM_PLATINUM_COIN = 2152,
    //ITEM_DWARF_COIN_1 =
    //ITEM_ELF_COIN_1 =
    //ITEM_MAN_COIN_1 =
    //ITEM_HOBBIT_COIN_1 =


    ITEM_CRYSTAL_COIN = 2160,
    //ITEM_DWARF_COIN_2 =   
    //ITEM_ELF_COIN_2 =
    //ITEM_MAN_COIN_2 =
    //ITEM_HOBBIT_COIN_2 =


    ITEM_STORE_COIN = 24774, // in-game store currency

You can use the script for alternatives of either gold coins, platinum coins, crystal coins. Remember that you can't name two coins the same. There must be different name (by even adding _2 or _3 at the end - as above).

Go to item.cpp & find
Code:
 uint32_t Item::getWorth() const

& Add your coins inside:

Code:
 uint32_t Item::getWorth() const
{
    switch (id) {
        case ITEM_GOLD_COIN:
            return count;

        case ITEM_DWARF_COIN:
            return count;

        case ITEM_PLATINUM_COIN:
            return count * 100;

        case ITEM_CRYSTAL_COIN:
            return count * 10000;

        default:
            return 0;
    }
}

Simply copy paste Gold Coin (or platinum or crystal), paste and change the name of the coin.


Go to luascrip.cpp
find:
Code:
    registerEnum(ITEM_GOLD_COIN)

and add your currency below:

Code:
    registerEnum(ITEM_DWARF_COIN)


Then go to player.cpp and find:
Code:
bool Player::updateSaleShopList(const Item* item)

& add your currency the same way as other currencies are added - "&& itemId != ITEM_DWARF_COIN"

Code:
bool Player::updateSaleShopList(const Item* item)
{
    uint16_t itemId = item->getID();
    if (itemId != ITEM_GOLD_COIN && itemId != ITEM_DWARF_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);
            });
        }
    }


Now, go to game.cpp & find:
Code:
 void Game::addMoney(Cylinder* cylinder, uint64_t money, uint32_t flags /*= 0*/)


& replace with:

Code:
void Game::addMoney(Cylinder* cylinder, uint64_t money, uint32_t flags /*= 0*/)
{
    if (money == 0) {
        return;
    }


    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(1, 100); 


    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) {
        if (dis(gen) <= 95) {
            Item* goldCoin = Item::CreateItem(ITEM_GOLD_COIN, money);
            ReturnValue ret = internalAddItem(cylinder, goldCoin, INDEX_WHEREEVER, flags);
            if (ret != RETURNVALUE_NOERROR) {
                internalAddItem(cylinder->getTile(), goldCoin, INDEX_WHEREEVER, FLAG_NOLIMIT);
            }
        }
        else {
            Item* dwarfCoin = Item::CreateItem(ITEM_DWARF_COIN, money);
            ReturnValue ret = internalAddItem(cylinder, dwarfCoin, INDEX_WHEREEVER, flags);
            if (ret != RETURNVALUE_NOERROR) {
                internalAddItem(cylinder->getTile(), dwarfCoin, INDEX_WHEREEVER, FLAG_NOLIMIT);
            }
        }
    }
}

You can change the % chance of getting standard coin here:
Code:
 if (dis(gen) <= 95)
95 is 95% for a standard gold coin. Meaning 5% is for a dwarf coin.


We've got experimental version for Crystal/PLatinum coins too (with shorter script/logics) but this has not been tested yet... The above (long, a bit ugly script) works so we share it. The below one is waiting for us to have some time to work on it further & can't guarantee it's working as it is.

Code:
uint32_t crystalCoins = money / 10000;
money -= crystalCoins * 10000;
while (crystalCoins > 0) {
    const uint16_t count = std::min<uint32_t>(100, crystalCoins);

    Item* remaindItem = nullptr;
    if (dis(gen) <= 95) {
        remaindItem = Item::CreateItem(ITEM_CRYSTAL_COIN, count);
    } else {
        remaindItem = Item::CreateItem(ITEM_DWARF_COIN_2, 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 = nullptr;
    if (dis(gen) <= 95) {
        remaindItem = Item::CreateItem(ITEM_PLATINUM_COIN, platinumCoins);
    } else {
        remaindItem = Item::CreateItem(ITEM_DWARF_COIN_1, 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 = nullptr;
    if (dis(gen) <= 95) {
        remaindItem = Item::CreateItem(ITEM_GOLD_COIN, money);
    } else {
        remaindItem = Item::CreateItem(ITEM_DWARF_COIN, money);
    }

    ReturnValue ret = internalAddItem(cylinder, remaindItem, INDEX_WHEREEVER, flags);
    if (ret != RETURNVALUE_NOERROR) {
        internalAddItem(cylinder->getTile(), remaindItem, INDEX_WHEREEVER, FLAG_NOLIMIT);
    }
}


If you wish to add more than 2 currencies the script will require further rework. Here's an initial idea to work on it further for more than 2 currencies:

Code:
uint32_t crystalCoins = money / 10000;
money -= crystalCoins * 10000;
while (crystalCoins > 0) {
    const uint16_t count = std::min<uint32_t>(100, crystalCoins);

    Item* remaindItem = nullptr;
    int randomChance = dis(gen);
    if (randomChance <= 85) {
        remaindItem = Item::CreateItem(ITEM_CRYSTAL_COIN, count);
    } else if (randomChance <= 90) {
        remaindItem = Item::CreateItem(ITEM_DWARF_COIN_2, count);
    } else if (randomChance <= 95) {
        remaindItem = Item::CreateItem(ITEM_ELF_COIN_2, count);
    } else {
        remaindItem = Item::CreateItem(ITEM_HOBBIT_COIN_2, 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 = nullptr;
    int randomChance = dis(gen);
    if (randomChance <= 85) {
        remaindItem = Item::CreateItem(ITEM_PLATINUM_COIN, platinumCoins);
    } else if (randomChance <= 90) {
        remaindItem = Item::CreateItem(ITEM_DWARF_COIN_1, platinumCoins);
    } else if (randomChance <= 95) {
        remaindItem = Item::CreateItem(ITEM_ELF_COIN_1, platinumCoins);
    } else {
        remaindItem = Item::CreateItem(ITEM_HOBBIT_COIN_1, 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 = nullptr;
    int randomChance = dis(gen);
    if (randomChance <= 85) {
        remaindItem = Item::CreateItem(ITEM_GOLD_COIN, money);
    } else if (randomChance <= 90) {
        remaindItem = Item::CreateItem(ITEM_DWARF_COIN, money);
    } else if (randomChance <= 95) {
        remaindItem = Item::CreateItem(ITEM_ELF_COIN, money);
    } else {
        remaindItem = Item::CreateItem(ITEM_HOBBIT_COIN, money);
    }

    ReturnValue ret = internalAddItem(cylinder, remaindItem, INDEX_WHEREEVER, flags);
    if (ret != RETURNVALUE_NOERROR) {
        internalAddItem(cylinder->getTile(), remaindItem, INDEX_WHEREEVER, FLAG_NOLIMIT);
    }
}

The experimental version for more than 2 currencies % chance work the following way:
-> 85% chance for a gold coin (if random chance between 1-85 then gold coin
-> 5% for a dwarf coin (if random number between 85-90 then dwarf coin)
-> 5% for Elf (90-95 -> elf coin)
-> 5% for hobbit (else then hobbit coin)

If you have any comments or feedback please feel free to share:)
 
Back
Top