From cfe6c15098623059881658aeae72f6e70314e5be Mon Sep 17 00:00:00 2001
From: Rudolf Polzer <divverent@alientrap.org>
Date: Fri, 22 Oct 2010 15:46:06 +0200
Subject: [PATCH] mapinfo: recode of game type specification, new keyword
 "gametype" replaces old "type" (old maps stay supported)

---
 qcsrc/client/csqc_builtins.qc |   1 +
 qcsrc/common/mapinfo.qc       | 149 ++++++++++++++++++++++++++++++++--
 2 files changed, 145 insertions(+), 5 deletions(-)

diff --git a/qcsrc/client/csqc_builtins.qc b/qcsrc/client/csqc_builtins.qc
index 760197a27..32c048f25 100644
--- a/qcsrc/client/csqc_builtins.qc
+++ b/qcsrc/client/csqc_builtins.qc
@@ -236,6 +236,7 @@ float (string s)	tokenize = #441;
 string (float argnum)	argv = #442;
 
 string (string s) cvar_string = #448;
+string (string s) cvar_defstring = #482;
 
 float ()						buf_create = #460;
 void (float bufhandle)					buf_del = #461;
diff --git a/qcsrc/common/mapinfo.qc b/qcsrc/common/mapinfo.qc
index 835c58f64..1dd1244a8 100644
--- a/qcsrc/common/mapinfo.qc
+++ b/qcsrc/common/mapinfo.qc
@@ -388,7 +388,7 @@ void _MapInfo_Map_Reset()
 	MapInfo_Map_maxs = '0 0 0';
 }
 
