diff --git a/Core/CategoryManager.lua b/Core/CategoryManager.lua index e434ac4..38c0b86 100644 --- a/Core/CategoryManager.lua +++ b/Core/CategoryManager.lua @@ -52,13 +52,21 @@ end -- texturePattern: Match icon texture path -- itemID: Specific item IDs (table of IDs) +-- Group constants +local GROUP_MAIN = "Main" +local GROUP_OTHER = "Other" +local GROUP_CLASS = "Class" + -- Default category definitions that replicate the existing hardcoded behavior local DEFAULT_CATEGORIES = { order = { - "Home", "BoE", "Weapon", "Armor", "Consumable", "Food", "Drink", + "BoE", "Weapon", "Armor", "Consumable", "Food", "Drink", "Trade Goods", "Reagent", "Recipe", "Quiver", "Container", - "Soul Bag", "Miscellaneous", "Quest", "Junk", "Class Items", "Keyring" + "Soul Bag", "Miscellaneous", "Quest", "Junk", + "Class Items", "Keyring", + "Home", "Tools", "Empty" }, + itemOverrides = {}, -- flat map: [itemID] = categoryId definitions = { ["BoE"] = { name = "BoE", @@ -70,6 +78,7 @@ local DEFAULT_CATEGORIES = { priority = 75, enabled = true, isBuiltIn = true, + group = GROUP_MAIN, }, ["Weapon"] = { name = "Weapon", @@ -81,6 +90,7 @@ local DEFAULT_CATEGORIES = { priority = 70, enabled = true, isBuiltIn = true, + group = GROUP_MAIN, }, ["Armor"] = { name = "Armor", @@ -92,6 +102,7 @@ local DEFAULT_CATEGORIES = { priority = 70, enabled = true, isBuiltIn = true, + group = GROUP_MAIN, }, ["Consumable"] = { name = "Consumable", @@ -103,6 +114,7 @@ local DEFAULT_CATEGORIES = { priority = 50, enabled = true, isBuiltIn = true, + group = GROUP_MAIN, }, ["Food"] = { name = "Food", @@ -115,6 +127,7 @@ local DEFAULT_CATEGORIES = { priority = 55, enabled = true, isBuiltIn = true, + group = GROUP_MAIN, }, ["Drink"] = { name = "Drink", @@ -127,6 +140,7 @@ local DEFAULT_CATEGORIES = { priority = 55, enabled = true, isBuiltIn = true, + group = GROUP_MAIN, }, ["Trade Goods"] = { name = "Trade Goods", @@ -138,6 +152,7 @@ local DEFAULT_CATEGORIES = { priority = 40, enabled = true, isBuiltIn = true, + group = GROUP_MAIN, }, ["Reagent"] = { name = "Reagent", @@ -149,6 +164,7 @@ local DEFAULT_CATEGORIES = { priority = 40, enabled = true, isBuiltIn = true, + group = GROUP_MAIN, }, ["Recipe"] = { name = "Recipe", @@ -160,6 +176,7 @@ local DEFAULT_CATEGORIES = { priority = 40, enabled = true, isBuiltIn = true, + group = GROUP_MAIN, }, ["Quiver"] = { name = "Quiver", @@ -171,6 +188,7 @@ local DEFAULT_CATEGORIES = { priority = 40, enabled = true, isBuiltIn = true, + group = GROUP_MAIN, }, ["Container"] = { name = "Container", @@ -182,6 +200,7 @@ local DEFAULT_CATEGORIES = { priority = 40, enabled = true, isBuiltIn = true, + group = GROUP_MAIN, }, ["Soul Bag"] = { name = "Soul Bag", @@ -193,6 +212,7 @@ local DEFAULT_CATEGORIES = { priority = 45, enabled = true, isBuiltIn = true, + group = GROUP_MAIN, }, ["Miscellaneous"] = { name = "Miscellaneous", @@ -203,6 +223,7 @@ local DEFAULT_CATEGORIES = { enabled = true, isBuiltIn = true, isFallback = true, + group = GROUP_MAIN, }, ["Quest"] = { name = "Quest", @@ -214,6 +235,7 @@ local DEFAULT_CATEGORIES = { priority = 80, enabled = true, isBuiltIn = true, + group = GROUP_MAIN, }, ["Junk"] = { name = "Junk", @@ -225,17 +247,20 @@ local DEFAULT_CATEGORIES = { priority = 85, enabled = true, isBuiltIn = true, + group = GROUP_MAIN, }, ["Class Items"] = { name = "Class Items", icon = "Interface\\Icons\\INV_Misc_Ammo_Arrow_01", rules = { - { type = "itemType", value = "Projectile" } + { type = "itemType", value = "Projectile" }, + { type = "isSoulShard", value = true } }, matchMode = "any", priority = 90, enabled = true, isBuiltIn = true, + group = GROUP_CLASS, }, ["Keyring"] = { name = "Keyring", @@ -247,20 +272,56 @@ local DEFAULT_CATEGORIES = { priority = 40, enabled = true, isBuiltIn = true, + group = GROUP_CLASS, }, ["Home"] = { name = "Home", icon = "Interface\\Icons\\INV_Misc_Rune_01", + rules = { + { type = "itemID", value = {6948} } + }, + matchMode = "all", + priority = 100, + enabled = true, + isBuiltIn = true, + group = GROUP_OTHER, + }, + ["Tools"] = { + name = "Tools", + icon = "Interface\\Icons\\Trade_BlackSmithing", + rules = { + { type = "isProfessionTool", value = true } + }, + matchMode = "all", + priority = 60, + enabled = true, + isBuiltIn = true, + group = GROUP_OTHER, + }, + ["Empty"] = { + name = "Empty", + icon = "Interface\\PaperDoll\\UI-PaperDoll-Slot-Bag", rules = {}, matchMode = "all", - priority = 0, + priority = -10, enabled = true, isBuiltIn = true, hideControls = true, + isEmptyCategory = true, + group = GROUP_OTHER, }, } } +-- Group definitions for display order and built-in group mapping +local GROUP_ORDER = { GROUP_MAIN, GROUP_CLASS, GROUP_OTHER } + +-- Map of built-in category IDs to their default groups (for migration) +local BUILTIN_GROUP_MAP = {} +for id, def in pairs(DEFAULT_CATEGORIES.definitions) do + BUILTIN_GROUP_MAP[id] = def.group +end + -- Deep copy a table local function deepCopy(orig) local copy @@ -404,6 +465,130 @@ function CategoryManager:MigrateCategories() addon:Debug("CategoryManager: Migrated Junk category to use isJunk rule") end end + + -- Migrate: Add group to all categories that lack it + for id, def in pairs(cats.definitions) do + if not def.group then + -- Use built-in mapping if available, otherwise default to Main + def.group = BUILTIN_GROUP_MAP[id] or GROUP_MAIN + addon:Debug("CategoryManager: Added group '%s' to category: %s", def.group, id) + end + end + + -- Migrate: Convert per-category itemOverrides arrays to flat map at categories level + if not cats.itemOverrides then + cats.itemOverrides = {} + end + local migratedOverrides = false + for catId, def in pairs(cats.definitions) do + if def.itemOverrides and type(def.itemOverrides) == "table" then + -- Check if it's an array (old format) by looking for numeric keys + local isArray = false + for k, v in pairs(def.itemOverrides) do + if type(k) == "number" then + isArray = true + break + end + end + if isArray then + for _, itemID in ipairs(def.itemOverrides) do + cats.itemOverrides[itemID] = catId + migratedOverrides = true + end + def.itemOverrides = nil + end + end + end + if migratedOverrides then + addon:Debug("CategoryManager: Migrated per-category itemOverrides to flat map") + end + + -- Migrate Home category: add rules and remove hideControls + local homeCat = cats.definitions["Home"] + if homeCat and homeCat.isBuiltIn then + -- Remove hideControls + if homeCat.hideControls then + homeCat.hideControls = nil + addon:Debug("CategoryManager: Removed hideControls from Home") + end + -- Add rules if empty + if not homeCat.rules or table.getn(homeCat.rules) == 0 then + homeCat.rules = { { type = "itemID", value = {6948} } } + homeCat.priority = 100 + addon:Debug("CategoryManager: Added itemID rule to Home category") + end + -- Ensure group is Other + if homeCat.group ~= GROUP_OTHER then + homeCat.group = GROUP_OTHER + end + end + + -- Migrate Class Items: add isSoulShard rule if missing + local classItemsCat = cats.definitions["Class Items"] + if classItemsCat and classItemsCat.isBuiltIn then + local hasSoulShard = false + if classItemsCat.rules then + for _, rule in ipairs(classItemsCat.rules) do + if rule.type == "isSoulShard" then + hasSoulShard = true + break + end + end + end + if not hasSoulShard then + if not classItemsCat.rules then classItemsCat.rules = {} end + table.insert(classItemsCat.rules, { type = "isSoulShard", value = true }) + classItemsCat.matchMode = "any" + addon:Debug("CategoryManager: Added isSoulShard rule to Class Items") + end + end + + -- Ensure new categories in the order list are in correct positions + -- Check if order needs rebuilding to include new group-based ordering + local hasTools, hasEmpty = false, false + for _, id in ipairs(cats.order) do + if id == "Tools" then hasTools = true end + if id == "Empty" then hasEmpty = true end + end + + -- If Tools or Empty were just added by the built-in migration above, + -- they're already at end of order. Move them to the Other group area. + if hasTools or hasEmpty then + -- Rebuild order to respect groups: Other, Main, Class + local grouped = {} + for _, g in ipairs(GROUP_ORDER) do + grouped[g] = {} + end + grouped["_ungrouped"] = {} + + for _, id in ipairs(cats.order) do + local def = cats.definitions[id] + if def then + local g = def.group or GROUP_MAIN + if grouped[g] then + table.insert(grouped[g], id) + else + table.insert(grouped["_ungrouped"], id) + end + end + end + + -- Rebuild order + local newOrder = {} + for _, g in ipairs(GROUP_ORDER) do + if grouped[g] then + for _, id in ipairs(grouped[g]) do + table.insert(newOrder, id) + end + end + end + for _, id in ipairs(grouped["_ungrouped"]) do + table.insert(newOrder, id) + end + + cats.order = newOrder + addon:Debug("CategoryManager: Rebuilt category order for group ordering") + end end -- Get all categories @@ -438,20 +623,50 @@ function CategoryManager:SaveCategories(categories) end -- Add a new custom category +-- If categoryId is nil, auto-generates a unique ID like "Custom_