From 9a8a446840b1a028446c757079b812ed077e2a6b Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@zdoom.fake>
Date: Sun, 19 Sep 2010 08:27:20 +0000
Subject: [PATCH] - added player class definition through the GAMEINFO section
 in MAPINFO. Also added a NOMENU flag that can be set for a player class. This
 means that the use of KEYCONF is now deprecated except for its original
 purpose: To define mod specific key binding options.

SVN r2832 (trunk)
---
 src/actor.h                          |  1 +
 src/gi.cpp                           |  1 +
 src/gi.h                             |  1 +
 src/p_user.cpp                       | 78 +++++++++++++---------------
 src/thingdef/thingdef_data.cpp       |  1 +
 wadsrc/static/mapinfo/chex.txt       |  1 +
 wadsrc/static/mapinfo/doomcommon.txt |  1 +
 wadsrc/static/mapinfo/heretic.txt    |  1 +
 wadsrc/static/mapinfo/hexen.txt      |  1 +
 wadsrc/static/mapinfo/strife.txt     |  1 +
 10 files changed, 44 insertions(+), 43 deletions(-)

diff --git a/src/actor.h b/src/actor.h
index 7de8a725e7..e089de96ac 100644
--- a/src/actor.h
+++ b/src/actor.h
@@ -323,6 +323,7 @@ enum
 	MF6_BLOCKEDBYSOLIDACTORS = 0x00080000, // Blocked by solid actors, even if not solid itself
 	MF6_ADDITIVEPOISONDAMAGE	= 0x00100000,
 	MF6_ADDITIVEPOISONDURATION	= 0x00200000,
+	MF6_NOMENU			= 0x00400000,	// Player class should not appear in the class selection menu.
 
 // --- mobj.renderflags ---
 
diff --git a/src/gi.cpp b/src/gi.cpp
index 190d2b0311..0a3f51dbb5 100644
--- a/src/gi.cpp
+++ b/src/gi.cpp
@@ -250,6 +250,7 @@ void FMapInfoParser::ParseGameInfo()
 		// Insert valid keys here.
 		GAMEINFOKEY_CSTRING(titlePage, "titlePage", 8)
 		GAMEINFOKEY_STRINGARRAY(creditPages, "creditPage", 8)
+		GAMEINFOKEY_STRINGARRAY(PlayerClasses, "playerclasses", 0)
 		GAMEINFOKEY_STRING(titleMusic, "titleMusic")
 		GAMEINFOKEY_FLOAT(titleTime, "titleTime")
 		GAMEINFOKEY_FLOAT(advisoryTime, "advisoryTime")
diff --git a/src/gi.h b/src/gi.h
index ef9777553c..df50060a9a 100644
--- a/src/gi.h
+++ b/src/gi.h
@@ -79,6 +79,7 @@ struct gameinfo_t
 	TArray<FName> finalePages;
 	TArray<FName> infoPages;
 	TArray<FName> DefaultWeaponSlots[10];
+	TArray<FName> PlayerClasses;
 
 	FString titleMusic;
 	float titleTime;
diff --git a/src/p_user.cpp b/src/p_user.cpp
index eef4f5025f..3fecc380f8 100644
--- a/src/p_user.cpp
+++ b/src/p_user.cpp
@@ -95,40 +95,43 @@ bool FPlayerClass::CheckSkin (int skin)
 	return false;
 }
 
