Thread Tools Display Modes
08-13-15, 07:51 AM   #1
Endzeit
A Deviate Faerie Dragon
Join Date: Aug 2015
Posts: 12
Problems with Big Tables

Edit#2:
It works now.. but i got stutter when hover over items.. is there a way with a ~1800 table to improve performance?
-----
EDIT:
i found the problem.. this is working:
Code:
local setName =  {
[1] = {  name = "Mystic's Regalia (Recolor)", items = {14090, 26008, 14094}, },
-- [2......1778]
[1779] = {  name = "Imperial Plate", items = {31436, 30002, 12424, 12425, 12422, 12427, 12429}, },
}
function addline_gametip()
local itemName,itemLink = GameTooltip:GetItem()
	if itemLink ~= nil then	   
		local itemString = string.match(itemLink, "item[%-?%d:]+");
		local _, itemId, enchantId, jewelId1, jewelId2, jewelId3, jewelId4, suffixId, uniqueId, linkLevel, reforgeId = strsplit(":", itemString);

 for i = 1, #setName do
j = 1 
while j <= 8 do

if (setName[i]['items'][j] ~= nil) and (format("%u",itemId) == format("%u", setName[i]['items'][j])) then
 		GameTooltip:AddLine("Transmog Set: " .. setName[i]['name'])
 		GameTooltip:Show();
 		end
j = j + 1
		end
 end
 end
 end

 

GameTooltip:HookScript("OnTooltipSetItem", addline_gametip);
-------

I'm working on my first wow addon and i'm a big newbie with lua and coding. I think im finished, but it dont work.

problems are the do while i think. here is my code:

Code:
local setName =  {
[1] = {  name = "Mystic's Regalia (Recolor)", items = {14090, 26008, 14094}, },
-- [2......1778]
[1779] = {  name = "Imperial Plate", items = {31436, 30002, 12424, 12425, 12422, 12427, 12429}, },
}

function addline_gametip()
local itemName,itemLink = GameTooltip:GetItem()
	if itemLink ~= nil then	   
		local itemString = string.match(itemLink, "item[%-?%d:]+");
		local _, itemId, enchantId, jewelId1, jewelId2, jewelId3, jewelId4, suffixId, uniqueId, linkLevel, reforgeId = strsplit(":", itemString);

 for i = 1, #setName do
j = 1 
while j <= 8 do
 if (itemId == setName[i]['items'][j]) then
 		GameTooltip:AddLine("Transmog Set: " .. setName[i]['name'])
 		GameTooltip:Show();
 		end
j = j + 1
		end
 end
 end
 end


GameTooltip:HookScript("OnTooltipSetItem", addline_gametip);
hope someone can help me

Last edited by Endzeit : 08-13-15 at 10:32 AM.
  Reply With Quote
08-13-15, 04:26 PM   #2
Mazzop
A Cliff Giant
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 74
cannot help on technical side and i am not sure if i get, what you trying to do
but what if you do table other way around and index by itemID with aray of sets name that item is in
adding tooltip then would be trivial
  Reply With Quote
08-13-15, 05:08 PM   #3
elcius
A Cliff Giant
AddOn Author - Click to view addons
Join Date: Sep 2011
Posts: 75
lua has no problem with very large tables, just make an itemid to setid lookup table.
Lua Code:
  1. local setName =  {
  2. [1] = {  name = "Mystic's Regalia (Recolor)", items = {14090, 26008, 14094}, },
  3. -- [2......1778]
  4. [1779] = {  name = "Imperial Plate", items = {31436, 30002, 12424, 12425, 12422, 12427, 12429}, },
  5. }
  6.  
  7. -- make lookup table, ideally this would be pre-made
  8. local itemSet = {};
  9. for i,set in pairs(setName) do
  10.     for j, id in pairs(set['items']) do
  11.         itemSet[id] = i;
  12.     end
  13. end
  14.  
  15. function addline_gametip()
  16.     local itemName,itemLink = GameTooltip:GetItem();
  17.     if not itemLink then return end
  18.    
  19.     local itemId = itemLink:match('item:(%d+)');
  20.     local setIndex = itemSet[tonumber(itemId)];
  21.    
  22.     if setIndex and setName[setIndex] then
  23.         GameTooltip:AddLine("Transmog Set: " .. setName[setIndex]['name']);
  24.     end
  25.  end
  26.  
  27.  
  28. GameTooltip:HookScript("OnTooltipSetItem", addline_gametip);
  Reply With Quote
