From 8faba2dd35e0dc0ec67e4adbfea934b96787e109 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Wed, 28 May 2025 10:35:32 -0400 Subject: [PATCH 1/3] Basic voting rows port Still crashes and seems to mess with the newgametype --- src/d_netcmd.c | 24 ++++-- src/d_netcmd.h | 2 + src/doomstat.h | 2 +- src/g_game.c | 2 +- src/p_saveg.c | 4 +- src/y_inter.c | 203 ++++++++++++++++++++++++++++++++++++++++--------- 6 files changed, 192 insertions(+), 45 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index abeb4f548..a9860d3f0 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -570,6 +570,9 @@ consvar_t cv_forceskin = CVAR_INIT ("forceskin", "None", CV_NETVAR|CV_CALL|CV_CH consvar_t cv_downloading = CVAR_INIT ("downloading", "On", 0, CV_OnOff, NULL); consvar_t cv_allowexitlevel = CVAR_INIT ("allowexitlevel", "No", CV_NETVAR, CV_YesNo, NULL); +static CV_PossibleValue_t votemaxrows_cons_t[] = {{1, "MIN"}, {3, "MAX"}, {0, NULL}}; +consvar_t cv_votemaxrows = CVAR_INIT ("votemaxrows", "2", CV_SAVE|CV_NETVAR, votemaxrows_cons_t, NULL); + consvar_t cv_netstat = CVAR_INIT ("netstat", "Off", 0, CV_OnOff, NULL); // show bandwidth statistics static CV_PossibleValue_t nettimeout_cons_t[] = {{TICRATE/7, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}}; consvar_t cv_nettimeout = CVAR_INIT ("nettimeout", "210", CV_CALL|CV_SAVE, nettimeout_cons_t, NetTimeout_OnChange); @@ -649,6 +652,9 @@ UINT8 splitscreen = 0; boolean circuitmap = false; INT32 adminplayers[MAXPLAYERS]; +#define VOTEROWS ((cv_votemaxrows.value*3) + ((cv_votemaxrows.value > 1) ? (cv_votemaxrows.value - 1) : 0)) +#define VOTEROWSADDSONE ((cv_votemaxrows.value*3) + 1 + ((cv_votemaxrows.value > 1) ? (cv_votemaxrows.value - 1) : 0)) + // Scheduled commands. scheduleTask_t **schedule = NULL; size_t schedule_size = 0; @@ -854,6 +860,7 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_playbackspeed); CV_RegisterVar(&cv_forceskin); CV_RegisterVar(&cv_downloading); + CV_RegisterVar(&cv_votemaxrows); K_RegisterKartStuff(); // SRB2kart @@ -2776,7 +2783,7 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pencoremode, boolean r void D_SetupVote(void) { - UINT8 buf[5*2]; // four UINT16 maps (at twice the width of a UINT8), and two gametypes + UINT8 buf[13*2]; // twelve UINT16 maps (at twice the width of a UINT8), and two gametypes UINT8 *p = buf; INT32 i; UINT8 gt = (cv_kartgametypepreference.value == -1) ? gametype : cv_kartgametypepreference.value; @@ -2794,16 +2801,17 @@ void D_SetupVote(void) WRITEUINT8(p, secondgt); secondgt &= ~VOTEMODIFIER_ENCORE; - for (i = 0; i < 4; i++) + for (i = 0; i < VOTEROWSADDSONE; i++) { UINT16 m; + if (i == 2) // sometimes a different gametype m = G_RandMap(G_TOLFlag(secondgt), prevmap, ((secondgt != gametype) ? 2 : 0), 0, true, votebuffer); - else if (i >= 3) // unknown-random and formerly force-unknown MAP HELL + else if (i >= VOTEROWS) // unknown-random and formerly force-unknown MAP HELL m = G_RandMap(G_TOLFlag(gt), prevmap, 0, (i-2), (i < 4), votebuffer); else m = G_RandMap(G_TOLFlag(gt), prevmap, 0, 0, true, votebuffer); - if (i < 3) + if (i < VOTEROWS) votebuffer[i] = m; WRITEUINT16(p, m); } @@ -5510,7 +5518,7 @@ static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum) { INT32 i; UINT8 gt, secondgt; - INT16 tempvotelevels[4][2]; + INT16 tempvotelevels[12][2]; if (playernum != serverplayer) // admin shouldn't be able to set up vote... { @@ -5520,6 +5528,7 @@ static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum) return; } + // Get gametype data. gt = (UINT8)READUINT8(*cp); secondgt = (UINT8)READUINT8(*cp); @@ -5530,7 +5539,7 @@ static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum) gt &= ~VOTEMODIFIER_ENCORE; } - for (i = 0; i < 4; i++) + for (i = 0; i < VOTEROWSADDSONE; i++) { tempvotelevels[i][0] = (UINT16)READUINT16(*cp); tempvotelevels[i][1] = gt; @@ -7320,3 +7329,6 @@ void Got_DiscordInfo(UINT8 **p, INT32 playernum) (*p) += 3; #endif } + +#undef VOTEROWS +#undef VOTEROWSADDSONE diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 9d9b7e656..4c9419642 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -52,6 +52,8 @@ extern consvar_t cv_numlaps; extern UINT32 timelimitintics, extratimeintics, secretextratime; extern consvar_t cv_allowexitlevel; +extern consvar_t cv_votemaxrows; + extern consvar_t cv_autobalance; extern consvar_t cv_teamscramble; extern consvar_t cv_scrambleonchange; diff --git a/src/doomstat.h b/src/doomstat.h index 26920a9f4..bbcc7c8cd 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -681,7 +681,7 @@ extern boolean legitimateexit; extern boolean comebackshowninfo; extern tic_t curlap, bestlap; -extern INT16 votelevels[4][2]; +extern INT16 votelevels[12][2]; extern SINT8 votes[MAXPLAYERS]; extern SINT8 pickedvote; diff --git a/src/g_game.c b/src/g_game.c index fa783f4e1..be2340a10 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -288,7 +288,7 @@ boolean franticitems; // Frantic items currently enabled? boolean comeback; // Battle Mode's karma comeback is on/off // Voting system -INT16 votelevels[4][2]; // Levels that were rolled by the host +INT16 votelevels[12][2]; // Levels that were rolled by the host SINT8 votes[MAXPLAYERS]; // Each player's vote SINT8 pickedvote; // What vote the host rolls diff --git a/src/p_saveg.c b/src/p_saveg.c index b608e3724..7961959f1 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -5140,7 +5140,7 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending) WRITEUINT8(save->p, slipdashactive); WRITEUINT8(save->p, purpledriftactive); - for (i = 0; i < 4; i++) + for (i = 0; i < 12; i++) { WRITEINT16(save->p, votelevels[i][0]); WRITEINT16(save->p, votelevels[i][1]); @@ -5313,7 +5313,7 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, bool slipdashactive = READUINT8(save->p); purpledriftactive = READUINT8(save->p); - for (i = 0; i < 4; i++) + for (i = 0; i < 12; i++) { votelevels[i][0] = READINT16(save->p); votelevels[i][1] = READINT16(save->p); diff --git a/src/y_inter.c b/src/y_inter.c index a1ee5c111..089bd2219 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -163,11 +163,14 @@ typedef struct boolean loaded; } y_voteclient; -static y_votelvlinfo levelinfo[5]; +static y_votelvlinfo levelinfo[13]; static y_voteclient voteclient; static INT32 votetic; static INT32 lastvotetic; static INT32 voteendtic = -1; +static SINT8 votemax = 3; +static INT32 voterowmem = 0; +static boolean rowchange = false; static boolean votenotyetpicked; static patch_t *cursor = NULL; static patch_t *cursor1 = NULL; @@ -1150,12 +1153,50 @@ static inline void Y_DrawAnimatedVoteScreenPatch(boolean widePatch) // void Y_VoteDrawer(void) { - INT32 i, x, y = 0, height = 0; + INT32 rowval, i, lvls, x, picdiff, y = 0, height = 0; UINT8 selected[4]; fixed_t rubyheight = 0; fixed_t scale; patch_t *pic; INT16 mapnum; + fixed_t picscale = FRACUNIT; // GREENRES + fixed_t picwidth = 160; + + // CEP: scale by screen hypotenuse for extra voting rows + INT32 vidx = ((vid.width) / vid.dupx); + INT32 vidy = ((vid.height) / vid.dupy); + fixed_t hypotf = 0; + INT32 hypoti = 0; + + // get the hypotenuse + hypoti = (vidx*vidx) + (vidy*vidy); + hypotf = FixedSqrt(hypoti); + + // convert the fixed_t back into an integer + hypoti = ((hypotf*10)/FRACUNIT); + + if ((voterowmem != cv_votemaxrows.value) && (votemax != cv_votemaxrows.value)) // voting rows were changed(?) + { + CONS_Printf(M_GetText("Max rows will be changed to %d on the next votescreen.\n"), cv_votemaxrows.value); // notify the players + voterowmem = cv_votemaxrows.value; + } + + // divisor for rescaling + INT32 hypotdiv = max(10, (40-hypoti)); + + // readjust the picscale + picscale *= 10; + picscale /= (40-hypoti); + picwidth *= picscale; + + // shitty hack to prevent alignment issues + if ( ((hypoti % 5) == 1) || ((hypoti % 5) == 4) || ((hypoti % 5) == 2) ) + { + if ((hypoti % 5) == 2) // scale DOWN the image + picscale -= (hypoti*16); + else + picscale += (hypoti*2); // scale UP the image + } if (rendermode == render_none) return; @@ -1200,7 +1241,8 @@ void Y_VoteDrawer(void) } } - for (i = 0; i < 4; i++) // First, we need to figure out the height of this thing... + rowval = (votemax*3)+((votemax > 1) ? (votemax - 1) : 0); + for (i = 0; i < (rowval+1); i++) // First, we need to figure out the height of this thing... { UINT8 j; selected[i] = 0; // Initialize @@ -1212,21 +1254,39 @@ void Y_VoteDrawer(void) } if (selected[i]) - height += 50; + height += 25; // 50 else height += 25; - if (i < 3) + if (i < rowval) height += 5-splitscreen; } + height /= votemax; + y = (200-height)/2; - for (i = 0; i < 4; i++) + picdiff = 80*( max(0, (votemax-1) ) ); // let's draw these in reverse order + lvls = -1; // shitty cheat + + for (i = 0; i < (rowval+1); i++) { const char *str; UINT8 j, color; - if (i == 3) + // CEP: hack hell + INT32 scaledpicdiff = ((picdiff*10)/hypotdiv); + INT32 fillscale = 800/hypotdiv; + INT32 hypotmod = (hypoti % 5); // hypotenuse mod 5, rescale the bounding box + INT32 hypotadd = ((hypotmod > 1) ? (hypotmod/4) : hypotmod); // how much do we add the bounding box by? + + // integer scaling makes me want to DIE + if (hypotmod == 3) + hypotadd += (1); + + scaledpicdiff *= 3; + scaledpicdiff /= 2; // 1.5 + + if (i == rowval) { str = "RANDOM"; mapnum = -1; @@ -1288,59 +1348,99 @@ void Y_VoteDrawer(void) if (votes[p] != -1 || players[p].spectator) continue; - handy += 6*(3-splitscreen) + (13*j); - V_DrawMappedPatch(BASEVIDWIDTH-124, handy, V_SNAPTORIGHT, thiscurs, colormap); + handy += 3*(3-splitscreen) + (13*j); + V_DrawMappedPatch(BASEVIDWIDTH-(1600/hypotdiv)-scaledpicdiff, handy, V_SNAPTORIGHT, thiscurs, colormap); if (votetic % 10 < 4) - V_DrawFill(BASEVIDWIDTH-100-sizeadd, y-sizeadd, 80+(sizeadd*2), 50+(sizeadd*2), 0|V_SNAPTORIGHT); + V_DrawFill(BASEVIDWIDTH-(1200/hypotdiv)-sizeadd-scaledpicdiff, y-sizeadd, (fillscale + (sizeadd*2) + hypotadd), ((500/hypotdiv)+(sizeadd*2)) + hypotadd, 0|V_SNAPTORIGHT); else - V_DrawFill(BASEVIDWIDTH-100-sizeadd, y-sizeadd, 80+(sizeadd*2), 50+(sizeadd*2), color|V_SNAPTORIGHT); + V_DrawFill(BASEVIDWIDTH-(1200/hypotdiv)-sizeadd-scaledpicdiff, y-sizeadd, (fillscale + (sizeadd*2) + hypotadd), ((500/hypotdiv)+(sizeadd*2)) + hypotadd, color|V_SNAPTORIGHT); sizeadd--; } if (!levelinfo[i].encore) - V_DrawFixedPatch((BASEVIDWIDTH-100)<= 16) + { + V_DrawFill(BASEVIDWIDTH-(1200/hypotdiv)-scaledpicdiff, y+10, w+1, 2, V_SNAPTORIGHT|31); + V_DrawFill(BASEVIDWIDTH-(1200/hypotdiv)-scaledpicdiff, y, w, 11, V_SNAPTORIGHT|levelinfo[i].gtc); + V_DrawDiag(BASEVIDWIDTH-(1200/hypotdiv)-scaledpicdiff+w+1, y, 12, V_SNAPTORIGHT|31); + V_DrawDiag(BASEVIDWIDTH-(1200/hypotdiv)-scaledpicdiff+w, y, 11, V_SNAPTORIGHT|levelinfo[i].gtc); + V_DrawThinString(BASEVIDWIDTH-(1188/hypotdiv)-scaledpicdiff, y+1, V_SNAPTORIGHT, levelinfo[i].gts); + } + else // literally almost entirely covers the map icon, let's just mark it red or something + { + V_DrawDiag(BASEVIDWIDTH-(1200/hypotdiv)-scaledpicdiff, y, 8, V_SNAPTORIGHT|31); + V_DrawDiag(BASEVIDWIDTH-(1200/hypotdiv)-scaledpicdiff, y, 6, V_SNAPTORIGHT|levelinfo[i].gtc); + } } - y += 50; + y += ((25*10) / (hypotdiv/2)); + lvls += 1; + + // screen height isn't doing us any favors + if (lvls >= 6) // loop over if we have an extra row + { + lvls = -2; + picdiff -= 90; // yes, this will overlap; no, I don't plan to change it + y = (200-height)/2; + y -= 5; + } } else { scale /= 2; if (!levelinfo[i].encore) - V_DrawFixedPatch((BASEVIDWIDTH-60)<= 6) + { + lvls = -2; + picdiff -= 90; + y = (200-height)/2; + y -= 5; } - y += 25; } y += 5-splitscreen; + lvls += 1; + + if (lvls >= 6) + { + lvls = -2; + picdiff -= 90; + y = (200-height)/2; + y -= 5; + } } x = 20; @@ -1353,7 +1453,7 @@ void Y_VoteDrawer(void) if ((playeringame[i] && !players[i].spectator) && votes[i] != -1) { - if (votes[i] >= 3 && (i != pickedvote || voteendtic == -1)) + if (votes[i] >= ((votemax*3)+((votemax > 1) ? (votemax - 1) : 0)) && (i != pickedvote || voteendtic == -1)) mapnum = -1; // randomlvl else mapnum = votelevels[votes[i]][0]; @@ -1442,7 +1542,7 @@ static void Y_VoteStops(SINT8 pick, SINT8 level) nextmap = votelevels[level][0]; //if (level == 4) - // S_StartSound(NULL, sfx_noooo2); // gasp + //S_StartSound(NULL, sfx_noooo2); // gasp if (mapheaderinfo[nextmap] && (mapheaderinfo[nextmap]->menuflags & LF2_HIDEINMENU)) S_StartSound(NULL, sfx_noooo1); // this is bad else if (netgame && P_IsLocalPlayer(&players[pick])) @@ -1490,7 +1590,7 @@ void Y_VoteTicker(void) if (!playeringame[i] || players[i].spectator) votes[i] = -1; // Spectators are the lower class, and have effectively no voice in the government. Democracy sucks. else if (pickedvote != -1 && votes[i] == -1) - votes[i] = 3; // Slow people get random + votes[i] = (votemax*3)+((votemax > 1) ? (votemax - 1) : 0); // Slow people get random } if (server && pickedvote != -1 && votes[pickedvote] == -1) // Uh oh! The person who got picked left! Recalculate, quick! @@ -1583,6 +1683,12 @@ void Y_VoteTicker(void) { UINT8 p; boolean pressed = false; + SINT8 votewrap = 0; + + if (votemax == 2) + votewrap = 3; + else if (votemax == 3) + votewrap = 7; switch (i) { @@ -1619,9 +1725,31 @@ void Y_VoteTicker(void) pressed = true; } + if (votemax > 1) // only allow side-movements for multi-row selections + { + // HORRIBLE hack, my GOD + if (G_PlayerInputDown(i, gc_turnright, false) && !pressed) // move right + { + if (voteclient.playerinfo[i].selection <= votewrap) + voteclient.playerinfo[i].selection += 4; + else + voteclient.playerinfo[i].selection -= ((votemax-1)*4); + pressed = true; + } + + if (G_PlayerInputDown(i, gc_turnleft, false) && !pressed) // move left + { + if (voteclient.playerinfo[i].selection > 3) + voteclient.playerinfo[i].selection -= 4; + else + voteclient.playerinfo[i].selection += ((votemax-1)*4); + pressed = true; + } + } + if (voteclient.playerinfo[i].selection < 0) - voteclient.playerinfo[i].selection = 3; - if (voteclient.playerinfo[i].selection > 3) + voteclient.playerinfo[i].selection = ((votemax*3)+((votemax > 1) ? (votemax-1) : 0) ); + if (voteclient.playerinfo[i].selection > ((votemax*3)+((votemax > 1) ? (votemax-1) : 0)) ) voteclient.playerinfo[i].selection = 0; if (G_PlayerInputDown(i, gc_accelerate, false) && pressed == false) @@ -1648,7 +1776,7 @@ void Y_VoteTicker(void) for (i = 0; i < MAXPLAYERS; i++) { if ((playeringame[i] && !players[i].spectator) && votes[i] == -1) - votes[i] = 3; + votes[i] = (votemax*3)+((votemax > 1) ? (votemax-1) : 0); } } else @@ -1690,8 +1818,13 @@ void Y_VoteTicker(void) void Y_StartVote(void) { INT32 i = 0; + INT32 rowval = (cv_votemaxrows.value*3)+((cv_votemaxrows.value > 1) ? (cv_votemaxrows.value - 1) : 0); boolean battlemode = ((votelevels[0][1] & ~VOTEMODIFIER_ENCORE) == GT_BATTLE); // todo gametyperules + votemax = cv_votemaxrows.value; // can we please avoid SIGSEGVs + voterowmem = cv_votemaxrows.value; // this is just for the notif system + rowchange = false; + votetic = -1; #ifdef PARANOIA @@ -1730,7 +1863,7 @@ void Y_StartVote(void) for (i = 0; i < MAXPLAYERS; i++) votes[i] = -1; - for (i = 0; i < 4; i++) + for (i = 0; i < (rowval + 1); i++) { // set up the encore levelinfo[i].encore = (votelevels[i][1] & VOTEMODIFIER_ENCORE); @@ -1836,7 +1969,7 @@ void Y_SetupVoteFinish(SINT8 pick, SINT8 level) for (i = 0; i < MAXPLAYERS; i++) { if ((playeringame[i] && !players[i].spectator) && votes[i] == -1) - votes[i] = 3; + votes[i] = (votemax*3)+((votemax > 1) ? (votemax - 1) : 0); if (votes[i] == -1 || endtype > 1) // Don't need to go on continue; From c96662e714267d2b763f3cf4134447ffb5943b01 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Wed, 28 May 2025 11:03:06 -0400 Subject: [PATCH 2/3] Fix incorrect gametype --- src/d_netcmd.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a9860d3f0..fee441638 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2804,15 +2804,21 @@ void D_SetupVote(void) for (i = 0; i < VOTEROWSADDSONE; i++) { UINT16 m; + UINT16 hellpick = 0; + + hellpick = ((i == ((VOTEROWS) + 1) ) ? 2 : 0); + + if (i == VOTEROWS) + hellpick = 1; if (i == 2) // sometimes a different gametype m = G_RandMap(G_TOLFlag(secondgt), prevmap, ((secondgt != gametype) ? 2 : 0), 0, true, votebuffer); else if (i >= VOTEROWS) // unknown-random and formerly force-unknown MAP HELL - m = G_RandMap(G_TOLFlag(gt), prevmap, 0, (i-2), (i < 4), votebuffer); + m = G_RandMap(G_TOLFlag(gt), prevmap, 0, hellpick, (i < VOTEROWSADDSONE), votebuffer); else m = G_RandMap(G_TOLFlag(gt), prevmap, 0, 0, true, votebuffer); if (i < VOTEROWS) - votebuffer[i] = m; + votebuffer[min(i, 2)] = m; // min() is a dumb workaround for gcc 4.4 array-bounds error WRITEUINT16(p, m); } From c1304672335a2bac58871484bc8daca6130f03b8 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Wed, 28 May 2025 15:53:27 -0400 Subject: [PATCH 3/3] Fix buffer overflow due to smaller array define --- src/y_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/y_inter.c b/src/y_inter.c index 089bd2219..a98d87205 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1154,7 +1154,7 @@ static inline void Y_DrawAnimatedVoteScreenPatch(boolean widePatch) void Y_VoteDrawer(void) { INT32 rowval, i, lvls, x, picdiff, y = 0, height = 0; - UINT8 selected[4]; + UINT8 selected[12]; fixed_t rubyheight = 0; fixed_t scale; patch_t *pic;