Fix the effect dispatch key: use BattlePetEffectPropertiesID (the
actual effect action type) instead of ParamTypeEnum[0] (parameter data
type). This single change fixes healing dealing damage, auras not
applying, state changes, stuns, weather, and multi-turn markers all
routing to the damage case.
Also lock swaps during multi-turn abilities, clear multi-turn state on
pet death, face the player toward the opponent on battle start, restore
NPC trainer movement after battle with a cry emote on loss, and show
quest menu alongside the battle gossip option.
Register BattlePetNPCTeamMember.db2 in the hotfix pipeline so the
server can populate it at runtime. The client ships this DB2 empty
(0 records) — names resolve via CreatureID in packets instead, but
the infrastructure is now in place for future name overrides.
Add initial seed data for 19 NPC pet battle trainers (57 pets) from
Eastern Kingdoms through Pandaria Grand Masters. All creature IDs
verified against TDB creature_template with exact name matches.
Multi-turn abilities (Dig, Burrow, etc.) were invisible to the client:
- Handle effectCategory 17/18 (MULTI_TURN_BEGIN/END) in ProcessEffect
that were falling through to default handler producing no effects
- Fix off-by-one: multi-turn state now clears on last turn instead of
one round late (>= TotalTurns-1 instead of >= TotalTurns)
- Emit fallback STATUS_CHANGE for empty multi-turn turns so the client
still shows the ability animation
NPC trainer pet naming and model support:
- Add npcTeamMemberID column to battle_pet_npc_team (maps to
BattlePetNPCTeamMember.db2 for pet name display on client)
- Add creatureId column for optional model override (0=species default)
- Send NpcTeamMemberID in packet for all teams, not just wild
Fix aura round data being lost before packet serialization by storing
RoundsRemaining/CurrentRound in PetBattleRoundEffect at creation time
instead of looking up live aura state after TickAuras() has already
decremented or removed them.
Defer captured pet journal addition from round resolution to
CompleteBattle() so the "Pet collected" message appears after the
client plays the crate animation, not before. Also add missing
PlayerObtainPetThroughBattle criteria call.
Add NPC pet battle support via StartNPCPetBattle() on WorldSession and
npc_pet_battle_trainer gossip CreatureScript. Trainers with a team in
battle_pet_npc_team and ScriptName='npc_pet_battle_trainer' will offer
a gossip battle option.
Continued analysis of WoD garrison sniff hex data revealed:
Shipment packets:
- CharacterShipment struct missing 2 fields: UnkInt32 (int32) and
GarrTypeID (uint8) per entry — 5 extra bytes confirmed by raw hex
decode of GET_SHIPMENT_INFO_RESPONSE and LANDING_PAGE_SHIPMENTS
- CreateShipmentResponse ShipmentRecID always 0 (sniff-confirmed)
Login/zone-in workflow:
- Send troop quality refresh (FOLLOWER_CHANGED_QUALITY) before main
GET_GARRISON_INFO_RESULT at login (sniff-confirmed ordering)
- Send GARRISON_UPDATE_GARRISON_MONUMENT_SELECTIONS on zone-in after
map data response (sniff-confirmed zone-in sequence)
- Set EditorMode UpdateField via SetHousingEditorModeUpdateField() when
entering/exiting edit mode. The client reads this from
PlayerHouseInfoComponentData to enable ClickTarget (flag 16) for decor
selection. Without it, the housing editor stays in mode 0 and all click
flags are disabled.
- Set UNIT_FLAG_PACIFIED, UNIT_FLAG2_NO_ACTIONS and SilencedSchoolMask=127
during edit mode (sniff-verified retail behavior). Clear on exit.
- Revert ignoreNestedChangesMask from true to false in
HousingStorageData::WriteUpdate. The true flag forced full-map Create
format inside VALUES_UPDATE which crashes the client (BLZ_ALLOC 41GB)
on subsequent Decor map updates after placing decor. The original
partial-serialization issue was actually caused by ContentsChangedMask=0
which is already fixed by the Account::SendUpdateToPlayer override.
- Fix SMSG_HOUSING_UPDATE_HOUSE_INFO to send actual BnetAccountGuid
instead of ObjectGuid::Empty so house owner displays correctly in the
settings/permissions UI.
- Make character_housing position columns SQL update idempotent to avoid
duplicate column errors when schema already includes posX/posY/posZ.
BaseEntity::SendUpdateToPlayer() is const and never calls
BuildUpdateChangesMask(), leaving ContentsChangedMask at 0. This means
BuildValuesUpdateBlockForPlayer() skips all fragment data — the
VALUES_UPDATE packet is sent empty with no FHousingStorage_C content.
The map's periodic update cycle (Account::BuildUpdate) does call
BuildUpdateChangesMask() and sends data correctly, but our explicit
handler calls to SendUpdateToPlayer were producing empty packets.
Override SendUpdateToPlayer on Account to call BuildUpdateChangesMask()
before serializing and ClearUpdateMask() after. This ensures
FHousingStorage_C Decor map data populated by
PopulateCatalogStorageEntries() is actually included in the packet.
The client correlates FHousingStorage_C Decor entries with MeshObject
FHousingDecor_C.DecorGUID for targeting/selection. VALUES_UPDATE packets
with partial change masks (ignoreNestedChangesMask=false) only sent
individual field bits, missing the complete Decor map structure the
client needs. Fix by forcing ignoreNestedChangesMask=true in
HousingStorageData::WriteUpdate so the Decor map is always serialized
in full-create format (WriteMapFieldCreate) inside VALUES_UPDATE.
Also fix SetHousingDecorStorageEntry to set SourceValue (empty string)
so all 3 fields have their change bits set for per-entry serialization.
The Account entity's GUID was never added to m_clientGUIDs after its
initial CREATE (embedded in the player's own create block). This caused
SendUpdateToPlayer() to always send a duplicate full CREATE instead of
a VALUES_UPDATE. When the Decor map was populated during edit mode, the
duplicate CREATE crashed the client with a 41GB BLZ_ALLOC allocation.