From 01dff34305b7869807d5a354ad474680802d4409 Mon Sep 17 00:00:00 2001 From: Relationship <571+relationship@noreply.octowow.st> Date: Thu, 23 Jul 2026 03:37:22 +0000 Subject: [PATCH] Upload files to "/" --- Database.lua | 8 +- Events.lua | 300 ++++++++++++++++++++++++++++++++++----------------- 2 files changed, 208 insertions(+), 100 deletions(-) diff --git a/Database.lua b/Database.lua index 6ef4543..9bcc334 100644 --- a/Database.lua +++ b/Database.lua @@ -48,7 +48,7 @@ RelationshipsAchievements_List = { { id = 106, cat = 1, name = "Money in the Bank", desc = "Use a bank for the first time.", points = 10, icon = "Interface\\Icons\\INV_Misc_Bag_15" }, { id = 107, cat = 1, name = "Big Spender", desc = "Purchase an item from an auction house.", points = 10, icon = "Interface\\Icons\\INV_Misc_Coin_02" }, { id = 108, cat = 1, name = "Take a Chill Pill", desc = "Bind to an inn.", points = 5, icon = "Interface\\Icons\\INV_Misc_Rune_01" }, - { id = 109, cat = 1, name = "Represent", desc = "Equip a tabard.", points = 10, icon = "Interface\\Icons\\INV_Shirt_GuildTabard_01" }, + { id = 109, cat = 1, name = "Represent", desc = "Equip a tabard.", points = 10, icon = "Interface\\Icons\\INV_Shirt_Guildtabard_01" }, { id = 110, cat = 1, name = "Mailbox Hero", desc = "Send your first piece of mail.", points = 5, icon = "Interface\\Icons\\INV_Letter_04" }, { id = 111, cat = 1, name = "Trainee", desc = "Visit a class trainer.", points = 5, icon = "Interface\\Icons\\INV_Misc_Book_11" }, @@ -223,7 +223,7 @@ RelationshipsAchievements_List = { { id = 707, cat = 7, name = "Master of the Bandage",desc = "Reach 300 in First Aid.", points = 10, icon = "Interface\\Icons\\INV_Misc_Bandage_15" }, { id = 708, cat = 7, name = "Master Alchemist", desc = "Reach 300 in Alchemy.", points = 10, icon = "Interface\\Icons\\Trade_Alchemy" }, { id = 709, cat = 7, name = "Master Blacksmith", desc = "Reach 300 in Blacksmithing.", points = 10, icon = "Interface\\Icons\\Trade_BlackSmithing" }, - { id = 710, cat = 7, name = "Master Enchanter", desc = "Reach 300 in Enchanting.", points = 10, icon = "Interface\\Icons\\INV_Enchant_ShardBrilliantLarge" }, + { id = 710, cat = 7, name = "Master Enchanter", desc = "Reach 300 in Enchanting.", points = 10, icon = "Interface\\Icons\\Trade_Engraving" }, { id = 711, cat = 7, name = "Master Engineer", desc = "Reach 300 in Engineering.", points = 10, icon = "Interface\\Icons\\Trade_Engineering" }, { id = 712, cat = 7, name = "Master Herbalist", desc = "Reach 300 in Herbalism.", points = 10, icon = "Interface\\Icons\\INV_Misc_Herb_07" }, { id = 713, cat = 7, name = "Master Leatherworker", desc = "Reach 300 in Leatherworking.", points = 10, icon = "Interface\\Icons\\Trade_LeatherWorking" }, @@ -335,14 +335,14 @@ RelationshipsAchievements_List = { { id = 1601, cat = 16, name = "One Life to Live", desc = "Roll a Hardcore character.", points = 10, icon = "Interface\\Icons\\Spell_Holy_GreaterHeal" }, { id = 1602, cat = 16, name = "Survivor", desc = "Reach level 20 on a Hardcore character.", points = 15, icon = "Interface\\Icons\\Spell_Holy_Heal" }, { id = 1603, cat = 16, name = "Untouchable", desc = "Reach level 40 on a Hardcore character.", points = 25, icon = "Interface\\Icons\\Spell_Holy_Renew" }, - { id = 1604, cat = 16, name = "Hardcore Hero", desc = "Reach level 60 on a Hardcore character.", points = 50, icon = "Interface\\Icons\\Spell_Holy_Resurrection" }, + { id = 1604, cat = 16, name = "Hardcore Hero", desc = "Reach level 60 on a Hardcore character.", points = 50, icon = "Interface\\Icons\\Spell_Holy_GuardianSpirit" }, { id = 1605, cat = 16, name = "Close Call", desc = "Survive dropping below 10% health.", points = 10, icon = "Interface\\Icons\\Spell_Shadow_Twilight" }, { id = 1606, cat = 16, name = "No Retreat", desc = "Defeat an elite of your level solo.", points = 15, icon = "Interface\\Icons\\Ability_Warrior_Innerrage" }, -- ============ SOCIAL ============ { id = 1701, cat = 17, name = "Say Hello", desc = "Emote /wave at another player.", points = 5, icon = "Interface\\Icons\\INV_Misc_Head_Human_02" }, { id = 1702, cat = 17, name = "Dance Off", desc = "Use the /dance emote.", points = 5, icon = "Interface\\Icons\\INV_Shirt_GuildTabard_01" }, - { id = 1703, cat = 17, name = "Guildmate", desc = "Have 10 members in your guild.", points = 10, icon = "Interface\\Icons\\INV_Shirt_GuildTabard_01" }, + { id = 1703, cat = 17, name = "Guildmate", desc = "Have 10 members in your guild.", points = 10, icon = "Interface\\Icons\\INV_Shirt_Guildtabard_01" }, { id = 1704, cat = 17, name = "Popular", desc = "Add 5 friends to your friends list.", points = 10, icon = "Interface\\Icons\\INV_Misc_Head_Human_02", progress = { stat = "friendCount", max = 5 } }, { id = 1705, cat = 17, name = "Chatty", desc = "Send 100 messages in chat.", points = 10, icon = "Interface\\Icons\\INV_Letter_04", diff --git a/Events.lua b/Events.lua index edcf73b..ed1218f 100644 --- a/Events.lua +++ b/Events.lua @@ -14,12 +14,14 @@ local trackedEvents = { "ZONE_CHANGED_INDOORS", "CHAT_MSG_COMBAT_HONOR_GAIN", "CHAT_MSG_COMBAT_FACTION_CHANGE", "SKILL_LINES_CHANGED", "CHAT_MSG_LOOT", "CHAT_MSG_MONEY", "CHAT_MSG_COMBAT_HOSTILE_DEATH", "CHAT_MSG_COMBAT_XP_GAIN", - "CHAT_MSG_SYSTEM", "CHAT_MSG_BG_SYSTEM_NEUTRAL", "CHAT_MSG_BG_SYSTEM_ALLIANCE", "CHAT_MSG_BG_SYSTEM_HORDE", "UPDATE_FACTION", "PARTY_MEMBERS_CHANGED", "FRIENDLIST_UPDATE", + "CHAT_MSG_SYSTEM", "UPDATE_FACTION", "PARTY_MEMBERS_CHANGED", "FRIENDLIST_UPDATE", "GUILD_ROSTER_UPDATE", "PLAYER_UNGHOST", "PLAYER_ALIVE", "CHAT_MSG_TEXT_EMOTE", "CHAT_MSG_EMOTE", "PLAYER_PVP_RANK_CHANGED", "PLAYER_PVP_KILLS_CHANGED", "PLAYER_PVPKILLS_CHANGED", "HONOR_CURRENCY_UPDATE", "HEARTHSTONE_BOUND", "BANKFRAME_OPENED", "TRAINER_SHOW", "MAIL_SEND_SUCCESS", "PLAYER_EQUIPMENT_CHANGED", - "BAG_UPDATE", "CHARACTER_POINTS_CHANGED", "SPELLS_CHANGED", "UNIT_HEALTH", "PLAYER_MONEY" + "BAG_UPDATE", "CHARACTER_POINTS_CHANGED", "SPELLS_CHANGED", "UNIT_HEALTH", "PLAYER_MONEY", + -- Vanilla 1.12 event names (PLAYER_EQUIPMENT_CHANGED does not exist here). + "UNIT_INVENTORY_CHANGED", "ADDON_LOADED", "MERCHANT_SHOW", "MERCHANT_CLOSED" } for i = 1, table.getn(trackedEvents) do SafeRegister(trackedEvents[i]) end @@ -92,29 +94,48 @@ local function ScanTalentChange() ScanTalents() end +-- Extract item quality from a link's color code. Robust when GetItemInfo has +-- not cached the item yet (common in 1.12 right after login or equip). +local QUALITY_BY_COLOR = { + ["ff9d9d9d"] = 0, ["ffffffff"] = 1, ["ff1eff00"] = 2, + ["ff0070dd"] = 3, ["ffa335ee"] = 4, ["ffff8000"] = 5, +} +local function QualityFromLink(link) + if not link then return nil end + local _, _, color = string.find(link, "|c(%x%x%x%x%x%x%x%x)") + if not color then return nil end + return QUALITY_BY_COLOR[string.lower(color)] +end + local function ScanEquipmentAndBags() if GetInventoryItemLink then if GetInventoryItemLink("player", 4) then RelationshipsAchievements:Unlock(1203) end if GetInventoryItemLink("player", 19) then RelationshipsAchievements:Unlock(109) end - local allRare, haveGear, epic = true, false, false - for slot = 1, 18 do - if slot ~= 4 and slot ~= 18 then - local link = GetInventoryItemLink("player", slot) - if link then - haveGear = true - local _, _, quality = GetItemInfo(link) - if quality and quality >= 4 then epic = true end - if not quality or quality < 3 then allRare = false end - local itemName = GetItemInfo(link) - if itemName == "Atiesh, Greatstaff of the Guardian" then RelationshipsAchievements:Unlock(1004) end - if itemName == "Thunderfury, Blessed Blade of the Windseeker" then RelationshipsAchievements:Unlock(1005) end - if itemName == "Sulfuras, Hand of Ragnaros" then RelationshipsAchievements:Unlock(1006) end - else - allRare = false - end + -- Well Equipped: every equipped armor/weapon slot must be Rare+. + -- Slots that are legitimately optional on a spec (shirt, tabard, + -- ranged, off-hand on 2H users) are skipped from the "all filled" + -- check but still count when present. + local requiredSlots = { 1,2,3,5,6,7,8,9,10,11,12,13,14,15,16 } + local optionalSlots = { 17, 18 } -- off-hand, ranged + local allRare, missing, epic = true, false, false + local function eval(slot, required) + local link = GetInventoryItemLink("player", slot) + if not link then + if required then missing = true end + return end + local _, _, q = GetItemInfo(link) + local quality = q or QualityFromLink(link) + if quality and quality >= 4 then epic = true end + if required and (not quality or quality < 3) then allRare = false end + local itemName = GetItemInfo(link) + if itemName == "Atiesh, Greatstaff of the Guardian" then RelationshipsAchievements:Unlock(1004) end + if itemName == "Thunderfury, Blessed Blade of the Windseeker" then RelationshipsAchievements:Unlock(1005) end + if itemName == "Sulfuras, Hand of Ragnaros" then RelationshipsAchievements:Unlock(1006) end end - if haveGear and allRare then RelationshipsAchievements:Unlock(1208) end + for i = 1, table.getn(requiredSlots) do eval(requiredSlots[i], true) end + for i = 1, table.getn(optionalSlots) do eval(optionalSlots[i], false) end + if not missing and allRare then RelationshipsAchievements:Unlock(1208) end if epic then RelationshipsAchievements:Unlock(1209) end end if GetContainerNumSlots then @@ -129,24 +150,85 @@ local function ScanEquipmentAndBags() end end +-- Hidden tooltip used for spellbook scanning. Vanilla 1.12 does not expose +-- mount / non-combat-pet flags on spells, so we read the tooltip text — it +-- reliably distinguishes them across every locale-agnostic edge case we care +-- about because the mount / pet tooltip prefixes are stable in enUS clients. +local RA_ScanTip = CreateFrame("GameTooltip", "RelationshipsAchievementsScanTip", UIParent, "GameTooltipTemplate") +RA_ScanTip:SetOwner(UIParent, "ANCHOR_NONE") + +local function TooltipText(index, book) + RA_ScanTip:ClearLines() + RA_ScanTip:SetSpell(index, book) + local text = "" + for line = 1, RA_ScanTip:NumLines() do + local fs = getglobal("RelationshipsAchievementsScanTipTextLeft"..line) + if fs then + local t = fs:GetText() + if t then text = text .. "\n" .. t end + end + end + return string.lower(text) +end + local function ScanSpellbook() if not GetSpellName then return end + local book = BOOKTYPE_SPELL or "spell" local mounts, pets = 0, 0 + local hasEpicMount = false + local seen = {} local i = 1 while true do - local name, rank = GetSpellName(i, BOOKTYPE_SPELL or "spell") + local name, rank = GetSpellName(i, book) if not name then break end - local low = string.lower(name) - if string.find(low, "summon ") and (string.find(low, "horse") or string.find(low, "ram") - or string.find(low, "tiger") or string.find(low, "raptor") or string.find(low, "wolf") - or string.find(low, "kodo") or string.find(low, "mechanostrider")) then mounts = mounts + 1 end - if string.find(low, "summon ") and not string.find(low, "demon") and not string.find(low, "elemental") then pets = pets + 1 end + local key = name .. "||" .. (rank or "") + if not seen[key] then + seen[key] = true + local tip = TooltipText(i, book) + -- Mounts: tooltip includes "mount speed" or "riding" descriptor. + -- We match both the classic "increases speed by X%" line and the + -- explicit "summons and dismisses a rideable" phrasing. + local isMount = string.find(tip, "mount speed", 1, true) + or string.find(tip, "rideable", 1, true) + or string.find(tip, "summons and dismisses a rideable", 1, true) + -- Non-combat pets: tooltip contains "right click to dismiss" + -- or the classic "companion" descriptor. Explicitly exclude + -- combat pets (hunter/warlock), which say "summons your pet". + local isPet = (string.find(tip, "companion", 1, true) + or string.find(tip, "right click to dismiss", 1, true)) + and not string.find(tip, "summons your", 1, true) + and not string.find(tip, "combat pet", 1, true) + if isMount then + mounts = mounts + 1 + -- Epic ground mounts grant +100% speed in vanilla. + if string.find(tip, "100%", 1, true) or string.find(tip, "epic", 1, true) then + hasEpicMount = true + end + elseif isPet then + pets = pets + 1 + end + end i = i + 1 end + + -- Fallback: Riding skill unambiguously proves mount ownership even if + -- tooltip scanning missed a custom mount (Turtle/OctoWoW variants). + if GetNumSkillLines then + for s = 1, GetNumSkillLines() do + local skill, header, _, rank = GetSkillLineInfo(s) + if not header and skill == "Riding" and rank and rank > 0 then + if mounts < 1 then mounts = 1 end + if rank >= 150 then hasEpicMount = true end + end + end + end + RelationshipsAchievements:UpdateStat("mountCount", mounts) RelationshipsAchievements:UpdateStat("petCount", pets) if mounts >= 1 then RelationshipsAchievements:Unlock(211) end - if mounts >= 1 and (UnitLevel("player") or 1) >= 60 then RelationshipsAchievements:Unlock(212) end + if hasEpicMount and (UnitLevel("player") or 1) >= 60 then + RelationshipsAchievements:Unlock(212) + end if pets >= 1 then RelationshipsAchievements:Unlock(1204) end end @@ -326,44 +408,79 @@ if _origSendMail then SendMail = function(name, subject, body) RelationshipsAchievements:Unlock(110) end end -local _origPostAuction = PostAuction -if _origPostAuction then PostAuction = function(minBid, buyoutPrice, runTime, stackSize, numStacks) - _origPostAuction(minBid, buyoutPrice, runTime, stackSize, numStacks) - RelationshipsAchievements:AddStat("auctionsListed", numStacks or 1) -end end - -local _origBuyoutAuction = BuyoutAuction -if _origBuyoutAuction then BuyoutAuction = function(index) - _origBuyoutAuction(index) - RelationshipsAchievements:Unlock(107) - RelationshipsAchievements:AddStat("auctionsWon", 1) -end end - -local OnQuestComplete - --- Hook ConfirmBinder(): the innkeeper popup's OnAccept calls this API and it --- fires exactly once per successful bind. The HEARTHSTONE_BOUND event does not --- exist in vanilla 1.12, and the CHAT_MSG_SYSTEM string fallback below is --- localised / worded differently on some Turtle/Octo builds, so hooking the --- API is the only reliable trigger for re-binding to a new inn. -local _origConfirmBinder = ConfirmBinder -if _origConfirmBinder then ConfirmBinder = function() - _origConfirmBinder() - if RelationshipsAchievements and RelationshipsAchievements.Unlock then - RelationshipsAchievements:Unlock(108) +-- Auction House API is provided by Blizzard_AuctionUI, which is Load-on-Demand +-- in 1.12. Hooking at file-load time silently no-ops because the globals are +-- still nil. HookAuctionHouse() runs again on ADDON_LOADED "Blizzard_AuctionUI" +-- so the hooks attach as soon as the AH frame is opened for the first time. +local auctionHooked = false +local function HookAuctionHouse() + if auctionHooked then return end + if not PostAuction and not BuyoutAuction and not PlaceAuctionBid then return end + auctionHooked = true + if PostAuction then + local _orig = PostAuction + PostAuction = function(minBid, buyoutPrice, runTime, stackSize, numStacks) + _orig(minBid, buyoutPrice, runTime, stackSize, numStacks) + RelationshipsAchievements:AddStat("auctionsListed", numStacks or 1) + end end - if RelationshipsAchievementsCharDB then - RelationshipsAchievementsCharDB.pendingInnBind = nil + if BuyoutAuction then + local _orig = BuyoutAuction + BuyoutAuction = function(index) + _orig(index) + RelationshipsAchievements:Unlock(107) + RelationshipsAchievements:AddStat("auctionsWon", 1) + end + end + -- Many AH addons (and the default UI in some 1.12 builds) route the + -- Buyout button through PlaceAuctionBid(list, index, bid) with bid == + -- buyout price. Hook it too so wins are always counted. + if PlaceAuctionBid then + local _orig = PlaceAuctionBid + PlaceAuctionBid = function(listType, index, bid) + _orig(listType, index, bid) + local _, _, _, _, _, _, _, _, buyout = GetAuctionItemInfo(listType, index) + if buyout and bid and bid >= buyout and buyout > 0 then + RelationshipsAchievements:Unlock(107) + RelationshipsAchievements:AddStat("auctionsWon", 1) + end + end + end +end +HookAuctionHouse() -- attempt immediately in case the UI is already loaded. + +-- ============ Vendor sales tracking ============ +-- The merchant window is always the default UI; hooks are safe to install at +-- file-load time. Two vectors cover every sell path: +-- * UseContainerItem while MerchantFrame is visible = shift-click / right- +-- click sell from the bag. +-- * Drag-and-drop onto the merchant → PickupContainerItem then a click on +-- the merchant, which resolves via UseContainerItem too, so one hook +-- catches both cases. +local function MerchantOpen() + return MerchantFrame and MerchantFrame:IsVisible() +end +local _origUseContainerItem = UseContainerItem +if _origUseContainerItem then UseContainerItem = function(bag, slot, target) + local sellable = false + if MerchantOpen() and GetContainerItemLink then + local link = GetContainerItemLink(bag, slot) + -- Skip if slot is empty or item is bound-cannot-sell? A no-op sell is + -- harmless — the vendor simply refuses — so we count only when the + -- API had something to act on. + if link then sellable = true end + end + _origUseContainerItem(bag, slot, target) + if sellable then + RelationshipsAchievements:AddStat("vendorSales", 1) end end end --- Hook GetQuestReward(): fires exactly once when the player accepts a quest --- reward. Much more reliable than QUEST_COMPLETE (which fires each time the --- reward window opens) for tracking completed-quest counters. -local _origGetQuestReward = GetQuestReward -if _origGetQuestReward then GetQuestReward = function(choice) - OnQuestComplete() - return _origGetQuestReward(choice) +local _origStaticPopupShow = StaticPopup_Show +if _origStaticPopupShow then StaticPopup_Show = function(which, text_arg1, text_arg2, data) + local popup = _origStaticPopupShow(which, text_arg1, text_arg2, data) + if which == "CONFIRM_BINDER" then RelationshipsAchievementsCharDB.pendingInnBind = true end + return popup end end -- ============ DoEmote hook (Say Hello / Dance Off) ============ @@ -410,7 +527,7 @@ local function OnLevelUp() RelationshipsAchievements_ScanCharacter() end -OnQuestComplete = function() +local function OnQuestComplete() -- QUEST_COMPLETE is the reliable 1.12 turn-in event. Custom clients that -- also emit QUEST_TURNED_IN are de-duplicated by time stamp below. local now = time() @@ -541,36 +658,20 @@ local function OnSystemMessage(msg) if string.find(low, "trick or treat") then RelationshipsAchievements:Unlock(903) end if string.find(low, "lunar festival") then RelationshipsAchievements:Unlock(909) end if string.find(low, "winter veil") then RelationshipsAchievements:Unlock(901) end - -- Battleground victories. On 1.12 the win message reads "The Alliance wins!" - -- or "The Horde wins!" via CHAT_MSG_BG_SYSTEM_NEUTRAL and does NOT include - -- the map name, so we look up the current BG from GetRealZoneText() and - -- credit the player's faction only. Guard with pendingBgWin so duplicate - -- messages (both faction and neutral system chat) don't double-count. - if string.find(msg, "wins!") or string.find(msg, "[Vv]ictory") then - local zone = (GetRealZoneText and GetRealZoneText()) or "" - local _, myFaction = UnitFactionGroup("player") - local winner - if string.find(msg, "Alliance") then winner = "Alliance" - elseif string.find(msg, "Horde") then winner = "Horde" - end - local key = zone .. "|" .. (winner or "?") - if RelationshipsAchievementsCharDB and RelationshipsAchievementsCharDB.lastBgWinKey ~= key then - RelationshipsAchievementsCharDB.lastBgWinKey = key - if not winner or winner == myFaction then - if string.find(zone, "Warsong Gulch") then - RelationshipsAchievements:Unlock(505) - RelationshipsAchievements:AddStat("wsgWins", 1) - RelationshipsAchievements:AddStat("bgWins", 1) - elseif string.find(zone, "Alterac Valley") then - RelationshipsAchievements:Unlock(506) - RelationshipsAchievements:AddStat("avWins", 1) - RelationshipsAchievements:AddStat("bgWins", 1) - elseif string.find(zone, "Arathi Basin") then - RelationshipsAchievements:Unlock(507) - RelationshipsAchievements:AddStat("abWins", 1) - RelationshipsAchievements:AddStat("bgWins", 1) - end - end + -- Battleground victories (system messages contain "Warsong Gulch", etc.) + if string.find(msg, "[Vv]ictory") or string.find(msg, "wins!") then + if string.find(msg, "Warsong Gulch") then + RelationshipsAchievements:Unlock(505) + RelationshipsAchievements:AddStat("wsgWins", 1) + RelationshipsAchievements:AddStat("bgWins", 1) + elseif string.find(msg, "Alterac Valley") then + RelationshipsAchievements:Unlock(506) + RelationshipsAchievements:AddStat("avWins", 1) + RelationshipsAchievements:AddStat("bgWins", 1) + elseif string.find(msg, "Arathi Basin") then + RelationshipsAchievements:Unlock(507) + RelationshipsAchievements:AddStat("abWins", 1) + RelationshipsAchievements:AddStat("bgWins", 1) end end end @@ -621,10 +722,7 @@ frame:SetScript("OnEvent", function() OnLootMessage(arg1) elseif event == "CHAT_MSG_COMBAT_HOSTILE_DEATH" or event == "CHAT_MSG_COMBAT_XP_GAIN" then OnEnemyDeath(arg1) - elseif event == "CHAT_MSG_SYSTEM" - or event == "CHAT_MSG_BG_SYSTEM_NEUTRAL" - or event == "CHAT_MSG_BG_SYSTEM_ALLIANCE" - or event == "CHAT_MSG_BG_SYSTEM_HORDE" then + elseif event == "CHAT_MSG_SYSTEM" then OnSystemMessage(arg1) elseif event == "CHAT_MSG_TEXT_EMOTE" or event == "CHAT_MSG_EMOTE" then OnTextEmote(arg1, arg2) @@ -642,8 +740,18 @@ frame:SetScript("OnEvent", function() RelationshipsAchievements:Unlock(111) elseif event == "MAIL_SEND_SUCCESS" then RelationshipsAchievements:Unlock(110) - elseif event == "PLAYER_EQUIPMENT_CHANGED" or event == "BAG_UPDATE" then + elseif event == "PLAYER_EQUIPMENT_CHANGED" + or event == "UNIT_INVENTORY_CHANGED" + or event == "BAG_UPDATE" then + if event == "UNIT_INVENTORY_CHANGED" and arg1 ~= "player" then return end ScanEquipmentAndBags() + elseif event == "ADDON_LOADED" then + if arg1 == "Blizzard_AuctionUI" then HookAuctionHouse() end + elseif event == "MERCHANT_SHOW" then + -- Rescan equipment when opening a vendor — buying gear or repairs + -- often coincides with equipping the item immediately after. + ScanEquipmentAndBags() + ScanSpellbook() elseif event == "CHARACTER_POINTS_CHANGED" then ScanTalentChange() elseif event == "SPELLS_CHANGED" then