class XGCharacterGenerator extends Actor
	dependson(X2StrategyGameRulesetDataStructures) config(NameList);

// American
var localized array<string> m_arrAmMFirstNames;
var localized array<string> m_arrAmFFirstNames;
var localized array<string> m_arrAmLastNames;
// Arab
var localized array<string> m_arrAbMFirstNames;
var localized array<string> m_arrAbFFirstNames;
var localized array<string> m_arrAbLastNames;
// Israel
var localized array<string> m_arrIsMFirstNames;
var localized array<string> m_arrIsFFirstNames;
var localized array<string> m_arrIsLastNames;
// Russia
var localized array<string> m_arrRsMFirstNames;
var localized array<string> m_arrRsFFirstNames;
var localized array<string> m_arrRsMLastNames;
var localized array<string> m_arrRsFLastnames;
// England
var localized array<string> m_arrEnMFirstNames;
var localized array<string> m_arrEnFFirstNames;
var localized array<string> m_arrEnLastNames;
// French
var localized array<string> m_arrFrMFirstNames;
var localized array<string> m_arrFrFFirstNames;
var localized array<string> m_arrFrLastNames;
// African
var localized array<string> m_arrAfMFirstNames;
var localized array<string> m_arrAfFFirstNames;
var localized array<string> m_arrAfLastNames;
// Japanese
var localized array<string> m_arrJpMFirstNames;
var localized array<string> m_arrJpFFirstNames;
var localized array<string> m_arrJpLastNames;
// Chinese
var localized array<string> m_arrChMFirstNames;
var localized array<string> m_arrChFFirstNames;
var localized array<string> m_arrChLastNames;
// Indian
var localized array<string> m_arrInMFirstNames;
var localized array<string> m_arrInFFirstNames;
var localized array<string> m_arrInLastNames;
// German
var localized array<string> m_arrGmMFirstNames;
var localized array<string> m_arrGmFFirstNames;
var localized array<string> m_arrGmLastNames;
// Italian
var localized array<string> m_arrItMFirstNames;
var localized array<string> m_arrItFFirstNames;
var localized array<string> m_arrItLastNames;
// Mexican
var localized array<string> m_arrMxMFirstNames;
var localized array<string> m_arrMxFFirstNames;
var localized array<string> m_arrMxLastNames;
// Australian
var localized array<string> m_arrAuMFirstNames;
var localized array<string> m_arrAuFFirstNames;
var localized array<string> m_arrAuLastNames;
// Spanish
var localized array<string> m_arrEsMFirstNames;
var localized array<string> m_arrEsFFirstNames;
var localized array<string> m_arrEsLastNames;
// Greece
var localized array<string> m_arrGrMFirstNames;
var localized array<string> m_arrGrFFirstNames;
var localized array<string> m_arrGrLastNames;
// Norway
var localized array<string> m_arrNwMFirstNames;
var localized array<string> m_arrNwFFirstNames;
var localized array<string> m_arrNwLastNames;
// Ireland
var localized array<string> m_arrIrMFirstNames;
var localized array<string> m_arrIrFFirstNames;
var localized array<string> m_arrIrLastNames;
// South Korea
var localized array<string> m_arrSkMFirstNames;
var localized array<string> m_arrSkFFirstNames;
var localized array<string> m_arrSkLastNames;
// The Netherlands
var localized array<string> m_arrDuMFirstNames;
var localized array<string> m_arrDuFFirstNames;
var localized array<string> m_arrDuLastNames;
// Scotland
var localized array<string> m_arrScMFirstNames;
var localized array<string> m_arrScFFirstNames;
var localized array<string> m_arrScLastNames;
// Belgium
var localized array<string> m_arrBgMFirstNames;
var localized array<string> m_arrBgFFirstNames;
var localized array<string> m_arrBgLastNames;
// Poland
var localized array<string> m_arrPlMFirstNames;
var localized array<string> m_arrPlMLastnames;
var localized array<string> m_arrPlFFirstNames;
var localized array<string> m_arrPlFLastNames;

