From 6a00173a12033cf7c6542ceace1b096eebb09c4e Mon Sep 17 00:00:00 2001
From: Randy Heit <rheit@zdoom.fake>
Date: Sun, 9 Dec 2007 03:40:02 +0000
Subject: [PATCH] - Fixed: SECSPAC_EyesSurface and SECSPAC_EyesDive did not
 trigger due to   crouching motion. - Fixed: The keypress for nightmare mode
 verification appeared in the console   if the fullscreen console was open
 while using the menu. - Added support for scaling down large console fonts in
 the customize   controls menu. - Fixed: Joining a negative team was possible.

SVN r590 (trunk)
---
 docs/rh-log.txt   |  7 +++++++
 src/d_netinfo.cpp |  4 ++++
 src/m_menu.cpp    | 25 +++++++++++++++++++++----
 src/m_options.cpp | 43 +++++++++++++++++++++++--------------------
 src/p_local.h     |  2 +-
 src/p_mobj.cpp    |  7 +++++--
 src/p_user.cpp    |  4 ++++
 src/v_text.cpp    | 27 ++++++++++++++++++++++++++-
 src/v_video.h     |  4 ++++
 9 files changed, 95 insertions(+), 28 deletions(-)

diff --git a/docs/rh-log.txt b/docs/rh-log.txt
index fadc85964..c5daa2696 100644
--- a/docs/rh-log.txt
+++ b/docs/rh-log.txt
@@ -1,4 +1,11 @@
 December 8, 2007
+- Fixed: SECSPAC_EyesSurface and SECSPAC_EyesDive did not trigger due to
+  crouching motion.
+- Fixed: The keypress for nightmare mode verification appeared in the console
+  if the fullscreen console was open while using the menu.
+- Added support for scaling down large console fonts in the customize
+  controls menu.
+- Fixed: Joining a negative team was possible.
 - Fixed: Skill level confirmation only worked with Doom. Also fixed parsing
   of MustConfirm: It looked for TK_String when it should have used TK_StringConst.
 - Fixed: When travelling to a new non-hub map, any items being carried with
diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp
index c567d517d..73900547b 100644
--- a/src/d_netinfo.cpp
+++ b/src/d_netinfo.cpp
@@ -250,6 +250,10 @@ static void UpdateTeam (int pnum, int team, bool update)
 	userinfo_t *info = &players[pnum].userinfo;
 	int oldteam;
 
+	if (team < 0)
+	{
+		team = TEAM_None;
+	}
 	oldteam = info->team;
 	info->team = team;
 
diff --git a/src/m_menu.cpp b/src/m_menu.cpp
index 623d66f15..cf36154a8 100644
--- a/src/m_menu.cpp
+++ b/src/m_menu.cpp
@@ -1733,7 +1733,7 @@ void M_VerifyNightmare (int ch)
 	{
 		gamestate = GS_HIDECONSOLE;
 		gameaction = ga_newgame;
-	} 
+	}
 	M_ClearMenus ();
 }
 
@@ -2716,6 +2716,10 @@ bool M_Responder (event_t *ev)
 			}
 			return true;
 		}
+		else if (ev->subtype == EV_GUI_Char && messageToPrint && messageNeedsInput)
+		{
+			ch = ev->data1;
+		}
 	}
 	
 	if (OptionsActive && !chatmodeon)
@@ -2763,10 +2767,23 @@ bool M_Responder (event_t *ev)
 	if (messageToPrint)
 	{
 		ch = tolower (ch);
-		if (messageNeedsInput &&
-			ch != ' ' && ch != 'n' && ch != 'y' && ch != GK_ESCAPE)
+		if (messageNeedsInput)
 		{
-			return false;
+			// For each printable keystroke, both EV_GUI_KeyDown and
+			// EV_GUI_Char will be generated, in that order. If we close
+			// the menu after the first event arrives and the fullscreen
+			// console is up, the console will get the EV_GUI_Char event
+			// next. Therefore, the message input should only respond to
+			// EV_GUI_Char events (sans Escape, which only generates
+			// EV_GUI_KeyDown.)
+			if (ev->subtype != EV_GUI_Char && ch != GK_ESCAPE)
+			{
+				return false;
+			}
+			if (ch != ' ' && ch != 'n' && ch != 'y' && ch != GK_ESCAPE)
+			{
+				return false;
+			}
 		}
 
 		menuactive = messageLastMenuActive;
diff --git a/src/m_options.cpp b/src/m_options.cpp
index c5bb87027..3102c09b1 100644
--- a/src/m_options.cpp
+++ b/src/m_options.cpp
@@ -1358,6 +1358,22 @@ CCMD (sizeup)
 	S_Sound (CHAN_VOICE, "menu/change", 1, ATTN_NONE);
 }
 
+// Draws a string in the console font, scaled to the 8x8 cells
+// used by the default console font.
+static void M_DrawConText (int color, int x, int y, const char *str)
+{
+	int len = (int)strlen(str);
+
+	screen->SetFont (ConFont);
+	x = (x - 160) * CleanXfac + screen->GetWidth() / 2;
+	y = (y - 100) * CleanYfac + screen->GetHeight() / 2;
+	screen->DrawText (color, x, y, str,
+		DTA_CellX, 8 * CleanXfac,
+		DTA_CellY, 8 * CleanYfac,
+		TAG_DONE);
+	screen->SetFont (SmallFont);
+}
+
 void M_BuildKeyList (menuitem_t *item, int numitems)
 {
 	int i;
@@ -1426,10 +1442,8 @@ void M_DrawSlider (int x, int y, float min, float max, float cur)
 
 	cur -= min;
 
-	screen->SetFont (ConFont);
-	screen->DrawText (CR_WHITE, x, y, "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12", DTA_Clean, true, TAG_DONE);
-	screen->DrawText (CR_ORANGE, x + 5 + (int)((cur * 78.f) / range), y, "\x13", DTA_Clean, true, TAG_DONE);
-	screen->SetFont (SmallFont);
+	M_DrawConText(CR_WHITE, x, y, "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12");
+	M_DrawConText(CR_ORANGE, x + 5 + (int)((cur * 78.f) / range), y, "\x13");
 }
 
 int M_FindCurVal (float cur, value_t *values, int numvals)
@@ -1676,10 +1690,7 @@ void M_OptDrawer ()
 				char description[64];
 
 				C_NameKeys (description, item->b.key1, item->c.key2);
-				screen->SetFont (ConFont);
-				screen->DrawText (CR_WHITE,
-					CurrentMenu->indent + 14, y-1+labelofs, description, DTA_Clean, true, TAG_DONE);
-				screen->SetFont (SmallFont);
+				M_DrawConText(CR_WHITE, CurrentMenu->indent + 14, y-1+labelofs, description);
 			}
 			break;
 
@@ -1768,10 +1779,7 @@ void M_OptDrawer ()
 				i == CurrentItem &&
 				(skullAnimCounter < 6 || menuactive == MENU_WaitKey))
 			{
-				screen->SetFont (ConFont);
-				screen->DrawText (CR_RED, CurrentMenu->indent + 3, y-1+labelofs, "\xd",
-					DTA_Clean, true, TAG_DONE);
-				screen->SetFont (SmallFont);
+				M_DrawConText(CR_RED, CurrentMenu->indent + 3, y-1+labelofs, "\xd");
 			}
 		}
 		else
@@ -1799,10 +1807,7 @@ void M_OptDrawer ()
 
 			if (i == CurrentItem && ((item->a.selmode != -1 && (skullAnimCounter < 6 || menuactive == MENU_WaitKey)) || testingmode))
 			{
-				screen->SetFont (ConFont);
-				screen->DrawText (CR_RED, item->a.selmode * 104 + 8, y-1 + labelofs, "\xd",
-					DTA_Clean, true, TAG_DONE);
-				screen->SetFont (SmallFont);
+				M_DrawConText(CR_RED, item->a.selmode * 104 + 8, y-1 + labelofs, "\xd");
 			}
 		}
 	}
@@ -1811,16 +1816,14 @@ void M_OptDrawer ()
 	CanScrollDown = (i < CurrentMenu->numitems);
 	VisBottom = i - 1;
 
-	screen->SetFont (ConFont);
 	if (CanScrollUp)
 	{
-		screen->DrawText (CR_ORANGE, 3, ytop + labelofs, "\x1a", DTA_Clean, true, TAG_DONE);
+		M_DrawConText(CR_ORANGE, 3, ytop + labelofs, "\x1a");
 	}
 	if (CanScrollDown)
 	{
-		screen->DrawText (CR_ORANGE, 3, y - 8 + labelofs, "\x1b", DTA_Clean, true, TAG_DONE);
+		M_DrawConText(CR_ORANGE, 3, y - 8 + labelofs, "\x1b");
 	}
-	screen->SetFont (SmallFont);
 
 	if (flagsvar)
 	{
diff --git a/src/p_local.h b/src/p_local.h
index 1b9316d27..2250a4e01 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -117,7 +117,7 @@ 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);
 
-void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz);
+void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz, bool oldz_has_viewheight=false);
 
 //
 // [RH] P_THINGS
diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp
index 82da04689..3876221ba 100644
--- a/src/p_mobj.cpp
+++ b/src/p_mobj.cpp
@@ -2058,7 +2058,7 @@ void P_ZMovement (AActor *mo)
 	P_CheckFakeFloorTriggers (mo, oldz);
 }
 
-void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz)
+void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz, bool oldz_has_viewheight)
 {
 	if (mo->player && (mo->player->cheats & CF_PREDICTING))
 	{
@@ -2092,7 +2092,10 @@ void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz)
 		}
 
 		newz = mo->z + viewheight;
-		oldz += viewheight;
+		if (!oldz_has_viewheight)
+		{
+			oldz += viewheight;
+		}
 
 		if (oldz <= waterz && newz > waterz)
 		{ // View went above fake floor
diff --git a/src/p_user.cpp b/src/p_user.cpp
index 23c06f1f9..af2fa56f2 100644
--- a/src/p_user.cpp
+++ b/src/p_user.cpp
@@ -1833,6 +1833,7 @@ void P_CrouchMove(player_t * player, int direction)
 	fixed_t defaultheight = player->mo->GetDefault()->height;
 	fixed_t savedheight = player->mo->height;
 	fixed_t crouchspeed = direction * CROUCHSPEED;
+	fixed_t oldheight = player->viewheight;
 
 	player->crouchdir = (signed char) direction;
 	player->crouchfactor += crouchspeed;
@@ -1854,6 +1855,9 @@ void P_CrouchMove(player_t * player, int direction)
 	player->crouchfactor = clamp<fixed_t>(player->crouchfactor, FRACUNIT/2, FRACUNIT);
 	player->viewheight = FixedMul(player->mo->ViewHeight, player->crouchfactor);
 	player->crouchviewdelta = player->viewheight - player->mo->ViewHeight;
+
+	// Check for eyes going above/below fake floor due to crouching motion.
+	P_CheckFakeFloorTriggers(player->mo, player->mo->z + oldheight, true);
 }
 
 //----------------------------------------------------------------------------
diff --git a/src/v_text.cpp b/src/v_text.cpp
index c4f526310..a4bebc773 100644
--- a/src/v_text.cpp
+++ b/src/v_text.cpp
@@ -98,6 +98,7 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st
 	int			boldcolor;
 	const BYTE *range;
 	int			height;
+	int			forcedwidth = 0;
 	int			scalex, scaley;
 	int			kerning;
 	FTexture *pic;
@@ -147,12 +148,14 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st
 #endif
 			break;
 
+		// We don't handle these. :(
 		case DTA_DestWidth:
 		case DTA_DestHeight:
 			*(DWORD *)tags = TAG_IGNORE;
 			data = va_arg (tags, DWORD);
 			break;
 
+		// Translation is specified explicitly by the text.
 		case DTA_Translation:
 			*(DWORD *)tags = TAG_IGNORE;
 			ptrval = va_arg (tags, void*);
@@ -186,6 +189,14 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st
 		case DTA_TextLen:
 			maxstrlen = va_arg (tags, int);
 			break;
+
+		case DTA_CellX:
+			forcedwidth = va_arg (tags, int);
+			break;
+
+		case DTA_CellY:
+			height = va_arg (tags, int);
+			break;
 		}
 		tag = va_arg (tags, DWORD);
 	}
@@ -219,7 +230,21 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st
 		{
 			va_list taglist;
 			va_start (taglist, string);
-			DrawTexture (pic, cx, cy, DTA_Translation, range, TAG_MORE, &taglist);
+			if (forcedwidth)
+			{
+				w = forcedwidth;
+				DrawTexture (pic, cx, cy,
+					DTA_Translation, range,
+					DTA_DestWidth, forcedwidth,
+					DTA_DestHeight, height,
+					TAG_MORE, &taglist);
+			}
+			else
+			{
+				DrawTexture (pic, cx, cy,
+					DTA_Translation, range,
+					TAG_MORE, &taglist);
+			}
 			va_end (taglist);
 		}
 		cx += (w + kerning) * scalex;
diff --git a/src/v_video.h b/src/v_video.h
index a9079b3d1..f97f13804 100644
--- a/src/v_video.h
+++ b/src/v_video.h
@@ -102,6 +102,10 @@ enum
 	DTA_KeepRatio,		// doesn't adjust screen size for DTA_Virtual* if the aspect ratio is not 4:3
 	DTA_TextLen,		// for DrawText: stop after this many characters, even if \0 not hit
 	DTA_RenderStyle,	// same as render style for actors
+
+	// For DrawText calls:
+	DTA_CellX,			// horizontal size of character cell
+	DTA_CellY,			// vertical size of character cell
 };
 
 enum