From 86e9504d04eee25fa51dd08e8c195b8de98f66d9 Mon Sep 17 00:00:00 2001
From: Leonard <hobbax3@gmail.com>
Date: Wed, 19 Aug 2015 15:59:54 +0200
Subject: [PATCH 01/19] Added weapon interpolation.

---
 src/d_player.h               |   1 +
 src/g_game.cpp               |   9 ++
 src/p_pspr.cpp               |  21 ++++
 src/p_pspr.h                 |   6 ++
 src/p_saveg.cpp              |   5 +
 src/p_user.cpp               |  15 +++
 src/r_data/r_interpolate.cpp | 199 ++++++++++++++++++++++++++++++++++-
 src/version.h                |   2 +-
 8 files changed, 254 insertions(+), 4 deletions(-)

diff --git a/src/d_player.h b/src/d_player.h
index e27bf1087f..2ac2ad0d50 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -427,6 +427,7 @@ public:
 	short		fixedcolormap;			// can be set to REDCOLORMAP, etc.
 	short		fixedlightlevel;
 	pspdef_t	psprites[NUMPSPRITES];	// view sprites (gun, etc)
+	TObjPtr<DInterpolation>	pspinterp[NUMPSPRITES];		// view sprite interpolations
 	int			morphTics;				// player is a chicken/pig if > 0
 	const PClass *MorphedPlayerClass;		// [MH] (for SBARINFO) class # for this player instance when morphed
 	int			MorphStyle;				// which effects to apply for this player instance when morphed
diff --git a/src/g_game.cpp b/src/g_game.cpp
index 8101ca23d2..f77949687d 100644
--- a/src/g_game.cpp
+++ b/src/g_game.cpp
@@ -1726,6 +1726,15 @@ void G_DoPlayerPop(int playernum)
 		players[playernum].mo = NULL;
 		players[playernum].camera = NULL;
 	}
+	// Now's the ideal time to remove his psprite interpolations.
+	for (int ii = 0; ii < NUMPSPRITES; ii++)
+	{
+		if (players[playernum].psprites[ii].interpolation != NULL)
+		{
+			players[playernum].psprites[ii].StopInterpolation();
+			players[playernum].pspinterp[ii] = NULL;
+		}
+	}
 	// [RH] Let the scripts know the player left
 	FBehavior::StaticStartTypedScripts(SCRIPT_Disconnect, NULL, true, playernum);
 }
diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp
index 63f3bc6486..d2bf8cc87d 100644
--- a/src/p_pspr.cpp
+++ b/src/p_pspr.cpp
@@ -1104,11 +1104,32 @@ void P_MovePsprites (player_t *player)
 			P_CheckWeaponZoom (player);
 		}
 	}
+
+	psp = &player->psprites[0];
+	for (i = 0; i < NUMPSPRITES; i++, psp++)
+	{
+		if (psp->state == NULL)
+		{
+			if (psp->interpolation != NULL)
+			{
+				player->pspinterp[i] = NULL;
+				psp->StopInterpolation();
+			}
+		}
+		else if (psp->interpolation == NULL)
+		{
+			player->pspinterp[i] = psp->SetInterpolation(player - players, i);
+		}
+	}
 }
 
 FArchive &operator<< (FArchive &arc, pspdef_t &def)
 {
 	arc << def.state << def.tics << def.sx << def.sy
 		<< def.sprite << def.frame;
+
+		if (SaveVersion >= 4525)
+			arc << def.interpolation;
+
 	return arc;
 }
diff --git a/src/p_pspr.h b/src/p_pspr.h
index ca9b45ee82..62c2a6fe48 100644
--- a/src/p_pspr.h
+++ b/src/p_pspr.h
@@ -26,6 +26,7 @@
 // Basic data types.
 // Needs fixed point, and BAM angles.
 #include "tables.h"
+#include "r_data/r_interpolate.h"
 #include "thingdef/thingdef.h"
 
 #define WEAPONBOTTOM			128*FRACUNIT
@@ -71,6 +72,11 @@ struct pspdef_t
 	int			sprite;
 	int			frame;
 	bool		processPending; // true: waiting for periodic processing on this tick
+
+	TObjPtr<DInterpolation>	interpolation;
+	DInterpolation			*SetInterpolation(int player, int position);
+	void					UpdateInterpolation(int player);
+	void					StopInterpolation();
 };
 
 class FArchive;
diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp
index 4804943203..f16bdb0f92 100644
--- a/src/p_saveg.cpp
+++ b/src/p_saveg.cpp
@@ -297,6 +297,11 @@ static void CopyPlayer (player_t *dst, player_t *src, const char *name)
 	{
 		dst->mo->player = dst;
 	}
+	// Fix the psprite interpolation pointers too.
+	for (int i = 0; i < NUMPSPRITES; i++)
+	{
+		dst->psprites[i].UpdateInterpolation(dst - players);
+	}
 	// These 2 variables may not be overwritten.
 	dst->attackdown = attackdown;
 	dst->usedown = usedown;
diff --git a/src/p_user.cpp b/src/p_user.cpp
index 0617e5d6a1..baea731e68 100644
--- a/src/p_user.cpp
+++ b/src/p_user.cpp
@@ -316,6 +316,7 @@ player_t::player_t()
 	memset (&cmd, 0, sizeof(cmd));
 	memset (frags, 0, sizeof(frags));
 	memset (psprites, 0, sizeof(psprites));
+	memset (pspinterp, 0, sizeof(pspinterp));
 }
 
 player_t &player_t::operator=(const player_t &p)
@@ -371,6 +372,7 @@ player_t &player_t::operator=(const player_t &p)
 	fixedcolormap = p.fixedcolormap;
 	fixedlightlevel = p.fixedlightlevel;
 	memcpy(psprites, &p.psprites, sizeof(psprites));
+	memcpy(pspinterp, &p.pspinterp, sizeof(pspinterp));
 	morphTics = p.morphTics;
 	MorphedPlayerClass = p.MorphedPlayerClass;
 	MorphStyle = p.MorphStyle;
@@ -435,6 +437,10 @@ size_t player_t::FixPointers (const DObject *old, DObject *rep)
 	if (*&ConversationNPC == old)	ConversationNPC = replacement, changed++;
 	if (*&ConversationPC == old)	ConversationPC = replacement, changed++;
 	if (*&MUSINFOactor == old)		MUSINFOactor = replacement, changed++;
