From 0569d948dfd18041d707acdfb4c68b8e5fb2be37 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@zdoom.fake>
Date: Sun, 7 Mar 2010 09:13:41 +0000
Subject: [PATCH] - added a 'player.clearcolorset' property so that inherited
 color sets can be removed. - fixed: Player color sets were not inheritable.

SVN r2202 (trunk)
---
 src/d_player.h                       | 12 ---------
 src/dobjtype.cpp                     |  6 +++++
 src/info.cpp                         | 19 ++++++++++++++
 src/info.h                           | 19 ++++++++++++--
 src/p_user.cpp                       | 38 ++++++++--------------------
 src/thingdef/thingdef.cpp            |  6 +++++
 src/thingdef/thingdef_properties.cpp | 29 ++++++++++++++++-----
 7 files changed, 80 insertions(+), 49 deletions(-)

diff --git a/src/d_player.h b/src/d_player.h
index 64d901329..2c77872e8 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -71,18 +71,6 @@ enum
 	APMETA_Slot9,
 };
 
-// Standard pre-defined skin colors
-struct FPlayerColorSet
-{
-	FName Name;			// Name of this color
-
-	int Lump;			// Lump to read the translation from, otherwise use next 2 fields
-	BYTE FirstColor, LastColor;		// Describes the range of colors to use for the translation
-
-	BYTE RepresentativeColor;		// A palette entry representative of this translation,
-									// for map arrows and status bar backgrounds and such
-};
-void P_AddPlayerColorSet(FName classname, int setnum, const FPlayerColorSet *colorset);
 FPlayerColorSet *P_GetPlayerColorSet(FName classname, int setnum);
 void P_EnumPlayerColorSets(FName classname, TArray<int> *out);
 
diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp
index 63d4a8423..b2622d1db 100644
--- a/src/dobjtype.cpp
+++ b/src/dobjtype.cpp
@@ -141,6 +141,11 @@ void PClass::StaticFreeData (PClass *type)
 			delete type->ActorInfo->PainChances;
 			type->ActorInfo->PainChances = NULL;
 		}
+		if (type->ActorInfo->ColorSets != NULL)
+		{
+			delete type->ActorInfo->ColorSets;
+			type->ActorInfo->ColorSets = NULL;
+		}
 		delete type->ActorInfo;
 		type->ActorInfo = NULL;
 	}
@@ -311,6 +316,7 @@ PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
 		info->StateList = NULL;
 		info->DamageFactors = NULL;
 		info->PainChances = NULL;
+		info->ColorSets = NULL;
 		m_RuntimeActors.Push (type);
 	}
 	return type;
diff --git a/src/info.cpp b/src/info.cpp
index 89628e5b7..c3e5ac63e 100644
--- a/src/info.cpp
+++ b/src/info.cpp
@@ -309,6 +309,25 @@ void FActorInfo::SetPainChance(FName type, int chance)
 //
 //==========================================================================
 
+void FActorInfo::SetColorSet(int index, const FPlayerColorSet *set)
+{
+	if (set != NULL) 
+	{
+		if (ColorSets == NULL) ColorSets = new FPlayerColorSetMap;
+		ColorSets->Insert(index, *set);
+	}
+	else 
+	{
+		if (ColorSets != NULL) 
+			ColorSets->Remove(index);
+	}
+}
+
+//==========================================================================
+//
+//
+//==========================================================================
+
 FDoomEdMap DoomEdMap;
 
 FDoomEdMap::FDoomEdEntry *FDoomEdMap::DoomEdHash[DOOMED_HASHSIZE];
diff --git a/src/info.h b/src/info.h
index da248b9ce..82de9486c 100644
--- a/src/info.h
+++ b/src/info.h
@@ -145,8 +145,21 @@ FArchive &operator<< (FArchive &arc, FState *&state);
 
 #include "gametype.h"
 
+// Standard pre-defined skin colors
+struct FPlayerColorSet
+{
+	FName Name;			// Name of this color
+
+	int Lump;			// Lump to read the translation from, otherwise use next 2 fields
+	BYTE FirstColor, LastColor;		// Describes the range of colors to use for the translation
+
+	BYTE RepresentativeColor;		// A palette entry representative of this translation,
+									// for map arrows and status bar backgrounds and such
+};
+
 typedef TMap<FName, fixed_t> DmgFactors;
 typedef TMap<FName, BYTE> PainChanceList;
+typedef TMap<int, FPlayerColorSet> FPlayerColorSetMap;
 
 struct FActorInfo
 {
@@ -158,6 +171,7 @@ struct FActorInfo
 	void RegisterIDs ();
 	void SetDamageFactor(FName type, fixed_t factor);
 	void SetPainChance(FName type, int chance);
+	void SetColorSet(int index, const FPlayerColorSet *set);
 
 	FState *FindState (int numnames, FName *names, bool exact=false) const;
 	FState *FindStateByString(const char *name, bool exact=false);
@@ -177,9 +191,10 @@ struct FActorInfo
 	BYTE GameFilter;
 	BYTE SpawnID;
 	SWORD DoomEdNum;
-	FStateLabels * StateList;
+	FStateLabels *StateList;
 	DmgFactors *DamageFactors;
-	PainChanceList * PainChances;
+	PainChanceList *PainChances;
+	FPlayerColorSetMap *ColorSets;
 };
 
 class FDoomEdMap
