Merge branch 'z-voting' into 'master'

Z Voting

Closes #265

See merge request KartKrew/Kart!1184
This commit is contained in:
Sal 2023-04-23 05:12:47 +00:00
commit 35728a00e3
21 changed files with 1746 additions and 94 deletions

View file

@ -142,6 +142,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
k_rank.c
k_vote.c
k_serverstats.c
k_zvote.c
)
if(SRB2_CONFIG_ENABLE_WEBM_MOVIES)

View file

@ -62,6 +62,7 @@
#include "g_party.h"
#include "k_vote.h"
#include "k_serverstats.h"
#include "k_zvote.h"
// cl loading screen
#include "v_video.h"
@ -220,7 +221,7 @@ consvar_t cv_playbackspeed = CVAR_INIT ("playbackspeed", "1", 0, playbackspeed_c
consvar_t cv_httpsource = CVAR_INIT ("http_source", "", CV_SAVE, NULL, NULL);
consvar_t cv_kicktime = CVAR_INIT ("kicktime", "10", CV_SAVE, CV_Unsigned, NULL);
consvar_t cv_kicktime = CVAR_INIT ("kicktime", "20", CV_SAVE, CV_Unsigned, NULL);
// Generate a message for an authenticating client to sign, with some guarantees about who we are.
void GenerateChallenge(uint8_t *buf)
@ -2308,6 +2309,7 @@ static void CL_ConnectToServer(void)
Schedule_Clear();
Automate_Clear();
K_ClearClientPowerLevels();
K_ResetMidVote();
pnumnodes = 1;
oldtic = 0;
@ -3151,7 +3153,7 @@ static void Command_Kick(void)
if (COM_Argc() == 2)
{
WRITEUINT8(p, KICK_MSG_GO_AWAY);
WRITEUINT8(p, KICK_MSG_KICKED);
SendNetXCmd(XD_KICK, &buf, 2);
}
else
@ -3197,6 +3199,11 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
return;
}
if (msg == KICK_MSG_CUSTOM_BAN || msg == KICK_MSG_CUSTOM_KICK)
{
READSTRINGN(*p, reason, MAX_REASONLENGTH+1);
}
// Is playernum authorized to make this kick?
if (playernum != serverplayer && !IsPlayerAdmin(playernum)
/*&& !(playernode[playernum] != UINT8_MAX && playerpernode[playernode[playernum]] == 2
@ -3241,9 +3248,20 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
msg = KICK_MSG_CON_FAIL;
}
if (msg == KICK_MSG_CUSTOM_BAN || msg == KICK_MSG_CUSTOM_KICK)
if (g_midVote.active == true && g_midVote.victim == &players[pnum])
{
READSTRINGN(*p, reason, MAX_REASONLENGTH+1);
if (g_midVote.type == MVT_KICK)
{
// Running the callback here would mean a very dumb infinite loop.
// We'll manually handle this here by changing the msg type.
msg = KICK_MSG_VOTE_KICK;
K_MidVoteFinalize(FRACUNIT); // Vote succeeded, so the delay is normal.
}
else
{
// It should be safe to run the vote callback directly.
K_MidVoteSuccess();
}
}
//CONS_Printf("\x82%s ", player_names[pnum]);
@ -3253,7 +3271,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
// to keep it all in one place.
if (server)
{
if (msg == KICK_MSG_GO_AWAY || msg == KICK_MSG_CUSTOM_KICK)
if (msg == KICK_MSG_KICKED || msg == KICK_MSG_VOTE_KICK || msg == KICK_MSG_CUSTOM_KICK)
{
// Kick as a temporary ban.
banMinutes = cv_kicktime.value;
@ -3293,10 +3311,14 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
switch (msg)
{
case KICK_MSG_GO_AWAY:
case KICK_MSG_KICKED:
HU_AddChatText(va("\x82*%s has been kicked (No reason given)", player_names[pnum]), false);
kickreason = KR_KICK;
break;
case KICK_MSG_VOTE_KICK:
HU_AddChatText(va("\x82*%s has been kicked (Popular demand)", player_names[pnum]), false);
kickreason = KR_KICK;
break;
case KICK_MSG_PING_HIGH:
HU_AddChatText(va("\x82*%s left the game (Broke delay limit)", player_names[pnum]), false);
kickreason = KR_PINGLIMIT;
@ -3404,6 +3426,8 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
M_StartMessage(va(M_GetText("You have been banned\n(%s)\nPress (B)\n"), reason), NULL, MM_NOTHING);
else if (msg == KICK_MSG_SIGFAIL)
M_StartMessage(M_GetText("Server closed connection\n(Invalid signature)\nPress (B)\n"), NULL, MM_NOTHING);
else if (msg == KICK_MSG_VOTE_KICK)
M_StartMessage(M_GetText("You have been kicked by popular demand\n\nPress (B)\n"), NULL, MM_NOTHING);
else
M_StartMessage(M_GetText("You have been kicked by the server\n\nPress (B)\n"), NULL, MM_NOTHING);
}
@ -3692,6 +3716,7 @@ void SV_ResetServer(void)
Automate_Clear();
K_ClearClientPowerLevels();
G_ObliterateParties();
K_ResetMidVote();
memset(splitscreen_invitations, -1, sizeof splitscreen_invitations);
memset(player_name_changes, 0, sizeof player_name_changes);
@ -3788,6 +3813,7 @@ void D_QuitNetGame(void)
Automate_Clear();
K_ClearClientPowerLevels();
G_ObliterateParties();
K_ResetMidVote();
DEBFILE("===========================================================================\n"
" Log finish\n"

View file

@ -458,15 +458,20 @@ extern consvar_t cv_playbackspeed;
#define FILETXHEADER offsetof(filetx_pak, data)
#define BASESERVERTICSSIZE offsetof(doomdata_t, u.serverpak.cmds[0])
#define KICK_MSG_GO_AWAY 1
#define KICK_MSG_CON_FAIL 2
#define KICK_MSG_PLAYER_QUIT 3
#define KICK_MSG_TIMEOUT 4
#define KICK_MSG_BANNED 5
#define KICK_MSG_PING_HIGH 6
#define KICK_MSG_CUSTOM_KICK 7
#define KICK_MSG_CUSTOM_BAN 8
#define KICK_MSG_SIGFAIL 9
typedef enum
{
KICK_MSG_PLAYER_QUIT = 0, // Player intentionally left
KICK_MSG_KICKED, // Server kick message w/ no reason
KICK_MSG_CUSTOM_KICK, // Server kick message w/ reason
KICK_MSG_VOTE_KICK, // Vote kick message
KICK_MSG_BANNED, // Ban message w/ no reason
KICK_MSG_CUSTOM_BAN, // Ban message w/ custom reason
KICK_MSG_TIMEOUT, // Player's connection timed out
KICK_MSG_PING_HIGH, // Player hit the ping limit
KICK_MSG_CON_FAIL, // Player failed to resync game state
KICK_MSG_SIGFAIL, // Player failed signature check
KICK_MSG__MAX // Number of unique messages
} kickmsg_t;
typedef enum
{
@ -476,7 +481,6 @@ typedef enum
KR_TIMEOUT = 4, //Connection Timeout
KR_BAN = 5, //Banned by server
KR_LEAVE = 6, //Quit the game
} kickreason_t;
/* the max number of name changes in some time period */

View file

@ -65,6 +65,7 @@
#include "k_race.h"
#include "g_party.h"
#include "k_vote.h"
#include "k_zvote.h"
#ifdef SRB2_CONFIG_ENABLE_WEBM_MOVIES
#include "m_avrecorder.h"
@ -632,6 +633,8 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
"AUTOMATE", // XD_AUTOMATE
"REQMAPQUEUE", // XD_REQMAPQUEUE
"MAPQUEUE", // XD_MAPQUEUE
"CALLZVOTE", // XD_CALLZVOTE
"SETZVOTE", // XD_SETZVOTE
};
// =========================================================================
@ -844,6 +847,8 @@ void D_RegisterServerCommands(void)
#ifdef LUA_ALLOW_BYTECODE
COM_AddCommand("dumplua", Command_Dumplua_f);
#endif
K_RegisterMidVoteCVars();
}
// =========================================================================

