87236a4 - Refactor OmaCD, create a more robust inspect scheme
authorAleksi Blinnikka <aleksi.blinnikka@gmail.com>
Tue, 20 Mar 2018 12:28:15 +0000
committerAleksi Blinnikka <aleksi.blinnikka@gmail.com>
Tue, 20 Mar 2018 12:28:15 +0000
WoW inspect API doesn't work well, these changes try to work around the
issues and hopefully provide requested info. Spec/talents are inspected
fine, but inventory inspection requires luck and retries.

OmaCD/Cooldowns.lua
OmaCD/Inspect.lua [new file with mode: 0644]
OmaCD/OmaCD.toc

index 916a5a0..3663615 100644 (file)
@@ -13,7 +13,6 @@ local UnitIsDeadOrGhost, UnitIsConnected = UnitIsDeadOrGhost, UnitIsConnected;
 local GetTalentInfo, GetInspectSpecialization = GetTalentInfo, GetInspectSpecialization;
 local GetSpecializationInfo, GetSpecialization = GetSpecializationInfo, GetSpecialization;
 local GetInventoryItemLink, GetInventoryItemID = GetInventoryItemLink, GetInventoryItemID;
 local GetTalentInfo, GetInspectSpecialization = GetTalentInfo, GetInspectSpecialization;
 local GetSpecializationInfo, GetSpecialization = GetSpecializationInfo, GetSpecialization;
 local GetInventoryItemLink, GetInventoryItemID = GetInventoryItemLink, GetInventoryItemID;
-local CanInspect, NotifyInspect, ClearInspectPlayer = CanInspect, NotifyInspect, ClearInspectPlayer;
 local INVSLOT_MAINHAND, INVSLOT_WRIST = INVSLOT_MAINHAND, INVSLOT_WRIST;
 
 local upColor = {0, 0.7, 0.2, 0.7};
 local INVSLOT_MAINHAND, INVSLOT_WRIST = INVSLOT_MAINHAND, INVSLOT_WRIST;
 
 local upColor = {0, 0.7, 0.2, 0.7};
@@ -68,8 +67,8 @@ local runningcds = {}; -- CDs currently active
 local idToGuid = {};
 local guidToId = {};
 local guidToSpecid = {};
 local idToGuid = {};
 local guidToId = {};
 local guidToSpecid = {};
+local monks = {};
 local monksWithLegendary = {};
 local monksWithLegendary = {};
-local inspectSent = {};
 local dead = {};
 local disconnected = {};
 
 local dead = {};
 local disconnected = {};
 
@@ -88,16 +87,6 @@ local function CdDown(guid, spellid, start)
     if start then frame.text:SetText(cds[guid][spellid]) end
 end
 
     if start then frame.text:SetText(cds[guid][spellid]) end
 end
 
-local function sendInspect(guid, id, func)
-    if not inspectSent[guid] and CanInspect(id) then
-        inspectSent[guid] = true;
-        local _, _, _, _, _, name = GetPlayerInfoByGUID(guid);
-        print(guid, name, "send inspect");
-        NotifyInspect(id);
-        CTimerAfter(20, func); -- precaution for never receiving INSPECT_READY
-    end
-end
-
 local encounter = nil;
 local function tick()
     if not encounter and IsEncounterInProgress() then
 local encounter = nil;
 local function tick()
     if not encounter and IsEncounterInProgress() then
