mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2025-01-17 23:21:05 +00:00
Merge branch 'master' into new-spb
This commit is contained in:
commit
2021897972
30 changed files with 1270 additions and 787 deletions
|
@ -1600,6 +1600,31 @@ void CV_AddValue(consvar_t *var, INT32 increment)
|
|||
return;
|
||||
}
|
||||
}
|
||||
else if (var == &cv_kartspeed)
|
||||
{
|
||||
INT32 maxspeed = (M_SecretUnlocked(SECRET_HARDSPEED) ? 2 : 1);
|
||||
// Special case for the kartspeed variable, used only directly from the menu to prevent selecting hard mode
|
||||
if (increment > 0) // Going up!
|
||||
{
|
||||
newvalue = var->value + 1;
|
||||
if (newvalue > maxspeed)
|
||||
newvalue = 0;
|
||||
var->value = newvalue;
|
||||
var->string = var->PossibleValue[var->value].strvalue;
|
||||
var->func();
|
||||
return;
|
||||
}
|
||||
else if (increment < 0) // Going down!
|
||||
{
|
||||
newvalue = var->value - 1;
|
||||
if (newvalue < 0)
|
||||
newvalue = maxspeed;
|
||||
var->value = newvalue;
|
||||
var->string = var->PossibleValue[var->value].strvalue;
|
||||
var->func();
|
||||
return;
|
||||
}
|
||||
}
|
||||
#ifdef PARANOIA
|
||||
if (currentindice == -1)
|
||||
I_Error("CV_AddValue: current value %d not found in possible value\n",
|
||||
|
|
|
@ -748,6 +748,19 @@ boolean CON_Responder(event_t *ev)
|
|||
if (modeattacking || metalrecording)
|
||||
return false;
|
||||
|
||||
if (ev->data1 >= KEY_MOUSE1) // See also: HUD_Responder
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < num_gamecontrols; i++)
|
||||
{
|
||||
if (gamecontrol[i][0] == ev->data1 || gamecontrol[i][1] == ev->data1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == num_gamecontrols)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (key == gamecontrol[gc_console][0] || key == gamecontrol[gc_console][1])
|
||||
{
|
||||
if (consdown) // ignore repeat
|
||||
|
|
184
src/d_clisrv.c
184
src/d_clisrv.c
|
@ -1633,18 +1633,18 @@ static void CL_LoadReceivedSavegame(void)
|
|||
// load a base level
|
||||
if (P_LoadNetGame())
|
||||
{
|
||||
CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap));
|
||||
CON_LogMessage(va(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)));
|
||||
if (strlen(mapheaderinfo[gamemap-1]->lvlttl) > 0)
|
||||
{
|
||||
CONS_Printf(": %s", mapheaderinfo[gamemap-1]->lvlttl);
|
||||
CON_LogMessage(va(": %s", mapheaderinfo[gamemap-1]->lvlttl));
|
||||
if (strlen(mapheaderinfo[gamemap-1]->zonttl) > 0)
|
||||
CONS_Printf(" %s", mapheaderinfo[gamemap-1]->zonttl);
|
||||
CON_LogMessage(va(" %s", mapheaderinfo[gamemap-1]->zonttl));
|
||||
else if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
|
||||
CONS_Printf(M_GetText(" ZONE"));
|
||||
CON_LogMessage(M_GetText(" ZONE"));
|
||||
if (strlen(mapheaderinfo[gamemap-1]->actnum) > 0)
|
||||
CONS_Printf(" %s", mapheaderinfo[gamemap-1]->actnum);
|
||||
CON_LogMessage(va(" %s", mapheaderinfo[gamemap-1]->actnum));
|
||||
}
|
||||
CONS_Printf("\"\n");
|
||||
CON_LogMessage("\"\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2375,8 +2375,11 @@ static void Command_connect(void)
|
|||
CONS_Alert(CONS_ERROR, M_GetText("There is no network driver\n"));
|
||||
}
|
||||
|
||||
splitscreen = 0;
|
||||
SplitScreen_OnChange();
|
||||
if (splitscreen != cv_splitplayers.value-1)
|
||||
{
|
||||
splitscreen = cv_splitplayers.value-1;
|
||||
SplitScreen_OnChange();
|
||||
}
|
||||
botingame = false;
|
||||
botskin = 0;
|
||||
CL_ConnectToServer(viams);
|
||||
|
@ -2417,14 +2420,15 @@ static void CL_RemovePlayer(INT32 playernum)
|
|||
if (server && !demoplayback)
|
||||
{
|
||||
INT32 node = playernode[playernum];
|
||||
//playerpernode[node] = 0; // It'd be better to remove them all at once, but ghosting happened, so continue to let CL_RemovePlayer do it one-by-one
|
||||
playerpernode[node]--;
|
||||
if (playerpernode[node] <= 0)
|
||||
{
|
||||
// If a resynch was in progress, well, it no longer needs to be.
|
||||
SV_InitResynchVars(playernode[playernum]);
|
||||
SV_InitResynchVars(node);
|
||||
|
||||
nodeingame[playernode[playernum]] = false;
|
||||
Net_CloseConnection(playernode[playernum]);
|
||||
nodeingame[node] = false;
|
||||
Net_CloseConnection(node);
|
||||
ResetNode(node);
|
||||
}
|
||||
}
|
||||
|
@ -2759,11 +2763,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
}
|
||||
|
||||
// Is playernum authorized to make this kick?
|
||||
if (playernum != serverplayer && !IsPlayerAdmin(playernum)
|
||||
&& !(playerpernode[playernode[playernum]] >= 2
|
||||
&& (nodetoplayer2[playernode[playernum]] == pnum
|
||||
|| nodetoplayer3[playernode[playernum]] == pnum
|
||||
|| nodetoplayer4[playernode[playernum]] == pnum)))
|
||||
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
|
||||
{
|
||||
// We received a kick command from someone who isn't the
|
||||
// server or admin, and who isn't in splitscreen removing
|
||||
|
@ -2775,12 +2775,6 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
// "consistency failure" and kicking the offending user
|
||||
// instead.
|
||||
|
||||
// Note: Splitscreen in netgames is broken because of
|
||||
// this. Only the server has any idea of which players
|
||||
// are using splitscreen on the same computer, so
|
||||
// clients cannot always determine if a kick is
|
||||
// legitimate.
|
||||
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal kick command received from %s for player %d\n"), player_names[playernum], pnum);
|
||||
|
||||
// In debug, print a longer message with more details.
|
||||
|
@ -2890,7 +2884,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
break;
|
||||
}
|
||||
|
||||
if (pnum == consoleplayer)
|
||||
if (playernode[pnum] == playernode[consoleplayer])
|
||||
{
|
||||
#ifdef DUMPCONSISTENCY
|
||||
if (msg == KICK_MSG_CON_FAIL) SV_SavedGame();
|
||||
|
@ -2899,7 +2893,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
CL_Reset();
|
||||
D_StartTitle();
|
||||
if (msg == KICK_MSG_CON_FAIL)
|
||||
M_StartMessage(M_GetText("Server closed connection\n(synch failure)\nPress ESC\n"), NULL, MM_NOTHING);
|
||||
M_StartMessage(M_GetText("Server closed connection\n(Synch failure)\nPress ESC\n"), NULL, MM_NOTHING);
|
||||
#ifdef NEWPING
|
||||
else if (msg == KICK_MSG_PING_HIGH)
|
||||
M_StartMessage(M_GetText("Server closed connection\n(Broke ping limit)\nPress ESC\n"), NULL, MM_NOTHING);
|
||||
|
@ -2913,8 +2907,32 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
else
|
||||
M_StartMessage(M_GetText("You have been kicked by the server\n\nPress ESC\n"), NULL, MM_NOTHING);
|
||||
}
|
||||
else
|
||||
CL_RemovePlayer(pnum);
|
||||
else if (server)
|
||||
{
|
||||
XBOXSTATIC UINT8 buf[0];
|
||||
|
||||
// Sal: Because kicks (and a lot of other commands) are player-based, we can't tell which player pnum is on the node from a glance.
|
||||
// When we want to remove everyone from a node, we have to get the kicked player's node, then remove everyone on that node manually so we don't miss any.
|
||||
// This avoids the bugs with older SRB2 version's online splitscreen kicks, specifically ghosting.
|
||||
// On top of this, it can't just be a CL_RemovePlayer call; it has to be a server-sided.
|
||||
// Clients don't bother setting any nodes for anything but THE server player (even ignoring the server's extra players!), so it'll often remove everyone because they all have node -1/255, insta-desync!
|
||||
// And yes. This is a netxcmd wrap for just CL_RemovePlayer! :V
|
||||
|
||||
#define removethisplayer(otherp) \
|
||||
if (otherp >= 0) \
|
||||
{ \
|
||||
if (otherp != pnum) \
|
||||
CONS_Printf("\x82%s\x80 left the game (Joined with \x82%s\x80)\n", player_names[otherp], player_names[pnum]); \
|
||||
buf[0] = (UINT8)otherp; \
|
||||
SendNetXCmd(XD_REMOVEPLAYER, &buf, 1); \
|
||||
otherp = -1; \
|
||||
}
|
||||
removethisplayer(nodetoplayer[playernode[pnum]])
|
||||
removethisplayer(nodetoplayer2[playernode[pnum]])
|
||||
removethisplayer(nodetoplayer3[playernode[pnum]])
|
||||
removethisplayer(nodetoplayer4[playernode[pnum]])
|
||||
#undef removethisplayer
|
||||
}
|
||||
}
|
||||
|
||||
consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
|
@ -2937,6 +2955,7 @@ static CV_PossibleValue_t downloadspeed_cons_t[] = {{0, "MIN"}, {32, "MAX"}, {0,
|
|||
consvar_t cv_downloadspeed = {"downloadspeed", "16", CV_SAVE, downloadspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static void Got_AddPlayer(UINT8 **p, INT32 playernum);
|
||||
static void Got_RemovePlayer(UINT8 **p, INT32 playernum);
|
||||
|
||||
// called one time at init
|
||||
void D_ClientServerInit(void)
|
||||
|
@ -2964,6 +2983,7 @@ void D_ClientServerInit(void)
|
|||
|
||||
RegisterNetXCmd(XD_KICK, Got_KickCmd);
|
||||
RegisterNetXCmd(XD_ADDPLAYER, Got_AddPlayer);
|
||||
RegisterNetXCmd(XD_REMOVEPLAYER, Got_RemovePlayer);
|
||||
#ifndef NONET
|
||||
CV_RegisterVar(&cv_allownewplayer);
|
||||
#ifdef VANILLAJOINNEXTROUND
|
||||
|
@ -3157,9 +3177,8 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
|||
newplayernum %= MAXPLAYERS;
|
||||
|
||||
// Clear player before joining, lest some things get set incorrectly
|
||||
// HACK: don't do this for splitscreen, it relies on preset values
|
||||
if (!splitscreen && !botingame)
|
||||
CL_ClearPlayer(newplayernum);
|
||||
CL_ClearPlayer(newplayernum);
|
||||
|
||||
playeringame[newplayernum] = true;
|
||||
G_AddPlayer(newplayernum);
|
||||
if (newplayernum+1 > doomcom->numslots)
|
||||
|
@ -3241,6 +3260,27 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
|||
#endif
|
||||
}
|
||||
|
||||
// Xcmd XD_REMOVEPLAYER
|
||||
static void Got_RemovePlayer(UINT8 **p, INT32 playernum)
|
||||
{
|
||||
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
|
||||
{
|
||||
// protect against hacked/buggy client
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal remove player command 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;
|
||||
}
|
||||
|
||||
CL_RemovePlayer(READUINT8(*p));
|
||||
}
|
||||
|
||||
static boolean SV_AddWaitingPlayers(void)
|
||||
{
|
||||
INT32 node, n, newplayer = false;
|
||||
|
@ -3258,69 +3298,17 @@ static boolean SV_AddWaitingPlayers(void)
|
|||
{
|
||||
newplayer = true;
|
||||
|
||||
if (netgame)
|
||||
// !!!!!!!!! EXTREMELY SUPER MEGA GIGA ULTRA ULTIMATELY TERRIBLY IMPORTANT !!!!!!!!!
|
||||
//
|
||||
// The line just after that comment is an awful, horrible, terrible, TERRIBLE hack.
|
||||
//
|
||||
// Basically, the fix I did in order to fix the download freezes happens
|
||||
// to cause situations in which a player number does not match
|
||||
// the node number associated to that player.
|
||||
// That is totally normal, there is absolutely *nothing* wrong with that.
|
||||
// Really. Player 7 being tied to node 29, for instance, is totally fine.
|
||||
//
|
||||
// HOWEVER. A few (broken) parts of the netcode do the TERRIBLE mistake
|
||||
// of mixing up the concepts of node and player, resulting in
|
||||
// incorrect handling of cases where a player is tied to a node that has
|
||||
// a different number (which is a totally normal case, or at least should be).
|
||||
// This incorrect handling can go as far as literally
|
||||
// anyone from joining your server at all, forever.
|
||||
//
|
||||
// Given those two facts, there are two options available
|
||||
// in order to let this download freeze fix be:
|
||||
// 1) Fix the broken parts that assume a node is a player or similar bullshit.
|
||||
// 2) Change the part this comment is located at, so that any player who joins
|
||||
// is given the same number as their associated node.
|
||||
//
|
||||
// No need to say, 1) is by far the obvious best, whereas 2) is a terrible hack.
|
||||
// Unfortunately, after trying 1), I most likely didn't manage to find all
|
||||
// of those broken parts, and thus 2) has become the only safe option that remains.
|
||||
//
|
||||
// So I did this hack.
|
||||
//
|
||||
// If it isn't clear enough, in order to get rid of this ugly hack,
|
||||
// you will have to fix all parts of the netcode that
|
||||
// make a confusion between nodes and players.
|
||||
//
|
||||
// And if it STILL isn't clear enough, a node and a player
|
||||
// is NOT the same thing. Never. NEVER. *NEVER*.
|
||||
//
|
||||
// And if someday you make the terrible mistake of
|
||||
// daring to have the unforgivable idea to try thinking
|
||||
// that a node might possibly be the same as a player,
|
||||
// or that a player should have the same number as its node,
|
||||
// be sure that I will somehow know about it and
|
||||
// hunt you down tirelessly and make you regret it,
|
||||
// even if you live on the other side of the world.
|
||||
//
|
||||
// TODO: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
// \todo >>>>>>>>>> Remove this horrible hack as soon as possible <<<<<<<<<<
|
||||
// TODO: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
//
|
||||
// !!!!!!!!! EXTREMELY SUPER MEGA GIGA ULTRA ULTIMATELY TERRIBLY IMPORTANT !!!!!!!!!
|
||||
newplayernum = node; // OMFG SAY WELCOME TO TEH NEW HACK FOR FIX FIL DOWNLOAD!!1!
|
||||
else // Don't use the hack if we don't have to
|
||||
// search for a free playernum
|
||||
// we can't use playeringame since it is not updated here
|
||||
for (; newplayernum < MAXPLAYERS; newplayernum++)
|
||||
{
|
||||
for (n = 0; n < MAXNETNODES; n++)
|
||||
if (nodetoplayer[n] == newplayernum || nodetoplayer2[n] == newplayernum
|
||||
|| nodetoplayer3[n] == newplayernum || nodetoplayer4[n] == newplayernum)
|
||||
break;
|
||||
if (n == MAXNETNODES)
|
||||
// search for a free playernum
|
||||
// we can't use playeringame since it is not updated here
|
||||
for (; newplayernum < MAXPLAYERS; newplayernum++)
|
||||
{
|
||||
for (n = 0; n < MAXNETNODES; n++)
|
||||
if (nodetoplayer[n] == newplayernum || nodetoplayer2[n] == newplayernum
|
||||
|| nodetoplayer3[n] == newplayernum || nodetoplayer4[n] == newplayernum)
|
||||
break;
|
||||
}
|
||||
if (n == MAXNETNODES)
|
||||
break;
|
||||
}
|
||||
|
||||
// should never happen since we check the playernum
|
||||
// before accepting the join
|
||||
|
@ -3495,7 +3483,7 @@ static void HandleConnect(SINT8 node)
|
|||
SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment"));
|
||||
else if (D_NumPlayers() >= cv_maxplayers.value)
|
||||
SV_SendRefuse(node, va(M_GetText("Maximum players reached: %d"), cv_maxplayers.value));
|
||||
else if (netgame && netbuffer->u.clientcfg.localplayers > 1) // Hacked client?
|
||||
else if (netgame && netbuffer->u.clientcfg.localplayers > 4) // Hacked client?
|
||||
SV_SendRefuse(node, M_GetText("Too many players from\nthis node."));
|
||||
else if (netgame && !netbuffer->u.clientcfg.localplayers) // Stealth join?
|
||||
SV_SendRefuse(node, M_GetText("No players from\nthis node."));
|
||||
|
@ -3529,8 +3517,8 @@ static void HandleConnect(SINT8 node)
|
|||
{
|
||||
G_SetGamestate(backupstate);
|
||||
/// \note Shouldn't SV_SendRefuse be called before ResetNode?
|
||||
ResetNode(node);
|
||||
SV_SendRefuse(node, M_GetText("Server couldn't send info, please try again"));
|
||||
ResetNode(node); // Yeah, lets try it!
|
||||
/// \todo fix this !!!
|
||||
return; // restart the while
|
||||
}
|
||||
|
@ -3983,10 +3971,10 @@ FILESTAMP
|
|||
--resynch_score[node];
|
||||
break;
|
||||
case PT_TEXTCMD:
|
||||
case PT_TEXTCMD2: // splitscreen special
|
||||
case PT_TEXTCMD2:
|
||||
case PT_TEXTCMD3:
|
||||
case PT_TEXTCMD4:
|
||||
if (netbuffer->packettype == PT_TEXTCMD2)
|
||||
if (netbuffer->packettype == PT_TEXTCMD2) // splitscreen special
|
||||
netconsole = nodetoplayer2[node];
|
||||
else if (netbuffer->packettype == PT_TEXTCMD3)
|
||||
netconsole = nodetoplayer3[node];
|
||||
|
@ -4073,9 +4061,9 @@ FILESTAMP
|
|||
else
|
||||
buf[1] = KICK_MSG_PLAYER_QUIT;
|
||||
SendNetXCmd(XD_KICK, &buf, 2);
|
||||
nodetoplayer[node] = -1;
|
||||
//nodetoplayer[node] = -1;
|
||||
|
||||
if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0
|
||||
/*if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0
|
||||
&& playeringame[(UINT8)nodetoplayer2[node]])
|
||||
{
|
||||
buf[0] = nodetoplayer2[node];
|
||||
|
@ -4097,7 +4085,7 @@ FILESTAMP
|
|||
buf[0] = nodetoplayer4[node];
|
||||
SendNetXCmd(XD_KICK, &buf, 2);
|
||||
nodetoplayer4[node] = -1;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
Net_CloseConnection(node);
|
||||
nodeingame[node] = false;
|
||||
|
|
15
src/d_main.c
15
src/d_main.c
|
@ -1362,11 +1362,26 @@ void D_SRB2Main(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
// Set up splitscreen players before joining!
|
||||
if (!dedicated && (M_CheckParm("-splitscreen") && M_IsNextParm()))
|
||||
{
|
||||
UINT8 num = atoi(M_GetNextParm());
|
||||
if (num >= 1 && num <= 4)
|
||||
{
|
||||
CV_StealthSetValue(&cv_splitplayers, num);
|
||||
splitscreen = num-1;
|
||||
SplitScreen_OnChange();
|
||||
}
|
||||
}
|
||||
|
||||
// init all NETWORK
|
||||
CONS_Printf("D_CheckNetGame(): Checking network game status.\n");
|
||||
if (D_CheckNetGame())
|
||||
autostart = true;
|
||||
|
||||
if (splitscreen) // Make sure multiplayer & autostart is set if you have splitscreen, even after D_CheckNetGame
|
||||
multiplayer = autostart = true;
|
||||
|
||||
// check for a driver that wants intermission stats
|
||||
// start the apropriate game based on parms
|
||||
if (M_CheckParm("-metal"))
|
||||
|
|
167
src/d_netcmd.c
167
src/d_netcmd.c
|
@ -375,6 +375,7 @@ consvar_t cv_kartdebugdistribution = {"kartdebugdistribution", "Off", CV_NETVAR|
|
|||
consvar_t cv_kartdebughuddrop = {"kartdebughuddrop", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_kartdebugcheckpoint = {"kartdebugcheckpoint", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_kartdebugnodes = {"kartdebugnodes", "Off", 0, CV_OnOff, 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};
|
||||
|
@ -419,9 +420,6 @@ consvar_t cv_numlaps = {"numlaps", "3", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_con
|
|||
static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}};
|
||||
consvar_t cv_basenumlaps = {"basenumlaps", "Map default", CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// log elemental hazards -- not a netvar, is local to current player
|
||||
consvar_t cv_hazardlog = {"hazardlog", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_forceskin = {"forceskin", "-1", CV_NETVAR|CV_CALL|CV_CHEAT, NULL, ForceSkin_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_downloading = {"downloading", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_allowexitlevel = {"allowexitlevel", "No", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
@ -594,8 +592,6 @@ void D_RegisterServerCommands(void)
|
|||
CV_RegisterVar(&cv_numlaps);
|
||||
CV_RegisterVar(&cv_basenumlaps);
|
||||
|
||||
CV_RegisterVar(&cv_hazardlog);
|
||||
|
||||
CV_RegisterVar(&cv_autobalance);
|
||||
CV_RegisterVar(&cv_teamscramble);
|
||||
CV_RegisterVar(&cv_scrambleonchange);
|
||||
|
@ -758,6 +754,8 @@ void D_RegisterClientCommands(void)
|
|||
CV_RegisterVar(&cv_playername4);
|
||||
CV_RegisterVar(&cv_playercolor4);
|
||||
CV_RegisterVar(&cv_skin4);
|
||||
// preferred number of players
|
||||
CV_RegisterVar(&cv_splitplayers);
|
||||
|
||||
#ifdef SEENAMES
|
||||
CV_RegisterVar(&cv_seenames);
|
||||
|
@ -1350,16 +1348,23 @@ static void SendNameAndColor(void)
|
|||
// splitscreen
|
||||
static void SendNameAndColor2(void)
|
||||
{
|
||||
INT32 secondplaya;
|
||||
INT32 secondplaya = -1;
|
||||
XBOXSTATIC char buf[MAXPLAYERNAME+2];
|
||||
char *p;
|
||||
|
||||
if (splitscreen < 1 && !botingame)
|
||||
return; // can happen if skin2/color2/name2 changed
|
||||
|
||||
if (secondarydisplayplayer != consoleplayer)
|
||||
secondplaya = secondarydisplayplayer;
|
||||
else // HACK
|
||||
else if (!netgame) // HACK
|
||||
secondplaya = 1;
|
||||
|
||||
if (secondplaya == -1)
|
||||
return;
|
||||
|
||||
p = buf;
|
||||
|
||||
// normal player colors
|
||||
if (G_GametypeHasTeams())
|
||||
{
|
||||
|
@ -1436,21 +1441,53 @@ static void SendNameAndColor2(void)
|
|||
return;
|
||||
}
|
||||
|
||||
// Don't actually send anything because splitscreen isn't actually allowed in netgames anyway!
|
||||
snac2pending++;
|
||||
|
||||
// Don't change name if muted
|
||||
if (cv_mute.value && !(server || IsPlayerAdmin(secondarydisplayplayer)))
|
||||
CV_StealthSet(&cv_playername2, player_names[secondarydisplayplayer]);
|
||||
else // Cleanup name if changing it
|
||||
CleanupPlayerName(secondarydisplayplayer, cv_playername2.zstring);
|
||||
|
||||
// Don't change skin if the server doesn't want you to.
|
||||
if (!CanChangeSkin(secondarydisplayplayer))
|
||||
CV_StealthSet(&cv_skin2, skins[players[secondarydisplayplayer].skin].name);
|
||||
|
||||
// check if player has the skin loaded (cv_skin2 may have
|
||||
// the name of a skin that was available in the previous game)
|
||||
cv_skin2.value = R_SkinAvailable(cv_skin2.string);
|
||||
if (cv_skin2.value < 0)
|
||||
{
|
||||
CV_StealthSet(&cv_skin2, DEFAULTSKIN);
|
||||
cv_skin2.value = 0;
|
||||
}
|
||||
|
||||
// Finally write out the complete packet and send it off.
|
||||
WRITESTRINGN(p, cv_playername2.zstring, MAXPLAYERNAME);
|
||||
WRITEUINT8(p, (UINT8)cv_playercolor2.value);
|
||||
WRITEUINT8(p, (UINT8)cv_skin2.value);
|
||||
SendNetXCmd2(XD_NAMEANDCOLOR, buf, p - buf);
|
||||
}
|
||||
|
||||
static void SendNameAndColor3(void)
|
||||
{
|
||||
INT32 thirdplaya;
|
||||
INT32 thirdplaya = -1;
|
||||
XBOXSTATIC char buf[MAXPLAYERNAME+2];
|
||||
char *p;
|
||||
|
||||
if (splitscreen < 2)
|
||||
return; // can happen if skin3/color3/name3 changed
|
||||
|
||||
if (thirddisplayplayer != consoleplayer)
|
||||
thirdplaya = thirddisplayplayer;
|
||||
else // HACK
|
||||
else if (!netgame) // HACK
|
||||
thirdplaya = 2;
|
||||
|
||||
if (thirdplaya == -1)
|
||||
return;
|
||||
|
||||
p = buf;
|
||||
|
||||
// normal player colors
|
||||
if (G_GametypeHasTeams())
|
||||
{
|
||||
|
@ -1519,21 +1556,53 @@ static void SendNameAndColor3(void)
|
|||
return;
|
||||
}
|
||||
|
||||
// Don't actually send anything because splitscreen isn't actually allowed in netgames anyway!
|
||||
snac3pending++;
|
||||
|
||||
// Don't change name if muted
|
||||
if (cv_mute.value && !(server || IsPlayerAdmin(thirddisplayplayer)))
|
||||
CV_StealthSet(&cv_playername3, player_names[thirddisplayplayer]);
|
||||
else // Cleanup name if changing it
|
||||
CleanupPlayerName(thirddisplayplayer, cv_playername3.zstring);
|
||||
|
||||
// Don't change skin if the server doesn't want you to.
|
||||
if (!CanChangeSkin(thirddisplayplayer))
|
||||
CV_StealthSet(&cv_skin3, skins[players[thirddisplayplayer].skin].name);
|
||||
|
||||
// check if player has the skin loaded (cv_skin3 may have
|
||||
// the name of a skin that was available in the previous game)
|
||||
cv_skin3.value = R_SkinAvailable(cv_skin3.string);
|
||||
if (cv_skin3.value < 0)
|
||||
{
|
||||
CV_StealthSet(&cv_skin3, DEFAULTSKIN);
|
||||
cv_skin3.value = 0;
|
||||
}
|
||||
|
||||
// Finally write out the complete packet and send it off.
|
||||
WRITESTRINGN(p, cv_playername3.zstring, MAXPLAYERNAME);
|
||||
WRITEUINT8(p, (UINT8)cv_playercolor3.value);
|
||||
WRITEUINT8(p, (UINT8)cv_skin3.value);
|
||||
SendNetXCmd3(XD_NAMEANDCOLOR, buf, p - buf);
|
||||
}
|
||||
|
||||
static void SendNameAndColor4(void)
|
||||
{
|
||||
INT32 fourthplaya;
|
||||
INT32 fourthplaya = -1;
|
||||
XBOXSTATIC char buf[MAXPLAYERNAME+2];
|
||||
char *p;
|
||||
|
||||
if (splitscreen < 3)
|
||||
return; // can happen if skin4/color4/name4 changed
|
||||
|
||||
if (fourthdisplayplayer != consoleplayer)
|
||||
fourthplaya = fourthdisplayplayer;
|
||||
else // HACK
|
||||
else if (!netgame) // HACK
|
||||
fourthplaya = 3;
|
||||
|
||||
if (fourthplaya == -1)
|
||||
return;
|
||||
|
||||
p = buf;
|
||||
|
||||
// normal player colors
|
||||
if (G_GametypeHasTeams())
|
||||
{
|
||||
|
@ -1610,7 +1679,32 @@ static void SendNameAndColor4(void)
|
|||
return;
|
||||
}
|
||||
|
||||
// Don't actually send anything because splitscreen isn't actually allowed in netgames anyway!
|
||||
snac4pending++;
|
||||
|
||||
// Don't change name if muted
|
||||
if (cv_mute.value && !(server || IsPlayerAdmin(fourthdisplayplayer)))
|
||||
CV_StealthSet(&cv_playername4, player_names[fourthdisplayplayer]);
|
||||
else // Cleanup name if changing it
|
||||
CleanupPlayerName(fourthdisplayplayer, cv_playername4.zstring);
|
||||
|
||||
// Don't change skin if the server doesn't want you to.
|
||||
if (!CanChangeSkin(fourthdisplayplayer))
|
||||
CV_StealthSet(&cv_skin4, skins[players[fourthdisplayplayer].skin].name);
|
||||
|
||||
// check if player has the skin loaded (cv_skin4 may have
|
||||
// the name of a skin that was available in the previous game)
|
||||
cv_skin4.value = R_SkinAvailable(cv_skin4.string);
|
||||
if (cv_skin4.value < 0)
|
||||
{
|
||||
CV_StealthSet(&cv_skin4, DEFAULTSKIN);
|
||||
cv_skin4.value = 0;
|
||||
}
|
||||
|
||||
// Finally write out the complete packet and send it off.
|
||||
WRITESTRINGN(p, cv_playername4.zstring, MAXPLAYERNAME);
|
||||
WRITEUINT8(p, (UINT8)cv_playercolor4.value);
|
||||
WRITEUINT8(p, (UINT8)cv_skin4.value);
|
||||
SendNetXCmd4(XD_NAMEANDCOLOR, buf, p - buf);
|
||||
}
|
||||
|
||||
static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
||||
|
@ -2010,16 +2104,20 @@ void D_SetupVote(void)
|
|||
|
||||
void D_ModifyClientVote(SINT8 voted, UINT8 splitplayer)
|
||||
{
|
||||
char buf[1];
|
||||
char buf[2];
|
||||
char *p = buf;
|
||||
UINT8 player = consoleplayer;
|
||||
|
||||
if (splitplayer > 0) // Don't actually send anything for splitscreen
|
||||
votes[splitplayer] = voted;
|
||||
else
|
||||
{
|
||||
WRITESINT8(p, voted);
|
||||
SendNetXCmd(XD_MODIFYVOTE, &buf, 1);
|
||||
}
|
||||
if (splitplayer == 1)
|
||||
player = secondarydisplayplayer;
|
||||
else if (splitplayer == 2)
|
||||
player = thirddisplayplayer;
|
||||
else if (splitplayer == 3)
|
||||
player = fourthdisplayplayer;
|
||||
|
||||
WRITESINT8(p, voted);
|
||||
WRITEUINT8(p, player);
|
||||
SendNetXCmd(XD_MODIFYVOTE, &buf, 2);
|
||||
}
|
||||
|
||||
void D_PickVote(void)
|
||||
|
@ -2388,11 +2486,12 @@ static void Command_Suicide(void)
|
|||
}*/
|
||||
|
||||
// Retry is quicker. Probably should force people to use it.
|
||||
if (!(netgame || multiplayer))
|
||||
// nope, this is srb2kart - a complete retry is overkill
|
||||
/*if (!(netgame || multiplayer))
|
||||
{
|
||||
CONS_Printf(M_GetText("You can't use this in Single Player! Use \"retry\" instead.\n"));
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
SendNetXCmd(XD_SUICIDE, &buf, 4);
|
||||
}
|
||||
|
@ -3217,11 +3316,11 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
|
|||
CONS_Printf(M_GetText("%s switched to the %c%s%c.\n"), player_names[playernum], '\x84', M_GetText("Blue Team"), '\x80');
|
||||
}
|
||||
else if (NetPacket.packet.newteam == 3)
|
||||
/*CONS_Printf(M_GetText("%s entered the game.\n"), player_names[playernum])*/;
|
||||
CON_LogMessage(va(M_GetText("%s entered the game.\n"), player_names[playernum]));
|
||||
else if (players[playernum].pflags & PF_WANTSTOJOIN)
|
||||
players[playernum].pflags &= ~PF_WANTSTOJOIN;
|
||||
else
|
||||
CONS_Printf(M_GetText("%s became a spectator.\n"), player_names[playernum]);
|
||||
CON_LogMessage(va(M_GetText("%s became a spectator.\n"), player_names[playernum]));
|
||||
|
||||
//reset view if you are changed, or viewing someone who was changed.
|
||||
if (playernum == consoleplayer || displayplayer == playernum)
|
||||
|
@ -4635,7 +4734,10 @@ static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum)
|
|||
static void Got_ModifyVotecmd(UINT8 **cp, INT32 playernum)
|
||||
{
|
||||
SINT8 voted = READSINT8(*cp);
|
||||
votes[playernum] = voted;
|
||||
UINT8 p = READUINT8(*cp);
|
||||
|
||||
(void)playernum;
|
||||
votes[p] = voted;
|
||||
}
|
||||
|
||||
static void Got_PickVotecmd(UINT8 **cp, INT32 playernum)
|
||||
|
@ -4792,10 +4894,10 @@ void Command_Retry_f(void)
|
|||
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"));
|
||||
else if (!&players[consoleplayer] || players[consoleplayer].lives <= 1)
|
||||
/*else if (!&players[consoleplayer] || players[consoleplayer].lives <= 1)
|
||||
CONS_Printf(M_GetText("You can't retry without any lives remaining!\n"));
|
||||
else if (G_IsSpecialStage(gamemap))
|
||||
CONS_Printf(M_GetText("You can't retry special stages!\n"));
|
||||
CONS_Printf(M_GetText("You can't retry special stages!\n"));*/
|
||||
else
|
||||
{
|
||||
M_ClearMenus(true);
|
||||
|
@ -5245,6 +5347,13 @@ static void KartFrantic_OnChange(void)
|
|||
|
||||
static void KartSpeed_OnChange(void)
|
||||
{
|
||||
if (!M_SecretUnlocked(SECRET_HARDSPEED) && cv_kartspeed.value == 2)
|
||||
{
|
||||
CONS_Printf(M_GetText("You haven't earned this yet.\n"));
|
||||
CV_StealthSetValue(&cv_kartspeed, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (G_RaceGametype())
|
||||
{
|
||||
if ((UINT8)cv_kartspeed.value != gamespeed && gamestate == GS_LEVEL && leveltime > starttime)
|
||||
|
|
|
@ -81,8 +81,6 @@ extern consvar_t cv_basenumlaps;
|
|||
extern UINT32 timelimitintics;
|
||||
extern consvar_t cv_allowexitlevel;
|
||||
|
||||
extern consvar_t cv_hazardlog;
|
||||
|
||||
extern consvar_t cv_autobalance;
|
||||
extern consvar_t cv_teamscramble;
|
||||
extern consvar_t cv_scrambleonchange;
|
||||
|
@ -134,7 +132,7 @@ extern consvar_t cv_karteliminatelast;
|
|||
extern consvar_t cv_votetime;
|
||||
|
||||
extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartdebugshrink, cv_kartdebugdistribution, cv_kartdebughuddrop;
|
||||
extern consvar_t cv_kartdebugcheckpoint;
|
||||
extern consvar_t cv_kartdebugcheckpoint, cv_kartdebugnodes;
|
||||
|
||||
extern consvar_t cv_itemfinder;
|
||||
|
||||
|
@ -197,9 +195,10 @@ typedef enum
|
|||
XD_SETUPVOTE, // 22
|
||||
XD_MODIFYVOTE, // 23
|
||||
XD_PICKVOTE, // 24
|
||||
XD_REMOVEPLAYER,// 25
|
||||
#ifdef HAVE_BLUA
|
||||
XD_LUACMD, // 25
|
||||
XD_LUAVAR, // 26
|
||||
XD_LUACMD, // 26
|
||||
XD_LUAVAR, // 27
|
||||
#endif
|
||||
MAXNETXCMD
|
||||
} netxcmd_t;
|
||||
|
|
|
@ -2431,6 +2431,8 @@ static void readunlockable(MYFILE *f, INT32 num)
|
|||
unlockables[num].type = SECRET_ENCORE;
|
||||
else if (fastcmp(word2, "HELLATTACK"))
|
||||
unlockables[num].type = SECRET_HELLATTACK;
|
||||
else if (fastcmp(word2, "HARDSPEED"))
|
||||
unlockables[num].type = SECRET_HARDSPEED;
|
||||
else
|
||||
unlockables[num].type = (INT16)i;
|
||||
}
|
||||
|
@ -6312,6 +6314,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_WIPEOUTTRAIL4",
|
||||
"S_WIPEOUTTRAIL5",
|
||||
|
||||
// Rocket sneaker
|
||||
"S_ROCKETSNEAKER_L",
|
||||
"S_ROCKETSNEAKER_R",
|
||||
"S_ROCKETSNEAKER_LVIBRATE",
|
||||
"S_ROCKETSNEAKER_RVIBRATE",
|
||||
|
||||
//{ Eggman Monitor
|
||||
"S_FAKEITEM1",
|
||||
"S_FAKEITEM2",
|
||||
|
@ -7286,6 +7294,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
"MT_DRIFTSPARK",
|
||||
"MT_DRIFTDUST",
|
||||
|
||||
"MT_ROCKETSNEAKER", // Rocket sneakers
|
||||
|
||||
"MT_FAKESHIELD",
|
||||
"MT_FAKEITEM",
|
||||
|
||||
|
@ -7297,7 +7307,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
|
||||
"MT_JAWZ", // Jawz stuff
|
||||
"MT_JAWZ_DUD",
|
||||
"MT_JAWZ_SHIELD",
|
||||
"MT_JAWZ_SHIELD",
|
||||
|
||||
"MT_PLAYERRETICULE", // Jawz reticule
|
||||
|
||||
|
|
|
@ -459,6 +459,7 @@ extern SINT8 battlewanted[4];
|
|||
extern tic_t wantedcalcdelay;
|
||||
extern tic_t indirectitemcooldown;
|
||||
extern tic_t mapreset;
|
||||
extern UINT8 nospectategrief;
|
||||
|
||||
extern boolean legitimateexit;
|
||||
extern boolean comebackshowninfo;
|
||||
|
|
28
src/g_game.c
28
src/g_game.c
|
@ -265,6 +265,7 @@ SINT8 battlewanted[4]; // WANTED players in battle, worth x2 points
|
|||
tic_t wantedcalcdelay; // Time before it recalculates WANTED
|
||||
tic_t indirectitemcooldown; // Cooldown before any more Shrink, SPB, or any other item that works indirectly is awarded
|
||||
tic_t mapreset; // Map reset delay when enough players have joined an empty game
|
||||
UINT8 nospectategrief; // How many players need to be in-game to eliminate last; for preventing spectate griefing
|
||||
|
||||
// Client-sided, unsynched variables (NEVER use in anything that needs to be synced with other players)
|
||||
boolean legitimateexit; // Did this client actually finish the match?
|
||||
|
@ -2098,10 +2099,12 @@ void G_Ticker(boolean run)
|
|||
G_ClearRetryFlag();
|
||||
|
||||
// Costs a life to retry ... unless the player in question is dead already.
|
||||
if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE)
|
||||
/*if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE)
|
||||
players[consoleplayer].lives -= 1;
|
||||
|
||||
G_DoReborn(consoleplayer);
|
||||
G_DoReborn(consoleplayer);*/
|
||||
|
||||
D_MapChange(gamemap, gametype, cv_kartencore.value, true, 1, false, false);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
@ -2933,7 +2936,7 @@ void G_DoReborn(INT32 playernum)
|
|||
if (oldmo)
|
||||
G_ChangePlayerReferences(oldmo, players[playernum].mo);
|
||||
}
|
||||
else if (countdowntimeup || (!multiplayer && gametype == GT_COOP))
|
||||
/*else if (countdowntimeup || (!multiplayer && !modeattacking))
|
||||
{
|
||||
// reload the level from scratch
|
||||
if (countdowntimeup)
|
||||
|
@ -3002,7 +3005,7 @@ void G_DoReborn(INT32 playernum)
|
|||
#ifdef HAVE_BLUA
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}*/
|
||||
else
|
||||
{
|
||||
// respawn at the start
|
||||
|
@ -3049,7 +3052,7 @@ void G_ExitLevel(void)
|
|||
}
|
||||
|
||||
if (netgame || multiplayer)
|
||||
CONS_Printf(M_GetText("The round has ended.\n"));
|
||||
CON_LogMessage(M_GetText("The round has ended.\n"));
|
||||
|
||||
// Remove CEcho text on round end.
|
||||
HU_DoCEcho("");
|
||||
|
@ -3117,7 +3120,7 @@ boolean G_GametypeHasSpectators(void)
|
|||
#if 0
|
||||
return (gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE);
|
||||
#else
|
||||
return (!splitscreen);//true;
|
||||
return (netgame); //true
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -4337,13 +4340,13 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool
|
|||
{
|
||||
char *title = G_BuildMapTitle(gamemap);
|
||||
|
||||
CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap));
|
||||
CON_LogMessage(va(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)));
|
||||
if (title)
|
||||
{
|
||||
CONS_Printf(": %s", title);
|
||||
CON_LogMessage(va(": %s", title));
|
||||
Z_Free(title);
|
||||
}
|
||||
CONS_Printf("\"\n");
|
||||
CON_LogMessage("\"\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4494,6 +4497,13 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
|||
|
||||
G_CopyTiccmd(cmd, &oldcmd, 1);
|
||||
|
||||
// SRB2kart: Copy-pasted from ticcmd building, removes that crappy demo cam
|
||||
if (((players[displayplayer].mo && players[displayplayer].speed > 0) // Moving
|
||||
|| (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn
|
||||
|| (players[displayplayer].spectator || objectplacing)) // Not a physical player
|
||||
&& !(players[displayplayer].kartstuff[k_spinouttimer] && players[displayplayer].kartstuff[k_sneakertimer])) // Spinning and boosting cancels out spinout
|
||||
localangle += (cmd->angleturn<<16);
|
||||
|
||||
if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER)
|
||||
{
|
||||
// end of demo data stream
|
||||
|
|
|
@ -62,6 +62,7 @@ extern consvar_t cv_turnaxis2,cv_moveaxis2,cv_brakeaxis2,cv_aimaxis2,cv_lookaxis
|
|||
extern consvar_t cv_turnaxis3,cv_moveaxis3,cv_brakeaxis3,cv_aimaxis3,cv_lookaxis3,cv_fireaxis3,cv_driftaxis3;
|
||||
extern consvar_t cv_turnaxis4,cv_moveaxis4,cv_brakeaxis4,cv_aimaxis4,cv_lookaxis4,cv_fireaxis4,cv_driftaxis4;
|
||||
extern consvar_t cv_ghost_besttime, cv_ghost_bestlap, cv_ghost_last, cv_ghost_guest, cv_ghost_staff;
|
||||
extern consvar_t cv_splitplayers;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -188,7 +189,6 @@ void G_StopMetalDemo(void);
|
|||
ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void);
|
||||
void G_StopDemo(void);
|
||||
boolean G_CheckDemoStatus(void);
|
||||
char *G_DemoPlayerName(char *defdemoname);
|
||||
|
||||
boolean G_IsSpecialStage(INT32 mapnum);
|
||||
boolean G_GametypeUsesLives(void);
|
||||
|
|
|
@ -1321,21 +1321,21 @@ void G_Controldefault(void)
|
|||
gamecontrolbis[gc_accelerate ][0] = KEY_2JOY1+0; // A
|
||||
gamecontrolbis[gc_lookback ][0] = KEY_2JOY1+1; // X
|
||||
gamecontrolbis[gc_brake ][0] = KEY_2JOY1+2; // B
|
||||
gamecontrolbis[gc_fire ][0] = KEY_2JOY1+4; // LB
|
||||
gamecontrolbis[gc_fire ][0] = KEY_2JOY1+4; // LB
|
||||
gamecontrolbis[gc_drift ][0] = KEY_2JOY1+5; // RB
|
||||
|
||||
// Player 3 controls
|
||||
gamecontrol3[gc_accelerate ][0] = KEY_3JOY1+0; // A
|
||||
gamecontrol3[gc_lookback ][0] = KEY_3JOY1+1; // X
|
||||
gamecontrol3[gc_brake ][0] = KEY_3JOY1+2; // B
|
||||
gamecontrol3[gc_fire ][0] = KEY_3JOY1+4; // LB
|
||||
gamecontrol3[gc_fire ][0] = KEY_3JOY1+4; // LB
|
||||
gamecontrol3[gc_drift ][0] = KEY_3JOY1+5; // RB
|
||||
|
||||
// Player 4 controls
|
||||
gamecontrol4[gc_accelerate ][0] = KEY_4JOY1+0; // A
|
||||
gamecontrol4[gc_lookback ][0] = KEY_4JOY1+1; // X
|
||||
gamecontrol4[gc_brake ][0] = KEY_4JOY1+2; // B
|
||||
gamecontrol4[gc_fire ][0] = KEY_4JOY1+4; // LB
|
||||
gamecontrol4[gc_fire ][0] = KEY_4JOY1+4; // LB
|
||||
gamecontrol4[gc_drift ][0] = KEY_4JOY1+5; // RB
|
||||
}
|
||||
//#endif
|
||||
|
|
111
src/hu_stuff.c
111
src/hu_stuff.c
|
@ -1066,6 +1066,26 @@ boolean HU_Responder(event_t *ev)
|
|||
|
||||
// only KeyDown events now...
|
||||
|
||||
// Shoot, to prevent P1 chatting from ruining the game for everyone else, it's either:
|
||||
// A. completely disallow opening chat entirely in online splitscreen
|
||||
// or B. iterate through all controls to make sure it's bound to player 1 before eating
|
||||
// You can see which one I chose.
|
||||
// (Unless if you're sharing a keyboard, since you probably establish when you start chatting that you have dibs on it...)
|
||||
// (Ahhh, the good ol days when I was a kid who couldn't afford an extra USB controller...)
|
||||
|
||||
if (ev->data1 >= KEY_MOUSE1)
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < num_gamecontrols; i++)
|
||||
{
|
||||
if (gamecontrol[i][0] == ev->data1 || gamecontrol[i][1] == ev->data1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == num_gamecontrols)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!chat_on)
|
||||
{
|
||||
// enter chat mode
|
||||
|
@ -1269,6 +1289,7 @@ static void HU_drawMiniChat(void)
|
|||
{
|
||||
INT32 x = chatx+2;
|
||||
INT32 charwidth = 4, charheight = 6;
|
||||
INT32 boxw = cv_chatwidth.value;
|
||||
INT32 dx = 0, dy = 0;
|
||||
size_t i = chat_nummsg_min;
|
||||
boolean prev_linereturn = false; // a hack to prevent double \n while I have no idea why they happen in the first place.
|
||||
|
@ -1280,9 +1301,12 @@ static void HU_drawMiniChat(void)
|
|||
if (!chat_nummsg_min)
|
||||
return; // needless to say it's useless to do anything if we don't have anything to draw.
|
||||
|
||||
if (splitscreen > 1)
|
||||
boxw = max(64, boxw/2);
|
||||
|
||||
for (; i>0; i--)
|
||||
{
|
||||
const char *msg = CHAT_WordWrap(x+2, cv_chatwidth.value-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]);
|
||||
const char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]);
|
||||
size_t j = 0;
|
||||
INT32 linescount = 0;
|
||||
|
||||
|
@ -1315,7 +1339,7 @@ static void HU_drawMiniChat(void)
|
|||
}
|
||||
prev_linereturn = false;
|
||||
dx += charwidth;
|
||||
if (dx >= cv_chatwidth.value)
|
||||
if (dx >= boxw)
|
||||
{
|
||||
dx = 0;
|
||||
linescount += 1;
|
||||
|
@ -1326,7 +1350,17 @@ static void HU_drawMiniChat(void)
|
|||
msglines += linescount+1;
|
||||
}
|
||||
|
||||
y = chaty - charheight*(msglines+1) - (cv_kartspeedometer.value ? 16 : 0);
|
||||
y = chaty - charheight*(msglines+1);
|
||||
|
||||
if (splitscreen)
|
||||
{
|
||||
y -= BASEVIDHEIGHT/2;
|
||||
if (splitscreen > 1)
|
||||
y += 16;
|
||||
}
|
||||
else
|
||||
y -= (cv_kartspeedometer.value ? 16 : 0);
|
||||
|
||||
dx = 0;
|
||||
dy = 0;
|
||||
i = 0;
|
||||
|
@ -1338,7 +1372,7 @@ static void HU_drawMiniChat(void)
|
|||
INT32 timer = ((cv_chattime.value*TICRATE)-chat_timers[i]) - cv_chattime.value*TICRATE+9; // see below...
|
||||
INT32 transflag = (timer >= 0 && timer <= 9) ? (timer*V_10TRANS) : 0; // you can make bad jokes out of this one.
|
||||
size_t j = 0;
|
||||
const char *msg = CHAT_WordWrap(x+2, cv_chatwidth.value-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it.
|
||||
const char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it.
|
||||
UINT8 *colormap = NULL;
|
||||
|
||||
while(msg[j]) // iterate through msg
|
||||
|
@ -1376,7 +1410,7 @@ static void HU_drawMiniChat(void)
|
|||
|
||||
dx += charwidth;
|
||||
prev_linereturn = false;
|
||||
if (dx >= cv_chatwidth.value)
|
||||
if (dx >= boxw)
|
||||
{
|
||||
dx = 0;
|
||||
dy += charheight;
|
||||
|
@ -1397,6 +1431,7 @@ static void HU_drawMiniChat(void)
|
|||
static void HU_drawChatLog(INT32 offset)
|
||||
{
|
||||
INT32 charwidth = 4, charheight = 6;
|
||||
INT32 boxw = cv_chatwidth.value, boxh = cv_chatheight.value;
|
||||
INT32 x = chatx+2, y, dx = 0, dy = 0;
|
||||
UINT32 i = 0;
|
||||
INT32 chat_topy, chat_bottomy;
|
||||
|
@ -1406,17 +1441,34 @@ static void HU_drawChatLog(INT32 offset)
|
|||
if (chat_scroll > chat_maxscroll)
|
||||
chat_scroll = chat_maxscroll;
|
||||
|
||||
y = chaty - offset*charheight - (chat_scroll*charheight) - cv_chatheight.value*charheight - 12 - (cv_kartspeedometer.value ? 16 : 0);
|
||||
chat_topy = y + chat_scroll*charheight;
|
||||
chat_bottomy = chat_topy + cv_chatheight.value*charheight;
|
||||
if (splitscreen)
|
||||
{
|
||||
boxh = max(6, boxh/2);
|
||||
if (splitscreen > 1)
|
||||
boxw = max(64, boxw/2);
|
||||
}
|
||||
|
||||
V_DrawFillConsoleMap(chatx, chat_topy, cv_chatwidth.value, cv_chatheight.value*charheight +2, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); // log box
|
||||
y = chaty - offset*charheight - (chat_scroll*charheight) - boxh*charheight - 12;
|
||||
|
||||
if (splitscreen)
|
||||
{
|
||||
y -= BASEVIDHEIGHT/2;
|
||||
if (splitscreen > 1)
|
||||
y += 16;
|
||||
}
|
||||
else
|
||||
y -= (cv_kartspeedometer.value ? 16 : 0);
|
||||
|
||||
chat_topy = y + chat_scroll*charheight;
|
||||
chat_bottomy = chat_topy + boxh*charheight;
|
||||
|
||||
V_DrawFillConsoleMap(chatx, chat_topy, boxw, boxh*charheight +2, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); // log box
|
||||
|
||||
for (i=0; i<chat_nummsg_log; i++) // iterate through our chatlog
|
||||
{
|
||||
INT32 clrflag = 0;
|
||||
INT32 j = 0;
|
||||
const char *msg = CHAT_WordWrap(x+2, cv_chatwidth.value-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it.
|
||||
const char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it.
|
||||
UINT8 *colormap = NULL;
|
||||
while(msg[j]) // iterate through msg
|
||||
{
|
||||
|
@ -1448,7 +1500,7 @@ static void HU_drawChatLog(INT32 offset)
|
|||
}
|
||||
|
||||
dx += charwidth;
|
||||
if (dx >= cv_chatwidth.value-charwidth-2 && i<chat_nummsg_log && msg[j] >= HU_FONTSTART) // end of message shouldn't count, nor should invisible characters!!!!
|
||||
if (dx >= boxw-charwidth-2 && i<chat_nummsg_log && msg[j] >= HU_FONTSTART) // end of message shouldn't count, nor should invisible characters!!!!
|
||||
{
|
||||
dx = 0;
|
||||
dy += charheight;
|
||||
|
@ -1466,10 +1518,10 @@ static void HU_drawChatLog(INT32 offset)
|
|||
|
||||
// getmaxscroll through a lazy hack. We do all these loops, so let's not do more loops that are gonna lag the game more. :P
|
||||
chat_maxscroll = (dy/charheight); // welcome to C, we don't know what min() and max() are.
|
||||
if (chat_maxscroll <= (UINT32)cv_chatheight.value)
|
||||
if (chat_maxscroll <= (UINT32)boxh)
|
||||
chat_maxscroll = 0;
|
||||
else
|
||||
chat_maxscroll -= cv_chatheight.value;
|
||||
chat_maxscroll -= boxh;
|
||||
|
||||
// if we're not bound by the time, autoscroll for next frame:
|
||||
if (atbottom)
|
||||
|
@ -1502,13 +1554,26 @@ static INT16 typelines = 1; // number of drawfill lines we need. it's some weird
|
|||
static void HU_DrawChat(void)
|
||||
{
|
||||
INT32 charwidth = 4, charheight = 6;
|
||||
INT32 t = 0, c = 0, y = chaty - (typelines*charheight) - (cv_kartspeedometer.value ? 16 : 0);
|
||||
INT32 boxw = cv_chatwidth.value;
|
||||
INT32 t = 0, c = 0, y = chaty - (typelines*charheight);
|
||||
UINT32 i = 0, saylen = strlen(w_chat); // You learn new things everyday!
|
||||
INT32 cflag = 0;
|
||||
const char *ntalk = "Say: ", *ttalk = "Team: ";
|
||||
const char *talk = ntalk;
|
||||
const char *mute = "Chat has been muted.";
|
||||
|
||||
if (splitscreen)
|
||||
{
|
||||
y -= BASEVIDHEIGHT/2;
|
||||
if (splitscreen > 1)
|
||||
{
|
||||
y += 16;
|
||||
boxw = max(64, boxw/2);
|
||||
}
|
||||
}
|
||||
else
|
||||
y -= (cv_kartspeedometer.value ? 16 : 0);
|
||||
|
||||
if (teamtalk)
|
||||
{
|
||||
talk = ttalk;
|
||||
|
@ -1527,7 +1592,7 @@ static void HU_DrawChat(void)
|
|||
cflag = V_GRAYMAP; // set text in gray if chat is muted.
|
||||
}
|
||||
|
||||
V_DrawFillConsoleMap(chatx, y-1, cv_chatwidth.value, (typelines*charheight), 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT);
|
||||
V_DrawFillConsoleMap(chatx, y-1, boxw, (typelines*charheight), 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT);
|
||||
|
||||
while (talk[i])
|
||||
{
|
||||
|
@ -1560,7 +1625,7 @@ static void HU_DrawChat(void)
|
|||
boolean skippedline = false;
|
||||
if (c_input == (i+1))
|
||||
{
|
||||
int cursorx = (c+charwidth < cv_chatwidth.value-charwidth) ? (chatx + 2 + c+charwidth) : (chatx+1); // we may have to go down.
|
||||
int cursorx = (c+charwidth < boxw-charwidth) ? (chatx + 2 + c+charwidth) : (chatx+1); // we may have to go down.
|
||||
int cursory = (cursorx != chatx+1) ? (y) : (y+charheight);
|
||||
if (hu_tick < 4)
|
||||
V_DrawChatCharacter(cursorx, cursory+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL);
|
||||
|
@ -1580,7 +1645,7 @@ static void HU_DrawChat(void)
|
|||
V_DrawChatCharacter(chatx + c + 2, y, w_chat[i++] | V_SNAPTOBOTTOM|V_SNAPTOLEFT | t, !cv_allcaps.value, NULL);
|
||||
|
||||
c += charwidth;
|
||||
if (c > cv_chatwidth.value-(charwidth*2) && !skippedline)
|
||||
if (c > boxw-(charwidth*2) && !skippedline)
|
||||
{
|
||||
c = 0;
|
||||
y += charheight;
|
||||
|
@ -1593,6 +1658,14 @@ static void HU_DrawChat(void)
|
|||
{
|
||||
INT32 count = 0;
|
||||
INT32 p_dispy = chaty - charheight -1;
|
||||
if (splitscreen)
|
||||
{
|
||||
p_dispy -= BASEVIDHEIGHT/2;
|
||||
if (splitscreen > 1)
|
||||
p_dispy += 16;
|
||||
}
|
||||
else
|
||||
p_dispy -= (cv_kartspeedometer.value ? 16 : 0);
|
||||
i = 0;
|
||||
for(i=0; (i<MAXPLAYERS); i++)
|
||||
{
|
||||
|
@ -1643,8 +1716,8 @@ static void HU_DrawChat(void)
|
|||
{
|
||||
char name[MAXPLAYERNAME+1];
|
||||
strlcpy(name, player_names[i], 7); // shorten name to 7 characters.
|
||||
V_DrawFillConsoleMap(chatx+ cv_chatwidth.value + 2, p_dispy- (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); // fill it like the chat so the text doesn't become hard to read because of the hud.
|
||||
V_DrawSmallString(chatx+ cv_chatwidth.value + 4, p_dispy- (6*count), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, va("\x82%d\x80 - %s", i, name));
|
||||
V_DrawFillConsoleMap(chatx+ boxw + 2, p_dispy- (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); // fill it like the chat so the text doesn't become hard to read because of the hud.
|
||||
V_DrawSmallString(chatx+ boxw + 4, p_dispy- (6*count), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, va("\x82%d\x80 - %s", i, name));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
|
44
src/info.c
44
src/info.c
|
@ -56,12 +56,12 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"SRBJ","SRBK","SRBL","SRBM","SRBN","SRBO",
|
||||
//SRB2kart Sprites
|
||||
"SPRG","BSPR","RNDM","RPOP","SGNS","FAST","DSHR","BOST","BOSM","KFRE",
|
||||
"KINV","KINF","WIPD","DRIF","DUST","FITM","BANA","ORBN","JAWZ","SSMN",
|
||||
"KRBM","BHOG","BHBM","SPBM","THNS","SINK","SITR","KBLN","DEZL","POKE",
|
||||
"AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM","SACO","CRAB",
|
||||
"SHAD","BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB","ARRO","ITEM",
|
||||
"ITMO","ITMI","ITMN","WANT","PBOM","RETI","AIDU","KSPK","LZI1","LZI2",
|
||||
"KLIT","VIEW"
|
||||
"KINV","KINF","WIPD","DRIF","DUST","RSHE","FITM","BANA","ORBN","JAWZ",
|
||||
"SSMN","KRBM","BHOG","BHBM","SPBM","THNS","SINK","SITR","KBLN","DEZL",
|
||||
"POKE","AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM","SACO",
|
||||
"CRAB","SHAD","BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB","ARRO",
|
||||
"ITEM","ITMO","ITMI","ITMN","WANT","PBOM","RETI","AIDU","KSPK","LZI1",
|
||||
"LZI2","KLIT","VIEW"
|
||||
};
|
||||
|
||||
// Doesn't work with g++, needs actionf_p1 (don't modify this comment)
|
||||
|
@ -2623,6 +2623,11 @@ state_t states[NUMSTATES] =
|
|||
{SPR_WIPD, 3, 3, {NULL}, 0, 0, S_WIPEOUTTRAIL5}, // S_WIPEOUTTRAIL4
|
||||
{SPR_WIPD, 4, 3, {NULL}, 0, 0, S_NULL}, // S_WIPEOUTTRAIL5
|
||||
|
||||
{SPR_RSHE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_ROCKETSNEAKER_L
|
||||
{SPR_RSHE, 1, -1, {NULL}, 0, 0, S_NULL}, // S_ROCKETSNEAKER_R
|
||||
{SPR_RSHE, 2, -1, {NULL}, 0, 0, S_NULL}, // S_ROCKETSNEAKER_LVIBRATE
|
||||
{SPR_RSHE, 3, -1, {NULL}, 0, 0, S_NULL}, // S_ROCKETSNEAKER_RVIBRATE
|
||||
|
||||
{SPR_FITM, FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM2}, // S_FAKEITEM1
|
||||
{SPR_FITM, 1|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM3}, // S_FAKEITEM2
|
||||
{SPR_FITM, 2|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM4}, // S_FAKEITEM3
|
||||
|
@ -14795,6 +14800,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_ROCKETSNEAKER
|
||||
-1, // doomednum
|
||||
S_ROCKETSNEAKER_L, // spawnstate
|
||||
1, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_tossed, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_s3k5d, // deathsound
|
||||
0, // speed
|
||||
16*FRACUNIT, // radius
|
||||
16*FRACUNIT, // height
|
||||
0, // display offset
|
||||
0, // mass
|
||||
0, // damage
|
||||
sfx_s3kc0s, // activesound
|
||||
MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_FAKESHIELD
|
||||
-1, // doomednum
|
||||
S_FAKEITEM1, // spawnstate
|
||||
|
|
|
@ -597,6 +597,7 @@ typedef enum sprite
|
|||
SPR_DUST, // Drift Dust
|
||||
|
||||
// Kart Items
|
||||
SPR_RSHE, // Rocket sneaker
|
||||
SPR_FITM, // Eggman Monitor
|
||||
SPR_BANA, // Banana Peel
|
||||
SPR_ORBN, // Orbinaut
|
||||
|
@ -3155,6 +3156,12 @@ typedef enum state
|
|||
S_WIPEOUTTRAIL4,
|
||||
S_WIPEOUTTRAIL5,
|
||||
|
||||
// Rocket sneaker
|
||||
S_ROCKETSNEAKER_L,
|
||||
S_ROCKETSNEAKER_R,
|
||||
S_ROCKETSNEAKER_LVIBRATE,
|
||||
S_ROCKETSNEAKER_RVIBRATE,
|
||||
|
||||
//{ Eggman Monitor
|
||||
S_FAKEITEM1,
|
||||
S_FAKEITEM2,
|
||||
|
@ -4146,6 +4153,8 @@ typedef enum mobj_type
|
|||
MT_DRIFTSPARK,
|
||||
MT_DRIFTDUST,
|
||||
|
||||
MT_ROCKETSNEAKER,
|
||||
|
||||
MT_FAKESHIELD,
|
||||
MT_FAKEITEM,
|
||||
|
||||
|
|
255
src/k_kart.c
255
src/k_kart.c
|
@ -29,6 +29,7 @@
|
|||
// battlewanted is an array of the WANTED player nums, -1 for no player in that slot
|
||||
// indirectitemcooldown is timer before anyone's allowed another Shrink/SPB
|
||||
// mapreset is set when enough players fill an empty server
|
||||
// nospectategrief is the players in-game needed to eliminate the person in last
|
||||
|
||||
|
||||
//{ SRB2kart Color Code
|
||||
|
@ -431,6 +432,7 @@ void K_RegisterKartStuff(void)
|
|||
CV_RegisterVar(&cv_kartdebughuddrop);
|
||||
|
||||
CV_RegisterVar(&cv_kartdebugcheckpoint);
|
||||
CV_RegisterVar(&cv_kartdebugnodes);
|
||||
}
|
||||
|
||||
//}
|
||||
|
@ -892,7 +894,35 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd)
|
|||
|
||||
// This makes the roulette produce the random noises.
|
||||
if ((player->kartstuff[k_itemroulette] % 3) == 1 && P_IsLocalPlayer(player))
|
||||
S_StartSound(NULL, sfx_mkitm1 + ((player->kartstuff[k_itemroulette] / 3) % 8));
|
||||
{
|
||||
#define PLAYROULETTESND S_StartSound(NULL, sfx_mkitm1 + ((player->kartstuff[k_itemroulette] / 3) % 8));
|
||||
if (splitscreen)
|
||||
{
|
||||
if (players[displayplayer].kartstuff[k_itemroulette])
|
||||
{
|
||||
if (player == &players[displayplayer])
|
||||
PLAYROULETTESND;
|
||||
}
|
||||
else if (players[secondarydisplayplayer].kartstuff[k_itemroulette])
|
||||
{
|
||||
if (player == &players[secondarydisplayplayer])
|
||||
PLAYROULETTESND;
|
||||
}
|
||||
else if (players[thirddisplayplayer].kartstuff[k_itemroulette] && splitscreen > 1)
|
||||
{
|
||||
if (player == &players[thirddisplayplayer])
|
||||
PLAYROULETTESND;
|
||||
}
|
||||
else if (players[fourthdisplayplayer].kartstuff[k_itemroulette] && splitscreen > 2)
|
||||
{
|
||||
if (player == &players[fourthdisplayplayer])
|
||||
PLAYROULETTESND;
|
||||
}
|
||||
}
|
||||
else
|
||||
PLAYROULETTESND;
|
||||
#undef PLAYROULETTESND
|
||||
}
|
||||
|
||||
roulettestop = TICRATE + (3*(pingame - player->kartstuff[k_position]));
|
||||
|
||||
|
@ -1239,7 +1269,7 @@ static void K_UpdateOffroad(player_t *player)
|
|||
}
|
||||
|
||||
// These have to go earlier than its sisters because of K_RespawnChecker...
|
||||
static void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master)
|
||||
void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master)
|
||||
{
|
||||
// flipping
|
||||
mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP)|(master->eflags & MFE_VERTICALFLIP);
|
||||
|
@ -2046,13 +2076,8 @@ void K_StealBumper(player_t *player, player_t *victim, boolean force)
|
|||
}
|
||||
}
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
if (player->kartstuff[k_bumper] <= 0)
|
||||
CONS_Printf(M_GetText("%s is back in the game!\n"), player_names[player-players]);
|
||||
else if (cv_hazardlog.value)
|
||||
CONS_Printf(M_GetText("%s stole a bumper from %s!\n"), player_names[player-players], player_names[victim-players]);
|
||||
}
|
||||
if (netgame && player->kartstuff[k_bumper] <= 0)
|
||||
CONS_Printf(M_GetText("%s is back in the game!\n"), player_names[player-players]);
|
||||
|
||||
newbumper = player->kartstuff[k_bumper];
|
||||
if (newbumper <= 1)
|
||||
|
@ -2971,35 +2996,66 @@ static void K_DoHyudoroSteal(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
void K_DoSneaker(player_t *player, boolean doPFlag)
|
||||
void K_DoSneaker(player_t *player, INT32 type)
|
||||
{
|
||||
const fixed_t prevboost = player->kartstuff[k_speedboost];
|
||||
fixed_t intendedboost;
|
||||
|
||||
switch (gamespeed)
|
||||
{
|
||||
case 0:
|
||||
intendedboost = 53740+768;
|
||||
break;
|
||||
case 2:
|
||||
intendedboost = 17294+768;
|
||||
break;
|
||||
default:
|
||||
intendedboost = 32768;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3)
|
||||
{
|
||||
S_StartSound(player->mo, sfx_cdfm01);
|
||||
K_SpawnDashDustRelease(player);
|
||||
if (intendedboost > player->kartstuff[k_speedboost])
|
||||
player->kartstuff[k_destboostcam] = FixedMul(FRACUNIT, FixedDiv((intendedboost - player->kartstuff[k_speedboost]), intendedboost));
|
||||
}
|
||||
|
||||
if (!player->kartstuff[k_sneakertimer])
|
||||
{
|
||||
mobj_t *overlay = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BOOSTFLAME);
|
||||
P_SetTarget(&overlay->target, player->mo);
|
||||
overlay->destscale = player->mo->scale;
|
||||
P_SetScale(overlay, player->mo->scale);
|
||||
if (type == 2)
|
||||
{
|
||||
if (player->mo->hnext)
|
||||
{
|
||||
mobj_t *cur = player->mo->hnext;
|
||||
while (cur && !P_MobjWasRemoved(cur))
|
||||
{
|
||||
if (!cur->tracer)
|
||||
{
|
||||
mobj_t *overlay = P_SpawnMobj(cur->x, cur->y, cur->z, MT_BOOSTFLAME);
|
||||
P_SetTarget(&overlay->target, cur);
|
||||
P_SetTarget(&cur->tracer, overlay);
|
||||
P_SetScale(overlay, (overlay->destscale = 3*cur->scale/4));
|
||||
}
|
||||
cur = cur->hnext;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj_t *overlay = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BOOSTFLAME);
|
||||
P_SetTarget(&overlay->target, player->mo);
|
||||
P_SetScale(overlay, (overlay->destscale = player->mo->scale));
|
||||
}
|
||||
}
|
||||
|
||||
player->kartstuff[k_sneakertimer] = sneakertime;
|
||||
|
||||
if (doPFlag)
|
||||
if (type != 0)
|
||||
{
|
||||
player->pflags |= PF_ATTACKDOWN;
|
||||
K_PlayBoostTaunt(player->mo);
|
||||
}
|
||||
|
||||
K_GetKartBoostPower(player);
|
||||
if (player->kartstuff[k_speedboost] > prevboost)
|
||||
player->kartstuff[k_destboostcam] = FRACUNIT;
|
||||
}
|
||||
|
||||
static void K_DoShrink(player_t *player)
|
||||
|
@ -3178,6 +3234,7 @@ void K_DropHnextList(player_t *player)
|
|||
break;
|
||||
// intentionally do nothing
|
||||
case MT_SINK_SHIELD:
|
||||
case MT_ROCKETSNEAKER:
|
||||
return;
|
||||
default:
|
||||
continue;
|
||||
|
@ -3525,6 +3582,93 @@ static void K_MoveHeldObjects(player_t *player)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case MT_ROCKETSNEAKER: // Special rocket sneaker stuff
|
||||
{
|
||||
mobj_t *cur = player->mo->hnext;
|
||||
INT32 num = 0;
|
||||
|
||||
while (cur && !P_MobjWasRemoved(cur))
|
||||
{
|
||||
const fixed_t radius = FixedHypot(player->mo->radius, player->mo->radius) + FixedHypot(cur->radius, cur->radius);
|
||||
boolean vibrate = ((leveltime & 1) && !cur->tracer);
|
||||
angle_t angoffset;
|
||||
fixed_t targx, targy, targz;
|
||||
|
||||
cur->flags &= ~MF_NOCLIPTHING;
|
||||
|
||||
if (player->kartstuff[k_rocketsneakertimer] <= TICRATE && (leveltime & 1))
|
||||
cur->flags2 |= MF2_DONTDRAW;
|
||||
else
|
||||
cur->flags2 &= ~MF2_DONTDRAW;
|
||||
|
||||
if (num & 1)
|
||||
P_SetMobjStateNF(cur, (vibrate ? S_ROCKETSNEAKER_LVIBRATE : S_ROCKETSNEAKER_L));
|
||||
else
|
||||
P_SetMobjStateNF(cur, (vibrate ? S_ROCKETSNEAKER_RVIBRATE : S_ROCKETSNEAKER_R));
|
||||
|
||||
if (!player->kartstuff[k_rocketsneakertimer] || cur->extravalue2 || !cur->health)
|
||||
{
|
||||
num = (num+1) % 2;
|
||||
cur = cur->hnext;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cur->extravalue1 < radius)
|
||||
cur->extravalue1 += FixedMul(P_AproxDistance(cur->extravalue1, radius), FRACUNIT/12);
|
||||
if (cur->extravalue1 > radius)
|
||||
cur->extravalue1 = radius;
|
||||
|
||||
// Shrink your items if the player shrunk too.
|
||||
P_SetScale(cur, (cur->destscale = FixedMul(FixedDiv(cur->extravalue1, radius), player->mo->scale)));
|
||||
|
||||
#if 1
|
||||
{
|
||||
angle_t input = player->mo->angle - cur->angle;
|
||||
boolean invert = (input > ANGLE_180);
|
||||
if (invert)
|
||||
input = InvAngle(input);
|
||||
|
||||
input = FixedAngle(AngleFixed(input)/4);
|
||||
if (invert)
|
||||
input = InvAngle(input);
|
||||
|
||||
cur->angle = cur->angle + input;
|
||||
}
|
||||
#else
|
||||
cur->angle = player->mo->angle;
|
||||
#endif
|
||||
|
||||
angoffset = ANGLE_90 + (ANGLE_180 * num);
|
||||
|
||||
targx = player->mo->x + P_ReturnThrustX(cur, cur->angle + angoffset, cur->extravalue1);
|
||||
targy = player->mo->y + P_ReturnThrustY(cur, cur->angle + angoffset, cur->extravalue1);
|
||||
|
||||
{ // bobbing, copy pasted from my kimokawaiii entry
|
||||
const fixed_t pi = (22<<FRACBITS) / 7; // loose approximation, this doesn't need to be incredibly precise
|
||||
fixed_t sine = 8 * FINESINE((((2*pi*(4*TICRATE)) * leveltime)>>ANGLETOFINESHIFT) & FINEMASK);
|
||||
targz = (player->mo->z + (player->mo->height/2)) + sine;
|
||||
}
|
||||
|
||||
if (cur->tracer)
|
||||
{
|
||||
fixed_t diffx, diffy, diffz;
|
||||
|
||||
diffx = targx - cur->x;
|
||||
diffy = targy - cur->y;
|
||||
diffz = targz - cur->z;
|
||||
|
||||
P_TeleportMove(cur->tracer, cur->tracer->x + diffx + P_ReturnThrustX(cur, cur->angle + angoffset, 6*cur->scale),
|
||||
cur->tracer->y + diffy + P_ReturnThrustY(cur, cur->angle + angoffset, 6*cur->scale), cur->tracer->z + diffz);
|
||||
P_SetScale(cur->tracer, (cur->tracer->destscale = 3*cur->scale/4));
|
||||
}
|
||||
|
||||
P_TeleportMove(cur, targx, targy, targz);
|
||||
|
||||
num = (num+1) % 2;
|
||||
cur = cur->hnext;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -4543,9 +4687,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
else if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO
|
||||
&& player->kartstuff[k_rocketsneakertimer] > 1)
|
||||
{
|
||||
K_DoSneaker(player, true);
|
||||
K_DoSneaker(player, 2);
|
||||
K_PlayBoostTaunt(player->mo);
|
||||
player->kartstuff[k_rocketsneakertimer] -= 5;
|
||||
player->kartstuff[k_rocketsneakertimer] -= 2*TICRATE;
|
||||
if (player->kartstuff[k_rocketsneakertimer] < 1)
|
||||
player->kartstuff[k_rocketsneakertimer] = 1;
|
||||
}
|
||||
|
@ -4560,7 +4704,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
case KITEM_SNEAKER:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO)
|
||||
{
|
||||
K_DoSneaker(player, true);
|
||||
K_DoSneaker(player, 1);
|
||||
K_PlayBoostTaunt(player->mo);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
}
|
||||
|
@ -4569,10 +4713,33 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO
|
||||
&& player->kartstuff[k_rocketsneakertimer] == 0)
|
||||
{
|
||||
K_DoSneaker(player, true);
|
||||
INT32 moloop;
|
||||
mobj_t *mo = NULL;
|
||||
mobj_t *prev = player->mo;
|
||||
|
||||
K_PlayBoostTaunt(player->mo);
|
||||
player->kartstuff[k_rocketsneakertimer] = itemtime;
|
||||
//player->kartstuff[k_itemheld] = 1;
|
||||
S_StartSound(player->mo, sfx_s3k3a);
|
||||
|
||||
//K_DoSneaker(player, 2);
|
||||
|
||||
player->kartstuff[k_rocketsneakertimer] = (itemtime*3);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_UpdateHnextList(player, true);
|
||||
|
||||
for (moloop = 0; moloop < 2; moloop++)
|
||||
{
|
||||
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_ROCKETSNEAKER);
|
||||
mo->flags |= MF_NOCLIPTHING;
|
||||
mo->angle = player->mo->angle;
|
||||
mo->threshold = 10;
|
||||
mo->movecount = moloop%2;
|
||||
mo->movedir = mo->lastlook = moloop+1;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
P_SetTarget(&mo->hprev, prev);
|
||||
P_SetTarget(&prev->hnext, mo);
|
||||
prev = mo;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KITEM_INVINCIBILITY:
|
||||
|
@ -4801,11 +4968,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
}
|
||||
break;
|
||||
case KITEM_THUNDERSHIELD:
|
||||
if (player->kartstuff[k_curshield] <= 0)
|
||||
if (player->kartstuff[k_curshield] != 1)
|
||||
{
|
||||
mobj_t *shield = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THUNDERSHIELD);
|
||||
P_SetScale(shield, (shield->destscale = (5*shield->destscale)>>2));
|
||||
P_SetTarget(&shield->target, player->mo);
|
||||
S_StartSound(shield, sfx_s3k41);
|
||||
player->kartstuff[k_curshield] = 1;
|
||||
}
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
|
@ -4903,8 +5071,10 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
player->mo->eflags |= MFE_DRAWONLYFORP3;
|
||||
else if (player == &players[fourthdisplayplayer] && splitscreen > 2)
|
||||
player->mo->eflags |= MFE_DRAWONLYFORP4;
|
||||
else
|
||||
else if (player == &players[consoleplayer])
|
||||
player->mo->eflags |= MFE_DRAWONLYFORP1;
|
||||
else
|
||||
player->mo->flags2 |= MF2_DONTDRAW;
|
||||
}
|
||||
else
|
||||
player->mo->eflags &= ~(MFE_DRAWONLYFORP1|MFE_DRAWONLYFORP2|MFE_DRAWONLYFORP3|MFE_DRAWONLYFORP4);
|
||||
|
@ -5046,7 +5216,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
if (player->kartstuff[k_boostcharge] <= 36)
|
||||
{
|
||||
player->kartstuff[k_startboost] = 0;
|
||||
K_DoSneaker(player, false);
|
||||
K_DoSneaker(player, 0);
|
||||
player->kartstuff[k_sneakertimer] = 70; // PERFECT BOOST!!
|
||||
|
||||
if (!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3) // Let everyone hear this one
|
||||
|
@ -5272,7 +5442,7 @@ void K_CheckSpectateStatus(void)
|
|||
return;
|
||||
if (numingame < 2 || leveltime < starttime || mapreset) // Allow if the match hasn't started yet
|
||||
continue;
|
||||
if (leveltime > 20*TICRATE) // DON'T allow if the match is 20 seconds in
|
||||
if (leveltime > (starttime + 20*TICRATE)) // DON'T allow if the match is 20 seconds in
|
||||
return;
|
||||
if (G_RaceGametype() && players[i].laps) // DON'T allow if the race is at 2 laps
|
||||
return;
|
||||
|
@ -5943,9 +6113,10 @@ static void K_drawKartItem(void)
|
|||
// Extensible meter, currently only used for rocket sneaker...
|
||||
if (itembar && hudtrans)
|
||||
{
|
||||
const INT32 barlength = (splitscreen > 1 ? 12 : 24);
|
||||
const INT32 max = itemtime; // timer's normal highest value
|
||||
const INT32 length = min(barlength, (itembar * barlength) / max);
|
||||
const INT32 barlength = (splitscreen > 1 ? 12 : 26);
|
||||
const INT32 maxl = (itemtime*3) - barlength; // timer's normal highest value
|
||||
const INT32 fill = ((itembar*barlength)/maxl);
|
||||
const INT32 length = min(barlength, fill);
|
||||
const INT32 height = (offset ? 1 : 2);
|
||||
const INT32 x = (offset ? 17 : 11), y = (offset ? 27 : 35);
|
||||
|
||||
|
@ -6813,10 +6984,15 @@ static void K_drawBattleFullscreen(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (stplyr == &players[secondarydisplayplayer])
|
||||
x = BASEVIDWIDTH-96;
|
||||
if (stplyr->exiting)
|
||||
{
|
||||
if (stplyr == &players[secondarydisplayplayer])
|
||||
x = BASEVIDWIDTH-96;
|
||||
else
|
||||
x = 96;
|
||||
}
|
||||
else
|
||||
x = 96;
|
||||
scale /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7337,7 +7513,7 @@ void K_drawKartHUD(void)
|
|||
K_drawKartMinimap();
|
||||
|
||||
// Draw full screen stuff that turns off the rest of the HUD
|
||||
if (mapreset)
|
||||
if (mapreset && stplyr == &players[displayplayer])
|
||||
{
|
||||
K_drawChallengerScreen();
|
||||
return;
|
||||
|
@ -7450,6 +7626,13 @@ void K_drawKartHUD(void)
|
|||
|
||||
if (cv_kartdebugcheckpoint.value)
|
||||
K_drawCheckpointDebugger();
|
||||
|
||||
if (cv_kartdebugnodes.value)
|
||||
{
|
||||
UINT8 p;
|
||||
for (p = 0; p < MAXPLAYERS; p++)
|
||||
V_DrawString(8, 64+(8*p), V_YELLOWMAP, va("%d - %d", p, playernode[p]));
|
||||
}
|
||||
}
|
||||
|
||||
//}
|
||||
|
|
|
@ -21,6 +21,7 @@ void K_RegisterKartStuff(void);
|
|||
boolean K_IsPlayerLosing(player_t *player);
|
||||
boolean K_IsPlayerWanted(player_t *player);
|
||||
void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid);
|
||||
void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master);
|
||||
void K_RespawnChecker(player_t *player);
|
||||
void K_KartMoveAnimation(player_t *player);
|
||||
void K_KartPlayerThink(player_t *player, ticcmd_t *cmd);
|
||||
|
@ -36,7 +37,7 @@ void K_SpawnBoostTrail(player_t *player);
|
|||
void K_SpawnSparkleTrail(mobj_t *mo);
|
||||
void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent);
|
||||
void K_DriftDustHandling(mobj_t *spawner);
|
||||
void K_DoSneaker(player_t *player, boolean doPFlag);
|
||||
void K_DoSneaker(player_t *player, INT32 type);
|
||||
void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound);
|
||||
void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source);
|
||||
void K_UpdateHnextList(player_t *player, boolean clean);
|
||||
|
|
|
@ -2094,6 +2094,19 @@ static int lib_kKartBouncing(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lib_kMatchGenericExtraFlags(lua_State *L)
|
||||
{
|
||||
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
mobj_t *master = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
|
||||
NOHUD
|
||||
if (!mo)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
if (!master)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
K_MatchGenericExtraFlags(mo, master);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_kDoInstashield(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
|
@ -2225,11 +2238,11 @@ static int lib_kDriftDustHandling(lua_State *L)
|
|||
static int lib_kDoSneaker(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
boolean doPFlag = luaL_checkboolean(L, 2);
|
||||
INT32 type = luaL_checkinteger(L, 2);
|
||||
NOHUD
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
K_DoSneaker(player, doPFlag);
|
||||
K_DoSneaker(player, type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2493,6 +2506,7 @@ static luaL_Reg lib[] = {
|
|||
{"K_IsPlayerLosing",lib_kIsPlayerLosing},
|
||||
{"K_IsPlayerWanted",lib_kIsPlayerWanted},
|
||||
{"K_KartBouncing",lib_kKartBouncing},
|
||||
{"K_MatchGenericExtraFlags",lib_kMatchGenericExtraFlags},
|
||||
{"K_DoInstashield",lib_kDoInstashield},
|
||||
{"K_SpinPlayer",lib_kSpinPlayer},
|
||||
{"K_SquishPlayer",lib_kSquishPlayer},
|
||||
|
|
33
src/m_cond.c
33
src/m_cond.c
|
@ -101,10 +101,11 @@ unlockable_t unlockables[MAXUNLOCKABLES] =
|
|||
/* 02 */ {"SMK Cup", "", -1, 2, SECRET_NONE, 0, false, false, 0},
|
||||
/* 03 */ {"Chao Cup", "", -1, 3, SECRET_NONE, 0, false, false, 0},
|
||||
|
||||
/* 04 */ {"Encore Mode", "", 3, 4, SECRET_ENCORE, 0, false, false, 0},
|
||||
/* 05 */ {"Hell Attack", "", 5, 5, SECRET_HELLATTACK, 0, false, false, 0},
|
||||
/* 04 */ {"Hard Game Speed", "", -1, 4, SECRET_HARDSPEED, 0, false, false, 0},
|
||||
/* 05 */ {"Encore Mode", "", 4, 5, SECRET_ENCORE, 0, false, false, 0},
|
||||
/* 06 */ {"Hell Attack", "", 6, 6, SECRET_HELLATTACK, 0, false, false, 0},
|
||||
|
||||
/* 06 */ {"Record Attack", "", -1, -1, SECRET_RECORDATTACK, 0, true, true, 0},
|
||||
/* 07 */ {"Record Attack", "", -1, -1, SECRET_RECORDATTACK, 0, true, true, 0},
|
||||
};
|
||||
|
||||
// Default number of emblems and extra emblems
|
||||
|
@ -120,23 +121,27 @@ void M_SetupDefaultConditionSets(void)
|
|||
M_AddRawCondition(1, 1, UC_TOTALEMBLEMS, 5, 0, 0);
|
||||
M_AddRawCondition(1, 2, UC_MATCHESPLAYED, 10, 0, 0);
|
||||
|
||||
// -- 2: Collect 15 emblems OR play 25 matches
|
||||
M_AddRawCondition(2, 1, UC_TOTALEMBLEMS, 15, 0, 0);
|
||||
// -- 2: Collect 10 emblems OR play 25 matches
|
||||
M_AddRawCondition(2, 1, UC_TOTALEMBLEMS, 10, 0, 0);
|
||||
M_AddRawCondition(2, 2, UC_MATCHESPLAYED, 25, 0, 0);
|
||||
|
||||
// -- 3: Collect 30 emblems OR play 50 matches
|
||||
M_AddRawCondition(3, 1, UC_TOTALEMBLEMS, 30, 0, 0);
|
||||
// -- 3: Collect 20 emblems OR play 50 matches
|
||||
M_AddRawCondition(3, 1, UC_TOTALEMBLEMS, 20, 0, 0);
|
||||
M_AddRawCondition(3, 2, UC_MATCHESPLAYED, 50, 0, 0);
|
||||
|
||||
// -- 4: Collect 40 emblems OR play 150 matches
|
||||
M_AddRawCondition(4, 1, UC_TOTALEMBLEMS, 40, 0, 0);
|
||||
M_AddRawCondition(4, 2, UC_MATCHESPLAYED, 150, 0, 0);
|
||||
// -- 4: Collect 30 emblems OR play 100 matches
|
||||
M_AddRawCondition(4, 1, UC_TOTALEMBLEMS, 30, 0, 0);
|
||||
M_AddRawCondition(4, 2, UC_MATCHESPLAYED, 100, 0, 0);
|
||||
|
||||
// -- 5: Collect 50 emblems ONLY
|
||||
M_AddRawCondition(5, 1, UC_TOTALEMBLEMS, 50, 0, 0);
|
||||
// -- 5: Collect 40 emblems OR play 150 matches
|
||||
M_AddRawCondition(5, 1, UC_TOTALEMBLEMS, 40, 0, 0);
|
||||
M_AddRawCondition(5, 2, UC_MATCHESPLAYED, 150, 0, 0);
|
||||
|
||||
// -- 10: Play 100 matches
|
||||
M_AddRawCondition(10, 1, UC_MATCHESPLAYED, 100, 0, 0);
|
||||
// -- 6: Collect 50 emblems ONLY
|
||||
M_AddRawCondition(6, 1, UC_TOTALEMBLEMS, 50, 0, 0);
|
||||
|
||||
// -- 10: Play 300 matches
|
||||
M_AddRawCondition(10, 1, UC_MATCHESPLAYED, 300, 0, 0);
|
||||
}
|
||||
|
||||
void M_AddRawCondition(UINT8 set, UINT8 id, conditiontype_t c, INT32 r, INT16 x1, INT16 x2)
|
||||
|
|
|
@ -113,7 +113,7 @@ typedef struct
|
|||
} unlockable_t;
|
||||
|
||||
// I have NO idea why these are going negative, but whatever.
|
||||
#define SECRET_NONE -6 // Does nil. Use with levels locked by UnlockRequired
|
||||
#define SECRET_NONE -6 // Does nil. Use with levels locked by UnlockRequired
|
||||
#define SECRET_ITEMFINDER -5 // Enables Item Finder/Emblem Radar
|
||||
#define SECRET_EMBLEMHINTS -4 // Enables Emblem Hints
|
||||
#define SECRET_PANDORA -3 // Enables Pandora's Box
|
||||
|
@ -124,8 +124,9 @@ typedef struct
|
|||
#define SECRET_WARP 2 // Selectable warp
|
||||
#define SECRET_SOUNDTEST 3 // Sound Test
|
||||
#define SECRET_CREDITS 4 // Enables Credits
|
||||
#define SECRET_ENCORE 5 // Enables Encore mode cvar
|
||||
#define SECRET_HELLATTACK 6 // Map Hell in record attack
|
||||
#define SECRET_ENCORE 5 // Enables Encore mode cvar
|
||||
#define SECRET_HELLATTACK 6 // Map Hell in record attack
|
||||
#define SECRET_HARDSPEED 7 // Enables Hard gamespeed
|
||||
|
||||
// If you have more secrets than these variables allow in your game,
|
||||
// you seriously need to get a life.
|
||||
|
|
614
src/m_menu.c
614
src/m_menu.c
File diff suppressed because it is too large
Load diff
204
src/p_inter.c
204
src/p_inter.c
|
@ -510,8 +510,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
}
|
||||
|
||||
special->target->player->kartstuff[k_comebackpoints] += 2 * (K_IsPlayerWanted(player) ? 2 : 1);
|
||||
if (netgame && cv_hazardlog.value)
|
||||
CONS_Printf(M_GetText("%s bombed %s!\n"), player_names[special->target->player-players], player_names[player-players]);
|
||||
if (special->target->player->kartstuff[k_comebackpoints] >= 3)
|
||||
K_StealBumper(special->target->player, player, true);
|
||||
special->target->player->kartstuff[k_comebacktimer] = comebacktime;
|
||||
|
@ -527,8 +525,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
special->target->player->kartstuff[k_comebackmode] = 0;
|
||||
special->target->player->kartstuff[k_comebackpoints]++;
|
||||
|
||||
if (netgame && cv_hazardlog.value)
|
||||
CONS_Printf(M_GetText("%s gave an item to %s.\n"), player_names[special->target->player-players], player_names[player-players]);
|
||||
if (special->target->player->kartstuff[k_comebackpoints] >= 3)
|
||||
K_StealBumper(special->target->player, player, true);
|
||||
special->target->player->kartstuff[k_comebacktimer] = comebacktime;
|
||||
|
@ -560,8 +556,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
special->target->player->kartstuff[k_comebackmode] = 0;
|
||||
special->target->player->kartstuff[k_comebackpoints]++;
|
||||
|
||||
if (netgame && cv_hazardlog.value)
|
||||
CONS_Printf(M_GetText("%s gave an \"item\" to %s.\n"), player_names[special->target->player-players], player_names[player-players]);
|
||||
if (special->target->player->kartstuff[k_comebackpoints] >= 3)
|
||||
K_StealBumper(special->target->player, player, true);
|
||||
special->target->player->kartstuff[k_comebacktimer] = comebacktime;
|
||||
|
@ -1700,199 +1694,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
/** Prints death messages relating to a dying or hit player.
|
||||
*
|
||||
* \param player Affected player.
|
||||
* \param inflictor The attack weapon used, can be NULL.
|
||||
* \param source The attacker, can be NULL.
|
||||
*/
|
||||
static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *source)
|
||||
{
|
||||
const char *str = NULL;
|
||||
boolean deathonly = false;
|
||||
boolean deadsource = false;
|
||||
boolean deadtarget = false;
|
||||
// player names complete with control codes
|
||||
char targetname[MAXPLAYERNAME+4];
|
||||
char sourcename[MAXPLAYERNAME+4];
|
||||
|
||||
if (G_RaceGametype())
|
||||
return; // Not in coop, etc.
|
||||
|
||||
if (!player)
|
||||
return; // Impossible!
|
||||
|
||||
if (player->spectator)
|
||||
return; // No messages for dying (crushed) spectators.
|
||||
|
||||
if (!netgame)
|
||||
return; // Presumably it's obvious what's happening in splitscreen.
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUAh_HurtMsg(player, inflictor, source))
|
||||
return;
|
||||
#endif
|
||||
|
||||
deadtarget = (player->health <= 0);
|
||||
|
||||
// Target's name
|
||||
snprintf(targetname, sizeof(targetname), "%s%s%s",
|
||||
CTFTEAMCODE(player),
|
||||
player_names[player - players],
|
||||
CTFTEAMENDCODE(player));
|
||||
|
||||
if (source)
|
||||
{
|
||||
// inflictor shouldn't be NULL if source isn't
|
||||
I_Assert(inflictor != NULL);
|
||||
|
||||
if (source->player)
|
||||
{
|
||||
// Source's name (now that we know there is one)
|
||||
snprintf(sourcename, sizeof(sourcename), "%s%s%s",
|
||||
CTFTEAMCODE(source->player),
|
||||
player_names[source->player - players],
|
||||
CTFTEAMENDCODE(source->player));
|
||||
|
||||
// We don't care if it's us.
|
||||
// "Player 1's [redacted] killed Player 1."
|
||||
if (source->player->playerstate == PST_DEAD && source->player != player &&
|
||||
(inflictor->flags2 & MF2_BEYONDTHEGRAVE))
|
||||
deadsource = true;
|
||||
|
||||
if (inflictor->flags & MF_PUSHABLE)
|
||||
{
|
||||
str = M_GetText("%s%s's playtime with heavy objects %s %s.\n");
|
||||
}
|
||||
else switch (inflictor->type)
|
||||
{
|
||||
case MT_PLAYER:
|
||||
if ((inflictor->player->powers[pw_shield] & SH_NOSTACK) == SH_BOMB)
|
||||
str = M_GetText("%s%s's armageddon blast %s %s.\n");
|
||||
else if (inflictor->player->powers[pw_invulnerability])
|
||||
str = M_GetText("%s%s's invincibility aura %s %s.\n");
|
||||
else if (inflictor->player->powers[pw_super])
|
||||
str = M_GetText("%s%s's super aura %s %s.\n");
|
||||
else
|
||||
str = M_GetText("%s%s's tagging hand %s %s.\n");
|
||||
break;
|
||||
case MT_SPINFIRE:
|
||||
str = M_GetText("%s%s's elemental fire trail %s %s.\n");
|
||||
break;
|
||||
case MT_THROWNBOUNCE:
|
||||
str = M_GetText("%s%s's bounce ring %s %s.\n");
|
||||
break;
|
||||
case MT_THROWNINFINITY:
|
||||
str = M_GetText("%s%s's infinity ring %s %s.\n");
|
||||
break;
|
||||
case MT_THROWNAUTOMATIC:
|
||||
str = M_GetText("%s%s's automatic ring %s %s.\n");
|
||||
break;
|
||||
case MT_THROWNSCATTER:
|
||||
str = M_GetText("%s%s's scatter ring %s %s.\n");
|
||||
break;
|
||||
// TODO: For next two, figure out how to determine if it was a direct hit or splash damage. -SH
|
||||
case MT_THROWNEXPLOSION:
|
||||
str = M_GetText("%s%s's explosion ring %s %s.\n");
|
||||
break;
|
||||
case MT_THROWNGRENADE:
|
||||
str = M_GetText("%s%s's grenade ring %s %s.\n");
|
||||
break;
|
||||
case MT_REDRING:
|
||||
if (inflictor->flags2 & MF2_RAILRING)
|
||||
str = M_GetText("%s%s's rail ring %s %s.\n");
|
||||
else
|
||||
str = M_GetText("%s%s's thrown ring %s %s.\n");
|
||||
break;
|
||||
default:
|
||||
str = M_GetText("%s%s %s %s.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
CONS_Printf(str,
|
||||
deadsource ? M_GetText("The late ") : "",
|
||||
sourcename,
|
||||
deadtarget ? M_GetText("killed") : M_GetText("hit"),
|
||||
targetname);
|
||||
return;
|
||||
}
|
||||
else switch (source->type)
|
||||
{
|
||||
case MT_NULL:
|
||||
switch(source->threshold)
|
||||
{
|
||||
case 42:
|
||||
deathonly = true;
|
||||
str = M_GetText("%s drowned.\n");
|
||||
break;
|
||||
case 43:
|
||||
str = M_GetText("%s was %s by spikes.\n");
|
||||
break;
|
||||
case 44:
|
||||
deathonly = true;
|
||||
str = M_GetText("%s was crushed.\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MT_EGGMANICO:
|
||||
case MT_EGGMANBOX:
|
||||
str = M_GetText("%s was %s by Eggman's nefarious TV magic.\n");
|
||||
break;
|
||||
case MT_SPIKE:
|
||||
str = M_GetText("%s was %s by spikes.\n");
|
||||
break;
|
||||
default:
|
||||
str = M_GetText("%s was %s by an environmental hazard.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// null source, environment kills
|
||||
// TERRIBLE HACK for hit damage because P_DoPlayerPain moves the player...
|
||||
// I'll put it back, I promise!
|
||||
player->mo->z -= player->mo->momz+1;
|
||||
if (P_PlayerTouchingSectorSpecial(player, 1, 2))
|
||||
str = M_GetText("%s was %s by chemical water.\n");
|
||||
else if (P_PlayerTouchingSectorSpecial(player, 1, 3))
|
||||
str = M_GetText("%s was %s by molten lava.\n");
|
||||
else if (P_PlayerTouchingSectorSpecial(player, 1, 4))
|
||||
str = M_GetText("%s was %s by electricity.\n");
|
||||
else if (deadtarget)
|
||||
{
|
||||
deathonly = true;
|
||||
if (P_PlayerTouchingSectorSpecial(player, 1, 6)
|
||||
|| P_PlayerTouchingSectorSpecial(player, 1, 7))
|
||||
str = M_GetText("%s fell into a bottomless pit.\n");
|
||||
else if (P_PlayerTouchingSectorSpecial(player, 1, 12))
|
||||
str = M_GetText("%s asphyxiated in space.\n");
|
||||
else
|
||||
str = M_GetText("%s died.\n");
|
||||
}
|
||||
if (!str)
|
||||
str = M_GetText("%s was %s by an environmental hazard.\n");
|
||||
|
||||
player->mo->z += player->mo->momz+1;
|
||||
}
|
||||
|
||||
if (!str) // Should not happen! Unless we missed catching something above.
|
||||
return;
|
||||
|
||||
// Don't log every hazard hit if they don't want us to.
|
||||
if (!deadtarget && !cv_hazardlog.value)
|
||||
return;
|
||||
|
||||
if (deathonly)
|
||||
{
|
||||
if (!deadtarget)
|
||||
return;
|
||||
CONS_Printf(str, targetname);
|
||||
}
|
||||
else
|
||||
CONS_Printf(str, targetname, deadtarget ? M_GetText("killed") : M_GetText("hit"));
|
||||
}
|
||||
|
||||
/** Checks if the level timer is over the timelimit and the round should end,
|
||||
* unless you are in overtime. In which case leveltime may stretch out beyond
|
||||
* timelimitintics and overtime's status will be checked here each tick.
|
||||
|
@ -2183,7 +1984,7 @@ boolean P_CheckRacers(void)
|
|||
numplayersingame++;
|
||||
}
|
||||
|
||||
if (numplayersingame > 1) // if there's more than one player in-game, this is safe to do
|
||||
if (numplayersingame >= nospectategrief) // prevent spectate griefing
|
||||
{
|
||||
// check if we just got unlucky and there was only one guy who was a problem
|
||||
for (j = i+1; j < MAXPLAYERS; j++)
|
||||
|
@ -2852,7 +2653,6 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou
|
|||
/*if (source->player->pflags & PF_TAGIT && !(player->pflags & PF_TAGIT))
|
||||
{
|
||||
P_AddPlayerScore(source->player, 1); //award points to tagger.
|
||||
P_HitDeathMessages(player, inflictor, source);
|
||||
|
||||
if (gametype == GT_TAG) //survivor
|
||||
{
|
||||
|
@ -3540,8 +3340,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
if (player->health < 0)
|
||||
player->health = 0;
|
||||
|
||||
P_HitDeathMessages(player, inflictor, source);
|
||||
|
||||
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
|
||||
}
|
||||
|
||||
|
|
142
src/p_mobj.c
142
src/p_mobj.c
|
@ -6639,20 +6639,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
case MT_SSMINE_SHIELD:
|
||||
case MT_FAKESHIELD:
|
||||
case MT_SINK_SHIELD:
|
||||
/*if (mobj->health > 0 && mobj->target && mobj->target->player
|
||||
&& mobj->target->player->health > 0 && !mobj->target->player->spectator)
|
||||
{
|
||||
// Was this so hard? -- Handled this with K_UpdateHnextList instead of thinking it away...
|
||||
if ((mobj->type == MT_ORBINAUT_SHIELD && mobj->target->player->kartstuff[k_itemtype] != KITEM_ORBINAUT)
|
||||
|| (mobj->type == MT_JAWZ_SHIELD && mobj->target->player->kartstuff[k_itemtype] != KITEM_JAWZ)
|
||||
|| (mobj->movedir > 0 && ((UINT16)mobj->target->player->kartstuff[k_itemamount] < mobj->movedir))
|
||||
|| (!mobj->target->player->kartstuff[k_itemheld]))
|
||||
{
|
||||
P_RemoveMobj(mobj);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else*/ if ((mobj->health > 0
|
||||
if ((mobj->health > 0
|
||||
&& (!mobj->target || !mobj->target->player || mobj->target->player->health <= 0 || mobj->target->player->spectator))
|
||||
|| (mobj->health <= 0 && mobj->z <= mobj->floorz)
|
||||
|| P_CheckDeathPitCollide(mobj)) // When in death state
|
||||
|
@ -6805,22 +6792,18 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
if (mobj->target && mobj->target->health
|
||||
&& mobj->target->player && !mobj->target->player->spectator
|
||||
&& mobj->target->player->health && mobj->target->player->playerstate != PST_DEAD
|
||||
&& players[displayplayer].mo && !players[displayplayer].spectator)
|
||||
/*&& players[displayplayer].mo && !players[displayplayer].spectator*/)
|
||||
{
|
||||
fixed_t scale = mobj->target->scale;
|
||||
mobj->color = mobj->target->color;
|
||||
K_MatchGenericExtraFlags(mobj, mobj->target);
|
||||
|
||||
if (G_RaceGametype()
|
||||
|| mobj->target->player == &players[displayplayer]
|
||||
|| mobj->target->player->kartstuff[k_bumper] <= 0
|
||||
|| (mobj->target->player->mo->flags2 & MF2_DONTDRAW)
|
||||
if ((G_RaceGametype() || mobj->target->player->kartstuff[k_bumper] <= 0)
|
||||
#if 1 // Set to 0 to test without needing to host
|
||||
|| !netgame
|
||||
|| ((mobj->target->player == &players[displayplayer]) || P_IsLocalPlayer(mobj->target->player))
|
||||
#endif
|
||||
)
|
||||
mobj->flags2 |= MF2_DONTDRAW;
|
||||
else
|
||||
mobj->flags2 &= ~MF2_DONTDRAW;
|
||||
|
||||
P_UnsetThingPosition(mobj);
|
||||
mobj->x = mobj->target->x;
|
||||
|
@ -6840,10 +6823,13 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
}
|
||||
P_SetThingPosition(mobj);
|
||||
|
||||
scale += FixedMul(FixedDiv(abs(P_AproxDistance(players[displayplayer].mo->x-mobj->target->x,
|
||||
players[displayplayer].mo->y-mobj->target->y)), RING_DIST), mobj->target->scale);
|
||||
if (scale > 16*FRACUNIT)
|
||||
scale = 16*FRACUNIT;
|
||||
if (!splitscreen)
|
||||
{
|
||||
scale += FixedMul(FixedDiv(abs(P_AproxDistance(players[displayplayer].mo->x-mobj->target->x,
|
||||
players[displayplayer].mo->y-mobj->target->y)), RING_DIST), mobj->target->scale);
|
||||
if (scale > 16*FRACUNIT)
|
||||
scale = 16*FRACUNIT;
|
||||
}
|
||||
mobj->destscale = scale;
|
||||
|
||||
if (!mobj->tracer)
|
||||
|
@ -8255,16 +8241,24 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
return;
|
||||
}
|
||||
|
||||
P_TeleportMove(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->target->angle+ANGLE_180, mobj->target->radius),
|
||||
mobj->target->y + P_ReturnThrustY(mobj, mobj->target->angle+ANGLE_180, mobj->target->radius), mobj->target->z);
|
||||
mobj->angle = mobj->target->angle;
|
||||
P_TeleportMove(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->angle+ANGLE_180, mobj->target->radius),
|
||||
mobj->target->y + P_ReturnThrustY(mobj, mobj->angle+ANGLE_180, mobj->target->radius), mobj->target->z);
|
||||
P_SetScale(mobj, mobj->target->scale);
|
||||
|
||||
if (mobj->target->player)
|
||||
{
|
||||
if (mobj->target->player->kartstuff[k_sneakertimer] > mobj->movecount)
|
||||
P_SetMobjState(mobj, S_BOOSTFLAME);
|
||||
mobj->movecount = mobj->target->player->kartstuff[k_sneakertimer];
|
||||
player_t *p = NULL;
|
||||
if (mobj->target->target && mobj->target->target->player)
|
||||
p = mobj->target->target->player;
|
||||
else if (mobj->target->player)
|
||||
p = mobj->target->player;
|
||||
|
||||
if (p)
|
||||
{
|
||||
if (p->kartstuff[k_sneakertimer] > mobj->movecount)
|
||||
P_SetMobjState(mobj, S_BOOSTFLAME);
|
||||
mobj->movecount = p->kartstuff[k_sneakertimer];
|
||||
}
|
||||
}
|
||||
|
||||
if (mobj->state == &states[S_BOOSTSMOKESPAWNER])
|
||||
|
@ -8279,7 +8273,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
smoke->momy = mobj->target->momy/2;
|
||||
smoke->momz = mobj->target->momz/2;
|
||||
|
||||
P_Thrust(smoke, mobj->target->angle+FixedAngle(P_RandomRange(135, 225)<<FRACBITS), P_RandomRange(0, 8) * mobj->target->scale);
|
||||
P_Thrust(smoke, mobj->angle+FixedAngle(P_RandomRange(135, 225)<<FRACBITS), P_RandomRange(0, 8) * mobj->target->scale);
|
||||
}
|
||||
break;
|
||||
case MT_SPARKLETRAIL:
|
||||
|
@ -8357,6 +8351,39 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
P_TeleportMove(mobj, destx, desty, mobj->target->z);
|
||||
break;
|
||||
}
|
||||
case MT_ROCKETSNEAKER:
|
||||
if (!mobj->target || !mobj->target->health)
|
||||
{
|
||||
P_RemoveMobj(mobj);
|
||||
return;
|
||||
}
|
||||
if (mobj->target->player && !mobj->target->player->kartstuff[k_rocketsneakertimer])
|
||||
{
|
||||
mobj->flags &= ~MF_NOGRAVITY;
|
||||
mobj->angle += ANGLE_45;
|
||||
|
||||
if (!mobj->extravalue2)
|
||||
{
|
||||
if (mobj->eflags & MFE_VERTICALFLIP)
|
||||
mobj->z -= mobj->height;
|
||||
else
|
||||
mobj->z += mobj->height;
|
||||
|
||||
S_StartSound(mobj, mobj->info->deathsound);
|
||||
P_SetObjectMomZ(mobj, 8*FRACUNIT, false);
|
||||
P_InstaThrust(mobj, R_PointToAngle2(mobj->target->x, mobj->target->y, mobj->x, mobj->y)+ANGLE_90, 16*FRACUNIT);
|
||||
mobj->momx += mobj->target->momx;
|
||||
mobj->momy += mobj->target->momy;
|
||||
mobj->momz += mobj->target->momz;
|
||||
mobj->extravalue2 = 1;
|
||||
}
|
||||
else if (P_IsObjectOnGround(mobj))
|
||||
{
|
||||
P_RemoveMobj(mobj);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MT_KARMAHITBOX:
|
||||
if (!mobj->target || !mobj->target->health || !mobj->target->player || mobj->target->player->spectator
|
||||
|| (G_RaceGametype() || mobj->target->player->kartstuff[k_bumper]))
|
||||
|
@ -9345,7 +9372,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
case MT_JAWZ: case MT_JAWZ_DUD: case MT_JAWZ_SHIELD:
|
||||
case MT_SSMINE: case MT_SSMINE_SHIELD:
|
||||
case MT_BALLHOG: case MT_SINK:
|
||||
case MT_THUNDERSHIELD: case MT_SPB:
|
||||
case MT_THUNDERSHIELD: case MT_ROCKETSNEAKER:
|
||||
case MT_SPB:
|
||||
P_SpawnShadowMobj(mobj);
|
||||
default:
|
||||
break;
|
||||
|
@ -10098,6 +10126,8 @@ void P_SpawnPlayer(INT32 playernum)
|
|||
continue;
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
continue;
|
||||
if (players[i].jointime <= 1) // Prevent splitscreen hosters/joiners from only adding 1 player at a time in empty servers
|
||||
continue;
|
||||
pcount++;
|
||||
}
|
||||
|
||||
|
@ -11239,7 +11269,7 @@ ML_NOCLIMB : Direction not controllable
|
|||
void P_SpawnHoopsAndRings(mapthing_t *mthing)
|
||||
{
|
||||
mobj_t *mobj = NULL;
|
||||
INT32 r, i;
|
||||
INT32 /*r,*/ i;
|
||||
fixed_t x, y, z, finalx, finaly, finalz;
|
||||
sector_t *sec;
|
||||
TVector v, *res;
|
||||
|
@ -11313,8 +11343,8 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
|
|||
|
||||
mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOP);
|
||||
|
||||
if (maptol & TOL_XMAS)
|
||||
P_SetMobjState(mobj, mobj->info->seestate + (i & 1));
|
||||
//if (maptol & TOL_XMAS)
|
||||
//P_SetMobjState(mobj, mobj->info->seestate + (i & 1));
|
||||
|
||||
mobj->z -= mobj->height/2;
|
||||
P_SetTarget(&mobj->target, hoopcenter); // Link the sprite to the center.
|
||||
|
@ -11323,8 +11353,10 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
|
|||
// Link all the sprites in the hoop together
|
||||
if (nextmobj)
|
||||
{
|
||||
mobj->hprev = nextmobj;
|
||||
mobj->hprev->hnext = mobj;
|
||||
P_SetTarget(&mobj->hprev, nextmobj);
|
||||
P_SetTarget(&mobj->hprev->hnext, mobj);
|
||||
//mobj->hprev = nextmobj;
|
||||
//mobj->hprev->hnext = mobj;
|
||||
}
|
||||
else
|
||||
mobj->hprev = mobj->hnext = NULL;
|
||||
|
@ -11354,8 +11386,10 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
|
|||
|
||||
// Link all the collision sprites together.
|
||||
mobj->hnext = NULL;
|
||||
mobj->hprev = nextmobj;
|
||||
mobj->hprev->hnext = mobj;
|
||||
P_SetTarget(&mobj->hprev, nextmobj);
|
||||
P_SetTarget(&mobj->hprev->hnext, mobj);
|
||||
//mobj->hprev = nextmobj;
|
||||
//mobj->hprev->hnext = mobj;
|
||||
|
||||
nextmobj = mobj;
|
||||
}
|
||||
|
@ -11381,8 +11415,10 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
|
|||
|
||||
// Link all the collision sprites together.
|
||||
mobj->hnext = NULL;
|
||||
mobj->hprev = nextmobj;
|
||||
mobj->hprev->hnext = mobj;
|
||||
P_SetTarget(&mobj->hprev, nextmobj);
|
||||
P_SetTarget(&mobj->hprev->hnext, mobj);
|
||||
//mobj->hprev = nextmobj;
|
||||
//mobj->hprev->hnext = mobj;
|
||||
|
||||
nextmobj = mobj;
|
||||
}
|
||||
|
@ -11455,8 +11491,8 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
|
|||
|
||||
mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOP);
|
||||
|
||||
if (maptol & TOL_XMAS)
|
||||
P_SetMobjState(mobj, mobj->info->seestate + (i & 1));
|
||||
//if (maptol & TOL_XMAS)
|
||||
//P_SetMobjState(mobj, mobj->info->seestate + (i & 1));
|
||||
|
||||
mobj->z -= mobj->height/2;
|
||||
P_SetTarget(&mobj->target, hoopcenter); // Link the sprite to the center.
|
||||
|
@ -11465,8 +11501,10 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
|
|||
// Link all the sprites in the hoop together
|
||||
if (nextmobj)
|
||||
{
|
||||
mobj->hprev = nextmobj;
|
||||
mobj->hprev->hnext = mobj;
|
||||
P_SetTarget(&mobj->hprev, nextmobj);
|
||||
P_SetTarget(&mobj->hprev->hnext, mobj);
|
||||
//mobj->hprev = nextmobj;
|
||||
//mobj->hprev->hnext = mobj;
|
||||
}
|
||||
else
|
||||
mobj->hprev = mobj->hnext = NULL;
|
||||
|
@ -11507,8 +11545,10 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
|
|||
|
||||
// Link all the collision sprites together.
|
||||
mobj->hnext = NULL;
|
||||
mobj->hprev = nextmobj;
|
||||
mobj->hprev->hnext = mobj;
|
||||
P_SetTarget(&mobj->hprev, nextmobj);
|
||||
P_SetTarget(&mobj->hprev->hnext, mobj);
|
||||
//mobj->hprev = nextmobj;
|
||||
//mobj->hprev->hnext = mobj;
|
||||
|
||||
nextmobj = mobj;
|
||||
}
|
||||
|
@ -11516,6 +11556,8 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
|
|||
|
||||
return;
|
||||
}
|
||||
else return; // srb2kart - no rings or ring-like objects in R1
|
||||
/*
|
||||
// Wing logo item.
|
||||
else if (mthing->type == mobjinfo[MT_NIGHTSWING].doomednum)
|
||||
{
|
||||
|
@ -11809,7 +11851,7 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
|
|||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -3285,6 +3285,7 @@ static void P_NetArchiveMisc(void)
|
|||
WRITEUINT32(save_p, wantedcalcdelay);
|
||||
WRITEUINT32(save_p, indirectitemcooldown);
|
||||
WRITEUINT32(save_p, mapreset);
|
||||
WRITEUINT8(save_p, nospectategrief);
|
||||
|
||||
// Is it paused?
|
||||
if (paused)
|
||||
|
@ -3389,6 +3390,7 @@ static inline boolean P_NetUnArchiveMisc(void)
|
|||
wantedcalcdelay = READUINT32(save_p);
|
||||
indirectitemcooldown = READUINT32(save_p);
|
||||
mapreset = READUINT32(save_p);
|
||||
nospectategrief = READUINT8(save_p);
|
||||
|
||||
// Is it paused?
|
||||
if (READUINT8(save_p) == 0x2f)
|
||||
|
|
|
@ -2209,7 +2209,7 @@ static void P_LevelInitStuff(void)
|
|||
players[i].lives = cv_startinglives.value;
|
||||
}
|
||||
#else
|
||||
players[i].lives = 1;
|
||||
players[i].lives = 1; // SRB2Kart
|
||||
#endif
|
||||
|
||||
players[i].realtime = countdown = countdown2 = 0;
|
||||
|
@ -3024,6 +3024,7 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
wantedcalcdelay = wantedfrequency*2;
|
||||
indirectitemcooldown = 0;
|
||||
mapreset = 0;
|
||||
nospectategrief = 0;
|
||||
|
||||
// clear special respawning que
|
||||
iquehead = iquetail = 0;
|
||||
|
|
27
src/p_spec.c
27
src/p_spec.c
|
@ -36,6 +36,7 @@
|
|||
#include "lua_hook.h" // LUAh_LinedefExecute
|
||||
|
||||
#include "k_kart.h" // SRB2kart
|
||||
#include "console.h" // CON_LogMessage
|
||||
|
||||
#ifdef HW3SOUND
|
||||
#include "hardware/hw3sound.h"
|
||||
|
@ -4022,7 +4023,7 @@ DoneSection2:
|
|||
player->kartstuff[k_floorboost] = 3;
|
||||
else
|
||||
player->kartstuff[k_floorboost] = 2;
|
||||
K_DoSneaker(player, false);
|
||||
K_DoSneaker(player, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -4201,15 +4202,8 @@ DoneSection2:
|
|||
if (player->pflags & PF_NIGHTSMODE)
|
||||
player->drillmeter += 48*20;
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
if (player->laps >= (UINT8)cv_numlaps.value)
|
||||
CONS_Printf(M_GetText("%s has finished the race.\n"), player_names[player-players]);
|
||||
else if (player->laps == (UINT8)(cv_numlaps.value - 1))
|
||||
CONS_Printf("%s started the final lap\n", player_names[player-players]);
|
||||
else
|
||||
CONS_Printf(M_GetText("%s started lap %u\n"), player_names[player-players], (UINT32)player->laps+1);
|
||||
}
|
||||
if (netgame && player->laps >= (UINT8)cv_numlaps.value)
|
||||
CON_LogMessage(va(M_GetText("%s has finished the race.\n"), player_names[player-players]));
|
||||
|
||||
// SRB2Kart: save best lap for record attack
|
||||
if (player == &players[consoleplayer])
|
||||
|
@ -4235,12 +4229,23 @@ DoneSection2:
|
|||
S_StartSound(NULL, sfx_s221);
|
||||
}
|
||||
|
||||
//
|
||||
//player->starpostangle = player->starposttime = player->starpostnum = 0;
|
||||
//player->starpostx = player->starposty = player->starpostz = 0;
|
||||
|
||||
// Play the starpost sound for 'consistency'
|
||||
// S_StartSound(player->mo, sfx_strpst);
|
||||
|
||||
// Figure out how many are playing on the last lap, to prevent spectate griefing
|
||||
if (!nospectategrief && player->laps >= (UINT8)(cv_numlaps.value - 1))
|
||||
{
|
||||
UINT8 i;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
continue;
|
||||
nospectategrief++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (player->starpostnum)
|
||||
{
|
||||
|
|
65
src/p_user.c
65
src/p_user.c
|
@ -45,6 +45,7 @@
|
|||
// SRB2kart
|
||||
#include "m_cond.h" // M_UpdateUnlockablesAndExtraEmblems
|
||||
#include "k_kart.h"
|
||||
#include "console.h" // CON_LogMessage
|
||||
|
||||
#ifdef HW3SOUND
|
||||
#include "hardware/hw3sound.h"
|
||||
|
@ -1139,34 +1140,57 @@ boolean P_EndingMusic(player_t *player)
|
|||
{
|
||||
char buffer[9];
|
||||
boolean looping = true;
|
||||
INT32 bestlocalpos;
|
||||
player_t *bestlocalplayer;
|
||||
|
||||
if (!P_IsLocalPlayer(player)) // Only applies to a local player
|
||||
return false;
|
||||
|
||||
// Event - Level Finish
|
||||
if (splitscreen
|
||||
&& (players[displayplayer].exiting
|
||||
|| players[secondarydisplayplayer].exiting
|
||||
|| ((splitscreen < 2) && players[thirddisplayplayer].exiting)
|
||||
|| ((splitscreen < 3) && players[fourthdisplayplayer].exiting)))
|
||||
// Check for if this is valid or not
|
||||
if (splitscreen)
|
||||
{
|
||||
sprintf(buffer, "k*ok");
|
||||
if (!((players[displayplayer].exiting || (players[displayplayer].pflags & PF_TIMEOVER))
|
||||
|| (players[secondarydisplayplayer].exiting || (players[secondarydisplayplayer].pflags & PF_TIMEOVER))
|
||||
|| ((splitscreen < 2) && (players[thirddisplayplayer].exiting || (players[thirddisplayplayer].pflags & PF_TIMEOVER)))
|
||||
|| ((splitscreen < 3) && (players[fourthdisplayplayer].exiting || (players[fourthdisplayplayer].pflags & PF_TIMEOVER)))))
|
||||
return false;
|
||||
|
||||
bestlocalplayer = &players[displayplayer];
|
||||
bestlocalpos = ((players[displayplayer].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[displayplayer].kartstuff[k_position]);
|
||||
#define setbests(p) \
|
||||
if (((players[p].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[p].kartstuff[k_position]) < bestlocalpos) \
|
||||
{ \
|
||||
bestlocalplayer = &players[p]; \
|
||||
bestlocalpos = ((players[p].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[p].kartstuff[k_position]); \
|
||||
}
|
||||
else if (player->pflags & PF_TIMEOVER) // || !player->lives) -- outta lives, outta time
|
||||
{
|
||||
sprintf(buffer, "k*lose");
|
||||
setbests(secondarydisplayplayer);
|
||||
if (splitscreen > 1)
|
||||
setbests(thirddisplayplayer);
|
||||
if (splitscreen > 2)
|
||||
setbests(fourthdisplayplayer);
|
||||
#undef setbests
|
||||
}
|
||||
else if (player->exiting)
|
||||
else
|
||||
{
|
||||
if (player->kartstuff[k_position] == 1)
|
||||
if (!(player->exiting || (player->pflags & PF_TIMEOVER)))
|
||||
return false;
|
||||
|
||||
bestlocalplayer = player;
|
||||
bestlocalpos = ((player->pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : player->kartstuff[k_position]);
|
||||
}
|
||||
|
||||
if (G_RaceGametype() && bestlocalpos == MAXPLAYERS+1)
|
||||
sprintf(buffer, "k*lose"); // krfail, for eventual F-Zero death results theme
|
||||
else
|
||||
{
|
||||
if (bestlocalpos == 1)
|
||||
sprintf(buffer, "k*win");
|
||||
else if (K_IsPlayerLosing(player))
|
||||
else if (K_IsPlayerLosing(bestlocalplayer))
|
||||
sprintf(buffer, "k*lose");
|
||||
else
|
||||
sprintf(buffer, "k*ok");
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
S_SpeedMusic(1.0f);
|
||||
|
||||
|
@ -8218,7 +8242,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
|||
// if (leveltime > 0 && timeinmap <= 0)
|
||||
// return true;
|
||||
|
||||
if (player->pflags & PF_NIGHTSMODE)
|
||||
if (demoplayback)
|
||||
{
|
||||
focusangle = mo->angle;
|
||||
focusaiming = 0;
|
||||
|
@ -8325,9 +8349,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
|||
input = InvAngle(input);
|
||||
|
||||
angle = thiscam->angle + input;
|
||||
|
||||
if (demoplayback && player == &players[consoleplayer])
|
||||
localangle = angle;
|
||||
}
|
||||
|
||||
if (!resetcalled && (leveltime > starttime)
|
||||
|
@ -8733,7 +8754,7 @@ boolean P_SpectatorJoinGame(player_t *player)
|
|||
if (P_IsLocalPlayer(player) && displayplayer != consoleplayer)
|
||||
displayplayer = consoleplayer;
|
||||
|
||||
CONS_Printf(M_GetText("%s entered the game.\n"), player_names[player-players]);
|
||||
CON_LogMessage(va(M_GetText("%s entered the game.\n"), player_names[player-players]));
|
||||
return true; // no more player->mo, cannot continue.
|
||||
}
|
||||
return false;
|
||||
|
@ -8936,7 +8957,7 @@ void P_PlayerThink(player_t *player)
|
|||
}
|
||||
|
||||
#ifdef SEENAMES
|
||||
if (netgame && player == &players[displayplayer] && !(leveltime % (TICRATE/5)))
|
||||
if (netgame && player == &players[displayplayer] && !(leveltime % (TICRATE/5)) && !splitscreen)
|
||||
{
|
||||
seenplayer = NULL;
|
||||
|
||||
|
@ -9150,10 +9171,10 @@ void P_PlayerThink(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
if ((netgame || splitscreen) && player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing])
|
||||
if ((netgame || multiplayer) && player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing])
|
||||
{
|
||||
player->pflags ^= PF_WANTSTOJOIN;
|
||||
//player->powers[pw_flashing] = TICRATE + 1;
|
||||
player->powers[pw_flashing] = TICRATE/2 + 1;
|
||||
/*if (P_SpectatorJoinGame(player))
|
||||
return; // player->mo was removed.*/
|
||||
}
|
||||
|
|
14
src/r_main.c
14
src/r_main.c
|
@ -185,16 +185,6 @@ void SplitScreen_OnChange(void)
|
|||
{
|
||||
UINT8 i;
|
||||
|
||||
if (!cv_debug && netgame)
|
||||
{
|
||||
if (splitscreen)
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Splitscreen not supported in netplay, sorry!\n"));
|
||||
splitscreen = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// recompute screen size
|
||||
R_ExecuteSetViewSize();
|
||||
|
||||
|
@ -861,7 +851,7 @@ void R_SkyboxFrame(player_t *player)
|
|||
{
|
||||
aimingangle = player->aiming;
|
||||
viewangle = player->mo->angle;
|
||||
if (!demoplayback && player->playerstate != PST_DEAD)
|
||||
if (/*!demoplayback && */player->playerstate != PST_DEAD)
|
||||
{
|
||||
if (player == &players[consoleplayer])
|
||||
{
|
||||
|
@ -1138,7 +1128,7 @@ void R_SetupFrame(player_t *player, boolean skybox)
|
|||
aimingangle = player->aiming;
|
||||
viewangle = viewmobj->angle;
|
||||
|
||||
if (!demoplayback && player->playerstate != PST_DEAD)
|
||||
if (/*!demoplayback && */player->playerstate != PST_DEAD)
|
||||
{
|
||||
if (player == &players[consoleplayer])
|
||||
{
|
||||
|
|
|
@ -2699,7 +2699,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
|
|||
|
||||
player->jumpfactor = skin->jumpfactor;
|
||||
|
||||
if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback || modeattacking))
|
||||
/*if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback || modeattacking))
|
||||
{
|
||||
if (playernum == consoleplayer)
|
||||
CV_StealthSetValue(&cv_playercolor, skin->prefcolor);
|
||||
|
@ -2712,7 +2712,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
|
|||
player->skincolor = skin->prefcolor;
|
||||
if (player->mo)
|
||||
player->mo->color = player->skincolor;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (player->mo)
|
||||
P_SetScale(player->mo, player->mo->scale);
|
||||
|
|
|
@ -1927,7 +1927,7 @@ static void ST_overlayDrawer(void)
|
|||
)
|
||||
ST_drawLevelTitle();
|
||||
|
||||
if (!hu_showscores && !splitscreen && netgame && displayplayer == consoleplayer && !mapreset)
|
||||
if (!hu_showscores && netgame && !mapreset)
|
||||
{
|
||||
/*if (G_GametypeUsesLives() && stplyr->lives <= 0 && countdown != 1)
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), 0, M_GetText("Press F12 to watch another player."));
|
||||
|
@ -1952,15 +1952,33 @@ static void ST_overlayDrawer(void)
|
|||
)
|
||||
{
|
||||
// SRB2kart: changed positions & text
|
||||
V_DrawString(2, BASEVIDHEIGHT-40, V_HUDTRANSHALF|V_YELLOWMAP, M_GetText("- SPECTATING -"));
|
||||
if (stplyr->pflags & PF_WANTSTOJOIN)
|
||||
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Cancel Join"));
|
||||
/*else if (G_GametypeHasTeams())
|
||||
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Join Team"));*/
|
||||
if (splitscreen)
|
||||
{
|
||||
INT32 splitflags = K_calcSplitFlags(0);
|
||||
V_DrawThinString(2, (BASEVIDHEIGHT/2)-20, V_YELLOWMAP|V_HUDTRANSHALF|splitflags, M_GetText("- SPECTATING -"));
|
||||
if (stplyr->powers[pw_flashing])
|
||||
V_DrawString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|splitflags, M_GetText("Item - . . ."));
|
||||
else if (stplyr->pflags & PF_WANTSTOJOIN)
|
||||
V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|splitflags, M_GetText("Item - Cancel Join"));
|
||||
/*else if (G_GametypeHasTeams())
|
||||
V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|splitflags, M_GetText("Item - Join Team"));*/
|
||||
else
|
||||
V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|splitflags, M_GetText("Item - Join Game"));
|
||||
}
|
||||
else
|
||||
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Join Game"));
|
||||
V_DrawString(2, BASEVIDHEIGHT-20, V_HUDTRANSHALF, M_GetText("Accelerate - Float"));
|
||||
V_DrawString(2, BASEVIDHEIGHT-10, V_HUDTRANSHALF, M_GetText("Brake - Sink"));
|
||||
{
|
||||
V_DrawString(2, BASEVIDHEIGHT-40, V_HUDTRANSHALF|V_YELLOWMAP, M_GetText("- SPECTATING -"));
|
||||
if (stplyr->powers[pw_flashing])
|
||||
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - . . ."));
|
||||
else if (stplyr->pflags & PF_WANTSTOJOIN)
|
||||
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Cancel Join"));
|
||||
/*else if (G_GametypeHasTeams())
|
||||
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Join Team"));*/
|
||||
else
|
||||
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Join Game"));
|
||||
V_DrawString(2, BASEVIDHEIGHT-20, V_HUDTRANSHALF, M_GetText("Accelerate - Float"));
|
||||
V_DrawString(2, BASEVIDHEIGHT-10, V_HUDTRANSHALF, M_GetText("Brake - Sink"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -296,9 +296,9 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
|
|||
else
|
||||
data.match.pos[data.match.numplayers] = data.match.numplayers+1;
|
||||
|
||||
if (!rankingsmode && !(players[i].pflags & PF_TIMEOVER) && (data.match.pos[data.match.numplayers] != numplayersingame))
|
||||
if (!rankingsmode && !(players[i].pflags & PF_TIMEOVER) && (data.match.pos[data.match.numplayers] < nospectategrief))
|
||||
{
|
||||
data.match.increase[i] = numplayersingame - data.match.pos[data.match.numplayers];
|
||||
data.match.increase[i] = nospectategrief - data.match.pos[data.match.numplayers];
|
||||
players[i].score += data.match.increase[i];
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue