From 8a9759a3e4dc7d87c706f232aac4c90469773709 Mon Sep 17 00:00:00 2001
From: Alam Ed Arias <alam@srb2.org>
Date: Sat, 19 Apr 2014 13:41:29 -0400
Subject: [PATCH] SRB2 2.1.8 release

---
 readme.txt                                    |  5 +-
 src/dehacked.c                                |  5 +-
 src/doomdef.h                                 |  6 +--
 src/hardware/hw_draw.c                        |  3 ++
 src/lua_baselib.c                             |  4 +-
 src/lua_consolelib.c                          | 53 +++++++++++--------
 src/lua_hooklib.c                             |  2 +-
 src/lua_playerlib.c                           | 12 ++++-
 src/m_anigif.c                                | 23 ++++++--
 src/p_inter.c                                 | 10 +++-
 src/p_mobj.c                                  | 14 +++++
 src/p_setup.c                                 |  2 +-
 src/p_user.c                                  | 13 -----
 .../macosx/Srb2mac.xcodeproj/project.pbxproj  |  4 +-
 14 files changed, 103 insertions(+), 53 deletions(-)

diff --git a/readme.txt b/readme.txt
index ed3c4ec5..d8a040be 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,4 +1,7 @@
-Here it is! SRB2 v2.1.7 source code!
+Here it is! SRB2 v2.1.8 source code!
+(why do we keep the version number up to date
+	when everything else in this file is hilariously old?
+	- Inuyasha)
 
 
 Win32 with Visual C (6SP6+Processor Pack OR 7)
diff --git a/src/dehacked.c b/src/dehacked.c
index cf40ac3e..9c2fe4d2 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -8489,7 +8489,10 @@ static inline int lib_getenum(lua_State *L)
 	// DYNAMIC variables too!!
 	// Try not to add anything that would break netgames or timeattack replays here.
 	// You know, like consoleplayer, displayplayer, secondarydisplayplayer, or gametime.
-	if (fastcmp(word,"maptol")) {
+	if (fastcmp(word,"gamemap")) {
+		lua_pushinteger(L, gamemap);
+		return 1;
+	} else if (fastcmp(word,"maptol")) {
 		lua_pushinteger(L, maptol);
 		return 1;
 	} else if (fastcmp(word,"mariomode")) {
diff --git a/src/doomdef.h b/src/doomdef.h
index 93503de3..3ce330af 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 7  // more precise version number
-#define VERSIONSTRING "v2.1.7"
+#define SUBVERSION 8  // more precise version number
+#define VERSIONSTRING "v2.1.8"
 #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 12
+#define MODVERSION 13
 
 
 
diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c
index e2229ea9..313bc6c2 100644
--- a/src/hardware/hw_draw.c
+++ b/src/hardware/hw_draw.c
@@ -179,6 +179,9 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
 	if (option & V_NOSCALESTART)
 		sdupx = sdupy = 2.0f;
 
+	if (option & V_SPLITSCREEN)
+		sdupy /= 2.0f;
+
 	if (option & V_FLIP) // Need to flip both this and sow
 	{
 		v[0].x = v[3].x = (cx*sdupx-(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1;
diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index ac801cdd..6225910a 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -1459,7 +1459,7 @@ static int lib_sSoundPlaying(lua_State *L)
 
 static int lib_gBuildMapName(lua_State *L)
 {
-	INT32 map = luaL_checkinteger(L, 1);
+	INT32 map = luaL_optinteger(L, 1, gamemap);
 	//HUDSAFE
 	lua_pushstring(L, G_BuildMapName(map));
 	return 1;
@@ -1484,7 +1484,7 @@ static int lib_gExitLevel(lua_State *L)
 
 static int lib_gIsSpecialStage(lua_State *L)
 {
-	INT32 mapnum = luaL_checkinteger(L, 1);
+	INT32 mapnum = luaL_optinteger(L, 1, gamemap);
 	//HUDSAFE
 	lua_pushboolean(L, G_IsSpecialStage(mapnum));
 	return 1;
diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c
index 6f185c69..ff702551 100644
--- a/src/lua_consolelib.c
+++ b/src/lua_consolelib.c
@@ -30,14 +30,21 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum)
 {
 	UINT8 i, argc, flags;
 	char buf[256];
-	I_Assert(gL != NULL);
+
+	// don't use I_Assert here, goto the deny code below
+	// to clean up and kick people who try nefarious exploits
+	// like sending random junk lua commands to crash the server
+
+	if (!gL) goto deny;
 	lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command
-	I_Assert(lua_istable(gL, -1));
+	if (!lua_istable(gL, -1)) goto deny;
 
 	argc = READUINT8(*cp);
 	READSTRINGN(*cp, buf, 255);
+	strlwr(buf); // must lowercase buffer
 	lua_getfield(gL, -1, buf); // push command info table
-	I_Assert(lua_istable(gL, -1));
+	if (!lua_istable(gL, -1)) goto deny;
+
 	lua_remove(gL, -2); // pop COM_Command
 
 	lua_rawgeti(gL, -1, 2); // push flags from command info table
@@ -47,26 +54,16 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum)
 		flags = (UINT8)lua_tointeger(gL, -1);
 	lua_pop(gL, 1); // pop flags
 
-	if (flags & 1 && playernum != serverplayer && playernum != adminplayer)
-	{
-		// not from server or remote admin, must be hacked/buggy client
-		CONS_Alert(CONS_WARNING, M_GetText("Illegal lua command received from %s\n"), player_names[playernum]);
-
-		lua_pop(gL, 1); // pop command info table
-
-		if (server)
-		{
-			XBOXSTATIC UINT8 bufn[2];
-
-			bufn[0] = (UINT8)playernum;
-			bufn[1] = KICK_MSG_CON_FAIL;
-			SendNetXCmd(XD_KICK, &bufn, 2);
-		}
-		return;
-	}
+	// requires server/admin and the player is not one of them
+	if ((flags & 1) && playernum != serverplayer && playernum != adminplayer)
+		goto deny;
 
 	lua_rawgeti(gL, -1, 1); // push function from command info table
-	I_Assert(lua_isfunction(gL, -1));
+
+	// although honestly this should be true anyway
+	// BUT GODDAMNIT I SAID NO I_ASSERTS SO NO I_ASSERTS IT IS
+	if (!lua_isfunction(gL, -1)) goto deny;
+
 	lua_remove(gL, -2); // pop command info table
 
 	LUA_PushUserdata(gL, &players[playernum], META_PLAYER);
@@ -76,6 +73,20 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum)
 		lua_pushstring(gL, buf);
 	}
 	LUA_Call(gL, (int)argc); // argc is 1-based, so this will cover the player we passed too.
+	return;
+
+deny:
+	//must be hacked/buggy client
+	lua_settop(gL, 0); // clear stack
+	CONS_Alert(CONS_WARNING, M_GetText("Illegal lua command received from %s\n"), player_names[playernum]);
+	if (server)
+	{
+		XBOXSTATIC UINT8 bufn[2];
+
+		bufn[0] = (UINT8)playernum;
+		bufn[1] = KICK_MSG_CON_FAIL;
+		SendNetXCmd(XD_KICK, &bufn, 2);
+	}
 }
 
 // Wrapper for COM_AddCommand commands
diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index 8bd1b49e..ed9f53d2 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -145,6 +145,7 @@ static int lib_addHook(lua_State *L)
 			lua_pushvalue(L, 2);
 			lua_rawseti(L, -2, hook);
 		}
+		hooksAvailable[hook/8] |= 1<<(hook%8);
 		return 0;
 	}
 
@@ -186,7 +187,6 @@ static int lib_addHook(lua_State *L)
 	if (subfield)
 		Z_Free(subfield);
 
-
 	hooksAvailable[hook/8] |= 1<<(hook%8);
 	return 0;
 }
diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c
index 18f8b283..20d9fb62 100644
--- a/src/lua_playerlib.c
+++ b/src/lua_playerlib.c
@@ -344,8 +344,16 @@ static int player_set(lua_State *L)
 	if (hud_running)
 		return luaL_error(L, "Do not alter player_t in HUD rendering code!");
 
-	if (fastcmp(field,"mo"))
-		plr->mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
+	if (fastcmp(field,"mo")) {
+		if (!lua_isnil(L, 3))
+		{
+			plr->mo->player = NULL;
+			plr->mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
+			plr->mo->player = plr;
+		}
+		else
+			return luaL_error(L, "player.mo should not be nil!");
+	}
 	else if (fastcmp(field,"cmd"))
 		return NOSET;
 	else if (fastcmp(field,"playerstate"))
diff --git a/src/m_anigif.c b/src/m_anigif.c
index c5efe876..0fe98f34 100644
--- a/src/m_anigif.c
+++ b/src/m_anigif.c
@@ -351,16 +351,28 @@ static void GIF_lzw(void)
 			scrbuf_pos = scrbuf_linebegin;
 		}
 		// Just a bit of overflow prevention
-		// We leave ourselves 40 bits of space JUST IN CASE the
-		// end of data is right here, as that's EXACTLY how much
-		// the end of data could require at worst
-		if (gifbwr_bufsize >= 250)
+		if (gifbwr_bufsize >= 248)
 			break;
 	}
 	if (scrbuf_pos > scrbuf_writeend)
 	{
+		// 4.15.14 - I failed to account for the possibility that
+		// these two writes could possibly cause minbits increases.
+		// Luckily, we have a guarantee that the first byte CANNOT exceed
+		// the maximum possible code.  So, we do a minbits check here...
+		if (giflzw_nextCodeToAssign++ > (1 << gifbwr_bits_min))
+			++gifbwr_bits_min; // out of room, extend minbits
 		GIF_bwrwrite(giflzw_workingCode);
+
+		// And luckily once more, if the data marker somehow IS at
+		// MAXCODE it doesn't matter, because it still marks the
+		// end of the stream and thus no extending will happen!
+		// But still, we need to check minbits again...
+		if (giflzw_nextCodeToAssign++ > (1 << gifbwr_bits_min))
+			++gifbwr_bits_min; // out of room, extend minbits
 		GIF_bwrwrite(GIFLZW_DATAEND);
+
+		// Okay, the flush is safe at least.
 		GIF_bwrflush();
 		gif_writeover = 1;
 	}
