forked from phenom/healer-man
116 lines
6.5 KiB
Markdown
116 lines
6.5 KiB
Markdown
# Pinned enemy equipment mapping — 2026-10-06
|
|
|
|
## Result
|
|
|
|
Recovered the exact AzerothCore `creature_equip_template.sql` at the currently
|
|
pinned world commit and added its hash-checked fixture and importer path. The
|
|
generated reference now joins imported spawn GUIDs and selectors to equipment
|
|
sets, then to Item.dbc class and inventory type. The runtime helper resolves
|
|
only an explicit source spawn GUID and entry; unknown, mismatched, unsupported,
|
|
or unresolvable assignments produce no equipment contract.
|
|
|
|
The recovered SQL is
|
|
`dungeon-pipeline/source-fixtures/azerothcore-4d9d1d4b5723e819c5c390f6ca1177283dbfb8e3/creature_equip_template.sql`.
|
|
It hashes to `877205c149fd447b08f0ff2c65976f20c862cd42f068a6fcc294a76c7108936a`
|
|
and belongs to AzerothCore commit
|
|
`4d9d1d4b5723e819c5c390f6ca1177283dbfb8e3`, matching the active
|
|
`creature.sql` and `creature_template.sql` pins. Its schema is
|
|
`CreatureID, ID, ItemID1, ItemID2, ItemID3, VerifiedBuild`; the source contains
|
|
10,854 SQL rows. The importer checks the full file hash before publishing the
|
|
equipment mapping and records it in `azerothCoreSourceLock.json`.
|
|
|
|
## Imported runtime scope
|
|
|
|
`azerothCoreReference.json` stores three related mappings under
|
|
`creature.equipment*`:
|
|
|
|
- `equipmentAssignmentsBySpawnGuid[guid]` records the source `id1`, optional
|
|
alternate entries `id2`/`id3`, and original `equipment_id` selector.
|
|
- `equipmentTemplatesByEntry[entry][equipmentId]` records raw source item IDs
|
|
and the three virtual item IDs retained after core loader validation.
|
|
- `equipmentItemsById[itemId]` stores the pinned Item.dbc `itemClass` and
|
|
`inventoryType` for IDs referenced by those equipment rows.
|
|
|
|
These assignments cover the source dungeon maps imported by the pipeline, not
|
|
all 149,879 rows in the world spawn table. The current generated snapshot has
|
|
13,277 spawn-GUID assignments, 755 equipment entries, 763 equipment sets, and
|
|
442 referenced item IDs. The spawn selectors are 7,632 zeroes, 5,637 ones, two
|
|
twos, and six `-1` values. Twenty-three spawn rows have alternate creature
|
|
entries. All 1,034 nonzero virtual item slots in this imported scope resolve
|
|
through the pinned Item.dbc and pass its hand-inventory validation.
|
|
|
|
The Item.dbc input is the WotLK 3.3.5a client file at
|
|
`../wow335a/Data/patch-A.MPQ/DBFilesClient/Item.dbc`, SHA-256
|
|
`22061a811523790ddd2ee95b36ade2ac6e0c79a8b3121324d32a639acf50567f`. Its
|
|
46,149 rows use eight 4-byte fields per 32-byte record; Class is field 1 and InventoryType is
|
|
field 6. The importer rejects a different hash or DBC layout. Both pins and
|
|
field indexes appear in the generated source lock and reference.
|
|
|
|
## Source behavior and selectors
|
|
|
|
The source behavior was checked against the exact commit-pinned
|
|
`Creature.cpp` (SHA-256
|
|
`ea19df5312b632bb7b9faf4323c1612fff8d8104e390d7193bae584318e3e11b`) and
|
|
`ObjectMgr.cpp` (SHA-256
|
|
`e4eae029cc30f84c26c258ba806d39eea61200f623aead1ee0813f6adebeed37`).
|
|
The relevant operations are `ObjectMgr::GetEquipmentInfo`,
|
|
`ObjectMgr::LoadEquipmentTemplates`, spawn data loading, `Creature::LoadEquipment`,
|
|
and `Creature::HasWeapon`.
|
|
|
|
For a database spawn, selector `0` means no equipment. A positive selector
|
|
looks up that exact equipment ID. Selector `-1` chooses a random row from the
|
|
entry's equipment map, then mutates the selector to `distance(begin, row) + 1`.
|
|
That is an ordinal-based ID, not the selected row's actual key. ObjectMgr checks
|
|
nonzero alternate entries using the mutated selector and clears the assignment
|
|
if a required alternate row is absent; the later creature load again looks up
|
|
the concrete ID. The runtime helper mirrors this sequence with an injected
|
|
uniform value in `[0, 1)`. It fails closed if the resulting exact lookup or any
|
|
alternate lookup is absent rather than choosing the row's key as a substitute.
|
|
|
|
This distinction matters for sparse IDs. The pinned table has creature 32239
|
|
with only equipment ID 2. Its one-row `-1` selection rewrites to ID 1, so a
|
|
later ID-1 lookup has no result; the helper will not grant its ID-2 equipment
|
|
under a random selector. An explicit selector `2` can resolve that row. The
|
|
focused test covers this ordinal-plus-one behavior.
|
|
|
|
`ObjectMgr::LoadEquipmentTemplates` also removes missing items and item rows
|
|
whose Item.dbc InventoryType is not one of `13, 14, 15, 17, 21, 22, 23, 25,
|
|
26` (weapon, shield, ranged, two-handed weapon, main-hand weapon, off-hand
|
|
weapon, holdable, thrown, or ranged-right). The importer applies this same
|
|
whitelist to all three virtual slots. After that validation,
|
|
`Creature::HasWeapon(OFF_ATTACK)` in AUTO mode checks the resolved Item.dbc
|
|
`ClassID == ITEM_CLASS_WEAPON` (2). No `item_template` lookup is needed for
|
|
that gate; this import does not claim to model item stats or item damage.
|
|
|
|
The helper `enemySpawnEquipmentContract(entry, sourceCreatureGuid, randomUnit?)`
|
|
returns the resolved virtual item IDs and offhand class, plus the existing
|
|
`autoOffhand` contract when the offhand item is a weapon. It requires a source
|
|
GUID whose imported entry list contains the requested creature. Database
|
|
spawns with selector zero resolve to empty virtual slots. Missing GUIDs,
|
|
synthetic spawns, entry mismatches, older references without equipment maps,
|
|
and failed selector lookups return no contract. Core's separate no-spawn-data
|
|
default `LoadEquipment()` selects ID 1; the GUID-based helper does not infer
|
|
that creation path for synthetic actors.
|
|
|
|
The mapping only supplies source equipment and AUTO offhand capability. It
|
|
does not schedule attacks, import item stats, change loot, alter the level-80
|
|
cap, or certify CoA/native balance. Ready-five remains the certification set;
|
|
CoA and native balance remain Needs Testing.
|
|
|
|
## Validation
|
|
|
|
- `node --test scripts/dungeon-pipeline/import-azerothcore-world.test.mjs` — 10
|
|
focused tests passed.
|
|
- `npx vitest run src/game/enemyEquipment.test.ts` — 7 focused tests passed.
|
|
- `node scripts/dungeon-pipeline/import-azerothcore-world.mjs --item-dbc
|
|
"F:\\Projects\\wow335a\\Data\\patch-A.MPQ\\DBFilesClient\\Item.dbc"` —
|
|
green; 54 imported dungeon snapshots, 13,277 creature spawns, 494 encounters,
|
|
with the three expected Ascension-only fallback maps.
|
|
|
|
The isolated source-data subprocess did not run a production build or live QA.
|
|
Root's combined continuation subsequently passes the standard build, Ready-five,
|
|
avatar checks and the one frozen Cellblock Rush clear. Targorr's live source
|
|
GUID 84027 resolves virtual slots `[5305, 5305, 0]` and weapon Class 2; eight
|
|
offhand outcomes are observed. Combined evidence and limitations are in
|
|
[the continuation report](ENEMY_SOURCE_PARITY_CONTINUATION_2026-10-06.md).
|