WoWInterface SVN LibSpellName2SID

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 151 to Rev 152
    Reverse comparison

Rev 151 → Rev 152

tags/LibSpellName2SID-1.1.03/test1.lua New file
0,0 → 1,99
---------------------------
-- LibSpellName2SID - test1
-- Test some base spells
---------------------------
 
local AddonName, AddonEnv = ...;
local testsSharedName = AddonName.."-Tests";
 
local LIBSN2SID = AddonEnv.LIBSN2SID or LibStub("LibSpellName2SID-1.1"):NewInstance(testsSharedName);
local SID = LIBSN2SID.clients[testsSharedName].SID;
local LSN = LIBSN2SID.clients[testsSharedName].LSN;
-- local SID = LIBSN2SID.SID;
-- local LSN = LIBSN2SID.LSN;
 
local Frame = CreateFrame("Frame");
Frame:RegisterEvent("PLAYER_LOGIN"); -- Not enough data from game til this event fires.
-- Frame:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED"); -- This talent and/or the one in the line bellow
-- Frame:RegisterEvent("PLAYER_TALENT_UPDATE"); -- should fire when the player switches spec.
-- TESTED: Both of these fire Twice on Changing
-- spec. On Login but "ACTIVE_..." fires Once,
-- but "PLAYER_TALENT_..." fires Twice.
-- Frame:RegisterEvent("PLAYER_ENTERING_WORLD");
 
Frame:SetScript("OnEvent", function()
C_Timer.After(3, function()
print(testsSharedName.. ": Starting test1 - some base spells.");
if SID and LSN then
local startTime = GetTime();
print(testsSharedName.. tostring(": SID and LSN found."));
local endTime = GetTime();
print("print time with tostring(...) = ".. (endTime - startTime).. "ns.");
 
startTime = GetTime();
print(testsSharedName.. ": SID[\"Auto Attack\"] = ".. tostring(SID["Auto Attack"])); --
endTime = GetTime();
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
 
startTime = GetTime();
print(testsSharedName.. ": LSN[\"Auto Attack\"] = ".. tostring(LSN["Auto Attack"])); --
endTime = GetTime();
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
 
startTime = GetTime();
print(testsSharedName.. ": SID[\"Made It Up\"] = ".. tostring(SID["Made It Up"])); --
endTime = GetTime();
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
 
startTime = GetTime();
print(testsSharedName.. ": LSN[\"Made It Up\"] = ".. tostring(LSN["Made It Up"])); --
endTime = GetTime();
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
 
startTime = GetTime();
print(testsSharedName.. ": SID[210873] = ".. tostring(SID[210873])); --
endTime = GetTime();
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
 
startTime = GetTime();
print(testsSharedName.. ": LSN[210873] = ".. tostring(LSN[210873])); --
endTime = GetTime();
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
 
startTime = GetTime();
print(testsSharedName.. ": SID[6603] = ".. tostring(SID[6603]));
endTime = GetTime();
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
 
startTime = GetTime();
print(testsSharedName.. ": LSN[6603] = ".. tostring(LSN[6603]));
endTime = GetTime();
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
 
startTime = GetTime();
print(testsSharedName.. ": SID[\"Lightning Bolt\"] = ".. tostring(SID["Lightning Bolt"])); --
endTime = GetTime();
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
 
startTime = GetTime();
print(testsSharedName.. ": LSN[\"Lightning Bolt\"] = ".. tostring(LSN["Lightning Bolt"])); --
endTime = GetTime();
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
 
startTime = GetTime();
print(testsSharedName.. ": SID[\"Taunt\"] = ".. tostring(SID["Taunt"])); --
endTime = GetTime();
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
 
startTime = GetTime();
print(testsSharedName.. ": LSN[\"Taunt\"] = ".. tostring(LSN["Taunt"])); --
endTime = GetTime();
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
else
print(testsSharedName.. ": SID and/or LSN not found.");
end
end);
end);
 
-- Export to addon's environment:
AddonEnv.LIBSN2SID = LIBSN2SID;
\ No newline at end of file
tags/LibSpellName2SID-1.1.03/test2.lua New file
0,0 → 1,68
------------------------------------------
-- LibSpellName2SID - test2
-- Test "Flyouts" and "Pets" and "Racials"
------------------------------------------
 
local AddonName, AddonEnv = ...;
local testsSharedName = AddonName.."-Tests";
 
local LIBSN2SID = AddonEnv.LIBSN2SID or LibStub("LibSpellName2SID-1.1"):NewInstance(testsSharedName);
local SID = LIBSN2SID.clients[testsSharedName].SID;
local LSN = LIBSN2SID.clients[testsSharedName].LSN;
-- local SID = LIBSN2SID.SID;
-- local LSN = LIBSN2SID.LSN;
 
local Frame = CreateFrame("Frame");
Frame:RegisterEvent("PLAYER_LOGIN"); -- Not enough data from game til this event fires.
-- Frame:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED"); -- This talent and/or the one in the line bellow
-- Frame:RegisterEvent("PLAYER_TALENT_UPDATE"); -- should fire when the player switches spec.
-- TESTED: Both of these fire Twice on Changing
-- spec. On Login but "ACTIVE_..." fires Once,
-- but "PLAYER_TALENT_..." fires Twice.
-- Frame:RegisterEvent("PLAYER_ENTERING_WORLD");
 
Frame:SetScript("OnEvent", function()
C_Timer.After(4, function()
print(testsSharedName.. ": Starting test2 - \"Flyouts\", \"Pets\" and \"Racials\".");
if SID and LSN then
startTime = GetTime();
print(testsSharedName.. ": SID[\"Hex\"] = ".. tostring(SID["Hex"])); --
endTime = GetTime();
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
startTime = GetTime();
print(testsSharedName.. ": SID[\"Hex(Spider)\"] = ".. tostring(SID["Hex(Spider)"])); --
endTime = GetTime();
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
startTime = GetTime();
print(testsSharedName.. ": SID[\"Web Spray\"] = ".. tostring(SID["Web Spray"])); --
endTime = GetTime();
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
startTime = GetTime();
print(testsSharedName.. ": SID[\"Gift of the Naaru\"] = ".. tostring(SID["Gift of the Naaru"])); --
endTime = GetTime();
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
 
startTime = GetTime() *1000000;
print(testsSharedName.. ": LSN[\"Hex\"] = ".. tostring(LSN["Hex"])); --
endTime = GetTime() *1000000;
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
startTime = GetTime() *1000000;
print(testsSharedName.. ": LSN[\"Hex(Spider)\"] = ".. tostring(LSN["Hex(Spider)"])); --
endTime = GetTime() *1000000;
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
startTime = GetTime() *1000000;
print(testsSharedName.. ": LSN[\"Web Spray\"] = ".. tostring(LSN["Web Spray"])); --
endTime = GetTime() *1000000;
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
startTime = GetTime();
print(testsSharedName.. ": LSN[\"Gift of the Naaru\"] = ".. tostring(LSN["Gift of the Naaru"])); --
endTime = GetTime();
print(testsSharedName.. "... in ".. endTime - startTime.. "ns.");
else
print(testsSharedName.. ": SID and/or LSN not found.");
end
end);
end);
 
-- Export to addon's environment:
AddonEnv.LIBSN2SID = LIBSN2SID;
\ No newline at end of file
tags/LibSpellName2SID-1.1.03/test3.lua New file
0,0 → 1,57
--------------------------------------------------------
-- LibSpellName2SID - test3
-- Test Alliance/Horde spells (same name, different IDs)
--------------------------------------------------------
 
local AddonName, AddonEnv = ...;
local testsSharedName = AddonName.."-Tests";
 
local LIBSN2SID = AddonEnv.LIBSN2SID or LibStub("LibSpellName2SID-1.1"):NewInstance(testsSharedName);
local SID = LIBSN2SID.clients[testsSharedName].SID;
local LSN = LIBSN2SID.clients[testsSharedName].LSN;
-- local SID = LIBSN2SID.SID;
-- local LSN = LIBSN2SID.LSN;
 
local Frame = CreateFrame("Frame");
Frame:RegisterEvent("PLAYER_LOGIN"); -- Not enough data from game til this event fires.
-- Frame:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED"); -- This talent and/or the one in the line bellow
-- Frame:RegisterEvent("PLAYER_TALENT_UPDATE"); -- should fire when the player switches spec.
-- TESTED: Both of these fire Twice on Changing
-- spec. On Login but "ACTIVE_..." fires Once,
-- but "PLAYER_TALENT_..." fires Twice.
-- Frame:RegisterEvent("PLAYER_ENTERING_WORLD");
 
Frame:SetScript("OnEvent", function()
C_Timer.After(5, function()
print(testsSharedName.. ": Starting test3 - Alliance/Horde spells (same name, different IDs).");
if SID and LSN then
print(testsSharedName.. ": LSN[\"Portal: Tol Barad(Alliance)\"] = ".. tostring(LSN["Portal: Tol Barad(Alliance)"])); --
print(testsSharedName.. ": LSN[\"Portal: Tol Barad(Horde)\"] = ".. tostring(LSN["Portal: Tol Barad(Horde)"])); --
print(testsSharedName.. ": LSN[\"Portal: Tol Barad\"] = ".. tostring(LSN["Portal: Tol Barad"])); --
print(testsSharedName.. ": SID[\"Portal: Tol Barad(Alliance)\"] = ".. tostring(SID["Portal: Tol Barad(Alliance)"])); --
print(testsSharedName.. ": SID[\"Portal: Tol Barad(Horde)\"] = ".. tostring(SID["Portal: Tol Barad(Horde)"])); --
print(testsSharedName.. ": SID[\"Portal: Tol Barad\"] = ".. tostring(SID["Portal: Tol Barad"])); --
 
print(testsSharedName.. ": Will now set faction to Alliance.");
LIBSN2SID.SetFaction("Alliance", testsSharedName);
print(testsSharedName.. ": LSN[\"Portal: Tol Barad\"] = ".. tostring(LSN["Portal: Tol Barad"]));
print(testsSharedName.. ": SID[\"Portal: Tol Barad\"] = ".. tostring(SID["Portal: Tol Barad"]));
 
print(testsSharedName.. ": Will now set faction to Horde.");
-- LIBSN2SID.SetFaction("Horde", testsSharedName);
LIBSN2SID.SetFaction("Horde", testsSharedName);
print(testsSharedName.. ": LSN[\"Portal: Tol Barad\"] = ".. tostring(LSN["Portal: Tol Barad"]));
print(testsSharedName.. ": SID[\"Portal: Tol Barad\"] = ".. tostring(SID["Portal: Tol Barad"]));
 
print(testsSharedName.. ": Will now set faction back to player\'s.");
LIBSN2SID.SetFaction((UnitFactionGroup("player")), testsSharedName);
print(testsSharedName.. ": LSN[\"Portal: Tol Barad\"] = ".. tostring(LSN["Portal: Tol Barad"]));
print(testsSharedName.. ": SID[\"Portal: Tol Barad\"] = ".. tostring(SID["Portal: Tol Barad"]));
else
print(testsSharedName.. ": SID and/or LSN not found.");
end
end);
end);
 
-- Export to addon's environment:
AddonEnv.LIBSN2SID = LIBSN2SID;
\ No newline at end of file
tags/LibSpellName2SID-1.1.03/test4.lua New file
0,0 → 1,105
--------------------------------------------------------
-- LibSpellName2SID - test4
-- Test Removal and re-Registration of library instances
--------------------------------------------------------
 
local AddonName, AddonEnv = ...;
local testsSharedName = AddonName.."-Tests";
 
local LIBSN2SID = AddonEnv.LIBSN2SID or LibStub("LibSpellName2SID-1.1"):NewInstance(testsSharedName);
local SID = LIBSN2SID.clients[testsSharedName].SID;
local LSN = LIBSN2SID.clients[testsSharedName].LSN;
-- local SID = LIBSN2SID.SID;
-- local LSN = LIBSN2SID.LSN;
 
local Frame = CreateFrame("Frame");
Frame:RegisterEvent("PLAYER_LOGIN"); -- Not enough data from game til this event fires.
-- Frame:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED"); -- This talent and/or the one in the line bellow
-- Frame:RegisterEvent("PLAYER_TALENT_UPDATE"); -- should fire when the player switches spec.
-- TESTED: Both of these fire Twice on Changing
-- spec. But On Login "ACTIVE_..." fires Once,
-- whereas "PLAYER_TALENT_..." fires Twice.
-- Frame:RegisterEvent("PLAYER_ENTERING_WORLD");
 
Frame:SetScript("OnEvent", function()
C_Timer.After(5, function()
print(testsSharedName.. ": Starting test4 - Removal and re-Registration of library instances.");
if SID and LSN then
print(testsSharedName.. ": LSN[\"Portal: Shattrath(Alliance)\"] = ".. tostring(LSN["Portal: Shattrath(Alliance)"])); --
print(testsSharedName.. ": LSN[\"Portal: Shattrath(Horde)\"] = ".. tostring(LSN["Portal: Shattrath(Horde)"])); --
print(testsSharedName.. ": LSN[\"Portal: Shattrath\"] = ".. tostring(LSN["Portal: Shattrath"])); --
print(testsSharedName.. ": SID[\"Portal: Shattrath(Alliance)\"] = ".. tostring(SID["Portal: Shattrath(Alliance)"])); --
print(testsSharedName.. ": SID[\"Portal: Shattrath(Horde)\"] = ".. tostring(SID["Portal: Shattrath(Horde)"])); --
print(testsSharedName.. ": SID[\"Portal: Shattrath\"] = ".. tostring(SID["Portal: Shattrath"])); --
 
print(testsSharedName.. ": type(LIBSN2SID) = ".. type(LIBSN2SID));
print(testsSharedName.. ": type(LIBSN2SID.clients) = ".. type(LIBSN2SID.clients));
print(testsSharedName.. ": type(LIBSN2SID.clients[".. testsSharedName.. "]) = ".. type(LIBSN2SID.clients[testsSharedName]));
if type(LIBSN2SID) == "table" then
-- local tableKey = next(LIBSN2SID, nil);
-- local tableValue;
-- while tableKey do
-- tableValue = tostring(LIBSN2SID[tableKey]);
-- print(testsSharedName.. ": Key = ".. tableKey.. " Value = ".. tableValue);
-- tableKey = next(LIBSN2SID, tableKey);
-- end
-- tableKey, tableValue = nil, nil;
-- print(testsSharedName.. ": No more values to print.");
if LIBSN2SID.clients[testsSharedName] then
local tableKey = next(LIBSN2SID.clients[testsSharedName], nil);
local tableValue;
while tableKey do
tableValue = tostring(LIBSN2SID.clients[testsSharedName][tableKey]);
print(testsSharedName.. ": Key = ".. tableKey.. " Value = ".. tableValue);
tableKey = next(LIBSN2SID.clients[testsSharedName], tableKey);
end
tableKey, tableValue = nil, nil;
print(testsSharedName.. ": No more values to print.");
end
end
print(testsSharedName.. ": Will now remove this instance of LibSpellName2SID-1.1 !");
LIBSN2SID:RemoveInstance(testsSharedName);
print(testsSharedName.. ": type(LIBSN2SID) = ".. type(LIBSN2SID));
print(testsSharedName.. ": type(LIBSN2SID.clients) = ".. type(LIBSN2SID.clients));
print(testsSharedName.. ": type(LIBSN2SID.clients[".. testsSharedName.. "]) = ".. type(LIBSN2SID.clients[testsSharedName]));
if type(LIBSN2SID) == "table" then
-- local tableKey = next(LIBSN2SID, nil);
-- local tableValue;
-- while tableKey do
-- tableValue = tostring(LIBSN2SID[tableKey]);
-- print(testsSharedName.. ": Key = ".. tableKey.. " Value = ".. tableValue);
-- tableKey = next(LIBSN2SID, tableKey);
-- end
-- tableKey, tableValue = nil, nil;
-- print(testsSharedName.. ": No more values to print.");
if LIBSN2SID.clients[testsSharedName] then
local tableKey = next(LIBSN2SID.clients[testsSharedName], nil);
local tableValue;
while tableKey do
tableValue = tostring(LIBSN2SID.clients[testsSharedName][tableKey]);
print(testsSharedName.. ": Key = ".. tableKey.. " Value = ".. tableValue);
tableKey = next(LIBSN2SID.clients[testsSharedName], tableKey);
end
tableKey, tableValue = nil, nil;
print(testsSharedName.. ": No more values to print.");
end
end
print(testsSharedName.. ": Will now register a new instance of LibSpellName2SID-1.1 as \"".. testsSharedName.. "\"!");
LIBSN2SID = LibStub("LibSpellName2SID-1.1"):NewInstance(testsSharedName);
 
print(testsSharedName.. ": SID[\"Auto Attack\"] = ".. tostring(SID["Auto Attack"]));
print(testsSharedName.. ": LSN[\"Auto Attack\"] = ".. tostring(LSN["Auto Attack"]));
print(testsSharedName.. ": SID[\"Made It Up\"] = ".. tostring(SID["Made It Up"]));
print(testsSharedName.. ": LSN[\"Made It Up\"] = ".. tostring(LSN["Made It Up"]));
print(testsSharedName.. ": SID[\"Hex(Spider)\"] = ".. tostring(SID["Hex(Spider)"]));
print(testsSharedName.. ": LSN[\"Hex(Spider)\"] = ".. tostring(LSN["Hex(Spider)"]));
print(testsSharedName.. ": LSN[\"Portal: Shattrath\"] = ".. tostring(LSN["Portal: Shattrath"]));
print(testsSharedName.. ": SID[\"Portal: Shattrath\"] = ".. tostring(SID["Portal: Shattrath"]));
else
print(testsSharedName.. ": SID and/or LSN not found.");
end
end);
end);
 
-- Export to addon's environment:
AddonEnv.LIBSN2SID = LIBSN2SID;
tags/LibSpellName2SID-1.1.03/LibStub/LibStub.toc New file
0,0 → 1,13
## Interface: 70000
## Title: Lib: LibStub
## Notes: Universal Library Stub
## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
## X-Website: http://www.wowace.com/addons/libstub/
## X-Category: Library
## X-License: Public Domain
## X-Curse-Packaged-Version: 1.0.2-70000
## X-Curse-Project-Name: LibStub
## X-Curse-Project-ID: libstub
## X-Curse-Repository-ID: wow/libstub/mainline
 
LibStub.lua
tags/LibSpellName2SID-1.1.03/LibStub/LibStub.lua New file
0,0 → 1,51
-- $Id: LibStub.lua 103 2014-10-16 03:02:50Z mikk $
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/addons/libstub/ for more info
-- LibStub is hereby placed in the Public Domain
-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
local LibStub = _G[LIBSTUB_MAJOR]
 
-- Check to see is this version of the stub is obsolete
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
LibStub = LibStub or {libs = {}, minors = {} }
_G[LIBSTUB_MAJOR] = LibStub
LibStub.minor = LIBSTUB_MINOR
 
-- LibStub:NewLibrary(major, minor)
-- major (string) - the major version of the library
-- minor (string or number ) - the minor version of the library
--
-- returns nil if a newer or same version of the lib is already present
-- returns empty library object or old library object if upgrade is needed
function LibStub:NewLibrary(major, minor)
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
 
local oldminor = self.minors[major]
if oldminor and oldminor >= minor then return nil end
self.minors[major], self.libs[major] = minor, self.libs[major] or {}
return self.libs[major], oldminor
end
 
-- LibStub:GetLibrary(major, [silent])
-- major (string) - the major version of the library
-- silent (boolean) - if true, library is optional, silently return nil if its not found
--
-- throws an error if the library can not be found (except silent is set)
-- returns the library object if found
function LibStub:GetLibrary(major, silent)
if not self.libs[major] and not silent then
error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
end
return self.libs[major], self.minors[major]
end
 
-- LibStub:IterateLibraries()
--
-- Returns an iterator for the currently registered libraries
function LibStub:IterateLibraries()
return pairs(self.libs)
end
 
setmetatable(LibStub, { __call = LibStub.GetLibrary })
end
tags/LibSpellName2SID-1.1.03/LibSpellName2SID-1.1/LibSpellName2SID-1.1.lua New file
0,0 → 1,3043
---------------------
-- LibspellName2SID (deprecated) / LibSpellName2SID
-- V.10000: 2009 originally by Twobits[1], as part of ReadySpells[2]
-- 2010 edited by benots4[3]
-- 2017 published as an addon of its own by aallkkaa[4]
-- V.10001 - 10103: 2017-2019 WoW 7.3.x to 8.x versions by aallkkaa [4]
--
-- [1] https://www.wowinterface.com/forums/member.php?userid=139157
-- https://www.curseforge.com/members/twobits
-- [2] https://www.curseforge.com/wow/addons/readyspells (Twobits' 3.x version:
-- 2009)
-- [3] https://www.wowinterface.com/forums/member.php?action=getinfo&userid=201937
-- [4] https://www.wowinterface.com/forums/member.php?u=335646
--------------------------------
-- -- -- API: -- -- --
----------------------
-- -- ENABLE IN YOUR ADDON -- --
-- local LibSpellName2SID = LibStub("LibSpellName2SID-1.1"):NewInstance(AddonName (STRING))
-- -- REMOVE FROM YOUR ADDON -- --
-- LibSpellName2SID:RemoveInstance(AddonName (STRING), DontErrorOnInexistentInstanceName (BOOLEAN))
-- -- USABLE METATABLES AND FUNCTIONS -- --
-- LibSpellName2SID.clients[testsSharedName].SID["EnglishSpellName"] -- Spell ID of English Spell
-- Name (STRING)
-- LibSpellName2SID.clients[testsSharedName].LSN["EnglishSpellName"] -- Localized Spell Name of
-- English Spell Name (STRING)
-- LibSpellName2SID.SetFaction(faction (STRING), AddonName (STRING)) -- Set the faction to look up
-- spells for (when applicable)
-- -- (OPTIONAL, BUT RECOMMENDED) LOCAL ALIAS -- --
-- local SID = LibSpellName2SID.clients[AddonName].SID -- Useage: SID["EnglishSpellName"]
-- local LSN = LibSpellName2SID.clients[AddonName].LSN -- Useage: LSN["EnglishSpellName"]
-- -- CURRENTLY UNAVAILABLE -- --
-- LibSpellName2SID:GetNumSpells() -- Get the number of spells in the database - TEMPORARILY OUT
---------------------
 
 
-- Initialization --
--------------------
 
-- Library's version values --
local LibSpellName2SID_MAJOR = "LibSpellName2SID-1.1";
local LibSpellName2SID_MINOR = 10103;
 
-- DataSource --
-- gameBuild = 29981
-- clientLocale = enUS
 
-- Register with LibStub --
assert(LibStub, LibSpellName2SID_MAJOR.. "-".. LibSpellName2SID_MINOR.." requires LibStub.");
local oldLibSN2SID, oldMinor = LibStub:NewLibrary(LibSpellName2SID_MAJOR, LibSpellName2SID_MINOR);
if oldLibSN2SID == nil then -- newer or same version of the lib is already present
return; -- Nothing needs to be done
else -- no old lib or upgrade is needed
if oldMinor and (oldMinor < LibSpellName2SID_MINOR) then -- old library object, upgrade needed
LibSN2SID = oldLibSN2SID;
if oldLibSN2SID.libFrame then -- Reuse old lib's frame if available
oldLibSN2SID.libFrame:UnregisterAllEvents();
LibSN2SID.libFrame = oldLibSN2SID.libFrame;
else
LibSN2SID.libFrame = CreateFrame("Frame");
end
else -- no old lib, return from LibStub:NewLibrary is an empty table
LibSN2SID = oldLibSN2SID;
LibSN2SID.libFrame = CreateFrame("Frame");
end
end
 
 
-- Set the library database contents --
---------------------------------------
 
LibSN2SID.minor = LibSpellName2SID_MINOR;
 
if LibSN2SID.DB then -- Clear old version's contents, if applicable
wipe(LibSN2SID.DB);
end
 