@@ -141,7 +130,12 @@ end
 local function removeFrame(frame)
     unused[#unused+1] = frame;
     frames[frame.guid][frame.spellid] = nil;
 local function removeFrame(frame)
     unused[#unused+1] = frame;
     frames[frame.guid][frame.spellid] = nil;
+    if not next(frames[frame.guid]) then frames[frame.guid] = nil end
     cds[frame.guid][frame.spellid] = nil;
     cds[frame.guid][frame.spellid] = nil;
+    monks[frame.guid] = nil;
+    monksWithLegendary[frame.guid] = nil;
+    dead[frame.guid] = nil;
+    disconnected[frame.guid] = nil;
     if runningcds[frame.guid] then runningcds[frame.guid][frame.spellid] = nil end
     tremove(shown, frame.pos);
     for i, frame in ipairs(shown) do
     if runningcds[frame.guid] then runningcds[frame.guid][frame.spellid] = nil end
     tremove(shown, frame.pos);
     for i, frame in ipairs(shown) do
@@ -209,47 +203,45 @@ local function updateUnitCD(guid)
     end
 end
 
     end
 end
 
-local function updateMonk(guid)
+local function updateMonk(guid, _, _, weapon, wrist)
     local id = guidToId[guid];
     local id = guidToId[guid];
-    if not id then return end -- called because another addon inspected
-    local weapon = GetInventoryItemLink(id, INVSLOT_MAINHAND);
-    if not weapon then
-        -- try again directly
-        if CanInspect(id) then
-            print(guid, "send inspect");NotifyInspect(id);
-            CTimerAfter(20, updateMonk);
+    if id then
+        local _, _, _, relic1, relic2, relic3 = strsplit(":", weapon);
+        local cdfix = 0;
+        if monkRelics[relic1] then cdfix = cdfix + monkRelics[relic1] end
+        if monkRelics[relic2] then cdfix = cdfix + monkRelics[relic2] end
+        if monkRelics[relic3] then cdfix = cdfix + monkRelics[relic3] end
+        if cdfix ~= 0 then
+            cdfixes[guid] = cdfix;
+        else
+            cdfixes[guid] = nil;
         end
         end
-        return;
+
+        if wrist == 137096 then -- Petrichor Lagniappe
+            monksWithLegendary[guid] = true;
+        else
+            monksWithLegendary[guid] = nil;
+        end
+        monks[guid] = true;
+        updateUnitCD(guid);
     end
     end
-    if inspectSent[guid] then inspectSent[guid] = nil end
-    print("Got monk", guid);
-    local _, _, _, relic1, relic2, relic3 = strsplit(":", weapon);
-    local cdfix = 0;
-    if monkRelics[relic1] then cdfix = cdfix + monkRelics[relic1] end
-    if monkRelics[relic2] then cdfix = cdfix + monkRelics[relic2] end
-    if monkRelics[relic3] then cdfix = cdfix + monkRelics[relic3] end
-    if cdfix ~= 0 then cdfixes[guid] = cdfix end
+end
 
 
-    local wrist = GetInventoryItemID(guidToId[guid], INVSLOT_WRIST);
-    if wrist == 137096 then -- Petrichor Lagniappe
-        monksWithLegendary[guid] = true;
-    else
-        monksWithLegendary[guid] = nil;
+-- a secondary tick for monks inventory check out of combat
+local function monkTick()
+    if not InCombatLockdown() then
+        for guid, _ in pairs(monks) do
+            local id = guidToId[guid];
+            if id then OmaInspect.Request(guid, id, updateMonk) end
+        end
     end
     end
-    updateUnitCD(guid);
+    CTimerAfter(10, monkTick);
 end
 
 end
 
-local function updateDruid(guid, player)
+local function updateDruid(guid, _, talent)
     local id = guidToId[guid];
     if id then
     local id = guidToId[guid];
     if id then
-        -- Inner Peace talent
-        local selected;
-        if player then
-            _, _, _, selected = GetTalentInfo(6, 2, 1);
-        else
-            _, _, _, selected = GetTalentInfo(6, 2, 1, true, id);
-        end
-        if selected then
+        if talent then
             cdfixes[guid] = -60;
         else
             cdfixes[guid] = nil;
             cdfixes[guid] = -60;
         else
             cdfixes[guid] = nil;
@@ -258,19 +250,14 @@ local function updateDruid(guid, player)
     end
 end
 
     end
 end
 
-local function updatePriest(guid)
+local function updatePriest(guid, specid)
     local id = guidToId[guid];
     if id then
     local id = guidToId[guid];
     if id then
-        local specid = GetInspectSpecialization(id);
-        if specid == 0 then
-            -- try again directly
-            if CanInspect(id) then
-                print(guid, "send inspect");NotifyInspect(id);
-                CTimerAfter(20, updatePriest);
+        if guidToSpecid[guid] ~= specid then
+            for _, frame in pairs(frames[guid]) do
+                removeFrame(frame);
             end
         end
             end
         end
-        if inspectSent[guid] then inspectSent[guid] = nil end
-        print("Got priest", guid);
         guidToSpecid[guid] = specid;
         updateUnitCD(guid);
     end
         guidToSpecid[guid] = specid;
         updateUnitCD(guid);
     end
@@ -283,9 +270,12 @@ local function updatePlayer()
         guidToId[guid] = "player";
         guidToSpecid[guid] = specid;
         if specid == 270 then -- Monk
         guidToId[guid] = "player";
         guidToSpecid[guid] = specid;
         if specid == 270 then -- Monk
-            updateMonk(guid);
+            local weapon = GetInventoryItemLink("player", INVSLOT_MAINHAND);
+            local wrist = GetInventoryItemID("player", INVSLOT_WRIST);
+            updateMonk(guid, nil, nil, weapon, wrist);
         elseif specid == 105 then -- Druid
         elseif specid == 105 then -- Druid
-            updateDruid(guid, true);
+            local _, _, _, talent = GetTalentInfo(6, 2, 1);
+            updateDruid(guid, nil, talent);
         else
             updateUnitCD(guid);
         end
         else
             updateUnitCD(guid);
         end
@@ -306,29 +296,27 @@ local function updateUnitid(id)
         local _, class = UnitClass(id);
         if specs[class] ~= nil then
             guidToId[guid] = id;
         local _, class = UnitClass(id);
         if specs[class] ~= nil then
             guidToId[guid] = id;
+            local specid = guidToSpecid[guid];
+            guidToSpecid[guid] = specs[class];
             if specs[class] == false then
             if specs[class] == false then
-                -- Priest, have to inspect to get spec, try immediately, if not available, inspect
-                local specid = GetInspectSpecialization(id);
-                if specid == 0 then
-                    sendInspect(guid, id, updatePriest);
-                elseif specid == 256 or specid == 257 then
-                    guidToSpecid[guid] = specid; -- only Holy and Discipline
-                    updateUnitCD(guid);
+                if specid == 256 or specid == 257 then
+                    guidToSpecid[guid] = specid;
+                else
+                    guidToSpecid[guid] = 257; -- assume Holy for now to get something visible
                 end
                 end
+                updateUnitCD(guid);
+                OmaInspect.Request(guid, id, updatePriest);
             elseif specs[class] == 270 then
                 -- Monk, have to check inventory for CD modifications
             elseif specs[class] == 270 then
                 -- Monk, have to check inventory for CD modifications
-                guidToSpecid[guid] = specs[class];
                 -- updateUnitCD (without having fixes yet)
                 updateUnitCD(guid);
                 -- updateUnitCD (without having fixes yet)
                 updateUnitCD(guid);
-                sendInspect(guid, id, updateMonk);
+                OmaInspect.Request(guid, id, updateMonk, true);
             elseif specs[class] == 105 then
                 -- Druid, have to inspect to get talents
             elseif specs[class] == 105 then
                 -- Druid, have to inspect to get talents
-                guidToSpecid[guid] = specs[class];
                 -- updateUnitCD (without having fixes yet)
                 updateUnitCD(guid);
                 -- updateUnitCD (without having fixes yet)
                 updateUnitCD(guid);
-                sendInspect(guid, id, updateDruid);
+                OmaInspect.Request(guid, id, updateDruid);
             else
             else
-                guidToSpecid[guid] = specs[class];
                 updateUnitCD(guid);
             end
             idToGuid[id] = guid;
                 updateUnitCD(guid);
             end
             idToGuid[id] = guid;
@@ -343,19 +331,15 @@ local function updateUnitid(id)
     end
 end
 
     end
 end
 
+local prevGroupType = "solo";
+local prevGroupSize = 0;
 local updateQueued = nil;
 local function updateUnitids()
     local size = 0;
 local updateQueued = nil;
 local function updateUnitids()
     local size = 0;
-    local prefix;
-    local newIdToGuid = {};
-    local prevIdToGuid = {};
+    local prefix = "solo";
     guidToId = {};
     updateQueued = nil;
 
     guidToId = {};
     updateQueued = nil;
 
-    for id, guid in pairs(idToGuid) do
-        prevIdToGuid[id] = guid;
-    end
-
     if IsInGroup() then
         if IsInRaid() then
             size = 40;
     if IsInGroup() then
         if IsInRaid() then
             size = 40;
@@ -366,21 +350,53 @@ local function updateUnitids()
         end
     end
 
         end
     end
 
+    if prevGroupType ~= prefix then
+        -- clean up players from old group
+        for i = 1,prevGroupSize do
+            local id = format("%s%i", prevGroupType, i);
+            local guid = idToGuid[id];
+            idToGuid[id] = nil;
+            if frames[guid] then
+                print(guid, "removing frames in overall updateUnitids");
+                for _, frame in pairs(frames[guid]) do
+                    removeFrame(frame);
+                end
+            end
+        end
+        prevGroupType = prefix;
+        prevGroupSize = size;
+    end
+
     updatePlayer();
     updatePlayer();
-    if prevIdToGuid["player"] then prevIdToGuid["player"] = nil end
     for i = 1,size do
         local id = format("%s%i", prefix, i);
     for i = 1,size do
         local id = format("%s%i", prefix, i);
-        if not UnitIsUnit(id, "player") then
+        if not UnitIsUnit(id, "player") then -- player is already done
             updateUnitid(id);
         end
             updateUnitid(id);
         end
-        if prevIdToGuid[id] then prevIdToGuid[id] = nil end
     end
     end
+end
 
 
-    -- clean up players leaving
-    for id, guid in pairs(prevIdToGuid) do
-        if frames[guid] then
-            for _, frame in pairs(frames[guid]) do
-                removeFrame(frame);
+-- just check removals, don't cause inspects
+local function fastUpdateUnitids()
+    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);
+        if not UnitExists(id) or UnitGroupRolesAssigned(id) ~= "HEALER" then
+            idToGuid[id] = nil;
+            if frames[guid] then
+                for _, frame in pairs(frames[guid]) do
+                    removeFrame(frame);
+                end
             end
         end
     end
             end
         end
     end
@@ -426,47 +442,34 @@ local events = {
                 if runningcds[guid] and runningcds[guid][115310] then
                     runningcds[guid][115310] = runningcds[guid][115310] - 2;
                 end
                 if runningcds[guid] and runningcds[guid][115310] then
                     runningcds[guid][115310] = runningcds[guid][115310] - 2;
                 end
+            elseif guidToSpecid[guid] == 257 and spellid == 62618 then
+                -- assumed Holy priest cast Barrier, set to update to Disc
+                guidToSpecid[guid] = 256;
+                for _, frame in pairs(frames[guid]) do
+                    removeFrame(frame);
+                end
+                updateUnitCD(guid);
+                CdDown(guid, spellid, GetTime());
             end
         end
     end,
     ["PLAYER_SPECIALIZATION_CHANGED"] = function(id)
         updateUnitid(id);
     end,
             end
         end
     end,
     ["PLAYER_SPECIALIZATION_CHANGED"] = function(id)
         updateUnitid(id);
     end,
-    ["UNIT_INVENTORY_CHANGED"] = function(id)
-        local guid = idToGuid[id];
-        if guid and guidToSpecid[guid] == 270 then
-            print("OmaCD Inventory: Monk inventory update");
-            updateMonk(guid);
-        end
-    end,
     ["GROUP_ROSTER_UPDATE"] = function()
     ["GROUP_ROSTER_UPDATE"] = function()
+        fastUpdateUnitids();
         if not updateQueued then
             updateQueued = true
         if not updateQueued then
             updateQueued = true
-            CTimerAfter(2, updateUnitids);
-        end
-    end,
-    ["INSPECT_READY"] = function(guid)
-        local specid = guidToSpecid[guid];
-        if inspectSent[guid] then inspectSent[guid] = nil end
-        if specid == 105 then -- Druid
-            print("OmaCD Inspect: druid,", guid);
-            updateDruid(guid);
-            ClearInspectPlayer();
-        elseif specid == 270 then -- Monk
-            print("OmaCD Inspect: monk,", guid);
-            -- don't clear inspect player, have to track inventory changes
-        elseif specid == false or specid == 256 or specid == 257 then -- Priest
-            print("OmaCD Inspect: priest,", guid);
-            updatePriest(guid);
-            ClearInspectPlayer();
+            CTimerAfter(4, updateUnitids);
         end
     end,
 };
 events["PLAYER_ROLES_ASSIGNED"] = events["GROUP_ROSTER_UPDATE"];
         end
     end,
 };
 events["PLAYER_ROLES_ASSIGNED"] = events["GROUP_ROSTER_UPDATE"];
