1655 lines
63 KiB
Lua
1655 lines
63 KiB
Lua
--[[
|
|
This file is part of Decursive.
|
|
|
|
Decursive (v 2.5.1-6-gd3885c5) add-on for World of Warcraft UI
|
|
Copyright (C) 2006-2007-2008-2009 John Wellesz (archarodim AT teaser.fr) ( http://www.2072productions.com/to/decursive.php )
|
|
|
|
Starting from 2009-10-31 and until said otherwise by its author, Decursive
|
|
is no longer free software, all rights are reserved to its author (John Wellesz).
|
|
|
|
The only official and allowed distribution means are www.2072productions.com, www.wowace.com and curse.com.
|
|
To distribute Decursive through other means a special authorization is required.
|
|
|
|
|
|
Decursive is inspired from the original "Decursive v1.9.4" by Quu.
|
|
The original "Decursive 1.9.4" is in public domain ( www.quutar.com )
|
|
|
|
Decursive is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY.
|
|
--]]
|
|
-------------------------------------------------------------------------------
|
|
|
|
local addonName, T = ...;
|
|
|
|
-- big ugly scary fatal error message display function {{{
|
|
if not T._FatalError then
|
|
-- the beautiful error popup : {{{ -
|
|
StaticPopupDialogs["DECURSIVE_ERROR_FRAME"] = {
|
|
text = "|cFFFF0000Decursive Error:|r\n%s",
|
|
button1 = "OK",
|
|
OnAccept = function()
|
|
return false;
|
|
end,
|
|
timeout = 0,
|
|
whileDead = 1,
|
|
hideOnEscape = 1,
|
|
showAlert = 1,
|
|
}; -- }}}
|
|
T._FatalError = function (TheError) StaticPopup_Show ("DECURSIVE_ERROR_FRAME", TheError); end
|
|
end
|
|
-- }}}
|
|
|
|
if not T._LoadedFiles or not T._LoadedFiles["Dcr_lists.xml"] or not T._LoadedFiles["Dcr_lists.lua"] then -- XML are loaded even if LUA syntax errors exixts
|
|
if not DecursiveInstallCorrupted then T._FatalError("Decursive installation is corrupted! (Dcr_lists.xml or Dcr_lists.lua not loaded)"); end;
|
|
DecursiveInstallCorrupted = true;
|
|
return;
|
|
end
|
|
|
|
local D = T.Dcr;
|
|
|
|
|
|
local L = D.L;
|
|
local LC = D.LC;
|
|
local DC = DcrC;
|
|
local DS = DC.DS;
|
|
|
|
|
|
-- NS def
|
|
D.MicroUnitF = {};
|
|
-- create a shortcut
|
|
local MicroUnitF = D.MicroUnitF;
|
|
MicroUnitF.prototype = {};
|
|
MicroUnitF.metatable ={ __index = MicroUnitF.prototype };
|
|
|
|
function MicroUnitF:new(...)
|
|
local instance = setmetatable({}, self.metatable);
|
|
instance:init(...);
|
|
return instance;
|
|
end
|
|
|
|
|
|
|
|
-- since there are tens of thousands of globals defined at all times, lets use some locals!
|
|
local BOOKTYPE_PET = BOOKTYPE_PET;
|
|
local BOOKTYPE_SPELL = BOOKTYPE_SPELL;
|
|
|
|
-- Init object factory defaults
|
|
--MicroUnitF.ExistingPerID = {};
|
|
MicroUnitF.ExistingPerUNIT = {};
|
|
MicroUnitF.ExistingPerNum = {};
|
|
MicroUnitF.UnitToMUF = {};
|
|
MicroUnitF.Number = 0;
|
|
MicroUnitF.UnitShown = 0;
|
|
MicroUnitF.UnitsDebuffedInRange = 0;
|
|
MicroUnitF.DraggingHandle = false;
|
|
D.ForLLDebuffedUnitsNum = 0;
|
|
|
|
|
|
-- using power 2 values just to OR them but only CHARMED_STATUS is ORed (it's a C style bitfield)
|
|
local NORMAL = DC.NORMAL;
|
|
local ABSENT = DC.ABSENT;
|
|
local FAR = DC.FAR;
|
|
local STEALTHED = DC.STEALTHED;
|
|
local BLACKLISTED = DC.BLACKLISTED;
|
|
local AFFLICTED = DC.AFFLICTED;
|
|
local AFFLICTED_NIR = DC.AFFLICTED_NIR;
|
|
local CHARMED_STATUS = DC.CHARMED_STATUS;
|
|
local AFFLICTED_AND_CHARMED = DC.AFFLICTED_AND_CHARMED;
|
|
|
|
|
|
-- Those are the different colors used for the MUFs main texture
|
|
local MF_colors = { };
|
|
|
|
local unpack = _G.unpack;
|
|
local select = _G.select;
|
|
local pairs = _G.pairs;
|
|
local ipairs = _G.ipairs;
|
|
local GetTime = _G.GetTime;
|
|
local PlaySoundFile = _G.PlaySoundFile;
|
|
local IsControlKeyDown = _G.IsControlKeyDown;
|
|
local floor = _G.math.floor;
|
|
local table = _G.table;
|
|
local t_insert = _G.table.insert;
|
|
local str_format = _G.string.format;
|
|
local str_sub = _G.string.gsub;
|
|
local table = _G.table;
|
|
local string = _G.string;
|
|
local UnitExists = _G.UnitExists;
|
|
local UnitClass = _G.UnitClass;
|
|
local fmod = _G.math.fmod;
|
|
local UnitIsUnit = _G.UnitIsUnit;
|
|
local str_upper = _G.string.upper;
|
|
local InCombatLockdown = _G.InCombatLockdown;
|
|
local UnitAura = _G.UnitAura;
|
|
local GetRaidTargetIndex= _G.GetRaidTargetIndex;
|
|
|
|
|
|
DC.AvailableButtonsReadable = { -- {{{
|
|
["%s1"] = L["HLP_LEFTCLICK"], -- left mouse button
|
|
["%s2"] = L["HLP_RIGHTCLICK"], -- right mouse button
|
|
["%s3"] = L["HLP_MIDDLECLICK"], -- middle mouse button
|
|
["ctrl-%s1"] = L["CTRL"] .. "-" .. L["HLP_LEFTCLICK"],
|
|
["ctrl-%s2"] = L["CTRL"] .. "-" .. L["HLP_RIGHTCLICK"],
|
|
["ctrl-%s3"] = L["CTRL"] .. "-" .. L["HLP_MIDDLECLICK"],
|
|
["shift-%s1"] = L["SHIFT"] .. "-" .. L["HLP_LEFTCLICK"],
|
|
["shift-%s2"] = L["SHIFT"] .. "-" .. L["HLP_RIGHTCLICK"],
|
|
["shift-%s3"] = L["SHIFT"] .. "-" .. L["HLP_MIDDLECLICK"],
|
|
["alt-%s1"] = L["ALT"] .. "-" .. L["HLP_LEFTCLICK"],
|
|
["alt-%s2"] = L["ALT"] .. "-" .. L["HLP_RIGHTCLICK"],
|
|
["alt-%s3"] = L["ALT"] .. "-" .. L["HLP_MIDDLECLICK"],
|
|
-- 3, -- middle mouse button || RESERVED FOR TARGETTING
|
|
}; -- }}}
|
|
|
|
-- modifier for the macro
|
|
local AvailableModifier = { -- {{{
|
|
"shift","ctrl","alt",
|
|
} -- }}}
|
|
|
|
-- MicroUnitF STATIC methods {{{
|
|
|
|
-- Updates the color table
|
|
function MicroUnitF:RegisterMUFcolors ()
|
|
-- MF_colors = D.profile.MF_colors; -- this should be enough but is not because D.profile can change at unexpected times....
|
|
D:tcopy(MF_colors, D.profile.MF_colors);
|
|
end
|
|
|
|
-- defines what is printed when the object is read as a string
|
|
function MicroUnitF:ToString() -- {{{
|
|
return "Decursive Micro Unit Frame Object";
|
|
end -- }}}
|
|
|
|
-- The Factory for MicroUnitF objects
|
|
function MicroUnitF:Create(Unit, ID) -- {{{
|
|
|
|
if InCombatLockdown() then
|
|
-- if we are fighting, postpone the call
|
|
D:AddDelayedFunctionCall (
|
|
"Create"..Unit, self.Create,
|
|
Unit, ID);
|
|
return false;
|
|
end
|
|
|
|
-- if we attempt to create a MUF that already exists, update it instead
|
|
if (self.ExistingPerUNIT[Unit]) then
|
|
return self.ExistingPerUNIT[Unit];
|
|
end
|
|
|
|
self.Number = self.Number + 1;
|
|
|
|
-- create a new MUF object
|
|
self.ExistingPerUNIT[Unit] = self:new(D.MFContainer, Unit, self.Number, ID);
|
|
|
|
self.ExistingPerNum[self.Number] = self.ExistingPerUNIT[Unit];
|
|
|
|
return self.ExistingPerUNIT[Unit];
|
|
end -- }}}
|
|
|
|
-- return a MUF object if it exists, nil otherwise
|
|
--[=[
|
|
function MicroUnitF:Exists(IdOrNum) -- {{{
|
|
return self.ExistingPerID[IdOrNum] or self.ExistingPerNum[IdOrNum];
|
|
end
|
|
--]=]
|
|
-- }}}
|
|
|
|
-- return the number MUFs we can use
|
|
function MicroUnitF:MFUsableNumber () -- {{{
|
|
return ((self.MaxUnit > D.Status.UnitNum) and D.Status.UnitNum or self.MaxUnit);
|
|
end -- }}}
|
|
|
|
-- this is used when a setting influencing MUF's position is changed
|
|
function MicroUnitF:ResetAllPositions () -- {{{
|
|
|
|
if InCombatLockdown() then
|
|
D:AddDelayedFunctionCall (
|
|
"ResetAllPositions", self.ResetAllPositions,
|
|
self);
|
|
return false;
|
|
end
|
|
|
|
local MF, i;
|
|
|
|
D:Debug("Resetting all MF position");
|
|
|
|
self:Delayed_MFsDisplay_Update ();
|
|
|
|
local Unit_Array = D.Status.Unit_Array;
|
|
|
|
for i=1, #Unit_Array do
|
|
MF = self.ExistingPerUNIT[ Unit_Array[i] ]
|
|
|
|
if MF then
|
|
MF.Frame:SetPoint(unpack(self:GiveMFAnchor(i)));
|
|
end
|
|
end
|
|
end -- }}}
|
|
|
|
-- return the anchor of a given MUF depending on its creation ID
|
|
do
|
|
local Anchor = { "TOPLEFT", x, y, "TOPLEFT" };
|
|
function MicroUnitF:GiveMFAnchor (ID) -- {{{
|
|
local LineNum = floor( (ID - 1) / D.profile.DebuffsFramePerline);
|
|
local NumOnLine = fmod( (ID - 1), D.profile.DebuffsFramePerline);
|
|
|
|
local x = (D.profile.DebuffsFrameGrowToTop and DC.MFSIZE or 0) + NumOnLine * (DC.MFSIZE + D.profile.DebuffsFrameXSpacing);
|
|
local y = (D.profile.DebuffsFrameGrowToTop and -1 or 1) * LineNum * ((-1 * D.profile.DebuffsFrameYSpacing) - DC.MFSIZE);
|
|
|
|
Anchor[2] = x; Anchor[3] = y;
|
|
|
|
return Anchor;
|
|
end
|
|
end-- }}}
|
|
|
|
|
|
function MicroUnitF:Delayed_MFsDisplay_Update ()
|
|
if D.profile.ShowDebuffsFrame then
|
|
D:ScheduleDelayedCall("Dcr_UpdateMUFsNUM", self.MFsDisplay_Update, 1.5, self);
|
|
end
|
|
end
|
|
|
|
-- This update the MUFs display, show and hide MUFs as necessary
|
|
function MicroUnitF:MFsDisplay_Update () -- {{{
|
|
|
|
if (not D.profile.ShowDebuffsFrame) then
|
|
return false; -- XXX we will have to call this function again when we show the MUFs
|
|
end
|
|
|
|
-- This function cannot do anything if we are fighting
|
|
if InCombatLockdown() then
|
|
-- if we are fighting, postpone the call
|
|
D:AddDelayedFunctionCall (
|
|
"UpdateMicroUnitFrameDisplay", self.MFsDisplay_Update,
|
|
self);
|
|
return false;
|
|
end
|
|
|
|
-- Get an up to date unit array if necessary
|
|
D:GetUnitArray(); -- this is the only place where GetUnitArray() is called directly
|
|
|
|
-- =======
|
|
-- Begin
|
|
-- =======
|
|
|
|
-- get the number of MUFs we should display
|
|
local NumToShow = self:MFUsableNumber();
|
|
|
|
|
|
-- if we don't have all the MUFs needed then return, we are not ready
|
|
if (self.Number < NumToShow) then
|
|
self:Delayed_MFsDisplay_Update ();
|
|
return false;
|
|
end
|
|
|
|
|
|
local MF = false;
|
|
local i = 1;
|
|
local Old_UnitShown = self.UnitShown;
|
|
|
|
|
|
D:Debug("Update required: NumToShow = ", NumToShow);
|
|
|
|
local Unit_Array_UnitToGUID = D.Status.Unit_Array_UnitToGUID;
|
|
local Unit_Array = D.Status.Unit_Array;
|
|
|
|
|
|
-- Scan unit array in display order and show the maximum until NumToShow is reached
|
|
-- The ID is set for all MUFs present in our unit array
|
|
local Updated = 0;
|
|
for i, Unit in ipairs(Unit_Array) do
|
|
|
|
MF = self.ExistingPerUNIT[Unit];
|
|
if MF then
|
|
MF.ID = i;
|
|
|
|
if not MF.Shown and i <= NumToShow then -- we got this unit in our group but it's hidden
|
|
|
|
MF.Shown = true;
|
|
self.UnitShown = self.UnitShown + 1;
|
|
MF.ToPlace = true;
|
|
Updated = Updated + 1;
|
|
|
|
D:ScheduleDelayedCall("Dcr_Update"..MF.CurrUnit, MF.UpdateWithCS, D.profile.DebuffsFrameRefreshRate * Updated, MF);
|
|
--D:Debug("|cFF88AA00Show schedule for MUF", Unit, "UnitShown:", self.UnitShown);
|
|
end
|
|
else
|
|
--D:errln("showhide: no muf for", Unit); -- call delay display up
|
|
self:Delayed_MFsDisplay_Update ();
|
|
end
|
|
|
|
end
|
|
|
|
-- hide remaining units
|
|
if self.UnitShown > NumToShow then
|
|
|
|
for Unit, MF in pairs(self.ExistingPerUNIT) do -- see all the MUF we ever created and show or hide them if there corresponding unit exists
|
|
|
|
-- show/hide
|
|
if MF.Shown and (not Unit_Array_UnitToGUID[Unit] or MF.ID > NumToShow ) then -- we don't have this unit but its MUF is shown
|
|
|
|
-- clear debuff before hiding to avoid leaving 'ghosts' behind...
|
|
if D.UnitDebuffed[MF.CurrUnit] then
|
|
D.ForLLDebuffedUnitsNum = D.ForLLDebuffedUnitsNum - 1;
|
|
end
|
|
|
|
MF.Debuffs = false;
|
|
MF.IsDebuffed = false;
|
|
MF.Debuff1Prio = false;
|
|
MF.PrevDebuff1Prio = false;
|
|
D.UnitDebuffed[MF.CurrUnit] = false; -- used by the live-list only
|
|
D.Stealthed_Units[MF.CurrUnit] = false;
|
|
|
|
|
|
MF.Shown = false;
|
|
self.UnitShown = self.UnitShown - 1;
|
|
--D:Debug("|cFF88AA00Hiding %d (%s), scheduling update in %f|r", i, MF.CurrUnit, D.profile.DebuffsFrameRefreshRate * i);
|
|
Updated = Updated + 1;
|
|
D:ScheduleDelayedCall("Dcr_Update"..MF.CurrUnit, MF.Update, D.profile.DebuffsFrameRefreshRate * Updated, MF);
|
|
MF.Frame:Hide();
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
-- manage to get what we show in the screen
|
|
if self.UnitShown > 0 and Old_UnitShown ~= self.UnitShown then
|
|
MicroUnitF:Place();
|
|
end
|
|
|
|
return true;
|
|
end -- }}}
|
|
|
|
|
|
function MicroUnitF:Delayed_Force_FullUpdate ()
|
|
if (D.profile.ShowDebuffsFrame) then
|
|
D:ScheduleDelayedCall("Dcr_Force_FullUpdate", self.Force_FullUpdate, 0.3, self);
|
|
end
|
|
end
|
|
|
|
function MicroUnitF:Force_FullUpdate () -- {{{
|
|
if (not D.profile.ShowDebuffsFrame) then
|
|
return false;
|
|
end
|
|
|
|
-- This function cannot do anything if we are fighting
|
|
if InCombatLockdown() then
|
|
-- if we are fighting, postpone the call
|
|
D:AddDelayedFunctionCall (
|
|
"Force_FullUpdate", self.Force_FullUpdate,
|
|
self);
|
|
return false;
|
|
end
|
|
|
|
local MF;--, MF_f;
|
|
|
|
D.Status.SpellsChanged = GetTime(); -- will force an update of all MUFs attributes
|
|
|
|
local i = 1;
|
|
for Unit, MF in pairs(self.ExistingPerUNIT) do
|
|
|
|
if not MF.IsDebuffed then
|
|
MF.UnitStatus = 0; -- reset status to force SetColor to update
|
|
end
|
|
|
|
MF.ChronoFontString:SetTextColor(unpack(MF_colors["COLORCHRONOS"]));
|
|
|
|
D:ScheduleDelayedCall("Dcr_Update"..MF.CurrUnit, MF.UpdateWithCS, D.profile.DebuffsFrameRefreshRate * i, MF);
|
|
i = i + 1;
|
|
end
|
|
end -- }}}
|
|
|
|
|
|
-- Those set the scalling of the MUF container
|
|
-- SACALING FUNCTIONS (MicroUnitF Children) {{{
|
|
-- Place the MUFs container according to its scale
|
|
function MicroUnitF:Place () -- {{{
|
|
|
|
if self.UnitShown == 0 or self.DraggingHandle then return end
|
|
|
|
if InCombatLockdown() then
|
|
-- if we are fighting, postpone the call
|
|
D:AddDelayedFunctionCall (
|
|
"MicroUnitFPlace", self.Place,
|
|
self);
|
|
return;
|
|
end
|
|
|
|
|
|
local UIScale = UIParent:GetEffectiveScale()
|
|
local FrameScale = self.Frame:GetEffectiveScale();
|
|
local x, y = D.profile.DebuffsFrame_x, D.profile.DebuffsFrame_y;
|
|
|
|
-- If executed for the very first time, then put it in the top right corner of the screen
|
|
if (not x or not y) then
|
|
x = (UIParent:GetWidth() * UIScale) - (UIParent:GetWidth() * UIScale) / 4;
|
|
y = - (UIParent:GetHeight() * UIScale) / 5;
|
|
|
|
D.profile.DebuffsFrame_x = x;
|
|
D.profile.DebuffsFrame_y = y;
|
|
end
|
|
|
|
|
|
local FirstLineNum = 0;
|
|
local Handle_x_offset = 0;
|
|
local Handle_y_offset = 0;
|
|
|
|
-- get the number of max unit per line
|
|
if self.UnitShown >= D.profile.DebuffsFramePerline then FirstLineNum = D.profile.DebuffsFramePerline; else FirstLineNum = self.UnitShown; end
|
|
|
|
-- get the offset of the handle we need to apply in order to align the MUFs on the right
|
|
if D.profile.DebuffsFrameStickToRight then
|
|
Handle_x_offset = -1 * FrameScale * (FirstLineNum * (DC.MFSIZE + D.profile.DebuffsFrameXSpacing) - D.profile.DebuffsFrameXSpacing );
|
|
end
|
|
|
|
Handle_x_offset = Handle_x_offset - FrameScale * (D.profile.DebuffsFrameGrowToTop and DC.MFSIZE or 0);
|
|
Handle_y_offset = Handle_y_offset + FrameScale * (D.profile.DebuffsFrameGrowToTop and DC.MFSIZE or 0);
|
|
|
|
-- check the right edge so it can't be out of the screen
|
|
local RightEdge = x + FrameScale * (FirstLineNum * (DC.MFSIZE + D.profile.DebuffsFrameXSpacing) - D.profile.DebuffsFrameXSpacing + (D.profile.DebuffsFrameGrowToTop and DC.MFSIZE or 0)) + Handle_x_offset ;
|
|
|
|
if (RightEdge > UIParent:GetWidth() * UIScale) then
|
|
Handle_x_offset = Handle_x_offset - (RightEdge - UIParent:GetWidth() * UIScale);
|
|
D:Debug("put the MUFs on the screen!!! (Right edge out)");
|
|
end
|
|
|
|
-- check the left edge so it can't be out of the screen
|
|
local LeftEdge = x + Handle_x_offset;
|
|
if (LeftEdge < 0) then
|
|
Handle_x_offset = Handle_x_offset - LeftEdge;
|
|
D:Debug("put the MUFs on the screen!!! (Left edge out)");
|
|
end
|
|
|
|
-- check the bottom edge
|
|
local NumberOfLines = floor( (self.UnitShown - 1) / D.profile.DebuffsFramePerline) + 1;
|
|
--D:Debug(NumberOfLines);
|
|
|
|
local BottomEdge = y - FrameScale * ((D.profile.DebuffsFrameGrowToTop and 1 or NumberOfLines) * (DC.MFSIZE + D.profile.DebuffsFrameYSpacing) - D.profile.DebuffsFrameYSpacing) + Handle_y_offset;
|
|
|
|
if -BottomEdge > UIParent:GetHeight() * UIScale then
|
|
Handle_y_offset = Handle_y_offset - (BottomEdge + UIParent:GetHeight() * UIScale);
|
|
D:Debug("put the MUFs on the screen!!! (Bottom edge out)");
|
|
end
|
|
|
|
-- check the top edge
|
|
local TopEdge = y + FrameScale * (((D.profile.DebuffsFrameGrowToTop and NumberOfLines > 1) and NumberOfLines - 1 or 1) * (DC.MFSIZE + D.profile.DebuffsFrameYSpacing) - ((not D.profile.DebuffsFrameGrowToTop) and 1 or 0) * D.profile.DebuffsFrameYSpacing) + Handle_y_offset;
|
|
if (TopEdge > 0) then
|
|
Handle_y_offset = Handle_y_offset - TopEdge;
|
|
D:Debug("put the MUFs on the screen!!! (Top edge out)");
|
|
end
|
|
|
|
x = x + Handle_x_offset;
|
|
y = y + Handle_y_offset;
|
|
|
|
|
|
|
|
-- set to the scaled position
|
|
self.Frame:ClearAllPoints();
|
|
self.Frame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", x/FrameScale , y/FrameScale);
|
|
D:Debug("MUF Window position set");
|
|
end -- }}}
|
|
|
|
-- Save the position of the frame without its scale
|
|
function MicroUnitF:SavePos () -- {{{
|
|
|
|
if self.UnitShown == 0 then return end
|
|
|
|
local FirstLineNum;
|
|
|
|
if self.Frame:IsVisible() then
|
|
-- We save the unscalled position (no problem if the sacale is changed behind our back)
|
|
D.profile.DebuffsFrame_x = self.Frame:GetEffectiveScale() * self.Frame:GetLeft();
|
|
D.profile.DebuffsFrame_y = self.Frame:GetEffectiveScale() * self.Frame:GetTop() - UIParent:GetHeight() * UIParent:GetEffectiveScale();
|
|
|
|
|
|
-- if we choosed to align the MUF to the right then we have to add the
|
|
-- width of the first line to get the original position of the handle
|
|
|
|
if D.profile.DebuffsFrameStickToRight then
|
|
|
|
if self.UnitShown >= D.profile.DebuffsFramePerline then
|
|
FirstLineNum = D.profile.DebuffsFramePerline;
|
|
else
|
|
FirstLineNum = self.UnitShown;
|
|
end
|
|
|
|
D.profile.DebuffsFrame_x = D.profile.DebuffsFrame_x + self.Frame:GetEffectiveScale() * (FirstLineNum * (DC.MFSIZE + D.profile.DebuffsFrameXSpacing) - D.profile.DebuffsFrameXSpacing);
|
|
end
|
|
|
|
D.profile.DebuffsFrame_x = D.profile.DebuffsFrame_x + self.Frame:GetEffectiveScale() * (D.profile.DebuffsFrameGrowToTop and DC.MFSIZE or 0);
|
|
D.profile.DebuffsFrame_y = D.profile.DebuffsFrame_y - self.Frame:GetEffectiveScale() * (D.profile.DebuffsFrameGrowToTop and DC.MFSIZE or 0);
|
|
|
|
-- D:Debug("Frame position saved");
|
|
end
|
|
|
|
end -- }}}
|
|
|
|
-- set the scaling of the MUFs container according to the user settings
|
|
function MicroUnitF:SetScale (NewScale) -- {{{
|
|
|
|
-- save the current position without any scaling
|
|
-- self:SavePos ();
|
|
-- Setting the new scale
|
|
self.Frame:SetScale(NewScale);
|
|
-- Place the frame adapting its position to the news cale
|
|
self:Place ();
|
|
|
|
end -- }}}
|
|
-- }}}
|
|
|
|
-- Update the MUF of a given unitid
|
|
function MicroUnitF:UpdateMUFUnit(Unitid, CheckStealth)
|
|
if not D.profile.ShowDebuffsFrame then
|
|
return;
|
|
end
|
|
|
|
local unit = false;
|
|
|
|
if (D.Status.Unit_Array_UnitToGUID[Unitid]) then
|
|
unit = Unitid;
|
|
else
|
|
D:Debug("Unit", Unitid, "not in raid or party!" );
|
|
return;
|
|
end
|
|
|
|
-- get the MUF object
|
|
local MF = self.UnitToMUF[unit];
|
|
|
|
if (MF and MF.Shown) then
|
|
-- The MUF will be updated only every DebuffsFrameRefreshRate seconds at most
|
|
-- but we don't miss any event XXX note this can be the cause of slowdown if 25 or 40 players got debuffed at the same instant, DebuffUpdateRequest is here to prevent that since 2008-02-17
|
|
if (not D:DelayedCallExixts("Dcr_Update"..unit)) then
|
|
D.DebuffUpdateRequest = D.DebuffUpdateRequest + 1;
|
|
D:ScheduleDelayedCall("Dcr_Update"..unit, CheckStealth and MF.UpdateWithCS or MF.Update, D.profile.DebuffsFrameRefreshRate * (1 + floor(D.DebuffUpdateRequest / (D.profile.DebuffsFramePerUPdate / 2))), MF);
|
|
D:Debug("Update scheduled for, ", unit, MF.ID);
|
|
|
|
return true; -- return value used to aknowledge that the function actually did something
|
|
end
|
|
else
|
|
D:Debug("No MUF found for ", unit, Unitid);
|
|
end
|
|
end
|
|
|
|
-- Event management functions
|
|
-- MUF EVENTS (MicroUnitF children) (OnEnter, OnLeave, OnLoad, OnPreClick) {{{
|
|
-- It's outside the function to avoid creating and discarding this table at each call
|
|
local DefaultTTAnchor = {"ANCHOR_TOPLEFT", 0, 6};
|
|
local UnitGUID = _G.UnitGUID;
|
|
local TooltipButtonsInfo = {}; -- help tooltip text table
|
|
local TooltipUpdate = 0; -- help tooltip change update check
|
|
-- This function is responsible for showing the tooltip when the mouse pointer is over a MUF
|
|
-- it also handles Unstable Affliction detection and warning.
|
|
function MicroUnitF:OnEnter(frame) -- {{{
|
|
D.Status.MouseOveringMUF = true;
|
|
|
|
local MF = frame.Object;
|
|
local Status;
|
|
|
|
local Unit = MF.CurrUnit; -- shortcut
|
|
local TooltipText = "";
|
|
|
|
|
|
local GUIDwasFixed = false;
|
|
local unitguid = UnitGUID(Unit);
|
|
|
|
if unitguid ~= D.Status.Unit_Array_UnitToGUID[Unit] or Unit ~= D.Status.Unit_Array_GUIDToUnit[unitguid] then
|
|
|
|
if unitguid then
|
|
D.Status.Unit_Array_UnitToGUID[Unit] = unitguid;
|
|
D.Status.Unit_Array_GUIDToUnit[unitguid] = Unit;
|
|
GUIDwasFixed = true;
|
|
end
|
|
|
|
end
|
|
|
|
MF:Update(false, false, true); -- will reset the color early and set the current status of the MUF
|
|
MF:SetClassBorder(); -- set the border if it wasn't possible at the time the unit was discovered
|
|
|
|
if not Unit then
|
|
return; -- If the user overs the MUF befor it's completely initialized
|
|
end
|
|
|
|
--Test for unstable affliction
|
|
if MF.Debuffs then
|
|
for i, Debuff in ipairs(MF.Debuffs) do
|
|
if Debuff.Type then
|
|
-- Create a warning if the Unstable Affliction is detected
|
|
if Debuff.Name == DS["Unstable Affliction"] then
|
|
--if Debuff.Name == "Malédiction de Stalvan" then -- to test easily
|
|
D:Println("|cFFFF0000 ==> %s !!|r (%s)", DS["Unstable Affliction"], D:MakePlayerName((D:PetUnitName( Unit, true ))));
|
|
PlaySoundFile("Sound\\Doodad\\G_NecropolisWound.wav");
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if D.profile.AfflictionTooltips then
|
|
|
|
-- removes the CHARMED_STATUS bit from Status, we don't need it
|
|
Status = bit.band(MF.UnitStatus, bit.bnot(CHARMED_STATUS));
|
|
|
|
-- First, write the name of the unit in its class color
|
|
if UnitExists(MF.CurrUnit) then
|
|
TooltipText =
|
|
((DC.RAID_ICON_LIST[GetRaidTargetIndex(Unit)]) and (DC.RAID_ICON_LIST[GetRaidTargetIndex(Unit)] .. "0:0:0:0|t ") or "" ) ..
|
|
-- Colored unit name
|
|
D:ColorText( (D:PetUnitName( Unit, true ))
|
|
, "FF" .. ((UnitClass(Unit)) and DC.HexClassColor[ (select(2, UnitClass(Unit))) ] or "AAAAAA")) .. " |cFF3F3F3F(".. Unit .. ")|r";
|
|
else
|
|
TooltipText = MF.CurrUnit;
|
|
end
|
|
|
|
|
|
-- set UnitStatus text
|
|
local StatusText = "";
|
|
|
|
-- set the status text, just translate the bitfield to readable text
|
|
if Status == NORMAL then
|
|
StatusText = L["NORMAL"];
|
|
|
|
elseif Status == ABSENT then
|
|
StatusText = str_format(L["ABSENT"], Unit);
|
|
|
|
elseif Status == FAR then
|
|
StatusText = L["TOOFAR"];
|
|
|
|
elseif Status == STEALTHED then
|
|
StatusText = L["STEALTHED"];
|
|
|
|
elseif Status == BLACKLISTED then
|
|
StatusText = L["BLACKLISTED"];
|
|
|
|
elseif MF.Debuffs and (Status == AFFLICTED or Status == AFFLICTED_NIR) then
|
|
local DebuffType = MF.Debuffs[1].Type;
|
|
StatusText = str_format(L["AFFLICTEDBY"], D:ColorText( L[str_upper(DC.TypeNames[DebuffType])], "FF" .. DC.TypeColors[DebuffType]) );
|
|
end
|
|
|
|
-- Unit Status
|
|
--TooltipText = TooltipText .. "\n" .. L["UNITSTATUS"] .. StatusText .. "\n";
|
|
TooltipText = TooltipText .. "\n" .. StatusText;
|
|
|
|
-- list the debuff(s) names
|
|
if MF.Debuffs then
|
|
for i, Debuff in ipairs(MF.Debuffs) do
|
|
if Debuff.Type then
|
|
local DebuffApps = Debuff.Applications;
|
|
TooltipText = TooltipText .. "\n" .. str_format("%s", D:ColorText(Debuff.Name, "FF" .. DC.TypeColors[Debuff.Type])) .. (DebuffApps>0 and str_format(" (%d)", DebuffApps) or "");
|
|
end
|
|
end
|
|
end
|
|
|
|
local VerticalMUF = floor((self.UnitShown - 1) / D.profile.DebuffsFramePerline ) * D.profile.DebuffsFramePerline + 1;
|
|
|
|
-- The tooltip is anchored above the top first MUF
|
|
if not D.profile.DebuffsFrameGrowToTop then
|
|
local FirstMUFAnchor = self:GiveMFAnchor(1);
|
|
DefaultTTAnchor[2] = FirstMUFAnchor[2];
|
|
DefaultTTAnchor[3] = FirstMUFAnchor[3];
|
|
else
|
|
local TopMUFAnchor = self:GiveMFAnchor(VerticalMUF);
|
|
DefaultTTAnchor[2] = TopMUFAnchor[2];
|
|
DefaultTTAnchor[3] = TopMUFAnchor[3];
|
|
end
|
|
|
|
-- Display the tooltip
|
|
D:DisplayTooltip( TooltipText , self.Frame, DefaultTTAnchor);
|
|
|
|
-- if the tooltip is at the top of the screen it means it's overlaping the MUF, let's move the tooltip somewhere else.
|
|
if floor(DcrDisplay_Tooltip:GetTop()) == floor(UIParent:GetTop()) then
|
|
local RefMUF = 1;
|
|
|
|
if not D.profile.DebuffsFrameGrowToTop then
|
|
RefMUF = VerticalMUF;
|
|
end
|
|
|
|
DcrDisplay_Tooltip:ClearAllPoints();
|
|
DcrDisplay_Tooltip:SetPoint("TOPLEFT", self.ExistingPerNum[RefMUF].Frame, "BOTTOMLEFT");
|
|
end
|
|
end
|
|
|
|
-- show a help text in the Game default tooltip
|
|
if D.profile.DebuffsFrameShowHelp then
|
|
-- if necessary we will update the help tooltip text
|
|
if (D.Status.SpellsChanged ~= TooltipUpdate) then
|
|
TooltipButtonsInfo = {};
|
|
local AvailableButtons = D.db.global.AvailableButtons;
|
|
|
|
for Spell, Prio in pairs(D.Status.CuringSpellsPrio) do
|
|
TooltipButtonsInfo[Prio] =
|
|
str_format("%s: %s", D:ColorText(DC.AvailableButtonsReadable[AvailableButtons[Prio]], D:NumToHexColor(MF_colors[Prio])), Spell);
|
|
end
|
|
|
|
t_insert(TooltipButtonsInfo, str_format("%s: %s", DC.AvailableButtonsReadable[AvailableButtons[#AvailableButtons - 1]], L["TARGETUNIT"]));
|
|
t_insert(TooltipButtonsInfo, str_format("%s: %s", DC.AvailableButtonsReadable[AvailableButtons[#AvailableButtons ]], L["FOCUSUNIT"]));
|
|
TooltipButtonsInfo = table.concat(TooltipButtonsInfo, "\n");
|
|
TooltipUpdate = D.Status.SpellsChanged;
|
|
end
|
|
|
|
GameTooltip_SetDefaultAnchor(GameTooltip, frame);
|
|
GameTooltip:SetText(TooltipButtonsInfo);
|
|
GameTooltip:Show();
|
|
|
|
end
|
|
|
|
end -- }}}
|
|
|
|
-- No longer used
|
|
--[===[
|
|
function MicroUnitF:LateAnalysis(From, Debuffs, MF, Status, GUIDwasFixed)
|
|
|
|
local Unit = MF.CurrUnit; -- shortcut
|
|
local unitguid = UnitGUID(Unit);
|
|
local RegisteredUnitguid = MF.UnitGUID;
|
|
-- search for detection by combat event manager
|
|
local foundcblevents = {}; local highestever = 0; local _; local i=1; local dname; local DebuffApplyTime = false;
|
|
local debuffname = Debuffs and Debuffs[1].Name or "No debuff, charmed?";
|
|
|
|
-- find the debuff on the unit and find out when it was applyed
|
|
while 1 do
|
|
dname = UnitAura(Unit, i, "HARMFUL");
|
|
|
|
if not dname then break end;
|
|
|
|
if dname == debuffname then
|
|
local Dduration, DexpireTime;
|
|
dname, _, _, _, _, Dduration, DexpireTime = UnitAura(Unit, i, "HARMFUL");
|
|
DebuffApplyTime = DexpireTime - Dduration;
|
|
break;
|
|
end
|
|
i = i + 1;
|
|
end
|
|
|
|
|
|
if not DebuffApplyTime or DebuffApplyTime == 0 then
|
|
D:AddDebugText("DebuffApplyTime could not be found for ", dname, "on", Unit, "DebuffApplyTime set to now - 3s");
|
|
DebuffApplyTime = GetTime() - 3;
|
|
end
|
|
|
|
local DetectHistoryIndex = 1;
|
|
local halfrange = 5; local RangeMatch = false; local latestever = "none"; local latesttime = 0;
|
|
local tconcat = _G.table.concat
|
|
D:Debug("Looking for events on", Unit, "between", DebuffApplyTime - halfrange, "and", DebuffApplyTime + halfrange);
|
|
-- look in the history of the combat log event handler
|
|
while D.DetectHistory[DetectHistoryIndex] do
|
|
-- take all the events related to this unit or debuffname around the time the missed debuff was applyed
|
|
if D.DetectHistory[DetectHistoryIndex][8] == unitguid or D.DetectHistory[DetectHistoryIndex][12] == debuffname then
|
|
|
|
if D.DetectHistory[DetectHistoryIndex][1] > DebuffApplyTime - halfrange and D.DetectHistory[DetectHistoryIndex][1] < DebuffApplyTime + halfrange then
|
|
t_insert(foundcblevents, tconcat(D.DetectHistory[DetectHistoryIndex],", "));
|
|
t_insert(foundcblevents, "\n");
|
|
RangeMatch = true;
|
|
elseif D.DetectHistory[DetectHistoryIndex][1] > latesttime then-- find the latest event concerning this unit
|
|
latesttime = D.DetectHistory[DetectHistoryIndex][1];
|
|
latestever = DetectHistoryIndex;
|
|
end
|
|
|
|
end
|
|
|
|
DetectHistoryIndex = DetectHistoryIndex + 1;
|
|
end
|
|
|
|
if latestever ~= "none" then
|
|
latestever = tconcat(D.DetectHistory[latestever],", ");
|
|
end
|
|
|
|
D:AddDebugText("Debuff late detection:", From, debuffname, "Type:", Debuffs[1].TypeName, "on unit:", Unit, unitguid, "_AppT_:", DebuffApplyTime, "DFRR:", D.profile.DebuffsFrameRefreshRate, "Status:", Status, "DT:", GetTime(), "LGU:", D.Status.GroupUpdatedOn, "LGuEr", D.Status.GroupUpdateEvent, "JFGUID:", GUIDwasFixed, "DbUreq:", D.DebuffUpdateRequest, "MFGuid~:", RegisteredUnitguid ~= unitguid, "Z:", GetZoneText(), "DTI:", DetectHistoryIndex);
|
|
|
|
-- trigger a dcr diag if DetectHistoryIndex is 1 :/
|
|
if DetectHistoryIndex == 1 then
|
|
T._SelfDiagnostic(true, true);
|
|
end
|
|
|
|
if #foundcblevents == 0 then
|
|
D:AddDebugText("No event in range at all for ", Unit, "or debuff:", debuffname, "latest found:", latestever);
|
|
else
|
|
D:AddDebugText(#foundcblevents / 2, "events for ", Unit, "or debuff:", debuffname, "Status:", Status, "Events:\n", unpack(foundcblevents));
|
|
end
|
|
end
|
|
--]===]
|
|
|
|
function MicroUnitF:OnLeave() -- {{{
|
|
D.Status.MouseOveringMUF = false;
|
|
--D:Debug("Micro unit Hidden");
|
|
DcrDisplay_Tooltip:Hide();
|
|
|
|
if (D.profile.DebuffsFrameShowHelp) then
|
|
GameTooltip:Hide();
|
|
end
|
|
end -- }}}
|
|
|
|
|
|
function D.MicroUnitF:OnCornerEnter(frame)
|
|
if (D.profile.DebuffsFrameShowHelp) then
|
|
D:DisplayGameTooltip(frame,
|
|
str_format(
|
|
"|cFF11FF11%s|r-|cFF11FF11%s|r: %s\n\n"..
|
|
--"|cFF11FF11%s|r: %s\n"..
|
|
"|cFF11FF11%s|r-|cFF11FF11%s|r: %s\n\n"..
|
|
"|cFF11FF11%s|r-|cFF11FF11%s|r: %s\n"..
|
|
"|cFF11FF11%s|r-|cFF11FF11%s|r: %s\n\n"..
|
|
"|cFF11FF11%s|r-|cFF11FF11%s|r: %s",
|
|
|
|
D.L["ALT"], D.L["HLP_LEFTCLICK"], D.L["HANDLEHELP"],
|
|
|
|
--D.L["HLP_RIGHTCLICK"], D.L["STR_OPTIONS"],
|
|
D.L["ALT"], D.L["HLP_RIGHTCLICK"], D.L["BINDING_NAME_DCRSHOWOPTION"],
|
|
|
|
D.L["CTRL"], D.L["HLP_LEFTCLICK"], D.L["BINDING_NAME_DCRPRSHOW"],
|
|
D.L["SHIFT"], D.L["HLP_LEFTCLICK"], D.L["BINDING_NAME_DCRSKSHOW"],
|
|
|
|
D.L["SHIFT"], D.L["HLP_RIGHTCLICK"], D.L["BINDING_NAME_DCRSHOW"]
|
|
));
|
|
end;
|
|
end
|
|
|
|
|
|
function MicroUnitF:OnLoad(frame) -- {{{
|
|
frame:SetScript("PreClick", self.OnPreClick);
|
|
frame:SetScript("PostClick", self.OnPostClick);
|
|
end
|
|
-- }}}
|
|
|
|
function MicroUnitF.OnPreClick(frame, Button) -- {{{
|
|
D:Debug("Micro unit Preclicked: ", Button);
|
|
|
|
local Unit = frame.Object.CurrUnit; -- shortcut
|
|
|
|
if (frame.Object.UnitStatus == NORMAL and (Button == "LeftButton" or Button == "RightButton")) then
|
|
|
|
D:Println(L["HLP_NOTHINGTOCURE"]);
|
|
|
|
elseif (frame.Object.UnitStatus == AFFLICTED) then
|
|
local NeededPrio = D:GiveSpellPrioNum(frame.Object.Debuffs[1].Type);
|
|
local RequestedPrio = false;
|
|
local ButtonsString = "";
|
|
|
|
if IsControlKeyDown() then
|
|
ButtonsString = "ctrl-";
|
|
elseif IsAltKeyDown() then
|
|
ButtonsString = "alt-";
|
|
elseif IsShiftKeyDown() then
|
|
ButtonsString = "shift-";
|
|
end
|
|
|
|
if Button == "LeftButton" then
|
|
ButtonsString = ButtonsString .. "%s1";
|
|
elseif Button == "RightButton" then
|
|
ButtonsString = ButtonsString .. "%s2";
|
|
end
|
|
|
|
RequestedPrio = D:tGiveValueIndex(D.db.global.AvailableButtons, ButtonsString);
|
|
|
|
if RequestedPrio and NeededPrio ~= RequestedPrio then
|
|
D:errln(L["HLP_WRONGMBUTTON"]);
|
|
if NeededPrio and MF_colors[NeededPrio] then
|
|
D:Println(L["HLP_USEXBUTTONTOCURE"], D:ColorText(DC.AvailableButtonsReadable[ D.db.global.AvailableButtons[NeededPrio] ], D:NumToHexColor(MF_colors[NeededPrio])));
|
|
--[===[@debug@
|
|
else
|
|
D:AddDebugText("Button wrong click info bug: NeededPrio:", NeededPrio, "Unit:", Unit, "RequestedPrio:", RequestedPrio, "Button clicked:", Button, "MF_colors:", unpack(MF_colors), "Debuff Type:", frame.Object.Debuffs[1].Type);
|
|
--@end-debug@]===]
|
|
end
|
|
|
|
|
|
elseif RequestedPrio and D.Status.HasSpell then
|
|
-- D:Print("XXX ClickedMF SET");
|
|
D.Status.ClickedMF = frame.Object; -- used to update the MUF on cast success and failure to know which unit is being cured
|
|
D.Status.ClickedMF.SPELL_CAST_SUCCESS = false;
|
|
D:Debuff_History_Add(frame.Object.Debuffs[1].Name, frame.Object.Debuffs[1].TypeName);
|
|
end
|
|
end
|
|
end -- }}}
|
|
|
|
-- }}}
|
|
|
|
-- }}}
|
|
|
|
|
|
|
|
-- MicroUnitF NON STATIC METHODS {{{
|
|
-- init a new micro frame (Call internally by :new() only)
|
|
function MicroUnitF.prototype:init(Container, Unit, FrameNum, ID) -- {{{
|
|
|
|
D:Debug("Initializing MicroUnit object", Unit, "with FrameNum=", FrameNum, " and ID", ID);
|
|
|
|
|
|
-- set object default variables
|
|
self.Parent = Container;
|
|
self.ID = ID; -- is set by te roaming updater
|
|
self.FrameNum = FrameNum;
|
|
self.ToPlace = true;
|
|
self.Debuffs = false;
|
|
self.Debuff1Prio = false;
|
|
self.PrevDebuff1Prio = false;
|
|
self.IsDebuffed = false;
|
|
self.CurrUnit = false;
|
|
self.UnitName = false;
|
|
self.UnitGUID = false;
|
|
self.UnitClass = false;
|
|
self.UnitStatus = 0;
|
|
self.FirstDebuffType = 0;
|
|
self.NormalAlpha = false;
|
|
self.BorderAlpha = false;
|
|
self.Color = {};
|
|
self.IsCharmed = false;
|
|
self.UpdateCountDown = 3;
|
|
self.LastAttribUpdate = 0;
|
|
self.LitTime = false;
|
|
self.Chrono = false;
|
|
self.PrevChrono = false;
|
|
self.Shown = false; -- Setting this to true will broke the stick to right option
|
|
self.UpdateCD = 0;
|
|
self.RaidTargetIcon = false;
|
|
self.PrevRaidTargetIndex= false;
|
|
|
|
-- create the frame
|
|
self.Frame = CreateFrame ("Button", "DcrMicroUnit"..Unit, self.Parent, "DcrMicroUnitTemplateSecure");
|
|
self.CooldownFrame = CreateFrame ("Cooldown", "DcrMicroUnitCD"..Unit, self.Frame, "DcrMicroUnitCDTemplate");
|
|
|
|
-- outer texture (the class border)
|
|
-- Bottom side
|
|
self.OuterTexture1 = self.Frame:CreateTexture("DcrMicroUnit"..Unit.."Bottom", "BORDER");
|
|
self.OuterTexture1:SetPoint("BOTTOMLEFT", self.Frame, "BOTTOMLEFT", 0, 0);
|
|
self.OuterTexture1:SetPoint("TOPRIGHT", self.Frame, "BOTTOMRIGHT", 0, 2);
|
|
|
|
-- left side
|
|
self.OuterTexture2 = self.Frame:CreateTexture("DcrMicroUnit"..Unit.."Left", "BORDER");
|
|
self.OuterTexture2:SetPoint("TOPLEFT", self.Frame, "TOPLEFT", 0, -2);
|
|
self.OuterTexture2:SetPoint("BOTTOMRIGHT", self.Frame, "BOTTOMLEFT", 2, 2);
|
|
|
|
-- top side
|
|
self.OuterTexture3 = self.Frame:CreateTexture("DcrMicroUnit"..Unit.."Top", "BORDER");
|
|
self.OuterTexture3:SetPoint("TOPLEFT", self.Frame, "TOPLEFT", 0, 0);
|
|
self.OuterTexture3:SetPoint("BOTTOMRIGHT", self.Frame, "TOPRIGHT", 0, -2);
|
|
|
|
-- right side
|
|
self.OuterTexture4 = self.Frame:CreateTexture("DcrMicroUnit"..Unit.."Right", "BORDER");
|
|
self.OuterTexture4:SetPoint("TOPRIGHT", self.Frame, "TOPRIGHT", 0, -2);
|
|
self.OuterTexture4:SetPoint("BOTTOMLEFT", self.Frame, "BOTTOMRIGHT", -2, 2);
|
|
|
|
|
|
-- global texture
|
|
self.Texture = self.Frame:CreateTexture("DcrMicroUnit"..Unit.."Back", "ARTWORK");
|
|
self.Texture:SetPoint("CENTER",self.Frame ,"CENTER",0,0)
|
|
self.Texture:SetHeight(16);
|
|
self.Texture:SetWidth(16);
|
|
|
|
-- inner Texture (Charmed special texture)
|
|
self.InnerTexture = self.Frame:CreateTexture("DcrMicroUnit"..Unit.."Charmed", "OVERLAY");
|
|
self.InnerTexture:SetPoint("CENTER",self.Frame ,"CENTER",0,0)
|
|
self.InnerTexture:SetHeight(7);
|
|
self.InnerTexture:SetWidth(7);
|
|
self.InnerTexture:SetTexture(unpack(MF_colors[CHARMED_STATUS]));
|
|
|
|
-- Chrono Font string
|
|
self.ChronoFontString = self.Frame:CreateFontString("DcrMicroUnit"..Unit.."Chrono", "ARTWORK", "DcrMicroUnitChronoFont");
|
|
self.ChronoFontString:SetTextColor(unpack(MF_colors["COLORCHRONOS"]));
|
|
|
|
-- raid target icon
|
|
self.RaidIconTexture = self.Frame:CreateTexture("DcrMicroUnit"..Unit.."RaidTargetIcon", "OVERLAY");
|
|
self.RaidIconTexture:SetPoint("CENTER",self.Frame ,"CENTER",0,8)
|
|
self.RaidIconTexture:SetHeight(13);
|
|
self.RaidIconTexture:SetWidth(13);
|
|
|
|
|
|
-- a reference to this object
|
|
self.Frame.Object = self;
|
|
|
|
-- register events
|
|
self.Frame:RegisterForClicks("AnyUp");
|
|
self.Frame:SetFrameStrata("MEDIUM");
|
|
|
|
-- set the frame attributes
|
|
self:UpdateAttributes(Unit);
|
|
|
|
-- once the MF frame is set up, schedule an event to show it
|
|
MicroUnitF:Delayed_MFsDisplay_Update();
|
|
end -- }}}
|
|
|
|
|
|
function MicroUnitF.prototype:Update(SkipSetColor, SkipDebuffs, CheckStealth)
|
|
|
|
local MF = self;
|
|
local ActionsDone = 0;
|
|
|
|
local Unit = MF.CurrUnit;
|
|
|
|
-- The unit is the same but the name isn't... (check for class change)
|
|
if MF.CurrUnit == Unit and D.Status.Unit_Array_UnitToGUID[self.CurrUnit] ~= self.UnitGUID then
|
|
if MF:SetClassBorder() then
|
|
ActionsDone = ActionsDone + 1; -- count expensive things done
|
|
end
|
|
-- if the guid changed we really need to rescan the unit!
|
|
SkipSetColor = false; SkipDebuffs = false; CheckStealth = true;
|
|
--[===[@debug@
|
|
D:Debug("|cFF00CC00MUF:Update(): Guid change rescanning", Unit, "|r");
|
|
--@end-debug@]===]
|
|
end
|
|
|
|
-- Update the frame attributes if necessary (Spells priority or unit id changes)
|
|
if (D.Status.SpellsChanged ~= MF.LastAttribUpdate ) then
|
|
--D:Debug("Attributes update required: ", MF.ID);
|
|
if (MF:UpdateAttributes(Unit, true)) then
|
|
ActionsDone = ActionsDone + 1; -- count expensive things done
|
|
SkipSetColor = false; SkipDebuffs = false; -- if some attributes were updated then update the rest
|
|
end
|
|
end
|
|
|
|
|
|
if (not SkipSetColor) then
|
|
if (not SkipDebuffs) then
|
|
-- get the manageable debuffs of this unit
|
|
MF:SetDebuffs();
|
|
D:Debug("Debuff set for ", MF.ID);
|
|
if CheckStealth then
|
|
D.Stealthed_Units[MF.CurrUnit] = D:CheckUnitStealth(MF.CurrUnit); -- update stealth status
|
|
-- D:Debug("MF:Update(): Stealth status checked as requested.");
|
|
end
|
|
end
|
|
|
|
if (MF:SetColor()) then
|
|
ActionsDone = ActionsDone + 1; -- count expensive things done
|
|
end
|
|
end
|
|
|
|
return ActionsDone;
|
|
end
|
|
|
|
|
|
function MicroUnitF.prototype:UpdateWithCS()
|
|
self:Update(false, false, true);
|
|
end
|
|
|
|
function MicroUnitF.prototype:UpdateSkippingSetBuf()
|
|
self:Update(false, true);
|
|
end
|
|
|
|
-- UPDATE attributes (Spells and Unit) {{{
|
|
|
|
|
|
|
|
do
|
|
-- used to tell if we changed something to improve performances.
|
|
-- Each attribute change trigger an event...
|
|
local ReturnValue = false;
|
|
-- this updates the sttributes of a MUF's frame object
|
|
function MicroUnitF.prototype:UpdateAttributes(Unit, DoNotDelay)
|
|
|
|
-- Delay the call if we are fighting
|
|
if InCombatLockdown() then
|
|
if not DoNotDelay then
|
|
D:AddDelayedFunctionCall (
|
|
"MicroUnit_" .. Unit, -- UID
|
|
self.UpdateAttributes, self, Unit); -- function call
|
|
end
|
|
return false;
|
|
end
|
|
|
|
ReturnValue = false;
|
|
|
|
-- if the unit is not set
|
|
if not self.CurrUnit then
|
|
self.Frame:SetAttribute("unit", Unit);
|
|
|
|
-- UnitToMUF[] can only be set when out of fight so it remains
|
|
-- coherent with what is displayed when groups are changed during a
|
|
-- fight
|
|
|
|
MicroUnitF.UnitToMUF[Unit] = self;
|
|
self.CurrUnit = Unit;
|
|
|
|
self:SetClassBorder();
|
|
|
|
-- set the return value because we did something expensive
|
|
ReturnValue = self;
|
|
end
|
|
|
|
if (D.Status.SpellsChanged == self.LastAttribUpdate) then
|
|
return ReturnValue; -- nothing changed
|
|
end
|
|
|
|
-- D:Debug("UpdateAttributes() executed");
|
|
|
|
if self.LastAttribUpdate == 0 then -- only once
|
|
-- set the mouse left-button actions on all modifiers
|
|
self.Frame:SetAttribute("type1", "macro");
|
|
self.Frame:SetAttribute("ctrl-type1", "macro");
|
|
self.Frame:SetAttribute("alt-type1", "macro");
|
|
self.Frame:SetAttribute("shift-type1", "macro");
|
|
|
|
-- set the mouse right-button actions on all modifiers
|
|
self.Frame:SetAttribute("type2", "macro");
|
|
self.Frame:SetAttribute("ctrl-type2", "macro");
|
|
self.Frame:SetAttribute("alt-type2", "macro");
|
|
self.Frame:SetAttribute("shift-type2", "macro");
|
|
|
|
-- set the mouse middle-button actions on all modifiers
|
|
self.Frame:SetAttribute("type3", "macro");
|
|
self.Frame:SetAttribute("ctrl-type3", "macro");
|
|
self.Frame:SetAttribute("alt-type3", "macro");
|
|
self.Frame:SetAttribute("shift-type3", "macro");
|
|
end
|
|
|
|
local AvailableButtons = D.db.global.AvailableButtons;
|
|
|
|
self.Frame:SetAttribute(str_format(AvailableButtons[#AvailableButtons - 1], "macrotext"), str_format("/target %s", Unit));
|
|
self.Frame:SetAttribute(str_format(AvailableButtons[#AvailableButtons ], "macrotext"), str_format("/focus %s", Unit));
|
|
|
|
-- set the spells attributes using the lookup tables above
|
|
for Spell, Prio in pairs(D.Status.CuringSpellsPrio) do
|
|
|
|
--the [target=%s, help][target=%s, harm] prevents the 'please select a unit' cursor problem (Blizzard should fix this...)
|
|
self.Frame:SetAttribute(str_format(AvailableButtons[Prio], "macrotext"), str_format("%s/cast [target=%s, help][target=%s, harm] %s%s",
|
|
((not D.Status.FoundSpells[Spell][1]) and "/stopcasting\n" or ""),
|
|
Unit,Unit,
|
|
Spell,
|
|
(DC.SpellsToUse[Spell].Rank and "(" .. (str_sub(DC.RANKNUMTRANS, '%d+', DC.SpellsToUse[Spell].Rank)) .. ")" or "") ));
|
|
|
|
|
|
--[[
|
|
D:Debug("XX-> macro: ",str_format(AvailableButtons[Prio], "macrotext"), str_format("%s/cast [target=%s, help][target=%s, harm] %s%s",
|
|
((not D.Status.FoundSpells[Spell][1]) and "/stopcasting\n" or ""),
|
|
Unit,Unit,
|
|
Spell,
|
|
(DC.SpellsToUse[Spell].Rank and "(" .. (str_sub(DC.RANKNUMTRANS, '%d+', DC.SpellsToUse[Spell].Rank)) .. ")" or "") ));
|
|
--]]
|
|
|
|
end
|
|
|
|
self.Debuff1Prio = false;
|
|
|
|
-- the update timestamp
|
|
self.LastAttribUpdate = D.Status.SpellsChanged;
|
|
return self;
|
|
end
|
|
end -- }}}
|
|
|
|
function MicroUnitF.prototype:SetDebuffs() -- {{{
|
|
self.Debuffs, self.IsCharmed = D:UnitCurableDebuffs(self.CurrUnit);
|
|
|
|
if D.UnitDebuffed[self.CurrUnit] then
|
|
D.ForLLDebuffedUnitsNum = D.ForLLDebuffedUnitsNum - 1;
|
|
end
|
|
|
|
if (self.Debuffs and self.Debuffs[1] and self.Debuffs[1].Type) then
|
|
--D:Debug("A debuff was found"); -- XXX
|
|
self.IsDebuffed = true;
|
|
self.Debuff1Prio = D:GiveSpellPrioNum( self.Debuffs[1].Type );
|
|
|
|
D.UnitDebuffed[self.CurrUnit] = true;
|
|
D.ForLLDebuffedUnitsNum = D.ForLLDebuffedUnitsNum + 1;
|
|
|
|
else
|
|
--D:Debug("No debuff found"); -- XXX
|
|
self.IsDebuffed = false;
|
|
self.Debuff1Prio = false;
|
|
self.PrevDebuff1Prio = false;
|
|
D.UnitDebuffed[self.CurrUnit] = false; -- used by the live-list only
|
|
end
|
|
end -- }}}
|
|
|
|
do
|
|
--[=[
|
|
-- This function is responsible for setting all the textures of a MUF object:
|
|
-- - The main color
|
|
-- - Showing/Hiding the charmed alert square
|
|
-- - The Alpha of the center and borders
|
|
-- This function also set the Status of the MUF that will be used in the tooltip
|
|
--]=]
|
|
local DebuffType, Unit, PreviousStatus, BorderAlpha, Class, ClassColor, ReturnValue, RangeStatus, Alpha, PrioChanged, PrevChrono, Time, Status;
|
|
local profile = {};
|
|
|
|
-- global access optimization
|
|
local IsSpellInRange = _G.IsSpellInRange;
|
|
local UnitClass = _G.UnitClass;
|
|
local UnitExists = _G.UnitExists;
|
|
local UnitIsVisible = _G.UnitIsVisible;
|
|
local UnitLevel = _G.UnitLevel;
|
|
local unpack = _G.unpack;
|
|
local select = _G.select;
|
|
local GetTime = _G.GetTime;
|
|
local floor = _G.math.floor;
|
|
local fmod = _G.math.fmod;
|
|
local CooldownFrame_SetTimer = _G.CooldownFrame_SetTimer;
|
|
local GetSpellCooldown = _G.GetSpellCooldown;
|
|
local GetRaidTargetIndex= _G.GetRaidTargetIndex;
|
|
local bor = _G.bit.bor;
|
|
|
|
function MicroUnitF.prototype:SetColor() -- {{{
|
|
|
|
profile = D.profile;
|
|
Status = D.Status;
|
|
|
|
-- register default alpha of the border
|
|
BorderAlpha = profile.DebuffsFrameElemBorderAlpha;
|
|
|
|
-- register local variables
|
|
DebuffType = false;
|
|
ReturnValue = false;
|
|
Unit = self.CurrUnit;
|
|
PreviousStatus = self.UnitStatus;
|
|
|
|
|
|
|
|
-- if unit not available, if a unit cease to exist (this happen often for pets)
|
|
if not UnitExists(Unit) then
|
|
if PreviousStatus ~= ABSENT then
|
|
self.Color = MF_colors[ABSENT];
|
|
self.UnitStatus = ABSENT;
|
|
if self.LitTime then
|
|
self.LitTime = false;
|
|
self.ChronoFontString:SetText(" ");
|
|
end
|
|
end
|
|
|
|
-- UnitIsVisible() behavior is not 100% reliable so we also use UnitLevel() that will return -1 when the Unit is too far...
|
|
elseif not UnitIsVisible(Unit) or UnitLevel(Unit) < 1 then
|
|
if PreviousStatus ~= FAR then
|
|
self.Color = MF_colors[FAR];
|
|
self.UnitStatus = FAR;
|
|
if self.LitTime then
|
|
self.LitTime = false;
|
|
self.ChronoFontString:SetText(" ");
|
|
|
|
end
|
|
end
|
|
|
|
else
|
|
-- If the Unit is invisible
|
|
if profile.Show_Stealthed_Status and D.Stealthed_Units[Unit] then
|
|
if PreviousStatus ~= STEALTHED then
|
|
self.Color = MF_colors[STEALTHED];
|
|
self.UnitStatus = STEALTHED;
|
|
if self.LitTime then
|
|
self.LitTime = false;
|
|
self.ChronoFontString:SetText(" ");
|
|
|
|
end
|
|
end
|
|
|
|
-- if unit is blacklisted
|
|
elseif Status.Blacklisted_Array[Unit] then
|
|
if PreviousStatus ~= BLACKLISTED then
|
|
self.Color = MF_colors[BLACKLISTED];
|
|
self.UnitStatus = BLACKLISTED;
|
|
if self.LitTime then
|
|
self.LitTime = false;
|
|
self.ChronoFontString:SetText(" ");
|
|
|
|
end
|
|
end
|
|
|
|
-- if the unit has some debuffs we can handle
|
|
elseif (self.IsDebuffed) then
|
|
DebuffType = self.Debuffs[1].Type;
|
|
|
|
if self.PrevDebuff1Prio ~= self.Debuff1Prio then
|
|
self.Color = MF_colors[self.Debuff1Prio];
|
|
self.PrevDebuff1Prio = self.Debuff1Prio;
|
|
PrioChanged = true;
|
|
end
|
|
|
|
-- Test if the spell we are going to use is in range
|
|
-- Some time can elaps between the instant the debuff is detected and the instant it is shown.
|
|
-- Between those instants, a reconfiguration can happen (pet dies or some spells become unavailable)
|
|
-- So we test before calling this api that we can still cure this debuff type
|
|
if Status.CuringSpells[DebuffType] then
|
|
RangeStatus = IsSpellInRange(Status.CuringSpells[DebuffType], Unit);
|
|
else
|
|
RangeStatus = false;
|
|
end
|
|
|
|
Time = GetTime();
|
|
|
|
if RangeStatus and self.UpdateCD < Status.UpdateCooldown then
|
|
CooldownFrame_SetTimer (self.CooldownFrame, GetSpellCooldown(Status.CuringSpells[DebuffType]) );
|
|
self.UpdateCD = Time;
|
|
end
|
|
|
|
-- update the chrono
|
|
if profile.DebuffsFrameChrono then
|
|
if self.LitTime then
|
|
PrevChrono = self.Chrono;
|
|
|
|
if not profile.DebuffsFrameTimeLeft then
|
|
self.Chrono = floor(Time - self.LitTime);
|
|
|
|
if self.Chrono ~= PrevChrono then
|
|
self.ChronoFontString:SetText( ((self.Chrono < 60) and self.Chrono or (floor(self.Chrono / 60) .. "\'") ));
|
|
end
|
|
else
|
|
self.Chrono = floor(self.Debuffs[1].expirationTime - Time);
|
|
|
|
if self.Chrono ~= PrevChrono then
|
|
self.ChronoFontString:SetText( ((self.Chrono < 60) and (self.Chrono + 1) or (floor(self.Chrono / 60 + 1) .. "\'") ));
|
|
end
|
|
end
|
|
else
|
|
self.LitTime = Time;
|
|
end
|
|
end
|
|
|
|
self.RaidTargetIcon = GetRaidTargetIndex(Unit);
|
|
if self.PrevRaidTargetIndex ~= self.RaidTargetIcon then
|
|
self.RaidIconTexture:SetTexture(self.RaidTargetIcon and DC.RAID_ICON_TEXTURE_LIST[self.RaidTargetIcon] or nil);
|
|
self.PrevRaidTargetIndex = self.RaidTargetIcon;
|
|
end
|
|
|
|
|
|
-- set the status according to RangeStatus
|
|
if (not RangeStatus or RangeStatus == 0) then
|
|
Alpha = 0.40;
|
|
self.UnitStatus = AFFLICTED_NIR;
|
|
else
|
|
Alpha = 1;
|
|
self.UnitStatus = AFFLICTED;
|
|
BorderAlpha = 1;
|
|
|
|
MicroUnitF.UnitsDebuffedInRange = MicroUnitF.UnitsDebuffedInRange + 1;
|
|
|
|
if (not Status.SoundPlayed) then
|
|
D:PlaySound (self.CurrUnit, "SetColor()" );
|
|
end
|
|
end
|
|
elseif PreviousStatus ~= NORMAL then
|
|
-- the unit has nothing special, set the status to normal
|
|
self.Color = MF_colors[NORMAL];
|
|
self.UnitStatus = NORMAL;
|
|
if self.LitTime then
|
|
self.LitTime = false;
|
|
self.ChronoFontString:SetText(" ");
|
|
end
|
|
|
|
if self.RaidTargetIcon then
|
|
self.RaidIconTexture:SetTexture(nil);
|
|
self.RaidTargetIcon = false;
|
|
self.PrevRaidTargetIndex = false;
|
|
end
|
|
|
|
-- if the previous status was FAR, trigger a full rescan of the unit (combat log event does not report events for far away units)
|
|
if PreviousStatus == FAR then
|
|
D.MicroUnitF:UpdateMUFUnit(self.CurrUnit, true); -- this is able to deal when a lot of update queries
|
|
end
|
|
end
|
|
end
|
|
|
|
if PreviousStatus == AFFLICTED or PreviousStatus == AFFLICTED_AND_CHARMED then
|
|
MicroUnitF.UnitsDebuffedInRange = MicroUnitF.UnitsDebuffedInRange - 1;
|
|
|
|
if MicroUnitF.UnitsDebuffedInRange == 0 and profile.Hide_LiveList then
|
|
D:Debug("SetColor(): No more unit, sound re-enabled");
|
|
Status.SoundPlayed = false;
|
|
end
|
|
end
|
|
|
|
if not profile.DebuffsFrameElemBorderShow then
|
|
BorderAlpha = 0;
|
|
end
|
|
|
|
|
|
-- set the class border color when needed (the class is unknown and the unit exists or the unit name changed)
|
|
--self:SetClassBorder();
|
|
|
|
-- set the alpha of the border if necessary
|
|
if self.BorderAlpha ~= BorderAlpha then
|
|
self.OuterTexture1:SetAlpha(BorderAlpha);
|
|
self.OuterTexture2:SetAlpha(BorderAlpha);
|
|
self.OuterTexture3:SetAlpha(BorderAlpha);
|
|
self.OuterTexture4:SetAlpha(BorderAlpha);
|
|
|
|
self.BorderAlpha = BorderAlpha;
|
|
|
|
-- set this to true because we just did something expensive...
|
|
ReturnValue = true;
|
|
--D:Debug("border alpha set");
|
|
end
|
|
|
|
|
|
-- Add the charm status to the bitfield (note that it's treated separatly because it's shown even if the unit is not afflicetd by anything we can cure)
|
|
if self.IsCharmed then
|
|
self.UnitStatus = bor(self.UnitStatus, CHARMED_STATUS);
|
|
end
|
|
|
|
-- if the unit is not afflicted or too far set the color to a lower alpha
|
|
if not DebuffType then -- if DebuffType was not set, it means that the unit is too far
|
|
Alpha = self.Color[4] * profile.DebuffsFrameElemAlpha;
|
|
self.PrevDebuff1Prio = false;
|
|
end
|
|
|
|
|
|
-- Apply the colors and alphas only if necessary
|
|
-- The MUF status changed
|
|
-- The user changed the defaultAlpha
|
|
-- The priority (and thus the color) of the first affliction changed
|
|
if (self.UnitStatus ~= PreviousStatus or self.NormalAlpha ~= profile.DebuffsFrameElemAlpha or PrioChanged) then-- or self.FirstDebuffType ~= DebuffType) then
|
|
|
|
if PrioChanged then PrioChanged = false; end
|
|
|
|
-- Set the main texture
|
|
self.Texture:SetTexture(self.Color[1], self.Color[2], self.Color[3], Alpha);
|
|
--self.Texture:SetAlpha(Alpha);
|
|
|
|
|
|
|
|
-- Show the charmed alert square
|
|
if self.IsCharmed then
|
|
self.InnerTexture:Show();
|
|
else
|
|
self.InnerTexture:Hide();
|
|
end
|
|
|
|
--D:Debug("Color Applied, MUF Status:", self.UnitStatus);
|
|
|
|
|
|
-- save the current global status
|
|
self.NormalAlpha = profile.DebuffsFrameElemAlpha;
|
|
self.FirstDebuffType = DebuffType;
|
|
|
|
-- set this to true because we just did something expensive...
|
|
ReturnValue = true;
|
|
end
|
|
|
|
return ReturnValue;
|
|
|
|
end -- }}}
|
|
|
|
function MicroUnitF.prototype:SetClassBorder()
|
|
--D:Debug("SetClassBorder called ", D.Status.Unit_Array_UnitToGUID[self.CurrUnit] , self.UnitGUID);
|
|
ReturnValue = false;
|
|
if (D.profile.DebuffsFrameElemBorderShow and (D.Status.Unit_Array_UnitToGUID[self.CurrUnit] ~= self.UnitGUID or (not self.UnitClass and UnitExists(self.CurrUnit)))) then
|
|
|
|
-- Get the GUID of this unit
|
|
self.UnitGUID = D.Status.Unit_Array_UnitToGUID[self.CurrUnit];
|
|
|
|
if self.UnitGUID then -- can be nil because of focus...
|
|
-- Get its class
|
|
Class = (select(2, UnitClass(self.CurrUnit)));
|
|
else
|
|
Class = false;
|
|
end
|
|
|
|
-- if the class changed
|
|
if (Class and Class ~= self.UnitClass) then
|
|
ClassColor = DC.ClassesColors[Class];
|
|
-- update the border color (the four borders)
|
|
self.OuterTexture1:SetTexture( unpack(ClassColor) );
|
|
self.OuterTexture2:SetTexture( unpack(ClassColor) );
|
|
self.OuterTexture3:SetTexture( unpack(ClassColor) );
|
|
self.OuterTexture4:SetTexture( unpack(ClassColor) );
|
|
|
|
-- save the class for futur reference
|
|
self.UnitClass = Class;
|
|
|
|
-- set this to true because we just did something expensive...
|
|
ReturnValue = true;
|
|
|
|
--D:Debug("Class '%s' set for '%s'", Class, self.CurrUnit);
|
|
elseif not Class and self.UnitClass then
|
|
-- if the class is not available, set it to false so this test will be done again and again until a class is found
|
|
self.UnitClass = false;
|
|
BorderAlpha = 0;
|
|
self.OuterTexture1:SetAlpha(BorderAlpha);
|
|
self.OuterTexture2:SetAlpha(BorderAlpha);
|
|
self.OuterTexture3:SetAlpha(BorderAlpha);
|
|
self.OuterTexture4:SetAlpha(BorderAlpha);
|
|
|
|
self.BorderAlpha = BorderAlpha;
|
|
|
|
ReturnValue = true;
|
|
--D:Debug("Class of unit %s is Nil", self.CurrUnit);
|
|
end
|
|
end
|
|
return ReturnValue;
|
|
|
|
end
|
|
|
|
end
|
|
-- }}}
|
|
|
|
do
|
|
local MicroFrameUpdateIndex = 1; -- MUFs are not updated all together
|
|
local NumToShow, ActionsDone, Unit, MF, pass, UnitNum;
|
|
-- updates the micro frames if needed (called regularly by ACE event, changed in the option menu)
|
|
function D:DebuffsFrame_Update() -- {{{
|
|
|
|
local Unit_Array = self.Status.Unit_Array;
|
|
local UnitToGUID = self.Status.Unit_Array_UnitToGUID;
|
|
|
|
UnitNum = self.Status.UnitNum; -- we need to go through all the units to set MF.ID properly
|
|
NumToShow = ((MicroUnitF.MaxUnit > UnitNum) and UnitNum or MicroUnitF.MaxUnit);
|
|
|
|
ActionsDone = 0; -- used to limit the maximum number of consecutive UI actions
|
|
|
|
|
|
-- we don't check all the MUF at each call, only some of them (changed in the options)
|
|
for pass = 1, self.profile.DebuffsFramePerUPdate do
|
|
|
|
-- When all frames have been updated, go back to the first
|
|
if (MicroFrameUpdateIndex > UnitNum) then
|
|
MicroFrameUpdateIndex = 1;
|
|
-- self:Debug("last micro frame updated,,:: %d", #self.Status.Unit_Array);
|
|
end
|
|
|
|
-- get a unit
|
|
Unit = Unit_Array[MicroFrameUpdateIndex];
|
|
|
|
-- should never fire unless the player choosed to ignore everything or something is wrong somewhere in the code
|
|
if not Unit then
|
|
--self:Debug("Unit is nil :/");
|
|
return false;
|
|
end
|
|
|
|
-- get its MUF
|
|
MF = MicroUnitF.ExistingPerUNIT[Unit];
|
|
|
|
-- if no MUF then create it (All MUFs are created here)
|
|
if (not MF) then
|
|
if not InCombatLockdown() then
|
|
MF = MicroUnitF:Create(Unit, MicroFrameUpdateIndex);
|
|
ActionsDone = ActionsDone + 1;
|
|
end
|
|
end
|
|
|
|
-- place the MUF ~right where it belongs~
|
|
if MF and MF.ToPlace ~= MicroFrameUpdateIndex and not InCombatLockdown() then
|
|
|
|
--sanity check
|
|
--[[
|
|
if MicroFrameUpdateIndex ~= MF.ID then -- XXX to remove for release
|
|
D:AddDebugText("DebuffsFrame_Update(): MicroFrameUpdateIndex ~= MF.ID", MicroFrameUpdateIndex, MF.ID, Unit, MF.CurrUnit, "ToPlace:", MF.ToPlace);
|
|
end
|
|
--]]
|
|
|
|
MF.ToPlace = MicroFrameUpdateIndex;
|
|
|
|
MF.Frame:SetPoint(unpack(MicroUnitF:GiveMFAnchor(MicroFrameUpdateIndex)));
|
|
if MF.Shown then
|
|
MF.Frame:Show();
|
|
end
|
|
|
|
-- test for GUID change and force a debuff update in this case
|
|
if UnitToGUID[MF.CurrUnit] ~= MF.UnitGUID then
|
|
MF.UpdateCountDown = 0; -- will force MF:Update() to be called
|
|
--[===[@debug@
|
|
D:Println("|cFFFFAA55GUID change detected while placing for |r", MicroFrameUpdateIndex, UnitToGUID[MF.CurrUnit], MF.UnitGUID );
|
|
--@end-debug@]===]
|
|
end
|
|
|
|
ActionsDone = ActionsDone + 1;
|
|
end
|
|
|
|
-- update the MUF attributes and its colors -- this is done by an event handler now (buff/debuff received...) except when the unit has a debuff and is in range
|
|
if MF and MicroFrameUpdateIndex <= NumToShow then
|
|
if not (MF.IsDebuffed or MF.IsCharmed) and MF.UpdateCountDown ~= 0 then
|
|
MF.UpdateCountDown = MF.UpdateCountDown - 1;
|
|
else -- if MF.IsDebuffed or MF.IsCharmed or MF.UpdateCountDown == 0
|
|
ActionsDone = ActionsDone + MF:Update(false, true);--, not ((MF.IsDebuffed or MF.IsCharmed) and MF.UnitStatus ~= AFFLICTED)); -- we rescan debuffs if the unit is not in spell range XXX useless now since we rescan everyone every second
|
|
MF.UpdateCountDown = 3;
|
|
end
|
|
end
|
|
|
|
-- we are done for this frame, go to te next
|
|
MicroFrameUpdateIndex = MicroFrameUpdateIndex + 1;
|
|
|
|
-- don't update more than 5 MUF in a row
|
|
-- don't loop when reaching the end, wait for the next call (useful when less MUFs than PerUpdate)
|
|
if (ActionsDone > 5 or pass == UnitNum) then
|
|
--self:Debug("Max actions count reached");
|
|
break;
|
|
end
|
|
|
|
end
|
|
-- end
|
|
end -- }}}
|
|
end
|
|
|
|
-- This little function returns the priority of the spell corresponding to an affliction type (one spell can be used for several types)
|
|
function D:GiveSpellPrioNum (Type) -- {{{
|
|
return D.Status.CuringSpellsPrio[D.Status.CuringSpells[Type]];
|
|
end -- }}}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- old unused variables and functions
|
|
-- UNUSED STUFF {{{
|
|
-- Micro Frame Events, useless for now
|
|
|
|
function MicroUnitF:OnPostClick(frame, button)
|
|
-- D:Debug("Micro unit PostClicked");
|
|
end
|
|
|
|
function MicroUnitF:OnAttributeChanged(self, name, value)
|
|
D:Debug("Micro unit", name, "AttributeChanged to", value);
|
|
end
|
|
|
|
|
|
local MUF_Status = { -- unused
|
|
[1] = "normal";
|
|
[2] = "absent";
|
|
[3] = "far";
|
|
[4] = "stealthed";
|
|
[5] = "blacklist";
|
|
[6] = "afflicted";
|
|
[7] = "afflicted-far";
|
|
[8] = "afflicted-charmed";
|
|
[9] = "afflicted-charmed-far";
|
|
}
|
|
|
|
|
|
local MF_Textures = { -- unused
|
|
"Interface/AddOns/Decursive/Textures/BackDrop-red", -- red
|
|
"Interface/AddOns/Decursive/Textures/BackDrop-blue", -- blue
|
|
"Interface/AddOns/Decursive/Textures/BackDrop-orange", -- orange
|
|
["grey"] = "Interface\\AddOns\\Decursive\\Textures\\BackDrop-grey-medium",
|
|
["black"] = "Interface/AddOns/Decursive/Textures/BackDrop",
|
|
};
|
|
|
|
|
|
-- }}}
|
|
|
|
T._LoadedFiles["Dcr_DebuffsFrame.lua"] = "2.5.1-6-gd3885c5";
|
|
|
|
-- Heresy
|