View Single Post
08-31-16, 08:07 AM   #1
Benio
A Murloc Raider
Join Date: Jul 2016
Posts: 8
Pandemic mechanic util

Here I present util how to handle with Pandemic mechanic, since I was unable to find any solution.
With a help of #WoWUIDev, this is the Pandemic util I made for my indev Warlock addon (note that the following util uses global Tooltip, but it's just for clarity):

Lua Code:
  1. Tooltip = Tooltip or {};
  2. local Tooltip = Tooltip;
  3.  
  4. Tooltip._tooltip = 'Tooltip._tooltip';
  5. Tooltip._tooltip_frame = CreateFrame('GameTooltip', Tooltip._tooltip, nil, 'GameTooltipTemplate');
  6.  
  7. -- @param {link} itemLink link to item
  8. -- @return {object} text object of line: text from given @itemLink Tooltip
  9. -- @credits Semlar#WoWUIDev
  10. Tooltip.GetTooltip = Tooltip.GetTooltip or function(itemLink)
  11.     Tooltip._tooltip_frame:SetOwner(UIParent, 'ANCHOR_NONE');
  12.     Tooltip._tooltip_frame:SetHyperlink(itemLink);
  13.    
  14.     local O = {}; -- output
  15.     for i = 1, Tooltip._tooltip_frame:NumLines() do
  16.         local line = _G[Tooltip._tooltip ..'TextLeft' ..i];
  17.         local text = line and line:GetText();
  18.         if not text then break end;
  19.         O[i] = tostring(text);
  20.     end;
  21.    
  22.     return O;
  23. end;
  24.  
  25. -- @param {uint|name} itemID item id or itemName item name
  26. -- @return {number|nil} realDuration real spell duration (unaffected by pandemic) or nil if unknown
  27. -- @credits Xuerian#WoWUIDev
  28. Tooltip.GetSpellDuration = Tooltip.GetSpellDuration or function(itemNameORID)
  29.     local link = GetSpellLink(itemNameORID);
  30.     local text = Tooltip.GetTooltip(link);
  31.     for i = 1, #text do
  32.         local duration = string.match(text[i], "over (%d+%.?%d?) sec");
  33.         if duration ~= nil then
  34.             return tonumber(duration);
  35.         end;
  36.     end;
  37.    
  38.     return nil;
  39. end;
  40.  
  41. -- @param {string} unitID unitID
  42. -- @param {name} itemName item name
  43. -- @param {string} rank UnitAura's rank
  44. -- @param {string} filter UnitAura's filter
  45. -- @return {bool|nil} pandemic if aura is affected by pandemic or nil if unknown
  46. Tooltip.GetUnitAuraPandemic = Tooltip.GetUnitAuraPandemic or function(unitID, itemName, rank, filter)
  47.     local realDuration = Tooltip.GetSpellDuration(itemName);
  48.     local _, _, _, _, _, duration = UnitAura(unitID, itemName, rank, filter);
  49.    
  50.     if
  51.             duration == nil
  52.         or  realDuration == nil
  53.     then return nil end;
  54.    
  55.      -- we love float, doesn't we?
  56.     if math.abs(realDuration - duration) < 0.01 then return false end;
  57.     if math.abs(realDuration *1.3 - duration) < 0.01 then return true end;
  58.    
  59.     return nil;
  60. end;

The idea behind this method is to read the spell duration directly from tooltip, using Tooltip.GetSpellDuration, ex.:
Lua Code:
  1. local realDuration = Tooltip.GetSpellDuration("Siphon Life");
The cache it and whenever checking UnitAura for the same spell, we can use cached value if it's not nil, ex.:
Lua Code:
  1. local _, _, _, _, _, duration = UnitAura("target" "Siphon Life", nil, "PLAYER HARMFUL");
  2. duration = realDuration or duration;

Finally, I've added a handy Tooltip.GetUnitAuraPandemic that takes same arguments like UnitAura, and returns if Spell duration already benefits from Pandemic or not.
Example: Before casting Siphon Life on target:
Lua Code:
  1. [15:20:07] Dump: value=Tooltip.GetUnitAuraPandemic("target", "Siphon Life", nil, "PLAYER HARMFUL");
  2. [15:20:07] empty result
After casting first Siphon Life on target:
Lua Code:
  1. [15:20:12] Dump: value=Tooltip.GetUnitAuraPandemic("target", "Siphon Life", nil, "PLAYER HARMFUL");
  2. [15:20:12] [1]=false
After casting second Siphon Life on target:
Lua Code:
  1. [15:20:15] Dump: value=Tooltip.GetUnitAuraPandemic("target", "Siphon Life", nil, "PLAYER HARMFUL");
  2. [15:20:15] [1]=true
  Reply With Quote