transfer) used lowercase column names (guid, currency, quantity) that
match a different fork's schema but not TrinityCore's character_currency
table, which uses PascalCase (CharacterGuid, Currency, Quantity) as
seen in CHAR_SEL_PLAYER_CURRENCY / CHAR_UPD_PLAYER_CURRENCY /
CHAR_REP_PLAYER_CURRENCY / CHAR_DEL_PLAYER_CURRENCY at the top of the
file. mysql_stmt_prepare rejected both statements at startup with
"Unknown column 'pc.guid' in 'on clause'" / "Unknown column 'guid'
in 'where clause'", taking the tc_characters pool down.
CHAR_SEL_ACCOUNT_CHARACTER_CURRENCIES: pc.currency -> pc.Currency,
pc.quantity -> pc.Quantity, ON c.guid = pc.guid ->
ON c.guid = pc.CharacterGuid.
CHAR_UPD_PLAYER_CURRENCY_QUANTITY: SET quantity -> SET Quantity,
WHERE guid -> WHERE CharacterGuid, currency -> Currency.
User feedback: the textureKit string is already in DB2 (Campaign.UiTextureKitID
-> UiTextureKit.KitPrefix); don't duplicate it in a fabricated world-config
column.
- Add UiTextureKit.db2 loader (struct, LoadInfo, store, LOAD_DB2 call,
HOTFIX_SEL_UI_TEXTURE_KIT enum + statement, ui_texture_kit hotfix table).
Schema: ID + KitPrefix string (FieldCount=1 per UiTextureKitMeta,
LayoutHash 0x4740638A at build 12.0.5.67186).
- MajorFactionMgr:
* Drop MajorFactionConfig::TextureKit (std::string).
* Add MajorFactionConfig::RenownCampaignID (uint32) - Campaign.db2 FK.
* Validate FK against sCampaignStore at LoadWorldData time; clear with
error log if the campaign row is missing.
* Add GetRenownCampaignID(factionId) and GetTextureKitPrefix(factionId).
GetTextureKitPrefix walks the canonical Blizzard chain:
faction -> renownCampaignId
-> Campaign.UiTextureKitID
-> UiTextureKit.KitPrefix
and returns the string the client uses as the atlas-name suffix
(e.g. "MajorFaction-DragonscaleExpedition").
- World data: 2026_05_16_01_world.sql rewritten. Column textureKit
replaced by renownCampaignId. Values pulled per-faction from the JSON
research files (campaign.id / campaign_id field):
DF: 166/197/189/174/203/231
TWW 11.0: 238/236/237/239
TWW 11.1+: 264/267/268
Midnight: 270 (shared 17-chapter)/267 (shared)
Plunderstorm/Gallagio/RitualSites: 0 (no associated campaign)
This was the user-observed redundancy: we had loaded 3 campaign DB2s
(Campaign, CampaignXQuestLine, CampaignXCondition - all wired) but
were not consuming Campaign.UiTextureKitID. Now wired.
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).