<commit_before>/// HL-Docs: feature:CustomTargetStyles; issue:763; tags:tactical,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](../misc/ClassIsNative.md) 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 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, 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, things will keep working.

class XComGameState_Ability_CH extends XComGameState_Ability;

simulated function name GatherAbilityTargets(out array<AvailableTarget> Targets, optional XComGameState_Unit OverrideOwnerState)
{
	local int i, j;
	local XComGameState_Unit kOwner;
	local name AvailableCode;
	local XComGameStateHistory History;

	GetMyTemplate();
	History = `XCOMHISTORY;<commit_msg>Clarify what CustomTargetStyles means for mod authors already using this<commit_after>/// HL-Docs: feature:CustomTargetStyles; issue:763; tags:tactical,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](../misc/ClassIsNative.md) 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 custom target style, your abilities will keep working the same way.

class XComGameState_Ability_CH extends XComGameState_Ability;

simulated function name GatherAbilityTargets(out array<AvailableTarget> Targets, optional XComGameState_Unit OverrideOwnerState)
{
	local int i, j;
	local XComGameState_Unit kOwner;
	local name AvailableCode;
	local XComGameStateHistory History;

	GetMyTemplate();
	History = `XCOMHISTORY;
{'fraction_non_alphanumeric': 0.07583879293230097, 'fraction_numerical': 0.001786777843954735, 'mean_word_length': 4.542354235423542, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6274296', 'n_tokens_mistral': 1283, 'n_tokens_neox': 1244, 'n_words': 606}