• 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.X+ Remove boss reward chest limits

ShadowProwl

New Member
Joined
Jan 8, 2024
Messages
13
Reaction score
1
Location
Tibia
I added boss reward chest to TFS 1.5 following
When reward bags inside the reward chest are more than 99 and the player logout, reward bags get inside each other and can't be opened. How to allow 100+ reward bags without the 99 max limit?
I think it's in the iologindata.cpp part
C++:
    //load reward chest items

    itemMap.clear();



    query.str(std::string());

    query << "SELECT `pid`, `sid`, `itemtype`, `count`, `attributes` FROM `player_rewards` WHERE `player_id` = " << player->getGUID() << " ORDER BY `sid` DESC";

    if ((result = db->storeQuery(query.str()))) {

        loadItems(itemMap, result);



        //first loop handles the reward containers to retrieve its date attribute

        //for (ItemMap::iterator it = itemMap.begin(), end = itemMap.end(); it != end; ++it) {

        for (auto& it : itemMap) {

            const std::pair<Item*, int32_t>& pair = it.second;

            Item* item = pair.first;



            int32_t pid = pair.second;

            if (pid >= 0 && pid < 100) {

                Reward* reward = player->getReward(item->getIntAttr(ITEM_ATTRIBUTE_DATE), true);

                if (reward) {

                    it.second = std::pair<Item*, int32_t>(reward->getItem(), pid); //update the map with the special reward container

                }

            } else {

                break;

            }

        }



        //second loop (this time a reverse one) to insert the items in the correct order

        //for (ItemMap::const_reverse_iterator it = itemMap.rbegin(), end = itemMap.rend(); it != end; ++it) {

        for (const auto& it : boost::adaptors::reverse(itemMap)) {

            const std::pair<Item*, int32_t>& pair = it.second;

            Item* item = pair.first;



            int32_t pid = pair.second;

            if (pid >= 0 && pid < 100) {

                break;

            }

           

            ItemMap::const_iterator it2 = itemMap.find(pid);

            if (it2 == itemMap.end()) {

                continue;

            }



            Container* container = it2->second.first->getContainer();

            if (container) {

                container->internalAddThing(item);

            }

        }

    }
 
Last edited:
Solution
nah it's possible to add 100+ containers, the code is confusing and I can see why the pull request is closed; it's really buggy.

What happens when you attack a boss logout, and kill it with another char? It can bug and give the logged out player nothing

Seems like the sql query that gives the offline player loot doesnt work in boss.lua, function: local function insertItems(buffer, info, parent, items), it should be:
Lua:
pushSeparated(buffer, ",", info.playerGuid, parent, info.running, item:getId(), item:getSubType(), db.escapeString(item:serializeAttributes()))

loading the reward chest you need to check all the reward containers first in iologinidata.cpp, bool IOLoginData::loadPlayer(Player* player, DBResult_ptr result)
C++:
//load...
I tried on Lua part to change these and it's still not working too.
Lua:
if pid < 100 then
    lastReward = pid
end
Lua:
local info = {
    playerGuid = playerGuid,
    running = lastStoreId or 100
}
 
If it's not possible to increase the 99 maximum reward containers, Can it allow reward containers to be opened if they get inside each other? After 99, they start to be placed inside each other instead of in the reward chest box.
 
Look in the database at table player_rewards.
The problem is the pid values of 1-99 is for the containers, the items start at 100 + containerid (pid). You can see how it will mess up when you add the 101th container, pid 101 will have entries for an item and the reward container.

edit: it's important to note that rewards get auto deleted after 7 days, do your players know that? You should let them know lmao
 
Last edited:
Look in the database at table player_rewards.
The problem is the pid values of 1-99 is for the containers, the items start at 100 + containerid (pid). You can see how it will mess up when you add the 101th container, pid 101 will have entries for an item and the reward container.
Exactly, the issue starts at 101. any way to solve this?
edit: it's important to note that rewards get auto deleted after 7 days, do your players know that? You should let them know lmao
Yes, they do, but some of them just don't clean the reward chest for days until it bugs.
 
nah it's possible to add 100+ containers, the code is confusing and I can see why the pull request is closed; it's really buggy.

What happens when you attack a boss logout, and kill it with another char? It can bug and give the logged out player nothing

Seems like the sql query that gives the offline player loot doesnt work in boss.lua, function: local function insertItems(buffer, info, parent, items), it should be:
Lua:
pushSeparated(buffer, ",", info.playerGuid, parent, info.running, item:getId(), item:getSubType(), db.escapeString(item:serializeAttributes()))

loading the reward chest you need to check all the reward containers first in iologinidata.cpp, bool IOLoginData::loadPlayer(Player* player, DBResult_ptr result)
C++:
//load reward chest items
itemMap.clear();