LibSN2SID.DB = {
["General"] = {
["Others"] = {
["Auto Attack"] = 6603,
["Auto Shot"] = 75,
["Cooking Fire"] = 818,
["Herbalism Skills"] = 193290,
["Honorable Medallion"] = 195710,
["Mining Skills"] = 2656,
["Revive Battle Pets"] = 125439,
["Shoot"] = 5019,
["Wartime Ability"] = 264739,
},
["Racials"] = {
["Draenei"] = {
["Gift of the Naaru"] = 59548,
},
["DarkIronDwarf"] = {
["Fireblood"] = 265221,
["Mole Machine"] = 265225,
},
["Worgen"] = {
["Running Wild"] = 87840,
["Darkflight"] = 68992,
["Two Forms"] = 68996,
},
["Pandaren"] = {
["Quaking Palm"] = 107079,
},
["Scourge"] = {
["Will of the Forsaken"] = 7744,
["Cannibalize"] = 20577,
},
["Orc"] = {
["Blood Fury"] = 20572,
},
["Gnome"] = {
["Escape Artist"] = 20589,
},
["Tauren"] = {
["War Stomp"] = 20549,
},
["Troll"] = {
["Berserking"] = 26297,
},
["BloodElf"] = {
["Arcane Torrent"] = 129597,
},
["VoidElf"] = {
["Spatial Rift"] = 256948,
},
["NightElf"] = {
["Shadowmeld"] = 58984,
},
["Dwarf"] = {
["Stoneform"] = 20594,
},
["Human"] = {
["Every Man for Himself"] = 59752,
},
["LightforgedDraenei"] = {
["Forge of Light"] = 259930,
["Light's Judgment"] = 255647,
},
["Goblin"] = {
["Rocket Barrage"] = 69041,
["Rocket Jump"] = 69070,
["Pack Hobgoblin"] = 69046,
},
["Nightborne"] = {
["Arcane Pulse"] = 260364,
["Cantrips"] = 255661,
},
["HighmountainTauren"] = {
["Bull Rush"] = 255654,
},
["KulTiran"] = {
["Haymaker"] = 287712,
},
["MagharOrc"] = {
["Ancestral Call"] = 274738,
},
["ZandalariTroll"] = {
["Embrace of the Loa"] = 292752,
["Regeneratin'"] = 291944,
["Pterrordax Swoop"] = 281954,
},
},
["ZoneAbilities"] = {
["Artillery Strike"] = 162075,
["Call to Arms"] = 161676,
["Champion's Honor"] = 164221,
["Combat Ally"] = 211390,
["Fel Heart Bond"] = 248011,
["Frostwolf War Wolf"] = 164222,
["Garrison Ability"] = 161691,
["Guardian Orb"] = 161767,
["Home Away from Home"] = 168487,
["Light's Judgment"] = 247427,
["Logging"] = 167895,
["Shroud of Arcane Echoes"] = 248779,
["Smuggling Run!"] = 170108,
["Summon Lightforged Warframe"] = 250436,
["Summon Mechashredder 5000"] = 164050,
["Telaari Siege Engine"] = 160240,
["Telaari Talbuk"] = 165803,
["Vindicaar Matrix Crystal"] = 251463,
},
["GuildPerks"] = {
["Mobile Banking"] = 83958,
},
},
["DEATHKNIGHT"] = {
["Frost_Talents"] = {
["Wraith Walk"] = 212552,
["Blinding Sleet"] = 207167,
["Frostscythe"] = 207230,
["Death Pact"] = 48743,
["Horn of Winter"] = 57330,
["Asphyxiate"] = 108194,
["Breath of Sindragosa"] = 152279,
["Frostwyrm's Fury"] = 279302,
["Glacial Advance"] = 194913,
},
["Unholy"] = {
["Anti-Magic Shell"] = 48707,
["Apocalypse"] = 275699,
["Army of the Dead"] = 42650,
["Chains of Ice"] = 45524,
["Control Undead"] = 111673,
["Corpse Exploder"] = 127344,
["Dark Command"] = 56222,
["Dark Transformation"] = 63560,
["Death Coil"] = 47541,
["Death Gate"] = 50977,
["Death Grip"] = 49576,
["Death Strike"] = 49998,
["Death and Decay"] = 43265,
["Death's Advance"] = 48265,
["Festering Strike"] = 85948,
["Icebound Fortitude"] = 48792,
["Mind Freeze"] = 47528,
["Outbreak"] = 77575,
["Path of Frost"] = 3714,
["Raise Ally"] = 61999,
["Raise Dead"] = 46584,
["Runeforging"] = 53428,
["Scourge Strike"] = 55090,
},
["Blood"] = {
["Anti-Magic Shell"] = 48707,
["Asphyxiate"] = 221562,
["Blood Boil"] = 50842,
["Control Undead"] = 111673,
["Corpse Exploder"] = 127344,
["Dancing Rune Weapon"] = 49028,
["Dark Command"] = 56222,
["Death Gate"] = 50977,
["Death Grip"] = 49576,
["Death Strike"] = 49998,
["Death and Decay"] = 43265,
["Death's Advance"] = 48265,
["Death's Caress"] = 195292,
["Gorefiend's Grasp"] = 108199,
["Heart Strike"] = 206930,
["Icebound Fortitude"] = 48792,
["Marrowrend"] = 195182,
["Mind Freeze"] = 47528,
["Path of Frost"] = 3714,
["Raise Ally"] = 61999,
["Runeforging"] = 53428,
["Vampiric Blood"] = 55233,
},
["Pets"] = {
["Ghoul"] = {
["Gnaw"] = 47481,
["Claw"] = 47468,
["Huddle"] = 47484,
["Leap"] = 47482,
},
},
["Frost"] = {
["Anti-Magic Shell"] = 48707,
["Chains of Ice"] = 45524,
["Control Undead"] = 111673,
["Corpse Exploder"] = 127344,
["Dark Command"] = 56222,
["Death Gate"] = 50977,
["Death Grip"] = 49576,
["Death Strike"] = 49998,
["Death's Advance"] = 48265,
["Empower Rune Weapon"] = 47568,
["Frost Strike"] = 49143,
["Howling Blast"] = 49184,
["Icebound Fortitude"] = 48792,
["Mind Freeze"] = 47528,
["Obliterate"] = 49020,
["Path of Frost"] = 3714,
["Pillar of Frost"] = 51271,
["Raise Ally"] = 61999,
["Remorseless Winter"] = 196770,
["Runeforging"] = 53428,
},
["Blood_Talents"] = {
["Tombstone"] = 219809,
["Wraith Walk"] = 212552,
["Rune Tap"] = 194679,
["Blooddrinker"] = 206931,
["Bonestorm"] = 194844,
["Rune Strike"] = 210764,
["Consumption"] = 274156,
["Mark of Blood"] = 206940,
},
["Unholy_PVPTalents"] = {
["Dark Simulacrum"] = 77606,
["Lichborne"] = 287081,
["Transfusion"] = 288977,
["Gladiator's Medallion"] = 208683,
["Necrotic Strike"] = 223829,
["Anti-Magic Zone"] = 51052,
["Reanimation"] = 210128,
["Raise Abomination"] = 288853,
},
["Unholy_Talents"] = {
["Summon Gargoyle"] = 49206,
["Wraith Walk"] = 212552,
["Clawing Shadows"] = 207311,
["Epidemic"] = 207317,
["Death Pact"] = 48743,
["Unholy Blight"] = 115989,
["Asphyxiate"] = 108194,
["Defile"] = 152280,
["Soul Reaper"] = 130736,
["Unholy Frenzy"] = 207289,
},
["Blood_PVPTalents"] = {
["Dark Simulacrum"] = 77606,
["Lichborne"] = 287081,
["Transfusion"] = 288977,
["Gladiator's Medallion"] = 208683,
["Necrotic Strike"] = 223829,
["Anti-Magic Zone"] = 51052,
["Reanimation"] = 210128,
["Raise Abomination"] = 288853,
},
["Frost_PVPTalents"] = {
["Dark Simulacrum"] = 77606,
["Lichborne"] = 287081,
["Transfusion"] = 288977,
["Gladiator's Medallion"] = 208683,
["Necrotic Strike"] = 223829,
["Anti-Magic Zone"] = 51052,
["Reanimation"] = 210128,
["Raise Abomination"] = 288853,
},
["METADATA"] = {
["Specs"] = {
["Unholy"] = 252,
["Frost"] = 251,
["Blood"] = 250,
},
},
},
["DEMONHUNTER"] = {
["Havoc_Talents"] = {
["Nemesis"] = 206491,
["Dark Slash"] = 258860,
["Netherwalk"] = 196555,
["Fel Eruption"] = 211881,
["Felblade"] = 232893,
["Fel Barrage"] = 258925,
["Immolation Aura"] = 258920,
},
["Vengeance_Talents"] = {
["Fracture"] = 263642,
["Sigil of Chains"] = 202138,
["Fel Devastation"] = 212084,
["Felblade"] = 232893,
["Soul Barrier"] = 263648,
["Spirit Bomb"] = 247454,
},
["Havoc"] = {
["Blur"] = 198589,
["Chaos Nova"] = 179057,
["Torment"] = 281854,
["Metamorphosis"] = 191427,
["Demon's Bite"] = 162243,
["Darkness"] = 196718,
["Eye Beam"] = 198013,
["Chaos Strike"] = 162794,
["Spectral Sight"] = 188501,
["Fel Rush"] = 195072,
["Disrupt"] = 183752,
["Consume Magic"] = 278326,
["Glide"] = 131347,
["Throw Glaive"] = 185123,
["Vengeful Retreat"] = 198793,
["Blade Dance"] = 188499,
["Imprison"] = 217832,
},
["Vengeance"] = {
["Soul Cleave"] = 162794,
["Torment"] = 198589,
["Fiery Brand"] = 179057,
["Metamorphosis"] = 191427,
["Shear"] = 203782,
["Imprison"] = 217832,
["Demon Spikes"] = 198793,
["Spectral Sight"] = 188501,
["Sigil of Misery"] = 207684,
["Disrupt"] = 183752,
["Consume Magic"] = 278326,
["Glide"] = 131347,
["Throw Glaive"] = 185123,
["Sigil of Flame"] = 188499,
["Infernal Strike"] = 195072,
["Sigil of Silence"] = 202137,
["Immolation Aura"] = 198013,
},
["Vengeance_PVPTalents"] = {
["Tormentor"] = 207029,
["Gladiator's Medallion"] = 208683,
["Illidan's Grasp"] = 205630,
["Demonic Trample"] = 205629,
["Reverse Magic"] = 205604,
},
["Havoc_PVPTalents"] = {
["Tormentor"] = 207029,
["Gladiator's Medallion"] = 208683,
["Illidan's Grasp"] = 205630,
["Demonic Trample"] = 205629,
["Reverse Magic"] = 205604,
},
["METADATA"] = {
["Specs"] = {
["Havoc"] = 577,
["Vengeance"] = 581,
},
},
},
["DRUID"] = {
["Restoration_PVPTalents"] = {
["Thorns"] = 236696,
["Overrun"] = 202246,
["Gladiator's Medallion"] = 208683,
["Faerie Swarm"] = 209749,
["Alpha Challenge"] = 207017,
["Demoralizing Roar"] = 201664,
["Cyclone"] = 209753,
},
["Feral_Talents"] = {
["Mass Entanglement"] = 102359,
["Brutal Slash"] = 202028,
["Savage Roar"] = 52610,
["Typhoon"] = 132469,
["Feral Frenzy"] = 274837,
["Tiger Dash"] = 252216,
["Wild Charge"] = 102401,
["Incarnation: King of the Jungle"] = 102543,
["Mighty Bash"] = 5211,
["Renewal"] = 108238,
["Primal Wrath"] = 285381,
},
["Feral"] = {
["Stampeding Roar"] = 106898,
["Skull Bash"] = 106839,
["Entangling Roots"] = 339,
["Mangle"] = 33917,
["Charm Woodland Creature"] = 127757,
["Hibernate"] = 2637,
["Shred"] = 5221,
["Tiger's Fury"] = 5217,
["Remove Corruption"] = 2782,
["Rebirth"] = 20484,
["Treant Form"] = 114282,
["Thrash"] = 106832,
["Travel Form"] = 783,
["Prowl"] = 5215,
["Regrowth"] = 8936,
["Ferocious Bite"] = 22568,
["Growl"] = 6795,
["Revive"] = 50769,
["Swipe"] = 213764,
["Rake"] = 1822,
["Rip"] = 1079,
["Cat Form"] = 768,
["Maim"] = 22570,
["Berserk"] = 106951,
["Dreamwalk"] = 193753,
["Moonfire"] = 8921,
["Teleport: Moonglade"] = 18960,
["Dash"] = 1850,
["Flap"] = 164862,
["Survival Instincts"] = 61336,
["Bear Form"] = 5487,
["Stag Form"] = 210053,
["Soothe"] = 2908,
},
["Feral_PVPTalents"] = {
["Thorns"] = 236696,
["Overrun"] = 202246,
["Gladiator's Medallion"] = 208683,
["Faerie Swarm"] = 209749,
["Alpha Challenge"] = 207017,
["Demoralizing Roar"] = 201664,
["Cyclone"] = 209753,
},
["METADATA"] = {
["Specs"] = {
["Feral"] = 103,
["Balance"] = 102,
["Guardian"] = 104,
["Restoration"] = 105,
},
},
["Restoration"] = {
["Swiftmend"] = 18562,
["Solar Wrath"] = 5176,
["Revitalize"] = 212040,
["Nature's Cure"] = 88423,
["Mangle"] = 33917,
["Efflorescence"] = 145205,
["Charm Woodland Creature"] = 127757,
["Hibernate"] = 2637,
["Shred"] = 5221,
["Rebirth"] = 20484,
["Treant Form"] = 114282,
["Travel Form"] = 783,
["Prowl"] = 5215,
["Tranquility"] = 740,
["Wild Growth"] = 48438,
["Lifebloom"] = 33763,
["Ursol's Vortex"] = 102793,
["Revive"] = 50769,
["Growl"] = 6795,
["Regrowth"] = 8936,
["Bear Form"] = 5487,
["Dash"] = 1850,
["Innervate"] = 29166,
["Entangling Roots"] = 339,
["Soothe"] = 2908,
["Cat Form"] = 768,
["Barkskin"] = 22812,
["Teleport: Moonglade"] = 18960,
["Stag Form"] = 210053,
["Moonfire"] = 8921,
["Dreamwalk"] = 193753,
["Ironbark"] = 102342,
["Rejuvenation"] = 774,
["Flap"] = 164862,
["Sunfire"] = 93402,
},
["Balance"] = {
["Solar Wrath"] = 190984,
["Prowl"] = 5215,
["Lunar Strike"] = 194153,
["Regrowth"] = 8936,
["Innervate"] = 29166,
["Bear Form"] = 5487,
["Celestial Alignment"] = 194223,
["Growl"] = 6795,
["Entangling Roots"] = 339,
["Revive"] = 50769,
["Teleport: Moonglade"] = 18960,
["Flap"] = 164862,
["Mangle"] = 33917,
["Starsurge"] = 78674,
["Charm Woodland Creature"] = 127757,
["Hibernate"] = 2637,
["Rebirth"] = 20484,
["Moonkin Form"] = 24858,
["Shred"] = 5221,
["Soothe"] = 2908,
["Starfall"] = 191034,
["Remove Corruption"] = 2782,
["Moonfire"] = 8921,
["Barkskin"] = 22812,
["Cat Form"] = 768,
["Stag Form"] = 210053,
["Treant Form"] = 114282,
["Dreamwalk"] = 193753,
["Dash"] = 1850,
["Sunfire"] = 93402,
["Solar Beam"] = 78675,
["Travel Form"] = 783,
},
["Guardian"] = {
["Swiftmend"] = 18562,
["Stampeding Roar"] = 106898,
["Skull Bash"] = 106839,
["Entangling Roots"] = 339,
["Mangle"] = 33917,
["Charm Woodland Creature"] = 127757,
["Hibernate"] = 2637,
["Shred"] = 5221,
["Remove Corruption"] = 2782,
["Rebirth"] = 20484,
["Ironfur"] = 192081,
["Thrash"] = 106832,
["Travel Form"] = 783,
["Prowl"] = 5215,
["Regrowth"] = 8936,
["Wild Growth"] = 48438,
["Growl"] = 6795,
["Maul"] = 6807,
["Revive"] = 50769,
["Frenzied Regeneration"] = 22842,
["Dreamwalk"] = 193753,
["Incapacitating Roar"] = 99,
["Bear Form"] = 5487,
["Dash"] = 1850,
["Soothe"] = 2908,
["Cat Form"] = 768,
["Barkskin"] = 22812,
["Swipe"] = 213764,
["Teleport: Moonglade"] = 18960,
["Moonfire"] = 8921,
["Stag Form"] = 210053,
["Survival Instincts"] = 61336,
["Rejuvenation"] = 774,
["Flap"] = 164862,
["Treant Form"] = 114282,
},
["Restoration_Talents"] = {
["Mass Entanglement"] = 102359,
["Flourish"] = 197721,
["Typhoon"] = 132469,
["Mighty Bash"] = 5211,
["Wild Charge"] = 102401,
["Tiger Dash"] = 252216,
["Cenarion Ward"] = 102351,
["Incarnation: Tree of Life"] = 33891,
["Renewal"] = 108238,
},
["Balance_Talents"] = {
["Force of Nature"] = 205636,
["New Moon"] = 274281,
["Stellar Flare"] = 202347,
["Mass Entanglement"] = 102359,
["Typhoon"] = 132469,
["Warrior of Elune"] = 202425,
["Mighty Bash"] = 5211,
["Wild Charge"] = 102401,
["Tiger Dash"] = 252216,
["Fury of Elune"] = 202770,
["Incarnation: Chosen of Elune"] = 102560,
["Renewal"] = 108238,
},
["Guardian_PVPTalents"] = {
["Thorns"] = 236696,
["Overrun"] = 202246,
["Gladiator's Medallion"] = 208683,
["Faerie Swarm"] = 209749,
["Alpha Challenge"] = 207017,
["Demoralizing Roar"] = 201664,
["Cyclone"] = 209753,
},
["Balance_PVPTalents"] = {
["Thorns"] = 236696,
["Overrun"] = 202246,
["Gladiator's Medallion"] = 208683,
["Faerie Swarm"] = 209749,
["Alpha Challenge"] = 207017,
["Demoralizing Roar"] = 201664,
["Cyclone"] = 209753,
},
["Guardian_Talents"] = {
["Mass Entanglement"] = 102359,
["Bristling Fur"] = 155835,
["Lunar Beam"] = 204066,
["Pulverize"] = 80313,
["Typhoon"] = 132469,
["Mighty Bash"] = 5211,
["Wild Charge"] = 102401,
["Ursol's Vortex"] = 102793,
["Tiger Dash"] = 252216,
["Incarnation: Guardian of Ursoc"] = 102558,
},
},
["HUNTER"] = {
["Beast Mastery_Talents"] = {
["Dire Beast"] = 120679,
["Chimaera Shot"] = 53209,
["Camouflage"] = 199483,
["A Murder of Crows"] = 131894,
["Binding Shot"] = 109248,
["Stampede"] = 201430,
["Barrage"] = 120360,
["Spitting Cobra"] = 194407,
},
["Marksmanship_Talents"] = {
["Piercing Shot"] = 198670,
["Camouflage"] = 199483,
["Serpent Sting"] = 271788,
["Explosive Shot"] = 212431,
["Double Tap"] = 260402,
["Hunter's Mark"] = 257284,
["Binding Shot"] = 109248,
["A Murder of Crows"] = 131894,
["Barrage"] = 120360,
},
["Marksmanship"] = {
["Pet Utility"] = 103,
["Flare"] = 1543,
["Rapid Fire"] = 257044,
["Command Pet"] = 272651,
["Feign Death"] = 5384,
["Arcane Shot"] = 185358,
["Feed Pet"] = 6991,
["Aimed Shot"] = 19434,
["Tar Trap"] = 187698,
["Multi-Shot"] = 257620,
["Aspect of the Turtle"] = 186265,
["Disengage"] = 781,
["Trueshot"] = 288613,
["Beast Lore"] = 1462,
["Counter Shot"] = 147362,
["Tame Beast"] = 1515,
["Bursting Shot"] = 186387,
["Eagle Eye"] = 6197,
["Steady Shot"] = 56641,
["Aspect of the Cheetah"] = 186257,
["Exhilaration"] = 109304,
["Call Pet"] = 9,
["Misdirection"] = 34477,
["Concussive Shot"] = 5116,
["Freezing Trap"] = 187650,
["Dismiss Pet"] = 2641,
},
["Flyouts"] = {
["Call Pet"] = {
["Call Pet 3"] = 83243,
["Call Pet 4"] = 83244,
["Call Pet 5"] = 83245,
["Call Pet 2"] = 83242,
["Call Pet 1"] = 883,
},
["Pet Utility"] = {
["Beast Lore"] = 1462,
["Feed Pet"] = 6991,
["Tame Beast"] = 1515,
["Dismiss Pet"] = 2641,
["Revive Pet"] = 982,
},
},
["Pets"] = {
["Ferocity"] = {
["Bite"] = 17253,
["Primal Rage"] = 264667,
["Smack"] = 49966,
["Dash"] = 61684,
["Claw"] = 16827,
["Growl"] = 2649,
},
["Mechanical"] = {
["Defense Matrix"] = 263868,
},
["Worm"] = {
["Acid Spit"] = 263446,
["Burrow Attack"] = 93433,
},
["Stag"] = {
["Nature's Grace"] = 264266,
},
["Wasp"] = {
["Toxic Sting"] = 263858,
},
["Quilen"] = {
["Stone Armor"] = 160049,
["Eternal Guardian"] = 267922,
},
["Basilisk"] = {
["Petrifying Gaze"] = 263841,
},
["Silithid"] = {
["Tendon Rip"] = 160065,
["Dune Strider"] = 280151,
},
["Lizard"] = {
["Grievous Bite"] = 279362,
},
["Water Strider"] = {
["Soothing Water"] = 264262,
["Surface Trot"] = 126311,
},
["Ravager"] = {
["Ravage"] = 263857,
},
["Scorpid"] = {
["Deadly Sting"] = 160060,
},
["Scalehide"] = {
["Scale Shield"] = 263865,
},
["Oxen"] = {
["Niuzao's Fortitude"] = 264023,
},
["Hydra"] = {
["Acid Bite"] = 263863,
},
["Bear"] = {
["Rest"] = 94019,
},
["Beetle"] = {
["Harden Carapace"] = 90339,
},
["Chimaera"] = {
["Froststorm Breath"] = 92380,
["Frost Breath"] = 54644,
},
["Clefthoof"] = {
["Thick Hide"] = 160057,
["Blood of the Rhino"] = 280069,
},
["Cunning"] = {
["Bite"] = 17253,
["Smack"] = 49966,
["Dash"] = 61684,
["Claw"] = 16827,
["Master's Call"] = 53271,
["Growl"] = 2649,
},
["Dog"] = {
["Lock Jaw"] = 263423,
},
["Bird of Prey"] = {
["Talon Rend"] = 263852,
["Trick"] = 94022,
},
["Pterrordax"] = {
["Updraft"] = 160007,
["Ancient Hide"] = 279399,
},
["Crocolisk"] = {
["Ankle Crack"] = 50433,
},
["Hyena"] = {
["Infected Bite"] = 263853,
},
["Dragonhawk"] = {
["Dragon's Guile"] = 263887,
},
["Devilsaur"] = {
["Feast"] = 159953,
["Monstrous Bite"] = 54680,
},
["Feathermane"] = {
["Feather Flurry"] = 263916,
["Updraft"] = 160007,
},
["Fox"] = {
["Play"] = 90347,
["Agile Reflexes"] = 160011,
},
["Monkey"] = {
["Primal Agility"] = 160044,
},
["Gorilla"] = {
["Silverback"] = 263939,
},
["Warp Stalker"] = {
["Warp Time"] = 35346,
},
["Sporebat"] = {
["Spore Cloud"] = 264056,
},
["Moth"] = {
["Serenity Dust"] = 264055,
},
["Serpent"] = {
["Serpent's Swiftness"] = 263904,
},
["Cat"] = {
["Catlike Reflexes"] = 263892,
["Prowl"] = 24450,
},
["Bat"] = {
["Sonic Blast"] = 264263,
},
["Carrion Bird"] = {
["Bloody Screech"] = 24423,
},
["Wolf"] = {
["Furious Bite"] = 263840,
},
["Toad"] = {
["Swarm of Flies"] = 279336,
},
["Krolusk"] = {
["Bulwark"] = 279410,
},
["Shale Spider"] = {
["Solid Shell"] = 160063,
},
["Riverbeast"] = {
["Gruesome Bite"] = 160018,
},
["Tallstrider"] = {
["Dust Cloud"] = 50285,
},
["Spider"] = {
["Web Spray"] = 160067,
},
["Crab"] = {
["Pin"] = 50245,
},
["Nether Ray"] = {
["Nether Shock"] = 264264,
},
["Core Hound"] = {
["Obsidian Skin"] = 263867,
["Molten Hide"] = 159788,
},
["Crane"] = {
["Chi-Ji's Tranquility"] = 264028,
["Trick"] = 126259,
},
["Boar"] = {
["Bristle"] = 263869,
},
["Rodent"] = {
["Gnaw"] = 263856,
["Rest"] = 126364,
},
["Wind Serpent"] = {
["Winged Agility"] = 264360,
},
["Turtle"] = {
["Shell Shield"] = 26064,
},
["Direhorn"] = {
["Gore"] = 263861,
},
["Raptor"] = {
["Savage Rend"] = 263854,
},
["Spirit Beast"] = {
["Spirit Walk"] = 90328,
["Spirit Shock"] = 264265,
["Spirit Mend"] = 90361,
},
["Tenacity"] = {
["Bite"] = 17253,
["Smack"] = 49966,
["Dash"] = 61684,
["Claw"] = 16827,
["Survival of the Fittest"] = 264735,
["Growl"] = 2649,
},
["Blood Beast"] = {
["Blood Bolt"] = 288962,
},
},
["Survival"] = {
["Harpoon"] = 190925,
["Flare"] = 1543,
["Command Pet"] = 272651,
["Kill Command"] = 259489,
["Feign Death"] = 5384,
["Misdirection"] = 34477,
["Muzzle"] = 187707,
["Feed Pet"] = 6991,
["Call Pet"] = 9,
["Tar Trap"] = 187698,
["Freezing Trap"] = 187650,
["Dismiss Pet"] = 2641,
["Disengage"] = 781,
["Raptor Strike"] = 186270,
["Coordinated Assault"] = 266779,
["Aspect of the Eagle"] = 186289,
["Beast Lore"] = 1462,
["Tame Beast"] = 1515,
["Aspect of the Cheetah"] = 186257,
["Intimidation"] = 19577,
["Carve"] = 187708,
["Eagle Eye"] = 6197,
["Exhilaration"] = 109304,
["Pet Utility"] = 103,
["Aspect of the Turtle"] = 186265,
["Wildfire Bomb"] = 259495,
["Wing Clip"] = 195645,
["Serpent Sting"] = 259491,
},
["Marksmanship_PVPTalents"] = {
["Spider Sting"] = 202914,
["Dire Beast: Basilisk"] = 205691,
["Hi-Explosive Trap"] = 236776,
["Viper Sting"] = 202797,
["Scorpid Sting"] = 202900,
["Gladiator's Medallion"] = 208683,
["Dire Beast: Hawk"] = 208652,
["Interlope"] = 248518,
["Roar of Sacrifice"] = 53480,
},
["Survival_PVPTalents"] = {
["Spider Sting"] = 202914,
["Dire Beast: Basilisk"] = 205691,
["Hi-Explosive Trap"] = 236776,
["Viper Sting"] = 202797,
["Scorpid Sting"] = 202900,
["Gladiator's Medallion"] = 208683,
["Dire Beast: Hawk"] = 208652,
["Interlope"] = 248518,
["Roar of Sacrifice"] = 53480,
},
["Survival_Talents"] = {
["Flanking Strike"] = 269751,
["Chakrams"] = 259391,
["Camouflage"] = 199483,
["A Murder of Crows"] = 131894,
["Butchery"] = 212436,
["Steel Trap"] = 162488,
["Mongoose Bite"] = 259387,
["Binding Shot"] = 109248,
},
["Beast Mastery_PVPTalents"] = {
["Spider Sting"] = 202914,
["Dire Beast: Basilisk"] = 205691,
["Hi-Explosive Trap"] = 236776,
["Viper Sting"] = 202797,
["Scorpid Sting"] = 202900,
["Gladiator's Medallion"] = 208683,
["Dire Beast: Hawk"] = 208652,
["Interlope"] = 248518,
["Roar of Sacrifice"] = 53480,
},
["Beast Mastery"] = {
["Pet Utility"] = 103,
["Cobra Shot"] = 193455,
["Command Pet"] = 272651,
["Kill Command"] = 34026,
["Feign Death"] = 5384,
["Misdirection"] = 34477,
["Master's Call"] = 272651,
["Feed Pet"] = 6991,
["Survival of the Fittest"] = 272651,
["Call Pet"] = 9,
["Dismiss Pet"] = 2641,
["Tar Trap"] = 187698,
["Multi-Shot"] = 2643,
["Aspect of the Turtle"] = 186265,
["Disengage"] = 781,
["Primal Rage"] = 272651,
["Flare"] = 1543,
["Aspect of the Wild"] = 193530,
["Counter Shot"] = 147362,
["Tame Beast"] = 1515,
["Eagle Eye"] = 6197,
["Intimidation"] = 19577,
["Beast Lore"] = 1462,
["Aspect of the Cheetah"] = 186257,
["Exhilaration"] = 109304,
["Mend Pet"] = 136,
["Barbed Shot"] = 217200,
["Concussive Shot"] = 5116,
["Freezing Trap"] = 187650,
["Bestial Wrath"] = 19574,
},
["METADATA"] = {
["Specs"] = {
["Marksmanship"] = 254,
["Beast Mastery"] = 253,
["Survival"] = 255,
},
},
},
["MAGE"] = {
["Fire_PVPTalents"] = {
["Ice Form"] = 198144,
["Gladiator's Medallion"] = 208683,
["Mass Invisibility"] = 198158,
["Temporal Shield"] = 198111,
},
["Frost_Talents"] = {
["Ice Nova"] = 157997,
["Ebonbolt"] = 257537,
["Glacial Spike"] = 199786,
["Mirror Image"] = 55342,
["Rune of Power"] = 116011,
["Ring of Frost"] = 113724,
["Ice Floes"] = 108839,
["Shimmer"] = 212653,
["Comet Storm"] = 153595,
["Ray of Frost"] = 205021,
},
["Arcane_Talents"] = {
["Mirror Image"] = 55342,
["Rune of Power"] = 116011,
["Nether Tempest"] = 114923,
["Charged Up"] = 205032,
["Ring of Frost"] = 113724,
["Arcane Orb"] = 153626,
["Shimmer"] = 212653,
["Arcane Familiar"] = 205022,
["Supernova"] = 157980,
},
["Flyouts"] = {
["Polymorph Variants"] = {
["Polymorph(Peacock)"] = 161372,
["Polymorph(Rabbit)"] = 61721,
["Polymorph(Monkey)"] = 161354,
["Polymorph(Direhorn)"] = 277787,
["Polymorph(Porcupine)"] = 126819,
["Polymorph(Black Cat)"] = 61305,
["Polymorph(Turtle)"] = 28271,
["Polymorph(Turkey)"] = 61780,
["Polymorph(Penguin)"] = 161355,
["Polymorph(Pig)"] = 28272,
["Polymorph(Serpent)"] = 61025,
["Polymorph(Bumblebee)"] = 277792,
["Polymorph(Polar Bear Cub)"] = 161353,
},
["Portal"] = {
["Portal: Exodar"] = 32266,
["Portal: Stonard"] = 49361,
["Portal: Undercity"] = 11418,
["Portal: Vale of Eternal Blossoms(Horde)"] = 132626,
["Portal: Vale of Eternal Blossoms(Alliance)"] = 132620,
["Ancient Portal: Dalaran"] = 120146,
["Portal: Stormwind"] = 10059,
["Portal: Warspear"] = 176244,
["Portal: Theramore"] = 49360,
["Portal: Thunder Bluff"] = 11420,
["Portal: Darnassus"] = 11419,
["Portal: Silvermoon"] = 32267,
["Portal: Tol Barad(Alliance)"] = 88345,
["Portal: Orgrimmar"] = 11417,
["Portal: Shattrath(Horde)"] = 35717,
["Portal: Dazar'alor"] = 281402,
["Portal: Tol Barad(Horde)"] = 88346,
["Portal: Stormshield"] = 176246,
["Portal: Shattrath(Alliance)"] = 33691,
["Portal: Dalaran - Broken Isles"] = 224871,
["Portal: Boralus"] = 281400,
["Portal: Dalaran - Northrend"] = 53142,
["Portal: Ironforge"] = 11416,
},
["Teleport"] = {
["Teleport: Dalaran - Northrend"] = 53140,
["Teleport: Vale of Eternal Blossoms(Horde)"] = 132627,
["Teleport: Stonard"] = 49358,
["Teleport: Stormshield"] = 176248,
["Teleport: Darnassus"] = 3565,
["Teleport: Vale of Eternal Blossoms(Alliance)"] = 132621,
["Teleport: Dalaran - Broken Isles"] = 224869,
["Teleport: Boralus"] = 281403,
["Teleport: Stormwind"] = 3561,
["Teleport: Hall of the Guardian"] = 193759,
["Teleport: Shattrath(Horde)"] = 35715,
["Teleport: Dazar'alor"] = 281404,
["Teleport: Tol Barad(Horde)"] = 88344,
["Teleport: Shattrath(Alliance)"] = 33690,
["Teleport: Tol Barad(Alliance)"] = 88342,
["Teleport: Orgrimmar"] = 3567,
["Teleport: Ironforge"] = 3562,
["Teleport: Warspear"] = 176242,
["Teleport: Theramore"] = 49359,
["Teleport: Silvermoon"] = 32272,
["Teleport: Undercity"] = 3563,
["Ancient Teleport: Dalaran"] = 120145,
["Teleport: Exodar"] = 32271,
["Teleport: Thunder Bluff"] = 3566,
},
},
["Pets"] = {
["Water Elemental"] = {
["Freeze"] = 33395,
["Waterbolt"] = 31707,
},
},
["Frost"] = {
["Arcane Intellect"] = 1459,
["Blizzard"] = 190356,
["Frostbolt"] = 116,
["Frozen Orb"] = 84714,
["Polymorph"] = 118,
["Cold Snap"] = 235219,
["Remove Curse"] = 475,
["Ice Lance"] = 108853,
["Polymorph(Sheep)"] = 118,
["Counterspell"] = 2139,
["Ice Barrier"] = 11426,
["Time Warp"] = 80353,
["Portal"] = 12,
["Teleport"] = 8,
["Icy Veins"] = 12472,
["Summon Water Elemental"] = 31687,
["Polymorph Variants"] = 92,
["Conjure Refreshment"] = 190336,
["Flurry"] = 44614,
["Blink"] = 1953,
["Slow Fall"] = 130,
["Ice Block"] = 45438,
["Frost Nova"] = 122,
["Spellsteal"] = 30449,
["Cone of Cold"] = 120,
["Invisibility"] = 66,
},
["Frost_PVPTalents"] = {
["Ice Form"] = 198144,
["Gladiator's Medallion"] = 208683,
["Mass Invisibility"] = 198158,
["Temporal Shield"] = 198111,
},
["Arcane"] = {
["Arcane Blast"] = 30451,
["Arcane Intellect"] = 1459,
["Arcane Explosion"] = 1449,
["Prismatic Barrier"] = 235450,
["Polymorph"] = 118,
["Presence of Mind"] = 205025,
["Remove Curse"] = 475,
["Slow"] = 31589,
["Arcane Power"] = 12042,
["Polymorph(Sheep)"] = 118,
["Conjure Refreshment"] = 190336,
["Time Warp"] = 80353,
["Portal"] = 12,
["Teleport"] = 8,
["Evocation"] = 12051,
["Arcane Missiles"] = 5143,
["Polymorph Variants"] = 92,
["Counterspell"] = 2139,
["Ice Block"] = 45438,
["Blink"] = 1953,
["Slow Fall"] = 130,
["Greater Invisibility"] = 110959,
["Frost Nova"] = 122,
["Arcane Barrage"] = 44425,
["Spellsteal"] = 30449,
["Displacement"] = 195676,
},
["Arcane_PVPTalents"] = {
["Ice Form"] = 198144,
["Gladiator's Medallion"] = 208683,
["Mass Invisibility"] = 198158,
["Temporal Shield"] = 198111,
},
["Fire"] = {
["Fireball"] = 133,
["Arcane Intellect"] = 1459,
["Fire Blast"] = 108853,
["Polymorph"] = 118,
["Pyroblast"] = 11366,
["Remove Curse"] = 475,
["Scorch"] = 2948,
["Flamestrike"] = 2120,
["Conjure Refreshment"] = 190336,
["Time Warp"] = 80353,
["Portal"] = 12,
["Teleport"] = 8,
["Polymorph(Sheep)"] = 118,
["Combustion"] = 190319,
["Polymorph Variants"] = 92,
["Frost Nova"] = 122,
["Ice Block"] = 45438,
["Blink"] = 1953,
["Slow Fall"] = 130,
["Dragon's Breath"] = 31661,
["Counterspell"] = 2139,
["Blazing Barrier"] = 235313,
["Spellsteal"] = 30449,
["Invisibility"] = 66,
},
["Fire_Talents"] = {
["Phoenix Flames"] = 257541,
["Blast Wave"] = 157981,
["Meteor"] = 153561,
["Ring of Frost"] = 113724,
["Mirror Image"] = 55342,
["Rune of Power"] = 116011,
["Shimmer"] = 212653,
["Living Bomb"] = 44457,
},
["METADATA"] = {
["Specs"] = {
["Fire"] = 63,
["Frost"] = 64,
["Arcane"] = 62,
},
},
},
["MONK"] = {
["Windwalker_Talents"] = {
["Chi Burst"] = 123986,
["Rushing Jade Wind"] = 116847,
["Fist of the White Tiger"] = 261947,
["Energizing Elixir"] = 115288,
["Ring of Peace"] = 116844,
["Chi Torpedo"] = 115008,
["Chi Wave"] = 115098,
["Diffuse Magic"] = 122783,
["Dampen Harm"] = 122278,
["Tiger's Lust"] = 116841,
["Invoke Xuen, the White Tiger"] = 123904,
["Whirling Dragon Punch"] = 152175,
["Serenity"] = 152173,
},
["Mistweaver_Talents"] = {
["Chi Burst"] = 123986,
["Diffuse Magic"] = 122783,
["Invoke Chi-Ji, the Red Crane"] = 198664,
["Song of Chi-Ji"] = 198898,
["Ring of Peace"] = 116844,
["Chi Torpedo"] = 115008,
["Refreshing Jade Wind"] = 196725,
["Mana Tea"] = 197908,
["Summon Jade Serpent Statue"] = 115313,
["Tiger's Lust"] = 116841,
["Healing Elixir"] = 122281,
["Dampen Harm"] = 122278,
["Chi Wave"] = 115098,
},
["Mistweaver"] = {
["Life Cocoon"] = 116849,
["Thunder Focus Tea"] = 116680,
["Resuscitate"] = 115178,
["Vivify"] = 116670,
["Renewing Mist"] = 115151,
["Leg Sweep"] = 119381,
["Detox"] = 115450,
["Roll"] = 109132,
["Soothing Mist"] = 115175,
["Transcendence"] = 101643,
["Revival"] = 115310,
["Zen Pilgrimage"] = 126892,
["Spinning Crane Kick"] = 101546,
["Rising Sun Kick"] = 107428,
["Crackling Jade Lightning"] = 117952,
["Provoke"] = 115546,
["Paralysis"] = 115078,
["Tiger Palm"] = 100780,
["Blackout Kick"] = 100784,
["Enveloping Mist"] = 124682,
["Transcendence: Transfer"] = 119996,
["Reawaken"] = 212051,
["Fortifying Brew"] = 243435,
["Essence Font"] = 191837,
},
["Brewmaster"] = {
["Resuscitate"] = 115178,
["Blackout Strike"] = 205523,
["Breath of Fire"] = 115181,
["Vivify"] = 116670,
["Expel Harm"] = 115072,
["Detox"] = 218164,
["Roll"] = 109132,
["Spear Hand Strike"] = 116705,
["Zen Meditation"] = 115176,
["Transcendence"] = 101643,
["Tiger Palm"] = 100780,
["Fortifying Brew"] = 115203,
["Zen Pilgrimage"] = 126892,
["Paralysis"] = 115078,
["Crackling Jade Lightning"] = 117952,
["Purifying Brew"] = 119582,
["Provoke"] = 115546,
["Transcendence: Transfer"] = 119996,
["Keg Smash"] = 121253,
["Leg Sweep"] = 119381,
["Ironskin Brew"] = 115308,
},
["Windwalker"] = {
["Fists of Fury"] = 113656,
["Resuscitate"] = 115178,
["Vivify"] = 116670,
["Touch of Death"] = 115080,
["Leg Sweep"] = 119381,
["Detox"] = 218164,
["Roll"] = 109132,
["Touch of Karma"] = 122470,
["Spear Hand Strike"] = 116705,
["Storm, Earth, and Fire"] = 137639,
["Zen Pilgrimage"] = 126892,
["Transcendence"] = 101643,
["Flying Serpent Kick"] = 101545,
["Tiger Palm"] = 100780,
["Crackling Jade Lightning"] = 117952,
["Transcendence: Transfer"] = 119996,
["Blackout Kick"] = 100784,
["Provoke"] = 115546,
["Paralysis"] = 115078,
["Rising Sun Kick"] = 107428,
["Spinning Crane Kick"] = 101546,
["Disable"] = 116095,
},
["Mistweaver_PVPTalents"] = {
["Gladiator's Medallion"] = 208683,
["Fortifying Brew"] = 201318,
["Tigereye Brew"] = 247483,
["Reverse Harm"] = 287771,
["Grapple Weapon"] = 233759,
},
["Windwalker_PVPTalents"] = {
["Gladiator's Medallion"] = 208683,
["Fortifying Brew"] = 201318,
["Tigereye Brew"] = 247483,
["Reverse Harm"] = 287771,
["Grapple Weapon"] = 233759,
},
["Brewmaster_Talents"] = {
["Chi Burst"] = 123986,
["Summon Black Ox Statue"] = 115315,
["Black Ox Brew"] = 115399,
["Ring of Peace"] = 116844,
["Chi Torpedo"] = 115008,
["Chi Wave"] = 115098,
["Dampen Harm"] = 122278,
["Invoke Niuzao, the Black Ox"] = 132578,
["Tiger's Lust"] = 116841,
["Healing Elixir"] = 122281,
["Guard"] = 115295,
["Rushing Jade Wind"] = 116847,
},
["Brewmaster_PVPTalents"] = {
["Gladiator's Medallion"] = 208683,
["Fortifying Brew"] = 201318,
["Tigereye Brew"] = 247483,
["Reverse Harm"] = 287771,
["Grapple Weapon"] = 233759,
},
["METADATA"] = {
["Specs"] = {
["Mistweaver"] = 270,
["Brewmaster"] = 268,
["Windwalker"] = 269,
},
},
},
["PALADIN"] = {
["Protection"] = {
["Divine Shield"] = 642,
["Guardian of Ancient Kings"] = 86659,
["Judgment"] = 275779,
["Light of the Protector"] = 184092,
["Hand of Reckoning"] = 62124,
["Hammer of Justice"] = 853,
["Consecration"] = 26573,
["Avenging Wrath"] = 31884,
["Blessing of Sacrifice"] = 6940,
["Rebuke"] = 96231,
["Blessing of Freedom"] = 1044,
["Blessing of Protection"] = 1022,
["Lay on Hands"] = 633,
["Shield of the Righteous"] = 53600,
["Redemption"] = 7328,
["Cleanse Toxins"] = 213644,
["Hammer of the Righteous"] = 53595,
["Flash of Light"] = 19750,
["Avenger's Shield"] = 31935,
["Ardent Defender"] = 31850,
["Divine Steed"] = 190784,
},
["Holy"] = {
["Divine Shield"] = 642,
["Holy Light"] = 82326,
["Cleanse"] = 4987,
["Judgment"] = 275773,
["Redemption"] = 7328,
["Holy Shock"] = 20473,
["Hand of Reckoning"] = 62124,
["Hammer of Justice"] = 853,
["Consecration"] = 26573,
["Beacon of Light"] = 53563,
["Divine Protection"] = 498,
["Blessing of Protection"] = 1022,
["Avenging Wrath"] = 31884,
["Light of the Martyr"] = 183998,
["Absolution"] = 212056,
["Blessing of Freedom"] = 1044,
["Light of Dawn"] = 85222,
["Blessing of Sacrifice"] = 6940,
["Aura Mastery"] = 31821,
["Flash of Light"] = 19750,
["Crusader Strike"] = 35395,
["Lay on Hands"] = 633,
["Divine Steed"] = 190784,
},
["Protection_PVPTalents"] = {
["Cleansing Light"] = 236186,
["Hammer of Reckoning"] = 247675,
["Blessing of Sanctuary"] = 210256,
["Gladiator's Medallion"] = 208683,
},
["Holy_Talents"] = {
["Holy Avenger"] = 105809,
["Blinding Light"] = 115750,
["Beacon of Faith"] = 156910,
["Bestow Faith"] = 223306,
["Light's Hammer"] = 114158,
["Rule of Law"] = 214202,
["Beacon of Virtue"] = 200025,
["Avenging Crusader"] = 216331,
["Holy Prism"] = 114165,
["Repentance"] = 20066,
},
["Holy_PVPTalents"] = {
["Cleansing Light"] = 236186,
["Hammer of Reckoning"] = 247675,
["Blessing of Sanctuary"] = 210256,
["Gladiator's Medallion"] = 208683,
},
["Retribution_Talents"] = {
["Word of Glory"] = 210191,
["Blinding Light"] = 115750,
["Hammer of Wrath"] = 24275,
["Justicar's Vengeance"] = 215661,
["Wake of Ashes"] = 255937,
["Inquisition"] = 84963,
["Crusade"] = 231895,
["Consecration"] = 205228,
["Eye for an Eye"] = 205191,
["Execution Sentence"] = 267798,
["Repentance"] = 20066,
},
["Retribution_PVPTalents"] = {
["Cleansing Light"] = 236186,
["Hammer of Reckoning"] = 247675,
["Blessing of Sanctuary"] = 210256,
["Gladiator's Medallion"] = 208683,
},
["Protection_Talents"] = {
["Bastion of Light"] = 204035,
["Blessing of Spellwarding"] = 204018,
["Blinding Light"] = 115750,
["Blessed Hammer"] = 204019,
["Seraphim"] = 152262,
["Hand of the Protector"] = 213652,
["Aegis of Light"] = 204150,
["Repentance"] = 20066,
},
["Retribution"] = {
["Divine Shield"] = 642,
["Avenging Wrath"] = 31884,
["Divine Storm"] = 53385,
["Shield of Vengeance"] = 184662,
["Judgment"] = 20271,
["Redemption"] = 7328,
["Hand of Reckoning"] = 62124,
["Hammer of Justice"] = 853,
["Rebuke"] = 96231,
["Greater Blessing of Kings"] = 203538,
["Hand of Hindrance"] = 183218,
["Blade of Justice"] = 184575,
["Lay on Hands"] = 633,
["Blessing of Freedom"] = 1044,
["Blessing of Protection"] = 1022,
["Templar's Verdict"] = 85256,
["Cleanse Toxins"] = 213644,
["Flash of Light"] = 19750,
["Crusader Strike"] = 35395,
["Greater Blessing of Wisdom"] = 203539,
["Divine Steed"] = 190784,
},
["METADATA"] = {
["Specs"] = {
["Protection"] = 66,
["Holy"] = 65,
["Retribution"] = 70,
},
},
},
["PRIEST"] = {
["Shadow"] = {
["Purify Disease"] = 213634,
["Resurrection"] = 2006,
["Shackle Undead"] = 9484,
["Shadow Word: Pain"] = 589,
["Fade"] = 586,
["Mind Vision"] = 2096,
["Shadowform"] = 232698,
["Silence"] = 15487,
["Dispersion"] = 47585,
["Mind Sear"] = 48045,
["Mind Blast"] = 8092,
["Vampiric Embrace"] = 15286,
["Void Eruption"] = 228260,
["Mind Flay"] = 15407,
["Shadow Mend"] = 186263,
["Mind Control"] = 605,
["Power Word: Fortitude"] = 21562,
["Psychic Scream"] = 8122,
["Leap of Faith"] = 73325,
["Power Word: Shield"] = 17,
["Levitate"] = 1706,
["Dispel Magic"] = 528,
["Vampiric Touch"] = 34914,
["Shadowfiend"] = 34433,
["Mass Dispel"] = 32375,
},
["Shadow_PVPTalents"] = {
["Dark Archangel"] = 197871,
["Archangel"] = 197862,
["Premonition"] = 209780,
["Gladiator's Medallion"] = 208683,
},
["Holy_Talents"] = {
["Circle of Healing"] = 204883,
["Divine Star"] = 110744,
["Shining Force"] = 204263,
["Binding Heal"] = 32546,
["Halo"] = 120517,
["Holy Word: Salvation"] = 265202,
["Apotheosis"] = 200183,
["Angelic Feather"] = 121536,
},
["Holy_PVPTalents"] = {
["Dark Archangel"] = 197871,
["Archangel"] = 197862,
["Premonition"] = 209780,
["Gladiator's Medallion"] = 208683,
},
["METADATA"] = {
["Specs"] = {
["Discipline"] = 256,
["Holy"] = 257,
["Shadow"] = 258,
},
},
["Discipline"] = {
["Power Word: Radiance"] = 194509,
["Resurrection"] = 2006,
["Shackle Undead"] = 9484,
["Rapture"] = 47536,
["Holy Nova"] = 132157,
["Fade"] = 586,
["Mind Vision"] = 2096,
["Mass Dispel"] = 32375,
["Shadow Word: Pain"] = 589,
["Shadowfiend"] = 34433,
["Desperate Prayer"] = 19236,
["Power Word: Shield"] = 17,
["Levitate"] = 1706,
["Flash Heal"] = 2061,
["Power Word: Fortitude"] = 21562,
["Shadow Mend"] = 2061,
["Mind Control"] = 605,
["Penance"] = 47540,
["Psychic Scream"] = 8122,
["Leap of Faith"] = 73325,
["Mass Resurrection"] = 212036,
["Smite"] = 585,
["Dispel Magic"] = 528,
["Purify"] = 527,
["Pain Suppression"] = 33206,
["Power Word: Barrier"] = 62618,
},
["Discipline_PVPTalents"] = {
["Dark Archangel"] = 197871,
["Archangel"] = 197862,
["Premonition"] = 209780,
["Gladiator's Medallion"] = 208683,
},
["Holy"] = {
["Renew"] = 139,
["Resurrection"] = 2006,
["Shackle Undead"] = 9484,
["Holy Nova"] = 132157,
["Symbol of Hope"] = 64901,
["Fade"] = 586,
["Mind Vision"] = 2096,
["Mass Dispel"] = 32375,
["Purify"] = 527,
["Holy Word: Serenity"] = 2050,
["Prayer of Healing"] = 596,
["Smite"] = 585,
["Desperate Prayer"] = 19236,
["Holy Fire"] = 14914,
["Levitate"] = 1706,
["Flash Heal"] = 2061,
["Power Word: Fortitude"] = 21562,
["Holy Word: Chastise"] = 88625,
["Mass Resurrection"] = 212036,
["Holy Word: Sanctify"] = 34861,
["Psychic Scream"] = 8122,
["Leap of Faith"] = 73325,
["Divine Hymn"] = 64843,
["Guardian Spirit"] = 47788,
["Dispel Magic"] = 528,
["Mind Control"] = 605,
["Heal"] = 2060,
["Prayer of Mending"] = 33076,
},
["Discipline_Talents"] = {
["Evangelism"] = 246287,
["Schism"] = 214621,
["Mindbender"] = 123040,
["Halo"] = 120517,
["Shadow Covenant"] = 204065,
["Angelic Feather"] = 121536,
["Power Word: Solace"] = 129250,
["Divine Star"] = 110744,
["Shining Force"] = 204263,
["Luminous Barrier"] = 271466,
["Purge the Wicked"] = 204197,
},
["Shadow_Talents"] = {
["Mindbender"] = 200174,
["Dark Void"] = 263346,
["Void Torrent"] = 263165,
["Shadow Word: Death"] = 32379,
["Shadow Crash"] = 205385,
["Shadow Word: Void"] = 205351,
["Psychic Horror"] = 64044,
["Mind Bomb"] = 205369,
["Surrender to Madness"] = 193223,
["Dark Ascension"] = 280711,
},
},
["ROGUE"] = {
["Subtlety_PVPTalents"] = {
["Death from Above"] = 269513,
["Neurotoxin"] = 206328,
["Gladiator's Medallion"] = 208683,
["Shiv"] = 248744,
["Smoke Bomb"] = 212182,
["Plunder Armor"] = 198529,
["Dismantle"] = 207777,
},
["Assassination_PVPTalents"] = {
["Death from Above"] = 269513,
["Neurotoxin"] = 206328,
["Gladiator's Medallion"] = 208683,
["Shiv"] = 248744,
["Smoke Bomb"] = 212182,
["Plunder Armor"] = 198529,
["Dismantle"] = 207777,
},
["Assassination"] = {
["Sprint"] = 2983,
["Evasion"] = 5277,
["Garrote"] = 703,
["Cloak of Shadows"] = 31224,
["Vanish"] = 1856,
["Envenom"] = 32645,
["Tricks of the Trade"] = 57934,
["Crimson Vial"] = 185311,
["Shadowstep"] = 36554,
["Rupture"] = 1943,
["Wound Poison"] = 8679,
["Feint"] = 1966,
["Stealth"] = 1784,
["Crippling Poison"] = 3408,
["Vendetta"] = 79140,
["Mutilate"] = 1329,
["Pick Pocket"] = 921,
["Blind"] = 2094,
["Poisoned Knife"] = 185565,
["Pick Lock"] = 1804,
["Sinister Strike"] = 1752,
["Shroud of Concealment"] = 114018,
["Distract"] = 1725,
["Fan of Knives"] = 51723,
["Kidney Shot"] = 408,
["Sap"] = 6770,
["Eviscerate"] = 196819,
["Kick"] = 1766,
["Poisons"] = 66,
["Cheap Shot"] = 1833,
["Deadly Poison"] = 2823,
},
["Assassination_Talents"] = {
["Crimson Tempest"] = 121411,
["Blindside"] = 111240,
["Toxic Blade"] = 245388,
["Exsanguinate"] = 200806,
["Marked for Death"] = 137619,
},
["Subtlety"] = {
["Sprint"] = 2983,
["Evasion"] = 5277,
["Backstab"] = 53,
["Symbols of Death"] = 212283,
["Eviscerate"] = 196819,
["Shadowstep"] = 36554,
["Shadow Blades"] = 121471,
["Shadowstrike"] = 185438,
["Cloak of Shadows"] = 31224,
["Vanish"] = 1856,
["Tricks of the Trade"] = 57934,
["Feint"] = 1966,
["Kidney Shot"] = 408,
["Pick Pocket"] = 921,
["Blind"] = 2094,
["Sap"] = 6770,
["Pick Lock"] = 1804,
["Shadow Dance"] = 185313,
["Shroud of Concealment"] = 114018,
["Distract"] = 1725,
["Stealth"] = 1784,
["Shuriken Storm"] = 197835,
["Nightblade"] = 195452,
["Shuriken Toss"] = 114014,
["Kick"] = 1766,
["Poisons"] = 66,
["Cheap Shot"] = 1833,
["Crimson Vial"] = 185311,
},
["Flyouts"] = {
["Poisons"] = {
["Leeching Poison"] = 108211,
["Crippling Poison"] = 3408,
["Deadly Poison"] = 2823,
["Wound Poison"] = 8679,
["Agonizing Poison"] = 200802,
},
},
["Outlaw_PVPTalents"] = {
["Death from Above"] = 269513,
["Neurotoxin"] = 206328,
["Gladiator's Medallion"] = 208683,
["Shiv"] = 248744,
["Smoke Bomb"] = 212182,
["Plunder Armor"] = 198529,
["Dismantle"] = 207777,
},
["Outlaw_Talents"] = {
["Slice and Dice"] = 5171,
["Ghostly Strike"] = 196937,
["Blade Rush"] = 271877,
["Marked for Death"] = 137619,
["Killing Spree"] = 51690,
},
["Outlaw"] = {
["Sprint"] = 2983,
["Vanish"] = 1856,
["Riposte"] = 199754,
["Pistol Shot"] = 185763,
["Crimson Vial"] = 185311,
["Cloak of Shadows"] = 31224,
["Between the Eyes"] = 199804,
["Dispatch"] = 2098,
["Grappling Hook"] = 195457,
["Stealth"] = 1784,
["Poisons"] = 66,
["Feint"] = 1966,
["Ambush"] = 8676,
["Blind"] = 2094,
["Roll the Bones"] = 193316,
["Pick Lock"] = 1804,
["Shroud of Concealment"] = 114018,
["Sinister Strike"] = 193315,
["Distract"] = 1725,
["Adrenaline Rush"] = 13750,
["Gouge"] = 1776,
["Sap"] = 6770,
["Pick Pocket"] = 921,
["Kick"] = 1766,
["Tricks of the Trade"] = 57934,
["Cheap Shot"] = 1833,
["Blade Flurry"] = 13877,
},
["Subtlety_Talents"] = {
["Secret Technique"] = 280719,
["Marked for Death"] = 137619,
["Gloomblade"] = 200758,
["Shuriken Tornado"] = 277925,
},
["METADATA"] = {
["Specs"] = {
["Outlaw"] = 260,
["Subtlety"] = 261,
["Assassination"] = 259,
},
},
},
["SHAMAN"] = {
["Restoration_PVPTalents"] = {
["Counterstrike Totem"] = 204331,
["Thundercharge"] = 204366,
["Gladiator's Medallion"] = 208683,
["Skyfury Totem"] = 204330,
["Ethereal Form"] = 210918,
["Lightning Lasso"] = 204437,
["Grounding Totem"] = 204336,
},
["Elemental"] = {
["Astral Shift"] = 108271,
["Healing Surge"] = 8004,
["Ghost Wolf"] = 2645,
["Flame Shock"] = 188389,
["Thunderstorm"] = 51490,
["Earth Elemental"] = 198103,
["Earthquake"] = 61882,
["Fire Elemental"] = 198067,
["Ancestral Spirit"] = 2008,
["Water Walking"] = 546,
["Capacitor Totem"] = 192058,
["Earthbind Totem"] = 2484,
["Hex"] = 51514,
["Far Sight"] = 6196,
["Purge"] = 370,
["Cleanse Spirit"] = 51886,
["Hex Variants"] = 106,
["Frost Shock"] = 196840,
["Lightning Bolt"] = 188196,
["Bloodlust"] = 2825,
["Heroism"] = 32182,
["Lava Burst"] = 51505,
["Wind Shear"] = 57994,
["Astral Recall"] = 556,
["Hex(Frog)"] = 51514,
["Tremor Totem"] = 8143,
["Chain Lightning"] = 188443,
["Earth Shock"] = 8042,
},
["METADATA"] = {
["Specs"] = {
["Enhancement"] = 263,
["Elemental"] = 262,
["Restoration"] = 264,
},
},
["Flyouts"] = {
["Hex Variants"] = {
["Hex(Wicker Mongrel)"] = 277784,
["Hex(Skeletal Hatchling)"] = 269352,
["Hex(Zandalari Tendonripper)"] = 277778,
["Hex(Spider)"] = 211004,
["Hex(Compy)"] = 210873,
["Hex(Cockroach)"] = 211015,
["Hex(Snake)"] = 211010,
},
},
["Pets"] = {
["Storm Elemental"] = {
["Call Lightning"] = 157348,
["Eye of the Storm"] = 157375,
["Wind Gust"] = 157331,
},
["Fire Elemental"] = {
["Meteor"] = 117588,
["Immolate"] = 118297,
["Fire Blast"] = 57984,
},
["Earth Elemental"] = {
["Angered Earth"] = 36213,
["Pulverize"] = 118345,
["Harden Skin"] = 118337,
},
},
["Enhancement_PVPTalents"] = {
["Counterstrike Totem"] = 204331,
["Thundercharge"] = 204366,
["Gladiator's Medallion"] = 208683,
["Skyfury Totem"] = 204330,
["Ethereal Form"] = 210918,
["Lightning Lasso"] = 204437,
["Grounding Totem"] = 204336,
},
["Enhancement"] = {
["Astral Shift"] = 108271,
["Healing Surge"] = 188070,
["Crash Lightning"] = 187874,
["Lava Lash"] = 60103,
["Ghost Wolf"] = 2645,
["Hex(Frog)"] = 51514,
["Flametongue"] = 193796,
["Earth Elemental"] = 198103,
["Ancestral Spirit"] = 2008,
["Water Walking"] = 546,
["Capacitor Totem"] = 192058,
["Earthbind Totem"] = 2484,
["Hex"] = 51514,
["Feral Spirit"] = 51533,
["Heroism"] = 32182,
["Frostbrand"] = 196834,
["Hex Variants"] = 106,
["Far Sight"] = 6196,
["Cleanse Spirit"] = 51886,
["Bloodlust"] = 2825,
["Purge"] = 370,
["Lightning Bolt"] = 187837,
["Wind Shear"] = 57994,
["Astral Recall"] = 556,
["Stormstrike"] = 17364,
["Spirit Walk"] = 58875,
["Tremor Totem"] = 8143,
["Rockbiter"] = 193786,
},
["Elemental_PVPTalents"] = {
["Counterstrike Totem"] = 204331,
["Thundercharge"] = 204366,
["Gladiator's Medallion"] = 208683,
["Skyfury Totem"] = 204330,
["Ethereal Form"] = 210918,
["Lightning Lasso"] = 204437,
["Grounding Totem"] = 204336,
},
["Elemental_Talents"] = {
["Liquid Magma Totem"] = 192222,
["Totem Mastery"] = 210643,
["Icefury"] = 210714,
["Wind Rush Totem"] = 192077,
["Earth Shield"] = 974,
["Storm Elemental"] = 192249,
["Stormkeeper"] = 191634,
["Ascendance"] = 114050,
["Ancestral Guidance"] = 108281,
["Elemental Blast"] = 117014,
},
["Restoration_Talents"] = {
["Earthen Wall Totem"] = 198838,
["Wind Rush Totem"] = 192077,
["Ancestral Protection Totem"] = 207399,
["Earth Shield"] = 974,
["Unleash Life"] = 73685,
["Wellspring"] = 197995,
["Cloudburst Totem"] = 157153,
["Ascendance"] = 114052,
["Downpour"] = 207778,
["Earthgrab Totem"] = 51485,
},
["Restoration"] = {
["Astral Shift"] = 108271,
["Tremor Totem"] = 8143,
["Ghost Wolf"] = 2645,
["Healing Wave"] = 77472,
["Healing Tide Totem"] = 108280,
["Earth Elemental"] = 198103,
["Ancestral Vision"] = 212048,
["Flame Shock"] = 188838,
["Spiritwalker's Grace"] = 79206,
["Earthbind Totem"] = 2484,
["Chain Heal"] = 1064,
["Capacitor Totem"] = 192058,
["Purge"] = 370,
["Water Walking"] = 546,
["Spirit Link Totem"] = 98008,
["Far Sight"] = 6196,
["Hex"] = 51514,
["Purify Spirit"] = 77130,
["Heroism"] = 32182,
["Healing Rain"] = 73920,
["Hex Variants"] = 106,
["Lava Burst"] = 51505,
["Lightning Bolt"] = 403,
["Bloodlust"] = 2825,
["Riptide"] = 61295,
["Hex(Frog)"] = 51514,
["Wind Shear"] = 57994,
["Astral Recall"] = 556,
["Ancestral Spirit"] = 2008,
["Healing Stream Totem"] = 5394,
["Chain Lightning"] = 421,
["Healing Surge"] = 8004,
},
["Enhancement_Talents"] = {
["Fury of Air"] = 197211,
["Wind Rush Totem"] = 192077,
["Earth Shield"] = 974,
["Lightning Shield"] = 192106,
["Totem Mastery"] = 262395,
["Sundering"] = 197214,
["Ascendance"] = 114051,
["Feral Lunge"] = 196884,
["Earthen Spike"] = 188089,
},
},
["WARLOCK"] = {
["Affliction_Talents"] = {
["Grimoire of Sacrifice"] = 108503,
["Siphon Life"] = 63106,
["Mortal Coil"] = 6789,
["Demonic Circle"] = 268358,
["Drain Soul"] = 198590,
["Phantom Singularity"] = 205179,
["Dark Soul: Misery"] = 113860,
["Haunt"] = 48181,
["Vile Taint"] = 278350,
["Deathbolt"] = 264106,
["Burning Rush"] = 111400,
["Dark Pact"] = 108416,
},
["Destruction_Talents"] = {
["Grimoire of Sacrifice"] = 108503,
["Dark Pact"] = 108416,
["Mortal Coil"] = 6789,
["Demonic Circle"] = 268358,
["Channel Demonfire"] = 196447,
["Shadowburn"] = 17877,
["Cataclysm"] = 152108,
["Dark Soul: Instability"] = 113858,
["Burning Rush"] = 111400,
["Soul Fire"] = 6353,
},
["Affliction"] = {
["Corruption"] = 172,
["Shadowfury"] = 30283,
["Soulstone"] = 20707,
["Command Demon"] = 119898,
["Summon Darkglare"] = 205180,
["Agony"] = 980,
["Ritual of Summoning"] = 698,
["Health Funnel"] = 755,
["Eye of Kilrogg"] = 126,
["Fear"] = 5782,
["Demonic Gateway"] = 111771,
["Create Soulwell"] = 29893,
["Unending Breath"] = 5697,
["Drain Life"] = 234153,
["Unstable Affliction"] = 30108,
["Shadow Bolt"] = 232670,
["Summon Succubus"] = 712,
["Create Healthstone"] = 6201,
["Unending Resolve"] = 104773,
["Seed of Corruption"] = 27243,
["Banish"] = 710,
["Summon Demon"] = 10,
["Enslave Demon"] = 1098,
["Summon Felhunter"] = 691,
},
["Flyouts"] = {
["Summon Demon"] = {
["Summon Imp"] = 688,
["Summon Wrathguard"] = 112870,
["Summon Voidlord"] = 112867,
["Summon Felhunter"] = 691,
["Summon Voidwalker"] = 697,
["Summon Succubus"] = 712,
["Summon Shivarra"] = 112868,
["Summon Observer"] = 112869,
["Summon Fel Imp"] = 112866,
["Summon Felguard"] = 30146,
},
},
["Pets"] = {
["Voidlord"] = {
["Suffering"] = 119907,
["Consuming Shadows"] = 3716,
["Shadow Bulwark"] = 17767,
["Void Shield"] = 115236,
["Threatening Presence"] = 134477,
},
["Voidwalker"] = {
["Suffering"] = 17735,
["Consuming Shadows"] = 3716,
["Threatening Presence"] = 134477,
["Shadow Bulwark"] = 17767,
},
["Shivarra"] = {
["Mesmerize"] = 115268,
["Lesser Invisibility"] = 7870,
["Bladedance"] = 115748,
["Fellash"] = 115770,
},
["Fel Imp"] = {
["Felbolt"] = 115746,
["Cauterize Master"] = 119905,
["Sear Magic"] = 115276,
["Flee"] = 89792,
},
["Wrathguard"] = {
["Mortal Cleave"] = 115625,
["Threatening Presence"] = 134477,
["Wrathstorm"] = 115831,
["Axe Toss"] = 89766,
["Pursuit"] = 30151,
},
["Succubus"] = {
["Seduction"] = 6358,
["Lesser Invisibility"] = 7870,
["Lash of Pain"] = 7814,
["Whiplash"] = 6360,
},
["Felguard"] = {
["Threatening Presence"] = 134477,
["Felstorm"] = 89751,
["Axe Toss"] = 89766,
["Pursuit"] = 30151,
["Legion Strike"] = 30213,
},
["Felhunter"] = {
["Shadow Bite"] = 54049,
["Spell Lock"] = 19647,
["Devour Magic"] = 19505,
},
["Observer"] = {
["Optical Blast"] = 115781,
["Devour Magic"] = 19505,
["Tongue Lash"] = 115778,
},
["Imp"] = {
["Flee"] = 89792,
["Singe Magic"] = 89808,
["Firebolt"] = 3110,
},
},
["Destruction_PVPTalents"] = {
["Call Felhunter"] = 212619,
["Singe Magic"] = 212623,
["Curse of Fragility"] = 199954,
["Curse of Tongues"] = 199890,
["Curse of Shadows"] = 234877,
["Call Observer"] = 201996,
["Nether Ward"] = 212295,
["Curse of Weakness"] = 199892,
["Gladiator's Medallion"] = 208683,
["Soulshatter"] = 212356,
["Call Fel Lord"] = 212459,
["Demon Armor"] = 285933,
["Casting Circle"] = 221703,
},
["Destruction"] = {
["Shadowfury"] = 30283,
["Soulstone"] = 20707,
["Command Demon"] = 119898,
["Immolate"] = 348,
["Conflagrate"] = 17962,
["Ritual of Summoning"] = 698,
["Health Funnel"] = 755,
["Eye of Kilrogg"] = 126,
["Fear"] = 5782,
["Summon Infernal"] = 1122,
["Create Soulwell"] = 29893,
["Demonic Gateway"] = 111771,
["Unending Breath"] = 5697,
["Incinerate"] = 29722,
["Drain Life"] = 234153,
["Enslave Demon"] = 1098,
["Unending Resolve"] = 104773,
["Summon Succubus"] = 712,
["Create Healthstone"] = 6201,
["Havoc"] = 80240,
["Summon Felhunter"] = 691,
["Chaos Bolt"] = 116858,
["Summon Demon"] = 10,
["Banish"] = 710,
["Rain of Fire"] = 5740,
},
["Demonology_PVPTalents"] = {
["Call Felhunter"] = 212619,
["Singe Magic"] = 212623,
["Curse of Fragility"] = 199954,
["Curse of Tongues"] = 199890,
["Curse of Shadows"] = 234877,
["Call Observer"] = 201996,
["Nether Ward"] = 212295,
["Curse of Weakness"] = 199892,
["Gladiator's Medallion"] = 208683,
["Soulshatter"] = 212356,
["Call Fel Lord"] = 212459,
["Demon Armor"] = 285933,
["Casting Circle"] = 221703,
},
["Demonology"] = {
["Call Dreadstalkers"] = 104316,
["Singe Magic"] = 119898,
["Soulstone"] = 20707,
["Command Demon"] = 119898,
["Create Soulwell"] = 29893,
["Summon Demonic Tyrant"] = 265187,
["Ritual of Summoning"] = 698,
["Health Funnel"] = 755,
["Eye of Kilrogg"] = 126,
["Axe Toss"] = 119898,
["Shadow Bulwark"] = 119898,
["Demonbolt"] = 264178,
["Fear"] = 5782,
["Implosion"] = 196277,
["Enslave Demon"] = 1098,
["Demonic Gateway"] = 111771,
["Shadow Bolt"] = 686,
["Hand of Gul'dan"] = 105174,
["Banish"] = 710,
["Unending Breath"] = 5697,
["Seduction"] = 119898,
["Summon Succubus"] = 712,
["Create Healthstone"] = 6201,
["Unending Resolve"] = 104773,
["Drain Life"] = 234153,
["Summon Felhunter"] = 691,
["Summon Demon"] = 10,
["Spell Lock"] = 119898,
["Shadowfury"] = 30283,
},
["Demonology_Talents"] = {
["Dark Pact"] = 108416,
["Demonic Strength"] = 267171,
["Demonic Circle"] = 268358,
["Soul Strike"] = 264057,
["Summon Vilefiend"] = 264119,
["Grimoire: Felguard"] = 111898,
["Nether Portal"] = 267217,
["Doom"] = 265412,
["Mortal Coil"] = 6789,
["Power Siphon"] = 264130,
["Burning Rush"] = 111400,
["Bilescourge Bombers"] = 267211,
},
["Affliction_PVPTalents"] = {
["Call Felhunter"] = 212619,
["Singe Magic"] = 212623,
["Curse of Fragility"] = 199954,
["Curse of Tongues"] = 199890,
["Curse of Shadows"] = 234877,
["Call Observer"] = 201996,
["Nether Ward"] = 212295,
["Curse of Weakness"] = 199892,
["Gladiator's Medallion"] = 208683,
["Soulshatter"] = 212356,
["Call Fel Lord"] = 212459,
["Demon Armor"] = 285933,
["Casting Circle"] = 221703,
},
["METADATA"] = {
["Specs"] = {
["Demonology"] = 266,
["Affliction"] = 265,
["Destruction"] = 267,
},
},
},
["WARRIOR"] = {
["Protection"] = {
["Shield Slam"] = 23922,
["Intimidating Shout"] = 5246,
["Avatar"] = 107574,
["Berserker Rage"] = 18499,
["Shield Block"] = 2565,
["Taunt"] = 355,
["Shockwave"] = 46968,
["Devastate"] = 20243,
["Shield Wall"] = 871,
["Ignore Pain"] = 190456,
["Demoralizing Shout"] = 1160,
["Rallying Cry"] = 97462,
["Last Stand"] = 12975,
["Intercept"] = 198304,
["Spell Reflection"] = 23920,
["Battle Shout"] = 6673,
["Revenge"] = 6572,
["Pummel"] = 6552,
["Heroic Leap"] = 6544,
["Victory Rush"] = 34428,
["Heroic Throw"] = 57755,
["Thunder Clap"] = 6343,
},
["Arms_Talents"] = {
["Warbreaker"] = 262161,
["Rend"] = 772,
["Skullsplitter"] = 260643,
["Defensive Stance"] = 197690,
["Deadly Calm"] = 262228,
["Impending Victory"] = 202168,
["Storm Bolt"] = 107570,
["Ravager"] = 152277,
["Cleave"] = 845,
["Avatar"] = 107574,
},
["Fury"] = {
["Taunt"] = 355,
["Intimidating Shout"] = 5246,
["Execute"] = 5308,
["Whirlwind"] = 190411,
["Rampage"] = 184367,
["Piercing Howl"] = 12323,
["Bloodthirst"] = 23881,
["Raging Blow"] = 85288,
["Recklessness"] = 1719,
["Rallying Cry"] = 97462,
["Battle Shout"] = 6673,
["Charge"] = 100,
["Pummel"] = 6552,
["Enraged Regeneration"] = 184364,
["Heroic Leap"] = 6544,
["Victory Rush"] = 34428,
["Heroic Throw"] = 57755,
["Berserker Rage"] = 18499,
},
["Fury_Talents"] = {
["Impending Victory"] = 202168,
["Storm Bolt"] = 107570,
["Bladestorm"] = 46924,
["Dragon Roar"] = 118000,
["Siegebreaker"] = 280772,
["Furious Slash"] = 100130,
},
["Protection_PVPTalents"] = {
["Spell Reflection"] = 216890,
["Death Wish"] = 199261,
["Gladiator's Medallion"] = 208683,
["Disarm"] = 236077,
["Sharpen Blade"] = 198817,
["War Banner"] = 236320,
["Duel"] = 236273,
},
["Fury_PVPTalents"] = {
["Spell Reflection"] = 216890,
["Death Wish"] = 199261,
["Gladiator's Medallion"] = 208683,
["Disarm"] = 236077,
["Sharpen Blade"] = 198817,
["War Banner"] = 236320,
["Duel"] = 236273,
},
["Arms_PVPTalents"] = {
["Spell Reflection"] = 216890,
["Death Wish"] = 199261,
["Gladiator's Medallion"] = 208683,
["Disarm"] = 236077,
["Sharpen Blade"] = 198817,
["War Banner"] = 236320,
["Duel"] = 236273,
},
["Arms"] = {
["Battle Shout"] = 6673,
["Intimidating Shout"] = 5246,
["Execute"] = 163201,
["Whirlwind"] = 1680,
["Mortal Strike"] = 12294,
["Berserker Rage"] = 18499,
["Overpower"] = 7384,
["Hamstring"] = 1715,
["Sweeping Strikes"] = 260708,
["Rallying Cry"] = 97462,
["Colossus Smash"] = 167105,
["Charge"] = 100,
["Die by the Sword"] = 118038,
["Bladestorm"] = 227847,
["Slam"] = 1464,
["Pummel"] = 6552,
["Heroic Leap"] = 6544,
["Victory Rush"] = 34428,
["Heroic Throw"] = 57755,
["Taunt"] = 355,
},
["Protection_Talents"] = {
["Dragon Roar"] = 118000,
["Ravager"] = 228920,
["Impending Victory"] = 202168,
["Storm Bolt"] = 107570,
},
["METADATA"] = {
["Specs"] = {
["Fury"] = 72,
["Arms"] = 71,
["Protection"] = 73,
},
},
},
};
 
 
-- Helper functions: Default lookup priorities, etc --
------------------------------------------------------
 
