diff --git a/Button.lua b/Button.lua index f6b4806..d1c84d5 100644 --- a/Button.lua +++ b/Button.lua @@ -573,7 +573,7 @@ end --[[ Set the individual types of actions including obtained any extra data they may need --]] function Button:SetCommandSpell(Id) - local Name, Rank = GetSpellInfo(Id); + local Name, Rank = Util.GetSpellInfo(Id); -- TBC Fix 2021/06/18 local NameRank = Util.GetFullSpellName(Name, Rank); self:SetCommandExplicitSpell(Id, NameRank, Name, Book); end @@ -1230,7 +1230,9 @@ function Button:TranslateMacro() self.CompanionIndex = CompanionID; end self.SpellName = SpellName; - self.SpellNameRank = GetSpellInfo(SpellName); --BFA fix: Cache is indexed by name and the old function returned the ID + -- self.SpellNameRank = GetSpellInfo(SpellName); --BFA fix: Cache is indexed by name and the old function returned the ID + local Rank = Util.GetSpellRank(SpellId) -- TBC Fix 2021/06/17 + self.SpellNameRank = Util.GetFullSpellName(SpellName, Rank); -- TBC Fix 2021/06/17 self.SpellId = SpellId; self.MacroMode = "spell"; else @@ -2034,7 +2036,8 @@ function Button:PromoteSpell() end --[[ if (self.Mode == "spell") then - local Name, Rank = GetSpellInfo(self.SpellName); --This will actually retrieve for the highest rank of the spell + -- local Name, Rank = GetSpellInfo(self.SpellName); --This will actually retrieve for the highest rank of the spell + local Name, Rank = Util.GetSpellInfo(self.SpellName) -- TBC Fix 2021/06/18 if (Name) then if (Util.LookupNewSpellIndex(Name.."("..Rank..")")) then if (strfind(Rank, Util.GetLocaleString("SpellRank"), 1, true) and strfind(self.SpellNameRank, Util.GetLocaleString("SpellRank"), 1, true)) then diff --git a/DumpSpells.lua b/DumpSpells.lua new file mode 100644 index 0000000..ddd434c --- /dev/null +++ b/DumpSpells.lua @@ -0,0 +1,247 @@ +local _G = getfenv(0) +local addon, L = ...; + +DS_Color1 = "|cff3399ff" +DS_Color2 = "|cff1eff00" + +DS_Loaded = false +DS_pName = UnitName("player") +DS_pClass = UnitClass("player") + +local function myprint(msg) + if msg ~= nil then + msg = tostring(msg) + print(DS_Color1..addon..": "..DS_Color2..msg) + return + end +end + +local function DS_PadiSpellId(t) + if strlen(t) == 2 then + tnum = "0000"..t + return tnum + elseif strlen(t) == 3 then + tnum = "000"..t + return tnum + elseif strlen(t) == 4 then + tnum = "00"..t + return tnum + elseif strlen(t) == 5 then + tnum = "0"..t + return tnum + end + return t +end + +function Init_DS_Tables() + + -- known spells + if DS_kSpellsTable == nil then DS_kSpellsTable = {} end + if DS_kSpellsTable2 == nil then DS_kSpellsTable2 = {} end + if DS_kSpellsTable3 == nil then DS_kSpellsTable3 = {} end + if DS_ktblSpellNames == nil then DS_ktblSpellNames = {} end + if DS_kSpellsRank == nil then DS_kSpellsRank = {} end + if DS_ktblSpellCount == nil then DS_ktblSpellCount = {} end + + DS_kSpellsTable[DS_pName] = {} + DS_kSpellsTable2[DS_pName] = {} + DS_kSpellsTable3[DS_pName] = {} + DS_ktblSpellNames[DS_pName] = {} + DS_kSpellsRank[DS_pName] = {} + DS_ktblSpellCount[DS_pName] = 0 + + -- all spells not pet + if DS_aSpellsTable == nil then DS_aSpellsTable = {} end + if DS_aSpellsTable2 == nil then DS_aSpellsTable2 = {} end + if DS_atblSpellNames == nil then DS_atblSpellNames = {} end + if DS_aSpellsRank == nil then DS_aSpellsRank = {} end + if DS_atblSpellCount == nil then DS_atblSpellCount = {} end + + DS_aSpellsTable[DS_pName] = {} + DS_aSpellsTable2[DS_pName] = {} + DS_atblSpellNames[DS_pName] = {} + DS_aSpellsRank[DS_pName] = {} + DS_atblSpellCount[DS_pName] = 0 +end + +-- RegisterEvents +local DS_Eventframe = CreateFrame("FRAME") +DS_Eventframe:RegisterEvent("ADDON_LOADED") +DS_Eventframe:RegisterEvent("PLAYER_LOGIN") + +local function DS_OnEvent(self, event, arg1, ...) + + if event == "ADDON_LOADED" and arg1 == addon then + myprint("Addon_Loaded") + DS_Loaded = true + self:UnregisterEvent("ADDON_LOADED") + end + + if event == "PLAYER_LOGIN" and DS_Loaded then + myprint("Player_Loaded") + myprint("Current Player :"..DS_pName) + myprint("Current Class :"..DS_pClass) + DS_GetSpellBook() + DS_Eventframe:UnregisterEvent("PLAYER_LOGIN") + end +end + +DS_Eventframe:SetScript("OnEvent", DS_OnEvent) + +-- Parse player's spellbook and build a list of available spells +function DS_GetSpellBook() + + Init_DS_Tables() + + -- known spells for character + + local i = 0 + local iIndex = 0 + local iSpellId = 0 + local old_iSpellId = 0 + local txt_iSpellId = "" + + for i = 1, GetNumSpellTabs() do + local _, _, offset, numSlots = GetSpellTabInfo(i) + + for iIndex = offset, offset+numSlots do + local slotType, iSpellId = GetSpellBookItemInfo(iIndex, BOOKTYPE_SPELL) + + if slotType == "SPELL" then + local slotName = GetSpellBookItemName(iIndex, "spell") + local spellName = GetSpellInfo(slotName) + + if (spellName) then + txt_iSpellId = DS_PadiSpellId(tostring(iSpellId)) + -- make sure iSpellId has not been seen + + if not DS_kSpellsRank[DS_pName][iSpellId] then + DS_kSpellsRank[DS_pName][iSpellId] = 0 + DS_ktblSpellNames[DS_pName][spellName] = spellName + + if old_iSpellId ~= iSpellId then + old_iSpellId = iSpellId + DS_ktblSpellCount[DS_pName] = DS_ktblSpellCount[DS_pName] + 1 + DS_kSpellsTable2[DS_pName][DS_ktblSpellCount[DS_pName]] = DS_pClass..", known, "..spellName..", "..txt_iSpellId + DS_kSpellsTable[DS_pName][DS_ktblSpellCount[DS_pName]] = { DS_pClass, "known", spellName, txt_iSpellId, 0 } + end + end + end + end + end -- for + end -- for + + -- all non pet spells for character + + local i = 0 + local iIndex = 0 + local iSpellId = 0 + local old_iSpellId = 0 + local txt_iSpellId = "" + + for i = 1, GetNumSpellTabs() do + local _, _, offset, numSlots = GetSpellTabInfo(i) + for iIndex = offset, offset+numSlots do + local slotType, iSpellId = GetSpellBookItemInfo(iIndex, BOOKTYPE_SPELL) + + if slotType == "SPELL" or slotType == "FUTURESPELL" then + local slotName = GetSpellBookItemName(iIndex, "spell") + local spellName = GetSpellInfo(slotName) + + if (spellName) then + txt_iSpellId = DS_PadiSpellId(tostring(iSpellId)) + -- make sure iSpellId has not been seen + + if not DS_aSpellsRank[DS_pName][iSpellId] then + DS_aSpellsRank[DS_pName][iSpellId] = 0 + DS_atblSpellNames[DS_pName][spellName] = spellName + + if old_iSpellId ~= iSpellId then + old_iSpellId = iSpellId + DS_atblSpellCount[DS_pName] = DS_atblSpellCount[DS_pName] + 1 + DS_aSpellsTable2[DS_pName][DS_atblSpellCount[DS_pName]] = DS_pClass..", all, "..spellName..", "..txt_iSpellId + DS_aSpellsTable[DS_pName][DS_atblSpellCount[DS_pName]] = { DS_pClass, "all", spellName, txt_iSpellId, 0 } + end + end + end + end + end -- for + end -- for + + table.sort({DS_aSpellsTable[DS_pName]}) + table.sort(DS_aSpellsTable2[DS_pName]) + + table.sort({DS_kSpellsTable[DS_pName]}) + table.sort(DS_kSpellsTable2[DS_pName]) + + local spellRank = 0 + local findinstr = "" + local findinstr2 = "" + + + + -- known entries + for spellName, _ in pairs(DS_ktblSpellNames[DS_pName]) do + spellRank = 0 + for loop = 1, DS_ktblSpellCount[DS_pName] do + + findinstr = DS_kSpellsTable2[DS_pName][loop] + if string.match(findinstr, spellName) then + spellRank = spellRank + 1 + DS_kSpellsTable2[DS_pName][loop] = findinstr..", Rank-"..spellRank + + findinstr2 = DS_kSpellsTable2[DS_pName][loop] + for loop2 = 1, DS_ktblSpellCount[DS_pName] do + + txt_iSpellId = DS_kSpellsTable[DS_pName][loop2][4] + if string.match(findinstr2,txt_iSpellId) then + DS_kSpellsTable[DS_pName][loop2][5] = spellRank + DS_kSpellsRank[DS_pName][tonumber(txt_iSpellId)] = spellRank + end + end + end + end + end + + -- build table3 + for loop = 1, DS_atblSpellCount[DS_pName] do + spellName = DS_kSpellsTable[DS_pName][loop][3] + iSpellId = tonumber(DS_kSpellsTable[DS_pName][loop][4]) + if DS_kSpellsTable3[DS_pName][spellName] == nil then + DS_kSpellsTable3[DS_pName][spellName] = {} + end + table.insert(DS_kSpellsTable3[DS_pName][spellName], iSpellId) + end + + -- test getting spellid for a rank + -- spellName = "Healing Touch" + -- r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14 = unpack(DS_kSpellsTable3[DS_pName][spellName]) + -- myprint("Spell is: "..spellName..", Max Ranks for this spell is: "..#DS_kSpellsTable3[DS_pName][spellName]..", Rank 10 spellId is: "..r10) + + + -- all entries + for spellName, _ in pairs(DS_atblSpellNames[DS_pName]) do + spellRank = 0 + for loop = 1, DS_atblSpellCount[DS_pName] do + findinstr = DS_aSpellsTable2[DS_pName][loop] + + if string.match(findinstr, spellName) then + spellRank = spellRank + 1 + DS_aSpellsTable2[DS_pName][loop] = findinstr..", Rank-"..spellRank + findinstr2 = DS_aSpellsTable2[DS_pName][loop] + + for loop2 = 1, DS_atblSpellCount[DS_pName] do + txt_iSpellId = DS_aSpellsTable[DS_pName][loop2][4] + + if string.match(findinstr2,txt_iSpellId) then + DS_aSpellsTable[DS_pName][loop2][5] = spellRank + DS_aSpellsRank[DS_pName][tonumber(txt_iSpellId)] = spellRank + end + end + end + end + end + + + +end diff --git a/EventManager.lua b/EventManager.lua index 76972a5..c22a6bb 100644 --- a/EventManager.lua +++ b/EventManager.lua @@ -228,6 +228,7 @@ function Full:InitialOnEvent(Event, Arg1) self.AddonLoaded = true; --Before setting up is complete we also need to have spell, and macro data available elseif (Event == "PLAYER_ENTERING_WORLD") then + Util.CacheSpellBookRanks() -- TBC Fix 2021/06/17 Util.CacheCompanions(); Util.CacheSpellIndexes(); Util.CachePetSpellIndexes(); diff --git a/Util.lua b/Util.lua index 1067c3b..c6b6be9 100644 --- a/Util.lua +++ b/Util.lua @@ -1746,8 +1746,8 @@ function Util.CacheSpellIndexes() for i = total, 1, -1 do ItemType, Id = GetSpellBookItemInfo(i, BOOKTYPE_SPELL); - --local Name, Rank, Icon, PowerCost, IsFunnel, PowerType = GetSpellInfo(i, BOOKTYPE_SPELL); - local Name, Rank, Icon, PowerCost, IsFunnel, PowerType = GetSpellInfo(Id); + -- local Name, Rank, Icon, castTime, minRange, maxRange, spellId = GetSpellInfo(i, BOOKTYPE_SPELL); + local Name, Rank, Icon, castTime, minRange, maxRange, spellId = Util.GetSpellInfo(Id); -- TBC Fix 2021/06/18 local NameRank = Util.GetFullSpellName(Name, Rank); if (ItemType == "SPELL") then NewSI[NameRank] = i; @@ -2397,7 +2397,9 @@ function Util.GetButtonActionInfo2(ButtonName) --]] if (Button.Mode == "spell") then - local Rank = select(2, GetSpellInfo(Button.SpellId)); + -- local Rank = select(2, GetSpellInfo(Button.SpellId)); + local Rank = select(2, Util.GetSpellInfo(Button.SpellId)); -- TBC Fix 2021/06/18 + return "spell", Button.SpellName, Rank, Button.SpellId, Util.LookupSpellIndex(Button.SpellNameRank), Button.SpellBook; elseif (Button.Mode == "item") then return "item", Button.ItemId, Button.ItemName; @@ -2558,3 +2560,221 @@ function Util.LookupEquipmentSetIndex(EquipmentSetID) return nil; end + +-- TBC Fix new functions for ranks 06/17/2021 +function Util.InitCacheSpellBookRanksVars() + BF_PlayerName = UnitName("player") + BF_ClassName = UnitClass("player") + + -- table of spellnames, spellIds and spellranks + BF_kwnSpellsTable = {} + BF_kwnSpellsTable[BF_PlayerName] = {} + + -- used to build spellranks using string.find, sorted by spellname, spellid + BF_kwnSpellsTableVis = {} + BF_kwnSpellsTableVis[BF_PlayerName] = {} + + -- for looped, each time spellname found, rank is bumped up + BF_kwntblSpellNames = {} + BF_kwntblSpellNames[BF_PlayerName] = {} + + -- stores rank for each spellId found + BF_kwnSpellsRank = {} + BF_kwnSpellsRank[BF_PlayerName] = {} + + -- stores spellId for max rank for spellname + BF_kwnSpellsTableR = {} + BF_kwnSpellsTableR[BF_PlayerName] = {} + + -- total known spells found + BF_kwntblSpellCount = {} + BF_kwntblSpellCount[BF_PlayerName] = 0 +end + +-- spellId converted to text and padded for sorting +function Util.PadiSpellId(t) + if strlen(t) == 2 then + tnum = "0000"..t + return tnum + elseif strlen(t) == 3 then + tnum = "000"..t + return tnum + elseif strlen(t) == 4 then + tnum = "00"..t + return tnum + elseif strlen(t) == 5 then + tnum = "0"..t + return tnum + end + return t +end + +-- Parse player's spellbook and build a list of available spells +function Util.CacheSpellBookRanks() + + Util.InitCacheSpellBookRanksVars() -- reset known spells for character + + local i = 0 + local iIndex = 0 + local iSpellId = 0 + local old_iSpellId = 0 + local txt_iSpellId = "" + + for i = 1, GetNumSpellTabs() do + local _, _, offset, numSlots = GetSpellTabInfo(i) + + for iIndex = offset, offset+numSlots do + local slotType, iSpellId = GetSpellBookItemInfo(iIndex, BOOKTYPE_SPELL) + + if slotType == "SPELL" then + local slotName = GetSpellBookItemName(iIndex, "spell") + local spellName = GetSpellInfo(slotName) + + if (spellName) then + txt_iSpellId = Util.PadiSpellId(tostring(iSpellId)) + -- make sure iSpellId has not been seen + + if not BF_kwnSpellsRank[BF_PlayerName][iSpellId] then + BF_kwnSpellsRank[BF_PlayerName][iSpellId] = 0 + BF_kwntblSpellNames[BF_PlayerName][spellName] = spellName + + if old_iSpellId ~= iSpellId then + old_iSpellId = iSpellId + BF_kwntblSpellCount[BF_PlayerName] = BF_kwntblSpellCount[BF_PlayerName] + 1 + BF_kwnSpellsTable[BF_PlayerName][BF_kwntblSpellCount[BF_PlayerName]] = { BF_ClassName, "known", spellName, txt_iSpellId, 0 } + BF_kwnSpellsTableVis[BF_PlayerName][BF_kwntblSpellCount[BF_PlayerName]] = BF_ClassName..", known, "..spellName..", "..txt_iSpellId + end + end + end + end + end -- for + end -- for + + table.sort({BF_kwnSpellsTable[BF_PlayerName]}) + table.sort(BF_kwnSpellsTableVis[BF_PlayerName]) + + local spellRank = 0 + local tstr = "" + + -- known entries, spellranks for each spellId + for spellName, _ in pairs(BF_kwntblSpellNames[BF_PlayerName]) do + spellRank = 0 + for loop = 1, BF_kwntblSpellCount[BF_PlayerName] do + tstr = BF_kwnSpellsTableVis[BF_PlayerName][loop] + + if string.match(tstr, spellName) then + spellRank = spellRank + 1 + BF_kwnSpellsTableVis[BF_PlayerName][loop] = tstr..", Rank-"..spellRank + tstr2 = BF_kwnSpellsTableVis[BF_PlayerName][loop] + + for loop2 = 1, BF_kwntblSpellCount[BF_PlayerName] do + txt_iSpellId = BF_kwnSpellsTable[BF_PlayerName][loop2][4] + + if string.match(tstr2,txt_iSpellId) then + BF_kwnSpellsTable[BF_PlayerName][loop2][5] = spellRank + BF_kwnSpellsRank[BF_PlayerName][tonumber(txt_iSpellId)] = spellRank + end + end + end + end + end + + -- build spell maxrank table + for loop = 1, BF_kwntblSpellCount[BF_PlayerName] do + spellName = BF_kwnSpellsTable[BF_PlayerName][loop][3] + iSpellId = tonumber(BF_kwnSpellsTable[BF_PlayerName][loop][4]) + + if BF_kwnSpellsTableR[BF_PlayerName][spellName] == nil then + BF_kwnSpellsTableR[BF_PlayerName][spellName] = {} + end + table.insert(BF_kwnSpellsTableR[BF_PlayerName][spellName], iSpellId) + end +end + +--[[ example to find max rank for spellId + if BF_kwnSpellsTableR[BF_PlayerName][spellName] ~= nil then + maxrank = #BF_kwnSpellsTableR[BF_PlayerName][spellName] + findSpellId = BF_kwnSpellsTableR[BF_PlayerName][spellName][maxrank] + return + end +]] + + +-- return highest rank for spellname +function Util.GetMaxSpellRank(spellname) + -- print("Function Util.GetMaxSpellRank(spellname) :"..spellname) + local Rank = 1 + if BF_kwnSpellsRank[BF_PlayerName][spellname] ~= nil then + Rank = #BF_kwnSpellsRank[BF_PlayerName][spellname] + -- print("Function Util.GetMaxSpellRank(spellname) :"..spellname..", Max Rank found :"..Rank) + return Rank + end + -- print("Function Util.GetMaxSpellRank(spellname) :"..spellname..", Max Rank not found") + return Rank +end + + +-- return rank for spellId +function Util.GetSpellRank(Id) + -- print("Function Util.GetSpellRank(Id) :"..Id) + local Rank = 1 + if BF_kwnSpellsRank[BF_PlayerName][Id] ~= nil then + Rank = BF_kwnSpellsRank[BF_PlayerName][Id] + -- print("Function Util.GetSpellRank(Id) :"..Id..", Rank found :"..Rank) + return Rank + end + -- print("Function Util.GetSpellRank(Id) :"..Id..", Rank not found") + return Rank +end + +-- our wrapper for GetSpellInfo() 06/18/2021 +function Util.GetSpellInfo(sName, spellId_or_Rank) + local rank = 1 + + -- Util.GetSpellInfo("Thorns",3) -- example: return info for spell thorns, rank 3 spellId + if (type(sName) ~= "number" and type(spellId_or_Rank) == "number") then -- spellname and looking for spellid of rank + sRank = spellId_or_Rank + rank = sRank + if BF_kwnSpellsTableR[BF_PlayerName][sName] ~= nil then + if BF_kwnSpellsTableR[BF_PlayerName][sName][sRank] ~= nil then + spellId = BF_kwnSpellsTableR[BF_PlayerName][sName][sRank] + local name, _, icon, castTime, minRange, maxRange, spellId = GetSpellInfo(spellId); + return name,rank,icon,castTime,minRange,maxRange,spellId + end + end + + -- rank not found in BF_kwnSpellsTableR, this should not happen + rank = 0 + local name, _, icon, castTime, minRange, maxRange, spellId = GetSpellInfo(sName); + return name,rank,icon,castTime,minRange,maxRange,spellId + + -- Util.GetSpellInfo("Thorns") -- example: return info for spellId for highest rank known for Thorns + elseif type(sName) ~= "number" then -- spellname only, return spellId for max rank + + if BF_kwnSpellsTableR[BF_PlayerName][sName] ~= nil then + maxrank = #BF_kwnSpellsTableR[BF_PlayerName][sName] + Id = BF_kwnSpellsTableR[BF_PlayerName][sName][maxrank] + local name, _, icon, castTime, minRange, maxRange, spellId = GetSpellInfo(Id); + return name,maxrank,icon,castTime,minRange,maxRange,Id + end + -- rank not found in BF_kwnSpellsTableR, this should not happen + rank = 0 + local name, _, icon, castTime, minRange, maxRange, spellId = GetSpellInfo(sName); + return name,rank,icon,castTime,minRange,maxRange,spellId + + + -- Util.GetSpellInfo(9910) -- example: return info for spellId + elseif type(sName) == "number" then -- spellId passed, not spell name, don't bother with sRank here + Id = sName + local name, _, icon, castTime, minRange, maxRange, spellId = GetSpellInfo(Id); + rank = Util.GetSpellRank(Id) + if spellId ~= Id then + print("Error in Util.GetSpellInfo, spellid mismatch "..spellId.." should match "..Id) + end + return name,rank,icon,castTime,minRange,maxRange,Id + end + + print("Error in Util.GetSpellInfo, params match didn't happen") + local name, _, icon, castTime, minRange, maxRange, spellId = GetSpellInfo(sName); + return name, 0 +end \ No newline at end of file