Add executive summary and ability migration matrix; finalize evidence index, runtime validation plan, and Phase 1 handoff. Co-authored-by: Cursor <cursoragent@cursor.com>
19 KiB
06 — Partial GAS Architecture
Status: Complete
- Scope: Complete static archaeology of partial GAS: ASC ownership, AttributeSet, Gameplay Effects, tags, cues, grant/activation absence, EffectActor boundary, legacy/GAS resource conflict, enemy ASC accessor defect.
- Inspection method: Native C++ read of all GAS-related Source/REALMSINRUIN files; AssetTools find/deps/refs; ObjectTools CDO properties / search_subclasses; BlueprintTools EventGraph DSL on consumable BPs; GameplayTagsToolset (read-only); prior Pass 5–8 ability/anim negative GAS results.
- Evidence classifications used: Observed Implementation, Documented Intent, Observed Runtime Behavior, Inferred, Unknown.
- Tool or visibility limitations:
GameplayEffectComponentsarray unreadable via ObjectTools (cues/component tags Unknown on GE CDOs); BlueprintGeneratedClass CDO sometimes rejects duration/modifier property names depending on load path — modifiers recovered via successful GE CDO queries on Default__ / generated class where available; no PIE. - Last updated: 2026-07-16
- Current phase: Phase 1 — Static Architecture (complete)
- Last completed pass: Pass 11 (Batch 5) — status close; content through Pass 10
- Next pass expected to contribute: Phase 2A (attribute SoT) when authorized
Completion notes
Static GAS archaeology for Phase 1 is complete (subsystem matrix, GE inventory, tags/cues negatives, dual-resource boundary, enemy GetASC). PIE Overlay/potion/authority tests deferred to doc 13.
1. GAS subsystem status matrix
| Subsystem | Status | Exact implementation | Active reference path | Conflict or gap | Evidence |
|---|---|---|---|---|---|
| Player ASC ownership | Active | ARIRPlayerState creates URIRAbilitySystemComponent; Mixed replication |
Character caches ASC from PlayerState in InitAbilityActorInfo |
None for players | RIRPlayerState.cpp |
| Enemy ASC ownership | Active (component) | ARIRBaseEnemyCharacter creates ASC + AttributeSet; Minimal replication; InitAbilityActorInfo(this,this) in BeginPlay |
Direct component on enemy | Conflicts with interface GetASC | RIRBaseEnemyCharacter.cpp |
| Actor-info initialization | Active | Player: PossessedBy + OnRep_PlayerState; Enemy: BeginPlay | Observed Implementation | — | RIRPlayerCharacter.cpp; RIRBaseEnemyCharacter.cpp |
| AttributeSet replication | Active | All six attrs DOREPLIFETIME + OnRep | Overlay binds change delegates | Stamina/MaxStamina not Init'd in ctor | RIRAttributeSet.cpp |
| Default attribute initialization | Scaffolding Only / Present but Unreferenced | Property DefaultAttributesGameplayEffect on PlayerState; four character GE assets |
None — BP_PlayerState = None; GE_*_DefaultAttributes referencers [] | Spawn uses native InitHealth/Mana only | ObjectTools; get_referencers |
| Runtime attribute modification | Partially Integrated | Consumable GEs via EffectActor ApplyGameplayEffectSpecToSelf | Potion/food overlap → ApplyEffectToTarget | Abilities use ApplyDamage / DEPRECATED floats, not GE | BP_HealthPotion DSL; Pass 5–6 |
| Gameplay Ability classes | Scaffolding Only | URIRGameplayAbility InstancedPerActor only |
No project subclass beyond engine jump/montage | No discrete GA assets (GA_ find = []) |
search_subclasses; find_assets |
| Ability granting | Missing | No GiveAbility / StartupAbilities / AbilitySet | None observed | — | Source grep; find_assets; BP find_nodes |
| Ability activation | Missing | No TryActivateAbility in native or playable ability graphs | Legacy Server_Ability_* instead |
— | Pass 5–6; Pass 7 searches |
| Ability costs / cooldowns | Missing | No GA cost/cooldown classes | Mana cost is DEPRECATED float + FCanUseMana | — | Pass 6 |
| Gameplay Effects | Partially Integrated | 8 GE BPs under GAS/GameplayEffects | 4 consumable GEs assigned + applied; 4 default GEs orphaned | No Max* on default GEs; no Gunslinger GE | Pass 7 inventory |
| Gameplay Tags | Present but Unreferenced | 12 tags in DefaultGameplayTags.ini | Zero native string refs; zero asset referencers observed | Tags unused by GEs (legacy containers empty) | Config; Source grep; tag tool |
| Gameplay Cues | Missing | No project cue notify assets; no GC_ assets; no GameplayCue.* project tags beyond Test orphan | None observed | SoundCue *_Cue assets are audio, not GAS |
find_assets; search_subclasses |
| Attribute-driven UI | Active but Unverified | InitOverlay → OverlayWidgetController → WBP_Overlay Health/Mana bars bind delegates | WBP_Overlay via WBP_PlayerHUD CDO classes assigned | Legacy UpdatePlayerHUD unimplemented; stamina broadcasts with no stamina widget | RIRHUD; WBP_Overlay DSL; PC list_events |
| Legacy-resource synchronization | Missing | No mirror code between ASC attrs and DEPRECATED_* | Both UI paths independent | Static divergence possible | Pass 5–7 |
| Enemy effect compatibility | Partially Integrated / Existing Baseline Defect | Enemy owns ASC; EffectActor uses GetAbilitySystemComponent via interface |
Interface GetASC → PlayerState → nullptr on enemies | Pickups/effects may skip enemies | RIRBaseCharacter.cpp; RIREffectActor.cpp |
2. Gameplay Effect inventory
All under /Game/_Main/Blueprints/Game/GameSystems/GAS/GameplayEffects/. Attribute owner: URIRAttributeSet. Magnitude type: ScalableFloat. StackingType: None / StackLimitCount 0 where read. Cues: Unknown — GameplayEffectComponents unreadable; no GC_ assets exist. Granted INI tags: not observed on readable legacy tag containers (empty).
| Effect | Duration | Modifiers | Tags | Cues | Referencers | Application path | Status | Evidence |
|---|---|---|---|---|---|---|---|---|
GE_PotionHeal |
Instant | Health AddBase 25 | Empty (legacy containers) | Unknown — Tool Limitation | BP_HealthPotion |
Overlap → ApplyEffectToTarget(Instant) → DestroyActor | Active (static path) | CDO + DSL |
GE_PotionMana |
Instant | Mana AddBase 30 | Empty | Unknown | BP_ManaPotion |
Same Instant pattern | Active (static path) | CDO + refs |
GE_HoT_Small |
HasDuration 1s, Period 0.1 | Health AddBase 0.5/tick | Empty | Unknown | BP_OrangeSlice |
Overlap → ApplyEffectToTarget(Duration) → Destroy | Active (static path) | CDO + refs |
GE_MoT_Small |
HasDuration 1s, Period 0.1 | Mana AddBase 0.25/tick | Empty | Unknown | BP_ManaCrystal |
Same Duration pattern | Active (static path) | CDO + refs |
GE_Paladin_DefaultAttributes |
Instant | Health Override 100; Mana Override 100 | Empty | Unknown | [] | None | Present but Unreferenced | get_referencers |
GE_Amazon_DefaultAttributes |
Instant | Health Override 100; Stamina Override 100 | Empty | Unknown | [] | None | Present but Unreferenced | get_referencers |
GE_Cleric_DefaultAttributes |
Instant | Health Override 50; Mana Override 200 | Empty | Unknown | [] | None | Present but Unreferenced | get_referencers |
GE_Wizard_DefaultAttributes |
Instant | Health Override 100; Mana Override 150 | Empty | Unknown | [] | None | Present but Unreferenced | get_referencers |
None observed: GE_Gunslinger_*; SetByCaller; MMC; ExecutionCalculation project subclasses (engine base only); overflow/expiration GE chains (not read / not present in modifiers).
Folder inventory: find_assets recursive on /Game/_Main/Blueprints/Game/GameSystems/GAS returned exactly these 8 assets — Observed Implementation (complete folder set).
3. Default attribute matrix
| Character | Effect | Health | MaxHealth | Mana | MaxMana | Stamina | MaxStamina | Assigned at | Applied at | Reachability |
|---|---|---|---|---|---|---|---|---|---|---|
| Paladin | .../Paladin/GE_Paladin_DefaultAttributes |
Override 100 | Not modified | Override 100 | Not modified | Not modified | Not modified | None | None | Unreachable |
| Amazonian | .../Amazon/GE_Amazon_DefaultAttributes (folder Amazon, not Amazonian) |
Override 100 | Not modified | Not modified | Not modified | Override 100 | Not modified | None | None | Unreachable |
| Cleric | .../Cleric/GE_Cleric_DefaultAttributes |
Override 50 | Not modified | Override 200 | Not modified | Not modified | Not modified | None | None | Unreachable |
| Wizard | .../Wizard/GE_Wizard_DefaultAttributes |
Override 100 | Not modified | Override 150 | Not modified | Not modified | Not modified | None | None | Unreachable |
| Gunslinger | None observed | — | — | — | — | — | — | — | — | Missing |
| All (PlayerState) | Property only | — | — | — | — | — | — | BP_PlayerState.defaultAttributesGameplayEffect = None |
Native never applies | Unreachable |
Native spawn fallback (Observed Implementation): URIRAttributeSet ctor InitHealth(75), InitMaxHealth(100), InitMana(25), InitMaxMana(50); Stamina/MaxStamina not Init'd.
Naming inconsistency: Amazon GE folder/asset uses Amazon; playable Blueprint is Player_Amazonian — Documented Intent / Technical Debt.
4. Attribute architecture matrix
| Attribute | Native default | Replication | GE modifiers | UI binding | Blueprint reads/writes | Legacy equivalent | Synchronization | Status |
|---|---|---|---|---|---|---|---|---|
| Health | Init 75 | Replicated + OnRep | Potion +25; HoT +0.5/0.1s; default Override orphaned | OnHealthChanged | Ability graphs: none (use DEPRECATED) | DEPRECATED_CurrentHealth | None observed | Dual sources |
| MaxHealth | Init 100 | Replicated + OnRep | None on any GE | OnMaxHealthChanged | None in abilities | DEPRECATED_MaxHealth | None | Partially Integrated |
| Mana | Init 25 | Replicated + OnRep | Potion +30; MoT +0.25/0.1s; default Override orphaned | OnManaChanged | Abilities use DEPRECATED mana | DEPRECATED_Mana / costs | None | Dual sources |
| MaxMana | Init 50 | Replicated + OnRep | None on any GE | OnMaxManaChanged | None | DEPRECATED_MaxMana | None | Partially Integrated |
| Stamina | Not Init'd | Replicated + OnRep | Amazon default Override 100 (orphaned) | OnStaminaChanged (typed as FOnManaChangedSignature) | None | None observed | None | Scaffolding / Technical Debt |
| MaxStamina | Not Init'd | Replicated + OnRep | None | OnMaxStaminaChanged (typed as FOnMaxManaChangedSignature) | None | None | None | Scaffolding / Technical Debt |
No PostGameplayEffectExecute / PreAttributeChange on URIRAttributeSet — no clamp-to-max or death-from-attribute logic in native AttributeSet — Observed Implementation (absence).
5. Gameplay Tag inventory
Defined in Config/DefaultGameplayTags.ini (ImportTagsFromConfig=True).
| Tag | Defined at | Native references | Blueprint references | GE/GA references | Status | Evidence |
|---|---|---|---|---|---|---|
| State.Dead | DefaultGameplayTags.ini L12 | None observed | None observed | None observed | Present but Unreferenced | Source string search; tag referencer search |
| State.Stunned | L13 | None | None | None | Present but Unreferenced | same |
| State.Blocking | L14 | None | None | None | Present but Unreferenced | same |
| State.Casting | L15 | None | None | None | Present but Unreferenced | same |
| Disable.Movement | L17 | None | None | None | Present but Unreferenced | same |
| Disable.Input | L18 | None | None | None | Present but Unreferenced | same |
| Disable.Attack | L19 | None | None | None | Present but Unreferenced | same |
| Disable.Ability | L20 | None | None | None | Present but Unreferenced | same |
| Effect.Damage | L22 | None | None | None | Present but Unreferenced | same |
| Effect.Heal | L23 | None | None | None | Present but Unreferenced | same |
| Effect.Buff | L24 | None | None | None | Present but Unreferenced | same |
| Effect.Debuff | L25 | None | None | None | Present but Unreferenced | same |
Documented Intent (DevComment strings in INI) describes intended roles; no Observed Implementation of add/query/grant usage.
GameplayCue.Test: reported as lone cue tag orphan by GameplayCueToolset — Present but Unreferenced; no project notify.
6. Gameplay Ability and grant inventory
| Ability or grant mechanism | Asset/symbol | Grant path | Activation path | Cost/cooldown | Reachability | Status | Evidence |
|---|---|---|---|---|---|---|---|
| URIRGameplayAbility | Source/.../RIRGameplayAbility.* |
None | None | None | Scaffolding only | Scaffolding Only | InstancedPerActor ctor only |
| UGameplayAbility subclasses (project) | search_subclasses → only engine Jump/Montage + URIRGameplayAbility | None | None | — | No project GA BP | Missing | search_subclasses |
| GA_* assets | find_assets /Game name GA_ |
— | — | — | [] | Missing | find_assets |
| AbilitySet / StartupAbilities | find_assets | — | — | — | [] | Missing | find_assets |
| GiveAbility / TryActivateAbility | Source + BP_PlayerCharacterBase | — | — | — | None observed | Missing | grep; find_nodes |
| DefaultAttributesGameplayEffect apply | ARIRPlayerState property | Never called in native | — | — | BP = None | Scaffolding Only | RIRPlayerState.h; CDO |
| Legacy Server_Ability_* | BP events | N/A (not GAS) | Enhanced Input | DEPRECATED mana | Active (legacy) | See doc 05 | Pass 5–6 |
Conclusion (Observed Implementation): No project-defined Gameplay Ability implementation or static grant path was observed within the inspected project scope. This does not prove GAS can never activate at runtime.
7. Gameplay Cue inventory
| Cue | Type | Trigger | Referencers | Reachability | Status | Evidence |
|---|---|---|---|---|---|---|
| None observed (project) | — | — | — | — | Missing | find_assets GC_/GameplayCue; search_subclasses cue notifies → engine-only |
| GameplayCue.Test | Tag only | None | None | Unreachable | Present but Unreferenced | GameplayCueToolset |
*_Cue SoundCue assets (e.g. MagicSpell_01_Cue) |
USoundCue audio | Multicast_PlaySFX | Ability graphs | Active as audio, not GAS cue | Not GAS | Pass 6–8 |
8. Legacy / GAS boundary table
| System | Legacy path | GAS path | Synchronization | Current source of truth | Conflict | Runtime question |
|---|---|---|---|---|---|---|
| Health combat damage | ApplyDamage + DEPRECATED_CurrentHealth (Amazonian AnyDamage) | Attribute Health via GE (potions only) | None | Legacy for combat; GAS for potions | Dual health pools possible | Does potion heal update combat death? |
| Mana ability cost | DEPRECATED_*ManaCost + FCanUseMana | Attribute Mana via GE potions | None | Legacy for abilities | Potion mana may not affect ability costs | PIE both meters |
| HUD bars | Server_UpdateHUD → UpdatePlayerHUD (DEPRECATED %) | InitOverlay → OverlayWidgetController ASC delegates | None | Overlay Connected; UpdatePlayerHUD Present but Unconnected | Incomplete dual UI | Overlay only? |
| Healing | DEPRECATED_RecoverPlayerHealth (Cleric) | GE_PotionHeal / HoT | None | Both | Inconsistent heal systems | — |
| Death | PlayerDeath / IsDead bool | State.Dead tag unused; no attr death | None | Legacy | Tag unused | — |
| Blocking | IsBlocking bool + ABP | State.Blocking unused | None | Legacy | Tag unused | — |
| Default spawn attrs | Native Init* only | Orphan default GEs | N/A | Native Init 75/100/25/50 | Orphan character GEs unused | Spawn values in PIE |
9. Enemy GAS compatibility table
| Consumer | ASC lookup method | Expected owner | Static result | Null behavior | Potential impact | Runtime verification |
|---|---|---|---|---|---|---|
ARIREffectActor::ApplyEffectToTarget |
Library GetASC → base GetASC → PlayerState | Enemy self ASC | nullptr | Early return | Potions/effects skip enemies | PIE |
| Enemy direct ASC member | Native TObjectPtr | Self | Valid if used | — | No combat consumer in enemy BP (Pass 9) | — |
| Enemy BP combat / chase | N/A | — | No ASC dependency | — | GetASC defect does not cause chase/attack failure | — |
| Player ApplyDamage → enemy | Engine TakeDamage (not ASC) | — | No enemy ReceiveAnyDamage / health mutation | Damage event may fire with no health consumer | Combat kill path missing on enemy | PIE |
| Enemy AttributeSet Health | Direct | Self | Exists; Init defaults only | — | Scaffolding for combat | PIE |
Pass 9 addition: Enemy EventGraphs contain no ASC reads/writes. Chase/attack failure classification is Implementation Missing, independent of the GetASC Incomplete Refactor.
Ownership and init (detail)
Player (Observed Implementation):
- ASC + AttributeSet on
ARIRPlayerState - ReplicationMode Mixed; NetUpdateFrequency 100 (Batch 1/2)
ARIRPlayerCharacter::InitAbilityActorInfo: Owner=PlayerState, Avatar=Character; PossessedBy + OnRep_PlayerState- Then
ARIRHUD::InitOverlaywhen local HUD present
Enemy (Observed Implementation):
- ASC + AttributeSet on
ARIRBaseEnemyCharacter - ReplicationMode Minimal
- BeginPlay:
InitAbilityActorInfo(this, this)
EffectActor boundary (Pass 7 + Pass 10)
ARIREffectActor::ApplyEffectToTarget:
UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(TargetActor)- null → return
- MakeOutgoingSpec(GEClass, 1.f) + ApplyGameplayEffectSpecToSelf
BlueprintCallable from children. Properties: InstantGameplayEffectClass, DurationGameplayEffectClass.
| BP | Instant | Duration | Graph |
|---|---|---|---|
BP_HealthPotion |
GE_PotionHeal | None | Sphere OnComponentBeginOverlap → ApplyEffecttoTarget(Instant) → DestroyActor |
BP_ManaPotion |
GE_PotionMana | None | Same Instant |
BP_ManaCrystal |
None | GE_MoT_Small | Sphere → Apply(Duration) → Destroy |
BP_OrangeSlice |
None | GE_HoT_Small | Sphere → Apply(Duration) → Destroy |
Pass 10 static: No SwitchHasAuthority on any of the four; bReplicates=false; no target filter; Destroy always follows Apply call (including null ASC early-out path); no UI notify; no respawn. Authority / client overlap = Authority Risk / Requires Runtime Inspection. Full matrices: 12-Pickups-And-Effects.md.
Overlay (Pass 10): WBP_Overlay forwards controller to Health + Mana progress bars only; no stamina widget. Bars bind OnHealth/ManaChanged → SetProgressBarPercent.
Distinctions (updated)
| Layer | Status | Evidence |
|---|---|---|
| GAS infrastructure | Present / Active for ASC+attrs+UI binding | Native classes |
| GAS data | Partially present | 8 GEs; 12 orphan tags; no cues; no GAs |
| GAS runtime abilities | Not observed | No grant/activate |
| GAS runtime effects | Partially Integrated | Consumables only |
| Legacy BP abilities | Active | doc 05 / 10 |
Negative-search evidence log
| Search | Scope | Result |
|---|---|---|
find_assets name GA_ folder /Game |
Project content | [] |
find_assets name GC_ / GameplayCue |
Project content | [] / no cue assets |
| find_assets under GAS folder | Complete | Exactly 8 GE assets |
| search_subclasses GameplayAbility | Engine+project | Engine Jump/Montage + URIRGameplayAbility only |
| search_subclasses RIRGameplayAbility | Project | No further subclasses |
| search_subclasses GameplayCueNotify_* | Engine+project | Engine unit-test/burst/etc only |
| search_subclasses GameplayEffectExecutionCalculation / ModMagnitudeCalculation | Engine+project | Engine base only |
| Source grep GiveAbility|TryActivateAbility|ApplyGameplayEffect | Source/REALMSINRUIN | Only EffectActor Apply + DefaultAttributes property |
| Source grep State.Dead / tag strings | Source/REALMSINRUIN | No matches (GameplayTags module linked in Build.cs only) |
| get_referencers each DefaultAttributes GE | Asset registry | [] |