+
+	for (int i = 0; i < NUMPSPRITES; i++)
+		if (*&pspinterp[i] == old)	pspinterp[i] = static_cast<DInterpolation *>(rep), changed++;
+
 	return changed;
 }
 
@@ -454,6 +460,11 @@ size_t player_t::PropagateMark()
 	{
 		GC::Mark(PendingWeapon);
 	}
+	for (int i = 0; i < NUMPSPRITES; i++)
+	{
+		GC::Mark(pspinterp[i]);
+	}
+
 	return sizeof(*this);
 }
 
@@ -3049,7 +3060,11 @@ void player_t::Serialize (FArchive &arc)
 	for (i = 0; i < MAXPLAYERS; i++)
 		arc << frags[i];
 	for (i = 0; i < NUMPSPRITES; i++)
+	{
 		arc << psprites[i];
+		if (SaveVersion >= 4525)
+			arc << pspinterp[i];
+	}
 
 	arc << CurrentPlayerClass;
 
diff --git a/src/r_data/r_interpolate.cpp b/src/r_data/r_interpolate.cpp
index 3ca3b557cf..2acbe21403 100644
--- a/src/r_data/r_interpolate.cpp
+++ b/src/r_data/r_interpolate.cpp
@@ -151,6 +151,35 @@ public:
 };
 
 
+//==========================================================================
+//
+//
+//
+//==========================================================================
+
+class DPSpriteInterpolation : public DInterpolation
+{
+	DECLARE_CLASS(DPSpriteInterpolation, DInterpolation)
+
+	pspdef_t *psp;
+	int player, position;
+	fixed_t oldx, oldy;
+	fixed_t bakx, baky;
+	fixed_t ofsx, ofsy;
+	fixed_t nfsx, nfsy;
+
+public:
+
+	DPSpriteInterpolation() {}
+	DPSpriteInterpolation(pspdef_t *psp, int player, int position);
+	void UpdatePointer(int player);
+	void Destroy();
+	void UpdateInterpolation();
+	void Restore();
+	void Interpolate(fixed_t smoothratio);
+	void Serialize(FArchive &arc);
+};
+
 //==========================================================================
 //
 //
@@ -162,6 +191,7 @@ IMPLEMENT_CLASS(DSectorPlaneInterpolation)
 IMPLEMENT_CLASS(DSectorScrollInterpolation)
 IMPLEMENT_CLASS(DWallScrollInterpolation)
 IMPLEMENT_CLASS(DPolyobjInterpolation)
+IMPLEMENT_CLASS(DPSpriteInterpolation)
 
 //==========================================================================
 //
@@ -628,7 +658,6 @@ void DSectorScrollInterpolation::Serialize(FArchive &arc)
 	arc << sector << ceiling << oldx << oldy;
 }
 
-
 //==========================================================================
 //
 //
@@ -824,6 +853,115 @@ void DPolyobjInterpolation::Serialize(FArchive &arc)
 	if (arc.IsLoading()) bakverts.Resize(oldverts.Size());
 }
 
+//==========================================================================
+//
+//
+//
+//==========================================================================
+
+//==========================================================================
+//
+//
+//
+//==========================================================================
+
+DPSpriteInterpolation::DPSpriteInterpolation(pspdef_t *_psp, int _player, int _position)
+: nfsx(0), nfsy(0), ofsx(0), ofsy(0)
+{
+	psp = _psp;
+	player = _player;
+	position = _position;
+	UpdateInterpolation ();
+	interpolator.AddInterpolation(this);
+}
+
+//==========================================================================
+//
+//
+//
+//==========================================================================
+
+void DPSpriteInterpolation::UpdatePointer(int _player)
+{
+	player = _player;
+	psp = &players[player].psprites[position];
+}
+
+//==========================================================================
+//
+//
+//
+//==========================================================================
+
+void DPSpriteInterpolation::Destroy()
+{
+	psp->interpolation = NULL;
+	Super::Destroy();
+}
+
+//==========================================================================
+//
+//
+//
+//==========================================================================
+
+void DPSpriteInterpolation::UpdateInterpolation()
+{
+	if ( position == ps_weapon )
+		P_BobWeapon( &players[player], psp, &ofsx, &ofsy );
+
+	oldx = psp->sx + ofsx;
+	oldy = psp->sy + ofsy;
+}
+
+//==========================================================================
+//
+//
+//
+//==========================================================================
+
+void DPSpriteInterpolation::Restore()
+{
+	psp->sx = bakx - nfsx;
+	psp->sy = baky - nfsy;
+}
+
+//==========================================================================
+//
+//
+//
+//==========================================================================
+
+void DPSpriteInterpolation::Interpolate(fixed_t smoothratio)
+{
+	if ( position == ps_weapon )
+		P_BobWeapon( &players[player], psp, &nfsx, &nfsy );
+
+	bakx = psp->sx + nfsx;
+	baky = psp->sy + nfsy;
+
+	psp->sx = oldx + FixedMul(bakx - oldx, smoothratio) - nfsx;
+	psp->sy = oldy + FixedMul(baky - oldy, smoothratio) - nfsy;
+}
+
+//==========================================================================
+//
+//
+//
+//==========================================================================
+
+void DPSpriteInterpolation::Serialize(FArchive &arc)
+{
+	Super::Serialize(arc);
+	arc << player << position << oldx << oldy << ofsx << ofsy;
+	UpdatePointer(player);
+}
+
+//==========================================================================
+//
+//
+//
+//==========================================================================
 
 //==========================================================================
 //
@@ -944,6 +1082,63 @@ void FPolyObj::StopInterpolation()
 	}
 }
 
+//==========================================================================
+//
+//
+//
+//==========================================================================
+
+DInterpolation *pspdef_t::SetInterpolation(int player, int position)
+{
+	if (interpolation == NULL)
+	{
+		interpolation = new DPSpriteInterpolation(this, player, position);
+	}
+	interpolation->AddRef();
+	GC::WriteBarrier(interpolation);
+	return interpolation;
+}
+
+//==========================================================================
+//
+//
+//
+//==========================================================================
+
+void pspdef_t::UpdateInterpolation(int player)
+{
+	if (interpolation != NULL)
+	{
+		DInterpolation *pointer = interpolation;
+		static_cast<DPSpriteInterpolation *>(pointer)->UpdatePointer(player);
+	}
+}
+
+//==========================================================================
+//
+//
+//
+//==========================================================================
+
+void pspdef_t::StopInterpolation()
+{
+	if (interpolation != NULL)
+	{
+		interpolation->DelRef();
+	}
+}
+
+//==========================================================================
+//
+//
+//
+//==========================================================================
+
+//==========================================================================
+//
+//
+//
+//==========================================================================
 
 ADD_STAT (interpolations)
 {
@@ -951,5 +1146,3 @@ ADD_STAT (interpolations)
 	out.Format ("%d interpolations", interpolator.CountInterpolations ());
 	return out;
 }
