Thread Tools Display Modes
08-27-21, 12:03 PM   #1
xubo
A Murloc Raider
Join Date: Aug 2021
Posts: 6
Need help understanding why loop is not always processing entire table

I'm in the process of creating my first addon and teaching myself lua... I'm not an expert by any means so any help would be appreciated.

The addon I'm creating is a simple mount collection log which mimics the functionality that simple armory mount collection shows. It lists all the obtainable mounts, categorizes them and marks off those you have collected.

I've managed to get the main GUI and functionality sorted but it's not performing consistently. Meaning sometimes when you initialize the addon, the entire lua table has not been processed leaving a lot mounts missing in the GUI.

This issue is less of a problem when there are no addons enabled, but happens a lot more when there are other addons enabled at the same time. The main function of the code is below, I imagine the problem is to do with how many loops there are.

Any help is appreciated. I can provide the entire files if need be.

Lua Code:
  1. local mountFrames = {}
  2. local collectableMounts = 0
  3. --Creating a frame to place expansion content in.
  4. --For each value section and category run this loop
  5. for k,v in pairs(sectionNames) do
  6.     --Reset location of frames
  7.     local yTwo = -20
  8.     local xTwo = 20
  9.     local rowC = 0
  10.     local frameName = MCL:GetName()
  11.     --Cycle through each section and check if database entry matches any string.
  12.     for s = 1, #sectionStrings do
  13.         if v.name == sectionStrings[s] then
  14.             --If string matches a section then we loop through all categories for that section and create a frame. 
  15.             for i = 1, #v.category do
  16.                 local a = self:CategoryFrame(v.category[i], sections[s], xTwo, yTwo)
  17.                 local rowC = 0
  18.                 local x = 10
  19.                 local y = -25
  20.                 for b,n in pairs(mountList) do
  21.                     if n.name == sectionStrings[s] then
  22.                         for h,j in pairs(n) do
  23.                             if j.name == v.category[i] then
  24.                                 if j.mounts then
  25.                                     local total = 0
  26.                                     local totalc = 0
  27.                                     for t = 1, #j.mountID do
  28.                                         if j.mountID[t] then
  29.                                             local _, _, icon, _, _, _, _, isFactionSpecific, faction, _, isCollected, ID = C_MountJournal.GetMountInfoByID(j.mountID[t])
  30.                                             if (isFactionSpecific == true and faction == playerFaction) or isFactionSpecific == false then
  31.                                                 if rowC > 0 then
  32.                                                     x = x+48
  33.                                                 end
  34.                                                 rowC = rowC+1                              
  35.                                                 local mountFrame = self:CreateMountIcons("TOPLEFT", x, y, a, isCollected, icon)
  36.                                                 collectableMounts = collectableMounts+1
  37.                                                 table.insert(mountFrames, collectableMounts, mountFrame)
  38.                                             end
  39.                                             if isCollected == true then
  40.                                                 totalc = totalc+1
  41.                                                 totalCollected = totalCollected+1
  42.                                                 if v.category[i] ~= "Blizzard Store" then
  43.                                                     totalCollectedNoStore = totalCollectedNoStore+1
  44.                                                 end
  45.                                             end
  46.                                         end                                
  47.                                     end                    
  48.                                     for t = 1, #j.mounts do
  49.                                         if C_MountJournal.GetMountFromItem(j.mounts[t]) then
  50.                                             local mountID = C_MountJournal.GetMountFromItem(j.mounts[t])
  51.                                             local _, _, _, _, isUsable, sourceType, _, isFactionSpecific, faction, _, isCollected, mountID = C_MountJournal.GetMountInfoByID(mountID)                                      
  52.                                             if (isFactionSpecific == true and faction == playerFaction) or isFactionSpecific == false then
  53.                                                 if rowC > 0 then
  54.                                                     x = x+48
  55.                                                 end
  56.                                                 rowC = rowC+1
  57.  
  58.                                                 local mountFrame = self:CreateIcons("TOPLEFT", x, y, j.mounts[t], a, isCollected)
  59.                                                 collectableMounts = collectableMounts+1
  60.                                                 table.insert(mountFrames, collectableMounts, mountFrame)                                                   
  61.                                                 if isCollected == true then
  62.                                                     totalc = totalc+1
  63.                                                     totalCollected = totalCollected+1
  64.                                                     if v.category[i] ~= "Blizzard Store" then
  65.                                                         totalCollectedNoStore = totalCollectedNoStore+1
  66.                                                     end
  67.                                                 end
  68.                                                 local item, itemLink = GetItemInfo(j.mounts[t]);
  69.                                                 mountFrame:SetScript("OnClick", function(self, button, down)
  70.                                                     if (itemLink) then
  71.                                                         print(itemLink)
  72.                                                     end
  73.                                                 end)
  74.                                             --This will determine when to start a new row of mounts. Currently set to 6 mounts per row.                            
  75.                                                 if(rowC == 50) then
  76.                                                     y = y-45
  77.                                                     x = 10
  78.                                                     rowC = 0
  79.                                                 end
  80.                                                 total = total+1
  81.                                             end
  82.                                         end                            
  83.                                     end
  84.                                     a.title:SetText(v.category[i].." ("..totalc.."/"..total..")")
  85.                                 end
  86.                             end
  87.                         end
  88.                     end
  89.                 end
  90.                 yTwo = yTwo - 80
  91.             end
  92.         end
  93.     end
  94. end

