---------- |
-- (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, DEBUG_messages and METAdata |
local SN2SID_table, SN2SID_PASSIVES_table, DEBUGmsgs, METADATA_table; |
|
-- 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 |
|
-- Metadata flags |
local updateGeneralTabMetadata, updateClassMetadata = false, false; |
|
-- (Usually) One-time fetched values |
local generalTabName, universalRaceName, universalClassName; |
local petFamily, petSpec; |
|
-- Table for storing of dealyed-fetch spells' information (namely de subSpellName ) |
local delayedSpellsInfo_tbl = { |
-- Id<number> = API_call, |
}; |
|
-- "Manually" added/modified spells - normally AFTER regular update functions were called |
local postUpdate_Spells2Add = { |
["General"] = { |
["AzeriteEssences"] = { |
-- https://www.wowhead.com/guides/heart-of-azeroth-essence-overview#list-of-all-essences |
["Heart Essence"] = 296208, -- Generic place-holder |
-- Rank 1 -- |
-- Essences Used by All Roles |
["Concentrated Flame"] = 295373, |
["Worldvein Resonance"] = 295186, |
["Reality Shift"] = 302916, |
["Vision of Perfection"] = 296325, |
["Memory of Lucid Dreams"] = 298357, |
["Conflict"] = 303823, |
-- Tank Essences |
["Aegis of the Deep"] = 298168, |
["Empowered Null Barrier"] = 295746, |
["Suppressing Pulse"] = 293031, |
["Azeroth's Undying Gift"] = 293019, |
["Anima of Death"] = 294926, |
-- Healer Essences |
["Overcharge Mana"] = 296072, |
["Refreshment"] = 296197, |
["Standstill"] = 296094, |
["Life-Binder's Invocation"] = 293032, |
["Vitality Conduit"] = 296230, |
}, |
["Racials"] = { |
["VoidElf"] = { |
-- ["Spatial Rift"] = 256948, |
["Spatial Rift(Step 1)"] = 256948, -- Tear rift! |
["Spatial Rift(Step 2)"] = 257040, -- Teleport! |
}, |
}, |
["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"] = { |
["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 |
["Ray"] = { -- "Nether Ray" got renamed to "Ray" in WoW 8.2.0 |
["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). |
--[[ |
["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, |
["Envenom"] = 32645, -- Replaces Eviscerate at level 36 |
["Eviscerate"] = 196819, -- Is replaced by Envenom at level 36 |
}, |
["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). |
["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 8.x.y, only the Elemental specialization has controllable pets, |
-- and only 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 all three Shaman specs, 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 |
}, |
}, |
}, |
["WARRIOR"] = { |
["Protection"] = { |
["Charge"] = 100, -- Replaced by Intercept at level 28 |
["Intercept"] = 198304, -- Replaces Charge at level 28 |
}, |
}, |
}; |
|
local postUpdate_Spells2Add_PASSIVES = { |
["General"] = { |
["AzeriteEssences"] = { |
-- https://www.wowhead.com/guides/heart-of-azeroth-essence-overview#list-of-all-essences |
-- Rank 1 -- |
-- Essences Used by All Roles |
["Ancient Flame"] = 295365, |
["Lifeblood"] = 295078, |
["Ripple in Space"] = 302731, |
["Strive for Perfection"] = 296320, |
["Lucid Dreams"] = 298268, |
["Strife"] = 304081, |
-- Tank Essences |
["Stand Your Ground"] = 298193, |
["Null Barrier"] = 295750, |
["Sphere of Suppression"] = 294910, |
["Hardened Azerite"] = 294668, |
["Anima of Life"] = 294964, |
-- Healer Essences |
["The Ever-Rising Tide"] = 296050, |
["The Well of Existence"] = 296136, |
["Artifice of Time"] = 296081, |
["Seed of Eonar"] = 296207, |
["Transference"] = 303448, |
}, |
["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, |
["Runes of Power"] = 178777, |
}, |
}, |
--[[ |
-- 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, |
}, |
}, |
}, |
--[[ |
-- Easely fetchable from server, on a Frost Mage with the pet summoned |
["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"); |
-- print(AddonName.. ": Will now check whether the GeneralTab Metadata needs updating."); |
if not updateGeneralTabMetadata then |
-- print(AddonName.. ": GeneralTab\'s Metadata does NOT need update."); |
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."); |
-- Actively-cast spells |
-- print(AddonName.. ": type(METADATA_table) = ".. tostring(type(METADATA_table))); |
-- print(AddonName.. ": type(generalTabName) = ".. tostring(type(generalTabName))); |
-- print(AddonName.. ": type(METADATA_table[generalTabName]) = ".. tostring(type(METADATA_table[generalTabName]))); |
if charLevel > METADATA_table[generalTabName].dataSource.charLevel then |
METADATA_table[generalTabName].dataSource.charLevel = charLevel; |
if charLevel > METADATA_table[generalTabName].dataSource.charMaxLevel then |
METADATA_table[generalTabName].dataSource.charMaxLevel = charLevel; |
end |
updateGeneralSpells = true; |
end |
if gameBuild > METADATA_table[generalTabName].dataSource.gameBuild then |
METADATA_table[generalTabName].dataSource.gameBuild = gameBuild; |
-- Highest charLevel stored upon the most recent gameBuild |
METADATA_table[generalTabName].dataSource.charLevel = charLevel; |
-- Highest charLevel ever stored is kept in [...].charMaxLevel |
updateGeneralSpells = true; |
end |
if not METADATA_table[generalTabName].raceBuilds then |
METADATA_table[generalTabName].raceBuilds = { [universalRaceName] = gameBuild, }; |
elseif (not METADATA_table[generalTabName].raceBuilds[universalRaceName]) or |
(gameBuild > METADATA_table[generalTabName].raceBuilds[universalRaceName]) then |
METADATA_table[generalTabName].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."); |
-- print(AddonName.. ": Will now check whether the ".. universalClassName.. " Metadata needs updating."); |
if not updateClassMetadata then |
-- print(AddonName.. ": ".. universalClassName.. "\'s Metadata does NOT need update."); |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": ".. universalClassName.. "\'s Metadata does NOT need update."); |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateClassMetadata_func: END"); |
return; |
end |
-- print(AddonName.. ": ".. universalClassName.. "\'s Metadata DOES need update."); |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": ".. universalClassName.. "\'s Metadata DOES need update."); |
if charLevel > METADATA_table[universalClassName].dataSource.charLevel then |
METADATA_table[universalClassName].dataSource.charLevel = charLevel; |
if charLevel > METADATA_table[universalClassName].dataSource.charMaxLevel then |
METADATA_table[universalClassName].dataSource.charMaxLevel = charLevel; |
end |
updateClassSpells = true; |
end |
if gameBuild > METADATA_table[universalClassName].dataSource.gameBuild then |
METADATA_table[universalClassName].dataSource.gameBuild = gameBuild; |
METADATA_table[universalClassName].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) |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updateTalentSpells_func: START"); |
if not updateClassSpells then -- Sanity check |
-- print(AddonName.. ": Mo need to update the ".. universalClassName.. " PvE Talents."); |
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.. ": PvE Talents: 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) |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updatePVPTalentSpells_func: START"); |
if not updateClassSpells then -- Sanity check |
-- print(AddonName.. ": No need to update the ".. universalClassName.. " PvP Talents."); |
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.. ": PvP Talents: 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 |
-- TODO Review this "NumberOfPVPTalentSlots" thing |
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 |
if SN2SID_PASSIVES_table[universalClassName][locSpecName.."_PVPTalents"] then |
SN2SID_PASSIVES_table[universalClassName][locSpecName.."_PVPTalents"][spellName] = spellID; |
else |
SN2SID_PASSIVES_table[universalClassName][locSpecName.."_PVPTalents"] = { [spellName] = spellID, }; |
end |
else |
if SN2SID_table[universalClassName][locSpecName.."_PVPTalents"] then |
SN2SID_table[universalClassName][locSpecName.."_PVPTalents"][spellName] = spellID; |
else |
SN2SID_table[universalClassName][locSpecName.."_PVPTalents"] = { [spellName] = spellID, }; |
end |
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 |
elseif spellSubName and strfind(spellSubName, "Azerite Essence") then |
if not SN2SID_PASSIVES_table[generalTabName].AzeriteEssences then |
SN2SID_PASSIVES_table[generalTabName].AzeriteEssences = { [spellName] = spellID }; |
else |
SN2SID_PASSIVES_table[generalTabName].AzeriteEssences[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: 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 |
elseif spellSubName and strfind(spellSubName, "Azerite Essence") then |
if not SN2SID_table[generalTabName].AzeriteEssences then |
SN2SID_table[generalTabName].AzeriteEssences = { [spellName] = spellID }; |
else |
SN2SID_table[generalTabName].AzeriteEssences[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)); |
-- Create an access to the info that will be fetched |
delayedSpellsInfo_tbl["Id"..flyoutSpellID] = Spell:CreateFromSpellID(flyoutSpellID); |
-- Actually get the info and use it to update our DB |
delayedSpellsInfo_tbl["Id"..flyoutSpellID]:ContinueOnSpellLoad(function() |
-- delayedSpellsInfo_tbl["Id"..flyoutSpellID]:ContinueOnSpellLoad(function(flyoutSpellID) |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": delayedFlyoutSpellInfo[Id".. flyoutSpellID.."]:ContinueOnSpellLoad: START"); |
-- print(AddonName.. ": Will now get the previously delayed information about flyoutSpellID: ".. flyoutSpellID); |
-- Although we should only need to update spellSubName, we'll fetch a new |
-- spellName + spellID by now. Thus, we'll update those fields too. |
flyoutSpellName = delayedSpellsInfo_tbl["Id"..flyoutSpellID]:GetSpellName(); |
flyoutSpellSubname = delayedSpellsInfo_tbl["Id"..flyoutSpellID]:GetSpellSubtext(); -- NEEDED |
flyoutSpellID = delayedSpellsInfo_tbl["Id"..flyoutSpellID]:GetSpellID(); |
-- Use the values above to add the spell |
addPolymorphOrHexFlyoutSpell_func(flyoutButtonName, flyoutSpellName, flyoutSpellSubname, flyoutSpellID); |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": delayedFlyoutSpellInfo[Id".. flyoutSpellID.."]:ContinueOnSpellLoad: END"); |
-- Discard the no longer used delayed callback |
delayedSpellsInfo_tbl["Id"..flyoutSpellID] = nil; |
end); |
else |
-- print(AddonName.. ": ".. tostring(flyoutSpellName).. " = ".. tostring(flyoutSpellID)); |
addPolymorphOrHexFlyoutSpell_func(flyoutButtonName, flyoutSpellName, flyoutSpellSubname, flyoutSpellID); |
end |
-- Add the default Polymorph(Sheep) and Hex(Frog) to the spell lists -- NOT WORKING!! TODO: Fix! |
if universalClassName == MAGE then |
-- In case the regualr spell hasn't been added to the DB yet, add it: |
if not (SN2SID_table.MAGE.Arcane["Polymorph"] and SN2SID_table.MAGE.Fire["Polymorph"] and SN2SID_table.MAGE.Frost["Polymorph"]) then |
print(AddonName.. ": Adding \'Polymorph\' to the list of spells."); |
local _, _, _, _, _, _, quickSpellID = GetSpellInfo("Polymorph"); |
SN2SID_table.MAGE.Arcane["Polymorph"] = quickSpellID; |
SN2SID_table.MAGE.Fire["Polymorph"] = quickSpellID; |
SN2SID_table.MAGE.Frost["Polymorph"] = quickSpellID; |
end |
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 |
-- In case the regualr spell hasn't been added to the DB yet, add it: |
if not (SN2SID_table.SHAMAN.Elemental["Hex"] and SN2SID_table.SHAMAN.Enhancement["Hex"] and SN2SID_table.SHAMAN.Restoration["Hex"]) then |
print(AddonName.. ": Adding \'Hex\' to the list of spells."); |
local _, _, _, _, _, _, quickSpellID = GetSpellInfo("Hex"); |
SN2SID_table.SHAMAN.Elemental["Hex"] = quickSpellID; |
SN2SID_table.SHAMAN.Enhancement["Hex"] = quickSpellID; |
SN2SID_table.SHAMAN.Restoration["Hex"] = quickSpellID; |
end |
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 |
-- Get rid of the STUB table member that was added upon its creation |
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) |
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 |
-- print(AddonName.. ": Will now update the GeneralTab spells."); |
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].AzeriteEssences then |
SN2SID_table[generalTabName].AzeriteEssences = {}; |
end |
-- if not SN2SID_PASSIVES_table[generalTabName].AzeriteEssences then |
-- SN2SID_PASSIVES_table[generalTabName].AzeriteEssences = {}; |
-- 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); |
delayedSpellsInfo_tbl["Id"..spellID] = 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 safety. |
-- |
-- ADENDA (from vague memory): :ContinueWithCancelOnSpellLoad() was causing some |
-- problem (I can't remember what) and its removal had no ill effects. |
-- |
-- 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: |
delayedSpellsInfo_tbl["Id"..spellID]:ContinueOnSpellLoad(function() |
-- delayedSpellsInfo_tbl["Id"..spellID]:ContinueOnSpellLoad(function(spellID) |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": delayedSpellInfo[Id".. spellID.."]:ContinueOnSpellLoad: START"); |
-- print(AddonName.. ": Will now get the previously delayed information about spell ID: ".. spellID); |
-- -- Although we should only need to update spellSubName, we'll fetch a new |
-- spellName + spellID by now. Thus, we'll update those fields too. |
spellName = delayedSpellsInfo_tbl["Id"..spellID]:GetSpellName(); |
spellSubName = delayedSpellsInfo_tbl["Id"..spellID]:GetSpellSubtext(); -- Mandatory |
spellID = delayedSpellsInfo_tbl["Id"..spellID]:GetSpellID(); |
-- Use the values above to add the spell |
addSpellbookSpellToGeneral_func(spellName, spellSubName, spellID); |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": delayedSpellInfo[Id".. spellID.."]:ContinueOnSpellLoad: END"); |
-- Discard the no longer used delayed callback |
delayedSpellsInfo_tbl["Id"..spellID] = nil; |
end); |
else |
addSpellbookSpellToGeneral_func(spellName, spellSubName, spellID); |
end |
end |
end |
-- end |
|
-- Class spells |
-- if updateClassSpells then |
-- print(AddonName.. ": Will now update the "..universalClassName .." spells."); |
updateTalentSpells_func(ClassNumSpecs); |
updatePVPTalentSpells_func(ClassNumSpecs); |
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); |
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 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 |
-- print(AddonName.. ": Add All Specs : ".. spellName); |
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 not SN2SID_table[universalClassName].Pets["Tenacity"] then |
SN2SID_table[universalClassName].Pets["Tenacity"] = { [spellName] = spellID, }; |
else |
SN2SID_table[universalClassName].Pets["Tenacity"][spellName] = spellID; |
end |
if not SN2SID_table[universalClassName].Pets["Cunning"] then |
SN2SID_table[universalClassName].Pets["Cunning"] = { [spellName] = spellID, }; |
else |
SN2SID_table[universalClassName].Pets["Cunning"][spellName] = spellID; |
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 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 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 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 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 not SN2SID_table[universalClassName].Pets["Ferocity"] then |
SN2SID_table[universalClassName].Pets["Ferocity"] = { [spellName] = spellID, }; |
else |
SN2SID_table[universalClassName].Pets["Ferocity"][spellName] = spellID; |
end |
end |
elseif strfind(spellSubName, "Tenacity") then -- Tenacity |
if isPassive then |
-- print(AddonName.. ": Add Tenacity Passive : ".. spellName); |
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 not SN2SID_table[universalClassName].Pets["Tenacity"] then |
SN2SID_table[universalClassName].Pets["Tenacity"] = { [spellName] = spellID, }; |
else |
SN2SID_table[universalClassName].Pets["Tenacity"][spellName] = spellID; |
end |
end |
elseif strfind(spellSubName, "Cunning") then -- Cunning |
if isPassive then |
-- print(AddonName.. ": Add Cunning Passive : ".. spellName); |
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 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 |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": Pet's family is n/a. Will not get any Pet spells."); |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": updatePetSpellNames: END"); |
return; -- UNIT_PET fires two to three times when a new pet is summoned. |
end |
-- print(AddonName.. ": Pet Family = ".. tostring(petFamily)); |
|
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 |
|
local _, isHunterPet = HasPetUI(); |
if isHunterPet then -- Hunter Pets, unlike all others, have specializations, thus 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 |
delayedSpellsInfo_tbl["Id"..spellID] = Spell:CreateFromSpellID(spellID); |
-- Actually get the information and use it to update our database: |
-- delayedSpellInfo:ContinueOnSpellLoad(function() |
delayedSpellsInfo_tbl["Id"..spellID]:ContinueOnSpellLoad(function() |
-- delayedSpellsInfo_tbl["Id"..spellID]:ContinueOnSpellLoad(function(spellID) |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": delayedSpellInfo[Id".. spellID.."]:ContinueOnSpellLoad: START"); |
-- print(AddonName.. ": Will now get the previously delayed information about spell ID: ".. spellID); |
-- Although we should only need to update spellSubName, we'll |
-- get spellName and spellID too. |
spellName = delayedSpellsInfo_tbl["Id"..spellID]:GetSpellName(); |
spellSubName = delayedSpellsInfo_tbl["Id"..spellID]:GetSpellSubtext(); -- Mandatory |
spellID = delayedSpellsInfo_tbl["Id"..spellID]:GetSpellID(); |
addSpellbookPetSpell_func(spellName, spellSubName, spellID); |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": delayedSpellInfo[Id".. spellID.."]:ContinueOnSpellLoad: END"); |
-- Discard the no longer used delayed callback |
delayedSpellsInfo_tbl["Id"..spellID] = nil; |
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 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 |
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_func = function() |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": addSpellsPostUpdate_func: 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); |
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 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_func: 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 {}; |
METADATA_table = AddonEnv.METAdata or METAdata or {}; |
-- print(AddonName.. ": Made local copies of addon's Saved Variables."); |
|
-- tinsert(DEBUGmsgs[DBG_CurrentEvent], 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.. ": AddonEnv.METAdata = ".. tostring(AddonEnv.METAdata)); -- 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.. ": METAdata = ".. tostring(METAdata)); -- TableB |
-- print(AddonName.. ": SN2SID_table = ".. tostring(SN2SID_table));-- TableA |
-- print(AddonName.. ": SN2SID_PASSIVES_table = ".. tostring(SN2SID_PASSIVES_table)); -- TableB |
-- print(AddonName.. ": DEBUGmsgs = ".. tostring(DEBUGmsgs)); -- TableC |
-- print(AddonName.. ": METADATA_table = ".. tostring(METADATA_table)); -- TableD |
-- tinsert(DEBUGmsgs[DBG_CurrentEvent], 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[DBG_CurrentEvent], 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[DBG_CurrentEvent], tostring(GetTime()).. ": Validated: curLocale"); |
local stubVal; |
stubVal, universalRaceName = UnitRace("player"); |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": Got: universalRaceName (no validation needed) = ".. universalRaceName); |
-- Self-explanatory: |
local _, gameBuild = GetBuildInfo(); |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": Got: gameBuild"); |
-- For some reason, the variable gameBuild is being saved as a string; convert to number: |
gameBuild = tonumber(gameBuild); |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": Validated that gameBuild is a number. gameBuild = ".. gameBuild.. ": Done."); |
local charLevel = UnitLevel("player"); |
tinsert(DEBUGmsgs[DBG_CurrentEvent], 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[DBG_CurrentEvent], tostring(GetTime()).. ": Got: generalTabName (no validation needed) = ".. generalTabName); |
-- Class stuff -- |
stubVal, universalClassName = UnitClass("player"); -- Locale-independent Class name |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": Got: universalClassName (no validation needed) = ".. universalClassName); |
local ClassNumSpecs = GetNumSpecializations(false, false); -- Number of Specialisations |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": Got: ClassNumSpecs (no validation needed) = ".. ClassNumSpecs); |
-- Ordered list of Class specs' IDs and Names -- Do we still use this? |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": Order list of Class specs' IDs and Names: START"); |
local specID, specName = GetSpecializationInfo(1); |
tinsert(DEBUGmsgs[DBG_CurrentEvent], 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("Local copy of saved variables is missing."); |
end |
if not SN2SID_PASSIVES_table then -- sanity check |
error("Local copy of saved variables is missing."); |
end |
if not DEBUGmsgs then -- sanity check |
error("Local copy of saved variables is missing."); |
end |
if not METADATA_table then -- sanity check |
error("Local copy of saved variables is missing."); |
end |
|
-- |
-- If needed, create and populate the Metadata subtables; -- |
-- Flag spell-lists for update if applicable -- |
-- |
-- General tab skeleton + dataSource + raceBuilds |
if not SN2SID_table[generalTabName] then |
SN2SID_table[generalTabName] = {}; |
end |
if not SN2SID_PASSIVES_table[generalTabName] then |
SN2SID_PASSIVES_table[generalTabName] = {}; |
end |
if not METADATA_table[generalTabName] then |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": Create the ".. generalTabName.. " dataSource: START"); |
-- print(AddonName.. ": Will now create the ".. generalTabName.. " dataSource."); |
METADATA_table[generalTabName] = { |
dataSource = { |
clientLocale = curLocale, -- Currently always enUS |
gameBuild = gameBuild, |
charLevel = charLevel, |
charMaxLevel = charLevel, |
}, |
}; |
METADATA_table[generalTabName].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[DBG_CurrentEvent], tostring(GetTime()).. ": Create the ".. generalTabName.. " dataSource: 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[DBG_CurrentEvent], tostring(GetTime()).. ": Updated the ".. generalTabName.. " Metadata \(or not\!\) for both Active and Passive spells."); |
|
-- Class spells' skeleton + dataSource (class Specs will be handled afterwards) |
if not SN2SID_table[universalClassName] then |
-- print(AddonName.. ": Will now create the ".. universalClassName.. "'s table for Active spells."); |
SN2SID_table[universalClassName] = {}; |
end |
if not SN2SID_PASSIVES_table[universalClassName] then |
-- print(AddonName.. ": Will now create the ".. universalClassName.. "'s table for Passive spells."); |
SN2SID_PASSIVES_table[universalClassName] = {}; |
end |
if not METADATA_table[universalClassName] then |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": Create the ".. universalClassName.. " dataSource: START"); |
METADATA_table[universalClassName] = {}; |
METADATA_table[universalClassName].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[DBG_CurrentEvent], tostring(GetTime()).. ": Create the ".. universalClassName.. " dataSource: 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 dataSource |
updateClassMetadata_func(curLocale, gameBuild, charLevel); |
tinsert(DEBUGmsgs[DBG_CurrentEvent], 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 METADATA_table[universalClassName].Specs then |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": Create the ".. universalClassName.. " \'Specs\' tables: START"); |
-- print(AddonName.. ": Will now create the ".. universalClassName.. "'s \'Specs\' tables."); |
for i = 1, ClassNumSpecs do |
local specID, specName = GetSpecializationInfo(i); |
-- print(AddonName.. ": ".. i.. " = ".. specName.. " = ".. specID); -- For reference |
if not METADATA_table[universalClassName].Specs then |
METADATA_table[universalClassName].Specs = { [specName] = specID }; -- Reference |
elseif not METADATA_table[universalClassName].Specs[i] then |
METADATA_table[universalClassName].Specs[specName] = specID; -- Reference |
end |
SN2SID_table[universalClassName][specName] = {}; -- For "[SpellName] = SpellID" |
SN2SID_PASSIVES_table[universalClassName][specName] = {}; -- For "[SpellName] = SpellID" |
end |
updateClassSpells = true; -- Do populate the actual list of spells. |
-- print(AddonName.. ": ".. universalClassName.. "'s \'Specs\' tables created."); |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": Create the ".. universalClassName.. " \'Specs\' tables: END"); |
end |
|
-- Update General (always ATM) and Class SpellNames2SIDs (both Actives and Passives) -- |
-- print(AddonName.. ": Will update ".. universalClassName.. " spells in its ".. ClassNumSpecs.. " Specs."); |
updateGeneralSpells = true; |
updateClassSpells = true; |
updateSpellbookSpells_func(ClassNumSpecs); |
-- print(AddonName.. ": Updated ".. universalClassName.. " spells in its ".. ClassNumSpecs.. " Specs."); |
-- 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". |
-- Adenda @WoW 8.1.5: For some reason, UNIT_PET seems to not be firing on PLAYER_LOGIN anymore |
-- (or some other borkness), so we'll try and do a quick check here: |
if UnitExists("pet") then |
-- print(AddonName.. ": Will update ".. universalClassName.. " Pet spells."); |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": Get Pet spells: START"); |
updatePetSpellNames(); |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": Get Pet spells: END"); |
-- print(AddonName.. ": Updated ".. universalClassName.. " Pet spells."); |
end |
|
|
-- 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", } |
-- print(AddonName.. ": ".. tostring(GetTime()).. ": "..DBG_CurrentEvent .. ": START"); |
-- updateGeneralSpells = true; -- unneeded, placeholder for future version |
updateClassSpells = true; |
updateSpellbookSpells_func(ClassNumSpecs); |
tinsert(DEBUGmsgs["PLAYER_TALENT_UPDATE"], tostring(GetTime()).. ": PLAYER_TALENT_UPDATE: END"); |
-- print(AddonName.. ": ".. tostring(GetTime()).. ": "..DBG_CurrentEvent .. ": END"); |
end |
|
function SN2SID_events:PLAYER_LEVEL_UP(self, ...) |
DBG_CurrentEvent = "PLAYER_LEVEL_UP"; |
DEBUGmsgs["PLAYER_LEVEL_UP"] = { tostring(GetTime()).. ": PLAYER_LEVEL_UP: START", } |
-- print(AddonName.. ": ".. tostring(GetTime()).. ": "..DBG_CurrentEvent .. ": 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. |
updateGeneralTabMetadata_func(curLocale, gameBuild, charLevel); |
updateClassMetadata_func(curLocale, gameBuild, charLevel); |
updateSpellbookSpells_func(ClassNumSpecs); |
tinsert(DEBUGmsgs["PLAYER_LEVEL_UP"], tostring(GetTime()).. ": PLAYER_LEVEL_UP: END"); |
-- print(AddonName.. ": ".. tostring(GetTime()).. ": "..DBG_CurrentEvent .. ": END"); |
end |
|
-- Update pets' existence and spells when one comes up for "player" |
-- NB: Fires on 'Pet Dismiss' and 'Summon Pet' button clicks. |
-- 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[DBG_CurrentEvent] = { tostring(GetTime()).. ": UNIT_PET: START", }; |
updatePetSpellNames(); |
tinsert(DEBUGmsgs["UNIT_PET"], tostring(GetTime()).. ": UNIT_PET: END"); |
end |
|
function SN2SID_events:PLAYER_LOGOUT(self) |
-- print(AddonName.. ": ".. tostring(GetTime()).. ": "..DBG_CurrentEvent .. ": START"); -- Meh! |
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); |
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_func(); |
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, and METADATA_table, to SavedVariables: START"); |
AddonEnv.SpellNamesAndIDs = SN2SID_table; |
SpellNamesAndIDs = SN2SID_table; |
AddonEnv.SpellNamesAndIDs_PASSIVES = SN2SID_PASSIVES_table; |
SpellNamesAndIDs_PASSIVES = SN2SID_PASSIVES_table; |
AddonEnv.METAdata = METADATA_table; |
METAdata = METADATA_table; |
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Copy session\'s Active and Passive Spells' tables, and METADATA_table, to SavedVariables: END"); |
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Copy the DEBUG messages to SavedVariables: START"); |
AddonEnv.DEBUG_messages = DEBUGmsgs; |
DEBUG_messages = DEBUGmsgs; |
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": Copy the DEBUG messages to SavedVariables: END"); |
-- print(AddonName.. ": ".. tostring(GetTime()).. ": "..DBG_CurrentEvent .. ": END"); -- Meh! |
tinsert(DEBUGmsgs["PLAYER_LOGOUT"], tostring(GetTime()).. ": PLAYER_LOGOUT: END"); |
end |
|
-- Unregister the event (handler) in which we are now running, to free up RAM |
SN2SID_frame:UnregisterEvent("PLAYER_LOGIN"); |
tinsert(DEBUGmsgs[DBG_CurrentEvent], tostring(GetTime()).. ": Unregistered Event: ".. DBG_CurrentEvent); |
-- Set the post-PLAYER_LOGIN event-handlers and Register the respective events |
SN2SID_frame:SetScript("OnEvent", function(self, event, ...) |
SN2SID_events[event](self, ...); |
end); |
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[DBG_CurrentEvent], tostring(GetTime()).. ": Registered Event: ".. k); |
end |
tinsert(DEBUGmsgs[DBG_CurrentEvent], (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) |
-- print(AddonName.. ": Event ".. event.. " fired."); |
DBG_CurrentEvent = event; |
DEBUGmsgs = AddonEnv.DEBUG_messages or DEBUG_messages or {}; |
if not DEBUGmsgs then |
DEBUGmsgs = { |
[DBG_CurrentEvent] = { |
tostring(GetTime()).. ": ".. DBG_CurrentEvent.. ": START", |
tostring(GetTime()).. ": Will startup in 5 seconds time.", |
}, |
}; |
else |
DEBUGmsgs[DBG_CurrentEvent] = { |
tostring(GetTime()).. ": ".. DBG_CurrentEvent.. ": START", |
tostring(GetTime()).. ": Will startup in 5 seconds time.", |
}; |
end |
C_Timer.After(5, lsn2sidpStartup); |
-- print(AddonName.. ": Event ".. event.. " handled."); |
end); |