LibSN2SID.libLocal = {
playerUniversalClassName = "", -- Player only, gathered upon PLAYER_LOGIN
playerUniversalRaceName = "", -- Player only, gathered upon PLAYER_LOGIN
petFamily = "",
 
FactionSpells = {
-- currrentFaction = "",
["Alliance"] = {
["MAGE"] = {
["Flyouts"] = {
["Portal"] = {
["Portal: Vale of Eternal Blossoms"] = 132620,
["Portal: Shattrath"] = 33691,
["Portal: Tol Barad"] = 88345,
},
["Teleport"] = {
["Teleport: Vale of Eternal Blossoms"] = 132621,
["Teleport: Shattrath"] = 33690,
["Teleport: Tol Barad"] = 88342,
},
},
},
},
["Horde"] = {
["MAGE"] = {
["Flyouts"] = {
["Portal"] = {
["Portal: Vale of Eternal Blossoms"] = 132626,
["Portal: Shattrath"] = 35717,
["Portal: Tol Barad"] = 88346,
},
["Teleport"] = {
["Teleport: Vale of Eternal Blossoms"] = 132627,
["Teleport: Shattrath"] = 35715,
["Teleport: Tol Barad"] = 88344,
},
},
},
},
["Neutral"] = { -- For Pandarens who haven't chosen their faction yet
},
},
};
LibSN2SID.SetFaction = function(faction, instanceName) -- TODO: Move to section "API" bellow !
-- print(LibSpellName2SID_MAJOR.. ": 2. Player faction = ".. tostring(faction));
assert((faction == "Alliance") or (faction == "Horde") or (faction == "Neutral"), "Bad argument #1 to LibSpellName2SID.SetFaction(); must be either \"Alliance\" or \"Horde\" (or possibly \"Neutral\").");
if not LibSN2SID.clients then
LibSN2SID.clients = {};
end
if not LibSN2SID.clients[instanceName] then
assert(instanceName == LibSpellName2SID_MAJOR, "Bad argument #2 to LibSpellName2SID.SetFaction(); must be a registered instance of ".. LibSpellName2SID_MAJOR);
end
-- print(LibSpellName2SID_MAJOR.. ": LibSpellName2SID.SetFaction called with instanceName = ".. tostring(instanceName));
-- print(LibSpellName2SID_MAJOR.. ": 2. Player currrentFaction = ".. tostring(LibSN2SID.libLocal.FactionSpells.currrentFaction));
if not LibSN2SID.clients[instanceName].SID then
LibSN2SID.clients[instanceName].SID = {};
LibSN2SID.clients[instanceName].LSN = {};
end
if not LibSN2SID.clients[instanceName].SID.FactionSpells then
LibSN2SID.clients[instanceName].SID.FactionSpells = {};
LibSN2SID.clients[instanceName].LSN.FactionSpells = {};
end
if not LibSN2SID.clients[instanceName].SID.FactionSpells.currentFaction then
LibSN2SID.clients[instanceName].SID.FactionSpells.currentFaction = "";
LibSN2SID.clients[instanceName].LSN.FactionSpells.currentFaction = "";
end
-- Sanity checks and fallback setups done. Now put the new faction spells into place if needed
if faction ~= LibSN2SID.clients[instanceName].SID.FactionSpells.currentFaction then
LibSN2SID.clients[instanceName].SID.FactionSpells.currentFaction = faction;
LibSN2SID.clients[instanceName].LSN.FactionSpells.currentFaction = faction;
local factionSpells_table = LibSN2SID.libLocal.FactionSpells[faction]; -- For human readers
-- Copy the spells from the apropriate table of faction sepcifics table to this lib instance
local classIndex = 1;
local classKey = (next(factionSpells_table, nil));
if not classKey then -- "Neutral" faction has no ... faction spells.
return false;
end
if not LibSN2SID.clients[instanceName].SID.FactionSpells[classKey] then
LibSN2SID.clients[instanceName].SID.FactionSpells[classKey] = {};
LibSN2SID.clients[instanceName].LSN.FactionSpells[classKey] = {};
end
while classKey do
-- print(LibSpellName2SID_MAJOR.. ": ".. classIndex.. ": ".. classKey);
-- print(LibSpellName2SID_MAJOR.. ": type of factionSpells_table[classKey] = ".. tostring(type(factionSpells_table[classKey])));
local specIndex = 1;
local specKey = (next(factionSpells_table[classKey], nil));
if not LibSN2SID.clients[instanceName].SID.FactionSpells[classKey][specKey] then
LibSN2SID.clients[instanceName].SID.FactionSpells[classKey][specKey] = {};
LibSN2SID.clients[instanceName].LSN.FactionSpells[classKey][specKey] = {};
end
while specKey do
-- print(LibSpellName2SID_MAJOR.. ": ".. classIndex.. ".".. specIndex.. ": ".. tostring(specKey));
local contentIndex = 1;
local contentKey = (next(factionSpells_table[classKey][specKey], nil));
while contentKey do
-- print(LibSpellName2SID_MAJOR.. ": ".. classIndex.. ".".. specIndex.. ".".. contentIndex.. ": ".. contentKey);
if type(factionSpells_table[classKey][specKey][contentKey]) == "table" then -- "Flyouts"->Button or "Pets"->Pet
local spellIndex = 1;
local spellKey = (next(factionSpells_table[classKey][specKey][contentKey], nil));
if not LibSN2SID.clients[instanceName].SID.FactionSpells[classKey][specKey][contentKey] then
LibSN2SID.clients[instanceName].SID.FactionSpells[classKey][specKey][contentKey] = {};
LibSN2SID.clients[instanceName].LSN.FactionSpells[classKey][specKey][contentKey] = {};
end
while spellKey do
-- print(LibSpellName2SID_MAJOR.. ": ".. classIndex.. ".".. specIndex.. ".".. contentIndex.. ".".. spellIndex.. ": ".. spellKey);
LibSN2SID.clients[instanceName].SID.FactionSpells[classKey][specKey][contentKey][spellKey] = factionSpells_table[classKey][specKey][contentKey][spellKey];
LibSN2SID.clients[instanceName].LSN.FactionSpells[classKey][specKey][contentKey][spellKey] = factionSpells_table[classKey][specKey][contentKey][spellKey];
-- print(LibSpellName2SID_MAJOR.. ": LibSN2SID.DB\[".. classKey.. "\]\[".. specKey.. "\]\[".. contentKey.. "\]\["..
spellKey = (next(factionSpells_table[classKey][specKey][contentKey], spellKey));
spellIndex = spellIndex + 1;
end
 
else
 
LibSN2SID.clients[instanceName].SID.FactionSpells[classKey][specKey][contentKey] = factionSpells_table[classKey][specKey][contentKey];
LibSN2SID.clients[instanceName].LSN.FactionSpells[classKey][specKey][contentKey] = factionSpells_table[classKey][specKey][contentKey];
end
contentKey = (next(factionSpells_table[classKey][specKey], contentKey));
contentIndex = contentIndex + 1;
end
specKey = (next(factionSpells_table[classKey], specKey));
specIndex = specIndex + 1;
end
classKey = (next(factionSpells_table, classKey));
classIndex = classIndex + 1;
end
end
end
LibSN2SID.libLocal.SetDefaultFaction = function(instanceName)
local instanceName = instanceName or LibSpellName2SID_MAJOR;
if instanceName == LibSpellName2SID_MAJOR then
LibSN2SID.clients[LibSpellName2SID_MAJOR] = {};
end
local englishFaction, _ = UnitFactionGroup("player");
-- print(LibSpellName2SID_MAJOR.. ": 1. Player faction = ".. tostring(englishFaction));
LibSN2SID.SetFaction(englishFaction, instanceName);
if instanceName == LibSpellName2SID_MAJOR then
-- for k, v in pairs(LibSN2SID.clients) do
local instName = (next(LibSN2SID.clients, nil));
while instName do
if (instName ~= LibSpellName2SID_MAJOR) then
if (not LibSN2SID.clients[instName].FactionSpells) or (not LibSN2SID.clients[instName].FactionSpells.currentFaction) or (LibSN2SID.clients[instName].FactionSpells.currentFaction == "") then
-- print(LibSpellName2SID_MAJOR.. ": Default faction set to reserved instance name \'".. LibSpellName2SID_MAJOR.. "\'. Will now set the same faction to instance ".. instName);
LibSN2SID.SetFaction(englishFaction, instName);
end
end
instName = (next(LibSN2SID.clients, instName));
end
end
end
 
LibSN2SID.libLocal.GetEnglishSpecialisationName = function(specID, ...) -- Any class/spec
-- Arguments (1 to 2):
-- specID (number) *mandatory - Specialisation ID for which we want to get the English Name.
-- universalClassName (string) *optional - Class where the specialisation should be found;
-- Defaults to the current Player's class.
-- Returns (2):
-- engSpecName (string): English name for the given Specialisation; Nil if the spec wasn't
-- found.
-- uniClassName (string): Non-localised name of the Class the spec belongs to (given as arg2
-- or otherwise discovered if the given class was wrong or nil). Nil if the spec wasn't
-- found.
--
-- Look first in the provided universal class name (or the player class if argument is missing)
local lookupFirstInClass = ... or LibSN2SID.libLocal.playerUniversalClassName;
for engSpecName, DBspecID in pairs(LibSN2SID.DB[lookupFirstInClass].METADATA.Specs) do
if DBspecID == specID then
return engSpecName, lookupFirstInClass;
end
end
-- Look up the specialisation ID in all other classes
local generalTabName = (GetSpellTabInfo(1));
local uniClassName = (next(LibSN2SID.DB, nil));
while uniClassName do
if (uniClassName ~= generalTabName) and (uniClassName ~= lookupFirstInClass) then
for engSpecName, DBspecID in pairs(LibSN2SID.DB[uniClassName].METADATA.Specs) do
-- print(uniClassName);
if DBspecID == specID then
return engSpecName, uniClassName;
end
end
end
uniClassName = (next(LibSN2SID.DB, uniClassName));
end
-- Could not find the given specID in the database
return nil, nil;
end
 
LibSN2SID.libLocal.GetActiveEnglishSpecialisationName = function() -- Player only
-- Returns(3):
-- engSpecName (string) - English name for the active Player Specialisation; Nil if no spec
-- is active (e.g. if character level < 10).
-- uniClassName (string) - Non-localised name of the Player Class. Nil if no active spec.
-- activeSpecID (number) - Specialisation ID for the active spec. Nil if no active spec.
--
local activeSpecIndex = (GetSpecialization());
-- print(tostring(activeSpecIndex));
if activeSpecIndex then
local activeSpecID = (GetSpecializationInfo(activeSpecIndex));
-- print(tostring(activeSpecID));
return LibSN2SID.libLocal.GetEnglishSpecialisationName(activeSpecID, LibSN2SID.libLocal.playerUniversalClassName), activeSpecID;
else
return nil, nil, nil; -- Player does not have an active specialisation
end
end
 
LibSN2SID.libLocal.LookupOrder_table = {}; -- Any class/spec
 
-- Order to lookup spells in the DB:
-- 1st: Player's class:
-- 1.1. Active spec baseline spells;
-- 1.2. Active spec Talents' spells;
-- 1.3. Active spec PvP Talents' spells;
-- 1.4. Flyouts (if there are spells for);
-- 1.5. Pets (if there are spells for);
-- 1.5.1. Current pet specialization (if there is one) spells; NOT properly working, pet family
-- 1.5.2. Current pet fmaily (if there is one) spells; gets bumped up above pet specicalization
-- 1.6. Other specs' baseline spells;
-- 1.7. Other specs' Talents' spells;
-- 1.8. Other specs' PvP Talents' spells;
-- 2nd: GeneralTab;
-- 3rd: Other classes:
-- 3.1. Each spec baseline spells;
-- 3.2. Each spec Talents' spells;
-- 3.3. Each spec PvP Talents' spells;
-- 3.4. Flyouts (if there are spells for);
-- 3.5. Pets (if there are spells for).
 
LibSN2SID.libLocal.setCurrentPetFirstInLookupOrder = function()
local classKey = LibSN2SID.libLocal.playerUniversalClassName;
if LibSN2SID.libLocal.LookupOrder_table[classKey].Pets then
wipe(LibSN2SID.libLocal.LookupOrder_table[classKey].Pets);
else
local index = (LibSN2SID.DB[classKey].Flyouts and 5) or 4;
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey], index, "Pets");
LibSN2SID.libLocal.LookupOrder_table[classKey].Pets = {};
end
local petSpecName;
if classKey == "HUNTER" then
local petSpecIndex = (GetSpecialization(false, true));
petSpecName = (petSpecIndex == 1 and "Ferocity") or (petSpecIndex == 2 and
"Tenacity") or (petSpecIndex == 3 and "Cunning") or nil;
-- print(tostring(petSpecIndex).. " : ".. tostring(petSpecName));
end
local petKey = (next(LibSN2SID.DB[classKey].Pets, nil));
while petKey do
if petSpecName and petKey == petSpecName then
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey].Pets, 1, petKey);
elseif LibSN2SID.libLocal.petFamily and petKey == LibSN2SID.libLocal.petFamily then
local index = (petSpecName and LibSN2SID.libLocal.LookupOrder_table[classKey].Pets[petSpecName] and 2) or 1;
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey].Pets, index, petKey);
else
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey].Pets, petKey);
end
petKey = (next(LibSN2SID.DB[classKey].Pets, petKey));
end
end
 