struct LocToSoldierLanguageElement
{
	var string LocString;
	var string GameLanguage;
};

var config array<LocToSoldierLanguageElement> LocToSoldierLanguage; //Allows the game to map the Loc string to an in-game language when picking soldiers

var config float NewSoldier_HatChance;
var config float NewSoldier_UpperFacePropChance;
var config float NewSoldier_LowerFacePropChance;
var config float NewSoldier_BeardChance;
var config bool  NewSoldier_ForceColors; //Forces units to use color selections 0-6 when being spawned

var config float NewCivlian_HatChance;
var config float NewCivlian_UpperFacePropChance;
var config float NewCivlian_LowerFacePropChance;
var config float NewCivlian_BeardChance;

// Temporary variable for uniquely randomized hair so artists
// can see potentially all hair types in a squad.
var int m_iHairType;

// temporary variable for solidier creation, used by TemplateMgr filter functions
var private TSoldier kSoldier;
var private X2BodyPartTemplate kTorsoTemplate;
var private name MatchCharacterTemplateForTorso;
var private name MatchArmorTemplateForTorso;

function GenerateName( int iGender, name CountryName, out string strFirst, out string strLast, optional int iRace = -1 )
{
	local X2StrategyElementTemplateManager StratMgr;
	local X2CountryTemplate CountryTemplate;
	local array<CountryNames> AllNames, GeneralNames, RaceSpecificNames;
	local int idx, iRoll;

	strFirst = "";
	strLast = "";
	StratMgr = class'X2StrategyElementTemplateManager'.static.GetStrategyElementTemplateManager();
	CountryTemplate = X2CountryTemplate(StratMgr.FindStrategyElementTemplate(CountryName));

	for(idx = 0; idx < CountryTemplate.Names.Length; idx++)
	{
		// Add to list of all names
		AllNames.AddItem(CountryTemplate.Names[idx]);

		if(!CountryTemplate.Names[idx].bRaceSpecific)
		{
			// Add to general list of names
			GeneralNames.AddItem(CountryTemplate.Names[idx]);
		}
		else if(CountryTemplate.Names[idx].bRaceSpecific && CountryTemplate.Names[idx].Race == iRace)
		{
			// Add to list of applicable race specific names
			RaceSpecificNames.AddItem(CountryTemplate.Names[idx]);
		}
	}

	// Roll for race specific name
	iRoll = `SYNC_RAND(100);
	while(RaceSpecificNames.Length > 0 && (strFirst == "" || strLast == ""))
	{
		if(RaceSpecificNames.Length == 1 || iRoll < RaceSpecificNames[0].PercentChance)
		{
			if(iGender == eGender_Female)
			{
				strFirst = RaceSpecificNames[0].FemaleNames[`SYNC_RAND(RaceSpecificNames[0].FemaleNames.Length)];
				strLast = RaceSpecificNames[0].FemaleLastNames[`SYNC_RAND(RaceSpecificNames[0].FemaleLastNames.Length)];
			}
			else
			{
				strFirst = RaceSpecificNames[0].MaleNames[`SYNC_RAND(RaceSpecificNames[0].MaleNames.Length)];
				strLast = RaceSpecificNames[0].MaleLastNames[`SYNC_RAND(RaceSpecificNames[0].MaleLastNames.Length)];
			}
		}
		else
		{
			iRoll -= RaceSpecificNames[0].PercentChance;
			RaceSpecificNames.Remove(0, 1);
		}
	}

	// Roll for general name
	iRoll = `SYNC_RAND(100);
	while(GeneralNames.Length > 0 && (strFirst == "" || strLast == ""))
	{
		if(GeneralNames.Length == 1 || iRoll < GeneralNames[0].PercentChance)
		{
			if(iGender == eGender_Female)
			{
				strFirst = GeneralNames[0].FemaleNames[`SYNC_RAND(GeneralNames[0].FemaleNames.Length)];
				strLast = GeneralNames[0].FemaleLastNames[`SYNC_RAND(GeneralNames[0].FemaleLastNames.Length)];
			}
			else
			{
				strFirst = GeneralNames[0].MaleNames[`SYNC_RAND(GeneralNames[0].MaleNames.Length)];
				strLast = GeneralNames[0].MaleLastNames[`SYNC_RAND(GeneralNames[0].MaleLastNames.Length)];
			}	
		}
		else
		{
			iRoll -= GeneralNames[0].PercentChance;
			GeneralNames.Remove(0, 1);
		}
	}

	// Roll on all names (could happen if only race specific names were configured for the country, and input race doesn't match)
	iRoll = `SYNC_RAND(100);
	while(AllNames.Length > 0 && (strFirst == "" || strLast == ""))
	{
		if(AllNames.Length == 1 || iRoll < AllNames[0].PercentChance)
		{
			if(iGender == eGender_Female)
			{
				strFirst = AllNames[0].FemaleNames[`SYNC_RAND(AllNames[0].FemaleNames.Length)];
				strLast = AllNames[0].FemaleLastNames[`SYNC_RAND(AllNames[0].FemaleLastNames.Length)];
			}
			else
			{
				strFirst = AllNames[0].MaleNames[`SYNC_RAND(AllNames[0].MaleNames.Length)];
				strLast = AllNames[0].MaleLastNames[`SYNC_RAND(AllNames[0].MaleLastNames.Length)];
			}		
		}
		else
		{
			iRoll -= AllNames[0].PercentChance;
			AllNames.Remove(0, 1);
		}
	}

	// Fall through case
	if(strFirst == "" || strLast == "")
	{
		if(iGender == eGender_Female)
		{
			strFirst = m_arrAmFFirstNames[`SYNC_RAND(m_arrAmFFirstNames.Length)];
		}
		else
		{
			strFirst = m_arrAmMFirstNames[`SYNC_RAND(m_arrAmMFirstNames.Length)];
		}

		strLast = m_arrAmLastNames[`SYNC_RAND(m_arrAmLastNames.Length)];
	}
}