View file

@ -163,7 +163,7 @@ typedef enum
XD_LUAVAR, // 20
XD_LUAFILE, // 21
// SRB2Kart
// Ring Racers
XD_SETUPVOTE, // 22
XD_MODIFYVOTE, // 23
XD_PICKVOTE, // 24
@ -181,6 +181,8 @@ typedef enum
XD_AUTOMATE, // 36
XD_REQMAPQUEUE, // 37
XD_MAPQUEUE, // 38
XD_CALLZVOTE, // 39
XD_SETZVOTE, // 40
MAXNETXCMD
} netxcmd_t;

View file

@ -68,6 +68,7 @@
#include "g_party.h"
#include "k_vote.h"
#include "k_serverstats.h"
#include "k_zvote.h"
#ifdef HAVE_DISCORDRPC
#include "discord.h"
@ -2390,6 +2391,11 @@ void G_Ticker(boolean run)
{
memset(player_name_changes, 0, sizeof player_name_changes);
}
if (Playing() == true)
{
K_TickMidVote();
}
}
}

View file

@ -305,6 +305,10 @@ void HU_Init(void)
PR ("MKFNT");
REG;
ADIM (TIMER);
PR ("TMFNT");
REG;
ADIM (LT);
PR ("GAMEM");
REG;
@ -316,6 +320,14 @@ void HU_Init(void)
PR ("TLWFN");
REG;
ADIM (NUM);
PR ("OPPRF");
REG;
ADIM (NUM);
PR ("PINGF");
REG;
#undef REG
#undef DIG
#undef PR
@ -2323,7 +2335,7 @@ Ping_gfx_color (int lag)
//
// HU_drawPing
//
void HU_drawPing(INT32 x, INT32 y, UINT32 lag, INT32 flags, boolean offline)
void HU_drawPing(fixed_t x, fixed_t y, UINT32 lag, INT32 flags, boolean offline)
{
UINT8 *colormap = NULL;
INT32 measureid = cv_pingmeasurement.value ? 1 : 0;
@ -2339,12 +2351,36 @@ void HU_drawPing(INT32 x, INT32 y, UINT32 lag, INT32 flags, boolean offline)
gfxnum = Ping_gfx_num(lag);
if (measureid == 1)
V_DrawScaledPatch(x+11 - pingmeasure[measureid]->width, y+9, flags, pingmeasure[measureid]);
{
V_DrawFixedPatch(
x + ((11 - pingmeasure[measureid]->width) * FRACUNIT),
y + (9 * FRACUNIT),
FRACUNIT, flags,
pingmeasure[measureid],
NULL
);
}
if (drawlocal)
V_DrawScaledPatch(x+2, y, flags, pinglocal[0]);
{
V_DrawFixedPatch(
x + (2 * FRACUNIT),
y,
FRACUNIT, flags,
pinglocal[0],
NULL
);
}
else
V_DrawScaledPatch(x+2, y, flags, pinggfx[gfxnum]);
{
V_DrawFixedPatch(
x + (2 * FRACUNIT),
y,
FRACUNIT, flags,
pinggfx[gfxnum],
NULL
);
}
colormap = R_GetTranslationColormap(TC_RAINBOW, Ping_gfx_color(lag), GTC_CACHE);
@ -2359,10 +2395,23 @@ void HU_drawPing(INT32 x, INT32 y, UINT32 lag, INT32 flags, boolean offline)
lag = (INT32)(lag * (1000.00f / TICRATE));
}
x = V_DrawPingNum(x + (measureid == 1 ? 11 - pingmeasure[measureid]->width : 10), y+9, flags, lag, colormap);
x = V_DrawPingNum(
x + (((measureid == 1) ? 11 - pingmeasure[measureid]->width : 10) * FRACUNIT),
y + (9 * FRACUNIT),
flags, lag,
colormap
);
if (measureid == 0)
V_DrawScaledPatch(x+1 - pingmeasure[measureid]->width, y+9, flags, pingmeasure[measureid]);
{
V_DrawFixedPatch(
x + ((1 - pingmeasure[measureid]->width) * FRACUNIT),
y + (9 * FRACUNIT),
FRACUNIT, flags,
pingmeasure[measureid],
NULL
);
}
}
void

