From 7b0bf921c45408799e6207e19d680257ee5cb5e5 Mon Sep 17 00:00:00 2001 From: Sumsebrum Date: Tue, 15 Jun 2021 09:05:20 +0200 Subject: [PATCH] Range Check added --- Gladdy.toc | 2 + Libs/LibSpellRange-1.0/LibSpellRange-1.0.lua | 232 +++++++++++ Libs/LibSpellRange-1.0/README.md | 61 +++ Libs/LibSpellRange-1.0/lib.xml | 3 + Modules/RangeCheck.lua | 407 +++++++++++++++++++ embeds.xml | 1 + 6 files changed, 706 insertions(+) create mode 100644 Libs/LibSpellRange-1.0/LibSpellRange-1.0.lua create mode 100644 Libs/LibSpellRange-1.0/README.md create mode 100644 Libs/LibSpellRange-1.0/lib.xml create mode 100644 Modules/RangeCheck.lua diff --git a/Gladdy.toc b/Gladdy.toc index 21b3a2d..5c43168 100644 --- a/Gladdy.toc +++ b/Gladdy.toc @@ -35,4 +35,6 @@ Modules\XiconProfiles.lua Modules\Pets.lua Modules\ExportImport.lua Modules\CombatIndicator.lua +Modules\RangeCheck.lua +Modules\ShadowsightTimer.lua EventListener.lua diff --git a/Libs/LibSpellRange-1.0/LibSpellRange-1.0.lua b/Libs/LibSpellRange-1.0/LibSpellRange-1.0.lua new file mode 100644 index 0000000..56f7b72 --- /dev/null +++ b/Libs/LibSpellRange-1.0/LibSpellRange-1.0.lua @@ -0,0 +1,232 @@ +--- = Background = +-- Blizzard's IsSpellInRange API has always been very limited - you either must have the name of the spell, or its spell book ID. Checking directly by spellID is simply not possible. +-- Now, in Mists of Pandaria, Blizzard changed the way that many talents and specialization spells work - instead of giving you a new spell when leaned, they replace existing spells. These replacement spells do not work with Blizzard's IsSpellInRange function whatsoever; this limitation is what prompted the creation of this lib. +-- = Usage = +-- **LibSpellRange-1.0** exposes an enhanced version of IsSpellInRange that: +-- * Allows ranged checking based on both spell name and spellID. +-- * Works correctly with replacement spells that will not work using Blizzard's IsSpellInRange method alone. +-- +-- @class file +-- @name LibSpellRange-1.0.lua + +local major = "SpellRange-1.0" +local minor = 15 + +assert(LibStub, format("%s requires LibStub.", major)) + +local Lib = LibStub:NewLibrary(major, minor) +if not Lib then return end + +local tonumber = _G.tonumber +local strlower = _G.strlower +local wipe = _G.wipe +local type = _G.type + +local GetSpellTabInfo = _G.GetSpellTabInfo +local GetNumSpellTabs = _G.GetNumSpellTabs +local GetSpellBookItemInfo = _G.GetSpellBookItemInfo +local GetSpellBookItemName = _G.GetSpellBookItemName +local GetSpellLink = _G.GetSpellLink +local GetSpellInfo = _G.GetSpellInfo + +local IsSpellInRange = _G.IsSpellInRange +local SpellHasRange = _G.SpellHasRange + +-- isNumber is basically a tonumber cache for maximum efficiency +Lib.isNumber = Lib.isNumber or setmetatable({}, { + __mode = "kv", + __index = function(t, i) + local o = tonumber(i) or false + t[i] = o + return o +end}) +local isNumber = Lib.isNumber + +-- strlower cache for maximum efficiency +Lib.strlowerCache = Lib.strlowerCache or setmetatable( +{}, { + __index = function(t, i) + if not i then return end + local o + if type(i) == "number" then + o = i + else + o = strlower(i) + end + t[i] = o + return o + end, +}) local strlowerCache = Lib.strlowerCache + +-- Matches lowercase player spell names to their spellBookID +Lib.spellsByName_spell = Lib.spellsByName_spell or {} +local spellsByName_spell = Lib.spellsByName_spell + +-- Matches player spellIDs to their spellBookID +Lib.spellsByID_spell = Lib.spellsByID_spell or {} +local spellsByID_spell = Lib.spellsByID_spell + +-- Matches lowercase pet spell names to their spellBookID +Lib.spellsByName_pet = Lib.spellsByName_pet or {} +local spellsByName_pet = Lib.spellsByName_pet + +-- Matches pet spellIDs to their spellBookID +Lib.spellsByID_pet = Lib.spellsByID_pet or {} +local spellsByID_pet = Lib.spellsByID_pet + +-- Updates spellsByName and spellsByID +local function UpdateBook(bookType) + local max = 0 + for i = 1, GetNumSpellTabs() do + local _, _, offs, numspells, _, specId = GetSpellTabInfo(i) + if specId == 0 then + max = offs + numspells + end + end + + local spellsByName = Lib["spellsByName_" .. bookType] + local spellsByID = Lib["spellsByID_" .. bookType] + + wipe(spellsByName) + wipe(spellsByID) + + for spellBookID = 1, max do + local type, baseSpellID = GetSpellBookItemInfo(spellBookID, bookType) + + if type == "SPELL" or type == "PETACTION" then + local currentSpellName = GetSpellBookItemName(spellBookID, bookType) + local link = GetSpellLink(currentSpellName) + local currentSpellID = tonumber(link and link:gsub("|", "||"):match("spell:(%d+)")) + + -- For each entry we add to a table, + -- only add it if there isn't anything there already. + -- This prevents weird passives from overwriting real, legit spells. + -- For example, in WoW 7.3.5 the ret paladin mastery + -- was coming back with a base spell named "Judgement", + -- which was overwriting the real "Judgement". + -- Passives usually come last in the spellbook, + -- so this should work just fine as a workaround. + -- This issue with "Judgement" is gone in BFA because the mastery changed. + + if currentSpellName and not spellsByName[strlower(currentSpellName)] then + spellsByName[strlower(currentSpellName)] = spellBookID + end + if currentSpellID and not spellsByID[currentSpellID] then + spellsByID[currentSpellID] = spellBookID + end + + if type == "SPELL" then + -- PETACTION (pet abilities) don't return a spellID for baseSpellID, + -- so base spells only work for proper player spells. + local baseSpellName = GetSpellInfo(baseSpellID) + if baseSpellName and not spellsByName[strlower(baseSpellName)] then + spellsByName[strlower(baseSpellName)] = spellBookID + end + if baseSpellID and not spellsByID[baseSpellID] then + spellsByID[baseSpellID] = spellBookID + end + end + end + end +end + +-- Handles updating spellsByName and spellsByID +if not Lib.updaterFrame then + Lib.updaterFrame = CreateFrame("Frame") +end +Lib.updaterFrame:UnregisterAllEvents() +Lib.updaterFrame:RegisterEvent("SPELLS_CHANGED") + +local function UpdateSpells() + UpdateBook("spell") + UpdateBook("pet") +end + +Lib.updaterFrame:SetScript("OnEvent", UpdateSpells) +UpdateSpells() + +--- Improved spell range checking function. +-- @name SpellRange.IsSpellInRange +-- @paramsig spell, unit +-- @param spell Name or spellID of a spell that you wish to check the range of. The spell must be a spell that you have in your spellbook or your pet's spellbook. +-- @param unit UnitID of the spell that you wish to check the range on. +-- @return Exact same returns as http://wowprogramming.com/docs/api/IsSpellInRange +-- @usage +-- -- Check spell range by spell name on unit "target" +-- local SpellRange = LibStub("SpellRange-1.0") +-- local inRange = SpellRange.IsSpellInRange("Stormstrike", "target") +-- +-- -- Check spell range by spellID on unit "mouseover" +-- local SpellRange = LibStub("SpellRange-1.0") +-- local inRange = SpellRange.IsSpellInRange(17364, "mouseover") +function Lib.IsSpellInRange(spellInput, unit) + if isNumber[spellInput] then + local spell = spellsByID_spell[spellInput] + if spell then + return IsSpellInRange(spell, "spell", unit) + else + local spell = spellsByID_pet[spellInput] + if spell then + return IsSpellInRange(spell, "pet", unit) + end + end + else + local spellInput = strlowerCache[spellInput] + + local spell = spellsByName_spell[spellInput] + if spell then + return IsSpellInRange(spell, "spell", unit) + else + local spell = spellsByName_pet[spellInput] + if spell then + return IsSpellInRange(spell, "pet", unit) + end + end + + return IsSpellInRange(spellInput, unit) + end + +end + + +--- Improved SpellHasRange. +-- @name SpellRange.SpellHasRange +-- @paramsig spell +-- @param spell Name or spellID of a spell that you wish to check for a range. The spell must be a spell that you have in your spellbook or your pet's spellbook. +-- @return Exact same returns as http://wowprogramming.com/docs/api/SpellHasRange +-- @usage +-- -- Check if a spell has a range by spell name +-- local SpellRange = LibStub("SpellRange-1.0") +-- local hasRange = SpellRange.SpellHasRange("Stormstrike") +-- +-- -- Check if a spell has a range by spellID +-- local SpellRange = LibStub("SpellRange-1.0") +-- local hasRange = SpellRange.SpellHasRange(17364) +function Lib.SpellHasRange(spellInput) + if isNumber[spellInput] then + local spell = spellsByID_spell[spellInput] + if spell then + return SpellHasRange(spell, "spell") + else + local spell = spellsByID_pet[spellInput] + if spell then + return SpellHasRange(spell, "pet") + end + end + else + local spellInput = strlowerCache[spellInput] + + local spell = spellsByName_spell[spellInput] + if spell then + return SpellHasRange(spell, "spell") + else + local spell = spellsByName_pet[spellInput] + if spell then + return SpellHasRange(spell, "pet") + end + end + + return SpellHasRange(spellInput) + end + +end diff --git a/Libs/LibSpellRange-1.0/README.md b/Libs/LibSpellRange-1.0/README.md new file mode 100644 index 0000000..992f4ed --- /dev/null +++ b/Libs/LibSpellRange-1.0/README.md @@ -0,0 +1,61 @@ +# LibSpellRange-1.0 + +## Background + +Blizzard's `IsSpellInRange` API has always been very limited - you either must have the name of the spell, +or its spell book ID. Checking directly by spellID is simply not possible. +Now, since Mists of Pandaria, Blizzard changed the way that many talents and specialization spells work - +instead of giving you a new spell when leaned, they replace existing spells. These replacement spells do +not work with Blizzard's IsSpellInRange function whatsoever; this limitation is what prompted the creation of this lib. + +## Usage + +**LibSpellRange-1.0** exposes an enhanced version of IsSpellInRange that: + +* Allows ranged checking based on both spell name and spellID. +* Works correctly with replacement spells that will not work using Blizzard's IsSpellInRange method alone. + +### `SpellRange.IsSpellInRange(spell, unit)` - Improved `IsSpellInRange` + +#### Parameters + +- `spell` - Name or spellID of a spell that you wish to check the range of. The spell must be a spell that you have in your spellbook or your pet's spellbook. +- `unit` - UnitID of the spell that you wish to check the range on. + +#### Return value + +Exact same returns as [the built-in `IsSpellInRange`](http://wowprogramming.com/docs/api/IsSpellInRange.html) + +#### Usage + +``` lua +-- Check spell range by spell name on unit "target" +local SpellRange = LibStub("SpellRange-1.0") +local inRange = SpellRange.IsSpellInRange("Stormstrike", "target") + +-- Check spell range by spellID on unit "mouseover" +local SpellRange = LibStub("SpellRange-1.0") +local inRange = SpellRange.IsSpellInRange(17364, "mouseover") +``` + +### `SpellRange.SpellHasRange(spell)` - Improved `SpellHasRange` + +#### Parameters + +- `spell` - Name or spellID of a spell that you wish to check for a range. The spell must be a spell that you have in your spellbook or your pet's spellbook. + +#### Return value + +Exact same returns as [the built-in `SpellHasRange`](http://wowprogramming.com/docs/api/SpellHasRange.html) + +#### Usage + +``` lua +-- Check if a spell has a range by spell name +local SpellRange = LibStub("SpellRange-1.0") +local hasRange = SpellRange.SpellHasRange("Stormstrike") + +-- Check if a spell has a range by spellID +local SpellRange = LibStub("SpellRange-1.0") +local hasRange = SpellRange.SpellHasRange(17364) +``` diff --git a/Libs/LibSpellRange-1.0/lib.xml b/Libs/LibSpellRange-1.0/lib.xml new file mode 100644 index 0000000..1214c3c --- /dev/null +++ b/Libs/LibSpellRange-1.0/lib.xml @@ -0,0 +1,3 @@ + +