Housing Decor Guide

All 1,690 housing decorations in one addon. Browse every acquirable item, plan vendor shopping routes with built-in waypoints, queue crafting recipes with material tracking, and monitor profit margins — all with account-wide alt awareness.

File Details

Housing Decor Guide v2.40.0

  • R
  • May 4, 2026
  • 1.92 MB
  • 15.9K
  • 12.0.5+2
  • Retail

File Name

HousingDecorGuide-2.40.0.zip

Supported Versions

  • 12.0.5
  • 12.0.1
  • 12.0.0

* StylesTab refactor (plans/2026-05-04-stylestab-split.md):
  HDG_StylesTab.lua decomposed from a 2920-line monolith to a 1656-line
  orchestrator + a UI/Tabs/Styles/ folder of screen modules + a UI/Widgets/
  folder of cross-tab widgets. -1264 lines (-43%) extracted across 8 phases.

  - Phase 1: shared widget seam at UI/Widgets/ -- HDG_W_SegmentedChip +
    HDG_W_TypePill. Replaces previous inline implementations.

  - Phase 2: state extracted to UI/Tabs/Styles/HDG_ST_State.lua. Single
    source of truth for all Styles selectors (selectedStyle, selectedTier,
    collectionFilter, etc.) with named mutators (SelectTier, ResetForStyle,
    SetCollectionFilter, etc.). 162 references migrated. Legacy
    uncollectedOnly + collectedOnly boolean pair consolidated into
    State.collectionFilter ("all" / "have" / "need").

  - Phase 3a: ItemPanel extracted to UI/Tabs/Styles/HDG_ST_ItemPanel.lua.
    Owns the right-side panel widget; Build/Render/LoadModel/Show/Hide/
    GetFrame surface. Shims (RefreshItemDetail, LoadPreviewModel) forward.

  - Phase 3c: Landing data layer extracted to UI/Tabs/Styles/HDG_ST_Landing.lua.
    BuildData{ statsCache } returns the full landing row array
    (curated + filtered + shopping lists + snapshots + sessions + room
    concepts + collections). Widget creation stays in StylesTab.

  - Phase 3d: Detail screen progressively extracted to
    UI/Tabs/Styles/HDG_ST_Detail.lua across five sub-phases:
      3d-1: helpers + cell handlers (TIER_TOOLTIP_LABELS, OnCellEnter/
            OnCellLeave/OnCellClick, UpdateCellHighlights, HideFilterButtons,
            SortByDecorName).
      3d-2: shared flat-gallery renderer (RenderFlatGallery, used by both
            snapshot + shopping-list views).
      3d-3: Snapshot + ShoppingList render bodies (RenderSnapshot,
            RenderShoppingList).
      3d-4: Session render body (RenderSession).
      3d-5: Main detail render (Render -- the tier/themed/curated/collection
            branching with chip rendering + tier counts + filter loop +
            view-mode dispatch). Plus card-grid, item-list row, and item-list
            renderers; IsItemHidden, ItemHasRepRequirement, ItemCostsEndeavor,
            SOURCE_FILTER_DEFS, ConstructItemListRow.

  - Subtitle anchor fix: detailDesc now anchors to detailHeader's BOTTOMLEFT
    instead of the frame edge -- previously the subtitle hugged the panel
    border.

  Remaining for a future session:
    - CreateDetail widget construction (~250 lines)
    - CreateLanding widget construction (~190 lines)
    - Smart Set landing rows showing 0/0 + empty preview icons in some
      states -- transient bug we couldn't reliably reproduce; needs a
      focused session with the recipe captured.

* Style tab landing header reworded -- "Browse by Style (Beta - in development)"
  becomes "Style, On Purpose -- Drag, drop, and act like that was the plan."
  Beta marker dropped.

* Style tab detail view polish, curated cleanup pass:
  - Curated styles no longer show the Signature/Accent/Versatile/Clashing
    tier chips or the Great Hall/Kitchen/etc. room chips. Those filters
    belong to Smart Set / themed styles where items actually classify by
    tier or room; on a curated set they were always rendering "(0)".
  - New CURATED / SMART SET / SNAPSHOT / COLLECTION / THEMED type pill next
    to the title.
  - Subtitle now reads "<N> items" + optional description (replaces the
    standalone "Curated" line).
  - Have/Need/All segmented chip replaces the Uncollected + Collected
    checkbox pair.
  - List/Grid view toggle moved out of the chip rows into the top-right
    utility cluster next to Export.
  - Curated/collection/snapshot detail views drop ~54px of vertical chrome
    so the item grid starts higher.