View file

@ -32,15 +32,25 @@ extern "C" {
#define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1)
// SRB2kart
#define KART_FONTSTART '\"' // the first font character
#define KART_FONTSTART '!' // the first font character
#define KART_FONTEND 'Z'
#define KART_FONTSIZE (KART_FONTEND - KART_FONTSTART + 1)
#define TIMER_FONTSTART '"' // the first font character
#define TIMER_FONTEND '9'
#define TIMER_FONTSIZE (TIMER_FONTEND - TIMER_FONTSTART + 1)
#define AZ_FONTSTART 'A' // the first font character
#define AZ_FONTEND 'Z'
#define AZ_FONTSIZE (AZ_FONTEND - AZ_FONTSTART + 1)
#define NUM_FONTSTART '-' // the first font character
#define NUM_FONTEND '9'
#define NUM_FONTSIZE (NUM_FONTEND - NUM_FONTSTART + 1)
//
// Level title font
@ -72,9 +82,13 @@ enum
X (PROFNUM),
X (KART),
X (TIMER),
X (GM),
X (LSHI),
X (LSLOW),
X (OPPRF),
X (PINGF),
};
#undef X
@ -143,7 +157,7 @@ void HU_TickSongCredits(void);
char HU_dequeueChatChar(void);
void HU_Erase(void);
void HU_clearChatChars(void);
void HU_drawPing(INT32 x, INT32 y, UINT32 ping, INT32 flags, boolean offline); // Lat': Ping drawer for scoreboard.
void HU_drawPing(fixed_t x, fixed_t y, UINT32 ping, INT32 flags, boolean offline); // Lat': Ping drawer for scoreboard.
void HU_drawMiniPing(INT32 x, INT32 y, UINT32 ping, INT32 flags);
INT32 HU_CreateTeamScoresTbl(playersort_t *tab, UINT32 dmtotals[]);

View file

