blankart/src/k_itemlist.cpp
2025-12-12 21:38:16 -05:00

151 lines
4.3 KiB
C++

#include <unordered_map>
#include "byteptr.h"
#include "d_player.h"
#include "doomdef.h"
#include "k_items.h"
#include "p_saveg.h"
#include "v_video.h"
extern "C"
{
std::unordered_map<kartitemtype_e, INT32> itemcounter[MAXPLAYERS];
//
// Clears out all item lists for all players. Should only run during race setup.
//
void K_ClearItemRollLists(void)
{
INT32 i;
for (i = 0; i < MAXPLAYERS; i++)
{
itemcounter[i].clear();
}
}
//
// Adds an item roll to the item roll list.
// If an entry for the item already exists, this function adds to its roll count.
//
void K_AddItemRollToList(INT32 pid, kartitemtype_e item, INT32 amount)
{
if (auto search = itemcounter[pid].find(item); search != itemcounter[pid].end())
itemcounter[pid][item] += amount;
else
itemcounter[pid][item] = amount; // If this roll didn't exist before, it does now :^)
}
//
// Gets the size of the item roll list. Primarily used for syncing netgames.
//
UINT32 K_GetItemListSize(INT32 pid)
{
return static_cast<UINT32>(itemcounter[pid].size());
}
//
// Sets an entry in the item roll list to a specific value.
//
void K_SetItemListEntry(INT32 pid, kartitemtype_e item, INT32 num)
{
itemcounter[pid][item] = num;
}
//
// Gets the value of an entry in the item roll list, given it exists.
// If nothing is found, this value returns 0.
//
UINT32 K_GetItemListEntry(INT32 pid, kartitemtype_e item)
{
if (auto search = itemcounter[pid].find(item); search != itemcounter[pid].end())
{
return itemcounter[pid][item];
}
return 0;
}
//
// C and C++ are like oil and water at points; we need to synch every entry in the unordered
// map by doing... this.
//
UINT32 K_SyncItemList(savebuffer_t* save, INT32 pid)
{
UINT32 buffer_size;
if (save->write)
{
// Buffer size = list size * 2 (2 entries for each buffer element)
buffer_size = static_cast<UINT32>(itemcounter[pid].size());
// First, write the size of the buffer we're about to send over.
WRITEUINT32(save->p, buffer_size);
// Then, comb through the map and write every entry in it to the save buffer.
for (const auto& n : itemcounter[pid])
{
WRITEUINT32(save->p, static_cast<UINT32>(n.first));
WRITEUINT32(save->p, static_cast<UINT32>(n.second));
}
return buffer_size;
}
else
{
// Get the buffer size.
buffer_size = READUINT32(save->p);
UINT32 i, item, amt;
for (i = 0; i < buffer_size; i++)
{
// Loop through the save buffer and write everything we find into the given item
// list.
item = READUINT32(save->p);
amt = READUINT32(save->p);
itemcounter[pid][static_cast<kartitemtype_e>(item)] = amt;
}
return buffer_size;
}
return 0;
}
#define ITEMLOG_SPACE 1
// Draws an item in the player's item list. Draws nothing if the list is empty.
fixed_t K_DrawItemList(INT32 pid, fixed_t x, fixed_t y)
{
if (itemcounter[pid].size() < 1)
return 0;
patch_t* localpatch;
fixed_t dx = x;
INT32 ir_length;
for (const auto& n : itemcounter[pid])
{
if (n.second < 1)
continue;
localpatch = K_GetCachedItemPatch(n.first, true, 0);
ir_length = static_cast<INT32>(strlen(va("%d", n.second)));
V_DrawFixedPatch(dx, y - (25 * FRACUNIT / 6), FRACUNIT / 3, 0, localpatch, NULL);
V_DrawSmallString((dx / FRACUNIT) + ((5 + (std::max(0, ir_length - 1) * 3))),
(y / FRACUNIT) + 2,
V_ALLOWLOWERCASE | V_6WIDTHSPACE,
va("%d", n.second));
dx += (6 + std::max(0, (ir_length * 3) - 3) + ITEMLOG_SPACE) * FRACUNIT;
}
// Return the overall "width" of the list.
return dx - x;
}
#undef ITEMLOG_SPACE
}