Document Batch 4C Pass 9 enemy AI archaeology: missing chase and attack implementation.

Records empty enemy EventGraphs, stock AIController possession, orphan attack montage, and separates GetASC defect from chase/attack failure.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-16 21:46:08 -07:00
co-authored by Cursor
parent e50c8032ef
commit 53315574a4
8 changed files with 354 additions and 216 deletions
@@ -2,75 +2,240 @@
**Status: Draft**
- **Scope:** Native enemy class (Batch 1) + Pass 3 structural Blueprint inventory. Deep Tick/overlap/AI graph walk deferred to Pass 9.
- **Inspection method:** Native read; Batch 2 AssetTools tags + BlueprintTools list_graphs/events/variables/deps.
- **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
- **Last completed pass:** Pass 3 (Batch 2) — structural only
- **Next pass expected to contribute:** Batch 4 Pass 9
- **Last completed pass:** Pass 9 (Batch 4C)
- **Next pass expected to contribute:** Pass 4 / Pass 10 when authorized — not auto-started
## Draft tracking
### Completed sections
- Native enemy ASC ownership and highlight interface
- Confirmation: no chase/attack/MoveTo in native C++
- Blueprint child paths + Pass 3 structural sheets
- BPI_EnemyCharacter API surface
- Native enemy ASC, highlight, no native AI combat
- Full BP_EnemyCharacterBase / BP_Enemy_Skeleton structural + EventGraph reconstruction
- BPI_EnemyCharacter implementation status
- Controller / AutoPossessAI class + instance
- AI framework negative inventory
- Targeting / chase / attack absence
- Attack montage orphan
- ABP_Skeleton locomotion + Death + IsDead forced false
- Damage/death reception absence at BP layer
- Enemy GAS compatibility (Pass 7 + Pass 9)
- Test01 navigation context (no NavMeshBoundsVolume / RecastNavMesh)
- Root-cause classifications for chase and attack
### Pending sections
- Connected Tick / overlap / timer / MoveTo graphs on enemy BPs
- AIControllerClass / AutoPossessAI on CDOs (reconfirm)
- Consumers of GetASC on enemies
- Runtime possession confirmation under PIE
- Whether engine TakeDamage has any other consumer outside enemy BP
- ABP Death transition condition exact VariableGet wiring (DSL empty)
### Evidence still required
- Where chase/attack was intended to live (Blueprint vs missing)
- Runtime root cause of nonfunctional chase/attack — Requires Runtime Inspection
- PIE: does stock AIController possess placed skeletons?
- PIE: player ApplyDamage visual/health effect on skeleton
- Manual Editor: ABP Death transition rule pins
---
## Native findings
## Executive summary
**Observed Implementation:** `ARIRBaseEnemyCharacter` implements:
**Observed Runtime Behavior (project brief):** Enemy chase and attack are nonfunctional — Existing Baseline Defect.
- ASC + AttributeSet on self (Minimal replication)
- InitAbilityActorInfo(this, this) in BeginPlay
- ITargetInterface highlight via custom depth
- Visibility collision on mesh
**Pass 9 static conclusion:**
**Observed Implementation:** No AIController subclass, no MoveTo, no perception, no attack timers in native.
| 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 |
**Calibration (prior Observed Implementation):** Stock `/Script/AIModule.AIController`; AutoPossessAI PlacedInWorld on skeleton instance; no project BehaviorTree assets.
**Issue:** Existing Baseline Defect (enemy chase/attack nonfunctional per project brief).
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.
---
## Pass 3 Blueprint structure (not Pass 9 deep dive)
## 1. Enemy class and control matrix
### `BP_EnemyCharacterBase`
| 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 |
| Field | Value |
|-------|--------|
| Path | `/Game/_Main/Blueprints/Characters/Enemies/BP_EnemyCharacterBase` |
| Parent | `RIRBaseEnemyCharacter` |
| IsDataOnly | True |
| Graphs | UserConstructionScript, EventGraph |
| Variables | [] |
| Implemented events | ReceiveBeginPlay, ReceiveTick, ReceiveActorBeginOverlap |
| Deps | `/Script/REALMSINRUIN` only |
**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.
### `BP_Enemy_Skeleton`
**Blueprint EventGraphs (both base and Skeleton) — Observed Implementation:**
| Field | Value |
|-------|--------|
| Path | `/Game/_Main/Blueprints/Characters/Enemies/Skeleton/BP_Enemy_Skeleton` |
| Parent | `BP_EnemyCharacterBase_C` |
| Interface | `BPI_EnemyCharacter` (`GetEnemyREF`) |
| Graphs | UCS, EventGraph, GetEnemyREF |
| Variables | [] |
| Implemented events | ReceiveBeginPlay, ReceiveTick, ReceiveActorBeginOverlap |
| Deps | SKM_Skeleton_Guard_Body, BPI_EnemyCharacter, BP_EnemyCharacterBase, ABP_Skeleton, REALMSINRUIN |
```
(event EventBeginPlay)
(event Collision|EventActorBeginOverlap (OtherActor))
(event EventTick (DeltaSeconds))
```
### `BPI_EnemyCharacter`
All three entry nodes are **Present but Unconnected** (no wired body). Variables on both BPs: **[]**.
Graphs: `GetEnemyREF`, `AddPlayerTarget`, `EnemyMeleeAttack`**Documented Intent** surface for targeting/melee; connected implementations on Skeleton/base **not traced in Batch 2** (Pass 9).
**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.