diff --git a/Libs/DF/button.lua b/Libs/DF/button.lua index dc3653cf..dd69d21e 100644 --- a/Libs/DF/button.lua +++ b/Libs/DF/button.lua @@ -876,6 +876,9 @@ local ButtonMetaFunctions = _G [DF.GlobalWidgetControlNames ["button"]] local x, y = GetCursorPosition() x = _math_floor (x) y = _math_floor (y) + + button.mouse_down = button.mouse_down or 0 --avoid issues when the button was pressed while disabled and release when enabled + if ( (x == button.x and y == button.y) or (button.mouse_down+0.5 > GetTime() and button:IsMouseOver()) @@ -892,6 +895,15 @@ local ButtonMetaFunctions = _G [DF.GlobalWidgetControlNames ["button"]] function ButtonMetaFunctions:SetTemplate (template) + if (type (template) == "string") then + template = DF:GetTemplate ("button", template) + end + + if (not template) then + DF:Error ("template not found") + return + end + if (template.width) then self:SetWidth (template.width) end diff --git a/Libs/DF/cooltip.lua b/Libs/DF/cooltip.lua index a7626ac0..0fcb5109 100644 --- a/Libs/DF/cooltip.lua +++ b/Libs/DF/cooltip.lua @@ -1652,9 +1652,9 @@ function DF:CreateCoolTip() if (CoolTip.Type == 2) then --> with bars if (CoolTip.OptionsTable.MinWidth) then local w = frame1.w + 34 - frame1:SetWidth (math.max (w, CoolTip.OptionsTable.MinWidth)) + PixelUtil.SetWidth (frame1, math.max (w, CoolTip.OptionsTable.MinWidth)) else - frame1:SetWidth (frame1.w + 34) + PixelUtil.SetWidth (frame1, frame1.w + 34) end else --> width stability check @@ -1666,22 +1666,24 @@ function DF:CreateCoolTip() end if (CoolTip.OptionsTable.MinWidth) then - frame1:SetWidth (math.max (width, CoolTip.OptionsTable.MinWidth)) + PixelUtil.SetWidth (frame1, math.max (width, CoolTip.OptionsTable.MinWidth)) else - frame1:SetWidth (width) + PixelUtil.SetWidth (frame1, width) end end end if (CoolTip.OptionsTable.FixedHeight) then - frame1:SetHeight (CoolTip.OptionsTable.FixedHeight) + PixelUtil.SetHeight (frame1, CoolTip.OptionsTable.FixedHeight) else if (CoolTip.OptionsTable.AlignAsBlizzTooltip) then - frame1:SetHeight ( ((temp-10) * -1) + (CoolTip.OptionsTable.AlignAsBlizzTooltipFrameHeightOffset or 0)) + PixelUtil.SetHeight (frame1, ((temp-10) * -1) + (CoolTip.OptionsTable.AlignAsBlizzTooltipFrameHeightOffset or 0)) + elseif (CoolTip.OptionsTable.IgnoreButtonAutoHeight) then - frame1:SetHeight ( (temp+spacing) * -1) + PixelUtil.SetHeight (frame1, (temp+spacing) * -1) + else - frame1:SetHeight ( _math_max ( (frame1.hHeight * CoolTip.Indexes) + 8 + ((CoolTip.OptionsTable.ButtonsYMod or 0)*-1), 22 )) + PixelUtil.SetHeight (frame1, _math_max ( (frame1.hHeight * CoolTip.Indexes) + 8 + ((CoolTip.OptionsTable.ButtonsYMod or 0)*-1), 22 )) end end @@ -1922,7 +1924,8 @@ function DF:CreateCoolTip() local anchor = CoolTip.OptionsTable.Anchor or CoolTip.Host - frame1:SetPoint (CoolTip.OptionsTable.MyAnchor, anchor, CoolTip.OptionsTable.RelativeAnchor, 0 + moveX + CoolTip.OptionsTable.WidthAnchorMod, 10 + CoolTip.OptionsTable.HeightAnchorMod + moveY) + --frame1:SetPoint (CoolTip.OptionsTable.MyAnchor, anchor, CoolTip.OptionsTable.RelativeAnchor, 0 + moveX + CoolTip.OptionsTable.WidthAnchorMod, 10 + CoolTip.OptionsTable.HeightAnchorMod + moveY) + PixelUtil.SetPoint (frame1, CoolTip.OptionsTable.MyAnchor, anchor, CoolTip.OptionsTable.RelativeAnchor, 0 + moveX + CoolTip.OptionsTable.WidthAnchorMod, 10 + CoolTip.OptionsTable.HeightAnchorMod + moveY) if (not x_mod) then --> check if cooltip is out of screen bounds diff --git a/Libs/DF/fw.lua b/Libs/DF/fw.lua index 6a4952b3..ab74c4bf 100644 --- a/Libs/DF/fw.lua +++ b/Libs/DF/fw.lua @@ -1,5 +1,5 @@ -local dversion = 126 +local dversion = 131 local major, minor = "DetailsFramework-1.0", dversion local DF, oldminor = LibStub:NewLibrary (major, minor) @@ -391,6 +391,17 @@ function DF:SetFontColor (fontString, r, g, b, a) fontString:SetTextColor (r, g, b, a) end +function DF:SetFontShadow (fontString, r, g, b, a, x, y) + r, g, b, a = DF:ParseColors (r, g, b, a) + fontString:SetShadowColor (r, g, b, a) + + local offSetX, offSetY = fontString:GetShadowOffset() + x = x or offSetX + y = y or offSetY + + fontString:SetShadowOffset (x, y) +end + function DF:AddClassColorToText (text, class) if (type (class) ~= "string") then return DF:RemoveRealName (text) @@ -705,6 +716,33 @@ end return true end + + local colorTableMixin = { + GetColor = function (self) + return self.r, self.g, self.b, self.a + end, + + SetColor = function (self, r, g, b, a) + r, g, b, a = DF:ParseColors (r, g, b, a) + self.r = r or self.r + self.g = g or self.g + self.b = b or self.b + self.a = a or self.a + end, + + IsColorTable = true, + } + + function DF:CreateColorTable (r, g, b, a) + local t = { + r = r or 1, + g = g or 1, + b = b or 1, + a = a or 1, + } + DF:Mixin (t, colorTableMixin) + return t + end function DF:IsHtmlColor (color) return DF.alias_text_colors [color] @@ -713,8 +751,12 @@ end local tn = tonumber function DF:ParseColors (_arg1, _arg2, _arg3, _arg4) if (_type (_arg1) == "table") then - if (not _arg1[1] and _arg1.r) then + if (_arg1.IsColorTable) then + return _arg1:GetColor() + + elseif (not _arg1[1] and _arg1.r) then _arg1, _arg2, _arg3, _arg4 = _arg1.r, _arg1.g, _arg1.b, _arg1.a + else _arg1, _arg2, _arg3, _arg4 = _unpack (_arg1) end @@ -869,7 +911,7 @@ end end if (value_change_hook) then - slider:SetHook ("OnValueChanged", value_change_hook) + slider:SetHook ("OnValueChange", value_change_hook) end --> hook list @@ -1483,6 +1525,10 @@ function DF:SetHook (hookType, func) end end +function DF:Error (errortext) + print ("|cFFFF2222Details! Framework Error|r:", errortext, self.GetName and self:GetName(), self.WidgetType, debugstack (2, 3, 0)) +end + ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ --> members @@ -2116,16 +2162,16 @@ function DF:CreateBorder (parent, alpha1, alpha2, alpha3) parent.SetLayerVisibility = SetLayerVisibility local border1 = parent:CreateTexture (nil, "background") - border1:SetPoint ("topleft", parent, "topleft", -1, 1) - border1:SetPoint ("bottomleft", parent, "bottomleft", -1, -1) + PixelUtil.SetPoint (border1, "topleft", parent, "topleft", -1, 1) + PixelUtil.SetPoint (border1, "bottomleft", parent, "bottomleft", -1, -1) border1:SetColorTexture (0, 0, 0, alpha1 or default_border_color1) local border2 = parent:CreateTexture (nil, "background") - border2:SetPoint ("topleft", parent, "topleft", -2, 2) - border2:SetPoint ("bottomleft", parent, "bottomleft", -2, -2) + PixelUtil.SetPoint (border2, "topleft", parent, "topleft", -2, 2) + PixelUtil.SetPoint (border2, "bottomleft", parent, "bottomleft", -2, -2) border2:SetColorTexture (0, 0, 0, alpha2 or default_border_color2) local border3 = parent:CreateTexture (nil, "background") - border3:SetPoint ("topleft", parent, "topleft", -3, 3) - border3:SetPoint ("bottomleft", parent, "bottomleft", -3, -3) + PixelUtil.SetPoint (border3, "topleft", parent, "topleft", -3, 3) + PixelUtil.SetPoint (border3, "bottomleft", parent, "bottomleft", -3, -3) border3:SetColorTexture (0, 0, 0, alpha3 or default_border_color3) tinsert (parent.Borders.Layer1, border1) @@ -2133,16 +2179,16 @@ function DF:CreateBorder (parent, alpha1, alpha2, alpha3) tinsert (parent.Borders.Layer3, border3) local border1 = parent:CreateTexture (nil, "background") - border1:SetPoint ("topleft", parent, "topleft", 0, 1) - border1:SetPoint ("topright", parent, "topright", 1, 1) + PixelUtil.SetPoint (border1, "topleft", parent, "topleft", 0, 1) + PixelUtil.SetPoint (border1, "topright", parent, "topright", 1, 1) border1:SetColorTexture (0, 0, 0, alpha1 or default_border_color1) local border2 = parent:CreateTexture (nil, "background") - border2:SetPoint ("topleft", parent, "topleft", -1, 2) - border2:SetPoint ("topright", parent, "topright", 2, 2) + PixelUtil.SetPoint (border2, "topleft", parent, "topleft", -1, 2) + PixelUtil.SetPoint (border2, "topright", parent, "topright", 2, 2) border2:SetColorTexture (0, 0, 0, alpha2 or default_border_color2) local border3 = parent:CreateTexture (nil, "background") - border3:SetPoint ("topleft", parent, "topleft", -2, 3) - border3:SetPoint ("topright", parent, "topright", 3, 3) + PixelUtil.SetPoint (border3, "topleft", parent, "topleft", -2, 3) + PixelUtil.SetPoint (border3, "topright", parent, "topright", 3, 3) border3:SetColorTexture (0, 0, 0, alpha3 or default_border_color3) tinsert (parent.Borders.Layer1, border1) @@ -2150,16 +2196,16 @@ function DF:CreateBorder (parent, alpha1, alpha2, alpha3) tinsert (parent.Borders.Layer3, border3) local border1 = parent:CreateTexture (nil, "background") - border1:SetPoint ("topright", parent, "topright", 1, 0) - border1:SetPoint ("bottomright", parent, "bottomright", 1, -1) + PixelUtil.SetPoint (border1, "topright", parent, "topright", 1, 0) + PixelUtil.SetPoint (border1, "bottomright", parent, "bottomright", 1, -1) border1:SetColorTexture (0, 0, 0, alpha1 or default_border_color1) local border2 = parent:CreateTexture (nil, "background") - border2:SetPoint ("topright", parent, "topright", 2, 1) - border2:SetPoint ("bottomright", parent, "bottomright", 2, -2) + PixelUtil.SetPoint (border2, "topright", parent, "topright", 2, 1) + PixelUtil.SetPoint (border2, "bottomright", parent, "bottomright", 2, -2) border2:SetColorTexture (0, 0, 0, alpha2 or default_border_color2) local border3 = parent:CreateTexture (nil, "background") - border3:SetPoint ("topright", parent, "topright", 3, 2) - border3:SetPoint ("bottomright", parent, "bottomright", 3, -3) + PixelUtil.SetPoint (border3, "topright", parent, "topright", 3, 2) + PixelUtil.SetPoint (border3, "bottomright", parent, "bottomright", 3, -3) border3:SetColorTexture (0, 0, 0, alpha3 or default_border_color3) tinsert (parent.Borders.Layer1, border1) @@ -2167,16 +2213,16 @@ function DF:CreateBorder (parent, alpha1, alpha2, alpha3) tinsert (parent.Borders.Layer3, border3) local border1 = parent:CreateTexture (nil, "background") - border1:SetPoint ("bottomleft", parent, "bottomleft", 0, -1) - border1:SetPoint ("bottomright", parent, "bottomright", 0, -1) + PixelUtil.SetPoint (border1, "bottomleft", parent, "bottomleft", 0, -1) + PixelUtil.SetPoint (border1, "bottomright", parent, "bottomright", 0, -1) border1:SetColorTexture (0, 0, 0, alpha1 or default_border_color1) local border2 = parent:CreateTexture (nil, "background") - border2:SetPoint ("bottomleft", parent, "bottomleft", -1, -2) - border2:SetPoint ("bottomright", parent, "bottomright", 1, -2) + PixelUtil.SetPoint (border2, "bottomleft", parent, "bottomleft", -1, -2) + PixelUtil.SetPoint (border2, "bottomright", parent, "bottomright", 1, -2) border2:SetColorTexture (0, 0, 0, alpha2 or default_border_color2) local border3 = parent:CreateTexture (nil, "background") - border3:SetPoint ("bottomleft", parent, "bottomleft", -2, -3) - border3:SetPoint ("bottomright", parent, "bottomright", 2, -3) + PixelUtil.SetPoint (border3, "bottomleft", parent, "bottomleft", -2, -3) + PixelUtil.SetPoint (border3, "bottomright", parent, "bottomright", 2, -3) border3:SetColorTexture (0, 0, 0, alpha3 or default_border_color3) tinsert (parent.Borders.Layer1, border1) @@ -2185,6 +2231,9 @@ function DF:CreateBorder (parent, alpha1, alpha2, alpha3) end +function DF:CreateBorderSolid (parent, size) + +end function DF:CreateBorderWithSpread (parent, alpha1, alpha2, alpha3, size, spread) @@ -2201,24 +2250,28 @@ function DF:CreateBorderWithSpread (parent, alpha1, alpha2, alpha3, size, spread parent.SetBorderColor = SetBorderColor parent.SetLayerVisibility = SetLayerVisibility + size = size or 1 + local minPixels = 1 + local spread = 0 + --left local border1 = parent:CreateTexture (nil, "background") - border1:SetPoint ("topleft", parent, "topleft", -1 + spread, 1 + (-spread)) - border1:SetPoint ("bottomleft", parent, "bottomleft", -1 + spread, -1 + spread) border1:SetColorTexture (0, 0, 0, alpha1 or default_border_color1) - border1:SetWidth (size) + PixelUtil.SetPoint (border1, "topleft", parent, "topleft", -1 + spread, 1 + (-spread), 0, 0) + PixelUtil.SetPoint (border1, "bottomleft", parent, "bottomleft", -1 + spread, -1 + spread, 0, 0) + PixelUtil.SetWidth (border1, size, minPixels) local border2 = parent:CreateTexture (nil, "background") - border2:SetPoint ("topleft", parent, "topleft", -2 + spread, 2 + (-spread)) - border2:SetPoint ("bottomleft", parent, "bottomleft", -2 + spread, -2 + spread) + PixelUtil.SetPoint (border2, "topleft", parent, "topleft", -2 + spread, 2 + (-spread)) + PixelUtil.SetPoint (border2, "bottomleft", parent, "bottomleft", -2 + spread, -2 + spread) border2:SetColorTexture (0, 0, 0, alpha2 or default_border_color2) - border2:SetWidth (size) + PixelUtil.SetWidth (border2, size, minPixels) local border3 = parent:CreateTexture (nil, "background") - border3:SetPoint ("topleft", parent, "topleft", -3 + spread, 3 + (-spread)) - border3:SetPoint ("bottomleft", parent, "bottomleft", -3 + spread, -3 + spread) + PixelUtil.SetPoint (border3, "topleft", parent, "topleft", -3 + spread, 3 + (-spread)) + PixelUtil.SetPoint (border3, "bottomleft", parent, "bottomleft", -3 + spread, -3 + spread) border3:SetColorTexture (0, 0, 0, alpha3 or default_border_color3) - border3:SetWidth (size) + PixelUtil.SetWidth (border3, size, minPixels) tinsert (parent.Borders.Layer1, border1) tinsert (parent.Borders.Layer2, border2) @@ -2226,22 +2279,22 @@ function DF:CreateBorderWithSpread (parent, alpha1, alpha2, alpha3, size, spread --top local border1 = parent:CreateTexture (nil, "background") - border1:SetPoint ("topleft", parent, "topleft", 0 + spread, 1 + (-spread)) - border1:SetPoint ("topright", parent, "topright", 1 + (-spread), 1 + (-spread)) + PixelUtil.SetPoint (border1, "topleft", parent, "topleft", 0 + spread, 1 + (-spread)) + PixelUtil.SetPoint (border1, "topright", parent, "topright", 1 + (-spread), 1 + (-spread)) border1:SetColorTexture (0, 0, 0, alpha1 or default_border_color1) - border1:SetHeight (size) + PixelUtil.SetHeight (border1, size, minPixels) local border2 = parent:CreateTexture (nil, "background") - border2:SetPoint ("topleft", parent, "topleft", -1 + spread, 2 + (-spread)) - border2:SetPoint ("topright", parent, "topright", 2 + (-spread), 2 + (-spread)) + PixelUtil.SetPoint (border2, "topleft", parent, "topleft", -1 + spread, 2 + (-spread)) + PixelUtil.SetPoint (border2, "topright", parent, "topright", 2 + (-spread), 2 + (-spread)) border2:SetColorTexture (0, 0, 0, alpha2 or default_border_color2) - border2:SetHeight (size) + PixelUtil.SetHeight (border2, size, minPixels) local border3 = parent:CreateTexture (nil, "background") - border3:SetPoint ("topleft", parent, "topleft", -2 + spread, 3 + (-spread)) - border3:SetPoint ("topright", parent, "topright", 3 + (-spread), 3 + (-spread)) + PixelUtil.SetPoint (border3, "topleft", parent, "topleft", -2 + spread, 3 + (-spread)) + PixelUtil.SetPoint (border3, "topright", parent, "topright", 3 + (-spread), 3 + (-spread)) border3:SetColorTexture (0, 0, 0, alpha3 or default_border_color3) - border3:SetHeight (size) + PixelUtil.SetHeight (border3, size, minPixels) tinsert (parent.Borders.Layer1, border1) tinsert (parent.Borders.Layer2, border2) @@ -2249,44 +2302,44 @@ function DF:CreateBorderWithSpread (parent, alpha1, alpha2, alpha3, size, spread --right local border1 = parent:CreateTexture (nil, "background") - border1:SetPoint ("topright", parent, "topright", 1 + (-spread), 0 + (-spread)) - border1:SetPoint ("bottomright", parent, "bottomright", 1 + (-spread), -1 + spread) + PixelUtil.SetPoint (border1, "topright", parent, "topright", 1 + (-spread), 0 + (-spread)) + PixelUtil.SetPoint (border1, "bottomright", parent, "bottomright", 1 + (-spread), -1 + spread) border1:SetColorTexture (0, 0, 0, alpha1 or default_border_color1) - border1:SetWidth (size) + PixelUtil.SetWidth (border1, size, minPixels) local border2 = parent:CreateTexture (nil, "background") - border2:SetPoint ("topright", parent, "topright", 2 + (-spread), 1 + (-spread)) - border2:SetPoint ("bottomright", parent, "bottomright", 2 + (-spread), -2 + spread) + PixelUtil.SetPoint (border2, "topright", parent, "topright", 2 + (-spread), 1 + (-spread)) + PixelUtil.SetPoint (border2, "bottomright", parent, "bottomright", 2 + (-spread), -2 + spread) border2:SetColorTexture (0, 0, 0, alpha2 or default_border_color2) - border2:SetWidth (size) + PixelUtil.SetWidth (border2, size, minPixels) local border3 = parent:CreateTexture (nil, "background") - border3:SetPoint ("topright", parent, "topright", 3 + (-spread), 2 + (-spread)) - border3:SetPoint ("bottomright", parent, "bottomright", 3 + (-spread), -3 + spread) + PixelUtil.SetPoint (border3, "topright", parent, "topright", 3 + (-spread), 2 + (-spread)) + PixelUtil.SetPoint (border3, "bottomright", parent, "bottomright", 3 + (-spread), -3 + spread) border3:SetColorTexture (0, 0, 0, alpha3 or default_border_color3) - border3:SetWidth (size) + PixelUtil.SetWidth (border3, size, minPixels) tinsert (parent.Borders.Layer1, border1) tinsert (parent.Borders.Layer2, border2) tinsert (parent.Borders.Layer3, border3) local border1 = parent:CreateTexture (nil, "background") - border1:SetPoint ("bottomleft", parent, "bottomleft", 0 + spread, -1 + spread) - border1:SetPoint ("bottomright", parent, "bottomright", 0 + (-spread), -1 + spread) + PixelUtil.SetPoint (border1, "bottomleft", parent, "bottomleft", 0 + spread, -1 + spread) + PixelUtil.SetPoint (border1, "bottomright", parent, "bottomright", 0 + (-spread), -1 + spread) border1:SetColorTexture (0, 0, 0, alpha1 or default_border_color1) - border1:SetHeight (size) + PixelUtil.SetHeight (border1, size, minPixels) local border2 = parent:CreateTexture (nil, "background") - border2:SetPoint ("bottomleft", parent, "bottomleft", -1 + spread, -2 + spread) - border2:SetPoint ("bottomright", parent, "bottomright", 1 + (-spread), -2 + spread) + PixelUtil.SetPoint (border2, "bottomleft", parent, "bottomleft", -1 + spread, -2 + spread) + PixelUtil.SetPoint (border2, "bottomright", parent, "bottomright", 1 + (-spread), -2 + spread) border2:SetColorTexture (0, 0, 0, alpha2 or default_border_color2) - border2:SetHeight (size) + PixelUtil.SetHeight (border2, size, minPixels) local border3 = parent:CreateTexture (nil, "background") - border3:SetPoint ("bottomleft", parent, "bottomleft", -2 + spread, -3 + spread) - border3:SetPoint ("bottomright", parent, "bottomright", 2 + (-spread), -3 + spread) + PixelUtil.SetPoint (border3, "bottomleft", parent, "bottomleft", -2 + spread, -3 + spread) + PixelUtil.SetPoint (border3, "bottomright", parent, "bottomright", 2 + (-spread), -3 + spread) border3:SetColorTexture (0, 0, 0, alpha3 or default_border_color3) - border3:SetHeight (size) + PixelUtil.SetHeight (border3, size, minPixels) tinsert (parent.Borders.Layer1, border1) tinsert (parent.Borders.Layer2, border2) @@ -2712,5 +2765,36 @@ function DF:GetCLEncounterIDs() end +------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +--> debug + +DF.DebugMixin = { + + debug = true, + + CheckPoint = function (self, checkPointName, ...) + print (self:GetName(), checkPointName, ...) + end, + + CheckVisibilityState = function (self, widget) + + self = widget or self + + local width, height = self:GetSize() + width = floor (width) + height = floor (height) + + local numPoints = self:GetNumPoints() + + print ("shown:", self:IsShown(), "visible:", self:IsVisible(), "alpha:", self:GetAlpha(), "size:", width, height, "points:", numPoints) + end, + + CheckStack = function (self) + local stack = debugstack() + Details:Dump (stack) + end, + +} + --doo elsee --was doing double loops due to not enought height diff --git a/Libs/DF/panel.lua b/Libs/DF/panel.lua index c0a3344b..a3851834 100644 --- a/Libs/DF/panel.lua +++ b/Libs/DF/panel.lua @@ -1524,8 +1524,8 @@ function DF:IconPick (callback, close_when_select, param1, param2) DF.IconPickFrame:SetScript ("OnShow", function() - MACRO_ICON_FILENAMES [1] = "INV_MISC_QUESTIONMARK"; - local index = 2; + MACRO_ICON_FILENAMES [1] = "INV_MISC_QUESTIONMARK" + local index = 2 for i = 1, GetNumSpellTabs() do local tab, tabTex, offset, numSpells, _ = GetSpellTabInfo (i) @@ -1537,7 +1537,7 @@ function DF:IconPick (callback, close_when_select, param1, param2) local spellType, ID = GetSpellBookItemInfo (j, "player") if (spellType ~= "FUTURESPELL") then MACRO_ICON_FILENAMES [index] = GetSpellBookItemTexture (j, "player") or 0 - index = index + 1; + index = index + 1 elseif (spellType == "FLYOUT") then local _, _, numSlots, isKnown = GetFlyoutInfo (ID) @@ -1546,7 +1546,7 @@ function DF:IconPick (callback, close_when_select, param1, param2) local spellID, overrideSpellID, isKnown = GetFlyoutSlotInfo (ID, k) if (isKnown) then MACRO_ICON_FILENAMES [index] = GetSpellTexture (spellID) or 0 - index = index + 1; + index = index + 1 end end end @@ -1601,7 +1601,7 @@ function DF:IconPick (callback, close_when_select, param1, param2) local newcheck = CreateFrame ("Button", "DetailsFrameworkIconPickFrameButton"..(i+1), DF.IconPickFrame) local image = newcheck:CreateTexture ("DetailsFrameworkIconPickFrameButton"..(i+1).."Icon", "overlay") newcheck.icon = image - image:SetPoint ("topleft", newcheck, "topleft", 2, -2); image:SetPoint ("bottomright", newcheck, "bottomright", -2, 2) + image:SetPoint ("topleft", newcheck, "topleft", 2, -2) image:SetPoint ("bottomright", newcheck, "bottomright", -2, 2) newcheck:SetSize (30, 28) newcheck:SetBackdrop (backdrop) @@ -1618,7 +1618,7 @@ function DF:IconPick (callback, close_when_select, param1, param2) local newcheck = CreateFrame ("Button", "DetailsFrameworkIconPickFrameButton"..i, DF.IconPickFrame) local image = newcheck:CreateTexture ("DetailsFrameworkIconPickFrameButton"..i.."Icon", "overlay") newcheck.icon = image - image:SetPoint ("topleft", newcheck, "topleft", 2, -2); image:SetPoint ("bottomright", newcheck, "bottomright", -2, 2) + image:SetPoint ("topleft", newcheck, "topleft", 2, -2) image:SetPoint ("bottomright", newcheck, "bottomright", -2, 2) newcheck:SetSize (30, 28) newcheck:SetBackdrop (backdrop) @@ -1635,7 +1635,7 @@ function DF:IconPick (callback, close_when_select, param1, param2) local newcheck = CreateFrame ("Button", "DetailsFrameworkIconPickFrameButton"..i, DF.IconPickFrame) local image = newcheck:CreateTexture ("DetailsFrameworkIconPickFrameButton"..i.."Icon", "overlay") newcheck.icon = image - image:SetPoint ("topleft", newcheck, "topleft", 2, -2); image:SetPoint ("bottomright", newcheck, "bottomright", -2, 2) + image:SetPoint ("topleft", newcheck, "topleft", 2, -2) image:SetPoint ("bottomright", newcheck, "bottomright", -2, 2) newcheck:SetSize (30, 28) newcheck:SetBackdrop (backdrop) @@ -1652,7 +1652,7 @@ function DF:IconPick (callback, close_when_select, param1, param2) local newcheck = CreateFrame ("Button", "DetailsFrameworkIconPickFrameButton"..i, DF.IconPickFrame) local image = newcheck:CreateTexture ("DetailsFrameworkIconPickFrameButton"..i.."Icon", "overlay") newcheck.icon = image - image:SetPoint ("topleft", newcheck, "topleft", 2, -2); image:SetPoint ("bottomright", newcheck, "bottomright", -2, 2) + image:SetPoint ("topleft", newcheck, "topleft", 2, -2) image:SetPoint ("bottomright", newcheck, "bottomright", -2, 2) newcheck:SetSize (30, 28) newcheck:SetBackdrop (backdrop) @@ -1669,7 +1669,7 @@ function DF:IconPick (callback, close_when_select, param1, param2) local newcheck = CreateFrame ("Button", "DetailsFrameworkIconPickFrameButton"..i, DF.IconPickFrame) local image = newcheck:CreateTexture ("DetailsFrameworkIconPickFrameButton"..i.."Icon", "overlay") newcheck.icon = image - image:SetPoint ("topleft", newcheck, "topleft", 2, -2); image:SetPoint ("bottomright", newcheck, "bottomright", -2, 2) + image:SetPoint ("topleft", newcheck, "topleft", 2, -2) image:SetPoint ("bottomright", newcheck, "bottomright", -2, 2) newcheck:SetSize (30, 28) newcheck:SetBackdrop (backdrop) @@ -1686,7 +1686,7 @@ function DF:IconPick (callback, close_when_select, param1, param2) local newcheck = CreateFrame ("Button", "DetailsFrameworkIconPickFrameButton"..i, DF.IconPickFrame) local image = newcheck:CreateTexture ("DetailsFrameworkIconPickFrameButton"..i.."Icon", "overlay") newcheck.icon = image - image:SetPoint ("topleft", newcheck, "topleft", 2, -2); image:SetPoint ("bottomright", newcheck, "bottomright", -2, 2) + image:SetPoint ("topleft", newcheck, "topleft", 2, -2) image:SetPoint ("bottomright", newcheck, "bottomright", -2, 2) newcheck:SetSize (30, 28) newcheck:SetBackdrop (backdrop) @@ -2252,7 +2252,7 @@ function DF:ShowTextPromptPanel (message, callback) button_true:SetPoint ("bottomright", f, "bottomright", -10, 5) f.button_true = button_true - local button_false = DF:CreateButton (f, function() f.textbox:ClearFocus(); f:Hide() end, 60, 20, "Cancel", nil, nil, nil, nil, nil, nil, options_dropdown_template) + local button_false = DF:CreateButton (f, function() f.textbox:ClearFocus() f:Hide() end, 60, 20, "Cancel", nil, nil, nil, nil, nil, nil, options_dropdown_template) button_false:SetPoint ("bottomleft", f, "bottomleft", 10, 5) f.button_false = button_false @@ -2994,7 +2994,7 @@ end function calc_cubeweight (i, j, d) local w = ( 1 - math.abs ((j-i)/d)^3)^3 if w < 0 then - w = 0; + w = 0 end return w end @@ -3035,11 +3035,11 @@ local calc_lowess_smoothing = function (self, data, bandwidth) end -- Calculate a (slope) and b (offset) for the linear fit - local a = (A*B-D*E)/(A^2 - C*E); - local b = (A*D-B*C)/(A^2 - C*E); + local a = (A*B-D*E)/(A^2 - C*E) + local b = (A*D-B*C)/(A^2 - C*E) -- Calculate the smoothed value by the formula y=a*x+b (x <- i) - newData [i] = a*i+b; + newData [i] = a*i+b end @@ -3802,6 +3802,7 @@ function DF:CreateTabContainer (parent, title, frame_name, frame_list, options_t title:SetPoint ("topleft", mainTitle, "bottomleft", 0, 0) local tabButton = DF:CreateButton (mainFrame, DF.TabContainerFunctions.SelectIndex, button_width, button_height, frame.title, i, nil, nil, nil, nil, false, button_tab_template) + PixelUtil.SetSize (tabButton, button_width, button_height) tabButton:SetFrameLevel (220) tabButton.textsize = button_text_size tabButton.mainFrame = mainFrame @@ -3846,7 +3847,7 @@ function DF:CreateTabContainer (parent, title, frame_name, frame_list, options_t for i = 2, #mainFrame.AllButtons do local button = mainFrame.AllButtons [i] - button:SetPoint ("topleft", mainTitle, "topleft", x, y) + PixelUtil.SetPoint (button, "topleft", mainTitle, "topleft", x, y) x = x + button_width + 2 if (i % amount_buttons_per_row == 0) then @@ -4763,9 +4764,9 @@ function DF:BuildKeybindFunctions (data, prefix) local classLoc, class = UnitClass ("player") local bindingList = data - local bindString = "self:ClearBindings();" - local bindKeyBindTypeFunc = [[local unitFrame = ...;]] - local bindMacroTextFunc = [[local unitFrame = ...;]] + local bindString = "self:ClearBindings()" + local bindKeyBindTypeFunc = [[local unitFrame = ...]] + local bindMacroTextFunc = [[local unitFrame = ...]] local isMouseBinding for i = 1, #bindingList do @@ -4779,7 +4780,7 @@ function DF:BuildKeybindFunctions (data, prefix) isMouseBinding = true else bindType = prefix .. "" .. i - bindString = bindString .. "self:SetBindingClick (0, '" .. bind.key .. "', self:GetName(), '" .. bindType .. "');" + bindString = bindString .. "self:SetBindingClick (0, '" .. bind.key .. "', self:GetName(), '" .. bindType .. "')" bindType = "-" .. prefix .. "" .. i isMouseBinding = nil end @@ -4792,9 +4793,9 @@ function DF:BuildKeybindFunctions (data, prefix) local keyBindType if (isMouseBinding) then - keyBindType = [[unitFrame:SetAttribute ("@COMMANDtype@BINDTYPE", "macro");]] + keyBindType = [[unitFrame:SetAttribute ("@COMMANDtype@BINDTYPE", "macro")]] else - keyBindType = [[unitFrame:SetAttribute ("type@BINDTYPE", "macro");]] + keyBindType = [[unitFrame:SetAttribute ("type@BINDTYPE", "macro")]] end keyBindType = keyBindType:gsub ("@BINDTYPE", bindType) @@ -4805,9 +4806,9 @@ function DF:BuildKeybindFunctions (data, prefix) if (bind.action == "_spell") then local macroTextLine if (isMouseBinding) then - macroTextLine = [[unitFrame:SetAttribute ("@COMMANDmacrotext@BINDTYPE", "/cast [@mouseover] @SPELL");]] + macroTextLine = [[unitFrame:SetAttribute ("@COMMANDmacrotext@BINDTYPE", "/cast [@mouseover] @SPELL")]] else - macroTextLine = [[unitFrame:SetAttribute ("macrotext@BINDTYPE", "/cast [@mouseover] @SPELL");]] + macroTextLine = [[unitFrame:SetAttribute ("macrotext@BINDTYPE", "/cast [@mouseover] @SPELL")]] end macroTextLine = macroTextLine:gsub ("@BINDTYPE", bindType) macroTextLine = macroTextLine:gsub ("@SPELL", bind.actiontext) @@ -4817,9 +4818,9 @@ function DF:BuildKeybindFunctions (data, prefix) elseif (bind.action == "_macro") then local macroTextLine if (isMouseBinding) then - macroTextLine = [[unitFrame:SetAttribute ("@COMMANDmacrotext@BINDTYPE", "@MACRO");]] + macroTextLine = [[unitFrame:SetAttribute ("@COMMANDmacrotext@BINDTYPE", "@MACRO")]] else - macroTextLine = [[unitFrame:SetAttribute ("macrotext@BINDTYPE", "@MACRO");]] + macroTextLine = [[unitFrame:SetAttribute ("macrotext@BINDTYPE", "@MACRO")]] end macroTextLine = macroTextLine:gsub ("@BINDTYPE", bindType) macroTextLine = macroTextLine:gsub ("@MACRO", bind.actiontext) @@ -4952,10 +4953,10 @@ DF.IconRowFunctions = { if (not iconFrame) then local newIconFrame = CreateFrame ("frame", "$parentIcon" .. self.NextIcon, self) - newIconFrame:SetSize (self.options.icon_width, self.options.icon_height) newIconFrame.Texture = newIconFrame:CreateTexture (nil, "artwork") - newIconFrame.Texture:SetAllPoints() + PixelUtil.SetPoint (newIconFrame.Texture, "topleft", newIconFrame, "topleft", 1, -1) + PixelUtil.SetPoint (newIconFrame.Texture, "bottomright", newIconFrame, "bottomright", -1, 1) newIconFrame.Border = newIconFrame:CreateTexture (nil, "background") newIconFrame.Border:SetAllPoints() @@ -4993,16 +4994,16 @@ DF.IconRowFunctions = { if (growDirection == 1) then --grow to right if (self.NextIcon == 1) then - iconFrame:SetPoint ("left", anchorTo, "left", xPadding, 0) + PixelUtil.SetPoint (iconFrame, "left", anchorTo, "left", xPadding, 0) else - iconFrame:SetPoint ("left", anchorTo, "right", xPadding, 0) + PixelUtil.SetPoint (iconFrame, "left", anchorTo, "right", xPadding, 0) end elseif (growDirection == 2) then --grow to left if (self.NextIcon == 1) then - iconFrame:SetPoint ("right", anchorTo, "right", xPadding, 0) + PixelUtil.SetPoint (iconFrame, "right", anchorTo, "right", xPadding, 0) else - iconFrame:SetPoint ("right", anchorTo, "left", xPadding, 0) + PixelUtil.SetPoint (iconFrame, "right", anchorTo, "left", xPadding, 0) end end @@ -5071,7 +5072,7 @@ DF.IconRowFunctions = { iconFrame.Desc:Hide() end - iconFrame:SetSize (self.options.icon_width, self.options.icon_height) + PixelUtil.SetSize (iconFrame, self.options.icon_width, self.options.icon_height) iconFrame:Show() --> update the size of the frame @@ -5802,7 +5803,7 @@ function DF:UpdateLoadConditionsTable (configTable) return configTable end ---/run Plater.OpenOptionsPanel();PlaterOptionsPanelContainer:SelectIndex (Plater, 14); +--/run Plater.OpenOptionsPanel()PlaterOptionsPanelContainer:SelectIndex (Plater, 14) function DF:OpenLoadConditionsPanel (optionsTable, callback, frameOptions) @@ -6166,16 +6167,16 @@ function DF:OpenLoadConditionsPanel (optionsTable, callback, frameOptions) local idList = f.OptionsTable [self.DBKey] self:SetText ("") for i = 1, #idList do - self:SetText (self:GetText() .. "; " .. idList [i]) + self:SetText (self:GetText() .. " " .. idList [i]) end - self:SetText (self:GetText():gsub ("^; ", "")) + self:SetText (self:GetText():gsub ("^ ", "")) end local textEntryOnEnterPressed = function (_, self) wipe (f.OptionsTable [self.DBKey]) local text = self:GetText() - for _, ID in ipairs ({strsplit (";", text)}) do + for _, ID in ipairs ({strsplit ("", text)}) do ID = DF:trim (ID) ID = tonumber (ID) if (ID) then @@ -6192,7 +6193,7 @@ function DF:OpenLoadConditionsPanel (optionsTable, callback, frameOptions) encounterIDEditbox:SetPoint ("topleft", encounterIDLabel, "bottomleft", 0, -2) encounterIDEditbox.DBKey = "encounter_ids" encounterIDEditbox.Refresh = textEntryRefresh - encounterIDEditbox.tooltip = "Enter multiple IDs separating with a semicolon (;)\nExample: 35; 45; 95\n\nUldir:\n" + encounterIDEditbox.tooltip = "Enter multiple IDs separating with a semicolon ()\nExample: 35 45 95\n\nUldir:\n" for _, encounterTable in ipairs (DF:GetCLEncounterIDs()) do encounterIDEditbox.tooltip = encounterIDEditbox.tooltip .. encounterTable.ID .. " - " .. encounterTable.Name .. "\n" end @@ -6206,7 +6207,7 @@ function DF:OpenLoadConditionsPanel (optionsTable, callback, frameOptions) mapIDEditbox:SetPoint ("topleft", mapIDLabel, "bottomleft", 0, -2) mapIDEditbox.DBKey = "map_ids" mapIDEditbox.Refresh = textEntryRefresh - mapIDEditbox.tooltip = "Enter multiple IDs separating with a semicolon (;)\nExample: 35; 45; 95" + mapIDEditbox.tooltip = "Enter multiple IDs separating with a semicolon ()\nExample: 35 45 95" mapIDEditbox:SetHook ("OnEnterPressed", textEntryOnEnterPressed) tinsert (f.AllTextEntries, mapIDEditbox) @@ -6563,16 +6564,2204 @@ end +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +--> statusbar mixin + +--[=[ + collection of functions to embed into a statusbar + statusBar:GetTexture() + statusBar:SetTexture (texture) + statusBar:SetColor (unparsed color) + statusBar:GetColor() + statusBar: + statusBar: + +--]=] + +DF.StatusBarFunctions = { + + GetTexture = function (self) + return self.barTexture:GetTexture() + end, + + SetTexture = function (self, texture) + self.barTexture:SetTexture (texture) + end, + + SetColor = function (self, r, g, b, a) + r, g, b, a = DF:ParseColors (r, g, b, a) + self:SetStatusBarColor (r, g, b, a) + end, + + GetColor = function (self) + return self:GetStatusBarColor() + end, + +} + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +--> health bar frame + +--[=[ + DF:CreateHealthBar (parent, name, settingsOverride) + creates a health bar to show an unit health + @parent = frame to pass for the CreateFrame function + @name = absolute name of the frame, if omitted it uses the parent's name .. "HealthBar" + @settingsOverride = table with keys and values to replace the defaults from the framework + + methods: + healthbar:SetUnit (unit) + healthBar:GetTexture() + healthBar:SetTexture (texture) +--]=] + +local debugPerformance = { + eventCall = {}, + unitCall = {}, + functionCall = {}, + CPUUsageByFunction = {}, +} + +local function CalcPerformance (type, data) + if (type == "event") then + debugPerformance.eventCall [data] = (debugPerformance.eventCall [data] or 0) + 1 + + elseif (type == "unit") then + debugPerformance.unitCall [data] = (debugPerformance.unitCall [data] or 0) + 1 + + elseif (type == "call") then + debugPerformance.functionCall [data] = (debugPerformance.functionCall [data] or 0) + 1 + + end +end + +function DF_CalcCpuUsage (name) + local cpu = debugPerformance.CPUUsageByFunction [name] or {usage = 0, last = 0, active = false} + debugPerformance.CPUUsageByFunction [name] = cpu + + if (cpu.active) then + cpu.active = false + local diff = debugprofilestop() - cpu.last + cpu.usage = cpu.usage + diff + else + cpu.active = true + cpu.last = debugprofilestop() + end +end + +function UnitFrameStats() + for functionName, functionTable in pairs (debugPerformance.CPUUsageByFunction) do + debugPerformance.CPUUsageByFunction [functionName] = floor (functionTable.usage) + end + + Details:Dump (debugPerformance) + + for functionName, functionTable in pairs (debugPerformance.CPUUsageByFunction) do + debugPerformance.CPUUsageByFunction [functionName] = {usage = 0, last = 0, active = false} + end +end + + +--CalcPerformance ("unit", data) + +DF.HealthFrameFunctions = { + + WidgetType = "healthBar", + SetHook = DF.SetHook, + RunHooksForWidget = DF.RunHooksForWidget, + + HookList = { + OnHide = {}, + OnShow = {}, + }, + + Settings = { + CanTick = false, --> if true calls the method 'OnTick' every tick, the function needs to be overloaded, it receives self and deltaTime as parameters + ShowHealingPrediction = true, --> when casting a healing pass, show the amount of health that spell will heal + ShowShields = true, --> indicator of the amount of damage absortion the unit has + + --appearance + BackgroundColor = DF:CreateColorTable (.2, .2, .2, .8), + Texture = [[Interface\RaidFrame\Raid-Bar-Hp-Fill]], + ShieldIndicatorTexture = [[Interface\RaidFrame\Shield-Fill]], + ShieldGlowTexture = [[Interface\RaidFrame\Shield-Overshield]], + ShieldGlowWidth = 16, + + --default size + Width = 100, + Height = 20, + }, + + HealthBarEvents = { + {"PLAYER_ENTERING_WORLD"}, + --{"UNIT_HEALTH", true}, + {"UNIT_MAXHEALTH", true}, + {"UNIT_HEALTH_FREQUENT", true}, + {"UNIT_HEAL_PREDICTION", true}, + {"UNIT_ABSORB_AMOUNT_CHANGED", true}, + {"UNIT_HEAL_ABSORB_AMOUNT_CHANGED", true}, + }, + + --> setup the castbar to be used by another unit + SetUnit = function (self, unit, displayedUnit) + if (self.unit ~= unit or self.displayedUnit ~= displayedUnit or unit == nil) then + + CalcPerformance ("call", "SetUnit") + + self.unit = unit + self.displayedUnit = displayedUnit or unit + + --> register events + if (unit) then + self.currentHealth = UnitHealth (unit) or 0 + self.currentHealthMax = UnitHealthMax (unit) or 0 + + for _, eventTable in ipairs (self.HealthBarEvents) do + local event = eventTable [1] + local isUnitEvent = eventTable [2] + if (isUnitEvent) then + self:RegisterUnitEvent (event, self.displayedUnit, self.unit) + else + self:RegisterEvent (event) + end + end + + --> check for settings and update some events + if (not self.Settings.ShowHealingPrediction) then + self:UnregisterEvent ("UNIT_HEAL_PREDICTION") + self:UnregisterEvent ("UNIT_HEAL_ABSORB_AMOUNT_CHANGED") + self.incomingHealIndicator:Hide() + self.healAbsorbIndicator:Hide() + end + if (not self.Settings.ShowShields) then + self:UnregisterEvent ("UNIT_ABSORB_AMOUNT_CHANGED") + self.shieldAbsorbIndicator:Hide() + self.shieldAbsorbGlow:Hide() + end + + --> set scripts + self:SetScript ("OnEvent", self.OnEvent) + + if (self.Settings.CanTick) then + self:SetScript ("OnUpdate", self.OnTick) + end + + self:PLAYER_ENTERING_WORLD (self.unit, self.displayedUnit) + else + --> remove all registered events + for _, eventTable in ipairs (self.HealthBarEvents) do + local event = eventTable [1] + self:UnregisterEvent (event) + end + + --> remove scripts + self:SetScript ("OnEvent", nil) + self:SetScript ("OnUpdate", nil) + self:Hide() + end + end + end, + + Initialize = function (self) + PixelUtil.SetWidth (self, self.Settings.Width, 1) + PixelUtil.SetHeight (self, self.Settings.Height, 1) + + self:SetTexture (self.Settings.Texture) + + self.background:SetAllPoints() + self.background:SetColorTexture (self.Settings.BackgroundColor:GetColor()) + + --setpoint of these widgets are set inside the function that updates the incoming heal + self.incomingHealIndicator:SetTexture (self:GetTexture()) + self.healAbsorbIndicator:SetTexture (self:GetTexture()) + self.healAbsorbIndicator:SetVertexColor (.1, .8, .8) + self.shieldAbsorbIndicator:SetTexture (self.Settings.ShieldIndicatorTexture, true, true) + + self.shieldAbsorbGlow:SetWidth (self.Settings.ShieldGlowWidth) + self.shieldAbsorbGlow:SetTexture (self.Settings.ShieldGlowTexture) + self.shieldAbsorbGlow:SetBlendMode ("ADD") + self.shieldAbsorbGlow:SetPoint ("topright", self, "topright", 8, 0) + self.shieldAbsorbGlow:SetPoint ("bottomright", self, "bottomright", 8, 0) + self.shieldAbsorbGlow:Hide() + + self:SetUnit (nil) + + CalcPerformance ("call", "HealthBar-Initialize") + end, + + --> call every tick + OnTick = function (self, deltaTime) end, --if overrided, set 'CanTick' to true on the settings table + + --> when an event happen for this unit, send it to the apropriate function + OnEvent = function (self, event, ...) + CalcPerformance ("unit", self.unit) + CalcPerformance ("event", event) + CalcPerformance ("call", "HealthBar-OnEvent") + + DF_CalcCpuUsage ("healthBar-OnEvent") + local eventFunc = self [event] + if (eventFunc) then + --the function doesn't receive which event was, only 'self' and the parameters + eventFunc (self, ...) + end + DF_CalcCpuUsage ("healthBar-OnEvent") + end, + + --colocar mais coisas aqui, um member dizendo quanto de health e o health max da unit + UpdateMaxHealth = function (self) + DF_CalcCpuUsage ("HealthBar-UpdateMaxHealth") + local maxHealth = UnitHealthMax (self.displayedUnit) + self:SetMinMaxValues (0, maxHealth) + self.currentHealthMax = maxHealth + DF_CalcCpuUsage ("HealthBar-UpdateMaxHealth") + + CalcPerformance ("call", "HealthBar-UpdateMaxHealth") + end, + + UpdateHealth = function (self) + DF_CalcCpuUsage ("HealthBar-UpdateHealth") + local health = UnitHealth (self.displayedUnit) + self.currentHealth = health + PixelUtil.SetStatusBarValue (self, health) + DF_CalcCpuUsage ("HealthBar-UpdateHealth") + + CalcPerformance ("call", "HealthBar-UpdateHealth") + end, + + --isso aqui vai ser complicado! + UpdateHealPrediction = function (self) + CalcPerformance ("call", "HealthBar-UpdateHealPrediction") + + DF_CalcCpuUsage ("HealthBar-UpdateHealPrediction") + + local currentHealth = self.currentHealth + local currentHealthMax = self.currentHealthMax + local healthPercent = currentHealth / currentHealthMax + + if (not currentHealthMax or currentHealthMax <= 0) then + DF_CalcCpuUsage ("HealthBar-UpdateHealPrediction") + return + end + + --order is: the health of the unit > damage absorb > heal absorb > incoming heal + local width = self:GetWidth() + + if (self.Settings.ShowHealingPrediction) then + --incoming heal on the unit from all sources + local unitHealIncoming = UnitGetIncomingHeals (self.displayedUnit) or 0 + --heal absorbs + local unitHealAbsorb = UnitGetTotalHealAbsorbs (self.displayedUnit) or 0 + + if (unitHealIncoming > 0) then + --calculate what is the percent of health incoming based on the max health the player has + local incomingPercent = unitHealIncoming / currentHealthMax + self.incomingHealIndicator:Show() + self.incomingHealIndicator:SetWidth (max (1, min (width * incomingPercent, abs (healthPercent - 1) * width))) + self.incomingHealIndicator:SetPoint ("topleft", self, "topleft", width * healthPercent, 0) + self.incomingHealIndicator:SetPoint ("bottomleft", self, "bottomleft", width * healthPercent, 0) + else + self.incomingHealIndicator:Hide() + end + + if (unitHealAbsorb > 0) then + local healAbsorbPercent = unitHealAbsorb / currentHealthMax + self.healAbsorbIndicator:Show() + self.healAbsorbIndicator:SetWidth (max (1, min (width * healAbsorbPercent, abs (healthPercent - 1) * width))) + self.healAbsorbIndicator:SetPoint ("topleft", self, "topleft", width * healthPercent, 0) + self.healAbsorbIndicator:SetPoint ("bottomleft", self, bottom"left", width * healthPercent, 0) + else + self.healAbsorbIndicator:Hide() + end + end + + if (self.Settings.ShowShields) then + --damage absorbs + local unitDamageAbsorb = UnitGetTotalAbsorbs (self.displayedUnit) or 0 + + if (unitDamageAbsorb > 0) then + local damageAbsorbPercent = unitDamageAbsorb / currentHealthMax + self.shieldAbsorbIndicator:Show() + --set the width where the max width size is what is lower: the absorb size or the missing amount of health in the health bar + --/dump NamePlate1PlaterUnitFrameHealthBar.shieldAbsorbIndicator:GetSize() + self.shieldAbsorbIndicator:SetWidth (max (1, min (width * damageAbsorbPercent, abs (healthPercent - 1) * width))) + self.shieldAbsorbIndicator:SetPoint ("topleft", self, "topleft", width * healthPercent, 0) + self.shieldAbsorbIndicator:SetPoint ("bottomleft", self, "bottomleft", width * healthPercent, 0) + + --if the absorb percent pass 100%, show the glow + if ((healthPercent + damageAbsorbPercent) > 1) then + self.shieldAbsorbGlow:Show() + else + self.shieldAbsorbGlow:Hide() + end + else + self.shieldAbsorbIndicator:Hide() + self.shieldAbsorbGlow:Hide() + end + else + self.shieldAbsorbIndicator:Hide() + self.shieldAbsorbGlow:Hide() + end + + DF_CalcCpuUsage ("HealthBar-UpdateHealPrediction") + end, + + PLAYER_ENTERING_WORLD = function (self, ...) + self:UpdateMaxHealth() + self:UpdateHealth() + self:UpdateHealPrediction() + end, + + --> health events + UNIT_HEALTH = function (self, ...) + self:UpdateHealth() + self:UpdateHealPrediction() + + local unitName = UnitName (self.unit) + CalcPerformance ("call", "HealthBar-UNIT_HEALTH-" .. unitName) + end, + UNIT_HEALTH_FREQUENT = function (self, ...) + self:UpdateHealth() + self:UpdateHealPrediction() + end, + UNIT_MAXHEALTH = function (self, ...) + self:UpdateMaxHealth() + self:UpdateHealth() + self:UpdateHealPrediction() + end, + + UNIT_HEAL_PREDICTION = function (self, ...) + self:UpdateMaxHealth() + self:UpdateHealth() + self:UpdateHealPrediction() + end, + UNIT_ABSORB_AMOUNT_CHANGED = function (self, ...) + self:UpdateMaxHealth() + self:UpdateHealth() + self:UpdateHealPrediction() + end, + UNIT_HEAL_ABSORB_AMOUNT_CHANGED = function (self, ...) + self:UpdateMaxHealth() + self:UpdateHealth() + self:UpdateHealPrediction() + end, +} + +-- ~healthbar +function DF:CreateHealthBar (parent, name, settingsOverride) + + assert (name or parent:GetName(), "DetailsFramework:CreateHealthBar parameter 'name' omitted and parent has no name.") + + local healthBar = CreateFrame ("StatusBar", name or (parent:GetName() .. "HealthBar"), parent) + do --layers + --background + healthBar.background = healthBar:CreateTexture (nil, "background") + healthBar.background:SetDrawLayer ("background", -6) + + --artwork + --healing incoming + healthBar.incomingHealIndicator = healthBar:CreateTexture (nil, "artwork") + healthBar.incomingHealIndicator:SetDrawLayer ("artwork", 4) + --current shields on the unit + healthBar.shieldAbsorbIndicator = healthBar:CreateTexture (nil, "artwork") + healthBar.shieldAbsorbIndicator:SetDrawLayer ("artwork", 5) + --debuff absorbing heal + healthBar.healAbsorbIndicator = healthBar:CreateTexture (nil, "artwork") + healthBar.healAbsorbIndicator:SetDrawLayer ("artwork", 6) + --the shield fills all the bar, show that cool glow + healthBar.shieldAbsorbGlow = healthBar:CreateTexture (nil, "artwork") + healthBar.shieldAbsorbGlow:SetDrawLayer ("artwork", 7) + --statusbar texture + healthBar.barTexture = healthBar:CreateTexture (nil, "artwork") + healthBar:SetStatusBarTexture (healthBar.barTexture) + end + + --> mixins + DF:Mixin (healthBar, DF.HealthFrameFunctions) + DF:Mixin (healthBar, DF.StatusBarFunctions) + + --> settings and hooks + local settings = DF.table.copy ({}, DF.HealthFrameFunctions.Settings) + if (settingsOverride) then + DF.table.copy (settings, settingsOverride) + end + healthBar.Settings = settings + + local hookList = DF.table.copy ({}, DF.HealthFrameFunctions.HookList) + healthBar.HookList = hookList + + --> initialize the cast bar + healthBar:Initialize() + + return healthBar +end + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +--> power bar frame + +--[=[ + DF:CreatePowerBar (parent, name, settingsOverride) + creates statusbar frame to show the unit power bar + @parent = frame to pass for the CreateFrame function + @name = absolute name of the frame, if omitted it uses the parent's name .. "PPowerBar" + @settingsOverride = table with keys and values to replace the defaults from the framework +--]=] + +DF.PowerFrameFunctions = { + + WidgetType = "powerBar", + SetHook = DF.SetHook, + RunHooksForWidget = DF.RunHooksForWidget, + + HookList = { + OnHide = {}, + OnShow = {}, + }, + + Settings = { + --> misc + ShowAlternatePower = true, --> if true it'll show alternate power over the regular power the unit uses + ShowPercentText = true, --> if true show a text with the current energy percent + HideIfNoPower = true, --> if true and the UnitMaxPower returns zero, it'll hide the power bar with self:Hide() + CanTick = false, --> if it calls the OnTick function every tick + + --appearance + BackgroundColor = DF:CreateColorTable (.2, .2, .2, .8), + Texture = [[Interface\RaidFrame\Raid-Bar-Resource-Fill]], + + --> default size + Width = 100, + Height = 20, + }, + + PowerBarEvents = { + {"PLAYER_ENTERING_WORLD"}, + {"UNIT_DISPLAYPOWER", true}, + {"UNIT_POWER_BAR_SHOW", true}, + {"UNIT_POWER_BAR_HIDE", true}, + {"UNIT_MAXPOWER", true}, + {"UNIT_POWER_UPDATE", true}, + {"UNIT_POWER_FREQUENT", true}, + }, + + --> setup the castbar to be used by another unit + SetUnit = function (self, unit, displayedUnit) + if (self.unit ~= unit or self.displayedUnit ~= displayedUnit or unit == nil) then + self.unit = unit + self.displayedUnit = displayedUnit or unit + + --> register events + if (unit) then + for _, eventTable in ipairs (self.PowerBarEvents) do + local event = eventTable [1] + local isUnitEvent = eventTable [2] + + if (isUnitEvent) then + self:RegisterUnitEvent (event, self.displayedUnit) + else + self:RegisterEvent (event) + end + end + + --> set scripts + self:SetScript ("OnEvent", self.OnEvent) + + if (self.Settings.CanTick) then + self:SetScript ("OnUpdate", self.OnTick) + end + + self:Show() + self:UpdatePowerBar() + else + --> remove all registered events + for _, eventTable in ipairs (self.PowerBarEvents) do + local event = eventTable [1] + self:UnregisterEvent (event) + end + + --> remove scripts + self:SetScript ("OnEvent", nil) + self:SetScript ("OnUpdate", nil) + self:Hide() + end + end + end, + + Initialize = function (self) + PixelUtil.SetWidth (self, self.Settings.Width) + PixelUtil.SetHeight (self, self.Settings.Height) + + self:SetTexture (self.Settings.Texture) + + self.background:SetAllPoints() + self.background:SetColorTexture (self.Settings.BackgroundColor:GetColor()) + + if (self.Settings.ShowPercentText) then + self.percentText:Show() + PixelUtil.SetPoint (self.percentText, "center", self, "center", 0, 0) + + DF:SetFontSize (self.percentText, 9) + DF:SetFontColor (self.percentText, "white") + DF:SetFontOutline (self.percentText, "OUTLINE") + else + self.percentText:Hide() + end + + self:SetUnit (nil) + end, + + --> call every tick + OnTick = function (self, deltaTime) end, --if overrided, set 'CanTick' to true on the settings table + + --> when an event happen for this unit, send it to the apropriate function + OnEvent = function (self, event, ...) + DF_CalcCpuUsage ("Powerbar-OnEvent") + local eventFunc = self [event] + if (eventFunc) then + --the function doesn't receive which event was, only 'self' and the parameters + eventFunc (self, ...) + end + DF_CalcCpuUsage ("Powerbar-OnEvent") + end, + + UpdatePowerBar = function (self) + self:UpdatePowerInfo() + self:UpdateMaxPower() + self:UpdatePower() + self:UpdatePowerColor() + end, + + --> power update + UpdateMaxPower = function (self) + self.currentPowerMax = UnitPowerMax (self.displayedUnit, self.powerType) + self:SetMinMaxValues (self.minPower, self.currentPowerMax) + + if (self.currentPowerMax == 0 and self.Settings.HideIfNoPower) then + self:Hide() + end + end, + UpdatePower = function (self) + DF_CalcCpuUsage ("Powerbar-UpdatePower") + self.currentPower = UnitPower (self.displayedUnit, self.powerType) + PixelUtil.SetStatusBarValue (self, self.currentPower) + + if (self.Settings.ShowPercentText) then + self.percentText:SetText (floor (self.currentPower / self.currentPowerMax * 100) .. "%") + end + DF_CalcCpuUsage ("Powerbar-UpdatePower") + end, + + --> when a event different from unit_power_update is triggered, update which type of power the unit should show + UpdatePowerInfo = function (self) + DF_CalcCpuUsage ("Powerbar-UpdatePowerInfo") + if (self.Settings.ShowAlternatePower) then + local _, minPower, _, _, _, _, showOnRaid = UnitAlternatePowerInfo (self.displayedUnit) + if (showOnRaid and IsInGroup()) then + self.powerType = ALTERNATE_POWER_INDEX + self.minPower = minPower + DF_CalcCpuUsage ("Powerbar-UpdatePowerInfo") + return + end + end + + self.powerType = UnitPowerType (self.displayedUnit) + self.minPower = 0 + DF_CalcCpuUsage ("Powerbar-UpdatePowerInfo") + end, + + --> tint the bar with the color of the power, e.g. blue for a mana bar + UpdatePowerColor = function (self) + if (not UnitIsConnected (self.unit)) then + self:SetStatusBarColor (.5, .5, .5) + return + end + + if (self.powerType == ALTERNATE_POWER_INDEX) then + --> don't change this, keep the same color as the game tints on CompactUnitFrame.lua + self:SetStatusBarColor (0.7, 0.7, 0.6) + return + end + + local powerColor = PowerBarColor [self.powerType] --> don't appear to be, but PowerBarColor is a global table with all power colors /run Details:Dump (PowerBarColor) + if (powerColor) then + self:SetStatusBarColor (powerColor.r, powerColor.g, powerColor.b) + return + end + + local _, _, r, g, b = UnitPowerType (self.displayedUnit) + if (r) then + self:SetStatusBarColor (r, g, b) + return + end + + --> if everything else fails, tint as rogue energy + powerColor = PowerBarColor ["ENERGY"] + self:SetStatusBarColor (powerColor.r, powerColor.g, powerColor.b) + end, + + --> events + PLAYER_ENTERING_WORLD = function (self, ...) + self:UpdatePowerBar() + end, + UNIT_DISPLAYPOWER = function (self, ...) + self:UpdatePowerBar() + end, + UNIT_POWER_BAR_SHOW = function (self, ...) + self:UpdatePowerBar() + end, + UNIT_POWER_BAR_HIDE = function (self, ...) + self:UpdatePowerBar() + end, + + UNIT_MAXPOWER = function (self, ...) + self:UpdateMaxPower() + self:UpdatePower() + end, + UNIT_POWER_UPDATE = function (self, ...) + self:UpdatePower() + end, + UNIT_POWER_FREQUENT = function (self, ...) + self:UpdatePower() + end, +} + +-- ~powerbar +function DF:CreatePowerBar (parent, name, settingsOverride) + + assert (name or parent:GetName(), "DetailsFramework:CreatePowerBar parameter 'name' omitted and parent has no name.") + + local powerBar = CreateFrame ("StatusBar", name or (parent:GetName() .. "PowerBar"), parent) + do --layers + --background + powerBar.background = powerBar:CreateTexture (nil, "background") + powerBar.background:SetDrawLayer ("background", -6) + + --artwork + powerBar.barTexture = powerBar:CreateTexture (nil, "artwork") + powerBar:SetStatusBarTexture (powerBar.barTexture) + + --overlay + powerBar.percentText = powerBar:CreateFontString (nil, "overlay", "GameFontNormal") + end + + --> mixins + DF:Mixin (powerBar, DF.PowerFrameFunctions) + DF:Mixin (powerBar, DF.StatusBarFunctions) + + --> settings and hooks + local settings = DF.table.copy ({}, DF.PowerFrameFunctions.Settings) + if (settingsOverride) then + DF.table.copy (settings, settingsOverride) + end + powerBar.Settings = settings + + local hookList = DF.table.copy ({}, DF.PowerFrameFunctions.HookList) + powerBar.HookList = hookList + + --> initialize the cast bar + powerBar:Initialize() + + return powerBar +end + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +--> cast bar frame + +--[=[ + DF:CreateCastBar (parent, name, settingsOverride) + creates a cast bar to show an unit cast + @parent = frame to pass for the CreateFrame function + @name = absolute name of the frame, if omitted it uses the parent's name .. "CastBar" + @settingsOverride = table with keys and values to replace the defaults from the framework +--]=] + +DF.CastFrameFunctions = { + + WidgetType = "castBar", + SetHook = DF.SetHook, + RunHooksForWidget = DF.RunHooksForWidget, + + HookList = { + OnHide = {}, + OnShow = {}, + + --can be regular cast or channel + OnCastStart = {}, + }, + + CastBarEvents = { + {"UNIT_SPELLCAST_INTERRUPTED"}, + {"UNIT_SPELLCAST_DELAYED"}, + {"UNIT_SPELLCAST_CHANNEL_START"}, + {"UNIT_SPELLCAST_CHANNEL_UPDATE"}, + {"UNIT_SPELLCAST_CHANNEL_STOP"}, + {"UNIT_SPELLCAST_INTERRUPTIBLE"}, + {"UNIT_SPELLCAST_NOT_INTERRUPTIBLE"}, + {"PLAYER_ENTERING_WORLD"}, + {"UNIT_SPELLCAST_START", true}, + {"UNIT_SPELLCAST_STOP", true}, + {"UNIT_SPELLCAST_FAILED", true}, + }, + + Settings = { + NoFadeEffects = false, --if true it won't play fade effects when a cast if finished + ShowTradeSkills = false, --if true, it shows cast for trade skills, e.g. creating an icon with blacksmith + ShowShield = true, --if true, shows the shield above the spell icon for non interruptible casts + CanTick = true, --if true it will run its OnTick function every tick. + ShowCastTime = true, --if true, show the remaining time to finish the cast, lazy tick must be enabled + FadeInTime = 0.1, --amount of time in seconds to go from zero to 100% alpha when starting to cast + FadeOutTime = 0.5, --amount of time in seconds to go from 100% to zero alpha when the cast finishes + CanLazyTick = true, --if true, it'll execute the lazy tick function, it ticks in a much slower pace comparece with the regular tick + LazyUpdateCooldown = 0.2, --amount of time to wait for the next lazy update, this updates non critical things like the cast timer + + --default size + Width = 100, + Height = 20, + + --colour the castbar statusbar by the type of the cast + Colors = { + Casting = DF:CreateColorTable (1, 0.73, .1, 1), + Channeling = DF:CreateColorTable (0, 1, 0, 1), + Finished = DF:CreateColorTable (0, 1, 0, 1), + NonInterruptible = DF:CreateColorTable (.7, .7, .7, 1), + Failed = DF:CreateColorTable (.4, .4, .4, 1), + Interrupted = DF:CreateColorTable (.965, .754, .154, 1), + }, + + --appearance + BackgroundColor = DF:CreateColorTable (.2, .2, .2, .8), + Texture = [[Interface\TargetingFrame\UI-StatusBar]], + BorderShieldWidth = 10, + BorderShieldHeight = 12, + BorderShieldCoords = {0.26171875, 0.31640625, 0.53125, 0.65625}, + BorderShieldTexture = 1300837, + SpellIconWidth = 10, + SpellIconHeight = 10, + ShieldIndicatorTexture = [[Interface\RaidFrame\Shield-Fill]], + ShieldGlowTexture = [[Interface\RaidFrame\Shield-Overshield]], + SparkTexture = [[Interface\CastingBar\UI-CastingBar-Spark]], + SparkWidth = 16, + SparkHeight = 16, + }, + + Initialize = function (self) + self.unit = "unutilized unit" + self.lazyUpdateCooldown = self.Settings.LazyUpdateCooldown + self.Colors = self.Settings.Colors + + self:SetUnit (nil) + PixelUtil.SetWidth (self, self.Settings.Width) + PixelUtil.SetHeight (self, self.Settings.Height) + + self.background:SetColorTexture (self.Settings.BackgroundColor:GetColor()) + self.background:SetAllPoints() + self.extraBackground:SetColorTexture (0, 0, 0, 1) + self.extraBackground:SetVertexColor (self.Settings.BackgroundColor:GetColor()) + self.extraBackground:SetAllPoints() + + self:SetTexture (self.Settings.Texture) + + self.BorderShield:SetPoint ("center", self, "left", 0, 0) + self.BorderShield:SetTexture (self.Settings.BorderShieldTexture) + self.BorderShield:SetTexCoord (unpack (self.Settings.BorderShieldCoords)) + self.BorderShield:SetSize (self.Settings.BorderShieldWidth, self.Settings.BorderShieldHeight) + + self.Icon:SetPoint ("center", self, "left", 2, 0) + self.Icon:SetSize (self.Settings.SpellIconWidth, self.Settings.SpellIconHeight) + + self.Spark:SetTexture (self.Settings.SparkTexture) + self.Spark:SetSize (self.Settings.SparkWidth, self.Settings.SparkHeight) + + self.percentText:SetPoint ("right", self, "right", -2, 0) + self.percentText:SetJustifyH ("right") + + self.fadeOutAnimation.alpha1:SetDuration (self.Settings.FadeOutTime) + self.fadeInAnimation.alpha1:SetDuration (self.Settings.FadeInTime) + end, + + SetDefaultColor = function (self, colorType, r, g, b, a) + assert (type (colorType) == "string", "DetailsFramework: CastBar:SetDefaultColor require a string in the first argument.") + self.Colors [colorType]:SetColor (r, g, b, a) + end, + + --> this get a color suggestion based on the type of cast being shown in the cast bar + GetCastColor = function (self) + if (not self.canInterrupt) then + return self.Colors.NonInterruptible + + elseif (self.channeling) then + return self.Colors.Channeling + + elseif (self.failed) then + return self.Colors.Failed + + elseif (self.interrupted) then + return self.Colors.Interrupted + + elseif (self.finished) then + return self.Colors.Finished + + else + return self.Colors.Casting + end + end, + + --> update all colors of the cast bar + UpdateCastColor = function (self) + local castColor = self:GetCastColor() + self:SetColor (castColor) --SetColor handles with ParseColors() + end, + + --> initial checks to know if this is a valid cast and should show the cast bar, if this fails the cast bar won't show + IsValid = function (self, unit, castName, isTradeSkill, ignoreVisibility) + if (not ignoreVisibility and not self:IsShown()) then + return false + end + + if (not self.Settings.ShowTradeSkills) then + if (isTradeSkill) then + return false + end + end + + if (not castName) then + return false + end + + return true + end, + + --> handle the interrupt state of the cast + --> this does not change the cast bar color because this function is called inside the start cast where is already handles the cast color + UpdateInterruptState = function (self) + if (self.Settings.ShowShield and not self.canInterrupt) then + self.BorderShield:Show() + else + self.BorderShield:Hide() + end + end, + + --> this check if the cast did reach 100% in the statusbar, mostly called from OnTick + CheckCastIsDone = function (self, event, isFinished) + + --> check max value + if (not isFinished and not self.finished) then + if (self.casting) then + if (self.value >= self.maxValue or self.value < 0) then + isFinished = true + end + + elseif (self.channeling) then + if (self.value > self.maxValue or self.value <= 0) then + isFinished = true + end + end + + --> check if passed an event + if (event) then + if (event == UNIT_SPELLCAST_STOP or event == UNIT_SPELLCAST_CHANNEL_STOP) then + isFinished = true + end + end + end + + --> the cast is finished + if (isFinished) then + self.finished = true + self:SetValue (self.maxValue) + self:UpdateCastColor() + self.Spark:Hide() + + --animations + self:Animation_FadeOut() + + return true + end + end, + + --> setup the castbar to be used by another unit + SetUnit = function (self, unit, displayedUnit) + if (self.unit ~= unit or self.displayedUnit ~= displayedUnit or unit == nil) then + self.unit = unit + self.displayedUnit = displayedUnit or unit + + --> reset the cast bar + self.casting = nil + self.channeling = nil + self.caninterrupt = nil + + --> register events + if (unit) then + for _, eventTable in ipairs (self.CastBarEvents) do + local event = eventTable [1] + local isUnitEvent = eventTable [2] + + if (isUnitEvent) then + self:RegisterUnitEvent (event, unit) + else + self:RegisterEvent (event) + end + end + + --> set scripts + self:SetScript ("OnEvent", self.OnEvent) + self:SetScript ("OnShow", self.OnShow) + self:SetScript ("OnHide", self.OnHide) + + if (self.Settings.CanTick) then + self:SetScript ("OnUpdate", self.OnTick) + end + + --> check is can show the cast time text + if (self.Settings.ShowCastTime and self.Settings.CanLazyTick) then + self.percentText:Show() + else + self.percentText:Hide() + end + + --> setup animtions + self:CancelScheduleToHide() + + --self:PLAYER_ENTERING_WORLD (unit, unit) + self:OnEvent ("PLAYER_ENTERING_WORLD", unit, unit) + + else + for _, eventTable in ipairs (self.CastBarEvents) do + local event = eventTable [1] + self:UnregisterEvent (event) + end + + --> register main events + self:SetScript ("OnUpdate", nil) + self:SetScript ("OnEvent", nil) + self:SetScript ("OnShow", nil) + self:SetScript ("OnHide", nil) + + self:Hide() + end + end + end, + + --> executed after a scheduled to hide timer is done + DoScheduledHide = function (timerObject) + timerObject.castBar.scheduledHideTime = nil + + --just to make sure it isn't casting + if (not timerObject.castBar.casting and not timerObject.castBar.channeling) then + timerObject.castBar:Animation_FadeOut() + end + end, + + HasScheduledHide = function (self) + return self.scheduledHideTime and not self.scheduledHideTime._cancelled + end, + + CancelScheduleToHide = function (self) + if (self:HasScheduledHide()) then + self.scheduledHideTime:Cancel() + end + end, + + --> after an interrupt, do not immediately hide the cast bar, let it up for short amount of time to give feedback to the player + ScheduleToHide = function (self, delay) + if (not delay) then + if (self.scheduledHideTime and not self.scheduledHideTime._cancelled) then + self.scheduledHideTime:Cancel() + end + + self.scheduledHideTime = nil + return + end + + --> already have a scheduled timer? + if (self.scheduledHideTime and not self.scheduledHideTime._cancelled) then + self.scheduledHideTime:Cancel() + end + + self.scheduledHideTime = C_Timer.NewTimer (delay, self.DoScheduledHide) + self.scheduledHideTime.castBar = self + end, + + OnHide = function (self) + --> just in case some other effects made it have a different alpha since SetUnit won't load if the unit is the same. + self:SetAlpha (1) + --> cancel any timer to hide scheduled + self:CancelScheduleToHide() + end, + + --> just update the current value if a spell is being cast since it wasn't running its tick function during the hide state + --> everything else should be in the correct state + OnShow = function (self) + self.flashTexture:Hide() + + if (self.unit) then + if (self.casting) then + local name, text, texture, startTime = UnitCastingInfo (self.unit) + if (name) then + self.value = GetTime() - self.spellStartTime + end + + self:RunHooksForWidget ("OnShow", self, self.unit) + + elseif (self.channeling) then + local name, text, texture, endTime = UnitChannelInfo (self.unit) + if (name) then + self.value = self.spellEndTime - GetTime() + end + + self:RunHooksForWidget ("OnShow", self, self.unit) + end + end + end, + + OnEvent = function (self, event, ...) + CalcPerformance ("event", event) + CalcPerformance ("call", "CastBar-OnEvent") + + DF_CalcCpuUsage ("CastBar-OnEvent") + + local arg1 = ... + local unit = self.unit + + if (event == "PLAYER_ENTERING_WORLD") then + local newEvent = self.PLAYER_ENTERING_WORLD (self, unit, ...) + if (newEvent) then + self.OnEvent (self, newEvent, unit) + DF_CalcCpuUsage ("CastBar-OnEvent") + return + end + + elseif (arg1 ~= unit) then + DF_CalcCpuUsage ("CastBar-OnEvent") + return + end + + local eventFunc = self [event] + if (eventFunc) then + eventFunc (self, unit, ...) + end + DF_CalcCpuUsage ("CastBar-OnEvent") + end, + + OnTick_LazyTick = function (self) + --> run the lazy tick if allowed + if (self.Settings.CanLazyTick) then + --> update the cast time + if (self.Settings.ShowCastTime) then + if (self.casting) then + self.percentText:SetText (format ("%.1f", abs (self.value - self.maxValue))) + + elseif (self.channeling) then + local remainingTime = abs (self.value) + if (remainingTime > 999) then + self.percentText:SetText ("") + else + self.percentText:SetText (format ("%.1f", remainingTime)) + end + else + self.percentText:SetText ("") + end + end + + return true + else + return false + end + end, + + --> tick function for regular casts + OnTick_Casting = function (self, deltaTime) + self.value = self.value + deltaTime + + if (self:CheckCastIsDone()) then + return + else + self:SetValue (self.value) + end + + --update spark position + local sparkPosition = self.value / self.maxValue * self:GetWidth() + self.Spark:SetPoint ("center", self, "left", sparkPosition, 0) + + --in order to allow the lazy tick run, it must return true, it tell that the cast didn't finished + return true + end, + + --> tick function for channeling casts + OnTick_Channeling = function (self, deltaTime) + self.value = self.value - deltaTime + + if (self:CheckCastIsDone()) then + return + else + self:SetValue (self.value) + end + + --update spark position + local sparkPosition = self.value / self.maxValue * self:GetWidth() + self.Spark:SetPoint ("center", self, "left", sparkPosition, 0) + + return true + end, + + OnTick = function (self, deltaTime) + DF_CalcCpuUsage ("CastBar-OnTick") + if (self.casting) then + if (not self:OnTick_Casting (deltaTime)) then + DF_CalcCpuUsage ("CastBar-OnTick") + return + end + + --lazy tick + self.lazyUpdateCooldown = self.lazyUpdateCooldown - deltaTime + if (self.lazyUpdateCooldown < 0) then + self:OnTick_LazyTick() + self.lazyUpdateCooldown = self.Settings.LazyUpdateCooldown + end + + elseif (self.channeling) then + if (not self:OnTick_Channeling (deltaTime)) then + DF_CalcCpuUsage ("CastBar-OnTick") + return + end + + --lazy tick + self.lazyUpdateCooldown = self.lazyUpdateCooldown - deltaTime + if (self.lazyUpdateCooldown < 0) then + self:OnTick_LazyTick() + self.lazyUpdateCooldown = self.Settings.LazyUpdateCooldown + end + end + DF_CalcCpuUsage ("CastBar-OnTick") + end, + + --> animation start script + Animation_FadeOutStarted = function (self) + + end, + + --> animation finished script + Animation_FadeOutFinished = function (self) + local castBar = self:GetParent() + castBar:SetAlpha (1) + castBar:Hide() + end, + + --> animation start script + Animation_FadeInStarted = function (self) + + end, + + --> animation finished script + Animation_FadeInFinished = function (self) + local castBar = self:GetParent() + castBar:Show() + castBar:SetAlpha (1) + end, + + --> animation calls + Animation_FadeOut = function (self) + self:ScheduleToHide (false) + + if (self.fadeInAnimation:IsPlaying()) then + self.fadeInAnimation:Stop() + end + + if (not self.fadeOutAnimation:IsPlaying()) then + self.fadeOutAnimation:Play() + end + end, + + Animation_FadeIn = function (self) + self:ScheduleToHide (false) + + if (self.fadeOutAnimation:IsPlaying()) then + self.fadeOutAnimation:Stop() + end + + if (not self.fadeInAnimation:IsPlaying()) then + self.fadeInAnimation:Play() + end + end, + + Animation_Flash = function (self) + if (not self.flashAnimation:IsPlaying()) then + self.flashAnimation:Play() + end + end, + + Animation_StopAllAnimations = function (self) + if (self.flashAnimation:IsPlaying()) then + self.flashAnimation:Stop() + end + + if (self.fadeOutAnimation:IsPlaying()) then + self.fadeOutAnimation:Stop() + end + + if (self.fadeInAnimation:IsPlaying()) then + self.fadeInAnimation:Stop() + end + end, + + PLAYER_ENTERING_WORLD = function (self, unit, arg1) + local isChannel = UnitChannelInfo (unit) + local isRegularCast = UnitCastingInfo (unit) + + if (isChannel) then + self.channeling = true + return self.unit == arg1 and "UNIT_SPELLCAST_CHANNEL_START" + + elseif (isRegularCast) then + self.casting = true + return self.unit == arg1 and "UNIT_SPELLCAST_START" + + else + self.casting = nil + self.channeling = nil + self.failed = nil + self.finished = nil + self.interrupted = nil + self.Spark:Hide() + self:Hide() + end + end, + + UNIT_SPELLCAST_START = function (self, unit) + local name, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID = UnitCastingInfo (unit) + + --> is valid? + if (not self:IsValid (unit, name, isTradeSkill, true)) then + return + end + + --> setup cast + self.casting = true + self.channeling = nil + self.interrupted = nil + self.failed = nil + self.finished = nil + self.canInterrupt = not notInterruptible + self.spellID = spellID + self.castID = castID + self.spellName = name + self.spellTexture = texture + self.spellStartTime = startTime / 1000 + self.spellEndTime = endTime / 1000 + self.value = GetTime() - self.spellStartTime + self.maxValue = self.spellEndTime - self.spellStartTime + + self:SetMinMaxValues (0, self.maxValue) + self:SetValue (self.value) + self:SetAlpha (1) + self.Icon:SetTexture (texture) + self.Icon:Show() + self.Text:SetText (text) + + if (self.Settings.ShowCastTime and self.Settings.CanLazyTick) then + self.percentText:Show() + end + + self.flashTexture:Hide() + self:Animation_StopAllAnimations() + + if (not self:IsShown()) then + self:Animation_FadeIn() + end + + self.Spark:Show() + self:SetAlpha (1) + self:Show() + + --> set the statusbar color + self:UpdateCastColor() + + --> update the interrupt cast border + self:UpdateInterruptState() + + self:RunHooksForWidget ("OnCastStart", self, self.unit, "UNIT_SPELLCAST_START") + end, + + UNIT_SPELLCAST_CHANNEL_START = function (self, unit, ...) + local name, text, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID = UnitChannelInfo (unit) + + --> is valid? + if (not self:IsValid (unit, name, isTradeSkill, true)) then + return + end + + --> setup cast + self.casting = nil + self.channeling = true + self.interrupted = nil + self.failed = nil + self.finished = nil + self.canInterrupt = not notInterruptible + self.spellID = spellID + self.castID = castID + self.spellName = name + self.spellTexture = texture + self.spellStartTime = startTime / 1000 + self.spellEndTime = endTime / 1000 + self.value = self.spellEndTime - GetTime() + self.maxValue = self.spellEndTime - self.spellStartTime + + self:SetMinMaxValues (0, self.maxValue) + self:SetValue (self.value) + + self:SetAlpha (1) + self.Icon:SetTexture (texture) + self.Icon:Show() + self.Text:SetText (text) + + if (self.Settings.ShowCastTime and self.Settings.CanLazyTick) then + self.percentText:Show() + end + + self.flashTexture:Hide() + self:Animation_StopAllAnimations() + + if (not self:IsShown()) then + self:Animation_FadeIn() + end + + self.Spark:Show() + self:SetAlpha (1) + self:Show() + + --> set the statusbar color + self:UpdateCastColor() + + --> update the interrupt cast border + self:UpdateInterruptState() + + self:RunHooksForWidget ("OnCastStart", self, self.unit, "UNIT_SPELLCAST_CHANNEL_START") + end, + + UNIT_SPELLCAST_STOP = function (self, unit, ...) + local unitID, castID, spellID = ... + + if (self.castID == castID) then + self.Spark:Hide() + self.percentText:Hide()self.percentText:Hide() + self:SetValue (self.maxValue or select (2, self:GetMinMaxValues()) or 1) + + self.casting = nil + self.finished = true + + if (not self:HasScheduledHide()) then + --> check if settings has no fade option or if its parents are not visible + if (self.Settings.NoFadeEffects or not self:IsVisible()) then + self:Hide() + else + self:Animation_Flash() + self:Animation_FadeOut() + end + end + end + end, + + UNIT_SPELLCAST_CHANNEL_STOP = function (self, unit, ...) + local unitID, castGUID, spellID = ... + + if (self.channeling) then + self.Spark:Hide() + self.percentText:Hide() + self:SetValue (self.maxValue or select (2, self:GetMinMaxValues()) or 1) + + self.channeling = nil + self.finished = true + + if (not self:HasScheduledHide()) then + --> check if settings has no fade option or if its parents are not visible + if (self.Settings.NoFadeEffects or not self:IsVisible()) then + self:Hide() + else + self:Animation_Flash() + self:Animation_FadeOut() + end + end + end + end, + + UNIT_SPELLCAST_FAILED = function (self, unit, ...) + local unitID, castID, spellID = ... + + if (self.casting and castID == self.castID and not self.fadeOut) then + self.casting = nil + self.channeling = nil + self.failed = true + self.finished = true + self:SetValue (self.maxValue or select (2, self:GetMinMaxValues()) or 1) + + --> set the statusbar color + self:UpdateCastColor() + + self.Spark:Hide() + self.percentText:Hide() + self.Text:SetText (FAILED) --> auto locale within the global namespace + + self:ScheduleToHide (1) + end + end, + + UNIT_SPELLCAST_INTERRUPTED = function (self, unit, ...) + local unitID, castID, spellID = ... + + if (self.casting and castID == self.castID and not self.fadeOut) then + self.casting = nil + self.channeling = nil + self.interrupted = true + self.finished = true + self:SetValue (self.maxValue or select (2, self:GetMinMaxValues()) or 1) + + local castColor = self:GetCastColor() + self:SetColor (castColor) --SetColor handles with ParseColors() + + self.Spark:Hide() + self.percentText:Hide() + self.Text:SetText (INTERRUPTED) --> auto locale within the global namespace + + self:ScheduleToHide (1) + end + end, + + UNIT_SPELLCAST_DELAYED = function (self, unit, ...) + local name, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible = UnitCastingInfo (unit) + + if (not self:IsValid (unit, name, isTradeSkill)) then + return + end + + --> update the cast time + self.spellStartTime = startTime / 1000 + self.spellEndTime = endTime / 1000 + self.value = GetTime() - self.spellStartTime + self.maxValue = self.spellEndTime - self.spellStartTime + self:SetMinMaxValues (0, self.maxValue) + end, + + UNIT_SPELLCAST_CHANNEL_UPDATE = function (self, unit, ...) + local name, text, texture, startTime, endTime, isTradeSkill = UnitChannelInfo (unit) + + if (not self:IsValid (unit, name, isTradeSkill)) then + return + end + + --> update the cast time + self.spellStartTime = startTime / 1000 + self.spellEndTime = endTime / 1000 + self.value = self.spellEndTime - GetTime() + self.maxValue = self.spellEndTime - self.spellStartTime + self:SetMinMaxValues (0, self.maxValue) + self:SetValue (self.value) + end, + + --> cast changed its state to interruptable + UNIT_SPELLCAST_INTERRUPTIBLE = function (self, unit, ...) + self.canInterrupt = true + self:UpdateCastColor() + self:UpdateInterruptState() + end, + + --> cast changed its state to non interruptable + UNIT_SPELLCAST_NOT_INTERRUPTIBLE = function (self, unit, ...) + self.canInterrupt = false + self:UpdateCastColor() + self:UpdateInterruptState() + end, + +} + +-- ~castbar +function DF:CreateCastBar (parent, name, settingsOverride) + + assert (name or parent:GetName(), "DetailsFramework:CreateCastBar parameter 'name' omitted and parent has no name.") + + local castBar = CreateFrame ("StatusBar", name or (parent:GetName() .. "CastBar"), parent) + + do --layers + + --these widgets was been made with back compatibility in mind + --they are using the same names as the retail game uses on the nameplate castbar + --this should make Plater core and Plater scripts made by users compatible with the new unit frame made on the framework + + --background + castBar.background = castBar:CreateTexture (nil, "background") + castBar.background:SetDrawLayer ("background", -6) + + castBar.extraBackground = castBar:CreateTexture (nil, "background") + castBar.extraBackground:SetDrawLayer ("background", -5) + + --overlay + castBar.Text = castBar:CreateFontString (nil, "overlay", "SystemFont_Shadow_Small") + castBar.Text:SetPoint ("center", 0, 0) + castBar.Text:SetDrawLayer ("overlay", 1) + + castBar.BorderShield = castBar:CreateTexture (nil, "overlay") + castBar.BorderShield:SetDrawLayer ("overlay", 2) + castBar.BorderShield:Hide() + + castBar.Icon = castBar:CreateTexture (nil, "overlay") + castBar.Icon:SetDrawLayer ("overlay", 1) + castBar.Icon:Hide() + + castBar.Spark = castBar:CreateTexture (nil, "overlay") + castBar.Spark:SetBlendMode ("ADD") + + --time left on the cast + castBar.percentText = castBar:CreateFontString (nil, "overlay", "SystemFont_Shadow_Small") + castBar.percentText:SetDrawLayer ("overlay", 7) + + --statusbar texture + castBar.barTexture = castBar:CreateTexture (nil, "artwork") + castBar:SetStatusBarTexture (castBar.barTexture) + + --animations fade in and out + local fadeOutAnimationHub = DF:CreateAnimationHub (castBar, DF.CastFrameFunctions.Animation_FadeOutStarted, DF.CastFrameFunctions.Animation_FadeOutFinished) + fadeOutAnimationHub.alpha1 = DF:CreateAnimation (fadeOutAnimationHub, "ALPHA", 1, 1, 1, 0) + castBar.fadeOutAnimation = fadeOutAnimationHub + + local fadeInAnimationHub = DF:CreateAnimationHub (castBar, DF.CastFrameFunctions.Animation_FadeInStarted, DF.CastFrameFunctions.Animation_FadeInFinished) + fadeInAnimationHub.alpha1 = DF:CreateAnimation (fadeInAnimationHub, "ALPHA", 1, 0.150, 0, 1) + castBar.fadeInAnimation = fadeInAnimationHub + + --animatios flash + local flashTexture = castBar:CreateTexture (nil, "overlay") + flashTexture:SetDrawLayer ("overlay", 7) + flashTexture:SetColorTexture (1, 1, 1, 1) + flashTexture:SetAllPoints() + flashTexture:SetAlpha (0) + flashTexture:Hide() + flashTexture:SetBlendMode ("ADD") + castBar.flashTexture = flashTexture + + local flashAnimationHub = DF:CreateAnimationHub (flashTexture, function() flashTexture:Show() end, function() flashTexture:Hide() end) + DF:CreateAnimation (flashAnimationHub, "ALPHA", 1, 0.2, 0, 0.8) + DF:CreateAnimation (flashAnimationHub, "ALPHA", 2, 0.2, 1, 0) + castBar.flashAnimation = flashAnimationHub + end + + --> mixins + DF:Mixin (castBar, DF.CastFrameFunctions) + DF:Mixin (castBar, DF.StatusBarFunctions) + + --> settings and hooks + local settings = DF.table.copy ({}, DF.CastFrameFunctions.Settings) + if (settingsOverride) then + DF.table.copy (settings, settingsOverride) + end + castBar.Settings = settings + + local hookList = DF.table.copy ({}, DF.CastFrameFunctions.HookList) + castBar.HookList = hookList + + --> initialize the cast bar + castBar:Initialize() + + return castBar +end + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +--> border frame + +--[=[ + DF:CreateBorderFrame (parent, name) + creates a frame with 4 child textures attached to each one of the 4 sides of a frame + @parent = parent frame to pass to CreateFrame function + @name = name of the frame, if omitted a random name is created +--]=] + +DF.BorderFunctions = { + SetBorderColor = function (self, r, g, b, a) + r, g, b, a = DF:ParseColors (r, g, b, a) + for _, texture in ipairs (self.allTextures) do + texture:SetVertexColor (r, g, b, a) + end + end, + + SetBorderThickness = function (self, newThickness) + PixelUtil.SetWidth (f.leftBorder, newThickness, newThickness) + PixelUtil.SetWidth (f.rightBorder, newThickness, newThickness) + PixelUtil.SetHeight (f.topBorder, newThickness, newThickness) + PixelUtil.SetHeight (f.bottomBorder, newThickness, newThickness) + end, + + WidgetType = "border", +} + +-- ~borderframe +function DF:CreateBorderFrame (parent, name) + + local parentName = name or "DetailsFrameworkBorderFrame" .. tostring (math.random (1, 100000000)) + + local f = CreateFrame ("frame", parentName, parent) + f:SetFrameLevel (f:GetFrameLevel()+1) + f:SetAllPoints() + + DF:Mixin (f, DF.BorderFunctions) + + f.allTextures = {} + + --> create left border + local leftBorder = f:CreateTexture (nil, "overlay") + leftBorder:SetDrawLayer ("overlay", 7) + leftBorder:SetColorTexture (1, 1, 1, 1) + tinsert (f.allTextures, leftBorder) + f.leftBorder = leftBorder + PixelUtil.SetPoint (leftBorder, "topright", f, "topleft", 0, 1, 0, 1) + PixelUtil.SetPoint (leftBorder, "bottomright", f, "bottomleft", 0, -1, 0, -1) + PixelUtil.SetWidth (leftBorder, 1, 1) + + --> create right border + local rightBorder = f:CreateTexture (nil, "overlay") + rightBorder:SetDrawLayer ("overlay", 7) + rightBorder:SetColorTexture (1, 1, 1, 1) + tinsert (f.allTextures, rightBorder) + f.rightBorder = rightBorder + PixelUtil.SetPoint (rightBorder, "topleft", f, "topright", 0, 1, 0, 1) + PixelUtil.SetPoint (rightBorder, "bottomleft", f, "bottomright", 0, -1, 0, -1) + PixelUtil.SetWidth (rightBorder, 1, 1) + + --> create top border + local topBorder = f:CreateTexture (nil, "overlay") + topBorder:SetDrawLayer ("overlay", 7) + topBorder:SetColorTexture (1, 1, 1, 1) + tinsert (f.allTextures, topBorder) + f.topBorder = topBorder + PixelUtil.SetPoint (topBorder, "bottomleft", f, "topleft", 0, 0, 0, 0) + PixelUtil.SetPoint (topBorder, "bottomright", f, "topright", 0, 0, 0, 0) + PixelUtil.SetHeight (topBorder, 1, 1) + + --> create border + local bottomBorder = f:CreateTexture (nil, "overlay") + bottomBorder:SetDrawLayer ("overlay", 7) + bottomBorder:SetColorTexture (1, 1, 1, 1) + tinsert (f.allTextures, bottomBorder) + f.bottomBorder = bottomBorder + PixelUtil.SetPoint (bottomBorder, "topleft", f, "bottomleft", 0, 0, 0, 0) + PixelUtil.SetPoint (bottomBorder, "topright", f, "bottomright", 0, 0, 0, 0) + PixelUtil.SetHeight (bottomBorder, 1, 1) + + return f +end + + + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +--> unit frame + +--[=[ + DF:CreateUnitFrame (parent, name, settingsOverride) + creates a very basic unit frame with a healthbar, castbar and power bar + each unit frame has a .Settings table which isn't shared among other unit frames created with this method + all members names are the same as the unit frame from the retail game + + @parent = frame to pass for the CreateFrame function + @name = absolute name of the frame, if omitted a random name is created + @settingsOverride = table with keys and values to replace the defaults from the framework + +--]=] + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +--> unit frame + + --> return true if the unit has been claimed by another player (health bar is gray) + local unit_is_tap_denied = function (unit) + return unit and not UnitPlayerControlled (unit) and UnitIsTapDenied (unit) + end + + DF.UnitFrameFunctions = { + + WidgetType = "unitFrame", + + Settings = { + --> unit frames + ClearUnitOnHide = true, --> if tue it'll set the unit to nil when the unit frame is set to hide + ShowCastBar = true, --if this is false, the cast bar for the unit won't be shown + ShowPowerBar = true, --if true it'll show the power bar for the unit, e.g. the mana bar + ShowUnitName = true, --if false, the unit name won't show + ShowBorder = true, --if false won't show the border frame + + --> health bar color + CanModifyHealhBarColor = true, --> if false it won't change the color of the health bar + ColorByAggro = false, --if true it'll color the healthbar with red color when the unit has aggro on player + FixedHealthColor = false, --color override with a table {r=1, g=1, b=1} + UseFriendlyClassColor = true, --make the healthbar class color for friendly players + UseEnemyClassColor = true, --make the healthbar class color for enemy players + + --> misc + ShowTargetOverlay = true, --shows a highlighht for the player current target + BorderColor = DF:CreateColorTable (0, 0, 0, 1), --border color, set to alpha zero for no border + CanTick = false, --if true it'll run the OnTick event + + --> size + Width = 100, + Height = 20, + PowerBarHeight = 4, + CastBarHeight = 8, + }, + + UnitFrameEvents = { + --> run for all units + {"PLAYER_ENTERING_WORLD"}, + {"PARTY_MEMBER_DISABLE"}, + {"PARTY_MEMBER_ENABLE"}, + {"PLAYER_TARGET_CHANGED"}, + + --> run for one unit + {"UNIT_NAME_UPDATE", true}, + {"UNIT_CONNECTION", true}, + {"UNIT_ENTERED_VEHICLE", true}, + {"UNIT_EXITED_VEHICLE", true}, + {"UNIT_PET", true}, + {"UNIT_THREAT_LIST_UPDATE", true}, + }, + + --> used when a event is triggered to quickly check if is a unit event + IsUnitEvent = { + ["UNIT_NAME_UPDATE"] = true, + ["UNIT_CONNECTION"] = true, + ["UNIT_ENTERED_VEHICLE"] = true, + ["UNIT_EXITED_VEHICLE"] = true, + ["UNIT_PET"] = true, + ["UNIT_THREAT_LIST_UPDATE"] = true, + }, + + Initialize = function (self) + self.border:SetBorderColor (self.Settings.BorderColor) + + PixelUtil.SetWidth (self, self.Settings.Width, 1) + PixelUtil.SetHeight (self, self.Settings.Height, 1) + + PixelUtil.SetPoint (self.powerBar, "bottomleft", self, "bottomleft", 0, 0, 1, 1) + PixelUtil.SetPoint (self.powerBar, "bottomright", self, "bottomright", 0, 0, 1, 1) + PixelUtil.SetHeight (self.powerBar, self.Settings.PowerBarHeight, 1) + + --make the castbar overlap the powerbar + PixelUtil.SetPoint (self.castBar, "bottomleft", self, "bottomleft", 0, 0, 1, 1) + PixelUtil.SetPoint (self.castBar, "bottomright", self, "bottomright", 0, 0, 1, 1) + PixelUtil.SetHeight (self.castBar, self.Settings.CastBarHeight, 1) + end, + + SetHealthBarColor = function (self, r, g, b, a) + self.healthBar:SetColor (r, g, b, a) + end, + + --> register all events which will be used by the unit frame + RegisterEvents = function (self) + --> register events + for index, eventTable in ipairs (self.UnitFrameEvents) do + local event, isUnitEvent = unpack (eventTable) + if (not isUnitEvent) then + self:RegisterEvent (event) + else + self:RegisterUnitEvent (event, self.unit, self.displayedUnit ~= unit and self.displayedUnit or nil) + end + end + + --> check settings and unregister events for disabled features + if (not self.Settings.ColorByAggro) then + self:UnregisterEvent ("UNIT_THREAT_LIST_UPDATE") + end + + --> set scripts + self:SetScript ("OnEvent", self.OnEvent) + self:SetScript ("OnHide", self.OnHide) + + if (self.Settings.CanTick) then + self:SetScript ("OnUpdate", self.OnTick) + end + end, + + --> unregister events, called when this unit frame losses its unit + UnregisterEvents = function (self) + for index, eventTable in ipairs (self.UnitFrameEvents) do + local event, firstUnit, secondUnit = unpack (eventTable) + self:UnregisterEvent (event) + end + + self:SetScript ("OnEvent", nil) + self:SetScript ("OnUpdate", nil) + self:SetScript ("OnHide", nil) + end, + + --> call every tick + OnTick = function (self, deltaTime) end, --if overrided, set 'CanTick' to true on the settings table + + --> when an event happen for this unit, send it to the apropriate function + OnEvent = function (self, event, ...) + --> run the function for this event + DF_CalcCpuUsage ("unitFrame-OnEvent") + local eventFunc = self [event] + if (eventFunc) then + --> is this event an unit event? + if (self.IsUnitEvent [event]) then + local unit = ... + --> check if is for this unit (even if the event is registered only for the unit) + if (unit == self.unit or unit == self.displayedUnit) then + eventFunc (self, ...) + end + else + eventFunc (self, ...) + end + end + DF_CalcCpuUsage ("unitFrame-OnEvent") + end, + + OnHide = function (self) + if (self.Settings.ClearUnitOnHide) then + self:SetUnit (nil) + end + end, + + --> run if the unit currently shown is different than the new one + SetUnit = function (self, unit) + if (unit ~= self.unit or unit == nil) then + self.unit = unit --absolute unit + self.displayedUnit = unit --~todo rename to 'displayedUnit' for back compatibility with older scripts in Plater + self.unitInVehicle = nil --true when the unit is in a vehicle + + if (unit) then + self:RegisterEvents() + + self.healthBar:SetUnit (unit, self.displayedUnit) + + --> is using castbars? + if (self.Settings.ShowCastBar) then + self.castBar:SetUnit (unit, self.displayedUnit) + else + self.castBar:SetUnit (nil) + end + + --> is using powerbars? + if (self.Settings.ShowPowerBar) then + self.powerBar:SetUnit (unit, self.displayedUnit) + else + self.powerBar:SetUnit (nil) + end + + --> is using the border? + if (self.Settings.ShowBorder) then + self.border:Show() + else + self.border:Hide() + end + else + self:UnregisterEvents() + self.healthBar:SetUnit (nil) + self.castBar:SetUnit (nil) + self.powerBar:SetUnit (nil) + end + + self:UpdateUnitFrame() + end + end, + + --> if the unit is controlling a vehicle, need to show the vehicle instead + --> .unit and .displayedUnit is always the same execept when the unit is controlling a vehicle, then .displayedUnit is the unitID for the vehicle + --> todo: see what 'UnitTargetsVehicleInRaidUI' is, there's a call for this in the CompactUnitFrame.lua but zero documentation + CheckVehiclePossession = function (self) + --> this unit is possessing a vehicle? + local unitPossessVehicle = UnitHasVehicleUI (self.unit) + if (unitPossessVehicle) then + if (not self.unitInVehicle) then + if (UnitIsUnit ("player", self.unit)) then + self.displayedUnit = "vehicle" + self.unitInVehicle = true + self:RegisterEvents() + self:UpdateAllWidgets() + return true + end + + local prefix, id, suffix = string.match (self.unit, "([^%d]+)([%d]*)(.*)") --CompactUnitFrame.lua + local vehicleUnitID = prefix .. "pet" .. id .. suffix + if (UnitExists (vehicleUnitID)) then + self.displayedUnit = vehicleUnitID + self.unitInVehicle = true + self:RegisterEvents() + self:UpdateAllWidgets() + return true + end + end + end + + if (self.unitInVehicle) then + self.displayedUnit = self.unit + self.unitInVehicle = nil + self:RegisterEvents() + self:UpdateAllWidgets() + end + end, + + --> find a color for the health bar, if a color has been passed in the arguments use it instead, 'CanModifyHealhBarColor' must be true for this function run + UpdateHealthColor = function (self, r, g, b) + + --> check if color changes is disabled + if (not self.Settings.CanModifyHealhBarColor) then + return + end + + local unit = self.displayedUnit + + --> check if a color has been passed within the parameters + if (r) then + --> check if passed a special color + if (type (r) ~= "number") then + r, g, b = DF:ParseColors (r) + end + + self:SetHealthBarColor (r, g, b) + return + end + + --> check if there is a color override in the settings + if (self.Settings.FixedHealthColor) then + local FixedHealthColor = self.Settings.FixedHealthColor + r, g, b = FixedHealthColor.r, FixedHealthColor.g, FixedHealthColor.b + self:SetHealthBarColor (r, g, b) + return + end + + --> check if the unit is a player + if (UnitIsPlayer (unit)) then + + --> check if the unit is disconnected (in case it is a player + if (not UnitIsConnected (unit)) then + self:SetHealthBarColor (.5, .5, .5) + return + end + + --is a friendly or enemy player? + if (UnitIsFriend ("player", unit)) then + if (self.Settings.UseFriendlyClassColor) then + local _, className = UnitClass (unit) + if (className) then + local classColor = RAID_CLASS_COLORS [className] + if (classColor) then + self:SetHealthBarColor (classColor.r, classColor.g, classColor.b) + return + end + end + else + self:SetHealthBarColor (0, 1, 0) + return + end + else + if (self.Settings.UseEnemyClassColor) then + local _, className = UnitClass (unit) + if (className) then + local classColor = RAID_CLASS_COLORS [className] + if (classColor) then + self:SetHealthBarColor (classColor.r, classColor.g, classColor.b) + return + end + end + else + self:SetHealthBarColor (1, 0, 0) + return + end + end + end + + --> is tapped? + if (unit_is_tap_denied (unit)) then + self:SetHealthBarColor (.6, .6, .6) + return + end + + --> is this is a npc attacking the player? + if (self.Settings.ColorByAggro) then + local _, threatStatus = UnitDetailedThreatSituation ("player", unit) + if (threatStatus) then + self:SetHealthBarColor (1, 0, 0) + return + end + end + + --> get the regular color by selection + r, g, b = UnitSelectionColor (unit) + self:SetHealthBarColor (r, g, b) + end, + + --> misc + UpdateName = function (self) + if (not self.Settings.ShowUnitName) then + self.unitName:Hide() + return + end + + --unit name without realm names by default + local name = UnitName (self.unit) + self.unitName:SetText (name) + self.unitName:Show() + end, + + --> this runs when the player it self changes its target, need to update the current target overlay + --> todo: add focus overlay + UpdateTargetOverlay = function (self) + if (not self.Settings.ShowTargetOverlay) then + self.targetOverlay:Hide() + return + end + + if (UnitIsUnit (self.displayedUnit, "target")) then + self.targetOverlay:Show() + else + self.targetOverlay:Hide() + end + end, + + UpdateAllWidgets = function (self) + if (UnitExists (self.displayedUnit)) then + local unit = self.unit + local displayedUnit = self.displayedUnit + + self:SetUnit (unit, displayedUnit) + + --> is using castbars? + if (self.Settings.ShowCastBar) then + self.castBar:SetUnit (unit, displayedUnit) + end + + --> is using powerbars? + if (self.Settings.ShowPowerBar) then + self.powerBar:SetUnit (unit, displayedUnit) + end + + self:UpdateName() + self:UpdateTargetOverlay() + self:UpdateHealthColor() + end + end, + + --> update the unit frame and its widgets + UpdateUnitFrame = function (self) + local unitInVehicle = self:CheckVehiclePossession() + + --> if the unit is inside a vehicle, the vehicle possession function will call an update on all widgets + if (not unitInVehicle) then + self:UpdateAllWidgets() + end + end, + + --> event handles + PLAYER_ENTERING_WORLD = function (self, ...) + self:UpdateUnitFrame() + end, + + --> update overlays when the player changes its target + PLAYER_TARGET_CHANGED = function (self, ...) + self:UpdateTargetOverlay() + end, + + --> unit received a name update + UNIT_NAME_UPDATE = function (self, ...) + self:UpdateName() + end, + + --> this is registered only if .settings.ColorByAggro is true + UNIT_THREAT_LIST_UPDATE = function (self, ...) + if (self.Settings.ColorByAggro) then + self:UpdateHealthColor() + end + end, + + --> vehicle + UNIT_ENTERED_VEHICLE = function (self, ...) + self:UpdateUnitFrame() + end, + UNIT_EXITED_VEHICLE = function (self, ...) + self:UpdateUnitFrame() + end, + + --> pet + UNIT_PET = function (self, ...) + self:UpdateUnitFrame() + end, + + --> player connection + UNIT_CONNECTION = function (self, ...) + if (UnitIsConnected (self.unit)) then + self:UpdateUnitFrame() + end + end, + PARTY_MEMBER_ENABLE = function (self, ...) + if (UnitIsConnected (self.unit)) then + self:UpdateName() + end + end, + } + +-- ~unitframe +function DF:CreateUnitFrame (parent, name, unitFrameSettingsOverride, healthBarSettingsOverride, castBarSettingsOverride, powerBarSettingsOverride) + + local parentName = name or ("DetailsFrameworkUnitFrame" .. tostring (math.random (1, 100000000))) + + --> create the main unit frame + local f = CreateFrame ("button", parentName, parent) + + --> base level + local baseFrameLevel = f:GetFrameLevel() + + --> create the healthBar + local healthBar = DF:CreateHealthBar (f, false, healthBarSettingsOverride) + healthBar:SetFrameLevel (baseFrameLevel + 1) + f.healthBar = healthBar + + --> create the power bar + local powerBar = DF:CreatePowerBar (f, false, powerBarSettingsOverride) + powerBar:SetFrameLevel (baseFrameLevel + 2) + f.powerBar = powerBar + + --> create the castBar + local castBar = DF:CreateCastBar (f, false, castBarSettingsOverride) + castBar:SetFrameLevel (baseFrameLevel + 3) + f.castBar = castBar + + --> border frame + local borderFrame = DF:CreateBorderFrame (f, f:GetName() .. "Border") + borderFrame:SetFrameLevel (f:GetFrameLevel() + 5) + f.border = borderFrame + + --> overlay frame (widgets that need to stay above the unit frame) + local overlayFrame = CreateFrame ("frame", "$parentOverlayFrame", f) + borderFrame:SetFrameLevel (f:GetFrameLevel() + 6) + f.overlayFrame = overlayFrame + + --> unit frame layers + do + --artwork + f.unitName = f:CreateFontString (nil, "artwork", "GameFontHighlightSmall") + PixelUtil.SetPoint (f.unitName, "topleft", healthBar, "topleft", 2, -2, 1, 1) + + --target overlay - it's parented in the healthbar so other widgets won't get the overlay + f.targetOverlay = overlayFrame:CreateTexture (nil, "artwork") + f.targetOverlay:SetTexture (healthBar:GetTexture()) + f.targetOverlay:SetBlendMode ("ADD") + f.targetOverlay:SetAlpha (.5) + f.targetOverlay:SetAllPoints (healthBar) + end + + --> mixins + --inject mixins + DF:Mixin (f, DF.UnitFrameFunctions) + + --create the settings table and copy the overrides into it, the table is set into the frame after the mixin + local unitFrameSettings = DF.table.copy ({}, DF.UnitFrameFunctions.Settings) + if (unitFrameSettingsOverride) then + unitFrameSettings = DF.table.copy (unitFrameSettings, unitFrameSettingsOverride) + end + f.Settings = unitFrameSettings + + --> initialize scripts + --unitframe + f:Initialize() + + return f +end + - - - - - - - - ---functionn falsee truee breakk elsea \ No newline at end of file +--functionn falsee truee breakk elsea endz \ No newline at end of file diff --git a/Libs/DF/slider.lua b/Libs/DF/slider.lua index b2cd3a82..70d8caca 100644 --- a/Libs/DF/slider.lua +++ b/Libs/DF/slider.lua @@ -729,6 +729,8 @@ local DFSliderMetaFunctions = _G [DF.GlobalWidgetControlNames ["slider"]] table_remove (slider.MyObject.previous_value, 4) local capsule = slider.MyObject + + --some plugins registered OnValueChanged and others with OnValueChange local kill = capsule:RunHooksForWidget ("OnValueChanged", slider, capsule.FixedValue, amt, capsule) if (kill) then return @@ -736,7 +738,7 @@ local DFSliderMetaFunctions = _G [DF.GlobalWidgetControlNames ["slider"]] local kill = capsule:RunHooksForWidget ("OnValueChange", slider, capsule.FixedValue, amt, capsule) if (kill) then return - end + end if (slider.MyObject.OnValueChanged) then slider.MyObject.OnValueChanged (slider, slider.MyObject.FixedValue, amt) @@ -752,6 +754,7 @@ local DFSliderMetaFunctions = _G [DF.GlobalWidgetControlNames ["slider"]] slider.amt:SetText (math.floor (amt)) end slider.MyObject.ivalue = amt + end ------------------------------------------------------------------------------------------------------------ diff --git a/boot.lua b/boot.lua index 1c15dc7c..6d129c2d 100644 --- a/boot.lua +++ b/boot.lua @@ -4,8 +4,8 @@ _ = nil _detalhes = LibStub("AceAddon-3.0"):NewAddon("_detalhes", "AceTimer-3.0", "AceComm-3.0", "AceSerializer-3.0", "NickTag-1.0") - _detalhes.build_counter = 6702 - _detalhes.alpha_build_counter = 6702 --if this is higher than the regular counter, use it instead + _detalhes.build_counter = 6861 + _detalhes.alpha_build_counter = 6861 --if this is higher than the regular counter, use it instead _detalhes.userversion = "v8.1.0." .. _detalhes.build_counter _detalhes.realversion = 135 --core version, this is used to check API version for scripts and plugins (see alias below) _detalhes.APIVersion = _detalhes.realversion --core version @@ -27,11 +27,15 @@ do local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" ) --[[ -|cFFFFFF00v8.1.0.6702.135 (|cFFFFCC00December 31th, 2018|r|cFFFFFF00)|r:\n\n -|cFFFFFF00-|r Streamers/Youtubers the Event Tracker tool has been fixed for 8.1, enjoy!\n\n +|cFFFFFF00v8.1.0.6861.135 (|cFFFFCC00January 20th, 2018|r|cFFFFFF00)|r:\n\n +|cFFFFFF00-|r Fixed rogue spec icons.\n\n +|cFFFFFF00-|r Some visuals improvements.\n\n +|cFFFFFF00-|r Added some buttons below the release death recap window, only show in raid after a boss.\n\n --]] - Loc ["STRING_VERSION_LOG"] = "|cFFFFFF00v8.1.0.6702.135 (|cFFFFCC00December 31th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Streamers/Youtubers the Event Tracker tool has been fixed for 8.1, enjoy!\n\n|cFFFFFF00v8.0.1.6692.135 (|cFFFFCC00December 11th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed East Asian myriads showing a giganting non formated number in the total bar DPS.\n\n|cFFFFFF00-|r Added a reset nickname button in the right side of the nickname field.\n\n|cFFFFFF00-|r Framework and NickTag library updates.\n\n|cFFFFFF00v8.0.1.6691.135 (|cFFFFCC00November 23th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Experimental: added deaths to overall data during a mythic dungeon run.\n\n|cFFFFFF00-|r Report window revamp: removed report history.\n\n|cFFFFFF00-|r Fixed report tooltip not closing on report button click.\n\n|cFFFFFF00-|r Fixed copy/paste report window.\n\n|cFFFFFF00-|r Time Line (plugin) added enemy cast time line.\n\n|cFFFFFF00v8.0.1.6678.135 (|cFFFFCC00November 07th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r New Feature: import and export profiles.\n\n|cFFFFFF00-|r Major improvements on bar text scripts.\n\n|cFFFFFF00-|r Improved import and export custom skins.\n\n|cFFFFFF00-|r Fixed shaman's sundering spell not showing in crowd control.\n\n|cFFFFFF00-|r Fixed sharing guild statistics.\n\n|cFFFFFF00-|r More spells added to spell consolidation: Whirlwind, Fracture, Mutilate.\n\n|cFFFFFF00-|r Monk Mistweaver Blackout Kick now has a indicator when it comes from passive 'Teachings of the Monastery'.\n\n|cFFFFFF00-|r Added slash command '/details debugwindow' for cases when the window isn't shown or are anchored in the wrong place.\n\n|cFFFFFF00-|r Exposed spell ignore table, you can now add spells to be ignored using Details.SpellsToIgnore [spellID] = true.\n\n|cFFFFFF00v8.0.1.6599.135 (|cFFFFCC00October 19th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed damage on low level training dummies where it was showing 1 damage for each ability.\n\n|cFFFFFF00-|r Added a line in the tooltip shown when hovering over the spec icon to show non-formated DPS, example: '12.0K' DPS shows '11,985.8'.\n\n|cFFFFFF00-|r Developers: command /run Details:DumpTable() should now show the correct table names with quotation marks if string.\n\n|cFFFFFF00v8.0.1.6553.135 (|cFFFFCC00October 06th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added a 'Macros' section in the options panel.\n\n|cFFFFFF00-|r Updated to BFA 'Potion Used' and 'Health Potion and Stone' custom displays.\n\n|cFFFFFF00-|r Backfire damage from Light of the Martyr now shows on death logs as friendly fire.\n\n|cFFFFFF00-|r Deprecated rules for friendly fire has been removed, this might fix some random issues with mind controlled players in the Lord Stormsong encounter in the Shrine of the Storm dungeon.\n\n|cFFFFFF00-|r Fixed DBM/BigWigs aura creation from the Spell List panel.\n\n|cFFFFFF00-|r Chart scripts now receives the envTable, use local envTable = ... .\n\n|cFFFFFF00-|r Polymorth (Black Cat) and Between the Eyes got added to Crowd Control list.\n\n|cFFFFFF00-|r Fixed Timeline plugin not showing the cooldown panel.\n\n|cFFFFFF00-|r Overall data setting won't reset on every logout.\n\n|cFFFFFF00-|r Slash command '/details merge' won't flag the merged combat as a trash segment anymore.\n\n|cFFFFFF00-|r Added function to use on macros to open the Player Details Window: /script Details:OpenPlayerDetails(1).\n\n|cFFFFFF00-|r Done more improvements on the Death Recap window.\n\n|cFFFFFF00v8.0.1.6449.134 (|cFFFFCC00September 11th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Details! is ready for Uldir mythic raiding!.\n\n|cFFFFFF00-|r Several improvements on Encounter Details plugin.\n\n|cFFFFFF00-|r Details! Scroll Damage for training in dummies is now ready for more tests, access it |cFFFFFF00/details scrolldamage|r.\n\n|cFFFFFF00-|r Damage and Healing tooltips now show a statusbar indicating the percent done by the ability.\n\n|cFFFFFF00-|r Added a scale slider to the options panel.\n\n|cFFFFFF00-|r Added monk's Quaking Palm to crowd control spells.\n\n|cFFFFFF00-|r Fixed an issue with Plater integration.\n\n|cFFFFFF00-|r Fixed tooltips not hiding when the cursor leaves the spell icon in the Damage Taken by Spell.\n\n|cFFFFFF00-|r Framework: fixed an issue with tooltips and menus where the division line wasn't hiding properly.\n\n|cFFFFFF00-|r Framework: fixed some buttons not showing its text in the options panel.\n\n|cFFFFFF00v8.0.1.6272.134 (|cFFFFCC00August 28th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed Dynamic Overall Data custom display.\n\n|cFFFFFF00-|r Fixed friendly fire on some dungeon fights with mind control.\n\n|cFFFFFF00-|r Raid Check plugin fully revamped, now shows talents, spec and role.\n\n|cFFFFFF00-|r Updated flask and food list for BFA.\n\n|cFFFFFF00-|r Added NpcID listing at the Spell List window.\n\n|cFFFFFF00-|r Fixed an issue with Alliance or Horde icons showing at random in player bars.\n\n|cFFFFFF00-|r Small revamp in the Death Recap window.\n\n|cFFFFFF00-|r Fixed new segment creation when the option to use only one segment while in a battleground is disabled.\n\n|cFFFFFF00-|r Fixed east asian number format on several strings.\n\n|cFFFFFF00-|r 'Smart Score' option renamed to 'Unique Segment' under the PvP options for battlegrounds.\n\n|cFFFFFF00v8.0.1.6120.132 (|cFFFFCC00August 07th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Death Knight: Epidemic, Scourge Strike and Howling Blast now has a better description on the spell name.\n\n|cFFFFFF00-|r Fixed snap button showing when 'Hide Resize Buttons' are enabled.\n\n|cFFFFFF00-|r Fixed title bar icons not hiding when 'Auto Hide Buttons' is enabled.\n\n|cFFFFFF00-|r Several improvements to overall data, it should be more consistent now.\n\n|cFFFFFF00-|r Details! now passes to identify the tank role of the player even when out of a party or raid.\n\n|cFFFFFF00-|r Debug helper /run Details:DumpTable(table) now correctly shows the key name when it isn't a string.\n\n|cFFFFFF00-|r Improvements done on the Bookmark config frame accessed by the options panel > display section.\n\n|cFFFFFF00-|r New slash command: '/details spells'.\n\n|cFFFFFF00-|r Statistics for Legion has been closed! You can access statistics from the orange gear > statistics.\n\n|cFFFFFF00v8.0.1.6027.132 (|cFFFFCC00July 28th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added size offset options for the chat tab embed feature.\n\n|cFFFFFF00-|r Revamp on the editor for the custom line text.\n\n|cFFFFFF00v8.0.1.5985.131 (|cFFFFCC00July 17th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added 'Auto Run Code' module.\n\n|cFFFFFF00-|r Added 'Plater Nameplates' integration.\n\n|cFFFFFF00-|r Weakauras integration with the Create Aura panel got great improvements.\n\n|cFFFFFF00-|r Many options has been renamed or moved from groups for better organization .\n\n|cFFFFFF00-|r Several skins got some revamp for 2018.\n\n|cFFFFFF00-|r Default settings for Arenas and Battlegrounds got changes and the experience should be more smooth now.\n\n|cFFFFFF00v7.3.5.5559.130 (|cFFFFCC00April 13th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added slash commands: /details 'softtoggle' 'softshow' 'softhide'. Use them to manipulate the window visibility while using auto hide.\n\n|cFFFFFF00-|r Mythic dungeon graphic window won't show up if the user leaves the dungeon before completing it.\n\n|cFFFFFF00v7.3.5.5529.130 (|cFFFFCC00April 06th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added minimize button on the mythic dungeon run chart.\n\n|cFFFFFF00-|r Added API calls: Details:ResetSegmentOverallData() and Details:ResetSegmentData().\n\n|cFFFFFF00v7.3.5.5499.130 (|cFFFFCC00Mar 30th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added outline option for the right text.\n\n|cFFFFFF00v7.3.5.5469.130 (|cFFFFCC00Mar 23th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed a few things on the mythic dungeon chart.\n\n|cFFFFFF00v7.3.5.5424.129 (|cFFFFCC00Mar 10th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added macro support to open plugins. Example:\n /run Details:OpenPlugin ('Time Line')\n\n|cFFFFFF00v7.3.5.5351.129 (|cFFFFCC00Feb 26rd, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added a damage chart for mythic dungeon runs, it shows at the of the run. You may disable it at the Streamer Settings.\n\n|cFFFFFF00v7.3.5.5231.128 (|cFFFFCC00Feb 02nd, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed an issue with wasted shield absorbs where the wasted amount was subtracting the total healing done.\n\n|cFFFFFF00v7.3.5.5221.128 (|cFFFFCC00Jan 26th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Warlock mana from Life Tap won't show up any more under mana regen, this makes easy to see Soul Shard gain.\n\n|cFFFFFF00v7.3.2.5183.128 (|cFFFFCC00Jan 12th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r The new bar animation is now applied to all users by default.\n\n|cFFFFFF00-|r Fixed an issue with the threat plugin where sometimes it was triggering errors.\n\n|cFFFFFF00v7.3.2.5175.128 (|cFFFFCC00Jan 03rd, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r ElvUI skins should have now a more good looking scrollbar.\n\n|cFFFFFF00-|r When starting to edit a custom display, the code window now clear the code from the previous display.\n\n|cFFFFFF00v7.3.2.5154.128 (|cFFFFCC00Dec 22th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r API and Create Aura windows are now attached to the new plugin window.\n\n|cFFFFFF00v7.3.2.5101.128 (|cFFFFCC00Dec 15th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Moving the custom display window to the new plugins window.\n\n|cFFFFFF00-|r Major layout changes on the Encounter Details plugin window.\n\n|cFFFFFF00v7.3.2.4919.128 (|cFFFFCC00Dec 08th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed an issue with the statistics sharing among guild members.\n\n|cFFFFFF00-|r Fixed an issue with Argus encounter where two segments were created.\n\n|cFFFFFF00-|r Fixed aura type images on the Create Aura Panel.\n\n|cFFFFFF00-|r Create Aura Panel can now be closed with Right Click.\n\n|cFFFFFF00-|r Framework updated to r60, plugins should be more stable now.\n\n|cFFFFFF00v7.3.0.4830.126 (|cFFFFFF00v7.3.2.4836.126 (|cFFFFCC00Nov 21th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Removed some tutorial windows popups.\n\n|cFFFFCC00Oct 21th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed opening windows when streamer settings > no alerts is enabled.\n\n|cFFFFFF00v7.3.0.4823.126 (|cFFFFCC00Oct 09th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added new options section: Streamer Settings, focused on adjustments for streamers and youtubers.\n\n|cFFFFFF00-|r Animations now always run at the same speed regardless the framerate.\n\n|cFFFFFF00-|r Click-To-Open menus now close the menu if the menu is already open.\n\n|cFFFFFF00v7.3.0.4723.126 (|cFFFFCC00Set 22th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed overall dungeon segments being added to overall data.\n\n|cFFFFFF00v7.3.0.4705.126 (|cFFFFCC00Set 19th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed damage taken tooltip for Brewmaster Monk where sometimes the tooltip didn't open.\n\n|cFFFFFF00-|r Fixed overall data on mythic dungeon not adding trash segments even with the option enabled on the options panel.\n\n|cFFFFFF00-|r Fixed the guild selection dropdown reseting everytime the Guild Rank window is opened.\n\n|cFFFFFF00v7.3.0.4677.126 (|cFFFFCC00Set 10th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r During mythic dungeons, the trash segments will be merged into a new segment at the end of the boss encounter (instead of merging on the fly while cleaning up).\n\n|cFFFFFF00v7.3.0.4615.125 (|cFFFFCC00Set 09th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Setting up the dungeon stuff as opt-in for early adopters while we continue to make improvements on the system.\n\n|cFFFFFF00v7.3.0.4586.125 (|cFFFFCC00Set 08th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Formating mythic+ dungeon segments, each segment should count the boss trash + boss fight.\n\n|cFFFFFF00-|r At the end of the mythic+ dungeon, it should create a new segment adding up all segments described above.\n\n|cFFFFFF00v7.3.0.4499.124 (|cFFFFCC00Set 05th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added an option to always show all players when using the standard mode. Option under PvP/PvE bracket on the options panel.\n\n|cFFFFFF00-|r Added a setting to exclude healing done lines from the death log below a certain healing amount. This options is also under PvP/PvE bracket.\n\n|cFFFFFF00-|r Fixed the guild selection on the ranking panel.\n\n|cFFFFFF00v7.3.0.4467.124 (|cFFFFCC00August 29th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Damage or Healing record for the encounter should be printed on chat on the boss pull.\nUse /run Details.announce_damagerecord.enabled = false; to disable.\n\n|cFFFFFF00v7.2.5.4437.124 (|cFFFFCC00August 21th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added healing done cap for death log. Use /run Details.deathlog_healingdone_min = 10000\n\n|cFFFFFF00-|r Fixed an issue where the alpha from the fixed bar color was used even when this option was disabled.\n\n|cFFFFFF00v7.2.5.4436.124 (|cFFFFCC00August 17th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Attempt to fix the issue where the window doesn't update after entering a raid or reseting data.\n\n|cFFFFFF00v7.2.5.4434.124 (|cFFFFCC00August 10th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added buttons to create an aura at Aura tab on the Player Details window.\n\n|cFFFFFF00-|r Fixes and improvements on the damage rank panel.\n\n|cFFFFFF00-|r Best damage or healing for the player on the current boss encounter is now shown on the spec icon tooltip.\n\n|cFFFFFF00-|r Major revamp on the aura creation panel.\n\n|cFFFFFF00v7.2.5.4369.124 (|cFFFFCC00August 1st, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Details! can now track debuff applications (stack) and refreshes.\n\n|cFFFFFF00-|r Added new tab on Player Detail Window called 'Auras', you can see your buffs and debuffs from there.\n\n|cFFFFFF00-|r Death log now show debuff applications.\n\n|cFFFFFF00v7.2.5.4275.123 (|cFFFFCC00July 18th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed some issues with tooltiops popup when the user press SHIFT.\n\n|cFFFFFF00-|r Now is possible to change the bar durating when selecting Cast Start trigger on Details! Forge.\n\n|cFFFFFF00-|r Kil'Jaeden adds should be consolidated into only one actor instead of having one for each player targeted.\n\n|cFFFFFF00v7.2.5.4236.122 (|cFFFFCC00July 05th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r The alert to open the raid ranking after a boss kill, is now shown for 10 seconds (down from 40).\n\n|cFFFFFF00-|r Added a report button on the raid ranking panel and boss are sort alphabetically.\n\n|cFFFFFF00-|r Fixed some issues on the combatlog introduced on the wow patch 7.2.5 where sometimes the source of an event has no name.\n\n|cFFFFFF00-|r Ticket #209, fixed more issues with the comparison panel where are pets involved.\n\n|cFFFFFF00v7.2.5.4201.121 (|cFFFFCC00June 26th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed Monk Stagger where it was only shown on the friendly fire and not under the Damage Taken display.\n\n|cFFFFFF00-|r Added Forge and Ranking options on the main menu (orange cogwheel).\n\n|cFFFFFF00v7.2.5.4102.121 (|cFFFFCC00June 22th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Details! Forge has updated and now is more usder friendly.\n\n|cFFFFFF00-|r Fixed an issue with player buff uptime where sometimes some buffs wans't showing in the tooltip.\n\n|cFFFFFF00v7.2.5.3968.120 (|cFFFFCC00June 20th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r New Death Recap implemented! replaces the default from Blizzard and can be configured at Options > Raid Tools.\n\n|cFFFFFF00-|r New Guild Damage and Heal rank on '/details ranking' panel.\n\n|cFFFFFF00-|r Added a Guild Sync button on the Details! Ranking Panel.\n\n|cFFFFFF00-|r Added Custom display 'Damage on Shields', useful for encounter like Maiden of Vigilance where there's big shields to be removed and you want to know who is doing more damage to it.\n\n|cFFFFFF00-|r Added Heal Absorbed display under Heal bracket.\n\nHeal Absorb are the heal denied by abilities such like DK's Necrotic Strike or raid boss Sisters of the Moon 'Embrace of the Eclipse' ability.\nThe tooltip of this display shows which players got heal denied, which abilities absorbed the heal, which abilities tried to heal but got the heal denied.\n\n|cFFFFFF00-|r Added Alternate Power display under Energy bracket, it shows the total of alternate power gain from each player, useful for encounters such as Demonic Inquisition.\n\n|cFFFFFF00-|r 'First Hit' message after pulling a boss, now also shows who the boss is targeting (almost always is who pulled).\n\n|cFFFFFF00-|r Raid Dps {rdps} and Hps {rhps} can now be used on the Broker Data Feed..\n\n|cFFFFFF00-|r Fixed an issue with Chromie from the scenario 'The Deaths of Chromie' where she wasn't being shown on the meter.\n\n|cFFFFFF00-|r Fixed Paladin 'Light of the Martyr' damage to self.\n\n|cFFFFFF00-|r Ticket #198 'Script Error' Fixed.\n\n|cFFFFFF00v7.2.0.3703.119 (|cFFFFCC00May 29th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed an error while killing low level mobs with warrior class.\n\n|cFFFFFF00v7.2.0.3693.118 (|cFFFFCC00May 25th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fury Warrior shouldn't be assigned as Protection any more.\n\n|cFFFFFF00-|r Some parser fixes.\n\n|cFFFFFF00v7.2.0.3673.118 (|cFFFFCC00May 09th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Ticket #187: Fixed an issue when comparing hunter pets on the player detail window.\n\n|cFFFFFF00-|r Ticket #189 #186: Fixed a taint issue for some classes when using friendly nameplates on.\n\n|cFFFFFF00v7.2.0.3512.116 (|cFFFFCC00April 27th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Havoc Demon Hunter: your fury energy is being shown under Mana Restored (don't ask me why, the combat log is telling us it's mana).\n\n|cFFFFFF00-|r Pets now are shown on damage tooltips.\n\n|cFFFFFF00-|r Pets are now also shown on the comparison panel.\n\n|cFFFFFF00v7.2.0.3474.116 (|cFFFFCC00April 20th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Plugin: Raid Check > added some food buffs which wasn't being tracked.\n\n|cFFFFFF00v7.2.0.3467.116 (|cFFFFCC00April 07th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fix for the custom display window where apply and cancel buttons where over the edit window.\n\n|cFFFFFF00-|r Fix for an issue on editing a bookmark.\n\n|cFFFFFF00v7.1.5.3459.116 (|cFFFFCC00Mar 21th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed an issue on dynamic overall data where it wasn't showing DPS.\n\n|cFFFFFF00-|r Fixed an issue with Apply, Save and Cancel buttons when editing a custom display.\n\n|cFFFFFF00-|r Removed the Damage and Healing presets for custom displays, now is only possible create custom displays by scripting them.\n\n|cFFFFFF00v7.1.5.3431.116 (|cFFFFCC00Mar 15th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed an issue with bar orientation right to left where fixed bar color isn't working.\n\n|cFFFFFF00-|r The nickname field now use FrizQuadrataTT font and shall be compatible with Cyrillic.\n\n|cFFFFFF00v7.1.5.3418.116 (|cFFFFCC00Mar 1st, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Ticket #167 fix: Light of the Martyr self-damage now does reduce the healing done (following WCL method).\n\n|cFFFFFF00-|r Ticket #169 fix: Damage Prevented is now working for new segments.\n\n|cFFFFFF00-|r Fixed an issue where sometimes BeastMaster's Hati pet wasn't detected correctly.\n\n|cFFFFFF00v7.1.5.3369.116 (|cFFFFCC00Feb 07th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added custom display 'Dynamic Overall Damage' for mythic dungeons.\n\n|cFFFFFF00-|r Fix for Ticket #168: 'Auto Hide While [Not] Inside Instance is broken'.\n\n|cFFFFFF00-|r The bar truncate frame 'DetailsLeftTextAntiTruncate' is now created on Details! load instead on demand.\n\n|cFFFFFF00v7.1.5.3315.116 (|cFFFFCC00Jan 23th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Ticket #162: 'no Monochrome font' available, added an experimental slash command: /run _detalhes:UseOutline ('MONOCHROME').\n\n|cFFFFFF00-|r Ticket #158: 'no elapsed time shown on report to chat', added the elapsed time when reporting a segment.\n\n|cFFFFFF00-|r Ticket #164: 'error when browsing segments', an attempt to fix the problem has been made." + + + Loc ["STRING_VERSION_LOG"] = "|cFFFFFF00v8.1.0.6861.135 (|cFFFFCC00January 20th, 2019|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed rogue spec icons.\n\n|cFFFFFF00-|r Some visuals improvements.\n\n|cFFFFFF00-|r Added some buttons below the release death recap window, only show in raid after a boss.\n\n|cFFFFFF00v8.1.0.6702.135 (|cFFFFCC00December 31th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Streamers/Youtubers the Event Tracker tool has been fixed for 8.1, enjoy!\n\n|cFFFFFF00v8.0.1.6692.135 (|cFFFFCC00December 11th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed East Asian myriads showing a giganting non formated number in the total bar DPS.\n\n|cFFFFFF00-|r Added a reset nickname button in the right side of the nickname field.\n\n|cFFFFFF00-|r Framework and NickTag library updates.\n\n|cFFFFFF00v8.0.1.6691.135 (|cFFFFCC00November 23th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Experimental: added deaths to overall data during a mythic dungeon run.\n\n|cFFFFFF00-|r Report window revamp: removed report history.\n\n|cFFFFFF00-|r Fixed report tooltip not closing on report button click.\n\n|cFFFFFF00-|r Fixed copy/paste report window.\n\n|cFFFFFF00-|r Time Line (plugin) added enemy cast time line.\n\n|cFFFFFF00v8.0.1.6678.135 (|cFFFFCC00November 07th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r New Feature: import and export profiles.\n\n|cFFFFFF00-|r Major improvements on bar text scripts.\n\n|cFFFFFF00-|r Improved import and export custom skins.\n\n|cFFFFFF00-|r Fixed shaman's sundering spell not showing in crowd control.\n\n|cFFFFFF00-|r Fixed sharing guild statistics.\n\n|cFFFFFF00-|r More spells added to spell consolidation: Whirlwind, Fracture, Mutilate.\n\n|cFFFFFF00-|r Monk Mistweaver Blackout Kick now has a indicator when it comes from passive 'Teachings of the Monastery'.\n\n|cFFFFFF00-|r Added slash command '/details debugwindow' for cases when the window isn't shown or are anchored in the wrong place.\n\n|cFFFFFF00-|r Exposed spell ignore table, you can now add spells to be ignored using Details.SpellsToIgnore [spellID] = true.\n\n|cFFFFFF00v8.0.1.6599.135 (|cFFFFCC00October 19th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed damage on low level training dummies where it was showing 1 damage for each ability.\n\n|cFFFFFF00-|r Added a line in the tooltip shown when hovering over the spec icon to show non-formated DPS, example: '12.0K' DPS shows '11,985.8'.\n\n|cFFFFFF00-|r Developers: command /run Details:DumpTable() should now show the correct table names with quotation marks if string.\n\n|cFFFFFF00v8.0.1.6553.135 (|cFFFFCC00October 06th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added a 'Macros' section in the options panel.\n\n|cFFFFFF00-|r Updated to BFA 'Potion Used' and 'Health Potion and Stone' custom displays.\n\n|cFFFFFF00-|r Backfire damage from Light of the Martyr now shows on death logs as friendly fire.\n\n|cFFFFFF00-|r Deprecated rules for friendly fire has been removed, this might fix some random issues with mind controlled players in the Lord Stormsong encounter in the Shrine of the Storm dungeon.\n\n|cFFFFFF00-|r Fixed DBM/BigWigs aura creation from the Spell List panel.\n\n|cFFFFFF00-|r Chart scripts now receives the envTable, use local envTable = ... .\n\n|cFFFFFF00-|r Polymorth (Black Cat) and Between the Eyes got added to Crowd Control list.\n\n|cFFFFFF00-|r Fixed Timeline plugin not showing the cooldown panel.\n\n|cFFFFFF00-|r Overall data setting won't reset on every logout.\n\n|cFFFFFF00-|r Slash command '/details merge' won't flag the merged combat as a trash segment anymore.\n\n|cFFFFFF00-|r Added function to use on macros to open the Player Details Window: /script Details:OpenPlayerDetails(1).\n\n|cFFFFFF00-|r Done more improvements on the Death Recap window.\n\n|cFFFFFF00v8.0.1.6449.134 (|cFFFFCC00September 11th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Details! is ready for Uldir mythic raiding!.\n\n|cFFFFFF00-|r Several improvements on Encounter Details plugin.\n\n|cFFFFFF00-|r Details! Scroll Damage for training in dummies is now ready for more tests, access it |cFFFFFF00/details scrolldamage|r.\n\n|cFFFFFF00-|r Damage and Healing tooltips now show a statusbar indicating the percent done by the ability.\n\n|cFFFFFF00-|r Added a scale slider to the options panel.\n\n|cFFFFFF00-|r Added monk's Quaking Palm to crowd control spells.\n\n|cFFFFFF00-|r Fixed an issue with Plater integration.\n\n|cFFFFFF00-|r Fixed tooltips not hiding when the cursor leaves the spell icon in the Damage Taken by Spell.\n\n|cFFFFFF00-|r Framework: fixed an issue with tooltips and menus where the division line wasn't hiding properly.\n\n|cFFFFFF00-|r Framework: fixed some buttons not showing its text in the options panel.\n\n|cFFFFFF00v8.0.1.6272.134 (|cFFFFCC00August 28th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed Dynamic Overall Data custom display.\n\n|cFFFFFF00-|r Fixed friendly fire on some dungeon fights with mind control.\n\n|cFFFFFF00-|r Raid Check plugin fully revamped, now shows talents, spec and role.\n\n|cFFFFFF00-|r Updated flask and food list for BFA.\n\n|cFFFFFF00-|r Added NpcID listing at the Spell List window.\n\n|cFFFFFF00-|r Fixed an issue with Alliance or Horde icons showing at random in player bars.\n\n|cFFFFFF00-|r Small revamp in the Death Recap window.\n\n|cFFFFFF00-|r Fixed new segment creation when the option to use only one segment while in a battleground is disabled.\n\n|cFFFFFF00-|r Fixed east asian number format on several strings.\n\n|cFFFFFF00-|r 'Smart Score' option renamed to 'Unique Segment' under the PvP options for battlegrounds.\n\n|cFFFFFF00v8.0.1.6120.132 (|cFFFFCC00August 07th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Death Knight: Epidemic, Scourge Strike and Howling Blast now has a better description on the spell name.\n\n|cFFFFFF00-|r Fixed snap button showing when 'Hide Resize Buttons' are enabled.\n\n|cFFFFFF00-|r Fixed title bar icons not hiding when 'Auto Hide Buttons' is enabled.\n\n|cFFFFFF00-|r Several improvements to overall data, it should be more consistent now.\n\n|cFFFFFF00-|r Details! now passes to identify the tank role of the player even when out of a party or raid.\n\n|cFFFFFF00-|r Debug helper /run Details:DumpTable(table) now correctly shows the key name when it isn't a string.\n\n|cFFFFFF00-|r Improvements done on the Bookmark config frame accessed by the options panel > display section.\n\n|cFFFFFF00-|r New slash command: '/details spells'.\n\n|cFFFFFF00-|r Statistics for Legion has been closed! You can access statistics from the orange gear > statistics.\n\n|cFFFFFF00v8.0.1.6027.132 (|cFFFFCC00July 28th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added size offset options for the chat tab embed feature.\n\n|cFFFFFF00-|r Revamp on the editor for the custom line text.\n\n|cFFFFFF00v8.0.1.5985.131 (|cFFFFCC00July 17th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added 'Auto Run Code' module.\n\n|cFFFFFF00-|r Added 'Plater Nameplates' integration.\n\n|cFFFFFF00-|r Weakauras integration with the Create Aura panel got great improvements.\n\n|cFFFFFF00-|r Many options has been renamed or moved from groups for better organization .\n\n|cFFFFFF00-|r Several skins got some revamp for 2018.\n\n|cFFFFFF00-|r Default settings for Arenas and Battlegrounds got changes and the experience should be more smooth now.\n\n|cFFFFFF00v7.3.5.5559.130 (|cFFFFCC00April 13th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added slash commands: /details 'softtoggle' 'softshow' 'softhide'. Use them to manipulate the window visibility while using auto hide.\n\n|cFFFFFF00-|r Mythic dungeon graphic window won't show up if the user leaves the dungeon before completing it.\n\n|cFFFFFF00v7.3.5.5529.130 (|cFFFFCC00April 06th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added minimize button on the mythic dungeon run chart.\n\n|cFFFFFF00-|r Added API calls: Details:ResetSegmentOverallData() and Details:ResetSegmentData().\n\n|cFFFFFF00v7.3.5.5499.130 (|cFFFFCC00Mar 30th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added outline option for the right text.\n\n|cFFFFFF00v7.3.5.5469.130 (|cFFFFCC00Mar 23th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed a few things on the mythic dungeon chart.\n\n|cFFFFFF00v7.3.5.5424.129 (|cFFFFCC00Mar 10th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added macro support to open plugins. Example:\n /run Details:OpenPlugin ('Time Line')\n\n|cFFFFFF00v7.3.5.5351.129 (|cFFFFCC00Feb 26rd, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added a damage chart for mythic dungeon runs, it shows at the of the run. You may disable it at the Streamer Settings.\n\n|cFFFFFF00v7.3.5.5231.128 (|cFFFFCC00Feb 02nd, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed an issue with wasted shield absorbs where the wasted amount was subtracting the total healing done.\n\n|cFFFFFF00v7.3.5.5221.128 (|cFFFFCC00Jan 26th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Warlock mana from Life Tap won't show up any more under mana regen, this makes easy to see Soul Shard gain.\n\n|cFFFFFF00v7.3.2.5183.128 (|cFFFFCC00Jan 12th, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r The new bar animation is now applied to all users by default.\n\n|cFFFFFF00-|r Fixed an issue with the threat plugin where sometimes it was triggering errors.\n\n|cFFFFFF00v7.3.2.5175.128 (|cFFFFCC00Jan 03rd, 2018|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r ElvUI skins should have now a more good looking scrollbar.\n\n|cFFFFFF00-|r When starting to edit a custom display, the code window now clear the code from the previous display.\n\n|cFFFFFF00v7.3.2.5154.128 (|cFFFFCC00Dec 22th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r API and Create Aura windows are now attached to the new plugin window.\n\n|cFFFFFF00v7.3.2.5101.128 (|cFFFFCC00Dec 15th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Moving the custom display window to the new plugins window.\n\n|cFFFFFF00-|r Major layout changes on the Encounter Details plugin window.\n\n|cFFFFFF00v7.3.2.4919.128 (|cFFFFCC00Dec 08th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed an issue with the statistics sharing among guild members.\n\n|cFFFFFF00-|r Fixed an issue with Argus encounter where two segments were created.\n\n|cFFFFFF00-|r Fixed aura type images on the Create Aura Panel.\n\n|cFFFFFF00-|r Create Aura Panel can now be closed with Right Click.\n\n|cFFFFFF00-|r Framework updated to r60, plugins should be more stable now.\n\n|cFFFFFF00v7.3.0.4830.126 (|cFFFFFF00v7.3.2.4836.126 (|cFFFFCC00Nov 21th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Removed some tutorial windows popups.\n\n|cFFFFCC00Oct 21th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed opening windows when streamer settings > no alerts is enabled.\n\n|cFFFFFF00v7.3.0.4823.126 (|cFFFFCC00Oct 09th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added new options section: Streamer Settings, focused on adjustments for streamers and youtubers.\n\n|cFFFFFF00-|r Animations now always run at the same speed regardless the framerate.\n\n|cFFFFFF00-|r Click-To-Open menus now close the menu if the menu is already open.\n\n|cFFFFFF00v7.3.0.4723.126 (|cFFFFCC00Set 22th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed overall dungeon segments being added to overall data.\n\n|cFFFFFF00v7.3.0.4705.126 (|cFFFFCC00Set 19th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed damage taken tooltip for Brewmaster Monk where sometimes the tooltip didn't open.\n\n|cFFFFFF00-|r Fixed overall data on mythic dungeon not adding trash segments even with the option enabled on the options panel.\n\n|cFFFFFF00-|r Fixed the guild selection dropdown reseting everytime the Guild Rank window is opened.\n\n|cFFFFFF00v7.3.0.4677.126 (|cFFFFCC00Set 10th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r During mythic dungeons, the trash segments will be merged into a new segment at the end of the boss encounter (instead of merging on the fly while cleaning up).\n\n|cFFFFFF00v7.3.0.4615.125 (|cFFFFCC00Set 09th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Setting up the dungeon stuff as opt-in for early adopters while we continue to make improvements on the system.\n\n|cFFFFFF00v7.3.0.4586.125 (|cFFFFCC00Set 08th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Formating mythic+ dungeon segments, each segment should count the boss trash + boss fight.\n\n|cFFFFFF00-|r At the end of the mythic+ dungeon, it should create a new segment adding up all segments described above.\n\n|cFFFFFF00v7.3.0.4499.124 (|cFFFFCC00Set 05th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added an option to always show all players when using the standard mode. Option under PvP/PvE bracket on the options panel.\n\n|cFFFFFF00-|r Added a setting to exclude healing done lines from the death log below a certain healing amount. This options is also under PvP/PvE bracket.\n\n|cFFFFFF00-|r Fixed the guild selection on the ranking panel.\n\n|cFFFFFF00v7.3.0.4467.124 (|cFFFFCC00August 29th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Damage or Healing record for the encounter should be printed on chat on the boss pull.\nUse /run Details.announce_damagerecord.enabled = false; to disable.\n\n|cFFFFFF00v7.2.5.4437.124 (|cFFFFCC00August 21th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added healing done cap for death log. Use /run Details.deathlog_healingdone_min = 10000\n\n|cFFFFFF00-|r Fixed an issue where the alpha from the fixed bar color was used even when this option was disabled.\n\n|cFFFFFF00v7.2.5.4436.124 (|cFFFFCC00August 17th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Attempt to fix the issue where the window doesn't update after entering a raid or reseting data.\n\n|cFFFFFF00v7.2.5.4434.124 (|cFFFFCC00August 10th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added buttons to create an aura at Aura tab on the Player Details window.\n\n|cFFFFFF00-|r Fixes and improvements on the damage rank panel.\n\n|cFFFFFF00-|r Best damage or healing for the player on the current boss encounter is now shown on the spec icon tooltip.\n\n|cFFFFFF00-|r Major revamp on the aura creation panel.\n\n|cFFFFFF00v7.2.5.4369.124 (|cFFFFCC00August 1st, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Details! can now track debuff applications (stack) and refreshes.\n\n|cFFFFFF00-|r Added new tab on Player Detail Window called 'Auras', you can see your buffs and debuffs from there.\n\n|cFFFFFF00-|r Death log now show debuff applications.\n\n|cFFFFFF00v7.2.5.4275.123 (|cFFFFCC00July 18th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed some issues with tooltiops popup when the user press SHIFT.\n\n|cFFFFFF00-|r Now is possible to change the bar durating when selecting Cast Start trigger on Details! Forge.\n\n|cFFFFFF00-|r Kil'Jaeden adds should be consolidated into only one actor instead of having one for each player targeted.\n\n|cFFFFFF00v7.2.5.4236.122 (|cFFFFCC00July 05th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r The alert to open the raid ranking after a boss kill, is now shown for 10 seconds (down from 40).\n\n|cFFFFFF00-|r Added a report button on the raid ranking panel and boss are sort alphabetically.\n\n|cFFFFFF00-|r Fixed some issues on the combatlog introduced on the wow patch 7.2.5 where sometimes the source of an event has no name.\n\n|cFFFFFF00-|r Ticket #209, fixed more issues with the comparison panel where are pets involved.\n\n|cFFFFFF00v7.2.5.4201.121 (|cFFFFCC00June 26th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed Monk Stagger where it was only shown on the friendly fire and not under the Damage Taken display.\n\n|cFFFFFF00-|r Added Forge and Ranking options on the main menu (orange cogwheel).\n\n|cFFFFFF00v7.2.5.4102.121 (|cFFFFCC00June 22th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Details! Forge has updated and now is more usder friendly.\n\n|cFFFFFF00-|r Fixed an issue with player buff uptime where sometimes some buffs wans't showing in the tooltip.\n\n|cFFFFFF00v7.2.5.3968.120 (|cFFFFCC00June 20th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r New Death Recap implemented! replaces the default from Blizzard and can be configured at Options > Raid Tools.\n\n|cFFFFFF00-|r New Guild Damage and Heal rank on '/details ranking' panel.\n\n|cFFFFFF00-|r Added a Guild Sync button on the Details! Ranking Panel.\n\n|cFFFFFF00-|r Added Custom display 'Damage on Shields', useful for encounter like Maiden of Vigilance where there's big shields to be removed and you want to know who is doing more damage to it.\n\n|cFFFFFF00-|r Added Heal Absorbed display under Heal bracket.\n\nHeal Absorb are the heal denied by abilities such like DK's Necrotic Strike or raid boss Sisters of the Moon 'Embrace of the Eclipse' ability.\nThe tooltip of this display shows which players got heal denied, which abilities absorbed the heal, which abilities tried to heal but got the heal denied.\n\n|cFFFFFF00-|r Added Alternate Power display under Energy bracket, it shows the total of alternate power gain from each player, useful for encounters such as Demonic Inquisition.\n\n|cFFFFFF00-|r 'First Hit' message after pulling a boss, now also shows who the boss is targeting (almost always is who pulled).\n\n|cFFFFFF00-|r Raid Dps {rdps} and Hps {rhps} can now be used on the Broker Data Feed..\n\n|cFFFFFF00-|r Fixed an issue with Chromie from the scenario 'The Deaths of Chromie' where she wasn't being shown on the meter.\n\n|cFFFFFF00-|r Fixed Paladin 'Light of the Martyr' damage to self.\n\n|cFFFFFF00-|r Ticket #198 'Script Error' Fixed.\n\n|cFFFFFF00v7.2.0.3703.119 (|cFFFFCC00May 29th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed an error while killing low level mobs with warrior class.\n\n|cFFFFFF00v7.2.0.3693.118 (|cFFFFCC00May 25th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fury Warrior shouldn't be assigned as Protection any more.\n\n|cFFFFFF00-|r Some parser fixes.\n\n|cFFFFFF00v7.2.0.3673.118 (|cFFFFCC00May 09th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Ticket #187: Fixed an issue when comparing hunter pets on the player detail window.\n\n|cFFFFFF00-|r Ticket #189 #186: Fixed a taint issue for some classes when using friendly nameplates on.\n\n|cFFFFFF00v7.2.0.3512.116 (|cFFFFCC00April 27th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Havoc Demon Hunter: your fury energy is being shown under Mana Restored (don't ask me why, the combat log is telling us it's mana).\n\n|cFFFFFF00-|r Pets now are shown on damage tooltips.\n\n|cFFFFFF00-|r Pets are now also shown on the comparison panel.\n\n|cFFFFFF00v7.2.0.3474.116 (|cFFFFCC00April 20th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Plugin: Raid Check > added some food buffs which wasn't being tracked.\n\n|cFFFFFF00v7.2.0.3467.116 (|cFFFFCC00April 07th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fix for the custom display window where apply and cancel buttons where over the edit window.\n\n|cFFFFFF00-|r Fix for an issue on editing a bookmark.\n\n|cFFFFFF00v7.1.5.3459.116 (|cFFFFCC00Mar 21th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed an issue on dynamic overall data where it wasn't showing DPS.\n\n|cFFFFFF00-|r Fixed an issue with Apply, Save and Cancel buttons when editing a custom display.\n\n|cFFFFFF00-|r Removed the Damage and Healing presets for custom displays, now is only possible create custom displays by scripting them.\n\n|cFFFFFF00v7.1.5.3431.116 (|cFFFFCC00Mar 15th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Fixed an issue with bar orientation right to left where fixed bar color isn't working.\n\n|cFFFFFF00-|r The nickname field now use FrizQuadrataTT font and shall be compatible with Cyrillic.\n\n|cFFFFFF00v7.1.5.3418.116 (|cFFFFCC00Mar 1st, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Ticket #167 fix: Light of the Martyr self-damage now does reduce the healing done (following WCL method).\n\n|cFFFFFF00-|r Ticket #169 fix: Damage Prevented is now working for new segments.\n\n|cFFFFFF00-|r Fixed an issue where sometimes BeastMaster's Hati pet wasn't detected correctly.\n\n|cFFFFFF00v7.1.5.3369.116 (|cFFFFCC00Feb 07th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Added custom display 'Dynamic Overall Damage' for mythic dungeons.\n\n|cFFFFFF00-|r Fix for Ticket #168: 'Auto Hide While [Not] Inside Instance is broken'.\n\n|cFFFFFF00-|r The bar truncate frame 'DetailsLeftTextAntiTruncate' is now created on Details! load instead on demand.\n\n|cFFFFFF00v7.1.5.3315.116 (|cFFFFCC00Jan 23th, 2017|r|cFFFFFF00)|r:\n\n|cFFFFFF00-|r Ticket #162: 'no Monochrome font' available, added an experimental slash command: /run _detalhes:UseOutline ('MONOCHROME').\n\n|cFFFFFF00-|r Ticket #158: 'no elapsed time shown on report to chat', added the elapsed time when reporting a segment.\n\n|cFFFFFF00-|r Ticket #164: 'error when browsing segments', an attempt to fix the problem has been made." Loc ["STRING_DETAILS1"] = "|cffffaeaeDetails!:|r " @@ -55,8 +59,8 @@ do _detalhes.MacroList = { {Name = "Click on Your Own Bar", Desc = "To open the player details window on your character, like if you click on your bar in the damage window. The number '1' is the window number where it'll click.", MacroText = "/script Details:OpenPlayerDetails(1)"}, - {Name = "Open Encounter Summary", Desc = "Open the encounter plugin in the summary tab. Details! Encounter (plugin) must be enabled.", MacroText = "/script Details:OpenPlugin ('Encounter Details')"}, - {Name = "Open Damage per Phase", Desc = "Open the encounter plugin in the phase tab.. Details! Encounter (plugin) must be enabled.", MacroText = "/script Details:OpenPlugin ('Encounter Details'); local a=Details_EncounterDetails and Details_EncounterDetails.buttonSwitchPhases:Click()"}, + {Name = "Open Encounter Breakdown", Desc = "Open the encounter breakdown plugin. Details! Encounter Breakdown (plugin) must be enabled.", MacroText = "/script Details:OpenPlugin ('Encounter Breakdown')"}, + {Name = "Open Damage per Phase", Desc = "Open the encounter breakdown plugin in the phase tab. Details! Encounter Breakdown (plugin) must be enabled.", MacroText = "/script Details:OpenPlugin ('Encounter Breakdown'); local a=Details_EncounterDetails and Details_EncounterDetails.buttonSwitchPhases:Click()"}, {Name = "Reset Data", Desc = "Reset the overall and regular segments data. Use 'ResetSegmentOverallData' to reset only the overall.", MacroText = "/script Details:ResetSegmentData()"}, {Name = "Change What the Window Shows", Desc = "Make a window show different data. SetDisplay uses (segment, displayGroup, displayID), the menu from the sword icon is in order (damage = group 1, overheal is: displayGroup 2 displayID 3.", MacroText = "/script Details:GetWindow(1):SetDisplay( DETAILS_SEGMENTID_CURRENT, 4, 5 )"}, {Name = "Toggle Window Height to Max Size", Desc = "Make a window be 450 pixel height, pressing the macro again toggle back to the original size. The number '1' if the window number. Hold a click in any window to show their number.", MacroText = "/script Details:GetWindow(1):ToggleMaxSize()"}, @@ -68,17 +72,9 @@ do --> quais raides devem ser guardadas no hist�rico _detalhes.InstancesToStoreData = { --> mapIDs + [2070] = true, --Battle for Dazaralor (BFA) GetInstanceInfo [1148] = true, --Uldir (BFA) uiMapID [1861] = true, --Uldir (BFA) from GetInstanceInfo - --[1712] = true, --Antorus, the Burning Throne - --[1676] = true, --Tomb of Sargeras - --[1648] = true, --Trial of Valor - --[1530] = true, --Nighthold - --[1520] = true, --Emerald Nightmare - --[1448] = true, --Hellfire Citadel - --[1205] = true, --Blackrock Foundry - --[1228] = true, --Highmaul - --[1136] = true, --SoO } _detalhes.BitfieldSwapDebuffsIDs = { @@ -91,6 +87,7 @@ do 260926, --BFA Waycrest Manor Heartsbane Triad Soul Manipulation } + --must fail in map and encounter id to not store data _detalhes.EncountersToStoreData = { --> encounterIDs --CLEU [2144] = 1, --Taloc - Taloc @@ -101,6 +98,17 @@ do [2145] = 6, --Zul - Zul, Reborn [2135] = 7, --Mythrax the Unraveler - Mythrax the Unraveler [2122] = 8, --G'huun - G'huun + + [2265] = 1, --Champion of the Light + [2263] = 2, --Grong, the Jungle Lord + [2266] = 3, --Jadefire Masters + [2271] = 4, --Opulence + [2268] = 5, --Conclave of the Chosen + [2272] = 6, --King Rastakhan + [2276] = 7, --High Tinker Mekkatorque + [2280] = 8, --Stormwall Blockade + [2281] = 9, --Lady Jaina Proudmoore + --EJID [2168] = 1, --Taloc [2167] = 2, --MOTHER @@ -110,6 +118,17 @@ do [2195] = 6, --Zul, Reborn [2194] = 7, --Mythrax the Unraveler [2147] = 8, --G'huun + + [2333] = 1, --Champion of the Light + [2325] = 2, --Grong, the Jungle Lord + [2341] = 3, --Jadefire Masters + [2342] = 4, --Opulence + [2330] = 5, --Conclave of the Chosen + [2335] = 6, --King Rastakhan + [2334] = 7, --High Tinker Mekkatorque + [2337] = 8, --Stormwall Blockade + [2343] = 9, --Lady Jaina Proudmoore + } --> armazena os escudos - Shields information for absorbs @@ -254,9 +273,9 @@ do --> Plugins --> plugin templates - + _detalhes.gump:NewColor ("DETAILS_PLUGIN_BUTTONTEXT_COLOR", 0.9999, 0.8196, 0, 1) - + _detalhes.gump:InstallTemplate ("button", "DETAILS_PLUGINPANEL_BUTTON_TEMPLATE", { backdrop = {edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true}, @@ -297,7 +316,22 @@ do width = 120, height = 20, } - ) + ) + + _detalhes.gump:InstallTemplate ("button", "DETAILS_TAB_BUTTON_TEMPLATE", + { + width = 100, + height = 20, + }, + "DETAILS_PLUGIN_BUTTON_TEMPLATE" + ) + _detalhes.gump:InstallTemplate ("button","DETAILS_TAB_BUTTONSELECTED_TEMPLATE", + { + width = 100, + height = 20, + }, + "DETAILS_PLUGIN_BUTTONSELECTED_TEMPLATE" + ) _detalhes.PluginsGlobalNames = {} _detalhes.PluginsLocalizedNames = {} diff --git a/core/plugins.lua b/core/plugins.lua index 54218710..ba86da2b 100644 --- a/core/plugins.lua +++ b/core/plugins.lua @@ -483,16 +483,16 @@ -- --> plugins menu title bar local titlebar_plugins = CreateFrame ("frame", nil, menuBackground) - titlebar_plugins:SetPoint ("topleft", menuBackground, "topleft", 2, -3) - titlebar_plugins:SetPoint ("topright", menuBackground, "topright", -2, -3) + PixelUtil.SetPoint (titlebar_plugins, "topleft", menuBackground, "topleft", 2, -3) + PixelUtil.SetPoint (titlebar_plugins, "topright", menuBackground, "topright", -2, -3) titlebar_plugins:SetHeight (f.TitleHeight) titlebar_plugins:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\AddOns\Details\images\background]], tileSize = 64, tile = true}) titlebar_plugins:SetBackdropColor (.5, .5, .5, 1) titlebar_plugins:SetBackdropBorderColor (0, 0, 0, 1) --> title local titleLabel = _detalhes.gump:NewLabel (titlebar_plugins, titlebar_plugins, nil, "titulo", "Plugins", "GameFontHighlightLeft", 12, {227/255, 186/255, 4/255}) - titleLabel:SetPoint ("center", titlebar_plugins , "center") - titleLabel:SetPoint ("top", titlebar_plugins , "top", 0, -5) + PixelUtil.SetPoint (titleLabel, "center", titlebar_plugins , "center", 0, 0) + PixelUtil.SetPoint (titleLabel, "top", titlebar_plugins , "top", 0, -5) --> plugins menu title bar local titlebar_tools = CreateFrame ("frame", nil, menuBackground) @@ -502,8 +502,8 @@ titlebar_tools:SetBackdropBorderColor (0, 0, 0, 1) --> title local titleLabel = _detalhes.gump:NewLabel (titlebar_tools, titlebar_tools, nil, "titulo", "Tools", "GameFontHighlightLeft", 12, {227/255, 186/255, 4/255}) - titleLabel:SetPoint ("center", titlebar_tools , "center") - titleLabel:SetPoint ("top", titlebar_tools , "top", 0, -5) + PixelUtil.SetPoint (titleLabel, "center", titlebar_tools , "center", 0, 0) + PixelUtil.SetPoint (titleLabel, "top", titlebar_tools , "top", 0, -5) --> scripts f:SetScript ("OnShow", function() @@ -628,7 +628,7 @@ --frame:SetScript ("OnHide", on_hide) frame:HookScript ("OnHide", on_hide) frame:ClearAllPoints() - frame:SetPoint ("topleft", f, "topleft", 0, 0) + PixelUtil.SetPoint (frame, "topleft", f, "topleft", 0, 0) frame:Show() end @@ -666,7 +666,7 @@ local addingTools = false for index, button in ipairs (f.MenuButtons) do button:ClearAllPoints() - button:SetPoint ("center", menuBackground, "center") + PixelUtil.SetPoint (button, "center", menuBackground, "center", 0, 0) if (button.IsUtility) then --> add -20 to add a gap between plugins and utilities @@ -674,13 +674,13 @@ if (not addingTools) then --> add the header addingTools = true - titlebar_tools:SetPoint ("topleft", menuBackground, "topleft", 2, f.MenuY + ( (index-1) * -f.MenuButtonHeight ) - index - 20) - titlebar_tools:SetPoint ("topright", menuBackground, "topright", -2, f.MenuY + ( (index-1) * -f.MenuButtonHeight ) - index - 20) + PixelUtil.SetPoint (titlebar_tools, "topleft", menuBackground, "topleft", 2, f.MenuY + ( (index-1) * -f.MenuButtonHeight ) - index - 20) + PixelUtil.SetPoint (titlebar_tools, "topright", menuBackground, "topright", -2, f.MenuY + ( (index-1) * -f.MenuButtonHeight ) - index - 20) end - button:SetPoint ("top", menuBackground, "top", 0, f.MenuY + ( (index-1) * -f.MenuButtonHeight ) - index - 40) + PixelUtil.SetPoint (button, "top", menuBackground, "top", 0, f.MenuY + ( (index-1) * -f.MenuButtonHeight ) - index - 40) else - button:SetPoint ("top", menuBackground, "top", 0, f.MenuY + ( (index-1) * -f.MenuButtonHeight ) - index) + PixelUtil.SetPoint (button, "top", menuBackground, "top", 0, f.MenuY + ( (index-1) * -f.MenuButtonHeight ) - index) end end diff --git a/functions/link.lua b/functions/link.lua index 254d97da..53a1c911 100644 --- a/functions/link.lua +++ b/functions/link.lua @@ -4860,6 +4860,212 @@ function _detalhes:OpenPlayerDetails (window) end end +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +--> extra buttons at the death options (release, death recap) + +local detailsOnDeathMenu = CreateFrame ("frame", "DetailsOnDeathMenu", UIParent) +detailsOnDeathMenu:SetHeight (30) +detailsOnDeathMenu.Debug = false +detailsOnDeathMenu:RegisterEvent ("PLAYER_REGEN_ENABLED") +detailsOnDeathMenu:RegisterEvent ("ENCOUNTER_END") +DetailsFramework:ApplyStandardBackdrop (detailsOnDeathMenu) +detailsOnDeathMenu:SetAlpha (0.75) + +--disable text +detailsOnDeathMenu.disableLabel = _detalhes.gump:CreateLabel (detailsOnDeathMenu, "you can disable this at /details > Raid Tools", 9) + +detailsOnDeathMenu.warningLabel = _detalhes.gump:CreateLabel (detailsOnDeathMenu, "", 11) +detailsOnDeathMenu.warningLabel.textcolor = "red" +detailsOnDeathMenu.warningLabel:SetPoint ("bottomleft", detailsOnDeathMenu, "bottomleft", 5, 2) +detailsOnDeathMenu.warningLabel:Hide() + +detailsOnDeathMenu:SetScript ("OnEvent", function (self, event, ...) + if (event == "ENCOUNTER_END") then --event == "PLAYER_REGEN_ENABLED" or + print ("encounter ended") + C_Timer.After (0.5, detailsOnDeathMenu.ShowPanel) + end +end) + +function detailsOnDeathMenu.OpenEncounterBreakdown() + if (not _detalhes:GetPlugin ("DETAILS_PLUGIN_ENCOUNTER_DETAILS")) then + detailsOnDeathMenu.warningLabel.text = "Encounter Breakdown plugin is disabled! Please enable it in the Addon Control Panel." + detailsOnDeathMenu.warningLabel:Show() + C_Timer.After (5, function() + detailsOnDeathMenu.warningLabel:Hide() + end) + end + + Details:OpenPlugin ("Encounter Breakdown") +end + +function detailsOnDeathMenu.OpenPlayerEndurance() + if (not _detalhes:GetPlugin ("DETAILS_PLUGIN_DEATH_GRAPHICS")) then + detailsOnDeathMenu.warningLabel.text = "Advanced Death Logs plugin is disabled! Please enable it (or download) in the Addon Control Panel." + detailsOnDeathMenu.warningLabel:Show() + C_Timer.After (5, function() + detailsOnDeathMenu.warningLabel:Hide() + end) + end + + DetailsPluginContainerWindow.OnMenuClick (nil, nil, "DETAILS_PLUGIN_DEATH_GRAPHICS", true) + + C_Timer.After (0, function() + local a = Details_DeathGraphsModeEnduranceButton and Details_DeathGraphsModeEnduranceButton.MyObject:Click() + end) +end + +function detailsOnDeathMenu.OpenPlayerSpells() + + local window1 = Details:GetWindow (1) + local window2 = Details:GetWindow (2) + local window3 = Details:GetWindow (3) + local window4 = Details:GetWindow (4) + + local assignedRole = UnitGroupRolesAssigned ("player") + if (assignedRole == "HEALER") then + if (window1 and window1:GetDisplay() == 2) then + Details:OpenPlayerDetails(1) + + elseif (window2 and window2:GetDisplay() == 2) then + Details:OpenPlayerDetails(2) + + elseif (window3 and window3:GetDisplay() == 2) then + Details:OpenPlayerDetails(3) + + elseif (window4 and window4:GetDisplay() == 2) then + Details:OpenPlayerDetails(4) + + else + Details:OpenPlayerDetails (1) + end + else + if (window1 and window1:GetDisplay() == 1) then + Details:OpenPlayerDetails(1) + + elseif (window2 and window2:GetDisplay() == 1) then + Details:OpenPlayerDetails(2) + + elseif (window3 and window3:GetDisplay() == 1) then + Details:OpenPlayerDetails(3) + + elseif (window4 and window4:GetDisplay() == 1) then + Details:OpenPlayerDetails(4) + + else + Details:OpenPlayerDetails (1) + end + end + +end + +--encounter breakdown button +detailsOnDeathMenu.breakdownButton = _detalhes.gump:CreateButton (detailsOnDeathMenu, detailsOnDeathMenu.OpenEncounterBreakdown, 120, 20, "Encounter Breakdown", "breakdownButton") +detailsOnDeathMenu.breakdownButton:SetTemplate (_detalhes.gump:GetTemplate ("button", "DETAILS_PLUGINPANEL_BUTTON_TEMPLATE")) +detailsOnDeathMenu.breakdownButton:SetPoint ("topleft", detailsOnDeathMenu, "topleft", 5, -5) +detailsOnDeathMenu.breakdownButton:Hide() + +--player endurance button +detailsOnDeathMenu.enduranceButton = _detalhes.gump:CreateButton (detailsOnDeathMenu, detailsOnDeathMenu.OpenPlayerEndurance, 120, 20, "Player Endurance", "enduranceButton") +detailsOnDeathMenu.enduranceButton:SetTemplate (_detalhes.gump:GetTemplate ("button", "DETAILS_PLUGINPANEL_BUTTON_TEMPLATE")) +detailsOnDeathMenu.enduranceButton:SetPoint ("topleft", detailsOnDeathMenu.breakdownButton, "topright", 2, 0) +detailsOnDeathMenu.enduranceButton:Hide() + +--spells +detailsOnDeathMenu.spellsButton = _detalhes.gump:CreateButton (detailsOnDeathMenu, detailsOnDeathMenu.OpenPlayerSpells, 48, 20, "Spells", "SpellsButton") +detailsOnDeathMenu.spellsButton:SetTemplate (_detalhes.gump:GetTemplate ("button", "DETAILS_PLUGINPANEL_BUTTON_TEMPLATE")) +detailsOnDeathMenu.spellsButton:SetPoint ("topleft", detailsOnDeathMenu.enduranceButton, "topright", 2, 0) +detailsOnDeathMenu.spellsButton:Hide() + +function detailsOnDeathMenu.CanShowPanel() + if (StaticPopup_Visible ("DEATH")) then + if (not _detalhes.on_death_menu) then + return + end + + if (detailsOnDeathMenu.Debug) then + return true + end + + --> check if the player just wiped in an encounter + if (IsInRaid()) then + local isInInstance = IsInInstance() + if (isInInstance) then + --> check if all players in the raid are out of combat + for i = 1, GetNumGroupMembers() do + if (UnitAffectingCombat ("raid" .. i)) then + C_Timer.After (0.5, detailsOnDeathMenu.ShowPanel) + return false + end + end + + if (_detalhes.in_combat) then + C_Timer.After (0.5, detailsOnDeathMenu.ShowPanel) + return false + end + + return true + end + end + end +end + +function detailsOnDeathMenu.ShowPanel() + if (not detailsOnDeathMenu.CanShowPanel()) then + return + end + + if (ElvUI) then + detailsOnDeathMenu:SetPoint ("topleft", StaticPopup1, "bottomleft", 0, -1) + detailsOnDeathMenu:SetPoint ("topright", StaticPopup1, "bottomright", 0, -1) + else + detailsOnDeathMenu:SetPoint ("topleft", StaticPopup1, "bottomleft", 4, 2) + detailsOnDeathMenu:SetPoint ("topright", StaticPopup1, "bottomright", -4, 2) + end + + detailsOnDeathMenu.breakdownButton:Show() + detailsOnDeathMenu.enduranceButton:Show() + detailsOnDeathMenu.spellsButton:Show() + + detailsOnDeathMenu:Show() + + detailsOnDeathMenu:SetHeight (30) + + if (not _detalhes:GetTutorialCVar ("DISABLE_ONDEATH_PANEL")) then + detailsOnDeathMenu.disableLabel:Show() + detailsOnDeathMenu.disableLabel:SetPoint ("bottomleft", detailsOnDeathMenu, "bottomleft", 5, 1) + detailsOnDeathMenu.disableLabel.color = "gray" + detailsOnDeathMenu.disableLabel.alpha = 0.5 + detailsOnDeathMenu:SetHeight (detailsOnDeathMenu:GetHeight() + 10) + + if (math.random (1, 3) == 3) then + _detalhes:SetTutorialCVar ("DISABLE_ONDEATH_PANEL", true) + end + end +end + +hooksecurefunc ("StaticPopup_Show", function (which, text_arg1, text_arg2, data, insertedFrame) + --print (which, text_arg1, text_arg2, data, insertedFrame) + --print ("popup Show:", which) + if (which == "DEATH") then + --StaticPopup1 + if (detailsOnDeathMenu.Debug) then + C_Timer.After (0.5, detailsOnDeathMenu.ShowPanel) + end + end +end) + +hooksecurefunc ("StaticPopup_Hide", function (which, data) +-- if (which and which:find ("EQUIP")) then +-- return +-- end + + --print ("popup Hide:", which) + + if (which == "DEATH") then + detailsOnDeathMenu:Hide() + end +end) + --endd \ No newline at end of file diff --git a/functions/profiles.lua b/functions/profiles.lua index 0e2f781f..b5057e85 100644 --- a/functions/profiles.lua +++ b/functions/profiles.lua @@ -1246,6 +1246,9 @@ local default_player_data = { last_difficulty = 15, last_raid = "", }, + + --> death panel buttons + on_death_menu = true, } _detalhes.default_player_data = default_player_data diff --git a/functions/raidinfo.lua b/functions/raidinfo.lua index 950f1090..522cd8ba 100644 --- a/functions/raidinfo.lua +++ b/functions/raidinfo.lua @@ -2,6 +2,194 @@ --> install data for raiding tiers +do + --> data for Crucible of Storms (BFA tier 1) + + local INSTANCE_EJID = 1177 + local INSTANCE_MAPID = 0 --TBD + local HDIMAGESPATH = "Details\\images\\raid" + local HDFILEPREFIX = "CrucibleRaid" + local LOADINGSCREEN_FILE, LOADINGSCREEN_COORDS = "LoadingScreen_Seapriestraid_wide_BattleforAzeroth", {0, 1, 285/1024, 875/1024} + local EJ_LOREBG = "UI-EJ-LOREBG-CrucibleOfStorms" + + local PORTRAIT_LIST = { + 2497795, --Zaxasj the Speaker - The Restless Cabal + 2497794, --Uu'nat - Uu'nat, Harbinger of the Void + } + + local ENCOUNTER_ID_CL = { + 2269, 2273, + [2269] = 1, --The Restless Cabal + [2273] = 2, --Uu'nat, Harbinger of the Void + } + + local ENCOUNTER_ID_EJ = { + 2328, 2332, + [2328] = 1, --The Restless Cabal + [2332] = 2, --Uu'nat, Harbinger of the Void + } + + --> install the raid + C_Timer.After (10, function() + + --load encounter journal + EJ_SelectInstance (INSTANCE_EJID) + + local InstanceName = EJ_GetInstanceInfo (INSTANCE_EJID) + + --build the boss name list + local BOSSNAMES = {} + local ENCOUNTERS = {} + + for i = 1, #PORTRAIT_LIST do + local bossName = EJ_GetEncounterInfoByIndex (i, INSTANCE_EJID) + if (bossName) then + tinsert (BOSSNAMES, bossName) + local encounterTable = { + boss = bossName, + --portrait = "Interface\\EncounterJournal\\" .. PORTRAIT_LIST [i], + portrait = PORTRAIT_LIST [i], + } + tinsert (ENCOUNTERS, encounterTable) + else + break + end + end + + _detalhes:InstallEncounter ({ + id = INSTANCE_MAPID, --map id + ej_id = INSTANCE_EJID, --encounter journal id + name = InstanceName, + icons = "Interface\\AddOns\\" .. HDIMAGESPATH .. "\\" .. HDFILEPREFIX .. "_BossFaces", + icon = "Interface\\AddOns\\" .. HDIMAGESPATH .. "\\" .. HDFILEPREFIX .. "_Icon256x128", + is_raid = true, + backgroundFile = {file = "Interface\\Glues\\LOADINGSCREENS\\" .. LOADINGSCREEN_FILE, coords = LOADINGSCREEN_COORDS}, + backgroundEJ = "Interface\\EncounterJournal\\" .. EJ_LOREBG, + + encounter_ids = ENCOUNTER_ID_EJ, + encounter_ids2 = ENCOUNTER_ID_CL, + boss_names = BOSSNAMES, + encounters = ENCOUNTERS, + + boss_ids = { + --npc ids + }, + }) + end) + +end + +do + --> data for Battle for Dazar'alor (BFA tier 1) + +-- DazaralorRaid_BossFaces.tga --TBD +-- DazaralorRaid_Icon256x128.tga --TBD + + local INSTANCE_EJID = 1176 + local INSTANCE_MAPID = 2070 + local HDIMAGESPATH = "Details\\images\\raid" + local HDFILEPREFIX = "DazaralorRaid" + local LOADINGSCREEN_FILE, LOADINGSCREEN_COORDS = "LoadScreen_ZuldazarRaid_Wide", {0, 1, 285/1024, 875/1024} + local EJ_LOREBG = "UI-EJ-LOREBG-BattleOfDazaralor" + + local PORTRAIT_LIST = { + 2497778, --Frida Ironbellows - Champion of the Light + 2497783, --Grong - Grong, the Jungle Lord + 2529383, --Manceroy Flamefist - Jadefire Masters + 2497790, --Opulence - Opulence + 2497779, --Pa'ku's Aspect - Conclave of the Chosen + 2497784, --King Rastakhan - King Rastakhan + 2497788, --High Tinker Mekkatorque - High Tinker Mekkatorque + 2497786, --Laminaria - Stormwall Blockade + 2497785, --Lady Jaina Proudmoore - Lady Jaina Proudmoore + } + + local ENCOUNTER_ID_CL = { + 2265, 2263, 2266, 2271, 2268, 2272, 2276, 2280, 2281, + [2265] = 1, --Champion of the Light + [2263] = 2, --Grong, the Jungle Lord + [2266] = 3, --Jadefire Masters + [2271] = 4, --Opulence + [2268] = 5, --Conclave of the Chosen + [2272] = 6, --King Rastakhan + [2276] = 7, --High Tinker Mekkatorque + [2280] = 8, --Stormwall Blockade + [2281] = 9, --Lady Jaina Proudmoore + } + + local ENCOUNTER_ID_EJ = { + 2333, 2325, 2341, 2342, 2330, 2335, 2334, 2337, 2343, + [2333] = 1, --Champion of the Light + [2325] = 2, --Grong, the Jungle Lord + [2341] = 3, --Jadefire Masters + [2342] = 4, --Opulence + [2330] = 5, --Conclave of the Chosen + [2335] = 6, --King Rastakhan + [2334] = 7, --High Tinker Mekkatorque + [2337] = 8, --Stormwall Blockade + [2343] = 9, --Lady Jaina Proudmoore + } + + --> install the raid + C_Timer.After (10, function() + + --load encounter journal + EJ_SelectInstance (INSTANCE_EJID) + + local InstanceName = EJ_GetInstanceInfo (INSTANCE_EJID) + + --build the boss name list + local BOSSNAMES = {} + local ENCOUNTERS = {} + + for i = 1, #PORTRAIT_LIST do + local bossName = EJ_GetEncounterInfoByIndex (i, INSTANCE_EJID) + if (bossName) then + tinsert (BOSSNAMES, bossName) + local encounterTable = { + boss = bossName, + --portrait = "Interface\\EncounterJournal\\" .. PORTRAIT_LIST [i], + portrait = PORTRAIT_LIST [i], + } + tinsert (ENCOUNTERS, encounterTable) + else + break + end + end + + _detalhes:InstallEncounter ({ + id = INSTANCE_MAPID, --map id + ej_id = INSTANCE_EJID, --encounter journal id + name = InstanceName, + icons = "Interface\\AddOns\\" .. HDIMAGESPATH .. "\\" .. HDFILEPREFIX .. "_BossFaces", + icon = "Interface\\AddOns\\" .. HDIMAGESPATH .. "\\" .. HDFILEPREFIX .. "_Icon256x128", + is_raid = true, + backgroundFile = {file = "Interface\\Glues\\LOADINGSCREENS\\" .. LOADINGSCREEN_FILE, coords = LOADINGSCREEN_COORDS}, + backgroundEJ = "Interface\\EncounterJournal\\" .. EJ_LOREBG, + + encounter_ids = ENCOUNTER_ID_EJ, + encounter_ids2 = ENCOUNTER_ID_CL, + boss_names = BOSSNAMES, + encounters = ENCOUNTERS, + + boss_ids = { + --npc ids + }, + }) + end) + +end + + + + + + + + + + + do --> data for Uldir (BFA tier 1) diff --git a/gumps/janela_info.lua b/gumps/janela_info.lua index beca15f0..239bef9f 100644 --- a/gumps/janela_info.lua +++ b/gumps/janela_info.lua @@ -1785,6 +1785,14 @@ function gump:CriaJanelaInfo() --> tabs: --> tab default + + local iconTableSummary = { + texture = [[Interface\AddOns\Details\images\icons]], + coords = {238/512, 255/512, 0, 18/512}, + width = 16, + height = 16, + } + _detalhes:CreatePlayerDetailsTab ("Summary", Loc ["STRING_SPELLS"], --[1] tab name [2] localized name function (tabOBject, playerObject) --[2] condition if (playerObject) then @@ -1799,7 +1807,8 @@ function gump:CriaJanelaInfo() tab.frame:Hide() end end, - nil --[5] oncreate + nil, --[5] oncreate + iconTableSummary --icon table ) --> search key: ~avoidance --> begining of avoidance tab @@ -2498,6 +2507,14 @@ function gump:CriaJanelaInfo() --]] end + local iconTableAvoidance = { + texture = [[Interface\AddOns\Details\images\icons]], + --coords = {363/512, 381/512, 0/512, 17/512}, + coords = {384/512, 402/512, 19/512, 38/512}, + width = 16, + height = 16, + } + _detalhes:CreatePlayerDetailsTab ("Avoidance", Loc ["STRING_INFO_TAB_AVOIDANCE"], --[1] tab name [2] localized name function (tabOBject, playerObject) --[2] condition if (playerObject.isTank) then @@ -2511,7 +2528,8 @@ function gump:CriaJanelaInfo() nil, --[4] onclick - avoidance_create --[5] oncreate + avoidance_create, --[5] oncreate + iconTableAvoidance ) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -2744,6 +2762,13 @@ function gump:CriaJanelaInfo() end end + local iconTableAuras = { + texture = [[Interface\AddOns\Details\images\icons]], + coords = {257/512, 278/512, 0/512, 19/512}, + width = 16, + height = 16, + } + _detalhes:CreatePlayerDetailsTab ("Auras", "Auras", --[1] tab name [2] localized name function (tabOBject, playerObject) --[2] condition return true @@ -2753,7 +2778,8 @@ function gump:CriaJanelaInfo() nil, --[4] onclick - auras_tab_create --[5] oncreate + auras_tab_create, --[5] oncreate + iconTableAuras --icon table ) @@ -4665,6 +4691,13 @@ function gump:CriaJanelaInfo() -- ~compare + local iconTableCompare = { + texture = [[Interface\AddOns\Details\images\icons]], + --coords = {363/512, 381/512, 0/512, 17/512}, + coords = {383/512, 403/512, 0/512, 15/512}, + width = 16, + height = 14, + } _detalhes:CreatePlayerDetailsTab ("Compare", Loc ["STRING_INFO_TAB_COMPARISON"], --[1] tab name [2] localized name function (tabOBject, playerObject) --[2] condition @@ -4716,7 +4749,8 @@ function gump:CriaJanelaInfo() nil, --[4] onclick - compare_create --[5] oncreate + compare_create, --[5] oncreate + iconTableCompare --icon table ) -- ~tab ~tabs @@ -4757,11 +4791,14 @@ function gump:CriaJanelaInfo() tab:Show() amt_positive = amt_positive + 1 - - --tab:SetPoint ("BOTTOMLEFT", info.container_barras, "TOPLEFT", 490 - (94 * (amt_positive-1)), 1) --left to right tab:ClearAllPoints() - tab:SetPoint ("bottomright", info, "topright", -17 - (94 * (amt_positive-1)), -74) --right to left + --get the button width + local buttonTemplate = gump:GetTemplate ("button", "DETAILS_TAB_BUTTON_TEMPLATE") + local buttonWidth = buttonTemplate.width + 1 + + PixelUtil.SetSize (tab, buttonTemplate.width, buttonTemplate.height) + PixelUtil.SetPoint (tab, "bottomright", info, "topright", -9 - (buttonWidth * (amt_positive-1)), -72) tab:SetAlpha (0.8) else tab.frame:Hide() @@ -4774,7 +4811,6 @@ function gump:CriaJanelaInfo() end _detalhes.player_details_tabs[1]:Click() - end este_gump:SetScript ("OnHide", function (self) @@ -4794,56 +4830,63 @@ end _detalhes.player_details_tabs = {} -function _detalhes:CreatePlayerDetailsTab (tabname, localized_name, condition, fillfunction, onclick, oncreate) +function _detalhes:CreatePlayerDetailsTab (tabname, localized_name, condition, fillfunction, onclick, oncreate, iconSettings) if (not tabname) then tabname = "unnamed" end local index = #_detalhes.player_details_tabs - local newtab = CreateFrame ("button", "DetailsInfoWindowTab" .. index, info, "ChatTabTemplate") - newtab.textWidth = 90 + --create a button for the tab + local newTabButton = gump:CreateButton (info, onclick, 20, 20) + newTabButton:SetTemplate ("DETAILS_TAB_BUTTON_TEMPLATE") + if (tabname == "Summary") then + newTabButton:SetTemplate ("DETAILS_TAB_BUTTONSELECTED_TEMPLATE") + end + newTabButton:SetText (localized_name) + newTabButton:SetFrameStrata ("HIGH") + newTabButton:SetFrameLevel (info:GetFrameLevel()+1) + newTabButton:Hide() - newtab:SetParent (info) - newtab:SetWidth (100) - newtab.middleTexture:SetWidth (70) + newTabButton.condition = condition + newTabButton.tabname = tabname + newTabButton.localized_name = localized_name + newTabButton.onclick = onclick + newTabButton.fillfunction = fillfunction + newTabButton.last_actor = {} - newtab:SetText (localized_name) - _G ["DetailsInfoWindowTab" .. index .. "Text"]:SetWidth (70) + newTabButton.frame = CreateFrame ("frame", "DetailsPDWTabFrame" .. tabname, UIParent) + newTabButton.frame:SetParent (info) + newTabButton.frame:SetFrameStrata ("HIGH") + newTabButton.frame:SetFrameLevel (info:GetFrameLevel()+5) + newTabButton.frame:EnableMouse (true) - newtab:SetFrameStrata ("HIGH") - newtab:SetFrameLevel (info:GetFrameLevel()+1) - newtab:Hide() + if (iconSettings) then + local texture = iconSettings.texture + local coords = iconSettings.coords + local width = iconSettings.width + local height = iconSettings.height + + local overlay, textdistance, leftpadding, textheight, short_method --nil + + newTabButton:SetIcon (texture, width, height, "overlay", coords, overlay, textdistance, leftpadding, textheight, short_method) + end - newtab.condition = condition - newtab.tabname = tabname - newtab.localized_name = localized_name - newtab.onclick = onclick - newtab.fillfunction = fillfunction - newtab.last_actor = {} - - --> frame - newtab.frame = CreateFrame ("frame", "DetailsPDWTabFrame" .. tabname, UIParent) - newtab.frame:SetParent (info) - newtab.frame:SetFrameStrata ("HIGH") - newtab.frame:SetFrameLevel (info:GetFrameLevel()+5) - newtab.frame:EnableMouse (true) - - if (newtab.fillfunction) then - newtab.frame:SetScript ("OnShow", function() - if (newtab.last_actor == info.jogador) then + if (newTabButton.fillfunction) then + newTabButton.frame:SetScript ("OnShow", function() + if (newTabButton.last_actor == info.jogador) then return end - newtab.last_actor = info.jogador - newtab:fillfunction (info.jogador, info.instancia.showing) + newTabButton.last_actor = info.jogador + newTabButton:fillfunction (info.jogador, info.instancia.showing) end) end if (oncreate) then - oncreate (newtab, newtab.frame) + oncreate (newTabButton, newTabButton.frame) end - newtab.frame:SetBackdrop({ + newTabButton.frame:SetBackdrop({ edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\AddOns\Details\images\background]], @@ -4851,55 +4894,45 @@ function _detalhes:CreatePlayerDetailsTab (tabname, localized_name, condition, f tile = true, insets = {left = 0, right = 0, top = 0, bottom = 0}} ) - - newtab.frame:SetBackdropColor (0, 0, 0, 0.3) - newtab.frame:SetBackdropBorderColor (.3, .3, .3, 0) - - newtab.frame:SetPoint ("TOPLEFT", info.container_barras, "TOPLEFT", 0, 2) - newtab.frame:SetPoint ("bottomright", info, "bottomright", -3, 3) - newtab.frame:SetSize (569, 274) - newtab.frame:Hide() + newTabButton.frame:SetBackdropColor (0, 0, 0, 0.3) + newTabButton.frame:SetBackdropBorderColor (.3, .3, .3, 0) + + newTabButton.frame:SetPoint ("TOPLEFT", info.container_barras, "TOPLEFT", 0, 2) + newTabButton.frame:SetPoint ("bottomright", info, "bottomright", -3, 3) + newTabButton.frame:SetSize (569, 274) - --> adicionar ao container - _detalhes.player_details_tabs [#_detalhes.player_details_tabs+1] = newtab + newTabButton.frame:Hide() + + _detalhes.player_details_tabs [#_detalhes.player_details_tabs+1] = newTabButton if (not onclick) then --> hide all tabs - newtab:SetScript ("OnClick", function() + newTabButton:SetScript ("OnClick", function() for _, tab in _ipairs (_detalhes.player_details_tabs) do tab.frame:Hide() - tab.leftSelectedTexture:SetVertexColor (1, 1, 1, 1) - tab.middleSelectedTexture:SetVertexColor (1, 1, 1, 1) - tab.rightSelectedTexture:SetVertexColor (1, 1, 1, 1) + tab:SetTemplate ("DETAILS_TAB_BUTTON_TEMPLATE") end - newtab.leftSelectedTexture:SetVertexColor (1, .7, 0, 1) - newtab.middleSelectedTexture:SetVertexColor (1, .7, 0, 1) - newtab.rightSelectedTexture:SetVertexColor (1, .7, 0, 1) - newtab.frame:Show() + newTabButton:SetTemplate ("DETAILS_TAB_BUTTONSELECTED_TEMPLATE") + newTabButton.frame:Show() end) else --> custom - newtab:SetScript ("OnClick", function() + newTabButton:SetScript ("OnClick", function() for _, tab in _ipairs (_detalhes.player_details_tabs) do tab.frame:Hide() - tab.leftSelectedTexture:SetVertexColor (1, 1, 1, 1) - tab.middleSelectedTexture:SetVertexColor (1, 1, 1, 1) - tab.rightSelectedTexture:SetVertexColor (1, 1, 1, 1) + tab:SetTemplate ("DETAILS_TAB_BUTTON_TEMPLATE") end - newtab.leftSelectedTexture:SetVertexColor (1, .7, 0, 1) - newtab.middleSelectedTexture:SetVertexColor (1, .7, 0, 1) - newtab.rightSelectedTexture:SetVertexColor (1, .7, 0, 1) - + newTabButton:SetTemplate ("DETAILS_TAB_BUTTONSELECTED_TEMPLATE") onclick() end) end - newtab:SetScript ("PostClick", function (self) - CurrentTab = self.tabname - + newTabButton:SetScript ("PostClick", function (self) + CurrentTab = self.tabname or self.MyObject.tabname + if (CurrentTab ~= "Summary") then for _, widget in ipairs (SummaryWidgets) do widget:Hide() @@ -4911,12 +4944,6 @@ function _detalhes:CreatePlayerDetailsTab (tabname, localized_name, condition, f end end) - --> remove os scripts padroes - newtab:SetScript ("OnDoubleClick", nil) - newtab:SetScript ("OnEnter", nil) - newtab:SetScript ("OnLeave", nil) - newtab:SetScript ("OnDragStart", nil) - end function _detalhes.janela_info:monta_relatorio (botao) diff --git a/gumps/janela_options.lua b/gumps/janela_options.lua index 388f8f7e..53a44440 100644 --- a/gumps/janela_options.lua +++ b/gumps/janela_options.lua @@ -10888,6 +10888,19 @@ function window:CreateFrame11() window:CreateLineBackground2 (frame11, "EnabledFirstHitSlider", "EnabledFirstHitLabel", Loc ["STRING_OPTIONS_RT_FIRST_HIT_DESC"]) + --> death menu + g:NewLabel (frame11, _, "$parentShowDeathMenuLabel", "ShowDeathMenuLabel", "Show Death Menu", "GameFontHighlightLeft") --localize-me + g:NewSwitch (frame11, _, "$parentShowDeathMenuSlider", "ShowDeathMenuSlider", 60, 20, _, _, _detalhes.on_death_menu, nil, nil, nil, nil, options_switch_template) + + frame11.ShowDeathMenuSlider:SetPoint ("left", frame11.ShowDeathMenuLabel, "right", 2) + frame11.ShowDeathMenuSlider:SetAsCheckBox() + frame11.ShowDeathMenuSlider.OnSwitch = function (_, _, value) + _detalhes.on_death_menu = value + _detalhes:SendOptionsModifiedEvent (DetailsOptionsWindow.instance) + end + + window:CreateLineBackground2 (frame11, "ShowDeathMenuSlider", "ShowDeathMenuLabel", "Show a panel below the Release / Death Recap panel with some shortcuts for Raid Leaders.") --localize-me + --> anchors --announcers anchor @@ -10934,6 +10947,7 @@ function window:CreateFrame11() {"AnnouncersOther", 6, true}, {"EnabledPrePotLabel", 7}, {"EnabledFirstHitLabel", 8}, + {"ShowDeathMenuLabel", 9}, } window:arrange_menu (frame11, right_side, window.right_start_at, window.top_start_at) diff --git a/images/icons.tga b/images/icons.tga index 42981098..fb8ac36b 100644 Binary files a/images/icons.tga and b/images/icons.tga differ diff --git a/images/raid/CrucibleRaid_BossFaces.tga b/images/raid/CrucibleRaid_BossFaces.tga new file mode 100644 index 00000000..5d05b71f Binary files /dev/null and b/images/raid/CrucibleRaid_BossFaces.tga differ diff --git a/images/raid/CrucibleRaid_Icon256x128.tga b/images/raid/CrucibleRaid_Icon256x128.tga new file mode 100644 index 00000000..01c0f6dd Binary files /dev/null and b/images/raid/CrucibleRaid_Icon256x128.tga differ diff --git a/images/raid/DazaralorRaid_BossFaces.tga b/images/raid/DazaralorRaid_BossFaces.tga new file mode 100644 index 00000000..17511188 Binary files /dev/null and b/images/raid/DazaralorRaid_BossFaces.tga differ diff --git a/images/raid/DazaralorRaid_Icon256x128.tga b/images/raid/DazaralorRaid_Icon256x128.tga new file mode 100644 index 00000000..8f10f83a Binary files /dev/null and b/images/raid/DazaralorRaid_Icon256x128.tga differ diff --git a/images/spec_icons_normal.tga b/images/spec_icons_normal.tga index f65cad68..7ccfa721 100644 Binary files a/images/spec_icons_normal.tga and b/images/spec_icons_normal.tga differ diff --git a/images/spec_icons_normal_alpha.tga b/images/spec_icons_normal_alpha.tga index a7965ae4..bd32da0f 100644 Binary files a/images/spec_icons_normal_alpha.tga and b/images/spec_icons_normal_alpha.tga differ diff --git a/plugins/Details_3DModelsPaths/Details_3DModelsPaths.toc b/plugins/Details_3DModelsPaths/Details_3DModelsPaths.toc index 159fa6cc..af3de1a8 100644 --- a/plugins/Details_3DModelsPaths/Details_3DModelsPaths.toc +++ b/plugins/Details_3DModelsPaths/Details_3DModelsPaths.toc @@ -1,4 +1,4 @@ -## Interface: 80000 +## Interface: 80100 ## Title: Details! 3D Model Viewer ## Notes: When the 3d models option is enabled, this tool is used to select which model will be used on the window's rows. ## DefaultState: Enabled diff --git a/plugins/Details_DataStorage/Details_DataStorage.toc b/plugins/Details_DataStorage/Details_DataStorage.toc index 0ef21e4f..140ed990 100644 --- a/plugins/Details_DataStorage/Details_DataStorage.toc +++ b/plugins/Details_DataStorage/Details_DataStorage.toc @@ -1,4 +1,4 @@ -## Interface: 80000 +## Interface: 80100 ## Title: Details Storage ## Notes: Stores information for Details! ## DefaultState: Enabled diff --git a/plugins/Details_DmgRank/Details_DmgRank.toc b/plugins/Details_DmgRank/Details_DmgRank.toc index 42b2099c..ab0716f4 100644 --- a/plugins/Details_DmgRank/Details_DmgRank.toc +++ b/plugins/Details_DmgRank/Details_DmgRank.toc @@ -1,4 +1,4 @@ -## Interface: 80000 +## Interface: 80100 ## Title: Details Damage, the Game! (plugin) ## Notes: Plugin for Details ## RequiredDeps: Details diff --git a/plugins/Details_DpsTuning/Details_DpsTuning.toc b/plugins/Details_DpsTuning/Details_DpsTuning.toc index 8145b39b..c093cc91 100644 --- a/plugins/Details_DpsTuning/Details_DpsTuning.toc +++ b/plugins/Details_DpsTuning/Details_DpsTuning.toc @@ -1,4 +1,4 @@ -## Interface: 80000 +## Interface: 80100 ## Title: Details Dps Tuning (plugin) ## Notes: Plugin for Details ## RequiredDeps: Details diff --git a/plugins/Details_EncounterDetails/Details_EncounterDetails.lua b/plugins/Details_EncounterDetails/Details_EncounterDetails.lua index 2aae2e2d..c395d839 100644 --- a/plugins/Details_EncounterDetails/Details_EncounterDetails.lua +++ b/plugins/Details_EncounterDetails/Details_EncounterDetails.lua @@ -3,6 +3,13 @@ local Loc = AceLocale:GetLocale ("Details_EncounterDetails") local Graphics = LibStub:GetLibrary("LibGraph-2.0") local _ +local isDebug = false +local function DebugMessage (...) + if (isDebug) then + print ("|cFFFFFF00EBreakDown|r:", ...) + end +end + --> Needed locals local _GetTime = GetTime --> wow api local local _UFC = UnitAffectingCombat --> wow api local @@ -49,7 +56,7 @@ local sort_by_name = function (t1, t2) return t1.nome < t2.nome end local CLASS_ICON_TCOORDS = _G.CLASS_ICON_TCOORDS -EncounterDetails.name = "Encounter Details" +EncounterDetails.name = "Encounter Breakdown" EncounterDetails.debugmode = false function EncounterDetails:FormatCooltipSettings() @@ -390,7 +397,7 @@ local function CreatePluginFrames (data) local alert = CreateFrame ("frame", "EncounterDetailsTutorialAlertButton1", EncounterDetails.ToolbarButton, "MicroButtonAlertTemplate") alert:SetFrameLevel (302) - alert.label = "Click here (on the skull icon) to bring the Encounter Details panel" + alert.label = "Click here (on the skull icon) to bring the Encounter Breakdown panel" alert.Text:SetSpacing (4) alert:SetClampedToScreen (true) MicroButtonAlert_SetText (alert, alert.label) @@ -491,8 +498,19 @@ local function CreatePluginFrames (data) end + EncounterDetailsFrame:HookScript ("OnShow", function() + C_Timer.After (0.1, function() + if (not EncounterDetails.LastOpenedTime or EncounterDetails.LastOpenedTime + 2 < GetTime()) then + if (_detalhes.AddOnStartTime and _detalhes.AddOnStartTime + 30 < GetTime()) then + EncounterDetails:OpenAndRefresh() + end + end + end) + end) + --> user clicked on button, need open or close window function EncounterDetails:OpenWindow() + if (EncounterDetails.Frame:IsShown()) then return EncounterDetails:CloseWindow() end @@ -1144,23 +1162,45 @@ function EncounterDetails:OpenAndRefresh (_, segment) local frame = EncounterDetailsFrame --alias + DebugMessage ("OpenAndRefresh() called") + + EncounterDetails.LastOpenedTime = GetTime() + + _G [frame:GetName().."SegmentsDropdown"].MyObject:Refresh() + if (segment) then _combat_object = EncounterDetails:GetCombat (segment) EncounterDetails._segment = segment + + DebugMessage ("there's a segment to use:", segment, _combat_object, _combat_object and _combat_object.is_boss) + else + DebugMessage ("no segment has been passed, looping segments to find one.") + local historico = _detalhes.tabela_historico.tabelas + local foundABoss = false + for index, combate in ipairs (historico) do if (combate.is_boss and combate.is_boss.index) then - _G [frame:GetName().."SegmentsDropdown"].MyObject:Select (index) EncounterDetails._segment = index _combat_object = combate + + DebugMessage ("segment found: ", index, combate:GetCombatName(), combate.is_trash) + _G [frame:GetName().."SegmentsDropdown"].MyObject:Select (index, true) + + foundABoss = index break end end + + if (not foundABoss) then + DebugMessage ("boss not found during the segment loop") + end end if (not _combat_object) then EncounterDetails:Msg ("no combat found.") + DebugMessage ("_combat_object is nil, EXIT") return end @@ -1181,16 +1221,32 @@ function EncounterDetails:OpenAndRefresh (_, segment) end if (not _combat_object.is_boss) then - for _, combat in _ipairs (EncounterDetails:GetCombatSegments()) do + + DebugMessage ("_combat_object is not a boss, trying another loop in the segments") + + local foundSegment + for index, combat in _ipairs (EncounterDetails:GetCombatSegments()) do if (combat.is_boss and EncounterDetails:GetBossDetails (combat.is_boss.mapid, combat.is_boss.index)) then _combat_object = combat + _G [frame:GetName().."SegmentsDropdown"].MyObject:Select (index, true) + + DebugMessage ("found another segment during another loop", index, combat:GetCombatName(), combat.is_trash) + foundSegment = true break end end + + if (not foundSegment) then + DebugMessage ("boss not found during the second loop segment") + end + if (not _combat_object.is_boss) then + DebugMessage ("_combat_object still isn't a boss segment, trying to get the last segment shown.") if (EncounterDetails.LastSegmentShown) then _combat_object = EncounterDetails.LastSegmentShown + DebugMessage ("found the last segment shown, using it.") else + DebugMessage ("the segment isn't a boss, EXIT.") return end end @@ -1198,6 +1254,8 @@ function EncounterDetails:OpenAndRefresh (_, segment) --> the segment is a boss + DebugMessage ("segment are OKAY, updating the panel") + boss_id = _combat_object.is_boss.index map_id = _combat_object.is_boss.mapid boss_info = _detalhes:GetBossDetails (_combat_object.is_boss.mapid, _combat_object.is_boss.index) diff --git a/plugins/Details_EncounterDetails/Details_EncounterDetails.toc b/plugins/Details_EncounterDetails/Details_EncounterDetails.toc index 72a643ce..2b3e5278 100644 --- a/plugins/Details_EncounterDetails/Details_EncounterDetails.toc +++ b/plugins/Details_EncounterDetails/Details_EncounterDetails.toc @@ -1,6 +1,6 @@ -## Interface: 80000 -## Title: Details Encounter (plugin) -## Notes: Plugin for Details +## Interface: 80100 +## Title: Details!: Encounter Breakdown (plugin) +## Notes: Show detailed information about a boss encounter. Also provide damage per phase, graphic charts, easy weakauras creation. ## RequiredDeps: Details ## OptionalDeps: Ace3 ## SavedVariablesPerCharacter: EncounterDetailsDB diff --git a/plugins/Details_EncounterDetails/enUS.lua b/plugins/Details_EncounterDetails/enUS.lua index 3bfb476a..5a6121b8 100644 --- a/plugins/Details_EncounterDetails/enUS.lua +++ b/plugins/Details_EncounterDetails/enUS.lua @@ -4,8 +4,8 @@ if (not Loc) then return end -Loc ["STRING_PLUGIN_NAME"] = "Encounter Details" -Loc ["STRING_WINDOW_TITLE"] = "Details! Encounter Info" +Loc ["STRING_PLUGIN_NAME"] = "Encounter Breakdown" +Loc ["STRING_WINDOW_TITLE"] = "Details! Encounter Breakdown" Loc ["STRING_TOTAL_DAMAGE"] = "Total Damage" Loc ["STRING_TOTAL_HEAL"] = "Total Heal" Loc ["STRING_SHOW_ALL_DATA"] = "Show overall data" diff --git a/plugins/Details_EncounterDetails/frames.lua b/plugins/Details_EncounterDetails/frames.lua index d24bc29b..bc2e2101 100644 --- a/plugins/Details_EncounterDetails/frames.lua +++ b/plugins/Details_EncounterDetails/frames.lua @@ -76,7 +76,7 @@ _detalhes.EncounterDetailsTempWindow = function (EncounterDetails) local build_options_panel = function() - local options_frame = EncounterDetails:CreatePluginOptionsFrame ("EncounterDetailsOptionsWindow", "Encounter Details Options", 2) + local options_frame = EncounterDetails:CreatePluginOptionsFrame ("EncounterDetailsOptionsWindow", "Encounter Breakdown Options", 2) -- 1 = only when inside a raid map -- 2 = only when in raid group @@ -132,7 +132,7 @@ _detalhes.EncounterDetailsTempWindow = function (EncounterDetails) type = "toggle", get = function() return EncounterDetails.db.hide_on_combat end, set = function (self, fixedparam, value) EncounterDetails.db.hide_on_combat = value end, - desc = "Encounter Details window automatically close when you enter in combat.", + desc = "Encounter Breakdown window automatically close when you enter in combat.", name = "Hide on Combat" }, { @@ -2635,7 +2635,7 @@ end BossFrame.MacroEditBox = DetailsFrameWork:CreateTextEntry (frame, function()end, 300, 20) BossFrame.MacroEditBox:SetPoint ("left", options, "right", 10, 0) BossFrame.MacroEditBox:SetAlpha (0.5) - BossFrame.MacroEditBox:SetText ("/run Details:OpenPlugin ('Encounter Details')") + BossFrame.MacroEditBox:SetText ("/run Details:OpenPlugin ('Encounter Breakdown')") BossFrame.MacroEditBox:SetTemplate (DetailsFrameWork:GetTemplate ("button", "DETAILS_PLUGIN_BUTTON_TEMPLATE")) BossFrame.MacroEditBox:SetSize (360, 20) diff --git a/plugins/Details_RaidCheck/Details_RaidCheck.toc b/plugins/Details_RaidCheck/Details_RaidCheck.toc index c25960e1..7b11887e 100644 --- a/plugins/Details_RaidCheck/Details_RaidCheck.toc +++ b/plugins/Details_RaidCheck/Details_RaidCheck.toc @@ -1,4 +1,4 @@ -## Interface: 80000 +## Interface: 80100 ## Title: Details Raid Check (plugin) ## Notes: Show a icon on Details title bar showing flask, food, pre-pots. ## RequiredDeps: Details diff --git a/plugins/Details_Streamer/Details_Streamer.toc b/plugins/Details_Streamer/Details_Streamer.toc index e43bdc35..fa6e590f 100644 --- a/plugins/Details_Streamer/Details_Streamer.toc +++ b/plugins/Details_Streamer/Details_Streamer.toc @@ -1,4 +1,4 @@ -## Interface: 80000 +## Interface: 80100 ## Title: Details!: Streamer (plugin) ## Notes: Show which spells you are casting, viewers can see what are you doing and follow your steps. ## RequiredDeps: Details diff --git a/plugins/Details_TimeAttack/Details_TimeAttack.toc b/plugins/Details_TimeAttack/Details_TimeAttack.toc index 45d5be77..57509e85 100644 --- a/plugins/Details_TimeAttack/Details_TimeAttack.toc +++ b/plugins/Details_TimeAttack/Details_TimeAttack.toc @@ -1,4 +1,4 @@ -## Interface: 80000 +## Interface: 80100 ## Title: Details TimeAttack (plugin) ## Notes: Plugin for Details ## SavedVariablesPerCharacter: _detalhes_databaseTimeAttack diff --git a/plugins/Details_TinyThreat/Details_TinyThreat.toc b/plugins/Details_TinyThreat/Details_TinyThreat.toc index af20b7d6..18c5a7e9 100644 --- a/plugins/Details_TinyThreat/Details_TinyThreat.toc +++ b/plugins/Details_TinyThreat/Details_TinyThreat.toc @@ -1,4 +1,4 @@ -## Interface: 80000 +## Interface: 80100 ## Title: Details Tiny Threat (plugin) ## Notes: Plugin for Details ## RequiredDeps: Details diff --git a/plugins/Details_Vanguard/Details_Vanguard.toc b/plugins/Details_Vanguard/Details_Vanguard.toc index 594c0520..bc06d9fc 100644 --- a/plugins/Details_Vanguard/Details_Vanguard.toc +++ b/plugins/Details_Vanguard/Details_Vanguard.toc @@ -1,4 +1,4 @@ -## Interface: 80000 +## Interface: 80100 ## Title: Details Vanguard (plugin) ## Notes: Plugin for Details ## SavedVariablesPerCharacter: _detalhes_databaseVanguard