QuestsChanged
Developer tool for tracking quests as you complete them... including the hidden behind the scenes tracking quests for objects/mobs. It also tracks details about the vignettes that you've seen in the current session.
I use it to work on my HandyNotes plugins, because the tracking quests are hard to work out otherwise.
This provides a DataBroker plugin to display the data.
If you don't have a broker viewer installed, type /questschanged to show the log.
You can also type /questschanged icon to toggle a minimap icon.
-
View User Profile
-
Send Message
Posted Sep 10, 2025Would you consider re-adding shift-right-click (or something even more obscure) to fully clear the log? I am having to go in and delete the WTF file now and then since I don't want it to grow forever. Or maybe a button in the settings like BugSack has?
https://github.com/kemayo/wow-questschanged/commit/0af98a0f340234c7d1871fab960717ddef9a09eb
Thanks!
-
View User Profile
-
Send Message
Posted Nov 13, 2022Would it be possible to add the ability for it to log the XP values for the quest, I know its a very niche request but it would be super useful for people like myself when authoring guides like my current one Dragonflight raiders guide
-
View User Profile
-
Send Message
Posted Jul 31, 2022This is a great tool, if you want for example set up WeakAuras that rely on “hidden” quest status, or also for creating custom entries in the WQAchievements addon.
All The Things provide the same information (if you enable the option), but this one is of course 100 times more lightweight and has a nice standalone log window.
Might also serve as a quick’n’dirty log that shows you what you have done in your session ;)
Thanks!
PS: An option to have a persistent (cross-session) log would be perfect :)Edit: Just noticed that the log is already persistent — if I open the window :) Perfect!
-
View User Profile
-
Send Message
Posted Aug 24, 2020I got a working version for 9.0
In the TOC you can just bump the version to 90001 and in addon.lua just change the code to...
local myname, ns = ... local icon = LibStub("LibDBIcon-1.0", true) local db, dbpc local quests = {} local new_quests = {} local quests_completed = {} ns.quests_completed = quests_completed local f = CreateFrame('Frame') f:SetScript("OnEvent", function(self, event, ...) ns[event](ns, event, ...) end) f:RegisterEvent("ADDON_LOADED") f:Hide() function ns:ADDON_LOADED(event, name) if name ~= myname then return end _G[myname.."DB"] = setmetatable(_G[myname.."DB"] or {}, { __index = { minimap = false, }, }) _G[myname.."DBPC"] = setmetatable(_G[myname.."DBPC"] or {}, { __index = { -- nothing right now }, }) db = _G[myname.."DB"] dbpc = _G[myname.."DBPC"] if not dbpc.log then dbpc.log = {} end ns.db = db ns.dbpc = dbpc if icon then icon:Register(myname, ns.dataobject, db) end f:UnregisterEvent("ADDON_LOADED") if IsLoggedIn() then self:PLAYER_LOGIN() else f:RegisterEvent("PLAYER_LOGIN") end end function ns:PLAYER_LOGIN() f:RegisterEvent("QUEST_LOG_UPDATE") f:RegisterEvent("ENCOUNTER_LOOT_RECEIVED") f:UnregisterEvent("PLAYER_LOGIN") for mid, questid in pairs(C_QuestLog.GetAllCompletedQuestIDs()) do quests[questid] = "true"; end end function ns:QUEST_LOG_UPDATE() f:Show() end ns.ENCOUNTER_LOOT_RECEIVED = ns.QUEST_LOG_UPDATE do local time_since = 0 f:SetScript("OnUpdate", function(self, elapsed) time_since = time_since + elapsed if time_since < 0.3 then return end ns:CheckQuests() time_since = 0 f:Hide() end) end local quest_names = {} ns.quest_names = quest_names do local tooltip local function tooltip_line(link, line) if not tooltip then tooltip = CreateFrame("GameTooltip", myname.."_Tooltip", nil, "GameTooltipTemplate") tooltip:SetOwner(UIParent, "ANCHOR_NONE") end tooltip:ClearLines() tooltip:SetHyperlink(link) if tooltip:NumLines() < line then return false end return _G[myname.."_TooltipTextLeft"..line]:GetText() end setmetatable(ns.quest_names, {__index = function(self, key) local link = (type(key) == 'string') and key or ('quest:'..key) local uid = string.match(link, '%d+') local name = tooltip_line(link, 1) if name then self[uid] = name return name end return false end,}) end function ns:CheckQuests() if not quests then return end local mapdata, x, y for mid, questid in pairs(C_QuestLog.GetAllCompletedQuestIDs()) do new_quests[questid] = "true"; end --new_quests = C_QuestLog.GetAllCompletedQuestIDs() for questid in pairs(new_quests) do if not quests[questid] then if not mapdata then local mapID = C_Map.GetBestMapForUnit('player') if mapID then mapdata = C_Map.GetMapInfo(mapID) local position = C_Map.GetPlayerMapPosition(mapdata.mapID, 'player') if position then x, y = position:GetXY() end end end local questName = quest_names[questid] -- prime it local quest = { id = questid, time = time(), map = mapdata and mapdata.mapID or 0, x = x or 0, y = y or 0, } table.insert(quests_completed, quest) table.insert(dbpc.log, quest) end end -- Swap `quests` and `new_quests` so we can hold on to the old `quests` and reuse the table on the next scan local temp = new_quests new_quests = quests quests = temp end local ldb = LibStub:GetLibrary("LibDataBroker-1.1") local dataobject = ldb:GetDataObjectByName("QuestsChanged") or ldb:NewDataObject("QuestsChanged", { type = "data source", label = "QuestsChanged", icon = [[Interface\Icons\Ability_Spy]], }) dataobject.OnClick = function(frame, button) if button == "RightButton" then -- clear the list! table.wipe(quests_completed) else ns:ShowLog() end end dataobject.OnTooltipShow = function(tooltip) ns:CheckQuests() -- in case tooltip:AddLine("QuestsChanged") for _, quest in ipairs(ns.quests_completed) do local map, level if type(quest.map) == 'string' then -- pre-8.0 quest logging has mapFiles, just show them map = quest.map level = quest.level else map, level = ns.MapNameFromID(quest.map) end tooltip:AddDoubleLine( ("%d: %s"):format(quest.id, quest_names[quest.id] or UNKNOWN), ("%s (%s) %.2f, %.2f"):format(quest.map, map .. (level and (' / ' .. level) or ''), quest.x * 100, quest.y * 100) ) end local x, y local mapID = C_Map.GetBestMapForUnit('player') if mapID then local position = C_Map.GetPlayerMapPosition(mapID, 'player') if position then x, y = position:GetXY() end end local mapname, subname = ns.MapNameFromID(mapID) -- TODO: check microdungeons here tooltip:AddDoubleLine("Location", ("%s (%s) %.2f, %.2f"):format(mapID or UNKNOWN, mapname .. (subname and (' / ' .. subname) or ''), (x or 0) * 100, (y or 0) * 100), 1, 0, 1, 1, 0, 1) tooltip:AddLine("Left-click to show your quest history", 0, 1, 1) tooltip:AddLine("Right-click to clear the list", 0, 1, 1) end ns.dataobject = dataobject -- slash _G["SLASH_".. myname:upper().."1"] = "/questschanged" SlashCmdList[myname:upper()] = function(msg) msg = msg:trim() if msg == "log" or msg == "" then ns:ShowLog() elseif msg == "icon" then if not icon then return end db.hide = not db.hide if db.hide then icon:Hide(myname) else icon:Show(myname) end end end -- utility function ns.MapNameFromID(mapID) if not mapID then return UNKNOWN end local mapdata = C_Map.GetMapInfo(mapID) local groupID = C_Map.GetMapGroupID(mapID) if group then local groupdata = C_Map.GetMapGroupMembersInfo(groupID) for _, subzonedata in ipairs(groupdata) do if subzonedata.mapID == mapID then return mapdata.name, subzonedata.name end end end return mapdata.name end-
View User Profile
-
Send Message
Posted Aug 24, 2020In reply to elidion:
GetQuestsCompleted()is removed from 9.0 and replaced with a function that spits out results differently. So I basically rewrote it to create a new array that matches the way it used to be. and call that array instead of the one spit out byC_QuestLog.GetAllCompletedQuestIDs()-
View User Profile
-
Send Message
Posted Aug 29, 2020In reply to elidion:
Very good, thank you!
Could you recommend a broker viewer that works in 9.x?
-
View User Profile
-
Send Message
Posted Aug 29, 2020In reply to Vox013:
Honestly I haven't used many external addons in 9.0, just some of them like this one is required for my own addon so I am forced to make it work so I can continue work on mine. I use this to discover hidden quest IDs for things like looting treasures or killing rares.
-
View User Profile
-
Send Message
Posted Aug 31, 2020In reply to elidion:
Yes, this is very useful for me too. But it would be way better if the addon just prints out the quest ID in the chat upon completion, rather than opening up a window manually every time to check if there's any new quest completed. Is this possible to do in 9.x ?
-
View User Profile
-
Send Message
Posted Aug 31, 2020It's unhelpfully hard to find, I admit, but I've had a branch up for shadowlands on github which handles the changes fine: https://github.com/kemayo/wow-questschanged/tree/shadowlands
-
View User Profile
-
Send Message
Posted Sep 17, 2020In reply to Kemayo:
btw I tried the version you have on the shadowlands branch and it bombs right of f the bat
Message: Interface\AddOns\QuestsChanged\addon.lua:3: attempt to call global 'LibStub' (a nil value) Time: Thu Sep 17 16:00:30 2020 Count: 1 Stack: Interface\AddOns\QuestsChanged\addon.lua:3: attempt to call global 'LibStub' (a nil value) [string "@Interface\AddOns\QuestsChanged\addon.lua"]:3: in main chunk Locals: myname = "QuestsChanged" ns = <table> { } (*temporary) = nil (*temporary) = "LibDBIcon-1.0" (*temporary) = true (*temporary) = "attempt to call global 'LibStub' (a nil value)"-
View User Profile
-
Send Message
Posted Sep 17, 2020The pure git checkout expects that you're running full external-libraries. You can get everything it needs by dropping LibDBIcon-1.0 into your addons directory.
-
View User Profile
-
Send Message
Posted Jul 26, 2020Looks like 9.0 errors in quests = GetQuestsCompleted(quests)
-
View User Profile
-
Send Message
Posted Aug 24, 2020In reply to Samnthar:
Not the author but I got it working in PTR/Beta, posted the addon.lua code on my post above.
-
View User Profile
-
Send Message
Posted Jun 23, 2020Outdated at 8.3.0
-
View User Profile
-
Send Message
Posted Jul 31, 2019Just discovered this addon, but it seems the log window formatting is broken now. The previous/next buttons and page indicators cover up some of the log content. For example, I just killed one rare, and its log entry is completely obscured by the buttons.
EDIT: Hm, strangely, after I reloadui, the first time I bring up the log window, it's formatted well. But then if I close and re-open it, it goes back to bad formatting with the page info/buttons covering up some of the log.
-
View User Profile
-
Send Message
Posted Aug 14, 2018Checked the code, this should be /questschanged icon
-
View User Profile
-
Send Message
Posted Aug 12, 2018Could you make the result copyable? I worry I mistype the ID when I report something.
I was thinking that either the popup window could be changed or an ALT+Click on the broker/icon to copy the last 5 results or something.
-
View User Profile
-
Send Message
Posted Jul 18, 2018When player is in instances, C_Map.GetPlayerMapPosition(mapID, 'player') returns nil.
That makes [local x, y = C_Map.GetPlayerMapPosition(mapID, 'player'):GetXY()] to cause Lua error.
I had to check if the value of playe's position returns numerical coords or not before doing GetXY().
-
View User Profile
-
Send Message
Posted Apr 13, 2017Pretty good! Thanks!!
-
View User Profile
-
Send Message
Posted Oct 27, 2016Error: http://paste2.org/k9maBVvO