mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Implement "CALL VOTE" for victimless commands on the pause menu
Currently just plays the squishy "nope" sound for "KICK PLAYER?", all others are functional Shows whether vote is active or the cooldown is too recent (via numerical timer) as reasons for why you can't select it
This commit is contained in:
parent
721d5d9da9
commit
d8ea8c0fe1
5 changed files with 281 additions and 28 deletions
|
|
@ -126,6 +126,9 @@ void M_PrevMenuGametype(UINT32 forbidden);
|
|||
void M_HandleHostMenuGametype(INT32 choice);
|
||||
void M_HandlePauseMenuGametype(INT32 choice);
|
||||
|
||||
extern UINT32 menucallvote; // not midVoteType_e to prevent #include k_zvote
|
||||
void M_HandlePauseMenuCallVote(INT32 choice);
|
||||
|
||||
//
|
||||
// MENU TYPEDEFS
|
||||
//
|
||||
|
|
@ -447,6 +450,7 @@ typedef enum
|
|||
#ifdef HAVE_DISCORDRPC
|
||||
mpause_discordrequests,
|
||||
#endif
|
||||
mpause_callvote,
|
||||
|
||||
mpause_continue,
|
||||
mpause_spectate,
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@
|
|||
#include "doomstat.h" // MAXSPLITSCREENPLAYERS
|
||||
#include "k_grandprix.h" // K_CanChangeRules
|
||||
#include "k_rank.h" // K_GetGradeColor
|
||||
#include "k_zvote.h" // K_GetMidVoteLabel
|
||||
|
||||
#include "y_inter.h" // Y_RoundQueueDrawer
|
||||
|
||||
|
|
@ -4360,26 +4361,61 @@ void M_DrawPause(void)
|
|||
|
||||
// Draw the string!
|
||||
|
||||
const char *maintext = NULL;
|
||||
const char *selectabletext = NULL;
|
||||
INT32 mainflags = V_YELLOWMAP, selectableflags = 0;
|
||||
|
||||
if (itemOn == mpause_changegametype)
|
||||
{
|
||||
selectabletext = gametypes[menugametype]->name;
|
||||
}
|
||||
else if (itemOn == mpause_callvote)
|
||||
{
|
||||
selectabletext = K_GetMidVoteLabel(menucallvote);
|
||||
|
||||
if (K_MinimalCheckNewMidVote(menucallvote) == false)
|
||||
{
|
||||
if (g_midVote.active == true)
|
||||
{
|
||||
maintext = "ACTIVE...";
|
||||
}
|
||||
else if (g_midVote.delay > 0)
|
||||
{
|
||||
if (g_midVote.delay != 1)
|
||||
maintext = va("%u", ((g_midVote.delay - 1) / TICRATE) + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
maintext = "INVALID!?";
|
||||
}
|
||||
|
||||
if (maintext != NULL)
|
||||
selectableflags |= V_MODULATE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
maintext = currentMenu->menuitems[itemOn].text;
|
||||
mainflags = 0;
|
||||
}
|
||||
|
||||
if (selectabletext != NULL)
|
||||
{
|
||||
// We have a selection. Let's show the full menu text on top, and the choice below.
|
||||
|
||||
INT32 w = V_LSTitleLowStringWidth(selectabletext, 0)/2;
|
||||
|
||||
if (currentMenu->menuitems[itemOn].text)
|
||||
V_DrawCenteredLSTitleHighString(220 + offset*2, 75, 0, currentMenu->menuitems[itemOn].text);
|
||||
V_DrawCenteredLSTitleHighString(220 + offset*2, 75, selectableflags, currentMenu->menuitems[itemOn].text);
|
||||
|
||||
V_DrawLSTitleLowString(220-w + offset*2, 103, V_YELLOWMAP, selectabletext);
|
||||
V_DrawCharacter(220-w + offset*2 - 8 - (skullAnimCounter/5), 103+6, '\x1C' | V_YELLOWMAP, false); // left arrow
|
||||
V_DrawCharacter(220+w + offset*2 + 4 + (skullAnimCounter/5), 103+6, '\x1D' | V_YELLOWMAP, false); // right arrow
|
||||
selectableflags |= V_YELLOWMAP;
|
||||
|
||||
INT32 w = V_LSTitleLowStringWidth(selectabletext, selectableflags)/2;
|
||||
V_DrawLSTitleLowString(220-w + offset*2, 103, selectableflags, selectabletext);
|
||||
|
||||
V_DrawCharacter(220-w + offset*2 - 8 - (skullAnimCounter/5), 103+6, '\x1C' | selectableflags, false); // left arrow
|
||||
V_DrawCharacter(220+w + offset*2 + (skullAnimCounter/5), 103+6, '\x1D' | selectableflags, false); // right arrow
|
||||
}
|
||||
else
|
||||
|
||||
if (maintext != NULL)
|
||||
{
|
||||
// This is a regular menu option. Try to break it onto two lines.
|
||||
|
||||
|
|
@ -4389,11 +4425,9 @@ void M_DrawPause(void)
|
|||
INT16 word2len = 0;
|
||||
boolean sok = false;
|
||||
|
||||
while (currentMenu->menuitems[itemOn].text[j] && j < MAXSTRINGLENGTH)
|
||||
while (maintext[j] && j < MAXSTRINGLENGTH)
|
||||
{
|
||||
const char c = currentMenu->menuitems[itemOn].text[j];
|
||||
|
||||
if (c == ' ' && !sok)
|
||||
if (maintext[j] == ' ' && !sok)
|
||||
{
|
||||
sok = true;
|
||||
j++;
|
||||
|
|
@ -4402,12 +4436,12 @@ void M_DrawPause(void)
|
|||
|
||||
if (sok)
|
||||
{
|
||||
word2[word2len] = c;
|
||||
word2[word2len] = maintext[j];
|
||||
word2len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
word1[word1len] = c;
|
||||
word1[word1len] = maintext[j];
|
||||
word1len++;
|
||||
}
|
||||
|
||||
|
|
@ -4419,10 +4453,10 @@ void M_DrawPause(void)
|
|||
|
||||
// If there's no 2nd word, take this opportunity to center this line of text.
|
||||
if (word1len)
|
||||
V_DrawCenteredLSTitleHighString(220 + offset*2, 75 + (!word2len ? 10 : 0), 0, word1);
|
||||
V_DrawCenteredLSTitleHighString(220 + offset*2, 75 + (!word2len ? 10 : 0), mainflags, word1);
|
||||
|
||||
if (word2len)
|
||||
V_DrawCenteredLSTitleLowString(220 + offset*2, 103, 0, word2);
|
||||
V_DrawCenteredLSTitleLowString(220 + offset*2, 103, mainflags, word2);
|
||||
}
|
||||
|
||||
if (gamestate != GS_INTERMISSION && roundqueue.size > 0)
|
||||
|
|
|
|||
118
src/k_zvote.c
118
src/k_zvote.c
|
|
@ -117,19 +117,11 @@ static midVoteTypeDef_t g_midVoteTypeDefs[MVT__MAX] =
|
|||
};
|
||||
|
||||
/*--------------------------------------------------
|
||||
static boolean K_MidVoteTypeUsesVictim(midVoteType_e voteType)
|
||||
boolean K_MidVoteTypeUsesVictim(midVoteType_e voteType)
|
||||
|
||||
Specifies whenever or not a vote type is intended
|
||||
to specify a "victim", or a player that would be
|
||||
negatively affected by the vote.
|
||||
|
||||
Input Arguments:-
|
||||
voteType - The vote type to check.
|
||||
|
||||
Return:-
|
||||
true if it uses a victim, otherwise false.
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
static boolean K_MidVoteTypeUsesVictim(midVoteType_e voteType)
|
||||
boolean K_MidVoteTypeUsesVictim(midVoteType_e voteType)
|
||||
{
|
||||
switch (voteType)
|
||||
{
|
||||
|
|
@ -380,6 +372,51 @@ boolean K_AnyMidVotesAllowed(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
midVoteType_e K_GetNextCallableMidVote(INT32 seed, boolean backwards)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
midVoteType_e K_GetNextAllowedMidVote(midVoteType_e seed, boolean backwards)
|
||||
{
|
||||
if (seed >= MVT__MAX)
|
||||
seed = 0;
|
||||
|
||||
midVoteType_e i = seed;
|
||||
|
||||
if (backwards)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (i <= 0)
|
||||
i = MVT__MAX;
|
||||
i--;
|
||||
|
||||
if (g_midVoteTypeDefs[i].cv_allowed.value != 0)
|
||||
return i;
|
||||
|
||||
}
|
||||
while (i != seed);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
i++;
|
||||
if (i >= MVT__MAX)
|
||||
i = 0;
|
||||
|
||||
if (g_midVoteTypeDefs[i].cv_allowed.value != 0)
|
||||
return i;
|
||||
|
||||
}
|
||||
while (i != seed);
|
||||
}
|
||||
|
||||
return MVT__MAX;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_PlayerIDAllowedInMidVote(const UINT8 id)
|
||||
|
||||
|
|
@ -507,6 +544,40 @@ UINT8 K_CountMidVotes(void)
|
|||
return voteCount;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_MinimalCheckNewMidVote(midVoteType_e type)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
boolean K_MinimalCheckNewMidVote(midVoteType_e type)
|
||||
{
|
||||
if (g_midVote.active == true)
|
||||
{
|
||||
// Don't allow another vote if one is already running.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_midVote.delay > 0)
|
||||
{
|
||||
// Don't allow another vote if one has recently just ran.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type < 0 || type >= MVT__MAX)
|
||||
{
|
||||
// Invalid range.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_midVoteTypeDefs[type].cv_allowed.value == 0)
|
||||
{
|
||||
// These types of votes aren't allowed on this server.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_AllowNewMidVote(player_t *caller, midVoteType_e type, INT32 variable, player_t *victim)
|
||||
|
||||
|
|
@ -866,6 +937,25 @@ void K_UpdateMidVotePatches(void)
|
|||
HU_UpdatePatch(&g_zBarEnds[1][1][1], "TLBXB0");
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
const char *K_GetMidVoteLabel(midVoteType_e i)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
const char *K_GetMidVoteLabel(midVoteType_e i)
|
||||
{
|
||||
if (
|
||||
i < 0
|
||||
|| i >= MVT__MAX
|
||||
|| g_midVoteTypeDefs[i].label == NULL)
|
||||
{
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
return g_midVoteTypeDefs[i].label;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_DrawMidVoteBar(fixed_t x, fixed_t y, INT32 flags, fixed_t fill, skincolornum_t color, boolean flipped)
|
||||
|
||||
|
|
@ -1049,11 +1139,13 @@ void K_DrawMidVote(void)
|
|||
(id & 1)
|
||||
);
|
||||
|
||||
const char *label = K_GetMidVoteLabel(g_midVote.type);
|
||||
|
||||
// Vote main label
|
||||
strWidth = V__OneScaleStringWidth(
|
||||
FRACUNIT,
|
||||
V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_SPLITSCREEN,
|
||||
KART_FONT, g_midVoteTypeDefs[g_midVote.type].label
|
||||
KART_FONT, label
|
||||
);
|
||||
|
||||
V__DrawOneScaleString(
|
||||
|
|
@ -1061,7 +1153,7 @@ void K_DrawMidVote(void)
|
|||
y - (18 * FRACUNIT),
|
||||
FRACUNIT,
|
||||
V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_SPLITSCREEN, NULL,
|
||||
KART_FONT, g_midVoteTypeDefs[g_midVote.type].label
|
||||
KART_FONT, label
|
||||
);
|
||||
|
||||
// Vote extra text
|
||||
|
|
|
|||
|
|
@ -64,6 +64,39 @@ struct midVote_t
|
|||
|
||||
extern midVote_t g_midVote;
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_MidVoteTypeUsesVictim(midVoteType_e voteType)
|
||||
|
||||
Specifies whenever or not a vote type is intended
|
||||
to specify a "victim", or a player that would be
|
||||
negatively affected by the vote.
|
||||
|
||||
Input Arguments:-
|
||||
voteType - The vote type to check.
|
||||
|
||||
Return:-
|
||||
true if it uses a victim, otherwise false.
|
||||
--------------------------------------------------*/
|
||||
|
||||
boolean K_MidVoteTypeUsesVictim(midVoteType_e voteType);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_SendCallMidVote(midVoteType_e voteType, INT32 voteVariable)
|
||||
|
||||
Prepares and sends net packet for calling a midvote.
|
||||
|
||||
Input Arguments:-
|
||||
voteType - The type of vote a local player is trying to call.
|
||||
variable - Extra arguments for the vote type.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_SendCallMidVote(midVoteType_e voteType, INT32 voteVariable);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_RegisterMidVoteCVars(void);
|
||||
|
||||
|
|
@ -100,6 +133,22 @@ void K_ResetMidVote(void);
|
|||
boolean K_AnyMidVotesAllowed(void);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
midVoteType_e K_GetNextCallableMidVote(midVoteType_e seed, boolean backwards)
|
||||
|
||||
Gets the next enabled Z-vote type in the list.
|
||||
|
||||
Input Arguments:-
|
||||
seed - position in the list to start with
|
||||
backwards - if true, traverses list in reverse order
|
||||
|
||||
Return:-
|
||||
next Z-vote id if any vote types are enabled, otherwise MVT__MAX.
|
||||
--------------------------------------------------*/
|
||||
|
||||
midVoteType_e K_GetNextAllowedMidVote(midVoteType_e seed, boolean backwards);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_PlayerIDAllowedInMidVote(const UINT8 id);
|
||||
|
||||
|
|
@ -171,6 +220,18 @@ boolean K_PlayerIDMidVoted(const UINT8 id);
|
|||
UINT8 K_CountMidVotes(void);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_MinimalCheckNewMidVote(midVoteType_e type)
|
||||
|
||||
Returns if the variables given are a valid state for
|
||||
pause menu Z-vote flow.
|
||||
|
||||
Input Arguments:-
|
||||
type - The type of vote they're trying to call.
|
||||
--------------------------------------------------*/
|
||||
|
||||
boolean K_MinimalCheckNewMidVote(midVoteType_e type);
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_AllowNewMidVote(player_t *caller, midVoteType_e type, INT32 variable, player_t *victim);
|
||||
|
||||
|
|
@ -264,6 +325,19 @@ void K_TickMidVote(void);
|
|||
void K_UpdateMidVotePatches(void);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
const char *K_GetMidVoteLabel(midVoteType_e i)
|
||||
|
||||
Input Arguments:-
|
||||
i - id in the list to retrieve label for
|
||||
|
||||
Return:-
|
||||
label associated with that id, or a sensible default (not NULL)
|
||||
--------------------------------------------------*/
|
||||
|
||||
const char *K_GetMidVoteLabel(midVoteType_e i);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_DrawMidVote(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "../../k_grandprix.h" // K_CanChangeRules
|
||||
#include "../../m_cond.h"
|
||||
#include "../../s_sound.h"
|
||||
#include "../../k_zvote.h"
|
||||
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
#include "../../discord.h"
|
||||
|
|
@ -39,6 +40,9 @@ menuitem_t PAUSE_Main[] =
|
|||
NULL, {.routine = M_DiscordRequests}, 0, 0},
|
||||
#endif
|
||||
|
||||
{IT_STRING | IT_ARROWS, "CALL VOTE", "M_ICOVOT",
|
||||
NULL, {.routine = M_HandlePauseMenuCallVote}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CALL, "RESUME GAME", "M_ICOUNP",
|
||||
NULL, {.routine = M_QuitPauseMenu}, 0, 0},
|
||||
|
||||
|
|
@ -123,6 +127,7 @@ void M_OpenPauseMenu(void)
|
|||
PAUSE_Main[mpause_switchmap].status = IT_DISABLED;
|
||||
PAUSE_Main[mpause_restartmap].status = IT_DISABLED;
|
||||
PAUSE_Main[mpause_tryagain].status = IT_DISABLED;
|
||||
PAUSE_Main[mpause_callvote].status = IT_DISABLED;
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
PAUSE_Main[mpause_discordrequests].status = IT_DISABLED;
|
||||
#endif
|
||||
|
|
@ -178,6 +183,18 @@ void M_OpenPauseMenu(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
menucallvote = K_GetNextAllowedMidVote(menucallvote, true);
|
||||
|
||||
if (menucallvote != MVT__MAX)
|
||||
{
|
||||
menucallvote = K_GetNextAllowedMidVote(menucallvote, false);
|
||||
|
||||
PAUSE_Main[mpause_callvote].status = IT_STRING | IT_ARROWS;
|
||||
}
|
||||
}
|
||||
|
||||
if (G_GametypeHasSpectators())
|
||||
{
|
||||
if (splitscreen)
|
||||
|
|
@ -302,6 +319,38 @@ void M_HandlePauseMenuGametype(INT32 choice)
|
|||
}
|
||||
}
|
||||
|
||||
// Call vote
|
||||
UINT32 menucallvote = MVT__MAX;
|
||||
|
||||
void M_HandlePauseMenuCallVote(INT32 choice)
|
||||
{
|
||||
if (choice == 2)
|
||||
{
|
||||
if (K_MinimalCheckNewMidVote(menucallvote) == false)
|
||||
{
|
||||
// Invalid.
|
||||
S_StartSound(NULL, sfx_s3k7b);
|
||||
}
|
||||
else if (K_MidVoteTypeUsesVictim(menucallvote) == true)
|
||||
{
|
||||
// Not yet implemented.
|
||||
S_StartSound(NULL, sfx_s3k7b);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bog standard and victimless, let's send it on its way!
|
||||
M_ClearMenus(true);
|
||||
K_SendCallMidVote(menucallvote, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
menucallvote = K_GetNextAllowedMidVote(menucallvote, (choice == 0));
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
}
|
||||
|
||||
// Restart map
|
||||
void M_RestartMap(INT32 choice)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue