Thread Tools Display Modes
10-14-19, 09:09 PM   #1
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,237
[Classic] GetNumFactions() not getting past index 1

I have a function that sets the watched faction by factionID, seeing how Blizzard's SetWatchedFactionIndex() only works from 1 to GetNumFactions() I had to create a function.

However, my code isn't advancing properly past index 1, "Alliance" in my testbed. Oddly, the test prints are getting the correct factionID and name. I am missing something, and can't spot it.

I don't think it matters that this code is for Classic, by all accounts it should work for Retail as well, except my comparison tables that return the factionID are based on Classic's UIMapIDs, which are not the same for both versions.

The first print's output is "Stormwind" because that is where my toon is, while the second's output is "1", which is not correct. Based on my low level and lack of world exploration, the index should be "5" for Stormwind.

Further testing from other print outputs does indicate that the factionID 1453 is correct, and matching for Stormwind.
Lua Code:
  1. -- Blizzard sets watched faction by index, not by factionID so create our own API
  2. function RepByZone:SetWatchedFactionByFactionID(id)
  3.     if type(id) == "table" then id = tonumber(id) end
  4.     if type(id) ~= "number" then return end
  5.  
  6.     self:OpenAllFactionHeaders()
  7.     for i = 1, GetNumFactions() do
  8.         local name, _, standingID, _, _, _, _, _, isHeader, _, _, isWatched, _, factionID = GetFactionInfoByID(id)
  9.         if id == factionID then
  10.             self:Print("DEBUG: SetWatchedFactionByFactionID name:", name)
  11.             self:Print("DEBUG: SetWatchedFactionByFactionID index:", i)
  12.             if not isWatched then
  13.                 SetWatchedFactionIndex(i)
  14.             end
  15.             self:CloseAllFactionHeaders()
  16.             return name, id
  17.         else
  18.             break
  19.         end
  20.     end
  21.     self:CloseAllFactionHeaders()
  22. end

Last edited by myrroddin : 10-14-19 at 09:12 PM. Reason: Noted factionID for Stormwind, and that finding the factionID code is working
  Reply With Quote
10-14-19, 09:16 PM   #2
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,237
It occurs to me to post more code, so this is my entire opening and closing of faction headers, plus setting of the faction by factionID. If anyone wants to see all of the code, I'll be happy to post that too.
Lua Code:
  1. local repsCollapsed = {} -- Obey user's settings about headers opened or closed
  2. -- Open all faction headers
  3. function RepByZone:OpenAllFactionHeaders()
  4.     local i = 1
  5.     while i <= GetNumFactions() do
  6.         local name, _, _, _, _, _, _, _, isHeader, isCollapsed = GetFactionInfo(i)
  7.         if isHeader then
  8.             repsCollapsed[name] = isCollapsed
  9.             if name == FACTION_INACTIVE then
  10.                 if not isCollapsed then
  11.                     CollapseFactionHeader(i)
  12.                 end
  13.                 break
  14.             elseif isCollapsed then
  15.                 ExpandFactionHeader(i)
  16.             end
  17.         end
  18.         i = i + 1
  19.     end
  20. end
  21.  
  22. -- Close all faction headers
  23. function RepByZone:CloseAllFactionHeaders()
  24.     local i = 1
  25.     while i <= GetNumFactions() do
  26.         local name, _, _, _, _, _, _, _, isHeader, isCollapsed = GetFactionInfo(i)
  27.         if isHeader then
  28.             if isCollapsed and not repsCollapsed[name] then
  29.                 ExpandFactionHeader(i)
  30.             elseif repsCollapsed[name] and not isCollapsed then
  31.                 CollapseFactionHeader(i)
  32.             end
  33.         end
  34.         i = i + 1
  35.     end
  36.     wipe(repsCollapsed)
  37. end
  38.  
  39. function RepByZone:GetAllFactions()
  40.     -- Will not return factions the user has marked as inactive
  41.     self:OpenAllFactionHeaders()
  42.     local factionList = {}
  43.  
  44.     for i = 1, GetNumFactions() do
  45.         local name, _, _, _, _, _, _, _, isHeader, _, _, _, _, factionID = GetFactionInfo(i)
  46.         if not isHeader then
  47.             factionList[factionID] = name
  48.         end
  49.     end
  50.  
  51.     self:CloseAllFactionHeaders()
  52.     return factionList
  53. end
  54.  
  55. -- Blizzard sets watched faction by index, not by factionID so create our own API
  56. function RepByZone:SetWatchedFactionByFactionID(id)
  57.     if type(id) == "table" then id = tonumber(id) end
  58.     if type(id) ~= "number" then return end
  59.  
  60.     self:OpenAllFactionHeaders()
  61.     for i = 1, GetNumFactions() do
  62.         local name, _, standingID, _, _, _, _, _, isHeader, _, _, isWatched, _, factionID = GetFactionInfoByID(id)
  63.         if id == factionID then
  64.             self:Print("DEBUG: SetWatchedFactionByFactionID name:", name)
  65.             self:Print("DEBUG: SetWatchedFactionByFactionID index:", i)
  66.             if not isWatched then
  67.                 SetWatchedFactionIndex(i)
  68.             end
  69.             self:CloseAllFactionHeaders()
  70.             return name, id
  71.         else
  72.             break
  73.         end
  74.     end
  75.     self:CloseAllFactionHeaders()
  76. end
  77.  
  78. -- Player switched zones, set watched faction
  79. function RepByZone:SwitchedZones()
  80.     local UImapID = IsInInstance() and select(8, GetInstanceInfo()) or C_Map.GetBestMapForUnit("player")
  81.     local locationsAndFactions = IsInInstance() and self:InstanceAndFactionList() or self:ZoneAndFactionList()
  82.     -- local mapID = C_Map.GetMapInfo(UImapID).mapID
  83.     self:Print("DEBUG: Current UImapID is", UImapID)
  84.     -- self:Print("DEBUG: Current mapID is", mapID)
  85.     self:SetWatchedFactionByFactionID(db.defaultRepID)
  86.     for zoneID, factionID in pairs(locationsAndFactions) do
  87.         if zoneID == UImapID then
  88.             self:Print("DEBUG: zoneID and UImapID match")
  89.             self:SetWatchedFactionByFactionID(factionID)
  90.             break
  91.         end
  92.     end
  93. end

Last edited by myrroddin : 10-14-19 at 09:43 PM. Reason: Modified SwitchedZones() function
  Reply With Quote
10-14-19, 09:47 PM   #3
Vrul
A Scalebane Royal Guard
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 404
It seems like the line:
Code:
local name, _, standingID, _, _, _, _, _, isHeader, _, _, isWatched, _, factionID = GetFactionInfoByID(id)
should be:
Code:
local name, _, standingID, _, _, _, _, _, isHeader, _, _, isWatched, _, factionID = GetFactionInfo(i)
otherwise you are iterating from 1 to GetNumFactions() but checking the same id over and over which doesn't change in the loop so you could just do it once.
  Reply With Quote
10-14-19, 10:04 PM   #4
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,237
Vrul, yes, that's probably a bug, though upon testing walking from Stormwind City to Elwynn Forest, the UIMapIDs sync, but the watched rep is now printing nothing. Hm, progress?
Lua Code:
  1. function RepByZone:SetWatchedFactionByFactionID(id)
  2.     if type(id) == "table" then id = tonumber(id) end
  3.     if type(id) ~= "number" then return end
  4.  
  5.     self:OpenAllFactionHeaders()
  6.     for i = 1, GetNumFactions() do
  7.         local name, _, standingID, _, _, _, _, _, isHeader, _, _, isWatched, _, factionID = GetFactionInfo(i)
  8.         if id == factionID then
  9.             self:Print("DEBUG: SetWatchedFactionByFactionID name:", name) --doesn't print now
  10.             self:Print("DEBUG: SetWatchedFactionByFactionID index:", i) -- doesn't print now
  11.             if not isWatched then
  12.                 SetWatchedFactionIndex(i)
  13.             end
  14.             self:CloseAllFactionHeaders()
  15.             return name, id
  16.         else
  17.             break
  18.         end
  19.     end
  20.     self:CloseAllFactionHeaders()
  21. end
  Reply With Quote
10-14-19, 10:18 PM   #5
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,857
Code:
 if type(id) == "table" then id = tonumber(id) end
Doesn't that just result in id being nil?
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
10-14-19, 10:28 PM   #6
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,237
I'll comment it out for now. Eventually that line is for when I pass subzone strings via a table for those smaller areas that have a different associated faction than the main zone.

I thought that if the type wasn't a table, the line would do nothing. Maybe it does, so I'll test by commenting it out.
  Reply With Quote
10-14-19, 10:32 PM   #7
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,237
Commenting it out still doesn't fix the issue. The lines
Code:
self:Print("DEBUG: SetWatchedFactionByFactionID name:", name)
self:Print("DEBUG: SetWatchedFactionByFactionID index:", i)
Are not printing anything in the function SetWatchedFactionByFactionID()
That means the code isn't even looping, right?
  Reply With Quote
10-14-19, 10:36 PM   #8
Vrul
A Scalebane Royal Guard
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 404
Originally Posted by myrroddin View Post
The lines
Code:
self:Print("DEBUG: SetWatchedFactionByFactionID name:", name)
self:Print("DEBUG: SetWatchedFactionByFactionID index:", i)
Are not printing anything in the function SetWatchedFactionByFactionID()
That means the code isn't even looping, right?
No, that just means the condition "id == factionID" is not being met.
  Reply With Quote
10-14-19, 10:40 PM   #9
Vrul
A Scalebane Royal Guard
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 404
See what you get with:
lua Code:
  1. function RepByZone:SetWatchedFactionByFactionID(id)
  2.     if type(id) == "table" then id = tonumber(id) end
  3.     if type(id) ~= "number" then return end
  4.  
  5.     self:OpenAllFactionHeaders()
  6.     for i = 1, GetNumFactions() do
  7.         local name, _, standingID, _, _, _, _, _, isHeader, _, _, isWatched, _, factionID = GetFactionInfo(i)
  8.         self:Print("DEBUG: SetWatchedFactionByFactionID name:", name)
  9.         self:Print("DEBUG: SetWatchedFactionByFactionID index:", i)
  10.         if id == factionID then
  11.             if not isWatched then
  12.                 SetWatchedFactionIndex(i)
  13.             end
  14.             self:CloseAllFactionHeaders()
  15.             return name, id
  16.         end
  17.     end
  18.     self:CloseAllFactionHeaders()
  19. end
  Reply With Quote
10-14-19, 11:17 PM   #10
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,237
Originally Posted by Vrul View Post
See what you get with:< snip >
That seems to be working, woot! I've tested between Stormwind and Elywnn Forest, as per usual. When I get a chance I will go to another zone.

Taking the else break part was the fix, huh?
  Reply With Quote
10-16-19, 03:49 AM   #11
Urtgard
A Fallenroot Satyr
AddOn Author - Click to view addons
Join Date: Apr 2016
Posts: 25
break stops the loop.

You stop the loop if id ~= factionID but you want to stop it when you found the correct id.
Lua Code:
  1. if id == factionID then
  2.     --do stuff with id
  3.     break
  4. end
  Reply With Quote
10-16-19, 11:14 AM   #12
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,237
Originally Posted by Urtgard View Post
break stops the loop.

You stop the loop if id ~= factionID but you want to stop it when you found the correct id.
Lua Code:
  1. if id == factionID then
  2.     --do stuff with id
  3.     break
  4. end
D'oh, of course. Thanks, Urtgard. Now I only need to get the Curseforge Packer to stop screwing up my code, and then RepByZone will be useful. If this continues into the afternoon, I'll manually input all fields and upload a manual zip file.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » [Classic] GetNumFactions() not getting past index 1

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