diff Main.lua @ 496:3938b87cfcd3

Radically rewrote currency support for WoWDBProfiler. It now uses currencyIDs everywhere instead of texture paths.
author MMOSimca <mmosimca@gmail.com>
date Tue, 11 Oct 2016 06:13:22 -0400
parents 1d1bbcad6563
children c8a8231c2336
line wrap: on
line diff
--- a/Main.lua	Fri Oct 07 15:44:40 2016 -0400
+++ b/Main.lua	Tue Oct 11 06:13:22 2016 -0400
@@ -16,6 +16,7 @@
 local unpack = _G.unpack
 
 local C_Timer = _G.C_Timer
+local GetCurrencyInfo = _G.GetCurrencyInfo
 
 
 -- ADDON NAMESPACE ----------------------------------------------------
@@ -316,6 +317,42 @@
 end -- do-block
 
 
+local CurrencyInfoToID
+local PopulateCurrencyInfoLookup
+do
+    local MAX_CURRENCY_ID_GAP = 800
+
+    local currency_info_lookup = {}
+
+
+    function CurrencyInfoToID(name, texture)
+        return currency_info_lookup[("%s:%s"):format(name, texture)]
+    end
+
+
+    function PopulateCurrencyInfoLookup()
+        local currency_index = 1
+        local gap_since_last_currency = 0
+        repeat
+            -- Store ID by info (name and texture combined)
+            local name, _, texture = GetCurrencyInfo(currency_index)
+            currency_info_lookup[("%s:%s"):format(name, texture)] = currency_index
+
+            -- If we found nothing, increment gap
+            if not name or not texture or (name == "" and texture == "") then
+                gap_since_last_currency = gap_since_last_currency + 1
+            else
+                gap_since_last_currency = 0
+            end
+
+            -- Increment loop counter
+            currency_index = currency_index + 1
+
+        until (gap_since_last_currency > MAX_CURRENCY_ID_GAP)
+    end
+end
+
+
 local function InstanceDifficultyToken()
     -- Sometimes, instance information is returned when not in an instance. This check protects against that.
     if _G.IsInInstance() then
@@ -472,12 +509,12 @@
 end -- do-block
 
 
-local function CurrencyLinkToTexture(currency_link)
+local function CurrencyLinkToID(currency_link)
     if not currency_link then
-        return
+        return nil
     end
-    local _, _, texture_path = _G.GetCurrencyInfo(tonumber(currency_link:match("currency:(%d+)")))
-    return texture_path:match("[^\\]+$"):lower()
+    return tonumber(currency_link:match("currency:(%d+)")) or 0
+    --texture_path:match("[^\\]+$"):lower()
 end
 
 
@@ -698,10 +735,14 @@
                         end
                     else
                         for loot_token, quantity in pairs(loot_data) do
-                            local label, currency_texture = (":"):split(loot_token)
-
-                            if label == "currency" and currency_texture then
-                                table.insert(loot_table, ("currency:%d:%s"):format(quantity, currency_texture))
+                            local label, currency_id = (":"):split(loot_token)
+
+                            if label == "currency" and currency_id then
+                                -- Convert currency_id back into number from string
+                                currency_id = tonumber(currency_id) or 0
+                                if currency_id ~= 0 then
+                                    table.insert(loot_table, ("currency:%d:%d"):format(quantity, currency_id))
+                                end
                             elseif loot_token == "money" then
                                 table.insert(loot_table, ("money:%d"):format(quantity))
                             else
@@ -832,10 +873,14 @@
             entry["contains_count"] = (entry["contains_count"] or 0) + 1
 
             for loot_token, quantity in pairs(chat_loot_data.loot) do
-                local label, currency_texture = (":"):split(loot_token)
-
-                if label == "currency" and currency_texture then
-                    table.insert(loot_table, ("currency:%d:%s"):format(quantity, currency_texture))
+                local label, currency_id = (":"):split(loot_token)
+
+                if label == "currency" and currency_id then
+                    -- Convert currency_id back into number from string
+                    currency_id = tonumber(currency_id) or 0
+                    if currency_id ~= 0 then
+                        table.insert(loot_table, ("currency:%d:%d"):format(quantity, currency_id))
+                    end
                 elseif loot_token == "money" then
                     table.insert(loot_table, ("money:%d"):format(quantity))
                 else
