Files
healer-man/docs/ROM_NATIVE_COMBAT_PASS_2026-10-03.md
2026-10-04 13:13:35 -04:00

79 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RoM native combat pass — 2026-10-03
The later [native resolution and enemy damage-type pass](ROM_NATIVE_COMBAT_RESOLUTION_PASS_2026-10-03.md) supersedes the open defense/hit/critical, negative DotMagic and special/multi-target input boundaries below. This report preserves the original amount/rotation pass and its historical validation.
## Scope and status
This pass connects source-derived native amount bindings to the existing combat runtime for the five targeted identities: Knight/Scout tank, Priest/Knight healer, Rogue/Warrior damage, Scout/Rogue damage, and Mage/Warlock damage. `romFiveIdentities.ts` remains the identity owner. The new shared-rotation profiles are exact-pair and role gated; they are clean-room heuristics informed by local active catalog data and the add-on source research in [`ROM_ROTATION_ADDON_REFERENCE_2026-10-03.md`](ROM_ROTATION_ADDON_REFERENCE_2026-10-03.md). No add-on code was retrieved or installed. CurseForge's archive request reached a Cloudflare JavaScript/cookie challenge, so the profile priorities are not copied presets.
The native amount routes improve source fidelity, but this is not a full RoM combat port or balance certification. Formula outputs still pass through HealerMan's shared target and combat-state machinery. Unsupported source shapes and gear intentionally retain the documented simulator fallback. The five identities remain targeted-test builds; no readiness or random-pool promotion is included.
## Binding and amount routing
`romAbilityCatalog.ts` attaches `romNativeSource` skill/component identities to supported active RuneWaker ability effects. `romNativeCombatAmount.ts` resolves those identities against the generated source binding catalog. The native route runs from `equipmentAdjustedCombatAmount` only for a RoM stat ruleset and a nonnumeric, source-bound ability amount. It tries the specific direct HolyHeal branch, the supported direct damage branch, and the periodic HolyHeal snapshot. If a source binding or required profile is unsupported, it returns no native amount and the existing shared HealerMan coefficient/scaling path continues.
`romNativeMagicLevel(level)` uses the active character level clamped to the project's 1–80 range as the simulator's effective `MagicProc.MagicLv`; it does not infer skill rank or a separate skill-level curve. The active player-build companion amount routes use the source `player` classification for the native player ExRate branch even though the runtime owner is an NPC actor. This is an explicit simulator choice for the five playable builds, not a claim about every ordinary RoM NPC.
Direct native damage requires a supported source attack component and the active five-class training-weapon profile. Since the stat sidecar has no item provenance or weapon speed, the adapter compares the complete native gear payload with the canonical automatic training profile before reversing its weapon contribution. Unverified/custom gear, unsupported class pairs, missing weapons or component bindings, unsupported calculation types, and unavailable school rates return an unsupported result; the generic shared amount path then remains in force. These gates prevent inferred weapon values from being presented as source-derived.
The direct damage helper returns a positive mean source power after its source target-count factor, before source random range/critical handling and target defenses. Its checked `MagicAttackCalENUM` fixed-type branches support 0, 1, 2, 3, and 5–9; throw, prior-hit, and shield-category inputs remain unsupported because the stat sidecar lacks those exact source values. The consumer also declines components marked `isShareDamage`, or nonzero `decreaseArg` on nonzero `rangeType`, until it receives the runtime target count and ordinal; the pure amount helper can represent those fields but the current consumer does not claim area-damage exactness. Reflected Shot has a regression check for this fail-closed behavior. Supported single-target ability amounts pass to the shared target-resolution path for modeled hit/critical rules, resistance/armor, target auras, absorbs, and damage application. It does not yet resolve every RoM source hit/avoidance point, native defense channel, ability random roll, or source critical-rate field.
`nativeTrainingAutoAttackProfile` provides native physical weapon damage and intervals for player Knight main-hand attacks and NPC Knight/Rogue melee plus Scout Bow attacks; NPC Rogue offhand is also covered. Player Rogue offhand handling requires an explicitly present equipped inventory item. It does not claim a player Scout bow auto profile: player Scout Shot instead uses the native direct-damage route for its actual bound Shoot hit. Caster ambient basic-spell attacks retain their generic interval and MDMG policy. Player melee timing explicitly reads the existing common haste aura via `resolveAuraStatValue` because native stat re-derivation does not populate the shared haste fields; race-affix timing is retained as well. Four focused auto/source-action cases passed: player Knight Main_DMG/source interval with semantic 50% haste, NPC Scout Bow/source clock with ranged haste, NPC Rogue offhand Sec_DMG/offhand clock with melee haste, and a player Scout Shot resolving an actual bound hit. These are source-backed channels, not complete native hit/avoidance, armor, variance, or critical models.
Outgoing damage-over-time still uses native stat inputs through the shared simulator amount path. The source DotMagic snapshot implemented in this pass covers healing; source-native periodic damage remains future work.
## Direct HolyHeal
`romNativeHealing.ts` resolves only source-bound calculation type 5 components. It applies the source MagicLv-adjusted `OrgPower`, clamped `SpellTime`, Wisdom/MND contribution and cap, MDMG coefficient, MPow, HealPowerRate, and HealPoint. The amount adapter samples `RandomRange` at its midpoint (`randomUnit = 0.5`), producing mean source power; the common healing resolver still handles its critical and overheal behavior.
The caster amount is computed without recipient-specific HealAbsorb modifiers. At each real recipient, `nativeHolyHealTargetAmount` applies that target's HealAbsorbRate and HealAbsorb once, unless the component says to ignore absorption. Normal aura/talent and healing-result stages then run through the shared resolver. This prevents the recipient's native absorption stats from being folded into caster power and applied a second time. Group heals resolve each recipient independently.
## Periodic HolyHeal snapshot
Source DotMagic healing is separate from direct HolyHeal. `nativePeriodicHealSnapshot` resolves the supported positive-HP DotMagic component when the buff is applied, using the caster/recipient native stats and the source rank, duration, tick interval, and effective MagicLv. The source rank correction computes a `Buff.Power` snapshot with MND, MDMG, HealPowerRate, HealPoint, the available MPow input, and the target absorption inputs, then stores the integer tick amount. Later ticks reuse the stored value; they do not rerun the caster formula or apply target absorption again.
This follows the observed Runewaker `CalAddDotMagicLv`/`BuffProc` ordering for bound components. The current sidecar exposes neutral all-magic MPow but not every element-specific `BodyRate`, so callers must not read the current default as proof that all elemental healing rates are 1. Unsupported DotMagic shapes return no native snapshot and continue through the existing fallback.
## Rotation and validation boundary
`romFiveRotation.ts` selects only the exact ordered `(statRuleset, primary, secondary, role)` tuple at level 10 or above. It retains learned catalog damage actions as low-priority fillers, while pair-specific guards cover cooldown/setup priority, useful target lifetime, AoE target minimums, emergency healing, current DoT ownership, and near-expiry refresh. The shared evaluator and its party/benchmark callers continue to enforce learned ability, cooldown, resource, range, target, and movement readiness. Pre-secondary levels and unsupported pairs stay on the existing semantic path. WoW keeps its existing specialization selector and is not filtered by the native RoM guards.
`romFiveRotation.integration.test.ts` covers all five exact pairs against active learned catalog abilities, a healthy Priest/Knight using Group Heal for injured allies, Urgent Heal before throughput when an ally is critical, actor/target-owned DoT refresh timing, and the unchanged WoW profile selector. The focused module and integration suites pass together (17 tests).
The fixed full-player diagnostic in `romFiveNativeRotation.integration.test.ts` rotates each of the five identities into the player seat, creates the other four native party members explicitly, and uses the shared BenchmarkController against a real Barren Caves trash spawn and Anglo at levels 1/10/30/60/65/66/79/80. This is 80 fixed samples, not a scene-driven encounter: actor positions are static and encounter mechanics/navigation are not simulated. The test writes `artifacts/rom-five-native-rotation/report.json`. `artifacts/rom-five-native-rotation/before-native-combat.json` preserves the earlier 60-sample, six-level pre-native-combat baseline. The final post-haste-retention report records 80/80 pulls completed, no player or companion deaths, and zero invalid casts. Trash kills were 4.5–9 seconds and Anglo was 39–53.4 seconds. The harness now checks for a dead target before requesting another player decision, so post-kill no-target attempts are not counted.
## Native-only health pacing
`dungeonEnemyScaling` now accepts the selected character stat ruleset, defaulting to `"wow"` for existing callers. Live `MobPopulation` passes the active character's ruleset. A piecewise-linear enemy-health factor applies only when the character source is RoM and the selected ruleset is native `"rom"`; legacy WoW-stat RoM characters retain their prior curve, and WoW/CoA-origin characters are unchanged. The factor changes neither damage nor enemy level, boss difficulty, authored multipliers, or the level-80 cap.
The anchors are indexed by clamped character level and each row is [trash health scale, boss health scale]:
| Level | Trash | Boss |
|---:|---:|---:|
| 1 | 0.9 | 0.45 |
| 10 | 1.4 | 0.85 |
| 30 | 1.4 | 0.95 |
| 60 | 1.5 | 1.25 |
| 65 | 1.8 | 1.5 |
| 66 | 2.1 | 1.9 |
| 79 | 3.6 | 2.8 |
| 80 | 3.6 | 2.8 |
This is a targeted native RoM simulator pacing policy measured against the five requested builds, not a claim about RuneWaker monster-health formulas or full balance. It does not alter loot, progression, source enemy damage, or readiness. The ordinary randomized companion pool is now restricted to the active five identities; the broader configured factory remains available for explicit party construction. This diagnostic's five fixed identities do not promote readiness or broaden the general pool.
## Current verification status
The focused 15-file selection passed 210 tests. Direct and periodic native healing coverage passed 14 player/NPC cases. The source-damage follow-up passed 13 focused tests: seven helper cases, two player/companion amount-parity and Reflected Shot fail-closed cases, and the four actual auto-attack cases above. Ready-five passed seven Vitest and twenty Python checks, avatar validation passed 47 tests, and the final TypeScript project check passed. One separate `combatRotation.test.ts` case still fails its existing unsupported-only `Killing Spree` expectation; that unrelated behavior is unchanged here. The final production build passed with asset audits, compression, and bundle verification. Browser QA passed on the current `index-D_h9IRuA.js` and `combatStore-BiA9BOQG.js` chunks; 11 screenshots were captured and four representative roster, dungeon, NPC-stat, and mobile screenshots were visually reviewed. There were no page/server errors and the network response-errors list was empty; the only console error was the optional existing favicon 404. `npm run release:check` passed on the final 249 changed paths, including untracked files; `git diff --check` passed. The worklog is closed; the unrelated Killing Spree test and remaining source-formula boundaries are documented above.
The fixed diagnostic instantiates only the five requested identities. The ordinary randomized companion pool is now restricted to those five, while the configured factory remains broader for explicit compositions. The pass does not alter the loot path, raise the level cap, change enemy damage, or promote RoM readiness.
## Source and validation references
- Source formulas and archived boundaries: [`ROM_NATIVE_STATS_SOURCE_2026-10-03.md`](ROM_NATIVE_STATS_SOURCE_2026-10-03.md), [`CHARACTER_STAT_RULESETS_2026-10-03.md`](CHARACTER_STAT_RULESETS_2026-10-03.md)
- Exact-pair add-on research and clean-room policy: [`ROM_ROTATION_ADDON_REFERENCE_2026-10-03.md`](ROM_ROTATION_ADDON_REFERENCE_2026-10-03.md)
- Native amount code: `src/game/romNativeCombatAmount.ts`, `src/game/romNativeHealing.ts`, `src/game/romNativeDamage.ts`
- Native rotation code and focused coverage: `src/game/romFiveRotation.ts`, `src/game/romFiveRotation.test.ts`, `src/game/romFiveRotation.integration.test.ts`
- Targeted fixed-cohort diagnostics: `src/game/romFiveNativeDungeonHealth.test.ts`, `src/game/romFiveNativeRotation.integration.test.ts`
No loot/progression, legacy/global enemy-HP curve, gear-cap, or readiness-promotion change is part of this pass. A separate native-stat RoM health budget was added and leaves the compatibility curve unchanged.