08-14-15, 07:19 AM   #4
Endzeit
A Deviate Faerie Dragon
Join Date: Aug 2015
Posts: 12
wow this works great. thanks

Next Step i want to add Message, when one of this Items received Loot.

Lua Code:
  1. function AddLootMsg(self, event, message, ...)
  2.     local itemName,itemLink = GetItemInfo(itemID);
  3.     if not itemLink then return end
  4.     local itemId = itemLink:match('item:(%d+)');
  5.     local setIndex = itemSet[tonumber(itemId)];
  6.  
  7.         if setIndex and setName[setIndex] then
  8.         DEFAULT_CHAT_FRAME:AddMessage("Hello, World!");
  9.     end
  10. end
  11.  
  12. ChatFrame_AddMessageEventFilter("CHAT_MSG_LOOT", AddLootMsg);

this is not working..
whats the different between GetItemInfo(itemID); and GameTooltip:GetItem(); ?
Can i use the same lookup table or i need a new one?
Can i use the same locals agains?
  Reply With Quote
08-14-15, 07:45 AM   #5
suicidalkatt
A Rage Talon Dragon Guard
 
suicidalkatt's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2008
Posts: 331
Originally Posted by elcius View Post
lua has no problem with very large tables, just make an itemid to setid lookup table.

~ Snip
While your method would be ideal, it doesn't really do what the author intended.

I believe they want to have the tooltip show every set that contains a particular itemID not just the first one that returns true.

Lua Code:
  1. local setName =  {
  2. [1] = {  name = "Mystic's Regalia (Recolor)", items = {14090, 26008, 14094}, },
  3. -- [2......1778]
  4. [1779] = {  name = "Imperial Plate", items = {31436, 30002, 12424, 12425, 12422, 12427, 12429}, },
  5. }
  6.  
  7. -- make lookup table, this will create a list that looks something like this
  8. --[[
  9. local table = {
  10.     [14090] = {201,560,888} -- Item id = Table of setName[index] values
  11. }
  12. ]]
  13. local itemSet = {}
  14. do
  15.     for i,set in pairs(setName) do -- Looks through all the set
  16.         for j, id in pairs(set['items']) do -- looks though just the items table within
  17.             if not itemSet[id] then itemSet[id] = {} end -- creates a table within itemSet for each id (only once)
  18.             tinsert(itemSet[id], i) -- inserts each set index into the table
  19.         end
  20.     end
  21. end
  22.  
  23. function addline_gametip()
  24.     local itemName,itemLink = GameTooltip:GetItem();
  25.     if not itemLink then return end
  26.    
  27.     local itemId = tonumber(itemLink:match('item:(%d+)'));
  28.     if itemSet[itemId] then -- if a set is found
  29.         for i, setIndex in pairs(itemSet[itemId]) do -- for each index the id has
  30.             GameTooltip:AddLine("Transmog Set: " .. setName[setIndex]['name']); -- add a line to the game tooltip
  31.         end
  32.     end
  33.  end
  34.  
  35.  
  36. GameTooltip:HookScript("OnTooltipSetItem", addline_gametip);

Last edited by suicidalkatt : 08-14-15 at 07:50 AM. Reason: spellcheck
  Reply With Quote
08-14-15, 07:55 PM   #6
Endzeit
A Deviate Faerie Dragon
Join Date: Aug 2015
Posts: 12
thanks suicidalkatt & elcius.

While your method would be ideal, it doesn't really do what the author intended.

I believe they want to have the tooltip show every set that contains a particular itemID not just the first one that returns true.
1 set = 1 itemid. Both variants are correct for me. ItemId 123456 can not be in 2 Sets in my table.


