From 49120f59d45708281a0ac74b3165948c36a30c28 Mon Sep 17 00:00:00 2001
From: Randy Heit <rheit@zdoom.fake>
Date: Tue, 16 Dec 2008 01:23:44 +0000
Subject: [PATCH] - Added Karate Chris's patch to optionally specify an angle
 offset for   summoning. - Added Karate Chris's fix for Serpent Staff
 vampirism on teammates. - Locks and teleporters now take precedence over
 one-sidedness for automap   coloring.

SVN r1317 (trunk)
---
 docs/rh-log.txt               |   5 ++
 src/am_map.cpp                | 116 +++++++++++++++++-----------------
 src/d_net.cpp                 |  15 ++++-
 src/d_protocol.h              |   3 +
 src/g_hexen/a_clericstaff.cpp |   4 +-
 src/info.cpp                  |  42 ++++--------
 src/version.h                 |   4 +-
 7 files changed, 94 insertions(+), 95 deletions(-)

diff --git a/docs/rh-log.txt b/docs/rh-log.txt
index 8bdec4224..416d9afab 100644
--- a/docs/rh-log.txt
+++ b/docs/rh-log.txt
@@ -1,4 +1,9 @@
 December 15, 2008
+- Added Karate Chris's patch to optionally specify an angle offset for
+  summoning.
+- Added Karate Chris's fix for Serpent Staff vampirism on teammates.
+- Locks and teleporters now take precedence over one-sidedness for automap
+  coloring.
 - Increased maximum number of per-pattern rows for the XM loader from
   256 to 1024 to deal with a module that otherwise would not load.
 - Removed the artificial restriction on not supporting Vorbis-compressed
diff --git a/src/am_map.cpp b/src/am_map.cpp
index a537fc5dd..29f42b006 100644
--- a/src/am_map.cpp
+++ b/src/am_map.cpp
@@ -1377,77 +1377,75 @@ void AM_drawWalls (bool allmap)
 				// map secret sectors like Boom
 				AM_drawMline(&l, SecretSectorColor);
 			}
