SRB2 2.1.3 release

This commit is contained in:
Alam Ed Arias 2014-03-18 13:56:54 -04:00
parent eb70242fd0
commit 2fed5d1270
26 changed files with 277 additions and 272 deletions

View file

@ -3044,8 +3044,6 @@ FILESTAMP
case PT_SERVERREFUSE: // negative response of client join request case PT_SERVERREFUSE: // negative response of client join request
if (server && serverrunning) if (server && serverrunning)
{ // but wait I thought I'm the server? { // but wait I thought I'm the server?
if (I_Shun)
I_Shun(node); // No more garbage from you!
Net_CloseConnection(node); Net_CloseConnection(node);
break; break;
} }
@ -3070,8 +3068,6 @@ FILESTAMP
if (server && serverrunning && node != servernode) if (server && serverrunning && node != servernode)
{ // but wait I thought I'm the server? { // but wait I thought I'm the server?
if (I_Shun)
I_Shun(node); // No more garbage from you!
Net_CloseConnection(node); Net_CloseConnection(node);
break; break;
} }
@ -3122,8 +3118,6 @@ FILESTAMP
case PT_FILEFRAGMENT: case PT_FILEFRAGMENT:
if (server) if (server)
{ // but wait I thought I'm the server? { // but wait I thought I'm the server?
if (I_Shun)
I_Shun(node); // No more garbage from you!
Net_CloseConnection(node); Net_CloseConnection(node);
break; break;
} }
@ -3147,8 +3141,6 @@ FILESTAMP
break; break;
default: default:
DEBFILE(va("unknown packet received (%d) from unknown host\n",netbuffer->packettype)); DEBFILE(va("unknown packet received (%d) from unknown host\n",netbuffer->packettype));
if (I_Shun)
I_Shun(node); // No more garbage from you!
Net_CloseConnection(node); Net_CloseConnection(node);
break; // ignore it break; // ignore it
} // switch } // switch
@ -3225,11 +3217,13 @@ FILESTAMP
// Careful: When a consistency packet is sent, it overwrites the incoming packet containing the ticcmd. // Careful: When a consistency packet is sent, it overwrites the incoming packet containing the ticcmd.
// Keep this in mind when changing the code that responds to these packets. // Keep this in mind when changing the code that responds to these packets.
if (realstart <= gametic && realstart > gametic - BACKUPTICS+1 if (realstart <= gametic && realstart > gametic - BACKUPTICS+1
&& players[netconsole].pflags & PF_CONSISTANCY && gamestate == GS_LEVEL && playeringame[netconsole]
&& consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy) && players[netconsole].playerstate == PST_LIVE
&& gamestate == GS_LEVEL) && !players[netconsole].spectator
&& players[netconsole].jointime > 10
&& consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy))
{ {
if (cv_consfailprotect.value && playeringame[netconsole] && consfailcount[netconsole] < cv_consfailprotect.value) if (cv_consfailprotect.value && consfailcount[netconsole] < cv_consfailprotect.value)
{ {
if (!consfailstatus[netconsole]) if (!consfailstatus[netconsole])
{ {
@ -3266,7 +3260,6 @@ FILESTAMP
DEBFILE(va("player %d kicked (consistency failure) [%u] %d!=%d\n", DEBFILE(va("player %d kicked (consistency failure) [%u] %d!=%d\n",
netconsole, realstart, consistancy[realstart%BACKUPTICS], netconsole, realstart, consistancy[realstart%BACKUPTICS],
SHORT(netbuffer->u.clientpak.consistancy))); SHORT(netbuffer->u.clientpak.consistancy)));
players[netconsole].pflags &= ~PF_CONSISTANCY;
consfailstatus[netconsole] = 0; consfailstatus[netconsole] = 0;
consfailcount[netconsole] = 0; consfailcount[netconsole] = 0;
break; break;
@ -3477,7 +3470,6 @@ FILESTAMP
// Builds ticcmds for console player, // Builds ticcmds for console player,
// sends out a packet // sends out a packet
// //
// no more use random generator, because at very first tic isn't yet synchronized
// Note: It is called consistAncy on purpose. // Note: It is called consistAncy on purpose.
// //
static INT16 Consistancy(void) static INT16 Consistancy(void)
@ -3487,14 +3479,14 @@ static INT16 Consistancy(void)
DEBFILE(va("TIC %u ", gametic)); DEBFILE(va("TIC %u ", gametic));
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !players[i].spectator && players[i].pflags & PF_CONSISTANCY) if (playeringame[i] && players[i].mo && players[i].playerstate == PST_LIVE && !players[i].spectator)
{ {
DEBFILE(va("p[%d].x = %f ", i, (double)FIXED_TO_FLOAT(players[i].mo->x))); //DEBFILE(va("p[%d].x = %f ", i, (double)FIXED_TO_FLOAT(players[i].mo->x)));
ret = (INT16)((ret + players[i].mo->x) & 0xFFFF); ret = (INT16)((ret + (players[i].mo->x>>8)) & 0xFFFF);
ret = (INT16)((ret + players[i].powers[pw_shield]) & 0xFFFF); ret = (INT16)((ret + players[i].powers[pw_shield]) & 0xFFFF);
} }
//DEBFILE(va("pos = %d, rnd %d\n", ret, P_GetRandSeed())); DEBFILE(va("players = %d, rnd %d\n", ret, P_GetRandSeed()));
//ret = (INT16)(ret + P_GetRandSeed()); ret = (INT16)(ret + P_GetRandSeed());
return ret; return ret;
} }

View file

@ -1087,16 +1087,14 @@ void D_SRB2Main(void)
#endif #endif
D_CleanFile(); D_CleanFile();
#if 1 // md5s last updated 3/15/14 #if 1 // md5s last updated 3/18/14
// Yes, you read that right, that's the day of release.
// Aren't we batshit insane?
// Check MD5s of autoloaded files // Check MD5s of autoloaded files
W_VerifyFileMD5(0, "ac309fb3c7d4b5b685e2cd26beccf0e8"); // srb2.srb/srb2.wad W_VerifyFileMD5(0, "ac309fb3c7d4b5b685e2cd26beccf0e8"); // srb2.srb/srb2.wad
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, "17461512387ba6c5d7f2daa10346e1b5"); // patch.dta W_VerifyFileMD5(4, "12c58561edf3be16a15505f1d5eacee0"); // 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.
@ -1191,12 +1189,11 @@ void D_SRB2Main(void)
{ {
if (!M_IsNextParm()) if (!M_IsNextParm())
I_Error("usage: -room <room_id>\nCheck the Master Server's webpage for room ID numbers.\n"); I_Error("usage: -room <room_id>\nCheck the Master Server's webpage for room ID numbers.\n");
ms_RoomId = atoi(M_GetNextParm());
#ifdef UPDATE_ALERT #ifdef UPDATE_ALERT
GetMODVersion_Console(); GetMODVersion_Console();
#endif #endif
ms_RoomId = atoi(M_GetNextParm());
} }
// init all NETWORK // init all NETWORK

View file

@ -71,7 +71,6 @@ void (*I_NetFreeNodenum)(INT32 nodenum) = NULL;
SINT8 (*I_NetMakeNodewPort)(const char *address, const char* port) = NULL; SINT8 (*I_NetMakeNodewPort)(const char *address, const char* port) = NULL;
boolean (*I_NetOpenSocket)(void) = NULL; boolean (*I_NetOpenSocket)(void) = NULL;
boolean (*I_Ban) (INT32 node) = NULL; boolean (*I_Ban) (INT32 node) = NULL;
boolean (*I_Shun) (INT32 node) = NULL;
void (*I_ClearBans)(void) = NULL; void (*I_ClearBans)(void) = NULL;
const char *(*I_GetNodeAddress) (INT32 node) = NULL; const char *(*I_GetNodeAddress) (INT32 node) = NULL;
const char *(*I_GetBanAddress) (size_t ban) = NULL; const char *(*I_GetBanAddress) (size_t ban) = NULL;
@ -990,8 +989,6 @@ boolean HGetPacket(void)
if (netbuffer->checksum != NetbufferChecksum()) if (netbuffer->checksum != NetbufferChecksum())
{ {
DEBFILE("Bad packet checksum\n"); DEBFILE("Bad packet checksum\n");
if (I_Shun)
I_Shun(doomcom->remotenode); // No more garbage from you!
Net_CloseConnection(doomcom->remotenode); Net_CloseConnection(doomcom->remotenode);
continue; continue;
} }

View file

@ -1079,6 +1079,10 @@ static void SendNameAndColor(void)
&& !strcmp(cv_skin.string, skins[players[consoleplayer].skin].name)) && !strcmp(cv_skin.string, skins[players[consoleplayer].skin].name))
return; return;
// We'll handle it later if we're not playing.
if (!Playing())
return;
// If you're not in a netgame, merely update the skin, color, and name. // If you're not in a netgame, merely update the skin, color, and name.
if (!netgame) if (!netgame)
{ {
@ -1212,6 +1216,10 @@ static void SendNameAndColor2(void)
CV_StealthSet(&cv_playercolor2, cv_playercolor2.defaultvalue); CV_StealthSet(&cv_playercolor2, cv_playercolor2.defaultvalue);
} }
// We'll handle it later if we're not playing.
if (!Playing())
return;
// If you're not in a netgame, merely update the skin, color, and name. // If you're not in a netgame, merely update the skin, color, and name.
if (botingame) if (botingame)
{ {
@ -1365,8 +1373,6 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
} }
else else
SetPlayerSkinByNum(playernum, skin); SetPlayerSkinByNum(playernum, skin);
players[playernum].pflags |= PF_CONSISTANCY;
} }
void SendWeaponPref(void) void SendWeaponPref(void)
@ -1983,7 +1989,7 @@ static void Command_Pause(void)
if (cv_pause.value || server || (adminplayer == consoleplayer)) if (cv_pause.value || server || (adminplayer == consoleplayer))
{ {
if (!(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION)) if (modeattacking || !(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION))
{ {
CONS_Printf(M_GetText("You can't pause here.\n")); CONS_Printf(M_GetText("You can't pause here.\n"));
return; return;
@ -2013,6 +2019,9 @@ static void Got_Pause(UINT8 **cp, INT32 playernum)
return; return;
} }
if (modeattacking)
return;
paused = READUINT8(*cp); paused = READUINT8(*cp);
dedicatedpause = READUINT8(*cp); dedicatedpause = READUINT8(*cp);
@ -3127,15 +3136,12 @@ static void Command_Addfile(void)
} }
p = fn+strlen(fn); p = fn+strlen(fn);
while(p > fn) while(--p >= fn)
{
--p;
if (*p == '\\' || *p == '/' || *p == ':') if (*p == '\\' || *p == '/' || *p == ':')
{ {
++p; ++p;
break; break;
} }
}
WRITESTRINGN(buf_p,p,240); WRITESTRINGN(buf_p,p,240);
{ {
@ -4240,24 +4246,11 @@ static void Color_OnChange(void)
{ {
if (!P_PlayerMoving(consoleplayer)) if (!P_PlayerMoving(consoleplayer))
{ {
// Color change menu scrolling fix // Color change menu scrolling fix is no longer necessary
// Determine what direction you are scrolling
// and skip the proper colors.
if (menuactive)
{
UINT8 prevcolor = players[consoleplayer].skincolor;
if (cv_playercolor.value == 0) // no color
{
if (prevcolor == 1)
CV_StealthSetValue(&cv_playercolor, MAXSKINCOLORS-1);
else
CV_StealthSetValue(&cv_playercolor, 1);
}
}
SendNameAndColor(); SendNameAndColor();
} }
else { else
{
CV_StealthSetValue(&cv_playercolor, CV_StealthSetValue(&cv_playercolor,
players[consoleplayer].skincolor); players[consoleplayer].skincolor);
} }
@ -4272,24 +4265,11 @@ static void Color2_OnChange(void)
{ {
if (!P_PlayerMoving(secondarydisplayplayer)) if (!P_PlayerMoving(secondarydisplayplayer))
{ {
// Color change menu scrolling fix // Color change menu scrolling fix is no longer necessary
// Determine what direction you are scrolling
// and skip the proper colors.
if (menuactive)
{
UINT8 prevcolor = players[secondarydisplayplayer].skincolor;
if (cv_playercolor2.value == 0) // no color
{
if (prevcolor == 1)
CV_StealthSetValue(&cv_playercolor2, MAXSKINCOLORS-1);
else
CV_StealthSetValue(&cv_playercolor2, 1);
}
}
SendNameAndColor2(); SendNameAndColor2();
} }
else { else
{
CV_StealthSetValue(&cv_playercolor2, CV_StealthSetValue(&cv_playercolor2,
players[secondarydisplayplayer].skincolor); players[secondarydisplayplayer].skincolor);
} }

View file

@ -147,9 +147,7 @@ typedef enum
PF_TAGGED = 1<<27, // Player has been tagged and awaits the next round in hide and seek. PF_TAGGED = 1<<27, // Player has been tagged and awaits the next round in hide and seek.
PF_TAGIT = 1<<28, // The player is it! For Tag Mode PF_TAGIT = 1<<28, // The player is it! For Tag Mode
// free: 1<<29, 1<<30 // free: 1<<29, 1<<31
PF_CONSISTANCY = 1<<31 // DON'T mess with this flag or horrible things will happen.
} pflags_t; } pflags_t;
typedef enum typedef enum

View file

@ -628,7 +628,7 @@ static void readfreeslots(MYFILE *f)
// TODO: Out-of-slots warnings/errors. // TODO: Out-of-slots warnings/errors.
// TODO: Name too long (truncated) warnings. // TODO: Name too long (truncated) warnings.
if (fastcmp(type, "SFX")) if (fastcmp(type, "SFX"))
S_AddSoundFx(word, false, -1, false); S_AddSoundFx(word, false, 0, false);
else if (fastcmp(type, "SPR")) else if (fastcmp(type, "SPR"))
{ {
for (i = SPR_FIRSTFREESLOT; i <= SPR_LASTFREESLOT; i++) for (i = SPR_FIRSTFREESLOT; i <= SPR_LASTFREESLOT; i++)
@ -8112,7 +8112,7 @@ static inline int lib_freeslot(lua_State *L)
sfxenum_t sfx; sfxenum_t sfx;
strlwr(word); strlwr(word);
CONS_Printf("Sound sfx_%s allocated.\n",word); CONS_Printf("Sound sfx_%s allocated.\n",word);
sfx = S_AddSoundFx(word, false, -1, false); sfx = S_AddSoundFx(word, false, 0, false);
if (sfx != sfx_None) { if (sfx != sfx_None) {
lua_pushinteger(L, sfx); lua_pushinteger(L, sfx);
r++; r++;
@ -8189,12 +8189,12 @@ static inline int lib_freeslot(lua_State *L)
static inline int lib_action(lua_State *L) static inline int lib_action(lua_State *L)
{ {
actionf_t *action = lua_touserdata(L,lua_upvalueindex(1)); actionf_t *action = lua_touserdata(L,lua_upvalueindex(1));
mobj_t **actor = luaL_checkudata(L,1,META_MOBJ); mobj_t *actor = *((mobj_t **)luaL_checkudata(L,1,META_MOBJ));
var1 = (INT32)luaL_optinteger(L,2,0); var1 = (INT32)luaL_optinteger(L,2,0);
var2 = (INT32)luaL_optinteger(L,3,0); var2 = (INT32)luaL_optinteger(L,3,0);
if (!*actor) if (!actor)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
action->acp1(*actor); action->acp1(actor);
return 0; return 0;
} }

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 2 // more precise version number #define SUBVERSION 3 // more precise version number
#define VERSIONSTRING "v2.1.2" #define VERSIONSTRING "v2.1.3"
#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 6 #define MODVERSION 7

View file

@ -1711,18 +1711,8 @@ boolean G_Responder(event_t *ev)
// don't let busy scripts prevent pausing // don't let busy scripts prevent pausing
pausedelay = NEWTICRATE/7; pausedelay = NEWTICRATE/7;
if (cv_pause.value == 1 || server || (adminplayer == consoleplayer)) // command will handle all the checks for us
{ COM_ImmedExecute("pause");
if (!(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION))
{
CONS_Printf(M_GetText("You can't pause here.\n"));
return true;
}
COM_ImmedExecute("pause");
}
else
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
return true; return true;
} }
else else
@ -1794,15 +1784,8 @@ void G_Ticker(boolean run)
} }
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ if (playeringame[i] && players[i].playerstate == PST_REBORN)
if (playeringame[i]) G_DoReborn(i);
{
if (players[i].playerstate == PST_REBORN)
{
G_DoReborn(i);
}
}
}
} }
P_MapEnd(); P_MapEnd();
@ -1988,7 +1971,7 @@ void G_PlayerReborn(INT32 player)
exiting = players[player].exiting; exiting = players[player].exiting;
jointime = players[player].jointime; jointime = players[player].jointime;
spectator = players[player].spectator; spectator = players[player].spectator;
pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED|PF_CONSISTANCY)); pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED));
// As long as we're not in multiplayer, carry over cheatcodes from map to map // As long as we're not in multiplayer, carry over cheatcodes from map to map
if (!(netgame || multiplayer)) if (!(netgame || multiplayer))
@ -2501,6 +2484,9 @@ void G_ExitLevel(void)
if (gametype != GT_COOP) if (gametype != GT_COOP)
CONS_Printf(M_GetText("The round has ended.\n")); CONS_Printf(M_GetText("The round has ended.\n"));
// Remove CEcho text on round end.
HU_DoCEcho("");
} }
} }

View file

@ -1180,7 +1180,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
if (players[tab[i].num].spectator) if (players[tab[i].num].spectator)
continue; //ignore them. continue; //ignore them.
V_DrawString(x + 24, y, V_DrawString(x + 20, y,
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
| ((players[tab[i].num].health > 0) ? 0 : V_60TRANS) | ((players[tab[i].num].health > 0) ? 0 : V_60TRANS)
| V_ALLOWLOWERCASE, tab[i].name); | V_ALLOWLOWERCASE, tab[i].name);
@ -1293,7 +1293,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
continue; continue;
strlcpy(name, tab[i].name, 9); strlcpy(name, tab[i].name, 9);
V_DrawString(x + 24, y, V_DrawString(x + 20, y,
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
| ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT) | ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT)
| V_ALLOWLOWERCASE, name); | V_ALLOWLOWERCASE, name);
@ -1326,7 +1326,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
else else
V_DrawSmallMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap); V_DrawSmallMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap);
} }
V_DrawRightAlignedString(x+120, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); V_DrawRightAlignedThinString(x+120, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count));
} }
} }
@ -1343,16 +1343,13 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T. V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T.
V_DrawFill(1, 180, 318, 1, 0); //And a horizontal line near the bottom. V_DrawFill(1, 180, 318, 1, 0); //And a horizontal line near the bottom.
if (gametype == GT_RACE || gametype == GT_COOP)
x -= 32; //we need more room!
for (i = 0; i < scorelines; i++) for (i = 0; i < scorelines; i++)
{ {
if (players[tab[i].num].spectator) if (players[tab[i].num].spectator)
continue; //ignore them. continue; //ignore them.
strlcpy(name, tab[i].name, 9); strlcpy(name, tab[i].name, 9);
V_DrawString(x + 24, y, V_DrawString(x + 20, y,
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
| ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT) | ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT)
| V_ALLOWLOWERCASE, name); | V_ALLOWLOWERCASE, name);
@ -1400,20 +1397,21 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
} }
} }
// All data drawn with thin string for space.
if (gametype == GT_RACE) if (gametype == GT_RACE)
{ {
if (circuitmap) if (circuitmap)
{ {
if (players[tab[i].num].exiting) if (players[tab[i].num].exiting)
V_DrawRightAlignedString(x+156, y, 0, va("%i:%02i.%02i", G_TicsToMinutes(players[tab[i].num].realtime,true), G_TicsToSeconds(players[tab[i].num].realtime), G_TicsToCentiseconds(players[tab[i].num].realtime))); V_DrawRightAlignedThinString(x+156, y, 0, va("%i:%02i.%02i", G_TicsToMinutes(players[tab[i].num].realtime,true), G_TicsToSeconds(players[tab[i].num].realtime), G_TicsToCentiseconds(players[tab[i].num].realtime)));
else else
V_DrawRightAlignedString(x+156, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); V_DrawRightAlignedThinString(x+156, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count));
} }
else else
V_DrawRightAlignedString(x+156, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count))); V_DrawRightAlignedThinString(x+156, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count)));
} }
else else
V_DrawRightAlignedString(x+120, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); V_DrawRightAlignedThinString(x+120, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count));
y += 16; y += 16;
if (y > 160) if (y > 160)

View file

@ -141,7 +141,6 @@ extern void (*I_NetCloseSocket)(void);
extern boolean (*I_Ban) (INT32 node); extern boolean (*I_Ban) (INT32 node);
extern boolean (*I_Shun) (INT32 node);
extern void (*I_ClearBans)(void); extern void (*I_ClearBans)(void);
extern const char *(*I_GetNodeAddress) (INT32 node); extern const char *(*I_GetNodeAddress) (INT32 node);
extern const char *(*I_GetBanAddress) (size_t ban); extern const char *(*I_GetBanAddress) (size_t ban);

View file

@ -239,9 +239,6 @@ static size_t broadcastaddresses = 0;
static boolean nodeconnected[MAXNETNODES+1]; static boolean nodeconnected[MAXNETNODES+1];
static mysockaddr_t banned[MAXBANS]; static mysockaddr_t banned[MAXBANS];
static UINT8 bannedmask[MAXBANS]; static UINT8 bannedmask[MAXBANS];
static mysockaddr_t shunned[MAXBANS];
static UINT8 shunnedmask[MAXBANS];
static size_t numshun = 0;
#endif #endif
static size_t numbans = 0; static size_t numbans = 0;
@ -528,12 +525,6 @@ static void SOCK_Get(void)
(void *)&fromaddress, &fromlen); (void *)&fromaddress, &fromlen);
if (c != ERRSOCKET) if (c != ERRSOCKET)
{ {
// check if it's a DoS attacker and don't respond.
for (i = 0; i < numshun; i++)
if (SOCK_cmpaddr(&fromaddress, &shunned[i], shunnedmask[i]))
break;
if (i < numshun)
continue;
// find remote node number // find remote node number
for (j = 0; j <= MAXNETNODES; j++) //include LAN for (j = 0; j <= MAXNETNODES; j++) //include LAN
{ {
@ -1344,34 +1335,6 @@ static boolean SOCK_Ban(INT32 node)
#endif #endif
} }
static boolean SOCK_Shun(INT32 node)
{
if (node > MAXNETNODES)
return false;
#ifdef NONET
return false;
#else
if (numshun == MAXBANS)
return false;
M_Memcpy(&shunned[numshun], &clientaddress[node], sizeof (mysockaddr_t));
if (shunned[numshun].any.sa_family == AF_INET)
{
shunned[numshun].ip4.sin_port = 0;
shunnedmask[numshun] = 32;
}
#ifdef HAVE_IPV6
else if (banned[numshun].any.sa_family == AF_INET6)
{
shunned[numshun].ip6.sin6_port = 0;
shunnedmask[numshun] = 128;
}
#endif
numshun++;
return true;
#endif
}
static boolean SOCK_SetBanAddress(const char *address, const char *mask) static boolean SOCK_SetBanAddress(const char *address, const char *mask)
{ {
#ifdef NONET #ifdef NONET
@ -1511,7 +1474,6 @@ boolean I_InitTcpNetwork(void)
I_NetOpenSocket = SOCK_OpenSocket; I_NetOpenSocket = SOCK_OpenSocket;
I_Ban = SOCK_Ban; I_Ban = SOCK_Ban;
I_Shun = SOCK_Shun;
I_ClearBans = SOCK_ClearBans; I_ClearBans = SOCK_ClearBans;
I_GetNodeAddress = SOCK_GetNodeAddress; I_GetNodeAddress = SOCK_GetNodeAddress;
I_GetBanAddress = SOCK_GetBanAddress; I_GetBanAddress = SOCK_GetBanAddress;

View file

@ -218,7 +218,7 @@ static int lib_pNewChaseDir(lua_State *L)
static int lib_pLookForPlayers(lua_State *L) static int lib_pLookForPlayers(lua_State *L)
{ {
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
fixed_t dist = (fixed_t)luaL_checkinteger(L, 2); fixed_t dist = (fixed_t)luaL_optinteger(L, 2, 0);
boolean allaround = lua_optboolean(L, 3); boolean allaround = lua_optboolean(L, 3);
boolean tracer = lua_optboolean(L, 4); boolean tracer = lua_optboolean(L, 4);
NOHUD NOHUD
@ -341,8 +341,8 @@ static int lib_pSPMAngle(lua_State *L)
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobjtype_t type = luaL_checkinteger(L, 2); mobjtype_t type = luaL_checkinteger(L, 2);
angle_t angle = (angle_t)luaL_checkinteger(L, 3); angle_t angle = (angle_t)luaL_checkinteger(L, 3);
UINT8 allowaim = (UINT8)luaL_checkinteger(L, 4); UINT8 allowaim = (UINT8)luaL_optinteger(L, 4, 0);
UINT32 flags2 = (UINT32)luaL_checkinteger(L, 5); UINT32 flags2 = (UINT32)luaL_optinteger(L, 5, 0);
NOHUD NOHUD
if (!source) if (!source)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
@ -356,7 +356,7 @@ static int lib_pSpawnPlayerMissile(lua_State *L)
{ {
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobjtype_t type = luaL_checkinteger(L, 2); mobjtype_t type = luaL_checkinteger(L, 2);
UINT32 flags2 = (UINT32)luaL_checkinteger(L, 3); UINT32 flags2 = (UINT32)luaL_optinteger(L, 3, 0);
NOHUD NOHUD
if (!source) if (!source)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");

View file

@ -26,23 +26,32 @@
boolean LUA_CallAction(const char *action, mobj_t *actor); boolean LUA_CallAction(const char *action, mobj_t *actor);
state_t *astate; state_t *astate;
enum sfxinfo_e { enum sfxinfo_read {
sfxinfo_name = 0, sfxinfor_name = 0,
sfxinfo_singularity, sfxinfor_singular,
sfxinfo_priority, sfxinfor_priority,
sfxinfo_flags, // "pitch" sfxinfor_flags, // "pitch"
sfxinfo_volume, sfxinfor_skinsound
sfxinfo_skinsound
}; };
const char *const sfxinfo_opt[] = { const char *const sfxinfo_ropt[] = {
"name", "name",
"singularity", "singular",
"priority", "priority",
"flags", "flags",
"volume",
"skinsound", "skinsound",
NULL}; NULL};
enum sfxinfo_write {
sfxinfow_singular = 0,
sfxinfow_priority,
sfxinfow_flags // "pitch"
};
const char *const sfxinfo_wopt[] = {
"singular",
"priority",
"flags",
NULL};
// //
// Sprite Names // Sprite Names
// //
@ -718,6 +727,7 @@ static int lib_getSfxInfo(lua_State *L)
static int lib_setSfxInfo(lua_State *L) static int lib_setSfxInfo(lua_State *L)
{ {
sfxinfo_t *info; sfxinfo_t *info;
lua_remove(L, 1); lua_remove(L, 1);
info = &S_sfx[luaL_checkinteger(L, 1)]; // get the mobjinfo to assign to. info = &S_sfx[luaL_checkinteger(L, 1)]; // get the mobjinfo to assign to.
luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table. luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table.
@ -729,22 +739,27 @@ static int lib_setSfxInfo(lua_State *L)
lua_pushnil(L); lua_pushnil(L);
while (lua_next(L, 1)) { while (lua_next(L, 1)) {
lua_Integer i = 0; enum sfxinfo_write i;
const char *str = NULL;
if (lua_isnumber(L, 2)) if (lua_isnumber(L, 2))
i = lua_tointeger(L, 2); i = lua_tointeger(L, 2);
else else
str = luaL_checkstring(L, 2); i = luaL_checkoption(L, 2, NULL, sfxinfo_wopt);
if (i == 1 || (str && fastcmp(str,"singularity"))) switch(i)
{
case sfxinfow_singular:
info->singularity = luaL_checkboolean(L, 3); info->singularity = luaL_checkboolean(L, 3);
else if (i == 2 || (str && fastcmp(str,"priority"))) break;
case sfxinfow_priority:
info->priority = (INT32)luaL_checkinteger(L, 3); info->priority = (INT32)luaL_checkinteger(L, 3);
else if (i == 3 || (str && fastcmp(str,"pitch")) || (str && fastcmp(str,"flags"))) break;
case sfxinfow_flags:
info->pitch = (INT32)luaL_checkinteger(L, 3); info->pitch = (INT32)luaL_checkinteger(L, 3);
else if (i == 4 || (str && fastcmp(str,"volume"))) break;
info->volume = (INT32)luaL_checkinteger(L, 3); default:
break;
}
lua_pop(L, 1); lua_pop(L, 1);
} }
@ -761,39 +776,38 @@ static int lib_sfxlen(lua_State *L)
static int sfxinfo_get(lua_State *L) static int sfxinfo_get(lua_State *L)
{ {
sfxinfo_t *sfx = *((sfxinfo_t **)luaL_checkudata(L, 1, META_SFXINFO)); sfxinfo_t *sfx = *((sfxinfo_t **)luaL_checkudata(L, 1, META_SFXINFO));
enum sfxinfo_e field = luaL_checkoption(L, 2, NULL, sfxinfo_opt); enum sfxinfo_read field = luaL_checkoption(L, 2, NULL, sfxinfo_ropt);
I_Assert(sfx != NULL); I_Assert(sfx != NULL);
switch (field) switch (field)
{ {
case sfxinfo_name: case sfxinfor_name:
lua_pushstring(L, sfx->name); lua_pushstring(L, sfx->name);
return 1; return 1;
case sfxinfo_singularity: case sfxinfor_singular:
lua_pushboolean(L, sfx->singularity); lua_pushboolean(L, sfx->singularity);
return 1; return 1;
case sfxinfo_priority: case sfxinfor_priority:
lua_pushinteger(L, sfx->priority); lua_pushinteger(L, sfx->priority);
return 1; return 1;
case sfxinfo_flags: case sfxinfor_flags:
lua_pushinteger(L, sfx->pitch); lua_pushinteger(L, sfx->pitch);
return 1; return 1;
case sfxinfo_volume: case sfxinfor_skinsound:
lua_pushinteger(L, sfx->volume);
return 1;
case sfxinfo_skinsound:
lua_pushinteger(L, sfx->skinsound); lua_pushinteger(L, sfx->skinsound);
return 1; return 1;
default:
return luaL_error(L, "impossible error");
} }
return luaL_error(L, "impossible error"); return 0;
} }
// sfxinfo_t *, field, value // sfxinfo_t *, field, value
static int sfxinfo_set(lua_State *L) static int sfxinfo_set(lua_State *L)
{ {
sfxinfo_t *sfx = *((sfxinfo_t **)luaL_checkudata(L, 1, META_SFXINFO)); sfxinfo_t *sfx = *((sfxinfo_t **)luaL_checkudata(L, 1, META_SFXINFO));
enum sfxinfo_e field = luaL_checkoption(L, 2, NULL, sfxinfo_opt); enum sfxinfo_write field = luaL_checkoption(L, 2, NULL, sfxinfo_wopt);
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter S_sfx in HUD rendering code!"); return luaL_error(L, "Do not alter S_sfx in HUD rendering code!");
@ -806,22 +820,18 @@ static int sfxinfo_set(lua_State *L)
switch (field) switch (field)
{ {
case sfxinfo_singularity: case sfxinfow_singular:
sfx->singularity = luaL_checkboolean(L, 1); sfx->singularity = luaL_checkboolean(L, 1);
break; break;
case sfxinfo_priority: case sfxinfow_priority:
sfx->priority = luaL_checkinteger(L, 1); sfx->priority = luaL_checkinteger(L, 1);
break; break;
case sfxinfo_flags: case sfxinfow_flags:
sfx->pitch = luaL_checkinteger(L, 1); sfx->pitch = luaL_checkinteger(L, 1);
break; break;
case sfxinfo_volume:
sfx->volume = luaL_checkinteger(L, 1);
break;
default: default:
return luaL_error(L, "Can't set 'S_sfx[%u].%s' here.", (UINT32)(sfx-S_sfx), sfxinfo_opt[field]); return luaL_error(L, "impossible error");
} }
return 0; return 0;
} }

View file

@ -131,7 +131,7 @@ static int player_get(lua_State *L)
else if (fastcmp(field,"powers")) else if (fastcmp(field,"powers"))
LUA_PushUserdata(L, plr->powers, META_POWERS); LUA_PushUserdata(L, plr->powers, META_POWERS);
else if (fastcmp(field,"pflags")) else if (fastcmp(field,"pflags"))
lua_pushinteger(L, (plr->pflags & ~PF_CONSISTANCY)); lua_pushinteger(L, plr->pflags);
else if (fastcmp(field,"panim")) else if (fastcmp(field,"panim"))
lua_pushinteger(L, plr->panim); lua_pushinteger(L, plr->panim);
else if (fastcmp(field,"flashcount")) else if (fastcmp(field,"flashcount"))
@ -378,7 +378,7 @@ static int player_set(lua_State *L)
else if (fastcmp(field,"powers")) else if (fastcmp(field,"powers"))
return NOSET; return NOSET;
else if (fastcmp(field,"pflags")) else if (fastcmp(field,"pflags"))
plr->pflags = (luaL_checkinteger(L, 3) & ~PF_CONSISTANCY)|(plr->pflags & PF_CONSISTANCY); plr->pflags = luaL_checkinteger(L, 3);
else if (fastcmp(field,"panim")) else if (fastcmp(field,"panim"))
plr->panim = luaL_checkinteger(L, 3); plr->panim = luaL_checkinteger(L, 3);
else if (fastcmp(field,"flashcount")) else if (fastcmp(field,"flashcount"))

View file

@ -1778,10 +1778,20 @@ UINT8 M_CountBits(UINT32 num, UINT8 size)
for (i = 0; i < size; ++i) for (i = 0; i < size; ++i)
if (num & (1 << i)) if (num & (1 << i))
++sum; ++sum;
return sum; return sum;
} }
/** Get the most significant bit in a number.
* (integer log2)
*/
UINT8 M_HighestBit(UINT32 num)
{
UINT8 i = 0;
while (num >>= 1) ++i;
return i;
}
const char *GetRevisionString(void) const char *GetRevisionString(void)
{ {
INT32 vinfo; INT32 vinfo;

View file

@ -94,7 +94,8 @@ void strcatbf(char *s1, const char *s2, const char *s3);
void M_SetupMemcpy(void); void M_SetupMemcpy(void);
// counting bits, for weapon ammo code, usually // counting bits, for weapon ammo code, usually
UINT8 M_CountBits(UINT32 num, UINT8 size); FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size);
FUNCMATH UINT8 M_HighestBit(UINT32 num);
// Flags for AA trees. // Flags for AA trees.
#define AATREE_ZUSER 1 // Treat values as z_zone-allocated blocks and set their user fields #define AATREE_ZUSER 1 // Treat values as z_zone-allocated blocks and set their user fields

View file

@ -1728,7 +1728,7 @@ void A_LobShot(mobj_t *actor)
if (LUA_CallAction("A_LobShot", actor)) if (LUA_CallAction("A_LobShot", actor))
return; return;
#endif #endif
if (!actor->target || P_MobjWasRemoved(actor->target)) if (!actor->target)
return; return;
A_FaceTarget(actor); A_FaceTarget(actor);
@ -1829,7 +1829,7 @@ void A_FireShot(mobj_t *actor)
if (LUA_CallAction("A_FireShot", actor)) if (LUA_CallAction("A_FireShot", actor))
return; return;
#endif #endif
if (!actor->target || P_MobjWasRemoved(actor->target)) if (!actor->target)
return; return;
A_FaceTarget(actor); A_FaceTarget(actor);
@ -1868,7 +1868,7 @@ void A_SuperFireShot(mobj_t *actor)
if (LUA_CallAction("A_SuperFireShot", actor)) if (LUA_CallAction("A_SuperFireShot", actor))
return; return;
#endif #endif
if (!actor->target || P_MobjWasRemoved(actor->target)) if (!actor->target)
return; return;
A_FaceTarget(actor); A_FaceTarget(actor);
@ -1915,7 +1915,7 @@ void A_BossFireShot(mobj_t *actor)
if (LUA_CallAction("A_BossFireShot", actor)) if (LUA_CallAction("A_BossFireShot", actor))
return; return;
#endif #endif
if (!actor->target || P_MobjWasRemoved(actor->target)) if (!actor->target)
return; return;
A_FaceTarget(actor); A_FaceTarget(actor);
@ -1998,7 +1998,7 @@ void A_Boss7FireMissiles(mobj_t *actor)
return; return;
#endif #endif
if (!actor->target || P_MobjWasRemoved(actor->target)) if (!actor->target)
{ {
P_SetMobjState(actor, actor->info->spawnstate); P_SetMobjState(actor, actor->info->spawnstate);
return; return;
@ -2056,7 +2056,7 @@ void A_Boss1Laser(mobj_t *actor)
if (LUA_CallAction("A_Boss1Laser", actor)) if (LUA_CallAction("A_Boss1Laser", actor))
return; return;
#endif #endif
if (!actor->target || P_MobjWasRemoved(actor->target)) if (!actor->target)
return; return;
switch (locvar2) switch (locvar2)
@ -2279,7 +2279,7 @@ void A_SkullAttack(mobj_t *actor)
if (LUA_CallAction("A_SkullAttack", actor)) if (LUA_CallAction("A_SkullAttack", actor))
return; return;
#endif #endif
if (!actor->target || P_MobjWasRemoved(actor->target)) if (!actor->target)
return; return;
speed = FixedMul(SKULLSPEED, actor->scale); speed = FixedMul(SKULLSPEED, actor->scale);
@ -2335,7 +2335,7 @@ void A_BossZoom(mobj_t *actor)
if (LUA_CallAction("A_BossZoom", actor)) if (LUA_CallAction("A_BossZoom", actor))
return; return;
#endif #endif
if (!actor->target || P_MobjWasRemoved(actor->target)) if (!actor->target)
return; return;
dest = actor->target; dest = actor->target;
@ -2501,6 +2501,9 @@ void A_1upThinker(mobj_t *actor)
if (!players[i].mo) if (!players[i].mo)
continue; continue;
if ((netgame || multiplayer) && players[i].playerstate != PST_LIVE)
continue;
temp = P_AproxDistance(players[i].mo->x-actor->x, players[i].mo->y-actor->y); temp = P_AproxDistance(players[i].mo->x-actor->x, players[i].mo->y-actor->y);
if (temp < dist) if (temp < dist)
@ -4815,12 +4818,6 @@ void A_UnidusBall(mobj_t *actor)
actor->angle += ANGLE_11hh; actor->angle += ANGLE_11hh;
if (!actor->target)
{
CONS_Debug(DBG_GAMELOGIC, "A_UnidusBall: Spikeball has no target\n");
return;
}
if (actor->movecount) if (actor->movecount)
{ {
if (P_AproxDistance(actor->momx, actor->momy) < FixedMul(actor->info->damage/2, actor->scale)) if (P_AproxDistance(actor->momx, actor->momy) < FixedMul(actor->info->damage/2, actor->scale))
@ -4828,15 +4825,16 @@ void A_UnidusBall(mobj_t *actor)
return; return;
} }
if (!actor->target->health) if (!actor->target || !actor->target->health)
{ {
CONS_Debug(DBG_GAMELOGIC, "A_UnidusBall: Removing unthrown spikeball from nonexistant Unidus\n");
P_RemoveMobj(actor); P_RemoveMobj(actor);
return; return;
} }
P_UnsetThingPosition(actor); P_UnsetThingPosition(actor);
{ {
const angle_t angle = actor->movedir + FixedAngle(actor->info->speed*leveltime); const angle_t angle = actor->movedir + FixedAngle(actor->info->speed*(leveltime%360));
const UINT16 fa = angle>>ANGLETOFINESHIFT; const UINT16 fa = angle>>ANGLETOFINESHIFT;
actor->x = actor->target->x + FixedMul(FINECOSINE(fa),actor->threshold); actor->x = actor->target->x + FixedMul(FINECOSINE(fa),actor->threshold);
@ -5030,27 +5028,9 @@ void A_MaceRotate(mobj_t *actor)
return; return;
#endif #endif
if (!actor->target) // This should NEVER happen.
{
CONS_Debug(DBG_GAMELOGIC, "Mace object (type %d) has no target!\n", actor->type);
P_RemoveMobj(actor);
return;
}
// Target was removed. // Target was removed.
if (P_MobjWasRemoved(actor->target)) if (!actor->target)
{ {
UINT8 i;
if (actor->flags & MF_AMBUSH) // outermost chain only (no point checking the others for players)
{
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].pflags & (PF_MACESPIN|PF_ITEMHANG) // is player in-game and attached to something?
&& players[i].mo && players[i].mo->tracer && players[i].mo->tracer == actor) // is player attached to YOU even?
{
players[i].pflags &= ~(PF_MACESPIN|PF_ITEMHANG);
P_SetTarget(&players[i].mo->tracer, NULL); // you're not going to exist in a sec anyway
} // don't stop yet, since apparently more than one player is able to grab onto these chains at a time
}
P_RemoveMobj(actor); P_RemoveMobj(actor);
return; return;
} }
@ -6478,7 +6458,7 @@ void A_Boss2PogoTarget(mobj_t *actor)
return; return;
#endif #endif
if (!actor->target || !(actor->target->flags & MF_SHOOTABLE) || actor->target->player->powers[pw_flashing] if (!actor->target || !(actor->target->flags & MF_SHOOTABLE) || (actor->target->player && actor->target->player->powers[pw_flashing])
|| P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) >= FixedMul(512*FRACUNIT, actor->scale)) || P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) >= FixedMul(512*FRACUNIT, actor->scale))
{ {
// look for a new target // look for a new target
@ -10064,7 +10044,7 @@ void A_BrakFireShot(mobj_t *actor)
if (LUA_CallAction("A_BrakFireShot", actor)) if (LUA_CallAction("A_BrakFireShot", actor))
return; return;
#endif #endif
if (!actor->target || P_MobjWasRemoved(actor->target)) if (!actor->target)
return; return;
A_FaceTarget(actor); A_FaceTarget(actor);

View file

@ -1518,6 +1518,8 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
str = M_GetText("%s%s's armageddon blast %s %s.\n"); str = M_GetText("%s%s's armageddon blast %s %s.\n");
else if (inflictor->player->powers[pw_invulnerability]) 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 if (inflictor->player->powers[pw_super])
str = M_GetText("%s%s's super aura %s %s.\n");
else else
str = M_GetText("%s%s's tagging hand %s %s.\n"); str = M_GetText("%s%s's tagging hand %s %s.\n");
break; break;
@ -1579,6 +1581,10 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
break; break;
} }
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: case MT_SPIKE:
str = M_GetText("%s was %s by spikes.\n"); str = M_GetText("%s was %s by spikes.\n");
break; break;

View file

@ -58,7 +58,7 @@ void P_RunCachedActions(void)
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
astate = &states[ac->statenum]; astate = &states[ac->statenum];
#endif #endif
if (ac->mobj) // just in case... if (ac->mobj && !P_MobjWasRemoved(ac->mobj)) // just in case...
states[ac->statenum].action.acp1(ac->mobj); states[ac->statenum].action.acp1(ac->mobj);
next = ac->next; next = ac->next;
Z_Free(ac); Z_Free(ac);
@ -288,6 +288,11 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
astate = st; astate = st;
#endif #endif
st->action.acp1(mobj); st->action.acp1(mobj);
// woah. a player was removed by an action.
// this sounds like a VERY BAD THING, but there's nothing we can do now...
if (P_MobjWasRemoved(mobj))
return false;
} }
seenstate[state] = 1 + st->nextstate; seenstate[state] = 1 + st->nextstate;
@ -5237,19 +5242,27 @@ INT32 numshields = 0;
void P_RunShields(void) void P_RunShields(void)
{ {
INT32 i; INT32 i;
mobj_t *mo; mobj_t *mo, *next;
fixed_t destx,desty,zoffs; fixed_t destx,desty,zoffs;
// run shields
for (i = 0; i < numshields; i++) for (i = 0; i < numshields; i++)
{ {
P_ShieldLook(shields[i], shields[i]->info->speed); P_ShieldLook(shields[i], shields[i]->info->speed);
P_SetTarget(&shields[i], NULL); P_SetTarget(&shields[i], NULL);
} }
numshields = 0; numshields = 0;
for (mo = overlaycap; mo; mo = mo->hnext) // run overlays
next = NULL;
for (mo = overlaycap; mo; mo = next)
{ {
I_Assert(!P_MobjWasRemoved(mo));
// grab next in chain, then unset the chain target
next = mo->hnext;
P_SetTarget(&mo->hnext, NULL);
if (!mo->target) if (!mo->target)
continue; continue;
if (!splitscreen /*&& rendermode != render_soft*/) if (!splitscreen /*&& rendermode != render_soft*/)
@ -5292,8 +5305,7 @@ void P_RunShields(void)
P_SetThingPosition(mo); P_SetThingPosition(mo);
P_CheckPosition(mo, mo->x, mo->y); P_CheckPosition(mo, mo->x, mo->y);
} }
P_SetTarget(&overlaycap, NULL);
overlaycap = NULL;
} }
static boolean P_AddShield(mobj_t *thing) static boolean P_AddShield(mobj_t *thing)
@ -5330,17 +5342,38 @@ static boolean P_AddShield(mobj_t *thing)
return true; return true;
} }
// Called only when MT_OVERLAY thinks.
static void P_AddOverlay(mobj_t *thing) static void P_AddOverlay(mobj_t *thing)
{ {
mobj_t *mo; I_Assert(thing != NULL);
if (!overlaycap)
overlaycap = thing; if (overlaycap == NULL)
P_SetTarget(&overlaycap, thing);
else { else {
mobj_t *mo;
for (mo = overlaycap; mo && mo->hnext; mo = mo->hnext) for (mo = overlaycap; mo && mo->hnext; mo = mo->hnext)
; ;
mo->hnext = thing;
I_Assert(mo != NULL);
I_Assert(mo->hnext == NULL);
P_SetTarget(&mo->hnext, thing);
} }
thing->hnext = NULL; P_SetTarget(&thing->hnext, NULL);
}
// Called only when MT_OVERLAY (or anything else in the overlaycap list) is removed.
// Keeps the hnext list from corrupting.
static void P_RemoveOverlay(mobj_t *thing)
{
mobj_t *mo;
for (mo = overlaycap; mo; mo = mo->hnext)
if (mo->hnext == thing)
{
P_SetTarget(&mo->hnext, thing->hnext);
P_SetTarget(&thing->hnext, NULL);
return;
}
} }
void A_BossDeath(mobj_t *mo); void A_BossDeath(mobj_t *mo);
@ -5528,7 +5561,7 @@ void P_MobjThinker(mobj_t *mobj)
// Don't touch my fuse! // Don't touch my fuse!
return; return;
case MT_OVERLAY: case MT_OVERLAY:
if (!mobj->target || P_MobjWasRemoved(mobj->target)) if (!mobj->target)
{ {
P_RemoveMobj(mobj); P_RemoveMobj(mobj);
return; return;
@ -5577,7 +5610,7 @@ void P_MobjThinker(mobj_t *mobj)
} }
break; break;
case MT_DROWNNUMBERS: case MT_DROWNNUMBERS:
if (!mobj->target || P_MobjWasRemoved(mobj->target)) if (!mobj->target)
{ {
P_RemoveMobj(mobj); P_RemoveMobj(mobj);
return; return;
@ -5972,7 +6005,6 @@ void P_MobjThinker(mobj_t *mobj)
break; break;
case MT_EGGMOBILE2_POGO: case MT_EGGMOBILE2_POGO:
if (!mobj->target if (!mobj->target
|| P_MobjWasRemoved(mobj->target)
|| !mobj->target->health || !mobj->target->health
|| mobj->target->state == &states[mobj->target->info->spawnstate] || mobj->target->state == &states[mobj->target->info->spawnstate]
|| mobj->target->state == &states[mobj->target->info->raisestate]) || mobj->target->state == &states[mobj->target->info->raisestate])
@ -6010,7 +6042,6 @@ void P_MobjThinker(mobj_t *mobj)
fixed_t jetx, jety; fixed_t jetx, jety;
if (!mobj->target // if you have no target if (!mobj->target // if you have no target
|| P_MobjWasRemoved(mobj->target) // or your target has been removed
|| (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now || (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now
{ // then remove yourself as well! { // then remove yourself as well!
P_RemoveMobj(mobj); P_RemoveMobj(mobj);
@ -6090,7 +6121,6 @@ void P_MobjThinker(mobj_t *mobj)
fixed_t jetx, jety; fixed_t jetx, jety;
if (!mobj->target // if you have no target if (!mobj->target // if you have no target
|| P_MobjWasRemoved(mobj->target) // or your target has been removed
|| (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now || (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now
{ // then remove yourself as well! { // then remove yourself as well!
P_RemoveMobj(mobj); P_RemoveMobj(mobj);
@ -6121,7 +6151,6 @@ void P_MobjThinker(mobj_t *mobj)
case MT_JETFLAME: case MT_JETFLAME:
{ {
if (!mobj->target // if you have no target if (!mobj->target // if you have no target
|| P_MobjWasRemoved(mobj->target) // or your target has been removed
|| (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now || (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now
{ // then remove yourself as well! { // then remove yourself as well!
P_RemoveMobj(mobj); P_RemoveMobj(mobj);
@ -6151,7 +6180,7 @@ void P_MobjThinker(mobj_t *mobj)
mobj->z = mobj->floorz + mobj->height + (mobj->spawnpoint->options >> ZSHIFT) * FRACUNIT; mobj->z = mobj->floorz + mobj->height + (mobj->spawnpoint->options >> ZSHIFT) * FRACUNIT;
mobj->angle = 0; mobj->angle = 0;
if (!mobj->target || P_MobjWasRemoved(mobj->target)) if (!mobj->target)
{ {
mobj_t *goalpost = P_SpawnMobj(mobj->x, mobj->y, mobj->z + FRACUNIT, MT_NIGHTSGOAL); mobj_t *goalpost = P_SpawnMobj(mobj->x, mobj->y, mobj->z + FRACUNIT, MT_NIGHTSGOAL);
CONS_Debug(DBG_NIGHTSBASIC, "Adding goal post\n"); CONS_Debug(DBG_NIGHTSBASIC, "Adding goal post\n");
@ -7325,6 +7354,10 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
astate = st; astate = st;
#endif #endif
st->action.acp1(mobj); st->action.acp1(mobj);
// DANGER! This is the ONLY way for P_SpawnMobj to return NULL!
// Avoid using MF_RUNSPAWNFUNC on mobjs whose spawn state expects target or tracer to already be set!
if (P_MobjWasRemoved(mobj))
return NULL;
} }
} }
@ -7434,6 +7467,9 @@ void P_RemoveMobj(mobj_t *mobj)
iquetail = (iquetail+1)&(ITEMQUESIZE-1); iquetail = (iquetail+1)&(ITEMQUESIZE-1);
} }
if (mobj->type == MT_OVERLAY)
P_RemoveOverlay(mobj);
mobj->health = 0; // Just because mobj->health = 0; // Just because
// unlink from sector and block lists // unlink from sector and block lists
@ -7862,9 +7898,19 @@ void P_SpawnPlayer(INT32 playernum)
p->spectator = false; p->spectator = false;
} }
// Fix stupid non spectator spectators. if (G_GametypeHasTeams())
if (G_GametypeHasTeams() && !p->spectator && !p->ctfteam) {
p->spectator = true; // Fix stupid non spectator spectators.
if (!p->spectator && !p->ctfteam)
p->spectator = true;
// Fix team colors.
// This code isn't being done right somewhere else. Oh well.
if (p->ctfteam == 1)
p->skincolor = skincolor_redteam;
else if (p->ctfteam == 2)
p->skincolor = skincolor_blueteam;
}
mobj = P_SpawnMobj(0, 0, 0, MT_PLAYER); mobj = P_SpawnMobj(0, 0, 0, MT_PLAYER);
(mobj->player = p)->mo = mobj; (mobj->player = p)->mo = mobj;

View file

@ -1598,7 +1598,7 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller)
if (!playeringame[i] || players[i].spectator) if (!playeringame[i] || players[i].spectator)
continue; continue;
if (!players[i].mo) if (!players[i].mo || players[i].mo->health < 1)
continue; continue;
rings += players[i].mo->health-1; rings += players[i].mo->health-1;
@ -2907,15 +2907,28 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo)
while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
{ {
boolean tryagain;
sec = sectors + secnum; sec = sectors + secnum;
for (thing = sec->thinglist; thing; thing = thing->snext) do {
if (thing->type == type) tryagain = false;
{ for (thing = sec->thinglist; thing; thing = thing->snext)
if (state != NUMSTATES) if (thing->type == type)
P_SetMobjState(thing, state); {
else if (state != NUMSTATES)
P_SetMobjState(thing, thing->state->nextstate); {
} if (!P_SetMobjState(thing, state)) // set state to specific state
{ // mobj was removed
tryagain = true; // snext is corrupt, we'll have to start over.
break;
}
}
else if (!P_SetMobjState(thing, thing->state->nextstate)) // set state to nextstate
{ // mobj was removed
tryagain = true; // snext is corrupt, we'll have to start over.
break;
}
}
} while (tryagain);
} }
break; break;
} }

View file

@ -261,6 +261,9 @@ boolean P_PlayerMoving(INT32 pnum)
{ {
player_t *p = &players[pnum]; player_t *p = &players[pnum];
if (!Playing())
return false;
if (p->jointime < 5*TICRATE || p->playerstate == PST_DEAD || p->playerstate == PST_REBORN || p->spectator) if (p->jointime < 5*TICRATE || p->playerstate == PST_DEAD || p->playerstate == PST_REBORN || p->spectator)
return false; return false;
@ -9134,7 +9137,7 @@ void P_PlayerAfterThink(player_t *player)
player->pflags &= ~PF_CARRIED; player->pflags &= ~PF_CARRIED;
} }
if (player->mo->tracer->health <= 0 || (player->mo->tracer->player && player->mo->tracer->player->powers[pw_flashing])) if (player->mo->tracer->health <= 0)
player->pflags &= ~PF_CARRIED; player->pflags &= ~PF_CARRIED;
else else
{ {

View file

@ -1231,6 +1231,15 @@ static void R_ProjectSprite(mobj_t *thing)
return; return;
} }
// quick check for possible overflows
// if either of these triggers then there's a possibility that drawing is unsafe
if (M_HighestBit(abs(gzt - viewz)) + M_HighestBit(abs(yscale)) > 47 // 31 bits + 16 from the division by FRACUNIT
|| M_HighestBit(abs(gz - viewz)) + M_HighestBit(abs(yscale)) > 47)
{
CONS_Debug(DBG_RENDER, "Suspected overflow in ProjectSprite (sprite %s), ignoring\n", sprnames[thing->sprite]);
return;
}
// store information in a vissprite // store information in a vissprite
vis = R_NewVisSprite(); vis = R_NewVisSprite();
vis->heightsec = heightsec; //SoM: 3/17/2000 vis->heightsec = heightsec; //SoM: 3/17/2000
@ -1437,6 +1446,15 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
} }
} }
// quick check for possible overflows
// if either of these triggers then there's a possibility that drawing is unsafe
if (M_HighestBit(abs(gzt - viewz)) + M_HighestBit(abs(yscale)) > 47) // 31 bits + 16 from the division by FRACUNIT
{
CONS_Debug(DBG_RENDER, "Suspected overflow in ProjectPrecipitationSprite (sprite %s), ignoring\n", sprnames[thing->sprite]);
return;
}
// store information in a vissprite // store information in a vissprite
vis = R_NewVisSprite(); vis = R_NewVisSprite();
vis->scale = yscale; //<<detailshift; vis->scale = yscale; //<<detailshift;
@ -2690,7 +2708,7 @@ void R_AddSkins(UINT16 wadnum)
stoken + 2)) stoken + 2))
{ {
skin->soundsid[S_sfx[i].skinsound] = skin->soundsid[S_sfx[i].skinsound] =
S_AddSoundFx(value+2,S_sfx[i].singularity,S_sfx[i].pitch, true); S_AddSoundFx(value+2, S_sfx[i].singularity, S_sfx[i].pitch, true);
found = true; found = true;
} }
} }

View file

@ -1447,7 +1447,7 @@ void S_StartSoundName(void *mo, const char *soundname)
return; return;
} }
soundnum = S_AddSoundFx(soundname, false, -1, false); soundnum = S_AddSoundFx(soundname, false, 0, false);
newsounds[i] = soundnum; newsounds[i] = soundnum;
} }

View file

@ -1359,7 +1359,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3k51", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k51", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"s3k52", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k52", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"s3k53", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k53", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"s3k54", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k54", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, // MetalSonic shot fire
{"s3k55", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k55", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"s3k56", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k56", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
{"s3k57", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k57", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
@ -1570,8 +1570,7 @@ void S_InitRuntimeSounds (void)
// Add a new sound fx into a free sfx slot. // Add a new sound fx into a free sfx slot.
// //
sfxenum_t S_AddSoundFx(const char *name, INT32 singularity, INT32 pitch, sfxenum_t S_AddSoundFx(const char *name, boolean singular, INT32 flags, boolean skinsound)
boolean skinsound)
{ {
sfxenum_t i, slot; sfxenum_t i, slot;
@ -1585,9 +1584,9 @@ sfxenum_t S_AddSoundFx(const char *name, INT32 singularity, INT32 pitch,
if (!S_sfx[i].priority) if (!S_sfx[i].priority)
{ {
strncpy(freeslotnames[i-sfx_freeslot0], name, 6); strncpy(freeslotnames[i-sfx_freeslot0], name, 6);
S_sfx[i].singularity = singularity; S_sfx[i].singularity = singular;
S_sfx[i].priority = 60; S_sfx[i].priority = 60;
S_sfx[i].pitch = pitch; S_sfx[i].pitch = flags;
S_sfx[i].volume = -1; S_sfx[i].volume = -1;
S_sfx[i].lumpnum = LUMPERROR; S_sfx[i].lumpnum = LUMPERROR;
S_sfx[i].skinsound = -1; S_sfx[i].skinsound = -1;

View file

@ -57,7 +57,7 @@ struct sfxinfo_struct
const char *name; const char *name;
// Sfx singularity (only one at a time) // Sfx singularity (only one at a time)
INT32 singularity; boolean singularity;
// Sfx priority // Sfx priority
INT32 priority; INT32 priority;
@ -1631,7 +1631,7 @@ typedef enum
void S_InitRuntimeSounds(void); void S_InitRuntimeSounds(void);
sfxenum_t S_AddSoundFx(const char *name, INT32 singularity, INT32 pitch, boolean skinsound); sfxenum_t S_AddSoundFx(const char *name, boolean singular, INT32 flags, boolean skinsound);
void S_RemoveSoundFx(sfxenum_t id); void S_RemoveSoundFx(sfxenum_t id);
#endif #endif

View file

@ -98,6 +98,11 @@ angle_t FixedAngleC(fixed_t fa, fixed_t factor)
if (fa == 0) if (fa == 0)
return 0; return 0;
// -2,147,483,648 has no absolute value in a 32 bit signed integer
// so this code _would_ infinite loop if passed it
if (fa == INT32_MIN)
return 0;
if (factor == 0) if (factor == 0)
return FixedAngle(fa); return FixedAngle(fa);
else if (factor > 0) else if (factor > 0)
@ -132,6 +137,11 @@ angle_t FixedAngle(fixed_t fa)
if (fa == 0) if (fa == 0)
return 0; return 0;
// -2,147,483,648 has no absolute value in a 32 bit signed integer
// so this code _would_ infinite loop if passed it
if (fa == INT32_MIN)
return 0;
fa = abs(fa); fa = abs(fa);
while (fa) while (fa)