Lua Code:
  1. function AddLootMsg(self, event, message, ...)
  2.      if not string.match(message,'Hbattlepet') then
  3.     local lootid = select(3, string.find(message, "item:(%d+):"))
  4.    
  5.     local itemName,itemLink = GetItemInfo(lootid);
  6.     if not itemLink then return end
  7.    
  8.    
  9.     local itemId = tonumber(itemLink:match('item:(%d+)'));
  10.    
  11.     if itemSet[itemId] then -- if a set is found
  12.         for i, setIndex in pairs(itemSet[itemId]) do -- for each index the id has
  13.         message = message:gsub("\124r.", "\124r (|cff9400D3Transmog Set: " .. setName[setIndex]['name'] .. "|cff00aa00).")
  14.         return false, message, ...
  15.  
  16.     end
  17. end
  18. end
  19. end
  20.  
  21. ChatFrame_AddMessageEventFilter("CHAT_MSG_LOOT", AddLootMsg);

thats my code for chat_msg_loot so far.. in my first tests it works.. have someone also an improvement for this code?

Last edited by Endzeit : 08-14-15 at 08:00 PM.
  Reply With Quote
08-15-15, 12:45 AM   #7
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
Since all the code is doing is matching items to set names, the lookup table doesn't need to be so complicated to use. Here's my example. There can be more optimizations depending on how you want the tooltip to look.

Lua Code:
  1. local TransmogSets={
  2.     {
  3.         name="Mystic's Regalia (Recolor)",
  4.         items={14090, 26008, 14094},
  5.     },
  6.     {
  7.         name="Imperial Plate",
  8.         items={31436, 30002, 12424, 12425, 12422, 12427, 12429},
  9.     },
  10. --  And so on ...
  11. };
  12.  
  13. --  Lookup Table
  14. local ItemSetNames={}; do
  15.     for _,set in ipairs(TransmogSets) do--  Scan through all sets
  16.         for _,itemid in ipairs(set.items) do--  Scan through items
  17. --          Add set name to list in lookup table
  18.             if not ItemSetNames[itemid] then ItemSetNames[itemid]={}; end
  19.             table.insert(ItemSetNames[itemid],set.name);
  20.         end
  21.     end
  22.  
  23. --  Sorts set names
  24.     for _,list in pairs(ItemSetNames) do table.sort(list); end
  25. end
  26.  
  27. --  Tooltip Hook
  28. GameTooltip:HookScript("OnTooltipSetItem",function(self)
  29.     local _,link=self:GetItem();
  30.     if not link then return; end--  Exit if we have no item
  31.  
  32.     local id=tonumber(link:match("|Hitem:(%d+)")) or 0;--   Force nil to zero if we have an invalid link (no items exist at index zero)
  33.     if ItemSetNames[id] then
  34.         for i,name in ipairs(ItemSetNames[id]) do
  35. --          Only show our label on the first line
  36.             self:AddDoubleLine(i<=1 and "Transmog Set:" or " ",name);
  37.         end
  38.     end
  39. end);
  40.  
  41. --  Chat Hook
  42. ChatFrame_AddMessageEventFilter("CHAT_MSG_LOOT",function(self,event,msg,...)
  43.     local id=tonumber(msg:match("|Hitem:(%d+)")) or 0;--    Force nil to zero if we have an invalid link (no items exist at index zero)
  44.     if ItemSetNames[id] then return false,msg.." (|cff9400d3Transmog Sets: "..table.concat(ItemSetNames[id],", ").."|r).",...; end
  45. end);

Edit: Replaced string.join() section with more efficient table.concat() call.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 08-17-15 at 03:15 PM.
  Reply With Quote
08-15-15, 01:06 PM   #8
Endzeit
A Deviate Faerie Dragon
Join Date: Aug 2015
Posts: 12
Lua Code:
  1. --  Chat Hook
  2. ChatFrame_AddMessageEventFilter("CHAT_MSG_LOOT",function(self,event,msg,...)
  3.     local id=tonumber(msg:match("|Hitem:(%d+)")) or 0;--    Force nil to zero if we have an invalid link (no items exist at index zero)
  4.     if ItemSetNames[id] then return false,msg.." (|cff9400d3Transmog Sets: "..string.join(", ",unpack(ItemSetNames[id])).."|r).",...; end
  5. end);