@ -1448,7 +1448,7 @@ static void K_drawKartItem(void)
else
{
V_DrawScaledPatch(fy+28, fy+41, V_HUDTRANS|V_SLIDEIN|fflags, kp_itemx);
V_DrawKartString(fx+38, fy+36, V_HUDTRANS|V_SLIDEIN|fflags, va("%d", stplyr->itemamount));
V_DrawTimerString(fx+38, fy+36, V_HUDTRANS|V_SLIDEIN|fflags, va("%d", stplyr->itemamount));
}
}
else
@ -1587,30 +1587,30 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT32 splitflags, U
}
if (mode && !drawtime)
V_DrawKartString(TX, TY+3, splitflags, va("--'--\"--"));
V_DrawTimerString(TX, TY+3, splitflags, va("--'--\"--"));
else
{
// minutes time 00 __ __
V_DrawKartString(TX, TY+3+jitter, splitflags, va("%d", worktime/10));
V_DrawKartString(TX+12, TY+3-jitter, splitflags, va("%d", worktime%10));
V_DrawTimerString(TX, TY+3+jitter, splitflags, va("%d", worktime/10));
V_DrawTimerString(TX+12, TY+3-jitter, splitflags, va("%d", worktime%10));
// apostrophe location _'__ __
V_DrawKartString(TX+24, TY+3, splitflags, va("'"));
V_DrawTimerString(TX+24, TY+3, splitflags, va("'"));
worktime = (drawtime/TICRATE % 60);
// seconds time _ 00 __
V_DrawKartString(TX+36, TY+3+jitter, splitflags, va("%d", worktime/10));
V_DrawKartString(TX+48, TY+3-jitter, splitflags, va("%d", worktime%10));
V_DrawTimerString(TX+36, TY+3+jitter, splitflags, va("%d", worktime/10));
V_DrawTimerString(TX+48, TY+3-jitter, splitflags, va("%d", worktime%10));
// quotation mark location _ __"__
V_DrawKartString(TX+60, TY+3, splitflags, va("\""));
V_DrawTimerString(TX+60, TY+3, splitflags, va("\""));
worktime = G_TicsToCentiseconds(drawtime);
// tics _ __ 00
V_DrawKartString(TX+72, TY+3+jitter, splitflags, va("%d", worktime/10));
V_DrawKartString(TX+84, TY+3-jitter, splitflags, va("%d", worktime%10));
V_DrawTimerString(TX+72, TY+3+jitter, splitflags, va("%d", worktime/10));
V_DrawTimerString(TX+84, TY+3-jitter, splitflags, va("%d", worktime%10));
}
// Medal data!
@ -2322,7 +2322,7 @@ void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, IN
}
else if (tab[i].num != serverplayer || !server_lagless)
{
HU_drawPing(x + ((i < 8) ? -17 : rightoffset + 11), y-4, playerpingtable[tab[i].num], 0, false);
HU_drawPing((x + ((i < 8) ? -17 : rightoffset + 11)) * FRACUNIT, (y-4) * FRACUNIT, playerpingtable[tab[i].num], 0, false);
}
}
@ -2490,7 +2490,7 @@ static void K_drawKartLaps(void)
{
// Laps
V_DrawScaledPatch(LAPS_X, LAPS_Y, V_HUDTRANS|V_SLIDEIN|splitflags, kp_lapsticker);
V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", min(stplyr->laps, numlaps), numlaps));
V_DrawTimerString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", min(stplyr->laps, numlaps), numlaps));
}
}
@ -2986,7 +2986,7 @@ static void K_drawKartBumpersOrKarma(void)
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|V_SLIDEIN|splitflags, kp_capsulestickerwide, NULL);
else
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|V_SLIDEIN|splitflags, kp_capsulesticker, NULL);
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", numtargets, maptargets));
V_DrawTimerString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", numtargets, maptargets));
}
else
{
@ -2998,7 +2998,7 @@ static void K_drawKartBumpersOrKarma(void)
else
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|V_SLIDEIN|splitflags, kp_bumpersticker, colormap);
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", bumpers, maxbumper));
V_DrawTimerString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", bumpers, maxbumper));
}
}
}
@ -4507,7 +4507,7 @@ static void K_drawBattleFullscreen(void)
else
{
V_DrawFixedPatch(x<<FRACBITS, ty<<FRACBITS, scale, 0, kp_timeoutsticker, NULL);
V_DrawKartString(x-txoff, ty, 0, va("%d", stplyr->karmadelay/TICRATE));
V_DrawTimerString(x-txoff, ty, 0, va("%d", stplyr->karmadelay/TICRATE));
}
}
@ -4919,8 +4919,17 @@ void K_drawKartFreePlay(void)
if (((leveltime-lt_endtime) % TICRATE) < TICRATE/2)
return;
V_DrawKartString((BASEVIDWIDTH - (LAPS_X+1)) - 72, // mirror the laps thingy
LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_SPLITSCREEN, "FREE PLAY");
V_DrawStringScaled(
((BASEVIDWIDTH - (LAPS_X+1)) - 72) * FRACUNIT, // mirror the laps thingy
(LAPS_Y+3) * FRACUNIT,
FRACUNIT,
FRACUNIT,
FRACUNIT,
V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_SPLITSCREEN,
NULL,
KART_FONT,
"FREE PLAY"
);
}
static void
@ -4955,11 +4964,16 @@ K_drawMiniPing (void)
}
}
void K_drawButton(fixed_t x, fixed_t y, INT32 flags, patch_t *button[2], boolean pressed)
{
V_DrawFixedPatch(x, y, FRACUNIT, flags, button[pressed], NULL);
}
void K_drawButtonAnim(INT32 x, INT32 y, INT32 flags, patch_t *button[2], tic_t animtic)
{
const UINT8 anim_duration = 16;
const UINT8 anim = (animtic % (anim_duration * 2)) < anim_duration;
V_DrawScaledPatch(x, y, flags, button[anim]);
const boolean anim = ((animtic % (anim_duration * 2)) < anim_duration);
K_drawButton(x << FRACBITS, y << FRACBITS, flags, button, anim);
}
static void K_DrawDirectorButton(INT32 idx, const char *label, patch_t *kp[2], INT32 textflags)
@ -5366,7 +5380,7 @@ void K_drawKartHUD(void)
else
{
INT32 karlen = strlen(countstr)*6; // half of 12
V_DrawKartString((BASEVIDWIDTH/2)-karlen, LAPS_Y+3, V_SPLITSCREEN, countstr);
V_DrawTimerString((BASEVIDWIDTH/2)-karlen, LAPS_Y+3, V_SPLITSCREEN, countstr);
}
}

View file

@ -45,6 +45,7 @@ void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, IN
void K_DrawMapThumbnail(INT32 x, INT32 y, INT32 width, UINT32 flags, UINT16 map, UINT8 *colormap);
void K_DrawLikeMapThumbnail(INT32 x, INT32 y, INT32 width, UINT32 flags, patch_t *patch, UINT8 *colormap);
void K_drawTargetHUD(const vector3_t *origin, player_t *player);
void K_drawButton(fixed_t x, fixed_t y, INT32 flags, patch_t *button[2], boolean pressed);
void K_drawButtonAnim(INT32 x, INT32 y, INT32 flags, patch_t *button[2], tic_t animtic);
extern patch_t *kp_capsuletarget_arrow[2][2];

View file

@ -1701,7 +1701,7 @@ static void M_DrawProfileCard(INT32 x, INT32 y, boolean greyedout, profile_t *p)
if (p != NULL)
{
V_DrawFixedPatch((x+30)*FRACUNIT, (y+84)*FRACUNIT, FRACUNIT, 0, pwrlv, colormap);
V_DrawCenteredKartString(x+30, y+87, 0, va("%d", p->wins));
V_DrawCenteredTimerString(x+30, y+87, 0, va("%d", p->wins));
}
@ -3839,7 +3839,7 @@ void M_DrawItemToggles(void)
V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITMUL", PU_CACHE));
V_DrawScaledPatch(onx-1, ony-2, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[itemOn].mvar1, false), PU_CACHE));
V_DrawScaledPatch(onx+27, ony+39, translucent, W_CachePatchName("K_ITX", PU_CACHE));
V_DrawKartString(onx+37, ony+34, translucent, va("%d", drawnum));
V_DrawTimerString(onx+37, ony+34, translucent, va("%d", drawnum));
}
else
V_DrawScaledPatch(onx-1, ony-2, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[itemOn].mvar1, false), PU_CACHE));
@ -5559,7 +5559,7 @@ challengedesc:
}
V_DrawFixedPatch((8+offs)*FRACUNIT, 5*FRACUNIT, FRACUNIT, 0, key, NULL);
V_DrawKartString((27+offs), 9-challengesmenu.unlockcount[CC_CHAOANIM], 0, va("%u", gamedata->chaokeys));
V_DrawTimerString((27+offs), 9-challengesmenu.unlockcount[CC_CHAOANIM], 0, va("%u", gamedata->chaokeys));
offs = challengekeybarwidth;
if (gamedata->chaokeys < GDMAX_CHAOKEYS)
@ -5577,7 +5577,7 @@ challengedesc:
challengesmenu.unlockcount[CC_UNLOCKED] + challengesmenu.unlockcount[CC_TALLY],
challengesmenu.unlockcount[CC_TOTAL]
);
V_DrawRightAlignedKartString(BASEVIDWIDTH-7, 9-challengesmenu.unlockcount[CC_ANIM], 0, str);
V_DrawRightAlignedTimerString(BASEVIDWIDTH-7, 9-challengesmenu.unlockcount[CC_ANIM], 0, str);
}
// Name bar

