missing/in-memory-created door GO templates previously had no Data10/goober.spell
that caused the client cast to be rejected or the door not to activate
now the generated door GO templates include the correct housing door spell
plate). Remove armor subclass restriction in CanTransmogrifyItemWithItem
while preserving slot compatibility and weapon category rules. Replace
CanUseItem check in transmog handler with faction/race-only gating.
Quest package items now learn appearances for all armor types.
Replace the narrow reagent-only / warbound-only auto-deposit handlers
with the modern "Deposit All" behaviour the warband bank UI expects:
- Each tab's BagSlotFlags::Priority<Equipment|Consumables|TradeGoods|
Junk|QuestItems|Reagents> are persisted in {character,account}_bank_
tab_settings.depositFlags. The handler now classifies every eligible
inventory item (Player::GetItemAutoDepositCategory) and routes it
to the first tab whose flags match (Player::PickAutoDepositTab),
falling back to the first tab without any priority filter, then to
any tab without DisableAutoSort ("Cleanup: Ignore this tab").
- Player::GetItemsForBankAutoDeposit collects eligible inventory
items per bank type, applying the warband bank's
"Include tradeable reagents" toggle (CVar bankAutoDepositReagents)
when bank == Account.
CMSG_AUTO_DEPOSIT_ACCOUNT_BANK actually carries that toggle on the
wire (verified against build 12.0.5.67186 client serializer): 1 bit
IncludeReagents, then the banker GUID. The previous Read() consumed
the GUID byte-aligned and silently mis-parsed when the bit was set.
Add the IncludeReagents field and read it first.
✅ Only creates new bot characters if there's space available (< 10 characters per account)
✅ Gracefully skips creation when account is full instead of failing with repeated errors
✅ Logs appropriate debug messages when accounts are full
Worldserver crashed at startup after applying 2026_04_29_00_hotfixes.sql
with mysql_stmt_prepare() id 249 "Unknown column 'FileDataID' in 'field
list'" — the C++ PrepareStatement was still on the older WoW-build
column set (FileDataID/ConditionID/HookID/Slot/SortOrder/
ComponentGroupID/UiTextureKitID/ExteriorComponentTypeID) while the SQL
table is now on the 12.0.5 layout (ParentComponentID/ModelFileDataID/
Flags/Field_7/Type/Field_9/GameObjectID/Field_11/ItemID/
HouseExteriorWmoDataID).
Updated the SELECT to match DB2LoadInfo::ExteriorComponentLoadInfo
column order (LayoutHash 0x53EA0925, 14 fields). The in-memory
ExteriorComponentEntry struct in DB2Structure.h was already on the new
layout — only the prepared statement lagged.
Sniff-decoded from C:\sniff\housing_stuff\{alliance,horde}_housing\
dump_12.0.5.67186_2026-04-28_*.pkt: when a player clicks a housing
door GO the 12.0.5 retail client emits CMSG_CAST_SPELL with
SpellID 1,271,876 (uint32 at body offset 0x15) targeting the door.
Both faction sniffs are byte-identical in the spell-id field; only the
target PackedGUID at offset 0x3D differs. CMSG_GAME_OBJ_REPORT_USE that
follows is criteria-tracking, NOT the trigger — the cast is.
The server side had four stacked gaps blocking this flow:
A. SpellID 1271876 was missing from spell_name / spell_misc / spell_effect.
Cast validation rejected it as unknown. Added a minimal row set with
SPELL_EFFECT_DUMMY targeting TARGET_GAMEOBJECT_TARGET so the cast
accepts and the SpellScript hook fires.
B. gameobject_template.Data10 (goober.spell) on the housing front-door
templates was either zero (575017, 602702) or pointing at the older
12.0.1 spell 1234192 (586576, 602705) / 1234193 (587318). Neither
matches what the 12.0.5 retail client casts, so the goober mechanism
wouldn't have routed correctly even if the spell existed. All five
entries now point at 1271876.
C. New SpellScript spell_housing_door_open, registered against 1271876
via spell_script_names, intercepts the cast and calls
GameObject::Use() on the spell target. That routes to the existing
go_housing_door::OnGossipHello which already handles edit-mode
gating, visitor permissions, and the interior round trip.
D. The exterior_component SQL hotfix table was on an older WoW build's
schema (FileDataID/ConditionID/HookID/Slot/SortOrder/...) that
doesn't line up with DB2LoadInfo's 12.0.5 layout
(Name + 3 floats + ID + Size + ParentComponentID + ModelFileDataID +
Flags + Field_7 + Type + Field_9 + GameObjectID + Field_11 +
ItemID + HouseExteriorWmoDataID). Without a GameObjectID column the
hotfix loader was filling that field with zeros, so HousingMap::
SpawnExtCompTree never spawned door GOs in the first place. Schema
rebuilt to match the 14-field 12.0.5 record (LayoutHash 0x53EA0925).
Tester noted PropsID 170 has Accuracy(param[1]) and IsPeriodic(param[4])
labels that weren't visible in the WEATHER_SET handler.
- Accuracy is already rolled at the top of ProcessEffect before the
switch dispatches; added a comment so the handler doesn't look
unwired.
- IsPeriodic was silently ignored. PetBattleEnvironment now carries
PeriodicStateIDs; WEATHER_SET inserts when the flag is set;
TickWeather re-emits SET_STATE each round for periodic states so
the client refreshes its visual/counter. ClearWeatherStates also
clears the periodic set.
Tester log shows a Squirrel (creature 61081, species 379) entering
combat at Level=0:
PetBattle LoadWildPetAbilities: Species=379 Level=0 entries=6 loaded=0
PetBattle GenerateWildTeamInput: NO available abilities! ... -> PASS
Every BattlePetSpeciesXAbility entry has RequiredLevel >= 1, so the
level gate (RequiredLevel > pet.Level with pet.Level = 0) filtered all
six entries out. The wild pet then idled every round because the AI's
ability-collection loop produced an empty list.
Root cause is that creature->GetWildBattlePetLevel() can legitimately
return 0 — SelectWildBattlePetLevel only assigns a level when
IsWildBattlePet() is true at the moment it runs (creature spawn /
respawn), and we've seen cases (summoned creatures, hot-respawned
spawns, zones with no AreaTable.WildBattlePetLevelMin entry) where
that path doesn't fire. Clamp the value at the read site in
GenerateWildTeam, log a WARN with the creature entry so the underlying
spawn data can be fixed, and reuse the clamped value for the +/-1
variation that derives extra wild pets in multi-pet wild battles.
Marcus Jensen (npc 63014) gives the four MoP intro pet-battle quests
which all use Type=0 MONSTER objectives against virtual kill-credit
creatures rather than QUEST_OBJECTIVE_CRITERIA_TREE. Without explicit
KilledMonsterCredit calls these quests never advance even though our
CriteriaType progress lines up.
- 31308 "Learning the Ropes" -> creature 65355 on any pet battle win,
fired in PetBattle::FinishBattle for the winning team.
- 31550 "Got one!" -> creature 65356 on first capture, fired in
PetBattle::CompleteBattle next to the existing AccountObtainPet /
PlayerObtainPet criteria.
- 31785 "Level Up!" -> creature 65876 on first 2->3 transition,
fired inside the level-up loop in BattlePetMgr::GrantBattlePetExperience
(only at level == 3 so larger XP grants don't double-credit).
- 31309 "On The Mend" -> creature 64320 when Revive Battle Pets
actually heals at least one pet, fired in
BattlePetMgr::HealBattlePetsPct after the updates list is non-empty
so casting the spell with full-HP pets doesn't credit.
KilledMonsterCredit no-ops if the player has no quest with that
objective, so each call is safe regardless of quest state.
Three tester-reported bugs in one pass:
1. Multi-round aura icon was missing because AURA_APPLY/AURA_CHANGE
wire param 0 (AbilityID — used by the client to look up the spell
icon) carried the parent cast ability instead of the actual aura
ability. When a wrapper ability applies a sub-aura via
AuraBattlePetAbilityID, the cast ability has no icon and the slot
came up blank. Use AuraBattlePetAbilityID when set, fall back to
the cast ability ID otherwise. Stored on the aura so AURA_CHANGE
and AURA_CANCEL ticks pick up the same ID.
2. Weather auras (Call Darkness etc.) were landing on the casting
pet with a turn counter instead of in the middle environment slot.
Root cause: BuildEffectActionMap's weather label match was an
exact string set ("weatherState"/"WeatherState"/"weatherAura"/
"WeatherAura"). Labels like "WeatherStateID" missed the weather
bucket and fell into the "State" substring branch, so the parent
ability never got into _weatherAbilityIDs and IsWeatherAbility
returned false at runtime. Replace with a case-insensitive
"weather" substring check that runs before the State/etc. checks.
3. Wild battles where the player captured the only opponent did not
credit DEFEATBATTLEPET quest objectives because the captured pet
stayed alive (Health > 0). Capture removes the pet from play just
like a kill, so credit it too.
Also raise GenerateWildTeamInput's "no available abilities" log from
DEBUG to WARN ("battlepet" channel) so the next time a tester sees a
wild pet idle, the species ID and ability slots show up in the log
without needing to flip the global log level.
Fix WarbandScenePlacementFilterReq layout to match client metadata.
Fix all parent index fields to be unsigned as required by DB2 loader.
Update warband group limit from 5 to 20 (retail 11.1+).