Last edited by xubo : 08-28-21 at 11:13 AM.
  Reply With Quote
08-27-21, 01:36 PM   #2
LudiusMaximus
A Rage Talon Dragon Guard
 
LudiusMaximus's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2018
Posts: 320
Hi and welcome!

You could try executing your code after PLAYER_LOGIN like this:

Lua Code:
  1. local startupFrame = CreateFrame("Frame")
  2. startupFrame:RegisterEvent("PLAYER_LOGIN")
  3. startupFrame:SetScript("OnEvent", function()
  4.   -- Your code here.
  5. end)
__________________
~ Be the change you want to see in the world... of warcraft interface! ~
  Reply With Quote
08-27-21, 03:24 PM   #3
xubo
A Murloc Raider
Join Date: Aug 2021
Posts: 6
Unfortunately I've already tried using that event trigger. I have better results with ADDON_LOADED trigger, however, still having issues with not all frames being created consistently.
  Reply With Quote
08-28-21, 04:10 PM   #4
LudiusMaximus
A Rage Talon Dragon Guard
 
LudiusMaximus's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2018
Posts: 320
Are you checking which addon is loaded when using the ADDON_LOADED trigger? Maybe you have to wait for Blizzard_Collections to be loaded, but that's just a very wild guess.

It's difficult to understand your code.
For example, you are traversing a table called "mountList".
I guess that is the table you say is sometime not fully traversed?

Your code does not show where you are getting "mountList" from in the first place.
__________________
~ Be the change you want to see in the world... of warcraft interface! ~
  Reply With Quote
08-29-21, 11:33 AM   #5
xubo
A Murloc Raider
Join Date: Aug 2021
Posts: 6
So the code I'm using for the ADDON_LOADED trigger is

Lua Code:
  1. function core:init(event, name)
  2.     if (name ~= "MCL") then return end
  3.     start = core.Config.Toggle();
  4.     hide = core.Config.Toggle();
  5.  
  6.     SLASH_MCL1 = "/mcl";
  7.     SlashCmdList.MCL = core.Config.Toggle; 
  8.     core:Print("Welcome back", UnitName("player").."!");
  9. end
  10.  
  11. local events = CreateFrame("Frame");
  12. events:RegisterEvent("ADDON_LOADED");
  13. events:SetScript("OnEvent", core.init);

My mountList, SectionNames are tables provided in a different file and they look like this.

