Combat, weapons, targeting and ability state¶
Status: This is a dated source and behavior baseline, not a current implementation map. References to AbilityHolder, Ability assets or planned compatibility bridges describe the earlier system. Use the roadmap and current source for remaining work; preserve relevant behavior when tracing abilities.
R0 contract, 2026-10-26, batch 29. This extends player capabilities, run/bootstrap and player/input. The rebuild plan still gates implementation. Preserve one/two-player mechanics, authored values, timing, trigger order, random calls and feedback. Four-slot device assignment/remapping is approved scope; new attacks, balance and placeholder effects are not.
Design refinement, 2026-10-28: the ability-module contract traces shields/views, conditional stats, time/count meters, carriers/summons, ordered trigger stages, child-attack inheritance, acquisition/evolution/pickups and HUD identity. Its 101-type reference index is lexical discovery, not runtime acceptance. Distinct ability behaviors receive focused runtime implementations; explicit capability/attack services preserve ownership and interactions. This refines R4a/b/c without moving concrete skills ahead of their remaining R3 dependencies or closing CA-01–CA-05.
Reference: the reviewed working files saved in checkpoint 93d92282, on codex/checkpoint-stabilization-and-r0-20261026. At contract creation, the active checkout was still dev-0.9.0-bootloader at 5347e460 because its nonempty index lock was preserved. Subsequent owner-requested local alignment/recovery is recorded in status. Neither revision is certified as the Steam build. Batch 29 changes documentation only and does not run Unity.
Current ability ownership · batch 57¶
Follow-on batch 58 now connects assigned dash commands, stamina/immunity ticks and scoped dash/weapon cleanup in the development actor. See the capability composition boundary. Concrete perk bodies, shields/counters, weapon/companion execution and complete combat still require migration; the batch-57 evidence below describes its earlier ownership prerequisite.
Batch 57, implementation ef1440f2, introduces PlayerAbilityRuntime and PlayerAbilityHost. The run participant opts in while preparing an inactive actor; the development launcher enables it. Default production scenes and non-opted-in factory callers retain legacy ownership. This is a prerequisite for R3 composition and a partial R4a slice, not completed AbilityHolder migration.
Each owner has a stable player/run identity and private Ability copies. Definitions and their GUIDs remain unchanged. Copies retain the old Ability-shaped fields as a temporary compatibility bridge: AbilityHolder's list points at the owner's entries. Reacquiring the same definition within one player appends the same private copy and resets its cooldown fields; distinct definition objects sharing a type remain distinct, with first-match admission preserved. Separate players never share these copies. Execution rejects raw/foreign definitions inserted through the compatibility list. Selected character abilities are acquired before final stat projection in the opt-in path; automatic character effects are not executed by acquisition alone.
Owned work includes admission/display timers and explicitly submitted effect iterators, including nested IEnumerators. Replacement is scoped by player, ability copy and operation, including delegate target. Disable, run cancellation and disposal retire work; disposal destroys copies even if cleanup fails. Acquisitions survive suspension/re-enable, but stopped work does not resume. Life/revive policy still owns flag resets. Effects must release their own temporary mutations in iterator cleanup; this scope cannot undo arbitrary writes or absorb global/ad hoc coroutines and native Coroutine handles started outside it. Unity-thread access remains required.
AbilityCooldownCycle shares the original admission/display arithmetic between legacy AbilityFunction and the new owner. It preserves the initial scaled 0.5-second wait, subsequent live cooldown read, separate 0.1-step display and float/overlap quirks. Sixteen original iterator traces match; this is not a normalized timer or measured wall-clock equivalence. Fourteen ownership groups, shared-scene release/failure checks, seven character definition/weapon handoffs and launcher retry/disposal pass headlessly. Dash input, counters/shields, concrete character/perk bodies, UI readers and service adapters remain to migrate. Sword/orb/Zenova effects and full combat have not been qualified by these handoff checks.
Evidence and limits¶
- Ability definitions: 121 authored Ability assets, interpreted against all 101 current enum members. There are 124 rows because JetCrash, Quartet and Quintet have no matching Ability asset. Raw cooldown/cost/runtime fields, direct boot-character/upgrade references and serialized GUID-reference file counts are recorded. A shared enum type is not a unique asset identity.
- Upgrade routes: all 177 Upgrade assets, raw numeric effect arrays interpreted using the current enum, direct membership in Bootloader's 95 special/50 basic lists and selected import fields. Membership establishes a catalog route, not that stage, unlock, weight, prerequisite and reward selection permit acquisition. Missing serialized fields are labelled, without guessing Unity defaults.
- Source references: 56 lexical category rows across 35 scripts. Includes declarations, Tutorial, Editor and consumer candidates; it is not a compiled call graph.
- Bindings: 96 combat-component records in scene/prefab files, 88 direct and eight stripped inherited references. Includes recovery/prototype content. Direct top-level fields are evidence, not a resolved prefab instance: nested lists, fixed modifiers, inheritance and instance overrides still require import validation.
- Persistent calls: 428 method-name matches for 28 WeaponEvoData methods, with serialized target/type and line. Validate target identity, enabled scene, invocation and dynamic arguments before replacing callbacks. The scan finds no StarBurstShield/StarBurstShieldActivator persistent method name.
- Comparison cases: source-derived cases to execute during implementation; none is a passed runtime test.
The serialized scan covers 1,256 .unity/.prefab/.asset files. Focused review covers PlayerWeapon, PlayerAttack, PlayerAttackCarrier, AbilityHolder, AbilityFunction, Ability/AbilityPanel/AbilityResources, Companion and its drone/sword/orb combat paths, CircularWeapon/Rotator, weapon-evolution adapters, Player target queries and Enemy damage/mark/bounce hooks. Companion movement curves, every upgrade combination and scene reachability are not fully verified. These maps supplement the existing whole-file inventory; its original review-depth counts remain historical.
Owners and extraction decisions¶
Names below describe proposed responsibilities, not newly implemented classes.
| Owner | Authority and lifetime | Current source disposition |
|---|---|---|
| Combat definitions | Stable asset/content identity, base weapon/projectile/ability values and explicit effect configuration. No live cooldowns, owner pointers or counters. | Retain authored data and GUIDs; migrate Ability's runtime fields out. Do not reorder enum ordinals or repair old assets by filename. |
| Per-player ability set | Acquired definitions and individual execution state, keyed by run generation, stable player slot and ability-instance identity. Cooldown/admission, charges, combo counters, shields, temporary bonuses and owned work live here. | Replace AbilityHolder's mixed authority and AbilityFunction's global execution state in slices; retain temporary adapters for existing callers until migrated. Do not merge distinct NoRefereces assets or silently change first-match-by-type/duplicate-acquisition behavior. |
| Per-weapon executor | Bound player/stats, selected projectile, ammo, reload and attack timers, fixed modifiers and attack admission. One instance per main/extra weapon. | Extract PlayerWeapon's simulation from aim visuals/audio/UI; retain exact formulas and hook order. Evolution-created mechanical arms use this same lifecycle. |
| Attack execution | Immutable origin identity plus explicitly timed values: attacker/credit source, attack source, kind, damage, amplification, flags, hit budget, target and motion. Child attacks inherit only the properties declared by their source route. | Replace ad hoc PlayerAttack/Carrier initialization with prepare-before-activate. Retain existing collision/homing/delay policies until compared. Do not rerun weapon procs automatically for every child attack. |
| Target service | Registry of active enemy identities and hit points; separate query policies for player weapons, companions, bounce and homing. Returns validity/generation-aware handles. | Extract Player's lists and Companion/Enemy searches behind named policies. A common registry must not impose one shared ranking policy. |
| Companion instance | Default owner, current master, combat cadence, target/orbit state, child attacks and lifetime. | Retain sword/orb/drone distinctions; move binding/reset out of Start-only assumptions. Drone master switching is distinct from sword/orb death handling. |
| Presentation adapters | Consume player/ability/weapon state and emitted feedback events; no gameplay inferred from visual active state or list position. | Replace AbilityPanel's asset/list-index polling and PlayerWeapon UI writes. Retain art/audio/config references from AbilityResources and current timing. |
| Upgrade/evolution adapters | Resolve selected player and ordered stat/ability/weapon operations through the above owners. | Retain current UpgradeFunction/WeaponEvoData callback names and signatures until all serialized targets migrate. Retire bridges only after source and serialized consumers are verified. |
The player-capability contract remains authoritative for stat projection, incoming player damage, resource mutation, death and revive. Combat hooks call that boundary with their original reason/order; they do not turn all health decreases into enemy damage. Run disposal cancels owned work and invalidates targets before references can affect the next run.
Existing weapon sequence to preserve¶
PlayerWeapon.Update runs UIUpdate, HandAimCursor, WeaponTimer, then CheckReadyFireWeapon. Separate component ordering against PlayerModifier.Calculate remains unproven. Start sets ammo to one, while setup and modifier initialization also write ammo; explicit readiness must replace that race after first-frame characterization.
WeaponTimer starts ranged reload when ammo is below one and not already reloading, decreases ReloadTimer while reloading, and always decreases AttackSpeedCounter by scaled deltaTime. Reload snapshots finalReloadSpeed / fixedModifier.reloadModifier, activates ReloadShield/audio/bar, waits that scaled duration, then refills int(live finalWeaponAmmo * fixedModifier.ammoModifier). A mid-reload stat/Frenzy change does not recompute the captured wait. UI currently divides ReloadTimer by finalReloadSpeed * (SoldierIsFrenzy ? 2 : 1), which differs from the reload wait. Preserve evidence of that disagreement; aligning them is an explicit bug disposition.
Admission rejects dash/pause, absent target and distance-to-hitpoint minus hitpoint-size exceeding finalAttackRange. StarBurst charges while stationary below four at deltaTime/finalAttackSpeed, only after those target/range checks. SkyYingSword and AbyssOrb skip ordinary weapon firing. Otherwise a ready target/counter fires; ranged ammo is checked/spent first. There is no manual-fire feature in this contract.
FireWeapon first triggers Shoot/audio, then ProtoSword, NeoSword, LusterBurst, GroundBreaker and StarBurst projectile selection; CCombo, Assassination, BerserkerBlood, SureFire, UnsteadyHand, BloodThirst and Rebuke hooks follow in source order. FireWeapon(false) returns after these hooks, before projectile spawning and attack-counter reset. Sword/orb callers rely on that path. Several fixedModifier ignore fields are not consulted at every similarly named hook; retain actual guards rather than implementing policy from field names.
For an ordinary shot, spawn the main attack, then Multishoot's two extra directions (±10 degrees, or ±30 for ProtoBarrier), then reset AttackSpeedCounter to finalAttackSpeed/fixed attackSpeedModifier. Multishoot spends one admission ammo, while each SpawnAttack independently invokes AttackModify and its random/proc side effects. Direct attacks spawn at the target point; extra direct attacks add the existing random offset. RotateSprite's random rotation happens before AttackModify.
AttackModify's ordered work is:
- Assign Player; conditionally set effect flags; roll VampireBE, then BloodThirst; set character flags and SpellAmp.
- Roll CImpact when eligible, then always roll critical chance. Crit eligibility also includes SuddenDeath, MinerAssuredCritCount <= 1, CImpactProc and Rebuke. On crit, reset SureFire/miner counters, trigger GroundBreaker crit work, then FatalFK growth/random reduction, piercing and CImpact data/stun hooks.
- Base damage is finalDamage × unsteadyModifier × fixed damageModifier; crit adds that value × finalCritDamage/100. Apply SoulWager's currentHP/4 addition, its separate type check and conditional HP gamble; then DoubleEdge ×1.6 and Multishoot ×0.3.
- StarBurst applies charge scaling and hit-budget bonus. Active LusterBurst replaces damage/type; otherwise its pierce roll occurs. Active GroundBreaker then replaces damage/type again. NeoSword combo color is presentation at the tail.
Do not combine those stages into one commutative multiplier sum. SoulWager's type test runs after the crit branch reset MinerAssuredCritCount and excludes some crit conditions; its HP change is a direct cost/heal with integer truncation, not TakeDamage. Temporary stat changes are read at their existing calculation point, which may still be a previously projected stat value. Preserve random overloads, endpoints, eligibility and ordering, including visual random calls that share Unity's global generator.
Character-specific attack preservation¶
Owner recollection, 2026-10-27: characters can have unique capabilities and attack outputs. In particular, Wu Ran and Tiamra appear to use ornamental held weapons while other entities perform their attacks; Zenova also requires special handling. Existing weapon-sequence and summons notes above partly covered this. Source inspection confirms the following routes; this is not new runtime verification or permission to change their behavior.
| Character / authored identity | Current attack route | Preserve when modifying shared code |
|---|---|---|
Wu Ran · CELESTIAL / Celestial.asset |
With SkyYingSword, PlayerWeapon skips ordinary firing. AbilityHolder initially creates one Yin sword and assigns its player and targeting priority. CompanionSword spawns the hit attack, calls the owner's weapon AttackModify, and halves damage when targetingPriority > 0. Its return cycle calls FireWeapon(false) for weapon/ability hooks. Yang swords and marking/lightning are additional ability paths. | Keep the held weapon's authored stat/modifier role, sword counts/priorities, live attack-speed/range dependence, travel/return cadence, hit attribution and hook timing. A generic held-weapon shot must not replace the companion or fire in addition to it. |
Tiamra · PRIESTESS / Priestess.asset |
With AbyssOrb, PlayerWeapon skips ordinary firing. AbilityHolder initially creates two owned orbs. CompanionOrb uses player stats for orbit motion; enemy trigger entry creates the hit attack via weapon AttackModify, may spawn a water volley, then calls FireWeapon(false). Splash attacks run AttackModify before replacing damage with 1 + finalBonusSkillAmp/8 and type MAGIC. | Keep contact-driven hits, orbit/count/spacing behavior, live stat dependencies, multishot expansion, water-volley chance/count and ordered modifier/proc side effects. Do not turn these into ordinary gun shots, an attack-speed timer for contact hits, or a one-time stat copy. |
Zenova · STARWANDERER / StarWanderer.asset |
The held gun has its own projectile path. When StarBurst is present, stationary charge depends on Player.Speed == 0, target/range admission and deltaTime/finalAttackSpeed; full charge changes projectile/speed and attack damage/hit budget. RocketBarrage separately spawns attributed homing carriers, with volley count from finalWeaponAmmo/4 and damage from skill amplification. | Preserve movement-sensitive charge, admission/reset order, projectile selection, modifiers and missile timing/target/attribution. Do not treat every Zenova output as an ordinary shot or assume charge exists without its ability. |
The held weapon can be visually ornamental as an attack origin and still be required gameplay data/behavior. Both Wu Ran's and Tiamra's held-weapon prefabs currently have null default/secondary projectiles, non-ranged mode and zero ammo. Those values are not sufficient evidence of broken or unused content. Their companions read the owning player's projected stats and reuse PlayerWeapon.AttackModify/FireWeapon(false); values are not simply transferred once at spawn. Preserve those dependencies until equivalent explicit stat, attack-modifier and hook owners replace them. Never delete the held weapon component or require every weapon to have a projectile solely to standardize character assembly.
This applies during R3 stats/movement/life work as well as R4 weapon/AbilityHolder migration. For every affected character, trace authored definition → stat sources → activation owner → executing entity → attack modifiers/hooks → damage attribution, including death/revive/pool/reset. These three are required comparison cases, not an exhaustive list of exceptions; inspect all affected catalog characters before changing shared assumptions. Reuse the existing authored baselines and combat maps rather than creating a parallel catalog.
Focused checks during implementation must distinguish the actual damage source, avoid duplicate ordinary firing, verify upgrades reach the correct owned entity and preserve per-player state. Cover stat changes after companion spawn, character-specific movement/attack-speed effects, proc ordering, and cancellation/death/revive/reset. Full end-to-end character qualification remains in the later integration campaign under the grouped workflow.
Source anchors: PlayerWeapon CheckReadyFireWeapon/FireWeapon/AttackModify; AbilityHolder (historical script) PlayerSettingsAbilityFirstTime, sword/orb spawns and RocketBarrage; CompanionSword; CompanionOrb; held prefabs Wu Ran, Tiamra and Zenova.
Current R3 integration: batch 55's damage/life boundaries establish ordered damage stages and actor-owned revive sequencing. Character effects remain in LegacyPlayerDamageHooks until R4 replaces their state/service callers. Source argument preservation does not silently correct old reflection attribution or change status delivery after blocked damage. Full ability execution and run-lifetime acceptance remain open.
Batch 56 also delegates the existing Dash coroutine to a Player-owned executor. LegacyPlayerDashHooks preserves perk ordering, character/pause/service reads and weapon hiding; shared Ability cooldowns and the global worker lifetime remain R4 work. Actor execution cancellation prevents stale body-phase completion, without claiming all perk/effect timers have migrated. See the capability boundary.
Ability timing, state and hooks¶
AbilityFunction.AddAbility currently appends the same asset and resets its cooldown state. UseAbility finds the first matching type; absent/on-cooldown calls return, bypass skips admission/timer, and execution starts on AbilityFunction's MonoBehaviour. This can outlive the actor's own coroutine lifecycle. The coroutine-worker key is delegate.ToString plus ability.ToString, with no explicit run/player key and no completion-based removal. Do not carry that ownership model into the rebuild.
CooldownTimer sets isOnCooldown, starts a separate visible countdown, waits 0.5 scaled seconds then (cooldownTime - 0.5) * modifier, and clears admission. Visible time starts from cooldownTime, subtracting 0.1 after each 0.1 * modifier wait. For a fixed cooldown of30 and modifier0.5, requested admission waits sum to15.25 seconds while nominal display ticks sum to15. Frame scheduling/negative waits need actual execution evidence. A single normalized timer would change this behavior. ProtoBarrier, GroundBreaker, HeavenYangSword and TidalVeil also set cooldowns/start timers themselves; LusterBurst/GroundBreaker use the same fields as count meters, not seconds. WarCry changes cooldownTime after admission starts. Model the distinct policies explicitly.
| Hook family | Boundary and behavior constraint |
|---|---|
| Automatic character cycles | Frenzy enters automatically when eligible; duration is 2 + max stamina ×0.02 and attack/reload stat factors stay in player capabilities. ProtoBarrier waits for reload-derived cooldown then polls stamina at0.5s before spending/activating. Artemis/RocketBarrage retain delayed volleys, captured origin/enemy-count versus live stats, target order and integer Random.Range offsets. |
| Attack-count character effects | Preserve Archer's decrement/reset/display sequence, Miner crit/assured-crit and cooldown counters, Knight long-slash/combo selection and StarBurst charge. Count meters must not become time-based cooldowns. |
| Summons and orbit | Celestial swords, Yang regeneration and Priestess orbs retain their count/priority, multishot expansion, orbit and return timing. Companion attacks may invoke main-weapon procs before replacing their final damage. CircularWeapon uses finalBonusSkillAmp even though it exposes other damage fields. |
| Incoming-hit hooks | Keep the ordered reflections, shields, mitigation, retaliation, lethal and immunity steps in player capabilities. Ability state owns block/capacity/recharge; views merely reflect it. No new overflow rule. |
| Dash and resource hooks | Preserve Dash admission/cost and ordered hooks from player capabilities. LightBlessing, AidRoll, LastStand, Meditate, Enrage, stamina conversion and SoulWager retain distinct direct mutation, timing and cap rules. |
| Temporary effects | Potion flags, tactical/run/fire/focus/blood buffs, magnet and stamina-regen bonuses require player-owned refresh/stack/expiry policies. Cancelling an operation must release its own contribution exactly once; it must not subtract another instance's bonus. First characterize the current refresh/cancel cases rather than inventing stacking rules. |
Two global AbilityFunction mechanisms are source risks: activePotionCoroutines keys only ItemType, so another player's same potion can stop the earlier cleanup; effectQueue serializes entire visual durations across players. Target ownership is per player, with refresh for that player's same effect and independent different-player effects. This corrects unintended shared ownership; verify timing/stack outcomes before migration and record any visible change explicitly. It does not authorize extra potion strength or redesigned effects.
Collision, attribution and pooled lifetime¶
Current PoolManager activates reused objects before setting transform; spawners assign attacker/damage/flags afterward. PlayerAttack.OnEnable starts lifetime/damaging/trail work and clears hit history/bonus hits, but does not clear all payload fields. ReturnPool clears only selected flags. PlayerAttackCarrier resets launch state and starts delayed work without resetting every owner/target/payload. Immediate OnEnable work and zero-delay content can observe stale values. A new lease follows acquire inactive → reset all owned state → set transform/parent/payload → activate → execute → stop/cancel/detach → return once. Validate this at R1 and migrate combat users at R4b; do not broadly change pool scheduling without comparisons.
PlayerAttack requires the Enemy tag, same-object Enemy component, hit points, collider/Rigidbody and its configured effect components. It rejects invulnerable enemies, records the collider object once, applies damage while count <= hit budget, then stops motion/collider at count >= budget and schedules0.45s return. Feedback/status/proc code still follows that budget block. Zero budget therefore need not mean no effects. Repeated colliders, already-dead targets and two callbacks before return need tests. A new IDamageable-only dummy is insufficient until the production receiver adapter exists.
Preserve impact order: damage → hit-budget stop → random hit feedback → freeze/stun/emergency/WarCry status → explosion → ricochet → Shrapnel placeholder → Hydra split → poison → vacuum → eclipse → lifesteal → Celestial mark. ProtoBarrier damage scales by target kind (creep0.5, miniboss/special1, boss1.5). Vampiric healing uses projectile Damage × live vampiric power/100 with minimum1, except SuddenDeath; it does not use mitigated HP loss. Enemy.TakeDamage applies resistance, records truncated damage, consumes popup random offsets even when indicators are disabled, invokes hit listeners, updates aggro and processes lethal/drop/knockback work. Attribution must distinguish actor, originating attack and current companion master.
Several secondary spawn paths omit Player/SpellAmp or other fields: explosion, ricochet, Hydra child attacks and Companion.AttackModify are examples. Do not rely on previous pooled payloads or fill every field with current weapon stats indiscriminately. Specify a complete payload per spawn route, compare the intended parent values with a fresh instance, and isolate any bug correction from formula changes. Hydra's inclusive loop requests 2 + floor(level/10) splits; preserve that count until explicitly changed. Enemy's Shrapnel path is separate from PlayerAttack's empty branch and uses IsGotSharpnell; trace its writer/reachability before declaring it complete or removing it.
Carrier behavior remains launch → wander → homing with scaled waits, target validity/re-route and single-explosion guard; airstrike retains its separate path/delay/count. Follow-up callbacks must reject an expired run/lease, not hit a recycled enemy or actor. On death/revive, keep the current default-master versus temporary drone-master policy; enumerate ability and child-attack keep/cancel/reset explicitly. A full new run resets all transient state. Do not run Start again as a universal revive reset.
Target query policies¶
| Consumer | Current policy to preserve/characterize |
|---|---|
| Player weapons/aim | Enemy hit-point entries ranked by center distance minus hit-point size; invulnerable entries get effective1000; priority clamps and searches toward lower indices. No valid result gives null or the camera-side aim fallback. Multiple hit points remain distinct candidates. Equal-distance order is not proven stable. |
| Companion.FindNearestEnemy | Finds tagged enemy roots, filters death/invulnerability, sorts center distance from reference actor, backs down priority/range and returns first hit-point GameObject. Drone then performs its own distance check from drone position. Do not collapse those two ranges. |
| Enemy bounce search | Nearest other nondead Enemy root within15; does not apply the companion invulnerability filter. |
| Carrier homing | Validates Enemy root death/invulnerability, aims at first hit point, re-routes using random player priority0–4, and may explode when no candidate exists. |
A registry avoids repeated scene discovery and component lookup, but changing scan/sort frequency, distance metric, target lock or random selection requires comparison and profiling. No measured speedup is claimed here. CircularWeapon's modulo by current enemy count and delayed volley target loss require explicit empty-registry cases.
Content disposition and open checks¶
GAME-11 is narrowed by source evidence. StarBurstShield only yields; its activator is absent from AbilityHolder.Update and has no other C# caller or matching persistent method name in the scan. StarBurst itself is real charge/projectile content, so do not remove that ability. No authored Upgrade effect array currently resolves to GKARMOR or DRONEMK2. Old GKArmor/GKCrown/GKStaff upgrade assets are outside the direct boot catalogs, have zero incoming serialized GUID references in this scan, and contain invalid current effect ordinals 59/57/58. Quarantine/retirement is a candidate, not deletion authority or proof that reflection/external tools cannot load them. Do not implement their missing effects as part of cleanup.
Frenzy's asset serializes isOnCooldown1/currentCooldownTime2.699998, while actor setup clears the admission flag and execution writes timers. This is serialized residue, not proof of a live cooldown defect. CONTENT-05's reload-display disagreement now has current source support; transition/death/pool observations remain unverified.
| Follow-up | Required disposition before the affected implementation slice |
|---|---|
| CA-01: shared timers/effects | Test same ability and same potion on two players, duplicate acquisitions, refresh/re-entry and run/actor cancellation; preserve intended independent ownership without silently inventing stacking. |
| CA-02: payload/reset | Enumerate each spawn route's full payload and lease reset, including child effects, drone owner, target generation, hit list, flags, collider, velocity, rotation, trail and delayed work. Test fresh versus recycled instances. |
| CA-03: ordering/timers | Characterize first-frame setup, live-vs-captured reload values, count UI, negative/short waits, bypass/double-start and crit/random/hook order. Decide display-only corrections explicitly. |
| CA-04: content and callbacks | Resolve inherited binding/override/event arguments in Unity, active catalogs/stage eligibility and remaining Shrapnel/placeholder reachability; preserve callback compatibility until all consumers migrate. |
| CA-05: target/roster integration | Test target death/despawn between waits, empty registry/modulo, multiple hit points and companion master/revive behavior. Stage/enemy and reward contracts must specify added-player participation before four-player acceptance. |
Implementation order and completion¶
After the entire R0 gate closes: R1 establishes lease/run cancellation and the F0 arena; R2 supplies slot/input identity; R3 migrates player capabilities. R4a then establishes per-player ability state and cooldown/display readers; R4b migrates targeting and weapon/projectile execution; R4c migrates concrete skills/companions/evolution consumers with F3 combat cases. Minimal dash admission/motor ownership is established earlier without implementing the entire skill catalog. Representative existing character content moves with each slice. An isolated ability service without real damage/stat/upgrade consumers is incomplete.
Do not begin Tutorial, final visual polish or broad measured optimization ahead of those owners. First preserve base attacks and each character's special path, then their upgrades/secondary attacks and repeated-run/co-op cases. Keep old caller adapters only where needed, with an explicit removal check. Finish source/serialized reference checks before retiring old authority. This batch completes a contract, not that implementation. The stage/enemy/encounter/event core contract now records the next boundary and follow-ups. The reward/progression core contract now records application/queue/pickup/result ownership and open participation decisions. The persistence/UI/service contract now records that integration. Batch 34 admits the first R1a lifetime slice, with CA-01–CA-05 retained in the phase gate register. Tutorial and the one-minute freeze stay parked.