-
-
diff --git a/src/version.h b/src/version.h
index 913c9bd181..168cb75191 100644
--- a/src/version.h
+++ b/src/version.h
@@ -76,7 +76,7 @@ const char *GetVersionString();
 
 // Use 4500 as the base git save version, since it's higher than the
 // SVN revision ever got.
-#define SAVEVER 4524
+#define SAVEVER 4525
 
 #define SAVEVERSTRINGIFY2(x) #x
 #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)

From 0fa24ab82d069f5fd44a55d5d307ff36b8642720 Mon Sep 17 00:00:00 2001
From: Leonard <hobbax3@gmail.com>
Date: Mon, 31 Aug 2015 13:04:40 +0200
Subject: [PATCH 02/19] Use barrier_cast instead of static_cast

---
 src/r_data/r_interpolate.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/r_data/r_interpolate.cpp b/src/r_data/r_interpolate.cpp
index 2acbe21403..46ac307892 100644
--- a/src/r_data/r_interpolate.cpp
+++ b/src/r_data/r_interpolate.cpp
@@ -1109,8 +1109,7 @@ void pspdef_t::UpdateInterpolation(int player)
 {
 	if (interpolation != NULL)
 	{
-		DInterpolation *pointer = interpolation;
-		static_cast<DPSpriteInterpolation *>(pointer)->UpdatePointer(player);
+		barrier_cast<DPSpriteInterpolation *>(interpolation)->UpdatePointer(player);
 	}
 }
 

From 143a4c78a9dd630f9d9c2583e56da2b17f31bd21 Mon Sep 17 00:00:00 2001
From: MajorCooke <paul.growney22@gmail.com>
Date: Sun, 6 Sep 2015 19:57:43 -0500
Subject: [PATCH 03/19] - Added A_SetFloatSpeed. - Sets the FloatSpeed of the
 actor/pointer.

---
 src/thingdef/thingdef_codeptr.cpp | 24 +++++++++++++++++++++++-
 wadsrc/static/actors/actor.txt    |  1 +
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp
index 54b816ebb0..62a22532cd 100644
--- a/src/thingdef/thingdef_codeptr.cpp
+++ b/src/thingdef/thingdef_codeptr.cpp
@@ -5071,7 +5071,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DropItem)
 // A_SetSpeed
 //
 //==========================================================================
-
 DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpeed)
 {
 	ACTION_PARAM_START(2);
@@ -5089,6 +5088,28 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpeed)
 	ref->Speed = speed;
 }
 
+//==========================================================================
+//
+// A_SetFloatSpeed
+//
+//==========================================================================
+DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetFloatSpeed)
+{
+	ACTION_PARAM_START(2);
+	ACTION_PARAM_FIXED(speed, 0);
+	ACTION_PARAM_INT(ptr, 1);
+
+	AActor *ref = COPY_AAPTR(self, ptr);
+
+	if (!ref)
+	{
+		ACTION_SET_RESULT(false);
+		return;
+	}
+
+	ref->FloatSpeed = speed;
+}
+
 //===========================================================================
 //
 // Common A_Damage handler
@@ -5823,3 +5844,4 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRipMax)
 	ACTION_PARAM_INT(max, 0);
 	self->RipLevelMax = max;
 }
+
diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt
index f231348d37..5877192cef 100644
--- a/wadsrc/static/actors/actor.txt
+++ b/wadsrc/static/actors/actor.txt
@@ -304,6 +304,7 @@ ACTOR Actor native //: Thinker
 	action native A_SetDamageType(name damagetype);
 	action native A_DropItem(class<Actor> item, int dropamount = -1, int chance = 256);
 	action native A_SetSpeed(float speed, int ptr = AAPTR_DEFAULT);
+	action native A_SetFloatSpeed(float speed, int ptr = AAPTR_DEFAULT);
 	action native A_DamageSelf(int amount, name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
 	action native A_DamageTarget(int amount, name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");
 	action native A_DamageMaster(int amount, name damagetype = "none", int flags = 0, class<Actor> filter = "None", name species = "None");

From 8948f5dc2bcbcf95a207a5e2e695b0f2c8410e93 Mon Sep 17 00:00:00 2001
From: Xaser Acheron <xaser@angryscience.net>
Date: Tue, 8 Sep 2015 10:40:21 -0500
Subject: [PATCH 04/19] Added FPF_NOAUTOAIM to A_FireCustomMissile

---
 src/p_local.h                             | 2 +-
 src/p_mobj.cpp                            | 4 ++--
 src/thingdef/thingdef_codeptr.cpp         | 3 ++-
 wadsrc/static/actors/constants.txt        | 1 +
 wadsrc/static/actors/shared/inventory.txt | 2 +-
 5 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/src/p_local.h b/src/p_local.h
index a2fa00c71a..a8aaaeb0d2 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -153,7 +153,7 @@ AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, const PCl
 AActor *P_SpawnPlayerMissile (AActor* source, const PClass *type);
 AActor *P_SpawnPlayerMissile (AActor *source, const PClass *type, angle_t angle);
 AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z, const PClass *type, angle_t angle, 
-							  AActor **pLineTarget = NULL, AActor **MissileActor = NULL, bool nofreeaim = false);
+							  AActor **pLineTarget = NULL, AActor **MissileActor = NULL, bool nofreeaim = false, bool noautoaim = false);
 
 void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz, bool oldz_has_viewheight=false);
 
diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp
index 267e71bb9a..901372eef5 100644
--- a/src/p_mobj.cpp
+++ b/src/p_mobj.cpp
@@ -5923,7 +5923,7 @@ AActor *P_SpawnPlayerMissile (AActor *source, const PClass *type, angle_t angle)
 
 AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z,
 							  const PClass *type, angle_t angle, AActor **pLineTarget, AActor **pMissileActor,
