From cc0c99640f77389f8adb454fe2a12a47579af348 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sat, 27 Jan 2018 01:17:08 -0500 Subject: [PATCH] Work so far Crashes, but baseline's there --- src/console.c | 3 +- src/d_clisrv.c | 4 + src/d_main.c | 6 + src/d_netcmd.c | 4 +- src/g_game.c | 25 +++- src/g_game.h | 3 +- src/g_state.h | 1 + src/hu_stuff.c | 3 +- src/p_saveg.c | 2 + src/y_inter.c | 374 ++++++++++++++++++++++++++++++++++++++++++++++++- src/y_inter.h | 5 + 11 files changed, 420 insertions(+), 10 deletions(-) diff --git a/src/console.c b/src/console.c index 2270c51f..ab357018 100644 --- a/src/console.c +++ b/src/console.c @@ -1618,6 +1618,7 @@ void CON_Drawer(void) if (con_curlines > 0) CON_DrawConsole(); - else if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE || gamestate == GS_CREDITS) + else if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE || gamestate == GS_CREDITS + || gamestate == GS_VOTING) CON_DrawHudlines(); } diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 634c6b81..c97966f9 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2070,6 +2070,8 @@ static void CL_ConnectToServer(boolean viams) if (gamestate == GS_INTERMISSION) Y_EndIntermission(); // clean up intermission graphics etc + if (gamestate == GS_VOTING) + Y_EndVote(); DEBFILE(va("waiting %d nodes\n", doomcom->numnodes)); G_SetGamestate(GS_WAITINGPLAYERS); @@ -3393,6 +3395,8 @@ void SV_StopServer(void) if (gamestate == GS_INTERMISSION) Y_EndIntermission(); + if (gamestate == GS_VOTING) + Y_EndVote(); gamestate = wipegamestate = GS_NULL; localtextcmd[0] = 0; diff --git a/src/d_main.c b/src/d_main.c index f94331cd..3dd9a674 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -335,6 +335,12 @@ static void D_Display(void) HU_Drawer(); break; + case GS_VOTING: + Y_VoteDrawer(); + HU_Erase(); + HU_Drawer(); + break; + case GS_TIMEATTACK: break; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index b8eb5ec8..9d9e7269 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -422,8 +422,8 @@ consvar_t cv_maxping = {"maxping", "0", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NUL static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}}; consvar_t cv_inttime = {"inttime", "20", CV_NETVAR, inttime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static CV_PossibleValue_t advancemap_cons_t[] = {{0, "Off"}, {1, "Next"}, {2, "Random"}, {0, NULL}}; -consvar_t cv_advancemap = {"advancemap", "Next", CV_NETVAR, advancemap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t advancemap_cons_t[] = {{0, "Off"}, {1, "Next"}, {2, "Random"}, {3, "Vote"}, {0, NULL}}; +consvar_t cv_advancemap = {"advancemap", "Vote", CV_NETVAR, advancemap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t playersforexit_cons_t[] = {{0, "One"}, {1, "All"}, {0, NULL}}; consvar_t cv_playersforexit = {"playersforexit", "One", CV_NETVAR, playersforexit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/g_game.c b/src/g_game.c index cb20dbe8..41360a4b 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1761,6 +1761,9 @@ void G_DoLoadLevel(boolean resetplayer) if (gamestate == GS_INTERMISSION) Y_EndIntermission(); + if (gamestate == GS_VOTING) + Y_EndVote(); + G_SetGamestate(GS_LEVEL); for (i = 0; i < MAXPLAYERS; i++) @@ -2138,6 +2141,12 @@ void G_Ticker(boolean run) HU_Ticker(); break; + case GS_VOTING: + if (run) + Y_VoteTicker(); + HU_Ticker(); + break; + case GS_TIMEATTACK: break; @@ -3025,7 +3034,7 @@ INT16 G_TOLFlag(INT32 pgametype) * has those flags. * \author Graue */ -static INT16 RandMap(INT16 tolflags, INT16 pprevmap) +INT16 RandMap(INT16 tolflags, INT16 pprevmap) { INT16 *okmaps = Z_Malloc(NUMMAPS * sizeof(INT16), PU_STATIC, NULL); INT32 numokmaps = 0; @@ -3184,7 +3193,7 @@ static void G_DoCompleted(void) P_AllocMapHeader(nextmap); if (skipstats && !modeattacking) // Don't skip stats if we're in record attack - G_AfterIntermission(); + G_AfterIntermission(false); else { G_SetGamestate(GS_INTERMISSION); @@ -3192,15 +3201,21 @@ static void G_DoCompleted(void) } } -void G_AfterIntermission(void) +void G_AfterIntermission(boolean vote) { HU_ClearCEcho(); + G_NextLevel(); if (mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking) // Start a custom cutscene. F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false); else { - if (nextmap < 1100-1) + if (cv_advancemap.value == 3 && !vote) + { + G_SetGamestate(GS_VOTING); + Y_StartVote(); + } + else if (nextmap < 1100-1) G_NextLevel(); else Y_EndGame(); @@ -5810,6 +5825,8 @@ void G_StopDemo(void) if (gamestate == GS_INTERMISSION) Y_EndIntermission(); // cleanup + if (gamestate == GS_VOTING) + Y_EndVote(); G_SetGamestate(GS_NULL); wipegamestate = GS_NULL; diff --git a/src/g_game.h b/src/g_game.h index dfc7b0df..4e4365be 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -173,7 +173,7 @@ void G_ExitLevel(void); void G_NextLevel(void); void G_Continue(void); void G_UseContinue(void); -void G_AfterIntermission(void); +void G_AfterIntermission(boolean vote); void G_Ticker(boolean run); boolean G_Responder(event_t *ev); @@ -218,5 +218,6 @@ FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics); // Don't split up TOL handling INT16 G_TOLFlag(INT32 pgametype); +INT16 RandMap(INT16 tolflags, INT16 pprevmap); #endif diff --git a/src/g_state.h b/src/g_state.h index 81548b7c..75ce2c30 100644 --- a/src/g_state.h +++ b/src/g_state.h @@ -23,6 +23,7 @@ typedef enum // Fadable gamestates GS_LEVEL, // Playing, in a level. GS_INTERMISSION, // Gazing at the intermission screen. + GS_VOTING, // SRB2Kart: MP voting screen GS_CONTINUING, // continue screen GS_TITLESCREEN, // title screen diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 24e4da10..f66eb27c 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1145,7 +1145,8 @@ void HU_Drawer(void) if (!Playing() || gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE || gamestate == GS_CREDITS || gamestate == GS_EVALUATION - || gamestate == GS_GAMEEND) + || gamestate == GS_GAMEEND + || gamestate == GS_VOTING) // SRB2kart return; // draw multiplayer rankings diff --git a/src/p_saveg.c b/src/p_saveg.c index 53ab044d..1a10ce36 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3364,6 +3364,8 @@ boolean P_LoadGame(INT16 mapoverride) { if (gamestate == GS_INTERMISSION) Y_EndIntermission(); + if (gamestate == GS_VOTING) + Y_EndVote(); G_SetGamestate(GS_NULL); // should be changed in P_UnArchiveMisc P_UnArchiveSPGame(mapoverride); diff --git a/src/y_inter.c b/src/y_inter.c index 5bfed538..4d520a2c 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -36,6 +36,8 @@ #include "m_cond.h" // condition sets +#include "m_random.h" // M_RandomKey + #ifdef HWRENDER #include "hardware/hw_main.h" #endif @@ -164,6 +166,47 @@ static void Y_CalculateMatchWinners(void); static void Y_FollowIntermission(void); static void Y_UnloadData(void); +// SRB2Kart: voting stuff + +typedef struct +{ + char str[40]; + patch_t *pic; + UINT16 num; +} y_votelvlinfo_t; + +typedef struct +{ + UINT8 *color; + INT32 *character; + UINT8 delay; + INT8 selection; + boolean voted; +} y_voteplayers_t; + +typedef struct +{ + UINT8 level; // 0 to 3; 3 is random + UINT8 playernum; +} y_vote_t; + +typedef struct +{ + y_votelvlinfo_t levels[4]; + y_voteplayers_t playerinfo[MAXPLAYERS]; + y_vote_t votes[MAXPLAYERS]; + UINT8 numvotes; + INT32 timeleft; +} y_votedata; + +static y_votedata votedata; +static INT32 votetic; +static INT32 voteendtic = -1; +static patch_t *cursor = NULL; + +static void Y_UnloadVoteData(void); +static void Y_FollowVote(void); + // Stuff copy+pasted from st_stuff.c static INT32 SCX(INT32 x) { @@ -2008,7 +2051,7 @@ static void Y_FollowIntermission(void) if (nextmap < 1100-1) { // normal level - G_AfterIntermission(); + G_AfterIntermission(false); return; } @@ -2076,3 +2119,332 @@ static void Y_UnloadData(void) break; } } + +// SRB2Kart: Voting! + +// +// Y_StartVote +// +// MK online style voting screen, appears after intermission +// +void Y_StartVote(void) +{ + INT32 i = 0; + + votetic = -1; + +#ifdef PARANOIA + if (voteendtic != -1) + I_Error("voteendtic is dirty"); +#endif + + bgpatch = W_CachePatchName("INTERSCR", PU_STATIC); + widebgpatch = W_CachePatchName("INTERSCW", PU_STATIC); + cursor = W_CachePatchName("M_CURSOR", PU_STATIC); + + //votedata.timeleft = 30*TICRATE; + votedata.numvotes = 0; + + for (i = 0; i < MAXPLAYERS; i++) + { + votedata.playerinfo[i].color = &players[i].skincolor; + votedata.playerinfo[i].character = &players[i].skin; + votedata.playerinfo[i].delay = 0; + votedata.playerinfo[i].selection = 0; + votedata.playerinfo[i].voted = false; + + votedata.votes[i].level = 0; + votedata.votes[i].playernum = 0; + } + + for (i = 0; i < 4; i++) + { + INT32 j; + lumpnum_t lumpnum; + + votedata.levels[i].num = RandMap(G_TOLFlag(gametype), prevmap); + + for (j = 0; j < 4; j++) + { + INT32 loopcount = 0; + if (i == j) + continue; + while (votedata.levels[i].num == votedata.levels[j].num && loopcount < 5) + { + votedata.levels[i].num = RandMap(G_TOLFlag(gametype), prevmap); + loopcount++; + } + } + + if (!mapheaderinfo[votedata.levels[i].num]) + P_AllocMapHeader(votedata.levels[i].num); + + if (i == 3) // Random is actually pre-calculated for ease of coding, shhhhh :V + { + //snprintf(votedata.levels[i].str, sizeof votedata.levels[i].str, "%.32s", "RANDOM"); + //votedata.levels[i].str[sizeof votedata.levels[i].str - 1] = '\0'; + votedata.levels[i].pic = W_CachePatchName("RANDOMLV", PU_STATIC); + } + else + { + // set up the str + /*if (mapheaderinfo[votedata.levels[i].num]->zonttl) + { + if (mapheaderinfo[votedata.levels[i].num]->actnum) + snprintf(votedata.levels[i].str, + sizeof votedata.levels[i].str, + "%.32s %.32s %d", + mapheaderinfo[votedata.levels[i].num]->lvlttl, mapheaderinfo[votedata.levels[i].num-1]->zonttl, mapheaderinfo[votedata.levels[i].num-1]->actnum); + else + snprintf(votedata.levels[i].str, + sizeof votedata.levels[i].str, + "%.32s %.32s", + mapheaderinfo[votedata.levels[i].num]->lvlttl, mapheaderinfo[votedata.levels[i].num-1]->zonttl); + } + else + { + if (mapheaderinfo[votedata.levels[i].num]->actnum) + snprintf(votedata.levels[i].str, + sizeof votedata.levels[i].str, + "%.32s %d", + mapheaderinfo[votedata.levels[i].num]->lvlttl, mapheaderinfo[votedata.levels[i].num-1]->actnum); + else + snprintf(votedata.levels[i].str, + sizeof votedata.levels[i].str, + "%.32s", + mapheaderinfo[votedata.levels[i].num]->lvlttl); + } + + votedata.levels[i].str[sizeof votedata.levels[i].str - 1] = '\0';*/ + + // A 160x100 image of the level as entry MAPxxP + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(votedata.levels[i].num))); + + if (lumpnum != LUMPERROR) + votedata.levels[i].pic = W_CachePatchName(va("%sP", G_BuildMapName(votedata.levels[i].num+1)), PU_STATIC); + else + votedata.levels[i].pic = W_CachePatchName("BLANKLVL", PU_STATIC); + } + } +} + +// +// Y_VoteTicker +// +// Vote screen thinking :eggthinking: +// +void Y_VoteTicker(void) +{ + UINT8 numplayers; + INT32 i; + + numplayers = 0; + + if (paused || P_AutoPause()) + return; + + votetic++; + + if (votetic >= voteendtic) + { + Y_EndVote(); + Y_FollowVote(); + return; + } + + if (votetic < TICRATE) + return; + + /*if (votedata.timeleft > 0) + votedata.timeleft--;*/ + + for (i = 0; i < MAXPLAYERS; i++) + { + boolean pressed = false; + + if (!playeringame[i] || players[i].spectator) + continue; + + numplayers++; + + if (votedata.playerinfo[i].voted) + continue; + + if (votedata.playerinfo[i].delay > 0) + { + votedata.playerinfo[i].delay--; + continue; + } + + if (players[i].cmd.buttons & BT_FORWARD && !pressed) + { + votedata.playerinfo[i].selection--; + pressed = true; + } + + if (players[i].cmd.buttons & BT_BACKWARD && !pressed) + { + votedata.playerinfo[i].selection++; + pressed = true; + } + + if (votedata.playerinfo[i].selection < 0) + votedata.playerinfo[i].selection = 3; + if (votedata.playerinfo[i].selection > 3) + votedata.playerinfo[i].selection = 0; + + if (players[i].cmd.buttons & BT_ACCELERATE && !pressed) + { + votedata.votes[votedata.numvotes].level = votedata.playerinfo[i].selection; + votedata.votes[votedata.numvotes].playernum = i; + votedata.playerinfo[i].voted = true; + pressed = true; + votedata.numvotes++; + } + + if (pressed) + { + if (i == consoleplayer) + S_StartSound(NULL, sfx_menu1); + votedata.playerinfo[i].delay = NEWTICRATE/7; + } + + /*if (votedata.timeleft <= 0 && !votedata.playerinfo[i].voted) + { + votedata.votes[votedata.numvotes].level = 3; // too slow? you pick random + votedata.votes[votedata.numvotes].playernum = i; + votedata.playerinfo[i].voted = true; + votedata.numvotes++; + }*/ + } + + /*if (votedata.numvotes >= numplayers) + votedata.timeleft = 0; + + if (votedata.timeleft == 0 && voteendtic == -1) + { + nextmap = (votedata.votes[P_RandomKey(votedata.numvotes)].level); + voteendtic = votetic+(10*TICRATE); + }*/ + + if (!votetic) + S_ChangeMusicInternal("racent", true); +} + +// +// Y_VoteDrawer +// +// Draws the voting screen! +// +void Y_VoteDrawer(void) +{ + INT32 i, x, y = 0; + + if (rendermode == render_none) + return; + + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + + if (widebgpatch && rendermode == render_soft && vid.width / vid.dupx == 400) + V_DrawScaledPatch(0, 0, V_SNAPTOLEFT, widebgpatch); + else + V_DrawScaledPatch(0, 0, 0, bgpatch); + + for (i = 0; i < 4; i++) + { + if (i == votedata.playerinfo[consoleplayer].selection) + { + y += 50; + V_DrawScaledPatch(BASEVIDWIDTH-142, y+21, 0, cursor); + //V_DrawFill(BASEVIDWIDTH-102, y-2, 84, 54, 103); + V_DrawSmallScaledPatch(BASEVIDWIDTH-100, y, 0, votedata.levels[i].pic); + //V_DrawRightAlignedThinString(BASEVIDWIDTH-20, 42+y, V_YELLOWMAP, votedata.levels[i].str); + } + else + { + V_DrawTinyScaledPatch(BASEVIDWIDTH-80, y, 0, votedata.levels[i].pic); + y += 62; + } + } + + x = 20; + y = 0; + + for (i = 0; i < votedata.numvotes; i++) + { + V_DrawTinyScaledPatch(x, y, 0, votedata.levels[votedata.votes[i].level].pic); + + if (votedata.playerinfo[votedata.votes[i].playernum].color == 0) + V_DrawSmallScaledPatch(x+48, y+18, 0, faceprefix[*votedata.playerinfo[votedata.votes[i].playernum].character]); + else + { + UINT8 *colormap = R_GetTranslationColormap(*votedata.playerinfo[votedata.votes[i].playernum].character, *votedata.playerinfo[votedata.votes[i].playernum].color, GTC_CACHE); + V_DrawSmallMappedPatch(x+48, y+18, 0, faceprefix[*votedata.playerinfo[votedata.votes[i].playernum].character], colormap); + } + + y += 25; + + if (y > BASEVIDHEIGHT-25) + { + x += 20; + y = 0; + } + } + + /*if (votedata.timeleft) + V_DrawCenteredString(BASEVIDWIDTH/2, 188, V_YELLOWMAP, + va("Vote ends in %d seconds", votedata.timeleft/TICRATE));*/ +} + +// +// Y_EndVote +// +void Y_EndVote(void) +{ + Y_UnloadVoteData(); + voteendtic = -1; +} + +// +// Y_UnloadVoteData +// +static void Y_UnloadVoteData(void) +{ + if (rendermode != render_soft) + return; + + UNLOAD(bgpatch); + UNLOAD(widebgpatch); + UNLOAD(cursor); + + UNLOAD(votedata.levels[3].pic); + UNLOAD(votedata.levels[2].pic); + UNLOAD(votedata.levels[1].pic); + UNLOAD(votedata.levels[0].pic); +} + +// +// Y_FollowVote +// +static void Y_FollowVote(void) +{ + if (modeattacking) + { + M_EndModeAttackRun(); + return; + } + + if (nextmap < 1100-1) + { + G_AfterIntermission(true); + return; + } + + if (mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking) + { + F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false); + return; + } + + Y_EndGame(); +} \ No newline at end of file diff --git a/src/y_inter.h b/src/y_inter.h index 358debf7..3f63b3ee 100644 --- a/src/y_inter.h +++ b/src/y_inter.h @@ -17,6 +17,11 @@ void Y_StartIntermission(void); void Y_EndIntermission(void); void Y_EndGame(void); +void Y_StartVote(void); +void Y_VoteTicker(void); +void Y_VoteDrawer(void); +void Y_EndVote(void); + typedef enum { int_none,