vanilla-wow-addons – Rev 1

Subversion Repositories:
Rev:
--[[ 
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

Generated by GNU Enscript 1.6.5.90.