Add executive summary and ability migration matrix; finalize evidence index, runtime validation plan, and Phase 1 handoff. Co-authored-by: Cursor <cursoragent@cursor.com>
220 lines
15 KiB
Markdown
220 lines
15 KiB
Markdown
# 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` / `EnemyMeleeAttack` are 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.
|