UE5.6的AbilitySystemComponent.h文件注释

这是一个非常庞大的头文件,包含了 Unreal Engine 中 Ability System 的核心组件 UAbilitySystemComponent 的定义。

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "Templates/SubclassOf.h"
#include "Engine/NetSerialization.h"
#include "Engine/EngineTypes.h"
#include "Engine/TimerHandle.h"
#include "GameplayTagContainer.h"
#include "AttributeSet.h"
#include "EngineDefines.h"
#include "GameplayPrediction.h"
#include "GameplayCueInterface.h"
#include "GameplayTagAssetInterface.h"
#include "GameplayAbilitySpec.h"
#include "GameplayEffect.h"
#include "GameplayTasksComponent.h"
#include "Abilities/GameplayAbilityRepAnimMontage.h"
#include "Abilities/GameplayAbilityTargetTypes.h"
#include "Abilities/GameplayAbility.h"
#include "AbilitySystemReplicationProxyInterface.h"
#include "Net/Core/PushModel/PushModel.h"
#include "AbilitySystemComponent.generated.h"

#define UE_API GAMEPLAYABILITIES_API

class AGameplayAbilityTargetActor;
class AHUD;
class FDebugDisplayInfo;
class UAnimMontage;
class UAnimSequenceBase;
class UCanvas;
class UInputComponent;

/** 
 *	UAbilitySystemComponent	
 *
 *	一个用于轻松与 AbilitySystem 的 3 个方面交互的组件:
 *	
 *	GameplayAbilities(游戏玩法能力):
 *		- 提供一种授予/分配能力的方式(例如,供玩家或 AI 使用)
 *		- 提供实例化能力的管理(必须有东西持有它们)
 *		- 提供复制功能
 *			- 能力状态必须始终在 UGameplayAbility 本身上复制,但 UAbilitySystemComponent 为能力的实际激活提供 RPC 复制
 *			
 *	GameplayEffects(游戏玩法效果):
 *		- 提供一个 FActiveGameplayEffectsContainer 用于持有激活的 GameplayEffects
 *		- 提供将 GameplayEffects 应用于目标或自身的方法
 *		- 提供用于查询 FActiveGameplayEffectsContainers 中信息的包装器(持续时间、强度等)
 *		- 提供清除/移除 GameplayEffects 的方法
 *		
 *	GameplayAttributes(游戏玩法属性)
 *		- 提供分配和初始化属性集的方法
 *		- 提供获取 AttributeSets 的方法
 *  
 */

/** 当目标选择 Actor 拒绝目标确认时调用 */
DECLARE_MULTICAST_DELEGATE_OneParam(FTargetingRejectedConfirmation, int32);

/** 当能力激活失败时调用,传递失败的能力和一个解释原因的标签 */
DECLARE_MULTICAST_DELEGATE_TwoParams(FAbilityFailedDelegate, const UGameplayAbility*, const FGameplayTagContainer&);

/** 当能力结束时调用 */
DECLARE_MULTICAST_DELEGATE_OneParam(FAbilityEnded, UGameplayAbility*);

/** 通知相关方能力规格已被修改 */
DECLARE_MULTICAST_DELEGATE_OneParam(FAbilitySpecDirtied, const FGameplayAbilitySpec&);

/** 当 GameplayEffectSpec 由于免疫而被 ActiveGameplayEffect 阻止时通知 */
DECLARE_MULTICAST_DELEGATE_TwoParams(FImmunityBlockGE, const FGameplayEffectSpec& /*BlockedSpec*/, const FActiveGameplayEffect* /*ImmunityGameplayEffect*/);

/** 我们允许一个委托列表来决定 Gameplay Effect 的应用是否可以被阻止。如果被阻止,将调用上面的 ImmunityBlockGE */
DECLARE_DELEGATE_RetVal_TwoParams(bool, FGameplayEffectApplicationQuery, const FActiveGameplayEffectsContainer& /*ActiveGEContainer*/, const FGameplayEffectSpec& /*GESpecToConsider*/);

/** 游戏玩法效果将如何复制到客户端 */
UENUM()
enum class EGameplayEffectReplicationMode : uint8
{
	/** 仅复制最少的游戏玩法效果信息。注意:这不适用于拥有的 AbilitySystemComponents(请改用 Mixed)。 */
	Minimal,
	/** 仅向模拟代理复制最少的游戏玩法效果信息,但向所有者和自主代理复制完整信息 */
	Mixed,
	/** 向所有对象复制完整的游戏玩法信息 */
	Full,
};

/** 当执行操作时(例如收集可激活能力),我们如何处理待处理项(例如,尚未添加或移除的能力) */
enum class EConsiderPending : uint8
{
	/** 不考虑任何待处理操作(例如待添加或移除的能力) */
	None = 0,

	/** 在执行操作时考虑待添加项 */
	PendingAdd = (1 << 0),

	/** 在执行操作时考虑待移除项 */
	PendingRemove = (1 << 1),

	All = PendingAdd | PendingRemove
};
ENUM_CLASS_FLAGS(EConsiderPending)

/** 用于与 GameplayAbilities 系统交互的核心 ActorComponent */
UCLASS(ClassGroup=AbilitySystem, hidecategories=(Object,LOD,Lighting,Transform,Sockets,TextureStreaming), editinlinenew, meta=(BlueprintSpawnableComponent), MinimalAPI)
class UAbilitySystemComponent : public UGameplayTasksComponent, public IGameplayTagAssetInterface, public IAbilitySystemReplicationProxyInterface
{
	GENERATED_UCLASS_BODY()

	/** 用于注册能力键输入的回调 */
	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAbilityAbilityKey, /*UGameplayAbility*, Ability, */int32, InputID);

	/** 用于注册确认/取消输入的回调 */
	DECLARE_DYNAMIC_MULTICAST_DELEGATE(FAbilityConfirmOrCancel);

	/** 当效果被应用时的委托 */
	DECLARE_MULTICAST_DELEGATE_ThreeParams(FOnGameplayEffectAppliedDelegate, UAbilitySystemComponent*, const FGameplayEffectSpec&, FActiveGameplayEffectHandle);

	// ----------------------------------------------------------------------------------------------------------------
	//	属性
	// ----------------------------------------------------------------------------------------------------------------

	/** 查找现有的 AttributeSet */
	template <class T >
	const T*	GetSet() const
	{
		return (T*)GetAttributeSubobject(T::StaticClass());
	}

	/** 查找现有的 AttributeSet。如果不存在则断言。 */
	template <class T >
	const T*	GetSetChecked() const
	{
		return (T*)GetAttributeSubobjectChecked(T::StaticClass());
	}

	/** 添加一个新的 AttributeSet(初始化为默认值) */
	template <class T >
	const T*  AddSet()
	{
		return (T*)GetOrCreateAttributeSubobject(T::StaticClass());
	}

	/** 
	 * 手动添加一个新的属性集,该属性集是此能力系统组件的子对象。
	 * 此组件的所有子对象在初始化期间都会自动添加。
	 */
	template <class T>
	const T* AddAttributeSetSubobject(T* Subobject)
	{
		AddSpawnedAttribute(Subobject);
		return Subobject;
	}

	/**
	 * 此能力系统组件是否具有此属性?
	 * 
	 * @param Attribute	要从中检索目标标签的游戏玩法效果的句柄
	 * 
	 * @return 如果 Attribute 有效且此能力系统组件包含一个包含 Attribute 的属性集,则返回 true。否则返回 false。
	 */
	UE_API bool HasAttributeSetForAttribute(FGameplayAttribute Attribute) const;

	/** 从数据表初始化起始属性。支持不佳,使用带有曲线表引用的游戏玩法效果可能是更好的解决方案 */
	UE_API const UAttributeSet* InitStats(TSubclassOf<class UAttributeSet> Attributes, const UDataTable* DataTable);

	UFUNCTION(BlueprintCallable, Category="Skills", meta=(DisplayName="InitStats", ScriptName="InitStats"))
	UE_API void K2_InitStats(TSubclassOf<class UAttributeSet> Attributes, const UDataTable* DataTable);
		
	/** 返回此能力系统组件的所有属性的列表 */
	UFUNCTION(BlueprintPure, Category="Gameplay Attributes")
	UE_API void GetAllAttributes(TArray<FGameplayAttribute>& OutAttributes);

	/**
	 * 返回属性集实例的引用(如果此组件中存在一个实例)
	 *
	 * @param AttributeSetClass 要查找的属性集类型
	 * @param bFound 如果属性集实例存在则设置为 true
	 */
	UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "Gameplay Attributes", meta=(DeterminesOutputType = AttributeSetClass))
	UE_API const UAttributeSet* GetAttributeSet(TSubclassOf<UAttributeSet> AttributeSetClass) const;

	/**
	 * 返回给定游戏玩法属性的当前值,如果未找到该属性则返回零。
	 * 注意:这不会考虑预测的游戏玩法效果修饰符,因此客户端的值可能并不总是准确的。
	 *
	 * @param Attribute 要查询的游戏玩法属性
	 * @param bFound 如果属性存在于此组件中则设置为 true
	 */
	UFUNCTION(BlueprintPure, Category = "Gameplay Attributes")
	UE_API float GetGameplayAttributeValue(FGameplayAttribute Attribute, bool& bFound) const;

	UPROPERTY(EditAnywhere, Category="AttributeTest")
	TArray<FAttributeDefaults>	DefaultStartingData; // 默认起始数据

	/** 移除所有当前 AttributeSets 并注册传入数组中的那些。注意,在可能的情况下,最好直接调用 Add/Remove。 */
	UE_API void SetSpawnedAttributes(const TArray<UAttributeSet*>& NewAttributeSet);

	UE_DEPRECATED(5.1, "此函数将变为私有。请改用 Add/Remove SpawnedAttributes")
	UE_API TArray<TObjectPtr<UAttributeSet>>& GetSpawnedAttributes_Mutable();

	/** 当你不打算修改列表时访问生成的属性列表。 */
	UE_API const TArray<UAttributeSet*>& GetSpawnedAttributes() const;

	/** 添加一个新的属性集 */
	UE_API void AddSpawnedAttribute(UAttributeSet* Attribute);

	/** 移除一个现有的属性集 */
	UE_API void RemoveSpawnedAttribute(UAttributeSet* Attribute);

	/** 移除所有属性集 */
	UE_API void RemoveAllSpawnedAttributes();


	/** 此组件将在其中播放蒙太奇的链接的 Anim Instance。使用 NAME_None 表示主动画实例。 */
	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Skills")
	FName AffectedAnimInstanceTag; // 受影响的动画实例标签


	/** 设置属性的基础值。不会清除现有的活动修饰符,它们将对新的基础值起作用。 */
	UE_API void SetNumericAttributeBase(const FGameplayAttribute &Attribute, float NewBaseValue);

	/** 获取属性的基础值。即,没有状态修饰符的属性值 */
	UE_API float GetNumericAttributeBase(const FGameplayAttribute &Attribute) const;

	/**
	 *	对给定属性应用原地修改。这会正确更新属性的聚合器,更新属性集属性,并调用 OnDirty 回调。
	 *	这不会在属性集上调用 Pre/PostGameplayEffectExecute。这不进行标签检查、应用要求、免疫等。
	 *	不会创建或应用 GameplayEffectSpec!
	 *	这应该仅在应用真实的 GameplayEffectSpec 太慢或不可能的情况下使用。
	 */
	UE_API void ApplyModToAttribute(const FGameplayAttribute &Attribute, TEnumAsByte<EGameplayModOp::Type> ModifierOp, float ModifierMagnitude);

	/**
	 *  对给定属性应用原地修改。与 ApplyModToAttribute 不同,此函数将在客户端或服务器上运行。
	 *  这可能会导致与预测相关的问题,并且无法正确回滚。
	 */
	UE_API void ApplyModToAttributeUnsafe(const FGameplayAttribute &Attribute, TEnumAsByte<EGameplayModOp::Type> ModifierOp, float ModifierMagnitude);

	/** 返回属性的当前(最终)值 */
	UE_API float GetNumericAttribute(const FGameplayAttribute &Attribute) const;
	UE_API float GetNumericAttributeChecked(const FGameplayAttribute &Attribute) const;

	/** 返回应用标签过滤器后的属性值 */
	UE_API float GetFilteredAttributeValue(const FGameplayAttribute& Attribute, const FGameplayTagRequirements& SourceTags, const FGameplayTagContainer& TargetTags, const TArray<FActiveGameplayEffectHandle>& HandlesToIgnore = TArray<FActiveGameplayEffectHandle>());

	// ----------------------------------------------------------------------------------------------------------------
	//	复制
	// ----------------------------------------------------------------------------------------------------------------

	/** 强制 Avatar Actor 更新其复制。对于需要为移动/位置原因进行复制的事情很有用。 */
	UE_API virtual void ForceAvatarReplication();

	/** 当为 true 时,我们将不会复制此能力系统组件的活动游戏玩法效果,因此属性和标签 */
	UE_API virtual void SetReplicationMode(EGameplayEffectReplicationMode NewReplicationMode);

	/** 游戏玩法效果如何被复制 */
	EGameplayEffectReplicationMode ReplicationMode; // 复制模式

	/** 如果启用了 ReplicationProxyEnabled,复制将通过谁路由(如果返回 null,当 ReplicationProxyEnabled 时,我们将不会复制) */
	UE_API virtual IAbilitySystemReplicationProxyInterface* GetReplicationInterface();

	/** 当前预测键,使用 FScopedPredictionWindow 设置 */
	FPredictionKey	ScopedPredictionKey; // 作用域预测键

	/** 返回应用于任何操作的预测键 */
	FPredictionKey GetPredictionKeyForNewAction() const
	{
		return ScopedPredictionKey.IsValidForMorePrediction() ? ScopedPredictionKey : FPredictionKey();
	}

	/** 我们是否有有效的预测键来进行更多的预测操作 */
	bool CanPredict() const
	{
		return ScopedPredictionKey.IsValidForMorePrediction();
	}

	/** 如果这是在服务器上运行或具有有效的预测键,则返回 true */
	UE_API bool HasAuthorityOrPredictionKey(const FGameplayAbilityActivationInfo* ActivationInfo) const;

	/** 如果此组件的 Actor 具有权限,则返回 true */
	UE_API virtual bool IsOwnerActorAuthoritative() const;

	/** 如果此组件应记录蒙太奇复制信息,则返回 true */
	UE_API virtual bool ShouldRecordMontageReplication() const;

	/** 将能力已结束/取消的信息复制到客户端或服务器(视情况而定) */
	UE_API virtual void ReplicateEndOrCancelAbility(FGameplayAbilitySpecHandle Handle, FGameplayAbilityActivationInfo ActivationInfo, UGameplayAbility* Ability, bool bWasCanceled);

	/** 强制取消能力并且不将此复制到另一端。当能力被另一端取消时应调用此函数 */
	UE_API virtual void ForceCancelAbilityDueToReplication(UGameplayAbility* Instance);

	/** 一个尚不能激活的待处理激活,将在稍后时间点重新检查 */
	struct FPendingAbilityInfo
	{
		bool operator==(const FPendingAbilityInfo& Other) const
		{
			// 不要比较事件数据,不允许具有相同键和句柄但不同事件数据的多个激活在飞行中
			return PredictionKey == Other.PredictionKey	&& Handle == Other.Handle;
		}

		/** 需要激活的能力的属性 */
		FGameplayAbilitySpecHandle Handle; // 能力规格句柄
		FPredictionKey	PredictionKey; // 预测键
		FGameplayEventData TriggerEventData; // 触发事件数据

		/** 如果此能力已在远程激活并需要跟进,则为 true;如果能力尚未激活,则为 false */
		bool bPartiallyActivated; // 是否部分激活

		FPendingAbilityInfo()
			: bPartiallyActivated(false)
		{}
	};

	/** 这是在服务器上激活但尚不能在客户端上执行的 GameplayAbilities 列表。它将在稍后时间点尝试执行这些操作 */
	TArray<FPendingAbilityInfo> PendingServerActivatedAbilities; // 待处理的服务器激活能力

	// ----------------------------------------------------------------------------------------------------------------
	//	GameplayEffects: 供其他系统使用的主要对外 API
	// ----------------------------------------------------------------------------------------------------------------

	/** 将先前创建的游戏玩法效果规格应用于目标 */
	UFUNCTION(BlueprintCallable, Category = GameplayEffects, meta = (DisplayName = "ApplyGameplayEffectSpecToTarget", ScriptName = "ApplyGameplayEffectSpecToTarget"))
	UE_API FActiveGameplayEffectHandle BP_ApplyGameplayEffectSpecToTarget(const FGameplayEffectSpecHandle& SpecHandle, UAbilitySystemComponent* Target);

	UE_API virtual FActiveGameplayEffectHandle ApplyGameplayEffectSpecToTarget(const FGameplayEffectSpec& GameplayEffect, UAbilitySystemComponent *Target, FPredictionKey PredictionKey=FPredictionKey());

	/** 将先前创建的游戏玩法效果规格应用于此组件 */
	UFUNCTION(BlueprintCallable, Category = GameplayEffects, meta = (DisplayName = "ApplyGameplayEffectSpecToSelf", ScriptName = "ApplyGameplayEffectSpecToSelf"))
	UE_API FActiveGameplayEffectHandle BP_ApplyGameplayEffectSpecToSelf(const FGameplayEffectSpecHandle& SpecHandle);

	UE_API virtual FActiveGameplayEffectHandle ApplyGameplayEffectSpecToSelf(const FGameplayEffectSpec& GameplayEffect, FPredictionKey PredictionKey = FPredictionKey());

	/** 根据传入的句柄获取 FActiveGameplayEffect */
	UE_API const UGameplayEffect* GetGameplayEffectDefForHandle(FActiveGameplayEffectHandle Handle);

	/** 
	* 通过句柄移除指定的 GameplayEffect。
	* @param Handle								要移除的游戏玩法效果的句柄
	* @param StacksToRemove						要移除的堆叠数,-1 表示移除所有
	* 
	* @return 效果是否成功移除。
	*/
	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = GameplayEffects)
	UE_API virtual bool RemoveActiveGameplayEffect(FActiveGameplayEffectHandle Handle, int32 StacksToRemove=-1);

	/** 
	 * 移除后备定义是指定游戏玩法效果类的活动游戏玩法效果
	 * 
	 * @param GameplayEffect					要移除的游戏玩法效果类;如果留空则不执行任何操作
	 * @param InstigatorAbilitySystemComponent	如果指定,将仅移除从此 instigator 能力系统组件应用的游戏玩法效果
	 * @param StacksToRemove					要移除的堆叠数,-1 表示移除所有
	 */
	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = GameplayEffects)
	UE_API virtual void RemoveActiveGameplayEffectBySourceEffect(TSubclassOf<UGameplayEffect> GameplayEffect, UAbilitySystemComponent* InstigatorAbilitySystemComponent, int32 StacksToRemove = -1);

	/** 获取一个准备应用于其他事物的传出 GameplayEffectSpec。 */
	UFUNCTION(BlueprintCallable, Category = GameplayEffects)
	UE_API virtual FGameplayEffectSpecHandle MakeOutgoingSpec(TSubclassOf<UGameplayEffect> GameplayEffectClass, float Level, FGameplayEffectContextHandle Context) const;

	/** 为此 AbilitySystemComponent 的所有者创建一个 EffectContext */
	UFUNCTION(BlueprintCallable, Category = GameplayEffects)
	UE_API virtual FGameplayEffectContextHandle MakeEffectContext() const;

	/**
	 * 获取能力系统组件上指定源效果的计数。对于非堆叠效果,这是所有活动实例的总和。
	 * 对于堆叠效果,这是所有有效堆叠计数的总和。如果指定了 instigator,则仅计算来自该 instigator 的效果。
	 * 
	 * @param SourceGameplayEffect					要获取计数的效果
	 * @param OptionalInstigatorFilterComponent		如果指定,仅计算由此能力系统组件应用的效果
	 * 
	 * @return 指定源效果的计数
	 */
	UFUNCTION(BlueprintCallable, BlueprintPure, Category=GameplayEffects)
	UE_API int32 GetGameplayEffectCount(TSubclassOf<UGameplayEffect> SourceGameplayEffect, UAbilitySystemComponent* OptionalInstigatorFilterComponent, bool bEnforceOnGoingCheck = true) const;

	/**
	 * 获取能力系统组件上指定源效果的计数。对于非堆叠效果,这是所有活动实例的总和。
	 * 对于堆叠效果,这是所有有效堆叠计数的总和。如果指定了 instigator,则仅计算来自该 instigator 的效果。
	 * 
	 * @param SoftSourceGameplayEffect				要获取计数的效果。如果当前未加载,则计数为 0
	 * @param OptionalInstigatorFilterComponent		如果指定,仅计算由此能力系统组件应用的效果
	 * 
	 * @return 指定源效果的计数
	 */
	UFUNCTION(BlueprintCallable, BlueprintPure, Category = GameplayEffects)
	UE_API int32 GetGameplayEffectCount_IfLoaded(TSoftClassPtr<UGameplayEffect> SoftSourceGameplayEffect, UAbilitySystemComponent* OptionalInstigatorFilterComponent, bool bEnforceOnGoingCheck = true) const;

	/** 返回通过查询的所有游戏玩法效果的 StackCount 的总和 */
	UE_API int32 GetAggregatedStackCount(const FGameplayEffectQuery& Query) const;

	/** 这仅存在以便它可以连接到多播委托 */
	UE_DEPRECATED_FORGAME(5.5, "这不应该是公共的。使用 RemoveActiveGameplayEffect(不允许非权限移除)或公开 RemoveActiveGameplayEffect_AllowClientRemoval 如果你的意图是打破该契约。")
	UE_API void RemoveActiveGameplayEffect_NoReturn(FActiveGameplayEffectHandle Handle, int32 StacksToRemove = -1);

	/** 为预测添加的游戏玩法提示调用。需要移除标签计数,并在预测错误时可能调用 OnRemove 事件 */
	UE_API virtual void OnPredictiveGameplayCueCatchup(FGameplayTag Tag);

	/** 返回游戏玩法效果的总持续时间 */
	UE_API float GetGameplayEffectDuration(FActiveGameplayEffectHandle Handle) const;

	/** 当服务器时间通过游戏状态复制时调用,以使我们的冷却计时器与服务器保持同步 */
	UE_API virtual void RecomputeGameplayEffectStartTimes(const float WorldTime, const float ServerWorldTime);

	/** 返回游戏玩法效果的开始时间和总持续时间 */
	UE_API void GetGameplayEffectStartTimeAndDuration(FActiveGameplayEffectHandle Handle, float& StartEffectTime, float& Duration) const;

	/** 动态更新活动游戏玩法效果的 set-by-caller 强度 */
	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = GameplayEffects)
	UE_API virtual void UpdateActiveGameplayEffectSetByCallerMagnitude(FActiveGameplayEffectHandle ActiveHandle, UPARAM(meta=(Categories = "SetByCaller"))FGameplayTag SetByCallerTag, float NewValue);

	/** 动态更新活动游戏玩法效果的多个 set-by-caller 强度 */
	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = GameplayEffects)
	UE_API virtual void UpdateActiveGameplayEffectSetByCallerMagnitudes(FActiveGameplayEffectHandle ActiveHandle, const TMap<FGameplayTag, float>& NewSetByCallerValues);

	/** 更新已应用游戏玩法效果的等级。意图是这是“无缝的”,并且不像移除/重新应用那样行为 */
	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = GameplayEffects)
	UE_API virtual void SetActiveGameplayEffectLevel(FActiveGameplayEffectHandle ActiveHandle, int32 NewLevel);

	/** 更新已应用游戏玩法效果的等级。意图是这是“无缝的”,并且不像移除/重新应用那样行为 */
	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = GameplayEffects)
	UE_API virtual void SetActiveGameplayEffectLevelUsingQuery(FGameplayEffectQuery Query, int32 NewLevel);

	/** 抑制活动游戏玩法效果,使其被禁用但未被移除 */
	UE_DEPRECATED(5.4, "使用 SetActiveGameplayEffectInhibit 并配合 MoveTemp(ActiveGEHandle),以便清楚地表明 Handle 不再有效。检查(然后使用)返回的 FActiveGameplayEffectHandle 以继续你的操作。")
	UE_API virtual void InhibitActiveGameplayEffect(FActiveGameplayEffectHandle ActiveGEHandle, bool bInhibit, bool bInvokeGameplayCueEvents);

	/**
	 * (取消)抑制活动游戏玩法效果,以便可以禁用它(并执行一些禁用操作,例如移除标签)。
	 * 被抑制的活动游戏玩法效果将处于休眠状态,以便在某个条件(通常是标签)下重新启用。当它被取消抑制时,它将重新应用其部分功能。
	 * 注意:传入的 ActiveGEHandle 不再有效。使用返回的 FActiveGameplayEffectHandle 来确定 Active GE Handle 是否仍处于活动状态。
	 */
	UE_API virtual FActiveGameplayEffectHandle SetActiveGameplayEffectInhibit(FActiveGameplayEffectHandle&& ActiveGEHandle, bool bInhibit, bool bInvokeGameplayCueEvents);

	/**
	 * 游戏玩法效果强度的原始访问器,不一定总是正确的。外部代码(UI 等)应该如何询问诸如“这个游戏玩法效果修改了我的多少伤害”之类的问题
	 * (很可能我们希望在后端捕获这一点 - 当伤害被应用时,我们可以获得数字如何到达那里的完整转储/历史记录。但我们仍然可能需要像下面这样的轮询方法(我的伤害会是多少)
	 */
	UFUNCTION(BlueprintCallable, Category = GameplayEffects)
	UE_API float GetGameplayEffectMagnitude(FActiveGameplayEffectHandle Handle, FGameplayAttribute Attribute) const;

	/** 返回已应用 GE 的当前堆叠计数 */
	UE_API int32 GetCurrentStackCount(FActiveGameplayEffectHandle Handle) const;

	/** 返回已应用 GE 的当前堆叠计数,但给定由 GE 授予的能力规格句柄 */
	UE_API int32 GetCurrentStackCount(FGameplayAbilitySpecHandle Handle) const;

	/** 返回描述活动游戏玩法效果的调试字符串 */
	UE_API FString GetActiveGEDebugString(FActiveGameplayEffectHandle Handle) const;

	/** 获取授予传入能力的 GE 的 GE 句柄 */
	UE_API FActiveGameplayEffectHandle FindActiveGameplayEffectHandle(FGameplayAbilitySpecHandle Handle) const;

	/** 返回实际活动游戏玩法效果结构的常量指针 */
	UE_API const FActiveGameplayEffect* GetActiveGameplayEffect(const FActiveGameplayEffectHandle Handle) const;

	/** 返回此 ASC 上的所有活动游戏玩法效果 */
	UE_API const FActiveGameplayEffectsContainer& GetActiveGameplayEffects() const;

	/** 返回与活动句柄关联的游戏玩法效果 CDO 的常量指针。 */
	UE_API const UGameplayEffect* GetGameplayEffectCDO(const FActiveGameplayEffectHandle Handle) const;

	/**
	 * 如果可能,从指定句柄表示的游戏玩法规格中获取源标签
	 * 
	 * @param Handle	要从中检索源标签的游戏玩法效果的句柄
	 * 
	 * @return 如果可能,从句柄表示的游戏玩法规格中获取的源标签
	 */
	UE_API const FGameplayTagContainer* GetGameplayEffectSourceTagsFromHandle(FActiveGameplayEffectHandle Handle) const;

	/**
	 * 如果可能,从指定句柄表示的游戏玩法规格中获取目标标签
	 * 
	 * @param Handle	要从中检索目标标签的游戏玩法效果的句柄
	 * 
	 * @return 如果可能,从句柄表示的游戏玩法规格中获取的目标标签
	 */
	UE_API const FGameplayTagContainer* GetGameplayEffectTargetTagsFromHandle(FActiveGameplayEffectHandle Handle) const;

	/**
	 * 使用从组件捕获属性所需的数据填充指定的捕获规格
	 * 
	 * @param OutCaptureSpec	[OUT] 要用捕获数据填充的捕获规格
	 */
	UE_API void CaptureAttributeForGameplayEffect(OUT FGameplayEffectAttributeCaptureSpec& OutCaptureSpec);
	
	// ----------------------------------------------------------------------------------------------------------------
	//  回调 / 通知
	//  (这些需要在 UObject 级别,以便我们可以安全地绑定,而不是绑定到 ActiveGameplayEffect/Container 级别的原始数据,如果 AbilitySystemComponent 被杀死,这是不安全的)。
	// ----------------------------------------------------------------------------------------------------------------

	/** 当特定属性聚合器值更改时调用,游戏玩法效果在此发生时刷新其值 */
	UE_API void OnAttributeAggregatorDirty(FAggregator* Aggregator, FGameplayAttribute Attribute, bool FromRecursiveCall=false);

	/** 当属性强度更改时调用,以将信息转发给依赖的游戏玩法效果 */
	UE_API void OnMagnitudeDependencyChange(FActiveGameplayEffectHandle Handle, const FAggregator* ChangedAggregator);

	/** 此 ASC 已成功将 GE 应用于某物(可能是自身) */
	UE_API void OnGameplayEffectAppliedToTarget(UAbilitySystemComponent* Target, const FGameplayEffectSpec& SpecApplied, FActiveGameplayEffectHandle ActiveHandle);
	UE_API void OnGameplayEffectAppliedToSelf(UAbilitySystemComponent* Source, const FGameplayEffectSpec& SpecApplied, FActiveGameplayEffectHandle ActiveHandle);
	UE_API void OnPeriodicGameplayEffectExecuteOnTarget(UAbilitySystemComponent* Target, const FGameplayEffectSpec& SpecExecuted, FActiveGameplayEffectHandle ActiveHandle);
	UE_API void OnPeriodicGameplayEffectExecuteOnSelf(UAbilitySystemComponent* Source, const FGameplayEffectSpec& SpecExecuted, FActiveGameplayEffectHandle ActiveHandle);

	/** 当游戏玩法效果的持续时间发生变化时调用 */
	UE_API virtual void OnGameplayEffectDurationChange(struct FActiveGameplayEffect& ActiveEffect);

	/** 在服务器上当 GE 应用于自身时调用。这包括即时和基于持续时间的 GE。 */
	FOnGameplayEffectAppliedDelegate OnGameplayEffectAppliedDelegateToSelf; // 应用于自身的游戏玩法效果委托

	/** 在服务器上当 GE 应用于其他人时调用。这包括即时和基于持续时间的 GE。 */
	FOnGameplayEffectAppliedDelegate OnGameplayEffectAppliedDelegateToTarget; // 应用于目标的游戏玩法效果委托

	/** 在客户端和服务器上当基于持续时间的 GE 被添加时调用(例如,即时 GE 不会触发此操作)。 */
	FOnGameplayEffectAppliedDelegate OnActiveGameplayEffectAddedDelegateToSelf; // 添加到自身的活动游戏玩法效果委托

	/** 在服务器上当周期性 GE 在自身执行时调用 */
	FOnGameplayEffectAppliedDelegate OnPeriodicGameplayEffectExecuteDelegateOnSelf; // 在自身执行的周期性游戏玩法效果委托

	/** 在服务器上当周期性 GE 在目标上执行时调用 */
	FOnGameplayEffectAppliedDelegate OnPeriodicGameplayEffectExecuteDelegateOnTarget; // 在目标上执行的周期性游戏玩法效果委托

	/** 免疫通知支持 */
	FImmunityBlockGE OnImmunityBlockGameplayEffectDelegate; // 免疫阻止游戏玩法效果委托

	/** 注册属性值更改时的回调,应被 GetGameplayAttributeValueChangeDelegate 替换 */
	UE_API FOnGameplayAttributeChange& RegisterGameplayAttributeEvent(FGameplayAttribute Attribute);

	/** 注册属性值更改时的回调 */
	UE_API FOnGameplayAttributeValueChange& GetGameplayAttributeValueChangeDelegate(FGameplayAttribute Attribute);

	/** 任何时候能力被激活(开始)时的通用回调 */
	FGenericAbilityDelegate AbilityActivatedCallbacks; // 能力激活回调

	/** 任何时候能力结束时的回调 */
	FAbilityEnded AbilityEndedCallbacks; // 能力结束回调

	/** 任何时候能力结束时的回调,带有额外信息 */
	FGameplayAbilityEndedDelegate OnAbilityEnded; // 能力结束委托

	/** 任何时候能力被提交(应用成本/冷却时间)时的通用回调 */
	FGenericAbilityDelegate AbilityCommittedCallbacks; // 能力提交回调

	/** 当能力激活失败时调用,带有失败原因 */
	FAbilityFailedDelegate AbilityFailedCallbacks; // 能力失败回调

	/** 当能力规格的内部发生更改时调用 */
	FAbilitySpecDirtied AbilitySpecDirtiedCallbacks; // 能力规格变脏回调

	/** 我们允许用户设置一系列必须为 true 的函数才能允许应用 GameplayEffect */
	TArray<FGameplayEffectApplicationQuery> GameplayEffectApplicationQueries; // 游戏玩法效果应用查询

	/** 调用上面的通知回调 */
	UE_API virtual void NotifyAbilityCommit(UGameplayAbility* Ability);
	UE_API virtual void NotifyAbilityActivated(const FGameplayAbilitySpecHandle Handle, UGameplayAbility* Ability);
	UE_API virtual void NotifyAbilityFailed(const FGameplayAbilitySpecHandle Handle, UGameplayAbility* Ability, const FGameplayTagContainer& FailureReason);

	/** 当任何游戏玩法效果被移除时调用 */
	UE_API FOnGivenActiveGameplayEffectRemoved& OnAnyGameplayEffectRemovedDelegate();

	/** 返回允许绑定到多个游戏玩法效果更改的委托结构 */
	UE_API FActiveGameplayEffectEvents* GetActiveEffectEventSet(FActiveGameplayEffectHandle Handle);
	UE_API FOnActiveGameplayEffectRemoved_Info* OnGameplayEffectRemoved_InfoDelegate(FActiveGameplayEffectHandle Handle);
	UE_API FOnActiveGameplayEffectStackChange* OnGameplayEffectStackChangeDelegate(FActiveGameplayEffectHandle Handle);
	UE_API FOnActiveGameplayEffectTimeChange* OnGameplayEffectTimeChangeDelegate(FActiveGameplayEffectHandle Handle);
	UE_API FOnActiveGameplayEffectInhibitionChanged* OnGameplayEffectInhibitionChangedDelegate(FActiveGameplayEffectHandle Handle);

	// ----------------------------------------------------------------------------------------------------------------
	//  游戏玩法标签操作
	//  使用 TagCountContainer 实现 IGameplayTagAssetInterface
	// ----------------------------------------------------------------------------------------------------------------
	FORCEINLINE bool HasMatchingGameplayTag(FGameplayTag TagToCheck) const override
	{
		return GameplayTagCountContainer.HasMatchingGameplayTag(TagToCheck);
	}

	FORCEINLINE bool HasAllMatchingGameplayTags(const FGameplayTagContainer& TagContainer) const override
	{
		return GameplayTagCountContainer.HasAllMatchingGameplayTags(TagContainer);
	}

	FORCEINLINE bool HasAnyMatchingGameplayTags(const FGameplayTagContainer& TagContainer) const override
	{
		return GameplayTagCountContainer.HasAnyMatchingGameplayTags(TagContainer);
	}

	FORCEINLINE void GetOwnedGameplayTags(FGameplayTagContainer& TagContainer) const override
	{
		TagContainer.Reset();
		TagContainer.AppendTags(GetOwnedGameplayTags());
	}

	[[nodiscard]] FORCEINLINE const FGameplayTagContainer& GetOwnedGameplayTags() const
	{
		return GameplayTagCountContainer.GetExplicitGameplayTags();
	}

	/** 检查查询是否匹配拥有的 GameplayTags */
	FORCEINLINE bool MatchesGameplayTagQuery(const FGameplayTagQuery& TagQuery) const
	{
		return TagQuery.Matches(GameplayTagCountContainer.GetExplicitGameplayTags());
	}

	/** 返回给定标签的实例数 */
	FORCEINLINE int32 GetTagCount(FGameplayTag TagToCheck) const
	{
		return GameplayTagCountContainer.GetTagCount(TagToCheck);
	}

	/** 强制设置给定标签的实例数 */
	FORCEINLINE void SetTagMapCount(const FGameplayTag& Tag, int32 NewCount)
	{
		GameplayTagCountContainer.SetTagCount(Tag, NewCount);
	}

	/** 更新给定标签的实例数并调用回调 */
	FORCEINLINE void UpdateTagMap(const FGameplayTag& BaseTag, int32 CountDelta)
	{
		if (GameplayTagCountContainer.UpdateTagCount(BaseTag, CountDelta))
		{
			OnTagUpdated(BaseTag, CountDelta > 0);
		}
	}

	/** 更新给定标签的实例数并调用回调 */
	FORCEINLINE void UpdateTagMap(const FGameplayTagContainer& Container, int32 CountDelta)
	{
		if (!Container.IsEmpty())
		{
			UpdateTagMap_Internal(Container, CountDelta);
		}
	}

	/** 用 BlockedAbilityTags 填充 TagContainer */
	FORCEINLINE void GetBlockedAbilityTags(FGameplayTagContainer& TagContainer) const
	{
		TagContainer.AppendTags(GetBlockedAbilityTags());
	}

	[[nodiscard]] FORCEINLINE const FGameplayTagContainer& GetBlockedAbilityTags() const
	{
		return BlockedAbilityTags.GetExplicitGameplayTags();
	}

	/** 	 
	 *  允许游戏代码添加不受 GameplayEffect 支持的松散游戏玩法标签。
	 *	以此方式添加的标签不会被复制!如果需要复制,请使用这些函数的“Replicated”版本。
	 *	由调用游戏代码确保在必要的客户端/服务器上添加这些标签
	 */
	FORCEINLINE void AddLooseGameplayTag(const FGameplayTag& GameplayTag, int32 Count=1)
	{
		UpdateTagMap(GameplayTag, Count);
	}

	FORCEINLINE void AddLooseGameplayTags(const FGameplayTagContainer& GameplayTags, int32 Count = 1)
	{
		UpdateTagMap(GameplayTags, Count);
	}

	FORCEINLINE void RemoveLooseGameplayTag(const FGameplayTag& GameplayTag, int32 Count = 1)
	{
		UpdateTagMap(GameplayTag, -Count);
	}

	FORCEINLINE void RemoveLooseGameplayTags(const FGameplayTagContainer& GameplayTags, int32 Count = 1)
	{
		UpdateTagMap(GameplayTags, -Count);
	}

	FORCEINLINE void SetLooseGameplayTagCount(const FGameplayTag& GameplayTag, int32 NewCount)
	{
		SetTagMapCount(GameplayTag, NewCount);
	}

	/**
	 * 返回给定游戏玩法标签的当前计数。
	 * 这包括松散标签,以及由游戏玩法效果和能力授予的标签。
	 * 此函数可以在客户端上调用,但它可能不会显示服务器上的最新计数。
	 *
	 * @param GameplayTag 要查询的游戏玩法标签
	 */
	UFUNCTION(BlueprintPure, Category = "Gameplay Tags")
	UE_API int32 GetGameplayTagCount(FGameplayTag GameplayTag) const;

	/**
	 *  允许游戏代码添加不受 GameplayEffect 支持的松散游戏玩法标签。使用 
	 *  这些函数添加的标签将被复制。注意,复制的松散标签将覆盖模拟代理上任何本地设置的标签计数
	 * 。
	 */
	FORCEINLINE void AddReplicatedLooseGameplayTag(const FGameplayTag& GameplayTag)
	{
		GetReplicatedLooseTags_Mutable().AddTag(GameplayTag);
	}

	FORCEINLINE void AddReplicatedLooseGameplayTags(const FGameplayTagContainer& GameplayTags)
	{
		GetReplicatedLooseTags_Mutable().AddTags(GameplayTags);
	}

	FORCEINLINE void RemoveReplicatedLooseGameplayTag(const FGameplayTag& GameplayTag)
	{
		GetReplicatedLooseTags_Mutable().RemoveTag(GameplayTag);
	}

	FORCEINLINE void RemoveReplicatedLooseGameplayTags(const FGameplayTagContainer& GameplayTags)
	{
		GetReplicatedLooseTags_Mutable().RemoveTags(GameplayTags);
	}

	FORCEINLINE void SetReplicatedLooseGameplayTagCount(const FGameplayTag& GameplayTag, int32 NewCount)
	{
		GetReplicatedLooseTags_Mutable().SetTagCount(GameplayTag, NewCount);
	}

	/** 	 
	 * 最小复制标签是当处于 bMinimalReplication 模式时来自 GE 的复制标签。
	 * (GE 不复制,但它们授予的标签通过这些函数复制)
	 */
	FORCEINLINE void AddMinimalReplicationGameplayTag(const FGameplayTag& GameplayTag)
	{
		GetMinimalReplicationTags_Mutable().AddTag(GameplayTag);
	}

	FORCEINLINE void AddMinimalReplicationGameplayTags(const FGameplayTagContainer& GameplayTags)
	{
		GetMinimalReplicationTags_Mutable().AddTags(GameplayTags);
	}

	FORCEINLINE void RemoveMinimalReplicationGameplayTag(const FGameplayTag& GameplayTag)
	{
		GetMinimalReplicationTags_Mutable().RemoveTag(GameplayTag);
	}

	FORCEINLINE void RemoveMinimalReplicationGameplayTags(const FGameplayTagContainer& GameplayTags)
	{
		GetMinimalReplicationTags_Mutable().RemoveTags(GameplayTags);
	}

	/** 允许注册特定游戏玩法标签被添加或移除时的事件 */
	UE_API FOnGameplayEffectTagCountChanged& RegisterGameplayTagEvent(FGameplayTag Tag, EGameplayTagEventType::Type EventType=EGameplayTagEventType::NewOrRemoved);

	/** 取消注册先前添加的事件 */
	UE_API bool UnregisterGameplayTagEvent(FDelegateHandle DelegateHandle, FGameplayTag Tag, EGameplayTagEventType::Type EventType=EGameplayTagEventType::NewOrRemoved);

	/** 注册标签事件并立即调用它 */
	UE_API FDelegateHandle RegisterAndCallGameplayTagEvent(FGameplayTag Tag, FOnGameplayEffectTagCountChanged::FDelegate Delegate, EGameplayTagEventType::Type EventType=EGameplayTagEventType::NewOrRemoved);

	/** 返回多播委托,每当标签被添加或移除时调用(但不仅仅是计数增加时。仅适用于“新”和“移除”事件) */
	UE_API FOnGameplayEffectTagCountChanged& RegisterGenericGameplayTagEvent();

	/** 执行游戏玩法事件。返回由事件触发的成功能力激活次数 */
	UE_API virtual int32 HandleGameplayEvent(FGameplayTag EventTag, const FGameplayEventData* Payload);

	/** 添加一个新的委托,在游戏玩法事件发生时调用。仅当它与传入过滤器容器中的任何标签匹配时才会被调用 */
	UE_API FDelegateHandle AddGameplayEventTagContainerDelegate(const FGameplayTagContainer& TagFilter, const FGameplayEventTagMulticastDelegate::FDelegate& Delegate);

	/** 移除先前注册的委托 */
	UE_API void RemoveGameplayEventTagContainerDelegate(const FGameplayTagContainer& TagFilter, FDelegateHandle DelegateHandle);

	/** 绑定到游戏玩法标签的回调,这些回调仅在使用了确切的标签时激活。要处理标签层次结构,请使用 AddGameplayEventContainerDelegate */
	TMap<FGameplayTag, FGameplayEventMulticastDelegate> GenericGameplayEventCallbacks; // 通用游戏玩法事件回调

	// ----------------------------------------------------------------------------------------------------------------
	//  系统属性
	// ----------------------------------------------------------------------------------------------------------------

	/** 内部属性,用于修改此组件创建的游戏玩法效果的持续时间 */
	UPROPERTY(meta=(SystemGameplayAttribute="true"))
	float OutgoingDuration; // 传出持续时间

	/** 内部属性,用于修改应用于此组件的游戏玩法效果的持续时间 */
	UPROPERTY(meta = (SystemGameplayAttribute = "true"))
	float IncomingDuration; // 传入持续时间

	static UE_API FProperty* GetOutgoingDurationProperty();
	static UE_API FProperty* GetIncomingDurationProperty();

	static UE_API const FGameplayEffectAttributeCaptureDefinition& GetOutgoingDurationCapture();
	static UE_API const FGameplayEffectAttributeCaptureDefinition& GetIncomingDurationCapture();

	// ----------------------------------------------------------------------------------------------------------------
	//  附加辅助函数
	// ----------------------------------------------------------------------------------------------------------------

	/** 将游戏玩法效果应用于传入的目标 */
	UFUNCTION(BlueprintCallable, Category = GameplayEffects, meta=(DisplayName = "ApplyGameplayEffectToTarget", ScriptName = "ApplyGameplayEffectToTarget"))
	UE_API FActiveGameplayEffectHandle BP_ApplyGameplayEffectToTarget(TSubclassOf<UGameplayEffect> GameplayEffectClass, UAbilitySystemComponent *Target, float Level, FGameplayEffectContextHandle Context);
	UE_API FActiveGameplayEffectHandle ApplyGameplayEffectToTarget(UGameplayEffect *GameplayEffect, UAbilitySystemComponent *Target, float Level = UGameplayEffect::INVALID_LEVEL, FGameplayEffectContextHandle Context = FGameplayEffectContextHandle(), FPredictionKey PredictionKey = FPredictionKey());

	/** 将游戏玩法效果应用于自身 */
	UFUNCTION(BlueprintCallable, Category = GameplayEffects, meta=(DisplayName = "ApplyGameplayEffectToSelf", ScriptName = "ApplyGameplayEffectToSelf"))
	UE_API FActiveGameplayEffectHandle BP_ApplyGameplayEffectToSelf(TSubclassOf<UGameplayEffect> GameplayEffectClass, float Level, FGameplayEffectContextHandle EffectContext);
	UE_API FActiveGameplayEffectHandle ApplyGameplayEffectToSelf(const UGameplayEffect *GameplayEffect, float Level, const FGameplayEffectContextHandle& EffectContext, FPredictionKey PredictionKey = FPredictionKey());

	/** 返回此能力系统组件上当前活动的游戏玩法效果的数量 */
	int32 GetNumActiveGameplayEffects() const
	{
		return ActiveGameplayEffects.GetNumGameplayEffects();
	}

	/** 复制此能力组件上所有活动效果的副本 */
	void GetAllActiveGameplayEffectSpecs(TArray<FGameplayEffectSpec>& OutSpecCopies) const
	{
		ActiveGameplayEffects.GetAllActiveGameplayEffectSpecs(OutSpecCopies);
	}

	/** 从 OnRep 函数调用,以在客户端上设置属性基础值 */
	void SetBaseAttributeValueFromReplication(const FGameplayAttribute& Attribute, float NewValue, float OldValue)
	{
		ActiveGameplayEffects.SetBaseAttributeValueFromReplication(Attribute, FGameplayAttributeData(NewValue), FGameplayAttributeData(OldValue) );
	}

	/** 从 OnRep 函数调用,以在客户端上设置属性基础值 */
	void SetBaseAttributeValueFromReplication(const FGameplayAttribute& Attribute, const FGameplayAttributeData& NewValue, const FGameplayAttributeData& OldValue)
	{
		ActiveGameplayEffects.SetBaseAttributeValueFromReplication(Attribute, NewValue, OldValue);
	}

	/** 测试此 GameplayEffect 中的所有修饰符是否会使属性 > 0.f */
	bool CanApplyAttributeModifiers(const UGameplayEffect *GameplayEffect, float Level, const FGameplayEffectContextHandle& EffectContext)
	{
		return ActiveGameplayEffects.CanApplyAttributeModifiers(GameplayEffect, Level, EffectContext);
	}

	/** 获取匹配查询的所有效果的剩余时间 */
	UE_API TArray<float> GetActiveEffectsTimeRemaining(const FGameplayEffectQuery& Query) const;

	/** 获取匹配查询的所有效果的总持续时间 */
	UE_API TArray<float> GetActiveEffectsDuration(const FGameplayEffectQuery& Query) const;

	/** 获取匹配查询的所有效果的剩余时间和总持续时间 */
	UE_API TArray<TPair<float,float>> GetActiveEffectsTimeRemainingAndDuration(const FGameplayEffectQuery& Query) const;

	/** 返回查询的活动效果列表 */
	UFUNCTION(BlueprintCallable, BlueprintPure=false, Category = "GameplayEffects", meta=(DisplayName = "Get Active Gameplay Effects for Query"))
	UE_API TArray<FActiveGameplayEffectHandle> GetActiveEffects(const FGameplayEffectQuery& Query) const;

	/** 返回具有所有传入标签的活动效果列表 */
	UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "GameplayEffects")
	UE_API TArray<FActiveGameplayEffectHandle> GetActiveEffectsWithAllTags(FGameplayTagContainer Tags) const;

	/** 这将给出匹配此查询的所有效果将完成的世界时间。如果多个效果匹配,则返回最后一个返回的效果 */
	UE_API float GetActiveEffectsEndTime(const FGameplayEffectQuery& Query) const;
	UE_API float GetActiveEffectsEndTimeWithInstigators(const FGameplayEffectQuery& Query, TArray<AActor*>& Instigators) const;

	/** 返回结束时间和总持续时间 */
	UE_API bool GetActiveEffectsEndTimeAndDuration(const FGameplayEffectQuery& Query, float& EndTime, float& Duration) const;

	/** 修改游戏玩法效果的开始时间,以处理最初不同步的计时器 */
	UE_API virtual void ModifyActiveEffectStartTime(FActiveGameplayEffectHandle Handle, float StartTimeDiff);

	/** 移除所有包含 Tags 中任何标签的活动效果 */
	UFUNCTION(BlueprintCallable, Category = GameplayEffects)
	UE_API int32 RemoveActiveEffectsWithTags(FGameplayTagContainer Tags);

	/** 移除所有具有包含 Tags 中任何标签的捕获源标签的活动效果 */
	UFUNCTION(BlueprintCallable, Category = GameplayEffects)
	UE_API int32 RemoveActiveEffectsWithSourceTags(FGameplayTagContainer Tags);

	/** 移除所有应用了 Tags 中任何标签的活动效果 */
	UFUNCTION(BlueprintCallable, Category = GameplayEffects)
	UE_API int32 RemoveActiveEffectsWithAppliedTags(FGameplayTagContainer Tags);

	/** 移除所有授予了 Tags 中任何标签的活动效果 */
	UFUNCTION(BlueprintCallable, Category = GameplayEffects)
	UE_API int32 RemoveActiveEffectsWithGrantedTags(FGameplayTagContainer Tags);

	/** 移除所有匹配给定查询的活动效果。StacksToRemove=-1 将移除所有堆叠。 */
	UE_API virtual int32 RemoveActiveEffects(const FGameplayEffectQuery& Query, int32 StacksToRemove = -1);

	// ----------------------------------------------------------------------------------------------------------------
	//	GameplayCues
	// ----------------------------------------------------------------------------------------------------------------
	
	// 不要直接调用这些函数,改为调用 GameplayCueManager 上的包装器
	UFUNCTION(NetMulticast, unreliable)
	UE_API void NetMulticast_InvokeGameplayCueExecuted_FromSpec(const FGameplayEffectSpecForRPC Spec, FPredictionKey PredictionKey) override;

	UFUNCTION(NetMulticast, unreliable)
	UE_API void NetMulticast_InvokeGameplayCueExecuted(const FGameplayTag GameplayCueTag, FPredictionKey PredictionKey, FGameplayEffectContextHandle EffectContext) override;

	UFUNCTION(NetMulticast, unreliable)
	UE_API void NetMulticast_InvokeGameplayCuesExecuted(const FGameplayTagContainer GameplayCueTags, FPredictionKey PredictionKey, FGameplayEffectContextHandle EffectContext) override;

	UFUNCTION(NetMulticast, unreliable)
	UE_API void NetMulticast_InvokeGameplayCueExecuted_WithParams(const FGameplayTag GameplayCueTag, FPredictionKey PredictionKey, FGameplayCueParameters GameplayCueParameters) override;

	UFUNCTION(NetMulticast, unreliable)
	UE_API void NetMulticast_InvokeGameplayCuesExecuted_WithParams(const FGameplayTagContainer GameplayCueTags, FPredictionKey PredictionKey, FGameplayCueParameters GameplayCueParameters) override;

	UFUNCTION(NetMulticast, unreliable)
	UE_API void NetMulticast_InvokeGameplayCueAdded(const FGameplayTag GameplayCueTag, FPredictionKey PredictionKey, FGameplayEffectContextHandle EffectContext) override;

	UFUNCTION(NetMulticast, unreliable)
	UE_API void NetMulticast_InvokeGameplayCueAdded_WithParams(const FGameplayTag GameplayCueTag, FPredictionKey PredictionKey, FGameplayCueParameters Parameters) override;
	
	UFUNCTION(NetMulticast, unreliable)
	UE_API void NetMulticast_InvokeGameplayCueAddedAndWhileActive_FromSpec(const FGameplayEffectSpecForRPC& Spec, FPredictionKey PredictionKey) override;

	UFUNCTION(NetMulticast, unreliable)
	UE_API void NetMulticast_InvokeGameplayCueAddedAndWhileActive_WithParams(const FGameplayTag GameplayCueTag, FPredictionKey PredictionKey, FGameplayCueParameters GameplayCueParameters) override;

	UFUNCTION(NetMulticast, unreliable)
	UE_API void NetMulticast_InvokeGameplayCuesAddedAndWhileActive_WithParams(const FGameplayTagContainer GameplayCueTags, FPredictionKey PredictionKey, FGameplayCueParameters GameplayCueParameters) override;

	/** GameplayCues 也可以自行出现。这些接受一个可选的 effect context 来传递命中结果等 */
	UE_API void ExecuteGameplayCue(const FGameplayTag GameplayCueTag, FGameplayEffectContextHandle EffectContext = FGameplayEffectContextHandle());
	UE_API void ExecuteGameplayCue(const FGameplayTag GameplayCueTag, const FGameplayCueParameters& GameplayCueParameters);

	/** 添加一个持久的游戏玩法提示 */
	UE_API void AddGameplayCue(const FGameplayTag GameplayCueTag, FGameplayEffectContextHandle EffectContext = FGameplayEffectContextHandle());
	UE_API void AddGameplayCue(const FGameplayTag GameplayCueTag, const FGameplayCueParameters& GameplayCueParameters);

	/** 为最小复制模式添加游戏玩法提示。仅当不在最小复制模式时,才会通过其他方式(例如通过 GE)复制游戏玩法提示的路径中调用 */
	UE_API void AddGameplayCue_MinimalReplication(const FGameplayTag GameplayCueTag, FGameplayEffectContextHandle EffectContext = FGameplayEffectContextHandle());

	/** 移除一个持久的游戏玩法提示 */
	UE_API void RemoveGameplayCue(const FGameplayTag GameplayCueTag);
	
	/** 为最小复制模式移除游戏玩法提示。仅当不在最小复制模式时,才会通过其他方式(例如通过 GE)复制游戏玩法提示的路径中调用 */
	UE_API void RemoveGameplayCue_MinimalReplication(const FGameplayTag GameplayCueTag);
	
	/** 移除任何自行添加的 GameplayCue,即不是作为 GameplayEffect 的一部分添加的。 */
	UE_API void RemoveAllGameplayCues();

	/** 处理来自外部源的游戏玩法提示事件 */
	UE_API void InvokeGameplayCueEvent(const FGameplayEffectSpecForRPC& Spec, EGameplayCueEvent::Type EventType);
	UE_API void InvokeGameplayCueEvent(const FGameplayTag GameplayCueTag, EGameplayCueEvent::Type EventType, FGameplayEffectContextHandle EffectContext = FGameplayEffectContextHandle());
	UE_API void InvokeGameplayCueEvent(const FGameplayTag GameplayCueTag, EGameplayCueEvent::Type EventType, const FGameplayCueParameters& GameplayCueParameters);

	/** 允许轮询以查看 GameplayCue 是否处于活动状态。我们期望大多数 GameplayCue 处理是基于事件的,但在某些情况下我们可能需要检查 GameplayCue 是否处于活动状态(例如动画蓝图) */
	UFUNCTION(BlueprintCallable, Category="GameplayCue", meta=(GameplayTagFilter="GameplayCue"))
	bool IsGameplayCueActive(const FGameplayTag GameplayCueTag) const
	{
		return HasMatchingGameplayTag(GameplayCueTag);
	}

	/** 将使用此 ASC 的所有者(Instigator)和 AvatarActor(EffectCauser)初始化游戏玩法提示参数 */
	UE_API virtual void InitDefaultGameplayCueParameters(FGameplayCueParameters& Parameters);

	/** 我们是否准备好调用游戏玩法提示了? */
	UE_API virtual bool IsReadyForGameplayCues();

	/** 处理在执行 NetDeltaSerialize 并等待 Avatar Actor 加载时可能被延迟的游戏玩法提示 */
	UE_API virtual void HandleDeferredGameplayCues(const FActiveGameplayEffectsContainer* GameplayEffectsContainer);

	/** 为所有处于活动状态、未被抑制的 GE 上的 GC 调用 WhileActive 事件。这通常用于“重生”或 Avatar 已更改的情况 */
	UE_DEPRECATED(5.4, "ReinvokeActiveGameplayCues 未被使用,并且其逻辑与预测游戏玩法效果不一致。如果你需要,可以在你自己的项目中实现它。")
	UE_API virtual void ReinvokeActiveGameplayCues();

	/**
	 *	GameplayAbilities
	 *	
	 *	AbilitySystemComponent 在能力方面的作用是提供:
	 *		- 能力实例的管理(无论是每个 Actor 还是每次执行实例)。
	 *			- 必须有*人*跟踪这些实例。
	 *			- 非实例化能力*可以*在没有 AbilitySystemComponent 中的任何能力内容的情况下执行。
	 *				它们应该能够操作 GameplayAbilityActorInfo + GameplayAbility。
	 *		
	 *	作为便利,它可能提供一些其他功能:
	 *		- 一些基本的输入绑定(无论是实例化还是非实例化能力)。
	 *		- 诸如“此组件具有这些能力”的概念
	 *	
	 */

	/*
	 * 授予一个能力。
	 * 如果 Actor 不是权威的,则将被忽略。
	 * 返回可在 TryActivateAbility 等中使用的句柄。
	 * 
	 * @param AbilitySpec 包含有关能力类、级别和要绑定到的输入 ID 信息的 FGameplayAbilitySpec。
	 */
	UE_API FGameplayAbilitySpecHandle GiveAbility(const FGameplayAbilitySpec& AbilitySpec);

	/*
	 * 授予一个能力并尝试恰好激活它一次,这将导致它被移除。
	 * 仅在服务器上有效,并且能力的网络执行策略不能设置为 Local 或 Local Predicted
	 * 
	 * @param AbilitySpec 包含有关能力类、级别和要绑定到的输入 ID 信息的 FGameplayAbilitySpec。
	 * @param GameplayEventData 可选的激活事件数据。如果提供,将调用 Activate Ability From Event 而不是 ActivateAbility,传递事件数据
	 */
	UE_API FGameplayAbilitySpecHandle GiveAbilityAndActivateOnce(FGameplayAbilitySpec& AbilitySpec, const FGameplayEventData* GameplayEventData = nullptr);

	/**
	 * 授予一个游戏玩法能力并返回其句柄。
	 * 如果 Actor 不是权威的,则将被忽略。
	 *
	 * @param AbilityClass 要授予的能力类型
	 * @param Level 授予能力的级别
	 * @param InputID 绑定能力激活的输入 ID 值。
	 */
	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = "Gameplay Abilities", meta = (DisplayName = "Give Ability", ScriptName = "GiveAbility"))
	UE_API FGameplayAbilitySpecHandle K2_GiveAbility(TSubclassOf<UGameplayAbility> AbilityClass, int32 Level = 0, int32 InputID = -1);

	/**
	 * 授予一个游戏玩法能力,激活它一次,然后移除它。
	 * 如果 Actor 不是权威的,则将被忽略。
	 *
	 * @param AbilityClass 要授予的能力类型
	 * @param Level 授予能力的级别
	 * @param InputID 绑定能力激活的输入 ID 值。
	 */
	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = "Gameplay Abilities", meta = (DisplayName = "Give Ability And Activate Once", ScriptName = "GiveAbilityAndActivateOnce"))
	UE_API FGameplayAbilitySpecHandle K2_GiveAbilityAndActivateOnce(TSubclassOf<UGameplayAbility> AbilityClass, int32 Level = 0, int32 InputID = -1);

	/** 清除所有“已授予”的能力。如果 Actor 不是权威的,则将被忽略。 */
	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category="Gameplay Abilities")
	UE_API void ClearAllAbilities();

	/**
	 * 清除绑定到给定输入 ID 的所有能力
	 * 如果 Actor 不是权威的,则将被忽略
	 *
	 * @param InputID 要移除的能力的数字输入 ID
	 */
	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = "Gameplay Abilities")
	UE_API void ClearAllAbilitiesWithInputID(int32 InputID = 0);

	/** 
	 * 移除指定的能力。
	 * 如果 Actor 不是权威的,则将被忽略。
	 * 
	 * @param Handle 要移除的能力的能力规格句柄
	 */
	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = "Gameplay Abilities")
	UE_API void ClearAbility(const FGameplayAbilitySpecHandle& Handle);
	
	/** 设置一个能力规格在其结束时移除。如果该规格当前未激活,则立即终止它。同时清除该规格的 InputID。 */
	UE_API void SetRemoveAbilityOnEnd(FGameplayAbilitySpecHandle AbilitySpecHandle);

	/** 
	 * 获取所有与 GameplayTagContainer 中的所有标签匹配且满足 DoesAbilitySatisfyTagRequirements() 的可激活游戏玩法能力。
	 * 后一个要求允许此函数在没有预先了解的情况下找到正确的能力。
	 * 例如,如果有两个“近战”能力,其中一个需要武器,另一个需要徒手,那么这些能力可以使用 Blocking 和 Required 标签来确定它们何时可以触发。
	 * 使用 Satisfying Tags 要求简化了许多使用情况。
	 * 例如,行为树可以使用各种装饰器来测试使用此机制获取的能力,以及执行该能力的任务,而无需知道甚至存在多个这样的能力。
	 */
	UE_API void GetActivatableGameplayAbilitySpecsByAllMatchingTags(const FGameplayTagContainer& GameplayTagContainer, TArray < struct FGameplayAbilitySpec* >& MatchingGameplayAbilities, bool bOnlyAbilitiesThatSatisfyTagRequirements = true) const;

	/** 
	 * 尝试激活每个与给定标签匹配且满足 DoesAbilitySatisfyTagRequirements() 的游戏玩法能力。
	 * 如果有任何东西尝试激活,则返回 true。可以激活多个能力,并且能力可能稍后失败。
	 * 如果 bAllowRemoteActivation 为 true,它将远程激活本地/服务器能力;如果为 false,它将仅尝试在本地激活能力。
	 */
	UFUNCTION(BlueprintCallable, Category = "Abilities")
	UE_API bool TryActivateAbilitiesByTag(const FGameplayTagContainer& GameplayTagContainer, bool bAllowRemoteActivation = true);

	/**
	 * 尝试激活传入的能力。这将检查成本和要求 before doing so。
	 * 如果它认为已激活,则返回 true,但由于稍后激活失败,可能会返回误报。
	 * 如果 bAllowRemoteActivation 为 true,它将远程激活本地/服务器能力;如果为 false,它将仅尝试在本地激活能力
	 */
	UFUNCTION(BlueprintCallable, Category = "Abilities")
	UE_API bool TryActivateAbilityByClass(TSubclassOf<UGameplayAbility> InAbilityToActivate, bool bAllowRemoteActivation = true);

	/** 
	 * 尝试激活给定的能力,将检查成本和要求 before doing so。
	 * 如果它认为已激活,则返回 true,但由于稍后激活失败,可能会返回误报。
	 * 如果 bAllowRemoteActivation 为 true,它将远程激活本地/服务器能力;如果为 false,它将仅尝试在本地激活能力
	 */
	UFUNCTION(BlueprintCallable, Category = "Abilities")
	UE_API bool TryActivateAbility(FGameplayAbilitySpecHandle AbilityToActivate, bool bAllowRemoteActivation = true);

	UE_API bool HasActivatableTriggeredAbility(FGameplayTag Tag);

	/** 从游戏玩法事件触发能力,将仅根据执行标志在本地/服务器上触发 */
	UE_API bool TriggerAbilityFromGameplayEvent(FGameplayAbilitySpecHandle AbilityToTrigger, FGameplayAbilityActorInfo* ActorInfo, FGameplayTag Tag, const FGameplayEventData* Payload, UAbilitySystemComponent& Component);

	// ----------------------------------------------------------------------------------------------------------------
	// 能力取消/中断
	// ----------------------------------------------------------------------------------------------------------------

	/** 取消指定的能力 CDO。 */
	UE_API void CancelAbility(UGameplayAbility* Ability);	

	/** 取消由传入的规格句柄指示的能力。如果在 reactivated 能力中未找到句柄,则不执行任何操作。 */
	UE_API void CancelAbilityHandle(const FGameplayAbilitySpecHandle& AbilityHandle);

	/** 取消所有具有指定标签的能力。不会取消 Ignore 实例 */
	UE_API void CancelAbilities(const FGameplayTagContainer* WithTags=nullptr, const FGameplayTagContainer* WithoutTags=nullptr, UGameplayAbility* Ignore=nullptr);

	/** 取消所有能力,无论标签如何。不会取消 ignore 实例 */
	UE_API void CancelAllAbilities(UGameplayAbility* Ignore=nullptr);

	/** 取消所有能力并杀死任何剩余的实例化能力 */
	UE_API virtual void DestroyActiveState();

	/** 
	 * 从能力激活或本机代码调用,将应用正确的能力阻止标签并取消现有能力。子类可以覆盖该行为 
	 * 
	 * @param AbilityTags 具有阻止和取消标志的能力的标签
	 * @param RequestingAbility 请求更改的游戏玩法能力,对于本机事件可以为 NULL
	 * @param bEnableBlockTags 如果为 true 将启用阻止标签,如果为 false 将禁用阻止标签
	 * @param BlockTags 要阻止的标签
	 * @param bExecuteCancelTags 如果为 true 将取消匹配标签的能力
	 * @param CancelTags 要取消的标签
	 */
	UE_API virtual void ApplyAbilityBlockAndCancelTags(const FGameplayTagContainer& AbilityTags, UGameplayAbility* RequestingAbility, bool bEnableBlockTags, const FGameplayTagContainer& BlockTags, bool bExecuteCancelTags, const FGameplayTagContainer& CancelTags);

	/** 当能力可取消或不可取消时调用。默认情况下不执行任何操作,可以被覆盖以与游戏玩法事件关联 */
	virtual void HandleChangeAbilityCanBeCanceled(const FGameplayTagContainer& AbilityTags, UGameplayAbility* RequestingAbility, bool bCanBeCanceled) {}

	/** 如果任何传入的标签被阻止,则返回 true */
	UE_API virtual bool AreAbilityTagsBlocked(const FGameplayTagContainer& Tags) const;

	/** 阻止或取消阻止特定能力标签 */
	UE_API void BlockAbilitiesWithTags(const FGameplayTagContainer& Tags);
	UE_API void UnBlockAbilitiesWithTags(const FGameplayTagContainer& Tags);

	/** 检查能力系统当前是否正在阻止 InputID。如果 InputID 被阻止,则返回 true,否则返回 false。 */
	UE_API bool IsAbilityInputBlocked(int32 InputID) const;

	/** 阻止或取消阻止特定输入 ID */
	UE_API void BlockAbilityByInputID(int32 InputID);
	UE_API void UnBlockAbilityByInputID(int32 InputID);

	// ----------------------------------------------------------------------------------------------------------------
	// 旨在从 GameplayAbility 及其子类调用的函数,但不适用于一般用途
	// ----------------------------------------------------------------------------------------------------------------

	/** 返回所有可激活能力的列表。只读。 */
	const TArray<FGameplayAbilitySpec>& GetActivatableAbilities() const
	{
		return ActivatableAbilities.Items;
	}

	/** 返回所有可激活能力的列表。 */
	TArray<FGameplayAbilitySpec>& GetActivatableAbilities()
	{
		return ActivatableAbilities.Items;
	}

	/** 返回能力上次激活的本地世界时间。在权限(服务器)和自主代理(控制客户端)上有效。 */
	float GetAbilityLastActivatedTime() const { return AbilityLastActivatedTime; }

	/** 从句柄返回能力规格。如果正在修改,请调用 MarkAbilitySpecDirty。将返回值视为临时的,因为指针可能在随后调用 AbilitySystemComponent 时无效。 */
	UE_API FGameplayAbilitySpec* FindAbilitySpecFromHandle(FGameplayAbilitySpecHandle Handle, EConsiderPending ConsiderPending = EConsiderPending::PendingRemove) const;
	
	/** 从 GE 句柄返回能力规格。如果正在修改,请调用 MarkAbilitySpecDirty */
	UE_DEPRECATED(5.3, "FindAbilitySpecFromGEHandle 从不准确,因为一个 GameplayEffect 可以授予多个 GameplayAbilities。它现在返回 nullptr。")
	UE_API FGameplayAbilitySpec* FindAbilitySpecFromGEHandle(FActiveGameplayEffectHandle Handle) const;

	/**
	* 返回从 GE 句柄授予的所有能力规格句柄。只有服务器可以调用此函数。
	* @param ScopeLock - 用于通知调用者的锁,返回值仅在此锁处于作用域内时有效
	* @param Handle - 授予我们正在寻找的能力的活动游戏玩法效果的句柄
	* @param ConsiderPending - 我们是否返回待添加/移除的能力规格?
	*/
	UE_API TArray<const FGameplayAbilitySpec*> FindAbilitySpecsFromGEHandle(const FScopedAbilityListLock& ScopeLock, FActiveGameplayEffectHandle Handle, EConsiderPending ConsiderPending = EConsiderPending::PendingRemove) const;

	/** 返回与给定能力类对应的能力规格。如果正在修改,请调用 MarkAbilitySpecDirty */
	UE_API FGameplayAbilitySpec* FindAbilitySpecFromClass(TSubclassOf<UGameplayAbility> InAbilityClass) const;

	/** 从句柄返回能力规格。如果正在修改,请调用 MarkAbilitySpecDirty */
	UE_API FGameplayAbilitySpec* FindAbilitySpecFromInputID(int32 InputID) const;

	/**
	 * 返回具有给定 InputID 的所有能力
	 *
	 * @param InputID 要匹配的输入 ID
	 * @param OutAbilitySpecs 指向匹配规格的指针数组
	 */
	UE_API virtual void FindAllAbilitySpecsFromInputID(int32 InputID, TArray<const FGameplayAbilitySpec*>& OutAbilitySpecs) const;

	/**
	 * 从类、级别和可选的输入 ID 构建一个简单的 FGameplayAbilitySpec
	 */
	UE_API virtual FGameplayAbilitySpec BuildAbilitySpecFromClass(TSubclassOf<UGameplayAbility> AbilityClass, int32 Level = 0, int32 InputID = -1);

	/**
	 * 返回一个包含所有已授予能力句柄的数组
	 * 注意:目前这不包括正在激活的能力
	 * 
	 * @param OutAbilityHandles 此数组将填充已授予的能力规格句柄
	 */
	UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "Gameplay Abilities")
	UE_API void GetAllAbilities(TArray<FGameplayAbilitySpecHandle>& OutAbilityHandles) const;

	/**
	 * 返回一个包含所有与提供标签匹配的能力的数组
	 *
	 * @param OutAbilityHandles 此数组将填充匹配的能力规格句柄
	 * @param Tags 要匹配的游戏玩法标签
	 * @param bExactMatch 如果为 true,标签必须完全匹配。否则,将返回匹配任何标签的能力
	 */
	UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "Gameplay Abilities")
	UE_API void FindAllAbilitiesWithTags(TArray<FGameplayAbilitySpecHandle>& OutAbilityHandles, FGameplayTagContainer Tags, bool bExactMatch = true) const;

	/**
	 * 返回一个包含所有与提供的游戏玩法标签查询匹配的能力的数组
	 *
	 * @param OutAbilityHandles 此数组将填充匹配的能力规格句柄
	 * @param Query 要匹配的游戏玩法标签查询
	 */
	UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "Gameplay Abilities")
	UE_API void FindAllAbilitiesMatchingQuery(TArray<FGameplayAbilitySpecHandle>& OutAbilityHandles, FGameplayTagQuery Query) const;

	/**
	 * 返回一个包含所有绑定到输入 ID 值的能力的数组
	 *
	 * @param OutAbilityHandles 此数组将填充匹配的能力规格句柄
	 * @param InputID 要匹配的输入 ID
	 */
	UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "Gameplay Abilities")
	UE_API void FindAllAbilitiesWithInputID(TArray<FGameplayAbilitySpecHandle>& OutAbilityHandles, int32 InputID = 0) const;

	/** 从活动游戏玩法效果的句柄中检索游戏玩法效果的 EffectContext。 */
	UE_API FGameplayEffectContextHandle GetEffectContextFromActiveGEHandle(FActiveGameplayEffectHandle Handle);

	/** 调用以标记能力规格已被修改 */
	UE_API void MarkAbilitySpecDirty(FGameplayAbilitySpec& Spec, bool WasAddOrRemove=false);

	/** 尝试激活给定的能力,仅当从正确的客户端/服务器上下文调用时才有效 */
	UE_API bool InternalTryActivateAbility(FGameplayAbilitySpecHandle AbilityToActivate, FPredictionKey InPredictionKey = FPredictionKey(), UGameplayAbility ** OutInstancedAbility = nullptr, FOnGameplayAbilityEnded::FDelegate* OnGameplayAbilityEndedDelegate = nullptr, const FGameplayEventData* TriggerEventData = nullptr);

	/** InternalTryActivateAbility 使用的失败标签(例如,这存储了上次调用 InternalTryActivateAbility 的 FailureTags) */
	FGameplayTagContainer InternalTryActivateAbilityFailureTags; // 内部尝试激活能力失败标签

	/** 从能力调用,让组件知道它已结束 */
	UE_API virtual void NotifyAbilityEnded(FGameplayAbilitySpecHandle Handle, UGameplayAbility* Ability, bool bWasCancelled);

	UE_API void ClearAbilityReplicatedDataCache(FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActivationInfo& ActivationInfo);

	/** 从 FScopedAbilityListLock 调用 */
	UE_API void IncrementAbilityListLock();
	UE_API void DecrementAbilityListLock();

	// ----------------------------------------------------------------------------------------------------------------
	// 调试
	// ----------------------------------------------------------------------------------------------------------------

	struct FAbilitySystemComponentDebugInfo
	{
		FAbilitySystemComponentDebugInfo()
		{
			FMemory::Memzero(*this);
		}

		class UCanvas* Canvas; // 画布

		bool bPrintToLog; // 是否打印到日志

		bool bShowAttributes; // 是否显示属性
		bool bShowGameplayEffects;; // 是否显示游戏玩法效果
		bool bShowAbilities; // 是否显示能力

		float XPos; // X 位置
		float YPos; // Y 位置
		float OriginalX; // 原始 X
		float OriginalY; // 原始 Y
		float MaxY; // 最大 Y
		float NewColumnYPadding; // 新列 Y 填充
		float YL; // Y 行高

		bool Accumulate; // 是否累积
		TArray<FString>	Strings; // 字符串数组

		int32 GameFlags; // 游戏在 Debug_Internal 中设置/读取的任意标志
	};

	static UE_API void OnShowDebugInfo(AHUD* HUD, UCanvas* Canvas, const FDebugDisplayInfo& DisplayInfo, float& YL, float& YPos);

	UE_API virtual void DisplayDebug(class UCanvas* Canvas, const class FDebugDisplayInfo& DebugDisplay, float& YL, float& YPos);
	UE_API virtual void PrintDebug();

	UE_API void AccumulateScreenPos(FAbilitySystemComponentDebugInfo& Info);
	UE_API virtual void Debug_Internal(struct FAbilitySystemComponentDebugInfo& Info);
	UE_API void DebugLine(struct FAbilitySystemComponentDebugInfo& Info, FString Str, float XOffset, float YOffset, int32 MinTextRowsToAdvance = 0);
	UE_API FString CleanupName(FString Str);

	/** 打印所有游戏玩法效果的调试列表 */
	UE_API void PrintAllGameplayEffects() const;

	/** 请求服务器将能力系统调试信息发送回客户端,通过 ClientPrintDebug_Response */
	UFUNCTION(Server, reliable, WithValidation)
	UE_API void ServerPrintDebug_Request();

	/** 与 ServerPrintDebug_Request 相同,但这包括客户端调试字符串,以便服务器可以将它们嵌入到重放中 */
	UFUNCTION(Server, reliable, WithValidation)
	UE_API void ServerPrintDebug_RequestWithStrings(const TArray<FString>& Strings);

	/** 虚拟函数,游戏可以覆盖以在 ServerPrintDebug 函数在服务器上运行时执行自己的操作 */
	UE_API virtual void OnServerPrintDebug_Request();

	/** 确定是调用 ServerPrintDebug_Request 还是 ServerPrintDebug_RequestWithStrings。 */
	UE_API virtual bool ShouldSendClientDebugStringsToServer() const;

	UFUNCTION(Client, reliable)
	UE_API void ClientPrintDebug_Response(const TArray<FString>& Strings, int32 GameFlags);
	UE_API virtual void OnClientPrintDebug_Response(const TArray<FString>& Strings, int32 GameFlags);

#if ENABLE_VISUAL_LOG
	UE_API void ClearDebugInstantEffects();
	
	UE_API virtual void GrabDebugSnapshot(FVisualLogEntry* Snapshot) const override;
#endif // ENABLE_VISUAL_LOG

	UE_DEPRECATED(4.26, "这将在未来的引擎版本中变为私有。请改用 SetClientDebugStrings、GetClientDebugStrings 或 GetClientDebugStrings_Mutable。")
	UPROPERTY(ReplicatedUsing=OnRep_ClientDebugString)
	TArray<FString>	ClientDebugStrings; // 客户端调试字符串

	UE_API void SetClientDebugStrings(TArray<FString>&& NewClientDebugStrings);
	UE_API TArray<FString>& GetClientDebugStrings_Mutable();
	UE_API const TArray<FString>& GetClientDebugStrings() const;

	UE_DEPRECATED(4.26, "这将在未来的引擎版本中变为私有。请改用 SetServerDebugStrings、GetServerDebugStrings 或 GetServerDebugStrings_Mutable。")
	UPROPERTY(ReplicatedUsing=OnRep_ServerDebugString)
	TArray<FString>	ServerDebugStrings; // 服务器调试字符串

	UE_API void SetServerDebugStrings(TArray<FString>&& NewServerDebugStrings);
	UE_API TArray<FString>& GetServerDebugStrings_Mutable();
	UE_API const TArray<FString>& GetServerDebugStrings() const;

	UFUNCTION()
	UE_API virtual void OnRep_ClientDebugString();

	UFUNCTION()
	UE_API virtual void OnRep_ServerDebugString();

	// ----------------------------------------------------------------------------------------------------------------
	// 批量处理客户端->服务器 RPC
	// 这是一个进行中的功能,用于批量处理客户端->服务器通信。它是可选的且不完整。它仅批量处理以下函数。在批处理窗口期间调用其他服务器 RPC 是不安全的。仅在你知道自己在做什么时才选择加入!
	// ----------------------------------------------------------------------------------------------------------------	

	UE_API void CallServerTryActivateAbility(FGameplayAbilitySpecHandle AbilityToActivate, bool InputPressed, FPredictionKey PredictionKey);
	UE_API void CallServerSetReplicatedTargetData(FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey, const FGameplayAbilityTargetDataHandle& ReplicatedTargetDataHandle, FGameplayTag ApplicationTag, FPredictionKey CurrentPredictionKey);
	UE_API void CallServerEndAbility(FGameplayAbilitySpecHandle AbilityToEnd, FGameplayAbilityActivationInfo ActivationInfo, FPredictionKey PredictionKey);

	virtual bool ShouldDoServerAbilityRPCBatch() const { return false; }
	UE_API virtual void BeginServerAbilityRPCBatch(FGameplayAbilitySpecHandle AbilityHandle);
	UE_API virtual void EndServerAbilityRPCBatch(FGameplayAbilitySpecHandle AbilityHandle);

	/** 在 EndServerAbilityRPCBatch 上批量发送到服务器的累积客户端数据 */
	TArray<FServerAbilityRPCBatch, TInlineAllocator<1> > LocalServerAbilityRPCBatchData; // 本地服务器能力 RPC 批处理数据

	UFUNCTION(Server, reliable, WithValidation)
	UE_API void	ServerAbilityRPCBatch(FServerAbilityRPCBatch BatchInfo);

	// 子类可覆盖的函数
	UE_API virtual void ServerAbilityRPCBatch_Internal(FServerAbilityRPCBatch& BatchInfo);

	// ----------------------------------------------------------------------------------------------------------------
	//	输入处理/目标选择
	// ----------------------------------------------------------------------------------------------------------------	

	/**
	 * 这旨在用于从输入角度抑制激活能力。(例如,菜单已拉起,另一个游戏机制正在消耗所有输入等)
	 * 这应仅在本地拥有的玩家上调用。
	 * 这不应用于游戏机制,如沉默或禁用。那些应该通过游戏玩法效果来完成。
	 */
	UFUNCTION(BlueprintCallable, Category="Abilities")
	UE_API bool GetUserAbilityActivationInhibited() const;
	
	/** 禁用或启用本地用户激活能力的能力。这应仅用于输入/UI 等相关抑制。不要用于游戏机制。 */
	UFUNCTION(BlueprintCallable, Category="Abilities")
	UE_API virtual void SetUserAbilityActivationInhibited(bool NewInhibit);

	/** 激活当前是否被抑制 */
	UPROPERTY()
	bool UserAbilityActivationInhibited; // 用户能力激活被抑制

	/** 当启用时,GameplayCue RPC 将通过 AvatarActor 的 IAbilitySystemReplicationProxyInterface 路由,而不是通过此组件 */
	UPROPERTY()
	bool ReplicationProxyEnabled; // 复制代理已启用

	/** 抑制通过 GE 在此组件上授予的所有能力 */
	UPROPERTY()
	bool bSuppressGrantAbility; // 是否抑制授予能力

	/** 抑制此组件上的所有 GameplayCues */
	UPROPERTY()
	bool bSuppressGameplayCues; // 是否抑制游戏玩法提示

	/** 当前活动的目标选择 Actor 列表 */
	UPROPERTY()
	TArray<TObjectPtr<AGameplayAbilityTargetActor>> SpawnedTargetActors; // 生成的目标 Actor

	/** 使用一些默认操作名称绑定到输入组件 */
	UE_API virtual void BindToInputComponent(UInputComponent* InputComponent);

	/** 使用自定义绑定绑定到输入组件 */
	UE_API virtual void BindAbilityActivationToInputComponent(UInputComponent* InputComponent, FGameplayAbilityInputBinds BindInfo);

	/** 初始化 BlockedAbilityBindings 变量 */
	UE_API virtual void SetBlockAbilityBindingsArray(FGameplayAbilityInputBinds BindInfo);

	/** 调用以处理能力绑定输入 */
	UE_API virtual void AbilityLocalInputPressed(int32 InputID);
	UE_API virtual void AbilityLocalInputReleased(int32 InputID);

	/*
	 * 发送具有提供的输入 ID 的本地玩家输入按下事件,通知任何绑定的能力
	 *
	 * @param InputID 要匹配的输入 ID
	 */
	UFUNCTION(BlueprintCallable, Category = "Gameplay Abilities")
	UE_API void PressInputID(int32 InputID);

	/**
	 * 发送具有提供的输入 ID 的本地玩家输入释放事件,通知任何绑定的能力
	 * @param InputID 要匹配的输入 ID
	 */
	UFUNCTION(BlueprintCallable, Category = "Gameplay Abilities")
	UE_API void ReleaseInputID(int32 InputID);

	/** 处理目标 Actor 的确认/取消 */
	UE_API virtual void LocalInputConfirm();
	UE_API virtual void LocalInputCancel();

	/**
	 * 发送本地玩家输入确认事件,通知能力
	 */
	UFUNCTION(BlueprintCallable, Category = "Gameplay Abilities")
	UE_API void InputConfirm();

	/**
	 * 发送本地玩家输入取消事件,通知能力
	 */
	UFUNCTION(BlueprintCallable, Category = "Gameplay Abilities")
	UE_API void InputCancel();
	
	/** 用于绑定 GenericConfirm/Cancel 事件的 InputID */
	int32 GenericConfirmInputID; // 通用确认输入 ID
	int32 GenericCancelInputID; // 通用取消输入 ID

	bool IsGenericConfirmInputBound(int32 InputID) const	{ return ((InputID == GenericConfirmInputID) && GenericLocalConfirmCallbacks.IsBound()); }
	bool IsGenericCancelInputBound(int32 InputID) const		{ return ((InputID == GenericCancelInputID) && GenericLocalCancelCallbacks.IsBound()); }

	/** 通用确认事件的通用本地回调,任何能力都可以监听 */
	FAbilityConfirmOrCancel	GenericLocalConfirmCallbacks; // 通用本地确认回调

	/** 通用取消事件的通用本地回调,任何能力都可以监听 */
	FAbilityConfirmOrCancel	GenericLocalCancelCallbacks; // 通用本地取消回调

	/** 任何活动的目标选择 Actor 将被通知停止并返回当前目标数据 */
	UFUNCTION(BlueprintCallable, Category = "Abilities")
	UE_API virtual void TargetConfirm();

	/** 任何活动的目标选择 Actor 将被停止并取消,不返回任何目标数据 */
	UFUNCTION(BlueprintCallable, Category = "Abilities")
	UE_API virtual void TargetCancel();

	// ----------------------------------------------------------------------------------------------------------------
	//	动画蒙太奇支持
	// ----------------------------------------------------------------------------------------------------------------	

	/** 播放蒙太奇并根据传入的能力/激活信息处理复制和预测 */
	UE_API virtual float PlayMontage(UGameplayAbility* AnimatingAbility, FGameplayAbilityActivationInfo ActivationInfo, UAnimMontage* Montage, float InPlayRate, FName StartSectionName = NAME_None, float StartTimeSeconds = 0.0f);

	UE_API virtual UAnimMontage* PlaySlotAnimationAsDynamicMontage(UGameplayAbility* AnimatingAbility, FGameplayAbilityActivationInfo ActivationInfo, UAnimSequenceBase* AnimAsset, FName SlotName, float BlendInTime, float BlendOutTime, float InPlayRate = 1.f, float StartTimeSeconds = 0.0f);

	UE_API virtual UAnimMontage* PlaySlotAnimationAsDynamicMontage_WithFractionalLoops(UGameplayAbility* AnimatingAbility, FGameplayAbilityActivationInfo ActivationInfo, UAnimSequenceBase* AnimAsset, FName SlotName, float BlendInTime, float BlendOutTime, float InPlayRate = 1.f, float StartTimeSeconds = 0.0f, float PlayCount = 1.0f);

	/** 播放蒙太奇而不更新复制/预测结构。当复制告诉模拟代理播放蒙太奇时使用。 */
	UE_API virtual float PlayMontageSimulated(UAnimMontage* Montage, float InPlayRate, FName StartSectionName = NAME_None);
	
	UE_API virtual UAnimMontage* PlaySlotAnimationAsDynamicMontageSimulated(UAnimSequenceBase* AnimAsset, FName SlotName, float BlendInTime, float BlendOutTime, float InPlayRate = 1.f);

	UE_API virtual UAnimMontage* PlaySlotAnimationAsDynamicMontage_WithFractionalLoopsSimulated(UAnimSequenceBase* AnimAsset, FName SlotName, float BlendInTime, float BlendOutTime, float InPlayRate = 1.f, float PlayCount = 1.0f);

	/** 停止当前正在播放的任何蒙太奇。期望调用者仅在他们当前是动画能力(或有充分理由不检查)时才停止它 */
	UE_API virtual void CurrentMontageStop(float OverrideBlendOutTime = -1.0f);

	/** 如果当前蒙太奇是作为 Montage 参数给出的蒙太奇,则停止当前蒙太奇 */
	UE_API virtual void StopMontageIfCurrent(const UAnimMontage& Montage, float OverrideBlendOutTime = -1.0f);

	/** 清除传入的动画能力,如果它当前仍在动画化 */
	UE_API virtual void ClearAnimatingAbility(UGameplayAbility* Ability);

	/** 将当前蒙太奇跳转到给定部分。期望调用者仅在他们当前是动画能力(或有充分理由不检查)时才停止它 */
	UE_API virtual void CurrentMontageJumpToSection(FName SectionName);

	/** 设置当前蒙太奇的下一个部分名称。期望调用者仅在他们当前是动画能力(或有充分理由不检查)时才停止它 */
	UE_API virtual void CurrentMontageSetNextSectionName(FName FromSectionName, FName ToSectionName);

	/** 设置当前蒙太奇的播放速率 */
	UE_API virtual void CurrentMontageSetPlayRate(float InPlayRate);

	/** 如果传入的能力是当前动画能力,则返回 true */
	UE_API bool IsAnimatingAbility(UGameplayAbility* Ability) const;

	/** 返回当前动画能力 */
	UE_API UGameplayAbility* GetAnimatingAbility() const;

	/** 返回当前正在播放的蒙太奇 */
	UE_API UAnimMontage* GetCurrentMontage() const;

	/** 获取当前正在播放的 AnimMontage 的 SectionID */
	UE_API int32 GetCurrentMontageSectionID() const;

	/** 获取当前正在播放的 AnimMontage 的 SectionName */
	UE_API FName GetCurrentMontageSectionName() const;

	/** 获取当前部分的时间长度 */
	UE_API float GetCurrentMontageSectionLength() const;

	/** 返回当前部分的剩余时间 */
	UE_API float GetCurrentMontageSectionTimeLeft() const;

	/** 设置蒙太奇中位置的复制方法 */
	UE_API void SetMontageRepAnimPositionMethod(ERepAnimPositionMethod InMethod);

	// ----------------------------------------------------------------------------------------------------------------
	//	Actor 交互
	// ----------------------------------------------------------------------------------------------------------------	

private:

	/** 在逻辑上拥有此组件的 Actor */
	UPROPERTY(ReplicatedUsing = OnRep_OwningActor)
	TObjectPtr<AActor> OwnerActor; // 所有者 Actor

	/** 用于能力的物理表示的 Actor。可以为 NULL */
	UPROPERTY(ReplicatedUsing = OnRep_OwningActor)
	TObjectPtr<AActor> AvatarActor; // Avatar Actor

public:

	UE_API void SetOwnerActor(AActor* NewOwnerActor);
	AActor* GetOwnerActor() const { return OwnerActor; }

	UE_API void SetAvatarActor_Direct(AActor* NewAvatarActor);
	AActor* GetAvatarActor_Direct() const { return AvatarActor; }
	
	UFUNCTION()
	UE_API void OnRep_OwningActor();

	UFUNCTION()
	UE_API void OnAvatarActorDestroyed(AActor* InActor);

	UFUNCTION()
	UE_API void OnOwnerActorDestroyed(AActor* InActor);

	UFUNCTION()
	UE_API void OnSpawnedAttributesEndPlayed(AActor* InActor, EEndPlayReason::Type EndPlayReason);

	/** 缓存的所有者 Actor 数据,能力需要频繁访问(移动组件、网格组件、动画实例等) */
	TSharedPtr<FGameplayAbilityActorInfo>	AbilityActorInfo; // 能力 Actor 信息

	/**
	 *	初始化能力的 ActorInfo - 保存关于我们在谁身上行动以及谁控制我们的信息的结构。
	 *      OwnerActor 是在逻辑上拥有此组件的 Actor。
	 *		AvatarActor 是我们在世界中行动的物理 Actor。通常是一个 Pawn,但它可能是一个 Tower、Building、Turret 等,可能与 Owner 相同
	 */
	UE_API virtual void InitAbilityActorInfo(AActor* InOwnerActor, AActor* InAvatarActor);

	/** 返回用于特定任务的 Avatar Actor,通常是 GetAvatarActor */
	UE_API virtual AActor* GetGameplayTaskAvatar(const UGameplayTask* Task) const override;

	/** 返回此组件的 Avatar Actor */
	UE_API AActor* GetAvatarActor() const;

	/** 更改 Avatar Actor,保持 Owner Actor 不变 */
	UE_API void SetAvatarActor(AActor* InAvatarActor);

	/** 当 ASC 的 AbilityActorInfo 设置了 PlayerController 时调用。 */
	virtual void OnPlayerControllerSet() { }

	/**
	* 当初始化到此系统的 Actor 死亡时调用,这将从该系统和中清除该 Actor FGameplayAbilityActorInfo
	*/
	UE_API virtual void ClearActorInfo();

	/**
	 *	这将根据当前的 ActorInfo 刷新能力的 ActorInfo 结构。也就是说,AvatarActor 将是相同的,但我们将寻找新的
	 *	AnimInstance、MovementComponent、PlayerController 等。
	 */	
	UE_API void RefreshAbilityActorInfo();

	// ----------------------------------------------------------------------------------------------------------------
	//	同步 RPC
	//  这些看起来是状态,但实际上是带有一些负载数据的同步事件
	// ----------------------------------------------------------------------------------------------------------------	
	
	/** 将通用复制事件复制到服务器。 */
	UFUNCTION(Server, reliable, WithValidation)
	UE_API void ServerSetReplicatedEvent(EAbilityGenericReplicatedEvent::Type EventType, FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey, FPredictionKey CurrentPredictionKey);

	/** 将带有负载的通用复制事件复制到服务器。 */
	UFUNCTION(Server, reliable, WithValidation)
	UE_API void ServerSetReplicatedEventWithPayload(EAbilityGenericReplicatedEvent::Type EventType, FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey, FPredictionKey CurrentPredictionKey, FVector_NetQuantize100 VectorPayload);

	/** 将通用复制事件复制到客户端。 */
	UFUNCTION(Client, reliable)
	UE_API void ClientSetReplicatedEvent(EAbilityGenericReplicatedEvent::Type EventType, FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey);

	/** 调用使用给定通用复制事件注册的本地回调 */
	UE_API bool InvokeReplicatedEvent(EAbilityGenericReplicatedEvent::Type EventType, FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey, FPredictionKey CurrentPredictionKey = FPredictionKey());

	/** 调用使用给定通用复制事件注册的本地回调 */
	UE_API bool InvokeReplicatedEventWithPayload(EAbilityGenericReplicatedEvent::Type EventType, FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey, FPredictionKey CurrentPredictionKey, FVector_NetQuantize100 VectorPayload);
	
	/** 将目标数据复制到服务器 */
	UFUNCTION(Server, reliable, WithValidation)
	UE_API void ServerSetReplicatedTargetData(FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey, const FGameplayAbilityTargetDataHandle& ReplicatedTargetDataHandle, FGameplayTag ApplicationTag, FPredictionKey CurrentPredictionKey);

	/** 复制到服务器,目标选择已被取消 */
	UFUNCTION(Server, reliable, WithValidation)
	UE_API void ServerSetReplicatedTargetDataCancelled(FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey, FPredictionKey CurrentPredictionKey);

	/** 设置当前目标数据并调用适用的回调 */
	UE_API virtual void ConfirmAbilityTargetData(FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey, const FGameplayAbilityTargetDataHandle& TargetData, const FGameplayTag& ApplicationTag);

	/** 取消能力目标数据并调用回调 */
	UE_API virtual void CancelAbilityTargetData(FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey);

	/** 删除所有缓存的能力客户端数据(以前是:ConsumeAbilityTargetData)*/
	UE_API void ConsumeAllReplicatedData(FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey);
	/** 使用来自客户端的目标数据(仅 TargetData) */
	UE_API void ConsumeClientReplicatedTargetData(FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey);

	/** 使用给定的通用复制事件(取消设置它)。 */
	UE_API void ConsumeGenericReplicatedEvent(EAbilityGenericReplicatedEvent::Type EventType, FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey);

	/** 获取给定通用复制事件的复制数据。 */
	UE_API FAbilityReplicatedData GetReplicatedDataOfGenericReplicatedEvent(EAbilityGenericReplicatedEvent::Type EventType, FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey);
	
	/** 调用任何已发送的复制委托(TargetData 或通用复制事件)。注意,如果能力中的多个位置注册事件然后调用此函数,这可能很危险。 */
	UE_API void CallAllReplicatedDelegatesIfSet(FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey);

	/** 如果已发送,则调用 TargetData 确认/取消事件。 */
	UE_API bool CallReplicatedTargetDataDelegatesIfSet(FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey);

	/** 如果事件已发送,则调用给定的通用复制事件委托 */
	UE_API bool CallReplicatedEventDelegateIfSet(EAbilityGenericReplicatedEvent::Type EventType, FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey);

	/** 如果客户端事件已发送,则调用传入的委托。如果没有,则将委托添加到我们的多播回调中,该回调将在事件发生时触发。 */
	UE_API bool CallOrAddReplicatedDelegate(EAbilityGenericReplicatedEvent::Type EventType, FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey, FSimpleMulticastDelegate::FDelegate Delegate);

	/** 返回给定能力/预测键对的 TargetDataSet 委托 */
	UE_API FAbilityTargetDataSetDelegate& AbilityTargetDataSetDelegate(FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey);

	/** 返回给定能力/预测键对的 TargetData 取消委托 */
	UE_API FSimpleMulticastDelegate& AbilityTargetDataCancelledDelegate(FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey);

	/** 返回给定能力/预测键对的通用复制事件 */
	UE_API FSimpleMulticastDelegate& AbilityReplicatedEventDelegate(EAbilityGenericReplicatedEvent::Type EventType, FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey AbilityOriginalPredictionKey);

	/** 直接输入状态复制。如果能力上的 bReplicateInputDirectly 为 true,则将调用这些,通常不是一件好事。(相反,更喜欢使用通用复制事件)。 */
	UFUNCTION(Server, reliable, WithValidation)
	UE_API void ServerSetInputPressed(FGameplayAbilitySpecHandle AbilityHandle);

	UFUNCTION(Server, reliable, WithValidation)
	UE_API void ServerSetInputReleased(FGameplayAbilitySpecHandle AbilityHandle);

	/** 总是在本地玩家上调用。仅当在 GameplayAbility 上设置了 bReplicateInputDirectly 时,才在服务器上调用。 */
	UE_API virtual void AbilitySpecInputPressed(FGameplayAbilitySpec& Spec);

	/** 总是在本地玩家上调用。仅当在 GameplayAbility 上设置了 bReplicateInputDirectly 时,才在服务器上调用。 */
	UE_API virtual void AbilitySpecInputReleased(FGameplayAbilitySpec& Spec);

	// ----------------------------------------------------------------------------------------------------------------
	//  组件覆盖
	// ----------------------------------------------------------------------------------------------------------------

	UE_API virtual void InitializeComponent() override;
	UE_API virtual void UninitializeComponent() override;
	UE_API virtual void OnComponentDestroyed(bool bDestroyingHierarchy) override;
	UE_API virtual bool GetShouldTick() const override;
	UE_API virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override;
	UE_API virtual void GetSubobjectsWithStableNamesForNetworking(TArray<UObject*>& Objs) override;
	UE_API virtual bool ReplicateSubobjects(class UActorChannel *Channel, class FOutBunch *Bunch, FReplicationFlags *RepFlags) override;
	/** 强制拥有 Actor 更新其复制,以确保游戏玩法提示快速发送下去。覆盖以更改此操作的积极程度 */
	UE_API virtual void ForceReplication() override;
	UE_API virtual void PreNetReceive() override;
	UE_API virtual void PostNetReceive() override;
	UE_API virtual void OnRegister() override;
	UE_API virtual void OnUnregister() override;
	UE_API virtual void ReadyForReplication() override;
	UE_API virtual void BeginPlay() override;