LibSN2SID.libLocal.SetLookupOrder = function()
-- LibSN2SID.libLocal.LookupOrder_table = {}; -- Reset the table
wipe(LibSN2SID.libLocal.LookupOrder_table); -- Reset the table
local classOrderIndex = 1;
local classKey = (next(LibSN2SID.DB, nil));
-- print(tostring(classKey));
while classKey do
if classKey == LibSN2SID.libLocal.playerUniversalClassName then -- Current player class
tinsert(LibSN2SID.libLocal.LookupOrder_table, 1, classKey);
LibSN2SID.libLocal.LookupOrder_table[classKey] = {};
-- print(tostring(LibSN2SID.libLocal.LookupOrder_table[1]));
-- Order specs et al
local playerActiveEnglishSpecName = (LibSN2SID.libLocal.GetActiveEnglishSpecialisationName());
-- print("Active SpecName = ".. tostring(playerActiveEnglishSpecName));
local specKey = (next(LibSN2SID.DB[classKey].METADATA.Specs, nil));
while specKey do
if specKey == playerActiveEnglishSpecName then
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey], 1, specKey);
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey], 2, specKey.."_Talents");
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey], 3, specKey.."_PVPTalents");
-- print(tostring(LibSN2SID.libLocal.LookupOrder_table[classKey][1]).. " *");
-- elseif LibSN2SID.DB[classKey].METADATA.Specs[specKey] then
else
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey], specKey);
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey], specKey.."_Talents");
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey], specKey.."_PVPTalents");
end
specKey = (next(LibSN2SID.DB[classKey].METADATA.Specs, specKey));
end
if LibSN2SID.DB[classKey].Flyouts then
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey], 4, "Flyouts");
LibSN2SID.libLocal.LookupOrder_table[classKey].Flyouts = {};
local flyoutButtonKey = (next(LibSN2SID.DB[classKey].Flyouts, nil));
while flyoutButtonKey do
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey].Flyouts, flyoutButtonKey);
flyoutButtonKey = (next(LibSN2SID.DB[classKey].Flyouts, flyoutButtonKey));
end
end
if LibSN2SID.DB[classKey].Pets then
LibSN2SID.libLocal.setCurrentPetFirstInLookupOrder();
end
elseif classKey ~= "General" then -- Other classes
tinsert(LibSN2SID.libLocal.LookupOrder_table, classKey);
-- print(tostring(LibSN2SID.libLocal.LookupOrder_table[classOrderIndex]));
LibSN2SID.libLocal.LookupOrder_table[classKey] = {};
local specKey = (next(LibSN2SID.DB[classKey].METADATA.Specs, nil));
while specKey do
-- local numSpecSubTables = 3; -- Unless we also have Flyouts, making it 4 or more
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey], specKey);
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey], specKey.."_Talents");
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey], specKey.."_PVPTalents");
specKey = (next(LibSN2SID.DB[classKey].METADATA.Specs, specKey));
end
if LibSN2SID.DB[classKey].Flyouts then
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey], "Flyouts");
LibSN2SID.libLocal.LookupOrder_table[classKey].Flyouts = {};
local flyoutButtonKey = (next(LibSN2SID.DB[classKey].Flyouts, nil));
while flyoutButtonKey do
-- print(LibSpellName2SID_MAJOR.. ": ".. tostring(flyoutButtonKey));
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey].Flyouts, flyoutButtonKey);
flyoutButtonKey = (next(LibSN2SID.DB[classKey].Flyouts, flyoutButtonKey));
end
end
if LibSN2SID.DB[classKey].Pets then
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey], "Pets");
LibSN2SID.libLocal.LookupOrder_table[classKey].Pets = {};
local petKey = (next(LibSN2SID.DB[classKey].Pets, nil));
while petKey do
tinsert(LibSN2SID.libLocal.LookupOrder_table[classKey].Pets, petKey);
petKey = (next(LibSN2SID.DB[classKey].Pets, petKey));
end
end
end
classKey = (next(LibSN2SID.DB, classKey));
classOrderIndex = classOrderIndex + 1;
end
tinsert(LibSN2SID.libLocal.LookupOrder_table, 2, "General");
LibSN2SID.libLocal.LookupOrder_table["General"] = {};
local categoryKey = (next(LibSN2SID.DB.General, nil));
while categoryKey do
if categoryKey == "Racials" then
tinsert(LibSN2SID.libLocal.LookupOrder_table.General, "Racials");
LibSN2SID.libLocal.LookupOrder_table.General.Racials = {};
local racialKey = (next(LibSN2SID.DB.General.Racials, nil));
while racialKey do
if racialKey == LibSN2SID.libLocal.playerUniversalRaceName then
tinsert(LibSN2SID.libLocal.LookupOrder_table.General.Racials, 1, racialKey);
else
tinsert(LibSN2SID.libLocal.LookupOrder_table.General.Racials, racialKey);
end
racialKey = (next(LibSN2SID.DB.General.Racials, racialKey));
end
-- elseif categoryKey ~= "METADATA" then -- Currentlu not in the database
else
tinsert(LibSN2SID.libLocal.LookupOrder_table.General, categoryKey);
end
categoryKey = (next(LibSN2SID.DB.General, categoryKey));
end
end
 
 
-- API --
---------
 
-- Return SpellID of the English Spell Name --
LibSN2SID.libLocal.instanceSID = {};
LibSN2SID.libLocal.instanceSID.stub = { ["stub"] = 0 };
LibSN2SID.libLocal.instanceSID.metaT = {};
LibSN2SID.libLocal.instanceSID.new = function(instObj)
setmetatable(instObj, LibSN2SID.libLocal.instanceSID.metaT);
return instObj;
end
 
LibSN2SID.libLocal.instanceSID.metaT.__index = function(tbl, engSpellName) -- If spell name not found in 'tbl'.
local paramType = type(engSpellName);
-- print(LibSpellName2SID_MAJOR.. ": ".. engSpellName.. " is a ".. paramType);
if (paramType == "string") then
for classIndex = 1, #LibSN2SID.libLocal.LookupOrder_table do
local classKey = LibSN2SID.libLocal.LookupOrder_table[classIndex];
-- print(LibSpellName2SID_MAJOR.. ": ".. tostring(classKey));
for specIndex = 1, #(LibSN2SID.libLocal.LookupOrder_table[classKey]) do
local specKey = LibSN2SID.libLocal.LookupOrder_table[classKey][specIndex];
local spID = LibSN2SID.DB[classKey][specKey][engSpellName] or nil;
if spID then
return spID; -- FOUND IT!
end
-- if specKey == "Flyouts" or specKey == "Pets" then
if LibSN2SID.libLocal.LookupOrder_table[classKey][specKey] ~= nil and type(LibSN2SID.libLocal.LookupOrder_table[classKey][specKey]) == "table" then
local subTableKey = (next(LibSN2SID.DB[classKey][specKey], nil));
while subTableKey do
-- print(tostring(classKey).. " ".. tostring(specKey).. " ".. tostring(subTableKey));
local spID = LibSN2SID.DB[classKey][specKey][subTableKey][engSpellName] or nil;
if spID then
return spID; -- FOUND IT!
end
subTableKey = (next(LibSN2SID.DB[classKey][specKey], subTableKey));
end
end
 
if tbl and tbl.FactionSpells and tbl.FactionSpells[classKey] and tbl.FactionSpells[classKey][specKey] then
-- print(LibSpellName2SID_MAJOR.. ": Looking for \'".. engSpellName.. "\' in client: ".. instanceName);
local spID = tbl.FactionSpells[classKey][specKey][engSpellName] or nil;
if spID then
return spID; -- FOUND IT!
end
 
if LibSN2SID.libLocal.LookupOrder_table[classKey][specKey] ~= nil and type(LibSN2SID.libLocal.LookupOrder_table[classKey][specKey]) == "table" then
local subTableKey = (next(tbl.FactionSpells[classKey][specKey], nil));
while subTableKey do
-- print(tostring(classKey).. " ".. tostring(specKey).. " ".. tostring(subTableKey));
local spID = tbl.FactionSpells[classKey][specKey][subTableKey][engSpellName] or nil;
if spID then
return spID; -- FOUND IT!
end
subTableKey = (next(tbl.FactionSpells[classKey][specKey], subTableKey));
end
end
end
end
end
-- Didn't find the given spell name in our database. So try and get it from game API
local locSpellName, _, _, _, _, _, spID = GetSpellInfo(engSpellName);
return spID;
elseif (paramType == "number") then
local locSpellName = (GetSpellInfo(engSpellName));
-- print(tostring(locSpellName));
if locSpellName then
return engSpellName;
else
return nil;
end
else
-- TODO: error() ?
return nil;
end
end
 
-- Return Localised Name of the English Spell Name --
LibSN2SID.libLocal.instanceLSN = {};
LibSN2SID.libLocal.instanceLSN.stub = { ["stub"] = 0 };
LibSN2SID.libLocal.instanceLSN.metaT = {};
LibSN2SID.libLocal.instanceLSN.new = function(instObj)
setmetatable(instObj, LibSN2SID.libLocal.instanceLSN.metaT);
return instObj;
end
LibSN2SID.libLocal.instanceLSN.metaT.__index = function(tbl, engSpellName)
-- print("LSN __index");
local paramType = type(engSpellName);
-- print(LibSpellName2SID_MAJOR.. ": ".. engSpellName.. " is a ".. paramType);
if paramType == "string" then
for classIndex = 1, #LibSN2SID.libLocal.LookupOrder_table do
local classKey = LibSN2SID.libLocal.LookupOrder_table[classIndex];
-- print(LibSpellName2SID_MAJOR.. ": ".. tostring(classKey));
for specIndex = 1, #(LibSN2SID.libLocal.LookupOrder_table[classKey]) do
local specKey = LibSN2SID.libLocal.LookupOrder_table[classKey][specIndex];
-- print(LibSpellName2SID_MAJOR.. ": ".. tostring(specKey));
local spID = LibSN2SID.DB[classKey][specKey][engSpellName] or nil;
if spID then
-- print("Found in ".. classKey.. ": ".. specKey);
local locSpellName = (GetSpellInfo(spID)); -- Localised spell name
return locSpellName; -- FOUND IT!
end
if LibSN2SID.libLocal.LookupOrder_table[classKey][specKey] ~= nil and type(LibSN2SID.libLocal.LookupOrder_table[classKey][specKey]) == "table" then
local subTableKey = (next(LibSN2SID.DB[classKey][specKey], nil));
while subTableKey do
-- print(tostring(classKey).. " ".. tostring(specKey).. " ".. tostring(subTableKey));
local spID = LibSN2SID.DB[classKey][specKey][subTableKey][engSpellName] or nil;
if spID then
local locSpellName = (GetSpellInfo(spID)); -- Localised spell name
return locSpellName; -- FOUND IT!
end
subTableKey = (next(LibSN2SID.DB[classKey][specKey], subTableKey));
end
end
if tbl and tbl.FactionSpells and tbl.FactionSpells[classKey] and tbl.FactionSpells[classKey][specKey] then
-- print(LibSpellName2SID_MAJOR.. ": Looking for \'".. engSpellName.. "\' in client: ".. instanceName);
local spID = tbl.FactionSpells[classKey][specKey][engSpellName] or nil;
if spID then
local locSpellName = (GetSpellInfo(spID)); -- Localised spell name
return locSpellName; -- FOUND IT!
end
 
if LibSN2SID.libLocal.LookupOrder_table[classKey][specKey] ~= nil and type(LibSN2SID.libLocal.LookupOrder_table[classKey][specKey]) == "table" then
local subTableKey = (next(tbl.FactionSpells[classKey][specKey], nil));
while subTableKey do
-- print(tostring(classKey).. " ".. tostring(specKey).. " ".. tostring(subTableKey));
local spID = tbl.FactionSpells[classKey][specKey][subTableKey][engSpellName] or nil;
if spID then
local locSpellName = (GetSpellInfo(spID)); -- Localised spell name
return locSpellName; -- FOUND IT!
end
subTableKey = (next(tbl.FactionSpells[classKey][specKey], subTableKey));
end
end
end
end
end
-- Didn't find the given spell name in our database. So try and get it from game API
local locSpellName, _, _, _, _, _, spID = GetSpellInfo(engSpellName);
return locSpellName;
elseif paramType == "number" then
local locSpellName = (GetSpellInfo(engSpellName));
-- print(locSpellName);
return locSpellName;
else
-- TODO: error() ?
return nil;
end
end
 
 
-- Blizzard events used by the library --
-----------------------------------------
 
LibSN2SID.libFrame:RegisterEvent("PLAYER_LOGIN");
LibSN2SID.libLocal.lookupOrderTableInitialized = false;
LibSN2SID.libFrame:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED"); -- This talent and/or the one in the line bellow
LibSN2SID.libFrame:RegisterEvent("PLAYER_TALENT_UPDATE"); -- should fire when the player switches spec.
LibSN2SID.libFrame:RegisterUnitEvent("UNIT_PET", "player"); -- Fired when a unit's pet changes.
LibSN2SID.libFrame:RegisterEvent("PET_SPECIALIZATION_CHANGED"); -- Fired upon pet's specialisation changes.
LibSN2SID.libFrame:SetScript("OnEvent", function(self, event)
if event == "PLAYER_LOGIN" or event == "PLAYER_ENTERING_WORLD" then
local stubVal;
stubVal, LibSN2SID.libLocal.playerUniversalClassName = UnitClass("player");
stubVal, LibSN2SID.libLocal.playerUniversalRaceName = UnitRace("player");
LibSN2SID.libLocal.SetDefaultFaction(instanceName);
if UnitExists("pet") then -- Get current Pet data to build the corresponding lookup table
LibSN2SID.libLocal.petFamily = UnitCreatureFamily("pet");
end
LibSN2SID.libLocal.SetLookupOrder();
LibSN2SID.libLocal.lookupOrderTableInitialized = true;
elseif LibSN2SID.libLocal.lookupOrderTableInitialized then
if event == "UNIT_PET" or event == "PET_SPECIALIZATION_CHANGED" then
if not LibSN2SID.libLocal.playerUniversalClassName or not LibSN2SID.libLocal.LookupOrder_table[LibSN2SID.libLocal.playerUniversalClassName] then
return; -- Build lookup table for Pet only after we built the lookup table for Class
end
LibSN2SID.libLocal.petFamily = UnitCreatureFamily("pet");
if not LibSN2SID.libLocal.petFamily then -- UNIT_PET fires several times when a pet
return; -- is lost and when a new one is called; we'll get the new pet
end -- info eventually, but we'll wait til it's up.
LibSN2SID.libLocal.setCurrentPetFirstInLookupOrder();
else
LibSN2SID.libLocal.SetLookupOrder();
end
end
-- for i = 1, #LibSN2SID.libLocal.LookupOrder_table do
-- local classKey = LibSN2SID.libLocal.LookupOrder_table[i];
-- print(LibSpellName2SID_MAJOR.. ": ".. i.. ". ".. tostring(classKey));
-- for ii = 1, #(LibSN2SID.libLocal.LookupOrder_table[classKey]) do
-- local specKey = LibSN2SID.libLocal.LookupOrder_table[classKey][ii];
-- print(LibSpellName2SID_MAJOR.. ": ".. i.. ".".. ii.. ". ".. tostring(specKey));
-- if type(LibSN2SID.libLocal.LookupOrder_table[classKey][specKey]) == "table" then
-- for iii = 1, #(LibSN2SID.libLocal.LookupOrder_table[classKey][specKey]) do
-- local subTableKey = LibSN2SID.libLocal.LookupOrder_table[classKey][specKey][iii];
-- print(LibSpellName2SID_MAJOR.. ": ".. i.. ".".. ii.. ".".. iii.. ". ".. tostring(subTableKey));
-- end
-- end
-- end
-- end
end);
 
 
-- Library Instances Registration and Removal --
------------------------------------------------
 
-- Register a new instance of this library
function LibSN2SID:NewInstance(instanceName)
-- print(LibSpellName2SID_MAJOR.. ": Just started function LibSN2SID:NewInstance(".. instanceName.. ")");
if (type(instanceName) ~= "string") or (instanceName == "") then
error("Must provide a valid instanceName (unique string) to the new library instance of ".. LibSpellName2SID_MAJOR.. ".");
elseif instanceName == LibSpellName2SID_MAJOR then
error("Cannot create a new instance of ".. LibSpellName2SID_MAJOR.. "with the name".. LibSpellName2SID_MAJOR.. " (that name is reserved).");
elseif LibSN2SID.clients and LibSN2SID.clients[instanceName] then
error("Will not create a duplicate instance of ".. LibSpellName2SID_MAJOR.. ", with the already existing name: ".. instanceName.. ".");
end
 
LibSN2SID.clients = LibSN2SID.clients or {};
LibSN2SID.clients[instanceName] = {};
LibSN2SID.clients[instanceName].SID = LibSN2SID.clients[instanceName].SID or {};
LibSN2SID.clients[instanceName].LSN = LibSN2SID.clients[instanceName].LSN or {};
 
LibSN2SID.clients[instanceName].SID = LibSN2SID.libLocal.instanceSID.new(LibSN2SID.clients[instanceName].SID);
LibSN2SID.clients[instanceName].LSN = LibSN2SID.libLocal.instanceLSN.new(LibSN2SID.clients[instanceName].LSN);
return LibSN2SID;
end
 
-- Remove an instance of this library, if the data isn't needed anymore
function LibSN2SID:RemoveInstance(instanceName, ...)
-- print(LibSpellName2SID_MAJOR.. ": RemoveInstance: ".. tostring(instanceName));
local DontErrorOnInexistentInstanceName = ... or false;
 
if (type(instanceName) ~= "string") or (instanceName == "") then
error("Must provide a valid instanceName (string) of the ".. LibSpellName2SID_MAJOR.. " library, to cleanup.");
elseif instanceName == LibSpellName2SID_MAJOR then
error("Will not remove base-instance \"".. instanceName.. "\" of library ".. LibSpellName2SID_MAJOR.. ".");
elseif (not LibSN2SID.clients) or (not LibSN2SID.clients[instanceName]) then
if DontErrorOnInexistentInstanceName then
return false;
else
error("Cannot clean up instance of ".. LibSpellName2SID_MAJOR.. ", with name: ".. instanceName.. " (non existent).");
end
end
 
LibSN2SID.clients[instanceName] = nil;
return LibSN2SID.clients[instanceName];
end
 
 
-- Get the number of spells in the database
-- TODO: Redo for new DB structure in 10008+ !
-- function LibSN2SID:GetNumSpells()
-- error("This function is not implemented in the current versions of ".. LibSpellName2SID_MAJOR.. ": ".. LibAlkaTest_MINOR);
-- local count = 0;
-- for _ in pairs(LibSN2SID.DB) do
-- count = count + 1;
-- end
-- return count;
-- end
 
 
------------------------------------------
-- print(LibSpellName2SID_MAJOR.. ": LibSN2SID.DB has ".. LibSN2SID.GetNumSpells().. " keys.");
tags/LibSpellName2SID-1.1.03/LibSpellName2SID-1.1.toc New file
0,0 → 1,19
## Interface: 80105
## Title: Lib: SpellName2SID-1.1
## Notes: Table of English Spell Names and corresponding Spell IDs
## Version: 1.1.03
## LoadOnDemand: 1
## Author: aallkkaa
## X-Original-Author: twobits
## X-Credits: benots4
## X-Category: Library
## X-WoWI-ID: 24509
 
LibStub\LibStub.lua
 
LibSpellName2SID-1.1\LibSpellName2SID-1.1.lua
 
#test1.lua
#test2.lua
#test3.lua
#test4.lua
trunk/LibSpellName2SID-1.1/LibSpellName2SID-1.1/LibSpellName2SID-1.1.lua
3,7 → 3,7
-- V.10000: 2009 originally by Twobits[1], as part of ReadySpells[2]
-- 2010 edited by benots4[3]
-- 2017 published as an addon of its own by aallkkaa[4]
-- V.10001 - 10102: 2017-2019 WoW 7.3.x to 8.0.1 versions by aallkkaa [4]
-- V.10001 - 10103: 2017-2019 WoW 7.3.x to 8.x versions by aallkkaa [4]
--
-- [1] https://www.wowinterface.com/forums/member.php?userid=139157
-- https://www.curseforge.com/members/twobits
38,7 → 38,7
 
-- Library's version values --
local LibSpellName2SID_MAJOR = "LibSpellName2SID-1.1";
local LibSpellName2SID_MINOR = 10102;
local LibSpellName2SID_MINOR = 10103;
 