@@ -527,7 +539,8 @@ static void GIF_framewrite(void)
 		while (!gif_writeover)
 		{
 			GIF_lzw(); // main lzw packing loop
-			if ((size_t)(p - gifframe_data) + gifbwr_bufsize > gifframe_size)
+
+			if ((size_t)(p - gifframe_data) + gifbwr_bufsize + 1 >= gifframe_size)
 			{
 				INT32 temppos = p - gifframe_data;
 				gifframe_data = Z_Realloc(gifframe_data, (gifframe_size *= 2), PU_STATIC, NULL);
diff --git a/src/p_inter.c b/src/p_inter.c
index 149c16b0..c55c3cf7 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -2865,6 +2865,13 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
 		}
 #endif
 	}
+#ifdef HAVE_BLUA
+	else if (target->flags & MF_ENEMY)
+	{
+		if (LUAh_MobjDamage(target, inflictor, source, damage) || P_MobjWasRemoved(target))
+			return true;
+	}
+#endif
 
 	player = target->player;
 
@@ -3030,7 +3037,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
 	}
 
 	// Killing dead. Just for kicks.
-	if (cv_killingdead.value && source && source->player && P_Random() < 80)
+	// Require source and inflictor be player.  Don't hurt for firing rings.
+	if (cv_killingdead.value && (source && source->player) && (inflictor && inflictor->player) && P_Random() < 80)
 		P_DamageMobj(source, target, target, 1);
 
 	// do the damage
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 98e0c9f8..81ad1a5e 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -5883,6 +5883,20 @@ void P_MobjThinker(mobj_t *mobj)
 				mobj->fuse--;
 			}
 			break;
+		case MT_PLAYER:
+			/// \todo Have the player's dead body completely finish its animation even if they've already respawned.
+			if (!(mobj->flags2 & MF2_DONTDRAW))
+			{
+				if (mobj->player && mobj->player->deadtimer > 3*TICRATE)
+				{ // Go away.
+					/// \todo Actually go ahead and remove mobj completely, and fix any bugs and crashes doing this creates. Chasecam should stop moving, and F12 should never return to it.
+					mobj->momz = 0;
+					mobj->flags2 |= MF2_DONTDRAW;
+				}
+				else // Apply gravity to fall downwards.
+					P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true);
+			}
+			break;
 		default:
 			break;
 		}
diff --git a/src/p_setup.c b/src/p_setup.c
index 64f67094..c5b6995e 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -2325,7 +2325,7 @@ boolean P_SetupLevel(boolean skipprecip)
 
 	if (cv_runscripts.value && mapheaderinfo[gamemap-1]->scriptname[0] != '#')
 	{
-		if (!mapheaderinfo[gamemap-1]->levelflags & LF_SCRIPTISFILE)
+		if (!(mapheaderinfo[gamemap-1]->levelflags & LF_SCRIPTISFILE))
 		{
 			lumpnum_t lumpnum;
 			char newname[9];
diff --git a/src/p_user.c b/src/p_user.c
index 0c016dfc..05c1595c 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -7772,19 +7772,6 @@ static void P_DeathThink(player_t *player)
 		return;
 
 	P_CalcHeight(player);
-
-	/// \todo Do all this physics stuff in a seperate thinker to be run by the mobj itself, and have your dead body completely finish its animation even if you've already respawned.
-	if (!(player->mo->flags2 & MF2_DONTDRAW))
-	{
-		if (player->deadtimer > 3*TICRATE)
-		{ // Go away.
-			/// \todo Actually go ahead and remove player->mo completely, and fix any bugs and crashes doing this creates. Chasecam should stop moving, and F12 should never return to it.
-			player->mo->momz = 0;
-			player->mo->flags2 |= MF2_DONTDRAW;
-		}
-		else // Apply gravity to fall downwards.
-			P_SetObjectMomZ(player->mo, -2*FRACUNIT/3, true);
-	}
 }
 
 //
diff --git a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj
index 1704f434..1b1a9fdf 100644
--- a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj
+++ b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj
@@ -1214,7 +1214,7 @@
 		C01FCF4B08A954540054247B /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				CURRENT_PROJECT_VERSION = 2.1.7;
+				CURRENT_PROJECT_VERSION = 2.1.8;
 				GCC_PREPROCESSOR_DEFINITIONS = (
 					"$(inherited)",
 					NORMALSRB2,
@@ -1226,7 +1226,7 @@
 		C01FCF4C08A954540054247B /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				CURRENT_PROJECT_VERSION = 2.1.7;
+				CURRENT_PROJECT_VERSION = 2.1.8;
 				GCC_ENABLE_FIX_AND_CONTINUE = NO;
 				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
 				GCC_PREPROCESSOR_DEFINITIONS = (