Add executive summary and ability migration matrix; finalize evidence index, runtime validation plan, and Phase 1 handoff. Co-authored-by: Cursor <cursoragent@cursor.com>
15 KiB
09 — Enemy AI Static Analysis
Status: Complete
- Scope: Complete static reconstruction of enemy control, targeting, chase, attack, damage, death, animation callbacks, navigation context, and enemy-GAS boundary (Pass 9). Builds on Batch 1 native + Pass 3 structural seeds.
- Inspection method: Native C++ read of
ARIRBaseEnemyCharacter/ARIRBaseCharacter/ITargetInterface; BlueprintTools EventGraph DSL + interface graphs; AssetTools find/deps/refs; ObjectTools CDO + placed-instance properties; SceneTools find_actors in Test01; project-wide AI asset/subclass searches. - Evidence classifications used: Observed Implementation, Documented Intent, Observed Runtime Behavior, Inferred, Unknown.
- Tool or visibility limitations: AnimGraph/transition DSL empty (Death transition rule not fully readable); CharacterMovement orient flags partially unreadable; no PIE possession/nav query validation.
- Last updated: 2026-07-16
- Current phase: Phase 1 — Static Architecture (complete)
- Last completed pass: Pass 11 (Batch 5) — status close; static content Pass 9 (Batch 4C). Superseded: earlier “next = Pass 4/10” — Batch 4D completed separately without reopening this doc’s combat findings.
- Next pass expected to contribute: Phase 2D when authorized
Completion notes
Static enemy AI archaeology is complete. Chase/attack classified Implementation Missing (not caused by GetASC). Runtime possession/damage/Death pins: doc 13.
Executive summary
Observed Runtime Behavior (project brief): Enemy chase and attack are nonfunctional — Existing Baseline Defect.
Pass 9 static conclusion:
| System | Primary classification |
|---|---|
| Target acquisition | Implementation Missing |
| Chase | Implementation Missing (secondary: no navmesh in Test01) |
| Attack initiation | Implementation Missing (interface stub + orphan montage) |
| Attack damage | Implementation Missing |
| Attack cleanup | Missing |
| Damage reception | Implementation Missing (BP); ASC Health unconnected to ApplyDamage |
| Death | Connected but Incomplete (ABP Death state exists; IsDead forced false every Update) |
| Enemy GE compatibility | Existing Baseline Defect (GetASC → nullptr); separate from chase/attack |
Chase and attack failures are not attributable to the enemy ASC accessor defect. They are attributable to absence of connected chase/attack implementation at native and Blueprint layers.
1. Enemy class and control matrix
| Asset/class | Parent | Controller class | AutoPossessAI | Movement component | AnimBP | Interfaces | Status | Evidence |
|---|---|---|---|---|---|---|---|---|
ARIRBaseEnemyCharacter |
ARIRBaseCharacter + ITargetInterface |
None set in native | N/A | Inherited CharacterMovement | N/A | ITargetInterface (Highlight/UnHighlight) | Active (ASC+highlight only) | RIRBaseEnemyCharacter.cpp |
BP_EnemyCharacterBase |
RIRBaseEnemyCharacter |
/Script/AIModule.AIController |
PlacedInWorld | CharMoveComp (inherited) | None on base | None | Scaffolding / empty graphs | CDO + EventGraph DSL |
BP_Enemy_Skeleton |
BP_EnemyCharacterBase_C |
/Script/AIModule.AIController |
PlacedInWorld | CharMoveComp | ABP_Skeleton |
BPI_EnemyCharacter (GetEnemyREF only) |
Scaffolding / empty combat graphs | CDO + DSL |
Native-only behavior (Observed Implementation): ASC + AttributeSet on self (Minimal); InitAbilityActorInfo(this,this) in BeginPlay; mesh Visibility Block; custom-depth highlight. No MoveTo, perception, attack, damage, or health mutation in native.
Blueprint EventGraphs (both base and Skeleton) — Observed Implementation:
(event EventBeginPlay)
(event Collision|EventActorBeginOverlap (OtherActor))
(event EventTick (DeltaSeconds))
All three entry nodes are Present but Unconnected (no wired body). Variables on both BPs: [].
GetEnemyREF (Skeleton only): returns self — Observed Implementation (trivial).
BPI members not implemented on Skeleton/base: AddPlayerTarget, EnemyMeleeAttack — Documented Intent only on interface asset.
2. Current-level instance matrix
Level: /Game/_Main/Levels/Testing/Test01
| Instance | Class | Controller override | AutoPossess override | Relevant instance overrides | Navigation context | Evidence |
|---|---|---|---|---|---|---|
BP_Enemy_Skeleton_C_1 |
BP_Enemy_Skeleton_C |
/Script/AIModule.AIController (same as CDO) |
PlacedInWorld | None observed vs CDO | No NavMeshBoundsVolume; no RecastNavMesh; only AbstractNavData fallback | get_properties; find_actors |
BP_Enemy_Skeleton_C_0 |
same | Unknown — not fully property-dumped | Unknown | Unknown | same level | find_actors presence only |
Selected actor at Pass 9 start/end: BP_Enemy_Skeleton_C_1 — unchanged.
Possession note: AutoPossessAI=PlacedInWorld statically allows placed instances to receive AI possession; spawned enemies would not auto-possess under this setting. Runtime possession state: Unknown without PIE. Stock AIController provides no project behavior tree / blackboard / custom logic.
3. AI framework inventory
| System | Assets/classes found | Active reference path | Status | Evidence |
|---|---|---|---|---|
| Behavior Tree | None (find_assets name BehaviorTree /Game → []) |
None | Missing | find_assets |
| Blackboard | None (find_assets Blackboard → []) |
None | Missing | find_assets |
| StateTree | None (find_assets StateTree → []) |
None | Missing | find_assets |
| EQS / EnvQuery | None (find_assets EnvQuery → []) |
None | Missing | find_assets |
| AIPerception assets | None (find_assets AIPerception → []) |
None | Missing | find_assets |
| PawnSensing | None on enemy components | None | Missing | ActorTools component list |
| Custom AIController | search_subclasses → only engine AIController, DetourCrowdAIController, GridPathAIController |
Assigned as stock AIController on enemy CDOs | Missing (project) | search_subclasses; CDO |
| MassAI / SmartObject | Not searched by name beyond above; no enemy component refs | None observed | Missing (Observed absence on enemies) | component inventory |
4. Targeting and chase table
| Entry point | Target source | Awareness check | Movement request | Update mechanism | Stop condition | Connection status | Root-cause relevance |
|---|---|---|---|---|---|---|---|
| EventTick (base/Skeleton) | None | None | None | Tick enabled natively; body empty | N/A | Present but Unconnected | Primary: no chase logic |
| EventActorBeginOverlap | OtherActor pin only | None | None | None | None | Present but Unconnected | No target store |
| BPI AddPlayerTarget | Interface signature only | — | — | — | — | Missing implementation | Documented Intent unused |
| BeginPlay | None | None | None | None | None | Present but Unconnected | No init chase |
| AI MoveTo / SimpleMoveTo / PathFollowing | — | — | None observed | — | — | Missing | No movement request exists |
| GetPlayerCharacter / GetPlayerPawn nodes | — | — | — | — | — | Missing in enemy graphs | No player acquisition |
Primary chase classification: Implementation Missing.
Secondary condition: Test01 has no NavMeshBoundsVolume and no RecastNavMesh (find_actors empty). Navmesh readiness is secondary — even with a baked mesh, no movement request exists to consume it.
5. Attack table
| Entry point | Range gate | State gate | Animation | Hit window | Damage path | Cooldown | Cleanup | Status | Evidence |
|---|---|---|---|---|---|---|---|---|---|
| BPI EnemyMeleeAttack | — | — | — | — | — | — | — | Missing (unimplemented) | list_graphs / Skeleton events |
| EventTick / Overlap | — | — | — | — | — | — | — | No attack body | EventGraph DSL |
Anim_SkeletonAttackMontage |
— | — | Asset exists | Unknown | None (0 referencers) | — | — | Present but Unreferenced | get_referencers [] |
| Native C++ | — | — | — | — | None | — | — | Missing | RIRBaseEnemyCharacter.cpp |
Primary attack initiation classification: Implementation Missing.
Secondary: Orphan attack montage /Game/_Main/Animations/Enemies/Skeleton/Anim_SkeletonAttackMontage — Present but Unreferenced; not evidence of an attack path.
6. Damage and death table
| Input mechanism | Health source | Mutation | Death threshold | Death behavior | Cleanup | Status | Evidence |
|---|---|---|---|---|---|---|---|
| Player ApplyDamage (Paladin/Amazonian/Cleric) | Expected engine TakeDamage | No enemy BP ReceiveAnyDamage; no ASC Health bridge |
None observed | None in enemy BP | None | Implementation Missing (reception) | Event list; AttributeSet has no PostGEExecute |
| ASC Health attribute | URIRAttributeSet on enemy |
Not written by combat graphs | None | None | — | Scaffolding Only for combat | Pass 7 + Pass 9 |
| Gameplay Effect on enemy | EffectActor library GetASC | nullptr via base GetASC | N/A | Early-out | — | Existing Baseline Defect | Pass 7 |
| Death animation | ABP Death state + Anim_Monster_Dead_1..4 |
IsDead set to literal false every UpdateAnimation |
Unreachable via IsDead | Death state present | Unknown | Connected but Incomplete | ABP EventGraph DSL |
| DestroyActor / ragdoll / rewards | — | — | — | None observed on enemy BP | Missing | Missing | EventGraph DSL |
Player→enemy ApplyDamage compatibility (static): Playable attacks do call ApplyDamage (Pass 6). Enemy Blueprints do not implement AnyDamage→health→death. Native AttributeSet does not clamp or kill from ApplyDamage. Inferred: player melee may deal engine damage events with no observed enemy health/death consumer — Requires Runtime Inspection for visual feedback only.
7. Animation callback table
| Asset | Notify/callback | Receiver | Gameplay consequence | State reset | Connection status | Evidence |
|---|---|---|---|---|---|---|
ABP_Skeleton EventGraph |
BlueprintInitializeAnimation | GetEnemyREF → Enemy Reference | Cache REF | — | Connected | read_graph_dsl |
ABP_Skeleton EventGraph |
BlueprintUpdateAnimation | SetSpeed from velocity; SetIsDead(false); DeathIndex DoOnce | Locomotion speed; blocks death flag | — | Connected (death flag forced false) | read_graph_dsl |
ABP_Skeleton Locomotion |
States: Idle/Walk/Run, Death | — | Presentation | — | Death transition Unknown (DSL empty) | list_graphs |
Anim_SkeletonAttackMontage |
Unknown notifies | No owner plays montage | None | — | Present but Unreferenced | get_referencers [] |
Death sequences Anim_Monster_Dead_1..4 |
Via ABP Death state | ABP_Skeleton | Cosmetic death pose if state entered | — | Referenced by ABP only | get_dependencies |
No enemy AnimNotify → damage / UseAbility / ApplyDamage path observed.
8. Enemy GAS compatibility table
| Consumer | ASC lookup method | Expected owner | Static result | Null behavior | Potential impact | Runtime verification |
|---|---|---|---|---|---|---|
ARIREffectActor::ApplyEffectToTarget |
UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent → ARIRBaseCharacter::GetAbilitySystemComponent → PlayerState |
Enemy self ASC | nullptr | Early return; no GE | Potions/effects skip enemies | PIE |
Enemy direct AbilitySystemComponent member |
Native TObjectPtr on enemy | Self | Valid if used | — | No combat consumer observed | — |
| IAbilitySystemInterface on enemy | Same as GetASC base | Self intended | nullptr | Same | Interface consumers fail | PIE |
| Enemy AttributeSet Health | Direct member | Self | Exists; unreplicated combat use | — | Spawn Init values only | PIE |
| Enemy BP damage/death | N/A | — | No ASC read/write in enemy graphs | — | Combat independent of ASC | — |
| Chase / attack graphs | N/A | — | No dependency on ASC | — | GetASC defect does not explain chase/attack failure | — |
9. Root-cause summary
| System | Primary classification | Secondary conditions | Exact evidence | Runtime question |
|---|---|---|---|---|
| Target acquisition | Implementation Missing | BPI AddPlayerTarget unimplemented; empty Tick/Overlap | EventGraph DSL; interface | — |
| Chase | Implementation Missing | No MoveTo; stock AIController; no navmesh in Test01 | DSL; find_assets; find_actors | Would possession alone idle forever? |
| Attack initiation | Implementation Missing | EnemyMeleeAttack unimplemented; attack montage 0 refs | Interface; get_referencers | — |
| Attack damage | Implementation Missing | No ApplyDamage/GE from enemy | Native + BP | — |
| Attack cleanup | Missing | — | — | — |
| Damage reception | Implementation Missing | No ReceiveAnyDamage; no ASC bridge from ApplyDamage | Event list | Do player hits show feedback? |
| Death | Connected but Incomplete | ABP Death + death anims exist; SetIsDead(false) every frame | ABP EventGraph DSL | Can Death state ever enter? |
| Enemy Gameplay Effect compatibility | Existing Baseline Defect / Incomplete Refactor | GetASC → PlayerState | RIRBaseCharacter.cpp | EffectActor on enemy |
BPI_EnemyCharacter inventory
Path: /Game/_Main/Blueprints/Interfaces/BPI_EnemyCharacter
| Member | Implemented on Skeleton | Callers (referencers of interface asset) |
|---|---|---|
| GetEnemyREF | Yes → return self | BP_Enemy_Skeleton, ABP_Skeleton |
| AddPlayerTarget | No | None observed beyond interface declaration |
| EnemyMeleeAttack | No | None observed |
Negative-search evidence log
| Search | Scope | Result |
|---|---|---|
find_assets BehaviorTree /Game |
Project | [] |
find_assets Blackboard /Game |
Project | [] |
find_assets StateTree /Game |
Project | [] |
find_assets EnvQuery /Game |
Project | [] |
find_assets AIPerception /Game |
Project | [] |
| search_subclasses AIController | Engine+project | Engine-only classes |
| Source grep MoveTo/BehaviorTree/Attack AI | Source/REALMSINRUIN | No AI combat (only enemy class highlight/ASC) |
| get_referencers Anim_SkeletonAttackMontage | Asset registry | [] |
| find_actors NavMeshBoundsVolume / RecastNavMesh | Test01 | [] |
| Enemy EventGraph MoveTo/GetPlayer*/ApplyDamage nodes | Both enemy BPs | None (empty DSL) |
Migration / defect notes (inventory only)
- Reconstructing enemy AI requires new implementation (or restoring unobserved deleted content) — not a reconnect of an existing connected graph.
- Interface
AddPlayerTarget/EnemyMeleeAttackare Documented Intent scaffolds. - Fixing enemy GetASC is a separate Incomplete Refactor; it does not restore chase/attack.
- ABP
SetIsDead(false)is a static death-path defect independent of chase.