-- DataSource --
-- gameBuild = 29981
923,6 → 923,9
["Survival of the Fittest"] = 264735,
["Growl"] = 2649,
},
["Blood Beast"] = {
["Blood Bolt"] = 288962,
},
},
["Survival"] = {
["Harpoon"] = 190925,
trunk/LibSpellName2SID-1.1/LibSpellName2SID-1.1.toc
1,7 → 1,7
## Interface: 80105
## Title: Lib: SpellName2SID-1.1
## Notes: Table of English Spell Names and corresponding Spell IDs
## Version: 1.1.02
## Version: 1.1.03
## LoadOnDemand: 1
## Author: aallkkaa
## X-Original-Author: twobits
populator/tags/LibSpellName2SID-Populator-1.1.03/LibSpellName2SID-1.1-Populator.lua New file
0,0 → 1,2348
----------
-- (C) 2017-2019 by aallkkaa
-- http://www.wowinterface.com/forums/member.php?action=getinfo&userid=335646
--
-- LibSpellName2SID-1.1: Populator
-- Notes: Populates the library's database
-- http://svn.wowinterface.com/listing.php?repname=LibSpellName2ID&path=%2Fpopulator%2F#_populator_
----------
local AddonName, AddonEnv = ...;
 
-- Local copies of the saved variables' tables: SpellNamesAndIDs, SpellNamesAndIDs_PASSIVES and DEBUG_messages
local SN2SID_table, SN2SID_PASSIVES_table, DEBUGmsgs;
 
-- Variables for debugging
local DBG_CurrentEvent = "" -- Event last fired when a task is being done
 
-- WoW Expansion/Patch constants
local NumberOfTalentTiers = 7; -- Current number of talent tiers - WoW-7.x.y and 8.x.y
-- local NumberOfPVPTalentTiers = 6; -- Current number of PVP talent tiers - WoW-7.x.y
local NumberOfPVPTalentSlots = 4; -- Current number of PVP talent tiers - WoW-8.x.y
 
-- (Usually) One-time ferched values
local generalTabName, universalRaceName, universalClassName;
local petFamily, petSpec;
 
-- "Manually" added/modified spells - normally AFTER regular update functions were called
local postUpdate_Spells2Add = {
["General"] = {
["ZoneAbilities"] = {
-- TODO: Maybe a hooksecurefunc(ZoneAbilityFrame, "Show", function())?
-- Also check: /dump Enum.ZoneAbilityType
-- Dump: value=Enum.ZoneAbilityType
-- [1]={
-- Argus=2,
-- OrderHall=1,
-- Garrison=0
-- }
--
-- Draenor -- These are never added to the Spellbook
["Garrison Ability"] = 161691, -- Cast the Garrison/Outpost ability active on the zone
["Call to Arms"] = 161676, -- Shadowmoon Valley / Frostfire Ridge
["Champion's Honor"] = 164221, -- Gorgrond outpost
["Summon Mechashredder 5000"] = 164050, -- Gorgrond outpost
["Telaari Siege Engine"] = 160240, -- Nagrand
["Telaari Talbuk"] = 165803, -- Nagrand (Alliance)
["Frostwolf War Wolf"] = 164222, -- Nagrand (Horde)
["Home Away from Home"] = 168487, -- Spires of Arak
["Smuggling Run!"] = 170108, -- Spires of Arak
["Artillery Strike"] = 162075, -- Talador outpost
["Guardian Orb"] = 161767, -- Talador outpost
["Logging"] = 167895, -- Mark lumber for gathering in Draenor (requires logging camp)
-- Broken Isles
["Combat Ally"] = 211390,
-- Argus
["Vindicaar Matrix Crystal"] = 251463, -- Cast the one active of the other four
["Light's Judgment"] = 247427, -- Same name, different ID, than that of the Lightforged
-- Draenei Racial spell.
["Summon Lightforged Warframe"] = 250436,
["Fel Heart Bond"] = 248011, -- Passive workings? - tooltip says "Instant"
["Shroud of Arcane Echoes"] = 248779,
},
},
["DEATHKNIGHT"] = {
["Blood"] = {
["Corpse Exploder"] = 127344, -- Cosmetic ability learned from tome
},
["Frost"] = {
["Corpse Exploder"] = 127344, -- Cosmetic ability learned from tome
},
["Unholy"] = {
["Corpse Exploder"] = 127344, -- Cosmetic ability learned from tome
},
--[[
["Pets"] = {
["Ghoul"] = {
-- The spell "Dark Transformation" used to temporarily change the Ghoul's regular
-- abilities into different ones (different names and IDs). Dark Transformation is
-- still in the game and still modifies the Ghoul's abilities, but these changes are
-- now "rolled into" the Ghoul's standard abilities; the old different ones can still
-- be referenced by their old spell IDs, but no longer by their names (even though
-- GetSpellInfo()* does return the spell name if queried through its ID).
-- Bottomline: For the purpose of doing anything with using these spells' name as
-- arguments, they are no longer existent.
-- * C_Spell.DoesSpellExist(spellID) works for these spells, DoesSpellExist("spellName")
-- does not.
-- ["Sweeping Claws"] = 91778,
-- ["Monstrous Blow"] = 91797,
-- ["Shambling Rush"] = 91802,
-- ["Putrid Bulwark"] = 91837,
-- The regular spells:
["Claw"] = 47468,
["Gnaw"] = 47481,
["Leap"] = 47482,
["Huddle"] = 47484,
},
-- The Unholy spec talent "Sludge Belcher" which summoned an Abomination instead of a
-- Ghoul before 8.0.1 is no longer ingame. I.e. this type of DK pet is now gone.
-- ["Abomination"] = { -- If the talent 'Sludge Belcher' is taken, the Ghoul becomes an
-- -- 'Abomination' instead.
-- ["Cleaver"] = 212333,
-- ["Smash"] = 212336,
-- ["Hook"] = 212468,
-- ["Protective Bile"] = 212384,
-- -- 'Abomination' + 'Dark Transformation':
44 -- ["Vile Gas"] = 212338,
-- ["Gastric Bloat"] = 212383,
-- },
 
},
]]--
},
["DRUID"] = { -- The two different teleports + Abilities learned from Tomes
["Balance"] = {
-- The two different teleports
["Teleport: Moonglade"] = 18960, -- BEFORE the Legion Druid quest that gives:
["Dreamwalk"] = 193753, -- AFTER the Legion Druid quest: [98 - 110] To The Dreamgrove .
-- The Minimap ability "Track Humanoids" is NOT on the Spellbook. It does have a spell
-- ID that returns its name and all when passed as argument to GetSpellInfo(), but the
-- spell name itself is not recognized by GetSpellBookItemInfo(). Thus we will NOT add
-- it to our database.
-- ["Track Humanoids"] = 19883
-- Abilities learned from Tomes
["Charm Woodland Creature"] = 127757, -- Turn a critter into a minion for 1 hour
["Flap"] = 164862, -- Requires Moonkin Form; channeled, NO CD other than Global
["Stag Form"] = 210053, -- Proper shapeshift (unlike Treant?) == Ground Travel Form
-- ["Track Beasts"] = 210065, -- Cat Form only, can be simultaneous with "Track
-- Humanoids", but suffers from the same exact
-- not-in-Spellbook issue; hence excluded from the DB.
["Treant Form"] = 114282, -- Shapeshift form, appearance only (?); Reportedly randomly
-- switches position with Moonkin Form (WoW-7.0.2 in the
-- Stance Bar (relog and respec); unsure if fixed later on)
-- "Nature's Beacon" is a (Druid-only) TOY
},
["Feral"] = {
-- The two different teleports
["Teleport: Moonglade"] = 18960, -- BEFORE the Legion Druid quest that gives:
["Dreamwalk"] = 193753, -- AFTER the Legion Druid quest: [98 - 110] "To The Dreamgrove".
-- The Minimap ability "Track Humanoids" is NOT on the Spellbook. It does have a spell
-- ID that returns its name and all when passed as argument to GetSpellInfo(), but the
-- spell name itself is not recognized by GetSpellBookItemInfo(). Thus we will NOT add
-- it to our database.
-- ["Track Humanoids"] = 19883
-- Abilities learned from Tomes
["Charm Woodland Creature"] = 127757, -- Turn a critter into a minion for 1 hour
["Flap"] = 164862, -- Requires Moonkin Form; channeled, NO CD other than Global
["Stag Form"] = 210053, -- Proper shapeshift (unlike Treant?) == Ground Travel Form
-- ["Track Beasts"] = 210065, -- Cat Form only, can be simultaneous with "Track
-- Humanoids", but suffers from the same exact
-- not-in-Spellbook issue; hence excluded from the DB.
["Treant Form"] = 114282, -- Shapeshift form, appearance only (?); Reportedly randomly
-- switches position with Moonkin Form (WoW-7.0.2 in the
-- Stance Bar (relog and respec); unsure if fixed later on)
-- "Nature's Beacon" is a (Druid-only) TOY
},
["Guardian"] = {
-- The two different teleports
["Teleport: Moonglade"] = 18960, -- BEFORE the Legion Druid quest that gives:
["Dreamwalk"] = 193753, -- AFTER the Legion Druid quest: [98 - 110] "To The Dreamgrove".
-- The Minimap ability "Track Humanoids" is NOT on the Spellbook. It does have a spell
-- ID that returns its name and all when passed as argument to GetSpellInfo(), but the
-- spell name itself is not recognized by GetSpellBookItemInfo(). Thus we will NOT add
-- it to our database.
-- ["Track Humanoids"] = 19883
-- Abilities learned from Tomes
-- Abilities learned from Tomes
["Charm Woodland Creature"] = 127757, -- Turn a critter into a minion for 1 hour
["Flap"] = 164862, -- Requires Moonkin Form; channeled, NO CD other than Global
["Stag Form"] = 210053, -- Proper shapeshift (unlike Treant?) == Ground Travel Form
-- ["Track Beasts"] = 210065, -- Cat Form only, can be simultaneous with "Track
-- Humanoids", but suffers from the same exact
-- not-in-Spellbook issue; hence excluded from the DB.s
["Treant Form"] = 114282, -- Shapeshift form, appearance only (?); Reportedly randomly
-- switches position with Moonkin Form (WoW-7.0.2 in the
-- Stance Bar (relog and respec); unsure if fixed later on)
-- "Nature's Beacon" is a (Druid-only) TOY
},
["Restoration"] = {
-- The two different teleports
["Teleport: Moonglade"] = 18960, -- BEFORE the Legion Druid quest that gives:
["Dreamwalk"] = 193753, -- AFTER the Legion Druid quest: [98 - 110] "To The Dreamgrove".
-- The Minimap ability "Track Humanoids" is NOT on the Spellbook. It does have a spell
-- ID that returns its name and all when passed as argument to GetSpellInfo(), but the
-- spell name itself is not recognized by GetSpellBookItemInfo(). Thus we will NOT add
-- it to our database.
-- ["Track Humanoids"] = 19883
-- Abilities learned from Tomes
["Charm Woodland Creature"] = 127757, -- Turn a critter into a minion for 1 hour
["Flap"] = 164862, -- Requires Moonkin Form; channeled, NO CD other than Global
["Stag Form"] = 210053, -- Proper shapeshift (unlike Treant?) == Ground Travel Form
-- ["Track Beasts"] = 210065, -- Cat Form only, can be simultaneous with "Track
-- Humanoids", but suffers from the same exact
-- not-in-Spellbook issue; hence excluded from the DB.
["Treant Form"] = 114282, -- Shapeshift form, appearance only (?); Reportedly randomly
-- switches position with Moonkin Form (WoW-7.0.2 in the
-- Stance Bar (relog and respec); unsure if fixed later on)
-- "Nature's Beacon" is a (Druid-only) TOY
},
},
["HUNTER"] = {
-- TODO: SPECS --
["Beast Mastery"] = {
["Call Pet"] = 9,
["Pet Utility"] = 103,
},
["Marksmanship"] = {
["Call Pet"] = 9,
["Pet Utility"] = 103,
},
["Survival"] = {
["Call Pet"] = 9,
["Pet Utility"] = 103,
},
["FlyoutsTOGET"] = {
["Call Pet"] = 9,
["Pet Utility"] = 103,
},
["Pets"] = {
-- https://www.wowhead.com/battle-for-azeroth-hunter-pet-guide#hunter-pet-family-list-tenacity
["Ferocity"] = {
-- Some pets Bite, some pets Claw and some pets Smack
["Bite"] = 17253,
["Claw"] = 16827,
["Smack"] = 49966,
-- Specialization ability
["Primal Rage"] = 264667,
-- All Hunter pets (regardless of spec or family) have these two Basic abilities:
["Dash"] = 61684,
["Growl"] = 2649,
},
["Tenacity"] = {
-- - Some pets Bite, some pets Claw and some pets Smack
["Bite"] = 17253,
["Claw"] = 16827,
["Smack"] = 49966,
-- Specialization ability
["Survival of the Fittest"] = 272679,
-- All Hunter pets (regardless of spec or family) have these two Basic abilities:
["Dash"] = 61684,
["Growl"] = 2649,
},
["Cunning"] = {
-- - Some pets Bite, some pets Claw and some pets Smack
["Bite"] = 17253,
["Claw"] = 16827,
["Smack"] = 49966,
-- Specialization ability
["Master's Call"] = 53271,
-- All Hunter pets (regardless of spec or family) have these two Basic abilities:
["Dash"] = 61684,
["Growl"] = 2649,
},
-- We categorize Hunter Pet spells mainly by their specialiZations, but some pet
-- families also have Special abilites. And yes, same-name diff-ID spells do occur.
-- Spell types: Special, Bonus and Exotic
-- NB: The comment "8.x" bellow denotes I checked the pet on wowhead.com (or ingame)
-- during WoW 8.x, NOT that they were introduced only in WoW 8.x (though of course some
-- were).
["Basilisk"] = { -- 8.x
["Petrifying Gaze"] = 263841,
},
["Bat"] = { -- 8.x
["Sonic Blast"] = 264263,
},
["Bear"] = { -- 8.x
["Rest"] = 94019,
},
["Beetle"] = { -- 8.x
["Harden Carapace"] = 90339,
},
["Bird of Prey"] = { -- 8.x
["Talon Rend"] = 263852,
["Trick"] = 94022,
},
["Blood Beast"] = { -- 8.1
["Blood Bolt"] = 288962,
},
["Boar"] = { -- 8.x
["Bristle"] = 263869,
},
["Carrion Bird"] = { -- 8.x
["Bloody Screech"] = 24423,
},
["Cat"] = { -- 8.x
["Catlike Reflexes"] = 263892,
["Prowl"] = 24450,
},
["Chimaera"] = { -- 8.x
["Frost Breath"] = 54644,
["Froststorm Breath"] = 92380,
},
["Clefthoof"] = { -- 8.x
["Thick Hide"] = 160057,
["Blood of the Rhino"] = 280069,
},
["Core Hound"] = { -- 8.x
["Obsidian Skin"] = 263867,
["Molten Hide"] = 159788,
},
["Crab"] = { -- 8.x
["Pin"] = 50245,
},
["Crane"] = { -- 8.x
["Chi-Ji's Tranquility"] = 264028,
["Trick"] = 126259,
},
["Crocolisk"] = { -- 8.x
["Ankle Crack"] = 50433,
},
["Devilsaur"] = { -- 8.x
["Feast"] = 159953,
["Monstrous Bite"] = 54680,
},
["Direhorn"] = { -- 8.x
["Gore"] = 263861,
},
["Dog"] = { -- 8.x
["Lock Jaw"] = 263423,
},
["Dragonhawk"] ={ -- 8.x
["Dragon's Guile"] = 263887,
},
["Feathermane"] ={ -- 8.x
["Feather Flurry"] = 263916,
["Updraft"] = 160007,
},
["Fox"] = { -- 8.x
["Agile Reflexes"] = 160011,
["Play"] = 90347,
},
["Gorilla"] = { -- 8.x
["Silverback"] = 263939,
},
["Hydra"] = { -- 8.x
["Acid Bite"] = 263863,
},
["Hyena"] = { -- 8.x
["Infected Bite"] = 263853,
},
["Krolusk"] = { -- 8.x
["Bulwark"] = 279410,
},
["Lizard"] = { -- 8.x
["Grievous Bite"] = 279362,
},
["Mechanical"] = { -- 8.x
["Defense Matrix"] = 263868,
},
["Monkey"] = { -- 8.x
["Primal Agility"] = 160044,
},
["Moth"] = { -- 8.x
["Serenity Dust"] = 264055,
},
["Nether Ray"] = { -- 8.x
["Nether Shock"] = 264264,
},
["Oxen"] = { -- 8.x
["Niuzao's Fortitude"] = 264023,
},
["Pterrordax"] = { -- 8.x
["Ancient Hide"] = 279399,
["Updraft"] = 160007,
},
["Quilen"] = { -- 8.x
["Eternal Guardian"] = 267922,
["Stone Armor"] = 160049,
},
["Raptor"] = { -- 8.x
["Savage Rend"] = 263854,
},
["Ravager"] = { -- 8.x
["Ravage"] = 263857,
},
["Riverbeast"] = { -- 8.x
["Gruesome Bite"] = 160018,
},
["Rodent"] = { -- 8.x
["Gnaw"] = 263856,
["Rest"] = 126364,
},
-- ["Rylak"] = { -- Rylak have been merged into Chimaera in 8.x
-- ["Updraft"] = 160007,
-- },
["Scalehide"] = { -- 8.x
["Scale Shield"] = 263865,
},
["Scorpid"] = { -- 8.x
["Deadly Sting"] = 160060,
},
["Serpent"] = { -- 8.x
["Serpent's Swiftness"] = 263904,
},
["Shale Spider"] = { -- 8.x
["Solid Shell"] = 160063,
},
["Silithid"] = { -- 8.x
["Tendon Rip"] = 160065,
["Dune Strider"] = 280151,
},
["Spider"] = { -- 8.x
["Web Spray"] = 160067,
},
["Spirit Beast"] = { -- 8.x
["Spirit Shock"] = 264265,
["Spirit Mend"] = 90361,
["Spirit Walk"] = 90328,
},
["Sporebat"] = { -- 8.x
["Spore Cloud"] = 264056,
},
["Stag"] = { -- 8.x
["Nature's Grace"] = 264266,
},
["Tallstrider"] = { -- 8.x
["Dust Cloud"] = 50285,
},
["Toad"] = { -- 8.x
["Swarm of Flies"] = 279336,
},
["Turtle"] = { -- 8.x
["Shell Shield"] = 26064,
},
["Warp Stalker"] = { -- 8.x
["Warp Time"] = 35346,
},
["Wasp"] = { -- 8.x
["Toxic Sting"] = 263858,
},
["Water Strider"] = { -- 8.x
["Soothing Water"] = 264262,
["Surface Trot"] = 126311,
},
["Wind Serpent"] = { -- 8.x
["Winged Agility"] = 264360,
},
["Wolf"] = { -- 8.x
["Furious Bite"] = 263840,
},
["Worm"] = { -- 8.x
["Acid Spit"] = 263446,
["Burrow Attack"] = 93433,
},
},
},
["MAGE"] = {
["Arcane"] = {
["Polymorph Variants"] = 92,
},
["Fire"] = {
["Polymorph Variants"] = 92,
},
["Frost"] = {
["Polymorph Variants"] = 92,
},
["FlyoutsTOGET"] = {
["Polymorph Variants"] = 92,
},
["Flyouts"] = {
-- Polymorph Variants are now fetchable (all the ones currently ingame) from the game,
-- regardless of whether the Mage has them or not (all, some, one or even none).
-- BUT the Mage must have learned at least one Polymorph variant for us to fetch them
-- normally; otherwise the "Polymorph Variants" flyout-button does not appear in the
-- SpellBook.
-- However, you can pass the Flyout-button ("Polymorph Variants")'s Spell ID to
-- GetFlyoutSlotInfo(Flyout-SpellID, FlyoutSlot) and retrieve the variants even if the
-- character has learned none of them yet. The Spell Id for Polymorph Variants is: 92.
-- GetFlyoutSlotInfo() returns 5 values:
-- 1. SpellID
-- 2. SpellID again (same as in 1)
-- 3. Unknown boolean
-- 4. Spell name (e.g. "Polymorph")
-- 5. Unknown number (0 for the first two slots of GetFlyoutSlotInfo(92, FlyoutSlot)
-- Testing the above returned SpellID=61305 for GetFlyoutSlotInfo(92, 1).
-- GetSpellInfo(61305) on a Mage with NO Polymorph variants learned, returns the correct
-- information for Polymorph(Black Cat), as retrieved with this addon, on another
-- Mage with one Polymorph variant learned. GetFlyoutSlotInfo(92, 2) on the ignorant
-- Mage returns the spell ID for Polymorph(Monkey).
-- TODO: Implement a way to fetch the Mage Polymorph Variants (as well as the Shaman Hex
-- Variants), even if the character does not know any, by using the logic above (and
-- bellow if needed).
--[[
["Polymorph Variants"] = { -- Polymorph variants (including the default "Sheep") are
-- all called "Polymorph" but, like the Shaman Hex, these
-- spells do bear information about the variant's flavor
-- via GetSpellInfo(), on its 2nd return value (spell
-- "rank" / spell subname). This subname can be suffixed
-- onto the spell name to specify the variant, as in e.g.
-- "Polymorph(Sheep)". It can be passed as argument to
-- GetSpellInfo() as well as the console/macro "/cast"
-- command.
-- Since WoW 8.0.1, the 2nd return value is now no longer
-- guaranteed to be provided upon calling GetSpellInfo().
-- The value can however be retrieved via the new Spell
-- Mixin API (that was introduced with that patch), after a
-- delay. But the former use of"Polymorph(Sheep)" and etc
-- as argument to GetSpellInfo(), or the "/cast" command,
-- still works, with no need to explicitly use the new
-- Spell Mixin API, as it did before.
--
-- WoW build 29981 (8.1.5): The following were all fetched
-- fetched from the server:
["Polymorph(Black Cat)"] = 61305,
["Polymorph(Bumblebee)"] = 277792,
["Polymorph(Direhorn)"] = 277787,
["Polymorph(Monkey)"] = 161354,
["Polymorph(Peacock)"] = 161372,
["Polymorph(Penguin)"] = 161355,
["Polymorph(Pig)"] = 28272,
["Polymorph(Polar Bear Cub)"] = 161353,
["Polymorph(Porcupine)"] = 126819,
["Polymorph(Rabbit)"] = 61721,
["Polymorph(Serpent)"] = 61025,
["Polymorph(Turkey)"] = 61780,
["Polymorph(Turtle)"] = 28271,
},
]]--
-- The 'Portal: ' and 'Teleport: ' flyouts have (mostly) different destinations for
-- Alliance and for Horde Magi. Thus, we'll add them all here (incl. faction-shared):
["Portal"] = {
["Portal: Exodar"] = 32266, -- Alliance only
["Portal: Stonard"] = 49361, -- Horde only
["Portal: Undercity"] = 11418, -- Horde only
["Portal: Vale of Eternal Blossoms(Alliance)"] = 132620, -- Added: "(Alliance)"
["Portal: Vale of Eternal Blossoms(Horde)"] = 132626, -- Added: "(Horde)"
["Ancient Portal: Dalaran"] = 120146, -- Dalaran Crater (way ABOVE it! -> FALL!)
["Portal: Tol Barad(Alliance)"] = 88345, -- Added: "(Alliance)"
["Portal: Tol Barad(Horde)"] = 88346, -- Added: "(Horde)"
["Portal: Shattrath(Alliance)"] = 33691, -- Added: "(Alliance)"
["Portal: Shattrath(Horde)"] = 35717, -- Added: "(Horde)"
["Portal: Warspear"] = 176244, -- Horde only
["Portal: Theramore"] = 49360, -- Alliance only
["Portal: Thunder Bluff"] = 11420, -- Horde only
["Portal: Darnassus"] = 11419, -- Alliance only
["Portal: Silvermoon"] = 32267, -- Horde only
["Portal: Dalaran - Northrend"] = 53142,
["Portal: Stormwind"] = 10059, -- Alliance only
["Portal: Stormshield"] = 176246, -- Alliance only
["Portal: Dalaran - Broken Isles"] = 224871,
["Portal: Orgrimmar"] = 11417, -- Horde only
["Portal: Ironforge"] = 11416, -- Alliance only
["Portal: Dalaran - Broken Isles"] = 224871,
["Portal: Boralus"] = 281400, -- Alliance only
["Portal: Dazar'alor"] = 281402, -- Horde only
},
["Teleport"] = {
["Teleport: Vale of Eternal Blossoms(Alliance)"] = 132621, -- Added: "(Alliance)"
["Teleport: Vale of Eternal Blossoms(Horde)"] = 132627, -- Added: (Horde)
["Teleport: Dalaran - Northrend"] = 53140,
["Teleport: Shattrath(Alliance)"] = 33690, -- Added: "(Alliance)"
["Teleport: Shattrath(Horde)"] = 35715, -- Added: "(Horde)"
["Teleport: Stonard"] = 49358, -- Horde only
["Teleport: Stormshield"] = 176248, -- Alliance only
["Teleport: Darnassus"] = 3565, -- Alliance only
["Teleport: Dalaran - Broken Isles"] = 224869,
["Teleport: Stormwind"] = 3561, -- Alliance only
["Teleport: Hall of the Guardian"] = 193759, -- Mage Class Hall
["Teleport: Tol Barad(Alliance)"] = 88342, -- Added: "(Alliance)"
["Teleport: Tol Barad(Horde)"] = 88344, -- Added: "(Horde)"
["Teleport: Orgrimmar"] = 3567, -- Horde only
["Teleport: Ironforge"] = 3562, -- Alliance only
["Teleport: Warspear"] = 176242, -- Horde only
["Teleport: Theramore"] = 49359, -- Alliance only
["Teleport: Silvermoon"] = 32272, -- Horde only
["Teleport: Undercity"] = 3563, -- Horde only
["Ancient Teleport: Dalaran"] = 120145, -- Dalaran Crater (way ABOVE it! -> FALL!)
["Teleport: Exodar"] = 32271, -- Alliance only
["Teleport: Thunder Bluff"] = 3566, -- Horde only
["Teleport: Boralus"] = 281403, -- Alliance only
["Teleport: Dazar'alor"] = 281404, -- Horde only
},
},
-- Get the Pets spell from a high level Frost Mage instead
--[[
["Pets"] = {
["Water Elemental"] = { -- Frost specialization only
["Freeze"] = 33395,
["Waterbolt"] = 31707,
},
},
]]--
},
-- All Rogue Poisons are fetchable from the logged in character. The bellow is no longer needed.
["ROGUE"] = {
["Assassination"] = {
["Poisons"] = 66,
},
["Subtlety"] = {
["Poisons"] = 66,
},
["Outlaw"] = {
["Poisons"] = 66,
},
["FlyoutsTOGET"] = {
["Poisons"] = 66,
},
--[[
["Flyouts"] = {
["Poisons"] = { -- Since WoW 7.0, (I think) Assassintation specialization only. But, at
-- least on WoW 8.1.5, on the SpellBook of all three specializations.
["Agonizing Poison"] = 200802,
["Crippling Poison"] = 3408,
["Deadly Poison"] = 2823,
["Leeching Poison"] = 108211,
["Wound Poison"] = 8679,
},
},
]]--
},
["SHAMAN"] = {
["Elemental"] = {
["Bloodlust"] = 2825, -- Horde
["Heroism"] = 32182, -- Alliance
["Hex Variants"] = 106,
},
["Enhancement"] = {
["Bloodlust"] = 2825, -- Horde
["Heroism"] = 32182, -- Alliance
["Hex Variants"] = 106,
},
["Restoration"] = {
["Bloodlust"] = 2825, -- Horde
["Heroism"] = 32182, -- Alliance
["Hex Variants"] = 106,
},
-- Hex Variants are now fetchable (all the ones currently ingame) from the game,
-- regardless of whether the Shaman has them or not (all, some, one or even none).
-- BUT the Shaman must have learned at least one Hex variant for us to fetch them
-- normally; otherwise the "Hex Variants" flyout-button does not appear in the
-- SpellBook.
-- However, you can pass the Flyout-button ("Hex Variants")'s Spell ID to
-- GetFlyoutSlotInfo(Flyout-SpellID, FlyoutSlot) and retrieve the variants even if the
-- character has learned none of them yet. The Spell Id for Hex Variants is: 106.
-- GetFlyoutSlotInfo() returns 5 values:
-- 1. SpellID
-- 2. SpellID again (same as in 1)
-- 3. Unknown boolean
-- 4. Spell name (e.g. "Hex")
-- 5. Unknown number (0 for the first two slots of GetFlyoutSlotInfo(106, FlyoutSlot)
-- Testing the above returned SpellID=210873 for GetFlyoutSlotInfo(106, 1).
-- GetSpellInfo(210873) on a Shaman with NO Hex variants learned, returns the correct
-- information for Hex(Compy), as retrieved with this addon, on another Shaman with
-- some Hex variants learned. GetFlyoutSlotInfo(106, 2) on the ignorant Shaman returns
-- the spell ID for Hex(Cockroach).
-- TODO: Implement a way to fetch the Shaman Hex Variants (as well as the Mage Polymorph
-- Variants), even if the character does not know any, by using the logic above (and
-- bellow if needed).
["FlyoutsTOGET"] = {
["Hex Variants"] = 106,
},
--[[
["Flyouts"] = {
["Hex Variants"] = { -- Hex variants (including the default "Frog") are all
-- called "Hex" but, (since WoW 8.1.5 or earlier) like the
-- Mage Polymorph, these spells do bear information
-- about the variant's flavor via GetSpellInfo(), on its
-- 2nd return value (spell "rank" / spell subname). This
-- subname can be suffixed onto the spell name to specify
-- the variant, as in e.g. "Hex(Frog)". It can be passed as
-- argument to GetSpellInfo() as well as the console/macro
-- "/cast" command.
-- Since WoW 8.0.1, the 2nd return value is now no longer
-- guaranteed to be provided upon calling GetSpellInfo().
-- The value can however be retrieved via the new Spell
-- Mixin API (that was introduced with that patch), after a
-- delay. But the use of "Hex(Frog)" and etc as argument
-- to GetSpellInfo(), or the "/cast" command, still works,
-- with no need to explicitly use the new Spell Mixin API.
["Hex(Cockroach)"] = 211015,
["Hex(Compy)"] = 210873,
["Hex(Skeletal Hatchling)"] = 269352,
["Hex(Snake)"] = 211010,
["Hex(Spider)"] = 211004,
["Hex(Wicker Mongrel)"] = 277784, -- Alliance only
["Hex(Zandalari Tendonripper)"] = 277778, -- Horde only
},
},
]]--
["Pets"] = { -- In WoW 7.x.y, only the Elemental specialization has pets, which are only
-- controllable if the talent "Primal Elementalist"(5,2) is active (they're
-- guardians (no spells castable by the player) otherwise). On top of that,
-- although the Earth Elemental is always available to the Elemental Shaman
-- , the Fire and Storm elementals are mutually exclusive (Fire Elemental
-- becomes Storm Elemental if the talent "Storm Elemental" is chosen).
-- TL;DR: Better make sure the spells bellow are added, rather than going
-- through the gimmick of swithcing the talents every time we update the
-- SHAMAN lists of spells.
["Earth Elemental"] = {
["Angered Earth"] = 36213, -- Taunt
["Harden Skin"] = 118337, -- -40% damage taken by the Shaman
["Pulverize"] = 118345, -- Stun
},
["Fire Elemental"] = {
["Fire Blast"] = 57984,
["Immolate"] = 118297,
["Meteor"] = 117588,
},
["Storm Elemental"] = {
["Call Lightning"] = 157348,
["Eye of the Storm"] = 157375,
["Wind Gust"] = 157331,
},
},
},
["WARLOCK"] = {
["Affliction"] = {
["Summon Demon"] = 10,
},
["Demonology"] = {
["Summon Demon"] = 10,
},
["Destruction"] = {
["Summon Demon"] = 10,
},
["FlyoutsTOGET"] = {
["Summon Demon"] = 10,
},
["Pets"] = { -- Spells of the glyph-enhanced versions of the regular Warlock Demons.
-- NB: We're including spells that remain the same on both versions of the
-- demon.
["Fel Imp"] = {
["Felbolt"] = 115746, -- Fel Imp
["Sear Magic"] = 115276, -- Fel Imp
["Cauterize Master"] = 119905, -- Fel Imp & Imp
["Flee"] = 89792, -- Fel Imp & Imp
},
["Voidlord"] = {
["Void Shield"] = 115236, -- Voidlord
["Suffering"] = 119907, -- Voidlord & Voidwalker
["Consuming Shadows"] = 3716, -- Voidlord & Voidwalker
["Shadow Bulwark"] = 17767, -- Voidlord & Voidwalker
["Threatening Presence"] = 134477, -- Voidlord & Voidwalker
},
["Observer"] = {
["Optical Blast"] = 115781, -- Observer
["Tongue Lash"] = 115778, -- Observer
["Devour Magic"] = 19505, -- Observer & Felhunter
},
["Shivarra"] = {
["Bladedance"] = 115748, -- Shivarra
["Fellash"] = 115770, -- Shivarra
["Mesmerize"] = 115268, -- Shivarra
["Lesser Invisibility"] = 7870, -- Shivarra & Succubus
},
["Wrathguard"] = {
["Mortal Cleave"] = 115625, -- Wrathguard
["Wrathstorm"] = 115831, -- Wrathguard
["Axe Toss"] = 89766, -- Wrathguard & Felguard
["Pursuit"] = 30151, -- Wrathguard & Felguard
["Threatening Presence"] = 134477 -- Wrathguard & Felguard
},
},
},
};
 
local postUpdate_Spells2Add_PASSIVES = {
["General"] = {
["Riding"] = {
["Draenor Pathfinder"] = 191645, -- One rank only -- Flying -- USABLE
["Apprentice Riding"] = 33388,
["Broken Isles Pathfinder(Rank 1)"] = 226342, -- +20% mounted speed -- USABLE
["Broken Isles Pathfinder(Rank 2)"] = 233368, -- Flying -- USABLE
["Broken Isles Pathfinder"] = 233368, -- Flying -- USABLE
["Expert Riding"] = 34090,
["Journeyman Riding"] = 33391,
["Artisan Riding"] = 34091,
["Master Riding"] = 90265,
["Battle for Azeroth Pathfinder"] = 281576, -- +20% mounted speed -- USABLE
["Battle for Azeroth Pathfinder(Rank 1)"] = 281576, -- +20% mounted speed -- USABLE
},
["ZoneAbilities"] = {
-- Draenor
["Dragoon"] = 169605,
["Swift Recovery"] = 169608,
["Trading Pact"] = 170200,
["Upgrades"] = 170733,
},
},
--[[
-- NB: See reason to no longer be hardcoding this in the Active Spells section above.
["DEATHKNIGHT"] = {
["Pets"] = {
-- With talent 'Sludge Belcher':
["Ghoul"] = {
["Avoidance"] = 62137,
},
-- The Unholy spec talent "Sludge Belcher" which summoned an Abomination instead of a
-- Ghoul before 8.0.1 is no longer ingame.
-- ["Abomination"] = {
-- ["Avoidance"] = 62137,
-- },
},
},
]]--
["HUNTER"] = {
["Pets"] = {
-- NB: The comment "8.x" bellow denotes I checked the pet on wowhead.com (or ingame)
-- during WoW 8.x, NOT that they were introduced only in WoW 8.x (though of course some
-- were).
-- Specializations
["Ferocity"] = { -- 8.x
["Avoidance"] = 65220, -- Present on a lvl 14 Hunter
["Predator's Thirst"] = 264663, -- Present on a lvl 14 Hunter
},
["Tenacity"] = { -- 8.x
["Avoidance"] = 65220, -- Present on a lvl 14 Hunter
["Endurance Training"] = 264662, -- Present on a lvl 14 Hunter
},
["Cunning"] = { -- 8.x
["Avoidance"] = 65220, -- Present on a lvl 14 Hunter
["Pathfinding"] = 264656, -- Present on a lvl 14 Hunter
},
-- Families
["Bear"] = { -- 8.x
["Thick Fur"] = 263934,
},
["Gorilla"] = { -- 8.x
["Silverback"] = 263939,
},
["Krolusk"] = { -- 8.x
["Calcified Carapace"] = 279254,
},
["Shale Spider"] = { -- 8.x
["Shimmering Shale"] = 279259,
},
},
},
["MAGE"] = {
["Pets"] = {
["Water Elemental"] = { -- Frost specialization only
["Avoidance"] = 65220,
},
},
},
["WARLOCK"] = {
["Pets"] = { -- Spells of the glyph-enhanced versions of the regular Warlock Demons.
-- NB: We're including spells that remain the same on both versions.
["Fel Imp"] = {
["Avoidance"] = 32233, -- Fel Imp & Imp
},
["Voidlord"] = {
["Avoidance"] = 32233, -- Voidlord & Voidwalker
["Void Reflexes"] = 117225, -- Voidlord & Voidwalker
},
["Observer"] = {
["Avoidance"] = 32233, -- Observer & Felhunter
},
["Shivarra"] = {
["Avoidance"] = 32233, -- Shivarra & Succubus
},
["Wrathguard"] = {
["Avoidance"] = 32233, -- Wrathguard & Felguard
["Void Reflexes"] = 117225, -- Wrathguard & Felguard
},
},
},
};
 
 
-- Functions to store information about the dataSource (how up to date it is) and other metadata --
----------------------------------------------------------------------------------------------------
 
-- Update the General tab dataSource + raceBuilds --
local updateGeneralTabMetadata_func = function(curLocale, gameBuild, charLevel)
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateGeneralTabMetadata_func: START");
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": Check whether GeneralTab\'s Metadata needs update");
if not updateGeneralTabMetadata then
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": GeneralTab\'s Metadata does NOT need update.");
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateGeneralTabMetadata_func: END");
return;
end
tinsert(DEBUGmsgs[DBG_CurrentEvent], "GeneralTab\'s Metadata DOES need update.");
-- print(AddonName.. ": Will now check whether the GeneralTab Metadata needs updating.");
-- Actively-cast spells
if charLevel > SN2SID_table[generalTabName].METADATA.dataSource.charLevel then
SN2SID_table[generalTabName].METADATA.dataSource.charLevel = charLevel;
if charLevel > SN2SID_table[generalTabName].METADATA.dataSource.charMaxLevel then
SN2SID_table[generalTabName].METADATA.dataSource.charMaxLevel = charLevel;
end
updateGeneralSpells = true;
end
if gameBuild > SN2SID_table[generalTabName].METADATA.dataSource.gameBuild then
SN2SID_table[generalTabName].METADATA.dataSource.gameBuild = gameBuild;
-- Highest charLevel stored upon the most recent gameBuild
SN2SID_table[generalTabName].METADATA.dataSource.charLevel = charLevel;
-- Highest charLevel ever stored is kept in [...].charMaxLevel
updateGeneralSpells = true;
end
if (not SN2SID_table[generalTabName].METADATA.raceBuilds[universalRaceName]) or
(gameBuild > SN2SID_table[generalTabName].METADATA.raceBuilds[universalRaceName]) then
SN2SID_table[generalTabName].METADATA.raceBuilds[universalRaceName] = gameBuild;
updateGeneralSpells = true;
end
-- Passive spells
if charLevel > SN2SID_PASSIVES_table[generalTabName].METADATA.dataSource.charLevel then
SN2SID_PASSIVES_table[generalTabName].METADATA.dataSource.charLevel = charLevel;
if charLevel > SN2SID_PASSIVES_table[generalTabName].METADATA.dataSource.charMaxLevel then
SN2SID_PASSIVES_table[generalTabName].METADATA.dataSource.charMaxLevel = charLevel;
end
updateGeneralSpells = true;
end
if gameBuild > SN2SID_PASSIVES_table[generalTabName].METADATA.dataSource.gameBuild then
SN2SID_PASSIVES_table[generalTabName].METADATA.dataSource.gameBuild = gameBuild;
-- Highest charLevel stored upon the most recent gameBuild
SN2SID_PASSIVES_table[generalTabName].METADATA.dataSource.charLevel = charLevel;
-- Highest charLevel ever stored is kept in [...].charMaxLevel
updateGeneralSpells = true;
end
if (not SN2SID_PASSIVES_table[generalTabName].METADATA.raceBuilds[universalRaceName]) or
(gameBuild > SN2SID_PASSIVES_table[generalTabName].METADATA.raceBuilds[universalRaceName]) then
SN2SID_PASSIVES_table[generalTabName].METADATA.raceBuilds[universalRaceName] = gameBuild;
updateGeneralSpells = true;
end
updateGeneralTabMetadata = false;
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateGeneralTabMetadata_func: END");
end
 
-- Update the Class dataSource --
local updateClassMetadata_func = function(curLocale, gameBuild, charLevel)
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateClassMetadata_func: START");
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": Check whether ".. universalClassName.. "\'s Metadata needs update.");
if not updateClassMetadata then
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": ".. universalClassName.. "\'s Metadata does NOT need update.");
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateClassMetadata_func: END");
return;
end
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": ".. universalClassName.. "\'s Metadata DOES need update.");
-- print(AddonName.. ": Will now check whether the ".. universalClassName.. " Metadata needs updating.");
-- Actively-cast spells
if charLevel > SN2SID_table[universalClassName].METADATA.dataSource.charLevel then
SN2SID_table[universalClassName].METADATA.dataSource.charLevel = charLevel;
if charLevel > SN2SID_table[universalClassName].METADATA.dataSource.charMaxLevel then
SN2SID_table[universalClassName].METADATA.dataSource.charMaxLevel = charLevel;
end
updateClassSpells = true;
end
if gameBuild > SN2SID_table[universalClassName].METADATA.dataSource.gameBuild then
SN2SID_table[universalClassName].METADATA.dataSource.gameBuild = gameBuild;
SN2SID_table[universalClassName].METADATA.dataSource.charLevel = charLevel;
updateClassSpells = true;
end
-- Passive spells
if charLevel > SN2SID_PASSIVES_table[universalClassName].METADATA.dataSource.charLevel then
SN2SID_PASSIVES_table[universalClassName].METADATA.dataSource.charLevel = charLevel;
if charLevel > SN2SID_PASSIVES_table[universalClassName].METADATA.dataSource.charMaxLevel then
SN2SID_PASSIVES_table[universalClassName].METADATA.dataSource.charMaxLevel = charLevel;
end
updateClassSpells = true;
end
if gameBuild > SN2SID_PASSIVES_table[universalClassName].METADATA.dataSource.gameBuild then
SN2SID_PASSIVES_table[universalClassName].METADATA.dataSource.gameBuild = gameBuild;
SN2SID_PASSIVES_table[universalClassName].METADATA.dataSource.charLevel = charLevel;
updateClassSpells = true;
end
updateClassMetadata = false;
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateClassMetadata_func: END");
end
 
 
---- Functions to update the lists of Spell Names and their IDs ----
--------------------------------------------------------------------
 
-- Update the PvE Talents' lists of spells
local updateTalentSpells_func = function(ClassNumSpecs, ClassSpecNames2IDs)
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateTalentSpells_func: START");
if not updateClassSpells then -- Sanity check
return;
end
 
for i = 1, ClassNumSpecs do
-- Create "SpecName_Talents" subtables if they doesn't exist yet
local specID, locSpecName = GetSpecializationInfo(i);
if locSpecName then -- Sanity check
-- print(AddonName.. ": locSpecName = ".. locSpecName);
-- Actives
-- if not SN2SID_table[universalClassName][locSpecName.."_Talents"] then
-- SN2SID_table[universalClassName][locSpecName.."_Talents"] = {};
-- end
-- Passives
-- if not SN2SID_PASSIVES_table[universalClassName][locSpecName.."_Talents"] then
-- SN2SID_PASSIVES_table[universalClassName][locSpecName.."_Talents"] = {};
-- end
else
-- print(AddonName.. ": PVE: NO specialization has been selected for this character!");
return;
end
-- Populate the "SpecName_Talents" subtables
for ii = 1, NumberOfTalentTiers do
for iii = 1, 3 do
local _, spellName, _, _, _, spellID, _, _, _, _, _ = GetTalentInfoBySpecialization(i, ii, iii);
if spellName then
if IsPassiveSpell(spellID) then
if SN2SID_PASSIVES_table[universalClassName][locSpecName.."_Talents"] then
SN2SID_PASSIVES_table[universalClassName][locSpecName.."_Talents"][spellName] = spellID;
else
SN2SID_PASSIVES_table[universalClassName][locSpecName.."_Talents"] = { [spellName] = spellID, };
end
else
if SN2SID_table[universalClassName][locSpecName.."_Talents"] then
SN2SID_table[universalClassName][locSpecName.."_Talents"][spellName] = spellID;
else
SN2SID_table[universalClassName][locSpecName.."_Talents"] = { [spellName] = spellID, };
end
end
end
end
end
-- NB: There is NO WAY to store a key-value pairs table of non-integer keys in ordered/
-- sorted mode in Lua.
-- At most, you could extract all keys and sort them in an array-like table (NO PAIRS!),
-- and then fetch the keys in order from that array-table and then the corresponding values
-- from another tab le (the original, unordered/unsorted key-value pairs table).
-- The function from https://wow.gamepedia.com/Orderedpairs gets you the ordered values
-- from the unordered table in running-time, but cannot be used to change the stored data,
-- just like the extract-keys-then-sort-them method above.
-- Thus, it's not possible to store the data in an easy to visually (or OS-based) diff two
-- versions of a database, as I wished.
end
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateTalentSpells_func: END");
end
 
-- Update the PvP Talents' lists of spells
local updatePVPTalentSpells_func = function(ClassNumSpecs, ClassSpecNames2IDs)
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updatePVPTalentSpells_func: START");
if not updateClassSpells then -- Sanity check
return;
end
 
for i = 1, ClassNumSpecs do
-- Create "SpecName_PVPTalents" subtables if they don't exist yet
local specID, locSpecName = GetSpecializationInfo(i);
if locSpecName then -- Sanity check
-- print(AddonName.. ": locSpecName = ".. locSpecName);
-- Actives
if not SN2SID_table[universalClassName][locSpecName.."_PVPTalents"] then
SN2SID_table[universalClassName][locSpecName.."_PVPTalents"] = {};
end
-- Passives
if not SN2SID_PASSIVES_table[universalClassName][locSpecName.."_PVPTalents"] then
SN2SID_PASSIVES_table[universalClassName][locSpecName.."_PVPTalents"] = {};
end
else
-- print(AddonName.. ": PVP: NO specialization has been selected for this character!");
return;
end
-- Populate the "SpecName_PVPTalents" subtables
for ii = 1, NumberOfPVPTalentSlots do
local talentOptions = C_SpecializationInfo.GetPvpTalentSlotInfo(ii).availableTalentIDs;
for iii = 1, #talentOptions do
-- local _, spellName, _, _, _, spellID, _, _, _, _, _ = GetPvpTalentInfoBySpecialization(i, ii, iii);
local talentID = talentOptions[iii];
local _, spellName, _, _, _, spellID, _, _, _, _, _ = GetPvpTalentInfoByID(talentID);
-- print(AddonName.. ": PVPTalent spellName = ".. tostring(spellName));
if spellName then
if IsPassiveSpell(spellID) then
SN2SID_PASSIVES_table[universalClassName][locSpecName.."_PVPTalents"][spellName] = spellID;
else
SN2SID_table[universalClassName][locSpecName.."_PVPTalents"][spellName] = spellID;
end
end
end
end
end
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updatePVPTalentSpells_func: END");
end
 
local armorSkills, weaponSkills;
-- Helper functions to function updateSpellbookSpells_func() --
local addSpellbookSpellToGeneral_func = function(spellName, spellSubName, spellID)
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addSpellbookSpellToGeneral_func: START");
-- Store Passive and Active abilities into their own separate tables
if IsPassiveSpell(spellID) then
if spellName == "Armor Skills" then
armorSkills = spellID;
elseif spellName == "Weapon Skills" then
weaponSkills = spellID;
elseif strfind(spellName, "Riding") or strfind(spellName, "Pathfinder") then
if not SN2SID_PASSIVES_table[generalTabName].Riding then
SN2SID_PASSIVES_table[generalTabName].Riding = { [spellName] = spellID };
else
SN2SID_PASSIVES_table[generalTabName].Riding[spellName] = spellID;
end
-- NB: See "NB" for non-passive spells bellow
elseif spellSubName and strfind(spellSubName, "Racial") then
if not SN2SID_PASSIVES_table[generalTabName].Racials[universalRaceName] then
SN2SID_PASSIVES_table[generalTabName].Racials[universalRaceName] = { [spellName] = spellID };
else
SN2SID_PASSIVES_table[generalTabName].Racials[universalRaceName][spellName] = spellID;
end
elseif spellSubName and strfind(spellSubName, "Guild") then
if not SN2SID_PASSIVES_table[generalTabName].GuildPerks then
SN2SID_PASSIVES_table[generalTabName].GuildPerks = { [spellName] = spellID };
else
SN2SID_PASSIVES_table[generalTabName].GuildPerks[spellName] = spellID;
end
-- Will now test for the hardcoded ZoneAbilities, to place them in the correct subcategory
elseif postUpdate_Spells2Add_PASSIVES.General.ZoneAbilities[spellName] then
if not SN2SID_table[generalTabName].ZoneAbilities then
SN2SID_PASSIVES_table[generalTabName].ZoneAbilities = { [spellName] = spellID };
else
SN2SID_PASSIVES_table[generalTabName].ZoneAbilities[spellName] = spellID;
end
-- All other spells go into the "Others" subcategory
elseif not SN2SID_PASSIVES_table[generalTabName].Others then
SN2SID_PASSIVES_table[generalTabName].Others = { [spellName] = spellID };
else
SN2SID_PASSIVES_table[generalTabName].Others[spellName] = spellID;
end
else
-- NB: Switched the order of checks: Before, we were checking for the presence of the spell
-- in our list of hardcoded Zone spells first. Now, we do that test last, as there is at
-- least one instance of a spell with the same name, but different IDs, that is a Racial
-- (that we fetch from the server) and also a hardcoded Zone ability: "Light's Judgment".
if spellSubName and strfind(spellSubName, "Racial") then
if not SN2SID_table[generalTabName].Racials[universalRaceName] then
SN2SID_table[generalTabName].Racials[universalRaceName] = { [spellName] = spellID };
else
SN2SID_table[generalTabName].Racials[universalRaceName][spellName] = spellID;
end
elseif spellSubName and strfind(spellSubName, "Guild") then
if not SN2SID_table[generalTabName].GuildPerks then
SN2SID_table[generalTabName].GuildPerks = { [spellName] = spellID };
else
SN2SID_table[generalTabName].GuildPerks[spellName] = spellID;
end
-- Will now test for the hardcoded ZoneAbilities, to place them in the correct subcategory
elseif postUpdate_Spells2Add.General.ZoneAbilities[spellName] then
if not SN2SID_table[generalTabName].ZoneAbilities then
SN2SID_table[generalTabName].ZoneAbilities = { [spellName] = spellID };
else
SN2SID_table[generalTabName].ZoneAbilities[spellName] = spellID;
end
-- All other spells go into the "Others" subcategory
elseif not SN2SID_table[generalTabName].Others then
SN2SID_table[generalTabName].Others = { [spellName] = spellID };
else
SN2SID_table[generalTabName].Others[spellName] = spellID;
end
end
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addSpellbookSpellToGeneral_func: END");
end
 
local addPolymorphOrHexFlyoutSpell_func = function(flyoutButton, flyoutSpellName, flyoutSpellSubname, flyoutSpellID)
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addPolymorphOrHexFlyoutSpell_func: START");
local flyoutSpellFullName = flyoutSpellName.. "(".. flyoutSpellSubname.. ")";
if not SN2SID_table[universalClassName].Flyouts[flyoutButton][flyoutSpellFullName]
or SN2SID_table[universalClassName].Flyouts[flyoutButton][flyoutSpellFullName] ~= flyoutSpellID then
-- print(AddonName.. "Adding flyout spellFullName ".. flyoutSpellFullName.. " = ".. flyoutSpellID);
SN2SID_table[universalClassName].Flyouts[flyoutButton][flyoutSpellFullName] = flyoutSpellID;
end
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addPolymorphOrHexFlyoutSpell_func: END");
end
 
local addFlyoutSpells_func = function(flyoutButtonName, flyoutButtonID)
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addFlyoutSpells_func: START");
-- print(AddonName.. ": SpellID ".. flyoutButtonID.. " on SpecTab ".. i.. ", Pos ".. ii.. " is a FLYOUT button.");
-- NB: Creating SN2SID_table[universalClassName].Flyouts either via
-- SN2SID_table[universalClassName].Flyouts = []; or via
-- tinsert(SN2SID_table[universalClassName], "Flyouts"); was causing a bug where the same
-- table would have two "Flyouts" fields: one with the correct values and another empty
-- (as if it were a simple member of an array). So we create a STUB value if needed and
-- later remove it when we're done adding the spells.
if not SN2SID_table[universalClassName].Flyouts then
SN2SID_table[universalClassName].Flyouts = { ["STUB"] = 0, };
end
 
if (flyoutButtonName == "Portal") or (flyoutButtonName == "Teleport") then
-- There are spells with the same Name but different IDs, depending on the
-- character's faction, when it comes to Portals and Teleports. Hence, for now,
-- we add them only in Post. TODO: Fetch them here as well, but check that they
-- are not one of those (known) smae-name, diff-IDs cases (in that case do not add
-- them here, only in post).
else
-- Insert the flyout spell in its proper table
if not SN2SID_table[universalClassName].Flyouts[flyoutButtonName] then
-- print(AddonName.. ": Adding Flyouts.".. flyoutButtonName.. " to ".. universalClassName);
SN2SID_table[universalClassName].Flyouts[flyoutButtonName] = { ["STUB"] = 0, };
-- else
-- print(AddonName.. ": Flyouts.".. flyoutButtonName.. " is already in ".. universalClassName);
end
local _, _, numFlyouts, flyoutKnown = GetFlyoutInfo(flyoutButtonID);
-- print(AddonName.. ": ".. flyoutButtonName.. " | ".. flyoutButtonID.. " | Number of Slots = ".. numFlyouts);
for flyoutSlot = 1, numFlyouts do
-- local flyoutSpellID, overrideSpellID, flyoutSlotKnown, slotSpecID = GetFlyoutSlotInfo(flyoutButtonID, flyoutSlot);
local flyoutSpellID, _, _, _ = GetFlyoutSlotInfo(flyoutButtonID, flyoutSlot);
local flyoutSpellName, flyoutSpellSubname, _, _, _, _, _ = GetSpellInfo(flyoutSpellID);
if flyoutButtonName == "Polymorph Variants" or flyoutButtonName == "Hex Variants" then
-- Mage "Polymorph Variants", and Shaman "Hex Variants",
-- are all called "Polymorph" or "Hex", respectively. But
-- they have a subname specifying the variant AND can be
-- addressed by suffixing the subname in parenthesis, as
-- in e.g. "Polymorph(Sheep)" or "Hex(Frog)". We'll do just
-- that and store their names as "name(subname)".
if (flyoutSpellSubname == nil) or (flyoutSpellSubname == "") then
-- print(AddonName.. ": ".. tostring(flyoutSpellName).. " = ".. tostring(flyoutSpellID));
-- TODO #1: Make a table, LOCAL-TO-FILE, to store
-- all the delayedFlyoutSpellInfo tables amd name
-- each one "delayedFlyoutSpellInfo"..flyoutSpellID .
-- Create an access to the info that will be fetched
local delayedFlyoutSpellInfo = Spell:CreateFromSpellID(flyoutSpellID);
-- Actually get the info and use it to update our DB
delayedFlyoutSpellInfo:ContinueOnSpellLoad(function()
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": delayedFlyoutSpellInfo:ContinueOnSpellLoad: START");
-- print(AddonName.. ": Will now get the previously delayed information about flyoutSpellID: ".. flyoutSpellID);
-- Although we should only need to update spellSubName, we might
-- have fetched a new spellName + spellID by now. Thus, we'll
-- update those fields too.
-- TODO #2: Pass the three
-- "delayedFlyoutSpellInfo"..flyoutSpellID:Some()
-- values bellow as arguments to
-- addPolymorphOrHexFlyoutSpell_func(...)
flyoutSpellName = delayedFlyoutSpellInfo:GetSpellName();
flyoutSpellSubname = delayedFlyoutSpellInfo:GetSpellSubtext(); -- Mandatory
flyoutSpellID = delayedFlyoutSpellInfo:GetSpellID();
addPolymorphOrHexFlyoutSpell_func(flyoutButtonName, flyoutSpellName, flyoutSpellSubname, flyoutSpellID);
-- TODO #3: Clean up! I.e.:
-- SaidMasterTable["delayedFlyoutSpellInfo"..flyoutSpellID] = nil;
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": delayedFlyoutSpellInfo:ContinueOnSpellLoad: END");
end);
else
-- print(AddonName.. ": ".. tostring(flyoutSpellName).. " = ".. tostring(flyoutSpellID));
addPolymorphOrHexFlyoutSpell_func(flyoutButtonName, flyoutSpellName, flyoutSpellSubname, flyoutSpellID);
end
-- Add the default Plymorph(Sheep) and Hex(Frog) to the spell lists
if universalClassName == MAGE then
SN2SID_table.MAGE.Arcane["Polymorph(Sheep)"] = SN2SID_table.MAGE.Arcane["Polymorph"] or nil;
SN2SID_table.MAGE.Fire["Polymorph(Sheep)"] = SN2SID_table.MAGE.Fire["Polymorph"] or nil;
SN2SID_table.MAGE.Frost["Polymorph(Sheep)"] = SN2SID_table.MAGE.Frost["Polymorph"] or nil;
end
if universalClassName == SHAMAN then
SN2SID_table.SHAMAN.Elemental["Hex(Frog)"] = SN2SID_table.SHAMAN.Elemental["Hex"] or nil;
SN2SID_table.SHAMAN.Enhancement["Hex(Frog)"] = SN2SID_table.SHAMAN.Enhancement["Hex"] or nil;
SN2SID_table.SHAMAN.Restoration["Hex(Frog)"] = SN2SID_table.SHAMAN.Restoration["Hex"] or nil;
end
elseif flyoutSpellName and (not SN2SID_table[universalClassName].Flyouts[flyoutButtonName][flyoutSpellName])
or flyoutSpellName and (SN2SID_table[universalClassName].Flyouts[flyoutButtonName][flyoutSpellName] ~= flyoutSpellID) then
-- print(AddonName.. ": ".. tostring(flyoutSpellName).. " = ".. tostring(flyoutSpellID));
SN2SID_table[universalClassName].Flyouts[flyoutButtonName][flyoutSpellName] = flyoutSpellID;
end
end
SN2SID_table[universalClassName].Flyouts[flyoutButtonName]["STUB"] = nil;
end
-- Get rid of the STUB table member that was added upon its creation
SN2SID_table[universalClassName].Flyouts["STUB"] = nil;
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addFlyoutSpells_func: END");
end
-- --
 
