Captures Blueprint hierarchy, legacy ability/RPC paths, animation dependency seeds, and handoff state without modifying Unreal assets. Co-authored-by: Cursor <cursoragent@cursor.com>
236 lines
17 KiB
Markdown
236 lines
17 KiB
Markdown
# 05 — Legacy Ability Architecture
|
||
|
||
**Status: Draft**
|
||
|
||
- **Scope:** Shared `BP_PlayerCharacterBase` ability architecture (Batch 2) plus per-character Ability 001–004 connected-path reconstruction (Batch 3 Pass 6).
|
||
- **Inspection method:** Read-only BlueprintTools `find_nodes` / `get_node_infos` / `get_connected_subgraph` / `read_graph_dsl`; AssetTools deps; ObjectTools CDO samples.
|
||
- **Evidence classifications used:** Observed Implementation, Documented Intent, Observed Runtime Behavior, Inferred, Unknown.
|
||
- **Tool or visibility limitations:** CustomEvent Reliable/Unreliable flags not exposed; comment-box regions not found via `find_nodes(title=Comment)`; Montage notify tracks not deep-inspected (Pass 8).
|
||
- **Last updated:** 2026-07-16
|
||
- **Current phase:** Phase 1 — Static Architecture
|
||
- **Last completed pass:** Pass 6 (Batch 3)
|
||
- **Next pass expected to contribute:** Batch 4 Pass 7 (GAS systemwide) / Pass 8 (AnimBP/Montage notifies)
|
||
|
||
## Draft tracking
|
||
|
||
### Completed sections
|
||
- Shared input → Server RPC routing on base
|
||
- Base Server_Ability_* stubs
|
||
- Multicast FX helpers
|
||
- Death / respawn / HUD (DEPRECATED floats)
|
||
- **Per-character Ability 001–004 connected paths for all five playables**
|
||
- Parent-call inventory
|
||
- Resource / damage / projectile inventories
|
||
- Montage dependency seeds
|
||
|
||
### Pending sections
|
||
- Cross-character migration matrix (Pass 11 → doc 07)
|
||
- Montage notify → UseAbility exact wiring (Pass 8)
|
||
- Runtime verification of CDO damage/mana values (PIE)
|
||
|
||
### Evidence still required
|
||
- Who fires UseAbility* (anim notifies vs other) — Requires Manual Editor Inspection / Pass 8
|
||
- FCanUseMana implementation body (function on base — not re-walked this batch beyond call sites)
|
||
- Client_Charge timeline details beyond ChargeTimeline / LineTrace / SetActorLocation
|
||
|
||
---
|
||
|
||
## Shared architecture (Batch 2 baseline — verified)
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
IA[IA_Ability_001to004] -->|Started| SBegin[Server_Ability_N_Begin]
|
||
IA -->|Completed_or_Canceled| SEnd[Server_Ability_N_End]
|
||
SBegin -->|base| Print[PrintString Override]
|
||
SBegin -->|child override| Child[Character body]
|
||
Child --> MC[Multicast_PlayMontage]
|
||
Child --> Use[UseAbilityN Authority]
|
||
Use --> Dmg[ApplyDamage or RecoverHealth]
|
||
```
|
||
|
||
**Observed Implementation:** No `UGameplayAbility` activation. Reliability: **Unknown — MCP property visibility limitation**.
|
||
|
||
| Base event | Body |
|
||
|---|---|
|
||
| Server_Ability_*_Begin | PrintString `"Override Ability N"` |
|
||
| Server_Ability_*_End | then unconnected |
|
||
| Multicast_PlayMontage / PlaySFX / Multi_SpawnParticle | Active helpers |
|
||
|
||
---
|
||
|
||
## Parent-call inventory (Pass 6)
|
||
|
||
| Character | Ability overrides call Parent? | Other Parent calls |
|
||
|---|---|---|
|
||
| Paladin | **No** on Ability Begin/UseAbility | Tick/Overlap call Parent; BeginPlay does **not** (leader-pose style local) |
|
||
| Amazonian | **No** | — |
|
||
| Cleric | **No** on any ability override | BeginPlay no Parent (leader pose) |
|
||
| Wizard | N/A (no ability overrides) | BeginPlay **no Parent**; Tick/Overlap **call Parent** |
|
||
| Gunslinger | N/A | BeginPlay/Tick/Overlap **call Parent** |
|
||
|
||
---
|
||
|
||
## Player_Paladin
|
||
|
||
**Path:** `/Game/_Main/Blueprints/Characters/PlayerCharacters/PlayerCharacterClasses/Paladin/Player_Paladin`
|
||
|
||
| Slot/System | Entry point | Parent called | Server path | Multicast/client path | Validation | Resource | Damage/effect | Animation | End/cleanup | Status | Evidence |
|
||
|---|---|---|---|---|---|---|---|---|---|---|---|
|
||
| Ability 001 | Server_Ability_001_Begin; UseAbility001 | No | Gate !attacking && !dead → CurrentlyAttacking → SetPlayerCanMove(true) → Multicast_PlayMontage(random Ability001Montages) | Multicast_PlayMontage | Gate only | None | UseAbility001 Authority: BoxOverlap(90,50,100) forward×150 → ApplyDamage(DEPRECATED_Ability001Damage) | Attack_A/B/C/D_Fast_Montage | Server_Ability_001_End not implemented locally | **Implemented** (End Partial) | get_connected_subgraph |
|
||
| Ability 002 | Server_Ability_002_Begin; Server_Ability_002_End | No | Begin: gate → CurrentlyAttacking → CanMove false → IsBlocking true | None in Begin | Gate | None | Block state only (no ApplyDamage in Begin) | None in Begin (IsBlocking likely AnimBP) | End: CurrentlyAttacking=false → CanMove true → IsBlocking false | **Partial** (block state; no hit absorb path traced) | subgraph Event_5 / Event_7 |
|
||
| Ability 003 | Server_Ability_003_Begin; Charge; Client_Charge; ChargeBox overlap | No | Gate → FCanUseMana(DEPRECATED_Ability003ManaCost) → CurrentlyAttacking → CanMove false → ChargeBox QueryOnly → Charge + Client_Charge | Client_Charge | Gate + mana | DEPRECATED_Ability003ManaCost via FCanUseMana | ChargeBox Authority: NOT tag Player → ApplyDamage(DEPRECATED_Ability003Damage) | ChargeTimeline + LineTrace + SetActorLocation lerp | Ends not locally implemented for 003 | **Implemented** (charge + overlap damage) | subgraph Event_6 / Charge / ChargeBox |
|
||
| Ability 004 | Server_Ability_004_Begin; UseAbility004 | No | Gate → FCanUseMana(DEPRECATED_Ability004ManaCost) → CurrentlyAttacking → CanMove false → Multicast_PlayMontage(Paladin_Ability004_Montage) | Multicast_PlayMontage; UseAbility004: Multi_SpawnParticle (EmitterTemplate empty) + Multicast_PlaySFX(MagicSpell_01_Cue) | Gate + mana | DEPRECATED_Ability004ManaCost | UseAbility004 Authority: SphereOverlap radius 300 → ApplyDamage(DEPRECATED_Ability004Damage) | Paladin_Ability004_Montage | End not local | **Implemented** (FX particle template empty) | subgraph Event_8 / Event_11 |
|
||
| Basic attack | Same as Ability 001 | No | Same | Same | Same | Same | Same | Attack_* montages | Same | **Implemented** (=001) | — |
|
||
| Passive | — | — | — | — | — | — | — | — | — | **Missing** | — |
|
||
| Death | Inherited PlayerDeath | — | Base | Base | — | DEPRECATED health (if damaged via AnyDamage — Paladin has no local AnyDamage) | Base | Base | Base | **Inherited** | list_events |
|
||
| Legacy HUD | Inherited Server_UpdateHUD | — | Base DEPRECATED floats | — | — | Reads DEPRECATED health/mana | — | — | — | **Inherited** | Batch 2 |
|
||
|
||
**Paladin montages:**
|
||
`/Game/_Main/Animations/PlayerCharacters/Human/CharacterClasses/Paladin/AnimMontages/Attack_{A,B,C,D}_Fast_Montage`
|
||
`/Game/_Main/Animations/PlayerCharacters/Human/CharacterClasses/Paladin/AnimMontages/Abilities/Paladin_Ability004_Montage`
|
||
|
||
---
|
||
|
||
## Player_Amazonian
|
||
|
||
**Path:** `/Game/_Main/Blueprints/Characters/PlayerCharacters/PlayerCharacterClasses/Amazonian/Player_Amazonian`
|
||
|
||
| Slot/System | Entry point | Parent called | Server path | Multicast/client path | Validation | Resource | Damage/effect | Animation | End/cleanup | Status | Evidence |
|
||
|---|---|---|---|---|---|---|---|---|---|---|---|
|
||
| Ability 001 | Server_Ability_001_Begin; UseAbility001 | No | Gate → CurrentlyAttacking → CanMove true → Multicast_PlayMontage(random Ability001Montage) | Multicast_PlayMontage | Gate | None | UseAbility001 Authority: BoxOverlap → ApplyDamage(DEPRECATED_Ability001Damage) | A_Hu_F_Combat_2H_Attack* montages | End not local; CurrentlyAttacking cleared via base SetIsAttacking (Inferred) | **Implemented** | subgraph |
|
||
| Ability 002–004 | Inherited only | N/A | Base PrintString | — | — | — | — | — | Base empty End | **Stub** (inherited) | list_events |
|
||
| Basic attack | Ability 001 | No | Same | Same | Same | Same | Same | Attack montages | Same | **Implemented** (=001); **Observed Runtime Behavior:** known working melee | parity brief + subgraph |
|
||
| Passive | — | — | — | — | — | — | — | — | — | **Missing** | — |
|
||
| Whirlwind | PerformingWhirlwind Get only | — | — | — | Gates AnyDamage | — | — | — | Never Set | **Partial / Present but Unconnected setter** | find_nodes |
|
||
| Death | ReceiveAnyDamage → PlayerDeath | — | Local health subtract DEPRECATED_CurrentHealth → Server_UpdateHUD → PlayerDeath if ≤0 | Base death | PlayerHitCheck when whirlwind | Writes DEPRECATED_CurrentHealth | ApplyDamage inbound | — | Base | **Partial** (legacy health) | subgraph |
|
||
| Legacy HUD | Server_UpdateHUD after damage | — | Base | — | — | DEPRECATED health | — | — | — | **Active** | subgraph |
|
||
|
||
**Amazonian montages:**
|
||
`/Game/_Main/Animations/PlayerCharacters/Human/CharacterClasses/Amazon/AnimMontages/A_Hu_F_Combat_2H_Attack01_Montage` (+ Attack02, Attack_Base, Attack)
|
||
|
||
---
|
||
|
||
## Player_Cleric
|
||
|
||
**Path:** `/Game/_Main/Blueprints/Characters/PlayerCharacters/PlayerCharacterClasses/Cleric/Player_Cleric`
|
||
|
||
| Slot/System | Entry point | Parent called | Server path | Multicast/client path | Validation | Resource | Damage/effect | Animation | End/cleanup | Status | Evidence |
|
||
|---|---|---|---|---|---|---|---|---|---|---|---|
|
||
| Ability 001 | Server_Ability_001_Begin | No | Gate → CurrentlyAttacking → CanMove false → Multicast_PlayMontage(random Ability001Montages) | Multicast_PlayMontage | Gate | None | **No UseAbility001** — no hit path | Cleric_PrimaryAttack_* | End not local | **Partial** (montage only) | subgraph |
|
||
| Ability 002 | Server_Ability_002_Begin; UseAbility002 | No | Gate → FCanUseMana(Ability002ManaCost) → CurrentlyAttacking → CanMove true → Multicast_PlayMontage(Cleric_Ability002_Montage) | Multi_SpawnParticle (EmitterTemplate **empty**); UseAbility002 Authority heal | Gate + mana | DEPRECATED_Ability002ManaCost | SphereOverlap 400 tag Player → DEPRECATED_RecoverPlayerHealth(Ability002Damage); self heal | Cleric_Ability002_Montage | End not local | **Partial** (heal works; particle empty) | subgraph |
|
||
| Ability 003 | Server_Ability_003_Begin; Server_Ability_003_End; ConcentrateHandle; EndConcentrate | No | Mana≥cost → DivineCircleActive + SetTimer 0.25 ConcentrateHandle | ConcentrateHandle: Multicast_PlayMontage(Cleric_Ability003) + ApplyDamage(Ability003Damage) on non-Player | Gate + mana | DEPRECATED_Ability003ManaCost | ApplyDamage DoT | Cleric_Ability003_Montage (in timer) | End → EndConcentrate clears timer/state | **Implemented** | subgraph + DSL |
|
||
| Ability 004 | Server_Ability_004_Begin; UseAbility004 | No | Gate → FCanUseMana called but Branch Condition=**literal true** (CanUse unwired) → montage | UseAbility004: find ClosestEnemy tag Enemy → SpawnActor **Class empty** | Gate; mana bypassed | DEPRECATED_Ability004ManaCost (unused result) | Spawn params Damage=20 HealPerHit=10 (unwired class) | Cleric_Ability004_Montage | End not local | **Partial / Existing Baseline Defect** | subgraph |
|
||
| Basic attack | Ability 001 montage | No | Same | Same | Same | — | Missing hit | PrimaryAttack montages | — | **Partial** | — |
|
||
| Passive | — | — | — | — | — | — | — | — | — | **Missing** | — |
|
||
| Death / HUD | Inherited | — | Base | Base | — | — | — | — | — | **Inherited** | — |
|
||
|
||
**Cleric GE** `GE_Cleric_DefaultAttributes` exists but **0 referencers**; not in ability graphs.
|
||
|
||
---
|
||
|
||
## Player_Wizard
|
||
|
||
**Path:** `/Game/_Main/Blueprints/Characters/PlayerCharacters/PlayerCharacterClasses/Wizard/Player_Wizard`
|
||
|
||
| Slot/System | Entry point | Parent called | Server path | Multicast/client path | Validation | Resource | Damage/effect | Animation | End/cleanup | Status | Evidence |
|
||
|---|---|---|---|---|---|---|---|---|---|---|---|
|
||
| Ability 001–004 | Inherited Server_Ability_* only | N/A | Base PrintString | — | — | — | — | — | Base empty End | **Stub** (inherited PrintString) | list_events + EventGraph walk |
|
||
| Basic attack | Same | N/A | Stub | — | — | — | — | — | — | **Stub** | — |
|
||
| Passive | — | — | — | — | — | — | — | — | — | **Missing** | — |
|
||
| Death / HUD | Inherited | Tick/Overlap Parent yes; BeginPlay **no Parent** | Base | Base | — | — | — | — | — | **Inherited** | subgraph |
|
||
| Alternate paths | UseAbility* false; no Input/Montage/spell nodes | — | — | — | — | — | — | — | — | **Missing** | find_nodes |
|
||
| Unwired assets | NS_Wizard_Ability001; GE_Wizard_DefaultAttributes; BP_PlayerProjectile | — | — | — | — | — | — | — | — | **Present but Unconnected** | deps/referencers |
|
||
|
||
Local vars `EnemyFound`, `IsBlocking`, `ClosestEnemy`: **declared, zero EventGraph uses**.
|
||
|
||
---
|
||
|
||
## Player_Gunslinger
|
||
|
||
**Path:** `/Game/_Main/Blueprints/Characters/PlayerCharacters/PlayerCharacterClasses/Gunslinger/Player_Gunslinger`
|
||
|
||
| Slot/System | Entry point | Parent called | Server path | Multicast/client path | Validation | Resource | Damage/effect | Animation | End/cleanup | Status | Evidence |
|
||
|---|---|---|---|---|---|---|---|---|---|---|---|
|
||
| Ability 001–004 | Inherited only | N/A | Base PrintString | — | — | — | — | — | Base empty End | **Stub** (inherited) | IsDataOnly + deps |
|
||
| Basic attack | Inherited stub | N/A | Stub | — | — | — | — | — | — | **Stub** | — |
|
||
| Passive | — | — | — | — | — | — | — | — | — | **Missing** | — |
|
||
| Death / HUD | Inherited; BeginPlay Parent | Yes | Base | Base | — | — | — | — | — | **Inherited** | subgraph |
|
||
| Weapon/projectile | None | — | — | — | — | — | — | — | — | **Missing** | deps only base |
|
||
|
||
**IsDataOnly=True.** No GE_Gunslinger. Referencers registry [].
|
||
|
||
---
|
||
|
||
## Cross-character RPC inventory (ability-related)
|
||
|
||
| Event | Paladin | Amazonian | Cleric | Wizard | Gunslinger |
|
||
|---|---|---|---|---|---|
|
||
| Server_Ability_001_Begin | Local override | Local | Local | Inherit stub | Inherit stub |
|
||
| Server_Ability_001_End | Inherit empty | Inherit empty | Inherit empty | Inherit | Inherit |
|
||
| Server_Ability_002_Begin | Local (block) | Inherit stub | Local | Inherit | Inherit |
|
||
| Server_Ability_002_End | Local | Inherit | Inherit empty | Inherit | Inherit |
|
||
| Server_Ability_003_Begin | Local (charge) | Inherit | Local (DivineCircle) | Inherit | Inherit |
|
||
| Server_Ability_003_End | Inherit | Inherit | Local → EndConcentrate | Inherit | Inherit |
|
||
| Server_Ability_004_Begin | Local | Inherit | Local (mana bypass) | Inherit | Inherit |
|
||
| Server_Ability_004_End | Inherit | Inherit | Inherit | Inherit | Inherit |
|
||
| UseAbility001 | Local Authority damage | Local Authority damage | Missing | Missing | Missing |
|
||
| UseAbility002 | Missing | Missing | Local Authority heal | Missing | Missing |
|
||
| UseAbility004 | Local Authority AoE | Missing | Local Authority spawn broken | Missing | Missing |
|
||
| Charge / Client_Charge | Local | — | — | — | — |
|
||
| ConcentrateHandle / EndConcentrate | — | — | Local | — | — |
|
||
|
||
Reliability: **Unknown — MCP property visibility limitation** for all CustomEvents.
|
||
|
||
---
|
||
|
||
## Resource and legacy-state inventory
|
||
|
||
| Symbol | Readers/Writers | Notes |
|
||
|---|---|---|
|
||
| DEPRECATED_Ability001Damage | Paladin UseAbility001; Amazonian UseAbility001 | ApplyDamage BaseDamage |
|
||
| DEPRECATED_Ability003Damage | Paladin ChargeBox | ApplyDamage |
|
||
| DEPRECATED_Ability004Damage | Paladin UseAbility004 | ApplyDamage |
|
||
| DEPRECATED_Ability002Damage | Cleric UseAbility002 | Heal amount via RecoverPlayerHealth |
|
||
| DEPRECATED_Ability00{2,3,4}ManaCost | Paladin 003/004; Cleric 002/003/004 | FCanUseMana / compare |
|
||
| DEPRECATED_CurrentHealth | Amazonian AnyDamage | Subtract + death check |
|
||
| DEPRECATED_RecoverPlayerHealth | Cleric UseAbility002 | Interface message |
|
||
| CurrentlyAttacking / IsDead | All ability gates | Replicated on base |
|
||
| IsBlocking | Paladin 002 Begin/End | Local; AnimBP dependency Unknown |
|
||
| PerformingWhirlwind | Amazonian AnyDamage | Get only — never Set |
|
||
| DivineCircleActive / TimerHandle | Cleric 003 | Timer loop |
|
||
|
||
**No ASC attribute reads/writes in ability graphs.** No GameplayAbility grant/activate.
|
||
|
||
---
|
||
|
||
## Authority / networking findings (flags, no fixes)
|
||
|
||
- Client IA → Server Begin: Observed Implementation
|
||
- Damage on UseAbility* / ChargeBox: Authority SwitchHasAuthority — Observed Implementation
|
||
- Multicast used for montage/SFX/particle presentation — Observed Implementation
|
||
- Cleric Ability 004: mana CanUse **unwired** (literal true) — Existing Baseline Defect
|
||
- Cleric Ability 004: SpawnActor Class empty — Existing Baseline Defect
|
||
- Multi_SpawnParticle EmitterTemplate empty (Paladin 004, Cleric 002) — Partially Implemented
|
||
- End events missing for most slots — Incomplete Refactor
|
||
- Amazonian/Paladin Ability 001: no mana cost — Observed Implementation
|
||
- Dual HUD still uses DEPRECATED floats on Server_UpdateHUD — Incomplete Refactor (Batch 2)
|
||
|
||
---
|
||
|
||
## Status rollup
|
||
|
||
| Classification | Characters / slots |
|
||
|---|---|
|
||
| **Implemented** | Paladin 001, 003, 004 (with noted FX holes); Amazonian 001; Cleric 003 |
|
||
| **Partial** | Paladin 002; Cleric 001, 002, 004; Amazonian End/whirlwind |
|
||
| **Stub** | Wizard 001–004; Gunslinger 001–004 (inherited PrintString) |
|
||
| **Missing** | Wizard/Gunslinger combat bodies; most Ends; UseAbility on Wizard/Gunslinger |
|
||
| **Present but Unconnected** | NS_Wizard_Ability001; GE_* DefaultAttributes orphans; BP_PlayerProjectile; PerformingWhirlwind setter |
|
||
| **Deprecated connected** | All DEPRECATED_* damage/mana/health in active paths |
|
||
|
||
---
|
||
|
||
## Migration relevance (inventory only)
|
||
|
||
Replacement targets: IA→Server custom events; ApplyDamage/RecoverPlayerHealth; FCanUseMana + DEPRECATED costs; Multicast_PlayMontage; Charge timeline; DivineCircle timer; dual HUD floats.
|