* Fixed: empty rows appearing in Style detail grids when scrolling or
  switching styles. HDG_StyleCardRow's shared cell pool was re-parenting
  cells across recycled WowScrollBoxList rowFrames -- new rows would steal
  cells from earlier rows, leaving the earlier rows visually empty. Each
  rowFrame now owns its cells exclusively (no shared pool); ScrollBox's
  built-in rowFrame recycling handles virtualization. UpdateStyleCellHighlights
  rewritten to walk visible rowFrames via ForEachFrame instead of the
  retired pool.

* New shared widget folder UI/Widgets/. First two residents:
  - HDG_W_SegmentedChip (mutually-exclusive 3+ state chip control; powers
    the new Have/Need/All filter)
  - HDG_W_TypePill (small dim-uppercase header label; powers the new
    CURATED / SMART SET pill)
  Both designed for cross-tab reuse. Acquisition / Preview / Goblin filter
  bars are candidates for future migration.

* Fixed: legacy customStyles weren't being restored from SavedVariables on
  load, so the v1-collections migration ran with a nil source table and
  silently copied zero styles. Affected anyone whose save predated the
  v1-collections migration's first run (saves restored from backup, fresh
  installs that imported old data, etc.). Saves where state.collections
  was already populated were unaffected. Fix: load HDG_DB.customStyles +
  customStyleOrder into state.* before Migration.RunAll, mirroring the
  save-side preservation block.

* Data tab no longer spins up its own catalog searcher. The legacy refresh
  flow (TriggerCollectionSearch) created a CreateCatalogSearcher with
  SetOwnedOnly(false) + BasicDecor mode, but immediately filtered every
  result through HDG_Data.GetCatalog — which only carries owned rows — so
  the un-owned 4k+ entries were enumerated and discarded each click.
  Replaced with a synchronous BuildCollectionSnapshot that iterates
  HDG_Data.GetAllCatalog() directly. Refresh is instant, the panel
  auto-populates on tab open, and HDG_Data is once again the only owner of
  CreateCatalogSearcher in the addon. ~120 lines net deletion.

* Catalog Store-canonicalization complete (Steps 1-4). HDG.Store's
  state.collection.decorCatalog and state.collection.catalogByItem are now
  the single source of truth for catalog data; the module-local _catalog /
  _catalogByItem upvalues in HDG_Data have been retired. Saves ~1.5-2 MB of
  persistent duplication and eliminates the ~3-4 MB transient deep-copy
  spike that fired on every sweep. External call sites (Acquisition,
  Preview, Styles, HouseEditor, ZoneTracker, etc.) read through the same
  HDG_Data.GetCatalog / GetCatalogByItem / GetAllCatalog accessors as
  before — internal plumbing change, no behavioural impact. Mutators
  (sweep finalize, UpdateSingleEntry, InvalidateCollectionCache) write
  through Store directly with wipe-in-place semantics, preserving table
  identity for short-lived caller handles.

* Login no longer rebuilds the catalog. The deferred-eager verification
  sweep (kicked 0.5s after SavedVariables restore) was responsible for the
  ~85 MB cold-open memory spike: it re-read every catalog entry, re-built
  ~1,706 row tables, and re-populated variants to confirm what the persisted
  save almost always already had right. Replaced with a lightweight ID-only
  diff (VerifyOwnedSetIDsOnce) — a one-shot owned-only searcher enumerates
  current decorIDs, compares to persisted ownedDecorIDs, and patches ONLY
  the few that drifted via the existing UpdateSingleEntry path. No row reads
  or variant population unless drift is actually detected. Catches the rare
  cases (addon disabled mid-session, crash before save flushed, etc.) without
  the per-login ~30-50 MB allocation churn. Drift during normal play remains
  caught by HOUSING_STORAGE_ENTRY_UPDATED (per-entry) and HOUSING_STORAGE_UPDATED
  (bulk, fires on housing customize entry). Refresh button still does a full
  rebuild on demand.

* Zone scanner no longer triggers WarmCollectionCache at PLAYER_ENTERING_WORLD.
  Persisted ownership data already lives in HDG.Store from SavedVariables by
  the time PEW fires, so IsItemCollected / IsDecorCollected now fall back to
  Store directly when the module-local cache hasn't been warmed. Result: the
  addon does no eager work at login; the scanner answers from persisted state
  for users with saved data, and silently no-ops on cold-cold sessions (first
  install) where Store has nothing yet — they populate it the first time they
  open the HDG window. IsCollectionCacheWarmed accepts Store data as warmed.