-			else if (!lines[i].backsector)
-			{
-				AM_drawMline(&l, WallColor);
+			else if (lines[i].flags & ML_SECRET)
+			{ // secret door
+				if (am_cheat != 0 && lines[i].backsector != NULL)
+					AM_drawMline(&l, SecretWallColor);
+			    else
+					AM_drawMline(&l, WallColor);
 			}
-			else
-			{
-				if (lines[i].flags & ML_SECRET)
-				{ // secret door
-					if (am_cheat != 0)
-						AM_drawMline(&l, SecretWallColor);
-				    else
-						AM_drawMline(&l, WallColor);
-				}
-				else if ((lines[i].special == Teleport ||
-					lines[i].special == Teleport_NoFog ||
-					lines[i].special == Teleport_ZombieChanger ||
-					lines[i].special == Teleport_Line) &&
-					(lines[i].activation & SPAC_PlayerActivate) &&
+			else if ((lines[i].special == Teleport ||
+				lines[i].special == Teleport_NoFog ||
+				lines[i].special == Teleport_ZombieChanger ||
+				lines[i].special == Teleport_Line) &&
+				(lines[i].activation & SPAC_PlayerActivate) &&
+				am_colorset == 0)
+			{ // intra-level teleporters
+				AM_drawMline(&l, IntraTeleportColor);
+			}
+			else if ((lines[i].special == Teleport_NewMap ||
+					 lines[i].special == Teleport_EndGame ||
+					 lines[i].special == Exit_Normal ||
+					 lines[i].special == Exit_Secret) &&
 					am_colorset == 0)
-				{ // intra-level teleporters
-					AM_drawMline(&l, IntraTeleportColor);
-				}
-				else if ((lines[i].special == Teleport_NewMap ||
-						 lines[i].special == Teleport_EndGame ||
-						 lines[i].special == Exit_Normal ||
-						 lines[i].special == Exit_Secret) &&
-						am_colorset == 0)
-				{ // inter-level/game-ending teleporters
-					AM_drawMline(&l, InterTeleportColor);
-				}
-				else if (lines[i].special == Door_LockedRaise ||
-						 lines[i].special == ACS_LockedExecute ||
-						 lines[i].special == ACS_LockedExecuteDoor ||
-						 (lines[i].special == Generic_Door && lines[i].args[4]!=0))
+			{ // inter-level/game-ending teleporters
+				AM_drawMline(&l, InterTeleportColor);
+			}
+			else if (lines[i].special == Door_LockedRaise ||
+					 lines[i].special == ACS_LockedExecute ||
+					 lines[i].special == ACS_LockedExecuteDoor ||
+					 (lines[i].special == Generic_Door && lines[i].args[4] !=0 ))
+			{
+				if (am_colorset == 0)
 				{
-					if (am_colorset == 0)
-					{
-						int P_GetMapColorForLock(int lock);
-						int lock;
+					int P_GetMapColorForLock(int lock);
+					int lock;
 
+					if (lines[i].special==Door_LockedRaise) lock=lines[i].args[3];
+					else lock=lines[i].args[4];
 
-						if (lines[i].special==Door_LockedRaise) lock=lines[i].args[3];
-						else lock=lines[i].args[4];
+					int color = P_GetMapColorForLock(lock);
 
-						int color = P_GetMapColorForLock(lock);
+					AMColor c;
 
-						AMColor c;
+					if (color >= 0)	c.FromRGB(RPART(color), GPART(color), BPART(color));
+					else c = LockedColor;
 
-						if (color >= 0)	c.FromRGB(RPART(color), GPART(color), BPART(color));
-						else c = LockedColor;
-
-						AM_drawMline (&l, c);
-					}
-					else
-						AM_drawMline (&l, LockedColor);  // locked special
+					AM_drawMline (&l, c);
 				}
-				else if (lines[i].backsector->floorplane
-					  != lines[i].frontsector->floorplane)
+				else
 				{
-					AM_drawMline(&l, FDWallColor); // floor level change
-				}
-				else if (lines[i].backsector->ceilingplane
-					  != lines[i].frontsector->ceilingplane)
-				{
-					AM_drawMline(&l, CDWallColor); // ceiling level change
-				}
-				else if (am_cheat != 0)
-				{
-					AM_drawMline(&l, TSWallColor);
+					AM_drawMline (&l, LockedColor);  // locked special
 				}
 			}
+			else if (lines[i].backsector == NULL)
+			{
+				AM_drawMline(&l, WallColor);	// one-sided wall
+			}
+			else if (lines[i].backsector->floorplane
+				  != lines[i].frontsector->floorplane)
+			{
+				AM_drawMline(&l, FDWallColor); // floor level change
+			}
+			else if (lines[i].backsector->ceilingplane
+				  != lines[i].frontsector->ceilingplane)
+			{
+				AM_drawMline(&l, CDWallColor); // ceiling level change
+			}
+			else if (am_cheat != 0)
+			{
+				AM_drawMline(&l, TSWallColor);
+			}
 		}
 		else if (allmap)
 		{
diff --git a/src/d_net.cpp b/src/d_net.cpp
index d7ad9e623..3da985425 100644
--- a/src/d_net.cpp
+++ b/src/d_net.cpp
@@ -2113,6 +2113,9 @@ void Net_DoCommand (int type, BYTE **stream, int player)
 	case DEM_SUMMON:
 	case DEM_SUMMONFRIEND:
 	case DEM_SUMMONFOE:
+	case DEM_SUMMON2:
+	case DEM_SUMMONFRIEND2:
+	case DEM_SUMMONFOE2:
 		{
 			const PClass *typeinfo;
 
@@ -2136,7 +2139,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
 							source->z + 8 * FRACUNIT, ALLOW_REPLACE);
 						if (spawned != NULL)
 						{
-							if (type == DEM_SUMMONFRIEND)
+							if (type == DEM_SUMMONFRIEND || type == DEM_SUMMONFRIEND2)
 							{
 								if (spawned->CountsAsKill()) 
 								{
@@ -2146,12 +2149,17 @@ void Net_DoCommand (int type, BYTE **stream, int player)
 								spawned->flags |= MF_FRIENDLY;
 								spawned->LastHeard = players[player].mo;
 							}
-							else if (type == DEM_SUMMONFOE)
+							else if (type == DEM_SUMMONFOE || type == DEM_SUMMONFOE2)
 							{
 								spawned->FriendPlayer = 0;
 								spawned->flags &= ~MF_FRIENDLY;
 							}
 						}
+						if (type >= DEM_SUMMON2 && type <= DEM_SUMMONFOE2)
+						{
+							int angle = ReadWord(stream);
+							spawned->angle = source->angle - (ANGLE_1 * angle);
+						}
 					}
 				}
 			}
@@ -2383,6 +2391,9 @@ void Net_SkipCommand (int type, BYTE **stream)
 
 		case DEM_GIVECHEAT:
 		case DEM_TAKECHEAT:
+		case DEM_SUMMON2:
+		case DEM_SUMMONFRIEND2:
+		case DEM_SUMMONFOE2:
 			skip = strlen ((char *)(*stream)) + 3;
 			break;
 
diff --git a/src/d_protocol.h b/src/d_protocol.h
index 6edfdaad1..cf268c746 100644
--- a/src/d_protocol.h
+++ b/src/d_protocol.h
@@ -148,6 +148,9 @@ enum EDemoCommand
 	DEM_DELCONTROLLER,	// 49 Player to remove from the controller list.
 	DEM_KILLCLASSCHEAT,	// 50 String: Class to kill.
 	DEM_CONVERSATION,	// 51 Make conversations work.
+	DEM_SUMMON2,		// 52 String: Thing to fabricate, WORD: angle offset
+	DEM_SUMMONFRIEND2,	// 53
+	DEM_SUMMONFOE2,		// 54
 };
 
 // The following are implemented by cht_DoCheat in m_cheat.cpp
