XCOM: Chimera Squad

XCOM: Chimera Squad

Create and Share Mods
Create your own enemies, characters, weapons, maps, and other content to expand XCOM: Chimera Squad. Mods are created by and for the XCOM community and are not officially supported by Firaxis or 2K.
Requesting help/example of how to insert new trainings for specific characters based on level
I've found X2Ability_ClassTraining.uc, which is where templates for abilities gained from training are defined. Good examples for how to create trained abilities, often as passives that act as conditionals for behavior in associated abilities.

I've found X2StrategyElement_DioHQTemplates.uc, where trainings themselves (X2DioTrainingProgramTemplates) are defined. Good examples for how to create custom trainings.

Where I'm stuck is how to associate a training with a specific character based on their level.

I've found DefaultClassData.ini, which looks to be where abilities and trainings are assigned to characters by level.

But I do not know the means to override this to insert training at the appropriate level. Is this the only place where that can happen?

I've been trying to do this programmatically instead, noting that if we can get a X2SoldierClassTemplate for a specific character from the X2SoldierClassTemplateManager, this var should be available to use:

var config protected array<SoldierClassRank> SoldierRanks;


A SoldierClassRank struct has:

var array<name> TrainingPrograms;

Problem is the SoldierRanks var on X2SoldierClassTemplate is protected, we can't access it directly. But this function is present in the same class:

function array<name> GetTrainingPrograms(int Rank)

My thinking was to find the soldier's template via the soldier class template manager, get its training programs for the desired rank (testing with 0), then add the name of the training program.

I don't think this part is working properly, though, it doesn't look like I can modify the training programs this way.

I did a redscreen of the contents of GetTrainingPrograms(0) after adding mine, which looked fine.

But as a sanity check, I accessed the training programs fresh after the addition, and my addition isn't present:

```
...
CharacterTemplateManager = class'X2SoldierClassTemplateManager'.static.GetSoldierClassTemplateManager();
PsionTemplate = CharacterTemplateManager.FindSoldierClassTemplate('SoldierClass_Psion');
TrainingPrograms = PsionTemplate.GetTrainingPrograms(0);
TrainingPrograms.AddItem('TrainingProgram_ShelterSlipstream');

// it should be added, sanity check

PsionTemplate = CharacterTemplateManager.FindSoldierClassTemplate('SoldierClass_Psion');
TrainingPrograms = PsionTemplate.GetTrainingPrograms(0);
foreach TrainingPrograms( Program )
{
`RedScreen( "Training program =" @ Program ); // my addition doesn't print
}
```

Looking for help or insight here. If there's a better way to add a training program to a character, I definitely want to know!
< >
Showing 1-3 of 3 comments
chair5768 8 8 May, 2020 @ 3:20am 
Trainingprograms becomes a copy of the array not a pointer to it. Arrays aren't treated as objects like that:

static event OnPostTemplatesCreated()
{
local int i;
local array <int> Array1, Array2;

for (i = 0; i < 5; i++)
Array1.AddItem(i);

Array2 = Array1;

for(i = 0; i < 5; i++)
Array2 = -1;

for(i = 0; i < 5; i++)
`log("Array1[" $ i $ "]:" $ Array1 $ " Array2[" $ i $ "]:" $ Array2, , 'Array Test---');

}

Results in an output of:
[0005.82] Array Test---: Array1[0]:0 Array2[0]:-1
[0005.82] Array Test---: Array1[1]:1 Array2[1]:-1
[0005.82] Array Test---: Array1[2]:2 Array2[2]:-1
[0005.82] Array Test---: Array1[3]:3 Array2[3]:-1
[0005.82] Array Test---: Array1[4]:4 Array2[4]:-1

InverseFalcon 1 8 May, 2020 @ 7:14pm 
Thank you for the confirmation, good to know.

So that rules out a programmatic change through altering the TrainingPrograms array, and we can't access the SoldierRanks array to get at the SoldierClassRank so we can replace the TrainingPrograms array.

I think that only leaves one possible approach, overriding the DefaultClassData.ini values.

How do we override these, such that we can add a training ability at a certain rank?

EDIT

I'm refreshing myself on overriding ini files, so my question is related to the ability / rank tree itself. It looks like there's nothing in each SoldierRanks line that associates an entry to a rank, it's just the natural order of repeated SoldierRanks lines in the file that determine this.

So for overriding this, would I have to - out the entire tree, and renter it all with my additional training program? That doesn't quite feel right, and would likely conflict with anyone else that's doing a similar ability tree change.

Is there a better way to do this? Seems like multiple training program additions from mods are ripe for conflicts with this approach.
Last edited by InverseFalcon; 8 May, 2020 @ 7:30pm
InverseFalcon 1 9 May, 2020 @ 4:31am 
Success!

If we create a subclass of X2SoldierClassTemplate, any function within can access the protected SoldierRanks array, allowing us to insert training directly into the appropriate place in the structure.

Something like this:

class TrainableSoldier extends X2SoldierClassTemplate; static function bool AddTrainingAtLevel(X2SoldierClassTemplate SoldierTemplate, name ProgramTemplateName, int Level) { SoldierTemplate.SoldierRanks[Level].TrainingPrograms.AddItem(ProgramTemplateName); return true; }


With that, from elsewhere, we can insert our training template where it needs to be:

... // add Slipstream training at rank 0 CharacterTemplateManager = class'X2SoldierClassTemplateManager'.static.GetSoldierClassTemplateManager(); PsionTemplate = CharacterTemplateManager.FindSoldierClassTemplate('SoldierClass_Psion'); class'TrainableSoldier'.static.AddTrainingAtLevel(PsionTemplate, 'TrainingProgram_ShelterSlipstream', 2);

Now to troubleshoot the trained ability, but relieved to have found a good means of adding custom training!

Feel free to reuse something like this in your own custom mods!
< >
Showing 1-3 of 3 comments
Per page: 1530 50