* Power Crafting raw-material totals are correct again when a crafted
  sub-reagent is reached via two parent paths in the same recipe. The
  dependency-graph walker was incrementing the revisited node's quantity but
  skipping recursion into its children, so the second path's leaves were
  lost. Player-reported repro: Kirin Tor Skyline Banner (8 Spellweave + 8
  Moonshroud) was showing 80 Frostweave Cloth and 16 Infinite Dust; correct
  totals are 160 and 32. Any recipe that pulls the same crafted intermediate
  from multiple parents (Imbued Bolts, Heavy Borean Leather, etc.) was
  understated by the same factor.

* Projects → Architect: Plan mode is live. Mode pill (Reflect / Plan) on
  the canvas; Plan mode unlocks drag-to-reposition (snap-to-grid + footprint
  collision rejection), right-click rotate (cycles 0/90/180/270 quarter-
  turns), right-click context menu Remove (planned-only) / Reset position
  (captured), and a left-dock palette of all 17 shapes that spawns a fresh
  greenfield room on click. Manual cell positions persist via cell.locked
  and override the auto-layout for both Reflect rendering and the lower-
  floor backdrop. "Reset auto-layout" wipes locks for the current floor.

* Projects → Architect: manual room-connection assertion in Reflect. Click
  any open-door orb → context menu of compatible rooms (same floor, opposite
  cardinal, also unfilled). Right-click a room → Connections submenu showing
  each cardinal's state with Disconnect actions. Asserted/blocked records
  live in projects.connections[floorID]; _floorLayout seeds them before the
  cardinal-matching algorithm runs, so manual overrides always win. Closes
  the topology heuristic ceiling — players can hand-fix mistakes the
  algorithm makes on ambiguous-cardinal houses.

* Projects → Crates: Library + Stamp. CrateDetail gains "Save as template"
  (clones members + name into a new lib_<uuid> entry). RoomSidePanel gains
  "Stamp template" (context menu of every library entry grouped by source —
  My Templates / Curated). Click → mints a fresh crate cloned from the
  template into the current room, opens its detail. Curated content data
  file ships 7 starter templates (Vrykul Throne Hall, Cosy Hearthstone,
  Tavern Essentials, Library/Study, Garden Sanctum, Winter Chalet, Vrykul
  Armory) — seeded by an idempotent v3-curated-library migration that
  remembers player deletes via state.curatedSeeded[key].

* Projects → Crates: orphan handling. Re-capture no longer cascade-deletes
  crates whose room is removed; DeleteProjectRoom detaches them (parent=nil)
  and they surface in any RoomSidePanel under "Unrooted crates (N)" with
  per-row "Move here" buttons that adopt the orphan into the current room.
  Crate_ListOrphans + Crate_Reparent helpers added.

* Projects → Crates: real decor picker. New modal HDG_CratePicker.lua
  with sticky header, search box, status chips (Owned / Missing / Craftable
  / Vendor), top carousel (All + 6 Blizzard categories with progress bars +
  My Styles + Templates cards purple-tinted), sub-carousel (subcategories
  of active category with progress), virtualised row list with checkboxes,
  3D model preview pane, and footer (selected count / Add visible / Done).
  Styles and Templates cards swap the row list to a list-view mode that
  shows each entry with [All N] [Missing N] bulk-add buttons, normalising
  itemID-keyed Style members to decorIDs before adding to the crate. The
  generic horizontal carousel widget (HDG_Carousel) and pure filter
  primitives (HDG_DecorFilter) are factored as standalone modules so Style
  Creator can adopt them later. CrateDetail's "+ Add decor" button replaces
  the placeholder "by ID" text input.

* Projects → Crates: CrateDetail decor list virtualised via WowScrollBoxList
  (no more rows overflowing the panel on large crates). Each row leads with
  the decor's icon (resolved via C_Item.GetItemIconByID) and shows the
  catalog name with a hover tooltip. Translucent lighter-blue overlay panel
  (instead of opaque sidebar) so the canvas remains visible behind. HIGH
  strata so room buttons can't bleed through.

