From 327035e68ecf2b5304c09af4a3d5b767336d2bc2 Mon Sep 17 00:00:00 2001 From: yamamama Date: Sat, 6 Dec 2025 04:13:19 -0500 Subject: [PATCH 01/10] Start work on an item roll tracker Uses an unordered-map system so we don't loop through every item constantly Opting for trying to fit everyone on the screen; 320x200 users can deal with it Scrolling is not yet implemented, and this system isn't netsynched yet --- src/CMakeLists.txt | 1 + src/d_netcmd.c | 7 ++++ src/d_netcmd.h | 2 + src/k_itemlist.cpp | 61 +++++++++++++++++++++++++++ src/k_itemlist.hpp | 15 +++++++ src/k_items.c | 3 ++ src/p_setup.c | 3 ++ src/y_inter.c | 101 ++++++++++++++++++++++++++++++++++++--------- 8 files changed, 174 insertions(+), 19 deletions(-) create mode 100644 src/k_itemlist.cpp create mode 100644 src/k_itemlist.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 603239ac4..d4e256c7c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -139,6 +139,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 k_botsearch.cpp k_cluster.cpp k_items.c + k_itemlist.cpp k_grandprix.c k_boss.c k_hud.c diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 3ceb00a64..9e7914e1e 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -69,6 +69,7 @@ #include "g_party.h" #include "k_specialstage.h" #include "k_items.h" +#include "k_itemlist.hpp" #define CV_RESTRICT CV_NETVAR @@ -605,6 +606,8 @@ consvar_t cv_kartlegacyspbdist = CVAR_INIT ("kartlegacyspbdist", "2216", CV_NETV // SPB Rush toggle; toggles on/off the more aggressive "pressure" odds when an SPB is active consvar_t cv_kartspbrush = CVAR_INIT ("kartspbrush", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_itemlist = CVAR_INIT ("kartitemlist", "On", CV_NETVAR, CV_OnOff, NULL); + // Time limit for Alt. Shrink static CV_PossibleValue_t altshrinktime_cons_t[] = {{0, "MIN"}, {(INT16_MAX / TICRATE), "MAX"}, {0, NULL}}; consvar_t cv_kartaltshrinktime = CVAR_INIT ("kartaltshrinktime", "14", CV_NETVAR|CV_CHEAT|CV_GUARD, altshrinktime_cons_t, NULL); @@ -1075,6 +1078,8 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_dummyconsvar); CV_RegisterVar(&cv_encorevotes); + CV_RegisterVar(&cv_itemlist); + #ifdef USE_STUN CV_RegisterVar(&cv_stunserver); #endif @@ -6527,6 +6532,8 @@ static void Got_Cheat(UINT8 **cp, INT32 playernum) } else { + K_AddItemRollToList((INT32)(player - players), item, amt); + CV_CheaterWarning(playernum, va("give item %s x%d", DEH_KartItemName(item), amt)); } break; diff --git a/src/d_netcmd.h b/src/d_netcmd.h index c569726cd..45de60434 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -221,6 +221,8 @@ extern consvar_t cv_kartlegacyspbdist; extern consvar_t cv_kartspbrush; +extern consvar_t cv_itemlist; + extern consvar_t cv_encorevotes; extern consvar_t cv_votetime; diff --git a/src/k_itemlist.cpp b/src/k_itemlist.cpp new file mode 100644 index 000000000..5cec443c9 --- /dev/null +++ b/src/k_itemlist.cpp @@ -0,0 +1,61 @@ +#include + +#include "d_player.h" +#include "doomdef.h" +#include "k_items.h" +#include "v_video.h" + +extern "C" +{ + std::unordered_map itemcounter[MAXPLAYERS]; + + void K_ClearItemRollLists(void) + { + INT32 i; + + for (i = 0; i < MAXPLAYERS; i++) + { + itemcounter[i].clear(); + } + } + + 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 :^) + } + +#define ITEMLOG_SPACE 1 + + // Draws an item in the player's item list. Draws nothing if the list is empty. + void K_DrawItemList(INT32 pid, fixed_t x, fixed_t y) + { + if (itemcounter[pid].size() < 1) + return; + + 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 = (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; + } + } + +#undef ITEMLOG_SPACE +} diff --git a/src/k_itemlist.hpp b/src/k_itemlist.hpp new file mode 100644 index 000000000..7f33a57c2 --- /dev/null +++ b/src/k_itemlist.hpp @@ -0,0 +1,15 @@ +#include "doomdef.h" +#include "k_items.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + void K_ClearItemRollLists(void); + void K_AddItemRollToList(INT32 pid, kartitemtype_e item, INT32 amount); + void K_DrawItemList(INT32 pid, fixed_t x, fixed_t y); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/src/k_items.c b/src/k_items.c index 2e2416178..5d15d8c1f 100644 --- a/src/k_items.c +++ b/src/k_items.c @@ -38,6 +38,7 @@ #include "k_waypoint.h" #include "k_director.h" #include "k_cluster.hpp" +#include "k_itemlist.hpp" #include "k_items.h" #include "k_collide.h" @@ -379,6 +380,8 @@ void K_AwardPlayerItem(player_t *player, kartitemtype_e type, UINT8 amount, kart amount *= 2; player->itemamount = amount; + + K_AddItemRollToList((INT32)(player - players), type, amount); } static void K_AwardPlayerResult(player_t *player, kartresult_t *result, kartitemblink_e blink) diff --git a/src/p_setup.c b/src/p_setup.c index 777008647..90674eed6 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -108,6 +108,7 @@ #include "k_mapuser.h" #include "p_deepcopy.h" #include "k_specialstage.h" +#include "k_itemlist.hpp" #include "g_input.h" #include "blan/b_soc.h" @@ -8217,6 +8218,8 @@ static void P_InitLevelSettings(boolean reloadinggamestate) antibumptime = (tic_t)cv_kartantibump.value * TICRATE; + K_ClearItemRollLists(); + // emerald hunt hunt1 = hunt2 = hunt3 = NULL; diff --git a/src/y_inter.c b/src/y_inter.c index 458650138..851d30819 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -49,6 +49,7 @@ #include "k_grandprix.h" #include "k_bot.h" // cv_botcanvote #include "r_fps.h" // R_GetTimeFrac +#include "k_itemlist.hpp" #ifdef HWRENDER #include "hardware/hw_main.h" @@ -80,9 +81,23 @@ typedef struct UINT8 pos[MAXPLAYERS]; // player positions. used for ties boolean rankingsmode; // rankings mode + boolean itemrolls; boolean encore; // encore mode } y_data; +static boolean Y_ItemListActive(void) +{ + UINT8 i = 0, nump = 0; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + nump++; + } + + return ((cv_itemlist.value != 0) && (nump > 1)); +} + static y_data data; // graphics @@ -99,6 +114,7 @@ static UINT8 *y_screenbuffer; static INT32 intertic; static INT32 endtic = -1; static INT32 sorttic = -1; +static INT32 rolltic = -1; intertype_t intertype = int_none; intertype_t intermissiontypes[NUMGAMETYPES]; @@ -253,6 +269,7 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) data.levelstring[sizeof data.levelstring - 1] = '\0'; data.encore = encoremode; + data.itemrolls = Y_ItemListActive(); memset(data.jitter, 0, sizeof (data.jitter)); } @@ -382,6 +399,7 @@ void Y_CleanupScreenBuffer(void) void Y_IntermissionDrawer(void) { INT32 i, whiteplayer = MAXPLAYERS, x = 4, hilicol = V_YELLOWMAP; // fallback + INT32 xx = x; if (intertype == int_none || rendermode == render_none) return; @@ -435,7 +453,18 @@ void Y_IntermissionDrawer(void) hilicol = V_YELLOWMAP; } - if (sorttic != -1 && intertic > sorttic) + if (rolltic != -1 && intertic > (rolltic - 8) && (intertic < (rolltic + 8))) + { + INT32 count = (intertic - (rolltic - 8)); + + if (count < 8) + x -= ((((count<>FRACBITS) / (8 * vid.dupx); + else if (count == 8) + goto skiptallydrawer; + else if (count < 16) + x += (((((16 - count)<>FRACBITS) / (8 * vid.dupx); + } + else if (sorttic != -1 && intertic > sorttic) { INT32 count = (intertic - sorttic); @@ -456,6 +485,10 @@ void Y_IntermissionDrawer(void) boolean manyplayers16 = (data.numplayers > NUMFORNEWCOLUMN*2); boolean manyplayers8 = (data.numplayers > NUMFORNEWCOLUMN); + boolean displayitemrolls = (data.itemrolls && (intertic <= rolltic)); + + if (displayitemrolls) + manyplayers16 = manyplayers8 = false; int y2; @@ -510,13 +543,6 @@ void Y_IntermissionDrawer(void) V_DrawRightAlignedString(x+152, 24, hilicol, timeheader); } - else - { - V_DrawCenteredString(x+6, 24, hilicol, "#"); - V_DrawString(x+36, 24, hilicol, "NAME"); - - V_DrawRightAlignedString(x+(BASEVIDWIDTH/2)+152, 24, hilicol, timeheader); - } for (i = 0; i < data.numplayers; i++) { @@ -530,36 +556,52 @@ void Y_IntermissionDrawer(void) if (dojitter) y--; - if (manyplayers16) - V_DrawPingNum(x+6, y+2, 0, data.pos[i], NULL); + if (manyplayers16||displayitemrolls) + V_DrawPingNum(x + 6, (displayitemrolls) ? y-2 : y+2, 0, data.pos[i], NULL); else V_DrawCenteredString(x+6, y, 0, va("%d", data.pos[i])); if (data.color[i]) { UINT8 *colormap = R_GetTranslationColormap(*data.character[i], *data.color[i], GTC_CACHE); - patch_t *facerank = faceprefix[*data.character[i]][FACE_RANK]; + patch_t *facerank; + + if (displayitemrolls) + facerank = faceprefix[*data.character[i]][FACE_MINIMAP]; + else + facerank = faceprefix[*data.character[i]][FACE_RANK]; + + fixed_t scale = FRACUNIT; if (manyplayers16) { - // fixed_t scale = K_UseHighResPortraits() ? FRACUNIT/4 : FRACUNIT/2; - fixed_t scale = FRACUNIT/2; + scale = FRACUNIT / 2; + V_DrawFixedPatch((x+8)<leftoffset, y-4+facerank->topoffset, 0, facerank, colormap); + INT32 xoffs, yoffs; + + scale = (displayitemrolls) ? FRACUNIT/2 : FRACUNIT; + + xoffs = FixedMul(16, scale); + yoffs = FixedMul(4, scale); + + V_DrawFixedPatch((x+xoffs)<leftoffset, y-4+highlight->topoffset, 0, highlight); } - if ((players[data.num[i]].pflags & PF_NOCONTEST) && players[data.num[i]].bot) + if ((!displayitemrolls) && (players[data.num[i]].pflags & PF_NOCONTEST) && players[data.num[i]].bot) { // RETIRED!! patch_t *retire = W_CachePatchName("K_NOBLNS", PU_CACHE); @@ -578,10 +620,20 @@ void Y_IntermissionDrawer(void) y2 = y; + INT32 slen = 0; + if (manyplayers16) V_DrawThinString(x+18, y, hilicol|V_ALLOWLOWERCASE|V_6WIDTHSPACE, strtime); + else if (displayitemrolls) + { + V_DrawSmallString(xx, y2 + 1, ((data.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, strtime); + slen = V_SmallStringWidth(strtime, ((data.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE); + } else if (manyplayers8) - V_DrawThinString(x+36, y2-1, ((data.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, strtime); + { + V_DrawThinString(xx, y2 - 1, ((data.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, strtime); + slen = V_ThinStringWidth(strtime, ((data.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE); + } else V_DrawString(x+36, y2, ((data.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE, strtime); @@ -622,6 +674,10 @@ void Y_IntermissionDrawer(void) else V_DrawRightAlignedString(x+152+gutter, y, 0, strtime); } + else if (data.itemrolls && (intertic <= rolltic)) + { + K_DrawItemList((INT32)(&players[data.num[i]] - players), (xx+2+slen) * FRACUNIT, (y-1) * FRACUNIT); + } else { if (data.val[i] == (UINT32_MAX-1)) @@ -671,9 +727,9 @@ void Y_IntermissionDrawer(void) } else { - y += 18; + y += (displayitemrolls) ? 8 : 18; - if (i == NUMFORNEWCOLUMN-1) + if ((!displayitemrolls) && i == NUMFORNEWCOLUMN-1) { y = 41; x += BASEVIDWIDTH/2; @@ -991,6 +1047,13 @@ void Y_StartIntermission(void) { // Calculate who won Y_CalculateMatchData(0, Y_CompareTime); + + if (data.itemrolls) + { + rolltic = 15 * TICRATE; + sorttic += rolltic; + timer += rolltic; + } break; } From 15b1d19d0fbd9f923142cbfc3f1b6676e7f1a86e Mon Sep 17 00:00:00 2001 From: yamamama Date: Sun, 7 Dec 2025 03:18:08 -0500 Subject: [PATCH 02/10] Netsync item lists --- src/k_itemlist.cpp | 88 +++++++++++++++++++++++++++++++++++++++++++++- src/k_itemlist.hpp | 9 +++++ src/p_saveg.c | 10 ++++++ 3 files changed, 106 insertions(+), 1 deletion(-) diff --git a/src/k_itemlist.cpp b/src/k_itemlist.cpp index 5cec443c9..c9daf85a8 100644 --- a/src/k_itemlist.cpp +++ b/src/k_itemlist.cpp @@ -1,14 +1,19 @@ #include +#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 itemcounter[MAXPLAYERS]; + // + // Clears out all item lists for all players. Should only run during race setup. + // void K_ClearItemRollLists(void) { INT32 i; @@ -19,6 +24,10 @@ extern "C" } } + // + // 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()) @@ -27,6 +36,83 @@ extern "C" 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(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(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(n.first)); + WRITEUINT32(save->p, static_cast(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(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. @@ -45,7 +131,7 @@ extern "C" continue; localpatch = K_GetCachedItemPatch(n.first, true, 0); - ir_length = (INT32)strlen(va("%d", n.second)); + ir_length = static_cast(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))), diff --git a/src/k_itemlist.hpp b/src/k_itemlist.hpp index 7f33a57c2..9b9c8f9e7 100644 --- a/src/k_itemlist.hpp +++ b/src/k_itemlist.hpp @@ -9,6 +9,15 @@ extern "C" void K_ClearItemRollLists(void); void K_AddItemRollToList(INT32 pid, kartitemtype_e item, INT32 amount); void K_DrawItemList(INT32 pid, fixed_t x, fixed_t y); + UINT32 K_GetItemListSize(INT32 pid); + + // Getter and setter + + void K_SetItemListEntry(INT32 pid, kartitemtype_e item, INT32 num); + UINT32 K_GetItemListEntry(INT32 pid, kartitemtype_e item); + + // Netsynch; returns the size of the list buffer, always. + UINT32 K_SyncItemList(savebuffer_t *save, INT32 pid); #ifdef __cplusplus } diff --git a/src/p_saveg.c b/src/p_saveg.c index e89325d48..51bdf4ce2 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -45,6 +45,7 @@ #include "acs/interface.h" #include "g_party.h" #include "k_waypoint.h" +#include "k_itemlist.hpp" #include @@ -404,6 +405,9 @@ static void P_RelinkWaypoint(savebuffer_t *save, waypoint_t **ptr) #define ARCHIVEBLOCK_SPECIALS 0x7F228378 #define ARCHIVEBLOCK_WAYPOINTS 0x7F46498F +// Specialized netsynch markers +#define PLYRSYNC_ITEMLIST (1) + static inline void P_ArchivePlayer(savebuffer_t *save) { const player_t *player = &players[consoleplayer]; @@ -457,6 +461,12 @@ static void P_NetSyncPlayers(savebuffer_t *save) SYNC(playerconsole[i]); SYNC(splitscreen_invitations[i]); + // Item lists + if (P_SyncUINT32(save, (K_GetItemListSize(i) ? PLYRSYNC_ITEMLIST : 0))) + { + K_SyncItemList(save, i); + } + SYNC(players[i].angleturn); SYNC(players[i].aiming); SYNC(players[i].drawangle); From 38f5c3044e0079e991cc9161e9c3db30e702e217 Mon Sep 17 00:00:00 2001 From: yamamama Date: Sun, 7 Dec 2025 03:19:05 -0500 Subject: [PATCH 03/10] Format the list display slightly better Instead of awkwardly listing off the names offset of the current... why not just do that for the longest name? --- src/y_inter.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/y_inter.c b/src/y_inter.c index 851d30819..643169eb4 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -621,13 +621,25 @@ void Y_IntermissionDrawer(void) y2 = y; INT32 slen = 0; + INT32 slen_temp = slen; if (manyplayers16) V_DrawThinString(x+18, y, hilicol|V_ALLOWLOWERCASE|V_6WIDTHSPACE, strtime); else if (displayitemrolls) { V_DrawSmallString(xx, y2 + 1, ((data.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, strtime); - slen = V_SmallStringWidth(strtime, ((data.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE); + + // Get the longest string size. This is... gross. + INT32 ii; + + for (ii = 0; ii < data.numplayers; ii++) + { + if (data.num[ii] != MAXPLAYERS && playeringame[data.num[ii]] && !players[data.num[ii]].spectator) + { + slen_temp = V_SmallStringWidth(data.name[ii], ((data.num[ii] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE); + slen = ((slen_temp > slen) ? slen_temp : slen); + } + } } else if (manyplayers8) { From bf8a54db50a8c16f885af558416d3f04ebb81c36 Mon Sep 17 00:00:00 2001 From: yamamama Date: Mon, 8 Dec 2025 18:09:13 -0500 Subject: [PATCH 04/10] Nitpick --- src/k_itemlist.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/k_itemlist.cpp b/src/k_itemlist.cpp index c9daf85a8..1ce618e38 100644 --- a/src/k_itemlist.cpp +++ b/src/k_itemlist.cpp @@ -134,6 +134,7 @@ extern "C" ir_length = static_cast(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, From cefe9dc783f0530005f9cc07f5905aaccb199234 Mon Sep 17 00:00:00 2001 From: yamamama Date: Mon, 8 Dec 2025 18:09:31 -0500 Subject: [PATCH 05/10] Make the itemlist scroll at above 18 players --- src/y_inter.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 116 insertions(+), 8 deletions(-) diff --git a/src/y_inter.c b/src/y_inter.c index 643169eb4..240163853 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -55,6 +55,11 @@ #include "hardware/hw_main.h" #endif +#define ITEMLIST_PLAYER_YOFFSET 8 +#define ITEMLIST_SCROLLSPEED (3 * FRACUNIT / 4) +#define ITEMLIST_SCROLLDELAY (TICRATE) +#define ITEMLIST_SCROLLREPEAT 2 + typedef struct { char patch[9]; @@ -116,6 +121,10 @@ static INT32 endtic = -1; static INT32 sorttic = -1; static INT32 rolltic = -1; +static boolean listscroll_reverse = false; +static INT32 listscroll_delay = 0; +fixed_t yscroll = 0; + intertype_t intertype = int_none; intertype_t intermissiontypes[NUMGAMETYPES]; @@ -404,6 +413,12 @@ void Y_IntermissionDrawer(void) if (intertype == int_none || rendermode == render_none) return; + INT32 w = (vid.width / vid.dupx); + INT32 h = (vid.height / vid.dupy); + + const INT32 vidxdiff = (w - BASEVIDWIDTH) / 2; + const INT32 vidydiff = (h - BASEVIDHEIGHT) / 2; + if (!useinterpic && y_screenbuffer == NULL #ifdef HWRENDER // TODO resolution changes breaks the screentexture capture, I have no clue why @@ -482,7 +497,7 @@ void Y_IntermissionDrawer(void) INT32 y = 41, gutter = ((data.numplayers > NUMFORNEWCOLUMN) ? 0 : (BASEVIDWIDTH/2)); INT32 dupadjust = (vid.width/vid.dupx), duptweak = (dupadjust - BASEVIDWIDTH)/2; const char *timeheader; - + boolean manyplayers16 = (data.numplayers > NUMFORNEWCOLUMN*2); boolean manyplayers8 = (data.numplayers > NUMFORNEWCOLUMN); boolean displayitemrolls = (data.itemrolls && (intertic <= rolltic)); @@ -557,7 +572,15 @@ void Y_IntermissionDrawer(void) y--; if (manyplayers16||displayitemrolls) - V_DrawPingNum(x + 6, (displayitemrolls) ? y-2 : y+2, 0, data.pos[i], NULL); + { + if (displayitemrolls) + V_SetClipRect((-vidxdiff - 2) * FRACUNIT, (36) * FRACUNIT, w*FRACUNIT, (h - 36)*FRACUNIT, 0); + + V_DrawPingNum(x + 6, ((displayitemrolls) ? y-2 : y+2) - (yscroll / FRACUNIT), 0, data.pos[i], NULL); + + if (displayitemrolls) + V_ClearClipRect(); + } else V_DrawCenteredString(x+6, y, 0, va("%d", data.pos[i])); @@ -588,7 +611,13 @@ void Y_IntermissionDrawer(void) xoffs = FixedMul(16, scale); yoffs = FixedMul(4, scale); - V_DrawFixedPatch((x+xoffs)< (TICRATE * 2)) && (intertic <= rolltic)) + { + + if (!listscroll_reverse) + { + if ((yscroll >= listscroll_length)) + { + if (!listscroll_delay) + listscroll_delay = ITEMLIST_SCROLLDELAY; + } + else + yscroll = min(listscroll_length, yscroll + ITEMLIST_SCROLLSPEED); + } + else + { + if ((yscroll <= 0)) + { + if (!listscroll_delay) + listscroll_delay = ITEMLIST_SCROLLDELAY; + } + else + yscroll = max(0, yscroll - ITEMLIST_SCROLLSPEED); + } + + if (listscroll_delay) + { + listscroll_delay--; + + if (!listscroll_delay) + listscroll_reverse = (!listscroll_reverse); + } + } + else + { + listscroll_delay = 0; + listscroll_reverse = false; + + if (yscroll > 0) + { + if (intertic < rolltic) + yscroll = max(0, yscroll - ITEMLIST_SCROLLSPEED); + else + yscroll = 0; + } + } + // Team scramble code for team match and CTF. // Don't do this if we're going to automatically scramble teams next round. /*if (G_GametypeHasTeams() && cv_teamscramble.value && !cv_scrambleonchange.value && server) @@ -1010,7 +1102,7 @@ void Y_StartIntermission(void) if (!timer) { // Prevent a weird bug - timer = 1; + timer = 1; } else if (nump < 2 && !netgame) { @@ -1062,7 +1154,19 @@ void Y_StartIntermission(void) if (data.itemrolls) { - rolltic = 15 * TICRATE; + // Used to scroll the end-of-race item list. + UINT16 manyplayers18 = max(0, nump - 18); + + // Let's precalculate this, so it's not being done in the Big Stupid Player Loop + fixed_t listscroll_length = (manyplayers18 * ITEMLIST_PLAYER_YOFFSET * FRACUNIT); + + // Same for the time needed + // We'll scroll the list up and down 3 times, and have 2 seconds before scrolling happens + tic_t timetoscrolllist = (listscroll_length / ITEMLIST_SCROLLSPEED); + tic_t listscroll_time = ((ITEMLIST_SCROLLREPEAT * 2) * (ITEMLIST_SCROLLDELAY + timetoscrolllist)) + (TICRATE * 2); + + rolltic = max(15 * TICRATE, listscroll_time); + sorttic += rolltic; timer += rolltic; } @@ -2227,3 +2331,7 @@ void Y_SetupVoteFinish(SINT8 pick, SINT8 level) g_pickedVote = pick; timer = 0; } + +#undef ITEMLIST_PLAYER_YOFFSET +#undef ITEMLIST_SCROLLSPEED +#undef ITEMLIST_SCROLLDELAY From 9cd116cc4fc2b2de0ea8af9f33154f17a181fc73 Mon Sep 17 00:00:00 2001 From: yamamama Date: Tue, 9 Dec 2025 23:01:59 -0500 Subject: [PATCH 06/10] Reformat item list --- src/k_hud.c | 2 +- src/k_hud.h | 2 ++ src/y_inter.c | 72 ++++++++++++++++++++++++--------------------------- 3 files changed, 37 insertions(+), 39 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index e356b3bb7..bd4e97e85 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -136,7 +136,7 @@ static patch_t *kp_racefinish[6]; static patch_t *kp_positionnum[NUMPOSNUMS][NUMPOSFRAMES]; static patch_t *kp_winnernum[NUMPOSFRAMES]; -static patch_t *kp_facenum[MAXPLAYERS+1]; +patch_t *kp_facenum[MAXPLAYERS+1]; static patch_t *kp_facehighlight[8]; static patch_t *kp_nocontestminimap; diff --git a/src/k_hud.h b/src/k_hud.h index 65f4bf8b2..d1c34057c 100644 --- a/src/k_hud.h +++ b/src/k_hud.h @@ -66,6 +66,8 @@ extern consvar_t cv_colorizedhudcolor; extern consvar_t cv_newtabranking; +extern patch_t *kp_facenum[MAXPLAYERS+1]; + struct trackingResult_t { fixed_t x, y; diff --git a/src/y_inter.c b/src/y_inter.c index 240163853..3b953f6dd 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -49,16 +49,17 @@ #include "k_grandprix.h" #include "k_bot.h" // cv_botcanvote #include "r_fps.h" // R_GetTimeFrac +#include "k_hud.h" #include "k_itemlist.hpp" #ifdef HWRENDER #include "hardware/hw_main.h" #endif -#define ITEMLIST_PLAYER_YOFFSET 8 +#define ITEMLIST_PLAYER_YOFFSET 9 #define ITEMLIST_SCROLLSPEED (3 * FRACUNIT / 4) -#define ITEMLIST_SCROLLDELAY (TICRATE) -#define ITEMLIST_SCROLLREPEAT 2 +#define ITEMLIST_SCROLLDELAY (3 * TICRATE) +#define ITEMLIST_SCROLLREPEAT 1 typedef struct { @@ -571,15 +572,16 @@ void Y_IntermissionDrawer(void) if (dojitter) y--; - if (manyplayers16||displayitemrolls) + if (displayitemrolls) { - if (displayitemrolls) - V_SetClipRect((-vidxdiff - 2) * FRACUNIT, (36) * FRACUNIT, w*FRACUNIT, (h - 36)*FRACUNIT, 0); - - V_DrawPingNum(x + 6, ((displayitemrolls) ? y-2 : y+2) - (yscroll / FRACUNIT), 0, data.pos[i], NULL); - - if (displayitemrolls) - V_ClearClipRect(); + if (data.pos[i] < 0 || data.pos[i] > 16) + V_DrawPingNum(x+2, y+1, 0, data.pos[i], NULL); + else + V_DrawScaledPatch(x-5, y+1, 0, kp_facenum[data.pos[i]]); + } + else if (manyplayers16) + { + V_DrawPingNum(x + 6, y + 2, 0, data.pos[i], NULL); } else V_DrawCenteredString(x+6, y, 0, va("%d", data.pos[i])); @@ -589,10 +591,7 @@ void Y_IntermissionDrawer(void) UINT8 *colormap = R_GetTranslationColormap(*data.character[i], *data.color[i], GTC_CACHE); patch_t *facerank; - if (displayitemrolls) - facerank = faceprefix[*data.character[i]][FACE_MINIMAP]; - else - facerank = faceprefix[*data.character[i]][FACE_RANK]; + facerank = faceprefix[*data.character[i]][FACE_RANK]; fixed_t scale = FRACUNIT; @@ -612,14 +611,22 @@ void Y_IntermissionDrawer(void) yoffs = FixedMul(4, scale); if (displayitemrolls) - V_SetClipRect((-vidxdiff - 2) * FRACUNIT, (36) * FRACUNIT, w*FRACUNIT, (h - 36)*FRACUNIT, 0); + { + V_DrawFixedPatch( + ((x+11)*FRACUNIT) + ((facerank->leftoffset) * scale), + ((y+1)*FRACUNIT) + ((facerank->topoffset) * scale), + scale, + 0, + facerank, + colormap + ); - V_DrawFixedPatch((x+xoffs)< slen) ? slen_temp : slen); } } @@ -726,9 +724,7 @@ void Y_IntermissionDrawer(void) } else if (data.itemrolls && (intertic <= rolltic)) { - V_SetClipRect((-vidxdiff - 2) * FRACUNIT, (36) * FRACUNIT, w*FRACUNIT, (h - 36)*FRACUNIT, 0); - K_DrawItemList((INT32)(&players[data.num[i]] - players), (xx+2+slen) * FRACUNIT, ((y-1-(yscroll / FRACUNIT)) * FRACUNIT)); - V_ClearClipRect(); + K_DrawItemList((INT32)(&players[data.num[i]] - players), (xx+2+slen) * FRACUNIT, ((y+1) * FRACUNIT)); } else { @@ -781,7 +777,7 @@ void Y_IntermissionDrawer(void) { y += (displayitemrolls) ? ITEMLIST_PLAYER_YOFFSET : 18; - if ((!displayitemrolls) && i == NUMFORNEWCOLUMN-1) + if ((i % 16) == (((displayitemrolls) ? 2 : 1) * NUMFORNEWCOLUMN) - 1) { y = 41; x += BASEVIDWIDTH/2; From 6a18829608f30a4c00f8d9711638fc9df8e13308 Mon Sep 17 00:00:00 2001 From: yamamama Date: Fri, 12 Dec 2025 19:58:43 -0500 Subject: [PATCH 07/10] HORIZONTAL scrolling! --- src/k_itemlist.cpp | 7 +++-- src/k_itemlist.hpp | 2 +- src/y_inter.c | 68 ++++++++++++++++++++++------------------------ 3 files changed, 39 insertions(+), 38 deletions(-) diff --git a/src/k_itemlist.cpp b/src/k_itemlist.cpp index 1ce618e38..2b17e31be 100644 --- a/src/k_itemlist.cpp +++ b/src/k_itemlist.cpp @@ -116,10 +116,10 @@ extern "C" #define ITEMLOG_SPACE 1 // Draws an item in the player's item list. Draws nothing if the list is empty. - void K_DrawItemList(INT32 pid, fixed_t x, fixed_t y) + fixed_t K_DrawItemList(INT32 pid, fixed_t x, fixed_t y) { if (itemcounter[pid].size() < 1) - return; + return 0; patch_t* localpatch; fixed_t dx = x; @@ -142,6 +142,9 @@ extern "C" 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 diff --git a/src/k_itemlist.hpp b/src/k_itemlist.hpp index 9b9c8f9e7..4ab4aa2c8 100644 --- a/src/k_itemlist.hpp +++ b/src/k_itemlist.hpp @@ -8,7 +8,7 @@ extern "C" void K_ClearItemRollLists(void); void K_AddItemRollToList(INT32 pid, kartitemtype_e item, INT32 amount); - void K_DrawItemList(INT32 pid, fixed_t x, fixed_t y); + fixed_t K_DrawItemList(INT32 pid, fixed_t x, fixed_t y); UINT32 K_GetItemListSize(INT32 pid); // Getter and setter diff --git a/src/y_inter.c b/src/y_inter.c index 3b953f6dd..89c0219a4 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -122,9 +122,10 @@ static INT32 endtic = -1; static INT32 sorttic = -1; static INT32 rolltic = -1; +static fixed_t listscroll_length = 0; static boolean listscroll_reverse = false; static INT32 listscroll_delay = 0; -fixed_t yscroll = 0; +static fixed_t xscroll = 0; intertype_t intertype = int_none; intertype_t intermissiontypes[NUMGAMETYPES]; @@ -409,7 +410,7 @@ void Y_CleanupScreenBuffer(void) void Y_IntermissionDrawer(void) { INT32 i, whiteplayer = MAXPLAYERS, x = 4, hilicol = V_YELLOWMAP; // fallback - INT32 xx = x; + INT32 xx = x, x_base = x; if (intertype == int_none || rendermode == render_none) return; @@ -497,6 +498,7 @@ void Y_IntermissionDrawer(void) #define NUMFORNEWCOLUMN 8 INT32 y = 41, gutter = ((data.numplayers > NUMFORNEWCOLUMN) ? 0 : (BASEVIDWIDTH/2)); INT32 dupadjust = (vid.width/vid.dupx), duptweak = (dupadjust - BASEVIDWIDTH)/2; + fixed_t newlist_xpush = (BASEVIDWIDTH/2) * FRACUNIT; const char *timeheader; boolean manyplayers16 = (data.numplayers > NUMFORNEWCOLUMN*2); @@ -560,6 +562,8 @@ void Y_IntermissionDrawer(void) V_DrawRightAlignedString(x+152, 24, hilicol, timeheader); } + INT32 xscroll_px = (xscroll / FRACUNIT); + for (i = 0; i < data.numplayers; i++) { boolean dojitter = data.jitter[data.num[i]]; @@ -575,9 +579,9 @@ void Y_IntermissionDrawer(void) if (displayitemrolls) { if (data.pos[i] < 0 || data.pos[i] > 16) - V_DrawPingNum(x+2, y+1, 0, data.pos[i], NULL); + V_DrawPingNum(x+2-xscroll_px, y+1, 0, data.pos[i], NULL); else - V_DrawScaledPatch(x-5, y+1, 0, kp_facenum[data.pos[i]]); + V_DrawScaledPatch(x-5-xscroll_px, y+1, 0, kp_facenum[data.pos[i]]); } else if (manyplayers16) { @@ -613,7 +617,7 @@ void Y_IntermissionDrawer(void) if (displayitemrolls) { V_DrawFixedPatch( - ((x+11)*FRACUNIT) + ((facerank->leftoffset) * scale), + ((x+11-xscroll_px)*FRACUNIT) + ((facerank->leftoffset) * scale), ((y+1)*FRACUNIT) + ((facerank->topoffset) * scale), scale, 0, @@ -621,7 +625,13 @@ void Y_IntermissionDrawer(void) colormap ); - xx = (x+11) + 20; + if ((x_base - x) == 0) + { + // Terrible hack to remedy offset woes: Set a "base" value for x to reference. + x_base = (x+11) + 20; + } + + xx = x + x_base - 4; } else { @@ -663,7 +673,7 @@ void Y_IntermissionDrawer(void) V_DrawThinString(x+18, y, ((data.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, strtime); else if (displayitemrolls) { - V_DrawThinString(x + 20, y, ((data.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, strtime); + V_DrawThinString(x + 20 - xscroll_px, y, ((data.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, strtime); // Get the longest string size. This is... gross. INT32 ii; @@ -724,7 +734,8 @@ void Y_IntermissionDrawer(void) } else if (data.itemrolls && (intertic <= rolltic)) { - K_DrawItemList((INT32)(&players[data.num[i]] - players), (xx+2+slen) * FRACUNIT, ((y+1) * FRACUNIT)); + const fixed_t itemlistlen = K_DrawItemList((INT32)(data.num[i]), ((xx+2+slen-xscroll_px) * FRACUNIT), ((y+1) * FRACUNIT)); + newlist_xpush = max(newlist_xpush, ((x_base+9+slen) * FRACUNIT) + itemlistlen); } else { @@ -780,12 +791,15 @@ void Y_IntermissionDrawer(void) if ((i % 16) == (((displayitemrolls) ? 2 : 1) * NUMFORNEWCOLUMN) - 1) { y = 41; - x += BASEVIDWIDTH/2; + x += (newlist_xpush / FRACUNIT); + + newlist_xpush = (BASEVIDWIDTH / 2) * FRACUNIT; } } - #undef NUMFORNEWCOLUMN } + + listscroll_length = max(0, x - BASEVIDWIDTH) * FRACUNIT; } skiptallydrawer: @@ -866,34 +880,28 @@ void Y_Ticker(void) intertic++; - // Used to scroll the end-of-race item list. - UINT16 manyplayers18 = max(0, data.numplayers - 18); - - // Let's precalculate this, so it's not being done in the Big Stupid Player Loop - fixed_t listscroll_length = (manyplayers18 * ITEMLIST_PLAYER_YOFFSET * FRACUNIT); - if (listscroll_length && (intertic > (TICRATE * 2)) && (intertic <= rolltic)) { if (!listscroll_reverse) { - if ((yscroll >= listscroll_length)) + if ((xscroll >= listscroll_length)) { if (!listscroll_delay) listscroll_delay = ITEMLIST_SCROLLDELAY; } else - yscroll = min(listscroll_length, yscroll + ITEMLIST_SCROLLSPEED); + xscroll = min(listscroll_length, xscroll + ITEMLIST_SCROLLSPEED); } else { - if ((yscroll <= 0)) + if ((xscroll <= 0)) { if (!listscroll_delay) listscroll_delay = ITEMLIST_SCROLLDELAY; } else - yscroll = max(0, yscroll - ITEMLIST_SCROLLSPEED); + xscroll = max(0, xscroll - ITEMLIST_SCROLLSPEED); } if (listscroll_delay) @@ -906,15 +914,16 @@ void Y_Ticker(void) } else { + listscroll_length = 0; listscroll_delay = 0; listscroll_reverse = false; - if (yscroll > 0) + if (xscroll > 0) { if (intertic < rolltic) - yscroll = max(0, yscroll - ITEMLIST_SCROLLSPEED); + xscroll = max(0, xscroll - ITEMLIST_SCROLLSPEED); else - yscroll = 0; + xscroll = 0; } } @@ -1150,18 +1159,7 @@ void Y_StartIntermission(void) if (data.itemrolls) { - // Used to scroll the end-of-race item list. - UINT16 manyplayers18 = max(0, nump - 18); - - // Let's precalculate this, so it's not being done in the Big Stupid Player Loop - fixed_t listscroll_length = (manyplayers18 * ITEMLIST_PLAYER_YOFFSET * FRACUNIT); - - // Same for the time needed - // We'll scroll the list up and down 3 times, and have 2 seconds before scrolling happens - tic_t timetoscrolllist = (listscroll_length / ITEMLIST_SCROLLSPEED); - tic_t listscroll_time = ((ITEMLIST_SCROLLREPEAT * 2) * (ITEMLIST_SCROLLDELAY + timetoscrolllist)) + (TICRATE * 2); - - rolltic = max(15 * TICRATE, listscroll_time); + rolltic = (15 * TICRATE); sorttic += rolltic; timer += rolltic; From a77355889b09809c41968609bb16a78ef1ee22be Mon Sep 17 00:00:00 2001 From: yamamama Date: Fri, 12 Dec 2025 21:06:43 -0500 Subject: [PATCH 08/10] Add some itemlist functions to Lua Proper library... at some point. --- src/lua_baselib.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 2a26b415b..c01d557a5 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -34,6 +34,7 @@ #include "k_hud.h" #include "k_waypoint.h" #include "k_items.h" +#include "k_itemlist.hpp" #include "d_netcmd.h" // IsPlayerAdmin #include "m_menu.h" // Player Setup menu color stuff #include "p_spec.h" // P_StartQuake @@ -5244,6 +5245,75 @@ static int lib_kSetPlayerItemCooldown(lua_State *L) return 0; } +static int lib_kAddItemRollToList(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + kartitemtype_e item_id = (kartitemtype_e)luaL_checkinteger(L, 2); + INT32 amt = luaL_checkinteger(L, 3); + //HUDSAFE + + if (!player) + return LUA_ErrInvalid(L, "player_t"); + + if (item_id < 1 || item_id >= numkartitems) + return luaL_error(L, "item number %d out of range (1 - %d)", item_id, numkartitems-1); + + INT32 pid = (INT32)(player - players); + + K_AddItemRollToList(pid, item_id, amt); + return 0; +} + +static int lib_kGetItemListSize(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + //HUDSAFE + + if (!player) + return LUA_ErrInvalid(L, "player_t"); + + INT32 pid = (INT32)(player - players); + + lua_pushinteger(L, K_GetItemListSize(pid)); + return 1; +} + +static int lib_kSetItemListEntry(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + kartitemtype_e item_id = (kartitemtype_e)luaL_checkinteger(L, 2); + INT32 num = luaL_checkinteger(L, 3); + //HUDSAFE + + if (!player) + return LUA_ErrInvalid(L, "player_t"); + + if (item_id < 1 || item_id >= numkartitems) + return luaL_error(L, "item number %d out of range (1 - %d)", item_id, numkartitems-1); + + INT32 pid = (INT32)(player - players); + + K_SetItemListEntry(pid, item_id, num); + return 0; +} + +static int lib_kGetItemListEntry(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + kartitemtype_e item_id = (kartitemtype_e)luaL_checkinteger(L, 2); + //HUDSAFE + + if (!player) + return LUA_ErrInvalid(L, "player_t"); + + if (item_id < 1 || item_id >= numkartitems) + return luaL_error(L, "item number %d out of range (1 - %d)", item_id, numkartitems-1); + + INT32 pid = (INT32)(player - players); + lua_pushinteger(L, K_GetItemListEntry(pid, item_id)); + return 1; +} + // G_INPUT //////////// @@ -5706,6 +5776,12 @@ static luaL_Reg lib[] = { // k_items {"K_SetPlayerItemCooldown", lib_kSetPlayerItemCooldown}, + // k_itemlist + {"K_AddItemRollToList", lib_kAddItemRollToList}, + {"K_GetItemListSize", lib_kGetItemListSize}, + {"K_SetItemListEntry", lib_kSetItemListEntry}, + {"K_GetItemListEntry", lib_kGetItemListEntry}, + //g_input {"G_SetPlayerGamepadIndicatorColor",lib_gSetPlayerGamepadIndicatorColor}, {"G_PlayerDeviceRumble",lib_gPlayerDeviceRumble}, From 67a0d061da03c018399cd2b141a0c4e49d208209 Mon Sep 17 00:00:00 2001 From: yamamama Date: Fri, 12 Dec 2025 21:17:29 -0500 Subject: [PATCH 09/10] *patrick mouth gif* --- src/k_items.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/k_items.c b/src/k_items.c index 5d15d8c1f..4b127ba17 100644 --- a/src/k_items.c +++ b/src/k_items.c @@ -381,7 +381,8 @@ void K_AwardPlayerItem(player_t *player, kartitemtype_e type, UINT8 amount, kart player->itemamount = amount; - K_AddItemRollToList((INT32)(player - players), type, amount); + if (cv_itemlist.value) + K_AddItemRollToList((INT32)(player - players), type, amount); } static void K_AwardPlayerResult(player_t *player, kartresult_t *result, kartitemblink_e blink) From b937c0519ca53844e63db1b26fc4c0e7e0d76646 Mon Sep 17 00:00:00 2001 From: yamamama Date: Fri, 12 Dec 2025 21:37:56 -0500 Subject: [PATCH 10/10] Reformat the stupid cvar --- src/d_netcmd.c | 36 +++++++++++++++++++++++++++++++++++- src/k_items.c | 2 +- src/k_kart.c | 11 +++++++++++ src/k_kart.h | 1 + src/lua_baselib.c | 7 +++++++ src/p_mobj.h | 1 + src/p_saveg.c | 1 + src/p_setup.c | 5 +++++ src/y_inter.c | 2 +- 9 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 9e7914e1e..0c6c5f92c 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -175,6 +175,7 @@ static void KartItemPush_OnChange(void); static void KartAntiBump_OnChange(void); static void KartItemBreaker_OnChange(void); static void KartBumpSpark_OnChange(void); +static void KartItemList_OnChange(void); static void Schedule_OnChange(void); @@ -606,7 +607,7 @@ consvar_t cv_kartlegacyspbdist = CVAR_INIT ("kartlegacyspbdist", "2216", CV_NETV // SPB Rush toggle; toggles on/off the more aggressive "pressure" odds when an SPB is active consvar_t cv_kartspbrush = CVAR_INIT ("kartspbrush", "On", CV_NETVAR, CV_OnOff, NULL); -consvar_t cv_itemlist = CVAR_INIT ("kartitemlist", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_itemlist = CVAR_INIT ("kartitemlist", "On", CV_NETVAR|CV_CALL|CV_NOINIT, CV_OnOff, KartItemList_OnChange); // Time limit for Alt. Shrink static CV_PossibleValue_t altshrinktime_cons_t[] = {{0, "MIN"}, {(INT16_MAX / TICRATE), "MAX"}, {0, NULL}}; @@ -8357,6 +8358,39 @@ static void KartBumpSpark_OnChange(void) } } +static void KartItemList_OnChange(void) +{ + if (K_CanChangeRules(false) == false) + { + return; + } + + if (!K_ItemListActive() && cv_itemlist.value) + { + if (leveltime < starttime) + { + itemlistactive = true; + CONS_Printf(M_GetText("Item rolls will be displayed.\n")); + } + else + { + CONS_Printf(M_GetText("Item rolls will be displayed next round.\n")); + } + } + else if (K_ItemListActive() && !cv_itemlist.value) + { + if (leveltime < starttime) + { + itemlistactive = false; + CONS_Printf(M_GetText("Item rolls will not be displayed.\n")); + } + else + { + CONS_Printf(M_GetText("Item rolls will not be displayed next round.\n")); + } + } +} + static void Schedule_OnChange(void) { size_t i; diff --git a/src/k_items.c b/src/k_items.c index 4b127ba17..62ecabf6e 100644 --- a/src/k_items.c +++ b/src/k_items.c @@ -381,7 +381,7 @@ void K_AwardPlayerItem(player_t *player, kartitemtype_e type, UINT8 amount, kart player->itemamount = amount; - if (cv_itemlist.value) + if (itemlistactive) K_AddItemRollToList((INT32)(player - players), type, amount); } diff --git a/src/k_kart.c b/src/k_kart.c index d27926797..7c21a3001 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10972,6 +10972,17 @@ boolean K_ItemLitterActive(void) return false; } +boolean K_ItemListActive(void) +{ + if (itemlistactive) + { + // Item listing is enabled! + return true; + } + + return false; +} + boolean K_ItemPushingActive(void) { return itempushing; diff --git a/src/k_kart.h b/src/k_kart.h index 9017f4a8f..9291108ba 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -357,6 +357,7 @@ boolean K_DraftingActive(void); boolean K_AirDropActive(void); boolean K_AirThrustActive(void); boolean K_ItemLitterActive(void); +boolean K_ItemListActive(void); boolean K_ItemPushingActive(void); INT32 K_GetBumpSpark(void); boolean K_BoostChain(player_t *player, INT32 timer, boolean chainsound); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index c01d557a5..263fbafb8 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -4365,6 +4365,12 @@ static int lib_kItemLitterActive(lua_State *L) return 1; } +static int lib_kItemListActive(lua_State *L) +{ + lua_pushboolean(L, K_ItemListActive()); + return 1; +} + // Gets the currently active bumpspark type. static int lib_kGetBumpSpark(lua_State *L) { @@ -5688,6 +5694,7 @@ static luaL_Reg lib[] = { {"K_DraftingActive",lib_kDraftingActive}, {"K_AirDropActive",lib_kAirDropActive}, {"K_ItemLitterActive",lib_kItemLitterActive}, + {"K_ItemListActive", lib_kItemListActive}, {"K_GetBumpSpark",lib_kGetBumpSpark}, {"K_UsingLegacyCheckpoints",lib_kUsingLegacyCheckpoints}, {"K_DoBoost",lib_kDoBoost}, diff --git a/src/p_mobj.h b/src/p_mobj.h index 6f83f8912..4501df66b 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -622,6 +622,7 @@ extern boolean airthrustactive; extern boolean itemlittering; extern boolean itempushing; extern UINT8 bumpsparkactive; +extern boolean itemlistactive; extern UINT16 bossdisabled; extern boolean stoppedclock; diff --git a/src/p_saveg.c b/src/p_saveg.c index 51bdf4ce2..ea58d3f74 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -4232,6 +4232,7 @@ static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending) SYNCBOOLEAN(airdropactive); SYNCBOOLEAN(itemlittering); SYNCBOOLEAN(itempushing); + SYNCBOOLEAN(itemlistactive); SYNC(bumpsparkactive); SYNC(antibumptime); diff --git a/src/p_setup.c b/src/p_setup.c index 90674eed6..8d1aff65b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -165,6 +165,7 @@ boolean airthrustactive; boolean itemlittering; boolean itempushing; UINT8 bumpsparkactive; +boolean itemlistactive; UINT16 bossdisabled; boolean stoppedclock; boolean levelloading; @@ -8178,6 +8179,7 @@ static void P_InitLevelSettings(boolean reloadinggamestate) airthrustactive = false; itemlittering = false; itempushing = false; + itemlistactive = false; bumpsparkactive = 0; antibumptime = 0; @@ -8214,6 +8216,9 @@ static void P_InitLevelSettings(boolean reloadinggamestate) if (cv_kartitempush.value) itempushing = true; + if (cv_itemlist.value) + itemlistactive = true; + bumpsparkactive = (UINT8)cv_kartbumpspark.value; antibumptime = (tic_t)cv_kartantibump.value * TICRATE; diff --git a/src/y_inter.c b/src/y_inter.c index 89c0219a4..d196758c9 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -101,7 +101,7 @@ static boolean Y_ItemListActive(void) nump++; } - return ((cv_itemlist.value != 0) && (nump > 1)); + return ((itemlistactive) && (nump > 1)); } static y_data data;