commit 5284007998424a3be13ed473bdb1da320ca85901 Author: dfj Date: Thu Jun 4 00:04:49 2026 +0200 Initial publication diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..54efa92 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,35 @@ +# Amibis — WoW TBC Classic Addon + +## What it is +World of Warcraft addon (TBC Classic, Interface 20505) that compares the player's equipped gear against Best-in-Slot lists sourced from wowtbc.gg. + +## Project structure +``` +Amibis/ +├── Amibis.toc # Addon manifest — defines load order +├── Amibis.lua # Core: DB init, item scanning, stat aggregation, gear comparison, slash commands +├── Data/ +│ └── BISLists.lua # BIS data store (class → spec → phase → slot) +└── UI/ + └── ComparisonFrame.lua # Main UI frame, slot rows, stats panel +``` + +## Key facts +- **Load order** is defined in `Amibis.toc`: `Amibis.lua` → `Data/BISLists.lua` → `UI/ComparisonFrame.lua` +- **Slash command**: `/amibis` toggles the UI; `/amibis spec ` overrides auto-detected spec; `/amibis spec clear` resets override +- **SavedVariables**: `AmibisDB` (account-wide, stores selected phase), `AmibisCharDB` (per-character, stores frame position + spec override) +- **Namespace pattern**: `local addonName, ns = ...` — all modules attach to `ns` +- **No build/test/lint tooling** — tested in-game via WoW client +- **Currently**: Only Priest (Discipline/Holy) T5 data populated + +## Adding new BIS data +1. Add a `local CLASS_T5 = { ... }` table in `Data/BISLists.lua` following the existing `PRIEST_T5` structure +2. Register it in `BIS_DATA` under the appropriate class/spec/phase key +3. Each slot entry: `{ itemID, name, source, enchant? }` +4. Ensure class name matches WoW's English class constant (e.g. `"WARRIOR"`, not `"Warrior"`) + +## UI conventions +- ElvUI-style dark backdrop (`{0.07, 0.07, 0.07}`, alpha 0.95) +- Color coding: green = BIS, yellow = upgrade available, gray = empty slot +- Max 17 visible rows; rows are clickable (Shift+click = chat link, Ctrl+click = dress-up) +- Stats panel shows: Healing, Spell Power, Intellect, Spirit, MP5, Haste, Crit diff --git a/Amibis/Amibis.lua b/Amibis/Amibis.lua new file mode 100644 index 0000000..bcadc8f --- /dev/null +++ b/Amibis/Amibis.lua @@ -0,0 +1,389 @@ +local addonName, ns = ... + +local Amibis = {} +ns.Amibis = Amibis +Amibis.version = "1.0.0" + +local DEFAULT_AMIBIS_DB = { + selectedPhase = "T5", +} + +local DEFAULT_AMIBIS_CHAR_DB = { + frameX = nil, + frameY = nil, + framePoint = nil, + frameRelPoint = nil, + overrideSpec = nil, +} + +local function InitializeDB() + if not AmibisDB then + AmibisDB = CopyTable(DEFAULT_AMIBIS_DB) + else + for k, v in pairs(DEFAULT_AMIBIS_DB) do + if AmibisDB[k] == nil then + AmibisDB[k] = v + end + end + end + + if not AmibisCharDB then + AmibisCharDB = CopyTable(DEFAULT_AMIBIS_CHAR_DB) + else + for k, v in pairs(DEFAULT_AMIBIS_CHAR_DB) do + if AmibisCharDB[k] == nil then + AmibisCharDB[k] = v + end + end + end +end + +function Amibis:GetPlayerClass() + return select(2, UnitClass("player")) +end + +function Amibis:GetPlayerSpec() + local class = self:GetPlayerClass() + local specNames = { + ["PRIEST"] = { "Discipline", "Holy", "Shadow" }, + ["MAGE"] = { "Arcane", "Fire", "Frost" }, + ["WARLOCK"] = { "Affliction", "Demonology", "Destruction" }, + ["DRUID"] = { "Balance", "Feral Combat", "Restoration" }, + ["PALADIN"] = { "Holy", "Protection", "Retribution" }, + ["SHAMAN"] = { "Elemental", "Enhancement", "Restoration" }, + ["WARRIOR"] = { "Arms", "Fury", "Protection" }, + ["ROGUE"] = { "Assassination", "Combat", "Subtlety" }, + ["HUNTER"] = { "Beast Mastery", "Marksmanship", "Survival" }, + } + + if not specNames[class] then + return nil + end + + local maxPoints = 0 + local specIndex = 1 + + for i = 1, 3 do + local r1, r2, r3, r4 = GetTalentTabInfo(i) + local points = tonumber(r1) or tonumber(r2) or tonumber(r3) or tonumber(r4) or 0 + if points > maxPoints then + maxPoints = points + specIndex = i + end + end + + return specNames[class][specIndex] +end + +function Amibis:GetEquippedItems() + local items = {} + local slotMap = { + ["Head"] = 1, + ["Neck"] = 2, + ["Shoulder"] = 3, + ["Back"] = 15, + ["Chest"] = 5, + ["Wrist"] = 9, + ["Hands"] = 10, + ["Waist"] = 6, + ["Legs"] = 7, + ["Feet"] = 8, + ["Finger0"] = 11, + ["Finger1"] = 12, + ["Trinket0"] = 13, + ["Trinket1"] = 14, + ["MainHand"] = 16, + ["SecondaryHand"] = 17, + ["Ranged"] = 18, + } + + for slotName, slotID in pairs(slotMap) do + local link = GetInventoryItemLink("player", slotID) + if link then + local itemID = tonumber(link:match("item:(%d+)")) + local name = GetItemInfo(itemID) or "Unknown" + items[slotName] = { + itemID = itemID, + name = name, + link = link, + slotID = slotID, + } + else + items[slotName] = nil + end + end + + return items +end + +local STAT_MAP = { + ["ITEM_MOD_HEALING_DONE_SHORT"] = "healing", + ["ITEM_MOD_SPELL_HEALING_DONE_SHORT"] = "healing", + ["ITEM_MOD_HEALING_DONE"] = "healing", + ["ITEM_MOD_SPELL_HEALING_DONE"] = "healing", + ["ITEM_MOD_DAMAGE_DONE_SHORT"] = "spellDamage", + ["ITEM_MOD_SPELL_DAMAGE_DONE_SHORT"] = "spellDamage", + ["ITEM_MOD_DAMAGE_DONE"] = "spellDamage", + ["ITEM_MOD_SPELL_DAMAGE_DONE"] = "spellDamage", + ["ITEM_MOD_INTELLECT_SHORT"] = "intellect", + ["ITEM_MOD_SPIRIT_SHORT"] = "spirit", + ["ITEM_MOD_STAMINA_SHORT"] = "stamina", + ["ITEM_MOD_MANA_REGENERATION_SHORT"] = "mp5", + ["ITEM_MOD_POWER_REGEN0_SHORT"] = "mp5", + ["ITEM_MOD_HASTE_RATING_SHORT"] = "haste", + ["ITEM_MOD_SPELL_HASTE_RATING_SHORT"] = "haste", + ["ITEM_MOD_SPELL_CRIT_RATING_SHORT"] = "crit", + ["ITEM_MOD_CRIT_RATING_SHORT"] = "crit", + ["ITEM_MOD_SPELL_POWER_SHORT"] = "spellPower", + ["ITEM_MOD_SPELL_DMG_SHORT"] = "spellDamage", + ["ITEM_MOD_HEALING_SHORT"] = "healing", +} + +function Amibis:ScanItemStats(itemID) + if not itemID then return nil end + + local _, link = GetItemInfo(itemID) + if not link then + link = "item:" .. itemID .. ":0:0:0:0:0:0:0:0" + end + + local stats = GetItemStats(link) + if not stats then return nil end + + local result = {} + for wowKey, ourKey in pairs(STAT_MAP) do + if stats[wowKey] then + result[ourKey] = (result[ourKey] or 0) + stats[wowKey] + end + end + + return result +end + +function Amibis:AggregateStats(items) + local totals = { + healing = 0, + spellDamage = 0, + intellect = 0, + spirit = 0, + stamina = 0, + mp5 = 0, + haste = 0, + crit = 0, + spellPower = 0, + } + + for slotName, item in pairs(items) do + if item and item.itemID then + local stats = self:ScanItemStats(item.itemID) + if stats then + for k, v in pairs(stats) do + totals[k] = (totals[k] or 0) + v + end + end + end + end + + return totals +end + +function Amibis:CompareGear() + local class = self:GetPlayerClass() + local spec = AmibisCharDB.overrideSpec or self:GetPlayerSpec() + local phase = AmibisDB.selectedPhase or "T5" + + local bisList = ns.Data.BISLists:GetBISList(class, spec, phase) + if not bisList then + return { + class = class, + spec = spec, + phase = phase, + hasBISList = false, + slots = {}, + bisCount = 0, + totalSlots = 0, + biggestUpgrade = nil, + } + end + + local equipped = self:GetEquippedItems() + local slots = {} + local bisCount = 0 + local totalSlots = 0 + local biggestUpgrade = nil + + for slotName, bisItem in pairs(bisList) do + totalSlots = totalSlots + 1 + local equippedItem = equipped[slotName] + local isBIS = false + + if equippedItem and equippedItem.itemID == bisItem.itemID then + isBIS = true + bisCount = bisCount + 1 + end + + local itemLevelDiff = nil + if equippedItem and not isBIS then + local equippedILvl = GetItemInfo(equippedItem.itemID) and select(4, GetItemInfo(equippedItem.itemID)) + local bisILvl = GetItemInfo(bisItem.itemID) and select(4, GetItemInfo(bisItem.itemID)) + if equippedILvl and bisILvl then + itemLevelDiff = bisILvl - equippedILvl + end + end + + if not isBIS and equippedItem then + if not biggestUpgrade or (itemLevelDiff and biggestUpgrade.itemLevelDiff and itemLevelDiff > biggestUpgrade.itemLevelDiff) then + biggestUpgrade = { + slot = slotName, + equipped = equippedItem, + bis = bisItem, + itemLevelDiff = itemLevelDiff, + } + elseif not biggestUpgrade then + biggestUpgrade = { + slot = slotName, + equipped = equippedItem, + bis = bisItem, + itemLevelDiff = itemLevelDiff, + } + end + elseif not isBIS and not biggestUpgrade then + biggestUpgrade = { + slot = slotName, + equipped = nil, + bis = bisItem, + itemLevelDiff = nil, + } + end + + table.insert(slots, { + slotName = slotName, + equipped = equippedItem, + bis = bisItem, + isBIS = isBIS, + itemLevelDiff = itemLevelDiff, + }) + end + + table.sort(slots, function(a, b) + if a.isBIS ~= b.isBIS then + return b.isBIS + end + return a.slotName < b.slotName + end) + + local equippedStats = self:AggregateStats(equipped) + + for slotName, bisItem in pairs(bisList) do + GetItemInfo(bisItem.itemID) + end + + local bisItems = {} + for slotName, bisItem in pairs(bisList) do + bisItems[slotName] = { itemID = bisItem.itemID } + end + local bisStats = self:AggregateStats(bisItems) + + local statsComplete = true + for slotName, bisItem in pairs(bisList) do + local _, link = GetItemInfo(bisItem.itemID) + if link then + local s = GetItemStats(link) + if not s or not next(s) then + statsComplete = false + break + end + else + statsComplete = false + break + end + end + + return { + class = class, + spec = spec, + phase = phase, + hasBISList = true, + slots = slots, + bisCount = bisCount, + totalSlots = totalSlots, + biggestUpgrade = biggestUpgrade, + equippedStats = equippedStats, + bisStats = bisStats, + statsComplete = statsComplete, + } +end + +function Amibis:SaveFramePosition(frame) + local point, _, relPoint, x, y = frame:GetPoint() + AmibisCharDB.framePoint = point + AmibisCharDB.frameRelPoint = relPoint + AmibisCharDB.frameX = x + AmibisCharDB.frameY = y +end + +function Amibis:LoadFramePosition(frame) + local point = AmibisCharDB.framePoint + local relPoint = AmibisCharDB.frameRelPoint + local x = AmibisCharDB.frameX + local y = AmibisCharDB.frameY + + if point and x and y then + frame:ClearAllPoints() + frame:SetPoint(point, UIParent, relPoint or point, x, y) + else + frame:SetPoint("CENTER", UIParent, "CENTER", 0, 0) + end +end + +function Amibis:InitializeUI() + if ns.UI and ns.UI.Initialize then + ns.UI.Initialize() + end +end + +function Amibis:ToggleFrame() + if ns.UI and ns.UI.ToggleFrame then + ns.UI.ToggleFrame() + end +end + +local eventFrame = CreateFrame("Frame") +eventFrame:RegisterEvent("ADDON_LOADED") +eventFrame:RegisterEvent("PLAYER_LOGIN") +eventFrame:RegisterEvent("PLAYER_TALENT_UPDATE") + +eventFrame:SetScript("OnEvent", function(self, event, ...) + if event == "ADDON_LOADED" then + local addon = ... + if addon == addonName then + InitializeDB() + end + elseif event == "PLAYER_LOGIN" then + Amibis:InitializeUI() + elseif event == "PLAYER_TALENT_UPDATE" then + if ns.UI and ns.UI.RefreshUI then + ns.UI.RefreshUI() + end + end +end) + +SLASH_AMIBIS1 = "/amibis" +SlashCmdList["AMIBIS"] = function(msg) + local cmd = msg:trim():lower() + if cmd == "" then + Amibis:ToggleFrame() + elseif cmd:find("^spec%s+") then + local spec = cmd:match("^spec%s+(.+)") + if spec and spec ~= "" then + spec = spec:gsub("^%l", string.upper) + AmibisCharDB.overrideSpec = spec + print("Amibis: Spec override set to " .. spec .. ". Type /amibis spec clear to reset.") + end + elseif cmd == "spec clear" then + AmibisCharDB.overrideSpec = nil + print("Amibis: Spec override cleared.") + else + Amibis:ToggleFrame() + end +end diff --git a/Amibis/Amibis.toc b/Amibis/Amibis.toc new file mode 100644 index 0000000..e4563c2 --- /dev/null +++ b/Amibis/Amibis.toc @@ -0,0 +1,11 @@ +## Interface: 20505 +## Title: Amibis +## Notes: Compares your gear against BIS lists from wowtbc.gg +## Version: 1.0.0 +## Author: Amibis +## SavedVariables: AmibisDB +## SavedVariablesPerCharacter: AmibisCharDB + +Amibis.lua +Data/BISLists.lua +UI/ComparisonFrame.lua diff --git a/Amibis/Data/BISLists.lua b/Amibis/Data/BISLists.lua new file mode 100644 index 0000000..2840a75 --- /dev/null +++ b/Amibis/Data/BISLists.lua @@ -0,0 +1,503 @@ +local _, ns = ... +ns.Data = ns.Data or {} +ns.Data.BISLists = {} + +-- ============================================================================= +-- BIS DATA STRUCTURE +-- Keys: CLASS -> SPEC -> PHASE -> SLOT -> { itemID, name, source } +-- Slots: Head, Neck, Shoulder, Back, Chest, Wrist, Hands, Waist, Legs, Feet, +-- Finger0, Finger1, Trinket0, Trinket1, MainHand, SecondaryHand, Ranged +-- ============================================================================= + +-- ============================================================================= +-- PRIEST T5 +-- ============================================================================= +local PRIEST_T5 = { + ["Head"] = { itemID = 30152, name = "Cowl of the Avatar", source = "SSC - Lady Vashj", enchant = { id = 35445, name = "Glyph of Renewal" } }, + ["Neck"] = { itemID = 30018, name = "Lord Sanguinar's Claim", source = "TK - Kael'thas Sunstrider" }, + ["Shoulder"] = { itemID = 30154, name = "Mantle of the Avatar", source = "TK - Void Reaver", enchant = { id = 2717, name = "Greater Inscription of Faith" } }, + ["Back"] = { itemID = 29989, name = "Sunshower Light Cloak", source = "TK - Kael'thas Sunstrider", enchant = { id = 2623, name = "Subtlety" } }, + ["Chest"] = { itemID = 30150, name = "Vestments of the Avatar", source = "TK - Kael'thas Sunstrider", enchant = { id = 2629, name = "Major Spirit" } }, + ["Wrist"] = { itemID = 32516, name = "Wraps of Purification", source = "SSC - Hydross the Unstable", enchant = { id = 1953, name = "Superior Healing" } }, + ["Hands"] = { itemID = 30151, name = "Gloves of the Avatar", source = "SSC - Leotheras the Blind", enchant = { id = 2617, name = "Major Healing" } }, + ["Waist"] = { itemID = 30036, name = "Belt of the Long Road", source = "Tailoring BoE (375)" }, + ["Legs"] = { itemID = 30153, name = "Breeches of the Avatar", source = "SSC - Fathom-Lord Karathress", enchant = { id = 2505, name = "Golden Spellthread" } }, + ["Feet"] = { itemID = 30100, name = "Soul-Strider Boots", source = "SSC - Fathom-Lord Karathress", enchant = { id = 2660, name = "Boar's Speed" } }, + ["Finger0"] = { itemID = 30110, name = "Coral Band of the Revived", source = "SSC - Lady Vashj", enchant = { id = 2675, name = "Healing Power" } }, + ["Finger1"] = { itemID = 29290, name = "Violet Signet of the Grand Restorer", source = "The Violet Eye - Exalted", enchant = { id = 2675, name = "Healing Power" } }, + ["Trinket0"] = { itemID = 29376, name = "Essence of the Martyr", source = "Badge of Justice - G'eras" }, + ["Trinket1"] = { itemID = 30665, name = "Earring of Soulful Meditation", source = "SSC - The Lurker Below" }, + ["MainHand"] = { itemID = 30108, name = "Lightfathom Scepter", source = "SSC - Lady Vashj", enchant = { id = 2673, name = "Major Healing" } }, + ["SecondaryHand"] = { itemID = 29170, name = "Windcaller's Orb", source = "Cenarion Expedition - Exalted" }, + ["Ranged"] = { itemID = 30080, name = "Luminescent Rod of the Naaru", source = "SSC - Morogrim Tidewalker", enchant = { id = 2673, name = "Major Healing" } }, +} + +local PRIEST_SHADOW_T5 = { + ["Head"] = { itemID = 29986, name = "Cowl of the Grand Engineer", source = "TK - Void Reaver", enchant = { id = 35444, name = "Glyph of Power" } }, + ["Neck"] = { itemID = 30666, name = "Ritssyn's Lost Pendant", source = "Karazhan - Trash" }, + ["Shoulder"] = { itemID = 21869, name = "Frozen Shadoweave Shoulders", source = "Tailoring (375)", enchant = { id = 2716, name = "Greater Inscription of Discipline" } }, + ["Back"] = { itemID = 29992, name = "Royal Cloak of the Sunstriders", source = "TK - Kael'thas Sunstrider", enchant = { id = 2623, name = "Subtlety" } }, + ["Chest"] = { itemID = 30107, name = "Vestments of the Sea-Witch", source = "SSC - Lady Vashj", enchant = { id = 2587, name = "Exceptional Stats" } }, + ["Wrist"] = { itemID = 29918, name = "Mindstorm Wristbands", source = "TK - Al'ar", enchant = { id = 2678, name = "Spellpower" } }, + ["Hands"] = { itemID = 28780, name = "Soul-Eater's Handwraps", source = "Magtheridon's Lair - Magtheridon", enchant = { id = 2676, name = "Major Spellpower" } }, + ["Waist"] = { itemID = 30038, name = "Belt of Blasting", source = "Tailoring BoP (375)" }, + ["Legs"] = { itemID = 29972, name = "Trousers of the Astromancer", source = "TK - High Astromancer Solarian", enchant = { id = 2507, name = "Runic Spellthread" } }, + ["Feet"] = { itemID = 21870, name = "Frozen Shadoweave Boots", source = "Tailoring (375)", enchant = { id = 2660, name = "Boar's Speed" } }, + ["Finger0"] = { itemID = 30109, name = "Ring of Endless Coils", source = "SSC - Lady Vashj", enchant = { id = 2676, name = "Spellpower" } }, + ["Finger1"] = { itemID = 29922, name = "Band of Al'ar", source = "TK - Al'ar", enchant = { id = 2676, name = "Spellpower" } }, + ["Trinket0"] = { itemID = 29370, name = "Icon of the Silver Crescent", source = "Badge of Justice - G'eras" }, + ["Trinket1"] = { itemID = 28789, name = "Eye of Magtheridon", source = "Magtheridon's Lair - Magtheridon" }, + ["MainHand"] = { itemID = 28770, name = "Nathrezim Mindblade", source = "Karazhan - Prince Malchezaar", enchant = { id = 2674, name = "Soulfrost" } }, + ["SecondaryHand"] = { itemID = 29272, name = "Orb of the Soul-Eater", source = "Badge of Justice - G'eras" }, + ["Ranged"] = { itemID = 29982, name = "Wand of the Forgotten Star", source = "TK - High Astromancer Solarian" }, +} + +-- ============================================================================= +-- DRUID T5 +-- ============================================================================= +local DRUID_BALANCE_T5 = { + ["Head"] = { itemID = 30233, name = "Nordrassil Headpiece", source = "SSC - Lady Vashj", enchant = { id = 35444, name = "Glyph of Power" } }, + ["Neck"] = { itemID = 30015, name = "The Sun King's Talisman", source = "Quest Reward - Kael'thas and the Verdant Sphere" }, + ["Shoulder"] = { itemID = 30235, name = "Nordrassil Wrath-Mantle", source = "TK - Void Reaver", enchant = { id = 2716, name = "Greater Inscription of Discipline" } }, + ["Back"] = { itemID = 28797, name = "Brute Cloak of the Ogre-Magi", source = "Gruul's Lair - High King Maulgar", enchant = { id = 2623, name = "Subtlety" } }, + ["Chest"] = { itemID = 30231, name = "Nordrassil Chestpiece", source = "TK - Kael'thas Sunstrider", enchant = { id = 2587, name = "Exceptional Stats" } }, + ["Wrist"] = { itemID = 29918, name = "Mindstorm Wristbands", source = "TK - Al'ar", enchant = { id = 2678, name = "Spellpower" } }, + ["Hands"] = { itemID = 30232, name = "Nordrassil Gauntlets", source = "SSC - Leotheras the Blind", enchant = { id = 2676, name = "Major Spellpower" } }, + ["Waist"] = { itemID = 30038, name = "Belt of Blasting", source = "Tailoring BoP (375)" }, + ["Legs"] = { itemID = 24262, name = "Spellstrike Pants", source = "Tailoring BoP (375)", enchant = { id = 2507, name = "Runic Spellthread" } }, + ["Feet"] = { itemID = 30037, name = "Boots of Blasting", source = "Tailoring BoE (375)", enchant = { id = 2660, name = "Boar's Speed" } }, + ["Finger0"] = { itemID = 28753, name = "Ring of Recurrence", source = "Karazhan - Chess Event", enchant = { id = 2676, name = "Spellpower" } }, + ["Finger1"] = { itemID = 29302, name = "Band of Eternity", source = "Quest Reward - The Vials of Eternity", enchant = { id = 2676, name = "Spellpower" } }, + ["Trinket0"] = { itemID = 29370, name = "Icon of the Silver Crescent", source = "Badge of Justice - G'eras" }, + ["Trinket1"] = { itemID = 27683, name = "Quagmirran's Eye", source = "Slave Pens (H) - Quagmirran" }, + ["MainHand"] = { itemID = 29988, name = "The Nexus Key", source = "TK - Kael'thas Sunstrider", enchant = { id = 2677, name = "Sunfire" } }, + ["SecondaryHand"] = { itemID = 30015, name = "The Sun King's Talisman", source = "TK - Kael'thas Sunstrider" }, + ["Ranged"] = { itemID = 27886, name = "Idol of the Raven Goddess", source = "Quest Reward - Vanquish the Raven God" }, +} + +local DRUID_RESTO_T5 = { + ["Head"] = { itemID = 30219, name = "Nordrassil Headguard", source = "SSC - Lady Vashj", enchant = { id = 35445, name = "Glyph of Renewal" } }, + ["Neck"] = { itemID = 30018, name = "Lord Sanguinar's Claim", source = "Quest Reward - Kael'thas and the Verdant Sphere" }, + ["Shoulder"] = { itemID = 30221, name = "Nordrassil Life-Mantle", source = "TK - Void Reaver", enchant = { id = 2717, name = "Greater Inscription of Faith" } }, + ["Back"] = { itemID = 29989, name = "Sunshower Light Cloak", source = "TK - Kael'thas Sunstrider", enchant = { id = 2623, name = "Subtlety" } }, + ["Chest"] = { itemID = 30216, name = "Nordrassil Chestguard", source = "TK - Kael'thas Sunstrider", enchant = { id = 2629, name = "Major Spirit" } }, + ["Wrist"] = { itemID = 30062, name = "Grove-Bands of Remulos", source = "SSC - The Lurker Below", enchant = { id = 1953, name = "Superior Healing" } }, + ["Hands"] = { itemID = 28521, name = "Mitts of the Treemender", source = "Karazhan - Maiden of Virtue", enchant = { id = 2617, name = "Major Healing" } }, + ["Waist"] = { itemID = 30036, name = "Belt of the Long Road", source = "Tailoring BoE (375)" }, + ["Legs"] = { itemID = 28591, name = "Earthsoul Leggings", source = "Karazhan - Opera Event", enchant = { id = 2505, name = "Golden Spellthread" } }, + ["Feet"] = { itemID = 30092, name = "Orca-Hide Boots", source = "SSC - Leotheras the Blind", enchant = { id = 2660, name = "Boar's Speed" } }, + ["Finger0"] = { itemID = 30110, name = "Coral Band of the Revived", source = "SSC - Lady Vashj", enchant = { id = 2675, name = "Healing Power" } }, + ["Finger1"] = { itemID = 28763, name = "Jade Ring of the Everliving", source = "Karazhan - Prince Malchezaar", enchant = { id = 2675, name = "Healing Power" } }, + ["Trinket0"] = { itemID = 29376, name = "Essence of the Martyr", source = "Badge of Justice - G'eras" }, + ["Trinket1"] = { itemID = 30841, name = "Lower City Prayerbook", source = "Lower City - Revered" }, + ["MainHand"] = { itemID = 30108, name = "Lightfathom Scepter", source = "SSC - Lady Vashj", enchant = { id = 2673, name = "Major Healing" } }, + ["SecondaryHand"] = { itemID = 29274, name = "Tears of Heaven", source = "Badge of Justice - G'eras" }, + ["Ranged"] = { itemID = 27886, name = "Idol of the Emerald Queen", source = "Shadow Labyrinth - Ambassador Hellmaw" }, +} + +-- ============================================================================= +-- PALADIN T5 +-- ============================================================================= +local PALADIN_HOLY_T5 = { + ["Head"] = { itemID = 30136, name = "Crystalforge Greathelm", source = "SSC - Lady Vashj", enchant = { id = 35445, name = "Glyph of Renewal" } }, + ["Neck"] = { itemID = 30018, name = "Lord Sanguinar's Claim", source = "Quest Reward - Kael'thas and the Verdant Sphere" }, + ["Shoulder"] = { itemID = 30138, name = "Crystalforge Pauldrons", source = "TK - Void Reaver", enchant = { id = 2717, name = "Greater Inscription of Faith" } }, + ["Back"] = { itemID = 29989, name = "Sunshower Light Cloak", source = "TK - Kael'thas Sunstrider", enchant = { id = 2623, name = "Subtlety" } }, + ["Chest"] = { itemID = 30134, name = "Crystalforge Chestpiece", source = "TK - Kael'thas Sunstrider", enchant = { id = 2602, name = "Restore Mana Prime" } }, + ["Wrist"] = { itemID = 30047, name = "Blackfathom Warbands", source = "SSC - Hydross the Unstable", enchant = { id = 1953, name = "Superior Healing" } }, + ["Hands"] = { itemID = 30112, name = "Glorious Gauntlets of Crestfall", source = "SSC - Lady Vashj", enchant = { id = 2617, name = "Major Healing" } }, + ["Waist"] = { itemID = 30030, name = "Girdle of Fallen Stars", source = "TK - Trash Mobs" }, + ["Legs"] = { itemID = 29991, name = "Sunhawk Leggings", source = "TK - Kael'thas Sunstrider", enchant = { id = 2505, name = "Golden Spellthread" } }, + ["Feet"] = { itemID = 30027, name = "Boots of Courage Unending", source = "SSC - Trash Mobs", enchant = { id = 2660, name = "Boar's Speed" } }, + ["Finger0"] = { itemID = 30110, name = "Coral Band of the Revived", source = "SSC - Lady Vashj", enchant = { id = 2675, name = "Healing Power" } }, + ["Finger1"] = { itemID = 29920, name = "Phoenix-Ring of Rebirth", source = "TK - Al'ar", enchant = { id = 2675, name = "Healing Power" } }, + ["Trinket0"] = { itemID = 29376, name = "Essence of the Martyr", source = "Badge of Justice - G'eras" }, + ["Trinket1"] = { itemID = 28590, name = "Ribbon of Sacrifice", source = "Karazhan - Opera Event" }, + ["MainHand"] = { itemID = 30108, name = "Lightfathom Scepter", source = "SSC - Lady Vashj", enchant = { id = 2673, name = "Major Healing" } }, + ["SecondaryHand"] = { itemID = 29458, name = "Aegis of the Vindicator", source = "Magtheridon's Lair - Magtheridon", enchant = { id = 2655, name = "Intellect" } }, + ["Ranged"] = { itemID = 25644, name = "Blessed Book of Nagrand", source = "Quest Reward - The Ultimate Bloodsport" }, +} + +-- ============================================================================= +-- SHAMAN T5 +-- ============================================================================= +local SHAMAN_ELEMENTAL_T5 = { + ["Head"] = { itemID = 29035, name = "Cyclone Faceguard", source = "Karazhan - Prince Malchezaar", enchant = { id = 35444, name = "Glyph of Power" } }, + ["Neck"] = { itemID = 30015, name = "The Sun King's Talisman", source = "Quest Reward - Kael'thas and the Verdant Sphere" }, + ["Shoulder"] = { itemID = 29037, name = "Cyclone Shoulderguards", source = "Gruul's Lair - High King Maulgar", enchant = { id = 2716, name = "Greater Inscription of Discipline" } }, + ["Back"] = { itemID = 28797, name = "Brute Cloak of the Ogre-Magi", source = "Gruul's Lair - High King Maulgar", enchant = { id = 2623, name = "Subtlety" } }, + ["Chest"] = { itemID = 30169, name = "Cataclysm Chestpiece", source = "TK - Kael'thas Sunstrider", enchant = { id = 2587, name = "Exceptional Stats" } }, + ["Wrist"] = { itemID = 29918, name = "Mindstorm Wristbands", source = "TK - Al'ar", enchant = { id = 2678, name = "Spellpower" } }, + ["Hands"] = { itemID = 28780, name = "Soul-Eater's Handwraps", source = "Magtheridon's Lair - Magtheridon", enchant = { id = 2676, name = "Major Spellpower" } }, + ["Waist"] = { itemID = 30038, name = "Belt of Blasting", source = "Tailoring BoP (375)" }, + ["Legs"] = { itemID = 30172, name = "Cataclysm Leggings", source = "SSC - Fathom-Lord Karathress", enchant = { id = 2507, name = "Runic Spellthread" } }, + ["Feet"] = { itemID = 30067, name = "Velvet Boots of the Guardian", source = "SSC - The Lurker Below", enchant = { id = 2660, name = "Boar's Speed" } }, + ["Finger0"] = { itemID = 30667, name = "Ring of Unrelenting Storms", source = "Karazhan - Trash Drop", enchant = { id = 2676, name = "Spellpower" } }, + ["Finger1"] = { itemID = 30109, name = "Ring of Endless Coils", source = "SSC - Lady Vashj", enchant = { id = 2676, name = "Spellpower" } }, + ["Trinket0"] = { itemID = 28785, name = "The Lightning Capacitor", source = "Karazhan - Terestian Illhoof" }, + ["Trinket1"] = { itemID = 29370, name = "Icon of the Silver Crescent", source = "Badge of Justice - G'eras" }, + ["MainHand"] = { itemID = 29988, name = "The Nexus Key", source = "TK - Kael'thas Sunstrider", enchant = { id = 2679, name = "Major Spellpower" } }, + ["SecondaryHand"] = { itemID = 29988, name = "The Nexus Key", source = "TK - Kael'thas Sunstrider" }, + ["Ranged"] = { itemID = 28248, name = "Totem of the Void", source = "Mechanar - Cache of the Legion" }, +} + +local SHAMAN_ENHANCEMENT_T5 = { + ["Head"] = { itemID = 30190, name = "Cataclysm Helm", source = "SSC - Lady Vashj", enchant = { id = 35446, name = "Glyph of Ferocity" } }, + ["Neck"] = { itemID = 30017, name = "Telonicus's Pendant of Mayhem", source = "Quest Reward - Kael'thas and the Verdant Sphere" }, + ["Shoulder"] = { itemID = 30055, name = "Shoulderpads of the Stranger", source = "SSC - Hydross the Unstable", enchant = { id = 2718, name = "Greater Inscription of Vengeance" } }, + ["Back"] = { itemID = 29994, name = "Thalassian Wildercloak", source = "TK - Kael'thas Sunstrider", enchant = { id = 2621, name = "Greater Agility" } }, + ["Chest"] = { itemID = 30185, name = "Cataclysm Chestplate", source = "TK - Kael'thas Sunstrider", enchant = { id = 2587, name = "Exceptional Stats" } }, + ["Wrist"] = { itemID = 30091, name = "True-Aim Stalker Bands", source = "SSC - Leotheras the Blind", enchant = { id = 2671, name = "Brawn" } }, + ["Hands"] = { itemID = 30189, name = "Cataclysm Gauntlets", source = "SSC - Leotheras the Blind", enchant = { id = 2657, name = "Major Strength" } }, + ["Waist"] = { itemID = 30106, name = "Belt of One-Hundred Deaths", source = "SSC - Lady Vashj" }, + ["Legs"] = { itemID = 30192, name = "Cataclysm Legplates", source = "SSC - Fathom-Lord Karathress", enchant = { id = 2506, name = "Nethercobra Leg Armor" } }, + ["Feet"] = { itemID = 30104, name = "Cobra-Lash Boots", source = "SSC - Lady Vashj", enchant = { id = 2658, name = "Cat's Swiftness" } }, + ["Finger0"] = { itemID = 29997, name = "Band of the Ranger-General", source = "TK - Kael'thas Sunstrider", enchant = { id = 2676, name = "Spellpower" } }, + ["Finger1"] = { itemID = 30052, name = "Ring of Lethality", source = "SSC - Hydross the Unstable", enchant = { id = 2676, name = "Spellpower" } }, + ["Trinket0"] = { itemID = 28830, name = "Dragonspine Trophy", source = "Gruul's Lair - Gruul the Dragonkiller" }, + ["Trinket1"] = { itemID = 29383, name = "Bloodlust Brooch", source = "Badge of Justice - G'eras" }, + ["MainHand"] = { itemID = 32944, name = "Talon of the Phoenix", source = "TK - Al'ar", enchant = { id = 2670, name = "Mongoose" } }, + ["SecondaryHand"] = { itemID = 29996, name = "Rod of the Sun King", source = "TK - Kael'thas Sunstrider", enchant = { id = 2670, name = "Mongoose" } }, + ["Ranged"] = { itemID = 27815, name = "Totem of the Astral Winds", source = "Mana Tombs (H) - Pandemonius" }, +} + +local SHAMAN_RESTO_T5 = { + ["Head"] = { itemID = 30166, name = "Cataclysm Headguard", source = "SSC - Lady Vashj", enchant = { id = 35445, name = "Glyph of Renewal" } }, + ["Neck"] = { itemID = 30018, name = "Lord Sanguinar's Claim", source = "Quest Reward - Kael'thas and the Verdant Sphere" }, + ["Shoulder"] = { itemID = 30168, name = "Cataclysm Shoulderguards", source = "TK - Void Reaver", enchant = { id = 2717, name = "Greater Inscription of Faith" } }, + ["Back"] = { itemID = 29989, name = "Sunshower Light Cloak", source = "TK - Kael'thas Sunstrider", enchant = { id = 2623, name = "Subtlety" } }, + ["Chest"] = { itemID = 30164, name = "Cataclysm Chestguard", source = "TK - Kael'thas Sunstrider", enchant = { id = 2602, name = "Restore Mana Prime" } }, + ["Wrist"] = { itemID = 30047, name = "Blackfathom Warbands", source = "SSC - Hydross the Unstable", enchant = { id = 1953, name = "Superior Healing" } }, + ["Hands"] = { itemID = 29976, name = "Worldstorm Gauntlets", source = "TK - High Astromancer Solarian", enchant = { id = 2617, name = "Major Healing" } }, + ["Waist"] = { itemID = 21873, name = "Primal Mooncloth Belt", source = "Tailoring Trainer (375)" }, + ["Legs"] = { itemID = 29991, name = "Sunhawk Leggings", source = "TK - Kael'thas Sunstrider", enchant = { id = 2505, name = "Golden Spellthread" } }, + ["Feet"] = { itemID = 30092, name = "Orca-Hide Boots", source = "SSC - Leotheras the Blind", enchant = { id = 2660, name = "Boar's Speed" } }, + ["Finger0"] = { itemID = 28763, name = "Jade Ring of the Everliving", source = "Karazhan - Prince Malchezaar", enchant = { id = 2675, name = "Healing Power" } }, + ["Finger1"] = { itemID = 29920, name = "Phoenix-Ring of Rebirth", source = "TK - Al'ar", enchant = { id = 2675, name = "Healing Power" } }, + ["Trinket0"] = { itemID = 29376, name = "Essence of the Martyr", source = "Badge of Justice - G'eras" }, + ["Trinket1"] = { itemID = 28190, name = "Scarab of the Infinite Cycle", source = "Black Morass - Aeonus" }, + ["MainHand"] = { itemID = 30108, name = "Lightfathom Scepter", source = "SSC - Lady Vashj", enchant = { id = 2673, name = "Major Healing" } }, + ["SecondaryHand"] = { itemID = 29458, name = "Aegis of the Vindicator", source = "Magtheridon's Lair - Magtheridon", enchant = { id = 2655, name = "Intellect" } }, + ["Ranged"] = { itemID = 28523, name = "Totem of Healing Rains", source = "Karazhan - Maiden of Virtue" }, +} + +-- ============================================================================= +-- MAGE T5 +-- ============================================================================= +local MAGE_ARCANE_T5 = { + ["Head"] = { itemID = 30206, name = "Cowl of Tirisfal", source = "SSC - Lady Vashj", enchant = { id = 35444, name = "Glyph of Power" } }, + ["Neck"] = { itemID = 30015, name = "The Sun King's Talisman", source = "Quest Reward - Kael'thas and the Verdant Sphere" }, + ["Shoulder"] = { itemID = 30210, name = "Mantle of Tirisfal", source = "TK - Void Reaver", enchant = { id = 2715, name = "Greater Inscription of the Orb" } }, + ["Back"] = { itemID = 29992, name = "Royal Cloak of the Sunstriders", source = "TK - Kael'thas Sunstrider", enchant = { id = 2623, name = "Subtlety" } }, + ["Chest"] = { itemID = 30196, name = "Robes of Tirisfal", source = "TK - Kael'thas Sunstrider", enchant = { id = 2587, name = "Exceptional Stats" } }, + ["Wrist"] = { itemID = 29918, name = "Mindstorm Wristbands", source = "TK - Al'ar", enchant = { id = 2678, name = "Spellpower" } }, + ["Hands"] = { itemID = 29987, name = "Gauntlets of the Sun King", source = "TK - Kael'thas Sunstrider", enchant = { id = 2676, name = "Major Spellpower" } }, + ["Waist"] = { itemID = 30038, name = "Belt of Blasting", source = "Tailoring BoP (375)" }, + ["Legs"] = { itemID = 30207, name = "Leggings of Tirisfal", source = "SSC - Fathom-Lord Karathress", enchant = { id = 2507, name = "Runic Spellthread" } }, + ["Feet"] = { itemID = 30067, name = "Velvet Boots of the Guardian", source = "SSC - The Lurker Below", enchant = { id = 2660, name = "Boar's Speed" } }, + ["Finger0"] = { itemID = 29287, name = "Violet Signet of the Archmage", source = "The Violet Eye - Exalted", enchant = { id = 2676, name = "Spellpower" } }, + ["Finger1"] = { itemID = 29302, name = "Band of Eternity", source = "Quest Reward - The Vials of Eternity", enchant = { id = 2676, name = "Spellpower" } }, + ["Trinket0"] = { itemID = 29370, name = "Icon of the Silver Crescent", source = "Badge of Justice - G'eras" }, + ["Trinket1"] = { itemID = 30720, name = "Serpent-Coil Braid", source = "SSC - Morogrim Tidewalker" }, + ["MainHand"] = { itemID = 29988, name = "The Nexus Key", source = "TK - Kael'thas Sunstrider", enchant = { id = 2677, name = "Sunfire" } }, + ["SecondaryHand"] = { itemID = 29988, name = "The Nexus Key", source = "TK - Kael'thas Sunstrider" }, + ["Ranged"] = { itemID = 28783, name = "Eredar Wand of Obliteration", source = "Magtheridon's Lair - Magtheridon" }, +} + +local MAGE_FIRE_T5 = { + ["Head"] = { itemID = 30206, name = "Cowl of Tirisfal", source = "SSC - Lady Vashj", enchant = { id = 35444, name = "Glyph of Power" } }, + ["Neck"] = { itemID = 30015, name = "The Sun King's Talisman", source = "Quest Reward - Kael'thas and the Verdant Sphere" }, + ["Shoulder"] = { itemID = 30210, name = "Mantle of Tirisfal", source = "TK - Void Reaver", enchant = { id = 2716, name = "Greater Inscription of Discipline" } }, + ["Back"] = { itemID = 28797, name = "Brute Cloak of the Ogre-Magi", source = "Gruul's Lair - High King Maulgar", enchant = { id = 2623, name = "Subtlety" } }, + ["Chest"] = { itemID = 30107, name = "Vestments of the Sea-Witch", source = "SSC - Lady Vashj", enchant = { id = 2587, name = "Exceptional Stats" } }, + ["Wrist"] = { itemID = 29918, name = "Mindstorm Wristbands", source = "TK - Al'ar", enchant = { id = 2678, name = "Spellpower" } }, + ["Hands"] = { itemID = 21847, name = "Spellfire Gloves", source = "Tailoring Trainer (375)", enchant = { id = 2676, name = "Major Spellpower" } }, + ["Waist"] = { itemID = 30038, name = "Belt of Blasting", source = "Tailoring BoP (375)" }, + ["Legs"] = { itemID = 24262, name = "Spellstrike Pants", source = "Tailoring BoP (375)", enchant = { id = 2507, name = "Runic Spellthread" } }, + ["Feet"] = { itemID = 30037, name = "Boots of Blasting", source = "Tailoring BoE (375)", enchant = { id = 2660, name = "Boar's Speed" } }, + ["Finger0"] = { itemID = 29302, name = "Band of Eternity", source = "Quest Reward - The Vials of Eternity", enchant = { id = 2676, name = "Spellpower" } }, + ["Finger1"] = { itemID = 28753, name = "Ring of Recurrence", source = "Karazhan - Chess Event", enchant = { id = 2676, name = "Spellpower" } }, + ["Trinket0"] = { itemID = 29370, name = "Icon of the Silver Crescent", source = "Badge of Justice - G'eras" }, + ["Trinket1"] = { itemID = 30626, name = "Sextant of Unstable Currents", source = "SSC - Fathom-Lord Karathress" }, + ["MainHand"] = { itemID = 30095, name = "Fang of the Leviathan", source = "SSC - Leotheras the Blind", enchant = { id = 2677, name = "Sunfire" } }, + ["SecondaryHand"] = { itemID = 29270, name = "Flametongue Seal", source = "Badge of Justice - G'eras" }, + ["Ranged"] = { itemID = 29982, name = "Wand of the Forgotten Star", source = "TK - High Astromancer Solarian" }, +} + +local MAGE_FROST_T5 = { + ["Head"] = { itemID = 30206, name = "Cowl of Tirisfal", source = "SSC - Lady Vashj", enchant = { id = 35444, name = "Glyph of Power" } }, + ["Neck"] = { itemID = 30015, name = "The Sun King's Talisman", source = "Quest Reward - Kael'thas and the Verdant Sphere" }, + ["Shoulder"] = { itemID = 30210, name = "Mantle of Tirisfal", source = "TK - Void Reaver", enchant = { id = 2716, name = "Greater Inscription of Discipline" } }, + ["Back"] = { itemID = 28797, name = "Brute Cloak of the Ogre-Magi", source = "Gruul's Lair - High King Maulgar", enchant = { id = 2623, name = "Subtlety" } }, + ["Chest"] = { itemID = 30107, name = "Vestments of the Sea-Witch", source = "SSC - Lady Vashj", enchant = { id = 2587, name = "Exceptional Stats" } }, + ["Wrist"] = { itemID = 29918, name = "Mindstorm Wristbands", source = "TK - Al'ar", enchant = { id = 2678, name = "Spellpower" } }, + ["Hands"] = { itemID = 28780, name = "Soul-Eater's Handwraps", source = "Magtheridon's Lair - Magtheridon", enchant = { id = 2676, name = "Major Spellpower" } }, + ["Waist"] = { itemID = 30038, name = "Belt of Blasting", source = "Tailoring BoP (375)" }, + ["Legs"] = { itemID = 24262, name = "Spellstrike Pants", source = "Tailoring BoP (375)", enchant = { id = 2507, name = "Runic Spellthread" } }, + ["Feet"] = { itemID = 21870, name = "Frozen Shadoweave Boots", source = "Tailoring Trainer (375)", enchant = { id = 2660, name = "Boar's Speed" } }, + ["Finger0"] = { itemID = 29302, name = "Band of Eternity", source = "Quest Reward - The Vials of Eternity", enchant = { id = 2676, name = "Spellpower" } }, + ["Finger1"] = { itemID = 28753, name = "Ring of Recurrence", source = "Karazhan - Chess Event", enchant = { id = 2676, name = "Spellpower" } }, + ["Trinket0"] = { itemID = 29370, name = "Icon of the Silver Crescent", source = "Badge of Justice - G'eras" }, + ["Trinket1"] = { itemID = 27683, name = "Quagmirran's Eye", source = "Slave Pens (H) - Quagmirran" }, + ["MainHand"] = { itemID = 30095, name = "Fang of the Leviathan", source = "SSC - Leotheras the Blind", enchant = { id = 2677, name = "Sunfire" } }, + ["SecondaryHand"] = { itemID = 29269, name = "Sapphiron's Wing Bone", source = "Badge of Justice - G'eras" }, + ["Ranged"] = { itemID = 29982, name = "Wand of the Forgotten Star", source = "TK - High Astromancer Solarian" }, +} + +-- ============================================================================= +-- WARRIOR T5 +-- ============================================================================= +local WARRIOR_ARMS_T5 = { + ["Head"] = { itemID = 30120, name = "Destroyer Battle-Helm", source = "SSC - Lady Vashj", enchant = { id = 35446, name = "Glyph of Ferocity" } }, + ["Neck"] = { itemID = 30022, name = "Pendant of the Perilous", source = "SSC - Trash Mobs" }, + ["Shoulder"] = { itemID = 30055, name = "Shoulderpads of the Stranger", source = "SSC - Hydross the Unstable", enchant = { id = 2718, name = "Greater Inscription of Vengeance" } }, + ["Back"] = { itemID = 24259, name = "Vengeance Wrap", source = "Tailoring BoE (365)", enchant = { id = 2621, name = "Greater Agility" } }, + ["Chest"] = { itemID = 30118, name = "Destroyer Breastplate", source = "TK - Kael'thas Sunstrider", enchant = { id = 2587, name = "Exceptional Stats" } }, + ["Wrist"] = { itemID = 28795, name = "Bladespire Warbands", source = "Gruul's Lair - High King Maulgar", enchant = { id = 2671, name = "Brawn" } }, + ["Hands"] = { itemID = 30119, name = "Destroyer Gauntlets", source = "SSC - Leotheras the Blind", enchant = { id = 2657, name = "Major Strength" } }, + ["Waist"] = { itemID = 30106, name = "Belt of One-Hundred Deaths", source = "SSC - Lady Vashj" }, + ["Legs"] = { itemID = 30121, name = "Destroyer Greaves", source = "SSC - Fathom-Lord Karathress", enchant = { id = 2506, name = "Nethercobra Leg Armor" } }, + ["Feet"] = { itemID = 30081, name = "Warboots of Obliteration", source = "SSC - Morogrim Tidewalker", enchant = { id = 2658, name = "Cat's Swiftness" } }, + ["Finger0"] = { itemID = 29997, name = "Band of the Ranger-General", source = "TK - Kael'thas Sunstrider", enchant = { id = 2671, name = "Brawn" } }, + ["Finger1"] = { itemID = 30061, name = "Ancestral Ring of Conquest", source = "SSC - The Lurker Below", enchant = { id = 2671, name = "Brawn" } }, + ["Trinket0"] = { itemID = 28830, name = "Dragonspine Trophy", source = "Gruul's Lair - Gruul the Dragonkiller" }, + ["Trinket1"] = { itemID = 29383, name = "Bloodlust Brooch", source = "Badge of Justice - G'eras" }, + ["MainHand"] = { itemID = 29993, name = "Twinblade of the Phoenix", source = "TK - Kael'thas Sunstrider", enchant = { id = 2670, name = "Mongoose" } }, + ["Ranged"] = { itemID = 30105, name = "Serpent Spine Longbow", source = "SSC - Lady Vashj" }, +} + +local WARRIOR_FURY_T5 = { + ["Head"] = { itemID = 30120, name = "Destroyer Battle-Helm", source = "SSC - Lady Vashj", enchant = { id = 35446, name = "Glyph of Ferocity" } }, + ["Neck"] = { itemID = 30022, name = "Pendant of the Perilous", source = "SSC - Trash Mobs" }, + ["Shoulder"] = { itemID = 30122, name = "Destroyer Shoulderblades", source = "TK - Void Reaver", enchant = { id = 2718, name = "Greater Inscription of Vengeance" } }, + ["Back"] = { itemID = 24259, name = "Vengeance Wrap", source = "Tailoring BoE (365)", enchant = { id = 2621, name = "Greater Agility" } }, + ["Chest"] = { itemID = 30118, name = "Destroyer Breastplate", source = "TK - Kael'thas Sunstrider", enchant = { id = 2587, name = "Exceptional Stats" } }, + ["Wrist"] = { itemID = 30057, name = "Bracers of Eradication", source = "SSC - The Lurker Below", enchant = { id = 2671, name = "Brawn" } }, + ["Hands"] = { itemID = 30119, name = "Destroyer Gauntlets", source = "SSC - Leotheras the Blind", enchant = { id = 2657, name = "Major Strength" } }, + ["Waist"] = { itemID = 30106, name = "Belt of One-Hundred Deaths", source = "SSC - Lady Vashj" }, + ["Legs"] = { itemID = 29995, name = "Leggings of Murderous Intent", source = "TK - Kael'thas Sunstrider", enchant = { id = 2506, name = "Nethercobra Leg Armor" } }, + ["Feet"] = { itemID = 30081, name = "Warboots of Obliteration", source = "SSC - Morogrim Tidewalker", enchant = { id = 2658, name = "Cat's Swiftness" } }, + ["Finger0"] = { itemID = 29997, name = "Band of the Ranger-General", source = "TK - Kael'thas Sunstrider", enchant = { id = 2671, name = "Brawn" } }, + ["Finger1"] = { itemID = 28757, name = "Ring of a Thousand Marks", source = "Karazhan - Prince Malchezaar", enchant = { id = 2671, name = "Brawn" } }, + ["Trinket0"] = { itemID = 28830, name = "Dragonspine Trophy", source = "Gruul's Lair - Gruul the Dragonkiller" }, + ["Trinket1"] = { itemID = 30627, name = "Tsunami Talisman", source = "SSC - Leotheras the Blind" }, + ["MainHand"] = { itemID = 28439, name = "Dragonstrike", source = "Blacksmithing Trainer (375)", enchant = { id = 2670, name = "Mongoose" } }, + ["SecondaryHand"] = { itemID = 30082, name = "Talon of Azshara", source = "SSC - Morogrim Tidewalker", enchant = { id = 2670, name = "Mongoose" } }, + ["Ranged"] = { itemID = 30105, name = "Serpent Spine Longbow", source = "SSC - Lady Vashj" }, +} + +local WARRIOR_PROT_T5 = { + ["Head"] = { itemID = 30115, name = "Destroyer Greathelm", source = "SSC - Lady Vashj", enchant = { id = 35446, name = "Glyph of Ferocity" } }, + ["Neck"] = { itemID = 33066, name = "Veteran's Pendant of Triumph", source = "PvP - Honor Points & EotS Marks" }, + ["Shoulder"] = { itemID = 30117, name = "Destroyer Shoulderguards", source = "TK - Void Reaver", enchant = { id = 2718, name = "Greater Inscription of Vengeance" } }, + ["Back"] = { itemID = 29925, name = "Phoenix-Wing Cloak", source = "TK - Al'ar", enchant = { id = 2621, name = "Greater Agility" } }, + ["Chest"] = { itemID = 30113, name = "Destroyer Chestguard", source = "TK - Kael'thas Sunstrider", enchant = { id = 2587, name = "Exceptional Stats" } }, + ["Wrist"] = { itemID = 32818, name = "Veteran's Plate Bracers", source = "PvP - Honor & WSG Marks", enchant = { id = 2653, name = "Fortitude" } }, + ["Hands"] = { itemID = 29947, name = "Gloves of the Searing Grip", source = "TK - Al'ar", enchant = { id = 2659, name = "Threat" } }, + ["Waist"] = { itemID = 30106, name = "Belt of One-Hundred Deaths", source = "SSC - Lady Vashj" }, + ["Legs"] = { itemID = 30116, name = "Destroyer Legguards", source = "SSC - Fathom-Lord Karathress", enchant = { id = 2504, name = "Nethercleft Leg Armor" } }, + ["Feet"] = { itemID = 32793, name = "Veteran's Plate Greaves", source = "PvP - Honor & EotS Marks", enchant = { id = 2660, name = "Boar's Speed" } }, + ["Finger0"] = { itemID = 30834, name = "Shapeshifter's Signet", source = "Lower City - Exalted", enchant = { id = 2671, name = "Brawn" } }, + ["Finger1"] = { itemID = 30083, name = "Ring of Sundered Souls", source = "SSC - Morogrim Tidewalker", enchant = { id = 2671, name = "Brawn" } }, + ["Trinket0"] = { itemID = 28121, name = "Icon of Unyielding Courage", source = "Blood Furnace (H) - Keli'dan the Breaker" }, + ["Trinket1"] = { itemID = 29383, name = "Bloodlust Brooch", source = "Badge of Justice - G'eras" }, + ["MainHand"] = { itemID = 30058, name = "Mallet of the Tides", source = "SSC - The Lurker Below", enchant = { id = 2670, name = "Mongoose" } }, + ["SecondaryHand"] = { itemID = 28825, name = "Aldori Legacy Defender", source = "Gruul's Lair - Gruul the Dragonkiller", enchant = { id = 2652, name = "Major Stamina" } }, + ["Ranged"] = { itemID = 32756, name = "Gyro-Balanced Khorium Destroyer", source = "Engineering Trainer (375)" }, +} + +-- ============================================================================= +-- ROGUE T5 +-- ============================================================================= +local ROGUE_ASSASSINATION_T5 = { + ["Head"] = { itemID = 30146, name = "Deathmantle Helm", source = "SSC - Lady Vashj", enchant = { id = 35446, name = "Glyph of Ferocity" } }, + ["Neck"] = { itemID = 29381, name = "Choker of Vile Intent", source = "Badge of Justice - G'eras" }, + ["Shoulder"] = { itemID = 30149, name = "Deathmantle Shoulderpads", source = "TK - Void Reaver", enchant = { id = 2718, name = "Greater Inscription of Vengeance" } }, + ["Back"] = { itemID = 28672, name = "Drape of the Dark Reavers", source = "Karazhan - Shade of Aran", enchant = { id = 2621, name = "Greater Agility" } }, + ["Chest"] = { itemID = 30101, name = "Bloodsea Brigand's Vest", source = "SSC - Fathom-Lord Karathress", enchant = { id = 2587, name = "Exceptional Stats" } }, + ["Wrist"] = { itemID = 29966, name = "Vambraces of Ending", source = "TK - High Astromancer Solarian", enchant = { id = 2671, name = "Assault" } }, + ["Hands"] = { itemID = 30145, name = "Deathmantle Handguards", source = "SSC - Leotheras the Blind", enchant = { id = 2656, name = "Superior Agility" } }, + ["Waist"] = { itemID = 30106, name = "Belt of One-Hundred Deaths", source = "SSC - Lady Vashj" }, + ["Legs"] = { itemID = 30148, name = "Deathmantle Legguards", source = "SSC - Fathom-Lord Karathress", enchant = { id = 2506, name = "Nethercobra Leg Armor" } }, + ["Feet"] = { itemID = 28545, name = "Edgewalker Longboots", source = "Karazhan - Moroes", enchant = { id = 2658, name = "Cat's Swiftness" } }, + ["Finger0"] = { itemID = 29997, name = "Band of the Ranger-General", source = "TK - Kael'thas Sunstrider", enchant = { id = 2671, name = "Brawn" } }, + ["Finger1"] = { itemID = 30052, name = "Ring of Lethality", source = "SSC - Hydross the Unstable", enchant = { id = 2671, name = "Brawn" } }, + ["Trinket0"] = { itemID = 28830, name = "Dragonspine Trophy", source = "Gruul's Lair - Gruul the Dragonkiller" }, + ["Trinket1"] = { itemID = 30450, name = "Warp-Spring Coil", source = "TK - Void Reaver" }, + ["MainHand"] = { itemID = 30103, name = "Fang of Vashj", source = "SSC - Lady Vashj", enchant = { id = 2670, name = "Mongoose" } }, + ["SecondaryHand"] = { itemID = 29962, name = "Heartrazor", source = "TK - High Astromancer Solarian", enchant = { id = 2670, name = "Mongoose" } }, + ["Ranged"] = { itemID = 29949, name = "Arcanite Steam-Pistol", source = "TK - Al'ar" }, +} + +local ROGUE_COMBAT_T5 = { + ["Head"] = { itemID = 30146, name = "Deathmantle Helm", source = "SSC - Lady Vashj", enchant = { id = 35446, name = "Glyph of Ferocity" } }, + ["Neck"] = { itemID = 29381, name = "Choker of Vile Intent", source = "Badge of Justice - G'eras" }, + ["Shoulder"] = { itemID = 30149, name = "Deathmantle Shoulderpads", source = "TK - Void Reaver", enchant = { id = 2718, name = "Greater Inscription of Vengeance" } }, + ["Back"] = { itemID = 28672, name = "Drape of the Dark Reavers", source = "Karazhan - Shade of Aran", enchant = { id = 2621, name = "Greater Agility" } }, + ["Chest"] = { itemID = 30101, name = "Bloodsea Brigand's Vest", source = "SSC - Fathom-Lord Karathress", enchant = { id = 2587, name = "Exceptional Stats" } }, + ["Wrist"] = { itemID = 29966, name = "Vambraces of Ending", source = "TK - High Astromancer Solarian", enchant = { id = 2671, name = "Assault" } }, + ["Hands"] = { itemID = 30145, name = "Deathmantle Handguards", source = "SSC - Leotheras the Blind", enchant = { id = 2656, name = "Superior Agility" } }, + ["Waist"] = { itemID = 30106, name = "Belt of One-Hundred Deaths", source = "SSC - Lady Vashj" }, + ["Legs"] = { itemID = 30148, name = "Deathmantle Legguards", source = "SSC - Fathom-Lord Karathress", enchant = { id = 2506, name = "Nethercobra Leg Armor" } }, + ["Feet"] = { itemID = 28545, name = "Edgewalker Longboots", source = "Karazhan - Moroes", enchant = { id = 2658, name = "Cat's Swiftness" } }, + ["Finger0"] = { itemID = 29997, name = "Band of the Ranger-General", source = "TK - Kael'thas Sunstrider", enchant = { id = 2671, name = "Brawn" } }, + ["Finger1"] = { itemID = 30052, name = "Ring of Lethality", source = "SSC - Hydross the Unstable", enchant = { id = 2671, name = "Brawn" } }, + ["Trinket0"] = { itemID = 28830, name = "Dragonspine Trophy", source = "Gruul's Lair - Gruul the Dragonkiller" }, + ["Trinket1"] = { itemID = 30450, name = "Warp-Spring Coil", source = "TK - Void Reaver" }, + ["MainHand"] = { itemID = 30082, name = "Talon of Azshara", source = "SSC - Morogrim Tidewalker", enchant = { id = 2670, name = "Mongoose" } }, + ["SecondaryHand"] = { itemID = 28189, name = "Latro's Shifting Sword", source = "Black Morass - Aeonus", enchant = { id = 2670, name = "Mongoose" } }, + ["Ranged"] = { itemID = 29949, name = "Arcanite Steam-Pistol", source = "TK - Al'ar" }, +} + +local ROGUE_SUBTLETY_T5 = ROGUE_COMBAT_T5 + +-- ============================================================================= +-- HUNTER T5 +-- ============================================================================= +local HUNTER_BM_T5 = { + ["Head"] = { itemID = 30141, name = "Rift Stalker Helm", source = "SSC - Lady Vashj", enchant = { id = 35446, name = "Glyph of Ferocity" } }, + ["Neck"] = { itemID = 30017, name = "Telonicus's Pendant of Mayhem", source = "Quest Reward - Kael'thas and the Verdant Sphere" }, + ["Shoulder"] = { itemID = 30143, name = "Rift Stalker Mantle", source = "TK - Void Reaver", enchant = { id = 2718, name = "Greater Inscription of Vengeance" } }, + ["Back"] = { itemID = 29994, name = "Thalassian Wildercloak", source = "TK - Kael'thas Sunstrider", enchant = { id = 2621, name = "Greater Agility" } }, + ["Chest"] = { itemID = 30139, name = "Rift Stalker Hauberk", source = "TK - Kael'thas Sunstrider", enchant = { id = 2587, name = "Exceptional Stats" } }, + ["Wrist"] = { itemID = 29966, name = "Vambraces of Ending", source = "TK - High Astromancer Solarian", enchant = { id = 2671, name = "Assault" } }, + ["Hands"] = { itemID = 30140, name = "Rift Stalker Gauntlets", source = "SSC - Leotheras the Blind", enchant = { id = 2656, name = "Superior Agility" } }, + ["Waist"] = { itemID = 30040, name = "Belt of Deep Shadow", source = "Leatherworking BoP (375)" }, + ["Legs"] = { itemID = 29995, name = "Leggings of Murderous Intent", source = "TK - Kael'thas Sunstrider", enchant = { id = 2506, name = "Nethercobra Leg Armor" } }, + ["Feet"] = { itemID = 30104, name = "Cobra-Lash Boots", source = "SSC - Lady Vashj", enchant = { id = 2658, name = "Cat's Swiftness" } }, + ["Finger0"] = { itemID = 29997, name = "Band of the Ranger-General", source = "TK - Kael'thas Sunstrider", enchant = { id = 2671, name = "Brawn" } }, + ["Finger1"] = { itemID = 28791, name = "Ring of the Recalcitrant", source = "Quest Reward - The Fall of Magtheridon", enchant = { id = 2671, name = "Brawn" } }, + ["Trinket0"] = { itemID = 28830, name = "Dragonspine Trophy", source = "Gruul's Lair - Gruul the Dragonkiller" }, + ["Trinket1"] = { itemID = 29383, name = "Bloodlust Brooch", source = "Badge of Justice - G'eras" }, + ["MainHand"] = { itemID = 29993, name = "Twinblade of the Phoenix", source = "TK - Kael'thas Sunstrider", enchant = { id = 2669, name = "Major Agility" } }, + ["Ranged"] = { itemID = 30105, name = "Serpent Spine Longbow", source = "SSC - Lady Vashj", enchant = { id = 23766, name = "Stabilized Eternium Scope" } }, +} + +local HUNTER_MM_T5 = HUNTER_BM_T5 + +local HUNTER_SURVIVAL_T5 = { + ["Head"] = { itemID = 30141, name = "Rift Stalker Helm", source = "SSC - Lady Vashj", enchant = { id = 35446, name = "Glyph of Ferocity" } }, + ["Neck"] = { itemID = 30017, name = "Telonicus's Pendant of Mayhem", source = "Quest Reward - Kael'thas and the Verdant Sphere" }, + ["Shoulder"] = { itemID = 30143, name = "Rift Stalker Mantle", source = "TK - Void Reaver", enchant = { id = 2715, name = "Greater Inscription of the Blade" } }, + ["Back"] = { itemID = 29994, name = "Thalassian Wildercloak", source = "TK - Kael'thas Sunstrider", enchant = { id = 2621, name = "Greater Agility" } }, + ["Chest"] = { itemID = 30139, name = "Rift Stalker Hauberk", source = "TK - Kael'thas Sunstrider", enchant = { id = 2587, name = "Exceptional Stats" } }, + ["Wrist"] = { itemID = 29966, name = "Vambraces of Ending", source = "TK - High Astromancer Solarian", enchant = { id = 2663, name = "Stats" } }, + ["Hands"] = { itemID = 28506, name = "Gloves of Dexterous Manipulation", source = "Karazhan - Attumen the Huntsman", enchant = { id = 2656, name = "Superior Agility" } }, + ["Waist"] = { itemID = 30040, name = "Belt of Deep Shadow", source = "Leatherworking BoP (375)" }, + ["Legs"] = { itemID = 30142, name = "Rift Stalker Leggings", source = "SSC - Fathom-Lord Karathress", enchant = { id = 2506, name = "Nethercobra Leg Armor" } }, + ["Feet"] = { itemID = 30104, name = "Cobra-Lash Boots", source = "SSC - Lady Vashj", enchant = { id = 2654, name = "Dexterity" } }, + ["Finger0"] = { itemID = 29302, name = "Band of Eternity", source = "Quest Reward - The Vials of Eternity", enchant = { id = 2663, name = "Stats" } }, + ["Finger1"] = { itemID = 28791, name = "Ring of the Recalcitrant", source = "Quest Reward - The Fall of Magtheridon", enchant = { id = 2663, name = "Stats" } }, + ["Trinket0"] = { itemID = 28830, name = "Dragonspine Trophy", source = "Gruul's Lair - Gruul the Dragonkiller" }, + ["Trinket1"] = { itemID = 29383, name = "Bloodlust Brooch", source = "Badge of Justice - G'eras" }, + ["MainHand"] = { itemID = 29993, name = "Twinblade of the Phoenix", source = "TK - Kael'thas Sunstrider", enchant = { id = 2669, name = "Major Agility" } }, + ["Ranged"] = { itemID = 30105, name = "Serpent Spine Longbow", source = "SSC - Lady Vashj", enchant = { id = 23766, name = "Stabilized Eternium Scope" } }, +} + +-- ============================================================================= +-- WARLOCK T5 (all specs share same gear) +-- ============================================================================= +local WARLOCK_T5 = { + ["Head"] = { itemID = 30212, name = "Hood of the Corruptor", source = "SSC - Lady Vashj", enchant = { id = 35444, name = "Glyph of Power" } }, + ["Neck"] = { itemID = 30015, name = "The Sun King's Talisman", source = "Quest Reward - Kael'thas and the Verdant Sphere" }, + ["Shoulder"] = { itemID = 28967, name = "Voidheart Mantle", source = "Gruul's Lair - High King Maulgar", enchant = { id = 2716, name = "Greater Inscription of Discipline" } }, + ["Back"] = { itemID = 28766, name = "Ruby Drape of the Mysticant", source = "Karazhan - Prince Malchezaar", enchant = { id = 2623, name = "Subtlety" } }, + ["Chest"] = { itemID = 30107, name = "Vestments of the Sea-Witch", source = "SSC - Lady Vashj", enchant = { id = 2587, name = "Exceptional Stats" } }, + ["Wrist"] = { itemID = 29918, name = "Mindstorm Wristbands", source = "TK - Al'ar", enchant = { id = 2678, name = "Spellpower" } }, + ["Hands"] = { itemID = 28968, name = "Voidheart Gloves", source = "Karazhan - The Curator", enchant = { id = 2676, name = "Major Spellpower" } }, + ["Waist"] = { itemID = 30038, name = "Belt of Blasting", source = "Tailoring BoP (375)" }, + ["Legs"] = { itemID = 30213, name = "Leggings of the Corruptor", source = "SSC - Fathom-Lord Karathress", enchant = { id = 2507, name = "Runic Spellthread" } }, + ["Feet"] = { itemID = 30037, name = "Boots of Blasting", source = "Tailoring BoE (375)", enchant = { id = 2660, name = "Boar's Speed" } }, + ["Finger0"] = { itemID = 30109, name = "Ring of Endless Coils", source = "SSC - Lady Vashj", enchant = { id = 2676, name = "Spellpower" } }, + ["Finger1"] = { itemID = 29302, name = "Band of Eternity", source = "Quest Reward - The Vials of Eternity", enchant = { id = 2676, name = "Spellpower" } }, + ["Trinket0"] = { itemID = 27683, name = "Quagmirran's Eye", source = "Slave Pens (H) - Quagmirran" }, + ["Trinket1"] = { itemID = 29370, name = "Icon of the Silver Crescent", source = "Badge of Justice - G'eras" }, + ["MainHand"] = { itemID = 30095, name = "Fang of the Leviathan", source = "SSC - Leotheras the Blind", enchant = { id = 2674, name = "Soulfrost" } }, + ["SecondaryHand"] = { itemID = 30049, name = "Fathomstone", source = "SSC - Hydross the Unstable" }, + ["Ranged"] = { itemID = 29982, name = "Wand of the Forgotten Star", source = "TK - High Astromancer Solarian" }, +} + +-- ============================================================================= +-- BIS DATA REGISTRY +-- ============================================================================= + +local BIS_DATA = { + ["PRIEST"] = { + ["Discipline"] = { ["T5"] = PRIEST_T5 }, + ["Holy"] = { ["T5"] = PRIEST_T5 }, + ["Shadow"] = { ["T5"] = PRIEST_SHADOW_T5 }, + }, + ["DRUID"] = { + ["Balance"] = { ["T5"] = DRUID_BALANCE_T5 }, + ["Restoration"] = { ["T5"] = DRUID_RESTO_T5 }, + }, + ["PALADIN"] = { + ["Holy"] = { ["T5"] = PALADIN_HOLY_T5 }, + }, + ["SHAMAN"] = { + ["Elemental"] = { ["T5"] = SHAMAN_ELEMENTAL_T5 }, + ["Enhancement"] = { ["T5"] = SHAMAN_ENHANCEMENT_T5 }, + ["Restoration"] = { ["T5"] = SHAMAN_RESTO_T5 }, + }, + ["MAGE"] = { + ["Arcane"] = { ["T5"] = MAGE_ARCANE_T5 }, + ["Fire"] = { ["T5"] = MAGE_FIRE_T5 }, + ["Frost"] = { ["T5"] = MAGE_FROST_T5 }, + }, + ["WARRIOR"] = { + ["Arms"] = { ["T5"] = WARRIOR_ARMS_T5 }, + ["Fury"] = { ["T5"] = WARRIOR_FURY_T5 }, + ["Protection"] = { ["T5"] = WARRIOR_PROT_T5 }, + }, + ["ROGUE"] = { + ["Assassination"] = { ["T5"] = ROGUE_ASSASSINATION_T5 }, + ["Combat"] = { ["T5"] = ROGUE_COMBAT_T5 }, + ["Subtlety"] = { ["T5"] = ROGUE_SUBTLETY_T5 }, + }, + ["HUNTER"] = { + ["Beast Mastery"] = { ["T5"] = HUNTER_BM_T5 }, + ["Marksmanship"] = { ["T5"] = HUNTER_MM_T5 }, + ["Survival"] = { ["T5"] = HUNTER_SURVIVAL_T5 }, + }, + ["WARLOCK"] = { + ["Affliction"] = { ["T5"] = WARLOCK_T5 }, + ["Demonology"] = { ["T5"] = WARLOCK_T5 }, + ["Destruction"] = { ["T5"] = WARLOCK_T5 }, + }, +} + +-- ============================================================================= +-- PUBLIC API +-- ============================================================================= + +function ns.Data.BISLists:GetBISList(class, spec, phase) + if not BIS_DATA[class] then return nil end + if not BIS_DATA[class][spec] then return nil end + return BIS_DATA[class][spec][phase] +end + +function ns.Data.BISLists:GetAvailableClasses() + local classes = {} + for class, _ in pairs(BIS_DATA) do + table.insert(classes, class) + end + return classes +end + +function ns.Data.BISLists:GetAvailableSpecs(class) + if not BIS_DATA[class] then return {} end + local specs = {} + for spec, _ in pairs(BIS_DATA[class]) do + table.insert(specs, spec) + end + return specs +end + +function ns.Data.BISLists:GetAvailablePhases(class, spec) + if not BIS_DATA[class] or not BIS_DATA[class][spec] then return {} end + local phases = {} + for phase, _ in pairs(BIS_DATA[class][spec]) do + table.insert(phases, phase) + end + return phases +end diff --git a/Amibis/UI/ComparisonFrame.lua b/Amibis/UI/ComparisonFrame.lua new file mode 100644 index 0000000..44b1100 --- /dev/null +++ b/Amibis/UI/ComparisonFrame.lua @@ -0,0 +1,561 @@ +local _, ns = ... +ns.UI = ns.UI or {} +local Amibis = ns.Amibis + +ns.UI.Frame = {} + +local ELVUI_BACKDROP_COLOR = { 0.07, 0.07, 0.07 } +local ELVUI_BACKDROP_ALPHA = 0.95 +local ELVUI_BORDER_COLOR = { 0.23, 0.23, 0.23 } +local ELVUI_BORDER_ALPHA = 1.0 +local ELVUI_TITLE_BG = { 0.15, 0.15, 0.15 } + +local COLOR_BIS = { 0.0, 1.0, 0.0 } +local COLOR_UPGRADE = { 1.0, 0.82, 0.0 } +local COLOR_EMPTY = { 0.6, 0.6, 0.6 } + +local MainFrame = nil +local TitleText = nil +local SummaryText = nil +local UpgradeText = nil +local ScrollFrame = nil +local SlotRows = {} +local MAX_VISIBLE_ROWS = 17 +local ROW_HEIGHT = 22 +local ROW_SPACING = 24 + +local function CreateMainFrame() + local frame = CreateFrame("Frame", "AmibisMainFrame", UIParent, "BackdropTemplate") + frame:SetSize(480, 680) + frame:SetFrameStrata("MEDIUM") + frame:SetFrameLevel(10) + + frame:SetBackdrop({ + bgFile = "Interface\\Buttons\\WHITE8x8", + edgeFile = "Interface\\Buttons\\WHITE8x8", + tile = false, + tileSize = 0, + edgeSize = 1, + insets = { left = 0, right = 0, top = 0, bottom = 0 } + }) + frame:SetBackdropColor(ELVUI_BACKDROP_COLOR[1], ELVUI_BACKDROP_COLOR[2], ELVUI_BACKDROP_COLOR[3], ELVUI_BACKDROP_ALPHA) + frame:SetBackdropBorderColor(ELVUI_BORDER_COLOR[1], ELVUI_BORDER_COLOR[2], ELVUI_BORDER_COLOR[3], ELVUI_BORDER_ALPHA) + + frame:SetMovable(true) + frame:EnableMouse(true) + frame:RegisterForDrag("LeftButton") + frame:SetClampedToScreen(true) + + frame:SetScript("OnDragStart", function(self) + self:StartMoving() + end) + frame:SetScript("OnDragStop", function(self) + self:StopMovingOrSizing() + Amibis:SaveFramePosition(self) + end) + + frame:SetPoint("CENTER", UIParent, "CENTER", 0, 0) + return frame +end + +local function CreateTitleBar(parent) + local titleBar = CreateFrame("Frame", nil, parent, "BackdropTemplate") + titleBar:SetPoint("TOPLEFT", parent, "TOPLEFT", 0, 0) + titleBar:SetPoint("TOPRIGHT", parent, "TOPRIGHT", 0, 0) + titleBar:SetHeight(28) + + titleBar:SetBackdrop({ + bgFile = "Interface\\Buttons\\WHITE8x8", + edgeFile = "Interface\\Buttons\\WHITE8x8", + tile = false, + edgeSize = 1, + insets = { left = 0, right = 0, top = 0, bottom = 0 } + }) + titleBar:SetBackdropColor(ELVUI_TITLE_BG[1], ELVUI_TITLE_BG[2], ELVUI_TITLE_BG[3], 1.0) + titleBar:SetBackdropBorderColor(ELVUI_BORDER_COLOR[1], ELVUI_BORDER_COLOR[2], ELVUI_BORDER_COLOR[3], 1.0) + + local titleText = titleBar:CreateFontString(nil, "OVERLAY", "GameFontNormal") + titleText:SetPoint("LEFT", titleBar, "LEFT", 8, 0) + titleText:SetText("Amibis - Gear Comparison") + titleText:SetTextColor(1, 1, 1, 1) + + local closeBtn = CreateFrame("Button", nil, titleBar) + closeBtn:SetSize(20, 20) + closeBtn:SetPoint("RIGHT", titleBar, "RIGHT", -4, 0) + closeBtn:SetText("X") + closeBtn:SetNormalFontObject("GameFontNormal") + closeBtn:SetScript("OnClick", function() + if MainFrame and MainFrame:IsShown() then + MainFrame:Hide() + end + end) + + titleBar:EnableMouse(true) + titleBar:RegisterForDrag("LeftButton") + titleBar:SetScript("OnDragStart", function() + parent:StartMoving() + end) + titleBar:SetScript("OnDragStop", function() + parent:StopMovingOrSizing() + Amibis:SaveFramePosition(parent) + end) + + return titleBar, titleText +end + +local function CreateSummaryBar(parent, anchor) + local bar = CreateFrame("Frame", nil, parent) + bar:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, -4) + bar:SetPoint("TOPRIGHT", anchor, "BOTTOMRIGHT", 0, -4) + bar:SetHeight(20) + + local summaryText = bar:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + summaryText:SetPoint("LEFT", bar, "LEFT", 8, 0) + summaryText:SetTextColor(0.8, 0.8, 0.8, 1) + + local upgradeText = bar:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + upgradeText:SetPoint("BOTTOMLEFT", bar, "TOPLEFT", 8, 2) + upgradeText:SetPoint("BOTTOMRIGHT", bar, "TOPRIGHT", -8, 2) + upgradeText:SetJustifyH("LEFT") + upgradeText:SetTextColor(COLOR_UPGRADE[1], COLOR_UPGRADE[2], COLOR_UPGRADE[3], 1) + + return bar, summaryText, upgradeText +end + +local function CreateColumnHeaders(parent, anchor) + local header = CreateFrame("Frame", nil, parent, "BackdropTemplate") + header:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, -4) + header:SetPoint("TOPRIGHT", anchor, "BOTTOMRIGHT", 0, -4) + header:SetHeight(18) + + header:SetBackdrop({ + bgFile = "Interface\\Buttons\\WHITE8x8", + edgeFile = "Interface\\Buttons\\WHITE8x8", + edgeSize = 1, + insets = { left = 0, right = 0, top = 0, bottom = 0 } + }) + header:SetBackdropColor(0.12, 0.12, 0.12, 0.5) + + local slotHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + slotHeader:SetPoint("LEFT", header, "LEFT", 8, 0) + slotHeader:SetWidth(55) + slotHeader:SetJustifyH("LEFT") + slotHeader:SetText("Slot") + slotHeader:SetTextColor(0.7, 0.7, 0.7, 1) + + local equippedHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + equippedHeader:SetPoint("LEFT", slotHeader, "RIGHT", 5, 0) + equippedHeader:SetWidth(115) + equippedHeader:SetJustifyH("LEFT") + equippedHeader:SetText("Equipped") + equippedHeader:SetTextColor(0.7, 0.7, 0.7, 1) + + local bisHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + bisHeader:SetPoint("LEFT", equippedHeader, "RIGHT", 5, 0) + bisHeader:SetWidth(115) + bisHeader:SetJustifyH("LEFT") + bisHeader:SetText("BIS Item") + bisHeader:SetTextColor(0.7, 0.7, 0.7, 1) + + local enchantHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + enchantHeader:SetPoint("LEFT", bisHeader, "RIGHT", 5, 0) + enchantHeader:SetWidth(60) + enchantHeader:SetJustifyH("LEFT") + enchantHeader:SetText("Enchant") + enchantHeader:SetTextColor(0.7, 0.7, 0.7, 1) + + local sourceHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + sourceHeader:SetPoint("RIGHT", header, "RIGHT", -8, 0) + sourceHeader:SetWidth(70) + sourceHeader:SetJustifyH("RIGHT") + sourceHeader:SetText("Source") + sourceHeader:SetTextColor(0.7, 0.7, 0.7, 1) + + return header +end + +local function CreateSlotRows(parent, anchor) + local container = CreateFrame("Frame", nil, parent) + container:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, -4) + container:SetPoint("TOPRIGHT", anchor, "BOTTOMRIGHT", 0, -4) + container:SetHeight(MAX_VISIBLE_ROWS * ROW_SPACING) + + for i = 1, MAX_VISIBLE_ROWS do + local row = CreateFrame("Button", nil, container) + row:SetPoint("TOPLEFT", container, "TOPLEFT", 0, -(i - 1) * ROW_SPACING) + row:SetPoint("TOPRIGHT", container, "TOPRIGHT", 0, -(i - 1) * ROW_SPACING) + row:SetHeight(ROW_HEIGHT) + + row.slotText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + row.slotText:SetPoint("LEFT", row, "LEFT", 8, 0) + row.slotText:SetWidth(55) + row.slotText:SetJustifyH("LEFT") + + row.equippedText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + row.equippedText:SetPoint("LEFT", row.slotText, "RIGHT", 5, 0) + row.equippedText:SetWidth(115) + row.equippedText:SetJustifyH("LEFT") + row.equippedText:SetWordWrap(true) + + row.bisText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + row.bisText:SetPoint("LEFT", row.equippedText, "RIGHT", 5, 0) + row.bisText:SetWidth(115) + row.bisText:SetJustifyH("LEFT") + row.bisText:SetWordWrap(true) + + row.enchantText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + row.enchantText:SetPoint("LEFT", row.bisText, "RIGHT", 5, 0) + row.enchantText:SetWidth(60) + row.enchantText:SetJustifyH("LEFT") + + row.sourceText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + row.sourceText:SetPoint("RIGHT", row, "RIGHT", -8, 0) + row.sourceText:SetWidth(70) + row.sourceText:SetJustifyH("RIGHT") + row.sourceText:SetWordWrap(true) + + row:SetScript("OnEnter", function(self) + if self.bisLink then + GameTooltip:SetOwner(self, "ANCHOR_RIGHT") + GameTooltip:SetHyperlink(self.bisLink) + GameTooltip:Show() + end + end) + row:SetScript("OnLeave", function() + GameTooltip:Hide() + end) + row:RegisterForClicks("LeftButtonUp", "RightButtonUp") + row:SetScript("OnClick", function(self, button) + if self.bisLink and button == "LeftButton" then + if IsShiftKeyDown() then + ChatEdit_InsertLink(self.bisLink) + elseif IsControlKeyDown() then + DressUpItemLink(self.bisLink) + end + end + end) + + SlotRows[i] = row + end + + return container +end + +local StatsPanel = nil +local StatsPanelTitle = nil +local StatLabels = {} +local StatValues = {} + +local STAT_DISPLAY = { + { key = "healing", label = "+Healing" }, + { key = "spellPower", label = "+Spell Power" }, + { key = "intellect", label = "Intellect" }, + { key = "spirit", label = "Spirit" }, + { key = "mp5", label = "MP5" }, + { key = "haste", label = "Haste" }, + { key = "crit", label = "Crit" }, +} + +local function CreateStatsPanel(parent, anchor) + local panel = CreateFrame("Frame", nil, parent, "BackdropTemplate") + panel:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, -8) + panel:SetPoint("TOPRIGHT", anchor, "BOTTOMRIGHT", 0, -8) + panel:SetHeight(#STAT_DISPLAY * 16 + 24) + + panel:SetBackdrop({ + bgFile = "Interface\\Buttons\\WHITE8x8", + edgeFile = "Interface\\Buttons\\WHITE8x8", + edgeSize = 1, + insets = { left = 0, right = 0, top = 0, bottom = 0 } + }) + panel:SetBackdropColor(0.1, 0.1, 0.1, 0.6) + panel:SetBackdropBorderColor(0.2, 0.2, 0.2, 1) + + local title = panel:CreateFontString(nil, "OVERLAY", "GameFontNormal") + title:SetPoint("TOPLEFT", panel, "TOPLEFT", 8, -4) + title:SetText("Stats Comparison") + title:SetTextColor(1, 0.82, 0, 1) + StatsPanelTitle = title + + local colW = 60 + local labelW = 80 + local currentX = labelW + 16 + local bisX = currentX + colW + local diffX = bisX + colW + + local currentLabel = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + currentLabel:SetPoint("TOPLEFT", panel, "TOPLEFT", currentX, -4) + currentLabel:SetWidth(colW) + currentLabel:SetJustifyH("CENTER") + currentLabel:SetText("Current") + currentLabel:SetTextColor(0.7, 0.7, 0.7, 1) + + local bisLabel = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + bisLabel:SetPoint("TOPLEFT", panel, "TOPLEFT", bisX, -4) + bisLabel:SetWidth(colW) + bisLabel:SetJustifyH("CENTER") + bisLabel:SetText("BIS") + bisLabel:SetTextColor(0.7, 0.7, 0.7, 1) + + local diffLabel = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + diffLabel:SetPoint("TOPLEFT", panel, "TOPLEFT", diffX, -4) + diffLabel:SetWidth(colW) + diffLabel:SetJustifyH("CENTER") + diffLabel:SetText("Diff") + diffLabel:SetTextColor(0.7, 0.7, 0.7, 1) + + for i, stat in ipairs(STAT_DISPLAY) do + local y = -(i - 1) * 16 - 22 + + local label = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + label:SetPoint("TOPLEFT", panel, "TOPLEFT", 8, y) + label:SetWidth(labelW) + label:SetJustifyH("RIGHT") + label:SetText(stat.label) + label:SetTextColor(0.6, 0.6, 0.6, 1) + + local current = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + current:SetPoint("TOPLEFT", panel, "TOPLEFT", currentX, y) + current:SetWidth(colW) + current:SetJustifyH("CENTER") + current:SetText("0") + current:SetTextColor(1, 0.5, 0.5, 1) + + local bis = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + bis:SetPoint("TOPLEFT", panel, "TOPLEFT", bisX, y) + bis:SetWidth(colW) + bis:SetJustifyH("CENTER") + bis:SetText("0") + bis:SetTextColor(0, 1, 0, 1) + + local diff = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + diff:SetPoint("TOPLEFT", panel, "TOPLEFT", diffX, y) + diff:SetWidth(colW) + diff:SetJustifyH("CENTER") + diff:SetText("0") + diff:SetTextColor(1, 1, 1, 1) + + StatLabels[stat.key] = label + StatValues[stat.key] = { current = current, bis = bis, diff = diff } + end + + StatsPanel = panel + return panel +end + +local function InitializeUI() + if MainFrame then return end + + MainFrame = CreateMainFrame() + local titleBar, title = CreateTitleBar(MainFrame) + TitleText = title + + local summaryBar, summary, upgrade = CreateSummaryBar(MainFrame, titleBar) + SummaryText = summary + UpgradeText = upgrade + + local header = CreateColumnHeaders(MainFrame, summaryBar) + local slotContainer = CreateSlotRows(MainFrame, header) + CreateStatsPanel(MainFrame, slotContainer) + + if AmibisCharDB and AmibisCharDB.frameX then + MainFrame:ClearAllPoints() + Amibis:LoadFramePosition(MainFrame) + end + + MainFrame:Hide() +end + +function ns.UI.Initialize() + InitializeUI() +end + +function ns.UI.ToggleFrame() + if not MainFrame then + InitializeUI() + end + + if MainFrame:IsShown() then + MainFrame:Hide() + if Amibis._statsRetryTimer then + Amibis._statsRetryTimer:Hide() + Amibis._statsRetryTimer = nil + end + else + MainFrame:Show() + ns.UI.RefreshUI() + end +end + +function ns.UI.RefreshUI() + if not MainFrame or not MainFrame:IsShown() then + return + end + + local data = Amibis:CompareGear() + + TitleText:SetText(string.format("Amibis - %s %s (%s)", data.class, data.spec or "Unknown", data.phase)) + + if not data.hasBISList then + SummaryText:SetText(string.format("|cffff6666No BIS list available for %s %s in %s|r", data.class, data.spec or "Unknown", data.phase)) + UpgradeText:SetText("") + for i = 1, MAX_VISIBLE_ROWS do + SlotRows[i].slotText:SetText("") + SlotRows[i].equippedText:SetText("") + SlotRows[i].bisText:SetText("") + SlotRows[i].enchantText:SetText("") + SlotRows[i].sourceText:SetText("") + SlotRows[i].bisLink = nil + end + return + end + + SummaryText:SetText(string.format("BIS: %d/%d slots", data.bisCount, data.totalSlots)) + + if data.biggestUpgrade then + local bu = data.biggestUpgrade + if bu.equipped then + UpgradeText:SetText(string.format("Biggest upgrade: %s -> %s (%s)", bu.equipped.name, bu.bis.name, bu.bis.source)) + else + UpgradeText:SetText(string.format("Empty slot: %s -> %s (%s)", bu.slot, bu.bis.name, bu.bis.source)) + end + else + UpgradeText:SetText("|cff00ff00All slots are BIS!|r") + end + + for i = 1, MAX_VISIBLE_ROWS do + local row = SlotRows[i] + local slotData = data.slots[i] + if slotData then + row.slotText:SetText(slotData.slotName) + row.slotText:SetTextColor(0.7, 0.7, 0.7, 1) + + if slotData.isBIS then + row.equippedText:SetText(slotData.equipped.link or slotData.equipped.name) + row.equippedText:SetTextColor(COLOR_BIS[1], COLOR_BIS[2], COLOR_BIS[3], 1) + row.bisText:SetText("|cff00ff00BIS|r") + row.bisText:SetTextColor(COLOR_BIS[1], COLOR_BIS[2], COLOR_BIS[3], 1) + row.sourceText:SetText(slotData.bis.source) + row.sourceText:SetTextColor(0.5, 0.5, 0.5, 1) + row.bisLink = slotData.equipped and slotData.equipped.link + if slotData.bis.enchant and slotData.equipped then + local hasEnchant = false + local link = slotData.equipped.link + if link then + local parts = {} + for part in link:gmatch("([^:]+)") do + table.insert(parts, part) + end + local enchantID = tonumber(parts[3]) + if enchantID and enchantID > 0 then + hasEnchant = true + end + end + if hasEnchant then + row.enchantText:SetText("|cff00ff00" .. slotData.bis.enchant.name .. "|r") + else + row.enchantText:SetText("|cffff6666" .. slotData.bis.enchant.name .. "|r") + end + elseif slotData.bis.enchant then + row.enchantText:SetText("|cffffcc00" .. slotData.bis.enchant.name .. "|r") + else + row.enchantText:SetText("") + end + else + if slotData.equipped then + row.equippedText:SetText(slotData.equipped.link or slotData.equipped.name) + row.equippedText:SetTextColor(1, 0.5, 0.5, 1) + else + row.equippedText:SetText("|cff666666Empty|r") + row.equippedText:SetTextColor(COLOR_EMPTY[1], COLOR_EMPTY[2], COLOR_EMPTY[3], 1) + end + row.bisText:SetText(slotData.bis.name) + row.bisText:SetTextColor(COLOR_UPGRADE[1], COLOR_UPGRADE[2], COLOR_UPGRADE[3], 1) + row.sourceText:SetText(slotData.bis.source) + row.sourceText:SetTextColor(0.5, 0.5, 0.5, 1) + if slotData.bis.enchant then + row.enchantText:SetText("|cffffcc00" .. slotData.bis.enchant.name .. "|r") + else + row.enchantText:SetText("") + end + local _, bisLink = GetItemInfo(slotData.bis.itemID) + row.bisLink = bisLink or ("|Hitem:" .. slotData.bis.itemID .. ":0:0:0:0:0:0:0:0|h[" .. slotData.bis.name .. "]|h") + end + else + row.slotText:SetText("") + row.equippedText:SetText("") + row.bisText:SetText("") + row.enchantText:SetText("") + row.sourceText:SetText("") + row.bisLink = nil + end + end + + if data.equippedStats and data.bisStats then + if not data.statsComplete then + if StatsPanelTitle then + StatsPanelTitle:SetText("Stats Comparison |cff888888(loading...)|r") + end + for _, stat in ipairs(STAT_DISPLAY) do + local vals = StatValues[stat.key] + if vals then + local current = data.equippedStats[stat.key] or 0 + vals.current:SetText(current) + vals.bis:SetText("|cff888888...|r") + vals.diff:SetText("") + end + end + + if not Amibis._statsRetryTimer then + Amibis._statsRetryTimer = CreateFrame("Frame") + Amibis._statsRetryTimer.elapsed = 0 + Amibis._statsRetryTimer:SetScript("OnUpdate", function(self, elapsed) + self.elapsed = self.elapsed + elapsed + if self.elapsed >= 1.5 then + self:Hide() + Amibis._statsRetryTimer = nil + if MainFrame and MainFrame:IsShown() then + ns.UI.RefreshUI() + end + end + end) + Amibis._statsRetryTimer:Show() + end + else + if StatsPanelTitle then + StatsPanelTitle:SetText("Stats Comparison") + end + for _, stat in ipairs(STAT_DISPLAY) do + local vals = StatValues[stat.key] + if vals then + local current = data.equippedStats[stat.key] or 0 + local bis = data.bisStats[stat.key] or 0 + local diff = bis - current + + vals.current:SetText(current) + vals.bis:SetText(bis) + + if diff > 0 then + vals.diff:SetText("+" .. diff) + vals.diff:SetTextColor(1, 0.5, 0.5, 1) + elseif diff < 0 then + vals.diff:SetText(tostring(diff)) + vals.diff:SetTextColor(0, 1, 0, 1) + else + vals.diff:SetText("-") + vals.diff:SetTextColor(0.5, 0.5, 0.5, 1) + end + end + end + end + end +end + +local initFrame = CreateFrame("Frame") +initFrame:RegisterEvent("PLAYER_LOGIN") +initFrame:SetScript("OnEvent", function(self, event) + if event == "PLAYER_LOGIN" then + InitializeUI() + self:UnregisterEvent("PLAYER_LOGIN") + end +end) diff --git a/README.md b/README.md new file mode 100644 index 0000000..b25c02a --- /dev/null +++ b/README.md @@ -0,0 +1,98 @@ +# Amibis + +*Beware this is AI slop. I don't usually work with LUA and haven't really done any verification beyond making sure there aren't rogue loops running calculations constantly* + +A World of Warcraft: The Burning Crusade Classic addon that compares your equipped gear against Best-in-Slot lists sourced from [wowtbc.gg](https://wowtbc.gg). + +## Features + +- **Gear Comparison** — See at a glance which slots are BIS and which can be upgraded +- **Auto-Detection** — Automatically detects your class and active talent spec +- **Stats Comparison** — Side-by-side stat breakdown (Healing, Spell Power, Intellect, Spirit, MP5, Haste, Crit) +- **Upgrade Highlight** — Identifies your biggest available upgrade +- **Persistent Settings** — Window position and spec overrides saved per character + +## Usage + +| Command | Description | +|---|---| +| `/amibis` | Toggle the comparison window | +| `/amibis spec ` | Override auto-detected spec (e.g. `/amibis spec Holy`) | +| `/amibis spec clear` | Reset spec override to auto-detection | + +### Interacting with the window + +- **Drag** the title bar to reposition (position is saved) +- **Shift+Click** a row to link the BIS item in chat +- **Ctrl+Click** a row to open the dress-up preview +- **Hover** a row to see the item tooltip + +## Adding BIS Lists + +BIS data lives in `Amibis/Data/BISLists.lua`. Each list follows this structure: + +### 1. Define a class table + +```lua +local WARRIOR_T5 = { + ["Head"] = { + itemID = 12345, + name = "Helm of the Fallen Defender", + source = "SSC - Lady Vashj", + enchant = { id = 35445, name = "Glyph of Renewal" }, -- optional + }, + -- ... repeat for each slot +} +``` + +### 2. Supported slots + +`Head`, `Neck`, `Shoulder`, `Back`, `Chest`, `Wrist`, `Hands`, `Waist`, `Legs`, `Feet`, `Finger0`, `Finger1`, `Trinket0`, `Trinket1`, `MainHand`, `SecondaryHand`, `Ranged` + +### 3. Register in BIS_DATA + +```lua +local BIS_DATA = { + ["PRIEST"] = { + ["Discipline"] = { ["T5"] = PRIEST_T5 }, + ["Holy"] = { ["T5"] = PRIEST_T5 }, + }, + ["WARRIOR"] = { + ["Protection"] = { ["T5"] = WARRIOR_T5 }, + }, +} +``` + +### Field reference + +| Field | Required | Description | +|---|---|---| +| `itemID` | Yes | WoW item ID (number) | +| `name` | Yes | Display name | +| `source` | Yes | Where it drops (e.g. `"TK - Kael'thas Sunstrider"`) | +| `enchant` | No | `{ id = , name = "" }` | + +### Important + +- Class keys must match WoW's English class constants: `"WARRIOR"`, `"PRIEST"`, `"MAGE"`, etc. (all caps) +- Spec names must match the values in `Amibis:GetPlayerSpec()` (e.g. `"Discipline"`, `"Holy"`, `"Arms"`) +- Phase keys are strings like `"T5"`, `"T6"` — the default phase is set in `Amibis.lua` under `DEFAULT_AMIBIS_DB.selectedPhase` + +## Installation + +Copy the `Amibis` folder into your WoW addon directory: + +``` +World of Warcraft/Interface/AddOns/Amibis/ +``` + +Required files: +``` +Amibis/ +├── Amibis.toc +├── Amibis.lua +├── Data/ +│ └── BISLists.lua +└── UI/ + └── ComparisonFrame.lua +```