works.. but it also show loot from other player.. this should not happen. i tried this:
Lua Code:
  1. --  Chat Hook
  2. ChatFrame_AddMessageEventFilter("CHAT_MSG_LOOT",function(self,event,msg,...)
  3.     local id=tonumber(msg:match("|Hitem:(%d+)")) or 0;--    Force nil to zero if we have an invalid link (no items exist at index zero)
  4.     if ItemSetNames[id] and LOOT_ITEM_PUSHED_SELF or LOOT_ITEM_SELF ~= nil then return false,msg.." (|cff9400d3Transmog Sets: "..string.join(", ",unpack(ItemSetNames[id])).."|r).",...; end
  5. end);
this works for myself.. but get lua errors if other player loot items.
  Reply With Quote
08-15-15, 02:50 PM   #9
Mazzop
A Cliff Giant
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 74
try

Lua Code:
  1. ChatFrame_AddMessageEventFilter("CHAT_MSG_LOOT",function(self,event,msg,who...)
  2.   if who==UnitName("player")
  3.     local id=tonumber(msg:match("|Hitem:(%d+)")) or 0;--    Force nil to zero if we have an invalid link (no items exist at index zero)
  4.     if ItemSetNames[id]  then return false,msg,who.." (|cff9400d3Transmog Sets: "..string.join(", ",unpack(ItemSetNames[id])).."|r).",...; end
  5.   end
  6. end);

Last edited by Mazzop : 08-15-15 at 02:55 PM.
  Reply With Quote
08-15-15, 03:13 PM   #10
Endzeit
A Deviate Faerie Dragon
Join Date: Aug 2015
Posts: 12
Originally Posted by Mazzop View Post
try

Lua Code:
  1. ChatFrame_AddMessageEventFilter("CHAT_MSG_LOOT",function(self,event,msg,who...)
  2.   if who==UnitName("player")
  3.     local id=tonumber(msg:match("|Hitem:(%d+)")) or 0;--    Force nil to zero if we have an invalid link (no items exist at index zero)
  4.     if ItemSetNames[id]  then return false,msg,who.." (|cff9400d3Transmog Sets: "..string.join(", ",unpack(ItemSetNames[id])).."|r).",...; end
  5.   end
  6. end);
this is not working.. lua errors.
also trying change from 'function(self,event,msg,who...)' to 'function(self,event,msg,who,...)'
and
' if who==UnitName("player")' to ' if who==UnitName("player") then'
no lua errors now, but is not working anymore

print(who); returns nothing like print();

Last edited by Endzeit : 08-15-15 at 03:18 PM.
  Reply With Quote
08-15-15, 03:23 PM   #11
Mazzop
A Cliff Giant
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 74
obviously i cannot drycode
its 5th argument, from fast /etrace

Lua Code:
  1. ChatFrame_AddMessageEventFilter("CHAT_MSG_LOOT",function(self,event,msg,who,language,channelString,target,  ...)
  2.       if target==UnitName("player") then
  3.         local id=tonumber(msg:match("|Hitem:(%d+)")) or 0;--    Force nil to zero if we have an invalid link (no items exist at index zero)
  4.         if ItemSetNames[id] then return false,msg,who,language,channelString,target,." (|cff9400d3Transmog Sets: "..string.join(", ",unpack(ItemSetNames[id])).."|r).",...; end
  5.       end
  6.     end);

Last edited by Mazzop : 08-15-15 at 03:30 PM.
  Reply With Quote
08-15-15, 03:43 PM   #12
Endzeit
A Deviate Faerie Dragon
Join Date: Aug 2015
Posts: 12
this cannot be working like this
for example playername: "Killer"
target returns "Killer"
UnitName("player") returns "Killer nil"


