CustomTargetStyles

Tracking Issue: #763

Tags: compatibility

Target styles are responsible for the initial target selection for tactical abilities. The AbilityTargetStyle builds an initial target list (or none, for cursor-targeted abilities). The AbilityMultiTargetStyle adds other targets to every target built by the AbilityTargetStyle or the cursor target.

Even though the results are cached, this code is extremely performance-critical: Every time a game state is added to the History, all cached results are invalidated. Whenever the AI evaluates a unit, the player selects a unit, or a reaction ability checks for valid targets, this code is run for every ability on the unit!

As a result, all of this code is native: The target styles themselves are native, and their functions are called by the native GatherAbilityTargets function. This native code simply cannot see UnrealScript implementations of target styles, so custom target styles are essentially ignored.

We can override GatherAbilityTargets in a subclass with the slower UnrealScript implementation that Firaxis helpfully provided in a comment. Doing this with all abilities would seriously degrade performance, so we use CH_ClassIsNative to check if any target styles are non-native, and if so use a custom XComGameState_Ability subclass when instanciating the game state object for an ability template.

TL;DR Custom, scripted ability target/multi-target styles magically start working.

Compatibility

In order to selectively override the XComGameState_Ability class, we modify X2AbilityTemplate:CreateInstanceFromTemplate. If your mod overrides CreateInstanceFromTemplate in a subclass of X2AbilityTemplate, the Highlander will not be able to apply this enhancement to that ability. On the other hand, if you override CreateInstanceFromTemplate precisely to instantiate your own ability state object with GatherAbilityTargets de-nativized for a custom target style, your abilities will keep working the same way.

Source code references