* Projects → Architect: Plan-mode budget impact preview. Rooms meter shows
  a translucent purple "planned" overlay on top of the actual spent bar;
  text suffix reads "→N (+M)" when over budget. Per-shape budget pulled
  from DB2 HouseRoom.WeightCost (closet=1, square_m=12, square_l=20,
  octagon_l=16, etc.) so totals match GetSpentPlacementBudget exactly.
  Decor count meter (GetNumDecorPlaced) added in Reflect, hidden in Plan.
  Floor + house room-count chip top of canvas.

* Projects → Architect: room-scoped Crates. Each room gains a Crates section
  in the right-side detail pane; "+ New crate" mints a path-keyed crate and
  opens a detail editor (rename, member list, "+ Add decor by ID", remove
  buttons). Crates persist via the new Collection_* API and survive reloads.
  Decor Preview rows now accept Ctrl+Right-click to drop the row's item into
  any crate via a context menu grouped by room. Plain right-click still
  toggles favorite — the existing UX is preserved.

* Style Curator + Smart Set Builder: cleaner split between the two surfaces.
  Style Creator is renamed Smart Set Builder and is now Smart-only — the
  Curated mode pill is gone, and new styles always start as smart filters.
  Curated style creation, editing, renaming, duplicating, and deleting all
  live in the Style Curator now (right-click any target row for the menu).
  Hero card subtitles on the Styles landing reframed to reflect the split.
  Existing curated styles still open in the legacy editor view from the
  landing list for backward compat, but the toggle is gone.

* Projects → Architect: clean rewrite of the room-layout pipeline. Pin-frame
  data → player-cardinals via a single N↔S flip in FP.facingToCardinal
  (Blizzard builds N→S internally but the editor view flips that axis on
  screen). Replaced the two-phase BFS+DFS, rotation deducer, and
  synthetic-door injection (~360 lines + a whole module) with a single-pass
  BFS that reads captured door multisets directly. Pin frames only emit
  internal connection doors and IsOccupiedDoor() honestly flags the
  connected ones — the earlier confusion was the missing axis flip, not a
  Blizzard bug. TopologyCapture now stores doorCardinals (every slot,
  drives orb rendering) and occupiedCardinals (real connections, drives
  BFS). Canvas anchors its host at the bottom so Entry sits at canvas south
  and rooms fan upward. CaptureAllFloors forces a Decorate→Layout toggle
  so pin frames re-emit on the first click; passive _onModeChanged
  early-returns during a sweep so the toggle can't race the capture.
  Removed: HDG_RotationDeducer, _preprocessImplicitDoors, the Entry-N
  hardcode override.

* Style Creator: new "Audit" mode lets you triage decor that isn't in any
  of your custom curated styles, fan items out into existing styles via
  instant-assign with an undo strip, and audit existing style contents.
  Filter the grid by Blizzard catalog category chips (Structural,
  Furnishings → Seating, etc.). Coverage progress bar tracks the
  shrinking gap as you triage. Multi-select via shift/ctrl/alt-click
  for bulk-add. Inline "+ New style" affordance creates a target style
  mid-session. (Synthea1979 request — for collections of 2000+ items
  where it's hard to spot what hasn't been categorised yet.)

* Note (root cause for v2.39.1): traced to BigWigsMods/WoWUI commit
  d0877949df, patch 12.0.5.67088 (2026-04-22). That patch added a new
  Blizzard_HousingMarketProductDisplay.lua and inserted a synchronous
  RestoreFilterAndFocusState call as the first line of
  HouseEditorStorageFrameMixin.OnTabChanged. RestoreFilterAndFocusState
  cascades into ScrollBox SetDataProvider → product card Init → calls
  CatalogShopUtil.GetProductInfo (async, returns nil before
  CATALOG_SHOP_DATA_REFRESH). The next ScrollBox Update runs Layout
  on the same card and indexes self.productInfo.catalogShopProductID
  on the nil. Any addon that holds a long-lived
  C_HousingCatalog.CreateCatalogSearcher delays the market fetch
  enough to expose this; bare client wins the race. This is a Blizzard
  bug — Layout/Init in the new mixin lack a nil guard. Re-enabling
  HDG's inline HE-storage-panel tab is gated on a Blizzard fix.
  Documented at Reference/HOUSING_CATALOG_API.md (Catalog Tab Gotcha
  section) and in the wow-api MCP under
  HouseEditorStorageFrameMixin.RestoreFilterAndFocusState,
  HousingMarketProductDisplayMixin, and
  CatalogShopDefaultProductCardMixin.Layout.