[TUTORIAL] Gossip menu pagination method

Darksoke

Well-known member
Darksoke Rep
1
0
0
Rep
1
Darksoke Vouches
0
0
0
Vouches
0
Posts
58
Likes
70
Bits
3 YEARS
3 YEARS OF SERVICE
LEVEL 2 50 XP
Working example, implementation for a title master npc

Screenshot_1.pngScreenshot_2.png

Simple method to paginate an unordered map into a gossip menu list. As you know, a gossip menu can handle up to 32 items / page but what if we have an unordered map of 100 items we want to paginate under a sub menu ? Unordered maps are a pain in the ass when it comes to accessing elements by index if your data doesn't have an incremented ID, so we can do it with a simple loop. TBH I'm still learning how unordered maps work but i find this solution very easy and efficient since we're talking about a gossip menu we're not talking about thousands of items neither hundreds. Anyways let's hop in the code

first of all we need an unordered map
C++:
typedef std::unordered_map<uint32, SomeStructData> ourItemsContainer;
private ourItemsContainer _ourItemsContainer;

then the method explained below
C++:
void Paginate(Player* player, uint32 current_page) {

            uint32 startPos = (current_page - 1) * RESULTS_PER_PAGE;
            uint32 currentPos = startPos;
            uint32 counter = 0;
            uint32 total_pages = ceil(_ourItemsContainer.size() / (double)RESULTS_PER_PAGE);

            // Show the current page out of total pages
            AddGossipItemFor(player, 0, "Page " + std::to_string(current_page) + " / " + std::to_string(total_pages == 0 ? 1 : total_pages), GOSSIP_SENDER_PAGE + current_page, GOSSIP_SENDER_ACTION);
            // Show a main menu option
            AddGossipItemFor(player, 0, "Main Menu", GOSSIP_SENDER_INN_INFO, 0);

            // Iterrating throught unordered map items since we can't efficiently access them by index
            for (ourItemsContainer::iterator it = _ourItemsContainer.begin(); it != _ourItemsContainer.end(); ++it)
            {
                // If our counter reaches start position, we start adding the gossip menu items
                // for the speccific page
                counter++;
                if (counter < startPos)
                    continue;

                AddGossipItemFor(player, 6, "Page " + std::to_string(current_page)  + " Item " + std::to_string(it->first), 0, GOSSIP_SENDER_EXAMPLE, GOSSIP_SENDER_EXAMPLE_ACTION, 0, false);

                // Then we break the loop once counter equals our results per page limit
                currentPos++;
                if (currentPos == startPos + RESULTS_PER_PAGE)
                    break;
            }
            // Finally we add our next/back controls
            if (currentPos == startPos + RESULTS_PER_PAGE && counter < _ourItemsContainer.size())
                AddGossipItemFor(player, 0, "Next page", GOSSIP_SENDER_PAGE + current_page + 1, GOSSIP_SENDER_ACTION);
            if (current_page > 1)
                AddGossipItemFor(player, 0, "Previous page", GOSSIP_SENDER_PAGE + current_page - 1, GOSSIP_SENDER_ACTION)
}
*Note this is just a generic method and can easly be updated to fit your needs !

As a side note, instead of
C++:
RESULTS_PER_PAGE
which is defined by me and equals 16, you can use
C++:
GOSSIP_MAX_MENU_ITEMS
which is the default definition.
 
Liked By 3 members :

3,575

1,285

9,621

433

Top