diff --git a/src/k_vote.c b/src/k_vote.c index 8213ca081..9993e6dd2 100644 --- a/src/k_vote.c +++ b/src/k_vote.c @@ -76,6 +76,8 @@ #define ARM_FRAMES (4) #define BULB_FRAMES (4) +#define SELECTOR_FRAMES (2) + #define CATCHER_SPEED (8*FRACUNIT) #define CATCHER_Y_OFFSET (48*FRACUNIT) #define CATCHER_OFFSCREEN (-CATCHER_Y_OFFSET * 2) @@ -91,6 +93,10 @@ #define SELECTION_SPACING_H (SELECTION_HEIGHT + SELECTION_SPACE) #define SELECTION_HOP (10*FRACUNIT) +#define SELECTOR_SPACE (8*FRACUNIT) +#define SELECTOR_Y ((SELECTION_HEIGHT / 2) + SELECTOR_SPACE) +#define SELECTOR_HEIGHT ((30*FRACUNIT) + SELECTOR_SPACE) + #define PILE_WIDTH (46*FRACUNIT) #define PILE_HEIGHT ((PILE_WIDTH * BASEVIDHEIGHT) / BASEVIDWIDTH) #define PILE_SPACE (4*FRACUNIT) @@ -146,6 +152,7 @@ typedef struct SINT8 selection; UINT8 delay; boolean sentTimeOutVote; + fixed_t x, destX; } y_vote_player; // Vote "pile" data. Objects for each vote scattered about. @@ -188,6 +195,13 @@ typedef struct fixed_t hop; } y_vote_draw_level; +// Voting selector drawing +typedef struct +{ + fixed_t x; + fixed_t destX; +} y_vote_draw_selector; + // General vote drawing typedef struct { @@ -206,6 +220,10 @@ typedef struct fixed_t selectTransition; y_vote_draw_level levels[VOTE_NUM_LEVELS]; + + patch_t *selector_arrow; + patch_t *selector_letter[MAXSPLITSCREENPLAYERS][2]; + y_vote_draw_selector selectors[MAXSPLITSCREENPLAYERS]; } y_vote_draw; static y_vote_data vote = {0}; @@ -241,6 +259,29 @@ boolean Y_PlayerIDCanVote(const UINT8 playerId) return true; } +static boolean Y_PlayerCanSelect(const UINT8 localId) +{ + const UINT8 p = g_localplayers[localId]; + + if (g_pickedVote != VOTE_NOT_PICKED) + { + return false; + } + + if (g_votes[p] != VOTE_NOT_PICKED) + { + return false; + } + + if (vote.players[localId].catcher.action != CATCHER_NA + || vote.players[localId].catcher.delay > 0) + { + return false; + } + + return Y_PlayerIDCanVote(p); +} + static void Y_SortPile(void) { UINT8 numVotes = 0; @@ -697,10 +738,61 @@ static void Y_DrawVoteBackground(void) bgTimer += renderdeltatics; } +static void Y_DrawVoteSelector(const fixed_t y, const fixed_t time, const UINT8 localPlayer) +{ + const fixed_t destX = SELECTION_X + (vote.players[localPlayer].selection * SELECTION_SPACING_W); + + vote_draw.selectors[localPlayer].x += FixedMul( + (destX - vote_draw.selectors[localPlayer].x) * 3 / 4, + renderdeltatics + ); + + if (Y_PlayerCanSelect(localPlayer) == false) + { + return; + } + + static const UINT8 freq = 7; + UINT8 *colormap = NULL; + + if (splitscreen > 0) + { + const UINT8 blink = ((time / freq / FRACUNIT) & 1); + + colormap = R_GetTranslationColormap(TC_RAINBOW, players[ g_localplayers[localPlayer] ].skincolor, GTC_CACHE); + + V_DrawFixedPatch( + vote_draw.selectors[localPlayer].x, y - SELECTOR_Y - (9*FRACUNIT), + FRACUNIT, 0, + vote_draw.selector_letter[localPlayer][blink], + colormap + ); + } + + fixed_t bob = FixedMul((time / freq * 2) + (FRACUNIT / 2), ANGLE_90); + if (localPlayer & 1) + { + bob = FCOS(bob); + } + else + { + bob = FSIN(bob); + } + + V_DrawFixedPatch( + vote_draw.selectors[localPlayer].x, y - SELECTOR_Y + bob, + FRACUNIT, 0, + vote_draw.selector_arrow, + colormap + ); +} + static void Y_DrawVoteSelection(fixed_t offset) { + static fixed_t selectorTimer = 0; + fixed_t x = SELECTION_X; - fixed_t y = SELECTION_Y + FixedMul(offset, SELECTION_HEIGHT * 2); + fixed_t y = SELECTION_Y + FixedMul(offset, (SELECTION_HEIGHT + SELECTOR_HEIGHT) * 2); INT32 i; // @@ -709,7 +801,6 @@ static void Y_DrawVoteSelection(fixed_t offset) for (i = 0; i < VOTE_NUM_LEVELS; i++) { boolean selected = false; - INT32 flags = 0; fixed_t destHop = 0; INT32 j; @@ -743,7 +834,7 @@ static void Y_DrawVoteSelection(fixed_t offset) Y_DrawVoteThumbnail( x, y - vote_draw.levels[i].hop, - SELECTION_WIDTH, flags, + SELECTION_WIDTH, 0, i, (selected == false), -1 ); @@ -758,6 +849,31 @@ static void Y_DrawVoteSelection(fixed_t offset) { Y_DrawCatcher(&vote.players[i].catcher); } + + if (offset != FRACUNIT) + { + // + // Draw splitscreen selectors + // + selectorTimer += renderdeltatics; + + //if (splitscreen > 0) + { + const UINT8 priority = vote.tic % (splitscreen + 1); + + for (i = 0; i <= splitscreen; i++) + { + if (i == priority) + { + continue; + } + + Y_DrawVoteSelector(y, selectorTimer, i); + } + + Y_DrawVoteSelector(y, selectorTimer, priority); + } + } } static void Y_DrawVotePile(void) @@ -1013,6 +1129,7 @@ static void Y_TickPlayerCatcher(const UINT8 localPlayer) { D_ModifyClientVote(g_localplayers[localPlayer], vote.players[localPlayer].selection); catcher->action = CATCHER_NA; + catcher->delay = 5; S_StopSoundByNum(sfx_kc37); } break; @@ -1191,28 +1308,6 @@ static void Y_TickVoteRoulette(void) } } -static boolean Y_PlayerCanSelect(const UINT8 localId) -{ - const UINT8 p = g_localplayers[localId]; - - if (g_pickedVote != VOTE_NOT_PICKED) - { - return false; - } - - if (g_votes[p] != VOTE_NOT_PICKED) - { - return false; - } - - if (vote.players[localId].catcher.action != CATCHER_NA) - { - return false; - } - - return Y_PlayerIDCanVote(p); -} - static void Y_TryMapAngerVote(void) { SINT8 angryMaps[VOTE_NUM_LEVELS] = { -1 }; @@ -1491,7 +1586,7 @@ void Y_VoteTicker(void) // static void Y_InitVoteDrawing(void) { - INT32 i = 0; + INT32 i = 0, j = 0; vote_draw.ruby_icon = W_CachePatchName("RUBYICON", PU_STATIC); @@ -1555,6 +1650,20 @@ static void Y_InitVoteDrawing(void) vote_draw.levels[i].str[sizeof vote_draw.levels[i].str - 1] = '\0'; } + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + y_vote_player *const player = &vote.players[i]; + + vote_draw.selectors[i].x = vote_draw.selectors[i].destX = SELECTION_X + (player->selection * SELECTION_SPACING_W); + + for (j = 0; j < SELECTOR_FRAMES; j++) + { + vote_draw.selector_letter[i][j] = W_CachePatchName(va("VSSPTR%c%d", 'A' + i, j + 1), PU_STATIC); + } + } + + vote_draw.selector_arrow = W_CachePatchName("VSSPTR1", PU_STATIC); + vote_draw.selectTransition = FRACUNIT; } @@ -1581,6 +1690,8 @@ void Y_StartVote(void) y_vote_player *const player = &vote.players[i]; y_vote_catcher *const catcher = &player->catcher; + player->selection = (i % VOTE_NUM_LEVELS); + catcher->action = CATCHER_NA; catcher->small = false; catcher->player = -1; @@ -1641,6 +1752,16 @@ static void Y_UnloadVoteData(void) UNLOAD(vote_draw.catcher_bulb[j][i]); } } + + for (j = 0; j < MAXSPLITSCREENPLAYERS; j++) + { + for (i = 0; i < SELECTOR_FRAMES; i++) + { + UNLOAD(vote_draw.selector_letter[j][i]); + } + } + + UNLOAD(vote_draw.selector_arrow); } //