@@ -913,9 +958,13 @@
         end
     end
 
+    -- Gather known languages
     for index = 1, _G.GetNumLanguages() do
         languages_known[_G.GetLanguageByIndex(index)] = true
     end
+    
+    -- Populate currency data from known currency information
+    PopulateCurrencyInfoLookup()
 
     -- These timers loop indefinitely using Lua's infinity constant
     item_process_timer_handle = C_Timer.NewTicker(DELAY_PROCESS_ITEMS, WDP.ProcessItems, math.huge)
@@ -976,23 +1025,21 @@
         -- Record currencies
         entry["rewards"]["currency_count"] = tonumber(_G.GetNumQuestLogRewardCurrencies(quest_id)) or 0
 
+        -- Create currency rewards sub-table and fill
         if entry["rewards"]["currency_count"] > 0 then
-
-            -- Create currency rewards sub-table and fill
             entry["rewards"]["currencies"] = {}
             for i = 1, entry["rewards"]["currency_count"] do
                 local name, texture_path, quantity = _G.GetQuestLogRewardCurrencyInfo(i, quest_id)
-                local currency_texture = texture_path:match("[^\\]+$"):lower()
-                table.insert(entry["rewards"]["currencies"], ("%d:%s"):format(quantity, currency_texture))
+                local currency_id = CurrencyInfoToID(name, texture_path)
+                table.insert(entry["rewards"]["currencies"], ("%d:%d"):format(quantity, currency_id))
             end
         end
 
         -- Record items
         entry["rewards"]["item_count"] = tonumber(_G.GetNumQuestLogRewards(quest_id)) or 0
 
+        -- Create item rewards sub-table and fill
         if entry["rewards"]["item_count"] > 0 then
-
-            -- Create item rewards sub-table and fill
             entry["rewards"]["items"] = {}
             for i = 1, entry["rewards"]["item_count"] do
                 local item_name, item_texture, quantity, quality, is_usable, item_id = _G.GetQuestLogRewardInfo(i, quest_id)
@@ -1172,6 +1219,7 @@
     }
 
 
