You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
236 lines
8.3 KiB
236 lines
8.3 KiB
|
4 years ago
|
--========================================================--
|
||
|
|
-- Scorpio UnitFrame Aura API --
|
||
|
|
-- --
|
||
|
|
-- Author : kurapica125@outlook.com --
|
||
|
|
-- Create Date : 2021/09/07 --
|
||
|
|
--========================================================--
|
||
|
|
|
||
|
|
--========================================================--
|
||
|
|
Scorpio "Scorpio.Secure.UnitFrame.AuraAPI" "1.0.0"
|
||
|
|
--========================================================--
|
||
|
|
|
||
|
|
namespace "Scorpio.Secure.UnitFrame"
|
||
|
|
|
||
|
|
import "System.Reactive"
|
||
|
|
import "System.Toolset"
|
||
|
|
|
||
|
|
|
||
|
|
__Final__() interface "UnitAuraPredicate" (function(_ENV)
|
||
|
|
local obUnitAura = Wow.FromUnitEvent("UNIT_AURA"):Next()
|
||
|
|
|
||
|
|
local scanResult = setmetatable({}, { __index = function(self, key) local ret = {} rawset(self, key, ret) return ret end })
|
||
|
|
local recycle = Recycle()
|
||
|
|
|
||
|
|
local singleSpellID = setmetatable({}, getmetatable(scanResult))
|
||
|
|
local singleSpellName = setmetatable({}, getmetatable(scanResult))
|
||
|
|
|
||
|
|
local auraFilter = { HELPFUL = 1, HARMFUL = 2, PLAYER = 3, RAID = 4, CANCELABLE = 5, NOT_CANCELABLE = 6, INCLUDE_NAME_PLATE_ONLY = 7, MAW = 8 }
|
||
|
|
|
||
|
|
local refreshAura, scanForUnit
|
||
|
|
|
||
|
|
if _G.UnitAuraSlots then
|
||
|
|
function refreshAura(cache, unit, filter, auraIdx, continuationToken, ...)
|
||
|
|
local singleSpellIDMap = singleSpellID[filter]
|
||
|
|
local singleSpellNameMap= singleSpellName[filter]
|
||
|
|
|
||
|
|
for i = 1, select("#", ...) do
|
||
|
|
local slot = select(i, ...)
|
||
|
|
local name, icon, count, dtype, duration, expires, caster, isStealable, nameplateShowPersonal, spellId = UnitAuraBySlot(unit, slot)
|
||
|
|
|
||
|
|
if singleSpellIDMap[spellId] then
|
||
|
|
cache[spellId] = auraIdx
|
||
|
|
end
|
||
|
|
|
||
|
|
if singleSpellNameMap[name] then
|
||
|
|
cache[name] = auraIdx
|
||
|
|
end
|
||
|
|
|
||
|
|
auraIdx = auraIdx + 1
|
||
|
|
end
|
||
|
|
|
||
|
|
return continuationToken and refreshAura(cache, unit, filter, auraIdx, UnitAuraSlots(unit, filter, 16, continuationToken))
|
||
|
|
end
|
||
|
|
|
||
|
|
function scanForUnit(cache, unit, filter)
|
||
|
|
return refreshAura(cache, unit, filter, 1, UnitAuraSlots(unit, filter, 16))
|
||
|
|
end
|
||
|
|
else
|
||
|
|
function scanForUnit(cache, unit, filter)
|
||
|
|
local singleSpellIDMap = singleSpellID[filter]
|
||
|
|
local singleSpellNameMap= singleSpellName[filter]
|
||
|
|
|
||
|
|
local auraIdx = 1
|
||
|
|
local name, icon, count, dtype, duration, expires, caster, isStealable, nameplateShowPersonal, spellId = UnitAura(unit, auraIdx, filter)
|
||
|
|
|
||
|
|
while name do
|
||
|
|
if singleSpellIDMap[spellId] then
|
||
|
|
cache[spellId] = auraIdx
|
||
|
|
end
|
||
|
|
|
||
|
|
if singleSpellNameMap[name] then
|
||
|
|
cache[name] = auraIdx
|
||
|
|
end
|
||
|
|
|
||
|
|
auraIdx = auraIdx + 1
|
||
|
|
name, icon, count, dtype, duration, expires, caster, isStealable, nameplateShowPersonal, spellId = UnitAura(unit, auraIdx, filter)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function getUnitCache(unit, filter)
|
||
|
|
local guid = UnitGUID(unit)
|
||
|
|
local now = GetTime()
|
||
|
|
local fcache = scanResult[filter]
|
||
|
|
local cache = fcache[guid]
|
||
|
|
|
||
|
|
if not cache then
|
||
|
|
cache = recycle()
|
||
|
|
fcache[guid] = cache
|
||
|
|
|
||
|
|
cache[0] = now
|
||
|
|
scanForUnit(cache, unit, filter)
|
||
|
|
elseif cache[0] < now then
|
||
|
|
wipe(cache)
|
||
|
|
cache[0] = now
|
||
|
|
scanForUnit(cache, unit, filter)
|
||
|
|
end
|
||
|
|
|
||
|
|
return cache
|
||
|
|
end
|
||
|
|
|
||
|
|
local function passFilter(filter)
|
||
|
|
return XList(filter:gmatch("[%w_]+")):ToList():Sort(function(a, b) return auraFilter[a] < auraFilter[b] end):Join("|")
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Clear Caches
|
||
|
|
Wow.FromEvent("PLAYER_REGEN_ENABLED"):Next():Subscribe(function()
|
||
|
|
for filter, fcache in pairs(scanResult) do
|
||
|
|
for guid, cache in pairs(fcache) do
|
||
|
|
recycle(wipe(cache))
|
||
|
|
end
|
||
|
|
|
||
|
|
wipe(fcache)
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
|
||
|
|
-- Used for full scan
|
||
|
|
__Static__() __Arguments__{}
|
||
|
|
function PredicateUnitAura()
|
||
|
|
return obUnitAura
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Predicate for one spell id
|
||
|
|
__Static__() __Arguments__{ String, Number } __Observable__()
|
||
|
|
function PredicateUnitAura(filter, id)
|
||
|
|
filter = passFilter(filter)
|
||
|
|
singleSpellID[filter][id] = true
|
||
|
|
|
||
|
|
return Operator(obUnitAura, function(observer, unit)
|
||
|
|
local cache = getUnitCache(unit, filter)
|
||
|
|
|
||
|
|
local auraID = cache[id]
|
||
|
|
return auraID and observer:OnNext(unit, filter, auraID)
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Predicate for one spell name
|
||
|
|
__Static__() __Arguments__{ String } __Observable__()
|
||
|
|
function PredicateUnitAura(filter, name)
|
||
|
|
filter = passFilter(filter)
|
||
|
|
singleSpellName[filter][name] = true
|
||
|
|
|
||
|
|
return Operator(obUnitAura, function(observer, unit)
|
||
|
|
local cache = getUnitCache(unit, filter)
|
||
|
|
|
||
|
|
local auraID = cache[name]
|
||
|
|
return auraID and observer:OnNext(unit, filter, auraID)
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Arguments__{ String, struct { Number }}
|
||
|
|
__Static__() __Observable__()
|
||
|
|
function PredicateUnitAura(filter, ids)
|
||
|
|
filter = passFilter(filter)
|
||
|
|
|
||
|
|
local clone = recycle()
|
||
|
|
local len = #ids
|
||
|
|
for i = 1, len do
|
||
|
|
singleSpellID[filter][ids[i]] = true
|
||
|
|
clone[i] = ids[i]
|
||
|
|
end
|
||
|
|
|
||
|
|
return Operator(obUnitAura, function(observer, unit)
|
||
|
|
local cache = getUnitCache(unit, filter)
|
||
|
|
|
||
|
|
local auraIDs = recycle()
|
||
|
|
local index = 1
|
||
|
|
|
||
|
|
for i = 1, len do
|
||
|
|
local auraID = cache[clone[i]]
|
||
|
|
if auraID then
|
||
|
|
auraIDs[index] = auraID
|
||
|
|
index = index + 1
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if index > 1 then
|
||
|
|
observer:OnNext(unit, filter, unpack(auraIDs))
|
||
|
|
end
|
||
|
|
|
||
|
|
recycle(wipe(auraIDs))
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
__Arguments__{ String, struct { String }}
|
||
|
|
__Static__() __Observable__()
|
||
|
|
function PredicateUnitAura(filter, names)
|
||
|
|
filter = passFilter(filter)
|
||
|
|
|
||
|
|
local clone = recycle()
|
||
|
|
local len = #names
|
||
|
|
for i = 1, len do
|
||
|
|
singleSpellName[filter][names[i]] = true
|
||
|
|
clone[i] = names[i]
|
||
|
|
end
|
||
|
|
|
||
|
|
return Operator(obUnitAura, function(observer, unit)
|
||
|
|
local cache = getUnitCache(unit, filter)
|
||
|
|
|
||
|
|
local auraIDs = recycle()
|
||
|
|
local index = 1
|
||
|
|
|
||
|
|
for i = 1, len do
|
||
|
|
local auraID = cache[clone[i]]
|
||
|
|
if auraID then
|
||
|
|
auraIDs[index] = auraID
|
||
|
|
index = index + 1
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if index > 1 then
|
||
|
|
observer:OnNext(unit, filter, unpack(auraIDs))
|
||
|
|
end
|
||
|
|
|
||
|
|
recycle(wipe(auraIDs))
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
|
||
|
|
__Static__()
|
||
|
|
Wow.UnitAura = UnitAuraPredicate.PredicateUnitAura
|
||
|
|
|
||
|
|
------------------------------------------------------------
|
||
|
|
-- Wow Classic --
|
||
|
|
------------------------------------------------------------
|
||
|
|
if Scorpio.IsRetail or Scorpio.IsBCC then return end
|
||
|
|
|
||
|
|
--- Try Get LibClassicDurations
|
||
|
|
pcall(LoadAddOn, "LibClassicDurations")
|
||
|
|
|
||
|
|
local ok, LibClassicDurations = pcall(_G.LibStub, "LibClassicDurations")
|
||
|
|
if not (ok and LibClassicDurations) then return end
|
||
|
|
|
||
|
|
LibClassicDurations:Register("Scorpio") -- tell library it's being used and should start working
|
||
|
|
_Parent.UnitAura = LibClassicDurations.UnitAuraWithBuffs
|
||
|
|
|
||
|
|
LibClassicDurations.RegisterCallback("Scorpio", "UNIT_BUFF", function(event, unit) return FireSystemEvent("UNIT_AURA", unit) end)
|