Skip to content

Commit

Permalink
Range Check added
Browse files Browse the repository at this point in the history
  • Loading branch information
XiconQoo committed Jun 15, 2021
1 parent a83c1ad commit 7b0bf92
Show file tree
Hide file tree
Showing 6 changed files with 706 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Gladdy.toc
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,6 @@ Modules\XiconProfiles.lua
Modules\Pets.lua
Modules\ExportImport.lua
Modules\CombatIndicator.lua
Modules\RangeCheck.lua
Modules\ShadowsightTimer.lua
EventListener.lua
232 changes: 232 additions & 0 deletions Libs/LibSpellRange-1.0/LibSpellRange-1.0.lua
Original file line number Diff line number Diff line change
@@ -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
61 changes: 61 additions & 0 deletions Libs/LibSpellRange-1.0/README.md
Original file line number Diff line number Diff line change
@@ -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)
```
3 changes: 3 additions & 0 deletions Libs/LibSpellRange-1.0/lib.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Ui>
<Script file="LibSpellRange-1.0.lua"/>
</Ui>
Loading

0 comments on commit 7b0bf92

Please sign in to comment.