Lua Code:
  1. mountList = {
  2.     SL = {
  3.         name = "SL",
  4.         Achievement = {
  5.             name = "Achievement",
  6.             mounts = {186654, 186637, 184183, 182596, 186653, 184166, 186655, 182717, 187525},
  7.             mountID = {}
  8.         },....
  9.  
  10. sectionNames = {
  11.     Classic = {
  12.         name = "Classic",
  13.         category = {"Reputation", "Dungeon Drop", "Raid Drop"},
  14.     },...

Yes I would say that is the table that is not always fully traversed. I've just tried adding a LoadAddon line for Blizzard_Collections inside the core.init function

Lua Code:
  1. SLASH_MCL1 = "/mcl";
  2.     LoadAddOn("Blizzard_Collections")
  3.     SlashCmdList.MCL = core.Config.Toggle; 
  4.     core:Print("Welcome back", UnitName("player").."!");

Still the same result. Attached is the addon, if anyone would take a look I would be appreciated.
Attached Files
File Type: zip MCL.zip (35.0 KB, 146 views)

Last edited by xubo : 08-29-21 at 01:24 PM.
  Reply With Quote
08-29-21, 03:11 PM   #6
Xrystal
nUI Maintainer
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 5,892
You are still not making sure that you are only accessing the collection information after the collection addon is loaded. You are checking for MCL addon is loaded but not checking if Blizzard_Collections addon is loaded before accessing its data. It might be that the first few accesses are failing in some way, do you have an error catch system like bugsack/buggrabber so that you can see if there are any particular errors that occur on that first access attempt.

Suggestions:

1. Install bugsack/buggrabber addons or any equivalents you may be aware of and prefer ..
2. In your event loop checking if the Blizzard_Collections addon is loaded and then do your collections related coding.
3. Make use of print statements to check what values are between code lines to see if values change and perhaps highlighting potential reasons why. - Just remember to remove them or put them in a if debug statement before releasing the addon if you plan to .
__________________
  Reply With Quote
08-30-21, 04:14 AM   #7
xubo
A Murloc Raider
Join Date: Aug 2021
Posts: 6
1. I already had bugcatcher/bugsack installed and been using it a lot. No errors pop up when it misses data.
2. I've added the code below (has no effect on the outcome).
Lua Code:
  1. local EventFrame = CreateFrame('Frame')
  2. EventFrame:RegisterEvent('ADDON_LOADED')
  3. EventFrame:SetScript('OnEvent', function(self, event, ...)
  4.     if self[event] then
  5.         self[event](self, ...)
  6.     end
  7. end)
  8.  
  9. function EventFrame:ADDON_LOADED(name)
  10.     if name == "MCL" then
  11.         if not IsAddOnLoaded("Blizzard_Collections") then
  12.             UIParentLoadAddOn("Blizzard_Collections")
  13.             print("LOADING COLLECTIONS")
  14.         else
  15.             print("Already Loaded")
  16.         end
  17.         SLASH_MCL1 = "/mcl";
  18.         SlashCmdList.MCL = core.Config.Toggle;
  19.         core:Print("Welcome back", UnitName("player").."!");
  20.         -- remove event
  21.         self:UnregisterEvent('ADDON_LOADED')
  22.         self.ADDON_LOADED = nil
  23.     end
  24. end

Have I done that correctly? This has had no effect on the original issue.
  Reply With Quote
08-30-21, 10:59 AM   #8
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,871
You've set up your data tables (sectionNames and mountList) as globals. They should really be included in your namespace table (core.sectionNames and core.mountList).

You could add the collection loaded check to MCL_Load:CreateMenu() before creating the frame and get rid of the whole init frame ADDON_LOADED stuff and just use the slash command
Lua Code:
  1. local _, core = ...; -- Namespace
  2. -------------------------------------------------------------
  3.  
  4. function core:Print(...)
  5.     local hex = select(4, self.Config:GetThemeColor());
  6.     local prefix = string.format("|cff%s%s|r", hex:upper(), "MCL:");   
  7.     DEFAULT_CHAT_FRAME:AddMessage(string.join(" ", prefix, ...));
  8. end
  9.  
  10. SLASH_MCL1 = "/mcl";
  11. SlashCmdList.MCL = core.Config.Toggle;

Lua Code:
  1. function MCL_Load:CreateMenu()
  2.     core:Print("Welcome back", UnitName("player").."!");
  3.     --Master Frame for addon
  4.     if not IsAddOnLoaded("Blizzard_Collections") then
  5.         LoadAddOn("Blizzard_Collections")
  6.     end
  7.  
  8.     local MCL = CreateFrame("Frame", "MLCFrame", UIParent, "BasicFrameTemplateWithInset");
  9.     ...
  10. end

The "Welcome back" message is not really needed, they know they are playing and using your addon if they've gotten this far so...

You're also using a lot of globals with names like totalCollected and u and total and x and y ... While it's easy for accessing data in various parts of your code, you really need to make sure that global names are absolutely unique to your addon MCL_totalCollected, MCL_u, MCL_total etc. It may not be the cause of you problems but it will help stopping future possible problems.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 08-30-21 at 01:23 PM.
  Reply With Quote
08-30-21, 03:53 PM   #9
xubo
A Murloc Raider
Join Date: Aug 2021
Posts: 6
Really appreciate everything so far guys, really helped me understand a few things. I've gone through and removed all my globals.

I've attached the current version as I'm still having issues with the entire mount table not being loaded consistently. Sometimes no mounts get loaded, sometimes 100-200, sometimes all of them. I can't seem to figure out why it varies.

Thanks so much for the replies so far guys.
Attached Files
File Type: zip MCL-0.2a.zip (35.2 KB, 134 views)
  Reply With Quote
08-30-21, 04:07 PM   #10
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,871
You have a timing problem between when you ask for data and when it is ready to use.
I couldn't find an event that worked to tell you when the mount information has been cached so I bodged something up (not really tested so...)

I also moved the update code into a function to be used OnShow so it gets update each time the Config. frame is displayed.
MCL.zip

I hope it gets you closer.

Edit: I didn't check on things like frame creation so you might be getting new icon frames created on top of older ones each OnSHow and stuff like that.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 08-30-21 at 04:12 PM.
  Reply With Quote
09-03-21, 09:09 AM   #11
xubo
A Murloc Raider
Join Date: Aug 2021
Posts: 6
Fizzlemizz, thank you so much for this. Calling for the data on addon_load seems to have fixed it.
  Reply With Quote

WoWInterface » AddOns, Compilations, Macros » AddOn Help/Support » Need help understanding why loop is not always processing entire table

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