-- Update the Spellbook's GeneralTab and ClassTabs lists of spells
local updateSpellbookSpells_func = function(ClassNumSpecs, ClassSpecNames2IDs)
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateSpellbookSpells_func: START");
-- "Armor Skills" and "Weapon Skills" are found on the Spellbook's General tab, but are indeed
-- different from one class to the other. Therefore, we'll save them into local variables upon
-- fetching the General tab spells and then insert them into the Class Specialisations' tables.
-- local armorSkills, weaponSkills;
 
-- General tab spells
-- if updateGeneralSpells then -- In current addon version, always true
local stubVal;
stubVal, universalRaceName = UnitRace("player");
if not SN2SID_table[generalTabName].Racials then
SN2SID_table[generalTabName].Racials = {};
end
if not SN2SID_PASSIVES_table[generalTabName].Racials then
SN2SID_PASSIVES_table[generalTabName].Racials = {};
end
if not SN2SID_PASSIVES_table[generalTabName].Riding then
SN2SID_PASSIVES_table[generalTabName].Riding = {};
end
if not SN2SID_table[generalTabName].GuildPerks then
SN2SID_table[generalTabName].GuildPerks = {};
end
if not SN2SID_PASSIVES_table[generalTabName].GuildPerks then
SN2SID_PASSIVES_table[generalTabName].GuildPerks = {};
end
if not SN2SID_table[generalTabName].Others then
SN2SID_table[generalTabName].Others = {};
end
if not SN2SID_PASSIVES_table[generalTabName].Others then
SN2SID_PASSIVES_table[generalTabName].Others = {};
end
generalTabName, _, offset, numEntries, _, _, _ = GetSpellTabInfo(1);
-- name, texture, offset, numEntries, isGuild, offspecID = GetSpellTabInfo(tabIndex)
for i = offset +1, offset +numEntries do
local spellName, spellSubName = GetSpellBookItemName(i, BOOKTYPE_SPELL);
if spellName then
local _, spellID = GetSpellBookItemInfo(i, BOOKTYPE_SPELL);
if (spellSubName == nil) or (spellSubName == "") then
local delayedSpellInfo = Spell:CreateFromSpellID(spellID);
-- I presume we don't actually need to cancel the request for the additional
-- information, i.e. presume once the information is given to us through the
-- function delayedSpellInfo:ContinueOnSpellLoad(), there will be no further
-- activity regarding this- But, just in case, we'll set up a function to
-- cancel the request after we got the information we need.
--
-- RESULT: The request-cancel function is being run BEFORE the requestFulfilled
-- one! But it's still storing the value NO PROB AT ALL! So, maybe we can just
-- do the whole add-spell-to-DB thing upon request cancelation? TODO: TRY IT!
--
-- FURTHER TESTING: Using only :ContinueWithCancelOnSpellLoad(), without
-- :ContinueOnSpellLoad(), does work. But the only spells added this way seem
-- to be spells that don't actually have a Spell Subname (with the eventual
-- exception of "Passive" spells). It would therefore seem we (usually?) get
-- every spell's subname from GetSpellBookItemName(). So, this test is not
-- conclusive. :-(
-- Better revert this to have both :ContinueWithCancelOnSpellLoad() and
-- ContinueOnSpellLoad() be run; ContinueOnSpellLoad() is run anyway after
-- ContinueWithCancelOnSpellLoad, so it should be alright... ?
--
-- MORE TESTING: With the 'Cache' folder and the saved variables' file deleted,
-- the results are the same (with calling only :ContinueWithCancelOnSpellLoad()
-- w/ no call to :ContinueOnSpellLoad() ). I will (again) revert to using both
-- functions, for the sake of safity.
--
 
-- local spellDataLoadedCancelFunc = delayedSpellInfo:ContinueWithCancelOnSpellLoad(function()
-- We don't need to do anything upon canceling the request
-- print(AddonName.. ": Now cancelling the request for delayed information about spell ID: ".. spellID);
-- end);
-- Actually get the information and use it to update our database:
delayedSpellInfo:ContinueOnSpellLoad(function()
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": delayedSpellInfo:ContinueOnSpellLoad: START");
-- print(AddonName.. ": Will now get the previously delayed information about spell ID: ".. spellID);
-- Although we should only need to update spellSubName, we might
-- have fetched a new spellName + spellID by now. Thus, we'll
-- update those fields too.
spellName = delayedSpellInfo:GetSpellName();
spellSubName = delayedSpellInfo:GetSpellSubtext(); -- Mandatory
spellID = delayedSpellInfo:GetSpellID();
addSpellbookSpellToGeneral_func(spellName, spellSubName, spellID);
-- Now cancel the request:
-- spellDataLoadedCancelFunc();
-- spellDataLoadedCancelFunc = nil; -- for safety!
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": delayedSpellInfo:ContinueOnSpellLoad: END");
end);
--[[
local spellDataLoadedCancelFunc = delayedSpellInfo:ContinueWithCancelOnSpellLoad(function()
-- We don't need to do anything upon canceling the request
-- print(AddonName.. ": Now cancelling the request for delayed information about spell ID: ".. spellID);
 
-- Although we should only need to update spellSubName, we might
-- have fetched a new spellName + spellID by now. Thus, we'll
-- update those fields too.
spellName = delayedSpellInfo:GetSpellName();
spellSubName = delayedSpellInfo:GetSpellSubtext(); -- Mandatory
spellID = delayedSpellInfo:GetSpellID();
addSpellbookSpellToGeneral_func(spellName, spellSubName, spellID);
 
spellDataLoadedCancelFunc = nil; -- for safety!
end);
]]--
else
addSpellbookSpellToGeneral_func(spellName, spellSubName, spellID);
end
-- --
end
end
-- end
 
-- Class spells
-- if updateClassSpells then
-- updateTalentSpells_func(SN2SID_table, SN2SID_PASSIVES_table, universalClassName, ClassNumSpecs, ClassSpecNames2IDs);
-- updateTalentSpells_func(universalClassName, ClassNumSpecs, ClassSpecNames2IDs);
updateTalentSpells_func(ClassNumSpecs, ClassSpecNames2IDs);
-- updatePVPTalentSpells_func(SN2SID_table, SN2SID_PASSIVES_table, universalClassName, ClassNumSpecs, ClassSpecNames2IDs);
updatePVPTalentSpells_func(ClassNumSpecs, ClassSpecNames2IDs);
for i = 2, (ClassNumSpecs +1) do
-- Get the current tab's first spell's index, total number of spells therein and specID
local _, _, offset, numEntries, _, _, _, specID = GetSpellTabInfo(i);
if specID then -- Sanity check
local _, locSpecName = GetSpecializationInfoByID(specID);
--- Create SpecName subtables and SpecName_Talents subtables if they doesn't exist yet
if locSpecName then -- Sanity check
if not SN2SID_table[universalClassName][locSpecName] then
SN2SID_table[universalClassName][locSpecName] = {};
end
if not SN2SID_PASSIVES_table[universalClassName][locSpecName] then
SN2SID_PASSIVES_table[universalClassName][locSpecName] = {};
end
end
-- Populate
-- print(AddonName.. ": numEntries = ".. numEntries);
for ii = offset +1, offset +numEntries do
-- local spellName, spellSubName = GetSpellBookItemName(ii, BOOKTYPE_SPELL);
local spellName = (GetSpellBookItemName(ii, BOOKTYPE_SPELL));
-- We actually don't use spellSubName on the population of the Class-spells list
-- (or at least currently we don't) ; thus we don't need to use the SpellMixin
-- API to retrieve it later; I.e. in this for loop, spellSubName is a stub val.
if spellName then
local spellType, spellID = GetSpellBookItemInfo(ii, BOOKTYPE_SPELL);
-- Store Passive and Active abilities into their own separate tables IF they
-- are not already stored in the respective Talents' tables.
if IsPassiveSpell(spellID) and ((not SN2SID_PASSIVES_table[universalClassName][locSpecName.."_Talents"])
or (not SN2SID_PASSIVES_table[universalClassName][locSpecName.."_Talents"][spellName])) then
-- print(AddonName.. ": Will add Passive: ".. spellName.. " / ID: ".. spellID);
if not SN2SID_PASSIVES_table[universalClassName][locSpecName] then
SN2SID_PASSIVES_table[universalClassName][locSpecName] ={ [spellName] = spellID, };
else
SN2SID_PASSIVES_table[universalClassName][locSpecName][spellName] = spellID;
end
elseif (not SN2SID_table[universalClassName][locSpecName.."_Talents"])
or (not SN2SID_table[universalClassName][locSpecName.."_Talents"][spellName]) then
-- print(AddonName.. ": Will add: ".. spellName.. " / ID: ".. spellID);
if not SN2SID_table[universalClassName][locSpecName] then
SN2SID_table[universalClassName][locSpecName] = { [spellName] = spellID, };
else
SN2SID_table[universalClassName][locSpecName][spellName] = spellID;
end
end
-- If it's a Flyout type of button (e.g. Mage Polymorph variants, Hunter Pet
-- Utility spells, etc), then fetch the spells that ... fly out.
if spellType == "FLYOUT" then
addFlyoutSpells_func(spellName, spellID);
--[[
-- print(AddonName.. ": SpellID ".. spellID.. " on SpecTab ".. i.. ", Pos ".. ii.. " is a FLYOUT button.");
-- NB: Creating SN2SID_table[universalClassName].Flyouts either via
-- SN2SID_table[universalClassName].Flyouts = []; or via
-- tinsert(SN2SID_table[universalClassName], "Flyouts"); was causing
-- a bug where the same table would have two "Flyouts" fields: one with
-- the correct values and another empty (as if it were a simple member
-- of an array). So we create a STUB value if needed and later remove
-- it when we're done adding the spells.
if not SN2SID_table[universalClassName].Flyouts then
SN2SID_table[universalClassName].Flyouts = { ["STUB"] = 0, };
end
 
if (spellName == "Portal") or (spellName == "Teleport") then
--break; -- There are spells with the same Name but different IDs,
-- depending on the character's faction, when it comes to
-- Portals and Teleports. Hence, for now, we add them only
-- in Post. TODO: Fetch them here as well, but check that
-- they are not one of those (known) smae-name, diff-IDs
-- cases (in that case do not add them here, only in post).
else
-- Insert the flyout spell in its proper table
if not SN2SID_table[universalClassName].Flyouts[spellName] then
-- print(AddonName.. ": Adding Flyouts.".. spellName.. " to ".. universalClassName);
SN2SID_table[universalClassName].Flyouts[spellName] = {};
-- else
-- print(AddonName.. ": Flyouts.".. spellName.. " is already in ".. universalClassName);
end
local _, _, numFlyouts, flyoutKnown = GetFlyoutInfo(spellID);
for flyoutSlot = 1, numFlyouts do
-- local flyoutSpellID, overrideSpellID, flyoutSlotKnown, slotSpecID = GetFlyoutSlotInfo(spellID, flyoutSlot);
local flyoutSpellID, _, _, _ = GetFlyoutSlotInfo(spellID, flyoutSlot);
local flyoutSpellName, flyoutSpellSubname, _, _, _, _, _ = GetSpellInfo(flyoutSpellID);
-- print(AddonName.. ": ".. tostring(flyoutSpellID).. " = ".. tostring(flyoutSpellName));
if spellName == "Polymorph Variants" or spellName == "Hex Variants" then
-- Mage "Polymorph Variants", and Shaman "Hex Variants",
-- are all called "Polymorph" or "Hex", respectively. But
-- they have a subname specifying the variant AND can be
-- addressed by suffixing the subname in parenthesis, as
-- in e.g. "Polymorph(Sheep)" or "Hex(Frog)". We'll do just
-- that and store their names as "name(subname)".
if (flyoutSpellSubname == nil) or (flyoutSpellSubname == "") then
 
-- TODO #1: Make a table, LOCAL-TO-FILE, to store
-- all the delayedFlyoutSpellInfo tables amd name
-- each one "delayedFlyoutSpellInfo"..flyoutSpellID .
-- Create an access to the info that will be fetched
local delayedFlyoutSpellInfo = Spell:CreateFromSpellID(flyoutSpellID);
 
-- Actually get the info and use it to update our DB
delayedFlyoutSpellInfo:ContinueOnSpellLoad(function()
-- print(AddonName.. ": Will now get the previously delayed information about flyoutSpellID: ".. flyoutSpellID);
-- Although we should only need to update spellSubName, we might
-- have fetched a new spellName + spellID by now. Thus, we'll
-- update those fields too.
 
-- TODO #2: Pass the three
-- "delayedFlyoutSpellInfo"..flyoutSpellID:Some()
-- values bellow as arguments to
-- addPolymorphOrHexFlyoutSpell_func(...)
flyoutSpellName = delayedFlyoutSpellInfo:GetSpellName();
flyoutSpellSubname = delayedFlyoutSpellInfo:GetSpellSubtext(); -- Mandatory
flyoutSpellID = delayedFlyoutSpellInfo:GetSpellID();
addPolymorphOrHexFlyoutSpell_func(spellName, flyoutSpellName, flyoutSpellSubname, flyoutSpellID);
 
-- TODO #3: Clean up! I.e.:
-- SaidMasterTable["delayedFlyoutSpellInfo"..flyoutSpellID] = nil;
end);
else
addPolymorphOrHexFlyoutSpell_func(spellName, flyoutSpellName, flyoutSpellSubname, flyoutSpellID);
end
-- Add the default Plymorph(Sheep) and Hex(Frog) to the spell lists
SN2SID_table.MAGE.Arcane["Polymorph(Sheep)"] = SN2SID_table.MAGE.Arcane["Polymorph"] or nil;
SN2SID_table.MAGE.Fire["Polymorph(Sheep)"] = SN2SID_table.MAGE.Fire["Polymorph"] or nil;
SN2SID_table.MAGE.Frost["Polymorph(Sheep)"] = SN2SID_table.MAGE.Frost["Polymorph"] or nil;
SN2SID_table.SHAMAN.Elemental["Hex(Frog)"] = SN2SID_table.SHAMAN.Elemental["Hex"] or nil;
SN2SID_table.SHAMAN.Enhancement["Hex(Frog)"] = SN2SID_table.SHAMAN.Enhancement["Hex"] or nil;
SN2SID_table.SHAMAN.Restoration["Hex(Frog)"] = SN2SID_table.SHAMAN.Restoration["Hex"] or nil;
elseif flyoutSpellName and (not SN2SID_table[universalClassName].Flyouts[spellName][flyoutSpellName])
or flyoutSpellName and (SN2SID_table[universalClassName].Flyouts[spellName][flyoutSpellName] ~= flyoutSpellID) then
-- print(AddonName.. ": ".. tostring(flyoutSpellName).. " = ".. tostring(flyoutSpellID));
SN2SID_table[universalClassName].Flyouts[spellName][flyoutSpellName] = flyoutSpellID;
end
end
end
-- Get rid of the STUB table member that was added upon its creation
SN2SID_table[universalClassName].Flyouts["STUB"] = nil;
]]--
end
end
end
SN2SID_PASSIVES_table[universalClassName][locSpecName]["Armor Skills"] = armorSkills;
-- print(AddonName.. ": Added Armor Skills = ".. armorSkills);
SN2SID_PASSIVES_table[universalClassName][locSpecName]["Weapon Skills"] = weaponSkills;
-- print(AddonName.. ": Added Weapon Skills = ".. weaponSkills);
end
end
updateClassSpells = false;
-- end
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateSpellbookSpells_func: END");
end
 
 
-- Update the Pet-Spellbook and PetActionBar's spells --
-- Table of spellnames to exclude from storage
local PetSpellNameExclusions = { PET_ASSIST, PET_ACTION_ATTACK, PET_DEFENSIVE,PET_ACTION_FOLLOW,
PET_ACTION_MOVE_TO, PET_PASSIVE, "Stay" };
-- TABLE ABOVE: The 7 default actions for which GetSpellInfo() returns
-- nil. QUESTION: Would it be desirable to save these spell references,
-- which names would be the tokens (string) above?
 
-- Add one Pet Spell to the apropriate subtable
local addSpellbookPetSpell_func = function(spellName, spellSubName, spellID)
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addSpellbookPetSpell_func: START");
local isPassive = IsPassiveSpell(spellID);
if strfind(spellSubName, "Special") or strfind(spellSubName, "Bonus") or strfind(spellSubName, "Exotic") then -- Pet Family ability
if isPassive then
print(AddonName.. ": Add ".. petFamily.. " Passive : ".. spellName);
-- if SN2SID_PASSIVES_table[universalClassName].Pets[petFamily] == nil then
if not SN2SID_PASSIVES_table[universalClassName].Pets[petFamily] then
SN2SID_PASSIVES_table[universalClassName].Pets[petFamily] = { [spellName] = spellID, };
else
SN2SID_PASSIVES_table[universalClassName].Pets[petFamily][spellName] = spellID;
end
else
print(AddonName.. ": Add ".. petFamily.. " : ".. spellName);
if not SN2SID_table[universalClassName].Pets[petFamily] then
SN2SID_table[universalClassName].Pets[petFamily] = { [spellName] = spellID, };
else
SN2SID_table[universalClassName].Pets[petFamily][spellName] = spellID;
end
end
-- elseif (strfind(spellSubName, "Basic") or (not isPassive)) and not
-- (strfind(spellSubName, "Ferocity") or strfind(spellSubName, "Tenacity")
-- or strfind(spellSubName, "Cunning")) then -- All three Pet Specializations
elseif strfind(spellSubName, "Basic") or ((not isPassive) and not
(strfind(spellSubName, "Ferocity") or strfind(spellSubName, "Tenacity")
or strfind(spellSubName, "Cunning"))) then -- All three Pet Specializations
print(AddonName.. ": Add All Specs : ".. spellName);
-- if SN2SID_table[universalClassName].Pets["Ferocity"] == nil then
if not SN2SID_table[universalClassName].Pets["Ferocity"] then
SN2SID_table[universalClassName].Pets["Ferocity"] = { [spellName] = spellID, };
else
SN2SID_table[universalClassName].Pets["Ferocity"][spellName] = spellID;
end
-- if SN2SID_table[universalClassName].Pets["Tenacity"] == nil then
if not SN2SID_table[universalClassName].Pets["Tenacity"] then
SN2SID_table[universalClassName].Pets["Tenacity"] = { [spellName] = spellID, };
else
SN2SID_table[universalClassName].Pets["Tenacity"][spellName] = spellID;
end
-- if SN2SID_table[universalClassName].Pets["Cunning"] == nil then
if not SN2SID_table[universalClassName].Pets["Cunning"] then
SN2SID_table[universalClassName].Pets["Cunning"] = { [spellName] = spellID, };
else
SN2SID_table[universalClassName].Pets["Cunning"][spellName] = spellID;
end
-- end
elseif isPassive and (not (strfind(spellSubName, "Ferocity") or strfind(spellSubName, "Tenacity")
or strfind(spellSubName, "Cunning"))) then
print(AddonName.. ": Add All Specs Passive : ".. spellName);
-- if SN2SID_PASSIVES_table[universalClassName].Pets["Ferocity"] == nil then
if not SN2SID_PASSIVES_table[universalClassName].Pets["Ferocity"] then
SN2SID_PASSIVES_table[universalClassName].Pets["Ferocity"] = { [spellName] = spellID, };
else
SN2SID_PASSIVES_table[universalClassName].Pets["Ferocity"][spellName] = spellID;
end
-- if SN2SID_PASSIVES_table[universalClassName].Pets["Tenacity"] == nil then
if not SN2SID_PASSIVES_table[universalClassName].Pets["Tenacity"] then
SN2SID_PASSIVES_table[universalClassName].Pets["Tenacity"] = { [spellName] = spellID, };
else
SN2SID_PASSIVES_table[universalClassName].Pets["Tenacity"][spellName] = spellID;
end
-- if SN2SID_PASSIVES_table[universalClassName].Pets["Cunning"] == nil then
if not SN2SID_PASSIVES_table[universalClassName].Pets["Cunning"] then
SN2SID_PASSIVES_table[universalClassName].Pets["Cunning"] = { [spellName] = spellID, };
else
SN2SID_PASSIVES_table[universalClassName].Pets["Cunning"][spellName] = spellID;
end
else
if strfind(spellSubName, "Ferocity") then -- Ferocity
if isPassive then
print(AddonName.. ": Add Ferocity Passive : ".. spellName);
-- if SN2SID_PASSIVES_table[universalClassName].Pets["Ferocity"] == nil then
if not SN2SID_PASSIVES_table[universalClassName].Pets["Ferocity"] then
SN2SID_PASSIVES_table[universalClassName].Pets["Ferocity"] = { [spellName] = spellID, };
else
SN2SID_PASSIVES_table[universalClassName].Pets["Ferocity"][spellName] = spellID;
end
else
print(AddonName.. ": Add Ferocity : ".. spellName);
-- if SN2SID_table[universalClassName].Pets["Ferocity"] == nil then
if not SN2SID_table[universalClassName].Pets["Ferocity"] then
SN2SID_table[universalClassName].Pets["Ferocity"] = { [spellName] = spellID, };
else
SN2SID_table[universalClassName].Pets["Ferocity"][spellName] = spellID;
end
end
-- end
elseif strfind(spellSubName, "Tenacity") then -- Tenacity
if isPassive then
print(AddonName.. ": Add Tenacity Passive : ".. spellName);
-- if SN2SID_PASSIVES_table[universalClassName].Pets["Tenacity"] == nil then
if not SN2SID_PASSIVES_table[universalClassName].Pets["Tenacity"] then
SN2SID_PASSIVES_table[universalClassName].Pets["Tenacity"] = { [spellName] = spellID, };
else
SN2SID_PASSIVES_table[universalClassName].Pets["Tenacity"][spellName] = spellID;
end
else
print(AddonName.. ": Add Tenacity : ".. spellName);
-- if SN2SID_table[universalClassName].Pets["Tenacity"] == nil then
if not SN2SID_table[universalClassName].Pets["Tenacity"] then
SN2SID_table[universalClassName].Pets["Tenacity"] = { [spellName] = spellID, };
else
SN2SID_table[universalClassName].Pets["Tenacity"][spellName] = spellID;
end
end
-- end
elseif strfind(spellSubName, "Cunning") then -- Cunning
if isPassive then
print(AddonName.. ": Add Cunning Passive : ".. spellName);
-- if SN2SID_PASSIVES_table[universalClassName].Pets["Cunning"] == nil then
if not SN2SID_PASSIVES_table[universalClassName].Pets["Cunning"] then
SN2SID_PASSIVES_table[universalClassName].Pets["Cunning"] = { [spellName] = spellID, };
else
SN2SID_PASSIVES_table[universalClassName].Pets["Cunning"][spellName] = spellID;
end
else
print(AddonName.. ": Add Cunning : ".. spellName);
-- if SN2SID_table[universalClassName].Pets["Cunning"] == nil then
if not SN2SID_table[universalClassName].Pets["Cunning"] then
SN2SID_table[universalClassName].Pets["Cunning"] = { [spellName] = spellID, };
else
SN2SID_table[universalClassName].Pets["Cunning"][spellName] = spellID;
end
end
end
end
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addSpellbookPetSpell_func: END");
end
 
-- Pet Spells update function
local updatePetSpellNames = function()
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updatePetSpellNames: START");
-- print(AddonName.. ": Fetching Pet spells");
-- local petHasSpellsConfirmed = false;
-- NOTES:
-- GetSpellInfo(spellName) is the most reliable way to get the SpellID for a give SpellName, 7th
-- return value. BUT we need to get a list of spell names first, and that's where the other two
-- Blizzard functions, GetPetActionInfo(buttonNumber) and GetSpellBookItemName(SpellbookIndex,
-- BOOKTYPE_PET), come in.
--
-- GetPetActionInfo(buttonNumber) only retrieves information for spells on the PetActionBar;
-- given that there might be other Pet Spells - on the PetSpellbook - we will later need to get
-- them using other means. But first we will get these spells from the bar, for these reasons:
-- - One thing to note is the 'isToken' return value from GetPetActionInfo(). This value will be
-- true if the spell is one of the 7 standard spells that every controllable pet gets: Assist,
-- Attack, Defensive, Follow, Move To, Passive, Stay. This flag is NOT returned by any of the
-- the other functions we get info on PetSpells from. Again, unfortunately, GetPetActionInfo()
-- only returns info on spells in the PetActionBar and not all PetSpells are in there.
-- Another important thing to note is that Temporary Controllable-pets (e.g. the Elemental
-- Shaman pets, if the talent 'Primal Elementalist' is active) do not have any spells in a
-- spellbook; but all their spells should be on the PetActionBar. Thus GetPetActionInfo is the
-- only way - and the only way needed - to get info on these pets' spells.
--
-- GetSpellBookItemInfo() not only does not return anything for Temporary Controllable-pets, it
-- also seems BUGGED, as it returns weird values for Pet SpellIDs (9 or 10 digits long numbers,
-- sometimes negatives!).
-- GetSpellBookItemName() (other function) however returns correct SpellNames and is rather
-- exaustive as far as getting them for permanent pets.
 
-- local petName = GetUnitName("pet", nil);
-- local petFamily = UnitCreatureFamily("pet");
petFamily = UnitCreatureFamily("pet");
if (not petFamily) or (petFamily == "") then -- First time UNIT_PET fires, the info on the Pet hasn't been loaded yet
return; -- UNIT_PET fires two to three times when a new pet is summoned.
end
print(AddonName.. ": Pet Family = ".. tostring(petFamily));
 
local _, isHunterPet = HasPetUI();
 
if isHunterPet then -- Hunter Pets, unlike all others, have specializations, so we'll handle
-- their spells differently
local curPetSpecIndex = GetSpecialization(false, true);
local stubVal;
stubVal, petSpec = GetSpecializationInfo(curPetSpecIndex or 1, false, true);
print(AddonName.. ": Pet Spec #".. tostring(curPetSpecIndex).. "; Pet Family: ".. tostring(petFamily));
 
-- GetSpellBookItemName(SpellbookIndex, BOOKTYPE_PET) + GetSpellInfo(spellName) --
if HasPetSpells() then -- I.e. whether there is a Pet Spellbook. WARNING: Returns 'true' for
-- classes which have pets but are too low level to have control
-- over them; e.g. Hunters and Warlocks under Level 10.
print(AddonName.. ": Getting SBook spells for pet: ".. petFamily);
local i = 0;
repeat
i = i + 1;
local spellName, spellSubName = GetSpellBookItemName(i, BOOKTYPE_PET);
-- print(AddonName.. ": Book: ".. tostring(spellName).. " ; ".. tostring(spellSubName));
if spellName then
-- No isToken flag from GetPetActionInfo() here, so do the check ourselves
local isToken = false;
if PetSpellNameExclusions[spellName] then
isToken = true;
end
if not isToken then
local _, _, _, _, _, _, spellID = GetSpellInfo(spellName);
-- local isPassive = IsPassiveSpell(spellID);
if spellID then -- Sanity check
-- NEW for 1.0.14 --
if (not spellSubName) or (spellSubName == "") then
local delayedSpellInfo = Spell:CreateFromSpellID(spellID);
-- I presume we don't actually need to cancel the request for the additional
-- information, i.e. presume once the information is given to us through the
-- function delayedSpellInfo:ContinueOnSpellLoad(), there will be no further
-- activity regarding this- But, just in case, we'll set up a function to
-- cancel the request after we got the information we need.
-- local spellDataLoadedCancelFunc = delayedSpellInfo:ContinueWithCancelOnSpellLoad(function() -- We don't need to do anything upon canceling the request
-- print(AddonName.. ": Now cancelling the request for delayed information about spell ID: ".. spellID);
-- end);
-- Actually get the information and use it to update our database:
delayedSpellInfo:ContinueOnSpellLoad(function()
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": delayedSpellInfo: START");
-- print(AddonName.. ": Will now get the previously delayed information about spell ID: ".. spellID);
-- Although we should only need to update spellSubName, we might
-- have fetched a new spellName + spellID by now. Thus, we'll
-- update those fields too.
spellName = delayedSpellInfo:GetSpellName();
spellSubName = delayedSpellInfo:GetSpellSubtext(); -- Mandatory
spellID = delayedSpellInfo:GetSpellID();
addSpellbookPetSpell_func(spellName, spellSubName, spellID);
-- Now cancel the request:
-- spellDataLoadedCancelFunc();
-- spellDataLoadedCancelFunc = nil; -- for safety!
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": delayedSpellInfo: END");
end);
else
addSpellbookPetSpell_func(spellName, spellSubName, spellID);
end
-- --
-- else
-- print(AddonName.. ": Pet spell #".. i.. ": NO ID!");
end
-- else
-- print(AddonName.. ": Pet spell #".. i.." is a token.");
end
end
until spellName == nil;
-- petHasSpellsConfirmed = true;
end
 
-- GetSpellBookItemName(SpellbookIndex, BOOKTYPE_PET) + GetSpellInfo(spellName) --
elseif HasPetSpells() then -- I.e. whether there is a Pet Spellbook. WARNING: Will return TRUE
-- for all characters whose classes have pets, regardless of
-- whether or not the character's level is high enough to have
-- control over them; e.g. TRUE for Warlocks under Level 10.
print(AddonName.. ": Getting SBook spells for pet: ".. petFamily);
local i = 0;
repeat
i = i + 1;
-- local spellName, spellSubName = GetSpellBookItemName(i, BOOKTYPE_PET);
local spellName = (GetSpellBookItemName(i, BOOKTYPE_PET));
-- NB: We don't actually use the value of 'spellSubName' within the current scope;
-- the value is a stub. Thus there is no need to use the SpellMixin API here.
-- print(AddonName.. ": Book: ".. tostring(spellName));
if spellName then
local isToken = false;
if PetSpellNameExclusions[spellName] then
isToken = true;
end
if not isToken then
-- local _, spellID = GetSpellBookItemInfo(i, BOOKTYPE_PET);
local _, _, _, _, _, _, spellID = GetSpellInfo(spellName);
if spellID then -- Sanity check
if IsPassiveSpell(spellID) then
-- if SN2SID_PASSIVES_table[universalClassName].Pets[petFamily] == nil then
if not SN2SID_PASSIVES_table[universalClassName].Pets[petFamily] then
SN2SID_PASSIVES_table[universalClassName].Pets[petFamily] = { [spellName] = spellID, };
else
SN2SID_PASSIVES_table[universalClassName].Pets[petFamily][spellName] = spellID;
end
else
-- if SN2SID_table[universalClassName].Pets[petFamily] == nil then
if not SN2SID_table[universalClassName].Pets[petFamily] then
SN2SID_table[universalClassName].Pets[petFamily] = { [spellName] = spellID, };
else
SN2SID_table[universalClassName].Pets[petFamily][spellName] = spellID;
end
end
end
end
end
until spellName == nil;
-- petHasSpellsConfirmed = true;
end
 
-- GetPetActionInfo(buttonNumber) + GetSpellInfo(spellName) --
if (not isHunterPet) and PetHasActionBar() then -- As all controllable pets are marked to have. Note: HasPetUI()
-- returns 'true' for classes which have pets but are too low level
-- to have control over them; e.g. Warlocks under Level 10.
-- PetHasActionBar() only returns 1 if a PetActionBar actually
-- should be shown (but regardless of the result of :IsShown).
print(AddonName.. ": Getting ABar spells for pet: ".. petFamily);
for i = 1, NUM_PET_ACTION_SLOTS do
-- local spellName, spellSubName, _, isToken, _, _, _ = GetPetActionInfo(i);
local spellName, _, _, isToken, _, _, _ = GetPetActionInfo(i);
-- NB: We don't actually use the value of 'spellSubName' within the current scope;
-- the value is a stub. Thus there is no need to use the SpellMixin API here.
-- print(AddonName.. ": BarButton".. i..": ".. tostring(spellName));
if spellName and (not isToken) then
local _, _, _, _, _, _, spellID = GetSpellInfo(spellName);
if spellID then -- Sanity check
if IsPassiveSpell(spellID) then
if not SN2SID_PASSIVES_table[universalClassName].Pets[petFamily] then
SN2SID_PASSIVES_table[universalClassName].Pets[petFamily] = { [spellName] = spellID, };
else
SN2SID_PASSIVES_table[universalClassName].Pets[petFamily][spellName] = spellID;
end
else
if not SN2SID_table[universalClassName].Pets[petFamily] then
SN2SID_table[universalClassName].Pets[petFamily] = { [spellName] = spellID, };
else
SN2SID_table[universalClassName].Pets[petFamily][spellName] = spellID;
end
end
end
end
end
-- petHasSpellsConfirmed = true;
end
-- print(AddonName.. ": Fetched? ".. tostring(petHasSpellsConfirmed));
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updatePetSpellNames: END");
end
 
 
local addSpellsPostUpdate = function()
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addSpellsPostUpdate: START");
if postUpdate_Spells2Add and SN2SID_table then -- Sanity check
for key, value in pairs(postUpdate_Spells2Add) do
if key == "General" or key == universalClassName then -- Only add hardcoded spells for
-- GeneralTab or Current Class
for keyk, valuev in pairs(value) do
if keyk == "FlyoutsTOGET" then
-- print(AddonName.. ": Will get flyout spells for FlyoutButtonName ".. keykk.. " with ID ".. valuevv);
-- addFlyoutSpells_func(keyk, valuev);
for keykk, valuevv in pairs(valuev) do
addFlyoutSpells_func(keykk, valuevv);
end
elseif not SN2SID_table[key][keyk] then -- specName(..somethingMaybe)
-- OR "FlyoutsTOGET" OR
-- "Flyouts" OR "Pets" OR
-- someGeneralTabCategory.
-- print(AddonName.. ": Adding: ".. tostring(valuev));
SN2SID_table[key][keyk] = valuev;
elseif type(valuev) == "table" then
for keykk, valuevv in pairs(valuev) do
if not SN2SID_table[key][keyk][keykk] then -- Spell OR Flyouts_spell OR
-- PetFamily is not on the
-- target table yet
-- print(AddonName.. ": Adding: ".. tostring(valuevv));
SN2SID_table[key][keyk][keykk] = valuevv;
end
if type(valuevv) == "table" then -- Flyouts_spell OR PetFamily
for keykkk, valuevvv in pairs(valuevv) do
if not SN2SID_table[key][keyk][keykk][keykkk] then
-- Flyouts_spell_Spell OR
-- PetFamily_spell is not
-- yet on the table.
-- print(AddonName.. ": Adding: ".. tostring(valuevvv));
SN2SID_table[key][keyk][keykk][keykkk] = valuevvv;
end
end
end
end
end
end
 
end
end
end
 
if postUpdate_Spells2Add_PASSIVES and SN2SID_PASSIVES_table then
for key, value in pairs(postUpdate_Spells2Add_PASSIVES) do
if key == "General" or key == universalClassName then -- Only add hardcoded spells for
-- GeneralTab or Current Class
for keyk, valuev in pairs(value) do
-- if SN2SID_PASSIVES_table[key][keyk] == nil then -- "Spells" OR specName(..somethingMaybe) OR
if not SN2SID_PASSIVES_table[key][keyk] then -- "Spells" OR specName(..somethingMaybe) OR
-- "Pets" is not on the target table yet
-- print(AddonName.. ": Adding: ".. tostring(valuev));
SN2SID_PASSIVES_table[key][keyk] = valuev;
elseif type(valuev) == "table" then -- "Spells" OR specName(..somethingMaybe) OR
-- "Pets" table
for keykk, valuevv in pairs(valuev) do
-- if SN2SID_PASSIVES_table[key][keyk][keykk] == nil then -- Spell OR Flyouts_spell OR
if not SN2SID_PASSIVES_table[key][keyk][keykk] then -- Spell OR Flyouts_spell OR
-- PetFamily is not on the
-- target table yet
-- print(AddonName.. ": Adding: ".. tostring(valuevv));
SN2SID_PASSIVES_table[key][keyk][keykk] = valuevv;
elseif type(valuevv) == "table" then -- Flyouts_spell OR PetFamily
for keykkk, valuevvv in pairs(valuevv) do
-- if SN2SID_PASSIVES_table[key][keyk][keykk][keykkk] == nil then -- Flyouts_spell_Spell OR
if not SN2SID_PASSIVES_table[key][keyk][keykk][keykkk] then -- Flyouts_spell_Spell OR
-- PetFamily_spell is not
-- on the target table yet
-- print(AddonName.. ": Adding: ".. tostring(valuevvv));
SN2SID_PASSIVES_table[key][keyk][keykk][keykkk] = valuevvv;
end
end
 
