vanilla-wow-addons – Rev 1
?pathlinks?
--[[
DynamicData
By sarf
This AddOn allows you to access dynamic data in WoW without being forced to rely on strange Blizzard functions
Thanks goes to the Sea people, the UltimateUI team and finally the nice (but strange) people at
#ultimateuitesters and Blizzard.
UltimateUIUI URL:
http://www.ultimateuiui.org/forums/viewtopic.php?t=NOT_YET_ANNOUNCED
]]
-- Utility functions
DynamicData.util = {
-- public functions
--
-- addOnWhateverHandler (func)
--
-- Adds a function name that will be called on whatever.
--
addOnWhateverHandler = function (list, func)
for k, v in list do
if ( v == func ) then
return false;
end
end
table.insert(list, func);
return true;
end;
--
-- removeOnWhateverHandler (list, func)
--
-- Removes the specified function, so that it will not be called on whatever.
--
removeOnWhateverHandler = function (list, func)
local index = nil;
for k, v in list do
if ( v == func ) then
index = k;
break;
end
end
if ( index ) then
table.remove(list, index);
return true;
else
return false;
end
end;
--
-- notifyWhateverHandlers (list, ...)
--
-- Args:
-- list - the list of handlers
--
-- Notifies all handlers that an Whatever has occurred.
--
notifyWhateverHandlers = function (list, ...)
local func = nil;
for k, v in list do
func = v;
if ( arg ) then
func(unpack(arg));
else
func();
end
end
end;
--
-- removeEntryFromList (value, list, limit)
--
-- Removes value from the list, up to limit times.
-- If limit is not specified, it will be removed once. If limit is 0 or lower, all values will be removed.
--
removeEntryFromList = function (value, list, limit)
if ( not limit ) then limit = 1; end
if ( limit <= 0 ) then limit = -1; end
local hasRemoved = false;
local found = true;
local index = 1;
while ( found ) do
found = false;
index = DynamicData.util.getIndexInList(value, list);
if ( index ) then
found = true;
table.remove(list, index);
hasRemoved = true;
if ( limit > 0 ) then
limit = limit - 1;
end
if ( limit == 0 ) then
break;
end
end
end
return hasRemoved;
end;
--
-- isThingyEqual(value, valueCheck)
--
-- compares two things and sees if they are equal to each other
--
isThingyEqual = function(value, valueCheck)
if ( value == valueCheck ) then
return true;
else
if ( type(valueCheck) == "table" ) then
return DynamicData.util.isStringInList(value, valueCheck);
end
return false;
end
end;
--
-- getIndexInList (value, list, start)
--
-- Retrieves the index of value in list, starting at start.
-- Start is 1 if unspecified.
--
getIndexInList = function (value, list, start)
if ( not value ) then
return nil;
end
if ( not list ) then
return nil;
end
if ( type(list) ~= "table" ) and ( type(value) == "table" ) then
local tmp = list;
list = value;
value = tmp;
end
local found = true;
local index = nil;
local listSize = table.getn(list);
local oldStart = start;
if ( listSize > 0 ) then
if ( not start ) then start = 1; end
for i = start, listSize do
if ( DynamicData.util.isThingyEqual(list[i], value ) ) then
index = i;
break;
end
end
if ( not index ) then
for k, v in list do
if ( ( not oldStart ) or ( oldStart >= k ) ) and ( DynamicData.util.isThingyEqual(v, value ) ) then
index = k;
break;
end
end
end
else
for k, v in list do
if ( DynamicData.util.isThingyEqual(v, value ) ) then
index = k;
break;
end
end
end
return index;
end;
--
-- isStringInList (str, list)
--
-- Returns true if str is a value of list.
--
isStringInList = function (param1, param2)
if ( not param1 ) or ( not param2 ) then
return false;
end
local str = param1;
local list = param2;
if ( type(param1) == "table" ) then
str = param2;
list = param1;
end
for k, v in list do
if ( v == str ) then
return true;
end
end
return false;
end;
--
-- safeToUseTooltips ()
--
-- Checks if it is "safe" to use tooltips to dump information.
-- Basically, it checks if one (or more) particular frames are visible.
-- If they are, it is not safe to use tooltips.
safeToUseTooltips = function (ignoreList)
local frame = nil;
local list = {};
if ( DynamicData.util.tooltipUsingFrames ) then
for k, v in DynamicData.util.tooltipUsingFrames do
list[v] = 1;
end
end
if ( ignoreList ) then
for k, v in ignoreList do
list[v] = nil;
end
end
for k, v in list do
frame = getglobal(k);
if ( ( frame ) and ( frame:IsVisible() ) ) then
return false;
end
end
return true;
end;
--
-- clearTooltipStrings (tooltipName)
--
-- Clears a tooltip of text.
--
clearTooltipStrings = function (tooltipName)
-- local tooltip = getglobal(tooltipName);
if ( tooltip ) then
local textObj = nil;
for i = 1, 15 do
textObj = getglobal(tooltipName.."TextLeft"..i);
if ( textObj ) then
textObj:SetText("");
end
textObj = getglobal(tooltipName.."TextRight"..i);
if ( textObj ) then
textObj:SetText("");
end
end
end
end;
--
-- getNameFromTooltip (tooltipName)
--
-- Retrieves the name from the specified tooltip.
--
getNameFromTooltip = function (tooltipName)
local strings = DynamicData.util.getTooltipStrings(tooltipName);
if ( strings ) and ( strings[1] ) then
return strings[1].left;
else
return nil;
end
end;
--
-- getTooltipStrings (tooltipName)
--
-- Retrieves strings from the specified tooltip.
-- It basically takes all strings in the tooltip and puts them in an array and returns the array.
-- All credit to Sea for this one, even though it is not copy/pasted! ;)
--
getTooltipStrings = function (tooltipName, strings)
if ( not strings ) then
strings = {};
end
local tooltip = getglobal(tooltipName);
if ( tooltip ) then
local textObj = nil;
local textLeft = nil;
local textRight = nil;
local hasElement = false;
for i = 1, 15 do
hasElement = false;
textObj = getglobal(tooltipName.."TextLeft"..i);
if ( textObj ) then
textLeft = textObj:GetText();
if ( textLeft ) and ( strlen(textLeft) > 0 ) then
hasElement = true;
end
else
textLeft = nil;
end
textObj = getglobal(tooltipName.."TextRight"..i);
if ( textObj ) then
textRight = textObj:GetText();
if ( textRight ) and ( strlen(textRight) > 0 ) then
hasElement = true;
end
else
textRight = nil;
end
if ( hasElement ) then
strings[i] = {};
strings[i].left = textLeft;
strings[i].right = textRight;
end
end
end
return strings;
end;
--
-- getItemTooltipInfo (bag, slot, tooltipName)
--
-- Retrieves info about a particular item.
--
getItemTooltipInfo = function (bag, slot, tooltipName, strings)
if ( not tooltipName ) then
tooltipName = "DynamicDataTooltip";
end
local tooltip = getglobal(tooltipName);
DynamicData.util.clearTooltipStrings(tooltipName);
if ( bag > -1 ) then
DynamicData.util.protectTooltipMoney();
tooltip:SetBagItem(bag, slot);
DynamicData.util.unprotectTooltipMoney();
strings = DynamicData.util.getTooltipStrings(tooltipName, strings);
else
if ( slot == -1 ) then
return nil;
end
DynamicData.util.protectTooltipMoney();
local hasItem, hasCooldown = tooltip:SetInventoryItem("player", slot);
DynamicData.util.unprotectTooltipMoney();
strings = DynamicData.util.getTooltipStrings(tooltipName, strings);
if ( not hasItem) then
DynamicData.util.clearTooltipStrings(tooltipName);
if ( strings[1] ) then
strings[1].left = "";
end
end
end
return strings;
end;
--
-- getCurrentAndMaxDurability (strings)
--
-- Extracts durability info from an array that correspond to a tooltip.
--
getCurrentAndMaxDurability = function (strings)
if ( not strings ) then
return nil, nil;
end
local index = nil;
local index2 = nil;
local tmp = nil;
for k, v in strings do
if ( v.left ) then
index = strfind(v.left, DYNAMICDATA_DURABILITY);
if ( index ) then
tmp = strsub(v.left, strlen(DYNAMICDATA_DURABILITY)+1);
while ( strsub(tmp, 1, 1) == " " ) do
tmp = strsub(tmp, 2);
end
index = strfind(tmp, " ");
index2 = strfind(tmp, "/");
if ( index2 < index ) then
local indexTmp = index;
index = index2;
index2 = indexTmp;
end
local currentDurability = tonumber(strsub(tmp, 1, index-1));
tmp = strsub(tmp, index2+1);
while ( strsub(tmp, 1, 1) == " " ) do
tmp = strsub(tmp, 2);
end
index = strfind(tmp, " ");
if ( not index ) then
index = strlen(tmp);
end
local maxDurability = tonumber(strsub(tmp, 1, index));
return currentDurability, maxDurability;
end
end
end
return nil, nil;
end;
--
-- getDPS (strings)
--
-- Extracts DPS info from an array that correspond to a tooltip.
--
getDPS = function (strings)
if ( not strings ) then
return nil, nil;
end
local tmpNumber = nil;
local tmp = nil;
for k, v in strings do
for tmp in string.gfind(v.left, DYNAMICDATA_DPS_GSUB) do
tmpNumber = tonumber(tmp);
if ( tmpNumber ) then
return tmpNumber;
end
end
end
return nil;
end;
--
-- getItemNameFromLink (link)
--
-- retrieves an item name from a link or nil if it fails
-- Thanks to Telo for providing me with the code!
--
getItemNameFromLink = function (link)
local name;
if( not link ) then
return nil;
end
for name in string.gfind(link, "|c%x+|Hitem:%d+:%d+:%d+:%d+|h%[(.-)%]|h|r") do
return name;
end
return nil;
end;
--
-- isItemNotBindOnAnything (strings)
--
-- Checks if the item represented by the parameter is not bind on anything.
--
isItemNotBindOnAnything = function (strings)
if ( not strings ) then
return false;
end
local tmpNumber = nil;
local tmp = nil;
for k, v in strings do
if ( ( v.left ) and ( string.find(v.left, DYNAMICDATA_BIND_ON) ) ) then
return true;
end
end
return false;
end;
--
-- getDamage (strings)
--
-- Extracts damage info from an array that correspond to a tooltip.
--
getDamage = function (strings)
if ( not strings ) then
return nil, nil;
end
local tmpNumber = nil;
local tmp = nil;
for k, v in strings do
if ( v.left ) then
local firstNumber = nil;
for tmp in string.gfind(v.left, "%w+") do
tmpNumber = tonumber(tmp);
if ( tmpNumber ) then
if ( firstNumber ) then
return firstNumber, tmpNumber;
else
firstNumber = tmpNumber;
end
end
end
end
end
return nil, nil;
end;
--
-- getItemStringType (strings)
--
-- Extracts item type information from an array that correspond to a tooltip.
--
getItemStringType = function (strings)
if ( not strings ) then
return nil;
end
local str = nil;
if ( ( strings[2] ) and ( strings[2].right ) ) then
str = strings[2].right;
end
if ( ( not str ) or ( strlen(str) <= 0 ) ) then
if ( ( strings[3] ) and ( strings[3].right ) ) then
str = strings[3].right;
end
end
if ( ( not str ) or ( strlen(str) <= 0 ) ) then
if ( ( strings[4] ) and ( strings[4].right ) ) then
str = strings[4].right;
end
end
return str;
end;
--
-- extractWeaponSpeed (str)
--
-- Extracts weapon speed information from a string.
--
extractWeaponSpeed = function (str)
local speed = -1;
local tmp = str;
local index = strfind(tmp, DYNAMICDATA_WEAPON_SPEED);
if ( index ) then
tmp = strsub(tmp, index+1);
while ( strsub(tmp, 1, 1) == " " ) do
tmp = strsub(tmp, 2);
end
speed = tonumber(tmp);
if ( not speed ) then
speed = -1;
end
end
return speed;
end;
--
-- getWeaponSpeed (strings)
--
-- Extracts weapon speed information from an array that correspond to a tooltip.
--
getWeaponSpeed = function (strings)
if ( not strings ) then
return nil;
end
local str = "";
if ( ( strings[2] ) and ( strings[2].right ) ) then
str = strings[2].right;
end
if ( strlen(str) <= 0 ) then
if ( ( strings[3] ) and ( strings[3].right ) ) then
str = strings[3].right;
end
else
end
if ( strlen(str) <= 0 ) then
if ( ( strings[4] ) and ( strings[4].right ) ) then
str = strings[4].right;
end
end
local speed = DynamicData.util.extractWeaponSpeed(str);
if ( speed <= 0 ) then
return nil;
else
return speed;
end
end;
--
-- protectTooltipMoney ()
--
-- Thanks to Telo for providing this solution!
-- Prevents the clearing of money from tooltips.
-- USE WITH CAUTION! ALWAYS CALL unhookMoneyTooltip() AFTER SETTING THE TOOLTIP!
--
protectTooltipMoney = function()
if ( not DynamicData.util.saved_GameTooltip_ClearMoney ) then
DynamicData.util.saved_GameTooltip_ClearMoney = GameTooltip_ClearMoney;
GameTooltip_ClearMoney = DynamicData.util.doNothing;
end
end;
--
-- unprotectTooltipMoney ()
--
-- Thanks to Telo for providing this solution!
-- Allows the clearing of money from tooltips.
--
unprotectTooltipMoney = function()
if ( DynamicData.util.saved_GameTooltip_ClearMoney ) then
GameTooltip_ClearMoney = DynamicData.util.saved_GameTooltip_ClearMoney;
DynamicData.util.saved_GameTooltip_ClearMoney = nil;
end
end;
--
-- scheduleFunction(when, function, [arguments])
--
-- schedules a function to occur in WHEN seconds.
--
scheduleFunction = function(when, func, ...)
if ( not when ) then
return;
end
if ( not func ) then
return;
end
local scheduledFunction = {};
scheduledFunction.time = when+GetTime();
scheduledFunction.func = func;
scheduledFunction.args = arg;
DynamicData.util.addScheduledFunction(scheduledFunction);
end;
--
-- scheduleNamedFunction(name, when, function, [arguments])
--
-- schedules a function to occur in WHEN seconds. Only one function with the same name will be scheduled.
--
scheduleNamedFunction = function(name, when, func, ...)
if ( not name ) then
if ( arg ) then
return DynamicData.util.scheduleFunction(when, func, unpack(arg));
else
return DynamicData.util.scheduleFunction(when, func);
end
end
if ( not func ) then
return;
end
local scheduledFunction = {};
scheduledFunction.name = name;
scheduledFunction.time = when+GetTime();
scheduledFunction.func = func;
scheduledFunction.args = arg;
local i;
local size = table.getn(DynamicData.util.scheduledFunctions);
local entry = nil;
for i=1, size, 1 do
entry = DynamicData.util.scheduledFunctions[i];
if ( ( entry.name ) and ( entry.name == name ) ) then
table.remove(DynamicData.util.scheduledFunctions, i);
break;
end
end
DynamicData.util.addScheduledFunction(scheduledFunction);
end;
--
-- scheduleAfterInitFunction (function, [args] )
--
-- schedules a function to be run after the init.
--
scheduleAfterInitFunction = function (func, ...)
local playerName = UnitName("player");
if ( ( playerName ) and ( playerName ~= TEXT(UKNOWNBEING) ) and ( DynamicData.util.variablesHasBeenLoaded ) ) then
if ( arg ) then
func(unpack(arg));
else
func();
end
else
if ( arg ) then
DynamicData.util.scheduleFunction(1, DynamicData.util.scheduleAfterInitFunction, func, unpack(arg));
else
DynamicData.util.scheduleFunction(1, DynamicData.util.scheduleAfterInitFunction, func);
end
end
end;
-- protected functions
--
-- postpone (params)
--
-- params.schedulingName = scheduling name
-- params.func = function name
-- params.args = function arguments
-- params.lastPostponedName = name of the variable with last postponed information
-- params.lastUpdatedName = name of the variable with last updated information
-- params.minimumDelay = the smallest amount of time between function calls
--
postpone = function (params)
local curTime = GetTime();
if ( not params.minimumDelay ) then
params.minimumDelay = 0.1;
end
if ( not params.lastPostponedName ) then
params.lastPostponedName = params.schedulingName.."_lastPostponedName";
end
if ( not params.lastUpdatedName ) then
params.lastUpdatedName = params.schedulingName.."_lastUpdatedName";
end
setglobal(params.lastPostponedName, curTime);
-- postpone checking until the updates have stopped
if ( params.schedulingName ) then
UltimateUI_ScheduleByName(params.schedulingName, params.minimumDelay+0.01, DynamicData.util.handlePostponement, params);
else
UltimateUI_Schedule(params.minimumDelay+0.01, DynamicData.util.handlePostponement, params);
end
end;
--
-- handlePostponement (params)
--
-- params.schedulingName = scheduling name
-- params.func = function name
-- params.args = function arguments
-- params.lastPostponedName = name of the variable with last postponed information
-- params.lastUpdatedName = name of the variable with last updated information
-- params.minimumDelay = the smallest amount of time between function calls
--
handlePostponement = function (params)
local curTime = GetTime();
local lastPostponed = getglobal(params.lastPostponedName);
local lastUpdated = getglobal(params.lastUpdatedName);
if ( not lastPostponed ) then
lastPostponed = 0;
end
if ( not lastUpdated ) then
lastUpdated = 0;
end
if ( ( lastPostponed == 0 ) or ( curTime-lastPostponed <= params.minimumDelay ) and ( params.allowInitialUpdate == 1 ) ) then
postpone(params);
return;
end
if ( curTime-lastUpdated <= params.minimumDelay ) then
postpone(params);
return;
end
setglobal(params.lastPostponedName, 0);
setglobal(params.lastUpdatedName, curTime);
local f = params.func;
if ( f ) then
if ( params.args ) then
f(unpack(params.args));
else
f();
end
end
end;
-- private functions
--
-- addTooltipUsingFrame (frame)
--
-- Adds a frame to the list of frames that want tooltips to be untouched.
--
addTooltipUsingFrame = function(frame)
if ( not frame ) then
return;
end
local frameName = nil;
if ( type(frame) == "string" ) then
frameName = frame;
else
frameName = frame:GetName();
end
if ( not frameName ) then
return;
end
for k, v in DynamicData.util.tooltipUsingFrames do
if ( v == frameName ) then
return;
end
end
table.insert(DynamicData.util.tooltipUsingFrames, frameName);
end;
--
-- doNothing()
--
-- Does nothing.
--
doNothing = function()
end;
--
-- handleScheduledFunctions(elapsed)
--
-- handles scheduled functions
--
handleScheduledFunctions = function(elapsed)
local curTime = GetTime();
local scheduledFunction = {};
while ( ( DynamicData.util.scheduledFunctions[1] ) and ( DynamicData.util.scheduledFunctions[1].time <= curTime ) ) do
scheduledFunction = table.remove(DynamicData.util.scheduledFunctions, 1);
if ( scheduledFunction.args) then
scheduledFunction.func(unpack(scheduledFunction.args));
else
scheduledFunction.func();
end
end
end;
--
-- OnLoad()
--
-- sets up the util library. NOTE: This inserts an emulated UltimateUI_Schedule if not present.
--
OnLoad = function()
local needHandler = false;
if ( not UltimateUI_Schedule ) then
UltimateUI_Schedule = DynamicData.util.scheduleFunction;
needHandler = true;
end
if ( not UltimateUI_ScheduleByName ) then
UltimateUI_ScheduleByName = DynamicData.util.scheduleNamedFunction;
needHandler = true;
end
if ( not UltimateUI_AfterInit ) then
UltimateUI_AfterInit = DynamicData.util.scheduleAfterInitFunction;
needHandler = true;
end
if ( needHandler ) then
DynamicData.util.addOnTimeUpdateHandler(DynamicData.util.handleScheduledFunctions);
end
end;
--
-- addOnTimeUpdateHandler(func)
--
-- adds the func to the OnTime update handlers
--
addOnTimeUpdateHandler = function (func)
DynamicData.util.addOnWhateverHandler(DynamicData.util.onUpdateHandlers, func);
end;
--
-- removeOnTimeUpdateHandler(func)
--
-- removes the func from the OnTime update handlers
--
removeOnTimeUpdateHandler = function (func)
DynamicData.util.removeOnWhateverHandler(DynamicData.util.onUpdateHandlers, func);
end;
--
-- variablesLoaded()
--
-- run on VARIABLES_LOADED event
--
variablesLoaded = function ()
variablesHasBeenLoaded = true;
end;
--
-- addScheduledFunction(scheduledFunction)
--
-- schedules a function to occur sometime
--
addScheduledFunction = function(scheduledFunction)
local i = 1;
while ( ( DynamicData.util.scheduledFunctions[i] ) and ( DynamicData.util.scheduledFunctions[i].time < scheduledFunction.time ) ) do
i = i + 1;
end
table.insert(DynamicData.util.scheduledFunctions, i, scheduledFunction);
end;
-- variables
variablesHasBeenLoaded = false;
scheduledFunctions = {};
onUpdateHandlers = {};
saved_GameTooltip_ClearMoney = nil;
-- contains default frames which should prevent tooltips from being parsed.
tooltipUsingFrames = {
"TaxiFrame", "MerchantFrame", "TradeSkillFrame",
"SuggestFrame", "WhoFrame", "AuctionFrame", "MailFrame"
};
};