4.9 KiB
Native RoM NPC Equipment Coverage Completion — 2026-10-03
Result
The native NPC equipment resolver now supports all 440 generated source NPCs under the default deterministic selection and every explicit main-hand/off-hand candidate pair: 440 defaults plus 11,000 candidate-pair snapshots (25 per NPC). The five source candidates and their 20% weights are preserved; the resolver still chooses one reproducible candidate rather than averaging equipment.
The pre-change audit reported 398/440 supported default selections. Its remaining unresolved groups were off-hand weapon DMG, fixed BowEQ channels, two nonzero values tagged EM_WearEqType_None on item 211800, and four valid but mismatched vocation/sub-vocation IDs. Some of the gear reasons overlapped on the same NPC. After the changes, those 42 default fallbacks are resolved.
Source-backed channels
RoleAttr.cpp::AddAbility routes type 25 to BaseEQ.Main_DMG, BaseEQ.Sec_DMG, or BaseEQ.Bow_DMG according to the main-hand, second-hand, or bow position (lines 1323, 1479, 1627). Type 25 on armor remains a generic body DMG contribution. The resolver now preserves the three weapon-position amounts independently and applies the NPC second-hand Dmg_SecHand coefficient when it produces offHandDamage. RoleAttr.cpp::_SecDMG defines that coefficient and its damage inputs (lines 766–806); _Bow_DMG defines the bow amount (lines 1124–1139). The generated NPC FixTable value for Dmg_SecHand is 0.7.
Selected off-hand and bow weapons also expose their source attack speed and range. Recognized armor type-23 attack-speed effects are applied to each weapon speed channel. A type-23 effect on an off-hand or bow weapon remains fail-closed because its position-specific behavior has not been established. Type 191 continues through the existing generic MDMG channel. No current imported NPC has an ornament item; any future non-empty ornament remains fail-closed until its slot-specific path is verified.
The source enum identifies wear index 0 as EM_WearEqType_None (ObjectStruct.h:1427). The two value-35 pairs on item 211800 are therefore treated as no-op channels, while the item's type-25 and type-191 rows continue to contribute normally. Its drop-ability metadata remains metadata and is not applied as an equipment affix.
Across all five choices for all 440 NPC records, the active effects are type 0, 3, 5, 8, 12, 13, 14, 22, 25, 150, and 191. No current NPC equipment record has an ornament item. Ten records have BowEQ, all now supported. Unknown nonzero wear types remain fail-closed; the resolver does not infer future effects from these present-day counts.
NPC sub-vocation growth
The four corrected source identities are NPCs 100074 (vocation 4/sub 6), 100594 (6/1), 100611 (0/6), and 100614 (0/6). RD_ValueCal.cxx::InitCal clears a duplicate primary/secondary vocation (lines 114–118), then assigns a valid NPC Level_Sub from its primary level (lines 154–161). RoleAttr.cpp adds one tenth of the secondary vocation's full race/vocation/sex base curve for each base attribute and for HP/MP (lines 96–124). The resolver now applies that one-tenth curve to the five exposed attributes and derived HP. Primary vocation coefficients and damage rate stay primary-vocation values, matching the source's separate primary Arg path. Sub-vocation mana is not exposed by this NPC combat snapshot.
The regression test locks each corrected NPC's resulting five attributes and health to its source-derived values. NPC recovery inputs are not part of this change.
Resolver API and limits
romNativeNpcCombatant(npcId, runtimeLevel, equipmentSelection) remains the integration entry point. Its result includes the exact equipment choice and selected candidate indexes. The outer result now has optional offHandDamage, offHandAttackSpeed, offHandAttackRange, bowDamage, bowAttackSpeed, and bowAttackRange fields when those source weapons are present. The embedded nativeCombatant and periodic snapshot stay separate from encounter health/damage budgets.
The fixed-bow rows currently have neutral source rate factors for all non-target bow modifiers. Rate effects that are not represented by the current equipment catalog remain unsupported and fail-closed if they occur. This pass does not wire equipment fields into combat scheduling, change authored loot, or alter player-stat resolution.
Validation
Focused validation: npx vitest run src/game/romNativeCombatResolution.test.ts src/game/romNativeNpcEquipment.test.ts — 2 files and 18 tests passed. The population regression checks all 440 default records and all 11,000 explicit candidate-pair selections.
Read-only source references are under F:\Projects\Runewaker\SourceCodeVS2019\Libraries\Union\RoleData: ObjectStruct.h, RD_Setting.cxx, RoleAttr.cpp, and RD_ValueCal.cxx. The generated NPC equipment catalog already contains the required source candidate and item rows, so this completion needed no exporter or generated-data change.