protected:
	UE_API virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
	UE_API virtual void GetReplicatedCustomConditionState(FCustomPropertyConditionState& OutActiveState) const override;

	UE_API void UpdateActiveGameplayEffectsReplicationCondition();
	UE_API void UpdateMinimalReplicationGameplayCuesCondition();

	/**
	 *	我们可以激活的能力。
	 *		-这将包括非实例化能力和每次执行实例化能力的 CDO。
	 *		-Actor 实例化能力将是实际实例(不是 CDO)
	 *		
	 *	此数组对于工作不是至关重要的。它是为了“将能力赋予 Actor”的便利。但是能力也可以在没有 AbilitySystemComponent 的情况下工作。
	 *	例如,可以编写一个能力在 StaticMeshActor 上执行。只要能力不需要实例化或 AbilitySystemComponent 将提供的任何其他东西,那么它就不需要该组件来运行。
	 */

	UPROPERTY(ReplicatedUsing = OnRep_ActivateAbilities, BlueprintReadOnly, Transient, Category = "Abilities")
	FGameplayAbilitySpecContainer ActivatableAbilities; // 可激活能力

	/** 从能力规格到目标数据的映射。用于跟踪复制数据和回调 */
	FGameplayAbilityReplicatedDataContainer AbilityTargetDataMap; // 能力目标数据映射

	/** 游戏玩法标签容器过滤器列表,以及它们调用的委托 */
	TArray<TPair<FGameplayTagContainer, FGameplayEventTagMulticastDelegate>> GameplayEventTagContainerDelegates; // 游戏玩法事件标签容器委托

	/** 与此组件关联的所有每次执行实例的游戏玩法能力的完整列表 */
	UE_DEPRECATED(5.1, "此数组将变为私有。请改用 GetReplicatedInstancedAbilities、AddReplicatedInstancedAbility 或 RemoveReplicatedInstancedAbility。")
	UPROPERTY()
	TArray<TObjectPtr<UGameplayAbility>>	AllReplicatedInstancedAbilities; // 所有复制的实例化能力

	/** 与此组件关联的所有每次执行实例的游戏玩法能力的完整列表 */
	PRAGMA_DISABLE_DEPRECATION_WARNINGS
	const TArray<UGameplayAbility*>& GetReplicatedInstancedAbilities() const { return AllReplicatedInstancedAbilities; }
	UE_API PRAGMA_ENABLE_DEPRECATION_WARNINGS

	/** 添加一个与此组件关联的游戏玩法能力 */
	void AddReplicatedInstancedAbility(UGameplayAbility* GameplayAbility);

	/** 移除一个与此组件关联的游戏玩法能力 */
	UE_API void RemoveReplicatedInstancedAbility(UGameplayAbility* GameplayAbility);

	/** 取消注册此组件的所有游戏玩法能力 */
	UE_API void RemoveAllReplicatedInstancedAbilities();

	/** 将从 GiveAbility 或 OnRep 调用。使用给定能力初始化事件(触发器和输入) */
	UE_API virtual void OnGiveAbility(FGameplayAbilitySpec& AbilitySpec);

	/** 将从 RemoveAbility 或 OnRep 调用。解绑与给定能力的输入 */
	UE_API virtual void OnRemoveAbility(FGameplayAbilitySpec& AbilitySpec);

	/** 从 ClearAbility、ClearAllAbilities 或 OnRep 调用。清除任何不应再存在的触发器。 */
	UE_API void CheckForClearedAbilities();

	/** 取消特定的能力规格 */
	UE_API virtual void CancelAbilitySpec(FGameplayAbilitySpec& Spec, UGameplayAbility* Ignore);

	/** 创建能力的新实例,将其存储在规格中 */
	UE_API virtual UGameplayAbility* CreateNewInstanceOfAbility(FGameplayAbilitySpec& Spec, const UGameplayAbility* Ability);

	/** 指示我们处于多少层 ABILITY_SCOPE_LOCK() 中。当 AbilityScopeLockCount > 0 时,能力列表可能不会被修改。 */
	int32 AbilityScopeLockCount; // 能力作用域锁计数
	/** 在退出当前能力作用域锁时将移除的能力。 */
	TArray<FGameplayAbilitySpecHandle, TInlineAllocator<2> > AbilityPendingRemoves; // 待移除能力
	/** 在退出当前能力作用域锁时将添加的能力。 */
	TArray<FGameplayAbilitySpec, TInlineAllocator<2> > AbilityPendingAdds; // 待添加能力
	/** 在退出当前能力作用域锁时是否应移除所有能力。将优先于待添加项。 */
	bool bAbilityPendingClearAll; // 是否待清除所有能力

	/** 上次能力激活的本地世界时间。这用于 AFK/空闲检测 */
	float AbilityLastActivatedTime; // 能力最后激活时间

	UFUNCTION()
	UE_API virtual void OnRep_ActivateAbilities();

	UFUNCTION(Server, reliable, WithValidation)
	UE_API void	ServerTryActivateAbility(FGameplayAbilitySpecHandle AbilityToActivate, bool InputPressed, FPredictionKey PredictionKey);

	UFUNCTION(Server, reliable, WithValidation)
	UE_API void	ServerTryActivateAbilityWithEventData(FGameplayAbilitySpecHandle AbilityToActivate, bool InputPressed, FPredictionKey PredictionKey, FGameplayEventData TriggerEventData);

	UFUNCTION(Client, reliable)
	UE_API void	ClientTryActivateAbility(FGameplayAbilitySpecHandle AbilityToActivate);

	/** 由 ServerEndAbility 和 ClientEndAbility 调用;避免代码重复。 */
	UE_API void	RemoteEndOrCancelAbility(FGameplayAbilitySpecHandle AbilityToEnd, FGameplayAbilityActivationInfo ActivationInfo, bool bWasCanceled);

	UFUNCTION(Server, reliable, WithValidation)
	UE_API void	ServerEndAbility(FGameplayAbilitySpecHandle AbilityToEnd, FGameplayAbilityActivationInfo ActivationInfo, FPredictionKey PredictionKey);

	UFUNCTION(Client, reliable)
	UE_API void	ClientEndAbility(FGameplayAbilitySpecHandle AbilityToEnd, FGameplayAbilityActivationInfo ActivationInfo);

	UFUNCTION(Server, reliable, WithValidation)
	UE_API void    ServerCancelAbility(FGameplayAbilitySpecHandle AbilityToCancel, FGameplayAbilityActivationInfo ActivationInfo);

	UFUNCTION(Client, reliable)
	UE_API void    ClientCancelAbility(FGameplayAbilitySpecHandle AbilityToCancel, FGameplayAbilityActivationInfo ActivationInfo);

	UFUNCTION(Client, Reliable)
	UE_API void	ClientActivateAbilityFailed(FGameplayAbilitySpecHandle AbilityToActivate, int16 PredictionKey);
	int32	ClientActivateAbilityFailedCountRecent; // 最近客户端激活能力失败计数
	float	ClientActivateAbilityFailedStartTime; // 客户端激活能力失败开始时间

	
	UE_API void	OnClientActivateAbilityCaughtUp(FGameplayAbilitySpecHandle AbilityToActivate, FPredictionKey::KeyType PredictionKey);

	UFUNCTION(Client, Reliable)
	UE_API void	ClientActivateAbilitySucceed(FGameplayAbilitySpecHandle AbilityToActivate, FPredictionKey PredictionKey);

	UFUNCTION(Client, Reliable)
	UE_API void	ClientActivateAbilitySucceedWithEventData(FGameplayAbilitySpecHandle AbilityToActivate, FPredictionKey PredictionKey, FGameplayEventData TriggerEventData);

	/** ServerTryActivateAbility 的实现 */
	UE_API virtual void InternalServerTryActivateAbility(FGameplayAbilitySpecHandle AbilityToActivate, bool InputPressed, const FPredictionKey& PredictionKey, const FGameplayEventData* TriggerEventData);

	/** 当播放蒙太奇的预测键被拒绝时调用 */
	UE_API void OnPredictiveMontageRejected(UAnimMontage* PredictiveMontage);

	/** 将 LocalAnimMontageInfo 复制到 RepAnimMontageInfo 中 */
	UE_API void AnimMontage_UpdateReplicatedData();
	UE_API void AnimMontage_UpdateReplicatedData(FGameplayAbilityRepAnimMontage& OutRepAnimMontageInfo);

	/** 为重复的动画数据复制播放标志 */
	UE_API void AnimMontage_UpdateForcedPlayFlags(FGameplayAbilityRepAnimMontage& OutRepAnimMontageInfo);

	UE_DEPRECATED(4.26, "这将在未来的引擎版本中变为私有。请改用 SetRepAnimMontageInfo、GetRepAnimMontageInfo 或 GetRepAnimMontageInfo_Mutable。")
	/** 用于将蒙太奇信息复制到模拟客户端的数据结构 */
	UPROPERTY(ReplicatedUsing=OnRep_ReplicatedAnimMontage)
	FGameplayAbilityRepAnimMontage RepAnimMontageInfo; // 复制动画蒙太奇信息

	UE_API void SetRepAnimMontageInfo(const FGameplayAbilityRepAnimMontage& NewRepAnimMontageInfo);
	UE_API FGameplayAbilityRepAnimMontage& GetRepAnimMontageInfo_Mutable();
	UE_API const FGameplayAbilityRepAnimMontage& GetRepAnimMontageInfo() const;

	/** 缓存的值,指示这是否是模拟 Actor */
	UPROPERTY()
	bool bCachedIsNetSimulated; // 缓存的网络模拟状态

	/** 设置如果在尚未与我们关联的动画实例时发生蒙太奇复制 */
	UPROPERTY()
	bool bPendingMontageRep; // 是否待处理蒙太奇复制

	/** 在本地发起的蒙太奇的数据结构(如果是服务器,则为所有内容;如果是客户端,则为预测内容;如果是模拟代理,则为复制内容) */
	UPROPERTY()
	FGameplayAbilityLocalAnimMontage LocalAnimMontageInfo; // 本地动画蒙太奇信息

	UFUNCTION()
	UE_API virtual void OnRep_ReplicatedAnimMontage();

	/** 如果我们准备好处理复制的蒙太奇信息,则返回 true */
	UE_API virtual bool IsReadyForReplicatedMontage();

	/** 从 CurrentMontageSetNextSectionName 调用的 RPC 函数,复制到其他客户端 */
	UFUNCTION(reliable, server, WithValidation)
	UE_API void ServerCurrentMontageSetNextSectionName(UAnimSequenceBase* ClientAnimation, float ClientPosition, FName SectionName, FName NextSectionName);

	/** 从 CurrentMontageJumpToSection 调用的 RPC 函数,复制到其他客户端 */
	UFUNCTION(reliable, server, WithValidation)
	UE_API void ServerCurrentMontageJumpToSectionName(UAnimSequenceBase* ClientAnimation, FName SectionName);

	/** 从 CurrentMontageSetPlayRate 调用的 RPC 函数,复制到其他客户端 */
	UFUNCTION(reliable, server, WithValidation)
	UE_API void ServerCurrentMontageSetPlayRate(UAnimSequenceBase* ClientAnimation, float InPlayRate);

	/** 从游戏玩法事件触发的能力 */
	TMap<FGameplayTag, TArray<FGameplayAbilitySpecHandle > > GameplayEventTriggeredAbilities; // 游戏玩法事件触发的能力

	/** 从添加到所有者的标签触发的能力 */
	TMap<FGameplayTag, TArray<FGameplayAbilitySpecHandle > > OwnedTagTriggeredAbilities; // 拥有的标签触发的能力

	/** 当绑定到能力的拥有的标签更改时调用的回调 */
	UE_API virtual void MonitoredTagChanged(const FGameplayTag Tag, int32 NewCount);

	/** 如果在此网络模式下应从事件激活指定能力,则返回 true */
	UE_API bool HasNetworkAuthorityToActivateTriggeredAbility(const FGameplayAbilitySpec &Spec) const;

	UE_DEPRECATED(5.3, "直接使用 OnImmunityBlockGameplayEffectDelegate。它由 UImmunityGameplayEffectComponent 触发。如果你需要不同的功能,可以创建你自己的 GameplayEffectComponent。")
	UE_API virtual void OnImmunityBlockGameplayEffect(const FGameplayEffectSpec& Spec, const FActiveGameplayEffect* ImmunityGE);

	// 内部游戏玩法提示函数
	UE_API virtual void AddGameplayCue_Internal(const FGameplayTag GameplayCueTag, FGameplayEffectContextHandle& EffectContext, FActiveGameplayCueContainer& GameplayCueContainer);
	UE_API virtual void AddGameplayCue_Internal(const FGameplayTag GameplayCueTag, const FGameplayCueParameters& GameplayCueParameters, FActiveGameplayCueContainer& GameplayCueContainer);
	UE_API virtual void RemoveGameplayCue_Internal(const FGameplayTag GameplayCueTag, FActiveGameplayCueContainer& GameplayCueContainer);

	/** 实际上将最终属性值推送到属性集的属性。不应由外部代码调用,因为这不会通过属性聚合器系统。 */
	UE_API void SetNumericAttribute_Internal(const FGameplayAttribute &Attribute, float& NewFloatValue);

	UE_API bool HasNetworkAuthorityToApplyGameplayEffect(FPredictionKey PredictionKey) const;

	UE_API void ExecutePeriodicEffect(FActiveGameplayEffectHandle	Handle);

	UE_API void ExecuteGameplayEffect(FGameplayEffectSpec &Spec, FPredictionKey PredictionKey);

	UE_API void CheckDurationExpired(FActiveGameplayEffectHandle Handle);
		
	UE_API TArray<TObjectPtr<UGameplayTask>>&	GetAbilityActiveTasks(UGameplayAbility* Ability);

	/** 一个允许我们移除活动游戏玩法效果的 RemoveActiveGameplayEffect 版本,即使我们没有权限 */
	UE_API void RemoveActiveGameplayEffect_AllowClientRemoval(FActiveGameplayEffectHandle Handle, int32 StacksToRemove = -1);

	/** 包含此组件上当前活动的所有游戏玩法效果 */
	UPROPERTY(Replicated)
	FActiveGameplayEffectsContainer ActiveGameplayEffects; // 活动游戏玩法效果

	/** 所有活动游戏玩法提示的列表(在游戏玩法效果之外执行) */
	UPROPERTY(Replicated)
	FActiveGameplayCueContainer ActiveGameplayCues; // 活动游戏玩法提示

	/** 在最小复制模式下的复制游戏玩法提示。这些是通常来自 ActiveGameplayEffects 的提示(但由于我们在最小模式下不复制 AGE,它们必须通过此处复制) */
	UPROPERTY(Replicated)
	FActiveGameplayCueContainer MinimalReplicationGameplayCues; // 最小复制游戏玩法提示

	/** 具有这些标签的能力无法被激活 */
	FGameplayTagCountContainer BlockedAbilityTags; // 被阻止的能力标签

	UE_DEPRECATED(4.26, "这将在未来的引擎版本中变为私有。请改用 SetBlockedAbilityBindings、GetBlockedAbilityBindings 或 GetBlockedAbilityBindings_Mutable。")
	/** 跟踪基于输入绑定被阻止的能力。如果 BlockedAbilityBindings[InputID] > 0,则能力被阻止 */
	UPROPERTY(Transient, Replicated)
	TArray<uint8> BlockedAbilityBindings; // 被阻止的能力绑定

	UE_API void SetBlockedAbilityBindings(const TArray<uint8>& NewBlockedAbilityBindings);
	UE_API TArray<uint8>& GetBlockedAbilityBindings_Mutable();
	UE_API const TArray<uint8>& GetBlockedAbilityBindings() const;

	UE_API void DebugCyclicAggregatorBroadcasts(struct FAggregator* Aggregator);
	
	/** 所有游戏玩法标签的加速映射(来自 GE 的 OwnedGameplayTags 和显式 GameplayCueTags) */
	FGameplayTagCountContainer GameplayTagCountContainer; // 游戏玩法标签计数容器

	UE_DEPRECATED(4.26, "这将在未来的引擎版本中变为私有。请改用 SetMinimalReplicationTags、GetMinimalReplicationTags 或 GetMinimalReplicationTags_Mutable。")
	UPROPERTY(Replicated)
	FMinimalReplicationTagCountMap MinimalReplicationTags; // 最小复制标签

	UE_API void SetMinimalReplicationTags(const FMinimalReplicationTagCountMap& NewMinimalReplicationTags);
	UE_API FMinimalReplicationTagCountMap& GetMinimalReplicationTags_Mutable();
	UE_API const FMinimalReplicationTagCountMap& GetMinimalReplicationTags() const;

	UE_API FMinimalReplicationTagCountMap& GetReplicatedLooseTags_Mutable();
	UE_API const FMinimalReplicationTagCountMap& GetReplicatedLooseTags() const;

	UE_API void ResetTagMap();

	UE_API void NotifyTagMap_StackCountChange(const FGameplayTagContainer& Container);

	virtual void OnTagUpdated(const FGameplayTag& Tag, bool TagExists) {};
	
	UE_API const UAttributeSet*	GetAttributeSubobject(const TSubclassOf<UAttributeSet> AttributeClass) const;
	UE_API const UAttributeSet*	GetAttributeSubobjectChecked(const TSubclassOf<UAttributeSet> AttributeClass) const;
	UE_API const UAttributeSet*	GetOrCreateAttributeSubobject(TSubclassOf<UAttributeSet> AttributeClass);

	UE_API void UpdateTagMap_Internal(const FGameplayTagContainer& Container, int32 CountDelta);

	friend struct FActiveGameplayEffect;
	friend struct FActiveGameplayEffectAction;
	friend struct FActiveGameplayEffectsContainer;
	friend struct FActiveGameplayCue;
	friend struct FActiveGameplayCueContainer;
	friend struct FGameplayAbilitySpec;
	friend struct FGameplayAbilitySpecContainer;
	friend struct FAggregator;
	friend struct FActiveGameplayEffectAction_Add;
	friend struct FGameplayEffectSpec;
	friend class AAbilitySystemDebugHUD;
	friend class UAbilitySystemGlobals;

