SRB2 2.1.2 release

This commit is contained in:
Alam Ed Arias 2014-03-17 08:13:16 -04:00
parent 3e0b5ef1cd
commit a03da73115
23 changed files with 261 additions and 120 deletions

View File

@ -1,7 +1,7 @@
srb2 for Debian srb2 for Debian
--------------- ---------------
Here it is! SRB2 v2.0 source code! Here it is! SRB2 v2.1.2 source code!
GNU/Linux GNU/Linux
~~~ ~~~

View File

@ -1,4 +1,4 @@
Here it is! SRB2 v2.1 (.1) source code! Here it is! SRB2 v2.1.2 source code!
Win32 with Visual C (6SP6+Processor Pack OR 7) Win32 with Visual C (6SP6+Processor Pack OR 7)

View File

@ -986,7 +986,6 @@ static UINT32 SL_SearchServer(INT32 node)
static void SL_InsertServer(serverinfo_pak* info, SINT8 node) static void SL_InsertServer(serverinfo_pak* info, SINT8 node)
{ {
UINT32 i; UINT32 i;
boolean moved;
// search if not already on it // search if not already on it
i = SL_SearchServer(node); i = SL_SearchServer(node);
@ -1008,49 +1007,8 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node)
serverlist[i].info = *info; serverlist[i].info = *info;
serverlist[i].node = node; serverlist[i].node = node;
// list is sorted, so move the entry until it is sorted // resort server list
do M_SortServerList();
{
INT32 keycurr = 0, keyprev = 0, keynext = 0;
switch(cv_serversort.value)
{
case 0: // Ping.
keycurr = (tic_t)LONG(serverlist[i].info.time);
if (i > 0) keyprev = (tic_t)LONG(serverlist[i-1].info.time);
if (i < serverlistcount - 1) keynext = (tic_t)LONG(serverlist[i+1].info.time);
break;
case 1: // Players.
keycurr = serverlist[i].info.numberofplayer;
if (i > 0) keyprev = serverlist[i-1].info.numberofplayer;
if (i < serverlistcount - 1) keynext = serverlist[i+1].info.numberofplayer;
break;
case 2: // Gametype.
keycurr = serverlist[i].info.gametype;
if (i > 0) keyprev = serverlist[i-1].info.gametype;
if (i < serverlistcount - 1) keynext = serverlist[i+1].info.gametype;
break;
}
moved = false;
if (i > 0 && keycurr < keyprev)
{
serverelem_t s;
s = serverlist[i];
serverlist[i] = serverlist[i-1];
serverlist[i-1] = s;
i--;
moved = true;
}
else if (i < serverlistcount - 1 && keycurr > keynext)
{
serverelem_t s;
s = serverlist[i];
serverlist[i] = serverlist[i+1];
serverlist[i+1] = s;
i++;
moved = true;
}
} while (moved);
} }
void CL_UpdateServerList(boolean internetsearch, INT32 room) void CL_UpdateServerList(boolean internetsearch, INT32 room)

View File

@ -1096,7 +1096,7 @@ void D_SRB2Main(void)
W_VerifyFileMD5(1, "a894044b555dfcc71865cee16a996e88"); // zones.dta W_VerifyFileMD5(1, "a894044b555dfcc71865cee16a996e88"); // zones.dta
W_VerifyFileMD5(2, "4c410c1de6e0440cc5b2858dcca80c3e"); // player.dta W_VerifyFileMD5(2, "4c410c1de6e0440cc5b2858dcca80c3e"); // player.dta
W_VerifyFileMD5(3, "85901ad4bf94637e5753d2ac2c03ea26"); // rings.dta W_VerifyFileMD5(3, "85901ad4bf94637e5753d2ac2c03ea26"); // rings.dta
W_VerifyFileMD5(4, "c529930ee5aed6dbe33625dc8075520b"); // patch.dta W_VerifyFileMD5(4, "17461512387ba6c5d7f2daa10346e1b5"); // patch.dta
// don't check music.dta because people like to modify it, and it doesn't matter if they do // don't check music.dta because people like to modify it, and it doesn't matter if they do
// ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for. // ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for.

View File

@ -3127,8 +3127,15 @@ static void Command_Addfile(void)
} }
p = fn+strlen(fn); p = fn+strlen(fn);
while(p > fn && *p != '\\' && *p != '/' && *p != ':') while(p > fn)
{
--p; --p;
if (*p == '\\' || *p == '/' || *p == ':')
{
++p;
break;
}
}
WRITESTRINGN(buf_p,p,240); WRITESTRINGN(buf_p,p,240);
{ {

View File

@ -6329,6 +6329,15 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_ORBITEM5", "S_ORBITEM5",
"S_ORBITEM6", "S_ORBITEM6",
"S_ORBITEM7", "S_ORBITEM7",
"S_ORBITEM8",
"S_ORBITEM9",
"S_ORBITEM10",
"S_ORBITEM11",
"S_ORBITEM12",
"S_ORBITEM13",
"S_ORBITEM14",
"S_ORBITEM15",
"S_ORBITEM16",
// "Flicky" helper // "Flicky" helper
"S_NIGHTOPIANHELPER1", "S_NIGHTOPIANHELPER1",

View File

@ -144,8 +144,8 @@ extern FILE *logstream;
#define VERSIONSTRING "Trunk" #define VERSIONSTRING "Trunk"
#else #else
#define VERSION 201 // Game version #define VERSION 201 // Game version
#define SUBVERSION 1 // more precise version number #define SUBVERSION 2 // more precise version number
#define VERSIONSTRING "v2.1.1" #define VERSIONSTRING "v2.1.2"
#endif #endif
// Modification options // Modification options
@ -201,7 +201,7 @@ extern FILE *logstream;
// it's only for detection of the version the player is using so the MS can alert them of an update. // it's only for detection of the version the player is using so the MS can alert them of an update.
// Only set it higher, not lower, obviously. // Only set it higher, not lower, obviously.
// Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1". // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1".
#define MODVERSION 5 #define MODVERSION 6

View File

@ -604,8 +604,14 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
if (tempchar) if (tempchar)
Z_Free(tempchar); Z_Free(tempchar);
} }
#ifdef _DEBUG
// I just want to point out while I'm here that because the data is still
// sent to all players, techincally anyone can see your chat if they really
// wanted to, even if you used sayto or sayteam.
// You should never send any sensitive info through sayto for that reason.
else else
CONS_Printf("Dropped chat: %d %d %s\n", playernum, target, msg); CONS_Printf("Dropped chat: %d %d %s\n", playernum, target, msg);
#endif
} }
#endif #endif