end
end
 
end
end
 
end
end
end
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addSpellsPostUpdate: END");
end
 
 
-- -- -- RUNTIME -- -- --
-------------------------
 
-- Frame to listen to game events
local SN2SID_frame, SN2SID_events = CreateFrame("Frame", nil), {};
-- NB: When ADDON_LOADED fires, the SpellBook etc aren't available yet, only upon PLAYER_LOGIN.
SN2SID_frame:RegisterEvent("PLAYER_LOGIN");
 
-- Function to call upon PLAYER_LOGIN (see bottom of file)
local lsn2sidpStartup = function()
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": lsn2sidpStartup: START");
-- Startup --
print(AddonName.. ": Startup!");
-- Copy the global saved-variables tables to our local tables
SN2SID_table = AddonEnv.SpellNamesAndIDs or SpellNamesAndIDs or {};
SN2SID_PASSIVES_table = AddonEnv.SpellNamesAndIDs_PASSIVES or SpellNamesAndIDs_PASSIVES or {};
-- DEBUGmsgs = AddonEnv.DEBUG_messages or DEBUG_messages or {};
 
-- tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Print tables\' tostring to console: START");
-- print(AddonName.. ": AddonEnv.SpellNamesAndIDs = ".. tostring(AddonEnv.SpellNamesAndIDs)); -- nil
-- print(AddonName.. ": AddonEnv.SpellNamesAndIDs_PASSIVES = ".. tostring(AddonEnv.SpellNamesAndIDs_PASSIVES)); -- nil
-- print(AddonName.. ": AddonEnv.DEBUG_messages = ".. tostring(AddonEnv.DEBUG_messages)); -- nil
-- print(AddonName.. ": SpellNamesAndIDs = ".. tostring(SpellNamesAndIDs)); -- TableA
-- print(AddonName.. ": SpellNamesAndIDs_PASSIVES = ".. tostring(SpellNamesAndIDs_PASSIVES)); -- TableB
-- print(AddonName.. ": DEBUG_messages = ".. tostring(DEBUG_messages)); -- TableB
-- print(AddonName.. ": SN2SID_table = ".. tostring(SN2SID_table));-- TableA
-- print(AddonName.. ": SN2SID_PASSIVES_table = ".. tostring(SN2SID_PASSIVES_table)); -- TableB
-- print(AddonName.. ": DEBUGmsgs = ".. tostring(DEBUGmsgs)); -- TableB
-- tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Print tables\' tostring to console: END");
 
-- -- Metadata fields: Data source, Class', ... -- --
-- Data source --
-- We're only interested in storing the English names, at least for now
local curLocale = GetLocale();
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Got: curLocale = ".. curLocale);
if ( curLocale ~= "enUS") then
SN2SID_frame:UnregisterAllEvents();
error(AddonName.. " only retrieves data from English (enUS or enGB) clients.");
-- return;
end
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Validated: curLocale");
local stubVal;
stubVal, universalRaceName = UnitRace("player");
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Got: universalRaceName (no validation needed) = ".. universalRaceName);
-- Self-explanatory:
local _, gameBuild = GetBuildInfo();
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Got: gameBuild");
-- For some reason, the variable gameBuild is being saved as a string; convert to number:
gameBuild = tonumber(gameBuild);
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Validated that gameBuild is a number. gameBuild = ".. gameBuild.. ": Done.");
local charLevel = UnitLevel("player");
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Got: charLevel (no validation needed) = ".. charLevel);
-- Spells in the General tab: Racial abilities, etc
-- local generalTabName = (GetSpellTabInfo(1)); -- Tab#1 = General
generalTabName = (GetSpellTabInfo(1)); -- Tab#1 = General
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Got: generalTabName (no validation needed) = ".. generalTabName);
-- Class stuff --
-- local universalClassName = select(2, UnitClass("player")); -- Locale-independent Class name
stubVal, universalClassName = UnitClass("player"); -- Locale-independent Class name
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Got: universalClassName (no validation needed) = ".. universalClassName);
local ClassNumSpecs = GetNumSpecializations(false, false); -- Number of Specialisations
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Got: ClassNumSpecs (no validation needed) = ".. ClassNumSpecs);
-- Ordered list of Class specs' IDs and Names -- Do we still use this?
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Order list of Class specs' IDs and Names: START");
local specID, specName = GetSpecializationInfo(1);
local ClassSpecNames2IDs = {};
for i = 1, ClassNumSpecs do
local specID, specName = GetSpecializationInfo(i);
ClassSpecNames2IDs[specName] = specID;
end
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Order list of Class specs' IDs and Names: END");
 
---- Check the tables' skeleton structure and build whatever may be missing ----
--
if not SN2SID_table then -- sanity check
error(AddonName.. "Local copy of saved variables is missing.");
-- return;
end
if not SN2SID_PASSIVES_table then -- sanity check
error(AddonName.. "Local copy of saved variables is missing.");
-- return;
end
--
-- If needed, create and populate the Metadata subtables; --
-- Flag spell-lists for update if applicable --
--
-- General tab skeleton + dataSource + raceBuilds
-- NB: We separate the two types of tables in two if-loops for the sake of sanity-keep (against
-- e.g. manual edits to the file).
if not SN2SID_table[generalTabName] then
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. generalTabName.. " dataSource for Active spells: START");
print(AddonName.. ": Will now create the ".. generalTabName.. " dataSource for Active spells.");
SN2SID_table[generalTabName] = {};
SN2SID_table[generalTabName].METADATA = {};
SN2SID_table[generalTabName].METADATA.dataSource = {
clientLocale = curLocale, -- Currently always enUS
gameBuild = gameBuild,
charLevel = charLevel,
charMaxLevel = charLevel,
};
SN2SID_table[generalTabName].METADATA.raceBuilds = { [universalRaceName] = gamebuild };
-- We've just created and populated the GeneralTabMetadata, hence no need to update
updateGeneralTabMetadata = false;
updateGeneralSpells = true; -- Do populate the actual list of spells
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. generalTabName.. " dataSource for Active spells: END");
else
updateGeneralTabMetadata = true; -- Will check whether it's updated; if not, will update;
-- The function which checks above var will also flag for Spells-list update if needed.
end
if not SN2SID_PASSIVES_table[generalTabName] then
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. generalTabName.. " dataSource for Passive spells: START");
print(AddonName.. ": Will now create the ".. generalTabName.. " dataSource for Passive spells.");
SN2SID_PASSIVES_table[generalTabName] = {};
SN2SID_PASSIVES_table[generalTabName].METADATA = {};
SN2SID_PASSIVES_table[generalTabName].METADATA.dataSource = {
clientLocale = curLocale, -- Currently always enUS
gameBuild = gameBuild,
charLevel = charLevel,
charMaxLevel = charLevel,
};
SN2SID_PASSIVES_table[generalTabName].METADATA.raceBuilds = { [universalRaceName] = gamebuild };
-- We've just created and populated the GeneralTabMetadata, hence no need to update ...
updateGeneralTabMetadata = false; -- And this seems redundant. Keep it 'cause I'll forget it otherwise...
updateGeneralSpells = true; -- Do populate the actual list of spells
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. generalTabName.. " dataSource for Passive spells: END");
else
updateGeneralTabMetadata = true; -- Will check whether it's updated, if not will update;
-- The function which checks above var will also flag for Spells-list update if needed.
end
-- Run the update function (does both Active and Passive trees)
updateGeneralTabMetadata_func(curLocale, gameBuild, charLevel);
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Updated the ".. generalTabName.. " Metadata \(or not\!\) for both Active and Passive spells.");
 
-- Class spells' Metadata (dataSource only; class Specs will be handled afterwards)
if not SN2SID_table[universalClassName] then
print(AddonName.. ": Will now create the ".. universalClassName.. "'s table and dataSource for Active spells.");
SN2SID_table[universalClassName] = {};
else
updateClassMetadata = true; -- Will check whether it's updated and if not, will update;
-- The function which checks above var will also flag for Spells-list update if needed.
end
if not SN2SID_table[universalClassName].METADATA then
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. universalClassName.. " dataSource for Active spells: START");
SN2SID_table[universalClassName].METADATA = {};
SN2SID_table[universalClassName].METADATA.dataSource = {
clientLocale = curLocale, -- Currently always enUS
gameBuild = gameBuild,
charLevel = charLevel,
charMaxLevel = charLevel,
};
-- We've just created and populated the Class' dataSource fields, hence no need to update;
-- Class Specs fields are updated in another if-clause, further ahead.
updateClassMetadata = false;
updateClassSpells = true; -- Do populate the actual list of spells.
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. universalClassName.. " dataSource for Active spells: END");
else
updateClassMetadata = true; -- Will check whether it's updated and if not, will update;
-- The function which checks above var will also flag for Spells-list update if needed.
end
 
if not SN2SID_PASSIVES_table[universalClassName] then
print(AddonName.. ": Will now create the ".. universalClassName.. "'s table and dataSource for Passive spells.");
SN2SID_PASSIVES_table[universalClassName] = {};
else
updateClassMetadata = true;
-- The function which checks above var will also flag for Spells-list update if needed.
end
if not SN2SID_PASSIVES_table[universalClassName].METADATA then
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. universalClassName.. " dataSource for Passive spells: START");
SN2SID_PASSIVES_table[universalClassName].METADATA = {};
SN2SID_PASSIVES_table[universalClassName].METADATA.dataSource = {
clientLocale = curLocale, -- Currently always enUS
gameBuild = gameBuild,
charLevel = charLevel,
charMaxLevel = charLevel,
};
-- We've just created and populated the Class' dataSource fields, hence no need to update;
-- Class Specs fields are updated in another if-clause, further ahead.
updateClassMetadata = false;
updateClassSpells = true; -- Do populate the actual list of spells.
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. universalClassName.. " dataSource for Passive spells: END");
else
updateClassMetadata = true; -- Will check whether it's updated and if not, will update;
-- The function which checks above var will also flag for Spells-list update if needed.
end
 
-- Do the actual update of the Class Metadata (dataSource only now; Specs will be handled next)
-- updateClassMetadata_func(SN2SID_table, SN2SID_PASSIVES_table, curLocale, gameBuild, universalClassName, charLevel);
-- updateClassMetadata_func(curLocale, gameBuild, universalClassName, charLevel);
updateClassMetadata_func(curLocale, gameBuild, charLevel);
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Ran updateClassMetadata_func().");
 
-- If needed, create and populate Class Specs' Active and Passive Spells --
-- Flag spell-lists for update if applicable --
if not SN2SID_table[universalClassName].METADATA.Specs then
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. universalClassName.. " \'Specs\' (Actives) tables: START");
print(AddonName.. ": Will now create the ".. universalClassName.. "'s \'Specs\' (Actives) tables.");
for i = 1, ClassNumSpecs do
local specID, specName = GetSpecializationInfo(i);
-- ClassSpecNames2IDs[i] = { specID, specName };
ClassSpecNames2IDs[specName] = specID;
-- print(AddonName.. ": ".. i.. " = ".. specID.. " = ".. specName); -- For reference
-- local specString = "Spec"..specID;
if not SN2SID_table[universalClassName].METADATA.Specs then
SN2SID_table[universalClassName].METADATA.Specs = {};
SN2SID_table[universalClassName].METADATA.Specs[specName] = specID; -- Reference
SN2SID_table[universalClassName][specName] = {}; -- For "[SpellName] = SpellID"
elseif not SN2SID_table[universalClassName].METADATA.Specs[i] then
SN2SID_table[universalClassName].METADATA.Specs[specName] = specID; -- Reference
SN2SID_table[universalClassName][specName] = {}; -- For "[SpellName] = SpellID"
end
end
updateClassSpells = true; -- Do populate the actual list of spells.
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. universalClassName.. " \'Specs\' (Actives) tables: END");
end
if not SN2SID_PASSIVES_table[universalClassName].METADATA.Specs then
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. universalClassName.. " \'Specs\' (Passives) tables: START");
print(AddonName.. ": Will now create the ".. universalClassName.. "'s \'Specs\' (Passives) tables.");
for i = 1, ClassNumSpecs do
local specID, specName = GetSpecializationInfo(i);
-- ClassSpecNames2IDs[i] = { specID, specName };
ClassSpecNames2IDs[specName] = specID;
-- print(AddonName.. ": ".. i.. " = ".. specID.. " = ".. specName); -- For reference
if not SN2SID_PASSIVES_table[universalClassName].METADATA.Specs then
SN2SID_PASSIVES_table[universalClassName].METADATA.Specs = {};
SN2SID_PASSIVES_table[universalClassName].METADATA.Specs[specName] = specID; -- Ref.
SN2SID_PASSIVES_table[universalClassName][specName] = {}; -- "[SpellName] = SpellID"
elseif not SN2SID_PASSIVES_table[universalClassName].METADATA.Specs[i] then
SN2SID_PASSIVES_table[universalClassName].METADATA.Specs[specName] = specID; -- Ref.
SN2SID_PASSIVES_table[universalClassName][specName] = {}; -- "[SpellName] = SpellID"
end
end
updateClassSpells = true; -- Do populate the actual list of spells.
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. universalClassName.. " \'Specs\' (Passives) tables: END");
end
 
-- Update General (always ATM) and Class SpellNames2SIDs (both Actives and Passives) --
updateClassSpells = true;
-- updateSpellbookSpells_func(SN2SID_table, SN2SID_PASSIVES_table, generalTabName, universalClassName, ClassNumSpecs, ClassSpecNames2IDs);
-- updateSpellbookSpells_func(generalTabName, universalClassName, ClassNumSpecs, ClassSpecNames2IDs);
-- updateSpellbookSpells_func(universalClassName, ClassNumSpecs, ClassSpecNames2IDs);
updateSpellbookSpells_func(ClassNumSpecs, ClassSpecNames2IDs);
-- Pet spells will only be available when a pet is out, so wait for it, i.e. wait for UNIT_PET
-- to fire for "player".
 
 
-- Set up Other Event-Handlers --
---------------------------------
 
function SN2SID_events:PLAYER_TALENT_UPDATE(self)
DBG_CurrentEvent = "PLAYER_TALENT_UPDATE";
DEBUGmsgs["PLAYER_TALENT_UPDATE"] = { tostring(GetTime()).. ": PLAYER_TALENT_UPDATE: START", }
-- updateGeneralSpells = true; -- unneeded, placeholder for future version
updateClassSpells = true;
-- updateSpellbookSpells_func(SN2SID_table, SN2SID_PASSIVES_table, generalTabName, universalClassName, ClassNumSpecs, ClassSpecNames2IDs);
-- updateSpellbookSpells_func(generalTabName, universalClassName, ClassNumSpecs, ClassSpecNames2IDs);
-- updateSpellbookSpells_func(universalClassName, ClassNumSpecs, ClassSpecNames2IDs);
updateSpellbookSpells_func(ClassNumSpecs, ClassSpecNames2IDs);
tinsert(DEBUGmsgs["PLAYER_TALENT_UPDATE"], tostring(GetTime()).. ": PLAYER_TALENT_UPDATE: END");
end
 
function SN2SID_events:PLAYER_LEVEL_UP(self, ...)
DBG_CurrentEvent = "PLAYER_LEVEL_UP";
DEBUGmsgs["PLAYER_LEVEL_UP"] = { tostring(GetTime()).. ": PLAYER_LEVEL_UP: START", }
-- UnitLevel("player") doesn't update its result soon enough to have it indicate the *new*
-- char level in response to this event. OTH, this event does provide arguments but,
-- whatever they are, they're NOT the new char leve, for sure. Might be best to just flag
-- for update on Logout. But we'll still do it here, for now.
updateGeneralTabMetadata = true; -- Maybe useful.
updateClassMetadata = true; -- Stuff like talents only become available at level 10.
-- updateClassMetadata_func(SN2SID_table, SN2SID_PASSIVES_table, curLocale, gameBuild, universalClassName, charLevel);
updateClassMetadata_func(curLocale, gameBuild, charLevel);
updateGeneralTabMetadata = true; -- Maybe useful.
updateClassMetadata = true; -- Stuff like talents only become available at level 10.
tinsert(DEBUGmsgs["PLAYER_LEVEL_UP"], tostring(GetTime()).. ": PLAYER_LEVEL_UP: END");
end
 
-- Update pets' existence and spells when one comes up for "player"
-- NB: Fires after PLAYER_LOGIN if the player already has a pet out. NO LONGER SO as of game
-- build 26365 and later; I only got this event to fire on 'Pet Dismiss' and 'Summon Pet' button
-- clicks. Also, see BUG described bellow!
-- fire on 'Pet Dismiss' and 'Summon Pet' button clicks. Also, see BUG described bellow!
-- function SN2SID_events:UNIT_PET(self, ...)
function SN2SID_events:UNIT_PET(...)
local arg1 = ...;
print(AddonName.. ": UNIT_PET fired with arg1 = ".. tostring(arg1));
if (not arg1) or (arg1 ~= "player") then
return;
end
DBG_CurrentEvent = "UNIT_PET";
DEBUGmsgs["UNIT_PET"] = { tostring(GetTime()).. ": UNIT_PET: START", }
if not SN2SID_table[universalClassName].Pets then
SN2SID_table[universalClassName].Pets = {};
end
if not SN2SID_PASSIVES_table[universalClassName].Pets then
SN2SID_PASSIVES_table[universalClassName].Pets = {};
end
-- updatePetSpellNames(SN2SID_table, SN2SID_PASSIVES_table, universalClassName);
-- updatePetSpellNames(universalClassName);
updatePetSpellNames();
tinsert(DEBUGmsgs["UNIT_PET"], tostring(GetTime()).. ": UNIT_PET: END");
end
 
function SN2SID_events:PLAYER_LOGOUT(self)
DBG_CurrentEvent = "PLAYER_LOGOUT";
-- Set up DEBUG = { LOGOUT = {} } subtable of messages
if not DEBUGmsgs["PLAYER_LOGOUT"] then
DEBUGmsgs["PLAYER_LOGOUT"] = {
tostring(GetTime()).. ": PLAYER_LOGOUT: START",
tostring(GetTime()).. ": DEBUGmsgs.PLAYER_LOGOUT created.",
};
else
DEBUGmsgs["PLAYER_LOGOUT"] = {
tostring(GetTime()).. ": PLAYER_LOGOUT: START",
tostring(GetTime()).. ": DEBUGmsgs.PLAYER_LOGOUT cleared.",
};
end
-- Bring everything up to date
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Update some variables\' values: START");
charLevel = UnitLevel("player");
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": charLevel's value = ".. tostring(charLevel));
updateGeneralTabMetadata = true;
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": updateGeneralTabMetadata's value = ".. tostring(updateGeneralTabMetadata));
updateClassMetadata = true;
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": updateClassMetadata's value = ".. tostring(updateClassMetadata));
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Update some variables\' values: END");
 
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Update Metadata: START");
updateGeneralTabMetadata_func(curLocale, gameBuild, charLevel);
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Updated GeneralTab Metadata.");
updateClassMetadata_func(curLocale, gameBuild, charLevel);
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Updated ".. universalClassName.. " Metadata.");
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Update Metadata: END");
 
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Update Spellbook spells: START");
updateSpellbookSpells_func(ClassNumSpecs, ClassSpecNames2IDs);
if SN2SID_table[universalClassName].Pets or SN2SID_PASSIVES_table[universalClassName].Pets
or UnitExists("pet") then
updatePetSpellNames();
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Updated Pet spells.");
else
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": NO Pet Spells to get.");
end
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Update Spellbook spells: END");
 
-- "Manually" add spells we cannot (or is not convenient to) get automatically
-- REENABLE THIS AFTER TEST:
addSpellsPostUpdate();
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Added hardcoded spells to General and Class tables.");
 
-- Copy our local tables to the global saved-variables tables --
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Copy session\'s Active and Passive Spells' tables to SavedVariables: START");
if AddonEnv.SpellNamesAndIDs then
AddonEnv.SpellNamesAndIDs = SN2SID_table;
else
SpellNamesAndIDs = SN2SID_table;
end
if AddonEnv.SpellNamesAndIDs_PASSIVES then
AddonEnv.SpellNamesAndIDs_PASSIVES = SN2SID_PASSIVES_table;
else
SpellNamesAndIDs_PASSIVES = SN2SID_PASSIVES_table;
end
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Copy session\'s Active and Passive Spells' tables to SavedVariables: END");
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Copy the DEBUG messages to SavedVariables: START");
if AddonEnv.DEBUG_messages then
AddonEnv.DEBUG_messages = DEBUGmsgs;
else
DEBUG_messages = DEBUGmsgs;
end
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Copy the DEBUG messages to SavedVariables: END");
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": PLAYER_LOGOUT: END");
end
 
-- Unregister the event (handler) in which we are now running
SN2SID_frame:UnregisterEvent("PLAYER_LOGIN");
-- Set the post-PLAYER_LOGIN event-handlers and Register the respective events
SN2SID_frame:SetScript("OnEvent", function(self, event, ...)
SN2SID_events[event](self, ...);
end);
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Unregistered Event: PLAYER_LOGIN");
for k, v in pairs(SN2SID_events) do
if k == "UNIT_PET" then
SN2SID_frame:RegisterUnitEvent("UNIT_PET", "player");
else
SN2SID_frame:RegisterEvent(k);
end
-- if SN2SID_frame:IsEventRegistered(k) then
-- print(AddonName.. ": Registered event: ".. tostring(k));
-- end
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Registered Event: ".. k);
end
tinsert(DEBUGmsgs["PLAYER_LOGIN"], (GetTime()).. ": PLAYER_LOGIN: END");
end
 
-- PLAYER_LOGIN event handler; we set up the other events when this one fires --
SN2SID_frame:SetScript("OnEvent", function(self, event)
DBG_CurrentEvent = "PLAYER_LOGIN";
DEBUGmsgs = AddonEnv.DEBUG_messages or DEBUG_messages or {};
if not DEBUGmsgs then
DEBUGmsgs = {
["PLAYER_LOGIN"] = {
tostring(GetTime()).. ": PLAYER_LOGIN: START",
tostring(GetTime()).. ": Will startup in 5 seconds time.",
},
};
else
DEBUGmsgs["PLAYER_LOGIN"] = {
tostring(GetTime()).. ": PLAYER_LOGIN: START",
tostring(GetTime()).. ": Will startup in 5 seconds time.",
};
end
C_Timer.After(5, lsn2sidpStartup);
end);
populator/tags/LibSpellName2SID-Populator-1.1.03/LibSpellName2SID-1.1-Populator.toc New file
0,0 → 1,10
## Interface: 80105
## Title: LibSpellName2SID-1.1: Populator (DEV)
## Notes: Get all spells from a character and save them to file.
## Author: aallkkaa
## Version: 1.1.03
## SavedVariables: SpellNamesAndIDs, SpellNamesAndIDs_PASSIVES, DEBUG_messages
## DefaultState: disabled
## X-Category: Development
 
LibSpellName2SID-1.1-Populator.lua
populator/trunk/LibSpellName2SID-1.1-Populator/LibSpellName2SID-1.1-Populator.lua
8,9 → 8,12
----------
local AddonName, AddonEnv = ...;
 
-- Local copies of the saved variables' tables: SpellNamesAndIDs and SpellNamesAndIDs_PASSIVES
local SN2SID_table, SN2SID_PASSIVES_table;
-- Local copies of the saved variables' tables: SpellNamesAndIDs, SpellNamesAndIDs_PASSIVES and DEBUG_messages
local SN2SID_table, SN2SID_PASSIVES_table, DEBUGmsgs;
 
-- Variables for debugging
local DBG_CurrentEvent = "" -- Event last fired when a task is being done
 
-- WoW Expansion/Patch constants
local NumberOfTalentTiers = 7; -- Current number of talent tiers - WoW-7.x.y and 8.x.y
-- local NumberOfPVPTalentTiers = 6; -- Current number of PVP talent tiers - WoW-7.x.y
194,6 → 197,23
},
},
["HUNTER"] = {
-- TODO: SPECS --
["Beast Mastery"] = {
["Call Pet"] = 9,
["Pet Utility"] = 103,
},
["Marksmanship"] = {
["Call Pet"] = 9,
["Pet Utility"] = 103,
},
["Survival"] = {
["Call Pet"] = 9,
["Pet Utility"] = 103,
},
["FlyoutsTOGET"] = {
["Call Pet"] = 9,
["Pet Utility"] = 103,
},
["Pets"] = {
-- https://www.wowhead.com/battle-for-azeroth-hunter-pet-guide#hunter-pet-family-list-tenacity
["Ferocity"] = {
251,6 → 271,9
["Talon Rend"] = 263852,
["Trick"] = 94022,
},
["Blood Beast"] = { -- 8.1
["Blood Bolt"] = 288962,
},
["Boar"] = { -- 8.x
["Bristle"] = 263869,
},
420,6 → 443,18
},
},
["MAGE"] = {
["Arcane"] = {
["Polymorph Variants"] = 92,
},
["Fire"] = {
["Polymorph Variants"] = 92,
},
["Frost"] = {
["Polymorph Variants"] = 92,
},
["FlyoutsTOGET"] = {
["Polymorph Variants"] = 92,
},
["Flyouts"] = {
-- Polymorph Variants are now fetchable (all the ones currently ingame) from the game,
-- regardless of whether the Mage has them or not (all, some, one or even none).
534,16 → 569,31
["Teleport: Dazar'alor"] = 281404, -- Horde only
},
},
-- Get the Pets spell from a high level Frost Mage instead
--[[
["Pets"] = {
["Water Elemental"] = { -- Frost specialization only
["Freeze"] = 33395,
["Waterbolt"] = 31707,
},
},
]]--
},
-- All Rogue Poisons are fetchable from the logged in character. The bellow is no longer needed.
--[[
["ROGUE"] = {
["Assassination"] = {
["Poisons"] = 66,
},
["Subtlety"] = {
["Poisons"] = 66,
},
["Outlaw"] = {
["Poisons"] = 66,
},
["FlyoutsTOGET"] = {
["Poisons"] = 66,
},
--[[
["Flyouts"] = {
["Poisons"] = { -- Since WoW 7.0, (I think) Assassintation specialization only. But, at
-- least on WoW 8.1.5, on the SpellBook of all three specializations.
554,20 → 604,23
["Wound Poison"] = 8679,
},
},
]]--
},
]]--
["SHAMAN"] = {
["Elemental"] = {
["Bloodlust"] = 2825, -- Horde
["Heroism"] = 32182, -- Alliance
["Hex Variants"] = 106,
},
["Enhancement"] = {
["Bloodlust"] = 2825, -- Horde
["Heroism"] = 32182, -- Alliance
["Hex Variants"] = 106,
},
["Restoration"] = {
["Bloodlust"] = 2825, -- Horde
["Heroism"] = 32182, -- Alliance
["Hex Variants"] = 106,
},
-- Hex Variants are now fetchable (all the ones currently ingame) from the game,
-- regardless of whether the Shaman has them or not (all, some, one or even none).
591,6 → 644,9
-- TODO: Implement a way to fetch the Shaman Hex Variants (as well as the Mage Polymorph
-- Variants), even if the character does not know any, by using the logic above (and
-- bellow if needed).
["FlyoutsTOGET"] = {
["Hex Variants"] = 106,
},
--[[
["Flyouts"] = {
["Hex Variants"] = { -- Hex variants (including the default "Frog") are all
620,14 → 676,14
},
]]--
["Pets"] = { -- In WoW 7.x.y, only the Elemental specialization has pets, which are only
-- controllable if the talent "Primal Elementalist"(5,2) is active (they're
-- guardians (no spells castable by the player) otherwise). On top of that,
-- although the Earth Elemental is always available to the Elemental Shaman
-- , the Fire and Storm elementals are mutually exclusive (Fire Elemental
-- becomes Storm Elemental if the talent "Storm Elemental" is chosen).
-- TL;DR: Better make sure the spells bellow are added, rather than going
-- through the gimmick of swithcing the talents every time we update the
-- SHAMAN lists of spells.
-- controllable if the talent "Primal Elementalist"(5,2) is active (they're
-- guardians (no spells castable by the player) otherwise). On top of that,
-- although the Earth Elemental is always available to the Elemental Shaman
-- , the Fire and Storm elementals are mutually exclusive (Fire Elemental
-- becomes Storm Elemental if the talent "Storm Elemental" is chosen).
-- TL;DR: Better make sure the spells bellow are added, rather than going
-- through the gimmick of swithcing the talents every time we update the
-- SHAMAN lists of spells.
["Earth Elemental"] = {
["Angered Earth"] = 36213, -- Taunt
["Harden Skin"] = 118337, -- -40% damage taken by the Shaman
646,6 → 702,18
},
},
["WARLOCK"] = {
["Affliction"] = {
["Summon Demon"] = 10,
},
["Demonology"] = {
["Summon Demon"] = 10,
},
["Destruction"] = {
["Summon Demon"] = 10,
},
["FlyoutsTOGET"] = {
["Summon Demon"] = 10,
},
["Pets"] = { -- Spells of the glyph-enhanced versions of the regular Warlock Demons.
-- NB: We're including spells that remain the same on both versions of the
-- demon.
792,14 → 860,15
----------------------------------------------------------------------------------------------------
 
-- Update the General tab dataSource + raceBuilds --
-- local updateGeneralTabMetadata_func = function(SN2SID_table, SN2SID_PASSIVES_table, curLocale, gameBuild, universalRaceName, generalTabName, charLevel)
-- local updateGeneralTabMetadata_func = function(curLocale, gameBuild, universalRaceName, generalTabName, charLevel)
-- local updateGeneralTabMetadata_func = function(curLocale, gameBuild, universalRaceName, charLevel)
local updateGeneralTabMetadata_func = function(curLocale, gameBuild, charLevel)
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateGeneralTabMetadata_func: START");
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": Check whether GeneralTab\'s Metadata needs update");
if not updateGeneralTabMetadata then
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": GeneralTab\'s Metadata does NOT need update.");
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateGeneralTabMetadata_func: END");
return;
end
 
tinsert(DEBUGmsgs[DBG_CurrentEvent], "GeneralTab\'s Metadata DOES need update.");
-- print(AddonName.. ": Will now check whether the GeneralTab Metadata needs updating.");
-- Actively-cast spells
if charLevel > SN2SID_table[generalTabName].METADATA.dataSource.charLevel then
842,15 → 911,19
updateGeneralSpells = true;
end
updateGeneralTabMetadata = false;
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateGeneralTabMetadata_func: END");
end
 
-- Update the Class dataSource --
-- local updateClassMetadata_func = function(SN2SID_table, SN2SID_PASSIVES_table, curLocale, gameBuild, universalClassName, charLevel)
-- local updateClassMetadata_func = function(curLocale, gameBuild, universalClassName, charLevel)
local updateClassMetadata_func = function(curLocale, gameBuild, charLevel)
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateClassMetadata_func: START");
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": Check whether ".. universalClassName.. "\'s Metadata needs update.");
if not updateClassMetadata then
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": ".. universalClassName.. "\'s Metadata does NOT need update.");
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateClassMetadata_func: END");
return;
end
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": ".. universalClassName.. "\'s Metadata DOES need update.");
-- print(AddonName.. ": Will now check whether the ".. universalClassName.. " Metadata needs updating.");
-- Actively-cast spells
if charLevel > SN2SID_table[universalClassName].METADATA.dataSource.charLevel then
879,16 → 952,16
updateClassSpells = true;
end
updateClassMetadata = false;
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateClassMetadata_func: END");
end
 
 
---- Functions to update the lists of Spell Names and their IDs ----
--------------------------------------------------------------------
 
-- Update the Talents' lists of spells
-- local updateTalentSpells_func = function(SN2SID_table, SN2SID_PASSIVES_table, universalClassName, ClassNumSpecs, ClassSpecNames2IDs)
-- local updateTalentSpells_func = function(universalClassName, ClassNumSpecs, ClassSpecNames2IDs)
-- Update the PvE Talents' lists of spells
local updateTalentSpells_func = function(ClassNumSpecs, ClassSpecNames2IDs)
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateTalentSpells_func: START");
if not updateClassSpells then -- Sanity check
return;
end
907,7 → 980,7
-- SN2SID_PASSIVES_table[universalClassName][locSpecName.."_Talents"] = {};
-- end
else
print(AddonName.. ": PVE: NO specialization has been selected for this character!");
-- print(AddonName.. ": PVE: NO specialization has been selected for this character!");
return;
end
-- Populate the "SpecName_Talents" subtables
937,16 → 1010,17
-- and then fetch the keys in order from that array-table and then the corresponding values
-- from another tab le (the original, unordered/unsorted key-value pairs table).
-- The function from https://wow.gamepedia.com/Orderedpairs gets you the ordered values
-- form the unordered table in running-time, but cannot be used to change the stored data,
-- from the unordered table in running-time, but cannot be used to change the stored data,
-- just like the extract-keys-then-sort-them method above.
-- Thus, it's not possible to store the data in an easy to visually (or OS-based) diff two
-- versions of a database, as I wished.
end
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateTalentSpells_func: END");
end
 
-- local updatePVPTalentSpells_func = function(SN2SID_table, SN2SID_PASSIVES_table, universalClassName, ClassNumSpecs, ClassSpecNames2IDs)
-- local updatePVPTalentSpells_func = function(universalClassName, ClassNumSpecs, ClassSpecNames2IDs)
-- Update the PvP Talents' lists of spells
local updatePVPTalentSpells_func = function(ClassNumSpecs, ClassSpecNames2IDs)
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updatePVPTalentSpells_func: START");
if not updateClassSpells then -- Sanity check
return;
end
965,7 → 1039,7
SN2SID_PASSIVES_table[universalClassName][locSpecName.."_PVPTalents"] = {};
end
else
print(AddonName.. ": PVP: NO specialization has been selected for this character!");
-- print(AddonName.. ": PVP: NO specialization has been selected for this character!");
return;
end
-- Populate the "SpecName_PVPTalents" subtables
986,11 → 1060,13
end
end
end
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updatePVPTalentSpells_func: END");
end
 
local armorSkills, weaponSkills;
-- Helper functions to function updateSpellbookSpells_func() --
local addSpellbookSpellToGeneral_func = function(spellName, spellSubName, spellID)
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addSpellbookSpellToGeneral_func: START");
-- Store Passive and Active abilities into their own separate tables
if IsPassiveSpell(spellID) then
if spellName == "Armor Skills" then
1034,7 → 1110,7
-- in our list of hardcoded Zone spells first. Now, we do that test last, as there is at
-- least one instance of a spell with the same name, but different IDs, that is a Racial
-- (that we fetch from the server) and also a hardcoded Zone ability: "Light's Judgment".
if spellSubName and strfind(spellSubName, "Racial") then
if spellSubName and strfind(spellSubName, "Racial") then
if not SN2SID_table[generalTabName].Racials[universalRaceName] then
SN2SID_table[generalTabName].Racials[universalRaceName] = { [spellName] = spellID };
else
1047,36 → 1123,131
SN2SID_table[generalTabName].GuildPerks[spellName] = spellID;
end
-- Will now test for the hardcoded ZoneAbilities, to place them in the correct subcategory
elseif postUpdate_Spells2Add.General.ZoneAbilities[spellName] then
if not SN2SID_table[generalTabName].ZoneAbilities then
SN2SID_table[generalTabName].ZoneAbilities = { [spellName] = spellID };
else
SN2SID_table[generalTabName].ZoneAbilities[spellName] = spellID;
end
elseif postUpdate_Spells2Add.General.ZoneAbilities[spellName] then
if not SN2SID_table[generalTabName].ZoneAbilities then
SN2SID_table[generalTabName].ZoneAbilities = { [spellName] = spellID };
else
SN2SID_table[generalTabName].ZoneAbilities[spellName] = spellID;
end
-- All other spells go into the "Others" subcategory
elseif not SN2SID_table[generalTabName].Others then
elseif not SN2SID_table[generalTabName].Others then
SN2SID_table[generalTabName].Others = { [spellName] = spellID };
else
SN2SID_table[generalTabName].Others[spellName] = spellID;
end
end
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addSpellbookSpellToGeneral_func: END");
end
 
local addPolymorphOrHexFlyoutSpell_func = function(flyoutButton, flyoutSpellName, flyoutSpellSubname, flyoutSpellID)
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addPolymorphOrHexFlyoutSpell_func: START");
local flyoutSpellFullName = flyoutSpellName.. "(".. flyoutSpellSubname.. ")";
if not SN2SID_table[universalClassName].Flyouts[flyoutButton][flyoutSpellFullName]
or SN2SID_table[universalClassName].Flyouts[flyoutButton][flyoutSpellFullName] ~= flyoutSpellID then
-- print(AddonName.. "Adding flyout spellFullName ".. flyoutSpellFullName.. " = ".. flyoutSpellID);
SN2SID_table[universalClassName].Flyouts[flyoutButton][flyoutSpellFullName] = flyoutSpellID;
end
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addPolymorphOrHexFlyoutSpell_func: END");
end
 
local addFlyoutSpells_func = function(flyoutButtonName, flyoutButtonID)
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addFlyoutSpells_func: START");
-- print(AddonName.. ": SpellID ".. flyoutButtonID.. " on SpecTab ".. i.. ", Pos ".. ii.. " is a FLYOUT button.");
-- NB: Creating SN2SID_table[universalClassName].Flyouts either via
-- SN2SID_table[universalClassName].Flyouts = []; or via
-- tinsert(SN2SID_table[universalClassName], "Flyouts"); was causing a bug where the same
-- table would have two "Flyouts" fields: one with the correct values and another empty
-- (as if it were a simple member of an array). So we create a STUB value if needed and
-- later remove it when we're done adding the spells.
if not SN2SID_table[universalClassName].Flyouts then
SN2SID_table[universalClassName].Flyouts = { ["STUB"] = 0, };
end
 
