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
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;
}

View file

@ -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 <room_id>\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

View file

@ -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;
}

View file

@ -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);
}

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_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

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}
// command will handle all the checks for us
COM_ImmedExecute("pause");
}
else
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
return true;
}
else
@ -1794,16 +1784,9 @@ void G_Ticker(boolean run)
}
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
{
if (players[i].playerstate == PST_REBORN)
{
if (playeringame[i] && players[i].playerstate == PST_REBORN)
G_DoReborn(i);
}
}
}
}
P_MapEnd();
// do things to change the game state
@ -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("");
}
}

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)
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)

View file

@ -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);

View file

@ -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;

View file

@ -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");

View file

@ -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 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;
}

View file

@ -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"))

View file

@ -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;

View file

@ -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

View file

@ -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);

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");
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;

View file

@ -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);
}
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;
}
thing->hnext = NULL;
}
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,10 +7898,20 @@ void P_SpawnPlayer(INT32 playernum)
p->spectator = false;
}
if (G_GametypeHasTeams())
{
// Fix stupid non spectator spectators.
if (G_GametypeHasTeams() && !p->spectator && !p->ctfteam)
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;

View file

@ -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,16 +2907,29 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo)
while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
{
boolean tryagain;
sec = sectors + secnum;
do {
tryagain = false;
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);
{
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;
}

View file

@ -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
{

View file

@ -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; //<<detailshift;
@ -2690,7 +2708,7 @@ void R_AddSkins(UINT16 wadnum)
stoken + 2))
{
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;
}
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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

View file

@ -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)