View File

@ -2782,6 +2782,15 @@ state_t states[NUMSTATES] =
{SPR_CEMG, FF_FULLBRIGHT+4, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM5}, // S_ORBITEM5 {SPR_CEMG, FF_FULLBRIGHT+4, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM5}, // S_ORBITEM5
{SPR_CEMG, FF_FULLBRIGHT+5, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM6}, // S_ORBITEM6 {SPR_CEMG, FF_FULLBRIGHT+5, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM6}, // S_ORBITEM6
{SPR_CEMG, FF_FULLBRIGHT+6, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM7}, // S_ORBITEM7 {SPR_CEMG, FF_FULLBRIGHT+6, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM7}, // S_ORBITEM7
{SPR_CEMG, FF_FULLBRIGHT+7, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM8
{SPR_CEMG, FF_FULLBRIGHT+8, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM9
{SPR_CEMG, FF_FULLBRIGHT+9, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM10
{SPR_CEMG, FF_FULLBRIGHT+10, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM11
{SPR_CEMG, FF_FULLBRIGHT+11, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM12
{SPR_CEMG, FF_FULLBRIGHT+12, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM13
{SPR_CEMG, FF_FULLBRIGHT+13, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM14
{SPR_CEMG, FF_FULLBRIGHT+14, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM15
{SPR_CEMG, FF_FULLBRIGHT+15, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM16
// Flicky helper for NiGHTS // Flicky helper for NiGHTS
{SPR_BIRD, 0, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER2}, // S_NIGHTOPIANHELPER1 {SPR_BIRD, 0, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER2}, // S_NIGHTOPIANHELPER1

View File

@ -3231,6 +3231,15 @@ typedef enum state
S_ORBITEM5, S_ORBITEM5,
S_ORBITEM6, S_ORBITEM6,
S_ORBITEM7, S_ORBITEM7,
S_ORBITEM8,
S_ORBITEM9,
S_ORBITEM10,
S_ORBITEM11,
S_ORBITEM12,
S_ORBITEM13,
S_ORBITEM14,
S_ORBITEM15,
S_ORBITEM16,
// "Flicky" helper // "Flicky" helper
S_NIGHTOPIANHELPER1, S_NIGHTOPIANHELPER1,

View File

@ -408,7 +408,7 @@ void LUAh_ThinkFrame(void)
// Remove this function from the hook table to prevent further errors. // Remove this function from the hook table to prevent further errors.
lua_pushvalue(gL, -1); // key lua_pushvalue(gL, -1); // key
lua_pushnil(gL); // value lua_pushnil(gL); // value
lua_rawset(gL, -5); // table lua_rawset(gL, -4); // table
CONS_Printf("Hook removed.\n"); CONS_Printf("Hook removed.\n");
} }
} }

View File

@ -195,7 +195,6 @@ static void M_StopMessage(INT32 choice);
static void M_HandleServerPage(INT32 choice); static void M_HandleServerPage(INT32 choice);
static void M_RoomMenu(INT32 choice); static void M_RoomMenu(INT32 choice);
#endif #endif
static void M_SortServerList(void);
// Prototyping is fun, innit? // Prototyping is fun, innit?
// ========================================================================== // ==========================================================================
@ -396,8 +395,11 @@ consvar_t cv_newgametype = {"newgametype", "Co-op", CV_HIDEN|CV_CALL, gametype_c
static CV_PossibleValue_t serversort_cons_t[] = { static CV_PossibleValue_t serversort_cons_t[] = {
{0,"Ping"}, {0,"Ping"},
{1,"Players"}, {1,"Modified State"},
{2,"Gametype"}, {2,"Most Players"},
{3,"Least Players"},
{4,"Max Players"},
{5,"Gametype"},
{0,NULL} {0,NULL}
}; };
consvar_t cv_serversort = {"serversort", "Ping", CV_HIDEN | CV_CALL, serversort_cons_t, M_SortServerList, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_serversort = {"serversort", "Ping", CV_HIDEN | CV_CALL, serversort_cons_t, M_SortServerList, 0, NULL, NULL, 0, 0, NULL};
@ -5770,15 +5772,46 @@ static boolean M_CancelConnect(void)
#define SERVER_LIST_ENTRY_COMPARATOR(key) \ #define SERVER_LIST_ENTRY_COMPARATOR(key) \
static int ServerListEntryComparator_##key(const void *entry1, const void *entry2) \ static int ServerListEntryComparator_##key(const void *entry1, const void *entry2) \
{ \ { \
return ((const serverelem_t*)entry1)->info.key - ((const serverelem_t*)entry2)->info.key; \ const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; \
if (sa->info.key != sb->info.key) \
return sa->info.key - sb->info.key; \
return strcmp(sa->info.servername, sb->info.servername); \
}
// This does descending instead of ascending.
#define SERVER_LIST_ENTRY_COMPARATOR_REVERSE(key) \
static int ServerListEntryComparator_##key##_reverse(const void *entry1, const void *entry2) \
{ \
const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; \
if (sb->info.key != sa->info.key) \
return sb->info.key - sa->info.key; \
return strcmp(sb->info.servername, sa->info.servername); \
} }
SERVER_LIST_ENTRY_COMPARATOR(time) SERVER_LIST_ENTRY_COMPARATOR(time)
SERVER_LIST_ENTRY_COMPARATOR(numberofplayer) SERVER_LIST_ENTRY_COMPARATOR(numberofplayer)
SERVER_LIST_ENTRY_COMPARATOR_REVERSE(numberofplayer)
SERVER_LIST_ENTRY_COMPARATOR_REVERSE(maxplayer)
SERVER_LIST_ENTRY_COMPARATOR(gametype) SERVER_LIST_ENTRY_COMPARATOR(gametype)
// Special one for modified state.
static int ServerListEntryComparator_modified(const void *entry1, const void *entry2)
{
const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2;
// Modified acts as 2 points, cheats act as one point.
int modstate_a = (sa->info.cheatsenabled ? 1 : 0) | (sa->info.modifiedgame ? 2 : 0);
int modstate_b = (sb->info.cheatsenabled ? 1 : 0) | (sb->info.modifiedgame ? 2 : 0);
if (modstate_a != modstate_b)
return modstate_a - modstate_b;
// Default to strcmp.
return strcmp(sa->info.servername, sb->info.servername);
}
#endif #endif
static void M_SortServerList(void) void M_SortServerList(void)
{ {
#ifndef NONET #ifndef NONET
switch(cv_serversort.value) switch(cv_serversort.value)
@ -5786,10 +5819,19 @@ static void M_SortServerList(void)
case 0: // Ping. case 0: // Ping.
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_time); qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_time);
break; break;
case 1: // Players. case 1: // Modified state.
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_modified);
break;
case 2: // Most players.
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_numberofplayer_reverse);
break;
case 3: // Least players.
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_numberofplayer); qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_numberofplayer);
break; break;
case 2: // Gametype. case 4: // Max players.
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_maxplayer_reverse);
break;
case 5: // Gametype.
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_gametype); qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_gametype);
break; break;
} }