-							  bool nofreeaim)
+							  bool nofreeaim, bool noautoaim)
 {
 	static const int angdiff[3] = { -1<<26, 1<<26, 0 };
 	angle_t an = angle;
@@ -5936,7 +5936,7 @@ AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z,
 	{
 		return NULL;
 	}
-	if (source->player && source->player->ReadyWeapon && (source->player->ReadyWeapon->WeaponFlags & WIF_NOAUTOAIM))
+	if (source->player && source->player->ReadyWeapon && ((source->player->ReadyWeapon->WeaponFlags & WIF_NOAUTOAIM) || noautoaim))
 	{
 		// Keep exactly the same angle and pitch as the player's own aim
 		an = angle;
diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp
index 62a22532cd..5cc54a247f 100644
--- a/src/thingdef/thingdef_codeptr.cpp
+++ b/src/thingdef/thingdef_codeptr.cpp
@@ -1320,6 +1320,7 @@ enum FP_Flags
 {
 	FPF_AIMATANGLE = 1,
 	FPF_TRANSFERTRANSLATION = 2,
+	FPF_NOAUTOAIM = 4,
 };
 DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile)
 {
@@ -1358,7 +1359,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile)
 		// Temporarily adjusts the pitch
 		fixed_t SavedPlayerPitch = self->pitch;
 		self->pitch -= pitch;
-		AActor * misl=P_SpawnPlayerMissile (self, x, y, z, ti, shootangle, &linetarget);
+		AActor * misl=P_SpawnPlayerMissile (self, x, y, z, ti, shootangle, &linetarget, NULL, false, Flags & FPF_NOAUTOAIM);
 		self->pitch = SavedPlayerPitch;
 
 		// automatic handling of seeker missiles
diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt
index 04ed6f1fc7..b5a8b8cd40 100644
--- a/wadsrc/static/actors/constants.txt
+++ b/wadsrc/static/actors/constants.txt
@@ -188,6 +188,7 @@ const int CPF_STEALARMOR = 32;
 // Flags for A_CustomMissile
 const int FPF_AIMATANGLE = 1;
 const int FPF_TRANSFERTRANSLATION = 2;
+const int FPF_NOAUTOAIM = 4;
 
 // Flags for A_Teleport
 enum
diff --git a/wadsrc/static/actors/shared/inventory.txt b/wadsrc/static/actors/shared/inventory.txt
index 541dd37acd..13ae00936b 100644
--- a/wadsrc/static/actors/shared/inventory.txt
+++ b/wadsrc/static/actors/shared/inventory.txt
@@ -10,7 +10,7 @@ ACTOR Inventory native
 	action native A_JumpIfNoAmmo(state label);
 	action native A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class<Actor> pufftype = "BulletPuff", float range = 0, float lifesteal = 0, int lifestealmax = 0, class<BasicArmorBonus> armorbonustype = "ArmorBonus");
 	action native A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", int flags = 1, float range = 0);
-	action native A_FireCustomMissile(class<Actor> missiletype, float angle = 0, bool useammo = true, int spawnofs_xy = 0, float spawnheight = 0, bool aimatangle = false, float pitch = 0);
+	action native A_FireCustomMissile(class<Actor> missiletype, float angle = 0, bool useammo = true, int spawnofs_xy = 0, float spawnheight = 0, int flags = 0, float pitch = 0);
 	action native A_RailAttack(int damage, int spawnofs_xy = 0, int useammo = true, color color1 = "", color color2 = "", int flags = 0, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class<Actor> spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270);
 	action native A_Light(int extralight);
 	action native A_Light0();

From 19c702a60843c0c2dc41409ae0a9c92b31e30def Mon Sep 17 00:00:00 2001
From: Edoardo Prezioso <edo88@email.it>
Date: Wed, 9 Sep 2015 21:26:44 +0200
Subject: [PATCH 05/19] - Fixed a crash when a player dies in damage floors.

---
 src/p_interaction.cpp | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp
index a0b1ddbc12..603535b7c2 100644
--- a/src/p_interaction.cpp
+++ b/src/p_interaction.cpp
@@ -184,7 +184,6 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf
 	const char *message;
 	const char *messagename;
 	char gendermessage[1024];
-	bool friendly;
 	int  gender;
 
 	// No obituaries for non-players, voodoo dolls or when not wanted
@@ -197,8 +196,6 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf
 	if (inflictor && inflictor->player && inflictor->player->mo != inflictor)
 		MeansOfDeath = NAME_None;
 
-	friendly = (self->player != attacker->player && self->IsTeammate(attacker));
-
 	mod = MeansOfDeath;
 	message = NULL;
 	messagename = NULL;
@@ -266,7 +263,7 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf
 
 	if (message == NULL && attacker != NULL && attacker->player != NULL)
 	{
-		if (friendly)
+		if (self->player != attacker->player && self->IsTeammate(attacker))
 		{
 			self = attacker;
 			gender = self->player->userinfo.GetGender();

From 5afbe8ca007093f7cb6525b5300e4a5436d596ef Mon Sep 17 00:00:00 2001
From: Xaser Acheron <xaser@angryscience.net>
Date: Wed, 9 Sep 2015 18:54:49 -0500
Subject: [PATCH 06/19] Fixed compiler warning for FPF_NOAUTOAIM flag check

---
 src/thingdef/thingdef_codeptr.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp
index 5cc54a247f..dab68867b7 100644
--- a/src/thingdef/thingdef_codeptr.cpp
+++ b/src/thingdef/thingdef_codeptr.cpp
@@ -1359,7 +1359,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile)
 		// Temporarily adjusts the pitch
 		fixed_t SavedPlayerPitch = self->pitch;
 		self->pitch -= pitch;
-		AActor * misl=P_SpawnPlayerMissile (self, x, y, z, ti, shootangle, &linetarget, NULL, false, Flags & FPF_NOAUTOAIM);
+		AActor * misl=P_SpawnPlayerMissile (self, x, y, z, ti, shootangle, &linetarget, NULL, false, (Flags & FPF_NOAUTOAIM) != 0);
 		self->pitch = SavedPlayerPitch;
 
 		// automatic handling of seeker missiles

From 36c7002628cdd73ae09eb0368ab2a9756ebcb529 Mon Sep 17 00:00:00 2001
From: Edward Richardson <Edward850@crantime.org>
Date: Sun, 13 Sep 2015 13:46:02 +1200
Subject: [PATCH 07/19] ACS module error was missing newline

---
 src/p_acs.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/p_acs.cpp b/src/p_acs.cpp
index b703b87dd6..5a25dd5cd6 100644
--- a/src/p_acs.cpp
+++ b/src/p_acs.cpp
@@ -1417,7 +1417,7 @@ FBehavior *FBehavior::StaticLoadModule (int lumpnum, FileReader *fr, int len)
 	else
 	{
 		delete behavior;
-		Printf(TEXTCOLOR_RED "%s: invalid ACS module", Wads.GetLumpFullName(lumpnum));
+		Printf(TEXTCOLOR_RED "%s: invalid ACS module\n", Wads.GetLumpFullName(lumpnum));
 		return NULL;
 	}
 }

