From 2fed5d1270afdfc8cacedb7181e1cef95453aac2 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Tue, 18 Mar 2014 13:56:54 -0400 Subject: [PATCH] SRB2 2.1.3 release --- src/d_clisrv.c | 30 ++++++---------- src/d_main.c | 9 ++--- src/d_net.c | 3 -- src/d_netcmd.c | 58 ++++++++++-------------------- src/d_player.h | 4 +-- src/dehacked.c | 10 +++--- src/doomdef.h | 6 ++-- src/g_game.c | 30 +++++----------- src/hu_stuff.c | 20 +++++------ src/i_net.h | 1 - src/i_tcp.c | 38 -------------------- src/lua_baselib.c | 8 ++--- src/lua_infolib.c | 84 ++++++++++++++++++++++++------------------- src/lua_playerlib.c | 4 +-- src/m_misc.c | 12 ++++++- src/m_misc.h | 3 +- src/p_enemy.c | 54 +++++++++------------------- src/p_inter.c | 6 ++++ src/p_mobj.c | 88 ++++++++++++++++++++++++++++++++++----------- src/p_spec.c | 31 +++++++++++----- src/p_user.c | 5 ++- src/r_things.c | 20 ++++++++++- src/s_sound.c | 2 +- src/sounds.c | 9 +++-- src/sounds.h | 4 +-- src/tables.c | 10 ++++++ 26 files changed, 277 insertions(+), 272 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 9513d23bf..f4b262bac 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3044,8 +3044,6 @@ FILESTAMP case PT_SERVERREFUSE: // negative response of client join request if (server && serverrunning) { // but wait I thought I'm the server? - if (I_Shun) - I_Shun(node); // No more garbage from you! Net_CloseConnection(node); break; } @@ -3070,8 +3068,6 @@ FILESTAMP if (server && serverrunning && node != servernode) { // but wait I thought I'm the server? - if (I_Shun) - I_Shun(node); // No more garbage from you! Net_CloseConnection(node); break; } @@ -3122,8 +3118,6 @@ FILESTAMP case PT_FILEFRAGMENT: if (server) { // but wait I thought I'm the server? - if (I_Shun) - I_Shun(node); // No more garbage from you! Net_CloseConnection(node); break; } @@ -3147,8 +3141,6 @@ FILESTAMP break; default: 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); break; // ignore it } // switch @@ -3225,11 +3217,13 @@ FILESTAMP // 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. if (realstart <= gametic && realstart > gametic - BACKUPTICS+1 - && players[netconsole].pflags & PF_CONSISTANCY - && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy) - && gamestate == GS_LEVEL) + && gamestate == GS_LEVEL && playeringame[netconsole] + && players[netconsole].playerstate == PST_LIVE + && !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]) { @@ -3266,7 +3260,6 @@ FILESTAMP DEBFILE(va("player %d kicked (consistency failure) [%u] %d!=%d\n", netconsole, realstart, consistancy[realstart%BACKUPTICS], SHORT(netbuffer->u.clientpak.consistancy))); - players[netconsole].pflags &= ~PF_CONSISTANCY; consfailstatus[netconsole] = 0; consfailcount[netconsole] = 0; break; @@ -3477,7 +3470,6 @@ FILESTAMP // Builds ticcmds for console player, // 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. // static INT16 Consistancy(void) @@ -3487,14 +3479,14 @@ static INT16 Consistancy(void) DEBFILE(va("TIC %u ", gametic)); 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))); - ret = (INT16)((ret + players[i].mo->x) & 0xFFFF); + //DEBFILE(va("p[%d].x = %f ", i, (double)FIXED_TO_FLOAT(players[i].mo->x))); + ret = (INT16)((ret + (players[i].mo->x>>8)) & 0xFFFF); ret = (INT16)((ret + players[i].powers[pw_shield]) & 0xFFFF); } - //DEBFILE(va("pos = %d, rnd %d\n", ret, P_GetRandSeed())); - //ret = (INT16)(ret + P_GetRandSeed()); + DEBFILE(va("players = %d, rnd %d\n", ret, P_GetRandSeed())); + ret = (INT16)(ret + P_GetRandSeed()); return ret; } diff --git a/src/d_main.c b/src/d_main.c index 61d5d4093..2492f622c 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1087,16 +1087,14 @@ void D_SRB2Main(void) #endif D_CleanFile(); -#if 1 // md5s last updated 3/15/14 - // Yes, you read that right, that's the day of release. - // Aren't we batshit insane? +#if 1 // md5s last updated 3/18/14 // Check MD5s of autoloaded files W_VerifyFileMD5(0, "ac309fb3c7d4b5b685e2cd26beccf0e8"); // srb2.srb/srb2.wad W_VerifyFileMD5(1, "a894044b555dfcc71865cee16a996e88"); // zones.dta W_VerifyFileMD5(2, "4c410c1de6e0440cc5b2858dcca80c3e"); // player.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 // ...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()) I_Error("usage: -room \nCheck the Master Server's webpage for room ID numbers.\n"); + ms_RoomId = atoi(M_GetNextParm()); #ifdef UPDATE_ALERT GetMODVersion_Console(); #endif - - ms_RoomId = atoi(M_GetNextParm()); } // init all NETWORK diff --git a/src/d_net.c b/src/d_net.c index f2f8f958d..3c2213fca 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -71,7 +71,6 @@ void (*I_NetFreeNodenum)(INT32 nodenum) = NULL; SINT8 (*I_NetMakeNodewPort)(const char *address, const char* port) = NULL; boolean (*I_NetOpenSocket)(void) = NULL; boolean (*I_Ban) (INT32 node) = NULL; -boolean (*I_Shun) (INT32 node) = NULL; void (*I_ClearBans)(void) = NULL; const char *(*I_GetNodeAddress) (INT32 node) = NULL; const char *(*I_GetBanAddress) (size_t ban) = NULL; @@ -990,8 +989,6 @@ boolean HGetPacket(void) if (netbuffer->checksum != NetbufferChecksum()) { DEBFILE("Bad packet checksum\n"); - if (I_Shun) - I_Shun(doomcom->remotenode); // No more garbage from you! Net_CloseConnection(doomcom->remotenode); continue; } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 0eddb5922..57445244d 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1079,6 +1079,10 @@ static void SendNameAndColor(void) && !strcmp(cv_skin.string, skins[players[consoleplayer].skin].name)) 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 (!netgame) { @@ -1212,6 +1216,10 @@ static void SendNameAndColor2(void) 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 (botingame) { @@ -1365,8 +1373,6 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) } else SetPlayerSkinByNum(playernum, skin); - - players[playernum].pflags |= PF_CONSISTANCY; } void SendWeaponPref(void) @@ -1983,7 +1989,7 @@ static void Command_Pause(void) 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")); return; @@ -2013,6 +2019,9 @@ static void Got_Pause(UINT8 **cp, INT32 playernum) return; } + if (modeattacking) + return; + paused = READUINT8(*cp); dedicatedpause = READUINT8(*cp); @@ -3127,15 +3136,12 @@ static void Command_Addfile(void) } p = fn+strlen(fn); - while(p > fn) - { - --p; + while(--p >= fn) if (*p == '\\' || *p == '/' || *p == ':') { ++p; break; } - } WRITESTRINGN(buf_p,p,240); { @@ -4240,24 +4246,11 @@ static void Color_OnChange(void) { if (!P_PlayerMoving(consoleplayer)) { - // Color change menu scrolling fix - // 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); - } - } - + // Color change menu scrolling fix is no longer necessary SendNameAndColor(); } - else { + else + { CV_StealthSetValue(&cv_playercolor, players[consoleplayer].skincolor); } @@ -4272,24 +4265,11 @@ static void Color2_OnChange(void) { if (!P_PlayerMoving(secondarydisplayplayer)) { - // Color change menu scrolling fix - // 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); - } - } - + // Color change menu scrolling fix is no longer necessary SendNameAndColor2(); } - else { + else + { CV_StealthSetValue(&cv_playercolor2, players[secondarydisplayplayer].skincolor); } diff --git a/src/d_player.h b/src/d_player.h index e98f23ed0..3abc6ddf3 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -147,9 +147,7 @@ typedef enum 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 - // free: 1<<29, 1<<30 - - PF_CONSISTANCY = 1<<31 // DON'T mess with this flag or horrible things will happen. + // free: 1<<29, 1<<31 } pflags_t; typedef enum diff --git a/src/dehacked.c b/src/dehacked.c index 4b1cbf76c..e25f66e72 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -628,7 +628,7 @@ static void readfreeslots(MYFILE *f) // TODO: Out-of-slots warnings/errors. // TODO: Name too long (truncated) warnings. if (fastcmp(type, "SFX")) - S_AddSoundFx(word, false, -1, false); + S_AddSoundFx(word, false, 0, false); else if (fastcmp(type, "SPR")) { for (i = SPR_FIRSTFREESLOT; i <= SPR_LASTFREESLOT; i++) @@ -8112,7 +8112,7 @@ static inline int lib_freeslot(lua_State *L) sfxenum_t sfx; strlwr(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) { lua_pushinteger(L, sfx); r++; @@ -8189,12 +8189,12 @@ static inline int lib_freeslot(lua_State *L) static inline int lib_action(lua_State *L) { 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); var2 = (INT32)luaL_optinteger(L,3,0); - if (!*actor) + if (!actor) return LUA_ErrInvalid(L, "mobj_t"); - action->acp1(*actor); + action->acp1(actor); return 0; } diff --git a/src/doomdef.h b/src/doomdef.h index a659b2320..3649db08e 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -144,8 +144,8 @@ extern FILE *logstream; #define VERSIONSTRING "Trunk" #else #define VERSION 201 // Game version -#define SUBVERSION 2 // more precise version number -#define VERSIONSTRING "v2.1.2" +#define SUBVERSION 3 // more precise version number +#define VERSIONSTRING "v2.1.3" #endif // 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. // 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". -#define MODVERSION 6 +#define MODVERSION 7 diff --git a/src/g_game.c b/src/g_game.c index f6bc1c6c8..e3f2a2813 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1711,18 +1711,8 @@ boolean G_Responder(event_t *ev) // don't let busy scripts prevent pausing pausedelay = NEWTICRATE/7; - if (cv_pause.value == 1 || server || (adminplayer == consoleplayer)) - { - 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")); + // command will handle all the checks for us + COM_ImmedExecute("pause"); return true; } else @@ -1794,15 +1784,8 @@ void G_Ticker(boolean run) } for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - { - if (players[i].playerstate == PST_REBORN) - { - G_DoReborn(i); - } - } - } + if (playeringame[i] && players[i].playerstate == PST_REBORN) + G_DoReborn(i); } P_MapEnd(); @@ -1988,7 +1971,7 @@ void G_PlayerReborn(INT32 player) exiting = players[player].exiting; jointime = players[player].jointime; 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 if (!(netgame || multiplayer)) @@ -2501,6 +2484,9 @@ void G_ExitLevel(void) if (gametype != GT_COOP) CONS_Printf(M_GetText("The round has ended.\n")); + + // Remove CEcho text on round end. + HU_DoCEcho(""); } } diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 558083bdb..c8f452a69 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1180,7 +1180,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I if (players[tab[i].num].spectator) continue; //ignore them. - V_DrawString(x + 24, y, + V_DrawString(x + 20, y, ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) | ((players[tab[i].num].health > 0) ? 0 : V_60TRANS) | V_ALLOWLOWERCASE, tab[i].name); @@ -1293,7 +1293,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) continue; strlcpy(name, tab[i].name, 9); - V_DrawString(x + 24, y, + V_DrawString(x + 20, y, ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) | ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT) | V_ALLOWLOWERCASE, name); @@ -1326,7 +1326,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) else 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, 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++) { if (players[tab[i].num].spectator) continue; //ignore them. strlcpy(name, tab[i].name, 9); - V_DrawString(x + 24, y, + V_DrawString(x + 20, y, ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) | ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT) | 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 (circuitmap) { 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 - 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 - 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 - 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; if (y > 160) diff --git a/src/i_net.h b/src/i_net.h index ecf6202de..7a18ad186 100644 --- a/src/i_net.h +++ b/src/i_net.h @@ -141,7 +141,6 @@ extern void (*I_NetCloseSocket)(void); extern boolean (*I_Ban) (INT32 node); -extern boolean (*I_Shun) (INT32 node); extern void (*I_ClearBans)(void); extern const char *(*I_GetNodeAddress) (INT32 node); extern const char *(*I_GetBanAddress) (size_t ban); diff --git a/src/i_tcp.c b/src/i_tcp.c index 2127f1fc0..df7b3cf28 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -239,9 +239,6 @@ static size_t broadcastaddresses = 0; static boolean nodeconnected[MAXNETNODES+1]; static mysockaddr_t banned[MAXBANS]; static UINT8 bannedmask[MAXBANS]; -static mysockaddr_t shunned[MAXBANS]; -static UINT8 shunnedmask[MAXBANS]; -static size_t numshun = 0; #endif static size_t numbans = 0; @@ -528,12 +525,6 @@ static void SOCK_Get(void) (void *)&fromaddress, &fromlen); 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 for (j = 0; j <= MAXNETNODES; j++) //include LAN { @@ -1344,34 +1335,6 @@ static boolean SOCK_Ban(INT32 node) #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) { #ifdef NONET @@ -1511,7 +1474,6 @@ boolean I_InitTcpNetwork(void) I_NetOpenSocket = SOCK_OpenSocket; I_Ban = SOCK_Ban; - I_Shun = SOCK_Shun; I_ClearBans = SOCK_ClearBans; I_GetNodeAddress = SOCK_GetNodeAddress; I_GetBanAddress = SOCK_GetBanAddress; diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 95f192623..ece3d4298 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -218,7 +218,7 @@ static int lib_pNewChaseDir(lua_State *L) static int lib_pLookForPlayers(lua_State *L) { 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 tracer = lua_optboolean(L, 4); NOHUD @@ -341,8 +341,8 @@ static int lib_pSPMAngle(lua_State *L) mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobjtype_t type = luaL_checkinteger(L, 2); angle_t angle = (angle_t)luaL_checkinteger(L, 3); - UINT8 allowaim = (UINT8)luaL_checkinteger(L, 4); - UINT32 flags2 = (UINT32)luaL_checkinteger(L, 5); + UINT8 allowaim = (UINT8)luaL_optinteger(L, 4, 0); + UINT32 flags2 = (UINT32)luaL_optinteger(L, 5, 0); NOHUD if (!source) 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)); mobjtype_t type = luaL_checkinteger(L, 2); - UINT32 flags2 = (UINT32)luaL_checkinteger(L, 3); + UINT32 flags2 = (UINT32)luaL_optinteger(L, 3, 0); NOHUD if (!source) return LUA_ErrInvalid(L, "mobj_t"); diff --git a/src/lua_infolib.c b/src/lua_infolib.c index b0e6ed27b..6aa503a6d 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -26,23 +26,32 @@ boolean LUA_CallAction(const char *action, mobj_t *actor); state_t *astate; -enum sfxinfo_e { - sfxinfo_name = 0, - sfxinfo_singularity, - sfxinfo_priority, - sfxinfo_flags, // "pitch" - sfxinfo_volume, - sfxinfo_skinsound +enum sfxinfo_read { + sfxinfor_name = 0, + sfxinfor_singular, + sfxinfor_priority, + sfxinfor_flags, // "pitch" + sfxinfor_skinsound }; -const char *const sfxinfo_opt[] = { +const char *const sfxinfo_ropt[] = { "name", - "singularity", + "singular", "priority", "flags", - "volume", "skinsound", NULL}; +enum sfxinfo_write { + sfxinfow_singular = 0, + sfxinfow_priority, + sfxinfow_flags // "pitch" +}; +const char *const sfxinfo_wopt[] = { + "singular", + "priority", + "flags", + NULL}; + // // Sprite Names // @@ -718,6 +727,7 @@ static int lib_getSfxInfo(lua_State *L) static int lib_setSfxInfo(lua_State *L) { sfxinfo_t *info; + lua_remove(L, 1); 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. @@ -729,22 +739,27 @@ static int lib_setSfxInfo(lua_State *L) lua_pushnil(L); while (lua_next(L, 1)) { - lua_Integer i = 0; - const char *str = NULL; + enum sfxinfo_write i; if (lua_isnumber(L, 2)) i = lua_tointeger(L, 2); 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); - else if (i == 2 || (str && fastcmp(str,"priority"))) + break; + case sfxinfow_priority: 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); - else if (i == 4 || (str && fastcmp(str,"volume"))) - info->volume = (INT32)luaL_checkinteger(L, 3); + break; + default: + break; + } lua_pop(L, 1); } @@ -761,39 +776,38 @@ static int lib_sfxlen(lua_State *L) static int sfxinfo_get(lua_State *L) { 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); switch (field) { - case sfxinfo_name: + case sfxinfor_name: lua_pushstring(L, sfx->name); return 1; - case sfxinfo_singularity: + case sfxinfor_singular: lua_pushboolean(L, sfx->singularity); return 1; - case sfxinfo_priority: + case sfxinfor_priority: lua_pushinteger(L, sfx->priority); return 1; - case sfxinfo_flags: + case sfxinfor_flags: lua_pushinteger(L, sfx->pitch); return 1; - case sfxinfo_volume: - lua_pushinteger(L, sfx->volume); - return 1; - case sfxinfo_skinsound: + case sfxinfor_skinsound: lua_pushinteger(L, sfx->skinsound); return 1; + default: + return luaL_error(L, "impossible error"); } - return luaL_error(L, "impossible error"); + return 0; } // sfxinfo_t *, field, value static int sfxinfo_set(lua_State *L) { 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) 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) { - case sfxinfo_singularity: + case sfxinfow_singular: sfx->singularity = luaL_checkboolean(L, 1); break; - case sfxinfo_priority: + case sfxinfow_priority: sfx->priority = luaL_checkinteger(L, 1); break; - case sfxinfo_flags: + case sfxinfow_flags: sfx->pitch = luaL_checkinteger(L, 1); break; - case sfxinfo_volume: - sfx->volume = luaL_checkinteger(L, 1); - break; 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; } diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index fd6baec42..34f79a42b 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -131,7 +131,7 @@ static int player_get(lua_State *L) else if (fastcmp(field,"powers")) LUA_PushUserdata(L, plr->powers, META_POWERS); else if (fastcmp(field,"pflags")) - lua_pushinteger(L, (plr->pflags & ~PF_CONSISTANCY)); + lua_pushinteger(L, plr->pflags); else if (fastcmp(field,"panim")) lua_pushinteger(L, plr->panim); else if (fastcmp(field,"flashcount")) @@ -378,7 +378,7 @@ static int player_set(lua_State *L) else if (fastcmp(field,"powers")) return NOSET; 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")) plr->panim = luaL_checkinteger(L, 3); else if (fastcmp(field,"flashcount")) diff --git a/src/m_misc.c b/src/m_misc.c index 5e6f5508a..acf6a5982 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -1778,10 +1778,20 @@ UINT8 M_CountBits(UINT32 num, UINT8 size) for (i = 0; i < size; ++i) if (num & (1 << i)) ++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) { INT32 vinfo; diff --git a/src/m_misc.h b/src/m_misc.h index 8dd5f0279..f681bfcb3 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -94,7 +94,8 @@ void strcatbf(char *s1, const char *s2, const char *s3); void M_SetupMemcpy(void); // 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. #define AATREE_ZUSER 1 // Treat values as z_zone-allocated blocks and set their user fields diff --git a/src/p_enemy.c b/src/p_enemy.c index c93e47c8d..560b7d34a 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -1728,7 +1728,7 @@ void A_LobShot(mobj_t *actor) if (LUA_CallAction("A_LobShot", actor)) return; #endif - if (!actor->target || P_MobjWasRemoved(actor->target)) + if (!actor->target) return; A_FaceTarget(actor); @@ -1829,7 +1829,7 @@ void A_FireShot(mobj_t *actor) if (LUA_CallAction("A_FireShot", actor)) return; #endif - if (!actor->target || P_MobjWasRemoved(actor->target)) + if (!actor->target) return; A_FaceTarget(actor); @@ -1868,7 +1868,7 @@ void A_SuperFireShot(mobj_t *actor) if (LUA_CallAction("A_SuperFireShot", actor)) return; #endif - if (!actor->target || P_MobjWasRemoved(actor->target)) + if (!actor->target) return; A_FaceTarget(actor); @@ -1915,7 +1915,7 @@ void A_BossFireShot(mobj_t *actor) if (LUA_CallAction("A_BossFireShot", actor)) return; #endif - if (!actor->target || P_MobjWasRemoved(actor->target)) + if (!actor->target) return; A_FaceTarget(actor); @@ -1998,7 +1998,7 @@ void A_Boss7FireMissiles(mobj_t *actor) return; #endif - if (!actor->target || P_MobjWasRemoved(actor->target)) + if (!actor->target) { P_SetMobjState(actor, actor->info->spawnstate); return; @@ -2056,7 +2056,7 @@ void A_Boss1Laser(mobj_t *actor) if (LUA_CallAction("A_Boss1Laser", actor)) return; #endif - if (!actor->target || P_MobjWasRemoved(actor->target)) + if (!actor->target) return; switch (locvar2) @@ -2279,7 +2279,7 @@ void A_SkullAttack(mobj_t *actor) if (LUA_CallAction("A_SkullAttack", actor)) return; #endif - if (!actor->target || P_MobjWasRemoved(actor->target)) + if (!actor->target) return; speed = FixedMul(SKULLSPEED, actor->scale); @@ -2335,7 +2335,7 @@ void A_BossZoom(mobj_t *actor) if (LUA_CallAction("A_BossZoom", actor)) return; #endif - if (!actor->target || P_MobjWasRemoved(actor->target)) + if (!actor->target) return; dest = actor->target; @@ -2501,6 +2501,9 @@ void A_1upThinker(mobj_t *actor) if (!players[i].mo) 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); if (temp < dist) @@ -4815,12 +4818,6 @@ void A_UnidusBall(mobj_t *actor) actor->angle += ANGLE_11hh; - if (!actor->target) - { - CONS_Debug(DBG_GAMELOGIC, "A_UnidusBall: Spikeball has no target\n"); - return; - } - if (actor->movecount) { 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; } - 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); return; } 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; actor->x = actor->target->x + FixedMul(FINECOSINE(fa),actor->threshold); @@ -5030,27 +5028,9 @@ void A_MaceRotate(mobj_t *actor) return; #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. - 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); return; } @@ -6478,7 +6458,7 @@ void A_Boss2PogoTarget(mobj_t *actor) return; #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)) { // look for a new target @@ -10064,7 +10044,7 @@ void A_BrakFireShot(mobj_t *actor) if (LUA_CallAction("A_BrakFireShot", actor)) return; #endif - if (!actor->target || P_MobjWasRemoved(actor->target)) + if (!actor->target) return; A_FaceTarget(actor); diff --git a/src/p_inter.c b/src/p_inter.c index 9954e8b61..03ad7c46e 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -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"); else if (inflictor->player->powers[pw_invulnerability]) str = M_GetText("%s%s's invincibility aura %s %s.\n"); + else if (inflictor->player->powers[pw_super]) + str = M_GetText("%s%s's super aura %s %s.\n"); else str = M_GetText("%s%s's tagging hand %s %s.\n"); break; @@ -1579,6 +1581,10 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour break; } break; + case MT_EGGMANICO: + case MT_EGGMANBOX: + str = M_GetText("%s was %s by Eggman's nefarious TV magic.\n"); + break; case MT_SPIKE: str = M_GetText("%s was %s by spikes.\n"); break; diff --git a/src/p_mobj.c b/src/p_mobj.c index c640a8b29..b973c6cc3 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -58,7 +58,7 @@ void P_RunCachedActions(void) #ifdef HAVE_BLUA astate = &states[ac->statenum]; #endif - if (ac->mobj) // just in case... + if (ac->mobj && !P_MobjWasRemoved(ac->mobj)) // just in case... states[ac->statenum].action.acp1(ac->mobj); next = ac->next; Z_Free(ac); @@ -288,6 +288,11 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) astate = st; #endif 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; @@ -5237,19 +5242,27 @@ INT32 numshields = 0; void P_RunShields(void) { INT32 i; - mobj_t *mo; + mobj_t *mo, *next; fixed_t destx,desty,zoffs; + // run shields for (i = 0; i < numshields; i++) { P_ShieldLook(shields[i], shields[i]->info->speed); P_SetTarget(&shields[i], NULL); } - 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) continue; if (!splitscreen /*&& rendermode != render_soft*/) @@ -5292,8 +5305,7 @@ void P_RunShields(void) P_SetThingPosition(mo); P_CheckPosition(mo, mo->x, mo->y); } - - overlaycap = NULL; + P_SetTarget(&overlaycap, NULL); } static boolean P_AddShield(mobj_t *thing) @@ -5330,17 +5342,38 @@ static boolean P_AddShield(mobj_t *thing) return true; } +// Called only when MT_OVERLAY thinks. static void P_AddOverlay(mobj_t *thing) { - mobj_t *mo; - if (!overlaycap) - overlaycap = thing; + I_Assert(thing != NULL); + + if (overlaycap == NULL) + P_SetTarget(&overlaycap, thing); else { + mobj_t *mo; 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); @@ -5528,7 +5561,7 @@ void P_MobjThinker(mobj_t *mobj) // Don't touch my fuse! return; case MT_OVERLAY: - if (!mobj->target || P_MobjWasRemoved(mobj->target)) + if (!mobj->target) { P_RemoveMobj(mobj); return; @@ -5577,7 +5610,7 @@ void P_MobjThinker(mobj_t *mobj) } break; case MT_DROWNNUMBERS: - if (!mobj->target || P_MobjWasRemoved(mobj->target)) + if (!mobj->target) { P_RemoveMobj(mobj); return; @@ -5972,7 +6005,6 @@ void P_MobjThinker(mobj_t *mobj) break; case MT_EGGMOBILE2_POGO: if (!mobj->target - || P_MobjWasRemoved(mobj->target) || !mobj->target->health || mobj->target->state == &states[mobj->target->info->spawnstate] || mobj->target->state == &states[mobj->target->info->raisestate]) @@ -6010,7 +6042,6 @@ void P_MobjThinker(mobj_t *mobj) fixed_t jetx, jety; 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 { // then remove yourself as well! P_RemoveMobj(mobj); @@ -6090,7 +6121,6 @@ void P_MobjThinker(mobj_t *mobj) fixed_t jetx, jety; 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 { // then remove yourself as well! P_RemoveMobj(mobj); @@ -6121,7 +6151,6 @@ void P_MobjThinker(mobj_t *mobj) case MT_JETFLAME: { 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 { // then remove yourself as well! 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->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); 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; #endif 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); } + if (mobj->type == MT_OVERLAY) + P_RemoveOverlay(mobj); + mobj->health = 0; // Just because // unlink from sector and block lists @@ -7862,9 +7898,19 @@ void P_SpawnPlayer(INT32 playernum) p->spectator = false; } - // Fix stupid non spectator spectators. - if (G_GametypeHasTeams() && !p->spectator && !p->ctfteam) - p->spectator = true; + if (G_GametypeHasTeams()) + { + // 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->player = p)->mo = mobj; diff --git a/src/p_spec.c b/src/p_spec.c index b3951222a..20d86176f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1598,7 +1598,7 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) if (!playeringame[i] || players[i].spectator) continue; - if (!players[i].mo) + if (!players[i].mo || players[i].mo->health < 1) continue; 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) { + boolean tryagain; sec = sectors + secnum; - for (thing = sec->thinglist; thing; thing = thing->snext) - if (thing->type == type) - { - if (state != NUMSTATES) - P_SetMobjState(thing, state); - else - P_SetMobjState(thing, thing->state->nextstate); - } + do { + tryagain = false; + for (thing = sec->thinglist; thing; thing = thing->snext) + if (thing->type == type) + { + if (state != NUMSTATES) + { + 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; } diff --git a/src/p_user.c b/src/p_user.c index c755cb5ed..5aa0d50a1 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -261,6 +261,9 @@ boolean P_PlayerMoving(INT32 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) return false; @@ -9134,7 +9137,7 @@ void P_PlayerAfterThink(player_t *player) 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; else { diff --git a/src/r_things.c b/src/r_things.c index ed776c5d0..afbda8da5 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1231,6 +1231,15 @@ static void R_ProjectSprite(mobj_t *thing) 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 vis = R_NewVisSprite(); 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 vis = R_NewVisSprite(); vis->scale = yscale; //<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; } } diff --git a/src/s_sound.c b/src/s_sound.c index f19100636..6e6c492a3 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1447,7 +1447,7 @@ void S_StartSoundName(void *mo, const char *soundname) return; } - soundnum = S_AddSoundFx(soundname, false, -1, false); + soundnum = S_AddSoundFx(soundname, false, 0, false); newsounds[i] = soundnum; } diff --git a/src/sounds.c b/src/sounds.c index a1e3bd791..c03d6cea2 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -1359,7 +1359,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k51", 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}, - {"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}, {"s3k56", 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. // -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) { sfxenum_t i, slot; @@ -1585,9 +1584,9 @@ sfxenum_t S_AddSoundFx(const char *name, INT32 singularity, INT32 pitch, if (!S_sfx[i].priority) { 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].pitch = pitch; + S_sfx[i].pitch = flags; S_sfx[i].volume = -1; S_sfx[i].lumpnum = LUMPERROR; S_sfx[i].skinsound = -1; diff --git a/src/sounds.h b/src/sounds.h index a42b986c2..ee1e60ba1 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -57,7 +57,7 @@ struct sfxinfo_struct const char *name; // Sfx singularity (only one at a time) - INT32 singularity; + boolean singularity; // Sfx priority INT32 priority; @@ -1631,7 +1631,7 @@ typedef enum 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); #endif diff --git a/src/tables.c b/src/tables.c index f85fc9fc5..fa71effef 100644 --- a/src/tables.c +++ b/src/tables.c @@ -98,6 +98,11 @@ angle_t FixedAngleC(fixed_t fa, fixed_t factor) if (fa == 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) return FixedAngle(fa); else if (factor > 0) @@ -132,6 +137,11 @@ angle_t FixedAngle(fixed_t fa) if (fa == 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); while (fa)