View File

@ -45,6 +45,9 @@ void M_StartControlPanel(void);
// Called upon end of a mode attack run // Called upon end of a mode attack run
void M_EndModeAttackRun(void); void M_EndModeAttackRun(void);
// Called on new server add, or other reasons
void M_SortServerList(void);
// Draws a box with a texture inside as background for messages // Draws a box with a texture inside as background for messages
void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines); void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines);

View File

@ -93,7 +93,7 @@ UINT8 P_Random(void)
#else #else
UINT8 P_RandomD(const char *rfile, INT32 rline) UINT8 P_RandomD(const char *rfile, INT32 rline)
{ {
CONS_Debug(DBG_RANDOMIZER, "P_Random() at: %sp %d\n", rfile, rline); CONS_Printf("P_Random() at: %sp %d\n", rfile, rline);
#endif #endif
randomseed = (randomseed*746151647)+48205429; randomseed = (randomseed*746151647)+48205429;
return (UINT8)((randomseed >> 17)&255); return (UINT8)((randomseed >> 17)&255);
@ -111,7 +111,7 @@ INT32 P_SignedRandom(void)
#else #else
INT32 P_SignedRandomD(const char *rfile, INT32 rline) INT32 P_SignedRandomD(const char *rfile, INT32 rline)
{ {
CONS_Debug(DBG_RANDOMIZER, "P_SignedRandom() at: %sp %d\n", rfile, rline); CONS_Printf("P_SignedRandom() at: %sp %d\n", rfile, rline);
#endif #endif
return P_Random() - 128; return P_Random() - 128;
} }
@ -129,7 +129,7 @@ INT32 P_RandomKey(INT32 a)
#else #else
INT32 P_RandomKeyD(const char *rfile, INT32 rline, INT32 a) INT32 P_RandomKeyD(const char *rfile, INT32 rline, INT32 a)
{ {
CONS_Debug(DBG_RANDOMIZER, "P_RandomKey() at: %sp %d\n", rfile, rline); CONS_Printf("P_RandomKey() at: %sp %d\n", rfile, rline);
#endif #endif
return (INT32)(((P_Random()|(P_Random() << 8))/65536.0f)*a); return (INT32)(((P_Random()|(P_Random() << 8))/65536.0f)*a);
} }
@ -146,7 +146,7 @@ INT32 P_RandomRange(INT32 a, INT32 b)
#else #else
INT32 P_RandomRangeD(const char *rfile, INT32 rline, INT32 a, INT32 b) INT32 P_RandomRangeD(const char *rfile, INT32 rline, INT32 a, INT32 b)
{ {
CONS_Debug(DBG_RANDOMIZER, "P_RandomRange() at: %sp %d\n", rfile, rline); CONS_Printf("P_RandomRange() at: %sp %d\n", rfile, rline);
#endif #endif
return (INT32)(((P_Random()|(P_Random() << 8))/65536.0f)*(b-a+1))+a; return (INT32)(((P_Random()|(P_Random() << 8))/65536.0f)*(b-a+1))+a;
} }
@ -168,8 +168,14 @@ UINT8 P_RandomPeek(void)
* \return Current random seed. * \return Current random seed.
* \sa P_SetRandSeed * \sa P_SetRandSeed
*/ */
#ifndef DEBUGRANDOM
UINT32 P_GetRandSeed(void) UINT32 P_GetRandSeed(void)
{ {
#else
UINT32 P_GetRandSeedD(const char *rfile, INT32 rline)
{
CONS_Printf("P_GetRandSeed() at: %sp %d\n", rfile, rline);
#endif
return randomseed; return randomseed;
} }
@ -178,8 +184,14 @@ UINT32 P_GetRandSeed(void)
* \return Initial random seed. * \return Initial random seed.
* \sa P_SetRandSeed * \sa P_SetRandSeed
*/ */
#ifndef DEBUGRANDOM
UINT32 P_GetInitSeed(void) UINT32 P_GetInitSeed(void)
{ {
#else
UINT32 P_GetInitSeedD(const char *rfile, INT32 rline)
{
CONS_Printf("P_GetInitSeed() at: %sp %d\n", rfile, rline);
#endif
return initialseed; return initialseed;
} }
@ -189,8 +201,14 @@ UINT32 P_GetInitSeed(void)
* \param rindex New random index. * \param rindex New random index.
* \sa P_GetRandSeed * \sa P_GetRandSeed
*/ */
#ifndef DEBUGRANDOM
void P_SetRandSeed(UINT32 seed) void P_SetRandSeed(UINT32 seed)
{ {
#else
void P_SetRandSeedD(const char *rfile, INT32 rline, UINT32 seed)
{
CONS_Printf("P_SetRandSeed() at: %sp %d\n", rfile, rline);
#endif
randomseed = initialseed = seed; randomseed = initialseed = seed;
} }

View File

@ -18,6 +18,8 @@
#include "doomtype.h" #include "doomtype.h"
#include "m_fixed.h" #include "m_fixed.h"
//#define DEBUGRANDOM
// M_Random functions pull random numbers of various types that aren't network synced. // M_Random functions pull random numbers of various types that aren't network synced.
// P_Random functions pulls random bytes from a LCG PRNG that is network synced. // P_Random functions pulls random bytes from a LCG PRNG that is network synced.
@ -46,9 +48,18 @@ INT32 P_RandomRange(INT32 a, INT32 b);
UINT8 P_RandomPeek(void); UINT8 P_RandomPeek(void);
// Working with the seed for PRNG // Working with the seed for PRNG
#ifdef DEBUGRANDOM
#define P_GetRandSeed() P_GetRandSeedD(__FILE__, __LINE__)
#define P_GetInitSeed() P_GetInitSeedD(__FILE__, __LINE__)
#define P_SetRandSeed(s) P_SetRandSeedD(__FILE__, __LINE__, s)
UINT32 P_GetRandSeedD(const char *rfile, INT32 rline);
UINT32 P_GetInitSeedD(const char *rfile, INT32 rline);
void P_SetRandSeedD(const char *rfile, INT32 rline, UINT32 seed);
#else
UINT32 P_GetRandSeed(void); UINT32 P_GetRandSeed(void);
UINT32 P_GetInitSeed(void); UINT32 P_GetInitSeed(void);
void P_SetRandSeed(UINT32 seed); void P_SetRandSeed(UINT32 seed);
#endif
UINT32 M_RandomizedSeed(void); UINT32 M_RandomizedSeed(void);
#endif #endif

View File

@ -550,7 +550,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Secret emblem thingy // Secret emblem thingy
case MT_EMBLEM: case MT_EMBLEM:
{ {
if (modeattacking == ATTACKING_RECORD || demoplayback || player->bot) if (demoplayback || player->bot)
return; return;
emblemlocations[special->health-1].collected = true; emblemlocations[special->health-1].collected = true;
@ -637,6 +637,17 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
P_GiveEmerald(false); P_GiveEmerald(false);
// Don't play Ideya sound in special stage mode // Don't play Ideya sound in special stage mode
} }
else // Make sure that SOMEONE has the emerald, at least!
{
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].playerstate == PST_LIVE
&& players[i].mo->tracer && players[i].mo->tracer->target
&& players[i].mo->tracer->target->type == MT_GOTEMERALD)
return;
// Well no one has an emerald, so exit anyway!
P_NightserizePlayer(player, special->health);
P_GiveEmerald(false);
}
} }
else if (player->bonustime && !player->exiting) //After-mare bonus time/emerald reward in special stages. else if (player->bonustime && !player->exiting) //After-mare bonus time/emerald reward in special stages.
{ {
@ -1505,8 +1516,10 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
case MT_PLAYER: case MT_PLAYER:
if ((inflictor->player->powers[pw_shield] & SH_NOSTACK) == SH_BOMB) if ((inflictor->player->powers[pw_shield] & SH_NOSTACK) == SH_BOMB)
str = M_GetText("%s%s's armageddon blast %s %s.\n"); str = M_GetText("%s%s's armageddon blast %s %s.\n");
else else if (inflictor->player->powers[pw_invulnerability])
str = M_GetText("%s%s's invincibility aura %s %s.\n"); str = M_GetText("%s%s's invincibility aura %s %s.\n");
else
str = M_GetText("%s%s's tagging hand %s %s.\n");
break; break;
case MT_SPINFIRE: case MT_SPINFIRE:
str = M_GetText("%s%s's elemental fire trail %s %s.\n"); str = M_GetText("%s%s's elemental fire trail %s %s.\n");
@ -1534,7 +1547,7 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
if (inflictor->flags2 & MF2_RAILRING) if (inflictor->flags2 & MF2_RAILRING)
str = M_GetText("%s%s's rail ring %s %s.\n"); str = M_GetText("%s%s's rail ring %s %s.\n");
else else
str = M_GetText("%s%s's red ring %s %s.\n"); str = M_GetText("%s%s's thrown ring %s %s.\n");
break; break;
default: default:
str = M_GetText("%s%s %s %s.\n"); str = M_GetText("%s%s %s %s.\n");

View File

@ -9129,8 +9129,6 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
else if (maptol & TOL_XMAS) else if (maptol & TOL_XMAS)
P_SetMobjState(mobj, mobj->info->seestate); P_SetMobjState(mobj, mobj->info->seestate);
if (mobj->tics > 0)
mobj->tics = 1 + P_RandomKey(mobj->tics);
mobj->angle = FixedAngle(mthing->angle*FRACUNIT); mobj->angle = FixedAngle(mthing->angle*FRACUNIT);
mobj->flags |= MF_AMBUSH; mobj->flags |= MF_AMBUSH;
mthing->mobj = mobj; mthing->mobj = mobj;
@ -9199,8 +9197,6 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
mobj->flags2 |= MF2_OBJECTFLIP; mobj->flags2 |= MF2_OBJECTFLIP;
} }
if (mobj->tics > 0)
mobj->tics = 1 + P_RandomKey(mobj->tics);
mobj->angle = FixedAngle(mthing->angle*FRACUNIT); mobj->angle = FixedAngle(mthing->angle*FRACUNIT);
mobj->flags |= MF_AMBUSH; mobj->flags |= MF_AMBUSH;
mthing->mobj = mobj; mthing->mobj = mobj;
@ -9252,9 +9248,6 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
mobj->flags2 |= MF2_OBJECTFLIP; mobj->flags2 |= MF2_OBJECTFLIP;
} }
if (mobj->tics > 0)
mobj->tics = 1 + P_RandomKey(mobj->tics);
mobj->angle = FixedAngle(mthing->angle*FRACUNIT); mobj->angle = FixedAngle(mthing->angle*FRACUNIT);
if (mthing->options & MTF_AMBUSH) if (mthing->options & MTF_AMBUSH)
mobj->flags |= MF_AMBUSH; mobj->flags |= MF_AMBUSH;
@ -9309,9 +9302,6 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
mobj->flags2 |= MF2_OBJECTFLIP; mobj->flags2 |= MF2_OBJECTFLIP;
} }
if (mobj->tics > 0)
mobj->tics = 1 + P_RandomKey(mobj->tics);
mobj->angle = FixedAngle(mthing->angle*FRACUNIT); mobj->angle = FixedAngle(mthing->angle*FRACUNIT);
if (mthing->options & MTF_AMBUSH) if (mthing->options & MTF_AMBUSH)
mobj->flags |= MF_AMBUSH; mobj->flags |= MF_AMBUSH;

