From b132ab15e113eb44470fdfc7d38aed06d9b06c33 Mon Sep 17 00:00:00 2001 From: Iridar Date: Sun, 21 May 2023 21:18:29 +0600 Subject: [PATCH] Implement Issue #1140 - fix bugs in #783 and update docs --- .../Classes/X2DownloadableContentInfo.uc | 25 +++++++++++----- .../XComGame/Classes/XGCharacterGenerator.uc | 2 +- .../Classes/XGCharacterGenerator_Reaper.uc | 29 ++++++------------ .../XGCharacterGenerator_Skirmisher.uc | 30 +++++++------------ .../Classes/XGCharacterGenerator_Templar.uc | 29 ++++++------------ 5 files changed, 46 insertions(+), 69 deletions(-) diff --git a/X2WOTCCommunityHighlander/Src/XComGame/Classes/X2DownloadableContentInfo.uc b/X2WOTCCommunityHighlander/Src/XComGame/Classes/X2DownloadableContentInfo.uc index 853d17f24..08de74867 100644 --- a/X2WOTCCommunityHighlander/Src/XComGame/Classes/X2DownloadableContentInfo.uc +++ b/X2WOTCCommunityHighlander/Src/XComGame/Classes/X2DownloadableContentInfo.uc @@ -723,30 +723,39 @@ static function UnitPawnPostInitAnimTree(XComGameState_Unit UnitState, XComUnitP /// ## 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 generated appearance is stored in `CharGen.kSoldier.kAppearance`, which you can modify directly. +/// +/// Other arguments are provided to for reference, as they were given to 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. +/// +/// # Issue #1140 Addendum +/// This hook is triggered twice for faction heroes. +/// Reapers and Templars run this hook the first time after initial character generation, +/// and the second time after their faction-specific country and class-specific nickname +/// have been generated. +/// Skirmishers additionally get their faction-specific name after the first time the hook is triggered. +/// /// ## 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 +/// +/// 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. diff --git a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator.uc b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator.uc index db14019d9..507065271 100644 --- a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator.uc +++ b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator.uc @@ -411,7 +411,7 @@ function TSoldier CreateTSoldier( optional name CharacterTemplateName, optional } // Start issue #783 -private function ModifyGeneratedUnitAppearance(optional name CharacterTemplateName, optional EGender eForceGender, optional name nmCountry = '', optional int iRace = -1, optional name ArmorName) +final protected function ModifyGeneratedUnitAppearance(optional name CharacterTemplateName, optional EGender eForceGender, optional name nmCountry = '', optional int iRace = -1, optional name ArmorName) { local array DLCInfos; local int i; diff --git a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Reaper.uc b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Reaper.uc index 210ab48cf..6401dad34 100644 --- a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Reaper.uc +++ b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Reaper.uc @@ -26,34 +26,23 @@ function X2CharacterTemplate SetCharacterTemplate(name CharacterTemplateName, na 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); - + kSoldier = super.CreateTSoldier('ReaperSoldier', eForceGender, nmCountry, iRace, ArmorName); + SetCountry('Country_Reaper'); ClassMgr = class'X2SoldierClassTemplateManager'.static.GetSoldierClassTemplateManager(); ClassTemplate = ClassMgr.FindSoldierClassTemplate('Reaper'); kSoldier.strNickName = GenerateNickname(ClassTemplate, kSoldier.kAppearance.iGender); + + // Start issue #783 + ModifyGeneratedUnitAppearance(CharacterTemplateName, eForceGender, nmCountry, iRace, ArmorName); + // End issue #783 + + return kSoldier; } -// End issue #783 function SetRace(int iRace) { @@ -130,4 +119,4 @@ function SetVoice(name CharacterTemplateName, name CountryName) } } } -} +} \ No newline at end of file diff --git a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Skirmisher.uc b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Skirmisher.uc index e4e4d226b..d037cbddf 100644 --- a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Skirmisher.uc +++ b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Skirmisher.uc @@ -19,34 +19,24 @@ function X2CharacterTemplate SetCharacterTemplate(name CharacterTemplateName, na 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 ); - + kSoldier = super.CreateTSoldier('SkirmisherSoldier', eForceGender, nmCountry, iRace, ArmorName); + SetCountry('Country_Skirmisher'); + 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); + + // Start issue #783 + ModifyGeneratedUnitAppearance(CharacterTemplateName, eForceGender, nmCountry, iRace, ArmorName); + // End issue #783 + + return kSoldier; } -// End issue #783 function SetAccessories(X2SimpleBodyPartFilter BodyPartFilter, name CharacterTemplateName) { @@ -104,4 +94,4 @@ function SetVoice(name CharacterTemplateName, name CountryName) } } } -} +} \ No newline at end of file diff --git a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Templar.uc b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Templar.uc index 93676ad6f..6481dd7f6 100644 --- a/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Templar.uc +++ b/X2WOTCCommunityHighlander/Src/XComGame/Classes/XGCharacterGenerator_Templar.uc @@ -21,34 +21,23 @@ function X2CharacterTemplate SetCharacterTemplate(name CharacterTemplateName, na 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 ); - + kSoldier = super.CreateTSoldier('TemplarSoldier', eForceGender, nmCountry, iRace, ArmorName); + SetCountry('Country_Templar'); ClassMgr = class'X2SoldierClassTemplateManager'.static.GetSoldierClassTemplateManager(); ClassTemplate = ClassMgr.FindSoldierClassTemplate('Templar'); kSoldier.strNickName = GenerateNickname(ClassTemplate, kSoldier.kAppearance.iGender); + + // Start issue #783 + ModifyGeneratedUnitAppearance(CharacterTemplateName, eForceGender, nmCountry, iRace, ArmorName); + // End issue #783 + + return kSoldier; } -// End issue #783 function SetRace(int iRace) { @@ -114,4 +103,4 @@ function SetVoice(name CharacterTemplateName, name CountryName) function SetAttitude() { kSoldier.kAppearance.iAttitude = 0; // Should correspond with Personality_ByTheBook -} +} \ No newline at end of file