# Phase 2A2a — Shared Gameplay Contracts | Field | Value | |---|---| | Status | Draft | | Date | 2026-07-17 | | Phase | 2A2a — Shared gameplay contract proposal | | Starting Git commit | `9919faab` | | Engine | Unreal Engine 5.8 | | Rule | All contracts are **Proposed**. None are Approved. No implementation in this pass. | ## Purpose Translate accepted Phase 1 static archaeology and Phase 2A1 runtime evidence into proposed shared gameplay contracts. These contracts define architectural boundaries for review. They do not authorize implementation, asset changes, or Phase 2B. ## Evidence vocabulary | Label | Meaning | |---|---| | Static evidence | Phase 1 archaeology observation | | Runtime evidence | Phase 2A1 observed runtime behavior or tool limitation | | Tool limitation | Cannot observe because tooling/environment blocked the path | | Inference | Reasonable conclusion not directly proven | | Recommendation | Proposed architectural choice (not observed fact) | | Required approval | Exact question for the project owner | | Deferred validation | Runtime test still required before trusting the rule | ## Decision states used in this pass Proposed · Alternative · Deferred · Blocked by Runtime Evidence · Blocked by Design Decision · Rejected by Existing Evidence **Do not use Approved.** ## Continuity | Check | Result | |---|---| | Phase 2A1 evidence reviewed | Yes — `00`, `01`, `02` under `Documentation/Phase2/` | | Starting `git rev-parse HEAD` | `9919faab4aa667cad4b4156bfa46c2d9f2113e40` | | Working tree at start | Clean | Cross-links: [`00-Phase2A-RuntimeBaseline.md`](00-Phase2A-RuntimeBaseline.md), [`01-Phase2A-RuntimeEvidenceIndex.md`](01-Phase2A-RuntimeEvidenceIndex.md), [`02-Phase2A-OpenDecisions.md`](02-Phase2A-OpenDecisions.md), [`04-Phase2A-DecisionRegister.md`](04-Phase2A-DecisionRegister.md). --- # C-001 — Canonical player resource source of truth **State:** Proposed ### Problem being solved Combat, death, ability costs, potions, and HUD currently read different resource stores. ASC and DEPRECATED Blueprint values diverge immediately after spawn, so UI and combat can disagree. ### Current implementation - Player ASC + AttributeSet live on `ARIRPlayerState`. - Overlay HUD binds ASC Health/Mana. - Abilities and Amazonian inbound damage use DEPRECATED floats (`DEPRECATED_CurrentHealth`, mana costs, etc.). - Consumable GEs modify ASC attributes only. - No sync between ASC and DEPRECATED pools. ### Confirmed evidence | Kind | Evidence | |---|---| | Static | Docs `05`, `06` §8, `01` P0 dual-resource risk — combat uses legacy; potions/Overlay use ASC; sync Missing | | Runtime | RE-2A1-001/012: ASC Health 75/100, Mana 25/50, Stamina 0/0 for Amazonian and Paladin | | Runtime | RE-2A1-004/005: Amazonian legacy health/mana 0; stamina 85/100 | | Runtime | RE-2A1-013: Paladin legacy Mana 100/100 vs ASC 25/50; legacy Health 0/0 | | Runtime | RE-2A1-002/003: no active GEs; no granted GAs at spawn | | Inference | Amazonian AnyDamage writing legacy health=0 is at immediate death-threshold risk if that path fires | ### Proposed rule ASC attributes are the **sole canonical source of truth** for Health, MaxHealth, Mana, MaxMana, Stamina, and MaxStamina. DEPRECATED Blueprint resource variables are **not authoritative**. UI, costs, healing, damage, death, and gameplay gating ultimately read the canonical ASC attributes. Spawn divergence is treated as a **confirmed dual-store defect**, not two valid truths. ### Allowed behavior - Reading ASC attributes for gameplay and UI. - Writing ASC attributes through shared authoritative boundaries (C-003, C-005, C-006). - Temporary ASC→legacy shadow copies for unconverted read-only consumers (C-004). ### Prohibited behavior - Treating DEPRECATED floats as authoritative for new gameplay. - UI or death decisions driven solely by DEPRECATED values after cutover. - Silent acceptance of ASC/legacy disagreement as intended design. ### Transitional behavior Until each consumer is migrated, an ASC→legacy one-way shadow may keep unconverted readers consistent (C-004). Legacy writers must be migrated or blocked before they can overwrite ASC. ### Dependencies C-002 (initialization), C-003 (access boundary), C-004 (legacy policy). ### Migration impact Ability costs, Amazonian AnyDamage/death, Cleric heal, Overlay (already ASC), any remaining `Server_UpdateHUD` callers, future stamina systems. ### Runtime validation required - After init policy lands: ASC and any permitted shadow values match at spawn for each playable. - Potion heal changes ASC and Overlay; combat damage changes ASC Health. - Death fires from ASC Health ≤ 0, not legacy zero alone. ### Failure modes - Partial migration leaves one system on ASC and another on legacy → desync returns. - Shadow omitted while legacy death still active → false immediate death or immortal combat. ### Approval question **Do you approve ASC AttributeSet as the sole canonical source of truth for Health, MaxHealth, Mana, MaxMana, Stamina, and MaxStamina, with DEPRECATED Blueprint resource variables treated as non-authoritative?** --- # C-002 — Character default attribute initialization **State:** Proposed (recommended option A) ### Problem being solved All inspected characters spawn with identical native ASC defaults. Orphan character default GEs are unreferenced. Stamina ASC remains 0/0. Missing character defaults fail silently via native Init*, producing incorrect balance and hiding misconfiguration. ### Current implementation - `URIRAttributeSet` ctor: InitHealth(75), InitMaxHealth(100), InitMana(25), InitMaxMana(50); Stamina/MaxStamina not Init'd. - `BP_PlayerState.DefaultAttributesGameplayEffect` = None. - Orphan GEs (`GE_*_DefaultAttributes`) exist per character but have **0 referencers** and do not modify Max* attributes. - Legacy CDO defaults differ per character (Amazonian stamina 85/100; Paladin mana 100/100; both health 0). ### Confirmed evidence | Kind | Evidence | |---|---| | Static | Doc `06` §§2–4 — orphan default GEs; native Init fallback; Max* absent on default GEs | | Runtime | RE-2A1-001/012 — ASC identical for Amazonian and Paladin | | Runtime | RE-2A1-002 — no active default GE at spawn | | Runtime | RE-2A1-011 — CDO explains legacy zeros / character-specific legacy stamina/mana | | Tool limitation | N/A for spawn values (observed) | ### Options compared | Option | Description | Fit to evidence | |---|---|---| | **A. Character-specific default GE** | Pawn/class selects a default GE; server applies after ASC actor info valid | Best fit — assets and `DefaultAttributesGameplayEffect` property already exist | | B. Shared init GE + SetByCaller | One GE; magnitudes passed per class | Viable; fewer assets; more native glue | | C. Native initialization service | Explicit server service sets all six attrs | Viable; strongest fail-visible control; bypasses existing GE assets | | D. Other | e.g. hybrid GE for currents + native Max* | Possible but adds dual paths | ### Proposed rule (Recommendation: Option A) Character defaults are applied on the **authoritative server** only after ASC OwnerActor/AvatarActor are valid. Every character receives **explicit** current and maximum Health, Mana, and Stamina. Stamina may not rely on an uninitialized native default. Initialization must be deterministic on initial spawn and respawn. A missing character default assignment must **fail visibly** (log/assert/fatal in development) rather than silently falling back to identical native Init* values. Existing orphan GEs must be completed (including MaxHealth/MaxMana/MaxStamina) before they are treated as production defaults. Incomplete GEs are migration work, not a license to keep silent Init*. **Alternatives retained:** B, C (Proposed alternatives, not rejected). ### Allowed behavior - Server ApplyGameplayEffect of character default GE after InitAbilityActorInfo. - Explicit Max* and current values in that GE (or immediate companion apply). - Visible failure when class data / GE assignment is missing. ### Prohibited behavior - Silent native-only fallback that leaves all classes at 75/100/25/50/0/0. - Client-authoritative default attribute application. - Relying on uninitialized Stamina ASC as “zero by design” without an explicit assignment. ### Transitional behavior Until GEs are completed, temporary use of Option C for Max* fill is acceptable only if documented as transitional and still fails visibly when class data is missing. ### Dependencies C-001, C-012 (ASC on PlayerState / re-init on possess). ### Migration impact `ARIRPlayerState`, character class data, orphan `GE_*_DefaultAttributes`, spawn and respawn paths, Gunslinger (no GE today). ### Runtime validation required - Per playable: ASC currents and maxes match class policy after spawn and after respawn. - Missing GE assignment produces a visible error in a controlled test. - No active unintended GEs beyond the intended default apply. ### Failure modes - GE overrides current without Max* → clamps/UI break. - Apply before actor info valid → no-op or wrong Owner. - Respawn skips reapply → stale or zeroed attributes. ### Approval question **Do you approve Option A (character-specific default Gameplay Effect applied server-side after ASC actor info is valid), with visible failure on missing assignment and mandatory explicit current+max Health/Mana/Stamina?** --- # C-003 — Resource-access boundary **State:** Proposed ### Problem being solved Gameplay mutates resources through ad-hoc Blueprint variables, `FCanUseMana`, `ApplyDamage`, and GEs without a single authoritative interface. Incremental migration risks two authoritative stores. ### Current implementation - Ability graphs read/write DEPRECATED mana/health/damage floats. - Potions apply ASC GEs via EffectActor. - Overlay reads ASC. - No shared resource API above ASC for costs/affordability. ### Confirmed evidence | Kind | Evidence | |---|---| | Static | Docs `05` resource inventory; `06` legacy/GAS boundary; `07` S9 | | Runtime | RE-2A1-001–005, 012–013 — dual values at spawn | | Runtime | Ability cost mutation path not exercised (RE-2A1-015/019/021 Tool Limitation) | ### Proposed rule New gameplay may not directly read or write DEPRECATED resource variables. Resource reads, affordability checks, costs, restoration, and maximum-value queries use a **shared authoritative interface** that operates on ASC attributes. Cost validation and mutation occur **atomically on the server**. ### Allowed behavior - Server: check affordability → commit cost → proceed, or fail without partial mutation. - Reads of current/max via the shared interface. - Migrated abilities calling the interface instead of DEPRECATED floats. ### Prohibited behavior - New code writing DEPRECATED resource vars as authority. - Client-side cost commitment. - Dual-write of ASC and DEPRECATED as both authoritative. ### Transitional behavior Migrate each dependent path to the interface **before** that path is considered converted. Until conversion, that path may still touch DEPRECATED vars under C-004 constraints, but must not invent a second ASC writer. Prefer converting cost/death/heal writers first. ### Dependencies C-001, C-002, C-004, C-006. ### Migration impact `FCanUseMana`, all DEPRECATED_*ManaCost call sites, RecoverPlayerHealth, Amazonian AnyDamage, future GA costs. ### Runtime validation required - Ability cost reduces ASC Mana once; Overlay updates; legacy shadow (if present) matches. - Failed affordability leaves attributes unchanged. ### Failure modes - Interface bypass leaves stray DEPRECATED writers. - Non-atomic check-then-spend races under replication. ### Approval question **Do you approve a shared server-authoritative ASC resource interface as the only allowed read/write path for new gameplay resource access, with atomic cost validation and mutation?** --- # C-004 — Legacy compatibility policy **State:** Proposed (recommended option C; bidirectional Rejected by Existing Evidence) ### Problem being solved Unconverted legacy readers still exist while ASC is becoming canonical. Bidirectional sync would create competing writers and feedback loops. Legacy writers must not silently overwrite ASC. ### Current implementation No sync code. ASC and DEPRECATED diverge at spawn. Overlay uses ASC; combat vars use legacy. ### Confirmed evidence | Kind | Evidence | |---|---| | Static | Doc `06` — legacy-resource synchronization Missing | | Runtime | RE-2A1-004/005/013 — divergent spawn values | | Inference | Bidirectional sync with Amazonian health=0 and ASC=75 would create writer conflict | ### Options evaluated | Option | Verdict | |---|---| | A. Bidirectional synchronization | **Rejected by Existing Evidence** — competing writers; feedback-loop risk | | B. Legacy→ASC synchronization | Rejected as primary policy — would promote non-authoritative / zeroed legacy into ASC | | **C. ASC→legacy one-way shadow** | **Recommended (Proposed)** for temporary unconverted read-only consumers | | D. No synchronization; migrate each path before use | Preferred when a path can cut over in one change; compatible with C | ### Proposed rule Temporary **one-way ASC→legacy** compatibility shadows are allowed only where an unconverted **read-only** consumer still requires DEPRECATED floats. Legacy **direct writers** must not silently overwrite canonical ASC values. Prefer Option D cutover when feasible. Bidirectional sync is prohibited. ### Allowed behavior - After ASC mutation, optionally push values into DEPRECATED vars for legacy UI/gates not yet migrated. - Document each shadow consumer and remove it when migrated. ### Prohibited behavior - Bidirectional sync. - Legacy AnyDamage / cost writers updating ASC without going through C-003/C-005/C-006. - Indefinite shadow without a migration owner. ### Transitional behavior Shadow is temporary scaffolding during reconstruction. Each shadowed consumer must be listed and retired. ### Dependencies C-001, C-003. ### Migration impact Amazonian AnyDamage, `FCanUseMana` readers, `Server_UpdateHUD` callers, any BP reading DEPRECATED health/mana. ### Runtime validation required - With shadow on: after ASC heal/damage, shadowed legacy matches ASC. - Legacy writer attempt cannot change ASC without shared boundary. ### Failure modes - Forgotten shadow → legacy death on zero. - Accidental reverse write → ASC corrupted. ### Approval question **Do you approve ASC→legacy one-way shadow only for temporary read-only consumers, with bidirectional sync prohibited and legacy writers forbidden from silently overwriting ASC?** --- # C-005 — Damage contract **State:** Proposed (ExecutionCalculation design Deferred) ### Problem being solved Player damage uses `ApplyDamage` into legacy health (Amazonian) or has no enemy consumer. Potions use ASC GEs. There is no single server entry for validated damage. ### Current implementation - Paladin/Amazonian/Cleric UseAbility* / ChargeBox: Authority `ApplyDamage`. - Amazonian `ReceiveAnyDamage` subtracts DEPRECATED_CurrentHealth. - Enemy: no ReceiveAnyDamage / health mutation (Implementation Missing). - No project GameplayEffectExecutionCalculation subclasses. ### Confirmed evidence | Kind | Evidence | |---|---| | Static | Docs `05`, `09`, `06` — ApplyDamage vs missing enemy reception; ASC Health unbridged | | Runtime | RE-2A1-022 — player damage/death path blocked (enemy attack Missing; ability input Tool Limitation) | | Runtime | RE-2A1-027/030 — enemy components present; damage reception not observed | ### Proposed rule One **server-authoritative damage entry boundary** for player and enemy targets: | Step | Owner | |---|---| | Who may request damage | Abilities, overlaps, environmental actors, future AI — as **requests** only | | Who validates | Server damage boundary | | Target validity | Server (alive, damageable, team/filter rules) | | Magnitude calculation | Server (data asset / ability / curve — implementation later) | | Mitigation | Server (block/armor tags — design later) | | Health change | Server writes **ASC Health** via shared resource path | | Instigator / causer | Recorded on the authoritative damage event | | Duplicate prevention | Server dedupe (e.g. ability instance / window / hit ID) | | Death evaluation | Trigger C-007 after Health change | | Legacy ApplyDamage | Transitional **adapter** into this boundary; not a second SoT | **Not chosen now:** final GameplayEffectExecutionCalculation design. Retained as Alternative for later approval if GAS execution is preferred after 2B. ### Allowed behavior - Server-only Health reduction through the boundary. - Transitional ApplyDamage → adapter → ASC. - Presentation multicast after authoritative apply. ### Prohibited behavior - Client-authoritative Health writes. - AnimNotify as sole damage authority without server validation (see C-009/C-010). - Damage that mutates only DEPRECATED health after cutover. ### Transitional behavior Keep Authority-gated UseAbility ApplyDamage call sites temporarily, but route Health mutation into ASC via adapter. Enemy reception remains blocked until Phase 2D implements the consumer under this contract. ### Dependencies C-001, C-003, C-007, C-009. Enemy consumers: Phase 2D. ### Migration impact All ApplyDamage call sites; Amazonian AnyDamage; future enemy inbound damage; block absorb design (Paladin 002). ### Runtime validation required - Controlled damage reduces ASC Health once; Overlay updates; no double apply. - Death triggers at ASC ≤ 0. - **Blocked today:** ability-driven and enemy-driven damage (Tool Limitation / Missing Implementation). ### Failure modes - Adapter forgotten → legacy and ASC diverge again. - No dedupe → double hits from multicast notifies. ### Approval question **Do you approve a single server-authoritative damage entry that writes ASC Health, with legacy ApplyDamage limited to a transitional adapter, and ExecutionCalculation design deferred?** --- # C-006 — Healing and resource restoration contract **State:** Proposed ### Problem being solved Healing exists as Cleric `RecoverPlayerHealth` (legacy) and consumable GEs (ASC). No shared clamp/attribution policy. ### Current implementation - Cleric UseAbility002: Authority heal via DEPRECATED recover interface. - Potions/food: GE Instant/Duration on ASC Health/Mana. - No AttributeSet PostGameplayEffectExecute clamp-to-max. ### Confirmed evidence | Kind | Evidence | |---|---| | Static | Docs `05` Cleric 002; `06` GE inventory; `12` pickups | | Runtime | RE-2A1-018 — consumable overlap not executed (movement/input blocked) | | Runtime | ASC MaxHealth/MaxMana exist; Overlay binds them | ### Proposed rule - Restoration is **server-authoritative**. - Values clamp to the attribute’s Max* unless an approved GE explicitly documents over-resource permission. - Source attribution recorded (instigator, GE class, ability ID). - Gameplay Effects and shared restore services both enter the **same resource boundary** (C-003). - UI updates only by observing replicated ASC changes. - Overheal / over-mana / over-stamina **not permitted** by default. - Consumables use the same boundary (apply GE or service on server). ### Allowed behavior - Server GE heal/mana restore; shared RestoreResource API; clamp to max. - Cosmetic feedback after authoritative change. ### Prohibited behavior - Client-side Health/Mana increases. - Unclamped restores that leave Current > Max without explicit approval. - Healing only DEPRECATED health while ASC remains unchanged. ### Transitional behavior Cleric recover path adapts to ASC via C-003; potions already on ASC remain preferred pattern. ### Dependencies C-001, C-003, C-014 (pickup apply). ### Migration impact Cleric 002, EffectActor GEs, any DEPRECATED recover paths, future HoT/MoT. ### Runtime validation required - Heal at full Health does not exceed MaxHealth. - Potion +25 Health updates ASC and Overlay once. - **Blocked today:** pickup overlap apply (RE-2A1-018). ### Failure modes - Dual heal systems → Overlay shows ASC heal while combat uses legacy. - Missing clamp → invalid Current > Max. ### Approval question **Do you approve server-authoritative restoration through the shared ASC resource boundary, clamping to Max* by default, with consumables and ability heals using the same path?** --- # C-007 — Death contract **State:** Proposed ### Problem being solved Death is evaluated from DEPRECATED health on Amazonian; ASC Health is unused for death. Animation can force enemy `IsDead` false. No idempotent shared death transition. ### Current implementation - Amazonian: AnyDamage → subtract DEPRECATED_CurrentHealth → PlayerDeath if ≤ 0. - Base: PlayerDeath / Client_PlayerDeath / IsDead replicated bool. - Enemy ABP forces IsDead false every update; no damage reception. - `State.Dead` tag Present but Unreferenced. ### Confirmed evidence | Kind | Evidence | |---|---| | Static | Docs `05` Amazonian death; `09` enemy death incomplete; `10` ABP death states | | Runtime | RE-2A1-006 — IsDead false at spawn | | Runtime | RE-2A1-004/013 — legacy health 0 at spawn (death-threshold risk if AnyDamage fires) | | Runtime | RE-2A1-022 — death/respawn not observed | ### Proposed rule - Death is evaluated from **canonical ASC Health**. - Health ≤ 0 is evaluated **authoritatively on the server**. - Death transition is **idempotent** — a player or enemy cannot execute the death transition twice. - Dead state is **replicated**. - Movement, abilities, collision, animation, and interaction respond to **one shared death state**. - Animation does **not** own the authoritative death decision. **Player vs enemy separation:** same Health≤0 evaluation and idempotent dead state; players proceed to C-008 respawn; enemies proceed to destroy/loot/presentation policy (Phase 2D) without player respawn. ### Allowed behavior - Server sets replicated dead state once; cancels abilities; disables input/movement as configured. - ABP reads replicated dead state for Death animation only. ### Prohibited behavior - AnimBP forcing alive over authoritative dead state. - Death decided solely from DEPRECATED health after cutover. - Re-entrant PlayerDeath without guard. ### Transitional behavior Until Amazonian AnyDamage is migrated, treat legacy≤0 as transitional trigger that must also drive ASC Health to 0 / call the shared death entry — not a second SoT. ### Dependencies C-001, C-005, C-008 (players), C-011 (ability cancel on death). ### Migration impact Amazonian AnyDamage, PlayerDeath, enemy death ABP, future tags (`State.Dead`). ### Runtime validation required - Damage to ASC 0 triggers death once; second damage does not re-enter. - ABP plays death from replicated state. - **Blocked today:** RT-006 (RE-2A1-022). ### Failure modes - Legacy health 0 at spawn + AnyDamage → instant death while Overlay shows 75. - Enemy ABP clears IsDead → corpse walks. ### Approval question **Do you approve authoritative, idempotent death evaluated from ASC Health ≤ 0, with animation as presentation-only and player/enemy differing only in post-death lifecycle?** --- # C-008 — Respawn contract **State:** Proposed ### Problem being solved Respawn/HUD recreation paths exist but are unverified. Risk of dying pawn owning its replacement, duplicate overlays, stale widgets, and skipped ASC re-init. ### Current implementation - `Server_RespawnPlayer` / `PlayerRespawn` SpawnActor+Possess paths on base / PC / GM. - Overlay created from `InitAbilityActorInfo` when local HUD present. - Char-select `PlayerFirstSpawn` emits Accessed None warning but still spawns (RE-2A1-010). ### Confirmed evidence | Kind | Evidence | |---|---| | Static | Docs `07` S8; `11` spawn/respawn; `03` PC_Character | | Runtime | RE-2A1-010 — PlayerFirstSpawn Accessed None; spawn still succeeds | | Runtime | RE-2A1-022 — respawn not observed (RT-006 blocked) | ### Proposed rule - **GameMode and PlayerController** own the server-side respawn request and timing. The destroyed/dying pawn must **not** be the sole authority that initiates its replacement. - Ordering: mark dead → cancel abilities (C-011) → schedule respawn delay → destroy or detach old pawn → spawn replacement → **re-Init ASC OwnerActor/AvatarActor** → reapply character defaults (C-002) → Possess → restore input → **idempotent HUD bind** (C-013). - PlayerState persists across pawn replacement. - Duplicate-respawn prevention: ignore respawn requests while already pending or while not dead. ### Allowed behavior - Server GM/PC timer-driven respawn. - Reuse PlayerState ASC; refresh Avatar to new pawn. ### Prohibited behavior - Client-authoritative respawn. - Multiple concurrent respawn schedules for one player. - Skipping default attribute reapplication. ### Transitional behavior Existing `Server_RespawnPlayer` on the pawn may forward a request to PC/GM but must not unilaterally complete the lifecycle without GM/PC ownership. ### Dependencies C-002, C-007, C-012, C-013. ### Migration impact `BP_PlayerCharacterBase` death/respawn, `PC_Character`, `GM_Dungeoneer`, HUD InitOverlay. ### Runtime validation required - One death → one respawn; ASC defaults restored; Overlay instance count stable; input restored. - **Blocked today:** RE-2A1-022. ### Failure modes - Double Overlay; stale widget bound to destroyed pawn; ASC Avatar still old pawn; spawn warning becomes hard failure. ### Approval question **Do you approve GameMode + PlayerController ownership of server respawn lifecycle (pawn must not solely replace itself), including ASC re-init, default reapplication, possession, input restore, and idempotent HUD bind?** --- # C-009 — Authority contract **State:** Proposed ### Problem being solved Legacy gameplay timing depends on Multicast montage AnimNotify evaluation. Interrupt and server/client notify roles are unverified. Clients must submit intent only. ### Current implementation ``` Input → Server_Ability_* → Multicast_PlayMontage → AnimNotify → UseAbility* (Authority gate) / SetIsAttacking ``` Montage OnCompleted/OnBlendOut/OnInterrupted pins unwired. Cleanup often via `AN_AttackComplete`. ### Confirmed evidence | Kind | Evidence | |---|---| | Static | Docs `05`, `10` — notify-driven gameplay; Authority Switch inside UseAbility*; Networking Risk | | Runtime | RE-2A1-015/019/021 — ability chain not executed (Enhanced Input Tool Limitation) | | Runtime | RE-2A1-023–026 — two-client replication not run | ### Proposed rule - Clients submit **intent**. - Server validates state, target, resource cost, cooldown, and gameplay result. - Multicast events are **presentation-only** unless a narrowly documented exception is later approved. - Client or multicast animation evaluation **cannot be the sole authority** for damage, healing, spawning, costs, or state transitions. - Replicated state is written only by its authoritative owner. ### Allowed behavior - Server RPC intent → server commit → replicate state → multicast montage/SFX/VFX. - Server-owned timing windows that *correlate* with animation (C-010) without requiring notify-as-authority. ### Prohibited behavior - Gameplay results that only occur if a multicast notify runs. - Client writing Health/Mana/IsDead/CurrentlyAttacking as authority. ### Transitional behavior Legacy notify→UseAbility Authority bodies may remain temporarily but must be treated as **technical debt**. Migration moves hit commit to server Ability Tasks / validated windows. Document each remaining notify gameplay call site. ### Dependencies C-003, C-005, C-006, C-010, C-011. ### Migration impact All Server_Ability / Multicast_PlayMontage / AN_Ability_* paths; Phase 2B framework. ### Runtime validation required - Listen-server + client: damage once on server; montage on both; no client-only Health change. - **Blocked today:** Enhanced Input + multi-client PIE (RE-2A1-015, 023). ### Failure modes - Server skips montage evaluation → missed hits under legacy design. - Interrupt skips AN_AttackComplete → stuck CurrentlyAttacking. ### Approval question **Do you approve client-intent / server-validation authority, with multicast limited to presentation, and AnimNotify forbidden as sole authority for damage, costs, or state transitions?** --- # C-010 — Animation responsibility contract **State:** Proposed ### Problem being solved Animation currently gates hit windows and attack lockout cleanup. Need a clear cosmetic vs authoritative split while preserving timing feel. ### Current implementation AN_Ability_* triggers UseAbility*; AN_AttackComplete clears CurrentlyAttacking; ABPs read IsDead/IsBlocking/etc. for presentation. ### Confirmed evidence | Kind | Evidence | |---|---| | Static | Doc `10` shared animation→ability architecture | | Runtime | Notify chain not exercised (RE-2A1-019/021) | ### Proposed rule **Animation may own:** - Visual playback - Sound timing - Cosmetic Niagara timing - Camera presentation - Cosmetic weapon-trail windows **Animation may not solely own:** - Authoritative damage - Cost commitment - Target validation - Death - Respawn - Guaranteed ability cleanup **Timing correlation:** Server (or server Ability Task) may open/close validated hit windows using durations/sections that match montage timing. Cosmetic notifies may fire predicted VFX. Authoritative commit remains server-side even if a notify is skipped. ### Allowed behavior - Montage playback from server-triggered multicast. - Cosmetic notifies. - Server tasks waiting on montage events as *hints* with failsafe timeouts (C-011). ### Prohibited behavior - Sole reliance on AN_AttackComplete for cleanup. - Damage that only applies inside a multicast notify without prior/server validation path. ### Transitional behavior Existing notify gameplay remains until Phase 2B replaces it under C-009/C-011. ### Dependencies C-009, C-011, C-007. ### Migration impact AN_Ability_001–004, AN_AttackComplete, Multicast_PlayMontage pins, character ABPs. ### Runtime validation required - Interrupt mid-montage still cleans ability state without AN_AttackComplete. - **Blocked today:** RE-2A1-020. ### Failure modes - Cosmetic-only migration that still requires notify for damage. - Desynced VFX vs server hit window (acceptable if documented; damage must still be correct). ### Approval question **Do you approve animation as cosmetic-only for authority purposes, with server-owned timing correlation allowed, and notify-driven authoritative gameplay prohibited as the end state?** --- # C-011 — Ability lifecycle and cleanup contract **State:** Proposed ### Problem being solved Most Server_Ability_*_End bodies are empty. Cleanup depends on AN_AttackComplete. Interrupt may leave CurrentlyAttacking stuck. ### Current implementation Gates on CurrentlyAttacking/IsDead; Ends mostly empty; AN_AttackComplete clears attacking; montage interrupt pins unwired. ### Confirmed evidence | Kind | Evidence | |---|---| | Static | Docs `05`, `07` S3/S12, `10` | | Runtime | RE-2A1-020 — interrupt test blocked | ### Proposed rule Shared lifecycle states: `Requested → Validated → Committed → Active → Ending → Completed | Canceled | Interrupted | Failed` | Event | Required behavior | |---|---| | Resource commitment | On Validated→Committed; atomic (C-003) | | Cooldown commitment | On Commit (when cooldowns exist) | | Montage start failure | → Failed; release commit if policy requires; clear attacking | | Normal completion | → Completed; clear locks; EndAbility equivalent | | Input release | Route to Ending/Canceled per ability policy | | Interruption | → Interrupted; **guaranteed** cleanup without AN_AttackComplete | | Death during ability | Cancel → Interrupted/Canceled; C-007 | | Pawn destruction | Force cleanup; no dangling timers | | Target invalidation | End or fail per ability; no further damage commits | | Timeout / failsafe | Absolute cleanup timer independent of montage | **No ability may depend solely on AN_AttackComplete for guaranteed state cleanup.** ### Allowed behavior - Explicit EndAbility / cancel tags / Ability Task end states. - Failsafe timers. ### Prohibited behavior - Cleanup only via montage end notify. - Leaving CurrentlyAttacking true after interrupt/death. ### Transitional behavior Wire montage OnInterrupted/OnBlendOut **or** native failsafe while notifies remain. ### Dependencies C-003, C-007, C-008, C-009, C-010. ### Migration impact All playable ability Begin/End/UseAbility paths; Phase 2B shared framework. ### Runtime validation required - Full montage: lockout clears. - Interrupt: lockout clears without AN_AttackComplete. - Death mid-ability: cleanup + no further damage. - **Blocked today:** RE-2A1-019–022. ### Failure modes - Stuck attack lockout; orphan timers; double cost on retry. ### Approval question **Do you approve the shared ability lifecycle states and the rule that cleanup must be guaranteed without sole dependence on AN_AttackComplete?** --- # C-012 — PlayerState and pawn ownership contract **State:** Proposed ### Problem being solved Need clear persistent vs transient ownership across respawn. Enemy ASC ownership differs and GetASC via PlayerState returns nullptr for enemies. ### Current implementation - Players: ASC + AttributeSet on `ARIRPlayerState`; InitAbilityActorInfo Owner=PS, Avatar=Character on PossessedBy / OnRep_PlayerState. - Enemies: ASC on self; InitAbilityActorInfo(this,this); interface GetASC → PlayerState → nullptr. ### Confirmed evidence | Kind | Evidence | |---|---| | Static | Doc `06` ownership detail; `09` enemy GetASC defect | | Runtime | RE-2A1-007 — PS ASC; pawn query resolves same set | | Runtime | RE-2A1-027/028 — enemy ASC components present; inspector rejects actor (Tool Limitation / possible init gap) | ### Proposed rule **PlayerState owns:** - Persistent player ASC - Persistent AttributeSet - Cross-pawn player state intended to survive respawn **Pawn owns:** - Avatar representation - Movement - Equipment components - Transient physical state - Animation - Pawn-specific targeting and presentation **On possession / pawn replacement:** re-InitAbilityActorInfo; bind Overlay if local; teardown transient pawn state on old pawn. **Enemies** keep self-owned ASC with a separate init/accessor contract (fix GetASC for non-PlayerState owners in Phase 2D/2E). ### Allowed behavior - Cache ASC pointer on pawn from PlayerState. - Persistent attributes survive pawn destroy. ### Prohibited behavior - Moving player ASC to pawn without an approved redesign. - Expecting enemy GetASC-via-PlayerState to succeed. ### Transitional behavior Keep current player PS ownership. Document enemy accessor as Existing Baseline Defect until fixed under this contract’s enemy clause. ### Dependencies C-002, C-008, C-013. ### Migration impact `ARIRPlayerCharacter`, `ARIRPlayerState`, enemy GetASC, EffectActor targeting. ### Runtime validation required - After respawn: OwnerActor still PlayerState; Avatar is new pawn; attributes persist then defaults reapplied per C-002. - Enemy ASC readable via corrected accessor (deferred). - Tool inaccessibility ≠ runtime absence (RE-2A1-028). ### Failure modes - Avatar not updated → abilities target wrong actor. - Enemy potions destroy without apply (nullptr ASC). ### Approval question **Do you approve keeping player ASC/AttributeSet on PlayerState with pawn as Avatar only, and treating enemy self-ASC as a separate ownership/init contract?** --- # C-013 — HUD data-flow contract **State:** Proposed ### Problem being solved Dual HUD paths: Overlay (ASC) works structurally; legacy `UpdatePlayerHUD` unimplemented. Respawn may recreate overlays. Stamina UI missing. ### Current implementation - `ARIRHUD::InitOverlay` → OverlayWidgetController → Health/Mana bars. - `Server_UpdateHUD` → `UpdatePlayerHUD` unimplemented on PC. - No stamina widget. ### Confirmed evidence | Kind | Evidence | |---|---| | Static | Docs `11`, `06`, `07` S10 | | Runtime | RE-2A1-008/009 — Overlay bars present; WBP_PlayerHUD spawned; no stamina widget | | Runtime | Respawn Overlay duplication not observed (RT-006 blocked) | ### Proposed rule - Gameplay HUD reads ASC attributes through the Overlay / widget-controller path. - Legacy `UpdatePlayerHUD` route is **retired** (remove or leave dead; do not implement as second SoT). - No UI independently stores authoritative resources. - HUD creation is **idempotent**. - Respawn and travel must not create duplicate overlays. - Stamina presentation is added **only after** C-001/C-002 are approved. - UI reflects replicated authoritative state and does **not** drive gameplay state. ### Allowed behavior - Rebind existing Overlay to new pawn/ASC avatar on respawn. - Progress bars from attribute delegates. ### Prohibited behavior - Implementing UpdatePlayerHUD as a parallel authoritative HUD. - UI writing Health/Mana. - Unconditional InitOverlay without duplicate guard. ### Transitional behavior Leave unimplemented UpdatePlayerHUD as dead code until removal; do not repair it. ### Dependencies C-001, C-002, C-008, C-012. ### Migration impact `RIRHUD`, Overlay widgets, BPI_PlayerController UpdatePlayerHUD, Server_UpdateHUD callers. ### Runtime validation required - One Overlay after spawn and after respawn. - Bars track ASC only. - **Blocked:** respawn path (RE-2A1-022). ### Failure modes - Duplicate overlays; stale bar bound to destroyed pawn; stamina UI before SoT approval. ### Approval question **Do you approve Overlay/widget-controller as the sole gameplay HUD data path, retirement of UpdatePlayerHUD, idempotent HUD creation, and deferred stamina UI until attribute contracts are approved?** --- # C-014 — Pickup authority and replication contract **State:** Proposed ### Problem being solved EffectActor pickups have no authority gate and `bReplicates=false`, risking desync and duplicate apply. Overlap apply not runtime-proven. ### Current implementation Overlap → ApplyEffectToTarget → DestroyActor; no SwitchHasAuthority; bReplicates=false; destroy even if ASC null. ### Confirmed evidence | Kind | Evidence | |---|---| | Static | Doc `12` Authority Risk matrix | | Runtime | RE-2A1-017 — HealthPotion `bReplicates=false` | | Runtime | RE-2A1-016 — pickups present in Test01 | | Runtime | RE-2A1-018 — overlap/GE apply not executed | ### Proposed rule - Server owns overlap validation. - Server applies the effect or mutation. - Server destroys or deactivates the pickup. - All clients receive a **consistent pickup-existence** state. - A pickup applies **at most once** per valid collection. - Cosmetic presentation may occur on clients **after** authoritative collection. - Non-replicated pickups must **not** be used for network gameplay without an explicit server-owned spawning/visibility model. ### Allowed behavior - Replicated pickup actors; server authority gate; server GE apply; server destroy. - SP prototype with documented non-replicated model only if never used in MP as-is. ### Prohibited behavior - Client-only destroy/apply for MP pickups. - Relying on `bReplicates=false` EffectActors for listen-server gameplay. ### Transitional behavior SP Test01 may keep current actors until 2E reconstruction, but they are classified Authority Risk and must not be treated as MP-correct. ### Dependencies C-003, C-006, C-012 (GetASC for enemies). ### Migration impact Four EffectActor pickups; gold path (separate AddGold defect); Phase 2E. ### Runtime validation required - Server apply once; ASC changes; actor gone on all clients. - **Blocked today:** movement/input and 2P (RE-2A1-018, 023, 026). ### Failure modes - Double GE apply; client destroy without server apply; enemy touch destroys without heal. ### Approval question **Do you approve server-owned pickup validation/apply/destroy with replicated existence, at-most-once collection, and a ban on non-replicated pickups for network gameplay without an explicit server visibility model?** --- # C-015 — Runtime observability contract **State:** Proposed ### Problem being solved Reconstruction needs inspectable evidence. Phase 2A1 showed tool gaps (Enhanced Input, multi-client, enemy ASC inspector). Observability must be defined without requiring permanent debug UI yet. ### Current implementation Ad-hoc MCP/ObjectTools/AbilitySystemInspector during Phase 2A1; no project harness. ### Confirmed evidence | Kind | Evidence | |---|---| | Runtime | Tool limitations RE-2A1-015, 023, 028, 031 | | Inference | Without logs/harness, C-005–C-011/C-014 cannot close | ### Proposed rule Before reconstruction claims are trusted, the following must be inspectable via logs, debugger, Ability System inspection, or a future temporary test harness: - Character identity - ASC OwnerActor and AvatarActor - Current/max attributes - Active Gameplay Effects - Granted abilities - Ability lifecycle state - Authoritative damage events - Death transitions - Respawn transitions - Pickup application count - Network role Permanent debug UI is **not** required yet. ### Allowed behavior - Structured log categories; temporary console/cheats in development builds; automation hooks. ### Prohibited behavior - Treating tool inaccessibility as proof of runtime absence. - Shipping permanent debug HUD as a substitute for contracts. ### Transitional behavior Use manual PIE + logging until harness exists; environment decisions for 2-client PIE and Enhanced Input remain open (see `02`). ### Dependencies All contracts for validation; harness work may be Phase 2A3 planning. ### Migration impact Logging helpers; future test harness; no gameplay SoT change. ### Runtime validation required - Each listed field obtainable in a controlled session for player pawn; enemy attributes once accessor fixed. ### Failure modes - False “missing ASC” from inspector limits; unverifiable MP claims. ### Approval question **Do you approve the minimum observability list above as a prerequisite for trusting reconstruction, without requiring permanent debug UI yet?** --- # Architectural recommendation summary ## 1. Recommended canonical architecture ASC attributes on PlayerState are the sole resource SoT. Character default GEs initialize explicit current+max H/M/S on the server after actor info is valid. All gameplay resource mutation flows through a shared server interface. Damage and healing write ASC through one authoritative boundary. Death evaluates ASC Health ≤ 0 idempotently. GameMode/PC own respawn. HUD reads Overlay/ASC only. Abilities use client intent → server validate → presentation multicast, with server-owned lifecycle/cleanup. Enemies and pickups consume the same damage/resource rules under later phases. ## 2. Transitional architecture - ASC→legacy one-way shadow for unconverted read-only consumers. - ApplyDamage adapter into ASC damage boundary. - Notify-timed UseAbility retained as debt until Ability Tasks / validated windows. - SP non-replicated pickups tolerated only as known Authority Risk until 2E. ## 3. Prohibited transitional patterns - Bidirectional ASC↔legacy sync - Legacy writers silently overwriting ASC - Multicast AnimNotify as sole gameplay authority - Silent native Init* fallback hiding missing character defaults - Non-replicated pickups used as-is for network gameplay - Implementing UpdatePlayerHUD as a second resource SoT - Treating tool limitation as runtime absence ## 4. Decisions requiring owner approval All C-001 through C-015 approval questions above. None are Approved in this pass. ## 5. Decisions blocked by runtime evidence | Area | Blocking evidence | Related contracts | |---|---|---| | Enhanced Input ability execution | RE-2A1-015/019/021 | C-009, C-010, C-011 | | AnimNotify authority roles | Not observed | C-009, C-010 | | Ability cost mutation | Not observed; Ability004 cost CDO=0 | C-003, C-004 | | Ability interruption | RE-2A1-020 | C-011 | | Player damage/death/respawn | RE-2A1-022 | C-005, C-007, C-008 | | Two-client replication | RE-2A1-023–026 | C-009, C-014 | | Remote character selection | Not run (needs 2P) | C-008 related / 2E | | Pickup authority and visibility | RE-2A1-018 | C-014 | | Enemy attribute mutation | RE-2A1-028/030 | C-005, C-012 | | Session behavior | Deferred to 2E; not in 2A1 matrices | Outside 2A2a contracts | ## 6. Phase 2A3 implementation-planning prerequisites 1. Owner review of Proposed contracts (still no Approved stamp until explicitly granted). 2. Plan for remaining blocked runtime evidence (input harness, 2-client PIE authorization, controlled damage actor if approved). 3. Migration sequencing: C-001/C-002/C-003/C-004 → C-005/C-006/C-007 → C-008/C-013 → C-009–C-011 → C-014 with 2E. 4. Observability harness outline per C-015. 5. Explicit non-goals: no Phase 2B ability rewrite; no Unreal edits in 2A2a. ## Dependency diagram ```mermaid flowchart TD attrs[CanonicalAttributes_C001_C002] resource[SharedResourceBoundary_C003_C004] dmgHeal[DamageHealing_C005_C006] death[Death_C007] respawn[Respawn_C008] hud[HUD_C013] ability[AbilityLifecycle_C009_C010_C011] migrate[CharacterMigration] enemy[EnemyReconstruction] pickups[Pickups_C014] observe[Observability_C015] attrs --> resource resource --> dmgHeal dmgHeal --> death death --> respawn resource --> hud respawn --> hud resource --> ability ability --> migrate dmgHeal --> enemy death --> enemy resource --> pickups observe -.-> attrs observe -.-> dmgHeal observe -.-> ability observe -.-> pickups ``` ## Integrity statement This document is Markdown-only architecture design. No Unreal assets, source, configuration, plugins, or maps were modified. No Unreal MCP or PIE was used in Phase 2A2a. No contract is Approved.