diff --git a/src/g_hexen/a_clericstaff.cpp b/src/g_hexen/a_clericstaff.cpp
index 09067aaf7..781578c0c 100644
--- a/src/g_hexen/a_clericstaff.cpp
+++ b/src/g_hexen/a_clericstaff.cpp
@@ -72,7 +72,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
 			P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, PClass::FindClass ("CStaffPuff"));
 			pmo->angle = R_PointToAngle2 (pmo->x, pmo->y, 
 				linetarget->x, linetarget->y);
-			if ((linetarget->player || linetarget->flags3&MF3_ISMONSTER)
+			if (((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0))|| linetarget->flags3&MF3_ISMONSTER)
 				&& (!(linetarget->flags2&(MF2_DORMANT+MF2_INVULNERABLE))))
 			{
 				newLife = player->health+(damage>>3);
@@ -96,7 +96,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
 			P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, PClass::FindClass ("CStaffPuff"));
 			pmo->angle = R_PointToAngle2 (pmo->x, pmo->y, 
 				linetarget->x, linetarget->y);
-			if (linetarget->player || linetarget->flags3&MF3_ISMONSTER)
+			if ((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0)) || linetarget->flags3&MF3_ISMONSTER)
 			{
 				newLife = player->health+(damage>>4);
 				newLife = newLife > 100 ? 100 : newLife;
diff --git a/src/info.cpp b/src/info.cpp
index 93f9502c2..4cac243bf 100644
--- a/src/info.cpp
+++ b/src/info.cpp
@@ -371,7 +371,7 @@ CCMD (dumpmapthings)
 
 bool CheckCheatmode ();
 
-CCMD (summon)
+static void SummonActor (int command, int command2, FCommandLine argv)
 {
 	if (CheckCheatmode ())
 		return;
@@ -384,43 +384,25 @@ CCMD (summon)
 			Printf ("Unknown class '%s'\n", argv[1]);
 			return;
 		}
-		Net_WriteByte (DEM_SUMMON);
+		Net_WriteByte (argv.argc() > 2 ? command2 : command);
 		Net_WriteString (type->TypeName.GetChars());
+
+		if (argv.argc () > 2)
+			Net_WriteWord (atoi (argv[2]));
 	}
 }
 
+CCMD (summon)
+{
+	SummonActor (DEM_SUMMON, DEM_SUMMON2, argv);
+}
+
 CCMD (summonfriend)
 {
-	if (CheckCheatmode ())
-		return;
-
-	if (argv.argc() > 1)
-	{
-		const PClass *type = PClass::FindClass (argv[1]);
-		if (type == NULL)
-		{
-			Printf ("Unknown class '%s'\n", argv[1]);
-			return;
-		}
-		Net_WriteByte (DEM_SUMMONFRIEND);
-		Net_WriteString (type->TypeName.GetChars());
-	}
+	SummonActor (DEM_SUMMONFRIEND, DEM_SUMMONFRIEND2, argv);
 }
 
 CCMD (summonfoe)
 {
-	if (CheckCheatmode ())
-		return;
-
-	if (argv.argc() > 1)
-	{
-		const PClass *type = PClass::FindClass (argv[1]);
-		if (type == NULL)
-		{
-			Printf ("Unknown class '%s'\n", argv[1]);
-			return;
-		}
-		Net_WriteByte (DEM_SUMMONFOE);
-		Net_WriteString (type->TypeName.GetChars());
-	}
+	SummonActor (DEM_SUMMONFOE, DEM_SUMMONFOE2, argv);
 }
diff --git a/src/version.h b/src/version.h
index 28ebf9d4c..58ff63a7a 100644
--- a/src/version.h
+++ b/src/version.h
@@ -54,7 +54,7 @@
 // Version identifier for network games.
 // Bump it every time you do a release unless you're certain you
 // didn't change anything that will affect sync.
-#define NETGAMEVERSION 217
+#define NETGAMEVERSION 218
 
 // Version stored in the ini's [LastRun] section.
 // Bump it if you made some configuration change that you want to
@@ -64,7 +64,7 @@
 // Protocol version used in demos.
 // Bump it if you change existing DEM_ commands or add new ones.
 // Otherwise, it should be safe to leave it alone.
-#define DEMOGAMEVERSION 0x20D
+#define DEMOGAMEVERSION 0x20E
 
 // Minimum demo version we can play.
 // Bump it whenever you change or remove existing DEM_ commands.