mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-12-03 06:33:14 +00:00
Merge branch 'duel-vote' into duel
This commit is contained in:
commit
7b3e7cfdc7
9 changed files with 740 additions and 103 deletions
|
|
@ -2339,11 +2339,11 @@ void D_SetupVote(INT16 newgametype)
|
||||||
|
|
||||||
void D_ModifyClientVote(UINT8 player, SINT8 voted)
|
void D_ModifyClientVote(UINT8 player, SINT8 voted)
|
||||||
{
|
{
|
||||||
char buf[2];
|
char buf[3];
|
||||||
char *p = buf;
|
char *p = buf;
|
||||||
UINT8 sendPlayer = consoleplayer;
|
UINT8 sendPlayer = 0;
|
||||||
|
|
||||||
if (player == UINT8_MAX)
|
if (player >= MAXPLAYERS)
|
||||||
{
|
{
|
||||||
// Special game vote (map anger, duel)
|
// Special game vote (map anger, duel)
|
||||||
if (!server)
|
if (!server)
|
||||||
|
|
@ -2352,16 +2352,16 @@ void D_ModifyClientVote(UINT8 player, SINT8 voted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player == UINT8_MAX)
|
// Context value -- if context has changed, then discard vote update.
|
||||||
{
|
// This is to prevent votes being registered from different vote types.
|
||||||
// special vote
|
// Currently used for Duel vs Normal votes.
|
||||||
WRITEUINT8(p, UINT8_MAX);
|
WRITEUINT8(p, Y_VoteContext());
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
INT32 i = 0;
|
|
||||||
WRITEUINT8(p, player);
|
|
||||||
|
|
||||||
|
WRITEUINT8(p, player);
|
||||||
|
|
||||||
|
if (player <= MAXPLAYERS)
|
||||||
|
{
|
||||||
|
INT32 i;
|
||||||
for (i = 0; i <= splitscreen; i++)
|
for (i = 0; i <= splitscreen; i++)
|
||||||
{
|
{
|
||||||
if (g_localplayers[i] == player)
|
if (g_localplayers[i] == player)
|
||||||
|
|
@ -2376,13 +2376,12 @@ void D_ModifyClientVote(UINT8 player, SINT8 voted)
|
||||||
SendNetXCmdForPlayer(sendPlayer, XD_MODIFYVOTE, buf, p - buf);
|
SendNetXCmdForPlayer(sendPlayer, XD_MODIFYVOTE, buf, p - buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void D_PickVote(void)
|
void D_PickVote(SINT8 angry_map)
|
||||||
{
|
{
|
||||||
char buf[2];
|
char buf[3];
|
||||||
char* p = buf;
|
char* p = buf;
|
||||||
SINT8 temppicks[VOTE_TOTAL];
|
SINT8 temppicks[VOTE_TOTAL];
|
||||||
SINT8 templevels[VOTE_TOTAL];
|
SINT8 templevels[VOTE_TOTAL];
|
||||||
SINT8 votecompare = VOTE_NOT_PICKED;
|
|
||||||
UINT8 numvotes = 0, key = 0;
|
UINT8 numvotes = 0, key = 0;
|
||||||
INT32 i;
|
INT32 i;
|
||||||
|
|
||||||
|
|
@ -2393,16 +2392,23 @@ void D_PickVote(void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i == VOTE_SPECIAL && angry_map != VOTE_NOT_PICKED)
|
||||||
|
{
|
||||||
|
// Anger map is going to change because of
|
||||||
|
// the vote ending. We need to account for this
|
||||||
|
// here because a net command would not be ready
|
||||||
|
// in time for this code.
|
||||||
|
temppicks[numvotes] = i;
|
||||||
|
templevels[numvotes] = angry_map;
|
||||||
|
numvotes++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (g_votes[i] != VOTE_NOT_PICKED)
|
if (g_votes[i] != VOTE_NOT_PICKED)
|
||||||
{
|
{
|
||||||
temppicks[numvotes] = i;
|
temppicks[numvotes] = i;
|
||||||
templevels[numvotes] = g_votes[i];
|
templevels[numvotes] = g_votes[i];
|
||||||
numvotes++;
|
numvotes++;
|
||||||
|
|
||||||
if (votecompare == VOTE_NOT_PICKED)
|
|
||||||
{
|
|
||||||
votecompare = g_votes[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2411,14 +2417,16 @@ void D_PickVote(void)
|
||||||
key = M_RandomKey(numvotes);
|
key = M_RandomKey(numvotes);
|
||||||
WRITESINT8(p, temppicks[key]);
|
WRITESINT8(p, temppicks[key]);
|
||||||
WRITESINT8(p, templevels[key]);
|
WRITESINT8(p, templevels[key]);
|
||||||
|
WRITESINT8(p, angry_map);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WRITESINT8(p, VOTE_NOT_PICKED);
|
WRITESINT8(p, VOTE_NOT_PICKED);
|
||||||
WRITESINT8(p, 0);
|
WRITESINT8(p, 0);
|
||||||
|
WRITESINT8(p, VOTE_NOT_PICKED);
|
||||||
}
|
}
|
||||||
|
|
||||||
SendNetXCmd(XD_PICKVOTE, &buf, 2);
|
SendNetXCmd(XD_PICKVOTE, &buf, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
|
|
@ -5811,30 +5819,35 @@ static void Got_SetupVotecmd(const UINT8 **cp, INT32 playernum)
|
||||||
|
|
||||||
static void Got_ModifyVotecmd(const UINT8 **cp, INT32 playernum)
|
static void Got_ModifyVotecmd(const UINT8 **cp, INT32 playernum)
|
||||||
{
|
{
|
||||||
|
UINT8 context = READUINT8(*cp);
|
||||||
UINT8 targetID = READUINT8(*cp);
|
UINT8 targetID = READUINT8(*cp);
|
||||||
SINT8 vote = READSINT8(*cp);
|
SINT8 vote = READSINT8(*cp);
|
||||||
|
|
||||||
if (targetID == UINT8_MAX)
|
if (context != Y_VoteContext())
|
||||||
{
|
{
|
||||||
if (playernum != serverplayer) // server-only special vote
|
// Silently discard. Server changed the
|
||||||
|
// vote type as we were sending our vote.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetID >= MAXPLAYERS)
|
||||||
|
{
|
||||||
|
// only the server is allowed to send these
|
||||||
|
if (playernum != serverplayer)
|
||||||
{
|
{
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
targetID = VOTE_SPECIAL;
|
|
||||||
}
|
}
|
||||||
else if (playeringame[targetID] == true && players[targetID].bot == true)
|
else if (playeringame[targetID] == true && players[targetID].bot == true)
|
||||||
{
|
{
|
||||||
if (targetID >= MAXPLAYERS
|
if (playernum != serverplayer)
|
||||||
|| playernum != serverplayer)
|
|
||||||
{
|
{
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (targetID >= MAXPLAYERS
|
if (playernode[targetID] != playernode[playernum])
|
||||||
|| playernode[targetID] != playernode[playernum])
|
|
||||||
{
|
{
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
@ -5859,6 +5872,7 @@ static void Got_PickVotecmd(const UINT8 **cp, INT32 playernum)
|
||||||
{
|
{
|
||||||
SINT8 pick = READSINT8(*cp);
|
SINT8 pick = READSINT8(*cp);
|
||||||
SINT8 level = READSINT8(*cp);
|
SINT8 level = READSINT8(*cp);
|
||||||
|
SINT8 anger = READSINT8(*cp);
|
||||||
|
|
||||||
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
|
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
|
||||||
{
|
{
|
||||||
|
|
@ -5868,7 +5882,7 @@ static void Got_PickVotecmd(const UINT8 **cp, INT32 playernum)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Y_SetupVoteFinish(pick, level);
|
Y_SetupVoteFinish(pick, level, anger);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Got_ScheduleTaskcmd(const UINT8 **cp, INT32 playernum)
|
static void Got_ScheduleTaskcmd(const UINT8 **cp, INT32 playernum)
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,7 @@ void D_GameTypeChanged(INT32 lastgametype); // not a real _OnChange function any
|
||||||
void D_MapChange(UINT16 pmapnum, INT32 pgametype, boolean pencoremode, boolean presetplayers, INT32 pdelay, boolean pskipprecutscene, boolean pforcespecialstage);
|
void D_MapChange(UINT16 pmapnum, INT32 pgametype, boolean pencoremode, boolean presetplayers, INT32 pdelay, boolean pskipprecutscene, boolean pforcespecialstage);
|
||||||
void D_SetupVote(INT16 newgametype);
|
void D_SetupVote(INT16 newgametype);
|
||||||
void D_ModifyClientVote(UINT8 player, SINT8 voted);
|
void D_ModifyClientVote(UINT8 player, SINT8 voted);
|
||||||
void D_PickVote(void);
|
void D_PickVote(SINT8 angry_map);
|
||||||
void ObjectPlace_OnChange(void);
|
void ObjectPlace_OnChange(void);
|
||||||
void P_SetPlayerSpectator(INT32 playernum);
|
void P_SetPlayerSpectator(INT32 playernum);
|
||||||
boolean IsPlayerAdmin(INT32 playernum);
|
boolean IsPlayerAdmin(INT32 playernum);
|
||||||
|
|
|
||||||
|
|
@ -874,11 +874,18 @@ extern tic_t bombflashtimer; // Used to avoid causing seizures if multiple mines
|
||||||
extern boolean legitimateexit;
|
extern boolean legitimateexit;
|
||||||
extern boolean comebackshowninfo;
|
extern boolean comebackshowninfo;
|
||||||
|
|
||||||
|
#define VOTE_NUM_LEVELS (4)
|
||||||
|
#define VOTE_NOT_PICKED (-1)
|
||||||
#define VOTE_SPECIAL (MAXPLAYERS)
|
#define VOTE_SPECIAL (MAXPLAYERS)
|
||||||
#define VOTE_TOTAL (MAXPLAYERS+1)
|
#define VOTE_TOTAL (MAXPLAYERS+1)
|
||||||
extern UINT16 g_voteLevels[4][2];
|
|
||||||
|
#define VOTE_TIMEOUT_LOSER (MAXPLAYERS+1) // not a real vote ID
|
||||||
|
#define VOTE_TIMEOUT_WINNER (MAXPLAYERS+2) // ditto
|
||||||
|
|
||||||
|
extern UINT16 g_voteLevels[VOTE_NUM_LEVELS][2];
|
||||||
extern SINT8 g_votes[VOTE_TOTAL];
|
extern SINT8 g_votes[VOTE_TOTAL];
|
||||||
extern SINT8 g_pickedVote;
|
extern SINT8 g_pickedVote;
|
||||||
|
extern boolean g_votes_striked[VOTE_NUM_LEVELS];
|
||||||
|
|
||||||
// ===========================
|
// ===========================
|
||||||
// Internal parameters, fixed.
|
// Internal parameters, fixed.
|
||||||
|
|
|
||||||
|
|
@ -305,9 +305,10 @@ boolean prevencoremode;
|
||||||
boolean franticitems; // Frantic items currently enabled?
|
boolean franticitems; // Frantic items currently enabled?
|
||||||
|
|
||||||
// Voting system
|
// Voting system
|
||||||
UINT16 g_voteLevels[4][2]; // Levels that were rolled by the host
|
UINT16 g_voteLevels[VOTE_NUM_LEVELS][2]; // Levels that were rolled by the host
|
||||||
SINT8 g_votes[VOTE_TOTAL]; // Each player's vote
|
SINT8 g_votes[VOTE_TOTAL]; // Each player's vote
|
||||||
SINT8 g_pickedVote; // What vote the host rolls
|
SINT8 g_pickedVote; // What vote the host rolls
|
||||||
|
boolean g_votes_striked[VOTE_NUM_LEVELS]; // Which levels were striked from votes?
|
||||||
|
|
||||||
// Server-sided, synched variables
|
// Server-sided, synched variables
|
||||||
tic_t wantedcalcdelay; // Time before it recalculates WANTED
|
tic_t wantedcalcdelay; // Time before it recalculates WANTED
|
||||||
|
|
|
||||||
695
src/k_vote.c
695
src/k_vote.c
|
|
@ -109,6 +109,7 @@
|
||||||
// Give time for the animations to finish before finalizing the vote stages.
|
// Give time for the animations to finish before finalizing the vote stages.
|
||||||
#define SELECT_DELAY_TIME (TICRATE*4)
|
#define SELECT_DELAY_TIME (TICRATE*4)
|
||||||
#define PICK_DELAY_TIME (TICRATE/2)
|
#define PICK_DELAY_TIME (TICRATE/2)
|
||||||
|
#define STRIKE_DELAY_TIME (TICRATE/3)
|
||||||
|
|
||||||
#define MAP_ANGER_MAX (2)
|
#define MAP_ANGER_MAX (2)
|
||||||
|
|
||||||
|
|
@ -179,12 +180,21 @@ typedef struct
|
||||||
{
|
{
|
||||||
INT32 timer;
|
INT32 timer;
|
||||||
INT32 tic, endtic;
|
INT32 tic, endtic;
|
||||||
INT32 selectFinalize, pickFinalize;
|
INT32 selectFinalize, pickFinalize, strikeFinalize;
|
||||||
boolean notYetPicked;
|
boolean notYetPicked;
|
||||||
boolean loaded;
|
boolean loaded;
|
||||||
SINT8 deferredLevel;
|
SINT8 deferredLevel;
|
||||||
y_vote_player players[MAXSPLITSCREENPLAYERS];
|
y_vote_player players[MAXSPLITSCREENPLAYERS];
|
||||||
y_vote_roulette roulette;
|
y_vote_roulette roulette;
|
||||||
|
|
||||||
|
// If both of these players are valid,
|
||||||
|
// and they're the only players in the server,
|
||||||
|
// then we want stage striking!
|
||||||
|
player_t *strike_loser;
|
||||||
|
player_t *strike_winner;
|
||||||
|
boolean strike_turn;
|
||||||
|
boolean strike_time_out;
|
||||||
|
boolean stage_striking;
|
||||||
} y_vote_data;
|
} y_vote_data;
|
||||||
|
|
||||||
// Voting level drawing
|
// Voting level drawing
|
||||||
|
|
@ -209,6 +219,8 @@ typedef struct
|
||||||
patch_t *ruby_icon;
|
patch_t *ruby_icon;
|
||||||
fixed_t ruby_height;
|
fixed_t ruby_height;
|
||||||
|
|
||||||
|
patch_t *strike_icon;
|
||||||
|
|
||||||
patch_t *bg_planet[PLANET_FRAMES];
|
patch_t *bg_planet[PLANET_FRAMES];
|
||||||
patch_t *bg_checker;
|
patch_t *bg_checker;
|
||||||
patch_t *bg_levelText;
|
patch_t *bg_levelText;
|
||||||
|
|
@ -230,13 +242,54 @@ typedef struct
|
||||||
static y_vote_data vote = {0};
|
static y_vote_data vote = {0};
|
||||||
static y_vote_draw vote_draw = {0};
|
static y_vote_draw vote_draw = {0};
|
||||||
|
|
||||||
|
static void Y_SetVoteTimer(void)
|
||||||
|
{
|
||||||
|
vote.timer = cv_votetime.value * TICRATE;
|
||||||
|
|
||||||
|
if (vote.stage_striking == true)
|
||||||
|
{
|
||||||
|
vote.timer /= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT8 Y_CountStriked(void)
|
||||||
|
{
|
||||||
|
INT32 i;
|
||||||
|
|
||||||
|
UINT8 num_striked = 0;
|
||||||
|
for (i = 0; i < VOTE_NUM_LEVELS; i++)
|
||||||
|
{
|
||||||
|
if (g_votes_striked[i] == true)
|
||||||
|
{
|
||||||
|
num_striked++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_striked;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean Y_VoteIDIsSpecial(const UINT8 playerId)
|
||||||
|
{
|
||||||
|
switch (playerId)
|
||||||
|
{
|
||||||
|
case VOTE_SPECIAL:
|
||||||
|
case VOTE_TIMEOUT_LOSER:
|
||||||
|
case VOTE_TIMEOUT_WINNER:
|
||||||
|
{
|
||||||
|
// Special vote spot, always allow
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boolean Y_PlayerIDCanVote(const UINT8 playerId)
|
boolean Y_PlayerIDCanVote(const UINT8 playerId)
|
||||||
{
|
{
|
||||||
player_t *player = NULL;
|
if (Y_VoteIDIsSpecial(playerId) == true)
|
||||||
|
|
||||||
if (playerId == VOTE_SPECIAL)
|
|
||||||
{
|
{
|
||||||
// Special vote spot, always allow
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -245,7 +298,7 @@ boolean Y_PlayerIDCanVote(const UINT8 playerId)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
player = &players[playerId];
|
const player_t *player = &players[playerId];
|
||||||
if (player->spectator == true)
|
if (player->spectator == true)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -260,8 +313,48 @@ boolean Y_PlayerIDCanVote(const UINT8 playerId)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean Y_IsPlayersTurn(const UINT8 playerId)
|
||||||
|
{
|
||||||
|
if (Y_VoteIDIsSpecial(playerId) == true)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vote.stage_striking == false)
|
||||||
|
{
|
||||||
|
// Not stage striking -- we can always vote.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is it our turn to strike a stage?
|
||||||
|
const player_t *player = &players[playerId];
|
||||||
|
if (vote.strike_turn == true)
|
||||||
|
{
|
||||||
|
return (player == vote.strike_winner);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (player == vote.strike_loser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean Y_PlayerIDCanVoteRightNow(const UINT8 playerId)
|
||||||
|
{
|
||||||
|
if (Y_IsPlayersTurn(playerId) == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Y_PlayerIDCanVote(playerId);
|
||||||
|
}
|
||||||
|
|
||||||
static boolean Y_PlayerCanSelect(const UINT8 localId)
|
static boolean Y_PlayerCanSelect(const UINT8 localId)
|
||||||
{
|
{
|
||||||
|
if (localId > splitscreen)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const UINT8 p = g_localplayers[localId];
|
const UINT8 p = g_localplayers[localId];
|
||||||
|
|
||||||
if (g_pickedVote != VOTE_NOT_PICKED)
|
if (g_pickedVote != VOTE_NOT_PICKED)
|
||||||
|
|
@ -280,7 +373,7 @@ static boolean Y_PlayerCanSelect(const UINT8 localId)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Y_PlayerIDCanVote(p);
|
return Y_PlayerIDCanVoteRightNow(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Y_SortPile(void)
|
static void Y_SortPile(void)
|
||||||
|
|
@ -381,21 +474,73 @@ static void Y_SortPile(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Y_SetPlayersVote(const UINT8 playerId, SINT8 newVote)
|
void Y_SetPlayersVote(const UINT8 inputPlayerId, SINT8 newVote)
|
||||||
{
|
{
|
||||||
y_vote_pile *const pile = &vote.roulette.pile[playerId];
|
INT32 i;
|
||||||
y_vote_catcher *const catcher = &pile->catcher;
|
|
||||||
|
|
||||||
if (gamestate != GS_VOTING)
|
if (gamestate != GS_VOTING)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UINT8 playerId = inputPlayerId;
|
||||||
|
|
||||||
|
// Manually overwrite these players for timed out votes.
|
||||||
|
// Loser/winner is encoded in the vote ID to prevent race
|
||||||
|
// race conditions with real votes causing problems.
|
||||||
|
if (inputPlayerId == VOTE_TIMEOUT_LOSER)
|
||||||
|
{
|
||||||
|
playerId = (vote.strike_loser - players);
|
||||||
|
}
|
||||||
|
else if (inputPlayerId == VOTE_TIMEOUT_WINNER)
|
||||||
|
{
|
||||||
|
playerId = (vote.strike_winner - players);
|
||||||
|
}
|
||||||
|
|
||||||
if (newVote < 0 || newVote >= VOTE_NUM_LEVELS)
|
if (newVote < 0 || newVote >= VOTE_NUM_LEVELS)
|
||||||
{
|
{
|
||||||
newVote = VOTE_NOT_PICKED;
|
newVote = VOTE_NOT_PICKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (playerId < MAXPLAYERS)
|
||||||
|
{
|
||||||
|
if (Y_PlayerIDCanVoteRightNow(playerId) == false)
|
||||||
|
{
|
||||||
|
// Not your turn, dude!
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vote.stage_striking == true)
|
||||||
|
{
|
||||||
|
if (newVote != VOTE_NOT_PICKED
|
||||||
|
&& g_votes_striked[newVote] == false
|
||||||
|
&& Y_CountStriked() < VOTE_NUM_LEVELS-1)
|
||||||
|
{
|
||||||
|
// Strike a stage, instead of voting.
|
||||||
|
g_votes_striked[newVote] = true;
|
||||||
|
|
||||||
|
// Change turn.
|
||||||
|
vote.strike_turn = !vote.strike_turn;
|
||||||
|
|
||||||
|
// Reset variables.
|
||||||
|
Y_SetVoteTimer();
|
||||||
|
for (i = 0; i <= splitscreen; i++)
|
||||||
|
{
|
||||||
|
vote.players[i].sentTimeOutVote = false;
|
||||||
|
vote.players[i].delay = NEWTICRATE/7;
|
||||||
|
}
|
||||||
|
vote.strike_time_out = false;
|
||||||
|
|
||||||
|
// TODO: striking animation
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
y_vote_pile *const pile = &vote.roulette.pile[playerId];
|
||||||
|
y_vote_catcher *const catcher = &pile->catcher;
|
||||||
|
|
||||||
g_votes[playerId] = newVote;
|
g_votes[playerId] = newVote;
|
||||||
|
|
||||||
Y_SortPile();
|
Y_SortPile();
|
||||||
|
|
@ -416,12 +561,12 @@ void Y_SetPlayersVote(const UINT8 playerId, SINT8 newVote)
|
||||||
if (vote.timer == -1)
|
if (vote.timer == -1)
|
||||||
{
|
{
|
||||||
// Someone has voted, so start the timer now.
|
// Someone has voted, so start the timer now.
|
||||||
vote.timer = cv_votetime.value * TICRATE;
|
Y_SetVoteTimer();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Y_DrawVoteThumbnail(fixed_t center_x, fixed_t center_y, fixed_t width, INT32 flags, SINT8 v, boolean dim, SINT8 playerID)
|
static void Y_DrawVoteThumbnail(fixed_t center_x, fixed_t center_y, fixed_t width, INT32 flags, SINT8 v, boolean dim, SINT8 playerID, boolean from_selection)
|
||||||
{
|
{
|
||||||
const boolean encore = vote_draw.levels[v].encore;
|
const boolean encore = vote_draw.levels[v].encore;
|
||||||
const fixed_t height = (width * BASEVIDHEIGHT) / BASEVIDWIDTH;
|
const fixed_t height = (width * BASEVIDHEIGHT) / BASEVIDWIDTH;
|
||||||
|
|
@ -468,29 +613,64 @@ static void Y_DrawVoteThumbnail(fixed_t center_x, fixed_t center_y, fixed_t widt
|
||||||
|
|
||||||
V_AdjustXYWithSnap(&fx, &fy, flags, dupx, dupy);
|
V_AdjustXYWithSnap(&fx, &fy, flags, dupx, dupy);
|
||||||
|
|
||||||
|
boolean striked = false;
|
||||||
|
if (from_selection == true)
|
||||||
|
{
|
||||||
|
striked = g_votes_striked[v];
|
||||||
|
}
|
||||||
|
|
||||||
V_DrawFill(
|
V_DrawFill(
|
||||||
fx - dupx, fy - dupy,
|
fx - dupx, fy - dupy,
|
||||||
fw + (dupx << 1), fh + (dupy << 1),
|
fw + (dupx << 1), fh + (dupy << 1),
|
||||||
0|flags|V_NOSCALESTART
|
0|flags|V_NOSCALESTART
|
||||||
);
|
);
|
||||||
|
|
||||||
K_DrawMapThumbnail(
|
if (striked == true)
|
||||||
x, y,
|
|
||||||
width, flags | ((encore == true) ? V_FLIP : 0),
|
|
||||||
g_voteLevels[v][0],
|
|
||||||
(dim == true ? R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_GREY, GTC_MENUCACHE) : NULL)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (encore == true)
|
|
||||||
{
|
{
|
||||||
const fixed_t rubyScale = width / 72;
|
const fixed_t strikeScale = width / 32;
|
||||||
V_DrawFixedPatch(
|
V_DrawFixedPatch(
|
||||||
center_x, center_y - FixedMul(vote_draw.ruby_height << 1, rubyScale),
|
center_x - (strikeScale * 25 / 2), center_y - (strikeScale * 22 / 2),
|
||||||
rubyScale, flags,
|
strikeScale, flags,
|
||||||
vote_draw.ruby_icon,
|
vote_draw.strike_icon,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
K_DrawMapThumbnail(
|
||||||
|
x, y,
|
||||||
|
width, flags | ((encore == true) ? V_FLIP : 0),
|
||||||
|
g_voteLevels[v][0],
|
||||||
|
(dim == true ? R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_GREY, GTC_MENUCACHE) : NULL)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (encore == true)
|
||||||
|
{
|
||||||
|
const fixed_t rubyScale = width / 72;
|
||||||
|
V_DrawFixedPatch(
|
||||||
|
center_x, center_y - FixedMul(vote_draw.ruby_height << 1, rubyScale),
|
||||||
|
rubyScale, flags,
|
||||||
|
vote_draw.ruby_icon,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vote.stage_striking == true
|
||||||
|
&& from_selection == true
|
||||||
|
&& dim == false)
|
||||||
|
{
|
||||||
|
if (Y_CountStriked() < VOTE_NUM_LEVELS-1)
|
||||||
|
{
|
||||||
|
const fixed_t strikeScale = width / 32;
|
||||||
|
V_DrawFixedPatch(
|
||||||
|
center_x - (strikeScale * 25 / 2), center_y - (strikeScale * 22 / 2),
|
||||||
|
strikeScale, flags /*| V_TRANSLUCENT*/,
|
||||||
|
vote_draw.strike_icon,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (dim == true)
|
if (dim == true)
|
||||||
{
|
{
|
||||||
|
|
@ -506,7 +686,7 @@ static void Y_DrawVoteThumbnail(fixed_t center_x, fixed_t center_y, fixed_t widt
|
||||||
{
|
{
|
||||||
const INT32 whiteSq = 16 * dupx;
|
const INT32 whiteSq = 16 * dupx;
|
||||||
|
|
||||||
if (playerID < MAXPLAYERS)
|
if (playerID < MAXPLAYERS) // Player vote
|
||||||
{
|
{
|
||||||
UINT8 *playerMap = R_GetTranslationColormap(players[playerID].skin, players[playerID].skincolor, GTC_CACHE);
|
UINT8 *playerMap = R_GetTranslationColormap(players[playerID].skin, players[playerID].skincolor, GTC_CACHE);
|
||||||
patch_t *playerPatch = faceprefix[players[playerID].skin][FACE_RANK];
|
patch_t *playerPatch = faceprefix[players[playerID].skin][FACE_RANK];
|
||||||
|
|
@ -518,7 +698,7 @@ static void Y_DrawVoteThumbnail(fixed_t center_x, fixed_t center_y, fixed_t widt
|
||||||
playerPatch, playerMap
|
playerPatch, playerMap
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else if (vote.stage_striking == false) // Angry map
|
||||||
{
|
{
|
||||||
const fixed_t iconHeight = (14 << FRACBITS);
|
const fixed_t iconHeight = (14 << FRACBITS);
|
||||||
const fixed_t iconWidth = (iconHeight * 320) / 200;
|
const fixed_t iconWidth = (iconHeight * 320) / 200;
|
||||||
|
|
@ -618,7 +798,7 @@ static void Y_DrawCatcher(y_vote_catcher *catcher)
|
||||||
baseX, catcher->y,
|
baseX, catcher->y,
|
||||||
((catcher->small == true) ? PILE_WIDTH : SELECTION_WIDTH), 0,
|
((catcher->small == true) ? PILE_WIDTH : SELECTION_WIDTH), 0,
|
||||||
catcher->level, false,
|
catcher->level, false,
|
||||||
catcher->player
|
catcher->player, false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -813,7 +993,7 @@ static void Y_DrawVoteSelection(fixed_t offset)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_votes[p] != VOTE_NOT_PICKED || Y_PlayerIDCanVote(p) == false)
|
if (g_votes[p] != VOTE_NOT_PICKED || Y_PlayerIDCanVoteRightNow(p) == false)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -881,12 +1061,41 @@ static void Y_DrawVoteSelection(fixed_t offset)
|
||||||
x, y - vote_draw.levels[i].hop,
|
x, y - vote_draw.levels[i].hop,
|
||||||
SELECTION_WIDTH, 0,
|
SELECTION_WIDTH, 0,
|
||||||
i, (selected == false),
|
i, (selected == false),
|
||||||
-1
|
-1, true
|
||||||
);
|
);
|
||||||
|
|
||||||
x += SELECTION_SPACING_W;
|
x += SELECTION_SPACING_W;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vote.stage_striking == true && Y_CountStriked() < VOTE_NUM_LEVELS-1)
|
||||||
|
{
|
||||||
|
UINT8 current_strike_player = (
|
||||||
|
(vote.strike_turn == true)
|
||||||
|
? (vote.strike_winner - players)
|
||||||
|
: (vote.strike_loser - players)
|
||||||
|
);
|
||||||
|
|
||||||
|
for (i = 0; i <= splitscreen; i++)
|
||||||
|
{
|
||||||
|
if (g_localplayers[i] == current_strike_player)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > splitscreen)
|
||||||
|
{
|
||||||
|
const char *wait_str = va("Waiting for %s...", player_names[current_strike_player]);
|
||||||
|
|
||||||
|
V_DrawThinString(
|
||||||
|
BASEVIDWIDTH / 2 - (V_ThinStringWidth(wait_str, 0) / 2),
|
||||||
|
180,
|
||||||
|
0,
|
||||||
|
wait_str
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Draw our catchers
|
// Draw our catchers
|
||||||
//
|
//
|
||||||
|
|
@ -944,7 +1153,7 @@ static void Y_DrawVotePile(void)
|
||||||
PILE_WIDTH, 0,
|
PILE_WIDTH, 0,
|
||||||
g_votes[i],
|
g_votes[i],
|
||||||
(i != vote.roulette.anim || g_pickedVote == VOTE_NOT_PICKED),
|
(i != vote.roulette.anim || g_pickedVote == VOTE_NOT_PICKED),
|
||||||
i
|
i, false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1033,7 +1242,7 @@ static void Y_VoteStops(SINT8 pick, SINT8 level)
|
||||||
{
|
{
|
||||||
Y_FinalizeVote(level);
|
Y_FinalizeVote(level);
|
||||||
|
|
||||||
if (netgame && P_IsPartyPlayer(&players[pick]))
|
if (netgame && pick < MAXPLAYERS && P_IsPartyPlayer(&players[pick]))
|
||||||
{
|
{
|
||||||
S_StartSound(NULL, sfx_yeeeah); // yeeeah!
|
S_StartSound(NULL, sfx_yeeeah); // yeeeah!
|
||||||
}
|
}
|
||||||
|
|
@ -1043,8 +1252,30 @@ static void Y_VoteStops(SINT8 pick, SINT8 level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void Y_PlayerSendStrike(const UINT8 localPlayer)
|
||||||
|
{
|
||||||
|
y_vote_player *const player = &vote.players[localPlayer];
|
||||||
|
y_vote_catcher *const catcher = &player->catcher;
|
||||||
|
|
||||||
|
if (g_votes_striked[player->selection] == true)
|
||||||
|
{
|
||||||
|
// TODO: "Can't select" animation
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
D_ModifyClientVote(g_localplayers[localPlayer], player->selection);
|
||||||
|
catcher->action = CATCHER_NA;
|
||||||
|
catcher->delay = 5;
|
||||||
|
}
|
||||||
|
|
||||||
static void Y_PlayerSendVote(const UINT8 localPlayer)
|
static void Y_PlayerSendVote(const UINT8 localPlayer)
|
||||||
{
|
{
|
||||||
|
if (vote.stage_striking == true)
|
||||||
|
{
|
||||||
|
Y_PlayerSendStrike(localPlayer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
y_vote_player *const player = &vote.players[localPlayer];
|
y_vote_player *const player = &vote.players[localPlayer];
|
||||||
y_vote_catcher *const catcher = &player->catcher;
|
y_vote_catcher *const catcher = &player->catcher;
|
||||||
|
|
||||||
|
|
@ -1171,7 +1402,11 @@ static void Y_TickPlayerCatcher(const UINT8 localPlayer)
|
||||||
{
|
{
|
||||||
if (catcher->x == catcher->destX && catcher->y == catcher->destY)
|
if (catcher->x == catcher->destX && catcher->y == catcher->destY)
|
||||||
{
|
{
|
||||||
D_ModifyClientVote(g_localplayers[localPlayer], vote.players[localPlayer].selection);
|
if (vote.stage_striking == false)
|
||||||
|
{
|
||||||
|
D_ModifyClientVote(g_localplayers[localPlayer], vote.players[localPlayer].selection);
|
||||||
|
}
|
||||||
|
|
||||||
catcher->action = CATCHER_NA;
|
catcher->action = CATCHER_NA;
|
||||||
catcher->delay = 5;
|
catcher->delay = 5;
|
||||||
S_StopSoundByNum(sfx_kc37);
|
S_StopSoundByNum(sfx_kc37);
|
||||||
|
|
@ -1352,7 +1587,7 @@ static void Y_TickVoteRoulette(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Y_TryMapAngerVote(void)
|
static SINT8 Y_TryMapAngerVote(void)
|
||||||
{
|
{
|
||||||
SINT8 angryMaps[VOTE_NUM_LEVELS] = { -1 };
|
SINT8 angryMaps[VOTE_NUM_LEVELS] = { -1 };
|
||||||
size_t angryMapsCount = 0;
|
size_t angryMapsCount = 0;
|
||||||
|
|
@ -1381,7 +1616,7 @@ static void Y_TryMapAngerVote(void)
|
||||||
if (numPlayers < 3)
|
if (numPlayers < 3)
|
||||||
{
|
{
|
||||||
// Don't handle map anger if there's not enough players.
|
// Don't handle map anger if there's not enough players.
|
||||||
return;
|
return VOTE_NOT_PICKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < VOTE_NUM_LEVELS; i++)
|
for (i = 0; i < VOTE_NUM_LEVELS; i++)
|
||||||
|
|
@ -1409,12 +1644,207 @@ static void Y_TryMapAngerVote(void)
|
||||||
|
|
||||||
if (angryMapsCount == 0)
|
if (angryMapsCount == 0)
|
||||||
{
|
{
|
||||||
return;
|
return VOTE_NOT_PICKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the special vote to a random angry map.
|
// Set the special vote to a random angry map.
|
||||||
pick = M_RandomKey(angryMapsCount);
|
pick = M_RandomKey(angryMapsCount);
|
||||||
D_ModifyClientVote(UINT8_MAX, angryMaps[pick]);
|
return angryMaps[pick];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Y_ExitStageStrike(void)
|
||||||
|
{
|
||||||
|
INT32 i;
|
||||||
|
|
||||||
|
vote.stage_striking = false;
|
||||||
|
|
||||||
|
for (i = 0; i < VOTE_NUM_LEVELS; i++)
|
||||||
|
{
|
||||||
|
g_votes_striked[i] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
vote.strike_loser = NULL;
|
||||||
|
vote.strike_winner = NULL;
|
||||||
|
vote.strike_turn = false;
|
||||||
|
vote.strike_time_out = false;
|
||||||
|
|
||||||
|
Y_SetVoteTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean Y_CheckStageStrikeStatus(void)
|
||||||
|
{
|
||||||
|
INT32 i;
|
||||||
|
UINT8 num_voters = 0;
|
||||||
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
|
{
|
||||||
|
if (Y_PlayerIDCanVote(i) == false)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
num_voters++;
|
||||||
|
if (num_voters > 2)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_voters != 2)
|
||||||
|
{
|
||||||
|
// Someone joined or left. Stage striking is broken!
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vote.strike_loser == NULL || Y_PlayerIDCanVote(vote.strike_loser - players) == false)
|
||||||
|
{
|
||||||
|
// Loser is invalidated!
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vote.strike_winner == NULL || Y_PlayerIDCanVote(vote.strike_winner - players) == false)
|
||||||
|
{
|
||||||
|
// Winner is invalidated!
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Looks good, we can tick stage striking.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Y_TickVoteStageStrike(void)
|
||||||
|
{
|
||||||
|
INT32 i;
|
||||||
|
|
||||||
|
if (Y_CheckStageStrikeStatus() == false)
|
||||||
|
{
|
||||||
|
Y_ExitStageStrike();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SINT8 the_only_level = VOTE_NOT_PICKED;
|
||||||
|
for (i = 0; i < VOTE_NUM_LEVELS; i++)
|
||||||
|
{
|
||||||
|
if (g_votes_striked[i] == true)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (the_only_level != VOTE_NOT_PICKED)
|
||||||
|
{
|
||||||
|
// More than 1 valid level.
|
||||||
|
// Unset and stop iterating.
|
||||||
|
the_only_level = VOTE_NOT_PICKED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
the_only_level = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (the_only_level != VOTE_NOT_PICKED)
|
||||||
|
{
|
||||||
|
vote.timer = 0;
|
||||||
|
vote.strikeFinalize = STRIKE_DELAY_TIME;
|
||||||
|
|
||||||
|
if (vote.selectFinalize < SELECT_DELAY_TIME)
|
||||||
|
{
|
||||||
|
if (vote.selectFinalize == 0)
|
||||||
|
{
|
||||||
|
for (i = 0; i <= splitscreen; i++)
|
||||||
|
{
|
||||||
|
UINT8 p = g_localplayers[i];
|
||||||
|
|
||||||
|
if (p != (vote.strike_loser - players)
|
||||||
|
&& p != (vote.strike_winner - players))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
y_vote_player *const player = &vote.players[i];
|
||||||
|
y_vote_catcher *const catcher = &player->catcher;
|
||||||
|
|
||||||
|
player->selection = the_only_level;
|
||||||
|
catcher->action = CATCHER_FG_LOWER;
|
||||||
|
|
||||||
|
catcher->x = catcher->destX = SELECTION_X + (SELECTION_SPACING_W * player->selection);
|
||||||
|
catcher->y = CATCHER_OFFSCREEN;
|
||||||
|
catcher->destY = SELECTION_Y - SELECTION_HOP;
|
||||||
|
catcher->spr = 0;
|
||||||
|
catcher->level = VOTE_NOT_PICKED;
|
||||||
|
|
||||||
|
S_StartSound(NULL, sfx_kc37);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vote.selectFinalize++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vote.selectFinalize >= SELECT_DELAY_TIME)
|
||||||
|
{
|
||||||
|
if (vote.pickFinalize < PICK_DELAY_TIME)
|
||||||
|
{
|
||||||
|
vote.pickFinalize++;
|
||||||
|
}
|
||||||
|
else if (vote.endtic == -1)
|
||||||
|
{
|
||||||
|
vote.notYetPicked = false; /* don't pick vote twice */
|
||||||
|
|
||||||
|
if (server)
|
||||||
|
{
|
||||||
|
D_PickVote( the_only_level );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (vote.timer == 0)
|
||||||
|
{
|
||||||
|
if (vote.strikeFinalize < STRIKE_DELAY_TIME)
|
||||||
|
{
|
||||||
|
vote.strikeFinalize++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vote.strikeFinalize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vote.strikeFinalize >= STRIKE_DELAY_TIME)
|
||||||
|
{
|
||||||
|
// We didn't get their timeout strike net command.
|
||||||
|
// Maybe they hacked their exe, or connection was
|
||||||
|
// interrupted, or some other issue.
|
||||||
|
|
||||||
|
// Let's just strike a random stage for them.
|
||||||
|
if (server && vote.strike_time_out == false)
|
||||||
|
{
|
||||||
|
INT32 rng = M_RandomKey(VOTE_NUM_LEVELS);
|
||||||
|
for (i = 0; i < VOTE_NUM_LEVELS; i++)
|
||||||
|
{
|
||||||
|
if (g_votes_striked[i] == false)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rng++;
|
||||||
|
if (rng >= VOTE_NUM_LEVELS)
|
||||||
|
{
|
||||||
|
rng = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
D_ModifyClientVote((vote.strike_turn == true) ? VOTE_TIMEOUT_WINNER : VOTE_TIMEOUT_LOSER, rng);
|
||||||
|
}
|
||||||
|
|
||||||
|
vote.strike_time_out = true;
|
||||||
|
}
|
||||||
|
else if (vote.timer > 0)
|
||||||
|
{
|
||||||
|
vote.timer--;
|
||||||
|
vote.selectFinalize = 0;
|
||||||
|
vote.pickFinalize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Y_TickVoteSelection(void)
|
static void Y_TickVoteSelection(void)
|
||||||
|
|
@ -1446,6 +1876,22 @@ static void Y_TickVoteSelection(void)
|
||||||
// Time's up, send our vote ASAP.
|
// Time's up, send our vote ASAP.
|
||||||
if (vote.players[i].sentTimeOutVote == false)
|
if (vote.players[i].sentTimeOutVote == false)
|
||||||
{
|
{
|
||||||
|
// Move off of striked stages for the timeout vote.
|
||||||
|
INT32 j;
|
||||||
|
for (j = 0; j < VOTE_NUM_LEVELS; j++)
|
||||||
|
{
|
||||||
|
if (g_votes_striked[vote.players[i].selection] == false)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
vote.players[i].selection++;
|
||||||
|
if (vote.players[i].selection >= VOTE_NUM_LEVELS)
|
||||||
|
{
|
||||||
|
vote.players[i].selection = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Y_PlayerSendVote(i);
|
Y_PlayerSendVote(i);
|
||||||
vote.players[i].sentTimeOutVote = true;
|
vote.players[i].sentTimeOutVote = true;
|
||||||
vote.players[i].delay = NEWTICRATE/7;
|
vote.players[i].delay = NEWTICRATE/7;
|
||||||
|
|
@ -1497,12 +1943,27 @@ static void Y_TickVoteSelection(void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (players[i].bot == true && g_votes[i] == VOTE_NOT_PICKED)
|
if (server && players[i].bot == true && Y_PlayerIDCanVoteRightNow(i) == true && g_votes[i] == VOTE_NOT_PICKED)
|
||||||
{
|
{
|
||||||
if (( M_RandomFixed() % 100 ) == 0)
|
if (( M_RandomFixed() % 100 ) == 0)
|
||||||
{
|
{
|
||||||
// bots vote randomly
|
// bots vote randomly
|
||||||
D_ModifyClientVote(i, M_RandomKey(VOTE_NUM_LEVELS));
|
INT32 rng = M_RandomKey(VOTE_NUM_LEVELS);
|
||||||
|
for (i = 0; i < VOTE_NUM_LEVELS; i++)
|
||||||
|
{
|
||||||
|
if (g_votes_striked[i] == false)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rng++;
|
||||||
|
if (rng >= VOTE_NUM_LEVELS)
|
||||||
|
{
|
||||||
|
rng = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
D_ModifyClientVote(i, rng);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1512,6 +1973,13 @@ static void Y_TickVoteSelection(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vote.stage_striking == true)
|
||||||
|
{
|
||||||
|
// Use the same selection logic, otherwise use separate ending logic.
|
||||||
|
Y_TickVoteStageStrike();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (everyone_voted == true)
|
if (everyone_voted == true)
|
||||||
{
|
{
|
||||||
vote.timer = 0;
|
vote.timer = 0;
|
||||||
|
|
@ -1542,8 +2010,7 @@ static void Y_TickVoteSelection(void)
|
||||||
|
|
||||||
if (server)
|
if (server)
|
||||||
{
|
{
|
||||||
Y_TryMapAngerVote();
|
D_PickVote( Y_TryMapAngerVote() );
|
||||||
D_PickVote();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1593,7 +2060,7 @@ void Y_VoteTicker(void)
|
||||||
|
|
||||||
if (server && g_pickedVote != VOTE_NOT_PICKED && g_votes[g_pickedVote] == VOTE_NOT_PICKED) // Uh oh! The person who got picked left! Recalculate, quick!
|
if (server && g_pickedVote != VOTE_NOT_PICKED && g_votes[g_pickedVote] == VOTE_NOT_PICKED) // Uh oh! The person who got picked left! Recalculate, quick!
|
||||||
{
|
{
|
||||||
D_PickVote();
|
D_PickVote( VOTE_NOT_PICKED );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vote.tic == 0)
|
if (vote.tic == 0)
|
||||||
|
|
@ -1633,6 +2100,7 @@ static void Y_InitVoteDrawing(void)
|
||||||
INT32 i = 0, j = 0;
|
INT32 i = 0, j = 0;
|
||||||
|
|
||||||
vote_draw.ruby_icon = W_CachePatchName("RUBYICON", PU_STATIC);
|
vote_draw.ruby_icon = W_CachePatchName("RUBYICON", PU_STATIC);
|
||||||
|
vote_draw.strike_icon = W_CachePatchName("K_NOBLNS", PU_STATIC);
|
||||||
|
|
||||||
for (i = 0; i < PLANET_FRAMES; i++)
|
for (i = 0; i < PLANET_FRAMES; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -1720,6 +2188,103 @@ static void Y_InitVoteDrawing(void)
|
||||||
vote_draw.selectTransition = FRACUNIT;
|
vote_draw.selectTransition = FRACUNIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean Y_DetermineStageStrike(void)
|
||||||
|
{
|
||||||
|
player_t *a = NULL;
|
||||||
|
player_t *b = NULL;
|
||||||
|
|
||||||
|
UINT8 num_voters = 0;
|
||||||
|
|
||||||
|
INT32 i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
|
{
|
||||||
|
if (Y_PlayerIDCanVote(i) == false)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
num_voters++;
|
||||||
|
|
||||||
|
// Just set the pointers for now, sort them later.
|
||||||
|
if (a == NULL)
|
||||||
|
{
|
||||||
|
a = &players[i];
|
||||||
|
}
|
||||||
|
else if (b == NULL)
|
||||||
|
{
|
||||||
|
b = &players[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Too many players
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_voters != 2 || a == NULL || b == NULL)
|
||||||
|
{
|
||||||
|
// Requires exactly 2 of them.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 score_a = 0;
|
||||||
|
UINT32 score_b = 0;
|
||||||
|
|
||||||
|
intertype_t scoring_type = Y_GetIntermissionType();
|
||||||
|
switch (scoring_type)
|
||||||
|
{
|
||||||
|
case int_time:
|
||||||
|
{
|
||||||
|
score_a = UINT32_MAX - a->realtime;
|
||||||
|
score_b = UINT32_MAX - b->realtime;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case int_score:
|
||||||
|
{
|
||||||
|
score_a = a->score;
|
||||||
|
score_b = b->realtime;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// Invalid, exit now.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->pflags & PF_NOCONTEST)
|
||||||
|
{
|
||||||
|
score_a = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b->pflags & PF_NOCONTEST)
|
||||||
|
{
|
||||||
|
score_b = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (score_a == score_b)
|
||||||
|
{
|
||||||
|
// TODO: should be a coin flip, but how
|
||||||
|
// should the RNG for this be handled?
|
||||||
|
score_a++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (score_a > score_b)
|
||||||
|
{
|
||||||
|
vote.strike_loser = b;
|
||||||
|
vote.strike_winner = a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vote.strike_loser = a;
|
||||||
|
vote.strike_winner = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
vote.stage_striking = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void Y_StartVote(void)
|
void Y_StartVote(void)
|
||||||
{
|
{
|
||||||
INT32 i = 0;
|
INT32 i = 0;
|
||||||
|
|
@ -1733,12 +2298,6 @@ void Y_StartVote(void)
|
||||||
|
|
||||||
vote.tic = vote.endtic = -1;
|
vote.tic = vote.endtic = -1;
|
||||||
|
|
||||||
#ifdef VOTE_TIME_WAIT_FOR_VOTE
|
|
||||||
vote.timer = -1; // Timer is not set until the first vote is added
|
|
||||||
#else
|
|
||||||
vote.timer = cv_votetime.value * TICRATE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
g_pickedVote = VOTE_NOT_PICKED;
|
g_pickedVote = VOTE_NOT_PICKED;
|
||||||
vote.notYetPicked = true;
|
vote.notYetPicked = true;
|
||||||
|
|
||||||
|
|
@ -1766,6 +2325,19 @@ void Y_StartVote(void)
|
||||||
catcher->player = i;
|
catcher->player = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < VOTE_NUM_LEVELS; i++)
|
||||||
|
{
|
||||||
|
g_votes_striked[i] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Y_DetermineStageStrike();
|
||||||
|
|
||||||
|
#ifdef VOTE_TIME_WAIT_FOR_VOTE
|
||||||
|
vote.timer = -1; // Timer is not set until the first vote is added
|
||||||
|
#else
|
||||||
|
Y_SetVoteTimer();
|
||||||
|
#endif
|
||||||
|
|
||||||
Y_InitVoteDrawing();
|
Y_InitVoteDrawing();
|
||||||
|
|
||||||
vote.loaded = true;
|
vote.loaded = true;
|
||||||
|
|
@ -1787,6 +2359,7 @@ static void Y_UnloadVoteData(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
UNLOAD(vote_draw.ruby_icon);
|
UNLOAD(vote_draw.ruby_icon);
|
||||||
|
UNLOAD(vote_draw.strike_icon);
|
||||||
|
|
||||||
for (i = 0; i < PLANET_FRAMES; i++)
|
for (i = 0; i < PLANET_FRAMES; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -1849,13 +2422,18 @@ enum
|
||||||
VOTE_END_NORMAL,
|
VOTE_END_NORMAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
void Y_SetupVoteFinish(SINT8 pick, SINT8 level)
|
void Y_SetupVoteFinish(SINT8 pick, SINT8 level, SINT8 anger)
|
||||||
{
|
{
|
||||||
if (vote.loaded == false)
|
if (vote.loaded == false)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (anger != VOTE_NOT_PICKED)
|
||||||
|
{
|
||||||
|
Y_SetPlayersVote(VOTE_SPECIAL, anger);
|
||||||
|
}
|
||||||
|
|
||||||
if (pick == VOTE_NOT_PICKED || level == VOTE_NOT_PICKED) // No other votes? We gotta get out of here, then!
|
if (pick == VOTE_NOT_PICKED || level == VOTE_NOT_PICKED) // No other votes? We gotta get out of here, then!
|
||||||
{
|
{
|
||||||
Y_EndVote();
|
Y_EndVote();
|
||||||
|
|
@ -1920,4 +2498,25 @@ void Y_SetupVoteFinish(SINT8 pick, SINT8 level)
|
||||||
vote.timer = -1;
|
vote.timer = -1;
|
||||||
vote.selectFinalize = SELECT_DELAY_TIME;
|
vote.selectFinalize = SELECT_DELAY_TIME;
|
||||||
vote.pickFinalize = PICK_DELAY_TIME;
|
vote.pickFinalize = PICK_DELAY_TIME;
|
||||||
|
vote.strikeFinalize = STRIKE_DELAY_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Y_VoteContext
|
||||||
|
//
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
VOTE_CTX_NORMAL = 0,
|
||||||
|
VOTE_CTX_DUEL,
|
||||||
|
};
|
||||||
|
|
||||||
|
UINT8 Y_VoteContext(void)
|
||||||
|
{
|
||||||
|
if (vote.stage_striking == true)
|
||||||
|
{
|
||||||
|
return VOTE_CTX_DUEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return VOTE_CTX_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,6 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define VOTE_NUM_LEVELS (4)
|
|
||||||
#define VOTE_NOT_PICKED (-1)
|
|
||||||
|
|
||||||
#define VOTE_MOD_ENCORE (0x01)
|
#define VOTE_MOD_ENCORE (0x01)
|
||||||
|
|
||||||
boolean Y_PlayerIDCanVote(const UINT8 playerId);
|
boolean Y_PlayerIDCanVote(const UINT8 playerId);
|
||||||
|
|
@ -31,7 +28,8 @@ void Y_VoteDrawer(void);
|
||||||
void Y_VoteTicker(void);
|
void Y_VoteTicker(void);
|
||||||
void Y_StartVote(void);
|
void Y_StartVote(void);
|
||||||
void Y_EndVote(void);
|
void Y_EndVote(void);
|
||||||
void Y_SetupVoteFinish(SINT8 pick, SINT8 level);
|
void Y_SetupVoteFinish(SINT8 pick, SINT8 level, SINT8 anger);
|
||||||
|
UINT8 Y_VoteContext(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
|
||||||
|
|
@ -6590,6 +6590,7 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending)
|
||||||
{
|
{
|
||||||
WRITEUINT16(save->p, g_voteLevels[i][0]);
|
WRITEUINT16(save->p, g_voteLevels[i][0]);
|
||||||
WRITEUINT16(save->p, g_voteLevels[i][1]);
|
WRITEUINT16(save->p, g_voteLevels[i][1]);
|
||||||
|
WRITEUINT8(save->p, g_votes_striked[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < VOTE_TOTAL; i++)
|
for (i = 0; i < VOTE_TOTAL; i++)
|
||||||
|
|
@ -6800,6 +6801,7 @@ static boolean P_NetUnArchiveMisc(savebuffer_t *save, boolean reloading)
|
||||||
{
|
{
|
||||||
g_voteLevels[i][0] = READUINT16(save->p);
|
g_voteLevels[i][0] = READUINT16(save->p);
|
||||||
g_voteLevels[i][1] = READUINT16(save->p);
|
g_voteLevels[i][1] = READUINT16(save->p);
|
||||||
|
g_votes_striked[i] = (boolean)READUINT8(save->p);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < VOTE_TOTAL; i++)
|
for (i = 0; i < VOTE_TOTAL; i++)
|
||||||
|
|
|
||||||
|
|
@ -1976,6 +1976,35 @@ boolean Y_ShouldDoIntermission(void)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Y_GetIntermissionType
|
||||||
|
//
|
||||||
|
// Returns the intermission type from the current gametype.
|
||||||
|
//
|
||||||
|
intertype_t Y_GetIntermissionType(void)
|
||||||
|
{
|
||||||
|
intertype_t ret = static_cast<intertype_t>(gametypes[gametype]->intermission);
|
||||||
|
|
||||||
|
if (ret == int_scoreortimeattack)
|
||||||
|
{
|
||||||
|
UINT8 i = 0, nump = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
|
{
|
||||||
|
if (!playeringame[i] || players[i].spectator)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
nump++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = (nump < 2 ? int_time : int_score);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Y_DetermineIntermissionType
|
// Y_DetermineIntermissionType
|
||||||
//
|
//
|
||||||
|
|
@ -1990,21 +2019,7 @@ void Y_DetermineIntermissionType(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set initially
|
intertype = Y_GetIntermissionType();
|
||||||
intertype = static_cast<intertype_t>(gametypes[gametype]->intermission);
|
|
||||||
|
|
||||||
// special cases
|
|
||||||
if (intertype == int_scoreortimeattack)
|
|
||||||
{
|
|
||||||
UINT8 i = 0, nump = 0;
|
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
|
||||||
{
|
|
||||||
if (!playeringame[i] || players[i].spectator)
|
|
||||||
continue;
|
|
||||||
nump++;
|
|
||||||
}
|
|
||||||
intertype = (nump < 2 ? int_time : int_score);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT8 Y_PlayersBestPossiblePosition(player_t *const player)
|
static UINT8 Y_PlayersBestPossiblePosition(player_t *const player)
|
||||||
|
|
|
||||||
|
|
@ -61,9 +61,6 @@ void Y_DrawIntermissionButton(INT32 startslide, INT32 through, boolean widescree
|
||||||
void Y_StartIntermission(void);
|
void Y_StartIntermission(void);
|
||||||
void Y_EndIntermission(void);
|
void Y_EndIntermission(void);
|
||||||
|
|
||||||
boolean Y_ShouldDoIntermission(void);
|
|
||||||
void Y_DetermineIntermissionType(void);
|
|
||||||
|
|
||||||
void Y_PlayIntermissionMusic(void);
|
void Y_PlayIntermissionMusic(void);
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
|
@ -76,6 +73,10 @@ typedef enum
|
||||||
|
|
||||||
extern intertype_t intertype;
|
extern intertype_t intertype;
|
||||||
|
|
||||||
|
boolean Y_ShouldDoIntermission(void);
|
||||||
|
intertype_t Y_GetIntermissionType(void);
|
||||||
|
void Y_DetermineIntermissionType(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue