Merge remote-tracking branch 'refs/remotes/origin/master' into sonicitems

# Conflicts:
#	src/k_kart.c

(Also I added some extra music for voting, because I forgot I didn't
commit the merge :V)
This commit is contained in:
TehRealSalt 2018-02-11 12:18:25 -05:00
commit 00d2038d61
27 changed files with 825 additions and 108 deletions

View File

@ -1618,6 +1618,7 @@ void CON_Drawer(void)
if (con_curlines > 0)
CON_DrawConsole();
else if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE || gamestate == GS_CREDITS)
else if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE || gamestate == GS_CREDITS
|| gamestate == GS_VOTING)
CON_DrawHudlines();
}

View File

@ -2073,6 +2073,8 @@ static void CL_ConnectToServer(boolean viams)
if (gamestate == GS_INTERMISSION)
Y_EndIntermission(); // clean up intermission graphics etc
if (gamestate == GS_VOTING)
Y_EndVote();
DEBFILE(va("waiting %d nodes\n", doomcom->numnodes));
G_SetGamestate(GS_WAITINGPLAYERS);
@ -3396,6 +3398,8 @@ void SV_StopServer(void)
if (gamestate == GS_INTERMISSION)
Y_EndIntermission();
if (gamestate == GS_VOTING)
Y_EndVote();
gamestate = wipegamestate = GS_NULL;
localtextcmd[0] = 0;
@ -3514,7 +3518,7 @@ static void HandleConnect(SINT8 node)
#ifdef JOININGAME
if (nodewaiting[node])
{
if ((gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) && newnode)
if ((gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING) && newnode)
{
SV_SendSaveGame(node); // send a complete game state
DEBFILE("send savegame\n");
@ -3726,8 +3730,9 @@ static void HandlePacketFromAwayNode(SINT8 node)
/// \note Wait. What if a Lua script uses some global custom variables synched with the NetVars hook?
/// Shouldn't them be downloaded even at intermission time?
/// Also, according to HandleConnect, the server will send the savegame even during intermission...
if (netbuffer->u.servercfg.gamestate == GS_LEVEL/* ||
netbuffer->u.servercfg.gamestate == GS_INTERMISSION*/)
if (netbuffer->u.servercfg.gamestate == GS_LEVEL
/*|| netbuffer->u.servercfg.gamestate == GS_INTERMISSION
|| netbuffer->u.servercfg.gamestate == GS_VOTING*/)
cl_mode = CL_DOWNLOADSAVEGAME;
else
#endif
@ -4324,7 +4329,7 @@ static INT16 Consistancy(void)
}
// I give up
// Coop desynching enemies is painful
if (!G_PlatformGametype())
if (!G_RaceGametype())
ret += P_GetRandSeed();
#ifdef MOBJCONSISTANCY

View File

@ -301,6 +301,8 @@ static void D_Display(void)
else //if (intertype != int_coop) // Multiplayer
wipedefindex = wipe_multinter_toblack;
}
else if (gamestate == GS_VOTING)
wipedefindex = wipe_multinter_toblack;
if (rendermode != render_none)
{
@ -335,6 +337,12 @@ static void D_Display(void)
HU_Drawer();
break;
case GS_VOTING:
Y_VoteDrawer();
HU_Erase();
HU_Drawer();
break;
case GS_TIMEATTACK:
break;

View File

@ -46,6 +46,7 @@
#include "m_cond.h"
#include "m_anigif.h"
#include "k_kart.h" // SRB2kart
#include "y_inter.h"
#ifdef NETGAME_DEVMODE
#define CV_RESTRICT CV_NETVAR
@ -61,6 +62,9 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum);
static void Got_WeaponPref(UINT8 **cp, INT32 playernum);
static void Got_Mapcmd(UINT8 **cp, INT32 playernum);
static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum);
static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum);
static void Got_ModifyVotecmd(UINT8 **cp, INT32 playernum);
static void Got_PickVotecmd(UINT8 **cp, INT32 playernum);
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum);
#ifdef DELFILE
static void Got_Delfilecmd(UINT8 **cp, INT32 playernum);
@ -367,6 +371,9 @@ consvar_t cv_kartdebugitem = {"kartdebugitem", "0", CV_NETVAR|CV_CHEAT, kartdebu
static CV_PossibleValue_t kartdebugamount_cons_t[] = {{1, "MIN"}, {255, "MAX"}, {0, NULL}};
consvar_t cv_kartdebugamount = {"kartdebugamount", "1", CV_NETVAR|CV_CHEAT, kartdebugamount_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t votetime_cons_t[] = {{10, "MIN"}, {3600, "MAX"}, {0, NULL}};
consvar_t cv_votetime = {"votetime", "20", CV_NETVAR, votetime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t cv_collideminimum_cons_t[] = {{1, "MIN"}, {16384, "MAX"}, {0, NULL}};
consvar_t cv_collideminimum = {"collide_minspeed", "25", CV_NETVAR, cv_collideminimum_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t cv_collidesoundnum_cons_t[] = {{1, "MIN"}, {1208, "MAX"}, {0, NULL}};
@ -434,8 +441,8 @@ consvar_t cv_maxping = {"maxping", "0", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NUL
static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}};
consvar_t cv_inttime = {"inttime", "20", CV_NETVAR, inttime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t advancemap_cons_t[] = {{0, "Off"}, {1, "Next"}, {2, "Random"}, {0, NULL}};
consvar_t cv_advancemap = {"advancemap", "Next", CV_NETVAR, advancemap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t advancemap_cons_t[] = {{0, "Off"}, {1, "Next"}, {2, "Random"}, {3, "Vote"}, {0, NULL}};
consvar_t cv_advancemap = {"advancemap", "Vote", CV_NETVAR, advancemap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t playersforexit_cons_t[] = {{0, "One"}, {1, "All"}, {0, NULL}};
consvar_t cv_playersforexit = {"playersforexit", "One", CV_NETVAR, playersforexit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -475,6 +482,9 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
"SETMOTD",
"SUICIDE",
"DEMOTED",
"SETUPVOTE",
"MODIFYVOTE",
"PICKVOTE",
#ifdef HAVE_BLUA
"LUACMD",
"LUAVAR"
@ -508,6 +518,10 @@ void D_RegisterServerCommands(void)
RegisterNetXCmd(XD_LUACMD, Got_Luacmd);
#endif
RegisterNetXCmd(XD_SETUPVOTE, Got_SetupVotecmd);
RegisterNetXCmd(XD_MODIFYVOTE, Got_ModifyVotecmd);
RegisterNetXCmd(XD_PICKVOTE, Got_PickVotecmd);
// Remote Administration
COM_AddCommand("password", Command_Changepassword_f);
RegisterNetXCmd(XD_LOGIN, Got_Login);
@ -1945,6 +1959,60 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese
}
}
void D_SetupVote(void)
{
XBOXSTATIC char buf[8];
char *p;
INT32 i;
p = buf;
for (i = 0; i < 4; i++)
{
if (i == 3)
WRITEUINT16(p, G_RandMap(G_TOLFlag(gametype), prevmap, true, false));
else
WRITEUINT16(p, G_RandMap(G_TOLFlag(gametype), prevmap, false, false));
}
SendNetXCmd(XD_SETUPVOTE, buf, p - buf);
}
void D_ModifyClientVote(INT8 voted)
{
XBOXSTATIC UINT8 buf[1];
buf[0] = (UINT8)(voted+1);
SendNetXCmd(XD_MODIFYVOTE, &buf, 1);
}
void D_PickVote(void)
{
XBOXSTATIC UINT8 buf[2];
UINT8 temppicks[MAXPLAYERS];
UINT8 templevels[MAXPLAYERS];
UINT8 numvotes = 0, key = 0;
INT32 i;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
if (votes[i] != -1)
{
temppicks[numvotes] = (UINT8)i;
templevels[numvotes] = (UINT8)votes[i];
numvotes++;
}
}
key = M_RandomKey(numvotes);
buf[0] = temppicks[key];
buf[1] = templevels[key];
SendNetXCmd(XD_PICKVOTE, &buf, 2);
}
// Warp to map code.
// Called either from map <mapname> console command, or idclev cheat.
//
@ -2193,7 +2261,7 @@ static void Command_Pause(void)
if (cv_pause.value || server || (IsPlayerAdmin(consoleplayer)))
{
if (modeattacking || !(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION))
if (modeattacking || !(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING))
{
CONS_Printf(M_GetText("You can't pause here.\n"));
return;
@ -2262,13 +2330,13 @@ static void Command_Suicide(void)
WRITEINT32(cp, consoleplayer);
if (!(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION))
if (!(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING))
{
CONS_Printf(M_GetText("You must be in a level to use this.\n"));
return;
}
/*if (!G_PlatformGametype()) // srb2kart: not necessary, suiciding makes you lose a balloon in battle, so it's not desirable to use as a way to escape a hit
/*if (!G_RaceGametype()) // srb2kart: not necessary, suiciding makes you lose a balloon in battle, so it's not desirable to use as a way to escape a hit
{
CONS_Printf(M_GetText("You may only use this in co-op, race, and competition!\n"));
return;
@ -2289,7 +2357,7 @@ static void Got_Suicide(UINT8 **cp, INT32 playernum)
INT32 suicideplayer = READINT32(*cp);
// You can't suicide someone else. Nice try, there.
if (suicideplayer != playernum) // srb2kart: "|| (!G_PlatformGametype())"
if (suicideplayer != playernum) // srb2kart: "|| (!G_RaceGametype())"
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal suicide command received from %s\n"), player_names[playernum]);
if (server)
@ -4021,7 +4089,7 @@ void ItemFinder_OnChange(void)
static void PointLimit_OnChange(void)
{
// Don't allow pointlimit in Single Player/Co-Op/Race!
if (server && Playing() && G_PlatformGametype())
if (server && Playing() && G_RaceGametype())
{
if (cv_pointlimit.value)
CV_StealthSetValue(&cv_pointlimit, 0);
@ -4069,7 +4137,7 @@ UINT32 timelimitintics = 0;
static void TimeLimit_OnChange(void)
{
// Don't allow timelimit in Single Player/Co-Op/Race!
if (server && Playing() && cv_timelimit.value != 0 && G_PlatformGametype())
if (server && Playing() && cv_timelimit.value != 0 && G_RaceGametype())
{
CV_SetValue(&cv_timelimit, 0);
return;
@ -4172,7 +4240,7 @@ void D_GameTypeChanged(INT32 lastgametype)
// reset timelimit and pointlimit in race/coop, prevent stupid cheats
if (server)
{
if (G_PlatformGametype())
if (G_RaceGametype())
{
if (cv_timelimit.value)
CV_SetValue(&cv_timelimit, 0);
@ -4287,7 +4355,7 @@ static void TeamScramble_OnChange(void)
boolean success = false;
// Don't trigger outside level or intermission!
if (!(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION))
if (!(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING))
return;
if (!cv_teamscramble.value)
@ -4505,6 +4573,63 @@ static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum)
G_ExitLevel();
}
static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum)
{
INT32 i;
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal vote setup received from %s\n"), player_names[playernum]);
if (server)
{
XBOXSTATIC UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
return;
}
for (i = 0; i < 4; i++)
{
votelevels[i] = (INT16)READUINT16(*cp);
if (!mapheaderinfo[votelevels[i]])
P_AllocMapHeader(votelevels[i]);
}
G_SetGamestate(GS_VOTING);
Y_StartVote();
}
static void Got_ModifyVotecmd(UINT8 **cp, INT32 playernum)
{
INT8 voted = READUINT8(*cp);
votes[playernum] = (INT8)(voted-1);
}
static void Got_PickVotecmd(UINT8 **cp, INT32 playernum)
{
INT8 pick = READUINT8(*cp);
INT8 level = READUINT8(*cp);
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal vote setup received from %s\n"), player_names[playernum]);
if (server)
{
XBOXSTATIC UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
return;
}
Y_SetupVoteFinish((INT8)pick, (INT8)level);
}
/** Prints the number of the displayplayer.
*
* \todo Possibly remove this; it was useful for debugging at one point.
@ -4630,7 +4755,7 @@ void Command_ExitGame_f(void)
void Command_Retry_f(void)
{
if (!(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION))
if (!(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING))
CONS_Printf(M_GetText("You must be in a level to use this.\n"));
else if (netgame || multiplayer)
CONS_Printf(M_GetText("This only works in single player.\n"));

View File

@ -127,6 +127,8 @@ extern consvar_t cv_kartcomeback;
extern consvar_t cv_kartmirror;
extern consvar_t cv_speedometer;
extern consvar_t cv_votetime;
extern consvar_t cv_collideminimum;
extern consvar_t cv_collidesoundnum;
extern consvar_t cv_collidesounds;
@ -192,9 +194,12 @@ typedef enum
XD_SETMOTD, // 19
XD_SUICIDE, // 20
XD_DEMOTED, // 21
XD_SETUPVOTE, // 22
XD_MODIFYVOTE, // 23
XD_PICKVOTE, // 24
#ifdef HAVE_BLUA
XD_LUACMD, // 22
XD_LUAVAR, // 23
XD_LUACMD, // 25
XD_LUAVAR, // 26
#endif
MAXNETXCMD
} netxcmd_t;
@ -249,6 +254,9 @@ void Command_ExitGame_f(void);
void Command_Retry_f(void);
void D_GameTypeChanged(INT32 lastgametype); // not a real _OnChange function anymore
void D_MapChange(INT32 pmapnum, INT32 pgametype, boolean pultmode, boolean presetplayers, INT32 pdelay, boolean pskipprecutscene, boolean pfromlevelselect);
void D_SetupVote(void);
void D_ModifyClientVote(INT8 voted);
void D_PickVote(void);
void ObjectPlace_OnChange(void);
boolean IsPlayerAdmin(INT32 playernum);
void SetAdminPlayer(INT32 playernum);

View File

@ -323,7 +323,6 @@ typedef enum
k_balloon, // Number of balloons left
k_comebackpoints, // Number of times you've bombed or gave an item to someone; once it's 3 it gets set back to 0 and you're given a balloon
k_comebackmode, // 0 = bomb, 1 = item
k_comebackshowninfo,// Have you already seen the info screen before?
NUMKARTSTUFF
} kartstufftype_t;

View File

@ -7418,8 +7418,7 @@ static const char *const KARTSTUFF_LIST[] = {
"BALLOON",
"COMEBACKPOINTS",
"COMEBACKMODE",
"COMEBACKSHOWNINFO"
"COMEBACKMODE"
};
static const char *const HUDITEMS_LIST[] = {

View File

@ -444,8 +444,14 @@ extern UINT8 gamespeed;
extern boolean franticitems;
extern boolean mirrormode;
extern boolean comeback;
extern tic_t curlap, bestlap;
extern boolean legitimateexit;
extern boolean comebackshowninfo;
extern tic_t curlap, bestlap;
extern INT16 votelevels[4];
extern INT8 votes[MAXPLAYERS];
extern INT8 pickedvote;
extern tic_t hidetime;

View File

@ -72,6 +72,7 @@ static void G_DoCompleted(void);
static void G_DoStartContinue(void);
static void G_DoContinued(void);
static void G_DoWorldDone(void);
static void G_DoStartVote(void);
char mapmusname[7]; // Music name
UINT16 mapmusflags; // Track and reset bit
@ -240,14 +241,23 @@ INT16 scramblecount; //for CTF team scramble
INT32 cheats; //for multiplayer cheat commands
// SRB2Kart
// Cvars that we don't want changed mid-game
UINT8 gamespeed; // Game's current speed (or difficulty, or cc, or etc); 0-2 for relaxed, standard, & turbo
boolean mirrormode; // Mirror Mode currently enabled?
boolean franticitems; // Frantic items currently enabled?
boolean comeback; // Battle Mode's karma comeback is on/off
boolean legitimateexit; // Did this client actually finish the match? Calculated locally
tic_t curlap; // Current lap time, calculated locally
tic_t bestlap; // Best lap time, locally
// Voting system
INT16 votelevels[4]; // Levels that were rolled by the host
INT8 votes[MAXPLAYERS]; // Each player's vote
INT8 pickedvote; // What vote the host rolls
// Client-sided variables (NEVER use in anything that needs to be synced with other players)
boolean legitimateexit; // Did this client actually finish the match?
boolean comebackshowninfo; // Have you already seen the "ATTACK OR PROTECT" message?
tic_t curlap; // Current lap time
tic_t bestlap; // Best lap time
static INT16 randmapbuffer[NUMMAPS]; // Buffer for maps RandMap is allowed to roll
tic_t hidetime;
@ -406,18 +416,6 @@ consvar_t cv_useranalog3 = {"useranalog3", "Off", CV_SAVE|CV_CALL, CV_OnOff, Use
consvar_t cv_useranalog4 = {"useranalog4", "Off", CV_SAVE|CV_CALL, CV_OnOff, UserAnalog4_OnChange, 0, NULL, NULL, 0, 0, NULL};
#endif
typedef enum
{
AXISNONE = 0,
AXISTURN,
AXISMOVE,
AXISLOOK,
AXISSTRAFE,
AXISDEAD, //Axises that don't want deadzones
AXISFIRE,
AXISFIRENORMAL,
} axis_input_e;
#if defined (_WII) || defined (WMINPUT)
consvar_t cv_turnaxis = {"joyaxis_turn", "LStick.X", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_moveaxis = {"joyaxis_move", "LStick.Y", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -1141,7 +1139,7 @@ static INT32 Joy4Axis(axis_input_e axissel)
return retaxis;
}
static boolean InputDown(INT32 gc, UINT8 p)
boolean InputDown(INT32 gc, UINT8 p)
{
switch (p)
{
@ -1156,7 +1154,7 @@ static boolean InputDown(INT32 gc, UINT8 p)
}
}
static INT32 JoyAxis(axis_input_e axissel, UINT8 p)
INT32 JoyAxis(axis_input_e axissel, UINT8 p)
{
switch (p)
{
@ -1751,6 +1749,8 @@ void G_DoLoadLevel(boolean resetplayer)
if (gamestate == GS_INTERMISSION)
Y_EndIntermission();
if (gamestate == GS_VOTING)
Y_EndVote();
G_SetGamestate(GS_LEVEL);
@ -1857,7 +1857,7 @@ boolean G_Responder(event_t *ev)
&& (players[consoleplayer].pflags & PF_TAGIT) != (players[displayplayer].pflags & PF_TAGIT))
continue;
}
else if (G_GametypeHasSpectators() && G_RingSlingerGametype())
else if (G_GametypeHasSpectators() && G_BattleGametype())
{
if (!players[consoleplayer].spectator)
continue;
@ -1957,7 +1957,7 @@ boolean G_Responder(event_t *ev)
else if (gamestate == GS_GAMEEND || gamestate == GS_EVALUATION || gamestate == GS_CREDITS)
return true;
else if (gamestate == GS_INTERMISSION)
else if (gamestate == GS_INTERMISSION || gamestate == GS_VOTING)
if (HU_Responder(ev))
return true; // chat ate the event
@ -2122,6 +2122,7 @@ void G_Ticker(boolean run)
case ga_startcont: G_DoStartContinue(); break;
case ga_continued: G_DoContinued(); break;
case ga_worlddone: G_DoWorldDone(); break;
case ga_startvote: G_DoStartVote(); break;
case ga_nothing: break;
default: I_Error("gameaction = %d\n", gameaction);
}
@ -2167,6 +2168,12 @@ void G_Ticker(boolean run)
HU_Ticker();
break;
case GS_VOTING:
if (run)
Y_VoteTicker();
HU_Ticker();
break;
case GS_TIMEATTACK:
break;
@ -2341,7 +2348,6 @@ void G_PlayerReborn(INT32 player)
INT32 offroad;
INT32 balloon;
INT32 comebackpoints;
INT32 comebackshowninfo;
score = players[player].score;
lives = players[player].lives;
@ -2399,7 +2405,6 @@ void G_PlayerReborn(INT32 player)
offroad = players[player].kartstuff[k_offroad];
balloon = players[player].kartstuff[k_balloon];
comebackpoints = players[player].kartstuff[k_comebackpoints];
comebackshowninfo = players[player].kartstuff[k_comebackshowninfo];
p = &players[player];
memset(p, 0, sizeof (*p));
@ -2459,7 +2464,6 @@ void G_PlayerReborn(INT32 player)
p->kartstuff[k_balloon] = balloon;
p->kartstuff[k_comebackpoints] = comebackpoints;
p->kartstuff[k_comebackshowninfo] = comebackshowninfo;
p->kartstuff[k_comebacktimer] = comebacktime;
// Don't do anything immediately
@ -2971,9 +2975,10 @@ void G_ExitLevel(void)
//
boolean G_IsSpecialStage(INT32 mapnum)
{
#if 0
if (gametype == GT_COOP && modeattacking != ATTACKING_RECORD && mapnum >= sstage_start && mapnum <= sstage_end)
return true;
#endif
return false;
}
@ -2985,13 +2990,18 @@ boolean G_IsSpecialStage(INT32 mapnum)
//
boolean G_GametypeUsesLives(void)
{
// Coop, Competitive
// SRB2kart NEEDS no lives
#if 0
// Coop, Competitive
if ((gametype == GT_COOP || gametype == GT_COMPETITION)
&& !modeattacking // No lives in Time Attack
//&& !G_IsSpecialStage(gamemap)
&& !(maptol & TOL_NIGHTS)) // No lives in NiGHTS
return true;
return false;
#else
return false;
#endif
}
//
@ -3022,30 +3032,30 @@ boolean G_GametypeHasSpectators(void)
}
//
// G_RingSlingerGametype
// G_BattleGametype
//
// Returns true if the current gametype supports firing rings.
// ANY gametype can be a ringslinger gametype, just flick a switch.
// Returns true in Battle gamemodes, previously was G_RingSlingerGametype.
//
boolean G_RingSlingerGametype(void)
boolean G_BattleGametype(void)
{
return ((gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE) || (cv_ringslinger.value));
return (gametype == GT_MATCH);
}
//
// G_PlatformGametype
// G_RaceGametype
//
// Returns true if a gametype is a more traditional platforming-type.
// Returns true in racing gamemodes, previously was G_PlatformGametype.
//
boolean G_PlatformGametype(void)
boolean G_RaceGametype(void)
{
return (gametype == GT_COOP || gametype == GT_RACE || gametype == GT_COMPETITION);
return (gametype == GT_RACE); //(gametype == GT_COOP || gametype == GT_RACE || gametype == GT_COMPETITION);
}
//
// G_TagGametype
//
// For Jazz's Tag/HnS modes that have a lot of special cases..
// For Jazz's Tag/HnS modes that have a lot of special cases...
// SRB2Kart: do we actually want to add Kart tag later? :V
//
boolean G_TagGametype(void)
{
@ -3074,6 +3084,24 @@ INT16 G_TOLFlag(INT32 pgametype)
return INT16_MAX;
}
static INT32 TOLMaps(INT16 tolflags)
{
INT32 num = 0;
INT16 i;
// Find all the maps that are ok and and put them in an array.
for (i = 0; i < NUMMAPS; i++)
{
if (!mapheaderinfo[i])
continue;
if ((mapheaderinfo[i]->typeoflevel & tolflags) == tolflags)
num++;
}
return num;
}
/** Select a random map with the given typeoflevel flags.
* If no map has those flags, this arbitrarily gives you map 1.
* \param tolflags The typeoflevel flags to insist on. Other bits may
@ -3082,24 +3110,59 @@ INT16 G_TOLFlag(INT32 pgametype)
* has those flags.
* \author Graue <graue@oceanbase.org>
*/
static INT16 RandMap(INT16 tolflags, INT16 pprevmap)
INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean dontadd, boolean ignorebuffer)
{
INT16 *okmaps = Z_Malloc(NUMMAPS * sizeof(INT16), PU_STATIC, NULL);
INT32 numokmaps = 0;
INT16 ix;
INT16 ix, bufx;
// Find all the maps that are ok and and put them in an array.
for (ix = 0; ix < NUMMAPS; ix++)
if (mapheaderinfo[ix] && (mapheaderinfo[ix]->typeoflevel & tolflags) == tolflags
&& ix != pprevmap // Don't pick the same map.
&& (dedicated || !M_MapLocked(ix+1)) // Don't pick locked maps.
)
{
boolean isokmap = true;
if (!mapheaderinfo[ix])
continue;
if ((mapheaderinfo[ix]->typeoflevel & tolflags) != tolflags
|| ix == pprevmap
|| (M_MapLocked(ix+1) && !dedicated))
isokmap = false;
if (!ignorebuffer)
{
for (bufx = 0; bufx < NUMMAPS; bufx++)
{
if (randmapbuffer[bufx] == -1) // Rest of buffer SHOULD be empty
break;
if (ix == randmapbuffer[bufx])
{
isokmap = false;
break;
}
}
}
if (isokmap)
okmaps[numokmaps++] = ix;
}
if (numokmaps == 0)
{
if (!ignorebuffer)
return G_RandMap(tolflags, pprevmap, dontadd, true); // If there's no matches, (An incredibly silly function chain, buuut... :V)
ix = 0; // Sorry, none match. You get MAP01.
for (bufx = 0; bufx < NUMMAPS; bufx++)
randmapbuffer[bufx] = -1; // if we're having trouble finding a map we should probably clear it
}
else
{
ix = okmaps[M_RandomKey(numokmaps)];
for (bufx = NUMMAPS; bufx > 0; bufx--)
randmapbuffer[bufx] = randmapbuffer[bufx-1];
randmapbuffer[0] = ix;
}
Z_Free(okmaps);
@ -3226,12 +3289,18 @@ static void G_DoCompleted(void)
automapactive = false;
if (randmapbuffer[TOLMaps(G_TOLFlag(gametype))-4] != -1) // we're getting pretty full, so lets clear it
{
for (i = 0; i < NUMMAPS; i++)
randmapbuffer[i] = -1;
}
if (gametype != GT_COOP)
{
if (cv_advancemap.value == 0) // Stay on same map.
nextmap = prevmap;
else if (cv_advancemap.value == 2) // Go to random map.
nextmap = RandMap(G_TOLFlag(gametype), prevmap);
nextmap = G_RandMap(G_TOLFlag(gametype), prevmap, false, false);
}
// We are committed to this map now.
@ -3252,6 +3321,7 @@ static void G_DoCompleted(void)
void G_AfterIntermission(void)
{
HU_ClearCEcho();
//G_NextLevel();
if (mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking) // Start a custom cutscene.
F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false);
@ -3272,7 +3342,11 @@ void G_AfterIntermission(void)
//
void G_NextLevel(void)
{
gameaction = ga_worlddone;
if ((cv_advancemap.value == 3 && gamestate != GS_VOTING)
&& !modeattacking && !skipstats && (multiplayer || netgame))
gameaction = ga_startvote;
else
gameaction = ga_worlddone;
}
static void G_DoWorldDone(void)
@ -3290,6 +3364,16 @@ static void G_DoWorldDone(void)
gameaction = ga_nothing;
}
//
// G_DoStartVote
//
static void G_DoStartVote(void)
{
if (server)
D_SetupVote();
gameaction = ga_nothing;
}
//
// G_UseContinue
//
@ -3904,6 +3988,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
ultimatemode = false;
legitimateexit = false; // SRB2Kart
comebackshowninfo = false;
if (!demoplayback && !netgame) // Netgame sets random seed elsewhere, demo playback sets seed just before us!
P_SetRandSeed(M_RandomizedSeed()); // Use a more "Random" random seed
@ -5878,6 +5963,8 @@ void G_StopDemo(void)
if (gamestate == GS_INTERMISSION)
Y_EndIntermission(); // cleanup
if (gamestate == GS_VOTING)
Y_EndVote();
G_SetGamestate(GS_NULL);
wipegamestate = GS_NULL;

View File

@ -62,6 +62,18 @@ extern consvar_t cv_sideaxis3,cv_turnaxis3,cv_moveaxis3,cv_lookaxis3,cv_fireaxis
extern consvar_t cv_sideaxis4,cv_turnaxis4,cv_moveaxis4,cv_lookaxis4,cv_fireaxis4,cv_firenaxis4;
extern consvar_t cv_ghost_besttime, cv_ghost_bestlap, cv_ghost_last, cv_ghost_guest, cv_ghost_staff;
typedef enum
{
AXISNONE = 0,
AXISTURN,
AXISMOVE,
AXISLOOK,
AXISSTRAFE,
AXISDEAD, //Axises that don't want deadzones
AXISFIRE,
AXISFIRENORMAL,
} axis_input_e;
// mouseaiming (looking up/down with the mouse or keyboard)
#define KB_LOOKSPEED (1<<25)
#define MAXPLMOVE (50)
@ -80,6 +92,9 @@ ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n);
INT16 G_ClipAimingPitch(INT32 *aiming);
INT16 G_SoftwareClipAimingPitch(INT32 *aiming);
boolean InputDown(INT32 gc, UINT8 p);
INT32 JoyAxis(axis_input_e axissel, UINT8 p);
extern angle_t localangle, localangle2, localangle3, localangle4;
extern INT32 localaiming, localaiming2, localaiming3, localaiming4; // should be an angle_t but signed
extern boolean camspin, camspin2, camspin3, camspin4; // SRB2Kart
@ -166,8 +181,8 @@ boolean G_IsSpecialStage(INT32 mapnum);
boolean G_GametypeUsesLives(void);
boolean G_GametypeHasTeams(void);
boolean G_GametypeHasSpectators(void);
boolean G_RingSlingerGametype(void);
boolean G_PlatformGametype(void);
boolean G_BattleGametype(void);
boolean G_RaceGametype(void);
boolean G_TagGametype(void);
void G_ExitLevel(void);
void G_NextLevel(void);
@ -220,4 +235,6 @@ FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics);
// Don't split up TOL handling
INT16 G_TOLFlag(INT32 pgametype);
INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean dontadd, boolean ignorebuffer);
#endif

View File

@ -23,6 +23,7 @@ typedef enum
// Fadable gamestates
GS_LEVEL, // Playing, in a level.
GS_INTERMISSION, // Gazing at the intermission screen.
GS_VOTING, // SRB2Kart: MP voting screen
GS_CONTINUING, // continue screen
GS_TITLESCREEN, // title screen
@ -47,6 +48,7 @@ typedef enum
ga_worlddone,
ga_startcont,
ga_continued,
ga_startvote,
} gameaction_t;
extern gamestate_t gamestate;

View File

@ -1186,7 +1186,8 @@ void HU_Drawer(void)
if (!Playing()
|| gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE
|| gamestate == GS_CREDITS || gamestate == GS_EVALUATION
|| gamestate == GS_GAMEEND)
|| gamestate == GS_GAMEEND
|| gamestate == GS_VOTING) // SRB2kart
return;
// draw multiplayer rankings

View File

@ -323,6 +323,7 @@ void K_RegisterKartStuff(void)
CV_RegisterVar(&cv_kartcomeback);
CV_RegisterVar(&cv_kartmirror);
CV_RegisterVar(&cv_speedometer);
CV_RegisterVar(&cv_votetime);
CV_RegisterVar(&cv_collideminimum);
CV_RegisterVar(&cv_collidesoundnum);
@ -1080,8 +1081,8 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
else if (player->kartstuff[k_comebacktimer])
{
player->kartstuff[k_comebacktimer]--;
if (player->kartstuff[k_balloon] <= 0 && player->kartstuff[k_comebacktimer] <= 0)
player->kartstuff[k_comebackshowninfo] = 1;
if (player == &players[consoleplayer] && player->kartstuff[k_balloon] <= 0 && player->kartstuff[k_comebacktimer] <= 0)
comebackshowninfo = true; // client has already seen the message
}
if (player->kartstuff[k_spinout] == 0 && player->kartstuff[k_spinouttimer] == 0 && player->powers[pw_flashing] == K_GetKartFlashing())
@ -4469,7 +4470,7 @@ static void K_drawBattleFullscreen(void)
ty += (BASEVIDHEIGHT/2);
}
if (!stplyr->kartstuff[k_comebackshowninfo])
if (!comebackshowninfo)
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, scale, 0, kp_battleinfo, NULL);
else
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, scale, 0, kp_battlewait, NULL);

View File

@ -1920,17 +1920,17 @@ static int lib_gGametypeHasSpectators(lua_State *L)
return 1;
}
static int lib_gRingSlingerGametype(lua_State *L)
static int lib_gBattleGametype(lua_State *L)
{
//HUDSAFE
lua_pushboolean(L, G_RingSlingerGametype());
lua_pushboolean(L, G_BattleGametype());
return 1;
}
static int lib_gPlatformGametype(lua_State *L)
static int lib_gRaceGametype(lua_State *L)
{
//HUDSAFE
lua_pushboolean(L, G_PlatformGametype());
lua_pushboolean(L, G_RaceGametype());
return 1;
}
@ -2328,8 +2328,8 @@ static luaL_Reg lib[] = {
{"G_GametypeUsesLives",lib_gGametypeUsesLives},
{"G_GametypeHasTeams",lib_gGametypeHasTeams},
{"G_GametypeHasSpectators",lib_gGametypeHasSpectators},
{"G_RingSlingerGametype",lib_gRingSlingerGametype},
{"G_PlatformGametype",lib_gPlatformGametype},
{"G_BattleGametype",lib_gBattleGametype},
{"G_RaceGametype",lib_gRaceGametype},
{"G_TagGametype",lib_gTagGametype},
{"G_TicsToHours",lib_gTicsToHours},
{"G_TicsToMinutes",lib_gTicsToMinutes},

View File

@ -159,7 +159,7 @@ void COM_Lua_f(void)
return;
}
// Do the command locally, NetXCmds don't go through outside of GS_LEVEL || GS_INTERMISSION
// Do the command locally, NetXCmds don't go through outside of GS_LEVEL || GS_INTERMISSION || GS_VOTING
lua_rawgeti(gL, -1, 1); // push function from command info table
I_Assert(lua_isfunction(gL, -1));
lua_remove(gL, -2); // pop command info table

View File

@ -3339,7 +3339,7 @@ static void M_DrawGenericMenu(void)
static void M_DrawPauseMenu(void)
{
if (!netgame && !multiplayer && (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION))
if (!netgame && !multiplayer && (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING))
{
emblem_t *emblem_detail[3] = {NULL, NULL, NULL};
char emblem_text[3][20];
@ -3350,10 +3350,20 @@ static void M_DrawPauseMenu(void)
// Draw any and all emblems at the top.
M_DrawMapEmblems(gamemap, 272, 28);
if (mapheaderinfo[gamemap-1]->actnum != 0)
V_DrawString(40, 28, V_YELLOWMAP, va("%s %d", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->actnum));
if (mapheaderinfo[gamemap-1]->zonttl)
{
if (mapheaderinfo[gamemap-1]->actnum != 0)
V_DrawString(40, 28, V_YELLOWMAP, va("%s %s %d", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->zonttl, mapheaderinfo[gamemap-1]->actnum));
else
V_DrawString(40, 28, V_YELLOWMAP, va("%s %s", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->zonttl));
}
else
V_DrawString(40, 28, V_YELLOWMAP, mapheaderinfo[gamemap-1]->lvlttl);
{
if (mapheaderinfo[gamemap-1]->actnum != 0)
V_DrawString(40, 28, V_YELLOWMAP, va("%s %d", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->actnum));
else
V_DrawString(40, 28, V_YELLOWMAP, mapheaderinfo[gamemap-1]->lvlttl);
}
// Set up the detail boxes.
{
@ -6019,7 +6029,7 @@ static void M_ModeAttackEndGame(INT32 choice)
(void)choice;
G_CheckDemoStatus(); // Cancel recording
if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION)
if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING)
Command_ExitGame_f();
M_StartControlPanel();

View File

@ -760,7 +760,7 @@ static int P_RecycleCompare(const void *p1, const void *p2)
player_t *player2 = &players[*(const UINT8 *)p2];
// Non-shooting gametypes
if (!G_PlatformGametype())
if (!G_RaceGametype())
{
// Invincibility.
if (player1->powers[pw_invulnerability] > player2->powers[pw_invulnerability]) return -1;

View File

@ -1567,7 +1567,7 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
char targetname[MAXPLAYERNAME+4];
char sourcename[MAXPLAYERNAME+4];
if (G_PlatformGametype())
if (G_RaceGametype())
return; // Not in coop, etc.
if (!player)
@ -1762,7 +1762,7 @@ void P_CheckTimeLimit(void)
if (!(multiplayer || netgame))
return;
if (G_PlatformGametype())
if (G_RaceGametype())
return;
if (leveltime < timelimitintics)
@ -1875,7 +1875,7 @@ void P_CheckPointLimit(void)
if (!(multiplayer || netgame))
return;
if (G_PlatformGametype())
if (G_RaceGametype())
return;
// pointlimit is nonzero, check if it's been reached by this player
@ -2692,7 +2692,7 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj
// In COOP/RACE/CHAOS, you can't hurt other players unless cv_friendlyfire is on
// ...But in SRB2kart, you can!
//if (!cv_friendlyfire.value && (G_PlatformGametype()))
//if (!cv_friendlyfire.value && (G_RaceGametype()))
// return false;
// Tag handling
@ -3117,7 +3117,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL)
return false; // Invincible to fire objects
if (G_PlatformGametype() && source && source->player)
if (G_RaceGametype() && source && source->player)
return false; // Don't get hurt by fire generated from friends.
}