diff --git a/src/p_user.cpp b/src/p_user.cpp
index 78e6eeb2e..ec80954b4 100644
--- a/src/p_user.cpp
+++ b/src/p_user.cpp
@@ -55,10 +55,6 @@
 
 static FRandom pr_skullpop ("SkullPop");
 
-// Color set class name -> mapping table
-typedef TMap<int, FPlayerColorSet> FPlayerColorSetMap;
-TMap<FName, FPlayerColorSetMap *> PlayerToColorsMap;
-
 // [RH] # of ticks to complete a turn180
 #define TURN180_TICKS	((TICRATE / 4) + 1)
 
@@ -2635,39 +2631,25 @@ void player_t::Serialize (FArchive &arc)
 }
 
 
-static FPlayerColorSetMap *GetPlayerColors(FName classname, bool create)
+static FPlayerColorSetMap *GetPlayerColors(FName classname)
 {
-	FPlayerColorSetMap *map, **value;
+	const PClass *cls = PClass::FindClass(classname);
 
-	value = PlayerToColorsMap.CheckKey(classname);
-	if (value == NULL)
+	if (cls != NULL)
 	{
-		if (create)
+		FActorInfo *inf = cls->ActorInfo;
+
+		if (inf != NULL)
 		{
-			map = new FPlayerColorSetMap;
-			PlayerToColorsMap.Insert(classname, map);
-		}
-		else
-		{
-			map = NULL;
+			return inf->ColorSets;
 		}
 	}
-	else
-	{
-		map = *value;
-	}
-	return map;
-}
-
-void P_AddPlayerColorSet(FName classname, int setnum, const FPlayerColorSet *colorset)
-{
-	FPlayerColorSetMap *map = GetPlayerColors(classname, true);
-	(*map)[setnum] = *colorset;
+	return NULL;
 }
 
 FPlayerColorSet *P_GetPlayerColorSet(FName classname, int setnum)
 {
-	FPlayerColorSetMap *map = GetPlayerColors(classname, false);
+	FPlayerColorSetMap *map = GetPlayerColors(classname);
 	if (map == NULL)
 	{
 		return NULL;
@@ -2683,7 +2665,7 @@ static int STACK_ARGS intcmp(const void *a, const void *b)
 void P_EnumPlayerColorSets(FName classname, TArray<int> *out)
 {
 	out->Clear();
-	FPlayerColorSetMap *map = GetPlayerColors(classname, false);
+	FPlayerColorSetMap *map = GetPlayerColors(classname);
 	if (map != NULL)
 	{
 		FPlayerColorSetMap::Iterator it(*map);
diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp
index 5dcab6c60..6362c62fe 100644
--- a/src/thingdef/thingdef.cpp
+++ b/src/thingdef/thingdef.cpp
@@ -159,6 +159,12 @@ FActorInfo *CreateNewActor(const FScriptPosition &sc, FName typeName, FName pare
 		info->PainChances = new PainChanceList;
 		*info->PainChances = *parent->ActorInfo->PainChances;
 	}
+	if (parent->ActorInfo->ColorSets != NULL)
+	{
+		// copy color sets from parent
+		info->ColorSets = new FPlayerColorSetMap;
+		*info->ColorSets = *parent->ActorInfo->ColorSets;
+	}
 	info->Replacee = info->Replacement = NULL;
 	info->DoomEdNum = -1;
 	return info;
diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp
index 5a8bfe0f5..0c2a8c96d 100644
--- a/src/thingdef/thingdef_properties.cpp
+++ b/src/thingdef/thingdef_properties.cpp
@@ -358,8 +358,7 @@ DEFINE_PROPERTY(painchance, ZI, Actor)
 		if (!stricmp(str, "Normal")) painType = NAME_None;
 		else painType=str;
 
-		if (info->PainChances == NULL) info->PainChances=new PainChanceList;
-		(*info->PainChances)[painType] = (BYTE)id;
+		info->SetPainChance(painType, id);
 	}
 }
 
@@ -953,13 +952,11 @@ DEFINE_PROPERTY(damagefactor, ZF, Actor)
 	}
 	else
 	{
-		if (info->DamageFactors == NULL) info->DamageFactors=new DmgFactors;
-
 		FName dmgType;
 		if (!stricmp(str, "Normal")) dmgType = NAME_None;
 		else dmgType=str;
 
-		(*info->DamageFactors)[dmgType]=id;
+		info->SetDamageFactor(dmgType, id);
 	}
 }
 
@@ -1884,7 +1881,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, colorset, ISIII, PlayerPawn)
 	}
 	else
 	{
-		P_AddPlayerColorSet(info->Class->TypeName, setnum, &color);
+		info->SetColorSet(setnum, &color);
 	}
 }
 
@@ -1908,9 +1905,27 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, colorsetfile, ISSI, PlayerPawn)
 	}
 	else if (color.Lump >= 0)
 	{
-		P_AddPlayerColorSet(info->Class->TypeName, setnum, &color);
+		info->SetColorSet(setnum, &color);
 	}
 }
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_CLASS_PROPERTY_PREFIX(player, clearcolorset, I, PlayerPawn)
+{
+	PROP_INT_PARM(setnum, 0);
+
+	if (setnum < 0)
+	{
+		bag.ScriptPosition.Message(MSG_WARNING, "Color set number must not be negative.\n");
+	}
+	else
+	{
+		info->SetColorSet(setnum, NULL);
+	}
+}
+
 //==========================================================================
 //
 //==========================================================================