View File

@ -34,6 +34,15 @@
savedata_t savedata; savedata_t savedata;
UINT8 *save_p; UINT8 *save_p;
// Block UINT32s to attempt to ensure that the correct data is
// being sent and received
#define ARCHIVEBLOCK_MISC 0x7FEEDEED
#define ARCHIVEBLOCK_PLAYERS 0x7F448008
#define ARCHIVEBLOCK_WORLD 0x7F8C08C0
#define ARCHIVEBLOCK_POBJS 0x7F928546
#define ARCHIVEBLOCK_THINKERS 0x7F37037C
#define ARCHIVEBLOCK_SPECIALS 0x7F228378
// Note: This cannot be bigger // Note: This cannot be bigger
// than an UINT16 // than an UINT16
typedef enum typedef enum
@ -102,6 +111,8 @@ static inline void P_NetArchivePlayers(void)
UINT16 flags; UINT16 flags;
// size_t q; // size_t q;
WRITEUINT32(save_p, ARCHIVEBLOCK_PLAYERS);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i]) if (!playeringame[i])
@ -272,6 +283,9 @@ static inline void P_NetUnArchivePlayers(void)
INT32 i, j; INT32 i, j;
UINT16 flags; UINT16 flags;
if (READUINT32(save_p) != ARCHIVEBLOCK_PLAYERS)
I_Error("Bad $$$.sav at archive block Players");
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
memset(&players[i], 0, sizeof (player_t)); memset(&players[i], 0, sizeof (player_t));
@ -414,7 +428,7 @@ static inline void P_NetUnArchivePlayers(void)
players[i].revitem = (mobjtype_t)READUINT32(save_p); players[i].revitem = (mobjtype_t)READUINT32(save_p);
players[i].actionspd = READFIXED(save_p); players[i].actionspd = READFIXED(save_p);
players[i].mindash = READFIXED(save_p); players[i].mindash = READFIXED(save_p);
players[i].maxdash = READINT32(save_p); players[i].maxdash = READFIXED(save_p);
players[i].normalspeed = READFIXED(save_p); players[i].normalspeed = READFIXED(save_p);
players[i].runspeed = READFIXED(save_p); players[i].runspeed = READFIXED(save_p);
players[i].thrustfactor = READUINT8(save_p); players[i].thrustfactor = READUINT8(save_p);
@ -464,7 +478,7 @@ static void P_NetArchiveWorld(void)
INT32 statsec = 0, statline = 0; INT32 statsec = 0, statline = 0;
const line_t *li = lines; const line_t *li = lines;
const side_t *si; const side_t *si;
UINT8 *put = save_p; UINT8 *put;
// reload the map just to see difference // reload the map just to see difference
const mapsector_t *ms; const mapsector_t *ms;
@ -473,6 +487,9 @@ static void P_NetArchiveWorld(void)
const sector_t *ss = sectors; const sector_t *ss = sectors;
UINT8 diff, diff2; UINT8 diff, diff2;
WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD);
put = save_p;
ms = W_CacheLumpNum(lastloadedmaplumpnum+ML_SECTORS, PU_CACHE); ms = W_CacheLumpNum(lastloadedmaplumpnum+ML_SECTORS, PU_CACHE);
for (i = 0; i < numsectors; i++, ss++, ms++) for (i = 0; i < numsectors; i++, ss++, ms++)
@ -653,6 +670,9 @@ static void P_NetUnArchiveWorld(void)
UINT8 *get; UINT8 *get;
UINT8 diff, diff2; UINT8 diff, diff2;
if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD)
I_Error("Bad $$$.sav at archive block World");
get = save_p; get = save_p;
for (;;) for (;;)
@ -1272,6 +1292,8 @@ static void P_NetArchiveThinkers(void)
UINT32 diff; UINT32 diff;
UINT16 diff2; UINT16 diff2;
WRITEUINT32(save_p, ARCHIVEBLOCK_THINKERS);
// save off the current thinkers // save off the current thinkers
for (th = thinkercap.next; th != &thinkercap; th = th->next) for (th = thinkercap.next; th != &thinkercap; th = th->next)
{ {
@ -2189,6 +2211,9 @@ static void P_NetUnArchiveThinkers(void)
UINT8 restoreNum = false; UINT8 restoreNum = false;
fixed_t z, floorz, ceilingz; fixed_t z, floorz, ceilingz;
if (READUINT32(save_p) != ARCHIVEBLOCK_THINKERS)
I_Error("Bad $$$.sav at archive block Thinkers");
// remove all the current thinkers // remove all the current thinkers
currentthinker = thinkercap.next; currentthinker = thinkercap.next;
for (currentthinker = thinkercap.next; currentthinker != &thinkercap; currentthinker = next) for (currentthinker = thinkercap.next; currentthinker != &thinkercap; currentthinker = next)
@ -2247,6 +2272,9 @@ static void P_NetUnArchiveThinkers(void)
else else
mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL);
// declare this as a valid mobj as soon as possible.
mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker;
mobj->z = z; mobj->z = z;
mobj->floorz = floorz; mobj->floorz = floorz;
mobj->ceilingz = ceilingz; mobj->ceilingz = ceilingz;
@ -2279,7 +2307,7 @@ static void P_NetUnArchiveThinkers(void)
{ {
mobj->x = mobj->spawnpoint->x << FRACBITS; mobj->x = mobj->spawnpoint->x << FRACBITS;
mobj->y = mobj->spawnpoint->y << FRACBITS; mobj->y = mobj->spawnpoint->y << FRACBITS;
mobj->angle = ANGLE_45 * (mobj->spawnpoint->angle/45); /// \bug unknown mobj->angle = FixedAngle(mobj->spawnpoint->angle*FRACUNIT);
} }
if (diff & MD_MOM) if (diff & MD_MOM)
{ {
@ -2421,7 +2449,6 @@ static void P_NetUnArchiveThinkers(void)
mobj->player->viewz = mobj->player->mo->z + mobj->player->viewheight; mobj->player->viewz = mobj->player->mo->z + mobj->player->viewheight;
} }
mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker;
P_AddThinker(&mobj->thinker); P_AddThinker(&mobj->thinker);
mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function
@ -2628,6 +2655,8 @@ static inline void P_ArchivePolyObjects(void)
{ {
INT32 i; INT32 i;
WRITEUINT32(save_p, ARCHIVEBLOCK_POBJS);
// save number of polyobjects // save number of polyobjects
WRITEINT32(save_p, numPolyObjects); WRITEINT32(save_p, numPolyObjects);
@ -2639,6 +2668,9 @@ static inline void P_UnArchivePolyObjects(void)
{ {
INT32 i, numSavedPolys; INT32 i, numSavedPolys;
if (READUINT32(save_p) != ARCHIVEBLOCK_POBJS)
I_Error("Bad $$$.sav at archive block Pobjs");
numSavedPolys = READINT32(save_p); numSavedPolys = READINT32(save_p);
if (numSavedPolys != numPolyObjects) if (numSavedPolys != numPolyObjects)
@ -2752,6 +2784,8 @@ static inline void P_NetArchiveSpecials(void)
{ {
size_t i, z; size_t i, z;
WRITEUINT32(save_p, ARCHIVEBLOCK_SPECIALS);
// itemrespawn queue for deathmatch // itemrespawn queue for deathmatch
i = iquetail; i = iquetail;
while (iquehead != i) while (iquehead != i)
@ -2786,6 +2820,9 @@ static void P_NetUnArchiveSpecials(void)
size_t i; size_t i;
INT32 j; INT32 j;
if (READUINT32(save_p) != ARCHIVEBLOCK_SPECIALS)
I_Error("Bad $$$.sav at archive block Specials");
// BP: added save itemrespawn queue for deathmatch // BP: added save itemrespawn queue for deathmatch
iquetail = iquehead = 0; iquetail = iquehead = 0;
while ((i = READUINT32(save_p)) != 0xffffffff) while ((i = READUINT32(save_p)) != 0xffffffff)
@ -2878,14 +2915,17 @@ static void P_NetArchiveMisc(void)
UINT32 pig = 0; UINT32 pig = 0;
INT32 i; INT32 i;
WRITEUINT32(save_p, ARCHIVEBLOCK_MISC);
WRITEINT16(save_p, gamemap); WRITEINT16(save_p, gamemap);
WRITEUINT16(save_p, gamestate); WRITEINT16(save_p, gamestate);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
pig |= (playeringame[i] != 0)<<i; pig |= (playeringame[i] != 0)<<i;
WRITEUINT32(save_p, pig); WRITEUINT32(save_p, pig);
WRITEUINT32(save_p, P_GetRandSeed()); WRITEUINT32(save_p, P_GetRandSeed());
WRITEUINT32(save_p, tokenlist); WRITEUINT32(save_p, tokenlist);
WRITEUINT32(save_p, leveltime); WRITEUINT32(save_p, leveltime);
@ -2934,6 +2974,9 @@ static inline boolean P_NetUnArchiveMisc(void)
UINT32 pig; UINT32 pig;
INT32 i; INT32 i;
if (READUINT32(save_p) != ARCHIVEBLOCK_MISC)
I_Error("Bad $$$.sav at archive block Misc");
gamemap = READINT16(save_p); gamemap = READINT16(save_p);
// gamemap changed; we assume that its map header is always valid, // gamemap changed; we assume that its map header is always valid,
@ -2941,13 +2984,17 @@ static inline boolean P_NetUnArchiveMisc(void)
if(!mapheaderinfo[gamemap-1]) if(!mapheaderinfo[gamemap-1])
P_AllocMapHeader(gamemap-1); P_AllocMapHeader(gamemap-1);
// tell the sound code to reset the music since we're skipping what
// normally sets this flag
mapmusic |= MUSIC_RELOADRESET;
G_SetGamestate(READINT16(save_p)); G_SetGamestate(READINT16(save_p));
pig = READUINT32(save_p); pig = READUINT32(save_p);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
playeringame[i] = (pig & (1<<i)) != 0; playeringame[i] = (pig & (1<<i)) != 0;
players[i].playerstate = PST_REBORN; // playerstate is set in unarchiveplayers
} }
P_SetRandSeed(READUINT32(save_p)); P_SetRandSeed(READUINT32(save_p));
@ -3086,6 +3133,9 @@ boolean P_LoadNetGame(void)
LUA_UnArchive(); LUA_UnArchive();
#endif #endif
// This is stupid and hacky, but maybe it'll work!
P_SetRandSeed(P_GetInitSeed());
// The precipitation would normally be spawned in P_SetupLevel, which is called by // The precipitation would normally be spawned in P_SetupLevel, which is called by
// P_NetUnArchiveMisc above. However, that would place it up before P_NetUnArchiveThinkers, // P_NetUnArchiveMisc above. However, that would place it up before P_NetUnArchiveThinkers,
// so the thinkers would be deleted later. Therefore, P_SetupLevel will *not* spawn // so the thinkers would be deleted later. Therefore, P_SetupLevel will *not* spawn

View File

@ -1055,7 +1055,7 @@ static inline void P_SpawnEmblems(void)
static void P_SpawnSecretItems(boolean loademblems) static void P_SpawnSecretItems(boolean loademblems)
{ {
// Now let's spawn those funky emblem things! Tails 12-08-2002 // Now let's spawn those funky emblem things! Tails 12-08-2002
if (netgame || multiplayer || (modifiedgame && !savemoddata) || modeattacking == ATTACKING_RECORD) // No cheating!! if (netgame || multiplayer || (modifiedgame && !savemoddata)) // No cheating!!
return; return;
if (loademblems) if (loademblems)

View File

@ -1212,7 +1212,7 @@
C01FCF4B08A954540054247B /* Debug */ = { C01FCF4B08A954540054247B /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
CURRENT_PROJECT_VERSION = 2.1.1; CURRENT_PROJECT_VERSION = 2.1.2;
GCC_PREPROCESSOR_DEFINITIONS = ( GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)", "$(inherited)",
NORMALSRB2, NORMALSRB2,
@ -1224,7 +1224,7 @@
C01FCF4C08A954540054247B /* Release */ = { C01FCF4C08A954540054247B /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
CURRENT_PROJECT_VERSION = 2.1.1; CURRENT_PROJECT_VERSION = 2.1.2;
GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_ENABLE_FIX_AND_CONTINUE = NO;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_PREPROCESSOR_DEFINITIONS = ( GCC_PREPROCESSOR_DEFINITIONS = (

View File

@ -1233,7 +1233,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"statu1", true, 64, 2, -1, NULL, 0, -1, -1, LUMPERROR}, {"statu1", true, 64, 2, -1, NULL, 0, -1, -1, LUMPERROR},
{"statu2", true, 64, 2, -1, NULL, 0, -1, -1, LUMPERROR}, {"statu2", true, 64, 2, -1, NULL, 0, -1, -1, LUMPERROR},
{"strpst", true, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Starpost Sound Tails 07-04-2002 {"strpst", true, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Starpost Sound Tails 07-04-2002
{"supert", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"supert", true, 127, 2, -1, NULL, 0, -1, -1, LUMPERROR},
{"telept", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"telept", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"tink" , false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"tink" , false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"token" , true, 224, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // SS token {"token" , true, 224, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // SS token

View File

@ -796,41 +796,54 @@ static void ST_drawFirstPersonHUD(void)
{ {
player_t *player = stplyr; player_t *player = stplyr;
patch_t *p = NULL; patch_t *p = NULL;
UINT16 invulntime = 0;
if (player->playerstate != PST_LIVE)
return;
// Graue 06-18-2004: no V_NOSCALESTART, no SCX, no SCY, snap to right // Graue 06-18-2004: no V_NOSCALESTART, no SCX, no SCY, snap to right
if (player->powers[pw_shield] & SH_FORCE) if (player->powers[pw_shield] & SH_FORCE)
{ {
if ((player->powers[pw_shield] & 0xFF) > 0 || leveltime & 1) if ((player->powers[pw_shield] & 0xFF) > 0 || leveltime & 1)
V_DrawScaledPatch(304, STRINGY(32), V_SNAPTORIGHT|V_TRANSLUCENT, forceshield); p = forceshield;
} }
else switch (player->powers[pw_shield] & SH_NOSTACK) else switch (player->powers[pw_shield] & SH_NOSTACK)
{ {
case SH_JUMP: case SH_JUMP: p = jumpshield; break;
V_DrawScaledPatch(304, STRINGY(32), V_SNAPTORIGHT|V_TRANSLUCENT, jumpshield); case SH_ELEMENTAL: p = watershield; break;
break; case SH_BOMB: p = bombshield; break;
case SH_ELEMENTAL: case SH_ATTRACT: p = ringshield; break;
V_DrawScaledPatch(304, STRINGY(32), V_SNAPTORIGHT|V_TRANSLUCENT, watershield); case SH_PITY: p = pityshield; break;
break; default: break;
case SH_BOMB:
V_DrawScaledPatch(304, STRINGY(32), V_SNAPTORIGHT|V_TRANSLUCENT, bombshield);
break;
case SH_ATTRACT:
V_DrawScaledPatch(304, STRINGY(32), V_SNAPTORIGHT|V_TRANSLUCENT, ringshield);
break;
case SH_PITY:
V_DrawScaledPatch(304, STRINGY(32), V_SNAPTORIGHT|V_TRANSLUCENT, pityshield);
break;
default:
break;
} }
if (player->playerstate != PST_DEAD && ((player->powers[pw_invulnerability] > 3*TICRATE || (player->powers[pw_invulnerability] if (p)
&& leveltime & 1)) || ((player->powers[pw_flashing] && leveltime & 1)))) {
V_DrawScaledPatch(304, STRINGY(60), V_SNAPTORIGHT|V_TRANSLUCENT, invincibility); if (splitscreen)
V_DrawSmallScaledPatch(312, STRINGY(24), V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, p);
else
V_DrawScaledPatch(304, 24, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, p);
}
if (player->powers[pw_sneakers] > 3*TICRATE || (player->powers[pw_sneakers] // pw_flashing just sets the icon to flash no matter what.
&& leveltime & 1)) invulntime = player->powers[pw_flashing] ? 1 : player->powers[pw_invulnerability];
V_DrawScaledPatch(304, STRINGY(88), V_SNAPTORIGHT|V_TRANSLUCENT, sneakers); if (invulntime > 3*TICRATE || (invulntime && leveltime & 1))
{
if (splitscreen)
V_DrawSmallScaledPatch(312, STRINGY(24) + 14, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, invincibility);
else
V_DrawScaledPatch(304, 24 + 28, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, invincibility);
}
if (player->powers[pw_sneakers] > 3*TICRATE || (player->powers[pw_sneakers] && leveltime & 1))
{
if (splitscreen)
V_DrawSmallScaledPatch(312, STRINGY(24) + 28, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, sneakers);
else
V_DrawScaledPatch(304, 24 + 56, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, sneakers);
}
p = NULL;
// Display the countdown drown numbers! // Display the countdown drown numbers!
if ((player->powers[pw_underwater] <= 11*TICRATE + 1 if ((player->powers[pw_underwater] <= 11*TICRATE + 1
@ -1505,15 +1518,15 @@ static void ST_drawCTFHUD(void)
break; // both flags were found, let's stop early break; // both flags were found, let's stop early
} }
if (stplyr->gotflag & GF_REDFLAG) // YOU have a flag. Display a monitor-like icon for it.
if (stplyr->gotflag)
{ {
// YOU HAVE THE RED FLAG patch_t *p = (stplyr->gotflag & GF_REDFLAG) ? gotrflag : gotbflag;
V_DrawScaledPatch(224, (splitscreen) ? STRINGY(160) : STRINGY(176), 0, gotrflag);
} if (splitscreen)
else if (stplyr->gotflag & GF_BLUEFLAG) V_DrawSmallScaledPatch(312, STRINGY(24) + 42, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, p);
{ else
// YOU HAVE THE BLUE FLAG V_DrawScaledPatch(304, 24 + 84, V_SNAPTORIGHT|V_SNAPTOTOP|V_TRANSLUCENT, p);
V_DrawScaledPatch(224, (splitscreen) ? STRINGY(160) : STRINGY(176), 0, gotbflag);
} }
// Display a countdown timer showing how much time left until the flag your team dropped returns to base. // Display a countdown timer showing how much time left until the flag your team dropped returns to base.

View File

@ -1058,8 +1058,11 @@ void Y_StartIntermission(void)
case int_spec: // coop or single player, special stage case int_spec: // coop or single player, special stage
{ {
// Update visitation flags? // Update visitation flags?
if (!stagefailed) if ((!modifiedgame || savemoddata) && !multiplayer && !demoplayback)
mapvisited[gamemap-1] |= MV_BEATEN; {
if (!stagefailed)
mapvisited[gamemap-1] |= MV_BEATEN;
}
// give out ring bonuses // give out ring bonuses
Y_AwardSpecialStageBonus(); Y_AwardSpecialStageBonus();