+bool ValidatePlayerClass(const PClass *ti, const char *name)
+{
+	if (!ti)
+	{
+		Printf ("Unknown player class '%s'\n", name);
+		return false;
+	}
+	else if (!ti->IsDescendantOf (RUNTIME_CLASS (APlayerPawn)))
+	{
+		Printf ("Invalid player class '%s'\n", name);
+		return false;
+	}
+	else if (ti->Meta.GetMetaString (APMETA_DisplayName) == NULL)
+	{
+		Printf ("Missing displayname for player class '%s'\n", name);
+		return false;
+	}
+	return true;
+}
+
 void SetupPlayerClasses ()
 {
 	FPlayerClass newclass;
 
-	newclass.Flags = 0;
+	for (unsigned i=0; i<gameinfo.PlayerClasses.Size(); i++)
+	{
+		newclass.Flags = 0;
+		newclass.Type = PClass::FindClass(gameinfo.PlayerClasses[i]);
 
-	if (gameinfo.gametype == GAME_Doom)
-	{
-		newclass.Type = PClass::FindClass (NAME_DoomPlayer);
-		PlayerClasses.Push (newclass);
-	}
-	else if (gameinfo.gametype == GAME_Heretic)
-	{
-		newclass.Type = PClass::FindClass (NAME_HereticPlayer);
-		PlayerClasses.Push (newclass);
-	}
-	else if (gameinfo.gametype == GAME_Hexen)
-	{
-		newclass.Type = PClass::FindClass (NAME_FighterPlayer);
-		PlayerClasses.Push (newclass);
-		newclass.Type = PClass::FindClass (NAME_ClericPlayer);
-		PlayerClasses.Push (newclass);
-		newclass.Type = PClass::FindClass (NAME_MagePlayer);
-		PlayerClasses.Push (newclass);
-	}
-	else if (gameinfo.gametype == GAME_Strife)
-	{
-		newclass.Type = PClass::FindClass (NAME_StrifePlayer);
-		PlayerClasses.Push (newclass);
-	}
-	else if (gameinfo.gametype == GAME_Chex)
-	{
-		newclass.Type = PClass::FindClass (NAME_ChexPlayer);
-		PlayerClasses.Push (newclass);
+		if (ValidatePlayerClass(newclass.Type, gameinfo.PlayerClasses[i]))
+		{
+			if ((GetDefaultByType(newclass.Type)->flags6 & MF6_NOMENU))
+			{
+				newclass.Flags |= PCF_NOMENU;
+			}
+			PlayerClasses.Push (newclass);
+		}
 	}
 }
 
@@ -146,19 +149,7 @@ CCMD (addplayerclass)
 	{
 		const PClass *ti = PClass::FindClass (argv[1]);
 
-		if (!ti)
-		{
-			Printf ("Unknown player class '%s'\n", argv[1]);
-		}
-		else if (!ti->IsDescendantOf (RUNTIME_CLASS (APlayerPawn)))
-		{
-			Printf ("Invalid player class '%s'\n", argv[1]);
-		}
-		else if (ti->Meta.GetMetaString (APMETA_DisplayName) == NULL)
-		{
-			Printf ("Missing displayname for player class '%s'\n", argv[1]);
-		}
-		else
+		if (ValidatePlayerClass(ti, argv[1]))
 		{
 			FPlayerClass newclass;
 
@@ -189,7 +180,8 @@ CCMD (playerclasses)
 {
 	for (unsigned int i = 0; i < PlayerClasses.Size (); i++)
 	{
-		Printf ("% 3d %s\n", i,
+		Printf ("%3d: Class = %s, Name = %s\n", i,
+			PlayerClasses[i].Type->TypeName.GetChars(),
 			PlayerClasses[i].Type->Meta.GetMetaString (APMETA_DisplayName));
 	}
 }
diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp
index 05e5bc3a7f..54de97aa86 100644
--- a/src/thingdef/thingdef_data.cpp
+++ b/src/thingdef/thingdef_data.cpp
@@ -228,6 +228,7 @@ static FFlagDef ActorFlags[]=
 	DEFINE_FLAG(MF6, ADDITIVEPOISONDAMAGE, AActor, flags6),
 	DEFINE_FLAG(MF6, ADDITIVEPOISONDURATION, AActor, flags6),
 	DEFINE_FLAG(MF6, BLOCKEDBYSOLIDACTORS, AActor, flags6),
+	DEFINE_FLAG(MF6, NOMENU, AActor, flags6),
 
 	// Effect flags
 	DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
diff --git a/wadsrc/static/mapinfo/chex.txt b/wadsrc/static/mapinfo/chex.txt
index 4692776813..0dac3e7c99 100644
--- a/wadsrc/static/mapinfo/chex.txt
+++ b/wadsrc/static/mapinfo/chex.txt
@@ -52,6 +52,7 @@ gameinfo
 	menufontcolor_highlight = "BLUE"
 	menufontcolor_selection = "GOLD"
 	menubackbutton = "M_BACK_H"
+	playerclasses = "ChexPlayer"
 }
 
 skill baby
diff --git a/wadsrc/static/mapinfo/doomcommon.txt b/wadsrc/static/mapinfo/doomcommon.txt
index 9fd4b96379..2a103d6a9f 100644
--- a/wadsrc/static/mapinfo/doomcommon.txt
+++ b/wadsrc/static/mapinfo/doomcommon.txt
@@ -52,6 +52,7 @@ gameinfo
 	menufontcolor_highlight = "YELLOW"
 	menufontcolor_selection = "BRICK"
 	menubackbutton = "M_BACK_D"
+	playerclasses = "DoomPlayer"
 }
 
 skill baby
diff --git a/wadsrc/static/mapinfo/heretic.txt b/wadsrc/static/mapinfo/heretic.txt
index b9f88e2b92..e6876ab2cc 100644
--- a/wadsrc/static/mapinfo/heretic.txt
+++ b/wadsrc/static/mapinfo/heretic.txt
@@ -51,6 +51,7 @@ gameinfo
 	menufontcolor_highlight = "YELLOW"
 	menufontcolor_selection = "DARKGREEN"
 	menubackbutton = "M_BACK_H"
+	playerclasses = "HereticPlayer"
 }
 
 skill baby
diff --git a/wadsrc/static/mapinfo/hexen.txt b/wadsrc/static/mapinfo/hexen.txt
index 8f0962a50e..46682b56f3 100644
--- a/wadsrc/static/mapinfo/hexen.txt
+++ b/wadsrc/static/mapinfo/hexen.txt
@@ -49,6 +49,7 @@ gameinfo
 	menufontcolor_highlight = "YELLOW"
 	menufontcolor_selection = "BRICK"
 	menubackbutton = "M_BACK_X"
+	PlayerClasses = "FighterPlayer", "ClericPlayer", "MagePlayer"
 }
 
 skill baby
diff --git a/wadsrc/static/mapinfo/strife.txt b/wadsrc/static/mapinfo/strife.txt
index ffb70e6966..edfe798e64 100644
--- a/wadsrc/static/mapinfo/strife.txt
+++ b/wadsrc/static/mapinfo/strife.txt
@@ -52,6 +52,7 @@ gameinfo
 	menufontcolor_highlight = "GREEN"
 	menufontcolor_selection = "GOLD"
 	menubackbutton = "M_BACK_S"
+	PlayerClasses = "StrifePlayer"
 }
 
 skill baby