private:

	// 修改 SpawnedAttributes 数组时必须调用,以便复制更改
	UE_API void SetSpawnedAttributesListDirty();

    // 在 AllReplicatedInstancedAbilities 数组上的弃用标记被移除并且我们可以再次直接引用该数组之前,对该数组的私有访问器。
	PRAGMA_DISABLE_DEPRECATION_WARNINGS
	TArray<TObjectPtr<UGameplayAbility>>& GetReplicatedInstancedAbilities_Mutable() { return AllReplicatedInstancedAbilities; }
	PRAGMA_ENABLE_DEPRECATION_WARNINGS

private:

	/** 属性集列表 */
	UPROPERTY(Replicated, ReplicatedUsing = OnRep_SpawnedAttributes, Transient)
	TArray<TObjectPtr<UAttributeSet>>	SpawnedAttributes; // 生成的属性

	UFUNCTION()
	UE_API void OnRep_SpawnedAttributes(const TArray<UAttributeSet*>& PreviousSpawnedAttributes);

	FDelegateHandle MonitoredTagChangedDelegateHandle; // 监视的标签更改委托句柄
	FTimerHandle    OnRep_ActivateAbilitiesTimerHandle; // OnRep 激活能力计时器句柄

	/** 用于复制松散游戏玩法标签的容器 */
	UPROPERTY(Replicated)
	FMinimalReplicationTagCountMap ReplicatedLooseTags; // 复制的松散标签

	uint8 bDestroyActiveStateInitiated : 1; // 是否已启动销毁活动状态
