From d8b0784789afa9eb79ba90cbe2568388545428f1 Mon Sep 17 00:00:00 2001 From: Iridar Date: Mon, 24 Feb 2020 01:33:53 +0300 Subject: [PATCH] Implemented Issue #783 - add DLC hook to modify generated unit appearance. --- .../Classes/X2DownloadableContentInfo.uc | 40 ++++++ .../XComGame/Classes/XGCharacterGenerator.uc | 56 +++++++- .../Classes/XGCharacterGenerator_Reaper.uc | 133 ++++++++++++++++++ .../XGCharacterGenerator_Skirmisher.uc | 107 ++++++++++++++ .../Classes/XGCharacterGenerator_Templar.uc | 117 +++++++++++++++ .../X2WOTCCommunityHighlander.x2proj | 9 ++ 6 files changed, 455 insertions(+), 7 deletions(-) create mode 100644 X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Reaper.uc create mode 100644 X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Skirmisher.uc create mode 100644 X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Templar.uc diff --git a/X2WOTCCommunityHighlander/Src/XComGame/Classes/X2DownloadableContentInfo.uc b/X2WOTCCommunityHighlander/Src/XComGame/Classes/X2DownloadableContentInfo.uc index 8b3aca8b6..1bd274b2d 100644 --- a/X2WOTCCommunityHighlander/Src/XComGame/Classes/X2DownloadableContentInfo.uc +++ b/X2WOTCCommunityHighlander/Src/XComGame/Classes/X2DownloadableContentInfo.uc @@ -762,3 +762,43 @@ final function string GetDisplayName() return ModDependency.DisplayName; } /// End Issue #524 + +// Start Issue #783 +// +/// Called from XGCharacterGenerator:CreateTSoldier +/// Has no return value, just modify the CharGen.kSoldier directly. +/// HL-Docs: feature:ModifyGeneratedUnitAppearance; issue:783; tags:customization,compatibility +/// ## Usage +/// This DLC hook allows mods to make arbitrary changes to unit appearance +/// after it has been generated by `XGCharacterGenerator::CreateTSoldier()`. +/// The generated appearance is stored in `CharGen.kSoldier`, which you can modify directly. +/// Other arguments are provided to you mostly for reference, +/// and presented to you as they were used by the `CreateTSoldier()` function. +/// The UnitState and the GameState will be passed to this hook +/// only if the `CreateTSoldier()` function was called from `CreateTSoldierFromUnit()`, +/// which normally happens only in the Shell code (TQL / Challenge Mode / Character Pool), +/// and will be `none` otherwise. +/// If you wish to "redo" some parts of the process of generating unit's appearance, +/// you can call various methods in the Character Generator, +/// but you must avoid calling the `CreateTSoldier()` and `CreateTSoldierFromUnit()` methods, +/// as that will retrigger the hook, potentially causing an inception loop and crashing the game. +/// ## Compatibility +/// Custom `XGCharacterGenerator` classes used by mods to generate appearance of custom units +/// can potentially interfere with the normal operation of this hook for themselves. +/// If the Character Generator implements a custom `CreateTSoldier()` function that +/// does not call `super.CreateTSoldier()`, then this DLC hook will not be called for that class. +/// If `super.CreateTSoldier()` *is* called, but the custom `CreateTSoldier()` function +/// makes changes to the generated appearance afterwards, it can potentially override +/// changes made by this hook. +/// For example, Character Generators for Faction Hero classes had to be adjusted +/// in the Highlander so that they do not override Country and Nickname after +/// calling `super.CreateTSoldier()`, and instead override the `SetCountry()` and +/// `GenerateName()` methods, which are called by `super.CreateTSoldier()`. +/// For best compatibility with this hook, mod-added `XGCharacterGenerator()` classes +/// should avoid making any appearance changes after calling `super.CreateTSoldier()`. +/// Ideally, that function should not be overridden at all, and the Character Generator +/// should rely on overriding other methods called by `CreateTSoldier()` as much as possible. +// +static function ModifyGeneratedUnitAppearance(XGCharacterGenerator CharGen, const name CharacterTemplateName, const EGender eForceGender, const name nmCountry, const int iRace, const name ArmorName, XComGameState_Unit UnitState, XComGameState UseGameState) +{} +/// End Issue #783 diff --git a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator.uc b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator.uc index 25e3b5fe4..2ce203e57 100644 --- a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator.uc +++ b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator.uc @@ -122,11 +122,13 @@ var config float DLCPartPackDefaultChance; var int m_iHairType; // temporary variable for soldier creation, used by TemplateMgr filter functions -var protected TSoldier kSoldier; -var protected X2BodyPartTemplate kTorsoTemplate; -var protected name MatchCharacterTemplateForTorso; -var protected name MatchArmorTemplateForTorso; -var protected array DLCNames; //List of DLC packs to pull parts from for the currently generating soldier. +// Start unprotect variables for issue #783 +var /*protected*/ TSoldier kSoldier; +var /*protected*/ X2BodyPartTemplate kTorsoTemplate; +var /*protected*/ name MatchCharacterTemplateForTorso; +var /*protected*/ name MatchArmorTemplateForTorso; +var /*protected*/ array DLCNames; //List of DLC packs to pull parts from for the currently generating soldier. +// End unprotect variables for issue #783 // Store a country name to be use in bios for soldiers that force a unique country var name BioCountryName; @@ -139,6 +141,11 @@ var X2CharacterTemplate m_CharTemplate; // New variable for issue #397 var config(Content) int iDefaultWeaponTint; +// Start issue #783 +var XComGameState_Unit GenerateAppearanceForUnitState; +var XComGameState GenerateAppearanceForGameState; +// End issue #783 + function GenerateName( int iGender, name CountryName, out string strFirst, out string strLast, optional int iRace = -1 ) { local X2StrategyElementTemplateManager StratMgr; @@ -294,10 +301,26 @@ function TSoldier CreateTSoldierFromUnit( XComGameState_Unit Unit, XComGameState { local XComGameState_Item ArmorItem; local name ArmorName; + // Variable for issue #783 + local TSoldier CreatedTSoldier; 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 ); + + // Start issue #783 + GenerateAppearanceForUnitState = Unit; + GenerateAppearanceForGameState = UseGameState; + + CreatedTSoldier = CreateTSoldier( Unit.GetMyTemplateName(), EGender(Unit.kAppearance.iGender), Unit.kAppearance.nmFlag, Unit.kAppearance.iRace, ArmorName ); + + // Blank the properties just in case this instance of the Character Generator will be used to also call CreateTSoldier() separately, + // which would trigger the 'PostUnitAppearanceGenerated' event another time, but it would still pass the same Unit State and Game State from the time CreateTSoldierFromUnit() + // was called. So we blank them out to make sure we're not passing irrelevant information with the event. + GenerateAppearanceForUnitState = none; + GenerateAppearanceForGameState = none; + + return CreatedTSoldier; + // End issue #783 } delegate bool FilterCallback(X2BodyPartTemplate Template); @@ -380,9 +403,28 @@ function TSoldier CreateTSoldier( optional name CharacterTemplateName, optional BioCountryName = kSoldier.nmCountry; + // Start issue #783 + ModifyGeneratedUnitAppearance(CharacterTemplateName, eForceGender, nmCountry, iRace, ArmorName); + // End issue #783 + return kSoldier; } +// Start issue #783 +private function ModifyGeneratedUnitAppearance(optional name CharacterTemplateName, optional EGender eForceGender, optional name nmCountry = '', optional int iRace = -1, optional name ArmorName) +{ + local array DLCInfos; + local int i; + + /// HL-Docs: ref:ModifyGeneratedUnitAppearance; issue:783 + DLCInfos = `ONLINEEVENTMGR.GetDLCInfos(false); + for (i = 0; i < DLCInfos.Length; i++) + { + DLCInfos[i].ModifyGeneratedUnitAppearance(self, CharacterTemplateName, eForceGender, nmCountry, iRace, ArmorName, GenerateAppearanceForUnitState, GenerateAppearanceForGameState); + } +} +// End issue #783 + static function Name GetLanguageByString(optional string strLanguage="") { if (len(strLanguage) == 0) @@ -1027,4 +1069,4 @@ function string GenerateNickname(X2SoldierClassTemplate Template, int iGender) } return ""; -} \ No newline at end of file +} diff --git a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Reaper.uc b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Reaper.uc new file mode 100644 index 000000000..210ab48cf --- /dev/null +++ b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Reaper.uc @@ -0,0 +1,133 @@ +class XGCharacterGenerator_Reaper extends XGCharacterGenerator + dependson(X2StrategyGameRulesetDataStructures) config(NameList); + +var config array PrimaryArmorColors; +var config array SecondaryArmorColors; +var config array MaleHeads; +var config array FemaleHeads; +var config array MaleHelmets; +var config array FemaleHelmets; +var config array MaleLeftArms; +var config array MaleRightArms; +var config array FemaleLeftArms; +var config array FemaleRightArms; + + +function bool IsSoldier(name CharacterTemplateName) +{ + return true; +} + +function X2CharacterTemplate SetCharacterTemplate(name CharacterTemplateName, name ArmorName) +{ + MatchArmorTemplateForTorso = (ArmorName == '') ? 'ReaperArmor' : ArmorName; + MatchCharacterTemplateForTorso = 'NoCharacterTemplateName'; //Force the selector to use the armor type to filter torsos + + return class'X2CharacterTemplateManager'.static.GetCharacterTemplateManager().FindCharacterTemplate('ReaperSoldier'); +} + +// Start issue #783 +// Normally this function calls the super.CreateTSoldier, and then manually sets the country and nickname. +// In order to make the DLC hook for this issue more compatible with resistance faction soldiers, +// this functionality has been moved into SetCountry() and GenerateName() methods which will be called by super.CreateTSoldier. +function TSoldier CreateTSoldier(optional name CharacterTemplateName, optional EGender eForceGender, optional name nmCountry = '', optional int iRace = -1, optional name ArmorName) +{ + kSoldier = super.CreateTSoldier('ReaperSoldier', eForceGender, nmCountry, iRace, ArmorName); + return kSoldier; +} + +function SetCountry(name nmCountry) +{ + kSoldier.nmCountry = 'Country_Reaper'; + kSoldier.kAppearance.nmFlag = kSoldier.nmCountry; // needs to be copied here for pawns -- jboswell +} + +function GenerateName(int iGender, name CountryName, out string strFirst, out string strLast, optional int iRace = -1) +{ + local X2SoldierClassTemplateManager ClassMgr; + local X2SoldierClassTemplate ClassTemplate; + + super.GenerateName(kSoldier.kAppearance.iGender, kSoldier.nmCountry, kSoldier.strFirstName, kSoldier.strLastName, kSoldier.kAppearance.iRace); + + ClassMgr = class'X2SoldierClassTemplateManager'.static.GetSoldierClassTemplateManager(); + ClassTemplate = ClassMgr.FindSoldierClassTemplate('Reaper'); + kSoldier.strNickName = GenerateNickname(ClassTemplate, kSoldier.kAppearance.iGender); +} +// End issue #783 + +function SetRace(int iRace) +{ + kSoldier.kAppearance.iRace = eRace_Caucasian; +} + +function SetHead(X2SimpleBodyPartFilter BodyPartFilter, X2CharacterTemplate CharacterTemplate) +{ + super.SetHead(BodyPartFilter, CharacterTemplate); + + if (kSoldier.kAppearance.iGender == eGender_Male) + { + kSoldier.kAppearance.nmHead = default.MaleHeads[`SYNC_RAND(default.MaleHeads.Length)]; + } + else + { + kSoldier.kAppearance.nmHead = default.FemaleHeads[`SYNC_RAND(default.FemaleHeads.Length)]; + } +} + +function SetArmsLegsAndDeco(X2SimpleBodyPartFilter BodyPartFilter) +{ + super.SetArmsLegsAndDeco(BodyPartFilter); + + if(kSoldier.kAppearance.iGender == eGender_Male) + { + kSoldier.kAppearance.nmLeftArm = default.MaleLeftArms[`SYNC_RAND(default.MaleLeftArms.Length)]; + kSoldier.kAppearance.nmRightArm = default.MaleRightArms[`SYNC_RAND(default.MaleRightArms.Length)]; + } + else + { + kSoldier.kAppearance.nmLeftArm = default.FemaleLeftArms[`SYNC_RAND(default.FemaleLeftArms.Length)]; + kSoldier.kAppearance.nmRightArm = default.FemaleRightArms[`SYNC_RAND(default.FemaleRightArms.Length)]; + } +} + +function SetAccessories(X2SimpleBodyPartFilter BodyPartFilter, name CharacterTemplateName) +{ + super.SetAccessories(BodyPartFilter, CharacterTemplateName); + + if(kSoldier.kAppearance.iGender == eGender_Male) + { + kSoldier.kAppearance.nmHelmet = default.MaleHelmets[`SYNC_RAND(default.MaleHelmets.Length)]; + } + else + { + kSoldier.kAppearance.nmHelmet = default.FemaleHelmets[`SYNC_RAND(default.FemaleHelmets.Length)]; + } +} + +function SetArmorTints(X2CharacterTemplate CharacterTemplate) +{ + super.SetArmorTints(CharacterTemplate); + + kSoldier.kAppearance.iArmorTint = default.PrimaryArmorColors[`SYNC_RAND(default.PrimaryArmorColors.Length)]; + kSoldier.kAppearance.iArmorTintSecondary = default.SecondaryArmorColors[`SYNC_RAND(default.SecondaryArmorColors.Length)]; +} + +function SetVoice(name CharacterTemplateName, name CountryName) +{ + if (IsSoldier(CharacterTemplateName)) + { + kSoldier.kAppearance.nmVoice = GetVoiceFromCountryAndGenderAndCharacter(CountryName, kSoldier.kAppearance.iGender, CharacterTemplateName); + + if (kSoldier.kAppearance.nmVoice == '') + { + if (kSoldier.kAppearance.iGender == eGender_Male) + { + kSoldier.kAppearance.nmVoice = 'ReaperMaleVoice1_Localized'; + } + else + { + kSoldier.kAppearance.nmVoice = 'ReaperFemaleVoice1_Localized'; + } + } + } +} diff --git a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Skirmisher.uc b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Skirmisher.uc new file mode 100644 index 000000000..e4e4d226b --- /dev/null +++ b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Skirmisher.uc @@ -0,0 +1,107 @@ +class XGCharacterGenerator_Skirmisher extends XGCharacterGenerator + dependson(X2StrategyGameRulesetDataStructures); + +var config array PrimaryArmorColors; +var config array SecondaryArmorColors; +var config array MaleHelmets; +var config array FemaleHelmets; + +function bool IsSoldier(name CharacterTemplateName) +{ + return true; +} + +function X2CharacterTemplate SetCharacterTemplate(name CharacterTemplateName, name ArmorName) +{ + MatchArmorTemplateForTorso = (ArmorName == '') ? 'SkirmisherArmor' : ArmorName; + MatchCharacterTemplateForTorso = 'NoCharacterTemplateName'; //Force the selector to use the armor type to filter torsos + + return class'X2CharacterTemplateManager'.static.GetCharacterTemplateManager().FindCharacterTemplate('SkirmisherSoldier'); +} + +// Start issue #783 +// Normally this function calls the super.CreateTSoldier, and then manually sets the country and nickname. +// In order to make the DLC hook for this issue more compatible with resistance faction soldiers, +// this functionality has been moved into SetCountry() and GenerateName() methods which will be called by super.CreateTSoldier. +function TSoldier CreateTSoldier(optional name CharacterTemplateName, optional EGender eForceGender, optional name nmCountry = '', optional int iRace = -1, optional name ArmorName) +{ + kSoldier = super.CreateTSoldier('SkirmisherSoldier', eForceGender, nmCountry, iRace, ArmorName); + return kSoldier; +} + +function SetCountry(name nmCountry) +{ + kSoldier.nmCountry = 'Country_Skirmisher'; + kSoldier.kAppearance.nmFlag = kSoldier.nmCountry; // needs to be copied here for pawns -- jboswell +} + +function GenerateName( int iGender, name CountryName, out string strFirst, out string strLast, optional int iRace = -1 ) +{ + local X2SoldierClassTemplateManager ClassMgr; + local X2SoldierClassTemplate ClassTemplate; + + super.GenerateName( kSoldier.kAppearance.iGender, kSoldier.nmCountry, kSoldier.strFirstName, kSoldier.strLastName, kSoldier.kAppearance.iRace ); + + ClassMgr = class'X2SoldierClassTemplateManager'.static.GetSoldierClassTemplateManager(); + ClassTemplate = ClassMgr.FindSoldierClassTemplate('Skirmisher'); + kSoldier.strNickName = GenerateNickname(ClassTemplate, kSoldier.kAppearance.iGender); +} +// End issue #783 + +function SetAccessories(X2SimpleBodyPartFilter BodyPartFilter, name CharacterTemplateName) +{ + local X2BodyPartTemplateManager PartTemplateManager; + + PartTemplateManager = class'X2BodyPartTemplateManager'.static.GetBodyPartTemplateManager(); + + //Turn off most customization options for Skirmishers + SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmPatterns, "Patterns", BodyPartFilter.FilterAny); + SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmWeaponPattern, "Patterns", BodyPartFilter.FilterAny); + SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmTattoo_LeftArm, "Tattoos", BodyPartFilter.FilterAny); + SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmTattoo_RightArm, "Tattoos", BodyPartFilter.FilterAny); + SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmHaircut, "Hair", BodyPartFilter.FilterAny); + SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmBeard, "Beards", BodyPartFilter.FilterAny); + SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmHelmet, "Helmets", BodyPartFilter.FilterAny); + SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmFacePropLower, "FacePropsLower", BodyPartFilter.FilterAny); + SetBodyPartToFirstInArray(PartTemplateManager, kSoldier.kAppearance.nmFacePropUpper, "FacePropsUpper", BodyPartFilter.FilterAny); + + // Randomly choose a Skirmisher scar + RandomizeSetBodyPart(PartTemplateManager, kSoldier.kAppearance.nmScars, "Scars", BodyPartFilter.FilterByCharacter); + + if (kSoldier.kAppearance.iGender == eGender_Male) + { + kSoldier.kAppearance.nmHelmet = default.MaleHelmets[`SYNC_RAND(default.MaleHelmets.Length)]; + } + else + { + kSoldier.kAppearance.nmHelmet = default.FemaleHelmets[`SYNC_RAND(default.FemaleHelmets.Length)]; + } +} + +function SetArmorTints(X2CharacterTemplate CharacterTemplate) +{ + super.SetArmorTints(CharacterTemplate); + + kSoldier.kAppearance.iArmorTint = default.PrimaryArmorColors[`SYNC_RAND(default.PrimaryArmorColors.Length)]; + kSoldier.kAppearance.iArmorTintSecondary = default.SecondaryArmorColors[`SYNC_RAND(default.SecondaryArmorColors.Length)]; +} + +function SetVoice(name CharacterTemplateName, name CountryName) +{ + if (IsSoldier(CharacterTemplateName)) + { + kSoldier.kAppearance.nmVoice = GetVoiceFromCountryAndGenderAndCharacter(CountryName, kSoldier.kAppearance.iGender, CharacterTemplateName); + + if (kSoldier.kAppearance.nmVoice == '') + { + if (kSoldier.kAppearance.iGender == eGender_Male) + { + kSoldier.kAppearance.nmVoice = 'SkirmisherMaleVoice1_Localized'; + } + else + { + kSoldier.kAppearance.nmVoice = 'SkirmisherFemaleVoice1_Localized'; + } + } + } +} diff --git a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Templar.uc b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Templar.uc new file mode 100644 index 000000000..93676ad6f --- /dev/null +++ b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Templar.uc @@ -0,0 +1,117 @@ +class XGCharacterGenerator_Templar extends XGCharacterGenerator + dependson(X2StrategyGameRulesetDataStructures) config(NameList); + +var config array PrimaryArmorColors; +var config array SecondaryArmorColors; +var config array MaleHeads; +var config array FemaleHeads; +var config array MaleHelmets; +var config array FemaleHelmets; + +function bool IsSoldier(name CharacterTemplateName) +{ + return true; +} + +function X2CharacterTemplate SetCharacterTemplate(name CharacterTemplateName, name ArmorName) +{ + MatchArmorTemplateForTorso = (ArmorName == '') ? 'TemplarArmor' : ArmorName; + MatchCharacterTemplateForTorso = 'NoCharacterTemplateName'; //Force the selector to use the armor type to filter torsos + + return class'X2CharacterTemplateManager'.static.GetCharacterTemplateManager().FindCharacterTemplate(CharacterTemplateName); +} + +// Start issue #783 +// Normally this function calls the super.CreateTSoldier, and then manually sets the country and nickname. +// In order to make the DLC hook for this issue more compatible with resistance faction soldiers, +// this functionality has been moved into SetCountry() and GenerateName() methods which will be called by super.CreateTSoldier. +function TSoldier CreateTSoldier(optional name CharacterTemplateName, optional EGender eForceGender, optional name nmCountry = '', optional int iRace = -1, optional name ArmorName) +{ + kSoldier = super.CreateTSoldier('TemplarSoldier', eForceGender, nmCountry, iRace, ArmorName); + return kSoldier; +} + +function SetCountry(name nmCountry) +{ + kSoldier.nmCountry = 'Country_Templar'; + kSoldier.kAppearance.nmFlag = kSoldier.nmCountry; // needs to be copied here for pawns -- jboswell +} + +function GenerateName( int iGender, name CountryName, out string strFirst, out string strLast, optional int iRace = -1 ) +{ + local X2SoldierClassTemplateManager ClassMgr; + local X2SoldierClassTemplate ClassTemplate; + + super.GenerateName( kSoldier.kAppearance.iGender, kSoldier.nmCountry, kSoldier.strFirstName, kSoldier.strLastName, kSoldier.kAppearance.iRace ); + + ClassMgr = class'X2SoldierClassTemplateManager'.static.GetSoldierClassTemplateManager(); + ClassTemplate = ClassMgr.FindSoldierClassTemplate('Templar'); + kSoldier.strNickName = GenerateNickname(ClassTemplate, kSoldier.kAppearance.iGender); +} +// End issue #783 + +function SetRace(int iRace) +{ + kSoldier.kAppearance.iRace = eRace_Hispanic; +} + +function SetHead(X2SimpleBodyPartFilter BodyPartFilter, X2CharacterTemplate CharacterTemplate) +{ + super.SetHead(BodyPartFilter, CharacterTemplate); + + if (kSoldier.kAppearance.iGender == eGender_Male) + { + kSoldier.kAppearance.nmHead = default.MaleHeads[`SYNC_RAND(default.MaleHeads.Length)]; + } + else + { + kSoldier.kAppearance.nmHead = default.FemaleHeads[`SYNC_RAND(default.FemaleHeads.Length)]; + } +} + +function SetAccessories(X2SimpleBodyPartFilter BodyPartFilter, name CharacterTemplateName) +{ + super.SetAccessories(BodyPartFilter, CharacterTemplateName); + + if (kSoldier.kAppearance.iGender == eGender_Male) + { + kSoldier.kAppearance.nmHelmet = default.MaleHelmets[`SYNC_RAND(default.MaleHelmets.Length)]; + } + else + { + kSoldier.kAppearance.nmHelmet = default.FemaleHelmets[`SYNC_RAND(default.FemaleHelmets.Length)]; + } +} + +function SetArmorTints(X2CharacterTemplate CharacterTemplate) +{ + super.SetArmorTints(CharacterTemplate); + + kSoldier.kAppearance.iArmorTint = default.PrimaryArmorColors[`SYNC_RAND(default.PrimaryArmorColors.Length)]; + kSoldier.kAppearance.iArmorTintSecondary = default.SecondaryArmorColors[`SYNC_RAND(default.SecondaryArmorColors.Length)]; +} + +function SetVoice(name CharacterTemplateName, name CountryName) +{ + if (IsSoldier(CharacterTemplateName)) + { + kSoldier.kAppearance.nmVoice = GetVoiceFromCountryAndGenderAndCharacter(CountryName, kSoldier.kAppearance.iGender, CharacterTemplateName); + + if (kSoldier.kAppearance.nmVoice == '') + { + if (kSoldier.kAppearance.iGender == eGender_Male) + { + kSoldier.kAppearance.nmVoice = 'TemplarMaleVoice1_Localized'; + } + else + { + kSoldier.kAppearance.nmVoice = 'TemplarFemaleVoice1_Localized'; + } + } + } +} + +function SetAttitude() +{ + kSoldier.kAppearance.iAttitude = 0; // Should correspond with Personality_ByTheBook +} diff --git a/X2WOTCCommunityHighlander/X2WOTCCommunityHighlander.x2proj b/X2WOTCCommunityHighlander/X2WOTCCommunityHighlander.x2proj index c3f37c205..064d77c75 100644 --- a/X2WOTCCommunityHighlander/X2WOTCCommunityHighlander.x2proj +++ b/X2WOTCCommunityHighlander/X2WOTCCommunityHighlander.x2proj @@ -646,6 +646,15 @@ Content + + Content + + + Content + + + Content + Content