# Gameplay Tags System

Gameplay Tags are hierarchical string identifiers (e.g., `Status.Buff.Speed`) used throughout UE5 for categorization, ability filtering, and state management. Critical for GAS, AI, and game logic.

## Create Gameplay Tags via Python
```python
import unreal
# Tags are typically defined in DefaultGameplayTags.ini or DataTable
# Verify tag registration:
tag_manager = unreal.GameplayTagsManager.get()
tag = unreal.GameplayTag.request_gameplay_tag('Category.Subcategory.Name')
if tag.is_valid():
    print(f'Tag valid: {tag.get_tag_name()}')
else:
    print('Tag not registered — add it to GameplayTags config')
```

## Register tags in config (via edit_file or write_file)
Config/DefaultGameplayTags.ini:
```ini
[/Script/GameplayTags.GameplayTagsSettings]
+GameplayTagList=(Tag="Category.Subcategory.Name",DevComment="Description of this tag")
```

Each line adds one tag. Use dot-separated hierarchical naming. Design your tag hierarchy to match your project's domain — the structure is entirely up to you.

## C++ Gameplay Tag usage
```cpp
// HEADER — Declare tag as static native (fastest lookup, no string search)
#include "NativeGameplayTags.h"

UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_MyCategory_MyTag);

// SOURCE
UE_DEFINE_GAMEPLAY_TAG(TAG_MyCategory_MyTag, "MyCategory.MyTag");

// Using native tags (zero-cost at runtime):
if (TagContainer.HasTag(TAG_MyCategory_MyTag))
{
    // React to tag presence
}
```

## Gameplay Tag Containers
```cpp
// Container = set of tags
FGameplayTagContainer TagContainer;
TagContainer.AddTag(TAG_MyCategory_MyTag);
TagContainer.RemoveTag(SomeOtherTag);

// Query operations:
bool bHasExact = TagContainer.HasTagExact(TAG_MyCategory_MyTag);  // exact match only
bool bHasAny   = TagContainer.HasTag(TAG_MyCategory_MyTag);        // matches parent tags too
bool bHasAll   = TagContainer.HasAll(RequiredTags);                 // all tags present
bool bHasAny2  = TagContainer.HasAny(FilterTags);                  // any tag present

// Tag hierarchy: "A.B.C" matches queries for "A", "A.B", "A.B.C"
```

## Gameplay Tag Queries (complex matching)
```cpp
// Create a query: has Buff AND NOT Debuff
FGameplayTagQuery Query = FGameplayTagQuery::MakeQuery_MatchAllTags(
    FGameplayTagContainer::CreateFromArray(
        TArray<FGameplayTag>{ TAG_MyCategory_MyTag }));

bool bMatches = Query.Matches(ActorTagContainer);
```

## GAS integration with tags
Discover tag-related properties on GAS classes at runtime:
Use `query_ue_api` to discover tag-related properties on GAS classes like GameplayAbility (activation, blocking, cancellation tags) and GameplayEffect (granted tags, requirements, removal conditions).
Key concept: Abilities use tag properties to control activation (owned tags, blocked tags) and interaction (cancel/block other abilities). Effects use tags for granting, application requirements, and removal conditions.

## Tag hierarchy design principles

- Use dot-separated levels: `Category.Subcategory.Name`
- Keep depth to 3-5 levels maximum
- Parent tag queries match all children (`Status` matches `Status.TypeA`, `Status.TypeB`, etc.)
- Design the hierarchy to match your project's domain — there is no single "correct" structure
- `GameplayCue.*` tags are special — they trigger associated Gameplay Cue notifiers

## Build.cs dependencies
```csharp
PublicDependencyModuleNames.AddRange(new string[] {
    "GameplayTags"
});
```

## Naming conventions
- Dot-separated hierarchy: `Category.Subcategory.Name`
- PascalCase per segment: `Status.Buff.Speed` (not `status.buff.speed`)
- TAG_ prefix for C++ static variables (underscores replace dots): TAG_Category_Name
- Keep hierarchies max 4-5 levels deep

## Critical rules
- Always use native tags (`UE_DECLARE_GAMEPLAY_TAG_EXTERN`) in C++ for performance
- Register all tags in DefaultGameplayTags.ini or GameplayTagTableRow DataTable
- Tags are hierarchical: querying parent tag matches all children
- HasTag() checks hierarchy, HasTagExact() checks exact match only
- Gameplay Tags are globally unique — avoid duplicate definitions
- Add "GameplayTags" to Build.cs PublicDependencyModuleNames
- Use `execute_python` with `dir(unreal.GameplayTagContainer)` to discover tag API