1119
src/k_zvote.c Normal file

File diff suppressed because it is too large Load diff

279
src/k_zvote.h Normal file
View file

@ -0,0 +1,279 @@
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) by Sally "TehRealSalt" Cochenour
// Copyright (C) by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file k_zvote.h
/// \brief Player callable mid-game vote
#ifndef __K_ZVOTE__
#define __K_ZVOTE__
#include "doomdef.h"
#include "doomstat.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ZVOTE_GUI_CONFIRM (TICRATE)
#define ZVOTE_GUI_SUCCESS (3 * TICRATE)
#define ZVOTE_GUI_SLIDE (TICRATE / 2)
typedef enum
{
MVT_KICK, // Kick another player in the server
MVT_RTV, // Exit level early
MVT__MAX, // Total number of vote types
} midVoteType_e;
extern const char *g_midVoteTypeNames[MVT__MAX];
struct midVoteGUI_t
{
tic_t slide; // Slide in when Z is first pressed.
tic_t confirm; // How long this player has held Z.
boolean unpress; // Z button needs unpressed to continue accepting input.
};
struct midVote_t
{
boolean active; // If true, a vote is currently running.
player_t *caller; // The player that called for this vote.
player_t *victim; // If non-NULL, then this vote targets a player (kicks), don't let them vote on it.
boolean votes[MAXPLAYERS]; // Votes recieved from each player.
midVoteType_e type; // Type of vote that was called, see midVoteType_e.
INT32 variable; // Extra variable, unique purpose for each vote type.
tic_t time; // Time until the vote times out and fails.
tic_t delay; // Delay before another vote is allowed to be called.
tic_t end; // Ended animation, wait a second before activating callback.
UINT8 endVotes; // How many votes it got when the vote went through.
UINT8 endRequired; // How many votes were required when the vote went through.
midVoteGUI_t gui[MAXSPLITSCREENPLAYERS]; // GUI / inputs struct
};
extern midVote_t g_midVote;
/*--------------------------------------------------
void K_RegisterMidVoteCVars(void);
Registers the console variables related to
the Z-voting systems.
--------------------------------------------------*/
void K_RegisterMidVoteCVars(void);
/*--------------------------------------------------
void K_ResetMidVote(void);
Resets Z-voting variables to their default state.
--------------------------------------------------*/
void K_ResetMidVote(void);
/*--------------------------------------------------
boolean K_AnyMidVotesAllowed(void);
Determines if the server has enabled any types
of Z-votes. If this is false, then any menu options
for Z-voting should be disabled.
Input Arguments:-
N/A
Return:-
true if any vote types are enabled, otherwise false.
--------------------------------------------------*/
boolean K_AnyMidVotesAllowed(void);
/*--------------------------------------------------
boolean K_PlayerIDAllowedInMidVote(const UINT8 id);
Determines if this player ID is allowed to
vote or not.
Input Arguments:-
id - Player index to check.
Return:-
true if the player index can vote, otherwise false.
--------------------------------------------------*/
boolean K_PlayerIDAllowedInMidVote(const UINT8 id);
/*--------------------------------------------------
UINT8 K_RequiredMidVotes(void);
Calculates the number of votes needed for thr
vote to go through (aka, the "quorum"), as
per the server's settings. Usually at least
2 players are required for the vote to go through.
Input Arguments:-
N/A
Return:-
Number of player votes needed before we should
call K_MidVoteSuccess.
--------------------------------------------------*/
UINT8 K_RequiredMidVotes(void);
/*--------------------------------------------------
boolean K_PlayerIDMidVoted(const UINT8 id);
Determines if this player ID has voted for
the current issue or not. Is mostly safety
checks for g_midVote.votes[id], to force
the player who called the vote to vote for it,
the victim being affected to vote against,
and invalid players not having a vote.
Input Arguments:-
id - Player index to check.
Return:-
true if the player index voted yes, otherwise false.
--------------------------------------------------*/
boolean K_PlayerIDMidVoted(const UINT8 id);
/*--------------------------------------------------
UINT8 K_CountMidVotes(void);
Counts the total number of votes in favor of
the current issue.
Input Arguments:-
N/A
Return:-
Number of votes that agree.
--------------------------------------------------*/
UINT8 K_CountMidVotes(void);
/*--------------------------------------------------
boolean K_AllowNewMidVote(player_t *caller, midVoteType_e type, INT32 variable, player_t *victim);
Returns if the variables given are a valid state for
K_InitNewMidVote. Creates console alerts if it's not.
Input Arguments:-
caller - The player that is trying to call for a vote.
type - The type of vote they're trying to call.
variable - Extra arguments for the vote type.
victim - If this is a vote that negatively affects a
player, the player being affected would go here.
Return:-
true if we can start a new vote, otherwise false.
--------------------------------------------------*/
boolean K_AllowNewMidVote(player_t *caller, midVoteType_e type, INT32 variable, player_t *victim);
/*--------------------------------------------------
void K_InitNewMidVote(player_t *caller, midVoteType_e type, INT32 variable, player_t *victim);
Tries to start a new Z-vote, or mid-game vote. This will
handle everything needed to be initialized. Also calls
K_AllowNewMidVote to prevent invalid states from happening.
Input Arguments:-
caller - The player that is trying to call for a vote.
type - The type of vote they're trying to call.
variable - Extra arguments for the vote type.
victim - If this is a vote that negatively affects a
player, the player being affected would go here.
Return:-
N/A
--------------------------------------------------*/
void K_InitNewMidVote(player_t *caller, midVoteType_e type, INT32 variable, player_t *victim);
/*--------------------------------------------------
void K_MidVoteFinalize(fixed_t delayMul);
Ran when a vote is totally done, and we need to
reset the struct and set the delay timer.
--------------------------------------------------*/
void K_MidVoteFinalize(fixed_t delayMul);
/*--------------------------------------------------
void K_MidVoteSuccess(void);
Ran whenever a vote meets the quorum, activates
the effect that the current vote is intended to
have.
--------------------------------------------------*/
void K_MidVoteSuccess(void);
/*--------------------------------------------------
void K_MidVoteFailure(void);
Ran when a vote times out without meeting the quorum.
Doesn't do anything but set a very long delay before
accepting another vote.
--------------------------------------------------*/
void K_MidVoteFailure(void);
/*--------------------------------------------------
void K_TickMidVote(void);
Run every game tick when in a server to process
the vote in progress, if it exists.
--------------------------------------------------*/
void K_TickMidVote(void);
/*--------------------------------------------------
void K_UpdateMidVotePatches(void);
Caches the patches needed for drawing the
HUD elements for Z-voting.
--------------------------------------------------*/
void K_UpdateMidVotePatches(void);
/*--------------------------------------------------
void K_DrawMidVote(void);
Handles drawing the HUD elements for Z-voting.
--------------------------------------------------*/
void K_DrawMidVote(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // __K_ZVOTE__

View file

@ -807,8 +807,8 @@ static int libd_drawPingNum(lua_State *L)
UINT8 *colormap = NULL;
huddrawlist_h list;
HUDONLY
x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2);
x = luaL_checkfixed(L, 1);
y = luaL_checkfixed(L, 2);
num = luaL_checkinteger(L, 3);
flags = luaL_optinteger(L, 4, 0);
flags &= ~V_PARAMMASK; // Don't let crashes happen.
@ -984,7 +984,7 @@ static int libd_drawKartString(lua_State *L)
if (LUA_HUD_IsDrawListValid(list))
LUA_HUD_AddDrawKartString(list, x, y, str, flags);
else
V_DrawKartString(x, y, flags, str);
V_DrawTimerString(x, y, flags, str);
return 0;
}

