-- Inspect.lua local _; local next, print = next, print; local format = string.format; local InCombatLockdown = InCombatLockdown; local CTimerAfter = C_Timer.After; local IsInGroup, IsInRaid = IsInGroup, IsInRaid; local CheckInteractDistance = CheckInteractDistance; local GetTime, UnitGUID, UnitName = GetTime, UnitGUID, UnitName; local CanInspect, NotifyInspect, ClearInspectPlayer = CanInspect, NotifyInspect, ClearInspectPlayer; local GetInventoryItemLink, GetInventoryItemID = GetInventoryItemLink, GetInventoryItemID; local GetTalentInfo, GetInspectSpecialization = GetTalentInfo, GetInspectSpecialization; local INVSLOT_MAINHAND, INVSLOT_WRIST = INVSLOT_MAINHAND, INVSLOT_WRIST; local cache = {}; local pending = {}; local inspecting = nil; local inspectui = nil; local frame = CreateFrame("Frame", "OmaInspect"); frame:Hide(); OmaInspect = {}; local redoGuid = nil; local function redo() if redoGuid and inspecting == redoGuid then print("hit redo timeout, putting back on pending"); pending[redoGuid] = true; inspecting = nil; redoGuid = nil; if not inspectui then ClearInspectPlayer() end end end local function inspect(id) local guid = UnitGUID(id); if not guid then return end if InCombatLockdown() then pending[guid] = true; elseif not inspectui then -- not necessary, but there's too many issues with inspect, -- try to hope being nearby makes it more likely to work -- no need to inspect people not in range before pull anyway if CheckInteractDistance(id, 1) then if not inspecting then inspecting = guid; print("Sending inspect", UnitName(id)); NotifyInspect(id); redoGuid = guid; CTimerAfter(20, redo); else pending[guid] = true; end else pending[guid] = true; end else pending[guid] = true; end end hooksecurefunc("InspectUnit", function() inspectui = true; end); hooksecurefunc("NotifyInspect", function(id) if inspecting ~= UnitGUID(id) then inspectui = true; end end); hooksecurefunc("ClearInspectPlayer", function() inspectui = nil; end); local function tick() -- make sure pending inspects get done at some point if not InCombatLockdown() then local guid, _ = next(pending); if guid and cache[guid] and cache[guid].id then pending[guid] = nil; inspect(cache[guid].id); end end CTimerAfter(2, tick); end function OmaInspect.Request(guid, id, callback, needItems, force) if not id or not CanInspect(id) then return false end if not guid or UnitGUID(id) ~= guid then return false end if not cache[guid] then cache[guid] = {} end local cached = cache[guid]; if not cached.time then cached.time = 0 end cached.id = id; cached.cb = callback; cached.needItems = needItems; local elapsed = GetTime() - cached.time; if force or (not needItems and (not cached.talent ~= nil or elapsed > 60)) or (needItems and (not cached.weapon or elapsed > 60)) then if not pending[guid] or inspecting ~= guid then -- don't send multiple inspects inspect(id); end else cached.cb(guid, cached.spec, cached.talent, cached.weapon, cached.wrist); end return true; end local function inspectReady(guid) if not guid or inspectui then return end local cached = cache[guid]; if cached and cached.id and UnitGUID(cached.id) == guid then local time = GetTime(); local id = cached.id; inspecting = nil; redoGuid = nil; if InCombatLockdown() and not inspectui then pending[guid] = true; ClearInspectPlayer(); else if CanInspect(id) then if time - cached.time > 60 then -- refresh >1min -- new inspect cached.time = time; if needItems then cached.weapon = GetInventoryItemLink(id, INVSLOT_MAINHAND); cached.wrist = GetInventoryItemID(id, INVSLOT_WRIST); end cached.spec = GetInspectSpecialization(id); local _, _, _, selected = GetTalentInfo(6, 2, 1, true, id); cached.talent = selected; end end ClearInspectPlayer(); if (cached.needItems and cached.weapon) or (not cached.needItems and cached.talent ~= nil) then print("Got inspect done", UnitName(id)); cached.cb(guid, cached.spec, cached.talent, cached.weapon, cached.wrist); else pending[guid] = true; end end end end local function updateIds() local size = 0; local prefix = "solo"; if IsInGroup() then if IsInRaid() then size = 40; prefix = "raid"; else size = 4; prefix = "party"; end end for i = 1,size do local id = format("%s%i", prefix, i); local guid = UnitGUID(id); if cache[guid] then cache[guid].id = id end end end local function create() frame:UnregisterAllEvents(); frame:SetScript("OnEvent", function(self, event, guid) if event == "INSPECT_READY" then inspectReady(guid); elseif event == "GROUP_ROSTER_UPDATE" then updateIds(); end end); frame:RegisterEvent("INSPECT_READY"); frame:RegisterEvent("GROUP_ROSTER_UPDATE"); tick(); end frame:RegisterEvent("PLAYER_LOGIN"); frame:SetScript("OnEvent", function(self, event) if event == "PLAYER_LOGIN" then return create(); end end);