View File

@ -1541,7 +1541,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
else if (thing->player->kartstuff[k_invincibilitytimer] && !tmthing->player->kartstuff[k_invincibilitytimer])
P_DamageMobj(tmthing, thing, thing, 1);
if (G_RingSlingerGametype() && (!G_GametypeHasTeams() || tmthing->player->ctfteam != thing->player->ctfteam))
if (G_BattleGametype() && (!G_GametypeHasTeams() || tmthing->player->ctfteam != thing->player->ctfteam))
{
if ((tmthing->player->powers[pw_invulnerability] || tmthing->player->powers[pw_super])
&& !thing->player->powers[pw_super])

View File

@ -9515,10 +9515,7 @@ void P_SpawnPlayer(INT32 playernum)
p->spectator = false;
}
else if (netgame && p->jointime < 1)
{
//p->spectator = true;
p->kartstuff[k_comebackshowninfo] = 0;
}
/*p->spectator = true*/;
else if (multiplayer && !netgame)
{
// If you're in a team game and you don't have a team assigned yet...
@ -9973,7 +9970,7 @@ void P_SpawnMapThing(mapthing_t *mthing)
return;
}
if (!G_RingSlingerGametype() || !cv_specialrings.value)
if (!G_BattleGametype() || !cv_specialrings.value)
if (P_WeaponOrPanel(i))
return; // Don't place weapons/panels in non-ringslinger modes
@ -10006,7 +10003,7 @@ void P_SpawnMapThing(mapthing_t *mthing)
runemeraldmanager = true;
}
if (!G_PlatformGametype()) // No enemies in match or CTF modes
if (!G_RaceGametype()) // No enemies in match or CTF modes
if ((mobjinfo[i].flags & MF_ENEMY) || (mobjinfo[i].flags & MF_BOSS))
return;
@ -10061,7 +10058,7 @@ void P_SpawnMapThing(mapthing_t *mthing)
}
}
if (!G_PlatformGametype() && (i == MT_SIGN || i == MT_STARPOST))
if (!G_RaceGametype() && (i == MT_SIGN || i == MT_STARPOST))
return; // Don't spawn exit signs or starposts in wrong game modes
if (modeattacking) // Record Attack special stuff