-string MapInfo_GetDefault(float t)
+string _MapInfo_GetDefault(float t)
 {
 	switch(t)
 	{
@@ -418,7 +418,7 @@ void _MapInfo_Map_ApplyGametype(string s, float pWantedType, float pThisType, fl
 		return;
 
 	if(load_default)
-		_MapInfo_Map_ApplyGametype(MapInfo_GetDefault(pThisType), pWantedType, pThisType, FALSE);
+		_MapInfo_Map_ApplyGametype(_MapInfo_GetDefault(pThisType), pWantedType, pThisType, FALSE);
 	
 	if(pWantedType == MAPINFO_TYPE_ASSAULT || pWantedType == MAPINFO_TYPE_ONSLAUGHT || pWantedType == MAPINFO_TYPE_RACE || pWantedType == MAPINFO_TYPE_CTS) // these modes don't use fraglimit
 	{
@@ -508,6 +508,132 @@ void _MapInfo_Map_ApplyGametype(string s, float pWantedType, float pThisType, fl
 	}
 }
 
+string _MapInfo_GetDefaultEx(float t)
+{
+	switch(t)
+	{
+		case MAPINFO_TYPE_DEATHMATCH:      return "timelimit=20 pointlimit=30";
+		case MAPINFO_TYPE_TEAM_DEATHMATCH: return "timelimit=20 pointlimit=50 teams=2";
+		case MAPINFO_TYPE_DOMINATION:      return "timelimit=20 pointlimit=200 teams=2";
+		case MAPINFO_TYPE_CTF:             return "timelimit=20 pointlimit=300 caplimit=10";
+		case MAPINFO_TYPE_RUNEMATCH:       return "timelimit=20 pointlimit=200";
+		case MAPINFO_TYPE_LMS:             return "timelimit=20 lives=9";
+		case MAPINFO_TYPE_ARENA:           return "timelimit=20 pointlimit=10";
+		case MAPINFO_TYPE_CA:              return "timelimit=20 pointlimit=10";
+		case MAPINFO_TYPE_KEYHUNT:         return "timelimit=20 pointlimit=1000 teams=3";
+		case MAPINFO_TYPE_ASSAULT:         return "timelimit=20";
+		case MAPINFO_TYPE_RACE:            return "timelimit=20 qualifying_timelimit=5 laplimit=7 teamlaplimit=15";
+		case MAPINFO_TYPE_ONSLAUGHT:       return "timelimit=20";
+		case MAPINFO_TYPE_NEXBALL:         return "timelimit=20 pointlimit=5";
+		case MAPINFO_TYPE_CTS:             return "timelimit=20";
+		default:                           return "";
+	}
+}
+
+void _MapInfo_Map_ApplyGametypeEx(string s, float pWantedType, float pThisType)
+{
+	string sa, k, v, spre;
+	float p;
+	string fraglimit_normal;
+	string fraglimit_caps;
+	string fraglimit_teams;
+
+	MapInfo_Map_supportedGametypes |= pThisType;
+	if(!(pThisType & pWantedType))
+		return;
+
+	// reset all the cvars to their defaults
+
+	cvar_set("timelimit", cvar_defstring("timelimit"));
+	cvar_set("leadlimit", cvar_defstring("leadlimit"));
+	cvar_set("fraglimit", cvar_defstring("fraglimit"));
+	cvar_set("g_tdm_teams", cvar_defstring("g_tdm_teams"));
+	cvar_set("g_keyhunt_teams", cvar_defstring("g_keyhunt_teams"));
+	cvar_set("g_domination_default_teams", cvar_defstring("g_domination_default_teams"));
+	cvar_set("g_race_qualifying_timelimit", cvar_defstring("g_race_qualifying_timelimit"));
+
+	fraglimit_normal = string_null;
+	fraglimit_caps = string_null;
+	fraglimit_teams = string_null;
+
+	s = strcat(_MapInfo_GetDefaultEx(pWantedType), " ", s);
+	while(s != "")
+	{
+		sa = car(s);
+		s = cdr(s);
+
+		if(sa == "")
+			continue;
+
+		p = strstrofs(sa, "=", 0);
+		if(p < 0)
+		{
+			k = "timelimit";
+			v = s;
+		}
+		else
+		{
+			k = substring(sa, 0, p);
+			v = substring(sa, p+1, -1);
+		}
+
+		if(k == "timelimit")
+		{
+			cvar_set("timelimit", v);
+		}
+		else if(k == "leadlimit")
+		{
+			cvar_set("leadlimit", v);
+		}
+		else if(k == "pointlimit" || k == "fraglimit" || k == "lives" || k == "laplimit")
+		{
+			fraglimit_normal = v;
+		}
+		else if(k == "caplimit")
+		{
+			fraglimit_caps = v;
+		}
+		else if(k == "teampointlimit" || k == "teamlaplimit")
+		{
+			fraglimit_teams = v;
+		}
+		else if(k == "teams")
+		{
+			cvar_set("g_tdm_teams", v);
+			cvar_set("g_keyhunt_teams", v);
+			cvar_set("g_domination_default_teams", v);
+		}
+		else if(k == "qualifying_timelimit")
+		{
+			cvar_set("g_race_qualifying_timelimit", v);
+		}
+		else if(k == "skill")
+		{
+			// ignore
+		}
+		else
+		{
+			print("Invalid gametype key in mapinfo: ", k, "\n");
+		}
+	}
+
+	if(pWantedType == MAPINFO_TYPE_CTF && cvar("g_ctf_win_mode") < 2)
+	{
+		if(fraglimit_caps)
+			cvar_set("fraglimit", fraglimit_caps);
+	}
+	else if(pWantedType == MAPINFO_TYPE_RACE && cvar("g_race_teams") >= 2)
+	{
+		if(fraglimit_teams)
+			cvar_set("fraglimit", fraglimit_teams);
+	}
+	else
+	{
+		if(fraglimit_normal)
+			cvar_set("fraglimit", fraglimit_normal);
+	}
+}
+
 float MapInfo_Type_FromString(string t)
 {
 	if     (t == "dm")      return MAPINFO_TYPE_DEATHMATCH;
@@ -654,7 +780,7 @@ float MapInfo_Get_ByName(string pFilename, float pAllowGenerate, float pGametype
 	string fn;
 	string s, t;
 	float fh, fh2;
-	float r, f, n, i;
+	float r, f, n, i, p;
 	string acl;
 
 	acl = MAPINFO_SETTEMP_ACL_USER;
@@ -720,7 +846,7 @@ float MapInfo_Get_ByName(string pFilename, float pAllowGenerate, float pGametype
 
 		for(i = 1; i <= MapInfo_Map_supportedGametypes; i *= 2)
 			if(MapInfo_Map_supportedGametypes & i)
-				fputs(fh, sprintf("type %s %s\n", MapInfo_Type_ToString(i), MapInfo_GetDefault(i)));
+				fputs(fh, sprintf("gametype %s\n", MapInfo_Type_ToString(i), " // ", _MapInfo_GetDefaultEx(i)));
 
 		fh2 = fopen(strcat("scripts/", pFilename, ".arena"), FILE_READ);
 		if(fh2 >= 0)
@@ -759,6 +885,10 @@ float MapInfo_Get_ByName(string pFilename, float pAllowGenerate, float pGametype
 		if(substring(s, 0, 1) == "_")  // q3map style
 			continue;
 
+		p = strstrofs(s, "//", 0);
+		if(p >= 0)
+			s = substring(s, 0, p);
+
 		t = car(s); s = cdr(s);
 		if(t == "title")
 			MapInfo_Map_title = s;
@@ -794,6 +924,15 @@ float MapInfo_Get_ByName(string pFilename, float pAllowGenerate, float pGametype
 			else
 				dprint("Map ", pFilename, " supports unknown game type ", t, ", ignored\n");
 		}
+		else if(t == "gametype")
+		{
+			t = car(s); s = cdr(s);
+			f = MapInfo_Type_FromString(t);
+			if(f)
+				_MapInfo_Map_ApplyGametypeEx (s, pGametypeToSet, f);
+			else
+				dprint("Map ", pFilename, " supports unknown game type ", t, ", ignored\n");
+		}
 		else if(t == "size")
 		{
 			float a, b, c, d, e;
@@ -884,7 +1023,7 @@ float MapInfo_Get_ByName(string pFilename, float pAllowGenerate, float pGametype
 		if(!(MapInfo_Map_supportedGametypes & pGametypeToSet))
 		{
 			print("Can't select the requested game type. Trying anyway with stupid settings.\n");
-			_MapInfo_Map_ApplyGametype(MapInfo_GetDefault(MAPINFO_TYPE_DEATHMATCH), pGametypeToSet, MAPINFO_TYPE_DEATHMATCH, FALSE);
+			_MapInfo_Map_ApplyGametypeEx("", pGametypeToSet, MAPINFO_TYPE_DEATHMATCH);
 		}
 	}
 
-- 
2.39.5