View file

@ -468,7 +468,7 @@ void LUA_HUD_DrawList(huddrawlist_h list)
V_DrawTitleCardString(item->x, item->y, itemstr, item->flags, item->bossmode, item->timer, item->threshold);
break;
case DI_DrawKartString:
V_DrawKartString(item->x, item->y, item->flags, itemstr);
V_DrawTimerString(item->x, item->y, item->flags, itemstr);
break;
default:
I_Error("can't draw draw list item: invalid draw list item type");

View file

@ -44,6 +44,7 @@
#include "acs/interface.h"
#include "g_party.h"
#include "k_vote.h"
#include "k_zvote.h"
savedata_t savedata;
@ -53,6 +54,7 @@ savedata_t savedata;
#define ARCHIVEBLOCK_PLAYERS 0x7F448008
#define ARCHIVEBLOCK_PARTIES 0x7F87AF0C
#define ARCHIVEBLOCK_ROUNDQUEUE 0x7F721331
#define ARCHIVEBLOCK_ZVOTE 0x7F54FF0D
#define ARCHIVEBLOCK_WORLD 0x7F8C08C0
#define ARCHIVEBLOCK_POBJS 0x7F928546
#define ARCHIVEBLOCK_THINKERS 0x7F37037C
@ -985,6 +987,87 @@ static void P_NetUnArchiveRoundQueue(savebuffer_t *save)
}
}
static void P_NetArchiveZVote(savebuffer_t *save)
{
INT32 i;
WRITEUINT32(save->p, ARCHIVEBLOCK_ZVOTE);
WRITEUINT8(save->p, g_midVote.active);
if (g_midVote.active == true)
{
WRITEUINT8(
save->p,
(g_midVote.caller != NULL) ? (g_midVote.caller - players) : UINT8_MAX
);
WRITEUINT8(
save->p,
(g_midVote.victim != NULL) ? (g_midVote.victim - players) : UINT8_MAX
);
for (i = 0; i < MAXPLAYERS; i++)
{
WRITEUINT8(save->p, g_midVote.votes[i]);
}
WRITEUINT8(save->p, g_midVote.type);
WRITEINT32(save->p, g_midVote.variable);
WRITEUINT32(save->p, g_midVote.time);
WRITEUINT32(save->p, g_midVote.end);
WRITEUINT8(save->p, g_midVote.endVotes);
WRITEUINT8(save->p, g_midVote.endRequired);
}
WRITEUINT32(save->p, g_midVote.delay);
}
static void P_NetUnArchiveZVote(savebuffer_t *save)
{
INT32 i;
if (READUINT32(save->p) != ARCHIVEBLOCK_ZVOTE)
{
I_Error("Bad $$$.sav at archive block Z-Vote");
}
K_ResetMidVote();
g_midVote.active = (boolean)READUINT8(save->p);
if (g_midVote.active == true)
{
UINT8 callerID = READUINT8(save->p);
UINT8 victimID = READUINT8(save->p);
if (callerID < MAXPLAYERS)
{
g_midVote.caller = &players[callerID];
}
if (victimID < MAXPLAYERS)
{
g_midVote.victim = &players[victimID];
}
for (i = 0; i < MAXPLAYERS; i++)
{
g_midVote.votes[i] = (boolean)READUINT8(save->p);
}
g_midVote.type = READUINT8(save->p);
g_midVote.variable = READINT32(save->p);
g_midVote.time = (tic_t)READUINT32(save->p);
g_midVote.end = (tic_t)READUINT32(save->p);
g_midVote.endVotes = READUINT8(save->p);
g_midVote.endRequired = READUINT8(save->p);
}
g_midVote.delay = (tic_t)READUINT32(save->p);
}
///
/// Colormaps
///
@ -5463,6 +5546,7 @@ void P_SaveNetGame(savebuffer_t *save, boolean resending)
P_NetArchivePlayers(save);
P_NetArchiveParties(save);
P_NetArchiveRoundQueue(save);
P_NetArchiveZVote(save);
if (gamestate == GS_LEVEL)
{
@ -5514,6 +5598,7 @@ boolean P_LoadNetGame(savebuffer_t *save, boolean reloading)
P_NetUnArchivePlayers(save);
P_NetUnArchiveParties(save);
P_NetUnArchiveRoundQueue(save);
P_NetUnArchiveZVote(save);
if (gamestate == GS_LEVEL)
{

View file

@ -637,7 +637,7 @@ void SCR_DisplayTicRate(void)
}
// draw total frame:
V_DrawPingNum(x, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT, cap, ticcntcolor);
V_DrawPingNum(x<<FRACBITS, 190<<FRACBITS, V_SNAPTOBOTTOM|V_SNAPTORIGHT, cap, ticcntcolor);
x -= digits * 4;
// draw "/"
@ -645,7 +645,7 @@ void SCR_DisplayTicRate(void)
}
// draw our actual framerate
V_DrawPingNum(x, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT, fps, ticcntcolor);
V_DrawPingNum(x<<FRACBITS, 190<<FRACBITS, V_SNAPTOBOTTOM|V_SNAPTORIGHT, fps, ticcntcolor);
}
// SCR_DisplayLocalPing
@ -660,7 +660,7 @@ void SCR_DisplayLocalPing(void)
{
INT32 dispy = cv_ticrate.value ? 160 : 181;
offline = (consoleplayer == serverplayer);
HU_drawPing(307, dispy, ping, V_SNAPTORIGHT | V_SNAPTOBOTTOM | V_HUDTRANS, offline);
HU_drawPing(307 * FRACUNIT, dispy * FRACUNIT, ping, V_SNAPTORIGHT | V_SNAPTOBOTTOM | V_HUDTRANS, offline);
}
}