public:

	/** 缓存指示此组件是否具有网络权限的标志。 */
	UE_API void CacheIsNetSimulated();

	/** PredictionKeys,更多信息请参见 GameplayPrediction.h。这必须出现在 AbilitySystemComponent 上所有复制属性的*最后*,以确保 OnRep/回调顺序。 */
	UPROPERTY(Replicated, Transient)
	FReplicatedPredictionKeyMap ReplicatedPredictionKeyMap; // 复制的预测键映射

protected:

	struct FAbilityListLockActiveChange
	{
		FAbilityListLockActiveChange(UAbilitySystemComponent& InAbilitySystemComp,
									 TArray<FGameplayAbilitySpec, TInlineAllocator<2> >& PendingAdds,
									 TArray<FGameplayAbilitySpecHandle, TInlineAllocator<2> >& PendingRemoves) :
			AbilitySystemComp(InAbilitySystemComp),
			Adds(MoveTemp(PendingAdds)),
			Removes(MoveTemp(PendingRemoves))
		{
			AbilitySystemComp.AbilityListLockActiveChanges.Add(this);
		}

		~FAbilityListLockActiveChange()
		{
			AbilitySystemComp.AbilityListLockActiveChanges.Remove(this);
		}

		UAbilitySystemComponent& AbilitySystemComp;
		TArray<FGameplayAbilitySpec, TInlineAllocator<2> > Adds;
		TArray<FGameplayAbilitySpecHandle, TInlineAllocator<2> > Removes;
	};

	TArray<FAbilityListLockActiveChange*> AbilityListLockActiveChanges; // 能力列表锁活动更改

private:
	UE_API float PlayMontageInternal(UGameplayAbility* AnimatingAbility, FGameplayAbilityActivationInfo ActivationInfo, UAnimMontage* Montage, float InPlayRate, FName StartSectionName, float StartTimeSeconds, TFunctionRef<void(FGameplayAbilityRepAnimMontage&)> MutateRepAnimMontageFunction);
	
};

#undef UE_API

关键部分的中文注释,包括:

  1. 类概述:说明了 UAbilitySystemComponent 的主要功能和职责
  2. 主要模块:将代码分为属性、复制、游戏玩法效果、游戏玩法标签、游戏玩法提示、能力等模块
  3. 重要函数:对关键的公开函数进行了注释说明其用途和参数
  4. 重要成员变量:解释了主要成员变量的作用和意义
  5. 委托和枚举:对定义的委托和枚举进行了中文说明

这个组件是 Unreal Engine 游戏玩法能力系统的核心,负责管理游戏中的能力、效果、属性和标签系统。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值