View File

@ -3209,6 +3209,14 @@ static void P_NetArchiveMisc(void)
WRITEUINT32(save_p, totalrings);
WRITEINT16(save_p, lastmap);
for (i = 0; i < 4; i++)
WRITEINT16(save_p, votelevels[i]);
for (i = 0; i < MAXPLAYERS; i++)
WRITESINT8(save_p, votes[i]);
WRITESINT8(save_p, pickedvote);
WRITEUINT16(save_p, emeralds);
WRITEUINT8(save_p, stagefailed);
@ -3292,6 +3300,14 @@ static inline boolean P_NetUnArchiveMisc(void)
totalrings = READUINT32(save_p);
lastmap = READINT16(save_p);
for (i = 0; i < 4; i++)
votelevels[i] = READINT16(save_p);
for (i = 0; i < MAXPLAYERS; i++)
votes[i] = READSINT8(save_p);
pickedvote = READSINT8(save_p);
emeralds = READUINT16(save_p);
stagefailed = READUINT8(save_p);
@ -3385,6 +3401,8 @@ boolean P_LoadGame(INT16 mapoverride)
{
if (gamestate == GS_INTERMISSION)
Y_EndIntermission();
if (gamestate == GS_VOTING)
Y_EndVote();
G_SetGamestate(GS_NULL); // should be changed in P_UnArchiveMisc
P_UnArchiveSPGame(mapoverride);

View File

@ -2810,7 +2810,7 @@ boolean P_SetupLevel(boolean skipprecip)
// Start players with pity shields if possible
players[i].pity = -1;
if (!G_PlatformGametype())
if (!G_RaceGametype())
{
players[i].mo = NULL;
G_DoReborn(i);

View File

@ -3311,7 +3311,7 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd) // SRB2kart - unused.
P_SpawnPlayerMissile(player->mo, MT_FIREBALL, 0);
S_StartSound(player->mo, sfx_mario7);
}
else if (G_RingSlingerGametype() && (!G_TagGametype() || player->pflags & PF_TAGIT)
else if (G_BattleGametype() && (!G_TagGametype() || player->pflags & PF_TAGIT)
&& !player->weapondelay && !player->climbing
&& !(player->pflags & PF_ATTACKDOWN))
{
@ -7788,7 +7788,7 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius)
if (mo->flags & MF_MONITOR)
continue; // Monitors cannot be 'nuked'.
//if (!G_RingSlingerGametype() && mo->type == MT_PLAYER)
//if (!G_BattleGametype() && mo->type == MT_PLAYER)
// continue; // Don't hurt players in Co-Op!
if (abs(inflictor->x - mo->x) > radius || abs(inflictor->y - mo->y) > radius || abs(inflictor->z - mo->z) > radius)
@ -8015,7 +8015,7 @@ static void P_DeathThink(player_t *player)
}
// Force respawn if idle for more than 30 seconds in shooter modes.
if (player->deadtimer > 30*TICRATE && !G_PlatformGametype())
if (player->deadtimer > 30*TICRATE && !G_RaceGametype())
player->playerstate = PST_REBORN;
else if (player->lives > 0 && !G_IsSpecialStage(gamemap) && leveltime >= 140) // Don't allow "click to respawn" in special stages!
{

View File

@ -521,7 +521,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"kc36", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc37", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc38", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc39", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc39", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Voting beep
{"kc3a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc3b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc3c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
@ -536,7 +536,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"kc45", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc46", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc47", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Voting pick
{"kc49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc4a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
@ -574,7 +574,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"kc6c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc6d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"kc6e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
// SRB2kart - Skin sounds
{"kwin", false, 64, 0, -1, NULL, 0, SKSWIN, -1, LUMPERROR},
{"klose", false, 64, 0, -1, NULL, 0, SKSLOSE, -1, LUMPERROR},

View File

@ -177,7 +177,7 @@ hudinfo_t hudinfo[NUMHUDITEMS] =
boolean ST_SameTeam(player_t *a, player_t *b)
{
// Just pipe team messages to everyone in co-op or race.
if (!G_RingSlingerGametype())
if (!G_BattleGametype())
return true;
// Spectator chat.
@ -1412,7 +1412,7 @@ static void ST_drawMatchHUD(void) // SRB2kart - unused.
{
INT32 offset = (BASEVIDWIDTH / 2) - (NUM_WEAPONS * 10);
if (!G_RingSlingerGametype())
if (!G_BattleGametype())
return;
if (G_TagGametype() && !(stplyr->pflags & PF_TAGIT))
@ -1850,7 +1850,7 @@ static void ST_overlayDrawer(void)
/* SRB2kart doesn't need this stuff, I think
// If you are in overtime, put a big honkin' flashin' message on the screen.
if (G_RingSlingerGametype() && cv_overtime.value
if (G_BattleGametype() && cv_overtime.value
&& (leveltime > (timelimitintics + TICRATE/2)) && cv_timelimit.value && (leveltime/TICRATE % 2 == 0))
{
if (splitscreen)
@ -1937,7 +1937,7 @@ static void ST_overlayDrawer(void)
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(116), 0, M_GetText("You cannot move while hiding."));
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), 0, M_GetText("Press F12 to watch another player."));
}
/*else if (!G_PlatformGametype() && stplyr->playerstate == PST_DEAD && stplyr->lives) //Death overrides spectator text.
/*else if (!G_RaceGametype() && stplyr->playerstate == PST_DEAD && stplyr->lives) //Death overrides spectator text.
{
INT32 respawntime = cv_respawntime.value - stplyr->deadtimer/TICRATE;
if (respawntime > 0 && !stplyr->spectator)
@ -1980,7 +1980,7 @@ void ST_Drawer(void)
va("%s%s", G_GametypeHasTeams() ? ((seenplayer->ctfteam == 1) ? "\x85" : "\x84") : "", player_names[seenplayer-players]));
else //if (cv_seenames.value == 3)
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF,
va("%s%s", !G_RingSlingerGametype() || (G_GametypeHasTeams() && players[consoleplayer].ctfteam == seenplayer->ctfteam)
va("%s%s", !G_BattleGametype() || (G_GametypeHasTeams() && players[consoleplayer].ctfteam == seenplayer->ctfteam)
? "\x83" : "\x85", player_names[seenplayer-players]));
}
#endif

View File

@ -36,6 +36,9 @@
#include "m_cond.h" // condition sets
#include "m_random.h" // P_RandomKey
#include "g_input.h" // PLAYER1INPUTDOWN
#ifdef HWRENDER
#include "hardware/hw_main.h"
#endif
@ -164,6 +167,34 @@ static void Y_CalculateMatchWinners(void);
static void Y_FollowIntermission(void);
static void Y_UnloadData(void);
// SRB2Kart: voting stuff
typedef struct
{
char str[40];
patch_t *pic;
} y_votelvlinfo;
typedef struct
{
INT8 selection;
UINT8 delay;
UINT8 ranim;
UINT8 rtics;
UINT8 roffset;
UINT8 rsynctime;
UINT8 rendoff;
} y_voteclient;
static y_votelvlinfo levelinfo[4];
static y_voteclient voteclient;
static INT32 votetic;
static INT32 voteendtic = -1;
static patch_t *cursor = NULL;
static patch_t *randomlvl = NULL;
static void Y_UnloadVoteData(void);
// Stuff copy+pasted from st_stuff.c
static INT32 SCX(INT32 x)
{
@ -2088,3 +2119,399 @@ static void Y_UnloadData(void)
break;
}
}
// SRB2Kart: Voting!
//
// Y_VoteDrawer
//
// Draws the voting screen!
//
void Y_VoteDrawer(void)
{
INT32 i, x, y = 0;
if (rendermode == render_none)
return;
if (votetic >= voteendtic && voteendtic != -1)
return;
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
if (widebgpatch && rendermode == render_soft && vid.width / vid.dupx > 320)
V_DrawScaledPatch(((vid.width/2) / vid.dupx) - (SHORT(widebgpatch->width)/2),
(vid.height / vid.dupy) - SHORT(widebgpatch->height),
V_SNAPTOTOP|V_SNAPTOLEFT, widebgpatch);
else
V_DrawScaledPatch(((vid.width/2) / vid.dupx) - (SHORT(bgpatch->width)/2), // Keep the width/height adjustments, for screens that are less wide than 320(?)
(vid.height / vid.dupy) - SHORT(bgpatch->height),
V_SNAPTOTOP|V_SNAPTOLEFT, bgpatch);
y = 30;
for (i = 0; i < 4; i++)
{
char str[40];
patch_t *pic;
if (i == 3)
{
snprintf(str, sizeof str, "%.32s", "RANDOM");
str[sizeof str - 1] = '\0';
pic = randomlvl;
}
else
{
strcpy(str, levelinfo[i].str);
pic = levelinfo[i].pic;
}
if (i == voteclient.selection)
{
if (votes[consoleplayer] == -1)
{
V_DrawScaledPatch(BASEVIDWIDTH-124, y+21, V_SNAPTORIGHT, cursor);
if (votetic % 4 > 1)
V_DrawFill(BASEVIDWIDTH-101, y-1, 82, 52, 120|V_SNAPTORIGHT);
else
V_DrawFill(BASEVIDWIDTH-101, y-1, 82, 52, 103|V_SNAPTORIGHT);
}
V_DrawSmallScaledPatch(BASEVIDWIDTH-100, y, V_SNAPTORIGHT, pic);
V_DrawRightAlignedThinString(BASEVIDWIDTH-20, 40+y, V_SNAPTORIGHT, str);
y += 55;
}
else
{
V_DrawTinyScaledPatch(BASEVIDWIDTH-60, y, V_SNAPTORIGHT, pic);
y += 30;
}
}
x = 20;
y = 15;
for (i = 0; i < MAXPLAYERS; i++)
{
if (votes[i] != -1)
{
patch_t *pic;
if (votes[i] == 3 && (i != pickedvote || voteendtic == -1))
pic = randomlvl;
else
pic = levelinfo[votes[i]].pic;
if (!timer && i == voteclient.ranim)
{
V_DrawScaledPatch(x-18, y+9, V_SNAPTOLEFT, cursor);
if (votetic % 4 > 1)
V_DrawFill(x-1, y-1, 42, 27, 120|V_SNAPTOLEFT);
else
V_DrawFill(x-1, y-1, 42, 27, 103|V_SNAPTOLEFT);
}
V_DrawTinyScaledPatch(x, y, V_SNAPTOLEFT, pic);
if (players[i].skincolor == 0)
V_DrawSmallScaledPatch(x+24, y+9, V_SNAPTOLEFT, faceprefix[players[i].skin]);
else
{
UINT8 *colormap = R_GetTranslationColormap(players[i].skin, players[i].skincolor, GTC_CACHE);
V_DrawSmallMappedPatch(x+24, y+9, V_SNAPTOLEFT, faceprefix[players[i].skin], colormap);
}
}
if (splitscreen) // only 1p has a vote in splitscreen
break;
y += 30;
if (y > BASEVIDHEIGHT-38)
{
x += 100;
y = 15;
}
}
//V_DrawScaledPatch(x, y, V_SNAPTOBOTTOM, pic);
if (timer)
V_DrawCenteredString(BASEVIDWIDTH/2, 188, V_YELLOWMAP|V_SNAPTOBOTTOM,
va("Vote ends in %d seconds", timer/TICRATE));
}
//
// Y_VoteTicker
//
// Vote screen thinking :eggthinking:
//
void Y_VoteTicker(void)
{
boolean pressed = false;
INT32 i;
if (paused || P_AutoPause())
return;
votetic++;
if (votetic == voteendtic)
{
Y_UnloadVoteData(); // Y_EndVote resets voteendtic too early apparently, causing the game to try to render patches that we just unloaded...
Y_FollowIntermission();
return;
}
for (i = 0; i < MAXPLAYERS; i++) // Correct votes as early as possible, before they're processed by the game at all
{
if (!playeringame[i] || players[i].spectator)
votes[i] = -1;
else if (pickedvote != -1 && votes[i] == -1 && !splitscreen)
votes[i] = 3; // Slow people get random
}
if (server && votes[pickedvote] == -1) // Uh oh! The person who got picked left! Recalculate, quick!
D_PickVote();
if (!votetic)
S_ChangeMusicInternal("vote", true);
if (timer)
timer--;
if (voteclient.delay)
voteclient.delay--;
if (pickedvote != -1)
{
timer = 0;
voteclient.rsynctime++;
if (voteendtic == -1)
{
UINT8 tempvotes[MAXPLAYERS];
UINT8 numvotes = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
if (votes[i] == -1)
continue;
tempvotes[numvotes] = i;
numvotes++;
}
voteclient.rtics--;
if (voteclient.rtics <= 0)
{
voteclient.roffset++;
voteclient.rtics = min(TICRATE/2, (voteclient.roffset/2)+5);
S_StartSound(NULL, sfx_kc39);
}
if (voteclient.rendoff == 0 || voteclient.roffset < voteclient.rendoff)
voteclient.ranim = tempvotes[((pickedvote + voteclient.roffset) % numvotes)];
if (voteclient.roffset >= 24)
{
if (voteclient.rendoff == 0)
{
if (tempvotes[((pickedvote + voteclient.roffset + 4) % numvotes)] == pickedvote
&& voteclient.rsynctime % (29*TICRATE/20) == 0) // Song is 1.45 seconds long (sorry @ whoever wants to replace it in a music wad :V)
{
voteclient.rendoff = voteclient.roffset+4;
S_ChangeMusicInternal("voteeb", false);
}
}
else if (voteclient.roffset >= voteclient.rendoff)
{
voteendtic = votetic + (3*TICRATE);
S_StartSound(NULL, sfx_kc48);
}
}
}
else
voteclient.ranim = pickedvote;
}
else
{
if (votetic < 3*(NEWTICRATE/7)) // give it some time before letting you control it :V
return;
if ((!playeringame[consoleplayer] || players[consoleplayer].spectator) && votes[consoleplayer] != -1)
D_ModifyClientVote(-1);
else if (pickedvote == -1 && votes[consoleplayer] == -1 && !voteclient.delay)
{
if (InputDown(gc_aimforward, 1) || JoyAxis(AXISMOVE, 1) < 0)
{
voteclient.selection--;
pressed = true;
}
if ((InputDown(gc_aimbackward, 1) || JoyAxis(AXISMOVE, 1) > 0) && !pressed)
{
voteclient.selection++;
pressed = true;
}
if (voteclient.selection < 0)
voteclient.selection = 3;
if (voteclient.selection > 3)
voteclient.selection = 0;
if (InputDown(gc_accelerate, 1) && !pressed)
{
D_ModifyClientVote(voteclient.selection);
pressed = true;
}
}
if (pressed)
{
S_StartSound(NULL, sfx_s3k5b);
voteclient.delay = NEWTICRATE/7;
}
if (server)
{
UINT8 numplayers = 0, numvotes = 0;
if (splitscreen)
{
numplayers = 1;
if (votes[0] != -1)
numvotes = 1;
}
else
{
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
numplayers++;
if (votes[i] != -1)
numvotes++;
}
}
if (numvotes >= numplayers)
timer = 0;
if (timer == 0 && voteendtic == -1)
D_PickVote();
}
}
}
//
// Y_StartVote
//
// MK online style voting screen, appears after intermission
//
void Y_StartVote(void)
{
INT32 i = 0;
votetic = -1;
#ifdef PARANOIA
if (voteendtic != -1)
I_Error("voteendtic is dirty");
#endif
widebgpatch = W_CachePatchName("INTERSCW", PU_STATIC);
bgpatch = W_CachePatchName("INTERSCR", PU_STATIC);
cursor = W_CachePatchName("M_CURSOR", PU_STATIC);
randomlvl = W_CachePatchName("RANDOMLV", PU_STATIC);
timer = cv_votetime.value*TICRATE;
pickedvote = -1;
voteclient.selection = 0;
voteclient.delay = 0;
voteclient.ranim = 0;
voteclient.rtics = 1;
voteclient.roffset = 0;
voteclient.rsynctime = 0;
voteclient.rendoff = 0;
for (i = 0; i < MAXPLAYERS; i++)
votes[i] = -1;
for (i = 0; i < 4; i++)
{
lumpnum_t lumpnum;
// set up the str
if (mapheaderinfo[votelevels[i]]->zonttl)
{
if (mapheaderinfo[votelevels[i]]->actnum)
snprintf(levelinfo[i].str,
sizeof levelinfo[i].str,
"%.32s %.32s %d",
mapheaderinfo[votelevels[i]]->lvlttl, mapheaderinfo[votelevels[i]]->zonttl, mapheaderinfo[votelevels[i]]->actnum);
else
snprintf(levelinfo[i].str,
sizeof levelinfo[i].str,
"%.32s %.32s",
mapheaderinfo[votelevels[i]]->lvlttl, mapheaderinfo[votelevels[i]]->zonttl);
}
else
{
if (mapheaderinfo[votelevels[i]]->actnum)
snprintf(levelinfo[i].str,
sizeof levelinfo[i].str,
"%.32s %d",
mapheaderinfo[votelevels[i]]->lvlttl, mapheaderinfo[votelevels[i]]->actnum);
else
snprintf(levelinfo[i].str,
sizeof levelinfo[i].str,
"%.32s",
mapheaderinfo[votelevels[i]]->lvlttl);
}
levelinfo[i].str[sizeof levelinfo[i].str - 1] = '\0';
lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(votelevels[i]+1)));
if (lumpnum != LUMPERROR)
levelinfo[i].pic = W_CachePatchName(va("%sP", G_BuildMapName(votelevels[i]+1)), PU_STATIC);
else
levelinfo[i].pic = W_CachePatchName("BLANKLVL", PU_STATIC);
}
}
//
// Y_EndVote
//
void Y_EndVote(void)
{
Y_UnloadVoteData();
voteendtic = -1;
}
//
// Y_UnloadVoteData
//
static void Y_UnloadVoteData(void)
{
if (rendermode != render_soft)
return;
UNLOAD(widebgpatch);
UNLOAD(bgpatch);
UNLOAD(cursor);
UNLOAD(randomlvl);
UNLOAD(levelinfo[3].pic);
UNLOAD(levelinfo[2].pic);
UNLOAD(levelinfo[1].pic);
UNLOAD(levelinfo[0].pic);
}
//
// Y_SetupVoteFinish
//
void Y_SetupVoteFinish(INT8 pick, INT8 level)
{
pickedvote = pick;
nextmap = votelevels[level];
timer = 0;
S_ChangeMusicInternal("voteea", true);
}

View File

@ -17,6 +17,12 @@ void Y_StartIntermission(void);
void Y_EndIntermission(void);
void Y_EndGame(void);
void Y_VoteDrawer(void);
void Y_VoteTicker(void);
void Y_StartVote(void);
void Y_EndVote(void);
void Y_SetupVoteFinish(INT8 pick, INT8 level);
typedef enum
{
int_none,