View file

@ -31,15 +31,9 @@
#include "m_misc.h" // moviemode
#include "m_anigif.h" // cv_gif_downscale
#include "p_setup.h" // NiGHTS grading
#include "k_grandprix.h" // we need to know grandprix status for titlecards
#include "k_boss.h"
#include "r_fps.h"
//random index
#include "m_random.h"
// item finder
#include "m_cond.h"
#include "m_random.h" // random index
#include "m_cond.h" // item finder
#ifdef HWRENDER
#include "hardware/hw_main.h"
@ -53,8 +47,9 @@
#include "k_hud.h" // SRB2kart
#include "v_video.h"
#include "r_skins.h" // NUMFACES
#include "r_fps.h"
#include "k_grandprix.h" // we need to know grandprix status for titlecards
#include "k_boss.h"
#include "k_zvote.h"
UINT16 objectsdrawn = 0;
@ -164,6 +159,7 @@ void ST_LoadGraphics(void)
// first anyway
// cache the status bar overlay icons (fullscreen mode)
K_LoadKartHUDGraphics();
K_UpdateMidVotePatches();
// Midnight Channel:
HU_UpdatePatch(&hud_tv1, "HUD_TV1");
@ -1242,6 +1238,8 @@ static void ST_overlayDrawer(void)
}
}
}
K_DrawMidVote();
}
void ST_DrawDemoTitleEntry(void)

View file

@ -212,6 +212,10 @@ TYPEDEF (waypoint_t);
// k_rank.h
TYPEDEF (gpRank_t);
// k_zvote.h
TYPEDEF (midVote_t);
TYPEDEF (midVoteGUI_t);
// lua_hudlib_drawlist.h
typedef struct huddrawlist_s *huddrawlist_h;

View file