if (flyoutButtonName == "Portal") or (flyoutButtonName == "Teleport") then
-- There are spells with the same Name but different IDs, depending on the
-- character's faction, when it comes to Portals and Teleports. Hence, for now,
-- we add them only in Post. TODO: Fetch them here as well, but check that they
-- are not one of those (known) smae-name, diff-IDs cases (in that case do not add
-- them here, only in post).
else
-- Insert the flyout spell in its proper table
if not SN2SID_table[universalClassName].Flyouts[flyoutButtonName] then
-- print(AddonName.. ": Adding Flyouts.".. flyoutButtonName.. " to ".. universalClassName);
SN2SID_table[universalClassName].Flyouts[flyoutButtonName] = { ["STUB"] = 0, };
-- else
-- print(AddonName.. ": Flyouts.".. flyoutButtonName.. " is already in ".. universalClassName);
end
local _, _, numFlyouts, flyoutKnown = GetFlyoutInfo(flyoutButtonID);
-- print(AddonName.. ": ".. flyoutButtonName.. " | ".. flyoutButtonID.. " | Number of Slots = ".. numFlyouts);
for flyoutSlot = 1, numFlyouts do
-- local flyoutSpellID, overrideSpellID, flyoutSlotKnown, slotSpecID = GetFlyoutSlotInfo(flyoutButtonID, flyoutSlot);
local flyoutSpellID, _, _, _ = GetFlyoutSlotInfo(flyoutButtonID, flyoutSlot);
local flyoutSpellName, flyoutSpellSubname, _, _, _, _, _ = GetSpellInfo(flyoutSpellID);
if flyoutButtonName == "Polymorph Variants" or flyoutButtonName == "Hex Variants" then
-- Mage "Polymorph Variants", and Shaman "Hex Variants",
-- are all called "Polymorph" or "Hex", respectively. But
-- they have a subname specifying the variant AND can be
-- addressed by suffixing the subname in parenthesis, as
-- in e.g. "Polymorph(Sheep)" or "Hex(Frog)". We'll do just
-- that and store their names as "name(subname)".
if (flyoutSpellSubname == nil) or (flyoutSpellSubname == "") then
-- print(AddonName.. ": ".. tostring(flyoutSpellName).. " = ".. tostring(flyoutSpellID));
-- TODO #1: Make a table, LOCAL-TO-FILE, to store
-- all the delayedFlyoutSpellInfo tables amd name
-- each one "delayedFlyoutSpellInfo"..flyoutSpellID .
-- Create an access to the info that will be fetched
local delayedFlyoutSpellInfo = Spell:CreateFromSpellID(flyoutSpellID);
-- Actually get the info and use it to update our DB
delayedFlyoutSpellInfo:ContinueOnSpellLoad(function()
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": delayedFlyoutSpellInfo:ContinueOnSpellLoad: START");
-- print(AddonName.. ": Will now get the previously delayed information about flyoutSpellID: ".. flyoutSpellID);
-- Although we should only need to update spellSubName, we might
-- have fetched a new spellName + spellID by now. Thus, we'll
-- update those fields too.
-- TODO #2: Pass the three
-- "delayedFlyoutSpellInfo"..flyoutSpellID:Some()
-- values bellow as arguments to
-- addPolymorphOrHexFlyoutSpell_func(...)
flyoutSpellName = delayedFlyoutSpellInfo:GetSpellName();
flyoutSpellSubname = delayedFlyoutSpellInfo:GetSpellSubtext(); -- Mandatory
flyoutSpellID = delayedFlyoutSpellInfo:GetSpellID();
addPolymorphOrHexFlyoutSpell_func(flyoutButtonName, flyoutSpellName, flyoutSpellSubname, flyoutSpellID);
-- TODO #3: Clean up! I.e.:
-- SaidMasterTable["delayedFlyoutSpellInfo"..flyoutSpellID] = nil;
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": delayedFlyoutSpellInfo:ContinueOnSpellLoad: END");
end);
else
-- print(AddonName.. ": ".. tostring(flyoutSpellName).. " = ".. tostring(flyoutSpellID));
addPolymorphOrHexFlyoutSpell_func(flyoutButtonName, flyoutSpellName, flyoutSpellSubname, flyoutSpellID);
end
-- Add the default Plymorph(Sheep) and Hex(Frog) to the spell lists
if universalClassName == MAGE then
SN2SID_table.MAGE.Arcane["Polymorph(Sheep)"] = SN2SID_table.MAGE.Arcane["Polymorph"] or nil;
SN2SID_table.MAGE.Fire["Polymorph(Sheep)"] = SN2SID_table.MAGE.Fire["Polymorph"] or nil;
SN2SID_table.MAGE.Frost["Polymorph(Sheep)"] = SN2SID_table.MAGE.Frost["Polymorph"] or nil;
end
if universalClassName == SHAMAN then
SN2SID_table.SHAMAN.Elemental["Hex(Frog)"] = SN2SID_table.SHAMAN.Elemental["Hex"] or nil;
SN2SID_table.SHAMAN.Enhancement["Hex(Frog)"] = SN2SID_table.SHAMAN.Enhancement["Hex"] or nil;
SN2SID_table.SHAMAN.Restoration["Hex(Frog)"] = SN2SID_table.SHAMAN.Restoration["Hex"] or nil;
end
elseif flyoutSpellName and (not SN2SID_table[universalClassName].Flyouts[flyoutButtonName][flyoutSpellName])
or flyoutSpellName and (SN2SID_table[universalClassName].Flyouts[flyoutButtonName][flyoutSpellName] ~= flyoutSpellID) then
-- print(AddonName.. ": ".. tostring(flyoutSpellName).. " = ".. tostring(flyoutSpellID));
SN2SID_table[universalClassName].Flyouts[flyoutButtonName][flyoutSpellName] = flyoutSpellID;
end
end
SN2SID_table[universalClassName].Flyouts[flyoutButtonName]["STUB"] = nil;
end
-- Get rid of the STUB table member that was added upon its creation
SN2SID_table[universalClassName].Flyouts["STUB"] = nil;
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addFlyoutSpells_func: END");
end
-- --
 
-- Update the Spellbook's GeneralTab and ClassTabs lists of spells
-- local updateSpellbookSpells_func = function(SN2SID_table, SN2SID_PASSIVES_table, generalTabName, universalClassName, ClassNumSpecs, ClassSpecNames2IDs)
-- local updateSpellbookSpells_func = function(generalTabName, universalClassName, ClassNumSpecs, ClassSpecNames2IDs)
-- local updateSpellbookSpells_func = function(universalClassName, ClassNumSpecs, ClassSpecNames2IDs)
local updateSpellbookSpells_func = function(ClassNumSpecs, ClassSpecNames2IDs)
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateSpellbookSpells_func: START");
-- "Armor Skills" and "Weapon Skills" are found on the Spellbook's General tab, but are indeed
-- different from one class to the other. Therefore, we'll save them into local variables upon
-- fetching the General tab spells and then insert them into the Class Specialisations' tables.
1084,7 → 1255,6
 
-- General tab spells
-- if updateGeneralSpells then -- In current addon version, always true
-- local _, universalRaceName = UnitRace("player");
local stubVal;
stubVal, universalRaceName = UnitRace("player");
if not SN2SID_table[generalTabName].Racials then
1108,14 → 1278,12
if not SN2SID_PASSIVES_table[generalTabName].Others then
SN2SID_PASSIVES_table[generalTabName].Others = {};
end
-- local generalTabName, _, offset, numEntries, _, _, _ = GetSpellTabInfo(1);
generalTabName, _, offset, numEntries, _, _, _ = GetSpellTabInfo(1);
-- name, texture, offset, numEntries, isGuild, offspecID = GetSpellTabInfo(tabIndex)
for i = offset +1, offset +numEntries do
local spellName, spellSubName = GetSpellBookItemName(i, BOOKTYPE_SPELL);
if spellName then
local _, spellID = GetSpellBookItemInfo(i, BOOKTYPE_SPELL);
-- NEW for 1.0.14 --
if (spellSubName == nil) or (spellSubName == "") then
local delayedSpellInfo = Spell:CreateFromSpellID(spellID);
-- I presume we don't actually need to cancel the request for the additional
1150,6 → 1318,7
-- end);
-- Actually get the information and use it to update our database:
delayedSpellInfo:ContinueOnSpellLoad(function()
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": delayedSpellInfo:ContinueOnSpellLoad: START");
-- print(AddonName.. ": Will now get the previously delayed information about spell ID: ".. spellID);
-- Although we should only need to update spellSubName, we might
-- have fetched a new spellName + spellID by now. Thus, we'll
1161,6 → 1330,7
-- Now cancel the request:
-- spellDataLoadedCancelFunc();
-- spellDataLoadedCancelFunc = nil; -- for safety!
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": delayedSpellInfo:ContinueOnSpellLoad: END");
end);
--[[
local spellDataLoadedCancelFunc = delayedSpellInfo:ContinueWithCancelOnSpellLoad(function()
1239,6 → 1409,8
-- If it's a Flyout type of button (e.g. Mage Polymorph variants, Hunter Pet
-- Utility spells, etc), then fetch the spells that ... fly out.
if spellType == "FLYOUT" then
addFlyoutSpells_func(spellName, spellID);
--[[
-- print(AddonName.. ": SpellID ".. spellID.. " on SpecTab ".. i.. ", Pos ".. ii.. " is a FLYOUT button.");
-- NB: Creating SN2SID_table[universalClassName].Flyouts either via
-- SN2SID_table[universalClassName].Flyouts = []; or via
1325,6 → 1497,7
end
-- Get rid of the STUB table member that was added upon its creation
SN2SID_table[universalClassName].Flyouts["STUB"] = nil;
]]--
end
end
end
1336,6 → 1509,7
end
updateClassSpells = false;
-- end
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateSpellbookSpells_func: END");
end
 
 
1348,8 → 1522,8
-- which names would be the tokens (string) above?
 
-- Add one Pet Spell to the apropriate subtable
-- local addSpellbookPetSpell_func = function(spellName, spellSubName, spellID, petFamily)
local addSpellbookPetSpell_func = function(spellName, spellSubName, spellID)
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addSpellbookPetSpell_func: START");
local isPassive = IsPassiveSpell(spellID);
if strfind(spellSubName, "Special") or strfind(spellSubName, "Bonus") or strfind(spellSubName, "Exotic") then -- Pet Family ability
if isPassive then
1474,11 → 1648,12
end
end
end
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addSpellbookPetSpell_func: END");
end
 
-- Pet Spells update function
-- local updatePetSpellNames = function(SN2SID_table, SN2SID_PASSIVES_table, universalClassName)
local updatePetSpellNames = function()
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updatePetSpellNames: START");
-- print(AddonName.. ": Fetching Pet spells");
-- local petHasSpellsConfirmed = false;
-- NOTES:
1556,6 → 1731,7
-- end);
-- Actually get the information and use it to update our database:
delayedSpellInfo:ContinueOnSpellLoad(function()
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": delayedSpellInfo: START");
-- print(AddonName.. ": Will now get the previously delayed information about spell ID: ".. spellID);
-- Although we should only need to update spellSubName, we might
-- have fetched a new spellName + spellID by now. Thus, we'll
1567,6 → 1743,7
-- Now cancel the request:
-- spellDataLoadedCancelFunc();
-- spellDataLoadedCancelFunc = nil; -- for safety!
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": delayedSpellInfo: END");
end);
else
addSpellbookPetSpell_func(spellName, spellSubName, spellID);
1663,67 → 1840,60
-- petHasSpellsConfirmed = true;
end
-- print(AddonName.. ": Fetched? ".. tostring(petHasSpellsConfirmed));
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updatePetSpellNames: END");
end
 
-- local addSpellsPostUpdate = function(SN2SID_table, SN2SID_PASSIVES_table, generalTabName, universalClassName)
-- local addSpellsPostUpdate = function(SN2SID_table, SN2SID_PASSIVES_table)
 
local addSpellsPostUpdate = function()
-- Sanity check
if (postUpdate_Spells2Add ~= nil) and (SN2SID_table ~= nil) then
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addSpellsPostUpdate: START");
if postUpdate_Spells2Add and SN2SID_table then -- Sanity check
for key, value in pairs(postUpdate_Spells2Add) do
-- if SN2SID_table[key] == nil then -- Sanity check, key == "General" OR universalClassName
if not SN2SID_table[key] then -- Sanity check, key == "General" OR universalClassName
-- print(AddonName.. ": Adding: ".. tostring(value));
SN2SID_table[key] = value
elseif type(value) == "table" then -- Should always be 'true' i.e. always either
-- specName(..somethingMaybe) OR "Flyouts" OR
-- "Pets" OR someGeneralTabCategory.
if key == "General" or key == universalClassName then -- Only add hardcoded spells for
-- GeneralTab or Current Class
for keyk, valuev in pairs(value) do
-- if SN2SID_table[key][keyk] == nil then -- specName(..somethingMaybe) OR
if not SN2SID_table[key][keyk] then -- specName(..somethingMaybe) OR
-- "Flyouts" OR "Pets" OR
-- someGeneralTabCategory.
if keyk == "FlyoutsTOGET" then
-- print(AddonName.. ": Will get flyout spells for FlyoutButtonName ".. keykk.. " with ID ".. valuevv);
-- addFlyoutSpells_func(keyk, valuev);
for keykk, valuevv in pairs(valuev) do
addFlyoutSpells_func(keykk, valuevv);
end
elseif not SN2SID_table[key][keyk] then -- specName(..somethingMaybe)
-- OR "FlyoutsTOGET" OR
-- "Flyouts" OR "Pets" OR
-- someGeneralTabCategory.
-- print(AddonName.. ": Adding: ".. tostring(valuev));
SN2SID_table[key][keyk] = valuev;
elseif type(valuev) == "table" then --
--
elseif type(valuev) == "table" then
for keykk, valuevv in pairs(valuev) do
-- if SN2SID_table[key][keyk][keykk] == nil then -- Spell OR Flyouts_spell OR
if not SN2SID_table[key][keyk][keykk] then -- Spell OR Flyouts_spell OR
-- PetFamily is not on the
-- target table yet
if not SN2SID_table[key][keyk][keykk] then -- Spell OR Flyouts_spell OR
-- PetFamily is not on the
-- target table yet
-- print(AddonName.. ": Adding: ".. tostring(valuevv));
SN2SID_table[key][keyk][keykk] = valuevv;
end
if type(valuevv) == "table" then -- Flyouts_spell OR PetFamily
for keykkk, valuevvv in pairs(valuevv) do
-- if SN2SID_table[key][keyk][keykk][keykkk] == nil then -- Flyouts_spell_Spell OR
if not SN2SID_table[key][keyk][keykk][keykkk] then -- Flyouts_spell_Spell OR
-- PetFamily_spell is not
-- on the target table yet
for keykkk, valuevvv in pairs(valuevv) do
if not SN2SID_table[key][keyk][keykk][keykkk] then
-- Flyouts_spell_Spell OR
-- PetFamily_spell is not
-- yet on the table.
-- print(AddonName.. ": Adding: ".. tostring(valuevvv));
SN2SID_table[key][keyk][keykk][keykkk] = valuevvv;
end
end
 
end
end
 
end
end
 
 
end
end
end
 
if (postUpdate_Spells2Add_PASSIVES ~= nil) and (SN2SID_PASSIVES_table ~= nil) then
if postUpdate_Spells2Add_PASSIVES and SN2SID_PASSIVES_table then
for key, value in pairs(postUpdate_Spells2Add_PASSIVES) do
-- if SN2SID_PASSIVES_table[key] == nil then -- Sanity check, key == "General" OR universalClassName
if not SN2SID_PASSIVES_table[key] then -- Sanity check, key == "General" OR universalClassName
-- print(AddonName.. ": Adding: ".. tostring(value));
SN2SID_PASSIVES_table[key] = value;
elseif type(value) == "table" then -- Should always be 'true' i.e. always either "Spells"
-- OR specName(..somethingMaybe) OR "Pets"
if key == "General" or key == universalClassName then -- Only add hardcoded spells for
-- GeneralTab or Current Class
for keyk, valuev in pairs(value) do
-- if SN2SID_PASSIVES_table[key][keyk] == nil then -- "Spells" OR specName(..somethingMaybe) OR
if not SN2SID_PASSIVES_table[key][keyk] then -- "Spells" OR specName(..somethingMaybe) OR
1759,6 → 1929,7
end
end
end
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addSpellsPostUpdate: END");
end
 
 
1772,60 → 1943,77
 
-- Function to call upon PLAYER_LOGIN (see bottom of file)
local lsn2sidpStartup = function()
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": lsn2sidpStartup: START");
-- Startup --
print(AddonName.. ": Startup!");
-- Copy the global saved-variables tables to our local tables
-- local SN2SID_table = AddonEnv.SpellNamesAndIDs or SpellNamesAndIDs or {};
-- local SN2SID_PASSIVES_table = AddonEnv.SpellNamesAndIDs_PASSIVES or SpellNamesAndIDs_PASSIVES or {};
SN2SID_table = AddonEnv.SpellNamesAndIDs or SpellNamesAndIDs or {};
SN2SID_PASSIVES_table = AddonEnv.SpellNamesAndIDs_PASSIVES or SpellNamesAndIDs_PASSIVES or {};
-- DEBUGmsgs = AddonEnv.DEBUG_messages or DEBUG_messages or {};
 
-- tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Print tables\' tostring to console: START");
-- print(AddonName.. ": AddonEnv.SpellNamesAndIDs = ".. tostring(AddonEnv.SpellNamesAndIDs)); -- nil
-- print(AddonName.. ": AddonEnv.SpellNamesAndIDs_PASSIVES = ".. tostring(AddonEnv.SpellNamesAndIDs_PASSIVES)); -- nil
-- print(AddonName.. ": AddonEnv.DEBUG_messages = ".. tostring(AddonEnv.DEBUG_messages)); -- nil
-- print(AddonName.. ": SpellNamesAndIDs = ".. tostring(SpellNamesAndIDs)); -- TableA
-- print(AddonName.. ": SpellNamesAndIDs_PASSIVES = ".. tostring(SpellNamesAndIDs_PASSIVES)); -- TableB
-- print(AddonName.. ": DEBUG_messages = ".. tostring(DEBUG_messages)); -- TableB
-- print(AddonName.. ": SN2SID_table = ".. tostring(SN2SID_table));-- TableA
-- print(AddonName.. ": SN2SID_PASSIVES_table = ".. tostring(SN2SID_PASSIVES_table)); -- TableB
-- print(AddonName.. ": DEBUGmsgs = ".. tostring(DEBUGmsgs)); -- TableB
-- tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Print tables\' tostring to console: END");
 
-- -- Metadata fields: Data source, Class', ... -- --
-- Data source --
-- We're only interested in storing the English names, at least for now
local curLocale = GetLocale();
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Got: curLocale = ".. curLocale);
if ( curLocale ~= "enUS") then
SN2SID_frame:UnregisterAllEvents();
error(AddonName.. " only retrieves data from English (enUS or enGB) clients.");
return;
-- return;
end
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Validated: curLocale");
local stubVal;
stubVal, universalRaceName = UnitRace("player");
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Got: universalRaceName (no validation needed) = ".. universalRaceName);
-- Self-explanatory:
local _, gameBuild = GetBuildInfo();
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Got: gameBuild");
-- For some reason, the variable gameBuild is being saved as a string; convert to number:
gameBuild = tonumber(gameBuild);
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Validated that gameBuild is a number. gameBuild = ".. gameBuild.. ": Done.");
local charLevel = UnitLevel("player");
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Got: charLevel (no validation needed) = ".. charLevel);
-- Spells in the General tab: Racial abilities, etc
-- local generalTabName = (GetSpellTabInfo(1)); -- Tab#1 = General
generalTabName = (GetSpellTabInfo(1)); -- Tab#1 = General
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Got: generalTabName (no validation needed) = ".. generalTabName);
-- Class stuff --
-- local universalClassName = select(2, UnitClass("player")); -- Locale-independent Class name
stubVal, universalClassName = UnitClass("player"); -- Locale-independent Class name
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Got: universalClassName (no validation needed) = ".. universalClassName);
local ClassNumSpecs = GetNumSpecializations(false, false); -- Number of Specialisations
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Got: ClassNumSpecs (no validation needed) = ".. ClassNumSpecs);
-- Ordered list of Class specs' IDs and Names -- Do we still use this?
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Order list of Class specs' IDs and Names: START");
local specID, specName = GetSpecializationInfo(1);
local ClassSpecNames2IDs = {};
for i = 1, ClassNumSpecs do
local specID, specName = GetSpecializationInfo(i);
ClassSpecNames2IDs[specName] = specID;
end
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Order list of Class specs' IDs and Names: END");
 
---- Check the tables' skeleton structure and build whatever may be missing ----
--
if not SN2SID_table then -- sanity check
error(AddonName.. "Local copy of saved variables is missing.");
return;
-- return;
end
if not SN2SID_PASSIVES_table then -- sanity check
error(AddonName.. "Local copy of saved variables is missing.");
return;
-- return;
end
--
-- If needed, create and populate the Metadata subtables; --
1835,9 → 2023,9
-- NB: We separate the two types of tables in two if-loops for the sake of sanity-keep (against
-- e.g. manual edits to the file).
if not SN2SID_table[generalTabName] then
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. generalTabName.. " dataSource for Active spells: START");
print(AddonName.. ": Will now create the ".. generalTabName.. " dataSource for Active spells.");
SN2SID_table[generalTabName] = {};
-- SN2SID_table[generalTabName].Spells = {};
SN2SID_table[generalTabName].METADATA = {};
SN2SID_table[generalTabName].METADATA.dataSource = {
clientLocale = curLocale, -- Currently always enUS
1849,14 → 2037,15
-- We've just created and populated the GeneralTabMetadata, hence no need to update
updateGeneralTabMetadata = false;
updateGeneralSpells = true; -- Do populate the actual list of spells
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. generalTabName.. " dataSource for Active spells: END");
else
updateGeneralTabMetadata = true; -- Will check whether it's updated; if not, will update;
-- The function which checks above var will also flag for Spells-list update if needed.
end
if not SN2SID_PASSIVES_table[generalTabName] then
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. generalTabName.. " dataSource for Passive spells: START");
print(AddonName.. ": Will now create the ".. generalTabName.. " dataSource for Passive spells.");
SN2SID_PASSIVES_table[generalTabName] = {};
-- SN2SID_PASSIVES_table[generalTabName].Spells = {};
SN2SID_PASSIVES_table[generalTabName].METADATA = {};
SN2SID_PASSIVES_table[generalTabName].METADATA.dataSource = {
clientLocale = curLocale, -- Currently always enUS
1866,19 → 2055,16
};
SN2SID_PASSIVES_table[generalTabName].METADATA.raceBuilds = { [universalRaceName] = gamebuild };
-- We've just created and populated the GeneralTabMetadata, hence no need to update ...
if not updateGeneralTabMetadata then -- ... unless it's needed for the Active spells
updateGeneralTabMetadata = false; -- And this seems redundant. Keep it 'cause I'll forget it otherwise...
end
updateGeneralTabMetadata = false; -- And this seems redundant. Keep it 'cause I'll forget it otherwise...
updateGeneralSpells = true; -- Do populate the actual list of spells
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. generalTabName.. " dataSource for Passive spells: END");
else
updateGeneralTabMetadata = true; -- Will check whether it's updated, if not will update;
-- The function which checks above var will also flag for Spells-list update if needed.
end
-- Run the update function (does both Active and Passive trees), delayed
-- updateGeneralTabMetadata_func(SN2SID_table, SN2SID_PASSIVES_table, curLocale, gameBuild, universalRaceName, generalTabName, charLevel);
-- updateGeneralTabMetadata_func(curLocale, gameBuild, universalRaceName, generalTabName, charLevel);
-- updateGeneralTabMetadata_func(curLocale, gameBuild, universalRaceName, charLevel);
-- Run the update function (does both Active and Passive trees)
updateGeneralTabMetadata_func(curLocale, gameBuild, charLevel);
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Updated the ".. generalTabName.. " Metadata \(or not\!\) for both Active and Passive spells.");
 
-- Class spells' Metadata (dataSource only; class Specs will be handled afterwards)
if not SN2SID_table[universalClassName] then
1886,9 → 2072,10
SN2SID_table[universalClassName] = {};
else
updateClassMetadata = true; -- Will check whether it's updated and if not, will update;
-- The function which checks above var will also flag for Spells-list update if needed.
-- The function which checks above var will also flag for Spells-list update if needed.
end
if not SN2SID_table[universalClassName].METADATA then
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. universalClassName.. " dataSource for Active spells: START");
SN2SID_table[universalClassName].METADATA = {};
SN2SID_table[universalClassName].METADATA.dataSource = {
clientLocale = curLocale, -- Currently always enUS
1900,29 → 2087,21
-- Class Specs fields are updated in another if-clause, further ahead.
updateClassMetadata = false;
updateClassSpells = true; -- Do populate the actual list of spells.
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. universalClassName.. " dataSource for Active spells: END");
else
updateClassMetadata = true; -- Will check whether it's updated and if not, will update;
-- The function which checks above var will also flag for Spells-list update if needed.
end
 
if not SN2SID_PASSIVES_table[universalClassName] then
print(AddonName.. ": Will now create the ".. universalClassName.. "'s table and dataSource for Passive spells.");
SN2SID_PASSIVES_table[universalClassName] = {};
SN2SID_PASSIVES_table[universalClassName].METADATA = {};
SN2SID_PASSIVES_table[universalClassName].METADATA.dataSource = {
clientLocale = curLocale, -- Currently always enUS
gameBuild = gameBuild,
charLevel = charLevel,
charMaxLevel = charLevel,
};
if not updateClassMetadata then -- See above, in the Actives snippet
updateClassMetadata = false;
end
updateClassSpells = true; -- Do populate the actual list of spells.
else
updateClassMetadata = true;
-- The function which checks above var will also flag for Spells-list update if needed.
end
 
if not SN2SID_PASSIVES_table[universalClassName].METADATA then
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. universalClassName.. " dataSource for Passive spells: START");
SN2SID_PASSIVES_table[universalClassName].METADATA = {};
SN2SID_PASSIVES_table[universalClassName].METADATA.dataSource = {
clientLocale = curLocale, -- Currently always enUS
1934,6 → 2113,7
-- Class Specs fields are updated in another if-clause, further ahead.
updateClassMetadata = false;
updateClassSpells = true; -- Do populate the actual list of spells.
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. universalClassName.. " dataSource for Passive spells: END");
else
updateClassMetadata = true; -- Will check whether it's updated and if not, will update;
-- The function which checks above var will also flag for Spells-list update if needed.
1943,10 → 2123,12
-- updateClassMetadata_func(SN2SID_table, SN2SID_PASSIVES_table, curLocale, gameBuild, universalClassName, charLevel);
-- updateClassMetadata_func(curLocale, gameBuild, universalClassName, charLevel);
updateClassMetadata_func(curLocale, gameBuild, charLevel);
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Ran updateClassMetadata_func().");
 
-- If needed, create and populate Class Specs' Active and Passive Spells --
-- Flag spell-lists for update if applicable --
if not SN2SID_table[universalClassName].METADATA.Specs then
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. universalClassName.. " \'Specs\' (Actives) tables: START");
print(AddonName.. ": Will now create the ".. universalClassName.. "'s \'Specs\' (Actives) tables.");
for i = 1, ClassNumSpecs do
local specID, specName = GetSpecializationInfo(i);
1964,8 → 2146,10
end
end
updateClassSpells = true; -- Do populate the actual list of spells.
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. universalClassName.. " \'Specs\' (Actives) tables: END");
end
if not SN2SID_PASSIVES_table[universalClassName].METADATA.Specs then
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. universalClassName.. " \'Specs\' (Passives) tables: START");
print(AddonName.. ": Will now create the ".. universalClassName.. "'s \'Specs\' (Passives) tables.");
for i = 1, ClassNumSpecs do
local specID, specName = GetSpecializationInfo(i);
1982,6 → 2166,7
end
end
updateClassSpells = true; -- Do populate the actual list of spells.
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Create the ".. universalClassName.. " \'Specs\' (Passives) tables: END");
end
 
-- Update General (always ATM) and Class SpellNames2SIDs (both Actives and Passives) --
1998,15 → 2183,20
---------------------------------
 
function SN2SID_events:PLAYER_TALENT_UPDATE(self)
DBG_CurrentEvent = "PLAYER_TALENT_UPDATE";
DEBUGmsgs["PLAYER_TALENT_UPDATE"] = { tostring(GetTime()).. ": PLAYER_TALENT_UPDATE: START", }
-- updateGeneralSpells = true; -- unneeded, placeholder for future version
updateClassSpells = true;
-- updateSpellbookSpells_func(SN2SID_table, SN2SID_PASSIVES_table, generalTabName, universalClassName, ClassNumSpecs, ClassSpecNames2IDs);
-- updateSpellbookSpells_func(generalTabName, universalClassName, ClassNumSpecs, ClassSpecNames2IDs);
-- updateSpellbookSpells_func(universalClassName, ClassNumSpecs, ClassSpecNames2IDs);
updateSpellbookSpells_func(ClassNumSpecs, ClassSpecNames2IDs);
tinsert(DEBUGmsgs["PLAYER_TALENT_UPDATE"], tostring(GetTime()).. ": PLAYER_TALENT_UPDATE: END");
end
 
function SN2SID_events:PLAYER_LEVEL_UP(self, ...)
DBG_CurrentEvent = "PLAYER_LEVEL_UP";
DEBUGmsgs["PLAYER_LEVEL_UP"] = { tostring(GetTime()).. ": PLAYER_LEVEL_UP: START", }
-- UnitLevel("player") doesn't update its result soon enough to have it indicate the *new*
-- char level in response to this event. OTH, this event does provide arguments but,
-- whatever they are, they're NOT the new char leve, for sure. Might be best to just flag
2017,6 → 2207,7
updateClassMetadata_func(curLocale, gameBuild, charLevel);
updateGeneralTabMetadata = true; -- Maybe useful.
updateClassMetadata = true; -- Stuff like talents only become available at level 10.
tinsert(DEBUGmsgs["PLAYER_LEVEL_UP"], tostring(GetTime()).. ": PLAYER_LEVEL_UP: END");
end
 
-- Update pets' existence and spells when one comes up for "player"
2031,6 → 2222,8
if (not arg1) or (arg1 ~= "player") then
return;
end
DBG_CurrentEvent = "UNIT_PET";
DEBUGmsgs["UNIT_PET"] = { tostring(GetTime()).. ": UNIT_PET: START", }
if not SN2SID_table[universalClassName].Pets then
SN2SID_table[universalClassName].Pets = {};
end
2040,56 → 2233,58
-- updatePetSpellNames(SN2SID_table, SN2SID_PASSIVES_table, universalClassName);
-- updatePetSpellNames(universalClassName);
updatePetSpellNames();
tinsert(DEBUGmsgs["UNIT_PET"], tostring(GetTime()).. ": UNIT_PET: END");
end
 
-- WoW 8.0.1: PET_SPECIALIZATION_CHANGED doesn't seem to be firing anymore
--[[
-- Switch Hunter pet's specialisation
-- function SN2SID_events:PET_SPECIALIZATION_CHANGED(self, ...)
function SN2SID_events:PET_SPECIALIZATION_CHANGED(...)
local arg1 = ...;
print(AddonName.. ": PET_SPECIALIZATION_CHANGED fired with arg1 = ".. tostring(arg1));
if arg1 and arg1 ~= "player" then
return;
function SN2SID_events:PLAYER_LOGOUT(self)
DBG_CurrentEvent = "PLAYER_LOGOUT";
-- Set up DEBUG = { LOGOUT = {} } subtable of messages
if not DEBUGmsgs["PLAYER_LOGOUT"] then
DEBUGmsgs["PLAYER_LOGOUT"] = {
tostring(GetTime()).. ": PLAYER_LOGOUT: START",
tostring(GetTime()).. ": DEBUGmsgs.PLAYER_LOGOUT created.",
};
else
DEBUGmsgs["PLAYER_LOGOUT"] = {
tostring(GetTime()).. ": PLAYER_LOGOUT: START",
tostring(GetTime()).. ": DEBUGmsgs.PLAYER_LOGOUT cleared.",
};
end
if not SN2SID_table[universalClassName].Pets then
SN2SID_table[universalClassName].Pets = {};
end
-- updatePetSpellNames(SN2SID_table, SN2SID_PASSIVES_table, universalClassName);
-- updatePetSpellNames(universalClassName);
updatePetSpellNames();
end
]]--
 
function SN2SID_events:PLAYER_LOGOUT(self)
-- Bring everything up to date
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Update some variables\' values: START");
charLevel = UnitLevel("player");
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": charLevel's value = ".. tostring(charLevel));
updateGeneralTabMetadata = true;
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": updateGeneralTabMetadata's value = ".. tostring(updateGeneralTabMetadata));
updateClassMetadata = true;
-- updateGeneralTabMetadata_func(SN2SID_table, SN2SID_PASSIVES_table, curLocale, gameBuild, universalRaceName, generalTabName, charLevel);
-- updateClassMetadata_func(SN2SID_table, SN2SID_PASSIVES_table, curLocale, gameBuild, universalClassName, charLevel);
-- updateSpellbookSpells_func(SN2SID_table, SN2SID_PASSIVES_table, generalTabName, universalClassName, ClassNumSpecs, ClassSpecNames2IDs);
-- updateGeneralTabMetadata_func(curLocale, gameBuild, universalRaceName, generalTabName, charLevel);
-- updateGeneralTabMetadata_func(curLocale, gameBuild, universalRaceName, charLevel);
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": updateClassMetadata's value = ".. tostring(updateClassMetadata));
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Update some variables\' values: END");
 
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Update Metadata: START");
updateGeneralTabMetadata_func(curLocale, gameBuild, charLevel);
-- updateClassMetadata_func(curLocale, gameBuild, universalClassName, charLevel);
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Updated GeneralTab Metadata.");
updateClassMetadata_func(curLocale, gameBuild, charLevel);
-- updateSpellbookSpells_func(generalTabName, universalClassName, ClassNumSpecs, ClassSpecNames2IDs);
-- updateSpellbookSpells_func(universalClassName, ClassNumSpecs, ClassSpecNames2IDs);
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Updated ".. universalClassName.. " Metadata.");
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Update Metadata: END");
 
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Update Spellbook spells: START");
updateSpellbookSpells_func(ClassNumSpecs, ClassSpecNames2IDs);
-- NB: UNIT_PET fires upon summoning new pets; but NOT upon switching Hunters' Pet-Specs.
if SN2SID_table[universalClassName].Pets or SN2SID_PASSIVES_table[universalClassName].Pets
or UnitExists("pet") then
-- updatePetSpellNames(SN2SID_table, SN2SID_PASSIVES_table, universalClassName);
-- updatePetSpellNames(universalClassName);
updatePetSpellNames();
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Updated Pet spells.");
else
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": NO Pet Spells to get.");
end
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Update Spellbook spells: END");
 
-- "Manually" add spells we cannot (or is not convenient to) get automatically
-- REENABLE THIS AFTER TEST:
addSpellsPostUpdate();
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Added hardcoded spells to General and Class tables.");
 
-- Copy our local tables to the global saved-variables tables --
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Copy session\'s Active and Passive Spells' tables to SavedVariables: START");
if AddonEnv.SpellNamesAndIDs then
AddonEnv.SpellNamesAndIDs = SN2SID_table;
else
2100,6 → 2295,15
else
SpellNamesAndIDs_PASSIVES = SN2SID_PASSIVES_table;
end
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Copy session\'s Active and Passive Spells' tables to SavedVariables: END");
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Copy the DEBUG messages to SavedVariables: START");
if AddonEnv.DEBUG_messages then
AddonEnv.DEBUG_messages = DEBUGmsgs;
else
DEBUG_messages = DEBUGmsgs;
end
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Copy the DEBUG messages to SavedVariables: END");
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": PLAYER_LOGOUT: END");
end
 
-- Unregister the event (handler) in which we are now running
2108,6 → 2312,7
SN2SID_frame:SetScript("OnEvent", function(self, event, ...)
SN2SID_events[event](self, ...);
end);
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Unregistered Event: PLAYER_LOGIN");
for k, v in pairs(SN2SID_events) do
if k == "UNIT_PET" then
SN2SID_frame:RegisterUnitEvent("UNIT_PET", "player");
2117,10 → 2322,27
-- if SN2SID_frame:IsEventRegistered(k) then
-- print(AddonName.. ": Registered event: ".. tostring(k));
-- end
tinsert(DEBUGmsgs["PLAYER_LOGIN"], tostring(GetTime()).. ": Registered Event: ".. k);
end
tinsert(DEBUGmsgs["PLAYER_LOGIN"], (GetTime()).. ": PLAYER_LOGIN: END");
end
 
-- PLAYER_LOGIN event handler; we set up the other events when this one fires --
SN2SID_frame:SetScript("OnEvent", function(self, event)
C_Timer.After(3, lsn2sidpStartup);
DBG_CurrentEvent = "PLAYER_LOGIN";
DEBUGmsgs = AddonEnv.DEBUG_messages or DEBUG_messages or {};
if not DEBUGmsgs then
DEBUGmsgs = {
["PLAYER_LOGIN"] = {
tostring(GetTime()).. ": PLAYER_LOGIN: START",
tostring(GetTime()).. ": Will startup in 5 seconds time.",
},
};
else
DEBUGmsgs["PLAYER_LOGIN"] = {
tostring(GetTime()).. ": PLAYER_LOGIN: START",
tostring(GetTime()).. ": Will startup in 5 seconds time.",
};
end
C_Timer.After(5, lsn2sidpStartup);
end);
populator/trunk/LibSpellName2SID-1.1-Populator/LibSpellName2SID-1.1-Populator.toc
2,8 → 2,8
## Title: LibSpellName2SID-1.1: Populator (DEV)
## Notes: Get all spells from a character and save them to file.
## Author: aallkkaa
## Version: 1.1.01
## SavedVariables: SpellNamesAndIDs, SpellNamesAndIDs_PASSIVES
## Version: 1.1.03
## SavedVariables: SpellNamesAndIDs, SpellNamesAndIDs_PASSIVES, DEBUG_messages
## DefaultState: disabled
## X-Category: Development