if ((result = db.storeQuery(fmt::format("SELECT `pid`, `sid`, `itemtype`, `count`, `attributes` FROM `player_rewards` WHERE `player_id` = {:d} ORDER BY `sid` DESC", player->getGUID())))) {
    loadItems(itemMap, result);

    //first loop handles the reward containers to retrieve its date attribute
    //for (ItemMap::iterator it = itemMap.begin(), end = itemMap.end(); it != end; ++it) {
    for (auto& it : itemMap) {
        const std::pair<Item*, int32_t>& pair = it.second;
        Item* item = pair.first;

        if (item->getID() != ITEM_REWARD_CONTAINER) continue; // for over 100 containers conflicting with items

        int32_t pid = pair.second;

        Reward* reward = player->getReward(item->getIntAttr(ITEM_ATTRIBUTE_DATE), true);
        if (reward) {
            it.second = std::pair<Item*, int32_t>(reward->getItem(), pid); //update the map with the special reward container
        }
    }

    //second loop (this time a reverse one) to insert the items in the correct order
    //for (ItemMap::const_reverse_iterator it = itemMap.rbegin(), end = itemMap.rend(); it != end; ++it) {
    for (const auto& it : boost::adaptors::reverse(itemMap)) {
        const std::pair<Item*, int32_t>& pair = it.second;
        Item* item = pair.first;

        int32_t pid = pair.second;

        if(item->getID() == ITEM_REWARD_CONTAINER)
            continue;

        ItemMap::const_iterator it2 = itemMap.find(pid);
        if (it2 == itemMap.end()) {
            std::cout << "Error loading item (item will be destroyed on logout) with id: " << item->getID() << ", there is no container with sid=" << pid<<". Player name: "<<player->getName()<<std::endl;
            continue;
        }

        Container* container = it2->second.first->getContainer();
        if (container) {
            container->internalAddThing(item);
        }
        else
            std::cout << "Error loading item (item will be destroyed on logout) with id: " << item->getID() << ", there is no container with sid=" << pid << ". Player name: " << player->getName() << std::endl;
    }
}

Anyway, that's just to get it to work, but it doesnt function correctly
 
Solution
nah it's possible to add 100+ containers, the code is confusing and I can see why the pull request is closed; it's really buggy.
the only free one I found.
nah it's possible to add 100+ containers, the code is confusing and I can see why the pull request is closed; it's really buggy.

What happens when you attack a boss logout, and kill it with another char? It can bug and give the logged out player nothing

Seems like the sql query that gives the offline player loot doesnt work in boss.lua, function: local function insertItems(buffer, info, parent, items), it should be:
pushSeparated(buffer, ",", info.playerGuid, parent, info.running, item:getId(), item:getSubType(), db.escapeString(item:serializeAttributes()))
Now it adds when player logout too.
loading the reward chest you need to check all the reward containers first in iologinidata.cpp, bool IOLoginData::loadPlayer(Player* player, DBResult_ptr result)
//load reward chest items itemMap.clear(); if ((result = db.storeQuery(fmt::format("SELECT `pid`, `sid`, `itemtype`, `count`, `attributes` FROM `player_rewards` WHERE `player_id` = {:d} ORDER BY `sid` DESC", player->getGUID())))) { loadItems(itemMap, result); //first loop handles the reward containers to retrieve its date attribute //for (ItemMap::iterator it = itemMap.begin(), end = itemMap.end(); it != end; ++it) { for (auto& it : itemMap) { const std::pair<Item*, int32_t>& pair = it.second; Item* item = pair.first; if (item->getID() != ITEM_REWARD_CONTAINER) continue; // for over 100 containers conflicting with items int32_t pid = pair.second; Reward* reward = player->getReward(item->getIntAttr(ITEM_ATTRIBUTE_DATE), true); if (reward) { it.second = std::pair<Item*, int32_t>(reward->getItem(), pid); //update the map with the special reward container } } //second loop (this time a reverse one) to insert the items in the correct order //for (ItemMap::const_reverse_iterator it = itemMap.rbegin(), end = itemMap.rend(); it != end; ++it) { for (const auto& it : boost::adaptors::reverse(itemMap)) { const std::pair<Item*, int32_t>& pair = it.second; Item* item = pair.first; int32_t pid = pair.second; if(item->getID() == ITEM_REWARD_CONTAINER) continue; ItemMap::const_iterator it2 = itemMap.find(pid); if (it2 == itemMap.end()) { std::cout << "Error loading item (item will be destroyed on logout) with id: " << item->getID() << ", there is no container with sid=" << pid<<". Player name: "<<player->getName()<<std::endl; continue; } Container* container = it2->second.first->getContainer(); if (container) { container->internalAddThing(item); } else std::cout << "Error loading item (item will be destroyed on logout) with id: " << item->getID() << ", there is no container with sid=" << pid << ". Player name: " << player->getName() << std::endl; } }
Anyway, that's just to get it to work, but it doesnt function correctly
I can now have more than 100 reward containers. thank you.
Does it change how the code used to work or the changes only for the 100+ limit?

Can you check? Maybe you know 1 or 2 of these?
 
Back
Top