--[[ Description If you have ever had a quest item you have no idea which quest it belongs to, and if it safe to destroy, this AddOn is for you. QuestItem stores an in-game database over quest items and tell you which quest they belong to. Useful to find out if you are still o n the quest, and if it safe to destroy it. The AddOn will map items to quests when you pick them up, but also has a limited backward compatability. If you see tooltip for a questitem you have picked up before installing the addon, QuestItem will try to find the item in your questlog, and map it to a quest. In case unsuccessful, the item will be marked as unidentified. QuestItem now has a configuration screen you can access by typing /questitem or /qi at the chat prompt. Here you can configure some of the functionallity as well as do manual mapping of unidentified items. Feature summary: - Identify quest items when picked up. - Show quest name and status in tooltip for quest items. - Will try to identify items picked up before the AddOn was installed. - Identified items are available for all your characters, and status is unique for your character. - Displays how many items are needed to complete quest, and how many you currently have. - Manual mapping for unidentified items. - Configuration + If you like this addon (or even if you don't), donations are always welcome to my character Shagoth on the Stormreaver server ;D + If you can translate the interface to german, edit the appropriate localization.lua file, and mail it to me at shagoth@gmail.com + Bug reports can be made adding a comment, or sending me a PM or email at shagoth@gmail.com History: New in version 1.6.0: - Added configurable tooltip for item list. - Added Alt + right click to open QuestLog for an item. New in version 1.5.3: - Updated french language New in version 1.5.2: - Fixed RegisterForSave in 1.10 New in version 1.5.1: - Fixed a weird graphics issue with the item list. - Resized the close button to fit the rectangle its placed inside - Added version information in the item list - Right click for pop-up on linked items in chat should be working New in version 1.5.0: - Sorting of items in the list. - Fixed the placement of the caption for the config window New in version 1.4.0: - Support for EngInventory New in version 1.3.5: - Should work in the bank, even with Emerald UI See older history in Changelog.txt ]]-- -- /script arg1="Dentrium-Kraftstein: 1/1"; QuestItem_OnEvent("DELETE"); arg1="Roon's Kodo Horn: 1/1"; QuestItem_OnEvent("UI_INFO_MESSAGE"); -- /script arg1="Ragefire Shaman slain: 5/8"; QuestItem_OnEvent("UI_INFO_MESSAGE"); QuestItem_OnEvent("DELETE"); -- /script arg1="Sent mail"; QuestItem_OnEvent("DELETE"); QuestItem_OnEvent("DELETE"); DEBUG = false; QI_CHANNEL_NAME = "QuestItem"; -- QuestItem array QuestItems = {}; -- Settings QuestItem_Settings = {}; ---------------------------------------------------- -- Updates the database with item and quest mappings ---------------------------------------------------- ---------------------------------------------------- function QuestItem_UpdateItem(item, quest, count, total, status) -- If item doesn't exist, add quest name and total item count to it if(not QuestItems[item]) then QuestItems[item] = {}; QuestItems[item].QuestName = quest; end -- If old quest name was unidentified, save new name if(QuestItem_SearchString(QuestItems[item].QuestName, QUESTITEM_UNIDENTIFIED) and not QuestItem_SearchString(quest, QuestItems[item].QuestName) ) then QuestItems[item].QuestName = quest; end if(not QuestItems[item][UnitName("player")]) then QuestItems[item][UnitName("player")] = {}; end -- Save total count if(total ~= nil and QuestItem_CheckNumeric(total) ) then QuestItems[item].Total = QuestItem_MakeIntFromHexString(total); else QuestItems[item].Total = 0; end -- Save item count if(count ~= nil and QuestItem_CheckNumeric(count) ) then QuestItems[item][UnitName("player")].Count = QuestItem_MakeIntFromHexString(count); else QuestItems[item][UnitName("player")].Count = 0; end QuestItems[item][UnitName("player")].QuestStatus = status; end ---------------------------------------------------------------------- -- Find a quest based on item name -- Returns: -- QuestName - the name of the Quest. -- Total - Total number of items required to complete it -- Count - The number of items you have -- Texture - Texture of the item ---------------------------------------------------------------------- ---------------------------------------------------------------------- function QuestItem_FindQuest(item) local total = 1; local count = 0; local texture = nil; local itemName; -- Iterate the quest log entries for y=1, GetNumQuestLogEntries(), 1 do local QuestName, level, questTag, isHeader, isCollapsed, complete = GetQuestLogTitle(y); -- Don't check headers if(not isHeader) then SelectQuestLogEntry(y); local QDescription, QObjectives = GetQuestLogQuestText(); -- Find out if this item has already been mapped to a quest. -- This is to to prevent any reset of the status for manually mapped items. if(QuestItems[item] and (QuestItems[item].QuestName and QuestItems[item].QuestName == QuestName) ) then QuestItem_UpdateItem(item, QuestName, count, total, 0) return QuestName, total, count, texture; end -- Look for the item in quest leader boards if (GetNumQuestLeaderBoards() > 0) then -- Look for the item in leader boards for i=1, GetNumQuestLeaderBoards(), 1 do --Objectives --local str = getglobal("QuestLogObjective"..i); local text, itemType, finished = GetQuestLogLeaderBoard(i); -- Check if type is an item, and if the item is what we are looking for --QuestItem_Debug("Item type: " ..itemType); if(itemType ~= nil and (itemType == "item" or itemType == "object") ) then if(QuestItem_SearchString(text, item)) then local count = gsub(text,"(.*): (%d+)/(%d+)","%2"); local total = gsub(text,"(.*): (%d+)/(%d+)","%3"); QuestItem_Debug("Count: " ..count); return QuestName, total, count, texture; end end end end -- Look for the item in the objectives - no count and total will be returned if(QuestItem_SearchString(QObjectives, item)) then return QuestName, total, count, texture; end end end return nil, total, count, texture; end -------------------------------------------------------------------------------- -- Check if there is a quest for the item. If it exists; update, if not, save it. -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- function QuestItem_LocateQuest(itemText, itemCount, itemTotal) local QuestName, texture; -- Only look through the questlog if the item has not already been mapped to a quest if(not QuestItems[itemText] or QuestItems[itemText].QuestName == QUESTITEM_UNIDENTIFIED) then QuestName, itemTotal, itemCount, texture = QuestItem_FindQuest(itemText); else QuestName = QuestItems[itemText].QuestName; end -- Update the QuestItems array if(QuestName ~= nil) then QuestItem_Debug("Found quest for " .. itemText .. ": " .. QuestName); QuestItem_UpdateItem(itemText, QuestName, itemCount, itemTotal, 0); elseif(QuestItem_Settings["Alert"]) then QuestItem_PrintToScreen(QUESTITEM_CANTIDENTIFY .. itemText); end end --------------- -- OnLoad event --------------- --------------- function QuestItem_OnLoad() -- RegisterForSave("QuestItems"); -- RegisterForSave("QuestItem_Settings"); this:RegisterEvent("VARIABLES_LOADED"); -- Register slash commands SLASH_QUESTITEM1 = "/questitem"; SLASH_QUESTITEM2 = "/qi"; SlashCmdList["QUESTITEM"] = QuestItem_Config_OnCommand; QuestItem_PrintToScreen(QUESTITEM_LOADED); --QuestItem_Sky_OnLoad(); QuestItem_HookTooltip(); end ----------------- -- OnEvent method ----------------- ----------------- function QuestItem_OnEvent(event) if(event == "VARIABLES_LOADED") then QuestItem_VariablesLoaded(); this:UnregisterEvent("VARIABLES_LOADED"); if(QuestItem_Settings["version"] and QuestItem_Settings["Enabled"] == true) then this:RegisterEvent("UI_INFO_MESSAGE"); end return; end if(not arg1) then return; end local itemText = gsub(arg1,"(.*): %d+/%d+","%1",1); if(event == "UI_INFO_MESSAGE") then local itemCount = gsub(arg1,"(.*): (%d+)/(%d+)","%2"); local itemTotal = gsub(arg1,"(.*): (%d+)/(%d+)","%3"); -- Ignore trade and duel events if(itemText ~= arg1 and not strfind(itemText, QUESTITEM_SLAIN)) then QuestItem_Debug("Looking for quest item "..itemText); QuestItem_LocateQuest(itemText, itemCount, itemTotal); end elseif(event == "DELETE") then if(QuestItems[itemText]) then QuestItems[itemText] = nil; QuestItem_Debug("Deleted"); end end end ------------------------------------ -- Initialize settings if not found. ------------------------------------ ------------------------------------ function QuestItem_VariablesLoaded() if ( QuestItem_Settings and QuestItem_Settings["version"] == QUESTITEM_VERSION ) then return; end if (not QuestItem_Settings) then QuestItem_Settings = { }; end -- No settings exist QuestItem_Settings["version"] = QUESTITEM_VERSION; QuestItem_Settings["Enabled"] = true; QuestItem_Settings["Alert"] = true; -- Check if AxuItemMenus is installed if(AxuItemMenus_AddTestHook) then QuestItem_Settings["DisplayRequest"] = false; else QuestItem_Settings["DisplayRequest"] = false; end QuestItem_Settings["ShiftOpen"] = false; QuestItem_Settings["AltOpen"] = true; end --------------- --------------- --------------- -- FUNCTIONS -- --------------- --------------- --------------- -- Print debug message to the default chatframe. -- Only works if the DEBUG variable in the -- beginning of QuestItem.lua is set to true. ------------------------------------------------ ------------------------------------------------ function QuestItem_Debug(message) if(DEBUG) then if(not message) then DEFAULT_CHAT_FRAME:AddMessage("Debug: Message was nil", 0.9, 0.5, 0.3); else DEFAULT_CHAT_FRAME:AddMessage("Debug: " ..message, 0.9, 0.5, 0.3); end end end function QuestItem_PrintToScreen(message) UIErrorsFrame:AddMessage(message, 0.4, 0.5, 0.8, 1.0, 8); end --------------------------------------------------- -- Find out if an item is a quest item by searching -- the text in the tooltip. --------------------------------------------------- --------------------------------------------------- function QuestItem_IsQuestItem(tooltip) if(tooltip) then local tooltip = getglobal(tooltip:GetName() .. "TextLeft"..2); if(tooltip and tooltip:GetText()) then if(QuestItem_SearchString(tooltip:GetText(), QUESTITEM_QUESTITEM)) then return true; end end end return false; end -------------------------------------------- -- Open the specified quest in the quest log -------------------------------------------- -------------------------------------------- function QuestItem_OpenQuestLog(questName) for y=1, GetNumQuestLogEntries(), 1 do local QuestName, level, questTag, isHeader, isCollapsed, complete = GetQuestLogTitle(y); if(questName == QuestName) then SelectQuestLogEntry(y); local logFrame = getglobal("QuestLogFrame"); if(logFrame ~= nil) then if(logFrame:IsVisible()) then ToggleQuestLog(); end if(QuestLog_SetSelection == nil) then QuestLog_SetSelection(y); end ToggleQuestLog(); end return; end end QuestItem_PrintToScreen(QUESTITEM_NO_QUEST); end --------------------------------------- -- Look for the item in the text string --------------------------------------- --------------------------------------- function QuestItem_SearchString(text, item) if(string.find(string.lower(text), string.lower(item)) ) then return true; end return false; end -- Copied functions - don't want to depend on too many AddOns -- From LootLink function QuestItem_MakeIntFromHexString(str) if(not str) then return 0; end local remain = str; local amount = 0; while( remain ~= "" ) do amount = amount * 10; local byteVal = string.byte(strupper(strsub(remain, 1, 1))); if( byteVal >= string.byte("0") and byteVal <= string.byte("9") ) then amount = amount + (byteVal - string.byte("0")); end remain = strsub(remain, 2); end return amount; end function QuestItem_CheckNumeric(string) local remain = string; local hasNumber; local hasPeriod; local char; while( remain ~= "" and remain ~= nil) do --while( remain ~= "") do char = strsub(remain, 1, 1); if( char >= "0" and char <= "9" ) then hasNumber = 1; elseif( char == "." and not hasPeriod ) then hasPeriod = 1; else return nil; end remain = strsub(remain, 2); end return hasNumber; end -- From Sea function QuestItem_ScanTooltip() local tooltipBase = "GameTooltip"; local strings = {}; for idx = 1, 10 do local textLeft = nil; local textRight = nil; ttext = getglobal(tooltipBase.."TextLeft"..idx); if(ttext and ttext:IsVisible() and ttext:GetText() ~= nil) then textLeft = ttext:GetText(); end ttext = getglobal(tooltipBase.."TextRight"..idx); if(ttext and ttext:IsVisible() and ttext:GetText() ~= nil) then textRight = ttext:GetText(); end if (textLeft or textRight) then strings[idx] = {}; strings[idx].left = textLeft; strings[idx].right = textRight; end end return strings; end