+events["PLAYER_ENTERING_WORLD"] = events["GROUP_ROSTER_UPDATE"];
 
 local function cdtracker()
     cdframe:SetFrameStrata("LOW");
 
 local function cdtracker()
     cdframe:SetFrameStrata("LOW");
-    cdframe:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 200, -200);
+    cdframe:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 580, -400);
     cdframe:SetWidth(1);
     cdframe:SetHeight(1);
 
     cdframe:SetWidth(1);
     cdframe:SetHeight(1);
 
@@ -478,13 +481,12 @@ local function cdtracker()
     cdframe:RegisterEvent("UNIT_CONNECTION");
     cdframe:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED");
     cdframe:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED");
     cdframe:RegisterEvent("UNIT_CONNECTION");
     cdframe:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED");
     cdframe:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED");
-    cdframe:RegisterEvent("UNIT_INVENTORY_CHANGED");
     cdframe:RegisterEvent("GROUP_ROSTER_UPDATE");
     cdframe:RegisterEvent("GROUP_ROSTER_UPDATE");
-    cdframe:RegisterEvent("INSPECT_READY");
     cdframe:RegisterEvent("PLAYER_ROLES_ASSIGNED");
     cdframe:RegisterEvent("PLAYER_ROLES_ASSIGNED");
-    -- initial update
-    events["GROUP_ROSTER_UPDATE"]();
+    cdframe:RegisterEvent("PLAYER_ENTERING_WORLD");
+    -- initial tick
     CTimerAfter(0.5, tick);
     CTimerAfter(0.5, tick);
+    CTimerAfter(10, monkTick);
 end
 
 cdframe:RegisterEvent("PLAYER_LOGIN");
 end
 
 cdframe:RegisterEvent("PLAYER_LOGIN");
diff --git a/OmaCD/Inspect.lua b/OmaCD/Inspect.lua
new file mode 100644 (file)
index 0000000..498ea06
--- /dev/null
@@ -0,0 +1,182 @@
+-- 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);
index 6e1a15e..6182dd3 100644 (file)
@@ -5,4 +5,5 @@
 ## Notes: My CD tracker
 
 Bres.lua
 ## Notes: My CD tracker
 
 Bres.lua
+Inspect.lua
 Cooldowns.lua
 Cooldowns.lua