From f02b52ef28549a4d35adb122384ca873bdda7e64 Mon Sep 17 00:00:00 2001
From: Braden Obrzut <admin@maniacsvault.net>
Date: Sun, 13 Sep 2015 20:56:20 -0400
Subject: [PATCH 08/19] - Fixed: Initialization ordering warning in
 DPSpriteInterpolation.

---
 src/r_data/r_interpolate.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/r_data/r_interpolate.cpp b/src/r_data/r_interpolate.cpp
index 46ac307892..6c22215203 100644
--- a/src/r_data/r_interpolate.cpp
+++ b/src/r_data/r_interpolate.cpp
@@ -866,11 +866,9 @@ void DPolyobjInterpolation::Serialize(FArchive &arc)
 //==========================================================================
 
 DPSpriteInterpolation::DPSpriteInterpolation(pspdef_t *_psp, int _player, int _position)
-: nfsx(0), nfsy(0), ofsx(0), ofsy(0)
+: psp(_psp), player(_player), position(_position),
+  ofsx(0), ofsy(0), nfsx(0), nfsy(0)
 {
-	psp = _psp;
-	player = _player;
-	position = _position;
 	UpdateInterpolation ();
 	interpolator.AddInterpolation(this);
 }

From d7a04b9e98a14f6e10793505cee877ebf080d081 Mon Sep 17 00:00:00 2001
From: Blue-Shadow <blueshadow_941@yahoo.com>
Date: Mon, 14 Sep 2015 17:22:41 +0300
Subject: [PATCH 09/19] dumpmapthings CCMD: Missing line break after "none".

---
 src/g_doomedmap.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/g_doomedmap.cpp b/src/g_doomedmap.cpp
index 45224329d8..08d5aa2e2f 100644
--- a/src/g_doomedmap.cpp
+++ b/src/g_doomedmap.cpp
@@ -135,7 +135,7 @@ CCMD (dumpmapthings)
 			}
 			else
 			{
-				Printf("%6d none", infos[i]->Key);
+				Printf("%6d none\n", infos[i]->Key);
 			}
 
 		}

From ee7eb3253a70933098cebc2054caea8c22eb02cb Mon Sep 17 00:00:00 2001
From: "alexey.lysiuk" <alexey.lysiuk@gmail.com>
Date: Tue, 15 Sep 2015 16:45:20 +0300
Subject: [PATCH 10/19] Added compatibility flag for point-on-line algorithm

It's possible to use original but buggy implementations of P_PointOnLineSide() and P_PointOnDivlineSide() function
See http://forum.zdoom.org/viewtopic.php?f=2&t=49544
---
 src/compatibility.cpp     |  1 +
 src/d_main.cpp            |  4 +++-
 src/doomdef.h             |  1 +
 src/g_mapinfo.cpp         |  1 +
 src/p_local.h             | 10 ++++++++--
 wadsrc/static/menudef.txt |  1 +
 6 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/src/compatibility.cpp b/src/compatibility.cpp
index d60677f64f..498fefb2a5 100644
--- a/src/compatibility.cpp
+++ b/src/compatibility.cpp
@@ -145,6 +145,7 @@ static FCompatOption Options[] =
 	{ "badangles",				COMPATF2_BADANGLES, SLOT_COMPAT2 },
 	{ "floormove",				COMPATF2_FLOORMOVE, SLOT_COMPAT2 },
 	{ "soundcutoff",			COMPATF2_SOUNDCUTOFF, SLOT_COMPAT2 },
+	{ "pointonline",			COMPATF2_POINTONLINE, SLOT_COMPAT2 },
 
 	{ NULL, 0, 0 }
 };
diff --git a/src/d_main.cpp b/src/d_main.cpp
index 98be13e337..3b3cce1f4f 100644
--- a/src/d_main.cpp
+++ b/src/d_main.cpp
@@ -561,7 +561,7 @@ CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL)
 			COMPATF_TRACE|COMPATF_MISSILECLIP|COMPATF_SOUNDTARGET|COMPATF_NO_PASSMOBJ|COMPATF_LIMITPAIN|
 			COMPATF_DEHHEALTH|COMPATF_INVISIBILITY|COMPATF_CROSSDROPOFF|COMPATF_CORPSEGIBS|COMPATF_HITSCAN|
 			COMPATF_WALLRUN|COMPATF_NOTOSSDROPS|COMPATF_LIGHT|COMPATF_MASKEDMIDTEX;
-		w = COMPATF2_BADANGLES|COMPATF2_FLOORMOVE;
+		w = COMPATF2_BADANGLES|COMPATF2_FLOORMOVE|COMPATF2_POINTONLINE;
 		break;
 
 	case 3: // Boom compat mode
@@ -580,6 +580,7 @@ CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL)
 	case 6:	// Boom with some added settings to reenable some 'broken' behavior
 		v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL|COMPATF_MISSILECLIP|COMPATF_NO_PASSMOBJ|
 			COMPATF_INVISIBILITY|COMPATF_CORPSEGIBS|COMPATF_HITSCAN|COMPATF_WALLRUN|COMPATF_NOTOSSDROPS;
+		w = COMPATF2_POINTONLINE;
 		break;
 
 	}
@@ -622,6 +623,7 @@ CVAR (Flag, compat_maskedmidtex,		compatflags,  COMPATF_MASKEDMIDTEX);
 CVAR (Flag, compat_badangles,			compatflags2, COMPATF2_BADANGLES);
 CVAR (Flag, compat_floormove,			compatflags2, COMPATF2_FLOORMOVE);
 CVAR (Flag, compat_soundcutoff,			compatflags2, COMPATF2_SOUNDCUTOFF);