Lua Code:
  1. ChatFrame_AddMessageEventFilter("CHAT_MSG_LOOT",function(self,event,msg,_,_,_,target,  ...)
  2.       local name, realm = UnitName("player")
  3.       if target==name then
  4.         local id=tonumber(msg:match("|Hitem:(%d+)")) or 0;--    Force nil to zero if we have an invalid link (no items exist at index zero)
  5.         if ItemSetNames[id] then return false,msg.." (|cff9400d3Transmog Sets: "..string.join(", ",unpack(ItemSetNames[id])).."|r).",...; end
  6.       end
  7.     end);

this works for UnitName("player"), cant check now if it works for other players

Last edited by Endzeit : 08-15-15 at 03:46 PM.
  Reply With Quote
08-15-15, 03:48 PM   #13
Mazzop
A Cliff Giant
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 74
instead of UnitName("player") use select(1, UnitName("player"))
or make a variable local playername=UnitName("player")
  Reply With Quote
08-15-15, 07:27 PM   #14
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
Originally Posted by Mazzop View Post
instead of UnitName("player") use select(1, UnitName("player"))
or make a variable local playername=UnitName("player")
The second option here ^^ is WAY better than the first. 1) it eliminates a needless function call. 2) select(1, ...) will still return everything after that 1st return.
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote
08-15-15, 08:45 PM   #15
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,196
There's also the option of

Code:
(UnitName("player"))
That will only evaluate the first return value, but it's a bit non-obvious if you're looking at the code months later.
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Author of NPCScan and many other AddOns.
  Reply With Quote
08-16-15, 01:55 AM   #16
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Mazzop View Post
select(1, UnitName("player"))
There is no reason to ever use select with 1 as the first argument. There's almost no reason to ever use select at all -- it's way slower than assigning variables, eg. local _, class = UnitClass("player") -- but there's really no reason to ever use it like this. >_<
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
08-16-15, 02:38 AM   #17
Mazzop
A Cliff Giant
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 74
ok ok, select is big nono, i get it
dont wanna hijack topic, but not even here

instead of sexy and nice
Lua Code:
  1. for j = 1, numbonuses do
  2.   bonus[j] = select(14 + j, strsplit(":", itemstring))
  3. end

would be better hideous abomination with numerous if depends of numbonuses and 14+ _ ?
  Reply With Quote
08-16-15, 04:25 AM   #18
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
Originally Posted by Mazzop View Post
ok ok, select is big nono, i get it
dont wanna hijack topic, but not even here

instead of sexy and nice
Lua Code:
  1. for j = 1, numbonuses do
  2.   bonus[j] = select(14 + j, strsplit(":", itemstring))
  3. end

would be better hideous abomination with numerous if depends of numbonuses and 14+ _ ?
A few calls here and there is not gonna make a difference. It's fine, and I'd say this is a perfectly reasonable situation in which to use it. That logic might be improved slightly in other ways, though!
__________________
Grab your sword and fight the Horde!
  Reply With Quote
08-16-15, 06:04 AM   #19
Rilgamon
Premium Member
 
Rilgamon's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 822
Originally Posted by Lombra View Post
A few calls here and there is not gonna make a difference.
Turn your logic around a little. The request was to improve the performance. And removing select will always be an improvement.
__________________
The cataclysm broke the world ... and the pandas could not fix it!
  Reply With Quote
08-16-15, 10:36 AM   #20
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
Originally Posted by Rilgamon View Post
Turn your logic around a little. The request was to improve the performance. And removing select will always be an improvement.
Sure, but I didn't read the word "performance" anywhere, only "better". If the performance gain is negligible I would definitely go for readability.

Edit: Without wanting to make a point of it, just did some quick benchmarks so people can get an idea of the difference.
This takes 43 ms to run:
Code:
for i = 1, 1e6 do
	local a, b, c = 1, 2, 3, 4, 5, 6, 7, 8, 9
end
This takes 94 ms to run, with the first select argument not affecting the result. No local reference.
Code:
for i = 1, 1e6 do
	local a, b, c = select(1, 1, 2, 3, 4, 5, 6, 7, 8, 9)
end
That's one million iterations, with each value adding a few ms in both tests.
__________________
Grab your sword and fight the Horde!

Last edited by Lombra : 08-16-15 at 10:55 AM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Problems with Big Tables

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off