--- LibRangeCheck-2.0 provides an easy way to check for ranges and get suitable range checking functions for specific ranges.\\
-- The checkers use spell and item range checks, or interact based checks for special units where those two cannot be used.\\
-- The lib handles the refreshing of checker lists in case talents / spells change and in some special cases when equipment changes (for example some of the mage pvp gloves change the range of the Fire Blast spell), and also handles the caching of items used for item-based range checks.\\
-- A callback is provided for those interested in checker changes.
-- @usage
-- local rc = LibStub("LibRangeCheck-2.0")
--
-- rc.RegisterCallback(self, rc.CHECKERS_CHANGED, function() print("need to refresh my stored checkers") end)
--
-- local minRange, maxRange = rc:GetRange('target')
-- if not minRange then
-- print("cannot get range estimate for target")
-- elseif not maxRange then
-- print("target is over " .. minRange .. " yards")
-- else
-- print("target is between " .. minRange .. " and " .. maxRange .. " yards")
-- end
--
-- local meleeChecker = rc:GetFriendMaxChecker(rc.MeleeRange) or rc:GetFriendMinChecker(rc.MeleeRange) -- use the closest checker (MinChecker) if no valid Melee checker is found
-- for i = 1, 4 do
-- -- TODO: check if unit is valid, etc
-- if meleeChecker("party" .. i) then
-- print("Party member " .. i .. " is in Melee range")
-- end
-- end
--
-- local safeDistanceChecker = rc:GetHarmMinChecker(30)
-- -- negate the result of the checker!
-- local isSafelyAway = not safeDistanceChecker('target')
-- interact distance based checks. ranges are based on my own measurements (thanks for all the folks who helped me with this)
localDefaultInteractList={
[3]=8,
-- [2] = 9,
[4]=28,
}
-- interact list overrides for races
localInteractLists={
["Tauren"]={
[3]=6,
-- [2] = 7,
[4]=25,
},
["Scourge"]={
[3]=7,
-- [2] = 8,
[4]=27,
},
}
localMeleeRange=2
-- list of friendly spells that have different ranges
localFriendSpells={}
-- list of harmful spells that have different ranges
localHarmSpells={}
FriendSpells["DEATHKNIGHT"]={
}
HarmSpells["DEATHKNIGHT"]={
49576,-- ["Death Grip"], -- 30
}
FriendSpells["DEMONHUNTER"]={
}
HarmSpells["DEMONHUNTER"]={
185123,-- ["Throw Glaive"], -- 30
}
FriendSpells["DRUID"]={
774,-- ["Rejuvenation"], -- 40
2782,-- ["Remove Corruption"], -- 40
}
HarmSpells["DRUID"]={
5176,-- ["Wrath"], -- 40
339,-- ["Entangling Roots"], -- 35
6795,-- ["Growl"], -- 30
33786,-- ["Cyclone"], -- 20
22568,-- ["Ferocious Bite"], -- Melee
}
FriendSpells["HUNTER"]={}
HarmSpells["HUNTER"]={
75,-- ["Auto Shot"], -- 40
}
FriendSpells["MAGE"]={
}
HarmSpells["MAGE"]={
44614,--["Frostfire Bolt"], -- 40
5019,-- ["Shoot"], -- 30
}
FriendSpells["MONK"]={
115450,-- ["Detox"], -- 40
115546,-- ["Provoke"], -- 30
}
HarmSpells["MONK"]={
115546,-- ["Provoke"], -- 30
115078,-- ["Paralysis"], -- 20
100780,-- ["Tiger Palm"], -- Melee
}
FriendSpells["PALADIN"]={
19750,-- ["Flash of Light"], -- 40
}
HarmSpells["PALADIN"]={
62124,-- ["Reckoning"], -- 30
20271,-- ["Judgement"], -- 30
853,-- ["Hammer of Justice"], -- 10
35395,-- ["Crusader Strike"], -- Melee
}
FriendSpells["PRIEST"]={
527,-- ["Purify"], -- 40
17,-- ["Power Word: Shield"], -- 40
}
HarmSpells["PRIEST"]={
589,-- ["Shadow Word: Pain"], -- 40
5019,-- ["Shoot"], -- 30
}
FriendSpells["ROGUE"]={}
HarmSpells["ROGUE"]={
2764,-- ["Throw"], -- 30
2094,-- ["Blind"], -- 15
}
FriendSpells["SHAMAN"]={
8004,-- ["Healing Surge"], -- 40
546,-- ["Water Walking"], -- 30
}
HarmSpells["SHAMAN"]={
403,-- ["Lightning Bolt"], -- 40
370,-- ["Purge"], -- 30
73899,-- ["Primal Strike"],. -- Melee
}
FriendSpells["WARRIOR"]={}
HarmSpells["WARRIOR"]={
355,-- ["Taunt"], -- 30
100,-- ["Charge"], -- 8-25
5246,-- ["Intimidating Shout"], -- 8
}
FriendSpells["WARLOCK"]={
5697,-- ["Unending Breath"], -- 30
}
HarmSpells["WARLOCK"]={
686,-- ["Shadow Bolt"], -- 40
5019,-- ["Shoot"], -- 30
}
-- Items [Special thanks to Maldivia for the nice list]
localFriendItems={
[1]={
90175,-- Gin-Ji Knife Set -- doesn't seem to work for pets (always returns nil)
},
[2]={
37727,-- Ruby Acorn
},
[3]={
42732,-- Everfrost Razor
},
[4]={
129055,-- Shoe Shine Kit
},
[5]={
8149,-- Voodoo Charm
136605,-- Solendra's Compassion
63427,-- Worgsaw
},
[6]={
164766,-- Iwen's Enchanting Rod
},
[7]={
61323,-- Ruby Seeds
},
[8]={
34368,-- Attuned Crystal Cores
33278,-- Burning Torch
},
[10]={
32321,-- Sparrowhawk Net
},
[15]={
1251,-- Linen Bandage
2581,-- Heavy Linen Bandage
3530,-- Wool Bandage
3531,-- Heavy Wool Bandage
6450,-- Silk Bandage
6451,-- Heavy Silk Bandage
8544,-- Mageweave Bandage
8545,-- Heavy Mageweave Bandage
14529,-- Runecloth Bandage
14530,-- Heavy Runecloth Bandage
21990,-- Netherweave Bandage
21991,-- Heavy Netherweave Bandage
34721,-- Frostweave Bandage
34722,-- Heavy Frostweave Bandage
-- 38643, -- Thick Frostweave Bandage
-- 38640, -- Dense Frostweave Bandage
},
[20]={
21519,-- Mistletoe
},
[25]={
31463,-- Zezzak's Shard
},
[30]={
1180,-- Scroll of Stamina
1478,-- Scroll of Protection II
3012,-- Scroll of Agility
1712,-- Scroll of Spirit II
2290,-- Scroll of Intellect II
1711,-- Scroll of Stamina II
34191,-- Handful of Snowflakes
},
[35]={
18904,-- Zorbin's Ultra-Shrinker
},
[38]={
140786,-- Ley Spider Eggs
},
[40]={
34471,-- Vial of the Sunwell
},
[45]={
32698,-- Wrangling Rope
},
[50]={
116139,-- Haunting Memento
},
[55]={
74637,-- Kiryn's Poison Vial
},
[60]={
32825,-- Soul Cannon
37887,-- Seeds of Nature's Wrath
},
[70]={
41265,-- Eyesore Blaster
},
[80]={
35278,-- Reinforced Net
},
[90]={
133925,-- Fel Lash
},
[100]={
41058,-- Hyldnir Harpoon
},
[150]={
46954,-- Flaming Spears
},
[200]={
75208,-- Rancher's Lariat
},
}
localHarmItems={
[1]={
},
[2]={
37727,-- Ruby Acorn
},
[3]={
42732,-- Everfrost Razor
},
[4]={
129055,-- Shoe Shine Kit
},
[5]={
8149,-- Voodoo Charm
136605,-- Solendra's Compassion
63427,-- Worgsaw
},
[6]={
164766,-- Iwen's Enchanting Rod
},
[7]={
61323,-- Ruby Seeds
},
[8]={
34368,-- Attuned Crystal Cores
33278,-- Burning Torch
},
[10]={
32321,-- Sparrowhawk Net
},
[15]={
33069,-- Sturdy Rope
},
[20]={
10645,-- Gnomish Death Ray
},
[25]={
24268,-- Netherweave Net
41509,-- Frostweave Net
31463,-- Zezzak's Shard
},
[30]={
835,-- Large Rope Net
7734,-- Six Demon Bag
34191,-- Handful of Snowflakes
},
[35]={
24269,-- Heavy Netherweave Net
18904,-- Zorbin's Ultra-Shrinker
},
[38]={
140786,-- Ley Spider Eggs
},
[40]={
28767,-- The Decapitator
},
[45]={
-- 32698, -- Wrangling Rope
23836,-- Goblin Rocket Launcher
},
[50]={
116139,-- Haunting Memento
},
[55]={
74637,-- Kiryn's Poison Vial
},
[60]={
32825,-- Soul Cannon
37887,-- Seeds of Nature's Wrath
},
[70]={
41265,-- Eyesore Blaster
},
[80]={
35278,-- Reinforced Net
},
[90]={
133925,-- Fel Lash
},
[100]={
33119,-- Malister's Frost Wand
},
[150]={
46954,-- Flaming Spears
},
[200]={
75208,-- Rancher's Lariat
},
}
-- This could've been done by checking player race as well and creating tables for those, but it's easier like this
fork,vinpairs(FriendSpells)do
tinsert(v,28880)-- ["Gift of the Naaru"]
end
-- >> END OF STATIC CONFIG
-- cache
localsetmetatable=setmetatable
localtonumber=tonumber
localpairs=pairs
localtostring=tostring
localprint=print
localnext=next
localtype=type
localwipe=wipe
localtinsert=tinsert
localtremove=tremove
localBOOKTYPE_SPELL=BOOKTYPE_SPELL
localGetSpellInfo=GetSpellInfo
localGetSpellBookItemName=GetSpellBookItemName
localGetNumSpellTabs=GetNumSpellTabs
localGetSpellTabInfo=GetSpellTabInfo
localGetItemInfo=GetItemInfo
localUnitAura=UnitAura
localUnitCanAttack=UnitCanAttack
localUnitCanAssist=UnitCanAssist
localUnitExists=UnitExists
localUnitIsDeadOrGhost=UnitIsDeadOrGhost
localCheckInteractDistance=CheckInteractDistance
localIsSpellInRange=IsSpellInRange
localIsItemInRange=IsItemInRange
localUnitClass=UnitClass
localUnitRace=UnitRace
localGetInventoryItemLink=GetInventoryItemLink
localGetSpecialization=GetSpecialization
localGetSpecializationInfo=GetSpecializationInfo
localGetTime=GetTime
localHandSlotId=GetInventorySlotInfo("HandsSlot")
localmath_floor=math.floor
localUnitIsVisible=UnitIsVisible
-- temporary stuff
localpendingItemRequest
localitemRequestTimeoutAt
localfoundNewItems
localcacheAllItems
localfriendItemRequests
localharmItemRequests
locallastUpdate=0
-- minRangeCheck is a function to check if spells with minimum range are really out of range, or fail due to range < minRange. See :init() for its setup
--- Return an iterator for checkers usable on friendly units as (**range**, **checker**) pairs.
functionlib:GetFriendCheckers()
returnrcIterator(self.friendRC)
end
--- Return an iterator for checkers usable on enemy units as (**range**, **checker**) pairs.
functionlib:GetHarmCheckers()
returnrcIterator(self.harmRC)
end
--- Return an iterator for checkers usable on miscellaneous units as (**range**, **checker**) pairs. These units are neither enemy nor friendly, such as people in sanctuaries or corpses.
functionlib:GetMiscCheckers()
returnrcIterator(self.miscRC)
end
--- Return a checker suitable for out-of-range checking on friendly units, that is, a checker whose range is equal or larger than the requested range.
-- @param range the range to check for.
-- @return **checker**, **range** pair or **nil** if no suitable checker is available. **range** is the actual range the returned **checker** checks for.
functionlib:GetFriendMinChecker(range)
returngetMinChecker(self.friendRC,range)
end
--- Return a checker suitable for out-of-range checking on enemy units, that is, a checker whose range is equal or larger than the requested range.
-- @param range the range to check for.
-- @return **checker**, **range** pair or **nil** if no suitable checker is available. **range** is the actual range the returned **checker** checks for.
functionlib:GetHarmMinChecker(range)
returngetMinChecker(self.harmRC,range)
end
--- Return a checker suitable for out-of-range checking on miscellaneous units, that is, a checker whose range is equal or larger than the requested range.
-- @param range the range to check for.
-- @return **checker**, **range** pair or **nil** if no suitable checker is available. **range** is the actual range the returned **checker** checks for.
functionlib:GetMiscMinChecker(range)
returngetMinChecker(self.miscRC,range)
end
--- Return a checker suitable for in-range checking on friendly units, that is, a checker whose range is equal or smaller than the requested range.
-- @param range the range to check for.
-- @return **checker**, **range** pair or **nil** if no suitable checker is available. **range** is the actual range the returned **checker** checks for.
functionlib:GetFriendMaxChecker(range)
returngetMaxChecker(self.friendRC,range)
end
--- Return a checker suitable for in-range checking on enemy units, that is, a checker whose range is equal or smaller than the requested range.
-- @param range the range to check for.
-- @return **checker**, **range** pair or **nil** if no suitable checker is available. **range** is the actual range the returned **checker** checks for.
functionlib:GetHarmMaxChecker(range)
returngetMaxChecker(self.harmRC,range)
end
--- Return a checker suitable for in-range checking on miscellaneous units, that is, a checker whose range is equal or smaller than the requested range.
-- @param range the range to check for.
-- @return **checker**, **range** pair or **nil** if no suitable checker is available. **range** is the actual range the returned **checker** checks for.
functionlib:GetMiscMaxChecker(range)
returngetMaxChecker(self.miscRC,range)
end
--- Return a checker for the given range for friendly units.
-- @param range the range to check for.
-- @return **checker** function or **nil** if no suitable checker is available.
functionlib:GetFriendChecker(range)
returngetChecker(self.friendRC,range)
end
--- Return a checker for the given range for enemy units.
-- @param range the range to check for.
-- @return **checker** function or **nil** if no suitable checker is available.
functionlib:GetHarmChecker(range)
returngetChecker(self.harmRC,range)
end
--- Return a checker for the given range for miscellaneous units.
-- @param range the range to check for.
-- @return **checker** function or **nil** if no suitable checker is available.
functionlib:GetMiscChecker(range)
returngetChecker(self.miscRC,range)
end
--- Return a checker suitable for out-of-range checking that checks the unit type and calls the appropriate checker (friend/harm/misc).
-- @param range the range to check for.
-- @return **checker** function.
functionlib:GetSmartMinChecker(range)
returncreateSmartChecker(
getMinChecker(self.friendRC,range),
getMinChecker(self.harmRC,range),
getMinChecker(self.miscRC,range))
end
--- Return a checker suitable for in-range checking that checks the unit type and calls the appropriate checker (friend/harm/misc).
-- @param range the range to check for.
-- @return **checker** function.
functionlib:GetSmartMaxChecker(range)
returncreateSmartChecker(
getMaxChecker(self.friendRC,range),
getMaxChecker(self.harmRC,range),
getMaxChecker(self.miscRC,range))
end
--- Return a checker for the given range that checks the unit type and calls the appropriate checker (friend/harm/misc).
-- @param range the range to check for.
-- @param fallback optional fallback function that gets called as fallback(unit) if a checker is not available for the given type (friend/harm/misc) at the requested range. The default fallback function return nil.
-- @return **checker** function.
functionlib:GetSmartChecker(range,fallback)
returncreateSmartChecker(
getChecker(self.friendRC,range)orfallback,
getChecker(self.harmRC,range)orfallback,
getChecker(self.miscRC,range)orfallback)
end
--- Get a range estimate as **minRange**, **maxRange**.
-- @param unit the target unit to check range to.
-- @param checkVisible if set to true, then a UnitIsVisible check is made, and **nil** is returned if the unit is not visible
-- @return **minRange**, **maxRange** pair if a range estimate could be determined, **nil** otherwise. **maxRange** is **nil** if **unit** is further away than the highest possible range we can check.
-- Includes checks for unit validity and friendly/enemy status.
-- @usage
-- local rc = LibStub("LibRangeCheck-2.0")
-- local minRange, maxRange = rc:GetRange('target')
-- local minRangeIfVisible, maxRangeIfVisible = rc:GetRange('target', true)