Darksoke
Well-known member
LEVEL 2
50 XP
Working example, implementation for a title master npc


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
then the method explained below
*Note this is just a generic method and can easly be updated to fit your needs !
As a side note, instead of
which is defined by me and equals 16, you can use
which is the default definition.


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)
}
As a side note, instead of
C++:
RESULTS_PER_PAGE
C++:
GOSSIP_MAX_MENU_ITEMS