+    -- We should just use IDs here someday; WoWDB site knows all about different power types
     local POWER_TYPE_NAMES = {
         ["0"] = "MANA",
         ["1"] = "RAGE",
@@ -1212,6 +1260,7 @@
         end
         level_data.max_health = level_data.max_health or _G.UnitHealthMax("target")
 
+        -- May not capture as much data as it could, since the API changed in Legion to report multiple types of power
         if not level_data.power then
             local max_power = _G.UnitPowerMax("target")
 
@@ -1385,8 +1434,8 @@
         UpdateDBEntryLocation("objects", ("OPENING:%d"):format(last_garrison_cache_object_id))
 
         -- Add drop data
-        local currency_texture = CurrencyLinkToTexture(item_link)
-        if currency_texture and currency_texture ~= "" then
+        local currency_id = CurrencyLinkToID(item_link)
+        if currency_id and currency_id ~= 0 then
             -- Check for top level object data
             local object_entry = DBEntry("objects", ("OPENING:%d"):format(last_garrison_cache_object_id))
             local difficulty_token = InstanceDifficultyToken()
@@ -1394,14 +1443,14 @@
                 -- Increment loot count
                 object_entry[difficulty_token]["opening_count"] = (object_entry[difficulty_token]["opening_count"] or 0) + 1
 
-                Debug("%s: %s X %d", event_name, currency_texture, quantity)
+                Debug("%s: %d X %d", event_name, currency_id, quantity)
                 object_entry[difficulty_token]["opening"] = object_entry[difficulty_token]["opening"] or {}
-                table.insert(object_entry[difficulty_token]["opening"], ("currency:%d:%s"):format(quantity, currency_texture))
+                table.insert(object_entry[difficulty_token]["opening"], ("currency:%d:%d"):format(quantity, currency_id))
             else
                 Debug("%s: When handling the Garrison cache, the top level loot data was missing for objectID %d.", event_name, last_garrison_cache_object_id)
             end
         else
-            Debug("%s: Currency texture is nil, from currency link %s", event_name, item_link)
+            Debug("%s: Currency ID is nil or 0, from currency link %s", event_name, item_link)
         end
 
         -- Wipe object ID until future mouseover
@@ -1428,12 +1477,12 @@
                 Debug("%s: money X %d", event_name, quantity)
                 table.insert(encounter_data[loot_label], ("money:%d"):format(quantity))
             elseif loot_type == "currency" then
-                local currency_texture = CurrencyLinkToTexture(item_link)
-                if currency_texture and currency_texture ~= "" then
-                    Debug("%s: %s X %d", event_name, currency_texture, quantity)
-                    table.insert(encounter_data[loot_label], ("currency:%d:%s"):format(quantity, currency_texture))
+                local currency_id = CurrencyLinkToID(item_link)
+                if currency_id and currency_id ~= 0 then
+                    Debug("%s: %d X %d", event_name, currency_id, quantity)
+                    table.insert(encounter_data[loot_label], ("currency:%d:%d"):format(quantity, currency_id))
                 else
-                    Debug("%s: Currency texture is nil, from currency link %s", event_name, item_link)
+                    Debug("%s: Currency ID is nil or 0, from currency link %s", event_name, item_link)
                     return
                 end
             end
@@ -1468,13 +1517,13 @@
             Debug("%s: money X %d", event_name, quantity)
             current_loot.sources[loot_toast_container_id]["money"] = (current_loot.sources[loot_toast_container_id]["money"] or 0) + quantity
         elseif loot_type == "currency" then
-            local currency_texture = CurrencyLinkToTexture(item_link)
-            if currency_texture and currency_texture ~= "" then
-                Debug("%s: %s X %d", event_name, currency_texture, quantity)
-                local currency_token = ("currency:%s"):format(currency_texture)
+            local currency_id = CurrencyLinkToID(item_link)
+            if currency_id and currency_id ~= 0 then
+                Debug("%s: %d X %d", event_name, currency_id, quantity)
+                local currency_token = ("currency:%d"):format(currency_id)
                 current_loot.sources[loot_toast_container_id][currency_token] = (current_loot.sources[loot_toast_container_id][currency_token] or 0) + quantity
             else
-                Debug("%s: Currency texture is nil, from currency link %s", event_name, item_link)
+                Debug("%s: Currency ID is nil or 0, from currency link %s", event_name, item_link)
                 current_loot = nil
                 return
             end
@@ -1486,12 +1535,12 @@
     elseif loot_source and (loot_source == LOOT_SOURCE_ID_REDUNDANT) and chat_loot_timer_handle then
         -- Handle currency loot toasts for chat-based loot (we do this instead of reading currency chat messages because the chat messages are very delayed)
         if loot_type == "currency" then
-            local currency_texture = CurrencyLinkToTexture(item_link)
-            if currency_texture and currency_texture ~= "" then
+            local currency_id = CurrencyLinkToID(item_link)
+            if currency_id and currency_id ~= 0 then
                 -- Verify that we're still assigning data to the right items
                 if chat_loot_data.identifier and (private.CONTAINER_ITEM_ID_LIST[chat_loot_data.identifier] ~= nil) then
-                    local currency_token = ("currency:%s"):format(currency_texture)
-                    Debug("%s: Captured currency for chat-based loot recording. %s X %d", event_name, currency_token, quantity)
+                    Debug("%s: Captured currency for chat-based loot recording. %d X %d", event_name, currency_id, quantity)
+                    local currency_token = ("currency:%d"):format(currency_id)
                     chat_loot_data.loot = chat_loot_data.loot or {}
                     chat_loot_data.loot[currency_token] = (chat_loot_data.loot[currency_token] or 0) + quantity
                 else -- If not, cancel the timer and wipe the loot table early
@@ -1499,7 +1548,7 @@
                     ClearChatLootData()
                 end
             else
-                Debug("%s: Currency texture is nil, from currency link %s", event_name, item_link)
+                Debug("%s: Currency ID is nil or 0, from currency link %s", event_name, item_link)
             end
         -- Handle money loot toasts for chat-based loot (we do this instead of reading money chat messages because the chat messages are very delayed)
         elseif loot_type == "money" then
@@ -1531,14 +1580,13 @@
 
 do
     local CHAT_MSG_CURRENCY_UPDATE_FUNCS = {
-        [AF.NPC] = function(currency_texture, quantity)
-            Debug("CHAT_MSG_CURRENCY: AF.NPC currency:%s (%d)", currency_texture, quantity)
+        [AF.NPC] = function(currency_id, quantity)
+            Debug("CHAT_MSG_CURRENCY: AF.NPC currency:%d (%d)", currency_id, quantity)
         end,
-        [AF.ZONE] = function(currency_texture, quantity)
-            local currency_token = ("currency:%s"):format(currency_texture)
-            Debug("CHAT_MSG_CURRENCY: AF.ZONE %s (%d)", currency_token, quantity)
+        [AF.ZONE] = function(currency_id, quantity)
+            Debug("CHAT_MSG_CURRENCY: AF.ZONE currency:%d (%d)", currency_id, quantity)
             InitializeCurrentLoot()
-            current_loot.list[1] = ("%s:%d"):format(currency_token, quantity)
+            current_loot.list[1] = ("currency:%d:%d"):format(quantity, currency_id)
             GenericLootUpdate("zones")
             current_loot = nil
         end,
@@ -1552,9 +1600,9 @@
         if not currency_link then
             quantity, currency_link = 1, deformat(message, _G.CURRENCY_GAINED)
         end
-        local currency_texture = CurrencyLinkToTexture(currency_link)
-
-        if not currency_texture or currency_texture == "" then
+        local currency_id = CurrencyLinkToID(currency_link)
+
+        if not currency_id or currency_id == 0 then
             return
         end
 
@@ -1570,7 +1618,7 @@
         if not category or not update_func then
             return
         end
-        update_func(currency_texture, quantity)
+        update_func(currency_id, quantity)
     end
 
 
@@ -1785,7 +1833,6 @@
         [215377] = true, -- The Maw Must Feed (applied by Maw of the Damned, Blood Death Knight artifact)
         [224762] = true, -- Leyline Rift (summoned by players with Leyline Mastery in Suramar)
         [225832] = true, -- Nightglow Wisp (cast by players using Wisp in a Bottle toy)
-        
     }
 
     local function RecordNPCSpell(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, spell_id, spell_name)
@@ -2068,10 +2115,14 @@
                     end
 
                     for loot_token, quantity in pairs(loot_data) do
-                        local loot_type, currency_texture = (":"):split(loot_token)
-
-                        if loot_type == "currency" and currency_texture then
-                            table.insert(encounter_data[loot_label], ("currency:%d:%s"):format(quantity, currency_texture))
+                        local loot_type, currency_id = (":"):split(loot_token)
+
+                        if loot_type == "currency" and currency_id then
+                            -- Convert currency_id back into number from string
+                            currency_id = tonumber(currency_id) or 0
+                            if currency_id ~= 0 then
+                                table.insert(encounter_data[loot_label], ("currency:%d:%d"):format(quantity, currency_id))
+                            end
                         elseif loot_token == "money" then
                             table.insert(encounter_data[loot_label], ("money:%d"):format(quantity))
                         else
@@ -2280,7 +2331,7 @@
         loot_guid_registry[current_loot.label] = loot_guid_registry[current_loot.label] or {}
 
         for loot_slot = 1, _G.GetNumLootItems() do
-            local texturefiledataID, item_text, slot_quantity, quality, locked = _G.GetLootSlotInfo(loot_slot)
+            local texture_filedata_id, item_text, slot_quantity, quality, locked = _G.GetLootSlotInfo(loot_slot)
             local slot_type = _G.GetLootSlotType(loot_slot)
             local loot_info = { _G.GetLootSourceInfo(loot_slot) }
             local loot_link = _G.GetLootSlotLink(loot_slot)
@@ -2322,12 +2373,12 @@
                         elseif slot_type == LOOT_SLOT_CURRENCY then
                             -- Same bug with GetLootSlotInfo() will screw up currency when it happens, so we won't process this slot's loot.
                             if loot_link then
-                                local icon_texture = CurrencyLinkToTexture(loot_link)
-                                Debug("GUID: %s - Type:ID: %s - Currency: %s - Amount: %d (%d)", loot_info[loot_index], source_key, icon_texture, loot_info[loot_index + 1], slot_quantity)
+                                local currency_id = CurrencyLinkToID(loot_link)
+                                Debug("GUID: %s - Type:ID: %s - Currency: %d - Amount: %d (%d)", loot_info[loot_index], source_key, currency_id, loot_info[loot_index + 1], slot_quantity)
                                 if current_loot.target_type == AF.ZONE then
-                                    table.insert(current_loot.list, ("currency:%d:%s"):format(loot_quantity, icon_texture))
+                                    table.insert(current_loot.list, ("currency:%d:%d"):format(loot_quantity, currency_id))
                                 else
-                                    local currency_token = ("currency:%s"):format(icon_texture)
+                                    local currency_token = ("currency:%d"):format(currency_id)
 
                                     current_loot.sources[source_guid] = current_loot.sources[source_guid] or {}
                                     current_loot.sources[source_guid][currency_token] = (current_loot.sources[source_guid][currency_token] or 0) + loot_quantity
@@ -2485,15 +2536,14 @@
 
                     for cost_index = 1, item_count do
                         -- The third return (Blizz calls "currency_link") of GetMerchantItemCostItem only returns item links as of Patch 5.3.0.
-                        local icon_texture, amount_required, item_link = _G.GetMerchantItemCostItem(item_index, cost_index)
-                        local currency_identifier = item_link and ItemLinkToID(item_link) or nil
-
-                        if (not currency_identifier or currency_identifier < 1) and icon_texture then
-                            currency_identifier = icon_texture:match("[^\\]+$"):lower()
-                        end
-
-                        if currency_identifier then
-                            currency_list[#currency_list + 1] = ("(%s:%s)"):format(amount_required, currency_identifier)
+                        local texture_path, amount_required, item_link, name = _G.GetMerchantItemCostItem(item_index, cost_index)
+
+                        -- Try to detect if this is actually a currency by looking for a nil item_link or item ID
+                        local is_item = item_link and ItemLinkToID(item_link)
+
+                        if not is_item then
+                            local currency_id = CurrencyInfoToID(name, texture_path)
+                            currency_list[#currency_list + 1] = ("(%s:%d)"):format(amount_required, currency_id)
                         end
                     end
 
@@ -2873,9 +2923,9 @@
                     Debug("%s: Assigned stored money loot data - money:%d", event_name, quantity)
                     table.insert(encounter_data[loot_label], ("money:%d"):format(quantity))
                 elseif loot_type == "currency" then
-                    local currency_texture = CurrencyLinkToTexture(hyperlink)
-                    Debug("%s: Assigned stored currency loot data - %s - currency:%d:%s", event_name, hyperlink, currency_texture, quantity)
-                    table.insert(encounter_data[loot_label], ("currency:%d:%s"):format(quantity, currency_texture))
+                    local currency_id = CurrencyLinkToID(hyperlink)
+                    Debug("%s: Assigned stored currency loot data - %s - currency:%d (%d)", event_name, hyperlink, currency_id, quantity)
+                    table.insert(encounter_data[loot_label], ("currency:%d:%d"):format(quantity, currency_id))
                 end
             end