+CVAR (Flag, compat_pointonline,			compatflags2, COMPATF2_POINTONLINE);
 
 //==========================================================================
 //
diff --git a/src/doomdef.h b/src/doomdef.h
index c8aa66c173..802591386c 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -340,6 +340,7 @@ enum
 	COMPATF2_BADANGLES		= 1 << 0,	// It is impossible to face directly NSEW.
 	COMPATF2_FLOORMOVE		= 1 << 1,	// Use the same floor motion behavior as Doom.
 	COMPATF2_SOUNDCUTOFF	= 1 << 2,	// Cut off sounds when an actor vanishes instead of making it owner-less
+	COMPATF2_POINTONLINE	= 1 << 3,	// Use original but buggy P_PointOnLineSide() and P_PointOnDivlineSide()
 };
 
 // Emulate old bugs for select maps. These are not exposed by a cvar
diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp
index 49493667e7..ac938797d2 100644
--- a/src/g_mapinfo.cpp
+++ b/src/g_mapinfo.cpp
@@ -1333,6 +1333,7 @@ MapFlagHandlers[] =
 	{ "compat_badangles",				MITYPE_COMPATFLAG, 0, COMPATF2_BADANGLES },
 	{ "compat_floormove",				MITYPE_COMPATFLAG, 0, COMPATF2_FLOORMOVE },
 	{ "compat_soundcutoff",				MITYPE_COMPATFLAG, 0, COMPATF2_SOUNDCUTOFF },
+	{ "compat_pointonline",				MITYPE_COMPATFLAG, 0, COMPATF2_POINTONLINE },
 	{ "cd_start_track",					MITYPE_EATNEXT,	0, 0 },
 	{ "cd_end1_track",					MITYPE_EATNEXT,	0, 0 },
 	{ "cd_end2_track",					MITYPE_EATNEXT,	0, 0 },
diff --git a/src/p_local.h b/src/p_local.h
index a8aaaeb0d2..0e06ad72b0 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -240,7 +240,10 @@ fixed_t P_AproxDistance (fixed_t dx, fixed_t dy);
 
 inline int P_PointOnLineSide (fixed_t x, fixed_t y, const line_t *line)
 {
-	return DMulScale32 (y-line->v1->y, line->dx, line->v1->x-x, line->dy) > 0;
+	const SDWORD result = DMulScale32 (y-line->v1->y, line->dx, line->v1->x-x, line->dy);
+	return (compatflags2 & COMPATF2_POINTONLINE)
+		? result >= 0
+		: result > 0;
 }
 
 //==========================================================================
@@ -254,7 +257,10 @@ inline int P_PointOnLineSide (fixed_t x, fixed_t y, const line_t *line)
 
 inline int P_PointOnDivlineSide (fixed_t x, fixed_t y, const divline_t *line)
 {
-	return DMulScale32 (y-line->y, line->dx, line->x-x, line->dy) > 0;
+	const SDWORD result = DMulScale32 (y-line->y, line->dx, line->x-x, line->dy);
+	return (compatflags2 & COMPATF2_POINTONLINE)
+		? result >= 0
+		: result > 0;
 }
 
 //==========================================================================
diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt
index f15f91dff3..b1ca44de7b 100644
--- a/wadsrc/static/menudef.txt
+++ b/wadsrc/static/menudef.txt
@@ -1303,6 +1303,7 @@ OptionMenu "CompatibilityOptions"
 	Option "Find shortest textures like Doom",			"compat_SHORTTEX", "YesNo"
 	Option "Use buggier stair building",				"compat_stairs", "YesNo"
 	Option "Use Doom's floor motion behavior",			"compat_floormove", "YesNo"
+	Option "Use Doom's point-on-line algorithm",		"compat_pointonline", "YesNo"
 	
 	StaticText " "
 	StaticText "Physics Behavior",1

From 39b18a3447c3960c31043dd73ec5f2dbf5e2bcca Mon Sep 17 00:00:00 2001
From: "alexey.lysiuk" <alexey.lysiuk@gmail.com>
Date: Tue, 15 Sep 2015 18:21:05 +0300
Subject: [PATCH 11/19] Improved point-on-line compatibility feature

P_PointOnLineSide() and P_PointOnDivlineSide() functions from the initial Doom source code release are used in compatibility mode
---
 src/p_local.h    | 16 +++++----
 src/p_maputl.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 98 insertions(+), 7 deletions(-)

diff --git a/src/p_local.h b/src/p_local.h
index 0e06ad72b0..cb404eb8cf 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -240,10 +240,11 @@ fixed_t P_AproxDistance (fixed_t dx, fixed_t dy);
 
 inline int P_PointOnLineSide (fixed_t x, fixed_t y, const line_t *line)
 {
-	const SDWORD result = DMulScale32 (y-line->v1->y, line->dx, line->v1->x-x, line->dy);
-	return (compatflags2 & COMPATF2_POINTONLINE)
-		? result >= 0
-		: result > 0;
+	extern int P_VanillaPointOnLineSide(fixed_t x, fixed_t y, const line_t* line);
+
+	return compatflags2 & COMPATF2_POINTONLINE
+		? P_VanillaPointOnLineSide(x, y, line)
+		: DMulScale32 (y-line->v1->y, line->dx, line->v1->x-x, line->dy) > 0;
 }
 
 //==========================================================================
@@ -257,10 +258,11 @@ inline int P_PointOnLineSide (fixed_t x, fixed_t y, const line_t *line)
 
 inline int P_PointOnDivlineSide (fixed_t x, fixed_t y, const divline_t *line)
 {
-	const SDWORD result = DMulScale32 (y-line->y, line->dx, line->x-x, line->dy);
+	extern int P_VanillaPointOnDivlineSide(fixed_t x, fixed_t y, const divline_t* line);
+
 	return (compatflags2 & COMPATF2_POINTONLINE)
-		? result >= 0
-		: result > 0;
+		? P_VanillaPointOnDivlineSide(x, y, line)
+		: (DMulScale32 (y-line->y, line->dx, line->x-x, line->dy) > 0);
 }
 
 //==========================================================================
diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp
index 3a4a4c6a04..0a39460e7d 100644
--- a/src/p_maputl.cpp
+++ b/src/p_maputl.cpp
@@ -1523,3 +1523,92 @@ static AActor *RoughBlockCheck (AActor *mo, int index, void *param)
 	}
 	return NULL;
 }
+
+//===========================================================================
+//
+// P_VanillaPointOnLineSide
+// P_PointOnLineSide() from the initial Doom source code release
+//
+//===========================================================================
+
+int P_VanillaPointOnLineSide(fixed_t x, fixed_t y, const line_t* line)
+{
+	fixed_t	dx;
+	fixed_t	dy;
+	fixed_t	left;
+	fixed_t	right;
+
+	if (!line->dx)
+	{
+		if (x <= line->v1->x)
+			return line->dy > 0;
+
+		return line->dy < 0;
+	}
+	if (!line->dy)
+	{
+		if (y <= line->v1->y)
+			return line->dx < 0;
+
+		return line->dx > 0;
+	}
+
+	dx = (x - line->v1->x);
+	dy = (y - line->v1->y);
+
+	left = FixedMul ( line->dy>>FRACBITS , dx );
+	right = FixedMul ( dy , line->dx>>FRACBITS );
+
+	if (right < left)
+		return 0;		// front side
+	return 1;			// back side
+}
+
+//===========================================================================
+//
+// P_VanillaPointOnDivlineSide
+// P_PointOnDivlineSide() from the initial Doom source code release
+//
+//===========================================================================
+
+int P_VanillaPointOnDivlineSide(fixed_t x, fixed_t y, const divline_t* line)
+{
+	fixed_t	dx;
+	fixed_t	dy;
+	fixed_t	left;
+	fixed_t	right;
+
+	if (!line->dx)
+	{
+		if (x <= line->x)
+			return line->dy > 0;
+
+		return line->dy < 0;
+	}
+	if (!line->dy)
+	{
+		if (y <= line->y)
+			return line->dx < 0;
+
+		return line->dx > 0;
+	}
+
+	dx = (x - line->x);
+	dy = (y - line->y);
+
+	// try to quickly decide by looking at sign bits
+	if ( (line->dy ^ line->dx ^ dx ^ dy)&0x80000000 )
+	{
+		if ( (line->dy ^ dx) & 0x80000000 )
+			return 1;		// (left is negative)
+		return 0;
+	}
+
+	left = FixedMul ( line->dy>>8, dx>>8 );
+	right = FixedMul ( dy>>8 , line->dx>>8 );
+
+	if (right < left)
+		return 0;		// front side
+	return 1;			// back side
+}
+

From fea2cb38cc3caf4a71922faf658c3524a19beccc Mon Sep 17 00:00:00 2001
From: "alexey.lysiuk" <alexey.lysiuk@gmail.com>
Date: Tue, 15 Sep 2015 19:27:05 +0300
Subject: [PATCH 12/19] Fixed compatibility flags comparison for point-on-line

Now it works in both cases: for compatibility mode set by user and for internal compatibility handler
---
 src/p_local.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/p_local.h b/src/p_local.h
index cb404eb8cf..95d7541a8f 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -242,7 +242,7 @@ inline int P_PointOnLineSide (fixed_t x, fixed_t y, const line_t *line)
 {
 	extern int P_VanillaPointOnLineSide(fixed_t x, fixed_t y, const line_t* line);
 
-	return compatflags2 & COMPATF2_POINTONLINE
+	return i_compatflags2 & COMPATF2_POINTONLINE
 		? P_VanillaPointOnLineSide(x, y, line)
 		: DMulScale32 (y-line->v1->y, line->dx, line->v1->x-x, line->dy) > 0;
 }
@@ -260,7 +260,7 @@ inline int P_PointOnDivlineSide (fixed_t x, fixed_t y, const divline_t *line)
 {
 	extern int P_VanillaPointOnDivlineSide(fixed_t x, fixed_t y, const divline_t* line);
 
-	return (compatflags2 & COMPATF2_POINTONLINE)
+	return (i_compatflags2 & COMPATF2_POINTONLINE)
 		? P_VanillaPointOnDivlineSide(x, y, line)
 		: (DMulScale32 (y-line->y, line->dx, line->x-x, line->dy) > 0);
 }

From 66437e32f6dec75e5692475ed737547d626bf1e4 Mon Sep 17 00:00:00 2001
From: "alexey.lysiuk" <alexey.lysiuk@gmail.com>
Date: Tue, 15 Sep 2015 19:29:43 +0300
Subject: [PATCH 13/19] Added compatibility setting for Return to Hadron E1M9

See http://forum.zdoom.org/viewtopic.php?f=2&t=49544
---
 wadsrc/static/compatibility.txt | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt
index 6cbe36af47..799168f759 100644
--- a/wadsrc/static/compatibility.txt
+++ b/wadsrc/static/compatibility.txt
@@ -401,3 +401,8 @@ D0139194F7817BF06F3988DFC47DB38D // Whispers of Satan map29
 {
 	nopassover
 }
+
+D7F6E9F08C39A17026349A04F8C0B0BE // Return to Hadron, e1m9
+{
+	pointonline
+}

From f4b637db626412dcc3890689fcedb9b2aaeef490 Mon Sep 17 00:00:00 2001
From: "alexey.lysiuk" <alexey.lysiuk@gmail.com>
Date: Tue, 15 Sep 2015 19:30:32 +0300
Subject: [PATCH 14/19] Changed compatibility fix for Nuke Mine E1M2

http://forum.zdoom.org/viewtopic.php?f=7&t=34013
---
 wadsrc/static/compatibility.txt | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt
index 799168f759..3c41f871f6 100644
--- a/wadsrc/static/compatibility.txt
+++ b/wadsrc/static/compatibility.txt
@@ -320,8 +320,7 @@ F481922F4881F74760F3C0437FD5EDD0 // map03
 
 7C1913DEE396BA26CFF22A0E9369B7D2 // Nuke Mine, e1m2
 {
-	clearlinespecial 1107
-	clearlinespecial 1108
+	pointonline
 }
 
 5B862477519B21B30059A466F2FF6460 // Khorus, map08

From 6ee0672885b5856899efc6214d3ea203b28f7ac9 Mon Sep 17 00:00:00 2001
From: "alexey.lysiuk" <alexey.lysiuk@gmail.com>
Date: Wed, 16 Sep 2015 13:36:18 +0300
Subject: [PATCH 15/19] Fixed missing hit sound for Heretic weapon Dragon Claw

