# Gameplay Ability System (GAS)

> Use `query_ue_api` to discover exact class names, functions, and properties before writing any code. Use `dir()` in `execute_python` to inspect objects at runtime.

GAS setup combines C++ (AttributeSet, ASC init) and Blueprint assets (GameplayEffects, Abilities, Gameplay Cues).
C++ code uses `write_file` + `live_coding_compile`. Blueprint assets use `execute_python` with `import unreal`.

## Implementation Workflow

1. **C++ AttributeSet** — `write_file` to create .h/.cpp with `ATTRIBUTE_ACCESSORS` macro, `RepNotify`, clamp in `PreAttributeChange`
2. **C++ ASC init** — add `UAbilitySystemComponent` + AttributeSet as subobjects on Character. Init in `PossessedBy` (server) and `OnRep_PlayerState` (client)
3. **Gameplay Tags** — register in `DefaultGameplayTags.ini` via `edit_file`, or use C++ native tags
4. **Blueprint GameplayEffect** — create Blueprint asset with parent class `UGameplayEffect`. Use `query_ue_api` to discover the factory class and creation API, then `execute_python` to create and save the asset
5. **Blueprint GameplayAbility** — create Blueprint asset with parent class `UGameplayAbility`. Same discovery + creation workflow as effects
6. **Grant abilities** — wire up in BeginPlay or PossessedBy using `GiveAbility` / `FGameplayAbilitySpec`

## Creating GAS Blueprint Assets

All GAS Blueprint assets (GameplayEffect, GameplayAbility, GameplayCue) follow the same pattern:

1. Discover factory class and asset creation API via `query_ue_api`
2. Set parent_class to the appropriate GAS base class (GameplayEffect, GameplayAbility, GameplayCueNotify_Actor, or GameplayCueNotify_Static)
3. Create the asset, save it
4. Configure properties on the CDO (Class Default Object) — use `dir()` and `query_ue_api` to discover available properties

For GameplayEffects, key CDO properties:
- Duration policy — Instant, HasDuration, or Infinite
- Modifiers — array of attribute modifiers (attribute, operation, magnitude)
- Gameplay Cue Tags — tags that trigger associated Gameplay Cues

## C++ AttributeSet Pattern

The `ATTRIBUTE_ACCESSORS` macro generates getter/setter/init helpers per attribute. Replace attribute names to match your design.

```cpp
// MyAttributeSet.h
#pragma once
#include "CoreMinimal.h"
#include "AttributeSet.h"
#include "AbilitySystemComponent.h"
#include "MyAttributeSet.generated.h"

#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
    GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
    GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
    GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
    GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)

UCLASS()
class UMyAttributeSet : public UAttributeSet
{
    GENERATED_BODY()
public:
    // Add UPROPERTY + ATTRIBUTE_ACCESSORS for EACH attribute you need.
    // Pattern per attribute:
    //   UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_AttrName, Category = "Attributes")
    //   FGameplayAttributeData AttrName;
    //   ATTRIBUTE_ACCESSORS(UMyAttributeSet, AttrName)
    //   UFUNCTION() void OnRep_AttrName(const FGameplayAttributeData& OldValue);

    // Clamp values in PreAttributeChange (runs before any modification commits):
    virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
    virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
};
```

## C++ ASC Init on Character

```cpp
// In Character constructor
AbilitySystemComponent = CreateDefaultSubobject<UAbilitySystemComponent>(TEXT("ASC"));
AttributeSet = CreateDefaultSubobject<UMyAttributeSet>(TEXT("AttributeSet"));

// In PossessedBy (server-side init)
void AMyCharacter::PossessedBy(AController* NewController)
{
    Super::PossessedBy(NewController);
    if (AbilitySystemComponent)
    {
        AbilitySystemComponent->InitAbilityActorInfo(this, this);
    }
}
```

## Critical Rules

- **ASC init timing**: Server uses `PossessedBy`, Client uses `OnRep_PlayerState`. NEVER access ASC in CDO or constructors — use `BeginPlay` / `PostInitializeComponents` at earliest
- **Replication mode** — choose based on game type:
  - **Full**: replicate all GEs and tags to all clients (simplest, most bandwidth)
  - **Mixed**: only replicate to owning client (typical for player characters)
  - **Minimal**: no GE replication, only tags/cues (for AI/minions)
- **Instant GE**: `DurationPolicy = Instant` — apply and forget (one-time modifiers)
- **Duration GE**: `DurationPolicy = HasDuration` — temporary effect with timer
- **Infinite GE**: `DurationPolicy = Infinite` — persists until explicitly removed

## Naming Conventions

- `GE_` prefix for Gameplay Effects
- `GA_` prefix for Gameplay Abilities
- `GC_` prefix for Gameplay Cues

## Gameplay Cues

Gameplay Cues provide visual/audio feedback triggered by GAS events.

- **Notify (one-shot)**: inherits from `UGameplayCueNotify_Static` — fire-and-forget effects
- **Actor (persistent)**: inherits from `AGameplayCueNotify_Actor` — looping effects
- The Gameplay Cue Blueprint's `GameplayCueTag` must match the tag used in the GE or ability
- Tag naming follows `GameplayCue.Category.Name`
- Triggered via `AbilitySystemComponent->ExecuteGameplayCue(Tag)` or automatically when a GE with matching cue tags is applied

## Ability Targeting

- **TargetActor**: spawned during ability activation to select targets interactively
- **TargetData**: struct containing hit results, actor refs, or locations
- Common patterns: `AbilityTask_WaitTargetData`, `GameplayAbilityTargetActor_SingleLineTrace`
- For simple abilities: use `GetAvatarActorFromActorInfo()` and do traces directly in the ability

## Key Concepts

- **Attribute clamping**: override `PreAttributeChange` to clamp values within valid range
- **Effect stacking**: `StackingType` (`AggregateBySource` / `AggregateByTarget`), `StackLimitCount`
- **Attribute initialization**: use an Instant GE to set starting values for all attributes
- **Ability activation control**: use `TagRequirements` (RequiredTags / BlockedTags) on the ability to control when it can activate
- **API discovery**: use `query_ue_api` to find GAS-related classes and `dir()` to explore properties at runtime
- For replication of abilities/attributes in multiplayer, see **replication_advanced** knowledge module
