GAS Ally
The complete beginner-to-advanced documentation for the WCGASAlly module — Wonderscape Creations' deep RPG extension for Unreal Engine's Gameplay Ability System.
🧬 What is GAS Ally?
GAS Ally (WCGASAlly) is the flagship RPG-depth module of the Wonderscape Creations plugin framework. It sits on top of Unreal Engine's Gameplay Ability System (GAS) and the WCGASCore attribute layer to deliver a complete, production-ready RPG character simulation system.
Where vanilla GAS gives you raw tools — Attributes, Abilities, and Effects — GAS Ally gives you fully designed RPG systems built on those tools: dynamic leveling, multi-layer heritage (race/class/subclass), skill trees, status effect evolution chains, multi-layer resistance, squad AI, boss phases, world context reactions, and much more.
Heritage System
Race, class, subrace, and class blessings. Each Heritage Set shapes base attributes and unlocks passive gameplay effects.
Dynamic Leveling
12 formula types for XP curves. Configurable thresholds, milestones, and level-up rewards all driven by data assets.
Skill Trees
Designer-authored skill tree presets with custom unlock requirements, point costs, and MMC-based stat bonuses.
Status Effects
Status effect evolution chains, synergy combos, stacking rules, and per-tick processing — all data-driven.
Resistance System
Four independent resistance layers: Damage Reduction, Absorption, Diminishing Returns, and Resilience — with immunity support.
AI Combat
Behavior Tree nodes, EQS contexts, StateTree tasks, squad coordination, multi-tier threat, and boss phase transitions.
World Context
Environment volumes that apply Gameplay Effects based on proximity — weather, biomes, day/night, temperature.
Ability Curriculum
Guided ability learning system with costs, prerequisites, save/load support, and Blueprint library integration.
WCGASCore for its attribute pool and ability foundation. You do not need to use every other framework module — GAS Ally can be used with just the core GAS layer.How GAS Ally Relates to Other Modules
✅ Prerequisites
Before diving into GAS Ally, make sure your environment and knowledge base are properly prepared.
Engine & Tools
| Requirement | Version | Notes |
|---|---|---|
| Unreal Engine | 5.7.0+ | GAS Ally is built for UE 5.7+. No earlier versions supported. |
| Platform | Windows 64-bit | Mac, Linux, Android, and iOS are excluded in the plugin manifest. |
| Visual Studio | 2022 | Required for C++ compilation. Install the "Game development with C++" workload. |
| Project Type | C++ Project | A Blueprint-only project must be converted before the plugin will compile. |
Required Engine Plugins (Auto-Enabled)
WCGASAlly's .uplugin automatically enables these. You do not need to enable them manually:
| Plugin | Why GAS Ally Needs It |
|---|---|
GameplayAbilities | Core GAS foundation — attributes, effects, abilities, attribute sets. |
DataValidation | Editor-time asset validation runs on all Data Assets via WCGASAllyEditor. |
StateTree | AI StateTree tasks and conditions used by the AI combat system. |
GameplayStateTree | Bridges GAS (Gameplay Tags, ASC queries) into StateTree logic. |
Knowledge Prerequisites
GAS Ally is complex. The following knowledge will dramatically reduce your ramp-up time:
| Topic | Importance | Where to Learn |
|---|---|---|
| Gameplay Ability System (GAS) | Essential | tranek/GASDocumentation |
| Gameplay Tags | Essential | UE Docs — Gameplay Tags |
| Gameplay Effects | Essential | UE Docs — Gameplay Effects |
| Data Assets (Primary/Secondary) | Essential | UE Docs — Primary Data Assets |
| Modifier Magnitude Calculations (MMC) | Important | tranek GASDocumentation — MMC section |
| Gameplay Cues | Important | UE Docs — Gameplay Cues |
| Behavior Trees & EQS | Helpful for AI | UE Docs — Behavior Trees |
| StateTree | Helpful for AI | UE Docs — StateTree |
🔧 Installation
GAS Ally ships as part of the Dynamic RPG Worlds plugin package. You install the whole plugin, then use whichever modules you need.
-
Convert to C++ Project (if needed)
Blueprint-only projects cannot compile the plugin. If your project has no
Source/folder:- Open Unreal Editor
- Go to Tools → New C++ Class
- Choose any parent class (e.g.,
Actor) and click Create Class - The editor will generate the
Source/folder and.slnfile
-
Place the Plugin
Copy the entire
DynamicRPGWorldsfolder into your project'sPlugins/directory. Create the directory if it doesn't exist:YourProject/ ├── Content/ ├── Source/ └── Plugins/ └── DynamicRPGWorlds/ ← the whole plugin folder goes here ├── DynamicRPGWorlds.uplugin ├── Source/ │ ├── WCGASAlly/ ← GAS Ally runtime module │ └── WCGASAllyEditor/ ← GAS Ally editor module └── Documentation/ -
Enable in the Editor
- Open your project in Unreal Editor (it will offer to rebuild — click Yes)
- Go to Edit → Plugins
- Search for "Dynamic RPG Worlds"
- Toggle Enabled and click Restart Now
-
Rebuild Project Files
Right-click your
.uprojectfile in Windows Explorer and choose "Generate Visual Studio project files" so the new modules appear in your solution. -
Compile
Open the
.slnin Visual Studio 2022. Select Development Editor | Win64 configuration and press Ctrl+Shift+B.The first build compiles hundreds of files across all modules. Expect 5–15 minutes depending on your hardware. Subsequent builds are incremental and take seconds. -
Verify the GAS Ally Module
After the Editor launches, verify:
- Edit → Project Settings → scroll to the "WC GAS Ally" section — you should see it
- Right-click in the Content Browser → Miscellaneous → Data Asset — search for
WCGASAllyto see all GAS Ally Data Asset types available - Check the Output Log for
LogWCGASAllycategory messages at startup
🚀 Quick Start Guide
Follow this guide to build a working GAS Ally character from scratch — with heritage, leveling, a skill tree, and a status effect — in under one hour.
📋 What We'll Build
- A player character with a Heritage (race + class)
- A leveling system with XP and level-up rewards
- A skill tree with two unlockable nodes
- A "Burning" status effect that evolves into "Scorched" at 3 stacks
- A basic damage resistance layer
Step 1 — Add GAS Ally Components to Your Character
Open your player character Blueprint (parent: WCPlayerCharacter or any AWCCharacterBase descendant). In the Components panel, add the following components if not already present:
| Component | Class Name | Purpose |
|---|---|---|
| Leveling | UWCLevelingComponent | Tracks XP, current level, milestones |
| Heritage | UWCHeritageComponent | Applies race/class/subrace attribute modifications |
| Skill Tree | UWCSkillTreeComponent | Manages skill point spending and node unlocking |
| Status Effect | UWCStatusEffectComponent | Tracks active status effects, stacks, evolution |
| Resistance | UWCResistanceComponent | Manages DR, absorption, and resilience layers |
| Auto Regen | UWCAutoRegenComponent | Drives tick-based attribute regeneration |
| Ability Curriculum | UWCAbilityCurriculumComponent | Manages learnable ability catalog and costs |
WCPlayerCharacter provided by the framework's Core module, many of these components are already configured on the base class. Check the Components panel before adding duplicates.Step 2 — Create a Heritage Set (Race + Class)
-
Create a Race Definition
In Content Browser: Right-click → Miscellaneous → Data Asset → WCHeritage_RaceDefinition. Name it
DA_WC_Race_Human. Configure:- Display Name: "Human"
- Base Attribute Modifiers: add a modifier for
Health.Max(+50),Stamina.Max(+25) - Racial Blessings: leave empty for now (covered in Advanced section)
-
Create a Class Definition
Right-click → Data Asset → WCHeritage_ClassDefinition. Name it
DA_WC_Class_Warrior. Configure:- Display Name: "Warrior"
- Class Attribute Modifiers:
PhysicalAttack(+20),Armor(+15)
-
Create a Heritage Set
Right-click → Data Asset → WCHeritageSet. Name it
DA_WC_Heritage_HumanWarrior.- Set Race to
DA_WC_Race_Human - Set Class to
DA_WC_Class_Warrior - Leave Subrace empty for now
- Set Race to
-
Apply Heritage at BeginPlay
On your character Blueprint's Event BeginPlay node, call the
UWCHeritageComponentfunction: Apply Heritage Set, passing inDA_WC_Heritage_HumanWarrior.
Step 3 — Set Up Leveling
-
Create Leveling Rules
Right-click → Data Asset → WCLevelingRules. Name it
DA_WC_LevelingRules_Default.- Formula Type: choose
Exponentialfor a classic RPG curve - Base XP: 100
- Exponent: 1.5 (each level requires 1.5× more XP)
- Max Level: 50
- Level-Up Rewards: add a row for every level — e.g., at Level 2: Grant 2 Skill Points
- Formula Type: choose
-
Assign Rules to the Component
On your character Blueprint, select the
WCLevelingComponent. In the Details panel, set Leveling Rules toDA_WC_LevelingRules_Default. -
Test Granting XP
In the Blueprint, wire a test Input Action (e.g., press G) to call Grant XP on the
WCLevelingComponentwith an amount of 150. Watch for level-up notifications in the Output Log.
Step 4 — Build a Skill Tree
-
Create Skill Tree Data
Right-click → Data Asset → WCSkillTreePreset. Name it
DA_WC_SkillTree_WarriorBasic. Add nodes:- Node 0 — "Iron Skin": Cost 1 point, no prerequisites, grants +10 Armor via Gameplay Effect
- Node 1 — "Battle Hardened": Cost 2 points, requires Node 0, grants +25 Health Max via Gameplay Effect
-
Assign the Preset
On your character Blueprint, select the
WCSkillTreeComponent. Set Skill Tree Preset toDA_WC_SkillTree_WarriorBasic. -
Unlock a Node
Call Try Unlock Node on the
WCSkillTreeComponent, passing the Node ID and the character's ASC. The component checks prerequisites and skill point costs automatically.
Step 5 — Add a Status Effect (Burning → Scorched)
-
Create the "Burning" Status Effect Definition
Right-click → Data Asset → WCStatusEffectDefinition. Name it
DA_WC_Status_Burning.- Effect Tag:
WC.Status.Burning - Stacking: Aggregate, Max Stacks: 5
- Duration: 8 seconds
- Tick Interval: 1 second
- Tick GE: a Gameplay Effect that deals 5 fire damage per tick
- Effect Tag:
-
Create the "Scorched" Status Effect
Create a second
WCStatusEffectDefinitionnamedDA_WC_Status_Scorchedwith more severe fire damage (15 per tick) and 12 second duration. -
Create an Evolution Rule
Right-click → Data Asset → WCStatusEvolutionRule. Configure:
- Source Effect:
DA_WC_Status_Burning - Evolves To:
DA_WC_Status_Scorched - Trigger: Stack Count ≥ 3
- Source Effect:
-
Apply the Status in Blueprint
Call Apply Status Effect on the target character's
WCStatusEffectComponent, passingDA_WC_Status_Burning. Each repeated call adds a stack. At 3 stacks, the evolution triggers automatically.
AWCDummy actor in your level. It has a pre-configured ASC you can apply status effects to, letting you test evolution and resistance without needing a full combat setup.🏗️ Architecture Overview
GAS Ally is organized into interconnected systems, each with its own component, subsystem, data assets, and function library. Understanding this structure is essential before building anything complex.
System Organization
| System | Component | Subsystem | Data Asset(s) |
|---|---|---|---|
| Heritage | UWCHeritageComponent | UWCHeritageSubsystem | WCHeritageSet, WCHeritage_RaceDefinition, WCHeritage_ClassDefinition, WCHeritage_SubraceDefinition |
| Leveling | UWCLevelingComponent | UWCLevelingSubsystem | WCLevelingRules |
| Skill Tree | UWCSkillTreeComponent | — | WCSkillTreePreset |
| Status Effects | UWCStatusEffectComponent | UWCStatusEffectSubsystem | WCStatusEffectDefinition, WCStatusEvolutionRule, WCStatusSynergyRule |
| Resistance | UWCResistanceComponent | UWCResistanceSubsystem | WCResistanceData |
| Auto Regen | UWCAutoRegenComponent | UWCRegenSubsystem | — |
| Curriculum | UWCAbilityCurriculumComponent | — | WCAbilityCurriculumData |
| Ability Library | — | — | WCAbilityBook, WCAbilityPage |
| Feats | UWCFeatComponent | — | WCFeatPool, WCFeatMilestone |
| World Context | — | UWCWorldContextSubsystem | WCWorldContextData, Volumes (AWCWorldContextVolume) |
| Transfer | — | UWCTransferSubsystem | WCTransferTypes |
| Difficulty | — | UWCDifficultySubsystem | WCDifficultyTier |
| Faction | — | — | WCFactionRelations, WCFactionAgent |
| AI Combat | UWCCombatAIComponent | UWCCombatAISubsystem | WCSquadData, WCThreatData, WCBossPhaseData |
| Overflow | — | UWCOverflowSubsystem | — |
Data Flow: How a Character is Initialized
UWCGASAttributeInitializer) — Pools and registers attributes from Definitions; sets base valuesThe Editor Module (WCGASAllyEditor)
The editor module provides quality-of-life tooling that is not present at runtime. It includes:
- Asset Factories — Right-click → Data Asset menus for all GAS Ally asset types
- Attribute Validator — Validates attribute definition assets at editor compile time
- Property Customizations — Custom Details panels for complex data structures (resistance tables, evolution chains)
- Gameplay Debug Category — Adds a
WCGASAllycategory to the Gameplay Debugger (` → 5) showing live attribute values, active status effects, and threat data
📊 Attribute System
GAS Ally uses the WCGASCore attribute pool as its foundation. Rather than hard-coding UAttributeSet subclasses with fixed properties (the vanilla GAS approach), WCGASCore provides a dynamic pool of 150 float attribute slots that are mapped at runtime to named definitions.
How Attributes Work in GAS Ally
- You create a
WCGASAttributeDefinitionData Asset for each attribute (Health, Mana, Stamina, PhysicalAttack, etc.). - You register each definition in Project Settings → WCGASCore → Attribute Definitions.
- At runtime, the
UWCGASAttributeInitializercomponent reads the registry and assigns each definition to a pool slot (up to 150). - Every GAS Ally system (damage calcs, regen, resistance, skill trees) references attributes by their Gameplay Tag name, not by C++ property pointers — so you never need to recompile to add a new attribute.
Attribute Definition Properties
| Property | Type | Description |
|---|---|---|
AttributeTag | FGameplayTag | Unique tag identifier, e.g. WC.Attribute.Health |
DisplayName | FText | Human-readable name shown in UI |
BaseValue | float | Default starting value |
MinValue | float | Hard minimum (usually 0) |
MaxValue | float | Hard maximum (usually driven by a MaxAttribute) |
MaxAttributeTag | FGameplayTag | Optional — links this attribute's max to another attribute's current value |
bSupportsRegen | bool | Enables auto-regen subsystem processing for this attribute |
RegenRateTag | FGameplayTag | Points to another attribute that stores the regen rate (e.g. WC.Attribute.HealthRegenRate) |
bSaveable | bool | Whether current value is included in save data |
Category | FName | Optional grouping for UI (e.g. "Vitals", "Offense", "Defense") |
The 12 Formula Types (Attribute Modifiers)
When other systems (Heritage, Skill Trees, Leveling rewards) apply modifications to attributes, they use one of 12 formula types:
| Formula | Behavior | Example |
|---|---|---|
FlatAdd | Adds a fixed number | +50 Health |
FlatMultiply | Multiplies by a fixed factor | ×1.2 Attack |
PercentAdd | Adds a percentage of base | +10% of base Max Health |
PercentMultiply | Multiplies current by a percent | ×85% (nerfs the stat) |
Clamp | Clamps attribute between min and max values | Ensure Armor stays 0–500 |
Override | Sets to a specific value, ignoring all other mods | Force Speed = 0 (frozen) |
LevelScale | Scales by character level | +5 × Level Armor |
AttributeRef | Derives value from another attribute | SpellPower = 0.5 × Intelligence |
CurveTable | Reads from a UCurveTable keyed on level | XP required per level from a curve |
Conditional | Applies only when a tag condition is met | +30 Attack when WC.Buff.Enrage is active |
Stacking | Scales with stack count of an active effect | Each Bleed stack = +3 damage |
Custom | Calls a custom UWCGASMMCalc subclass | Complex multi-stat formula in C++ |
UWCGASMMCalc_AttributeMod, the framework's universal Modifier Magnitude Calculation class. You rarely need to create custom MMCs unless your formula is uniquely complex.🔩 Key Components
Every GAS Ally system is delivered as an Actor Component. You add them to any character (player or AI) and they auto-register with their corresponding subsystem.
Component Quick Reference
| Component Class | Replicates? | Add to | Key Events/Functions |
|---|---|---|---|
UWCLevelingComponent | Yes | Character or PlayerState | GrantXP, OnLevelUp (delegate), GetCurrentLevel |
UWCHeritageComponent | Yes | Character | ApplyHeritageSet, GetActiveRace, GetActiveClass |
UWCSkillTreeComponent | Yes | Character or PlayerState | TryUnlockNode, GetAvailablePoints, IsNodeUnlocked |
UWCStatusEffectComponent | Yes | Any Actor with ASC | ApplyStatusEffect, RemoveStatusEffect, GetActiveEffects |
UWCResistanceComponent | Yes | Any Actor with ASC | RegisterResistanceData, QueryFinalDamage |
UWCAutoRegenComponent | No (server only) | Any Actor with ASC | PauseRegen, ResumeRegen, SetRegenMultiplier |
UWCAbilityCurriculumComponent | Yes | Character or PlayerState | LearnAbility, CanLearnAbility, GetCurriculumProgress |
UWCFeatComponent | Yes | Character or PlayerState | CheckMilestone, GetEarnedFeats |
UWCCombatAIComponent | Server only | AI Character | SetCurrentTarget, GetSquadAgent, TransitionBossPhase |
⚙️ Subsystems
Subsystems are long-lived game-wide or world-wide singletons that manage global state for each GAS Ally system. They are accessed via GetWorld()->GetSubsystem<U...Subsystem>() in C++ or via the Blueprint function libraries.
| Subsystem Class | Type | Responsibilities |
|---|---|---|
UWCRegenSubsystem | World | Tick-based regen and degen processing for all registered characters |
UWCAttributeModSubsystem | World | Queues and batches attribute modification events for performance |
UWCResistanceSubsystem | World | Centralized resistance query cache; reduces per-frame GE queries |
UWCStatusEffectSubsystem | World | Global registry of active status effects; drives tick and evolution logic |
UWCLevelingSubsystem | World | Centralized XP event routing; handles multi-grant and milestone checks |
UWCHeritageSubsystem | World | Validates heritage asset combinations; caches applied GEs per character |
UWCEventsSubsystem | World | Global event bus for GAS Ally events (level up, evolution, feat earned, etc.) |
UWCWorldContextSubsystem | World | Manages active context volumes and applies/removes their GEs dynamically |
UWCOverflowSubsystem | World | Handles attribute value overflow (excess HP → shield, excess Mana → stored) |
UWCCombatAISubsystem | World | Manages squad registrations, threat tables, and boss phase orchestration |
UWCDifficultySubsystem | Game Instance | Persists difficulty tier across levels; applies global difficulty GE modifiers |
Listening to Subsystem Events
The UWCEventsSubsystem is the recommended way to react to GAS Ally events in Blueprint. All major events are broadcast as delegates:
// C++ — bind to the events subsystem
if (UWCEventsSubsystem* Events = GetWorld()->GetSubsystem<UWCEventsSubsystem>())
{
Events->OnCharacterLevelUp.AddDynamic(this, &ThisClass::HandleLevelUp);
Events->OnStatusEffectEvolved.AddDynamic(this, &ThisClass::HandleEvolution);
Events->OnFeatEarned.AddDynamic(this, &ThisClass::HandleFeat);
}
⚙️ Settings Reference
GAS Ally settings live under Edit → Project Settings → WC GAS Ally via the UWCGASAllySettings class. All settings are loaded once at startup and cached.
| Property | Type | Description |
|---|---|---|
DefaultDifficultyTier | TSoftObjectPtr<WCDifficultyTier> | Starting difficulty tier applied on new game |
GlobalStatusEvolutionRules | TArray<...> | Evolution rules applied globally regardless of which component applied the effect |
GlobalSynergyRules | TArray<...> | Synergy combos checked globally across all active status effects |
RegenTickInterval | float | How often (seconds) the regen subsystem ticks. Default: 0.25 |
bEnableOverflowSystem | bool | Toggle the overflow attribute system entirely |
bEnableDebugLogging | bool | Enables verbose LogWCGASAlly output |
DefaultResistanceData | TSoftObjectPtr<WCResistanceData> | Fallback resistance rules used if a character has no resistance component |
ThreatDecayInterval | float | How often (seconds) the threat system decays threat values. Default: 5.0 |
ThreatDecayRate | float | Fraction of threat lost per decay tick. Default: 0.1 (10%) |
MaxSquadSize | int32 | Hard cap on squad member count. Default: 8 |
BossPhaseTransitionDelay | float | Seconds to wait after threshold hit before triggering boss phase. Default: 0.5 |
🧬 Heritage System
The Heritage System defines a character's biological and vocational identity. A Heritage Set is composed of up to four layers:
Race
Base biological traits. Affects vitals, natural resistances, and grants racial passive effects.
Class
Vocational archetype. Affects combat stats, unlocks class-specific abilities, and defines role bonuses.
Subrace
Optional refinement of race. Adds deeper thematic attributes and modifies racial bonuses.
Blessings
Optional passive GES granted at character creation. Can be unlocked by game events or quests.
Heritage Data Assets
WCHeritage_RaceDefinition
| Property | Description |
|---|---|
RaceTag | Gameplay Tag for this race, e.g. WC.Heritage.Race.Human |
DisplayName | Localizable name shown in character creation UI |
Description | Lore text for the race |
AttributeModifiers | Array of FWCAttributeModifierData — stat boosts applied via GE on character init |
GrantedGameplayEffects | Permanent GEs granted at init (e.g. a passive "Night Vision" GE for Elves) |
GrantedAbilities | Ability classes granted automatically (e.g. "Darkvision" ability for Dark Elves) |
ValidSubraces | Array of compatible WCHeritage_SubraceDefinition assets |
WCHeritage_ClassDefinition
| Property | Description |
|---|---|
ClassTag | Gameplay Tag, e.g. WC.Heritage.Class.Warrior |
AttributeModifiers | Combat stat boosts (Attack, Defense, Speed, etc.) |
GrantedAbilities | Class-specific ability classes granted at init |
DefaultSkillTreePreset | Skill tree automatically assigned when this class is chosen |
DefaultCurriculumData | Ability curriculum automatically assigned |
WCHeritageSet
The Heritage Set is the top-level asset you apply to a character. It references all four layers and is the only asset the WCHeritageComponent needs:
// Apply a heritage set in Blueprint via the component function
UWCHeritageComponent* Heritage = Character->FindComponentByClass<UWCHeritageComponent>();
Heritage->ApplyHeritageSet(HumanWarriorHeritageSet);
Heritage Validation
The WCGASAllyEditor module validates Heritage assets at compile time. Common validation errors:
| Error | Cause | Fix |
|---|---|---|
| "Subrace not valid for Race" | The selected Subrace is not in the Race's ValidSubraces list | Add the Subrace to the Race's ValidSubraces array, or choose a compatible subrace |
| "Missing RaceTag" | Race definition has no RaceTag assigned | Assign a unique Gameplay Tag to the Race asset |
| "Duplicate heritage tag" | Two races or two classes share the same Gameplay Tag | Ensure every heritage definition has a unique tag |
📈 Leveling System
The Leveling System provides a completely data-driven approach to character progression. XP formulas, thresholds, milestones, and rewards are all authored in Data Assets — no C++ required for most setups.
WCLevelingRules Data Asset
| Property | Type | Description |
|---|---|---|
FormulaType | EWCLevelingFormula | Which XP formula to use (see table below) |
BaseXP | float | XP required at Level 1 → 2 |
Exponent | float | Used by Exponential / Power formulas |
LinearIncrement | float | Added XP per level (for Linear formula) |
XPCurveTable | UCurveTable | Custom XP curve when FormulaType = CurveTable |
MaxLevel | int32 | Cap on character level |
LevelUpRewards | TMap<int32, FWCLevelReward> | Per-level reward configuration (skill points, GEs, abilities) |
Milestones | TArray<FWCLevelMilestone> | Special events at key levels (e.g. unlock Subrace choice at Level 5) |
XP Formula Types
| Formula | Equation | Best For |
|---|---|---|
Linear | XP(L) = BaseXP + (LinearIncrement × L) | Consistent, flat progression (casual games) |
Exponential | XP(L) = BaseXP × Exponent^L | Classic RPG steep late-game curve |
Power | XP(L) = BaseXP × L^Exponent | Moderate curve that scales with level |
Polynomial | XP(L) = BaseXP × L² × Exponent | Quadratic — mild early, steep late |
CurveTable | XP(L) = CurveTable.Eval(L) | Full designer control per level |
Custom | Calls a subclassed UWCLevelingCustomFormula | Complex or runtime-dynamic formulas in C++ |
Level-Up Rewards
The LevelUpRewards TMap lets you specify exactly what happens at each level-up. Each FWCLevelReward struct contains:
- SkillPointsGranted — How many skill points are added to the Skill Tree pool
- AbilitiesToGrant — Array of ability classes to grant via the ASC
- GameplayEffectsToApply — GEs applied at level-up (stat boosts, permanent buffs)
- MilestoneTag — Optional tag broadcast on the events subsystem at this level
Using the Leveling Component
// Blueprint callable functions on UWCLevelingComponent:
// Grant XP (triggers level-up if threshold reached)
LevelingComp->GrantXP(500.0f);
// Get current level
int32 Level = LevelingComp->GetCurrentLevel();
// Get XP progress toward next level (0.0 - 1.0)
float Progress = LevelingComp->GetLevelProgress();
// Force set level (bypasses XP, used for save-game restore)
LevelingComp->SetLevel(10, /* bApplyRewards */ false);
GrantXP must be called on the server. Level-up and reward processing happens server-side and replicates the new level/XP values to clients. Bind to the OnLevelUp multicast delegate for client-side effects (UI updates, VFX).🌳 Skill Trees
The Skill Tree system is a graph-based progression system where characters spend earned skill points to unlock nodes that permanently enhance their capabilities.
WCSkillTreePreset Data Asset
A Skill Tree Preset defines the entire tree for a character archetype. Properties:
| Property | Description |
|---|---|
TreeTag | Unique Gameplay Tag for this tree, e.g. WC.SkillTree.Warrior |
DisplayName | Name shown in UI |
Nodes | Array of FWCSkillTreeNode structs defining all nodes |
Skill Tree Node Properties (FWCSkillTreeNode)
| Property | Description |
|---|---|
NodeID | Unique integer ID within the tree |
DisplayName | Node name shown in UI |
Description | What this node does (for tooltips) |
PointCost | Skill points required to unlock |
PrerequisiteNodeIDs | Array of NodeIDs that must be unlocked first |
GameplayEffectsToApply | GEs permanently applied when unlocked |
AbilitiesToGrant | Abilities granted when unlocked |
UnlockRequirement | Optional custom C++ UWCSkillTreeUnlockRequirement class for special gates |
UIGridPosition | FVector2D position for visual layout in the UI grid |
MMC-Based Bonuses
Skill tree nodes that grant attribute bonuses use the GAS Modifier Magnitude Calculation system. The recommended pattern is to create a Gameplay Effect with a Modifier that uses an MMC_WCSkillTree_* class — these are pre-built MMCs in the framework that evaluate bonuses based on how many nodes in a category are unlocked:
// Example: A node that grants +5 Strength per Warrior-category node unlocked
// GE Modifier: Attribute = WC.Attribute.Strength
// Magnitude Calculation: MMC_WCSkillTree_CategoryCount
// Coefficient: 5.0
// Category Tag: WC.SkillTree.Category.Warrior
Custom Unlock Requirements Advanced
For complex unlock conditions (e.g. "Unlock only if player has completed a quest tag"), create a C++ class inheriting UWCSkillTreeUnlockRequirement and override:
UCLASS()
class UMyCustomUnlock : public UWCSkillTreeUnlockRequirement
{
GENERATED_BODY()
public:
virtual bool CanUnlock(const UWCSkillTreeComponent* TreeComp,
const UAbilitySystemComponent* ASC,
const FWCSkillTreeNode& Node) const override
{
// Your custom logic here
return ASC->HasMatchingGameplayTag(FGameplayTag::RequestGameplayTag("WC.Quest.Completed.HunterTrial"));
}
};
🎓 Ability Curriculum
The Ability Curriculum is a guided learning system for abilities. Instead of abilities being granted automatically (as with Heritage or Leveling), the Curriculum lets designers define a catalog of learnable abilities with costs and prerequisites — and players actively choose what to learn.
WCAbilityCurriculumData
| Property | Description |
|---|---|
CurriculumTag | Unique tag for this curriculum, e.g. WC.Curriculum.Warrior |
LearnableAbilities | Array of FWCCurriculumEntry — each entry is one ability and its cost/prerequisite |
Curriculum Entry (FWCCurriculumEntry)
| Property | Description |
|---|---|
AbilityClass | The Gameplay Ability class to learn |
DisplayName | Name shown in the ability selection UI |
Description | Tooltip / description text |
CurrencyCost | Amount of in-game currency required |
SkillPointCost | Skill points required (shared pool with Skill Tree) |
RequiredLevel | Minimum character level to learn |
PrerequisiteAbilities | Array of ability classes that must be learned first |
RequiredTags | Gameplay Tag Container — character must have ALL tags to learn this ability |
Learning an Ability in Blueprint
-
Check if Learnable
Call
CanLearnAbility(AbilityClass)on theUWCAbilityCurriculumComponent. Returns a struct with:bCanLearn,FailureReason(for UI feedback). -
Spend Resources and Learn
Call
LearnAbility(AbilityClass)on the server. The component deducts costs, grants the ability via the ASC, and saves the learned state. -
Listen for the Callback
Bind to
OnAbilityLearneddelegate on the component or listen via theUWCEventsSubsystem.
📚 Ability Library
The Ability Library provides a hierarchical catalog system for organizing abilities — Books contain Pages, and Pages contain Ability Definitions. This gives designers a structured way to author and navigate large ability sets.
| Asset Type | Analogy | Contains |
|---|---|---|
WCAbilityBook | A spellbook tome | Multiple WCAbilityPage assets |
WCAbilityPage | A chapter in the tome | Multiple WCAbilityDefinition references |
WCAbilityDefinition | A single spell/ability entry | Ability class, metadata, requirements, icon |
The Ability Library is primarily a data organization and query tool. You can ask it: "Give me all Fire magic abilities available to a Level 10 Mage" and it returns the filtered list. UI systems then present the results to the player.
// Blueprint API example:
// Get all abilities in a book that the character can use
TArray<FWCAbilityDefinition> Available =
UWCGASAbilityLibFuncLib::QueryAbilityBook(FireMagicBook, Character->GetASC());
🏆 Feats System
Feats are achievement-like milestones that characters earn through gameplay events. They are tracked by the UWCFeatComponent and trigger gameplay rewards when milestones are reached.
WCFeatPool
A collection of trackable feat counters. Each feat in the pool has:
| Property | Description |
|---|---|
FeatTag | Unique tag, e.g. WC.Feat.EnemiesKilled |
DisplayName | UI name, e.g. "Kills" |
IncrementEvents | Gameplay Tags that, when fired at the ASC, automatically increment this counter |
WCFeatMilestone
Milestones define rewards at specific counter thresholds:
| Property | Description |
|---|---|
FeatTag | Which feat counter this milestone watches |
Threshold | Counter value that triggers this milestone |
MilestoneTag | Broadcast tag when milestone triggers |
RewardGE | Gameplay Effect applied as reward (permanent stat boost, new ability, etc.) |
bOneTimeOnly | If true, only triggers once even if counter passes threshold again |
Auto-Tracking via Gameplay Tags
The most powerful feature of Feats: they can auto-increment using existing Gameplay Event Tags. If you set IncrementEvents to include WC.Event.EnemyKilled, then every time that tag is sent to the ASC (e.g. by a damage execution), the feat counter goes up — no extra Blueprint wiring needed.
// Send a feat increment event from C++ or Blueprint
FGameplayEventData Payload;
UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(
Character,
FGameplayTag::RequestGameplayTag("WC.Event.EnemyKilled"),
Payload
);
💀 Status Effects
GAS Ally's Status Effect system extends standard Gameplay Effects with stacking logic, custom tick behavior, evolution chains, and synergy combos. It is one of the most powerful and configurable systems in the plugin.
WCStatusEffectDefinition
| Property | Description |
|---|---|
EffectTag | Unique tag, e.g. WC.Status.Burning |
DisplayName | UI name |
Icon | Texture2D icon for status bar UI |
StackingPolicy | How stacks are counted: Aggregate, Replace, Unique |
MaxStacks | Maximum number of stacks allowed (1 = non-stacking) |
DurationSeconds | How long the effect lasts. 0 = infinite (until removed) |
bRefreshOnStack | If true, adding a stack resets the duration timer |
TickIntervalSeconds | How often the Tick GE is applied. 0 = no tick |
TickGameplayEffect | GE applied each tick (damage, heal, drain, etc.) |
OnApplyGameplayEffect | GE applied once when first applied |
OnRemoveGameplayEffect | GE applied once when removed (e.g. reverse a stat debuff) |
EvolutionRules | Inline list of evolution conditions — see Status Evolution section |
TagsToAddOnApply | Gameplay Tags added to the target's tag container while active |
TagsToBlockWhileActive | Gameplay Tags that cannot be applied while this effect is active |
Stacking Policies
| Policy | Behavior |
|---|---|
Aggregate | Each application adds a stack. All stacks share one timer (refreshable). Tick GE scales with stack count. |
Replace | Each new application replaces the previous entirely, resetting timer and stack count to 1. |
Unique | Applying while already active does nothing. Only one instance allowed, no stacks. |
Applying and Removing Status Effects
// Blueprint callable via UWCStatusEffectComponent:
// Apply a status effect (adds a stack if already present)
StatusEffectComp->ApplyStatusEffect(DA_WC_Status_Burning, Instigator);
// Remove all stacks of a specific status
StatusEffectComp->RemoveStatusEffect(DA_WC_Status_Burning);
// Remove one stack
StatusEffectComp->RemoveStatusEffectStack(DA_WC_Status_Burning, 1);
// Check if a status is active
bool bIsBurning = StatusEffectComp->IsStatusEffectActive(FGameplayTag("WC.Status.Burning"));
🔥 Status Effect Evolution
Evolution allows a status effect to automatically transform into a more powerful variant when certain conditions are met. This enables deep combat interaction design — e.g., Wet + Lightning = Electrified, or 3× Burning → Scorched.
WCStatusEvolutionRule
| Property | Description |
|---|---|
SourceEffectTag | The status effect that triggers the evolution |
EvolvesToDefinition | The WCStatusEffectDefinition to replace the source with |
TriggerCondition | What causes evolution: StackThreshold, DurationThreshold, TagPresent, HealthThreshold |
StackThreshold | Stack count that triggers (used with StackThreshold condition) |
DurationRemainingSeconds | Triggers when this many seconds remain (used with DurationThreshold) |
RequiredTag | Tag that must be present on target (used with TagPresent) |
HealthPercentThreshold | Target health % at or below which evolution triggers (0.0–1.0) |
bConsumeSource | If true, the source status is removed when evolving (default: true) |
bTransferStacks | If true, remaining stacks are transferred to the evolved effect |
Evolution Flow
OnStatusEffectEvolved broadcast on UWCEventsSubsystem (bind for VFX/SFX/UI)⚡ Status Synergy
Synergy goes beyond evolution — it triggers effects when two or more different status effects are active simultaneously on the same target. This creates emergent elemental interaction systems.
WCStatusSynergyRule
| Property | Description |
|---|---|
RequiredStatusTags | All of these status tags must be active simultaneously to trigger the synergy |
SynergyTag | Gameplay Tag broadcast as a Gameplay Event when synergy triggers |
SynergyEffect | Optional GE applied immediately when synergy fires (e.g. a burst of damage) |
NewStatusToApply | Optional new status effect applied as a result of the synergy |
bConsumeInputEffects | If true, all RequiredStatusTags are removed when synergy fires |
CooldownSeconds | How long before this synergy can trigger again on the same target |
Priority | Higher priority synergies are evaluated first when multiple could fire simultaneously |
Example: Wet + Burning = Explosion
// Synergy Rule Data Asset: DA_WC_Synergy_WetBurning
// RequiredStatusTags: [WC.Status.Wet, WC.Status.Burning]
// SynergyEffect: DA_GE_SteamExplosion (heavy AoE damage)
// NewStatusToApply: DA_WC_Status_Steamed (vision-impairing steam cloud)
// bConsumeInputEffects: true (removes Wet and Burning)
// CooldownSeconds: 10.0
WCStatusEffectDefinition's inline array, but global rules are the recommended approach for elemental interactions.🛡️ Resistance System
GAS Ally provides four independent resistance layers, each implemented as a Gameplay Effect Component. They are evaluated in order during damage calculation and can be stacked, overridden, or diminished.
The Four Resistance Layers
Damage Reduction (DR)
Flat point reduction applied before percentage calculations. Example: 50 DR reduces 100 damage to 50.
Absorption
Percentage of damage absorbed after DR. Example: 20% absorption on 50 damage = 40 final damage.
Diminishing Returns (DR²)
Prevents stacking resistance to trivialize combat. A DR² component caps effective resistance using a configured curve.
Resilience
Post-absorption resilience factor — how quickly the character recovers from high damage spikes. Applied as a multiplier on the damage received this frame.
Resistance Data Asset (WCResistanceData)
| Property | Description |
|---|---|
DamageTypeTag | Which damage type this data applies to (e.g. WC.DamageType.Fire). Use WC.DamageType.Any for global resistance. |
FlatReduction | Flat DR amount subtracted from incoming damage |
AbsorptionPercent | 0.0–1.0 percentage of post-DR damage absorbed |
DiminishingCurve | CurveFloat mapping total absorption % to effective absorption % (to implement DR²) |
ResilienceFactor | Multiplier on final damage received. 1.0 = no effect. 0.8 = 20% effective reduction. |
Damage Calculation Order
Per-Damage-Type vs. Global Resistance
You can register multiple WCResistanceData assets with different DamageTypeTag values on the same character. When damage comes in, the system queries:
- Exact type match (e.g.
WC.DamageType.Fire) - Parent tag match (e.g.
WC.DamageType.Elementalif Fire has no specific entry) - Global fallback (
WC.DamageType.Any)
All matching entries are combined — so a character can have base physical resistance AND bonus fire resistance from a Heritage effect simultaneously.
🚫 Immunity System
The Immunity GE Component (UWCImmunityGEComponent) is a Gameplay Effect Component that, when active on a character's ASC, blocks specific damage types or status effects entirely.
Creating an Immunity Effect
-
Create a Gameplay Effect
Create a new Gameplay Effect of type Infinite (since immunity usually needs to stay active).
-
Add the Immunity Component
In the GE's Gameplay Effect Components array, add
WCImmunityGEComponent. -
Configure Tags to Block
In the component's properties:
- DamageTypesToBlock: Tag container of damage types that are completely nullified
- StatusEffectsToBlock: Tag container of status effect tags that cannot be applied
- bBlockAll: Set true for complete damage immunity (boss phase invincibility, cutscene, etc.)
-
Apply the GE
Apply this GE to the character's ASC like any Gameplay Effect. Remove it to end immunity.
WC.Status.Immune Gameplay Tag with TagsToBlockWhileActive on a Status Effect definition instead.💚 Regen & Degeneration
The Auto-Regen system ticks at a configurable interval and applies regeneration or degeneration to any attribute that has bSupportsRegen = true in its definition and a configured regen-rate attribute.
How Regen Works
- The
UWCRegenSubsystemticks everyRegenTickIntervalseconds (default: 0.25s). - For each registered character, it queries all attributes with
bSupportsRegen = true. - It reads the current value of the linked
RegenRateTagattribute. - It applies a small GE that adds
RegenRate × TickIntervalto the attribute. - Degeneration works identically — a negative regen rate causes the attribute to decrease over time.
Regen MMCs
For more complex regen behavior (e.g. regen that scales with out-of-combat duration), GAS Ally provides pre-built MMCs:
| MMC Class | Behavior |
|---|---|
UWCGASMMCalc_PercentRegen | Regenerates a percentage of max attribute per tick |
UWCGASMMCalc_Degeneration | Applies degeneration (negative regen) scaled by a tag condition |
UWCGASMMCalc_AttributeMod | Universal modifier calc (see Attribute System section) |
Pausing and Resuming Regen
The UWCAutoRegenComponent exposes control functions for gameplay scenarios (stunned characters shouldn't regen mana, combat zones stop health regen, etc.):
// Pause all regen on this character
AutoRegenComp->PauseRegen();
// Resume with a multiplier (0.5 = half regen rate, useful for out-of-combat bonus)
AutoRegenComp->ResumeRegen(/* Multiplier */ 2.0f);
// Pause only specific attribute
AutoRegenComp->PauseAttributeRegen(FGameplayTag::RequestGameplayTag("WC.Attribute.Mana"));
⚔️ Damage & Healing Calculations
GAS Ally provides a rich set of Execution Calculations and helper libraries for all damage and healing processing.
Damage Execution Calculation
All combat damage flows through the GAS Execution Calculation system. GAS Ally's damage calc (UWCGASExecCalc_Damage) performs the following pipeline:
Damage Calculation Library (UWCDamageCalcLibrary)
Blueprint-callable helper functions for querying and manually computing damage values:
| Function | Description |
|---|---|
CalculatePhysicalDamage | Compute final physical damage between attacker and defender without applying it |
CalculateMagicalDamage | Same for magical damage (uses SpellPower, MagicDefense) |
GetEffectiveDamageAfterResistance | Run only the resistance pipeline on a raw damage value |
WillCritical | Evaluate crit chance roll (for ability prediction/preview) |
Healing Execution Calculation
Healing uses UWCGASExecCalc_Healing. It captures the healer's HealingPower attribute, applies any healing bonuses (buffs via GE), and clamps the result to the target's MaxHealth. Overheal (excess healing) routes to the Overflow System if configured.
🤖 AI Systems Overview
GAS Ally ships a complete AI combat framework that integrates tightly with GAS. The AI system is not just about movement — it is a full tactical simulation layer including threat management, squad coordination, and boss phase scripting.
AI Architecture Layers
Behavior Trees
Custom BT Tasks, Decorators, and Services that query GAS state, manage threat, and coordinate with squads.
EQS Integration
Custom EQS Contexts, Tests, and Generators that let AI queries understand GAS concepts like line of sight, threat range, and ally positions.
StateTree
StateTree Tasks and Conditions for high-level AI state management — patrol, combat, retreat, boss phases.
Squad System
Groups of AI actors that share threat information, coordinate attacks, and divide roles (tank, flanker, ranged).
Threat System
Multi-tier threat tables that determine target priority. Threat decays over time and is modified by actions.
Boss Phases
Health-threshold-based phase transitions that change AI behavior, abilities, and stats dramatically.
The Combat AI Component
UWCCombatAIComponent is the hub that connects all AI systems. Add it to any AI character class:
| Property | Description |
|---|---|
SquadData | Reference to WCSquadData asset defining this AI's squad configuration |
ThreatData | Reference to WCThreatData asset defining threat modifiers and decay |
BossPhaseData | Reference to WCBossPhaseData asset (leave null for non-bosses) |
CombatRange | Max distance at which this AI engages targets |
PreferredCombatTags | Tags for preferred combat style (Melee, Ranged, Support) — used by squad role assignment |
🌳 Behavior Tree Nodes
GAS Ally provides a full library of custom Behavior Tree nodes in all three categories (Tasks, Decorators, Services) that understand the GAS Ally world.
Tasks
| Task Node | Description |
|---|---|
BTTask_WC_UseGASAbility | Activate a Gameplay Ability by tag, ability class, or ability handle. Handles prediction keys for multiplayer. |
BTTask_WC_ApplyStatusEffect | Apply a Status Effect Definition to a target actor (from BB key) |
BTTask_WC_UpdateThreat | Manually modify threat values in the threat table (e.g. boost threat on the character that just healed an ally) |
BTTask_WC_CallSquadAction | Broadcast a squad action tag to all squad members (e.g. "FlankLeft", "FocusFire") |
BTTask_WC_TransitionBossPhase | Trigger a boss phase transition manually from within a BT |
BTTask_WC_SetCombatTarget | Set the current combat target on the Combat AI Component and update threat |
BTTask_WC_SendGameplayEvent | Send a Gameplay Event Tag to any actor's ASC from within a BT |
BTTask_WC_WaitAbilityCooldown | Wait until a specific ability (by tag) is no longer on cooldown |
Decorators
| Decorator Node | Description |
|---|---|
BTDecorator_WC_HasGASTag | Succeeds if the specified actor has (or does not have) a Gameplay Tag |
BTDecorator_WC_AttributeThreshold | Succeeds when an attribute value is above/below a threshold |
BTDecorator_WC_IsStatusEffectActive | Succeeds if a specific status effect tag is active on the target |
BTDecorator_WC_IsThreatLeader | Succeeds if this AI is the highest-threat target for its squad lead |
BTDecorator_WC_AbilityReady | Succeeds if a specific ability is not on cooldown |
BTDecorator_WC_IsInBossPhase | Succeeds if this boss AI is currently in a specific phase number |
Services
| Service Node | Description |
|---|---|
BTService_WC_UpdateThreatTarget | Periodically re-evaluates the threat table and updates the BB key for the highest-threat target |
BTService_WC_MonitorSquad | Monitors squad health, broadcasts squad events when members die or retreat |
BTService_WC_SyncCombatTags | Syncs current combat-state Gameplay Tags (InCombat, LowHealth, Fleeing) to Blackboard for use by decorators |
BTService_WC_AttributeMonitor | Polls a set of attributes and writes their values to Blackboard for downstream decorator use |
🗺️ EQS Integration
GAS Ally extends the Environment Query System so your AI can make spatial decisions that account for GAS-aware concepts like threat, cover, and ally grouping.
Custom EQS Contexts
| Context Class | Returns |
|---|---|
UWCEQSContext_HighestThreatTarget | The actor with the highest threat value in the querier's threat table |
UWCEQSContext_SquadMembers | All living members of the querier's squad |
UWCEQSContext_LowHealthAlly | The ally (in squad) with the lowest health percentage — for support AI |
UWCEQSContext_NearestEnemy | The nearest actor with a hostile faction relation to the querier |
Custom EQS Tests
| Test Class | What It Scores |
|---|---|
UWCEQSTest_AttributeValue | Score candidate locations by a nearby actor's attribute value (e.g. "find position near low-health enemy") |
UWCEQSTest_ThreatRange | Score based on distance from high-threat actors — used for flanking positioning |
UWCEQSTest_StatusEffectPresent | Filter candidates by whether nearby actors have/lack a specific status effect |
UWCEQSTest_FactionRelation | Filter candidates by faction relationship (Hostile, Neutral, Friendly) to the querier |
🔄 StateTree Tasks & Conditions
GAS Ally provides StateTree integration for high-level AI state management. StateTree is ideal for modeling the AI's overarching behavioral mode (Patrol, Combat, Retreat, BossPhase1, BossPhase2, etc.) while Behavior Trees handle the moment-to-moment decision-making within each state.
StateTree Tasks (WCGASAlly)
| Task Class | Description |
|---|---|
FWCSTTask_EnterCombat | Registers the AI with the Combat AI Subsystem, sets up threat table, notifies squad |
FWCSTTask_ExitCombat | Clears threat table, removes combat tags, notifies squad of retreat |
FWCSTTask_ExecuteBossPhase | Applies the Boss Phase GE set (stat changes, new abilities, visual changes) for a given phase index |
FWCSTTask_ApplyWorldContext | Manually pushes a World Context effect stack (for boss arenas that change environment) |
FWCSTTask_BroadcastSquadEvent | Broadcast a squad event tag to all registered squad members via the subsystem |
StateTree Conditions (WCGASAlly)
| Condition Class | Evaluates |
|---|---|
FWCSTCond_HasGameplayTag | True if the bound actor has a specific Gameplay Tag |
FWCSTCond_AttributeBelow | True when an attribute value is below a threshold (e.g. Health < 30%) |
FWCSTCond_BossPhaseReady | True when health crosses a boss phase threshold |
FWCSTCond_SquadAlive | True if a minimum number of squad members are still alive |
👥 Squad System
The Squad System allows groups of AI characters to coordinate their behavior as a tactical unit. Squads share threat information, can issue commands to each other, and behave collectively in combat.
WCSquadData Asset
| Property | Description |
|---|---|
SquadTag | Unique tag for this squad type, e.g. WC.Squad.BanditRaiders |
MaxSize | Maximum squad members (overrides global setting for this squad) |
RoleAssignment | TMap of role tags to max count (e.g. 1 Tanker, 2 Flankers, 1 Healer) |
SharedThreatPercent | What percentage (0–1) of one member's threat is shared with all other members |
FormationPreset | Optional formation data for pathfinding in coordinated movement |
SquadLeaderClass | AI controller class used for the squad leader (first member registered) |
How Squads Work
- AI characters register themselves with the
UWCCombatAISubsystemon BeginPlay via theirWCCombatAIComponent. - Members are grouped into squads based on their
SquadDataasset tag. - The first member to register becomes the Squad Leader.
- When a squad member generates threat (by attacking, receiving damage, using abilities), a percentage is broadcast to all other members.
- Squad commands (e.g. "FlankLeft", "FocusFire", "Retreat") are sent via
BTTask_WC_CallSquadActionand received by all members listening viaBTService_WC_MonitorSquad.
WCSquadData asset on their WCCombatAIComponent. They automatically self-organize into a squad at runtime — no explicit squad manager actor needed.🎯 Threat System
The Threat System determines which target an AI focuses on at any given moment. It is more nuanced than simple distance-based targeting — it models an AI's awareness of who poses the greatest strategic threat.
WCThreatData Asset
| Property | Description |
|---|---|
BaseThreatOnDamage | Threat gained per point of damage dealt to this AI |
ThreatOnHeal | Threat gained when target heals an ally |
ThreatOnAbilityUse | Flat threat added when the target uses any Gameplay Ability near this AI |
TagThreatModifiers | TMap — tag presence multiplies threat generation. E.g. WC.Role.Healer × 1.5 (tanks focus healers more) |
DecayInterval | Seconds between threat decay ticks (overrides global setting) |
DecayRate | Fraction of threat lost per decay tick for targets not currently attacked |
MaxThreatTargets | How many targets this AI tracks simultaneously in its threat table |
Threat Modifiers from GAS Events
Threat is automatically generated when the threat system intercepts Gameplay Events sent to the AI's ASC:
| Event Tag | Effect on Threat Table |
|---|---|
WC.Event.DamageTaken | Adds threat to the instigator equal to damage × BaseThreatOnDamage |
WC.Event.AbilityUsedNearby | Adds flat threat to the ability user |
WC.Event.AllyHealed | Adds threat to the healer equal to heal amount × ThreatOnHeal |
WC.Event.TauntReceived | Overrides current target to the taunter for Taunt duration |
👑 Boss Phase System
The Boss Phase System allows AI bosses to dramatically change their behavior, abilities, and stats at specific health thresholds — without any special-casing in code.
WCBossPhaseData Asset
| Property | Description |
|---|---|
BossTag | Unique tag for this boss type, e.g. WC.Boss.DragonLord |
Phases | Ordered array of FWCBossPhase structs, from Phase 1 (full health) to Phase N (near death) |
Boss Phase Struct (FWCBossPhase)
| Property | Description |
|---|---|
PhaseIndex | Zero-based phase index (0 = first/full-health phase) |
HealthPercentThreshold | Health % at or below which this phase activates (e.g. 0.75 = below 75% health triggers Phase 2) |
PhaseTag | Tag added to boss's ASC when in this phase (for decorators and conditions) |
OnEnterGameplayEffects | GEs applied when entering this phase (stat changes, ability grants, immunity windows) |
OnExitGameplayEffects | GEs removed (or reverse GEs applied) when leaving this phase |
AbilitiesToGrant | New abilities unlocked in this phase (e.g. AoE fire breath at Phase 2) |
AbilitiesToRevoke | Abilities lost when entering this phase |
BehaviorTreeOverride | Optional BT asset that replaces the current Behavior Tree for this phase |
MontageToPlay | Optional montage played as a cinematic transition into this phase |
bGrantInvincibility | If true, applies a damage immunity GE for TransitionDelay seconds during phase intro |
Setting Up a Boss
-
Create Boss Phase Data
Right-click → Data Asset → WCBossPhaseData. Add phases — e.g. Phase 0 (100%), Phase 1 triggers at 70% health, Phase 2 at 40%, Phase 3 (final) at 15%.
-
Assign to the Combat AI Component
On the boss AI character Blueprint, select
WCCombatAIComponentand set Boss Phase Data to your new asset. -
Create Phase-Specific Gameplay Effects
For each phase, create GEs for the stat changes. Example: Phase 2 GE grants +50% movement speed, +30% attack, removes slow walk animation tag.
-
Add Phase Decorators to BT
In your boss's Behavior Tree, use
BTDecorator_WC_IsInBossPhaseon branches to run different logic per phase. Alternatively, specify aBehaviorTreeOverrideper phase in the Data Asset for a complete swap. -
Test
Use console command
WCBoss.ForcePhase <PhaseIndex>on the boss actor to instantly trigger a phase transition for testing.
🌍 World Context System
The World Context System lets the environment itself apply GAS effects to characters. Place AWCWorldContextVolume actors in your world and characters automatically receive configured Gameplay Effects while inside the volume — and have them removed on exit.
Use Cases
- Lava Zone: Characters inside take periodic fire damage (a ticking GE)
- Blizzard Area: Speed and regen are penalized (debuff GE)
- Sacred Grove: Health regeneration greatly increased (buff GE)
- Dark Cavern: Perception/vision attributes reduced (debuff GE)
- Day/Night: Bridge to the Calendar subsystem — daytime gives different bonuses than night
AWCWorldContextVolume Setup
-
Place the Volume
Search Content Browser or the Place menu for
WCWorldContextVolume. Drag it into the level. Resize with the standard Unreal brush tools to cover your environmental area. -
Create World Context Data
Right-click → Data Asset → WCWorldContextData. Configure:
- ContextTag: e.g.
WC.WorldContext.LavaZone - GameplayEffectsToApply: Add your lava damage GE (Infinite duration, periodic tick, fire damage)
- AffectedActorFilter: Which actor classes react (leave empty for all actors with ASC)
- Priority: When multiple volumes overlap, higher priority wins or combines (configurable)
- ContextTag: e.g.
-
Assign to the Volume
Select your placed volume actor and in the Details panel, set World Context Data to your new asset.
WCWorldContextBridge
The UWCWorldContextBridge component links the World Context System to other systems (Calendar, Difficulty). It allows context effects to change dynamically — for example, a forest volume that applies different GEs at night vs. daytime based on a Calendar query.
// The Bridge queries the calendar and applies conditionally:
// WorldContext Volume: "Enchanted Forest"
// Day Context: GE_ForestRegen (health regen bonus)
// Night Context: GE_ForestHunted (periodic fear chance)
// Bridge reads UWCCalendarSubsystem::GetCurrentTimeOfDay() each tick
🔄 Transfer System
The Transfer System provides a structured mechanism for moving attribute values, abilities, or Gameplay Effects between actors at runtime. This powers mechanics like:
- Life Drain: Attacker steals Health from target
- Mana Siphon: Spell drains target Mana, adds it to caster Mana
- Buff Transfer: Support ability moves a buff GE from caster to ally
- Curse Transfer: Cleanse spell moves a status effect from ally to enemy
Transfer Types (WCTransferTypes)
| Transfer Type | What is Transferred | Direction |
|---|---|---|
AttributeValue | A specific amount of an attribute value | Source → Target or bidirectional |
GameplayEffect | An active GE instance (by tag) | Source → Target |
StatusEffect | A WCStatusEffectDefinition instance | Source → Target (moves, not copies) |
Ability | A granted ability | Source loses it, Target gains it |
Executing a Transfer
// Blueprint via UWCTransferFuncLib:
// Transfer 50 Health from Target to Caster (Life Drain)
FWCTransferRequest Request;
Request.TransferType = EWCTransferType::AttributeValue;
Request.AttributeTag = FGameplayTag::RequestGameplayTag("WC.Attribute.Health");
Request.Amount = 50.f;
Request.Source = TargetActor; // Where value comes FROM
Request.Destination = CasterActor; // Where value GOES TO
Request.bCappedBySourceCurrent = true; // Don't drain more than target has
UWCTransferSubsystem::ExecuteTransfer(GetWorld(), Request);
⚙️ Difficulty System
The Difficulty System applies global multipliers and modifiers across all characters based on the active difficulty tier. It is a Game Instance Subsystem, so it persists across level loads.
WCDifficultyTier Asset
| Property | Description |
|---|---|
TierTag | e.g. WC.Difficulty.Hard |
DisplayName | "Hard", "Nightmare", etc. |
EnemyDamageMultiplier | Global multiplier on all AI damage output. 1.5 = 50% more damage. |
EnemyHealthMultiplier | Scales all enemy Max Health attributes on spawn |
PlayerHealingMultiplier | Scales all healing received by players |
XPMultiplier | Scales XP granted from all sources |
GlobalGameplayEffects | GEs applied to all actors on difficulty change (e.g. a passive "Hard Mode" GE that gives enemies extra abilities) |
// Change difficulty tier at runtime (from main menu, settings, etc.)
if (UWCDifficultySubsystem* Difficulty = GetGameInstance()->GetSubsystem<UWCDifficultySubsystem>())
{
Difficulty->SetDifficulty(DA_WC_Difficulty_Nightmare);
}
⚔️ Faction System
The Faction System defines relationships between groups of actors. It drives AI target selection (attack enemies, help allies), EQS queries, and UI display of faction standing.
WCFactionRelations Asset
A faction relations asset defines all faction-to-faction relationships. Each entry is a pair of faction tags and a relationship type:
| Relationship Type | Behavior Impact |
|---|---|
Hostile | AI with this faction attacks actors of the other faction on sight. EQS threat contexts return these actors. |
Neutral | Neither attacks nor helps. EQS ignores for targeting but not for blocking. |
Friendly | AI helps defend against Hostile actors. Squad system may bridge across friendly factions. |
Allied | Deep alliance — shares threat tables, coordinates squad actions across faction lines. |
WCFactionAgent Component
Add UWCFactionAgentComponent to any actor to make it faction-aware:
// Get this actor's current faction tag
FGameplayTag Faction = FactionAgent->GetCurrentFaction();
// Change faction at runtime (e.g. player betrays their guild)
FactionAgent->SetFaction(FGameplayTag::RequestGameplayTag("WC.Faction.Bandits"));
// Query relationship between two actors
EWCFactionRelationship Relation =
UWCFactionLibrary::GetRelationship(ActorA, ActorB);
💧 Overflow System
The Overflow System handles what happens when an attribute receives more modification than it can absorb. Instead of silently discarding excess, overflow can be routed to another attribute or system.
Common Use Cases
| Scenario | Overflow Routing |
|---|---|
| Healed beyond Max Health | Excess healing → Shield attribute (temporary HP buffer) |
| Mana gained beyond Max Mana | Excess Mana → Arcane Overflow Pool (triggers a special ability when full) |
| Stamina fills completely | Excess Stamina → Boost Charge (powers a sprint burst) |
| Damage reduced to 0 by armor | Overkill reduction → Stored as Momentum (next attack bonus) |
Configuring Overflow
Overflow rules are configured per-attribute in the WCGASAttributeDefinition. Set:
- OverflowAttributeTag: The attribute that receives overflow (e.g.
WC.Attribute.Shield) - OverflowMultiplier: How much of the overflow is transferred (0.0–1.0). 1.0 = full overflow, 0.5 = half.
- OverflowEventTag: Gameplay Event sent when overflow occurs (bind for VFX or ability triggers)
- bClearOnThreshold: If true, once overflow attribute fills, it is cleared and
OverflowEventTagfires
🔬 Deep Dive: Custom Attributes Advanced
While the Attribute Definition Data Asset covers most cases, some games need fully custom attribute behavior. Here is the complete process for creating an attribute system extension in C++.
Step 1 — Create an Attribute Definition Asset
Even for custom attributes, always start with a WCGASAttributeDefinition Data Asset. Set the attribute tag to your new tag, configure base/min/max, and register it in Project Settings. This ensures it is part of the pool.
Step 2 — Create a Custom MMC (if needed)
If your formula type is Custom, subclass UGameplayModMagnitudeCalculation:
UCLASS()
class UMyGame_MMC_ManaFromIntelligence : public UGameplayModMagnitudeCalculation
{
GENERATED_BODY()
public:
UMyGame_MMC_ManaFromIntelligence();
virtual float CalculateBaseMagnitude_Implementation(
const FGameplayEffectSpec& Spec) const override;
private:
FGameplayEffectAttributeCaptureDefinition IntelligenceDef;
};
// In .cpp
UMyGame_MMC_ManaFromIntelligence::UMyGame_MMC_ManaFromIntelligence()
{
// Capture Intelligence attribute from the Source
IntelligenceDef = FGameplayEffectAttributeCaptureDefinition(
UWCAttributeSet::GetIntelligenceAttribute(), // Get via pool accessor
EGameplayEffectAttributeCaptureSource::Source,
false // don't snapshot
);
RelevantAttributesToCapture.Add(IntelligenceDef);
}
float UMyGame_MMC_ManaFromIntelligence::CalculateBaseMagnitude_Implementation(
const FGameplayEffectSpec& Spec) const
{
FAggregatorEvaluateParameters Params;
Params.SourceTags = Spec.CapturedSourceTags.GetAggregatedTags();
float Intelligence = 0.f;
GetCapturedAttributeMagnitude(IntelligenceDef, Spec, Params, Intelligence);
return Intelligence * 5.0f; // 1 Intelligence = 5 Max Mana
}
Step 3 — Reference the MMC in a Gameplay Effect
Create a Gameplay Effect. Add a Modifier targeting your attribute with Magnitude Calculation Class set to your custom MMC. Apply this GE on character init (or via the Attribute Initializer component).
Step 4 — Listen for Changes
// Bind to attribute changes for reactive UI or logic
ASC->GetGameplayAttributeValueChangeDelegate(
UWCAttributeSet::GetAttributeFromTag(MyAttributeTag)
).AddUObject(this, &ThisClass::OnMyAttributeChanged);
🔬 Deep Dive: Custom Status Effects Advanced
Beyond data-driven effects, you can create fully custom status effect behavior by subclassing the status processing pipeline.
Custom Per-Tick Processing
If a data-driven Tick GE isn't enough, implement a custom UWCStatusEffect_CustomTick class:
UCLASS()
class UMyStatus_FrostbiteTick : public UWCStatusEffect_CustomTick
{
GENERATED_BODY()
public:
virtual void ProcessTick(
UAbilitySystemComponent* TargetASC,
const FWCStatusEffectState& State,
float DeltaTime) override
{
// Scale damage with current stack count
float Damage = State.CurrentStacks * 3.0f;
// Apply damage GE manually
FGameplayEffectContextHandle Context = TargetASC->MakeEffectContext();
// ... apply your custom GE
}
};
Custom Evolution Conditions
For evolution conditions beyond the built-in triggers, subclass UWCStatusEvolutionCondition:
UCLASS()
class UMyEvolution_MoonlightCondition : public UWCStatusEvolutionCondition
{
GENERATED_BODY()
public:
virtual bool EvaluateCondition(
UAbilitySystemComponent* TargetASC,
const FWCStatusEffectState& State) const override
{
// Evolve only at night (reading the calendar subsystem)
UWCWorldContextSubsystem* WorldCtx = GetWorld()->GetSubsystem<UWCWorldContextSubsystem>();
return WorldCtx && WorldCtx->IsNightTime();
}
};
🔬 Deep Dive: Custom Resistance Rules Advanced
If you need resistance behavior beyond the four standard layers (e.g. block-based parry mechanics, damage reflection, conditional resistance), you can inject custom resistance logic into the pipeline.
The Resistance Pipeline Hook
Override UWCResistanceComponent::OnPreDamageApplied in a Blueprint subclass of the component — or in C++ via the delegate:
// C++: Bind to the pre-damage delegate on the component
ResistanceComp->OnPreDamageApplied.AddDynamic(
this, &ThisClass::CustomResistanceHook);
void AMyCharacter::CustomResistanceHook(
FWCDamageInfo& DamageInfo)
{
// Reflect 20% of physical damage back at the attacker
if (DamageInfo.DamageTypeTag.MatchesTag(TAG_DamageType_Physical))
{
float Reflected = DamageInfo.FinalDamage * 0.2f;
// Apply reflected damage to DamageInfo.Instigator
// Reduce DamageInfo.FinalDamage by reflected amount
DamageInfo.FinalDamage -= Reflected;
}
}
🔬 Deep Dive: Custom Heritage Blessings Advanced
Heritage Blessings are special passive effects that go beyond simple attribute modifiers. They are defined as a combination of a Gameplay Tag, a Gameplay Effect, and optional Blueprint logic.
Creating a Complex Blessing
Example: "Dragon's Blessing" — while the character is below 30% health, they deal 50% more damage.
-
Create the Conditional GE
Create a Gameplay Effect with a Modifier on your damage output attribute. Set Modifier Magnitude to use a
Conditionalformula type (from the 12 formula types list). The condition tag:WC.Status.LowHealth. -
Create the "LowHealth" Tag Setter
Create a second Gameplay Effect that adds tag
WC.Status.LowHealthand remove it when not triggered. Use a GE with a Health threshold checker — or use a customUWCGEComponent_AttributeThresholdTagcomponent on the GE that automatically adds/removes the tag when the attribute crosses 30%. -
Add Both GEs to the Blessing
In the
WCHeritage_RaceDefinition, add both GEs toGrantedGameplayEffectswith Infinite duration. They will be active as long as the heritage is applied.
🌐 Multiplayer Guide
GAS Ally is designed server-authoritative from the ground up. All gameplay-critical state modifications happen on the server and replicate to clients. This section documents which systems are server-only, which replicate, and how to avoid common pitfalls.
Replication Summary
| System | Authority | Client Receives |
|---|---|---|
| Attribute Values | Server | Replicated via GAS attribute replication |
| Level / XP | Server | Replicated properties on WCLevelingComponent |
| Heritage | Server applies GEs | GEs replicate to clients via ASC |
| Skill Tree nodes | Server | Replicated TArray<int32> of unlocked node IDs |
| Status Effects | Server | Active GE handles replicate via ASC |
| Status Stack Count | Server | Replicated on WCStatusEffectComponent |
| Resistance Data | Server resolves | Not replicated (computed server-side only) |
| Threat Tables | Server only | Not replicated — AI is always server-authoritative |
| Squad State | Server only | Not replicated — AI decisions are server-only |
| Boss Phase Index | Server | Replicated int on WCCombatAIComponent |
| World Context GEs | Server applies | GEs replicate via ASC |
Critical Rules
TMap. Any TMap used for networked state in GAS Ally (e.g. threat tables, squad assignments) is server-only. Never try to access or display threat data directly on clients — use server RPCs or replicated snapshots.HasAuthority() or equivalent server check. These functions will do nothing on clients by design. For player-initiated actions (e.g. clicking "Learn Ability"), use a Server RPC or Gameplay Ability to reach the server first.Prediction
GAS Ally supports Gameplay Ability System's native client-side prediction. For player-initiated abilities:
- Activate abilities through the GAS standard
TryActivateAbilitypath — this automatically uses prediction keys - Status Effect visuals (VFX, UI icons) can be client-predicted by listening to GAS OnGameplayEffectAdded with the status tag
- Never predict damage values on clients; damage always resolves server-side
Testing Multiplayer Locally
Set Player Count
In the Unreal Editor toolbar, set Play As: 2 Players in the Play dropdown.
Use Net Mode: Listen Server
Set Net Mode: Play As Listen Server so one client is also the server — ideal for local co-op testing.
Monitor Replication
Use
WCGASDebugCommandsconsole commands (see Debug section) to inspect attribute values and active GEs on both the server and client windows simultaneously.
📋 Class Reference
Runtime Module (WCGASAlly) — Key Classes
| Class | Type | Description |
|---|---|---|
UWCHeritageComponent | ActorComponent | Applies Heritage Sets to ASC; saves/loads heritage state |
UWCLevelingComponent | ActorComponent | Tracks XP and level; fires level-up rewards |
UWCSkillTreeComponent | ActorComponent | Manages skill tree node unlocks and point pools |
UWCStatusEffectComponent | ActorComponent | Manages active status effects, stacks, evolution |
UWCResistanceComponent | ActorComponent | Manages multi-layer resistance data |
UWCAutoRegenComponent | ActorComponent | Drives tick-based attribute regen/degen |
UWCAbilityCurriculumComponent | ActorComponent | Ability learning system with cost/prerequisite enforcement |
UWCFeatComponent | ActorComponent | Tracks feat counters and fires milestone rewards |
UWCCombatAIComponent | ActorComponent | AI hub: squad membership, threat table, boss phases |
UWCRegenSubsystem | WorldSubsystem | Global regen tick orchestrator |
UWCStatusEffectSubsystem | WorldSubsystem | Global status effect registry and evolution processor |
UWCLevelingSubsystem | WorldSubsystem | Centralized XP event router |
UWCEventsSubsystem | WorldSubsystem | Global event bus for all GAS Ally events |
UWCWorldContextSubsystem | WorldSubsystem | Manages active world context volumes and their GEs |
UWCCombatAISubsystem | WorldSubsystem | Manages squad registrations and boss phase orchestration |
UWCDifficultySubsystem | GameInstanceSubsystem | Persists difficulty tier across map loads |
UWCTransferSubsystem | WorldSubsystem | Executes transfer requests between actors |
UWCOverflowSubsystem | WorldSubsystem | Routes attribute overflow to configured destinations |
UWCGASExecCalc_Damage | GameplayEffectExecutionCalculation | Full damage pipeline with resistance, crit, and events |
UWCGASExecCalc_Healing | GameplayEffectExecutionCalculation | Healing pipeline with overflow support |
UWCGASMMCalc_AttributeMod | ModMagnitudeCalculation | Universal attribute modifier supporting all 12 formula types |
UWCGASMMCalc_PercentRegen | ModMagnitudeCalculation | Percentage-of-max regen calculator |
UWCGASMMCalc_Degeneration | ModMagnitudeCalculation | Tag-conditional degeneration calculator |
AWCWorldContextVolume | Actor (Volume) | Brush volume that applies context GEs to overlapping actors |
UWCFactionAgentComponent | ActorComponent | Makes an actor faction-aware for AI targeting and EQS |
Editor Module (WCGASAllyEditor) — Key Classes
| Class | Type | Description |
|---|---|---|
UWCAttributeDefinitionFactory | UFactory | Enables right-click → Data Asset creation for attribute definitions |
UWCHeritageFactory | UFactory | Factory for Race, Class, Subrace, and Heritage Set assets |
UWCSkillTreeFactory | UFactory | Factory for Skill Tree Preset assets |
UWCStatusEffectFactory | UFactory | Factory for Status Effect Definition assets |
UWCResistanceDataFactory | UFactory | Factory for Resistance Data assets |
UWCBossPhaseDataFactory | UFactory | Factory for Boss Phase Data assets |
UWCAttributeValidator | UEditorValidator | Validates all attribute definitions at save/cook time |
🏷️ Tag Reference
GAS Ally uses the WC.GASAlly.* tag namespace. All tags are defined in the WCGASAlly module's tag files and should not be duplicated in your project.
Character State Tags
| Tag | Set When |
|---|---|
WC.State.InCombat | Character has an active combat target |
WC.State.Dead | Character health has reached 0 |
WC.State.Stunned | Character cannot take actions |
WC.State.LowHealth | Health below configured threshold (default 30%) |
WC.State.Immune | Immunity GE is active — damage is blocked |
WC.State.Fleeing | AI is in retreat state (health critically low) |
Status Effect Tags (Common Examples)
| Tag | Meaning |
|---|---|
WC.Status.Burning | Fire damage over time |
WC.Status.Poisoned | Nature damage over time |
WC.Status.Frozen | Movement and action penalty |
WC.Status.Wet | Increases lightning damage taken; synergy target |
WC.Status.Bleeding | Delayed physical DoT |
WC.Status.Stunned | Complete action lockout |
Damage Type Tags
| Tag | Damage Category |
|---|---|
WC.DamageType.Physical | Physical / melee damage |
WC.DamageType.Fire | Elemental fire damage |
WC.DamageType.Lightning | Elemental lightning damage |
WC.DamageType.Ice | Elemental ice damage |
WC.DamageType.Poison | Nature/poison damage |
WC.DamageType.Arcane | Pure magical damage |
WC.DamageType.Elemental | Parent tag for all elemental types |
WC.DamageType.Any | Global fallback — matches all damage types |
Event Tags
| Tag | Fired When |
|---|---|
WC.Event.DamageTaken | Character receives final damage (after all resistance) |
WC.Event.Healed | Character's health is restored |
WC.Event.LevelUp | Character level increases |
WC.Event.StatusEffectEvolved | A status effect has evolved to a new form |
WC.Event.SynergyTriggered | A status synergy combo fired |
WC.Event.EnemyKilled | An enemy was killed (send to killer's ASC for feat tracking) |
WC.Event.BossPhaseChanged | Boss transitions to a new phase |
WC.Event.TauntReceived | AI receives a taunt, overriding threat target |
Heritage Tags
| Tag Pattern | Purpose |
|---|---|
WC.Heritage.Race.* | Race identifiers (e.g. WC.Heritage.Race.Human) |
WC.Heritage.Class.* | Class identifiers (e.g. WC.Heritage.Class.Warrior) |
WC.Heritage.Subrace.* | Subrace identifiers |
WC.Heritage.Blessing.* | Blessing identifiers |
📐 Blueprint API
GAS Ally exposes a comprehensive set of Blueprint function libraries so you can access all systems without writing C++.
UWCHeritageLibrary
| Function | Description |
|---|---|
ApplyHeritageSet(Character, HeritageSet) | Apply a Heritage Set to a character (calls component; server only) |
GetActiveRaceTag(Character) | Returns the Gameplay Tag of the character's current race |
GetActiveClassTag(Character) | Returns the Gameplay Tag of the character's current class |
HasBlessing(Character, BlessingTag) | Returns true if the character has a specific heritage blessing active |
UWCLevelingLibrary
| Function | Description |
|---|---|
GrantXP(Character, Amount) | Grant XP and trigger level-up if threshold crossed (server only) |
GetCurrentLevel(Character) | Returns the character's current level |
GetXPProgress(Character) | Returns 0.0–1.0 progress toward next level (safe to call on clients) |
GetXPToNextLevel(Character) | Returns exact XP remaining until next level |
UWCStatusEffectLibrary
| Function | Description |
|---|---|
ApplyStatusEffect(Target, Definition, Instigator) | Apply a status effect (server only) |
RemoveStatusEffect(Target, StatusTag) | Remove all stacks of a status effect |
GetStackCount(Target, StatusTag) | Returns the current stack count for a status effect |
IsStatusEffectActive(Target, StatusTag) | Returns true if the status is currently active |
GetActiveStatusEffects(Target) | Returns an array of all active status effect definitions |
UWCResistanceLibrary
| Function | Description |
|---|---|
GetEffectiveDamage(Target, RawDamage, DamageTypeTag) | Compute final damage after all resistance layers (for preview/tooltip) |
GetTotalAbsorption(Target, DamageTypeTag) | Returns total effective absorption % for a damage type |
RegisterResistanceData(Character, Data) | Add a resistance data asset to a character's resistance component |
UWCFactionLibrary
| Function | Description |
|---|---|
GetRelationship(ActorA, ActorB) | Returns the faction relationship between two actors (Hostile/Neutral/Friendly/Allied) |
IsHostile(ActorA, ActorB) | Quick boolean check for hostility |
SetActorFaction(Actor, FactionTag) | Change an actor's faction at runtime |
UWCDamageCalcLibrary
| Function | Description |
|---|---|
CalculatePhysicalDamage(Attacker, Defender) | Preview physical damage without applying it |
CalculateMagicalDamage(Attacker, Defender) | Preview magical damage without applying it |
WillCritical(Attacker) | Roll and return whether next hit would crit (uses CritChance attribute) |
🐛 Debug & Console Commands
GAS Ally provides a rich set of debug tools accessible via the console (tilde key ~ or `) and via the Gameplay Debugger.
Gameplay Debugger
Press ` (backtick) in PIE, then press 5 to activate the WCGASAlly debug category. Click any character to inspect their live GAS Ally state:
- All attribute current/base/max values from the pool
- Active status effects with stack counts and remaining duration
- Active Gameplay Effects and their expiry timers
- Threat table (for AI characters)
- Boss phase index (for bosses)
- Heritage race/class tags
- Current level and XP progress
Console Commands
| Command | Description |
|---|---|
WCAttr.Set <Tag> <Value> | Force-set an attribute to a value on the selected/focused actor |
WCAttr.Print | Print all attribute values for the selected actor to the Output Log |
WCStatus.Apply <StatusTag> | Apply a status effect (by tag) to the selected actor |
WCStatus.Remove <StatusTag> | Remove a status effect from the selected actor |
WCStatus.Evolve <StatusTag> | Force-trigger all evolution rules for a given status tag immediately |
WCLevel.Set <Level> | Force the selected character to a specific level (skips XP) |
WCLevel.GrantXP <Amount> | Grant XP to the selected character |
WCBoss.ForcePhase <PhaseIndex> | Force a boss phase transition to a specific phase index |
WCThreat.Print | Print the threat table of the selected AI to the Output Log |
WCThreat.Clear | Clear all threat entries for the selected AI |
WCDifficulty.Set <TierTag> | Set global difficulty tier by tag |
WCResist.PrintLayers | Print all resistance layers and values for the selected actor |
WCDebug.AttributeHUD | Toggle an on-screen HUD showing real-time attribute values for the player character |
bEnableDebugLogging in Project Settings → WC GAS Ally for verbose LogWCGASAlly output in the Output Log. This logs every attribute change, status effect apply/remove, evolution, and subsystem event — invaluable during development but should be disabled in shipping builds.🔧 Troubleshooting
Build Errors
| Error | Likely Cause | Fix |
|---|---|---|
| "Cannot find module WCGASAlly" | Plugin not properly installed or Plugins folder not generated | Verify plugin is in Plugins/ folder; right-click .uproject → Generate VS project files; rebuild |
| "GameplayAbilities module not found" | GameplayAbilities engine plugin disabled | Enable GameplayAbilities in Edit → Plugins; the DynamicRPGWorlds .uplugin should do this automatically |
| C2259 / Abstract class instantiation error | Subclassing a GAS Ally class and not implementing all pure virtual functions | Check which virtual functions your override must implement; see class header for = 0 declarations |
Runtime Issues
| Problem | Likely Cause | Fix |
|---|---|---|
| Attributes all show 0 at runtime | Attribute Definitions not registered in Project Settings → WCGASCore | Add all Definition assets to the Attribute Definitions array in settings |
| Heritage has no effect on attributes | ApplyHeritageSet called on client, not server | Ensure the call is wrapped in HasAuthority() or called via a Server RPC |
| Status effects not evolving | Evolution rules not registered in Global Settings or not linked to effect | Add evolution rules to Project Settings → WC GAS Ally → Global Status Evolution Rules |
| Skill Tree points not granting | LevelUpRewards not configured in WCLevelingRules asset | Open your WCLevelingRules asset; check LevelUpRewards TMap has entries with SkillPointsGranted > 0 |
| AI not targeting player | Faction relations not configured or WCFactionAgentComponent missing | Add WCFactionAgentComponent to both player and AI; configure WCFactionRelations asset |
| Boss phases not triggering | BossPhaseData not assigned or HealthPercentThreshold set incorrectly | Check WCBossPhaseData; thresholds should be descending (0.75, 0.40, 0.15). Verify WCCombatAIComponent has data assigned |
| World Context volume GEs not applying | AWCWorldContextVolume has no collision or wrong filter | Check Brush Collision profile; ensure AffectedActorFilter includes your character class |
| "LogWCGASAlly: Warning: Pool full" | More than 150 attribute definitions registered | Increase AttributePoolSize in WCGASCoreSettings or reduce your attribute count |
Performance Issues
| Symptom | Cause | Solution |
|---|---|---|
| Frame drops when many AI are active | Too many BT nodes querying ASC every tick | Use BTService_WC_SyncCombatTags to cache values in Blackboard; reduce service tick intervals |
| Hitches every 0.25 seconds | Regen subsystem tick processing many actors | Increase RegenTickInterval in settings (0.5–1.0s is acceptable for most games) |
| Status effect synergy causing lag | Too many global synergy rules evaluated per frame | Reduce synergy rule count; use per-actor inline rules for rare synergies instead of global rules |
VersionName), the relevant Output Log section (enable debug logging first), and the steps to reproduce. Check the Wonderscape Creations FAB Marketplace page for known issues and patch notes.