See http://forum.zdoom.org/viewtopic.php?f=2&t=49459
---
 wadsrc/static/actors/heretic/hereticweaps.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/wadsrc/static/actors/heretic/hereticweaps.txt b/wadsrc/static/actors/heretic/hereticweaps.txt
index 711c3fd292..f0db7caf2d 100644
--- a/wadsrc/static/actors/heretic/hereticweaps.txt
+++ b/wadsrc/static/actors/heretic/hereticweaps.txt
@@ -802,6 +802,7 @@ ACTOR BlasterPuff
 	+NOGRAVITY
 	+PUFFONACTORS
 	RenderStyle Add
+	SeeSound "weapons/blasterhit"
 	States
 	{
 	Crash:

From b2fa4970fd57773f5f3353fa64af6a3480177009 Mon Sep 17 00:00:00 2001
From: "alexey.lysiuk" <alexey.lysiuk@gmail.com>
Date: Wed, 16 Sep 2015 16:13:56 +0300
Subject: [PATCH 16/19] Fixed potential crash in ACS engine

Unknown p-code in compiled script may lead to a crash if the current module was changed during script execution, e.g. by function call
See http://forum.zdoom.org/viewtopic.php?f=2&t=48524
---
 src/p_acs.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/p_acs.cpp b/src/p_acs.cpp
index b85ae28e16..f4d148d09a 100644
--- a/src/p_acs.cpp
+++ b/src/p_acs.cpp
@@ -6032,6 +6032,7 @@ int DLevelScript::RunScript ()
 	int sp = 0;
 	int *pc = this->pc;
 	ACSFormat fmt = activeBehavior->GetFormat();
+	FBehavior* const savedActiveBehavior = activeBehavior;
 	unsigned int runaway = 0;	// used to prevent infinite loops
 	int pcd;
 	FString work;
@@ -6065,6 +6066,7 @@ int DLevelScript::RunScript ()
 		{
 		default:
 			Printf ("Unknown P-Code %d in %s\n", pcd, ScriptPresentation(script).GetChars());
+			activeBehavior = savedActiveBehavior;
 			// fall through
 		case PCD_TERMINATE:
 			DPrintf ("%s finished\n", ScriptPresentation(script).GetChars());

From 924a2aaaa7e12bf1ddb3fa1991735a4fe1be1e96 Mon Sep 17 00:00:00 2001
From: "alexey.lysiuk" <alexey.lysiuk@gmail.com>
Date: Wed, 16 Sep 2015 16:56:43 +0300
Subject: [PATCH 17/19] Added "support" for PCD_CONSOLECOMMAND in ACS

Now attempt to execute a console command from a script will not terminate its execution
An error message will be issued in the console on every such attempt
---
 src/p_acs.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/p_acs.cpp b/src/p_acs.cpp
index f4d148d09a..63ab717175 100644
--- a/src/p_acs.cpp
+++ b/src/p_acs.cpp
@@ -75,6 +75,7 @@
 #include "actorptrselect.h"
 #include "farchive.h"
 #include "decallib.h"
+#include "version.h"
 
 #include "g_shared/a_pickups.h"
 
@@ -9357,6 +9358,10 @@ scriptwait:
 			}
 			break;
 
+		case PCD_CONSOLECOMMAND:
+			Printf (TEXTCOLOR_RED GAMENAME " doesn't support execution of console commands from scripts\n");
+			sp -= 3;
+			break;
  		}
  	}
 

From 4de57cd2967236a31b8206aec2a04c026a8c2b87 Mon Sep 17 00:00:00 2001
From: "alexey.lysiuk" <alexey.lysiuk@gmail.com>
Date: Thu, 17 Sep 2015 10:14:54 +0300
Subject: [PATCH 18/19] Fixed compatibility issues on MAP25 of Eternal Doom

See http://forum.zdoom.org/viewtopic.php?f=2&t=49577
---
 wadsrc/static/compatibility.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt
index 3c41f871f6..1bd031ed8e 100644
--- a/wadsrc/static/compatibility.txt
+++ b/wadsrc/static/compatibility.txt
@@ -55,6 +55,8 @@ A80E7EE40E0D0C76A6FBD242BE29FE27 // map15
 {
 	stairs
 	maskedmidtex
+	corpsegibs
+	vileghosts
 }
 
 10E1E2B36302D31AC4AE68C84B5DC457 // Eternal Doom MAP28
@@ -125,7 +127,6 @@ BA530202AF0BA0C6CBAE6A0C7076FB72 // Requiem map04
 CBDFEFAC579A62DE8F1B48CA4A09D381 // gather2.wad map05 and darkside.wad map01
 C7A2FAFB0AFB2632C50AD625CDB50E51 // Reverie map18
 9E5724BC6135AA6F86EE54FD4D91F1E2 // Project X map14
-6DA6FCBA8089161BDEC6A1D3F6C8D60F // Eternal Doom map25
 01899825FFEAE016D39C02A7DA4B218F // Archie map01
 1D9F3AFDC2517C2E450491ED13896712 // Seej map01
 0AE745A3AB86D15FB2FB74489962C421 // 6pack2 map02

From 621116a289d6066889eefd02693b60117795429d Mon Sep 17 00:00:00 2001
From: "alexey.lysiuk" <alexey.lysiuk@gmail.com>
Date: Fri, 18 Sep 2015 10:53:46 +0300
Subject: [PATCH 19/19] Disabled loading of SDL output plugin for FMOD Ex on OS
 X

Long path to executable file corrupts stack inside FMOD library
This plugin is not being built for OS X, output through CoreAudio works just fine
---
 src/sound/fmodsound.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp
index 8433b301b0..33ca0495dd 100644
--- a/src/sound/fmodsound.cpp
+++ b/src/sound/fmodsound.cpp
@@ -771,7 +771,7 @@ bool FMODSoundRenderer::Init()
 	}
 #endif
 
-#ifndef _WIN32
+#if !defined _WIN32 && !defined __APPLE__
 	// Try to load SDL output plugin
 	result = Sys->setPluginPath(progdir);	// Should we really look for it in the program directory?
 	result = Sys->loadPlugin("liboutput_sdl.so", &OutputPlugin);