function name PickOriginCountry()
{
	local X2StrategyElementTemplateManager StratMgr;
	local array<X2StrategyElementTemplate> CountryTemplates;
	local array<name> arrCountries;
	local int idx, i;

	StratMgr = class'X2StrategyElementTemplateManager'.static.GetStrategyElementTemplateManager();
	CountryTemplates = StratMgr.GetAllTemplatesOfClass(class'X2CountryTemplate');

	for(idx = 0; idx < CountryTemplates.Length; idx++)
	{
		for(i = 0; i < X2CountryTemplate(CountryTemplates[idx]).UnitWeight; i++)
		{
			arrCountries.AddItem(CountryTemplates[idx].DataName);
		}
	}

	if(arrCountries.Length > 0)
	{
		return arrCountries[`SYNC_RAND(arrCountries.Length)];
	}
	
	return 'Country_USA';
}

function name DefaultGetRandomUberTemplate_WarnAboutFilter(string PartType)
{
	`log("WARNING:"@ `ShowVar(self) $": Unable to find a GetRandomUberTemplate for '"$PartType$"' given Torso '"$kSoldier.kAppearance.nmTorso$"' Armor '"$MatchArmorTemplateForTorso$"' Character '"$MatchCharacterTemplateForTorso$"'", ,'XCom_Templates');
	return '';
}

//In some cases we already have unit that we want to just want to randomize the appearance of. This method is used for that purpose. UsedGameState is the game state
//that contains Unit
function TSoldier CreateTSoldierFromUnit( XComGameState_Unit Unit, XComGameState UseGameState )
{
	local XComGameState_Item ArmorItem;
	local name ArmorName;

	ArmorItem = Unit.GetItemInSlot(eInvSlot_Armor, UseGameState, true);
	ArmorName = ArmorItem == none ? '' : ArmorItem.GetMyTemplateName();	
	return CreateTSoldier( Unit.GetMyTemplateName(), EGender(Unit.kAppearance.iGender), Unit.kAppearance.nmFlag, Unit.kAppearance.iRace, ArmorName );
}

delegate bool FilterCallback(X2BodyPartTemplate Template);
function X2BodyPartTemplate SetBodyPartToFirstInArray(X2BodyPartTemplateManager PartTemplateManager, out name DataName, string PartTypeName, delegate<FilterCallback> CallbackFn)
{
	local array<X2BodyPartTemplate> listPartTemplate;
	PartTemplateManager.GetFilteredUberTemplates(PartTypeName, `XCOMGAME.SharedBodyPartFilter, CallbackFn, listPartTemplate);
	DataName = (listPartTemplate.length > 0) ? listPartTemplate[0].DataName : DefaultGetRandomUberTemplate_WarnAboutFilter(PartTypeName);
	return (listPartTemplate.length > 0) ? listPartTemplate[0] : none;
}
function X2BodyPartTemplate RandomizeSetBodyPart(X2BodyPartTemplateManager PartTemplateManager, out name DataName, string PartTypeName, delegate<FilterCallback> CallbackFn)
{
	local X2BodyPartTemplate RandomPart;
	RandomPart = PartTemplateManager.GetRandomUberTemplate(PartTypeName, `XCOMGAME.SharedBodyPartFilter, CallbackFn);
	DataName = (RandomPart != none) ? RandomPart.DataName : DefaultGetRandomUberTemplate_WarnAboutFilter(PartTypeName);
	return RandomPart;
}

function TSoldier CreateTSoldier( optional name CharacterTemplateName, optional EGender eForceGender, optional name nmCountry = '', optional int iRace = -1, optional name ArmorName )
{
	local X2BodyPartTemplateManager PartTemplateManager;
	local XComLinearColorPalette HairPalette;
	local X2SimpleBodyPartFilter BodyPartFilter;
	local XComLinearColorPalette ArmorPalette;
	local X2CharacterTemplate CharacterTemplate;
	local TAppearance DefaultAppearance;
	local int SkipColors;
	local int DefaultColors;
		
	if( CharacterTemplateName == 'Soldier' || CharacterTemplateName == '' )
	{	
		MatchArmorTemplateForTorso = (ArmorName == '') ? 'KevlarArmor' : ArmorName;		
		MatchCharacterTemplateForTorso = 'NoCharacterTemplateName'; //Force the selector to use the armor type to filter torsos
	}
	else
	{
		MatchArmorTemplateForTorso = 'NoArmor'; //Default armor match value
		MatchCharacterTemplateForTorso = CharacterTemplateName;
	}

	CharacterTemplate = class'X2CharacterTemplateManager'.static.GetCharacterTemplateManager().FindCharacterTemplate(CharacterTemplateName);
	if(CharacterTemplate == None)
	{
		CharacterTemplate = class'X2CharacterTemplateManager'.static.GetCharacterTemplateManager().FindCharacterTemplate('Soldier');
	}

	//`log( `location @ `ShowVar(eForceGender) @ `ShowVar(iCountry) @ `ShowVar(iRace), , 'XCom_Templates');

	if( nmCountry == '' )
		nmCountry = PickOriginCountry();
	
	kSoldier.nmCountry = nmCountry;
	kSoldier.kAppearance.nmFlag = kSoldier.nmCountry; // needs to be copied here for pawns -- jboswell

	if( iRace == -1 )
		kSoldier.kAppearance.iRace = GetRandomRaceByCountry( kSoldier.nmCountry );
	else
		kSoldier.kAppearance.iRace = iRace;

	kSoldier.iRank = 0;

	if( eForceGender != eGender_None )
		kSoldier.kAppearance.iGender = eForceGender;
	else
		kSoldier.kAppearance.iGender = (Rand(2) == 0) ? eGender_Female : eGender_Male;

	PartTemplateManager = class'X2BodyPartTemplateManager'.static.GetBodyPartTemplateManager();

	BodyPartFilter = `XCOMGAME.SharedBodyPartFilter;
	
	//Set up for the torso selection
	BodyPartFilter.Set(EGender(kSoldier.kAppearance.iGender), ECharacterRace(kSoldier.kAppearance.iRace), ''); //Don't have a torso yet
	BodyPartFilter.SetTorsoSelection(MatchCharacterTemplateForTorso, MatchArmorTemplateForTorso);
	kTorsoTemplate = RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmTorso, "Torso", BodyPartFilter.FilterTorso);
	
	//Set again now that we have picked our torso
	BodyPartFilter.Set(EGender(kSoldier.kAppearance.iGender), ECharacterRace(kSoldier.kAppearance.iRace), kSoldier.kAppearance.nmTorso, !(CharacterTemplateName == 'Soldier' || CharacterTemplateName == ''));
	RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmHaircut, "Hair", BodyPartFilter.FilterByGenderAndNonSpecialized);
	RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmHead, "Head", BodyPartFilter.FilterByGenderAndRace);
	RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmLegs, "Legs", BodyPartFilter.FilterByTorsoAndArmorMatch);
	RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmArms, "Arms", BodyPartFilter.FilterByTorsoAndArmorMatch);	
	RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmEye, "Eyes", BodyPartFilter.FilterAny);
	RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmTeeth, "Teeth", BodyPartFilter.FilterAny);

	//Custom settings depending on whether the unit is a soldier or not
	SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmPatterns, "Patterns", BodyPartFilter.FilterAny);
	SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmTattoo_LeftArm, "Tattoos", BodyPartFilter.FilterAny);
	SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmTattoo_RightArm, "Tattoos", BodyPartFilter.FilterAny);
	if(CharacterTemplateName == 'Soldier' || CharacterTemplateName == '')
	{
		if(`SYNC_FRAND() < NewSoldier_BeardChance )
		{
			RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmBeard, "Beards", BodyPartFilter.FilterByGenderAndNonSpecialized);
		}
		else
		{
			SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmBeard, "Beards", BodyPartFilter.FilterAny);
		}
		

		if( `SYNC_FRAND() < NewSoldier_HatChance )
		{
			RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmHelmet, "Helmets", BodyPartFilter.FilterByGenderAndNonSpecializedAndTech);
		}
		else
		{
			SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmHelmet, "Helmets", BodyPartFilter.FilterAny);
		}

		if(`SYNC_FRAND() < NewSoldier_LowerFacePropChance )
		{
			RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmFacePropLower, "FacePropsLower", BodyPartFilter.FilterByGenderAndNonSpecialized);
		}
		else
		{
			SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmFacePropLower, "FacePropsLower", BodyPartFilter.FilterAny);
		}

		if(`SYNC_FRAND() < NewSoldier_UpperFacePropChance )
		{
			RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmFacePropUpper, "FacePropsUpper", BodyPartFilter.FilterByGenderAndNonSpecialized);
		}
		else
		{
			SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmFacePropUpper, "FacePropsUpper", BodyPartFilter.FilterAny);
		}
	}
	else
	{
		if(`SYNC_FRAND() < NewCivlian_BeardChance )
		{
			RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmBeard, "Beards", BodyPartFilter.FilterByGenderAndNonSpecialized);
		}
		else
		{
			SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmBeard, "Beards", BodyPartFilter.FilterAny);
		}

		if(`SYNC_FRAND() < NewCivlian_HatChance )
		{
			RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmHelmet, "Helmets", BodyPartFilter.FilterByGenderAndNonSpecializedAndTech);
		}
		else
		{
			SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmHelmet, "Helmets", BodyPartFilter.FilterAny);
		}

		if(`SYNC_FRAND() < NewCivlian_LowerFacePropChance )
		{
			RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmFacePropLower, "FacePropsLower", BodyPartFilter.FilterByGenderAndNonSpecializedCivilian);
		}
		else
		{
			SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmFacePropLower, "FacePropsLower", BodyPartFilter.FilterAny);
		}

		if(`SYNC_FRAND() < NewCivlian_UpperFacePropChance )
		{
			RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmFacePropUpper, "FacePropsUpper", BodyPartFilter.FilterByGenderAndNonSpecializedCivilian);
		}
		else
		{
			SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmFacePropUpper, "FacePropsUpper", BodyPartFilter.FilterAny);
		}
	}	

	//All character templates that use the character generator get an underlay definition, reset the filter for underlay part selection	
	BodyPartFilter.Set(EGender(kSoldier.kAppearance.iGender), ECharacterRace(kSoldier.kAppearance.iRace), '');
	BodyPartFilter.SetTorsoSelection(MatchCharacterTemplateForTorso, 'Underlay');
	RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmTorso_Underlay, "Torso", BodyPartFilter.FilterTorso);
	BodyPartFilter.Set(EGender(kSoldier.kAppearance.iGender), ECharacterRace(kSoldier.kAppearance.iRace), kSoldier.kAppearance.nmTorso_Underlay);
	RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmLegs_Underlay, "Legs", BodyPartFilter.FilterByTorsoAndArmorMatch);
	RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmArms_Underlay, "Arms", BodyPartFilter.FilterByTorsoAndArmorMatch);
	
	//Randomly select colors for new soldiers
	ArmorPalette = `CONTENT.GetColorPalette(ePalette_ArmorTint); 
	SkipColors = 10; //The last colors in the palette are rainbow colors, so skip those
	DefaultColors = 7; //Military default colors are 0-7

	//Use the default defined by the character template if set
	if(CharacterTemplate.DefaultAppearance.iArmorTint != DefaultAppearance.iArmorTint)
	{
		kSoldier.kAppearance.iArmorTint = CharacterTemplate.DefaultAppearance.iArmorTint;
	}
	else
	{
		if(NewSoldier_ForceColors)
		{
			kSoldier.kAppearance.iArmorTint = `SYNC_RAND(DefaultColors);
		}
		else
		{
			kSoldier.kAppearance.iArmorTint = `SYNC_RAND(ArmorPalette.Entries.length - SkipColors);
		}
	}

	//Use the default defined by the character template if set
	if(CharacterTemplate.DefaultAppearance.iArmorTintSecondary != DefaultAppearance.iArmorTintSecondary)
	{
		kSoldier.kAppearance.iArmorTintSecondary = CharacterTemplate.DefaultAppearance.iArmorTintSecondary;
	}
	else
	{
		if(NewSoldier_ForceColors)
		{
			kSoldier.kAppearance.iArmorTintSecondary = `SYNC_RAND(DefaultColors);
		}
		else
		{
			kSoldier.kAppearance.iArmorTintSecondary = `SYNC_RAND(ArmorPalette.Entries.length - SkipColors);
		}
	}

	//For generated soldiers, weapon tint now defaults to no tint
	kSoldier.kAppearance.iWeaponTint = -1;
	
	kSoldier.kAppearance.iTattooTint = `SYNC_RAND(ArmorPalette.Entries.length - SkipColors);
	SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmWeaponPattern, "Patterns", BodyPartFilter.FilterAny);

	HairPalette = `CONTENT.GetColorPalette(ePalette_HairColor);

	kSoldier.kAppearance.iEyeColor = 0; //right now initialized to the first one, todo when we decides which are the base colors for the different races.

	kSoldier.kAppearance.iHairColor = ChooseHairColor(kSoldier.kAppearance, HairPalette.BaseOptions); // Only generate with base options
		
	// SHIP HACK: There are at least 5 base options for every palette. I am not proud. -- jboswell
	kSoldier.kAppearance.iSkinColor = Rand(5);

	// Determine voice	
	// Only do this for soldiers.  Civilians don't use Wwise voice banks.  mdomowicz 2015_08_22
	if(CharacterTemplateName == 'Soldier' || CharacterTemplateName == '')
	{
		kSoldier.kAppearance.nmVoice = GetVoiceFromCountryAndGender(nmCountry, kSoldier.kAppearance.iGender);	

		if ( kSoldier.kAppearance.nmVoice == '' )
		{
			if (kSoldier.kAppearance.iGender == eGender_Male)
			{
				kSoldier.kAppearance.nmVoice = 'MaleVoice1_English_US';
			}
			else
			{
				kSoldier.kAppearance.nmVoice = 'FemaleVoice1_English_US';
			}
		}
	}

	kSoldier.kAppearance.iAttitude = Rand(class'X2StrategyElementTemplateManager'.static.GetStrategyElementTemplateManager().GetAllTemplatesOfClass(class'X2SoldierPersonalityTemplate').Length);

	GenerateName( kSoldier.kAppearance.iGender, kSoldier.nmCountry, kSoldier.strFirstName, kSoldier.strLastName, kSoldier.kAppearance.iRace );

	return kSoldier;
}