@ -2264,7 +2264,7 @@ void V_DrawStringScaled(
spacew = 16;
break;
case KART_FONT:
spacew = 12;
spacew = 3;
switch (spacing)
{
case V_MONOSPACE:
@ -2287,6 +2287,12 @@ void V_DrawStringScaled(
case LSLOW_FONT:
spacew = 16;
break;
case OPPRF_FONT:
spacew = 5;
break;
case PINGF_FONT:
spacew = 3;
break;
}
switch (fontno)
@ -2311,6 +2317,10 @@ void V_DrawStringScaled(
case LSLOW_FONT:
lfh = 38;
break;
case OPPRF_FONT:
case PINGF_FONT:
lfh = 10;
break;
}
hchw = chw >> 1;
@ -2363,6 +2373,12 @@ void V_DrawStringScaled(
else
dim_fn = VariableCharacterDim;
break;
case KART_FONT:
if (chw)
dim_fn = FixedCharacterDim;
else
dim_fn = BunchedCharacterDim;
break;
case TINY_FONT:
if (chw)
dim_fn = FixedCharacterDim;
@ -2394,6 +2410,13 @@ void V_DrawStringScaled(
else
dim_fn = LSTitleCharacterDim;
break;
case OPPRF_FONT:
case PINGF_FONT:
if (chw)
dim_fn = FixedCharacterDim;
else
dim_fn = VariableCharacterDim;
break;
}
cx = x;
@ -2535,7 +2558,7 @@ fixed_t V_StringScaledWidth(
spacew = 16;
break;
case KART_FONT:
spacew = 12;
spacew = 3;
switch (spacing)
{
case V_MONOSPACE:
@ -2556,6 +2579,12 @@ fixed_t V_StringScaledWidth(
case LSLOW_FONT:
spacew = 16;
break;
case OPPRF_FONT:
spacew = 5;
break;
case PINGF_FONT:
spacew = 3;
break;
}
switch (fontno)
@ -2580,6 +2609,10 @@ fixed_t V_StringScaledWidth(
case LSLOW_FONT:
lfh = 38;
break;
case OPPRF_FONT:
case PINGF_FONT:
lfh = 10;
break;
}
hchw = chw >> 1;
@ -2619,6 +2652,12 @@ fixed_t V_StringScaledWidth(
else
dim_fn = VariableCharacterDim;
break;
case KART_FONT:
if (chw)
dim_fn = FixedCharacterDim;
else
dim_fn = BunchedCharacterDim;
break;
case TINY_FONT:
if (chw)
dim_fn = FixedCharacterDim;
@ -2650,6 +2689,13 @@ fixed_t V_StringScaledWidth(
else
dim_fn = LSTitleCharacterDim;
break;
case OPPRF_FONT:
case PINGF_FONT:
if (chw)
dim_fn = FixedCharacterDim;
else
dim_fn = VariableCharacterDim;
break;
}
cx = cy = 0;
@ -2734,37 +2780,36 @@ void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, con
// Draws a number using the PING font thingy.
// TODO: Merge number drawing functions into one with "font name" selection.
INT32 V_DrawPingNum(INT32 x, INT32 y, INT32 flags, INT32 num, const UINT8 *colormap)
fixed_t V_DrawPingNum(fixed_t x, fixed_t y, INT32 flags, INT32 num, const UINT8 *colormap)
{
INT32 w = SHORT(fontv[PINGNUM_FONT].font[0]->width); // this SHOULD always be 5 but I guess custom graphics exist.
if (flags & V_NOSCALESTART)
w *= vid.dupx;
// this SHOULD always be 5 but I guess custom graphics exist.
const fixed_t w = (fontv[PINGNUM_FONT].font[0]->width) * FRACUNIT;
if (num < 0)
num = -num;
// draw the number
do
{
x -= (w-1); // Oni wanted their outline to intersect.
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT, flags, fontv[PINGNUM_FONT].font[num%10], colormap);
num = -num;
}
do // draw the number
{
x -= (w - FRACUNIT); // Oni wanted their outline to intersect.
V_DrawFixedPatch(x, y, FRACUNIT, flags, fontv[PINGNUM_FONT].font[num % 10], colormap);
num /= 10;
} while (num);
} while (num > 0);
return x;
}
void V_DrawCenteredKartString(INT32 x, INT32 y, INT32 option, const char *string)
void V_DrawCenteredTimerString(INT32 x, INT32 y, INT32 option, const char *string)
{
x -= V_KartStringWidth(string, option)/2;
V_DrawKartString(x, y, option, string);
x -= V_TimerStringWidth(string, option)/2;
V_DrawTimerString(x, y, option, string);
}
void V_DrawRightAlignedKartString(INT32 x, INT32 y, INT32 option, const char *string)
void V_DrawRightAlignedTimerString(INT32 x, INT32 y, INT32 option, const char *string)
{
x -= V_KartStringWidth(string, option);
V_DrawKartString(x, y, option, string);
x -= V_TimerStringWidth(string, option);
V_DrawTimerString(x, y, option, string);
}
void V_DrawCenteredGamemodeString(INT32 x, INT32 y, INT32 option, const UINT8 *colormap, const char *string)

View file

@ -353,7 +353,7 @@ void V_DrawPaddedTallNum(INT32 x, INT32 y, INT32 flags, INT32 num, INT32 digits)
// Draw ping numbers. Used by the scoreboard and that one ping option. :P
// This is a separate function because IMO lua should have access to it as well.
INT32 V_DrawPingNum(INT32 x, INT32 y, INT32 flags, INT32 num, const UINT8 *colormap);
fixed_t V_DrawPingNum(fixed_t x, fixed_t y, INT32 flags, INT32 num, const UINT8 *colormap);
void V_DrawProfileNum(INT32 x, INT32 y, INT32 flags, UINT8 num);
@ -364,14 +364,14 @@ void V_DrawProfileNum(INT32 x, INT32 y, INT32 flags, UINT8 num);
V__IntegerStringWidth ( FRACUNIT,0,CRED_FONT,string )
// SRB2Kart
#define V_DrawKartString( x,y,option,string ) \
V__DrawDupxString (x,y,FRACUNIT,option,NULL,KART_FONT,string)
#define V_DrawTimerString( x,y,option,string ) \
V__DrawDupxString (x,y,FRACUNIT,option,NULL,TIMER_FONT,string)
#define V_KartStringWidth( string,option ) \
V__IntegerStringWidth ( FRACUNIT,option,KART_FONT,string )
#define V_TimerStringWidth( string,option ) \
V__IntegerStringWidth ( FRACUNIT,option,TIMER_FONT,string )
void V_DrawCenteredKartString(INT32 x, INT32 y, INT32 option, const char *string);
void V_DrawRightAlignedKartString(INT32 x, INT32 y, INT32 option, const char *string);
void V_DrawCenteredTimerString(INT32 x, INT32 y, INT32 option, const char *string);
void V_DrawRightAlignedTimerString(INT32 x, INT32 y, INT32 option, const char *string);
#define V_DrawGamemodeString( x,y,option,cm,string ) \
V__DrawDupxString (x,y,FRACUNIT,option,cm,GM_FONT,string)