vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 --[[
2 CommonFunctions
3  
4 This file is for commonly used functions available to any
5 UltimateUI Mod. Thanks to Chitinous, Skrag and Thott for most of
6 these functions. :-)
7  
8 by Alexander Brazie
9  
10 ]]--
11  
12 DEBUG_CHAT_FRAME = ChatFrame1;
13  
14 -- Output functions
15  
16 -- NOTE*** ChatTimeStamps is completely overloading this function when enabled
17 function Print(msg, r, g, b, frame, id)
18 if (not r) then r = 1.0; end
19 if (not g) then g = 1.0; end
20 if (not b) then b = 1.0; end
21 if (not frame) then frame = DEFAULT_CHAT_FRAME; end
22 if (frame) then
23 if (not id) then
24 frame:AddMessage(msg,r,g,b);
25 else
26 frame:AddMessage(msg,r,g,b,id);
27 end
28 end
29 end
30  
31 -- Prints a table in an organized format
32 function PrintTable(table, rowname, level)
33 if ( rowname == nil ) then rowname = "ROOT"; end
34 if ( level == nil ) then level = 1; end
35  
36 local msg = "";
37 for i=1,level, 1 do
38 msg = msg .. " ";
39 end
40  
41 if ( table == nil ) then Print (msg.."["..rowname.."] := nil "); return end
42 if ( type(table) == "table" ) then
43 Print (msg..rowname.." { ");
44 for k,v in table do
45 PrintTable(v,k,level+1);
46 end
47 Print(msg.."} ");
48 elseif (type(table) == "function" ) then
49 Print(msg.."["..rowname.."] => {{FunctionPtr*}}");
50 elseif (type(table) == "userdata" ) then
51 Print(msg.."["..rowname.."] => {{UserData}}");
52 elseif (type(table) == "boolean" ) then
53 local value = "true";
54 if ( not table ) then
55 value = "false";
56 end
57 Print(msg.."["..rowname.."] => "..value);
58 else
59 Print(msg.."["..rowname.."] => "..table);
60 end
61 end
62  
63 -- DebugPrint takes a message and a debug key.
64 --
65 -- The default is "ULTIMATEUI_DEBUG", but you can set it to any
66 -- value you like. The result is that if setglobal(debugkey,1);
67 -- has been called, your debug message will be output.
68 --
69 function DebugPrint(msg, debugkey)
70 if ( not debugkey ) then debugkey = "ULTIMATEUI_DEBUG"; end
71  
72 if ( type(msg) == "string" ) then
73 if ( getglobal(debugkey) == 1 ) then
74 Print("DBG: "..msg, 1, 1, .5, DEBUG_CHAT_FRAME);
75 end
76 end
77 end
78  
79 -- Prints an error message
80 function ErrorPrint(msg)
81 local info = ChatTypeInfo["YELL"];
82 UIErrorsFrame:AddMessage(msg, info.r, info.g, info.b, 1.0, UIERRORS_HOLD_TIME);
83 end
84  
85 -- Table functions
86 function GetIndexInList(list,item)
87 for k,v in list do
88 if ( v == item ) then return k; end
89 end
90 return -1;
91 end
92  
93 -- Function Hooking (From ThottbotUtil.lua)
94  
95 -- HookFunction("some_blizzard_function","my_function","before|after|hide")
96 -- calls "my_function" before/after "some_blizzard_function".
97 -- if type is "hide", calls "my_function" before all others, and only continues if it returns true
98 -- This method is used so the hook can be later undone without screwing up someone else's later hook.
99 HookFunction = function (...)
100 -- Sea.io.error (this:GetName(), " is using HookFunction, which is outdated. Please upgrade to -- Sea.util.hook!" );
101 -- Sea.util.hook(unpack(arg));
102 end
103 -- same format as HookFunction
104 -- UnHookFunction = -- Sea.util.unhook;
105 -- Tooltip Scanning and Changing Functions
106  
107 -- Clears a tooltip for usage.
108 function ClearTooltip(TooltipNameBase)
109 for i=1, 15, 1 do
110 getglobal(TooltipNameBase.."TextLeft"..i):SetText("");
111 getglobal(TooltipNameBase.."TextRight"..i):SetText("");
112 end
113  
114 end
115  
116 --
117 -- Prints an items' text into the chat window.
118 --
119 function PrintItemText( bag, slot, TooltipNameBase )
120 if ( TooltipNameBase == nil ) then
121 TooltipNameBase = "UltimateUITooltip";
122 end
123  
124 local tooltip = getglobal (TooltipNameBase);
125  
126 --ClearToolTip(TooltipNameBase);
127 tooltip:SetOwner( getglobal("UIParent"), "ANCHOR_CURSOR" );
128 -- Sea.wow.tooltip.protectTooltipMoney();
129 tooltip:SetBagItem( bag, slot );
130 -- Sea.wow.tooltip.unprotectTooltipMoney();
131 if( tooltip:IsVisible() ) then
132 Print( "Visible tooltip" );
133 tooltip:Hide();
134  
135 for i=1, tooltip:NumLines(), 1 do
136 show = 0;
137 str = "Left"..i..": ";
138 str2 = getglobal(TooltipNameBase.."TextLeft"..i):GetText();
139 if( str2 ~= nil ) then
140 show = 1;
141 str = str..str2;
142 end
143 str = str.." Right"..i..": ";
144 str2 = getglobal(TooltipNameBase.."TextRight"..i):GetText();
145 if( str2 ~= nil ) then
146 show = 1;
147 str = str..str2;
148 end
149 if( show == 1 ) then Print( str ); end
150 end
151 end
152 end
153  
154 -- Gets all lines out of a tooltip.
155 function ScanTooltip(TooltipNameBase)
156 if ( TooltipNameBase == nil ) then
157 TooltipNameBase = "UltimateUITooltip";
158 end
159  
160 local strings = {};
161 for idx = 1, 10 do
162 local textLeft = nil;
163 local textRight = nil;
164 ttext = getglobal(TooltipNameBase.."TextLeft"..idx);
165 if(ttext and ttext:IsVisible() and ttext:GetText() ~= nil)
166 then
167 textLeft = ttext:GetText();
168 end
169 ttext = getglobal(TooltipNameBase.."TextRight"..idx);
170 if(ttext and ttext:IsVisible() and ttext:GetText() ~= nil)
171 then
172 textRight = ttext:GetText();
173 end
174 if (textLeft or textRight)
175 then
176 strings[idx] = {};
177 strings[idx].left = textLeft;
178 strings[idx].right = textRight;
179 end
180 end
181  
182 return strings;
183 end
184  
185 function GetItemName(bag, slot)
186 local name = "";
187 local strings = nil;
188 if ( bag > -1 ) then
189 strings = GetItemInfoStrings(bag, slot, "UltimateUITooltip");
190 else
191 -- Sea.wow.tooltip.protectTooltipMoney();
192 local hasItem, hasCooldown = UltimateUITooltip:SetInventoryItem("player", slot);
193 -- Sea.wow.tooltip.unprotectTooltipMoney();
194 strings = ScanTooltip("UltimateUITooltip");
195 if ( not hasItem) then
196 if ( strings[1] ) then
197 strings[1].left = "";
198 end
199 end
200 end
201 -- Determine if the item is an ore, gem or herb
202 if ( strings[1] ) then
203 name = strings[1].left;
204 end
205 return name;
206 end
207  
208 --Sets the tooltip relative to the owner in a position
209 --appropriate for where the owner is on the screen.
210 --owner - optional, the owner object, defaults to this
211 --tooltip, optional, the tooltip to set, defaults to GameTooltip
212 --setX, optional, sets the x offset(flipped based on screen corner)
213 --setY, optional, sets the y offset(flipped based on screen corner)
214 function SmartSetOwner(owner, tooltip, setX, setY)
215 if (not owner) then
216 owner = this;
217 end
218 if (not tooltip) then
219 tooltip = GameTooltip;
220 end
221 if (not setX) then
222 setX = 0;
223 end
224 if (not setY) then
225 setY = 0;
226 end
227 if (owner and (owner ~= UIParent)) then
228 local x,y = owner:GetCenter();
229 local left = owner:GetLeft();
230 local right = owner:GetRight();
231 local top = owner:GetTop();
232 local bottom = owner:GetBottom();
233 local screenWidth = UIParent:GetWidth();
234 local screenHeight = UIParent:GetHeight();
235 local scale = owner:GetScale();
236 if (x~=nil and y~=nil and left~=nil and right~=nil and top~=nil and bottom~=nil and screenWidth>0 and screenHeight>0) then
237 setX = setX * scale;
238 setY = setY * scale;
239 x = x * scale;
240 y = y * scale;
241 left = left * scale;
242 right = right * scale;
243 width = right - left;
244 top = top * scale;
245 bottom = bottom * scale;
246 local anchorPoint = "";
247 if (y <= (screenHeight * (1/2))) then
248 top = top + setY;
249 anchorPoint = "TOP";
250 if (top < 0) then
251 setY = setY - top;
252 end
253 else
254 setY = -setY;
255 bottom = bottom + setY;
256 anchorPoint = "BOTTOM";
257 if (bottom > screenHeight) then
258 setY = setY + (screenHeight - bottom);
259 end
260 end
261  
262 if (x <= (screenWidth * (1/2))) then
263 left = left + setX;
264 if (anchorPoint == "BOTTOM") then
265 anchorPoint = anchorPoint.."RIGHT";
266 setX = setX - width;
267 if (left < 0) then
268 setX = setX - left;
269 end
270 else
271 anchorPoint = anchorPoint.."LEFT";
272 if (left < 0) then
273 setX = setX - left;
274 end
275 end
276 else
277 setX = -setX;
278 right = right + setX;
279 if (anchorPoint == "BOTTOM") then
280 anchorPoint = anchorPoint.."LEFT";
281 setX = setX + width;
282 if (right > screenWidth) then
283 setX = setX - (right - screenWidth);
284 end
285 else
286 anchorPoint = anchorPoint.."RIGHT";
287 if (right > screenWidth) then
288 setX = setX + (screenWidth - right);
289 end
290 end
291 end
292  
293 if (anchorPoint == "") then
294 anchorPoint = "TOPLEFT";
295 end
296 scale = tooltip:GetScale();
297 if (scale) then
298 setX = setX / scale;
299 setY = setY / scale;
300 end
301 tooltip:SetOwner(owner, "ANCHOR_"..anchorPoint, setX, setY);
302 end
303 elseif (owner == UIParent) then
304 local x,y = GetCursorPosition();
305 local width = tooltip:GetWidth();
306 local height = tooltip:GetHeifht();
307 local screenWidth = UIParent:GetWidth();
308 local screenHeight = UIParent:GetHeight();
309 local scale = owner:GetScale();
310 if (x~=nil and y~=nil and width and height and screenWidth>0 and screenHeight>0) then
311 setX = setX * scale;
312 setY = setY * scale;
313 x = x * scale;
314 y = y * scale;
315 width = width * scale;
316 height = height * scale;
317 local anchorPoint = "";
318 if (y <= (screenHeight * (1/2))) then
319 local top = (y + height) + setY;
320 if (top < 0) then
321 setY = setY - top;
322 end
323 else
324 setY = -setY;
325 local bottom = (y - height) + setY;
326 setY = setY - height;
327 if (bottom > screenHeight) then
328 setY = setY + (screenHeight - bottom);
329 end
330 end
331  
332 if (x <= (screenWidth * (1/2))) then
333 local left = x + setX;
334 setX = setX + (width / 2);
335 if (left < 0) then
336 setX = setX - left;
337 end
338 else
339 setX = -setX;
340 local right = x + setX;
341 setX = setX - (width / 2);
342 if (right > screenWidth) then
343 setX = setX - (right - screenWidth);
344 end
345 end
346  
347 scale = tooltip:GetScale();
348 if (scale) then
349 setX = setX / scale;
350 setY = setY / scale;
351 end
352 tooltip:SetOwner(owner, "ANCHOR_CURSOR", setX, setY);
353 end
354 else
355 tooltip:SetOwner(owner, "ANCHOR_TOPLEFT");
356 end
357 end
358  
359 -- Obtains all information about a bag/slot and returns it as an array
360 function GetItemInfoStrings(bag,slot, TooltipNameBase)
361 if ( TooltipNameBase == nil ) then
362 TooltipNameBase = "UltimateUITooltip";
363 end
364  
365 ClearTooltip(TooltipNameBase);
366  
367 local tooltip = getglobal(TooltipNameBase);
368  
369 -- Open tooltip & read contents
370 -- Sea.wow.tooltip.protectTooltipMoney();
371 tooltip:SetBagItem( bag, slot );
372 -- Sea.wow.tooltip.protectTooltipMoney();
373 local strings = ScanTooltip(TooltipNameBase);
374  
375 -- Done our duty, send report
376 return strings;
377 end
378  
379 -- Item Classification
380 -- Thanks to Zatharas, Narands, Xdra, Mirodin and Reima for this list
381 HerbList = {
382 "Peacebloom",
383 "Silverleaf",
384 "Snakeroot",
385 "Magebloom",
386 "Bruiseweed",
387 "Swiftthistle",
388 "Fadeleaf",
389 "Briarthorn",
390 "Kingsblood",
391 "Wild Steelbloom",
392 "Grave Moss",
393 "Liferoot",
394 "Firebloom",
395 "Goldthorn",
396 "Stranglekelp",
397 "Khadgar's Whiskers"
398 };
399 -- Baccarus for Truesilver
400 OreList = {
401 "Copper Ore",
402 "Tin Ore",
403 "Silver Ore",
404 "Mithril Ore",
405 "Iron Ore",
406 "Gold Ore",
407 "Truesilver Ore",
408 "Thorium Ore"
409 };
410 -- Melwein for Malachite
411 GemList = {
412 "Malachite",
413 "Pearl",
414 "Moss Agate",
415 "Tigerseye",
416 "Citrine",
417 "Jade",
418 "Shadowgem",
419 "Aquamarine",
420 "Blue Pearl",
421 "Star Ruby"
422 };
423 -- Potion List ugh...
424 -- Thanks to Zatharas for linking holy spring water
425 PotionList = {
426 "Potion",
427 "Elixir",
428 "Oil",
429 "Holy Spring Water"
430 };
431 -- Tailoring List... ugh...
432 -- Thanks to Able for Silk (Spider etc)
433 TailorList = {
434 "Bolt",
435 "Cloth",
436 "Thread",
437 "Dye",
438 "Silk",
439 "Bleach",
440 "Magewave",
441 "Runecloth",
442 "Felcloth"
443 }
444 -- Leathercrafting ... ugh...
445 LeatherList = {
446 "Leather",
447 "Hide",
448 "Scales"
449 };
450 -- Fishing
451 FishingList = {
452 "Bauble",
453 "Nightcrawler",
454 "Fishing Pole",
455 "Fish Attractor"
456 };
457 -- Warlock Items
458 WarlockList = {
459 "Soul Shard",
460 "Healthstone",
461 "Manastone",
462 "Soulstone"
463 };
464 -- Shaman Items
465 ShamanList = {
466 "Earth Totem",
467 "Fire Totem",
468 "Water Totem",
469 "Air Totem",
470 "Sapta"
471 };
472  
473 -- And the worst ones: (Prepare for bad humor)
474  
475 -- HP restoring items
476 FoodList = {
477 "Bread", -- Boring but important first
478 "Cornbread",
479 "Haunch",
480 "Mutton Chop",
481 "Hog Shank",
482 "Tough Jerky",
483 "Stormwind Brie", -- What is Brie anyways?
484 "Aged Cheddar",
485 "Alterac Swiss",
486 "Apple",
487 "Watermelon",
488 "Banana",
489 "Ham Steak", -- I Love Ham Steak!
490 "Dalaran Sharp", -- Ouch
491 "Bleu", -- Ewwww Bleu cheese
492 "Dwarven Mild", -- About time them dorfs got it right
493 "Wolf Meat", -- Hawooooo
494 "Roasted Boar Meat",
495 "Mackerel",
496 "Smallfish",
497 "Kaldorei Caviar",
498 "Scorpid Surprise",
499 "Beer Basted",
500 "Smoked Bear Meat",
501 "Roasted Kodo Meat",
502 "Mud Snapper",
503 "Rainbow Fin Albacore",
504 "Halibut",
505 "Strider Stew",
506 "Fillet of Frenzy",
507 "Boiled Clams",
508 "Goretusk Liver Pie",
509 "Loch Frenzy Delights",
510 "Coyote Steak",
511 "Blood Sausage",
512 "Westfall Stew",
513 "Crab Cake",
514 "Crispy Lizard",
515 "Pork Ribs",
516 "Croclist Steak",
517 "Savory Deviate",
518 "Scorpid Surprise",
519 "Cooked Crab Claw",
520 "Dig Rat Stew",
521 "Murloc Fin Soup",
522 "Clam Chowder",
523 "Seasoned Wolf",
524 "Spider Cake",
525 "Bear Steak",
526 "Venison",
527 "Pork Ribs",
528 "Gumbo",
529 "Lion Chops",
530 "Goblin Deviled",
531 "Omelet",
532 "Tasty Lion Steak",
533 "Barbecued Buzzard",
534 "Giant Clam Scorcho",
535 "Soothing Turtle",
536 "Rockscale Cod",
537 "Cave Mold",
538 "eckled Mushroom",
539 "Mushroom Cap",
540 "Bolete",
541 "Morel",
542 "Truffle",
543 "Strider Stew",
544 "Mystery Stew",
545 "Roast Raptor",
546 "Carrion Surprise",
547 "Dragonbreath Chi",
548 "Spiced Chi",
549 "Monster Om",
550 "Spiced Wolf",
551 "Goldthorn Tea",
552 "Squid",
553 "Pumpkin",
554 "Ice Cream" -- Tigule's specialty
555 };
556 -- Mana restoring items
557 DrinkList = {
558 "Cherry Grog", -- The ONE AND ONLY BABY!
559 "Moonberry Juice",
560 "Cold Milk",
561 "Melon Juice",
562 "Sweet Nectar",
563 "Spring Water",
564 "Glory Dew"
565 };
566  
567 -- Checks if any item from a list is in a specified word
568  
569 function IsListItemInWord(list, word)
570 for k,v in list do
571 if ( string.find(word,v) ~= nil ) then
572 return true;
573 end
574 end
575 return false;
576 end
577  
578 -- This function obtains all the information you could ever want about an item...
579 -- ... if its available.
580 --
581 -- classification, name, quality, itemCount, leftString, rightString, minLevel, unique, soulbound, bindsOnPickup, bindsOnEquip, questItem;
582 function ClassifyItem(bag, slot, TooltipNameBase)
583 if ( TooltipNameBase == nil ) then
584 TooltipNameBase = "UltimateUITooltip";
585 end
586  
587 local strings = GetItemInfoStrings(bag, slot, TooltipNameBase);
588 local classification = "Misc";
589 local leftString, rightString, minLevel;
590 local unique = false;
591 local soulbound = false;
592 local bindsOnPickup = false;
593 local bindsOnEquip = false;
594 local questItem = false;
595 local isHerb = false;
596 local isGem = false;
597 local isOre = false;
598 local isLeather = false;
599 local isTailor = false;
600 local isFishing = false;
601 local isFood = false;
602 local isDrink = false;
603 local isShaman = false;
604 local isWarlock = false;
605 local isJunk = false;
606 local engineering = false;
607 local firstaid = false;
608 local classitem = false;
609 local class = "";
610 local texture, itemCount, locked, quality = GetContainerItemInfo(bag,slot);
611 local name = "";
612 -- Look for the target line that identifies an item; it'll either be line 2, 3, or 4.
613  
614 -- Determine if the item is an ore, gem or herb
615 if ( strings[1] ) then
616 name = strings[1].left;
617 end
618  
619 isHerb = IsListItemInWord(HerbList, name);
620 isGem = IsListItemInWord(GemList, name);
621 isOre = IsListItemInWord(OreList, name);
622 isLeather = IsListItemInWord(LeatherList, name);
623 isFishing = IsListItemInWord(FishingList, name);
624 isTailor = IsListItemInWord(TailorList, name);
625 isPotion = IsListItemInWord(PotionList, name);
626 isFood = IsListItemInWord(FoodList, name);
627 isDrink = IsListItemInWord(DrinkList, name);
628 isShaman = IsListItemInWord(ShamanList, name);
629 isWarlock = IsListItemInWord(WarlockList, name);
630  
631 if ( ( quality ) and ( quality < 0 ) ) then
632 isJunk = true;
633 end
634  
635 for i = 2, 5, 1 do
636 if (not strings[i])
637 then
638 break;
639 end
640 if (strings[i].left == ITEM_UNIQUE or strings[i].left == ITEM_UNIQUE_MULTIPLE ) then unique = true; end
641 if (strings[i].left == ITEM_SOULBOUND ) then soulbound = true; end
642 if (strings[i].left == ITEM_BIND_ON_PICKUP ) then bindsOnPickup = true; end
643 if (strings[i].left == ITEM_BIND_ON_EQUIP ) then bindsOnEquip = true; end
644 if (strings[i].left == ITEM_BIND_QUEST ) then questItem = true; end
645  
646 if (string.find(strings[i].left,"First Aid", 0, true ) ) then firstaid = true; end
647 if (string.find(strings[i].left,"Engineering", 0, true ) ) then engineering = true; end
648 if (string.find(strings[i].left,"Classes:", 0, true ) ) then classitem = true; class = string.sub(strings[i].left, string.find(strings[i].left,":", 0, true )+2); end
649  
650 if (strings[i].left and
651 strings[i].left ~= ITEM_UNIQUE and
652 strings[i].left ~= ITEM_SOULBOUND and
653 strings[i].left ~= ITEM_BIND_ON_EQUIP and
654 strings[i].left ~= ITEM_BIND_ON_PICKUP and
655 strings[i].left ~= ITEM_BIND_QUEST)
656 then
657 leftString = strings[i].left;
658 rightString = strings[i].right;
659 break;
660 end
661 end
662  
663 -- Find last line
664 local lastLine;
665 for i = 1, 10, 1 do
666 if (strings[i] and strings[i].left)
667 then
668 lastLine = strings[i].left;
669 else
670 break;
671 end
672 end
673  
674 -- look at last line to see if it's a level requirement
675 local minLevel = 0;
676 if (lastLine)
677 then
678 local index, length, levelString = string.find(lastLine, "^Requires Level (%d+)$");
679 if (index)
680 then
681 minLevel = MakeIntFromString(levelString);
682 end
683 end
684  
685 -- classify item based on found strings
686 if (leftString)
687 then
688 if (leftString == "Main Hand" or
689 leftString == "Two-Hand" or
690 leftString == "One-Hand")
691 then
692 classification = "Weapon";
693 elseif (leftString == "Head" or
694 leftString == "Hand" or
695 leftString == "Waist" or
696 leftString == "Shoulders" or
697 leftString == "Legs" or
698 leftString == "Back" or
699 leftString == "Feet" or
700 leftString == "Chest" or
701 leftString == "Wrist")
702 then
703 classification = "Armor";
704 elseif (leftString == "Off Hand")
705 then
706 classification = "Shield";
707 elseif (leftString == "Wand" or
708 leftString == "Ranged" or
709 leftString == "Gun" )
710 then
711 classification = "Ranged";
712 elseif (leftString == "Projectile")
713 then
714 classification = "Ammo";
715 elseif (leftString == "Shirt" or
716 leftString == "Tabard" or
717 leftString == "Finger" or
718 leftString == "Neck" or
719 leftString == "Trinket" or
720 leftString == "Held In Hand")
721 then
722 classification = "Clothing";
723 end
724 end
725 if ( classification == "Misc" ) then
726 if ( isGem ) then classification = "Gem"; end
727 if ( isOre ) then classification = "Ore"; end
728 if ( isHerb ) then classification = "Herb"; end
729 if ( engineering ) then classification = "Engineering"; end
730 if ( firstaid ) then classification = "First Aid"; end
731 if ( isLeather ) then classification = "Leather"; end
732 if ( isTailor ) then classification = "Thread"; end
733 if ( isPotion ) then classification = "Potion"; end
734 if ( isFishing ) then classification = "Fishing"; end
735 if ( isFood ) then classification = "Food"; end
736 if ( isDrink ) then classification = "Drink"; end
737 if ( isShaman ) then classification = "Shaman"; end
738 if ( isWarlock ) then classification = "Warlock"; end
739 if ( classitem ) then classification = class; end
740 if ( questItem ) then classification = "QuestItem"; end
741 if ( isJunk ) then classification = "Junk"; end
742 end
743  
744 return classification, name, quality, itemCount, leftString, rightString, minLevel, unique, soulbound, bindsOnPickup, bindsOnEquip, questItem;
745 end
746  
747 -- String Functions
748  
749 function MakeIntFromString(str)
750 DebugPrint("MakeIntFromString("..str..")", 4);
751 local remain = str;
752 local amount = 0;
753 while (remain ~= "") do
754 amount = amount * 10;
755 amount = amount + (string.byte(strsub(remain, 1, 1)) - string.byte("0"));
756 remain = strsub(remain, 2);
757 end
758 DebugPrint("MakeIntFromStr("..str..") = "..amount, 4);
759 return amount;
760 end
761  
762 function MakeIntFromHexString(str)
763 DebugPrint("MakeIntFromHexString("..str..")", 4);
764 local remain = str;
765 local amount = 0;
766 while (remain ~= "") do
767 amount = amount * 16;
768 local byteVal = string.byte(strupper(strsub(remain, 1, 1)));
769 if (byteVal >= string.byte("0") and byteVal <= string.byte("9"))
770 then
771 amount = amount + (byteVal - string.byte("0"));
772 elseif (byteVal >= string.byte("A") and byteVal <= string.byte("F"))
773 then
774 amount = amount + 10 + (byteVal - string.byte("A"));
775 end
776 remain = strsub(remain, 2);
777 end
778 DebugPrint("MakeIntFromHexStr("..str..") = "..amount, 4);
779 return amount;
780 end
781  
782 function MakeHexStringFromInt(intval, minlength)
783 return string.format("%"..minlength.."x", intval );
784 end
785  
786 function EscapeString(plainString, disallowedChars)
787 -- yay URL-encoding
788 local str = "";
789 local remain = plainString;
790 disallowedChars = disallowedChars.."%";
791 while (remain ~= "") do
792 local char = strsub(remain, 1, 1);
793 if (string.find(disallowedChars, char, 1, true))
794 then
795 str = str.."%";
796 local hexRepresentation = string.format("%02x", string.byte(char));
797 str = str..hexRepresentation;
798 else
799 str = str..char;
800 end
801 remain = strsub(remain, 2);
802 end
803 return str;
804 end
805  
806 function UnescapeString(escapedString)
807 local str = "";
808 local remain = escapedString;
809 while (remain ~= "") do
810 local char = strsub(remain, 1, 1);
811 if (char == "%")
812 then
813 str = str..string.char(MakeIntFromHexString(strsub(remain, 2, 3)));
814 remain = strsub(remain, 4);
815 else
816 str = str..char;
817 remain = strsub(remain, 2);
818 end
819 end
820 return str;
821 end
822  
823 -- Converts numeric time into readable time.
824 function GetTimeString(time)
825 if (time < 0)
826 then
827 time = 0;
828 end
829  
830 local seconds = mod(floor(time), 60);
831 if (seconds < 10)
832 then
833 seconds = "0"..seconds;
834 end
835 local minutes = mod(floor(time/60), 60);
836 local hours = floor(time/(60*60));
837  
838 local timeString;
839 if (hours > 0)
840 then
841 if (minutes < 10)
842 then
843 minutes = "0"..minutes;
844 end
845 timeString = hours..":"..minutes..":"..seconds;
846 else
847 timeString = minutes..":"..seconds;
848 end
849 return timeString;
850 end
851  
852  
853 function GetRGBAFromHexColor(hexColor)
854 local alpha = MakeIntFromHexString(strsub(hexColor, 1, 2)) / 256;
855 local red = MakeIntFromHexString(strsub(hexColor, 3, 4)) / 256;
856 local green = MakeIntFromHexString(strsub(hexColor, 5, 6)) / 256;
857 local blue = MakeIntFromHexString(strsub(hexColor, 7, 8)) / 256;
858 return red, green, blue;
859 end
860  
861 -- Mathematical Functions (yuck!)
862 function CheckBits(field, bits)
863 local result = true;
864 while (bits > 0) do
865 if (mod(bits, 2) > 0)
866 then
867 if (mod(field, 2) == 0)
868 then
869 result = false;
870 break;
871 end
872 end
873 field = floor(field / 2);
874 bits = floor(bits / 2);
875 end
876 return result;
877 end
878  
879  
880 function SetBit(field, bit)
881 local source = 2^31; -- 1 in highest-order bit
882 local shiftCount = 1;
883 local result = 0;
884 while (bit > 0) do
885 result = floor(result / 2);
886 -- if we're about to shift off a 1, put a 1 on the destination.
887 if ((mod(bits, 2) == 1) or (mod(field, 2) == 1))
888 then
889 result = result + source;
890 end
891 field = floor(field / 2);
892 bits = floor(bits / 2);
893 shiftCount = shiftCount + 1;
894 end
895 for i = shiftCount, 32, 1 do
896 result = floor(result / 2);
897 -- if we're about to shift off a 1, put a 1 on the destination.
898 if (mod(bits, 2) == 1)
899 then
900 result = result + source;
901 end
902 field = floor(field / 2);
903 end
904 return result;
905 end
906  
907 function ClearBit(field, bit)
908 local source = 2^31; -- 1 in highest-order bit
909 local shiftCount = 1;
910 local result = 0;
911 while (bit > 0) do
912 result = floor(result / 2);
913 -- if we're about to shift off a 1, put a 1 on the destination. AS LONG AS this is not the bit to clear
914 if ((mod(field, 2) == 1) and not (mod(bit, 2) == 1))
915 then
916 result = result + source;
917 end
918 field = floor(field / 2);
919 bits = floor(bits / 2);
920 shiftCount = shiftCount + 1;
921 end
922 for i = shiftCount, 32, 1 do
923 result = floor(result / 2);
924 -- if we're about to shift off a 1, put a 1 on the destination.
925 if (mod(bits, 2) == 1)
926 then
927 result = result + source;
928 end
929 field = floor(field / 2);
930 end
931 return result;
932 end
933  
934 function UnitFaction(who)
935 local faction;
936 local race = UnitRace(who);
937 local HordeRaces = {"Orc", "Tauren", "Troll", "Undead" };
938  
939 for index, hordeRace in HordeRaces do
940 if (race == hordeRace)
941 then
942 return 1; -- Horde
943 end
944 end
945 return 0; -- Alliance
946 end
947  
948 function BaseConversion(input, inputBase, outputBase)
949 -----------------------------------------------------------
950 -- Function made by KaTTaNa ! --
951 -- -------------------------- --
952 -- http://www.wc3sear.ch/index.php?p=JASS&ID=37&sid= --
953 -- -------------------------- --
954 -- Converted in LUA by vjeux --
955 -- --
956 -- Usage : BaseConversion(255, 10, 16) --
957 -- => Return "ff" --
958 -- --
959 -- Usage : BaseConversion("ff", 16, 10) --
960 -- => Return "10" --
961 -----------------------------------------------------------
962 local charMap = "0123456789abcdefghijklmnopqrstuvwxyz~!@#$%^&*()_+-=[]";
963 local s;
964 local result = "";
965 local val = 0;
966 local i;
967 local p = 0;
968 local pow = 1;
969 local sign = "";
970  
971 if ( inputBase < 2 or inputBase > strlen(charMap) or outputBase < 2 or outputBase > strlen(charMap) ) then
972 -- Bases are invalid or out of bounds
973 return "Invalid bases given";
974 end
975 if ( strsub(input, 1, 1) == "-" ) then
976 sign = "-";
977 input = strsub(input, 1, strlen(input));
978 end
979 i = strlen(input);
980 -- Get the integer value of input
981 while (i > 0) do
982 s = strsub(input, i, i);
983 p = 0;
984 local bool = false;
985 while (bool == false) do
986 if ( p >= inputBase ) then
987 -- Input cannot match base
988 return "Input does not match base!\n P = "..p;
989 end
990 if ( s == strsub(charMap, p+1, p+1) ) then
991 val = val + pow * p;
992 pow = pow * inputBase;
993 bool = true;
994 end
995 p = p + 1;
996 end
997 i = i - 1;
998 end
999 while (val > 0) do
1000 p = mod(val, outputBase);
1001 result = strsub(charMap, p+1, p+1)..result;
1002 val = val / outputBase;
1003 end
1004  
1005 for i = 1, strlen(result), 1 do
1006 if (strsub(result, 1, 1) == "0") then
1007 result = strsub(result, 2, strlen(result));
1008 else
1009 return sign..result
1010 end
1011 end
1012  
1013 if (strlen(sign..result) == 0) then
1014 return "0";
1015 else
1016 return sign..result.."-"..strlen(sign..result);
1017 end
1018 end
1019  
1020  
1021 -- Thott's personalized functions
1022 function dbanner(...)
1023 if ( (Thottbot) and (Thottbot.Debug) ) then
1024 UIErrorsFrame:AddMessage(join(arg,""), 0.9, 0.9, 0.0, 1.0, UIERRORS_HOLD_TIME);
1025 dprint(join(arg,""));
1026 end
1027 end
1028 function banner(...)
1029 UIErrorsFrame:AddMessage(join(arg,""), 0.9, 0.9, 0.0, 1.0, UIERRORS_HOLD_TIME);
1030 end
1031 function dbyte(c)
1032 return string.format("<%02X>",string.byte(c));
1033 end
1034 --function dprint_runqueue()
1035 -- if(dprint_nextmsg) then
1036 -- print2(dprint_nextmsg);
1037 -- dprint_nextmsg = nil;
1038 -- end
1039 -- if(dprint_queue and dprint_queue[1]) then
1040 -- local msg = table.remove(dprint_queue,1);
1041 -- dprint_nextmsg = msg;
1042 -- msg = string.gsub(msg,"([^%w%s])",dbyte)
1043 -- print2("Next: ",msg);
1044 -- UltimateUI_Schedule(0.01,dprint_runqueue);
1045 -- dprint_queue_scheduled = true;
1046 -- else
1047 -- dprint_queue_scheduled = false;
1048 -- end
1049 --end
1050 function dprint(...)
1051 if ( ( Thottbot ) and (Thottbot.Debug) ) then
1052 local msg = join(arg,"");
1053 msg = string.gsub(msg,"|","<pipe>");
1054 msg = string.gsub(msg,"([^%w%s%a%p])",dbyte);
1055 if(Thottbot.DebugFrame) then
1056 printframe(Thottbot.DebugFrame,msg);
1057 else
1058 print2(msg);
1059 end
1060 -- if(not dprint_queue) then
1061 -- dprint_queue = {};
1062 -- end
1063 -- table.insert(dprint_queue,join(arg,""));
1064 -- if(not dprint_queue_scheduled) then
1065 -- dprint_queue_scheduled = true;
1066 -- UltimateUI_Schedule(0.01,dprint_runqueue);
1067 -- -- 68.94.173.94
1068 -- end
1069 end
1070 end
1071 -- Thottbot.PrintCount = Thottbot.PrintCount + 1;
1072 -- if(Thottbot.PrintCount < 60) then
1073 -- for key,value in arg do
1074 -- arg[key] = string.gsub(value,"[^%w%s%p]",".");
1075 -- end
1076 -- print2(Thottbot.PrintCount,":",join(arg,""));
1077 function dprint1(...)
1078 if ( (Thottbot) and (Thottbot.Debug) ) then
1079 print1(join(arg,""));
1080 end
1081 end
1082 function split(s,seperator)
1083 local t = {};
1084 t.n = 0;
1085 for value in string.gfind(s,"[^"..seperator.."]+") do
1086 t.n = t.n + 1;
1087 t[t.n] = value;
1088 end
1089 return t;
1090 end
1091 function join(list,seperator)
1092 local i;
1093 local c = "";
1094 local msg = "";
1095 if(type(list) ~= "table") then
1096 dbanner("unknown type ",type(list)," table passed to join, seperator ",seperator);
1097 return;
1098 end
1099 if(not list.n) then
1100 dbanner("ERROR: no .n variable in list!");
1101 return "";
1102 end
1103 for i=1, list.n, 1 do
1104 if(list[i]) then
1105 if(type(list[i]) ~= "string" and type(list[i]) ~= "number") then
1106 dbanner("found ",type(list[i])," in list!");
1107 msg = msg .. c .. "(" .. type(list[i]) .. ")";
1108 else
1109 msg = msg .. c .. list[i];
1110 end
1111 else
1112 msg = msg .. c .. "(nil)";
1113 end
1114 c = seperator;
1115 end
1116 return msg;
1117 end
1118 function dprintlist(list)
1119 if ( (Thottbot) and (Thottbot.Debug) ) then
1120 if(list) then
1121 dprint(join(list,","));
1122 else
1123 dprint("nil list");
1124 end
1125 end
1126 end
1127 function dprintcomma(...)
1128 dprint(join(arg,","));
1129 end
1130 function printframe(frame,...)
1131 if(frame) then
1132 frame:AddMessage(join(arg,""), 1.0, 1.0, 0.0);
1133 end
1134 end
1135 function print2(...)
1136 if(ChatFrame2) then
1137 ChatFrame2:AddMessage(join(arg,""), 1.0, 1.0, 0.0);
1138 end
1139 end
1140 function print1(...)
1141 if(ChatFrame1) then
1142 ChatFrame1:AddMessage(join(arg,""), 1.0, 1.0, 0.0);
1143 end
1144 end
1145 function push(t,v)
1146 if(not t or not t.n) then
1147 dbanner("Bad table passed to push");
1148 return nil;
1149 end
1150 t.n = t.n+1;
1151 t[t.n] = v;
1152 end
1153 function pop(t)
1154 if(not t or not t.n) then
1155 dbanner("Bad table passed to push");
1156 return nil;
1157 end
1158 local v = t[t.n];
1159 t.n = t.n - 1;
1160 return v;
1161 end
1162 function push2(t,x,y)
1163 if(not t or not t.n) then
1164 dbanner("Bad table passed to push2");
1165 return nil;
1166 end
1167 t.n = t.n+1;
1168 t[t.n] = x;
1169 t.n = t.n+1;
1170 t[t.n] = y;
1171 end
1172 function pop2(t)
1173 if(not t or not t.n) then
1174 --dbanner("Bad table passed to pop2");
1175 return nil;
1176 end
1177 if(t.n < 2) then
1178 return nil;
1179 end
1180 local tt = {};
1181 tt.n = 2;
1182 tt[1] = t[t.n-1];
1183 tt[2] = t[t.n];
1184 t.n = t.n - 2;
1185 return tt;
1186 end
1187 function fixnil(...)
1188 for i=1, arg.n, 1 do
1189 if(not arg[i]) then
1190 arg[i] = "(nil)";
1191 end
1192 end
1193 return arg;
1194 end
1195 function fixnilempty(...)
1196 for i=1, arg.n, 1 do
1197 if(not arg[i]) then
1198 arg[i] = "";
1199 end
1200 end
1201 return arg;
1202 end
1203 function fixnilzero(...)
1204 for i=1, arg.n, 1 do
1205 if(not arg[i]) then
1206 arg[i] = 0;
1207 end
1208 end
1209 return arg;
1210 end
1211 function HookHandler(name,arg)
1212 --dprint("HookHandler ",name);
1213 local called = false;
1214 local continue = true;
1215 local retval;
1216 for key,value in Hooks[name].hide do
1217 if(type(value) == "function") then
1218 --dprint("calling before ",name);
1219 if(not value(unpack(arg))) then
1220 continue = false;
1221 end
1222 called = true;
1223 end
1224 end
1225 if(not continue) then
1226 dprint("hide returned false, aborting call to ",name);
1227 return;
1228 end
1229 for key,value in Hooks[name].before do
1230 if(type(value) == "function") then
1231 --dprint("calling before ",name);
1232 value(unpack(arg));
1233 called = true;
1234 end
1235 end
1236 --dprint("calling original ",name);
1237 retval = Hooks[name].orig(unpack(arg));
1238 for key,value in Hooks[name].after do
1239 if(type(value) == "function") then
1240 --dprint("calling after ",name);
1241 value(unpack(arg));
1242 called = true;
1243 end
1244 end
1245 if(not called) then
1246 dprint("no hooks left for ",name,", clearing");
1247 setglobal(name,Hooks[name].orig);
1248 Hooks[name] = nil;
1249 end
1250 return retval;
1251 end
1252  
1253 -- Thanks to George Warner for suggesting this refactoring suggestion... as always, I modified it a bit :) /sarf
1254 -- Source : http://www.ultimateuiui.org/cgi-bin/bugzilla/show_bug.cgi?id=158
1255 function UltimateUI_IsUltimateUIUser(name)
1256 if ( not name ) then return false; end
1257 if ( UltimateUIMaster_UltimateUIUsers ) then
1258 if ( UltimateUIMaster_UltimateUIUsers[name] ) then
1259 return true;
1260 end
1261 end
1262 return false;
1263 end
1264  
1265 -- helper function - returns value as a byte
1266 function UltimateUI_GetByteValue(pValue)
1267 local value = tonumber(pValue);
1268 if ( value <= 0 ) then return 0; end
1269 if ( value >= 255 ) then return 255; end
1270 return value;
1271 end
1272  
1273  
1274 -- Yet another function from George Warner, modified a bit to fit my own nefarious purposes.
1275 -- It can now accept r, g and b specifications, too (leaving out a), as well as handle 255 255 255
1276 -- Source : http://www.ultimateuiui.org/cgi-bin/bugzilla/show_bug.cgi?id=159
1277 function UltimateUI_GetColorFormatString(a, r, g, b)
1278 local percent = false;
1279 if ( ( ( not b ) or ( b <= 1 ) ) and ( a <= 1 ) and ( r <= 1 ) and ( g <= 1) ) then percent = true; end
1280 if ( ( not b ) and ( a ) and ( r ) and ( g ) ) then b = g; g = r; r = a; if ( percent ) then a = 1; else a = 255; end end
1281 if ( percent ) then a = a * 255; r = r * 255; g = g * 255; b = b * 255; end
1282 a = UltimateUI_GetByteValue(a); r = UltimateUI_GetByteValue(r); g = UltimateUI_GetByteValue(g); b = UltimateUI_GetByteValue(b);
1283  
1284 return format("|c%02X%02X%02X%02X%%s|r", a, r, g, b);
1285 end
1286  
1287  
1288 -- global localization string functions START
1289  
1290 function loc_format(...)
1291 ret = arg[1];
1292 for i=2, arg.n, 1 do
1293 ret = string.gsub (ret, "<"..(i-1)..">", arg[i]);
1294 end
1295 return ret;
1296 end
1297  
1298 function loc_read(str, fmt, ord, n)
1299 local ret = {};
1300 fmt1 = string.gsub (fmt, "%b<>", "(.+)");
1301 for i=1, n, 1 do
1302 ret[ord[i]] = string.gsub(str, fmt1, "%"..i);
1303 end
1304 return unpack(ret);
1305 end
1306  
1307 -- global localization string functions END
1308  
1309 --Returns true if variable is not nill and a table
1310 function isTable(var)
1311 if (var and (type(var) == "table")) then
1312 return true;
1313 end
1314 return false;
1315 end
1316  
1317 function MakeHyperLink(type, name, color)
1318 local link = "["..name.."]";
1319 if (color) then
1320 link = "|cFF"..color.."["..name.."]|r";
1321 end
1322 return "|H"..type.."|h"..link.."|h";
1323 end
1324  
1325 -- elite frame functions
1326  
1327 function UUISetElite()
1328 PlayerFrameTexture:SetTexture("Interface\\TargetingFrame\\UI-TargetingFrame-Elite");
1329 end