static function Name GetLanguageByString(optional string strLanguage="")
{
	if (len(strLanguage) == 0)
		strLanguage = GetLanguage();

	switch (strLanguage)
	{
	case "DEU":
		return 'german';
	case "ESN":
		return 'spanish';
	case "FRA":
		return 'french';
	case "ITA":
		return 'italian';	
	}

	return 'english';
}

function Name GetLanguageByCountry(name CountryName)
{
	local X2StrategyElementTemplateManager StratMgr;
	local X2CountryTemplate CountryTemplate;
	local name LanguageName;
	local string LanguageString;
	local string LocString;	
	local int Index;
	local bool bWantsForeignLanguages;
	local XComOnlineProfileSettings ProfileSettings;

	StratMgr = class'X2StrategyElementTemplateManager'.static.GetStrategyElementTemplateManager();
	CountryTemplate = X2CountryTemplate(StratMgr.FindStrategyElementTemplate(CountryName));
	if(CountryTemplate != none)
	{
		LanguageName = CountryTemplate.Language;
	}
	
	ProfileSettings = `XPROFILESETTINGS;
	bWantsForeignLanguages = ProfileSettings != none && ProfileSettings.Data != none && ProfileSettings.Data.m_bForeignLanguages;
	//Try to get a language from the LOC settings if the player has an option set to do so or something is wrong with the country settings
	if(!bWantsForeignLanguages || LanguageName == '') 
	{
		LocString = GetLanguage(); //Get the three letter code for our language
		for(Index = 0; Index < LocToSoldierLanguage.Length; ++Index)
		{
			if(LocString == LocToSoldierLanguage[Index].LocString)
			{				
				LanguageString = string(LanguageName);

				//Do str in str check so that we can match language accents, ie english matching englishUK
				if(InStr(LanguageString, LocToSoldierLanguage[Index].GameLanguage) == -1)
				{
					//The country language did not match our loc settings, change it
					LanguageName = name(LocToSoldierLanguage[Index].GameLanguage);
				}
			}
		}
	}

	//If we STILL don't have a language, pick english
	if(LanguageName == '')
	{
		LanguageName = 'english';
	}
	
	return LanguageName;
}

function name GetVoiceFromCountryAndGender(name CountryName, int iGender)
{
	local name nmLanguage;

	local X2BodyPartTemplateManager PartTemplateManager;
	local X2BodyPartTemplate SelectedVoiceTemplate;

	local array<X2BodyPartTemplate> AllVoiceTemplates;
	local array<X2BodyPartTemplate> FilteredVoiceTemplates;
	local X2BodyPartTemplate VoiceTemplate;
	local X2SimpleBodyPartFilter BodyPartFilter;	

	local int iRoll;
	
	// Get a language spoken in the given country. If the player doesn't want foreign languages, will return a language that matches their loc settings
	nmLanguage = GetLanguageByCountry(CountryName);	

	// Get all the Voice body part templates
	PartTemplateManager = class'X2BodyPartTemplateManager'.static.GetBodyPartTemplateManager();
	PartTemplateManager.GetUberTemplates("Voice", AllVoiceTemplates);


	// Filter Voice templates, selecting ones that match the determined language and given gender.
	foreach AllVoiceTemplates(VoiceTemplate)
	{
		if (VoiceTemplate.Gender == iGender && VoiceTemplate.Language == nmLanguage)
			FilteredVoiceTemplates.AddItem(VoiceTemplate);
	}


	// From the filtered list, select and return a random template.
	if (FilteredVoiceTemplates.Length > 0)
	{
		iRoll = `SYNC_RAND( FilteredVoiceTemplates.Length );
		SelectedVoiceTemplate = FilteredVoiceTemplates[iRoll];

		if (SelectedVoiceTemplate != none)
			return SelectedVoiceTemplate.DataName;
	}

	BodyPartFilter = `XCOMGAME.SharedBodyPartFilter;
	BodyPartFilter.Set(EGender(iGender), ECharacterRace(0), ''); //Just picking voice, only need gender
	VoiceTemplate = PartTemplateManager.GetRandomUberTemplate("Voice", BodyPartFilter, BodyPartFilter.FilterByGenderAndNonSpecialized);

	return VoiceTemplate.DataName;
}

function int ChooseHairColor( const out TAppearance kAppearance, int iNumBaseOptions )
{
	local int iHairChoice;
	local array<int> arrChoices;

	switch( kAppearance.iRace )
	{
	case eRace_African:
		arrChoices.AddItem(11);
		arrChoices.AddItem(12);
		arrChoices.AddItem(13);
		iHairChoice = arrChoices[Rand(arrChoices.Length)];
		break;
	case eRace_Hispanic:
		arrChoices.AddItem(11);
		arrChoices.AddItem(12);
		arrChoices.AddItem(13);
		iHairChoice = arrChoices[Rand(arrChoices.Length)];
		break;
	case eRace_Asian:
		arrChoices.AddItem(11);
		arrChoices.AddItem(12);
		arrChoices.AddItem(13);
		iHairChoice = arrChoices[Rand(arrChoices.Length)];
		break;
	default:
		iHairChoice = Rand(iNumBaseOptions);
		break;
	}

	if( iHairChoice >= iNumBaseOptions )
		iHairChoice = Rand(iNumBaseOptions);

	return iHairChoice;
}

function int ChooseFacialHair( const out TAppearance kAppearance, name nmOrigin, int iNumBaseOptions )
{
	local int iHairChoice;

	if( Rand(4) == 0 )
		iHairChoice = Rand(iNumBaseOptions);
	else
		iHairChoice = 0;

	return iHairChoice;
}

function int GetRandomRaceByCountry(name CountryName)
{
	local X2StrategyElementTemplateManager StratMgr;
	local X2CountryTemplate CountryTemplate;
	local int iRoll;

	StratMgr = class'X2StrategyElementTemplateManager'.static.GetStrategyElementTemplateManager();
	CountryTemplate = X2CountryTemplate(StratMgr.FindStrategyElementTemplate(CountryName));

	if(CountryTemplate != none)
	{
		iRoll = `SYNC_RAND(CountryTemplate.Races.iCaucasian + CountryTemplate.Races.iAfrican + 
			CountryTemplate.Races.iHispanic + CountryTemplate.Races.iAsian);

		if(CountryTemplate.Races.iCaucasian > 0 && iRoll < CountryTemplate.Races.iCaucasian)
			return eRace_Caucasian;
		else
			iRoll -= CountryTemplate.Races.iCaucasian;

		if(CountryTemplate.Races.iAfrican > 0 && iRoll < CountryTemplate.Races.iAfrican)
			return eRace_African;
		else
			iRoll -= CountryTemplate.Races.iAfrican;

		if(CountryTemplate.Races.iHispanic > 0 && iRoll < CountryTemplate.Races.iHispanic)
			return eRace_Hispanic;
		else
			iRoll -= CountryTemplate.Races.iHispanic;

		if(CountryTemplate.Races.iAsian > 0 && iRoll < CountryTemplate.Races.iAsian)
			return eRace_Asian;
		else
			iRoll -= CountryTemplate.Races.iAsian;
	}

	return eRace_Caucasian;
}

defaultproperties
{

}
