diff --git a/Definitions.lua b/Definitions.lua index 71bc63ac..2dfa1f12 100644 --- a/Definitions.lua +++ b/Definitions.lua @@ -1,6 +1,12 @@ ----@alias spellschool number +---@alias plugintype +---| "SOLO" +---| "RAID" +---| "TOOLBAR" +---| "STATUSBAR" + +---@alias containertype number this container type is the number used to identify the actorcontainer type when using combat:GetContainer(containertype), can be 1, 2, 3, or 4. ---@class details ---@field SpellTableMixin spelltablemixin @@ -46,12 +52,12 @@ ---@field GetBossInfo fun(combat: combat) : table a table containing many informations about the boss fight ---@field SetEndTime fun(combat: combat, time: number) ---@field CopyDeathsFrom fun(combat1: combat, combat2: combat, bMythicPlus: boolean) copy the deaths from combat2 to combat1, use true on bMythicPlus if the combat is from a mythic plus run ----@field GetContainer fun(combat: combat, containerType: number) : actorcontainer get an actor container, containerType can be 1 for damage, 2 heal, 3 energy, 4 utility +---@field GetContainer fun(combat: combat, containerType: containertype) : actorcontainer get an actorcontainer, containerType can be 1 for damage, 2 heal, 3 resources, 4 utility ---@field GetSpellCastAmount fun(combat: combat, actorName: string, spellName: string) : number get the amount of times a spell was casted ---@field RemoveActorFromSpellCastTable fun(combat: combat, actorName: string) ---@field GetSpellCastTable fun(combat: combat, actorName: string|nil) : table ---@field GetSpellUptime fun(combat: combat, actorName: string, spellId: number, auraType: string|nil) : number get the uptime of a buff or debuff ----@field GetActor fun(combat: combat, attribute: number, playerName: string) : actor +---@field GetActor fun(combat: combat, containerType: number, playerName: string) : actor ---@field CreateAlternatePowerTable fun(combat: combat, actorName: string) : alternatepowertable ---@field GetCombatNumber fun(combat: combat) : number get a unique number representing the combatId, each combat has a unique number ---@field SetDate fun(combat: combat, startDate: string, endDate: string) set the start and end date of the combat, format: "H:M:S" @@ -61,6 +67,7 @@ ---@field IsTrash fun(combat: combat) : boolean is true if the combat is a trash combat ---@class actorcontainer : table contains two tables _ActorTable and _NameIndexTable, the _ActorTable contains the actors, the _NameIndexTable contains the index of the actors in the _ActorTable, making quick to reorder them without causing overhead +---@field need_refresh boolean when true the container is dirty and needs to be refreshed ---@field _ActorTable table array of actors ---@field _NameIndexTable table [actorName] = actorIndex in the _ActorTable, actorcontainer:Remap() refreshes the _NameIndexTable ---@field GetActor fun(container: actorcontainer, actorName: string) get an actor by its name @@ -85,7 +92,7 @@ ---@class friendlyfiretable : table ---@field total number total amount of friendly fire caused by the actor ----@field spells table spellId = total +---@field spells table spellId = total ---@class spelltable : table ---@field uptime number @@ -177,7 +184,7 @@ ---@class actordamage : actor ---@field friendlyfire_total number ----@field friendlyfire friendlyfiretable +---@field friendlyfire table ---@field damage_taken number amount of damage the actor took during the segment ---@field damage_from table store the name of the actors which damaged the actor, format: [actorName] = true ---@field totalabsorbed number amount of damage dealt by the actor by got absorbed by the target, this is a "ABSORB" type of miss but still counts as damage done @@ -235,6 +242,7 @@ ---@field freezed boolean ---@field sub_atributo_last table ---@field row_info table +---@field GetSize fun(instance: instance) : width, height ---@field GetInstanceGroup fun() : table ---@field GetCombat fun(instance: instance) ---@field ChangeIcon fun(instance: instance) @@ -269,6 +277,15 @@ ---@class tabframe : frame this is the tab frame object for the breakdown window +---@class breakdownwindow : frame +---@field shownPluginObject table +---@field BreakdownSideMenuFrame frame frame attached to the left or right side of the breakdown window +---@field BreakdownPluginSelectionFrame frame frame which has buttons to select a plugin to show in the breakdown window +---@field BreakdownTabsFrame frame where the tab buttons are located (parent frame) +---@field RegisteredPluginButtons button[] table which contains plugins buttons that are registered to the breakdown window +---@field RegisterPluginButton fun(button: button) register a plugin button to the breakdown window + + ---@class breakdownscrolldata : table ---@field totalValue number total done by the actor ---@field combatTime number @@ -314,6 +331,8 @@ ---@field Icon texture ---@field InLineTexts fontstring[] ---@field statusBar breakdownspellbarstatusbar +---@field bIsFromLeftScroll boolean +---@field bIsFromRightScroll boolean ---@class breakdowntargetbar : button, df_headerfunctions ---@field index number @@ -437,12 +456,14 @@ ---@field subAttribute number ---@field TargetScrollFrame breakdowntargetscrollframe ---@field PhaseScrollFrame breakdownphasescrollframe ----@field GenericScrollFrame breakdowngenericscrollframe +---@field GenericScrollFrameLeft breakdowngenericscrollframe +---@field GenericScrollFrameRight breakdowngenericscrollframe ---@field SpellContainerFrame df_framecontainer ---@field BlocksContainerFrame df_framecontainer ---@field TargetsContainerFrame df_framecontainer ---@field PhaseContainerFrame df_framecontainer ----@field GenericContainerFrame df_framecontainer +---@field GenericContainerFrameLeft df_framecontainer +---@field GenericContainerFrameRight df_framecontainer ---@field GetActor fun() : actor ---@field GetCombat fun() : combat ---@field GetInstance fun() : instance @@ -465,6 +486,7 @@ ---@field CreateSpellBlockContainer fun(tabFrame: tabframe) : breakdownspellblockframe ---@field UpdateShownSpellBlock fun() ---@field CreateTargetContainer fun(tabFrame: tabframe) : breakdowntargetscrollframe +---@field CreateGenericContainers fun(tabFrame: tabframe) : breakdowngenericscrollframe, breakdowngenericscrollframe ---@field CreateSpellScrollContainer fun(tabFrame: tabframe) : breakdownspellscrollframe ---@field CreateTargetBar fun(self: breakdowntargetscrollframe, index: number) : breakdowntargetbar ---@field CreateSpellBar fun(self: breakdownspellscrollframe, index: number) : breakdownspellbar diff --git a/Details.toc b/Details.toc index 66bc3abe..a5584ad8 100644 --- a/Details.toc +++ b/Details.toc @@ -93,6 +93,7 @@ frames\window_breakdown\window_playerbreakdown_spells_options.lua frames\window_breakdown\breakdown_spells_genericframes.lua frames\window_breakdown\breakdown_spells_spellframes.lua frames\window_breakdown\breakdown_spells_targetframes.lua +frames\window_breakdown\breakdown_spells_phaseframes.lua frames\window_report.lua frames\window_main.lua frames\window_custom.lua diff --git a/Details_Classic.toc b/Details_Classic.toc index 318e4cee..014c5e6f 100644 --- a/Details_Classic.toc +++ b/Details_Classic.toc @@ -87,6 +87,7 @@ frames\window_breakdown\window_playerbreakdown_spells_options.lua frames\window_breakdown\breakdown_spells_genericframes.lua frames\window_breakdown\breakdown_spells_spellframes.lua frames\window_breakdown\breakdown_spells_targetframes.lua +frames\window_breakdown\breakdown_spells_phaseframes.lua frames\window_report.lua frames\window_main.lua frames\window_custom.lua diff --git a/Details_Wrath.toc b/Details_Wrath.toc index 15fb61db..cfbd98a9 100644 --- a/Details_Wrath.toc +++ b/Details_Wrath.toc @@ -87,6 +87,7 @@ frames\window_breakdown\window_playerbreakdown_spells_options.lua frames\window_breakdown\breakdown_spells_genericframes.lua frames\window_breakdown\breakdown_spells_spellframes.lua frames\window_breakdown\breakdown_spells_targetframes.lua +frames\window_breakdown\breakdown_spells_phaseframes.lua frames\window_report.lua frames\window_main.lua frames\window_custom.lua diff --git a/Libs/LibLuaServer/LuaServerDefinitions.lua b/Libs/LibLuaServer/LuaServerDefinitions.lua index 045880b4..bb389bd2 100644 --- a/Libs/LibLuaServer/LuaServerDefinitions.lua +++ b/Libs/LibLuaServer/LuaServerDefinitions.lua @@ -88,6 +88,7 @@ ---@alias spellid number each spell in the game has a unique spell id, this id can be used to identify a spell. ---@alias actorname string name of a unit ---@alias spellname string name of a spell +---@alias spellschool number each spell in the game has a school, such as fire, frost, shadow and many others. This value can be used to identify the school of a spell. ---@alias actorid string unique id of a unit (GUID) ---@alias serial string unique id of a unit (GUID) ---@alias color table, string @table(r: red|number, g: green|number, b: blue|number, a: alpha|number) @string(color name) @hex (000000-ffffff) value representing a color, the value must be a table with the following fields: r, g, b, a. r, g, b are numbers between 0 and 1, a is a number between 0 and 1. To retrieve a color from a string or table use: local red, green, blue, alpha = DetailsFramework:ParseColors(color) @@ -99,6 +100,7 @@ ---@alias textureid number each texture from the game client has an id. ---@alias texturepath string access textures from addons. + ---@class _G ---@field RegisterAttributeDriver fun(statedriver: frame, attribute: string, conditional: string) ---@field RegisterStateDriver fun(statedriver: frame, attribute: string, conditional: string) diff --git a/Libs/LibOpenRaid/ThingsToMantain_Dragonflight.lua b/Libs/LibOpenRaid/ThingsToMantain_Dragonflight.lua index f30d52eb..b42b9379 100644 --- a/Libs/LibOpenRaid/ThingsToMantain_Dragonflight.lua +++ b/Libs/LibOpenRaid/ThingsToMantain_Dragonflight.lua @@ -518,6 +518,7 @@ do [115450] = {cooldown = 8, duration = 0, specs = {270}, talent = false, charges = 1, class = "MONK", type = 7}, --Detox (healer) [218164] = {cooldown = 8, duration = 0, specs = {269,268}, talent = false, charges = 1, class = "MONK", type = 7}, --Detox (DPS/Tank) [325153] = {cooldown = 60, duration = 3, specs = {268}, talent = false, charges = 1, class = "MONK", type = 2}, --Exploding Keg + [115078] = {cooldown = 45, duration = 60, specs = {268, 269, 270}, talent = false, charges = 1, class = "MONK", type = 8}, --Paralysis --hunter @@ -747,6 +748,7 @@ do [357170] = {cooldown = 60, duration = 8, specs = {1468}, talent = false, charges = 1, class = "EVOKER", type = 3}, --Time Dilation [374968] = {cooldown = 120, duration = 10, specs = {1467, 1468}, talent = false, charges = 1, class = "EVOKER", type = 5}, --Time Spiral [374227] = {cooldown = 120, duration = 8, specs = {1467, 1468}, talent = false, charges = 1, class = "EVOKER", type = 4}, --Zephyr + [360806] = {cooldown = 15, duration = 20, specs = {1467, 1468}, talent = false, charges = 1, class = "EVOKER", type = 8}, --Sleep Walk } --this table store all cooldowns the player currently have available diff --git a/boot.lua b/boot.lua index 8e612782..22f3b489 100644 --- a/boot.lua +++ b/boot.lua @@ -867,38 +867,39 @@ do local CreateFrame = CreateFrame --api locals local UIParent = UIParent --api locals - --Info Window - _detalhes.playerDetailWindow = CreateFrame("Frame", "DetailsBreakdownWindow", UIParent, "BackdropTemplate") - _detalhes.PlayerDetailsWindow = _detalhes.playerDetailWindow - Details.BreakdownWindow = _detalhes.playerDetailWindow + --create the breakdown window frame + ---@type breakdownwindow + Details.BreakdownWindowFrame = CreateFrame("Frame", "DetailsBreakdownWindow", UIParent, "BackdropTemplate") + Details.PlayerDetailsWindow = Details.BreakdownWindowFrame + Details.BreakdownWindow = Details.BreakdownWindowFrame --Event Frame - _detalhes.listener = CreateFrame("Frame", nil, UIParent) - _detalhes.listener:RegisterEvent("ADDON_LOADED") - _detalhes.listener:SetFrameStrata("LOW") - _detalhes.listener:SetFrameLevel(9) - _detalhes.listener.FrameTime = 0 + Details.listener = CreateFrame("Frame", nil, UIParent) + Details.listener:RegisterEvent("ADDON_LOADED") + Details.listener:SetFrameStrata("LOW") + Details.listener:SetFrameLevel(9) + Details.listener.FrameTime = 0 - _detalhes.overlay_frame = CreateFrame("Frame", nil, UIParent) - _detalhes.overlay_frame:SetFrameStrata("TOOLTIP") + Details.overlay_frame = CreateFrame("Frame", nil, UIParent) + Details.overlay_frame:SetFrameStrata("TOOLTIP") --Pet Owner Finder - CreateFrame("GameTooltip", "DetailsPetOwnerFinder", nil, "GameTooltipTemplate") + CreateFrame("GameTooltip", "DetailsPetOwnerFinder", nil, "GameTooltipTemplate") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --plugin defaults --backdrop - _detalhes.PluginDefaults = {} + Details.PluginDefaults = {} - _detalhes.PluginDefaults.Backdrop = {bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16, + Details.PluginDefaults.Backdrop = {bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16, edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, insets = {left = 1, right = 1, top = 1, bottom = 1}} - _detalhes.PluginDefaults.BackdropColor = {0, 0, 0, .6} - _detalhes.PluginDefaults.BackdropBorderColor = {0, 0, 0, 1} + Details.PluginDefaults.BackdropColor = {0, 0, 0, .6} + Details.PluginDefaults.BackdropBorderColor = {0, 0, 0, 1} - function _detalhes.GetPluginDefaultBackdrop() - return _detalhes.PluginDefaults.Backdrop, _detalhes.PluginDefaults.BackdropColor, _detalhes.PluginDefaults.BackdropBorderColor + function Details.GetPluginDefaultBackdrop() + return Details.PluginDefaults.Backdrop, Details.PluginDefaults.BackdropColor, Details.PluginDefaults.BackdropBorderColor end diff --git a/classes/class_damage.lua b/classes/class_damage.lua index 09b05ee8..8cbddd46 100644 --- a/classes/class_damage.lua +++ b/classes/class_damage.lua @@ -78,7 +78,7 @@ local headerColor = {1, 0.9, 0.0, 1} - local info = Details.playerDetailWindow + local breakdownWindowFrame = Details.BreakdownWindowFrame local keyName local OBJECT_TYPE_PLAYER = 0x00000400 @@ -4011,42 +4011,70 @@ end ---------DETALHES BIFURCA��O ~detalhes ~detailswindow ~bi function damageClass:MontaInfo() - if (info.sub_atributo == 1 or info.sub_atributo == 2 or info.sub_atributo == 6) then --damage done & dps - return self:MontaInfoDamageDone() - elseif (info.sub_atributo == 3) then --damage taken - return self:MontaInfoDamageTaken() - elseif (info.sub_atributo == 4) then --friendly fire - return self:MontaInfoFriendlyFire() + if (breakdownWindowFrame.sub_atributo == 1 or breakdownWindowFrame.sub_atributo == 2 or breakdownWindowFrame.sub_atributo == 6) then --damage done & dps + return self:MontaInfoDamageDone() --has new code for the new destails window | left scroll and 6 blocks implemented + elseif (breakdownWindowFrame.sub_atributo == 3) then --damage taken + return self:MontaInfoDamageTaken() --has new code for the new destails window | left and right scrolls implemented + elseif (breakdownWindowFrame.sub_atributo == 4) then --friendly fire + return self:MontaInfoFriendlyFire() --has new code for the new destails window | left scroll implemeneted (need to implemente the right scroll yet) end end ---------DETALHES bloco da direita BIFURCA��O -function damageClass:MontaDetalhes (spellid, barra, instancia) - if (info.sub_atributo == 1 or info.sub_atributo == 2) then - return self:MontaDetalhesDamageDone (spellid, barra, instancia) +function damageClass:MontaDetalhes (spellid, barra, instancia) --these functions were used to fill the 5 blocks from the old breakdown window + if (breakdownWindowFrame.sub_atributo == 1 or breakdownWindowFrame.sub_atributo == 2) then + return self:MontaDetalhesDamageDone (spellid, barra, instancia) --deprecated - elseif (info.sub_atributo == 3) then + elseif (breakdownWindowFrame.sub_atributo == 3) then return self:MontaDetalhesDamageTaken (spellid, barra, instancia) - elseif (info.sub_atributo == 4) then + elseif (breakdownWindowFrame.sub_atributo == 4) then return self:MontaDetalhesFriendlyFire (spellid, barra, instancia) - elseif (info.sub_atributo == 6) then + elseif (breakdownWindowFrame.sub_atributo == 6) then if (bitBand(self.flag_original, 0x00000400) ~= 0) then --� um jogador - return self:MontaDetalhesDamageDone (spellid, barra, instancia) + return self:MontaDetalhesDamageDone (spellid, barra, instancia) --deprecated end return self:MontaDetalhesEnemy (spellid, barra, instancia) end end +local friendlyFireSpellSourcesHeadersAllowed = {icon = true, name = true, rank = true, amount = true, persecond = true, percent = true} +---when hovering over the player name in the breakdown window, this function will be called to build a the list of spells used to inflict damage on that player +---@param friendlyFireAggressorActor actordamage +---@param targetName string +function damageClass.BuildFriendlySpellListFromAgressor(friendlyFireAggressorActor, targetName) + ---@type combat + local combatObject = Details:GetCombatFromBreakdownWindow() + + ---@type friendlyfiretable + local friendlyFireTable = friendlyFireAggressorActor.friendlyfire[targetName] + + local totalDamage = friendlyFireTable.total + local spellsUsed = friendlyFireTable.spells + + --create the table which will be returned with the data + ---@type {topValue: number, totalValue: number, headersAllowed: table, combatTime: number} + local resultTable = {topValue = 0, totalValue = totalDamage, headersAllowed = friendlyFireSpellSourcesHeadersAllowed, combatTime = combatObject:GetCombatTime()} + + --iterate among the spells used by the aggressorActor + for spellId, amountDamage in pairs(spellsUsed) do + --add the spell to the list + local spellName = GetSpellInfo(spellId) + resultTable[#resultTable+1] = {spellId = spellId, total = amountDamage, petName = "", spellScholl = Details.spell_school_cache[spellName] or 1} + end + + return resultTable +end ------ Friendly Fire local friendlyFireHeadersAllowed = {icon = true, name = true, rank = true, amount = true, persecond = true, percent = true} +---build the friendly fire list, the list contains players who were damaged by this actor. function damageClass:MontaInfoFriendlyFire() --~friendlyfire ~friendly ~ff ---@type actordamage local actorObject = self ---@type instance - local instance = info.instancia + local instance = breakdownWindowFrame.instancia ---@type combat local combatObject = instance:GetCombat() ---@type string @@ -4064,13 +4092,14 @@ function damageClass:MontaInfoFriendlyFire() --~friendlyfire ~friendly ~ff for targetName, friendlyFireTable in pairs(damagedPlayers) do local amountOfFriendlyFire = friendlyFireTable.total if (amountOfFriendlyFire > 0) then + ---@type actordamage this is an actor who was damaged by the friendly fire of the actorObject local targetActorObject = damageContainer:GetActor(targetName) if (targetActorObject) then ---@type texturetable local iconTable = Details:GetActorIcon(targetActorObject) - ---@type {name: string, amount: number, icon: texturetable} - local ffTable = {name = targetName, total = amountOfFriendlyFire, icon = iconTable} + ---@type {name: string, amount: number, icon: texturetable, class: string} + local ffTable = {name = targetName, total = amountOfFriendlyFire, icon = iconTable, class = targetActorObject:Class()} resultTable[#resultTable+1] = ffTable end @@ -4084,151 +4113,204 @@ function damageClass:MontaInfoFriendlyFire() --~friendlyfire ~friendly ~ff Details222.BreakdownWindow.SendGenericData(resultTable, actorObject, combatObject, instance) if true then return end + do + local instancia = breakdownWindowFrame.instancia + local combat = instancia:GetShowingCombat() + local barras = breakdownWindowFrame.barras1 + local barras2 = breakdownWindowFrame.barras2 + local barras3 = breakdownWindowFrame.barras3 - local instancia = info.instancia - local combat = instancia:GetShowingCombat() - local barras = info.barras1 - local barras2 = info.barras2 - local barras3 = info.barras3 + local FriendlyFireTotal = self.friendlyfire_total - local FriendlyFireTotal = self.friendlyfire_total + local DamagedPlayers = {} + local Skills = {} - local DamagedPlayers = {} - local Skills = {} + for target_name, ff_table in pairs(self.friendlyfire) do - for target_name, ff_table in pairs(self.friendlyfire) do + local actor = combat (1, target_name) + if (actor) then + tinsert(DamagedPlayers, {target_name, ff_table.total, ff_table.total / FriendlyFireTotal * 100, actor.classe}) - local actor = combat (1, target_name) - if (actor) then - tinsert(DamagedPlayers, {target_name, ff_table.total, ff_table.total / FriendlyFireTotal * 100, actor.classe}) - - for spellid, amount in pairs(ff_table.spells) do - Skills [spellid] = (Skills [spellid] or 0) + amount + for spellid, amount in pairs(ff_table.spells) do + Skills [spellid] = (Skills [spellid] or 0) + amount + end end end - end - _table_sort(DamagedPlayers, Details.Sort2) + _table_sort(DamagedPlayers, Details.Sort2) - local amt = #DamagedPlayers - gump:JI_AtualizaContainerBarras (amt) + local amt = #DamagedPlayers + gump:JI_AtualizaContainerBarras (amt) - local FirstPlaceDamage = DamagedPlayers [1] and DamagedPlayers [1][2] or 0 + local FirstPlaceDamage = DamagedPlayers [1] and DamagedPlayers [1][2] or 0 - for index, tabela in ipairs(DamagedPlayers) do - local barra = barras [index] + for index, tabela in ipairs(DamagedPlayers) do + local barra = barras [index] - if (not barra) then - barra = gump:CriaNovaBarraInfo1 (instancia, index) - barra.textura:SetStatusBarColor(1, 1, 1, 1) - barra.on_focus = false - end + if (not barra) then + barra = gump:CriaNovaBarraInfo1 (instancia, index) + barra.textura:SetStatusBarColor(1, 1, 1, 1) + barra.on_focus = false + end - if (not info.mostrando_mouse_over) then - if (tabela[1] == self.detalhes) then --tabela [1] = NOME = NOME que esta na caixa da direita - if (not barra.on_focus) then --se a barra n�o tiver no foco - barra.textura:SetStatusBarColor(129/255, 125/255, 69/255, 1) - barra.on_focus = true - if (not info.mostrando) then - info.mostrando = barra + if (not breakdownWindowFrame.mostrando_mouse_over) then + if (tabela[1] == self.detalhes) then --tabela [1] = NOME = NOME que esta na caixa da direita + if (not barra.on_focus) then --se a barra n�o tiver no foco + barra.textura:SetStatusBarColor(129/255, 125/255, 69/255, 1) + barra.on_focus = true + if (not breakdownWindowFrame.mostrando) then + breakdownWindowFrame.mostrando = barra + end + end + else + if (barra.on_focus) then + barra.textura:SetStatusBarColor(1, 1, 1, 1) --volta a cor antiga + barra:SetAlpha(.9) --volta a alfa antiga + barra.on_focus = false end end + end + + if (index == 1) then + barra.textura:SetValue(100) else - if (barra.on_focus) then - barra.textura:SetStatusBarColor(1, 1, 1, 1) --volta a cor antiga - barra:SetAlpha(.9) --volta a alfa antiga - barra.on_focus = false - end + barra.textura:SetValue(tabela[2]/FirstPlaceDamage*100) + end + + barra.lineText1:SetText(index .. instancia.divisores.colocacao .. Details:GetOnlyName(tabela[1])) --seta o texto da esqueda + barra.lineText4:SetText(Details:comma_value (tabela[2]) .. " (" .. format("%.1f", tabela[3]) .."%)") --seta o texto da direita + + local classe = tabela[4] + if (not classe) then + classe = "MONSTER" + end + + barra.icone:SetTexture(breakdownWindowFrame.instancia.row_info.icon_file) + + if (Details.class_coords [classe]) then + barra.icone:SetTexCoord(unpack(Details.class_coords [classe])) + else + barra.icone:SetTexture("") + end + + local color = Details.class_colors [classe] + if (color) then + barra.textura:SetStatusBarColor(unpack(color)) + else + barra.textura:SetStatusBarColor(1, 1, 1) + end + + barra.minha_tabela = self + barra.show = tabela[1] + barra:Show() + + if (self.detalhes and self.detalhes == barra.show) then + self:MontaDetalhes (self.detalhes, barra, instancia) end end - if (index == 1) then - barra.textura:SetValue(100) - else - barra.textura:SetValue(tabela[2]/FirstPlaceDamage*100) + local SkillTable = {} + for spellid, amt in pairs(Skills) do + local nome, _, icone = _GetSpellInfo(spellid) + SkillTable [#SkillTable+1] = {nome, amt, amt/FriendlyFireTotal*100, icone} end - barra.lineText1:SetText(index .. instancia.divisores.colocacao .. Details:GetOnlyName(tabela[1])) --seta o texto da esqueda - barra.lineText4:SetText(Details:comma_value (tabela[2]) .. " (" .. format("%.1f", tabela[3]) .."%)") --seta o texto da direita + _table_sort(SkillTable, Details.Sort2) - local classe = tabela[4] - if (not classe) then - classe = "MONSTER" + amt = #SkillTable + if (amt < 1) then + return end - barra.icone:SetTexture(info.instancia.row_info.icon_file) + gump:JI_AtualizaContainerAlvos (amt) - if (Details.class_coords [classe]) then - barra.icone:SetTexCoord(unpack(Details.class_coords [classe])) - else - barra.icone:SetTexture("") + FirstPlaceDamage = SkillTable [1] and SkillTable [1][2] or 0 + + for index, tabela in ipairs(SkillTable) do + local barra = barras2 [index] + + if (not barra) then + barra = gump:CriaNovaBarraInfo2 (instancia, index) + barra.textura:SetStatusBarColor(1, 1, 1, 1) + end + + if (index == 1) then + barra.textura:SetValue(100) + else + barra.textura:SetValue(tabela[2]/FirstPlaceDamage*100) + end + + barra.lineText1:SetText(index..instancia.divisores.colocacao..tabela[1]) --seta o texto da esqueda + barra.lineText4:SetText(Details:comma_value (tabela[2]) .." (" ..format("%.1f", tabela[3]) .. ")") --seta o texto da direita + barra.icone:SetTexture(tabela[4]) + + barra.minha_tabela = nil --desativa o tooltip + + barra:Show() end + end +end - local color = Details.class_colors [classe] - if (color) then - barra.textura:SetStatusBarColor(unpack(color)) - else - barra.textura:SetStatusBarColor(1, 1, 1) - end +local damageTakenSpellSourcesHeadersAllowed = {icon = true, name = true, rank = true, amount = true, persecond = true, percent = true} +function damageClass.BuildDamageTakenSpellListFromAgressor(targetActor, aggressorActor) + --target actor name + local targetActorName = targetActor:Name() - barra.minha_tabela = self - barra.show = tabela[1] - barra:Show() + ---@type combat + local combatObject = Details:GetCombatFromBreakdownWindow() - if (self.detalhes and self.detalhes == barra.show) then - self:MontaDetalhes (self.detalhes, barra, instancia) + --get the list of spells from the aggressorActor and check each one to see if it was casted on the targetActor + ---@type spellcontainer + local spellContainer = aggressorActor:GetSpellContainer("spell") + + --create the table which will be returned with the data + ---@type {topValue: number, totalValue: number, headersAllowed: table, combatTime: number} + local resultTable = {topValue = 0, totalValue = 0, headersAllowed = damageTakenSpellSourcesHeadersAllowed, combatTime = combatObject:GetCombatTime()} + + for spellId, spellTable in spellContainer:ListSpells() do + ---@cast spellTable spelltable + for targetName, amount in pairs(spellTable.targets) do + if (targetName == targetActorName) then + --add the spell to the list + resultTable[#resultTable+1] = {spellId = spellId, total = amount, petName = "", spellScholl = spellTable.spellschool} + resultTable.totalValue = resultTable.totalValue + amount + end end end - local SkillTable = {} - for spellid, amt in pairs(Skills) do - local nome, _, icone = _GetSpellInfo(spellid) - SkillTable [#SkillTable+1] = {nome, amt, amt/FriendlyFireTotal*100, icone} - end + --iterate among the pets of the aggressorActor and get the spells casted by them + ---@type table + local petTable = aggressorActor.pets - _table_sort(SkillTable, Details.Sort2) + for i = 1, #petTable do + local petName = petTable[i] + local petActorObject = combatObject:GetActor(DETAILS_ATTRIBUTE_DAMAGE, petName) + if (petActorObject) then + ---@type spellcontainer + local petSpellContainer = petActorObject:GetSpellContainer("spell") - amt = #SkillTable - if (amt < 1) then - return - end - - gump:JI_AtualizaContainerAlvos (amt) - - FirstPlaceDamage = SkillTable [1] and SkillTable [1][2] or 0 - - for index, tabela in ipairs(SkillTable) do - local barra = barras2 [index] - - if (not barra) then - barra = gump:CriaNovaBarraInfo2 (instancia, index) - barra.textura:SetStatusBarColor(1, 1, 1, 1) + for spellId, spellTable in petSpellContainer:ListSpells() do + for targetName, amount in pairs(spellTable.targets) do + if (targetName == targetActorName) then + --add the spell to the list + resultTable[#resultTable+1] = {spellId = spellId, total = amount, petName = petName, spellScholl = spellTable.spellschool} + resultTable.totalValue = resultTable.totalValue + amount + end + end + end end - - if (index == 1) then - barra.textura:SetValue(100) - else - barra.textura:SetValue(tabela[2]/FirstPlaceDamage*100) - end - - barra.lineText1:SetText(index..instancia.divisores.colocacao..tabela[1]) --seta o texto da esqueda - barra.lineText4:SetText(Details:comma_value (tabela[2]) .." (" ..format("%.1f", tabela[3]) .. ")") --seta o texto da direita - barra.icone:SetTexture(tabela[4]) - - barra.minha_tabela = nil --desativa o tooltip - - barra:Show() end + return resultTable end ------ Damage Taken local damageTakenHeadersAllowed = {icon = true, name = true, rank = true, amount = true, persecond = true, percent = true} function damageClass:MontaInfoDamageTaken() - ---@type actor + ---@type actordamage local actorObject = self ---@type instance - local instance = info.instancia + local instance = breakdownWindowFrame.instancia ---@type combat local combatObject = instance:GetCombat() ---@type string @@ -4245,18 +4327,18 @@ function damageClass:MontaInfoDamageTaken() ---@type string for aggressorName in pairs(damageTakenFrom) do - local sourceActorObject = damageContainer:GetActor(aggressorName) - if (sourceActorObject) then + local aggressorActor = damageContainer:GetActor(aggressorName) + if (aggressorActor) then ---@type table - local targets = sourceActorObject:GetTargets() + local targets = aggressorActor:GetTargets() ---@type number|nil local amountOfDamage = targets[actorName] if (amountOfDamage) then ---@type texturetable - local iconTable = Details:GetActorIcon(sourceActorObject) + local iconTable = Details:GetActorIcon(aggressorActor) ---@type {name: string, amount: number, icon: texturetable} - local damageTakenTable = {name = aggressorName, total = amountOfDamage, icon = iconTable} + local damageTakenTable = {name = aggressorName, total = amountOfDamage, icon = iconTable, class = aggressorActor:Class()} resultTable[#resultTable+1] = damageTakenTable end @@ -4268,54 +4350,6 @@ function damageClass:MontaInfoDamageTaken() resultTable.headersAllowed = damageTakenHeadersAllowed Details222.BreakdownWindow.SendGenericData(resultTable, actorObject, combatObject, instance) - - if true then return end - - local barras = info.barras1 - local meus_agressores = {} - - local este_agressor - for nome, _ in pairs(damageTakenFrom) do - este_agressor = damageContainer._ActorTable[damageContainer._NameIndexTable[nome]] - if (este_agressor) then - local alvos = este_agressor.targets - local este_alvo = alvos [self.nome] - if (este_alvo) then - meus_agressores [#meus_agressores+1] = {nome, este_alvo, este_alvo/damageTakenTotal*100, este_agressor.classe} - end - end - end - - local amt = #meus_agressores - - if (amt < 1) then --caso houve apenas friendly fire - return true - end - - --_table_sort(meus_agressores, function(a, b) return a[2] > b[2] end) - _table_sort(meus_agressores, Details.Sort2) - - gump:JI_AtualizaContainerBarras (amt) - - local max_ = meus_agressores [1] and meus_agressores [1][2] or 0 - - local barra - for index, tabela in ipairs(meus_agressores) do - barra = barras [index] - if (not barra) then - barra = gump:CriaNovaBarraInfo1 (instance, index) - end - - self:FocusLock(barra, tabela[1]) - - local texCoords = Details.class_coords [tabela[4]] - if (not texCoords) then - texCoords = Details.class_coords ["UNKNOW"] - end - - local formated_value = SelectedToKFunction(_, _math_floor(tabela[2])) - self:UpdadeInfoBar(barra, index, tabela[1], tabela[1], tabela[2], formated_value, max_, tabela[3], "Interface\\AddOns\\Details\\images\\classes_small_alpha", true, texCoords, nil, tabela[4]) - end end --[[exported]] function Details:UpdadeInfoBar(row, index, spellId, name, value, formattedValue, max, percent, icon, detalhes, texCoords, spellSchool, class) @@ -4396,20 +4430,20 @@ end end end - if (detalhes and self.detalhes and self.detalhes == spellId and info.showing == index) then - self:MontaDetalhes(row.show, row, info.instancia) + if (detalhes and self.detalhes and self.detalhes == spellId and breakdownWindowFrame.showing == index) then + self:MontaDetalhes(row.show, row, breakdownWindowFrame.instancia) end end --lock into a line after clicking on it --[[exported]] function Details:FocusLock(row, spellId) --will be deprecated - if (not info.mostrando_mouse_over) then + if (not breakdownWindowFrame.mostrando_mouse_over) then if (spellId == self.detalhes) then --tabela [1] = spellid = spellid que esta na caixa da direita if (not row.on_focus) then --se a barra n�o tiver no foco row.textura:SetStatusBarColor(129/255, 125/255, 69/255, 1) row.on_focus = true - if (not info.mostrando) then - info.mostrando = row + if (not breakdownWindowFrame.mostrando) then + breakdownWindowFrame.mostrando = row end end else @@ -4504,7 +4538,7 @@ function damageClass:MontaInfoDamageDone() --I guess this fills the list of spel ---@type actor local actorObject = self ---@type instance - local instance = info.instancia + local instance = breakdownWindowFrame.instancia ---@type combat local combatObject = instance:GetCombat() ---@type number @@ -4525,15 +4559,15 @@ function damageClass:MontaInfoDamageDone() --I guess this fills the list of spel --discover which are the player position in the guild rank local playerTable, onEncounter, rankPosition = Details.storage:GetPlayerGuildRank (diff, combatObject:GetBossInfo().id, "damage", playerName, true) local text1 = playerName .. " Guild Rank on " .. (combatObject:GetBossInfo().name or "") .. ": |cFFFFFF00" .. (rankPosition or "x") .. "|r Best Dps: |cFFFFFF00" .. Details:ToK2((bestRank[1] or 0) / encounterTable.elapsed) .. "|r (" .. encounterTable.date:gsub(".*%s", "") .. ")" - info:SetStatusbarText (text1, 10, "gray") + breakdownWindowFrame:SetStatusbarText (text1, 10, "gray") else - info:SetStatusbarText() + breakdownWindowFrame:SetStatusbarText() end else - info:SetStatusbarText() + breakdownWindowFrame:SetStatusbarText() end else - info:SetStatusbarText() + breakdownWindowFrame:SetStatusbarText() end end @@ -4554,7 +4588,7 @@ function damageClass:MontaInfoDamageDone() --I guess this fills the list of spel if (Details.time_type == 1 or not actorObject.grupo) then actorCombatTime = actorObject:Tempo() elseif (Details.time_type == 2) then - actorCombatTime = info.instancia.showing:GetCombatTime() + actorCombatTime = breakdownWindowFrame.instancia.showing:GetCombatTime() end --actor spells @@ -4766,7 +4800,7 @@ function damageClass:MontaInfoDamageDone() --I guess this fills the list of spel local name = tabela[4] - if (info.sub_atributo == 2) then + if (breakdownWindowFrame.sub_atributo == 2) then local formated_value = SelectedToKFunction(_, _math_floor(tabela[2]/actorCombatTime)) self:UpdadeInfoBar(barra, index, tabela[1], name, tabela[2], formated_value, max_, tabela[3], tabela[5], true, nil, tabela [7]) else @@ -4783,7 +4817,7 @@ function damageClass:MontaInfoDamageDone() --I guess this fills the list of spel local damageTakenFrom = self.damage_from local combatObject = instance:GetShowingCombat() local damageContainer = combatObject:GetContainer(DETAILS_ATTRIBUTE_DAMAGE) - local barras = info.barras2 + local barras = breakdownWindowFrame.barras2 local enemyTable = {} local targetName = self:Name() @@ -4889,7 +4923,7 @@ function damageClass:MontaInfoDamageDone() --I guess this fills the list of spel local barra for index, targetTable in ipairs(allActorTargets) do - barra = info.barras2[index] + barra = breakdownWindowFrame.barras2[index] if (not barra) then barra = gump:CriaNovaBarraInfo2(instance, index) @@ -4924,7 +4958,7 @@ function damageClass:MontaInfoDamageDone() --I guess this fills the list of spel barra.lineText1:SetText(index .. ". " .. Details:GetOnlyName(targetName)) - if (info.sub_atributo == 2) then + if (breakdownWindowFrame.sub_atributo == 2) then barra.lineText4:SetText(Details:comma_value ( _math_floor(targetTable[2]/actorCombatTime)) .. " (" .. format("%.1f", targetTable[3]) .. "%)") else barra.lineText4:SetText(SelectedToKFunction(_, targetTable[2]) .." (" .. format("%.1f", targetTable[3]) .. "%)") @@ -4952,10 +4986,10 @@ end ------ Detalhe Info Friendly Fire function damageClass:MontaDetalhesFriendlyFire (nome, barra) - local barras = info.barras3 - local instancia = info.instancia + local barras = breakdownWindowFrame.barras3 + local instancia = breakdownWindowFrame.instancia - local tabela_do_combate = info.instancia.showing + local tabela_do_combate = breakdownWindowFrame.instancia.showing local showing = tabela_do_combate [class_type] --o que esta sendo mostrado -> [1] - dano [2] - cura --pega o container com ._NameIndexTable ._ActorTable local friendlyfire = self.friendlyfire @@ -5017,9 +5051,9 @@ end -- detalhes info enemies function damageClass:MontaDetalhesEnemy (spellid, barra) - local container = info.instancia.showing[1] - local barras = info.barras3 - local instancia = info.instancia + local container = breakdownWindowFrame.instancia.showing[1] + local barras = breakdownWindowFrame.barras3 + local instancia = breakdownWindowFrame.instancia local other_actor = barra.other_actor if (other_actor) then @@ -5041,7 +5075,7 @@ function damageClass:MontaDetalhesEnemy (spellid, barra) for target_name, amount in pairs(targets) do local classe - local this_actor = info.instancia.showing (1, target_name) + local this_actor = breakdownWindowFrame.instancia.showing (1, target_name) if (this_actor) then classe = this_actor.classe or "UNKNOW" else @@ -5115,10 +5149,10 @@ end ------ Detalhe Info Damage Taken function damageClass:MontaDetalhesDamageTaken (nome, barra) - local barras = info.barras3 - local instancia = info.instancia + local barras = breakdownWindowFrame.barras3 + local instancia = breakdownWindowFrame.instancia - local tabela_do_combate = info.instancia.showing + local tabela_do_combate = breakdownWindowFrame.instancia.showing local showing = tabela_do_combate [class_type] --o que esta sendo mostrado -> [1] - dano [2] - cura --pega o container com ._NameIndexTable ._ActorTable local este_agressor = showing._ActorTable[showing._NameIndexTable[nome]] @@ -5129,7 +5163,7 @@ function damageClass:MontaDetalhesDamageTaken (nome, barra) local conteudo = este_agressor.spells._ActorTable --pairs[] com os IDs das magias - local actor = info.jogador.nome + local actor = breakdownWindowFrame.jogador.nome local total = este_agressor.targets [actor] or 0 @@ -5212,7 +5246,7 @@ end local MontaDetalhesBuffProcs = function(actor, row, instance) - instance = instance or info.instancia + instance = instance or breakdownWindowFrame.instancia local spec = actor.spec if (spec) then @@ -5524,7 +5558,7 @@ function damageClass:MontaDetalhesDamageDone (spellId, spellLine, instance) --th end end - Details.playerDetailWindow.spell_icone:SetTexture(icone) + Details.BreakdownWindowFrame.spell_icone:SetTexture(icone) local total = self.total @@ -5533,7 +5567,7 @@ function damageClass:MontaDetalhesDamageDone (spellId, spellLine, instance) --th meu_tempo = self:Tempo() elseif (Details.time_type == 2) then - meu_tempo = info.instancia.showing:GetCombatTime() + meu_tempo = breakdownWindowFrame.instancia.showing:GetCombatTime() end local total_hits = spellTable.counter @@ -5571,15 +5605,15 @@ function damageClass:MontaDetalhesDamageDone (spellId, spellLine, instance) --th local hits_string = "" .. total_hits local cast_string = Loc ["STRING_CAST"] .. ": " - local misc_actor = info.instancia.showing (4, self:name()) + local misc_actor = breakdownWindowFrame.instancia.showing (4, self:name()) if (misc_actor) then local uptime_spellid = spellTable.id local debuff_uptime = misc_actor.debuff_uptime_spells and misc_actor.debuff_uptime_spells._ActorTable [uptime_spellid] and misc_actor.debuff_uptime_spells._ActorTable [uptime_spellid].uptime if (debuff_uptime) then - hits_string = hits_string .. " |cFFDDDD44(" .. _math_floor(debuff_uptime / info.instancia.showing:GetCombatTime() * 100) .. "% uptime)|r" + hits_string = hits_string .. " |cFFDDDD44(" .. _math_floor(debuff_uptime / breakdownWindowFrame.instancia.showing:GetCombatTime() * 100) .. "% uptime)|r" end - local amountOfCasts = info.instancia.showing:GetSpellCastAmount(self:Name(), spellName) + local amountOfCasts = breakdownWindowFrame.instancia.showing:GetSpellCastAmount(self:Name(), spellName) if (amountOfCasts == 0) then amountOfCasts = "(|cFFFFFF00?|r)" end @@ -5736,7 +5770,7 @@ function damageClass:MontaDetalhesDamageDone (spellId, spellLine, instance) --th end --Details:BuildPlayerDetailsSpellChart() - --DetailsPlayerDetailSmallChart.ShowChart (Details.playerDetailWindow.grupos_detalhes [5].bg, info.instancia.showing, info.instancia.showing.cleu_events, self.nome, false, spellid, 1, 2, 3, 4, 5, 6, 7, 8, 15) + --DetailsPlayerDetailSmallChart.ShowChart (Details.BreakdownWindowFrame.grupos_detalhes [5].bg, info.instancia.showing, info.instancia.showing.cleu_events, self.nome, false, spellid, 1, 2, 3, 4, 5, 6, 7, 8, 15) --spell damage chart --events: 1 2 3 4 5 6 7 8 15 @@ -5905,7 +5939,7 @@ function Details:BuildPlayerDetailsSpellChart() if (not playerDetailSmallChart) then - playerDetailSmallChart = CreateFrame("frame", "DetailsPlayerDetailSmallChart", info,"BackdropTemplate") + playerDetailSmallChart = CreateFrame("frame", "DetailsPlayerDetailSmallChart", breakdownWindowFrame,"BackdropTemplate") DetailsFramework:ApplyStandardBackdrop(playerDetailSmallChart) playerDetailSmallChart.Lines = {} @@ -5915,7 +5949,7 @@ function Details:BuildPlayerDetailsSpellChart() tinsert(playerDetailSmallChart.Lines, texture) end - --Details.playerDetailWindow.grupos_detalhes [index] + --Details.BreakdownWindowFrame.grupos_detalhes [index] function playerDetailSmallChart.ShowChart (parent, combatObject, cleuData, playerName, targetName, spellId, ...) local tokenIdList = {} local eventList = {} @@ -5984,7 +6018,7 @@ function Details:BuildPlayerDetailsSpellChart() end function damageClass:MontaTooltipDamageTaken (thisLine, index) - local aggressor = info.instancia.showing [1]:PegarCombatente (_, thisLine.nome_inimigo) + local aggressor = breakdownWindowFrame.instancia.showing [1]:PegarCombatente (_, thisLine.nome_inimigo) local container = aggressor.spells._ActorTable local habilidades = {} @@ -6099,10 +6133,10 @@ function damageClass:MontaTooltipAlvos (thisLine, index, instancia) --~deprecate if (Details.time_type == 1 or not self.grupo) then meu_tempo = self:Tempo() elseif (Details.time_type == 2) then - meu_tempo = info.instancia.showing:GetCombatTime() + meu_tempo = breakdownWindowFrame.instancia.showing:GetCombatTime() end - local is_dps = info.instancia.sub_atributo == 2 + local is_dps = breakdownWindowFrame.instancia.sub_atributo == 2 if (is_dps) then Details:AddTooltipSpellHeaderText (Loc ["STRING_DAMAGE_DPS_IN"] .. ":", {1, 0.9, 0.0, 1}, 1, Details.tooltip_spell_icon.file, unpack(Details.tooltip_spell_icon.coords)) diff --git a/classes/class_heal.lua b/classes/class_heal.lua index d9d62eab..8893b5ba 100644 --- a/classes/class_heal.lua +++ b/classes/class_heal.lua @@ -63,7 +63,7 @@ local TooltipMaximizedMethod = 1 local headerColor = "yellow" -local info = _detalhes.playerDetailWindow +local breakdownWindowFrame = Details.BreakdownWindowFrame local keyName function healingClass:NovaTabela (serial, nome, link) @@ -1656,7 +1656,7 @@ end --------------------------------------------- // JANELA DETALHES // --------------------------------------------- ---------- bifurca��o function healingClass:MontaInfo() - if (info.sub_atributo == 1 or info.sub_atributo == 2) then + if (breakdownWindowFrame.sub_atributo == 1 or breakdownWindowFrame.sub_atributo == 2) then self:MontaInfoHealingDone() --[=[ @@ -1690,7 +1690,7 @@ function healingClass:MontaInfo() end --]=] - elseif (info.sub_atributo == 3) then + elseif (breakdownWindowFrame.sub_atributo == 3) then self:MontaInfoHealingDone() --[=[ @@ -1724,7 +1724,7 @@ function healingClass:MontaInfo() end --]=] - elseif (info.sub_atributo == 4) then + elseif (breakdownWindowFrame.sub_atributo == 4) then self:MontaInfoHealTaken() end end @@ -1734,7 +1734,7 @@ function healingClass:MontaInfoHealTaken() ---@type actor local actorObject = self ---@type instance - local instance = info.instancia + local instance = breakdownWindowFrame.instancia ---@type combat local combatObject = instance:GetCombat() ---@type string @@ -1779,10 +1779,10 @@ function healingClass:MontaInfoHealTaken() local healing_taken = self.healing_taken local curandeiros = self.healing_from - local instancia = info.instancia + local instancia = breakdownWindowFrame.instancia local tabela_do_combate = instancia.showing local showing = tabela_do_combate [class_type] --o que esta sendo mostrado -> [1] - dano [2] - cura --pega o container com ._NameIndexTable ._ActorTable - local barras = info.barras1 + local barras = breakdownWindowFrame.barras1 local meus_curandeiros = {} local este_curandeiro @@ -1834,11 +1834,11 @@ end function healingClass:MontaInfoOverHealing() --this should be deprecated now --pegar as habilidade de dar sort no heal - local instancia = info.instancia + local instancia = breakdownWindowFrame.instancia local total = self.totalover local tabela = self.spells._ActorTable local minhas_curas = {} - local barras = info.barras1 + local barras = breakdownWindowFrame.barras1 for spellid, tabela in pairs(tabela) do local nome, _, icone = _GetSpellInfo(spellid) @@ -1876,13 +1876,13 @@ function healingClass:MontaInfoOverHealing() --this should be deprecated now barra.on_focus = false end - if (not info.mostrando_mouse_over) then + if (not breakdownWindowFrame.mostrando_mouse_over) then if (tabela[1] == self.detalhes) then --tabela [1] = spellid = spellid que esta na caixa da direita if (not barra.on_focus) then --se a barra n�o tiver no foco barra.textura:SetStatusBarColor(129/255, 125/255, 69/255, 1) barra.on_focus = true - if (not info.mostrando) then - info.mostrando = barra + if (not breakdownWindowFrame.mostrando) then + breakdownWindowFrame.mostrando = barra end end else @@ -1938,7 +1938,7 @@ function healingClass:MontaInfoOverHealing() --this should be deprecated now for index, tabela in ipairs(jogadores_overhealed) do - local barra = info.barras2 [index] + local barra = breakdownWindowFrame.barras2 [index] if (not barra) then barra = gump:CriaNovaBarraInfo2 (instancia, index) @@ -1975,7 +1975,7 @@ function healingClass:MontaInfoHealingDone() ---@type actor local actorObject = self ---@type instance - local instance = info.instancia + local instance = breakdownWindowFrame.instancia ---@type combat local combatObject = instance:GetCombat() ---@type string @@ -1993,7 +1993,7 @@ function healingClass:MontaInfoHealingDone() if (Details.time_type == 1 or not actorObject.grupo) then actorCombatTime = actorObject:Tempo() elseif (Details.time_type == 2) then - actorCombatTime = info.instancia.showing:GetCombatTime() + actorCombatTime = breakdownWindowFrame.instancia.showing:GetCombatTime() end --actor spells @@ -2165,18 +2165,18 @@ function healingClass:MontaInfoHealingDone() if 1 then return end - local instancia = info.instancia + local instancia = breakdownWindowFrame.instancia local total = self.total local tabela = self.spells._ActorTable local minhas_curas = {} - local barras = info.barras1 + local barras = breakdownWindowFrame.barras1 --get time type local meu_tempo if (_detalhes.time_type == 1 or not self.grupo) then meu_tempo = self:Tempo() elseif (_detalhes.time_type == 2) then - meu_tempo = info.instancia.showing:GetCombatTime() + meu_tempo = breakdownWindowFrame.instancia.showing:GetCombatTime() end for spellid, tabela in pairs(tabela) do @@ -2192,7 +2192,7 @@ function healingClass:MontaInfoHealingDone() }) end - info:SetStatusbarText() + breakdownWindowFrame:SetStatusbarText() --add pets local ActorPets = self.pets @@ -2238,7 +2238,7 @@ function healingClass:MontaInfoHealingDone() barra.other_actor = tabela [6] - if (info.sub_atributo == 2) then + if (breakdownWindowFrame.sub_atributo == 2) then local formated_value = SelectedToKFunction (_, _math_floor(tabela[2]/meu_tempo)) self:UpdadeInfoBar(barra, index, tabela[1], tabela[4], tabela[2], formated_value, max_, tabela[3], tabela[5], true) else @@ -2272,7 +2272,7 @@ function healingClass:MontaInfoHealingDone() local topHealingDone = max(healedTargets[1] and healedTargets[1][2] or 0, 0.0001) for index, healDataTable in ipairs(healedTargets) do - local barra = info.barras2[index] + local barra = breakdownWindowFrame.barras2[index] if (not barra) then barra = gump:CriaNovaBarraInfo2(instancia, index) @@ -2299,7 +2299,7 @@ function healingClass:MontaInfoHealingDone() barra.lineText1:SetText(index .. ". " .. _detalhes:GetOnlyName(healDataTable[1])) barra.textura:SetStatusBarColor(1, 1, 1, 1) - if (info.sub_atributo == 2) then + if (breakdownWindowFrame.sub_atributo == 2) then barra.lineText4:SetText(_detalhes:comma_value(_math_floor(healingDone/meu_tempo)) .." (" .. _cstr ("%.1f", healDataTable[3]) .. "%)") else barra.lineText4:SetText(SelectedToKFunction(_, healingDone) .. " (" .. _cstr ("%.1f", healDataTable[3]) .. "%)") @@ -2321,7 +2321,7 @@ function healingClass:MontaTooltipAlvos (thisLine, index, instancia) local container = self.spells._ActorTable local habilidades = {} local total - local sub_atributo = info.instancia.sub_atributo + local sub_atributo = breakdownWindowFrame.instancia.sub_atributo local targets_key = "" @@ -2372,10 +2372,10 @@ function healingClass:MontaTooltipAlvos (thisLine, index, instancia) if (_detalhes.time_type == 1 or not self.grupo) then meu_tempo = self:Tempo() elseif (_detalhes.time_type == 2) then - meu_tempo = info.instancia.showing:GetCombatTime() + meu_tempo = breakdownWindowFrame.instancia.showing:GetCombatTime() end - local is_hps = info.instancia.sub_atributo == 2 + local is_hps = breakdownWindowFrame.instancia.sub_atributo == 2 if (is_hps) then --GameTooltip:AddLine(index..". "..inimigo) @@ -2422,25 +2422,25 @@ end function healingClass:MontaDetalhes (spellid, barra) --bifurga��es - if (info.sub_atributo == 1 or info.sub_atributo == 2 or info.sub_atributo == 3) then + if (breakdownWindowFrame.sub_atributo == 1 or breakdownWindowFrame.sub_atributo == 2 or breakdownWindowFrame.sub_atributo == 3) then return self:MontaDetalhesHealingDone (spellid, barra) - elseif (info.sub_atributo == 4) then + elseif (breakdownWindowFrame.sub_atributo == 4) then healingClass:MontaDetalhesHealingTaken (spellid, barra) end end function healingClass:MontaDetalhesHealingTaken (nome, barra) - local barras = info.barras3 - local instancia = info.instancia + local barras = breakdownWindowFrame.barras3 + local instancia = breakdownWindowFrame.instancia - local tabela_do_combate = info.instancia.showing + local tabela_do_combate = breakdownWindowFrame.instancia.showing local showing = tabela_do_combate [class_type] --o que esta sendo mostrado -> [1] - dano [2] - cura --pega o container com ._NameIndexTable ._ActorTable local este_curandeiro = showing._ActorTable[showing._NameIndexTable[nome]] local conteudo = este_curandeiro.spells._ActorTable --pairs[] com os IDs das magias - local actor = info.jogador.nome + local actor = breakdownWindowFrame.jogador.nome local total = este_curandeiro.targets [actor] @@ -2518,7 +2518,7 @@ function healingClass:MontaDetalhesHealingDone (spellid, barra) --deprecated wit --icone direito superior local spellName, _, icone = _GetSpellInfo(spellid) - info.spell_icone:SetTexture(icone) + breakdownWindowFrame.spell_icone:SetTexture(icone) local total = self.total @@ -2529,7 +2529,7 @@ function healingClass:MontaDetalhesHealingDone (spellid, barra) --deprecated wit if (_detalhes.time_type == 1 or not self.grupo) then meu_tempo = self:Tempo() elseif (_detalhes.time_type == 2) then - meu_tempo = info.instancia.showing:GetCombatTime() + meu_tempo = breakdownWindowFrame.instancia.showing:GetCombatTime() end local total_hits = esta_magia.counter @@ -2564,14 +2564,14 @@ function healingClass:MontaDetalhesHealingDone (spellid, barra) --deprecated wit local hits_string = "" .. total_hits local cast_string = Loc ["STRING_CAST"] .. ": " - local misc_actor = info.instancia.showing (4, self:name()) + local misc_actor = breakdownWindowFrame.instancia.showing (4, self:name()) if (misc_actor) then local buff_uptime = misc_actor.buff_uptime_spells and misc_actor.buff_uptime_spells._ActorTable [spellid] and misc_actor.buff_uptime_spells._ActorTable [spellid].uptime if (buff_uptime) then - hits_string = hits_string .. " |cFFDDDD44(" .. _math_floor(buff_uptime / info.instancia.showing:GetCombatTime() * 100) .. "% uptime)|r" + hits_string = hits_string .. " |cFFDDDD44(" .. _math_floor(buff_uptime / breakdownWindowFrame.instancia.showing:GetCombatTime() * 100) .. "% uptime)|r" end - local amountOfCasts = info.instancia.showing:GetSpellCastAmount(self:Name(), spellName) + local amountOfCasts = breakdownWindowFrame.instancia.showing:GetSpellCastAmount(self:Name(), spellName) if (not amountOfCasts) then amountOfCasts = "(|cFFFFFF00?|r)" end diff --git a/classes/class_instance.lua b/classes/class_instance.lua index 1c9061e6..38e68c63 100644 --- a/classes/class_instance.lua +++ b/classes/class_instance.lua @@ -270,6 +270,7 @@ local instanceMixins = { end, ---call a refresh in the data shown in the instance + ---@param instance instance ---@param bForceRefresh boolean|nil RefreshData = function(instance, bForceRefresh) --deprecates Details:RefreshAllMainWindows() local combatObject = instance:GetCombat() @@ -282,9 +283,20 @@ local instanceMixins = { return end + --debug: check if the if combatObject has been destroyed + if (combatObject.__destroyed) then + Details:Msg("a deleted combat object was found refreshing a window, please report this bug on discord:") + Details:Msg("combat destroyed by:", combatObject.__destroyedBy) + local bForceChange = true + instance:SetSegment(DETAILS_SEGMENTID_CURRENT, bForceChange) + return + end + local mainAttribute, subAttribute = instance:GetDisplay() - local needRefresh = combatObject:GetContainer(mainAttribute).need_refresh + ---@type actorcontainer + local actorContainer = combatObject:GetContainer(mainAttribute) + local needRefresh = actorContainer.need_refresh if (not needRefresh and not bForceRefresh) then return end @@ -513,7 +525,7 @@ local instanceMixins = { Details:SendEvent("DETAILS_INSTANCE_CHANGEATTRIBUTE", nil, instance, attributeId, subAttributeId) end - if (Details.playerDetailWindow:IsShown() and instance == Details.playerDetailWindow.instancia) then + if (Details.BreakdownWindowFrame:IsShown() and instance == Details.BreakdownWindowFrame.instancia) then ---@type combat local combatObject = instance:GetCombat() if (not combatObject or instance.atributo > 4) then @@ -2393,7 +2405,7 @@ function Details:PostponeSwitchToCurrent(instance) (instance.ativa) and (instance.last_interaction+3 < Details._tempo) and (not DetailsReportWindow or not DetailsReportWindow:IsShown()) and - (not Details.playerDetailWindow:IsShown()) + (not Details.BreakdownWindowFrame:IsShown()) ) ) then instance._postponing_switch = nil @@ -2419,7 +2431,7 @@ function Details:CheckSwitchToCurrent() instance.last_interaction = Details._tempo end - if ((instance.last_interaction and (instance.last_interaction+3 > Details._tempo)) or (DetailsReportWindow and DetailsReportWindow:IsShown()) or (Details.playerDetailWindow:IsShown())) then + if ((instance.last_interaction and (instance.last_interaction+3 > Details._tempo)) or (DetailsReportWindow and DetailsReportWindow:IsShown()) or (Details.BreakdownWindowFrame:IsShown())) then --postpone --instance._postponing_switch = Details:ScheduleTimer("PostponeSwitchToCurrent", 1, instance) instance._postponing_switch = Details.Schedules.NewTimer(1, Details.PostponeSwitchToCurrent, Details, instance) @@ -2831,11 +2843,11 @@ function _detalhes:TrocaTabela(instance, segmentId, attributeId, subAttributeId, instance:ChangeIcon() end - if (Details.playerDetailWindow:IsShown() and instance == Details.playerDetailWindow.instancia) then + if (Details.BreakdownWindowFrame:IsShown() and instance == Details.BreakdownWindowFrame.instancia) then if (not instance.showing or instance.atributo > 4) then Details:CloseBreakdownWindow() else - local actorObject = instance.showing (instance.atributo, Details.playerDetailWindow.jogador.nome) + local actorObject = instance.showing (instance.atributo, Details.BreakdownWindowFrame.jogador.nome) if (actorObject) then Details:OpenBreakdownWindow(instance, actorObject, true) else @@ -3387,13 +3399,13 @@ function _detalhes:monta_relatorio (este_relatorio, custom) --push it to front local t = tremove(_detalhes.latest_report_table, already_exists) t [4] = amt - tinsert(_detalhes.latest_report_table, 1, t) + table.insert(_detalhes.latest_report_table, 1, t) else if (self.atributo == 5) then local custom_name = self:GetCustomObject():GetName() - tinsert(_detalhes.latest_report_table, 1, {self.meu_id, self.atributo, self.sub_atributo, amt, _detalhes.report_where, custom_name}) + table.insert(_detalhes.latest_report_table, 1, {self.meu_id, self.atributo, self.sub_atributo, amt, _detalhes.report_where, custom_name}) else - tinsert(_detalhes.latest_report_table, 1, {self.meu_id, self.atributo, self.sub_atributo, amt, _detalhes.report_where}) + table.insert(_detalhes.latest_report_table, 1, {self.meu_id, self.atributo, self.sub_atributo, amt, _detalhes.report_where}) end end @@ -3532,7 +3544,7 @@ function _detalhes:monta_relatorio (este_relatorio, custom) if (is_reverse) then local t = {} for i = #raw_data_to_report, 1, -1 do - tinsert(t, raw_data_to_report [i]) + table.insert(t, raw_data_to_report [i]) if (#t >= amt) then break end diff --git a/classes/class_resources.lua b/classes/class_resources.lua index b91d38e6..b5fa1eed 100644 --- a/classes/class_resources.lua +++ b/classes/class_resources.lua @@ -56,7 +56,7 @@ local headerColor = "yellow" local actor_class_color_r, actor_class_color_g, actor_class_color_b -local info = _detalhes.playerDetailWindow +local breakdownWindowFrame = Details.BreakdownWindowFrame local keyName @@ -1046,14 +1046,14 @@ end ---------DETALHES BIFURCA��O function atributo_energy:MontaInfo() - if (info.sub_atributo <= 4) then + if (breakdownWindowFrame.sub_atributo <= 4) then return self:MontaInfoRegenRecebido() end end ---------DETALHES bloco da direita BIFURCA��O function atributo_energy:MontaDetalhes (spellid, barra) - if (info.sub_atributo <= 4) then + if (breakdownWindowFrame.sub_atributo <= 4) then return self:MontaDetalhesRegenRecebido (spellid, barra) end end @@ -1064,11 +1064,11 @@ function atributo_energy:MontaInfoRegenRecebido() reset_tooltips_table() - local barras = info.barras1 - local barras2 = info.barras2 - local barras3 = info.barras3 + local barras = breakdownWindowFrame.barras1 + local barras2 = breakdownWindowFrame.barras2 + local barras3 = breakdownWindowFrame.barras3 - local instancia = info.instancia + local instancia = breakdownWindowFrame.instancia local tabela_do_combate = instancia.showing local container = tabela_do_combate [class_type] @@ -1188,7 +1188,7 @@ function atributo_energy:MontaInfoRegenRecebido() break end - barra = info.barras2 [index] + barra = breakdownWindowFrame.barras2 [index] if (not barra) then barra = gump:CriaNovaBarraInfo2 (instancia, index) @@ -1229,10 +1229,10 @@ function atributo_energy:MontaDetalhesRegenRecebido (nome, barra) reset_tooltips_table() - local barras = info.barras3 - local instancia = info.instancia + local barras = breakdownWindowFrame.barras3 + local instancia = breakdownWindowFrame.instancia - local tabela_do_combate = info.instancia.showing + local tabela_do_combate = breakdownWindowFrame.instancia.showing local container = tabela_do_combate [class_type] local total_regenerado = self.received @@ -1321,7 +1321,7 @@ end function atributo_energy:MontaTooltipAlvos (esta_barra, index) - local instancia = info.instancia + local instancia = breakdownWindowFrame.instancia local tabela_do_combate = instancia.showing local container = tabela_do_combate [class_type] diff --git a/classes/class_utility.lua b/classes/class_utility.lua index 6444e86d..251d4346 100644 --- a/classes/class_utility.lua +++ b/classes/class_utility.lua @@ -47,7 +47,7 @@ local UsingCustomRightText = false local TooltipMaximizedMethod = 1 -local info = _detalhes.playerDetailWindow +local breakdownWindowFrame = Details.BreakdownWindowFrame local keyName local headerColor = "yellow" @@ -2042,14 +2042,14 @@ end ---------DETALHES BIFURCA��O function atributo_misc:MontaInfo() - if (info.sub_atributo == 3) then --interrupt + if (breakdownWindowFrame.sub_atributo == 3) then --interrupt return self:MontaInfoInterrupt() end end ---------DETALHES bloco da direita BIFURCA��O function atributo_misc:MontaDetalhes (spellid, barra) - if (info.sub_atributo == 3) then --interrupt + if (breakdownWindowFrame.sub_atributo == 3) then --interrupt return self:MontaDetalhesInterrupt (spellid, barra) end end @@ -2065,8 +2065,8 @@ function atributo_misc:MontaInfoInterrupt() local minha_tabela = self.interrupt_spells._ActorTable - local barras = info.barras1 - local instancia = info.instancia + local barras = breakdownWindowFrame.barras1 + local instancia = breakdownWindowFrame.instancia local meus_interrupts = {} @@ -2110,13 +2110,13 @@ function atributo_misc:MontaInfoInterrupt() --isso aqui � tudo da sele��o e descele��o das barras - if (not info.mostrando_mouse_over) then + if (not breakdownWindowFrame.mostrando_mouse_over) then if (tabela[1] == self.detalhes) then --tabela [1] = spellid = spellid que esta na caixa da direita if (not barra.on_focus) then --se a barra n�o tiver no foco barra.textura:SetStatusBarColor(129/255, 125/255, 69/255, 1) barra.on_focus = true - if (not info.mostrando) then - info.mostrando = barra + if (not breakdownWindowFrame.mostrando) then + breakdownWindowFrame.mostrando = barra end end else @@ -2166,7 +2166,7 @@ function atributo_misc:MontaInfoInterrupt() local barra for index, tabela in ipairs(meus_alvos) do - barra = info.barras2 [index] + barra = breakdownWindowFrame.barras2 [index] if (not barra) then barra = gump:CriaNovaBarraInfo2 (instancia, index) @@ -2214,7 +2214,7 @@ function atributo_misc:MontaDetalhesInterrupt (spellid, barra) local nome, _, icone = _GetSpellInfo(spellid) local infospell = {nome, nil, icone} - _detalhes.playerDetailWindow.spell_icone:SetTexture(infospell[3]) + Details.BreakdownWindowFrame.spell_icone:SetTexture(infospell[3]) local total = self.interrupt local meu_total = esta_magia.counter @@ -2223,8 +2223,8 @@ function atributo_misc:MontaDetalhesInterrupt (spellid, barra) local data = {} - local barras = info.barras3 - local instancia = info.instancia + local barras = breakdownWindowFrame.barras3 + local instancia = breakdownWindowFrame.instancia local habilidades_alvos = {} for spellid, amt in pairs(esta_magia.interrompeu_oque) do @@ -2278,7 +2278,7 @@ function atributo_misc:MontaTooltipAlvos (esta_barra, index) local inimigo = esta_barra.nome_inimigo local container - if (info.instancia.sub_atributo == 3) then --interrupt + if (breakdownWindowFrame.instancia.sub_atributo == 3) then --interrupt container = self.interrupt_spells._ActorTable end diff --git a/classes/container_segments.lua b/classes/container_segments.lua index 83ab331d..3834e7dd 100644 --- a/classes/container_segments.lua +++ b/classes/container_segments.lua @@ -447,6 +447,7 @@ function segmentClass:ResetOverallData() Details:CloseBreakdownWindow() Details:DestroyCombat(Details.tabela_overall) + Details:SendEvent("DETAILS_DATA_SEGMENTREMOVED") Details.tabela_overall = combatClass:NovaTabela() for index, instanceObject in ipairs(Details:GetAllInstances()) do @@ -501,10 +502,17 @@ function segmentClass:ResetAllCombatData() for _, combatObject in ipairs(Details.tabela_historico.tabelas) do ---@cast combatObject combat Details:DestroyCombat(combatObject) + Details:SendEvent("DETAILS_DATA_SEGMENTREMOVED") + end + + --the current combat when finished will be moved to the first index of "tabela_historico.tabelas", need the check if the current combat was already destroyed + if (not Details.tabela_vigente.__destroyed) then + Details:DestroyCombat(Details.tabela_vigente) + Details:SendEvent("DETAILS_DATA_SEGMENTREMOVED") end - Details:DestroyCombat(Details.tabela_vigente) Details:DestroyCombat(Details.tabela_overall) + Details:SendEvent("DETAILS_DATA_SEGMENTREMOVED") Details:Destroy(Details.spellcache) if (Details.schedule_add_to_overall) then --deprecated diff --git a/core/control.lua b/core/control.lua index 8dbd7ea3..e29c8cea 100644 --- a/core/control.lua +++ b/core/control.lua @@ -28,7 +28,7 @@ local atributo_energy = Details.atributo_energy --details local local atributo_misc = Details.atributo_misc --details local local atributo_custom = Details.atributo_custom --details local - local info = Details.playerDetailWindow --details local + local breakdownWindowFrame = Details.BreakdownWindowFrame --details local local UnitGroupRolesAssigned = DetailsFramework.UnitGroupRolesAssigned @@ -788,13 +788,13 @@ if (Details.tabela_vigente.is_boss.killed) then cleuIDData.kills = cleuIDData.kills + 1 cleuIDData.best_try = 0 - tinsert(cleuIDData.try_history, {0, Details.tabela_vigente:GetCombatTime()}) + table.insert(cleuIDData.try_history, {0, Details.tabela_vigente:GetCombatTime()}) --print("KILL", "best try", cleuIDData.best_try, "amt kills", cleuIDData.kills, "wipes", cleuIDData.wipes, "longest", cleuIDData.longest) else cleuIDData.wipes = cleuIDData.wipes + 1 if (Details.boss1_health_percent and Details.boss1_health_percent < cleuIDData.best_try) then cleuIDData.best_try = Details.boss1_health_percent - tinsert(cleuIDData.try_history, {Details.boss1_health_percent, Details.tabela_vigente:GetCombatTime()}) + table.insert(cleuIDData.try_history, {Details.boss1_health_percent, Details.tabela_vigente:GetCombatTime()}) end --print("WIPE", "best try", cleuIDData.best_try, "amt kills", cleuIDData.kills, "wipes", cleuIDData.wipes, "longest", cleuIDData.longest) end @@ -1489,7 +1489,7 @@ (instance.ativa) and (instance.last_interaction+3 < _tempo) and (not DetailsReportWindow or not DetailsReportWindow:IsShown()) and - (not Details.playerDetailWindow:IsShown()) + (not Details.BreakdownWindowFrame:IsShown()) ) ) then instance._postponing_current = nil @@ -1515,7 +1515,7 @@ end end - if ((instancia.last_interaction and (instancia.last_interaction+3 > Details._tempo)) or (DetailsReportWindow and DetailsReportWindow:IsShown()) or (Details.playerDetailWindow:IsShown())) then + if ((instancia.last_interaction and (instancia.last_interaction+3 > Details._tempo)) or (DetailsReportWindow and DetailsReportWindow:IsShown()) or (Details.BreakdownWindowFrame:IsShown())) then --postpone instancia._postponing_current = Details:ScheduleTimer("PostponeInstanceToCurrent", 1, instancia) return @@ -1789,7 +1789,7 @@ end --call update functions - function Details:RefreshAllMainWindows(bForceRefresh) + function Details:RefreshAllMainWindows(bForceRefresh) --getting deprecated soon local combatObject = self.showing --the the segment does not have a valid combat, freeze the window @@ -1846,7 +1846,7 @@ self:RefreshMainWindow(true) end - function Details:RefreshMainWindow(instanceObject, bForceRefresh) + function Details:RefreshMainWindow(instanceObject, bForceRefresh) --getting deprecated soon if (not instanceObject or type(instanceObject) == "boolean") then bForceRefresh = instanceObject instanceObject = self @@ -1859,17 +1859,18 @@ if (instanceObject == -1) then --update for index, thisInstance in ipairs(Details.tabela_instancias) do - if (thisInstance.ativa) then - if (thisInstance.modo == modo_GROUP or thisInstance.modo == modo_ALL) then - thisInstance:RefreshAllMainWindows(bForceRefresh) + ---@cast thisInstance instance + if (thisInstance:IsEnabled()) then + if (thisInstance:GetMode() == DETAILS_MODE_GROUP or thisInstance:GetMode() == DETAILS_MODE_ALL) then + thisInstance:RefreshData(bForceRefresh) end end end --flag windows as no need update next tick for index, thisInstance in ipairs(Details.tabela_instancias) do - if (thisInstance.ativa and thisInstance.showing) then - if (thisInstance.modo == modo_GROUP or thisInstance.modo == modo_ALL) then + if (thisInstance:IsEnabled() and thisInstance.showing) then + if (thisInstance:GetMode() == DETAILS_MODE_GROUP or thisInstance:GetMode() == DETAILS_MODE_ALL) then if (thisInstance.atributo <= 4) then thisInstance.showing[thisInstance.atributo].need_refresh = false end @@ -1878,8 +1879,8 @@ end if (not bForceRefresh) then --update player details window if opened - if (info.ativo) then - return info.jogador:MontaInfo() + if (breakdownWindowFrame.ativo) then + return breakdownWindowFrame.jogador:MontaInfo() end end return diff --git a/core/meta.lua b/core/meta.lua index f9bcf46a..76da1911 100644 --- a/core/meta.lua +++ b/core/meta.lua @@ -468,7 +468,7 @@ local classTypeUtility = Details.atributos.misc local combatObject = allSegments[i] if (combatObject:IsTrash()) then --error, IsTrash is not a function, probably because the combat got destroyed table.remove(allSegments, i) - Details:DestroyCombat(combatObject) + Details:DestroyCombat(combatObject) --no need to send DETAILS_DATA_SEGMENTREMOVED due to this be in the logout process end end @@ -819,6 +819,11 @@ local classTypeUtility = Details.atributos.misc --collect the garbage for i, combatObject in ipairs(segmentsList) do + if (combatObject.__destroyed) then + Details:Msg("a deleted combat object was found by the g.collector, please report this bug on discord:") + Details:Msg("combat destroyed by:", combatObject.__destroyedBy) + end + local removedActors = collectGarbage(combatObject, overriteLastEvent) if (i == #segmentsList) then --print("current segment removed:", removedActors, "actors.") diff --git a/core/plugins.lua b/core/plugins.lua index 1c65d217..ccf3999a 100644 --- a/core/plugins.lua +++ b/core/plugins.lua @@ -1,64 +1,76 @@ - ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - local Loc = LibStub("AceLocale-3.0"):GetLocale ( "Details" ) - local _detalhes = _G.Details + local Loc = LibStub("AceLocale-3.0"):GetLocale( "Details" ) + local Details = _G.Details local PixelUtil = PixelUtil or DFPixelUtil + local addonName, Details222 = ... + local CreateFrame = CreateFrame + local detailsFramework = DetailsFramework + local UIParent = UIParent + local UISpecialFrames = UISpecialFrames - DETAILSPLUGIN_ALWAYSENABLED = 0x1 - - --consts - local CONST_PLUGINWINDOW_MENU_WIDTH = 150 - local CONST_PLUGINWINDOW_MENU_HEIGHT = 22 - local CONST_PLUGINWINDOW_MENU_X = -5 - local CONST_PLUGINWINDOW_MENU_Y = -26 - local CONST_PLUGINWINDOW_WIDTH = 925 - local CONST_PLUGINWINDOW_HEIGHT = 600 - ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ---details api functions - function _detalhes:GetPlugin (PAN) --plugin absolute name - return _detalhes.SoloTables.NameTable [PAN] or _detalhes.RaidTables.NameTable [PAN] or _detalhes.ToolBar.NameTable [PAN] or _detalhes.StatusBar.NameTable [PAN] or _detalhes.PluginsLocalizedNames [PAN] or _detalhes.PluginsGlobalNames [PAN] + DETAILSPLUGIN_ALWAYSENABLED = 0x1 --[[GLOBAL]] + + local CONST_PLUGINWINDOW_MENU_WIDTH = 150 + local CONST_PLUGINWINDOW_MENU_HEIGHT = 22 + local CONST_PLUGINWINDOW_MENU_X = -5 + local CONST_PLUGINWINDOW_MENU_Y = -26 + local CONST_PLUGINWINDOW_WIDTH = 925 + local CONST_PLUGINWINDOW_HEIGHT = 600 + + ---comment + ---@param pluginAbsoluteName string + ---@return unknown + function Details:GetPlugin(pluginAbsoluteName) + return Details.SoloTables.NameTable[pluginAbsoluteName] or Details.RaidTables.NameTable[pluginAbsoluteName] or Details.ToolBar.NameTable[pluginAbsoluteName] or Details.StatusBar.NameTable[pluginAbsoluteName] or Details.PluginsLocalizedNames[pluginAbsoluteName] or Details.PluginsGlobalNames[pluginAbsoluteName] end - - function _detalhes:GetPluginSavedTable (PluginAbsoluteName) - return _detalhes.plugin_database [PluginAbsoluteName] + + ---comment + ---@param pluginAbsoluteName string + ---@return unknown + function Details:GetPluginSavedTable(pluginAbsoluteName) + return Details.plugin_database[pluginAbsoluteName] end - - function _detalhes:UpdatePluginBarsConfig() - local instance = self:GetPluginInstance() - if (instance) then + + ---comment + function Details:UpdatePluginBarsConfig() + ---@type instance + local instanceObject = self:GetPluginInstance() + if (instanceObject) then self.row_info = self.row_info or {} - _detalhes.table.copy(self.row_info, instance.row_info) - self.bars_grow_direction = instance.bars_grow_direction - self.row_height = instance.row_height + Details.table.copy(self.row_info, instanceObject.row_info) + self.bars_grow_direction = instanceObject.bars_grow_direction + self.row_height = instanceObject.row_height self:SetBarGrowDirection() end end - - function _detalhes:AttachToInstance() - local instance = self:GetPluginInstance() - if (instance) then - local w, h = instance:GetSize() - self.Frame:SetSize(w, h) + + function Details:AttachToInstance() + ---@type instance + local instanceObject = self:GetPluginInstance() + if (instanceObject) then + local width, height = instanceObject:GetSize() + self.Frame:SetSize(width, height) end end - - function _detalhes:GetPluginInstance (PluginAbsoluteName) + + ---comment + ---@param pluginAbsoluteName string|nil + ---@return any + function Details:GetPluginInstance(pluginAbsoluteName) local plugin = self - if (PluginAbsoluteName) then - plugin = _detalhes:GetPlugin (PluginAbsoluteName) + if (pluginAbsoluteName) then + plugin = Details:GetPlugin(pluginAbsoluteName) end - + local id = plugin.instance_id if (id) then - return _detalhes:GetInstance(id) + return Details:GetInstance(id) end end - - function _detalhes:IsPluginEnabled (PluginAbsoluteName) - if (PluginAbsoluteName) then - local plugin = _detalhes.plugin_database [PluginAbsoluteName] + + function Details:IsPluginEnabled(pluginAbsoluteName) + if (pluginAbsoluteName) then + local plugin = Details.plugin_database[pluginAbsoluteName] if (plugin) then return plugin.enabled end @@ -66,527 +78,545 @@ return self.__enabled end end - - function _detalhes:SetPluginDescription (desc) + + ---comment + ---@param desc string + function Details:SetPluginDescription(desc) self.__description = desc end - function _detalhes:GetPluginDescription() + + ---get the description of a plugin + ---@return string + function Details:GetPluginDescription() return self.__description or "" end - - function _detalhes:DisablePlugin (AbsoluteName) - local plugin = _detalhes:GetPlugin (AbsoluteName) - + + ---disable a plugin + ---@param pluginAbsoluteName string + ---@return boolean + function Details:DisablePlugin(pluginAbsoluteName) + local plugin = Details:GetPlugin(pluginAbsoluteName) + if (plugin) then - local saved_table = _detalhes:GetPluginSavedTable (AbsoluteName) - - saved_table.enabled = false + local savedTable = Details:GetPluginSavedTable(pluginAbsoluteName) + savedTable.enabled = false plugin.__enabled = false - - _detalhes:SendEvent("PLUGIN_DISABLED", plugin) - - _detalhes:DelayOptionsRefresh() + + Details:SendEvent("PLUGIN_DISABLED", plugin) + Details:DelayOptionsRefresh() return true end + + return false end - - function _detalhes:CheckDefaultTable (current, default) - for key, value in pairs(default) do + + ---check if the plugin saved table has all the default key and values + ---@param savedTable table + ---@param defaultSavedTable table + function Details:CheckDefaultTable(savedTable, defaultSavedTable) + for key, value in pairs(defaultSavedTable) do if (type(value) == "table") then - if (type(current [key]) ~= "table") then - current [key] = Details.CopyTable(value) + if (type(savedTable[key]) ~= "table") then + savedTable[key] = Details.CopyTable(value) else - _detalhes:CheckDefaultTable (current [key], value) + Details:CheckDefaultTable(savedTable[key], value) end else - if (current [key] == nil) then - current [key] = value - --elseif (type(current [key]) ~= type(value)) then - -- current [key] = value + if (savedTable[key] == nil) then + savedTable[key] = value end end end end - function _detalhes:InstallPlugin (PluginType, PluginName, PluginIcon, PluginObject, PluginAbsoluteName, MinVersion, Author, Version, DefaultSavedTable) + function Details:InstallPlugin(pluginType, pluginName, pluginIcon, pluginObject, pluginAbsoluteName, minVersion, authorName, version, defaultSavedTable) + if (minVersion and minVersion > Details.realversion) then + print(pluginName, Loc["STRING_TOOOLD"]) + return Details:NewError("Details version is out of date.") + end - if (MinVersion and MinVersion > _detalhes.realversion) then - print(PluginName, Loc ["STRING_TOOOLD"]) - return _detalhes:NewError ("Details version is out of date.") + if (pluginType == "TANK") then + pluginType = "RAID" end - - if (PluginType == "TANK") then - PluginType = "RAID" + + if (not pluginType) then + return Details:NewError("InstallPlugin parameter 1 (plugin type) not especified") + elseif (not pluginName) then + return Details:NewError("InstallPlugin parameter 2 (plugin name) can't be nil") + elseif (not pluginIcon) then + return Details:NewError("InstallPlugin parameter 3 (plugin icon) can't be nil") + elseif (not pluginObject) then + return Details:NewError("InstallPlugin parameter 4 (plugin object) can't be nil") + elseif (not pluginAbsoluteName) then + return Details:NewError("InstallPlugin parameter 5 (plugin absolut name) can't be nil") end - - if (not PluginType) then - return _detalhes:NewError ("InstallPlugin parameter 1 (plugin type) not especified") - elseif (not PluginName) then - return _detalhes:NewError ("InstallPlugin parameter 2 (plugin name) can't be nil") - elseif (not PluginIcon) then - return _detalhes:NewError ("InstallPlugin parameter 3 (plugin icon) can't be nil") - elseif (not PluginObject) then - return _detalhes:NewError ("InstallPlugin parameter 4 (plugin object) can't be nil") - elseif (not PluginAbsoluteName) then - return _detalhes:NewError ("InstallPlugin parameter 5 (plugin absolut name) can't be nil") - end - - if (_G [PluginAbsoluteName]) then - print(Loc ["STRING_PLUGIN_NAMEALREADYTAKEN"] .. ": " .. PluginName .. " name: " .. PluginAbsoluteName) + + if (_G[pluginAbsoluteName]) then + print(Loc["STRING_PLUGIN_NAMEALREADYTAKEN"] .. ": " .. pluginName .. " name: " .. pluginAbsoluteName) return else - _G [PluginAbsoluteName] = PluginObject - PluginObject.real_name = PluginAbsoluteName + _G[pluginAbsoluteName] = pluginObject + pluginObject.real_name = pluginAbsoluteName end - - PluginObject.__name = PluginName - PluginObject.__author = Author or "--------" - PluginObject.__version = Version or "v1.0.0" - PluginObject.__icon = PluginIcon or [[Interface\ICONS\Trade_Engineering]] - PluginObject.real_name = PluginAbsoluteName - - _detalhes.PluginsGlobalNames [PluginAbsoluteName] = PluginObject - _detalhes.PluginsLocalizedNames [PluginName] = PluginObject - - local saved_table - - if (PluginType ~= "STATUSBAR") then - saved_table = _detalhes.plugin_database [PluginAbsoluteName] - - if (not saved_table) then - saved_table = {enabled = true, author = Author or "--------"} - _detalhes.plugin_database [PluginAbsoluteName] = saved_table - end - - if (DefaultSavedTable) then - _detalhes:CheckDefaultTable (saved_table, DefaultSavedTable) - end - - PluginObject.__enabled = saved_table.enabled - end - - if (PluginType == "SOLO") then - if (not PluginObject.Frame) then - return _detalhes:NewError ("plugin doesn't have a Frame, please check case-sensitive member name: Frame") - end - - --Install Plugin - _detalhes.SoloTables.Plugins [#_detalhes.SoloTables.Plugins+1] = PluginObject - _detalhes.SoloTables.Menu [#_detalhes.SoloTables.Menu+1] = {PluginName, PluginIcon, PluginObject, PluginAbsoluteName} - _detalhes.SoloTables.NameTable [PluginAbsoluteName] = PluginObject - _detalhes:SendEvent("INSTALL_OKEY", PluginObject) - - _detalhes.PluginCount.SOLO = _detalhes.PluginCount.SOLO + 1 - elseif (PluginType == "RAID") then - - --Install Plugin - _detalhes.RaidTables.Plugins [#_detalhes.RaidTables.Plugins+1] = PluginObject - _detalhes.RaidTables.Menu [#_detalhes.RaidTables.Menu+1] = {PluginName, PluginIcon, PluginObject, PluginAbsoluteName} - _detalhes.RaidTables.NameTable [PluginAbsoluteName] = PluginObject - _detalhes:SendEvent("INSTALL_OKEY", PluginObject) - - _detalhes.PluginCount.RAID = _detalhes.PluginCount.RAID + 1 - - _detalhes:InstanceCall("RaidPluginInstalled", PluginAbsoluteName) - - elseif (PluginType == "TOOLBAR") then - - --Install Plugin - _detalhes.ToolBar.Plugins [#_detalhes.ToolBar.Plugins+1] = PluginObject - _detalhes.ToolBar.Menu [#_detalhes.ToolBar.Menu+1] = {PluginName, PluginIcon, PluginObject, PluginAbsoluteName} - _detalhes.ToolBar.NameTable [PluginAbsoluteName] = PluginObject - _detalhes:SendEvent("INSTALL_OKEY", PluginObject) - - _detalhes.PluginCount.TOOLBAR = _detalhes.PluginCount.TOOLBAR + 1 - - elseif (PluginType == "STATUSBAR") then - - --Install Plugin - _detalhes.StatusBar.Plugins [#_detalhes.StatusBar.Plugins+1] = PluginObject - _detalhes.StatusBar.Menu [#_detalhes.StatusBar.Menu+1] = {PluginName, PluginIcon} - _detalhes.StatusBar.NameTable [PluginAbsoluteName] = PluginObject - _detalhes:SendEvent("INSTALL_OKEY", PluginObject) - - _detalhes.PluginCount.STATUSBAR = _detalhes.PluginCount.STATUSBAR + 1 + pluginObject.__name = pluginName + pluginObject.__author = authorName or "--------" + pluginObject.__version = version or "v1.0.0" + pluginObject.__icon = pluginIcon or[[Interface\ICONS\Trade_Engineering]] + pluginObject.real_name = pluginAbsoluteName + + Details.PluginsGlobalNames[pluginAbsoluteName] = pluginObject + Details.PluginsLocalizedNames[pluginName] = pluginObject + + local savedTable + + if (pluginType ~= "STATUSBAR") then + savedTable = Details.plugin_database[pluginAbsoluteName] + + if (not savedTable) then + savedTable = {enabled = true, author = authorName or "--------"} + Details.plugin_database[pluginAbsoluteName] = savedTable + end + + if (defaultSavedTable) then + Details:CheckDefaultTable(savedTable, defaultSavedTable) + end + + pluginObject.__enabled = savedTable.enabled end - - if (saved_table) then - PluginObject.db = saved_table + + if (pluginType == "SOLO") then + if (not pluginObject.Frame) then + return Details:NewError("plugin doesn't have a Frame, please check case-sensitive member name: Frame") + end + + Details.SoloTables.Plugins[#Details.SoloTables.Plugins+1] = pluginObject + Details.SoloTables.Menu[#Details.SoloTables.Menu+1] = {pluginName, pluginIcon, pluginObject, pluginAbsoluteName} + Details.SoloTables.NameTable[pluginAbsoluteName] = pluginObject + Details:SendEvent("INSTALL_OKEY", pluginObject) + Details.PluginCount.SOLO = Details.PluginCount.SOLO + 1 + + elseif (pluginType == "RAID") then + Details.RaidTables.Plugins[#Details.RaidTables.Plugins+1] = pluginObject + Details.RaidTables.Menu[#Details.RaidTables.Menu+1] = {pluginName, pluginIcon, pluginObject, pluginAbsoluteName} + Details.RaidTables.NameTable[pluginAbsoluteName] = pluginObject + Details:SendEvent("INSTALL_OKEY", pluginObject) + Details.PluginCount.RAID = Details.PluginCount.RAID + 1 + Details:InstanceCall("RaidPluginInstalled", pluginAbsoluteName) + + elseif (pluginType == "TOOLBAR") then + Details.ToolBar.Plugins[#Details.ToolBar.Plugins+1] = pluginObject + Details.ToolBar.Menu[#Details.ToolBar.Menu+1] = {pluginName, pluginIcon, pluginObject, pluginAbsoluteName} + Details.ToolBar.NameTable[pluginAbsoluteName] = pluginObject + Details:SendEvent("INSTALL_OKEY", pluginObject) + Details.PluginCount.TOOLBAR = Details.PluginCount.TOOLBAR + 1 + + elseif (pluginType == "STATUSBAR") then + Details.StatusBar.Plugins[#Details.StatusBar.Plugins+1] = pluginObject + Details.StatusBar.Menu[#Details.StatusBar.Menu+1] = {pluginName, pluginIcon} + Details.StatusBar.NameTable[pluginAbsoluteName] = pluginObject + Details:SendEvent("INSTALL_OKEY", pluginObject) + Details.PluginCount.STATUSBAR = Details.PluginCount.STATUSBAR + 1 end - - if (PluginObject.__enabled) then - return true, saved_table, true + + if (savedTable) then + pluginObject.db = savedTable + end + + if (pluginObject.__enabled) then + return true, savedTable, true else - return true, saved_table, false + return true, savedTable, false end - end ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --internal functions - - _detalhes.PluginCount = { + + ---@type table + Details.PluginCount = { ["SOLO"] = 0, ["RAID"] = 0, ["TOOLBAR"] = 0, ["STATUSBAR"] = 0 - } - - local OnEnableFunction = function(self) + } + + local onEnableFunction = function(self) self.__parent.Enabled = true - --self = frame __parent = plugin object - local instance = _detalhes:GetInstance(self.__parent.instance_id) - if (instance) then - self:SetParent(instance.baseframe) + ---@type instance + local instanceObject = Details:GetInstance(self.__parent.instance_id) + if (instanceObject) then + self:SetParent(instanceObject.baseframe) end - _detalhes:SendEvent("SHOW", self.__parent) + Details:SendEvent("SHOW", self.__parent) end - local OnDisableFunction = function(self) - _detalhes:SendEvent("HIDE", self.__parent) + local onDisableFunction = function(self) + Details:SendEvent("HIDE", self.__parent) if (bit.band(self.__parent.__options, DETAILSPLUGIN_ALWAYSENABLED) == 0) then self.__parent.Enabled = false end end - local BuildDefaultStatusBarMembers = function(self) + local buildDefaultStatusBarMembers = function(self) self.childs = {} self.__index = self function self:Setup() - _detalhes.StatusBar:OpenOptionsForChild (self) + Details.StatusBar:OpenOptionsForChild(self) end end - + local temp_event_function = function() print("=====================") print("Hello There plugin developer!") print("Please make sure you are declaring") print("A member called 'OnDetailsEvent' on your plugin object") print("With a function to receive the events like bellow:") - print("function PluginObject:OnDetailsEvent (event, ...) end") + print("function PluginObject:OnDetailsEvent(event, ...) end") print("Thank You Sir!===================") end - local register_event_func = function(self, event) + local registerEventFunc = function(self, event) self.Frame:RegisterEvent(event) end - local unregister_event_func = function(self, event) - self.Frame:UnregisterEvent (event) - end - - function _detalhes:NewPluginObject (FrameName, PluginOptions, PluginType) - PluginOptions = PluginOptions or 0x0 - local NewPlugin = {__options = PluginOptions, __enabled = true, RegisterEvent = register_event_func, UnregisterEvent = unregister_event_func} - - local Frame = CreateFrame("Frame", FrameName, UIParent,"BackdropTemplate") - Frame:RegisterEvent("PLAYER_LOGIN") - Frame:RegisterEvent("PLAYER_LOGOUT") - - Frame:SetScript("OnEvent", function(self, event, ...) - if (NewPlugin.OnEvent) then + local unregisterEventFunc = function(self, event) + self.Frame:UnregisterEvent(event) + end + + ---@param frameName string + ---@param pluginFlag number + ---@param pluginType plugintype + function Details:NewPluginObject(frameName, pluginFlag, pluginType) + pluginFlag = pluginFlag or 0x0 + local newPluginObject = {__options = pluginFlag, __enabled = true, RegisterEvent = registerEventFunc, UnregisterEvent = unregisterEventFunc} + + local pluginFrame = CreateFrame("Frame", frameName, UIParent, "BackdropTemplate") + pluginFrame:RegisterEvent("PLAYER_LOGIN") + pluginFrame:RegisterEvent("PLAYER_LOGOUT") + pluginFrame:SetFrameStrata("HIGH") + pluginFrame:SetFrameLevel(6) + pluginFrame:Hide() + pluginFrame:SetScript("OnShow", onEnableFunction) + pluginFrame:SetScript("OnHide", onDisableFunction) + pluginFrame.__parent = newPluginObject + + pluginFrame:SetScript("OnEvent", function(self, event, ...) + if (newPluginObject.OnEvent) then if (event == "PLAYER_LOGIN") then - NewPlugin:OnEvent (self, "ADDON_LOADED", NewPlugin.Frame:GetName()) - NewPlugin.Frame:Hide() + newPluginObject:OnEvent(self, "ADDON_LOADED", newPluginObject.Frame:GetName()) + newPluginObject.Frame:Hide() return end - return NewPlugin:OnEvent (self, event, ...) + return newPluginObject:OnEvent(self, event, ...) end end) - - Frame:SetFrameStrata("HIGH") - Frame:SetFrameLevel(6) - Frame:Hide() - Frame.__parent = NewPlugin - - if (bit.band(PluginOptions, DETAILSPLUGIN_ALWAYSENABLED) ~= 0) then - NewPlugin.Enabled = true + if (bit.band(pluginFlag, DETAILSPLUGIN_ALWAYSENABLED) ~= 0) then + newPluginObject.Enabled = true else - NewPlugin.Enabled = false + newPluginObject.Enabled = false end - + --default members - if (PluginType == "STATUSBAR") then - BuildDefaultStatusBarMembers (NewPlugin) + if (pluginType == "STATUSBAR") then + buildDefaultStatusBarMembers(newPluginObject) end - - NewPlugin.Frame = Frame - - Frame:SetScript("OnShow", OnEnableFunction) - Frame:SetScript("OnHide", OnDisableFunction) - - --temporary details event function - NewPlugin.OnDetailsEvent = temp_event_function - - setmetatable(NewPlugin, _detalhes) - - return NewPlugin + + newPluginObject.Frame = pluginFrame + newPluginObject.OnDetailsEvent = temp_event_function + setmetatable(newPluginObject, Details) + + return newPluginObject end - function _detalhes:CreatePluginOptionsFrame (name, title, template) - + function Details:CreatePluginOptionsFrame(name, title, template) template = template or 1 - - if (template == 2) then - local options_frame = CreateFrame("frame", name, UIParent, "ButtonFrameTemplate,BackdropTemplate") - tinsert(UISpecialFrames, name) - options_frame:SetSize(500, 200) - - options_frame:SetScript("OnMouseDown", function(self, button) - if (button == "RightButton") then - if (self.moving) then - self.moving = false - self:StopMovingOrSizing() - end - return options_frame:Hide() - elseif (button == "LeftButton" and not self.moving) then - self.moving = true - self:StartMoving() - end - end) - options_frame:SetScript("OnMouseUp", function(self) - if (self.moving) then - self.moving = false - self:StopMovingOrSizing() - end - end) - - options_frame:SetMovable(true) - options_frame:EnableMouse(true) - options_frame:SetFrameStrata("DIALOG") - options_frame:SetToplevel(true) - - options_frame:Hide() - - options_frame:SetPoint("center", UIParent, "center") - --options_frame.TitleText:SetText(title) --10.0 fuck - --options_frame.portrait:SetTexture([[Interface\CHARACTERFRAME\TEMPORARYPORTRAIT-FEMALE-BLOODELF]]) - - return options_frame - - elseif (template == 1) then - - local options_frame = CreateFrame("frame", name, UIParent,"BackdropTemplate") - tinsert(UISpecialFrames, name) - options_frame:SetSize(500, 200) - options_frame:SetScript("OnMouseDown", function(self, button) + if (template == 2) then + local optionsFrame = CreateFrame("frame", name, UIParent, "ButtonFrameTemplate, BackdropTemplate") + table.insert(UISpecialFrames, name) + optionsFrame:SetSize(500, 200) + optionsFrame:SetMovable(true) + optionsFrame:EnableMouse(true) + optionsFrame:SetFrameStrata("DIALOG") + optionsFrame:SetToplevel(true) + optionsFrame:SetPoint("center", UIParent, "center") + optionsFrame:Hide() + + optionsFrame:SetScript("OnMouseDown", function(self, button) if (button == "RightButton") then - if (self.moving) then + if (self.moving) then self.moving = false self:StopMovingOrSizing() end - return options_frame:Hide() + return optionsFrame:Hide() elseif (button == "LeftButton" and not self.moving) then self.moving = true self:StartMoving() end end) - options_frame:SetScript("OnMouseUp", function(self) - if (self.moving) then + + optionsFrame:SetScript("OnMouseUp", function(self) + if (self.moving) then self.moving = false self:StopMovingOrSizing() end end) - - options_frame:SetMovable(true) - options_frame:EnableMouse(true) - options_frame:SetFrameStrata("DIALOG") - options_frame:SetToplevel(true) - - options_frame:Hide() - - options_frame:SetPoint("center", UIParent, "center") - - options_frame:SetBackdrop({bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16, + + return optionsFrame + + elseif (template == 1) then + local optionsFrame = CreateFrame("frame", name, UIParent, "BackdropTemplate") + table.insert(UISpecialFrames, name) + optionsFrame:SetSize(500, 200) + optionsFrame:SetMovable(true) + optionsFrame:EnableMouse(true) + optionsFrame:SetFrameStrata("DIALOG") + optionsFrame:SetToplevel(true) + optionsFrame:SetPoint("center", UIParent, "center", 0, 0) + optionsFrame:Hide() + + optionsFrame:SetScript("OnMouseDown", function(self, button) + if (button == "RightButton") then + if (self.moving) then + self.moving = false + self:StopMovingOrSizing() + end + return optionsFrame:Hide() + elseif (button == "LeftButton" and not self.moving) then + self.moving = true + self:StartMoving() + end + end) + + optionsFrame:SetScript("OnMouseUp", function(self) + if (self.moving) then + self.moving = false + self:StopMovingOrSizing() + end + end) + + optionsFrame:SetBackdrop({bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16, edgeFile = [[Interface\AddOns\Details\images\border_2]], edgeSize = 32, insets = {left = 1, right = 1, top = 1, bottom = 1}}) - options_frame:SetBackdropColor(0, 0, 0, .7) + optionsFrame:SetBackdropColor(0, 0, 0, .7) - Details.gump:ApplyStandardBackdrop(options_frame) - Details.gump:CreateTitleBar (options_frame, title) + detailsFramework:ApplyStandardBackdrop(optionsFrame) + detailsFramework:CreateTitleBar(optionsFrame, title) - local bigdog = _detalhes.gump:NewImage(options_frame, [[Interface\MainMenuBar\UI-MainMenuBar-EndCap-Human]], 110, 120, nil, {1, 0, 0, 1}, "backgroundBigDog", "$parentBackgroundBigDog") - bigdog:SetPoint("bottomright", options_frame, "bottomright", -3, 0) - bigdog:SetAlpha(.25) - - return options_frame + local bigDogTexture = detailsFramework:NewImage(optionsFrame, [[Interface\MainMenuBar\UI-MainMenuBar-EndCap-Human]], 110, 120, nil, {1, 0, 0, 1}, "backgroundBigDog", "$parentBackgroundBigDog") + bigDogTexture:SetPoint("bottomright", optionsFrame, "bottomright", -3, 0) + bigDogTexture:SetAlpha(.25) + + return optionsFrame end end - function _detalhes:CreatePluginWindowContainer() + function Details:CreatePluginWindowContainer() + local pluginContainerFrame = CreateFrame("frame", "DetailsPluginContainerWindow", UIParent, "BackdropTemplate") + pluginContainerFrame:EnableMouse(true) + pluginContainerFrame:SetMovable(true) + pluginContainerFrame:SetPoint("center", UIParent, "center", 0, 0) + pluginContainerFrame:SetBackdrop(Details.PluginDefaults and Details.PluginDefaults.Backdrop or {bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16, edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1}) + pluginContainerFrame:SetBackdropColor(0, 0, 0, 0.3) + pluginContainerFrame:SetBackdropBorderColor(0, 0, 0, 1) + table.insert(UISpecialFrames, "DetailsPluginContainerWindow") - local f = CreateFrame("frame", "DetailsPluginContainerWindow", UIParent,"BackdropTemplate") - f:EnableMouse(true) - f:SetMovable(true) - f:SetPoint("center", UIParent, "center") - f:SetBackdrop(_detalhes.PluginDefaults and _detalhes.PluginDefaults.Backdrop or {bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16, edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1}) - f:SetBackdropColor(0, 0, 0, 0.3) - f:SetBackdropBorderColor(0, 0, 0, 1) - tinsert(UISpecialFrames, "DetailsPluginContainerWindow") - - - local scaleBar = DetailsFramework:CreateScaleBar(f, Details.options_window) + local scaleBar = DetailsFramework:CreateScaleBar(pluginContainerFrame, Details.options_window) scaleBar:SetFrameStrata("fullscreen") - f:SetScale(Details.options_window.scale) + pluginContainerFrame:SetScale(Details.options_window.scale) - f:Hide() + pluginContainerFrame:Hide() --members - f.MenuX = CONST_PLUGINWINDOW_MENU_X - f.MenuY = CONST_PLUGINWINDOW_MENU_Y - f.MenuButtonWidth = CONST_PLUGINWINDOW_MENU_WIDTH - f.MenuButtonHeight = CONST_PLUGINWINDOW_MENU_HEIGHT - f.FrameWidth = CONST_PLUGINWINDOW_WIDTH - f.FrameHeight = CONST_PLUGINWINDOW_HEIGHT - f.TitleHeight = 20 - - --store button references for the left menu - f.MenuButtons = {} - --store all plugins embed - f.EmbedPlugins = {} - + pluginContainerFrame.MenuX = CONST_PLUGINWINDOW_MENU_X + pluginContainerFrame.MenuY = CONST_PLUGINWINDOW_MENU_Y + pluginContainerFrame.MenuButtonWidth = CONST_PLUGINWINDOW_MENU_WIDTH + pluginContainerFrame.MenuButtonHeight = CONST_PLUGINWINDOW_MENU_HEIGHT + pluginContainerFrame.FrameWidth = CONST_PLUGINWINDOW_WIDTH + pluginContainerFrame.FrameHeight = CONST_PLUGINWINDOW_HEIGHT + pluginContainerFrame.TitleHeight = 20 + + --store button references for the left menu + pluginContainerFrame.MenuButtons = {} + --store all plugins embed + pluginContainerFrame.EmbedPlugins = {} + --lib window - f:SetSize(f.FrameWidth, f.FrameHeight) - local LibWindow = LibStub("LibWindow-1.1") - LibWindow.RegisterConfig(f, _detalhes.plugin_window_pos) - LibWindow.RestorePosition(f) - LibWindow.MakeDraggable(f) - LibWindow.SavePosition(f) - + pluginContainerFrame:SetSize(pluginContainerFrame.FrameWidth, pluginContainerFrame.FrameHeight) + local LibWindow = LibStub("LibWindow-1.1") + LibWindow.RegisterConfig(pluginContainerFrame, Details.plugin_window_pos) + LibWindow.RestorePosition(pluginContainerFrame) + LibWindow.MakeDraggable(pluginContainerFrame) + LibWindow.SavePosition(pluginContainerFrame) + --menu background - local menuBackground = CreateFrame("frame", "$parentMenuFrame", f, "BackdropTemplate") - DetailsFramework:ApplyStandardBackdrop(menuBackground) + local menuBackground = CreateFrame("frame", "$parentMenuFrame", pluginContainerFrame, "BackdropTemplate") + DetailsFramework:ApplyStandardBackdrop(menuBackground) --statusbar - local statusBar = CreateFrame("frame", nil, menuBackground,"BackdropTemplate") - statusBar:SetPoint("topleft", menuBackground, "bottomleft", 0, 1) - statusBar:SetPoint("topright", f, "bottomright", 0, 1) - statusBar:SetHeight(20) - statusBar:SetAlpha(1) + local statusBar = CreateFrame("frame", nil, menuBackground, "BackdropTemplate") + statusBar:SetPoint("topleft", menuBackground, "bottomleft", 0, 1) + statusBar:SetPoint("topright", pluginContainerFrame, "bottomright", 0, 1) + statusBar:SetHeight(20) + statusBar:SetAlpha(1) - DetailsFramework:BuildStatusbarAuthorInfo(statusBar) - DetailsFramework:ApplyStandardBackdrop(statusBar) + DetailsFramework:BuildStatusbarAuthorInfo(statusBar) + DetailsFramework:ApplyStandardBackdrop(statusBar) - local extraDarkTexture = statusBar:CreateTexture(nil, "background") - extraDarkTexture:SetAllPoints() - extraDarkTexture:SetColorTexture(.2, .2, .2, .8) + local extraDarkTexture = statusBar:CreateTexture(nil, "background") + extraDarkTexture:SetAllPoints() + extraDarkTexture:SetColorTexture(.2, .2, .2, .8) - -- - local right_click_to_back = _detalhes.gump:CreateLabel(statusBar, "right click to close", 10, "gray") - right_click_to_back:SetPoint("bottomright", statusBar, "bottomright", -1, 5) - right_click_to_back:SetAlpha(.4) + local rightClickToBackLabel = detailsFramework:CreateLabel(statusBar, "right click to close", 10, "gray") + rightClickToBackLabel:SetPoint("bottomright", statusBar, "bottomright", -1, 5) + rightClickToBackLabel:SetAlpha(.4) - --point - menuBackground:SetPoint("topright", f, "topleft", -2, 0) - menuBackground:SetPoint("bottomright", f, "bottomleft", -2, 0) - menuBackground:SetWidth(f.MenuButtonWidth + 6) - - local bigdog = _detalhes.gump:NewImage(menuBackground, [[Interface\MainMenuBar\UI-MainMenuBar-EndCap-Human]], 180*0.7, 200*0.7, "overlay", {0, 1, 0, 1}, "backgroundBigDog", "$parentBackgroundBigDog") - bigdog:SetPoint("bottomleft", custom_window, "bottomleft", 0, 1) - bigdog:SetAlpha(0.3) + menuBackground:SetPoint("topright", pluginContainerFrame, "topleft", -2, 0) + menuBackground:SetPoint("bottomright", pluginContainerFrame, "bottomleft", -2, 0) + menuBackground:SetWidth(pluginContainerFrame.MenuButtonWidth + 6) - local gradientBelowTheLine = DetailsFramework:CreateTexture(menuBackground, {gradient = "vertical", fromColor = {0, 0, 0, 0.45}, toColor = "transparent"}, 1, 95, "artwork", {0, 1, 0, 1}, "dogGradient") - gradientBelowTheLine:SetPoint("bottoms") + local bigDogTexture = detailsFramework:NewImage(menuBackground, [[Interface\MainMenuBar\UI-MainMenuBar-EndCap-Human]], 180*0.7, 200*0.7, "overlay", {0, 1, 0, 1}, "backgroundBigDog", "$parentBackgroundBigDog") + bigDogTexture:SetPoint("bottomleft", custom_window, "bottomleft", 0, 1) + bigDogTexture:SetAlpha(0.3) - local bigdogRow = menuBackground:CreateTexture(nil, "artwork") - bigdogRow:SetPoint("bottomleft", menuBackground, "bottomleft", 1, 1) - bigdogRow:SetPoint("bottomright", menuBackground, "bottomright", -1, 1) - bigdogRow:SetHeight(20) - bigdogRow:SetColorTexture(.5, .5, .5, .1) - bigdogRow:Hide() + local gradientBelowTheLine = DetailsFramework:CreateTexture(menuBackground, {gradient = "vertical", fromColor = {0, 0, 0, 0.45}, toColor = "transparent"}, 1, 95, "artwork", {0, 1, 0, 1}, "dogGradient") + gradientBelowTheLine:SetPoint("bottoms") + + local bigDogRowTexture = menuBackground:CreateTexture(nil, "artwork") + bigDogRowTexture:SetPoint("bottomleft", menuBackground, "bottomleft", 1, 1) + bigDogRowTexture:SetPoint("bottomright", menuBackground, "bottomright", -1, 1) + bigDogRowTexture:SetHeight(20) + bigDogRowTexture:SetColorTexture(.5, .5, .5, .1) + bigDogRowTexture:Hide() - -- --plugins menu title bar - local titlebar_plugins = CreateFrame("frame", nil, menuBackground,"BackdropTemplate") - 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}) - PixelUtil.SetPoint(titleLabel, "center", titlebar_plugins , "center", 0, 0) - PixelUtil.SetPoint(titleLabel, "top", titlebar_plugins , "top", 0, -5) - + local titleBarPlugins = CreateFrame("frame", nil, menuBackground, "BackdropTemplate") + PixelUtil.SetPoint(titleBarPlugins, "topleft", menuBackground, "topleft", 2, -3) + PixelUtil.SetPoint(titleBarPlugins, "topright", menuBackground, "topright", -2, -3) + titleBarPlugins:SetHeight(pluginContainerFrame.TitleHeight) + titleBarPlugins:SetBackdrop({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\AddOns\Details\images\background]], tileSize = 64, tile = true}) + titleBarPlugins:SetBackdropColor(.5, .5, .5, 1) + titleBarPlugins:SetBackdropBorderColor(0, 0, 0, 1) + + --title label + local titleBarPlugins_TitleLabel = detailsFramework:NewLabel(titleBarPlugins, titleBarPlugins, nil, "titulo", "Plugins", "GameFontHighlightLeft", 12, {227/255, 186/255, 4/255}) + PixelUtil.SetPoint(titleBarPlugins_TitleLabel, "center", titleBarPlugins , "center", 0, 0) + PixelUtil.SetPoint(titleBarPlugins_TitleLabel, "top", titleBarPlugins , "top", 0, -5) + --plugins menu title bar - local titlebar_tools = CreateFrame("frame", nil, menuBackground,"BackdropTemplate") - titlebar_tools:SetHeight(f.TitleHeight) - titlebar_tools:SetBackdrop({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\AddOns\Details\images\background]], tileSize = 64, tile = true}) - titlebar_tools:SetBackdropColor(.5, .5, .5, 1) - 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}) - PixelUtil.SetPoint(titleLabel, "center", titlebar_tools , "center", 0, 0) - PixelUtil.SetPoint(titleLabel, "top", titlebar_tools , "top", 0, -5) - - --scripts - f:SetScript("OnShow", function() - --check if the window isn't out of screen - C_Timer.After(1, function() - local right = f:GetRight() - if (right and right > GetScreenWidth() + 500) then - f:ClearAllPoints() - f:SetPoint("center", UIParent, "center", 0, 0) - LibWindow.SavePosition(f) - _detalhes:Msg("detected options panel out of screen, position has reset") - end - end) - end) - - f:SetScript("OnHide", function() - - end) - - f:SetScript("OnMouseDown", function(self, button) - if (button == "RightButton") then - f.ClosePlugin() + local titleBarTools = CreateFrame("frame", nil, menuBackground, "BackdropTemplate") + titleBarTools:SetHeight(pluginContainerFrame.TitleHeight) + titleBarTools:SetBackdrop({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\AddOns\Details\images\background]], tileSize = 64, tile = true}) + titleBarTools:SetBackdropColor(.5, .5, .5, 1) + titleBarTools:SetBackdropBorderColor(0, 0, 0, 1) + + --title label + local titleBarTools_TitleLabel = detailsFramework:NewLabel(titleBarTools, titleBarTools, nil, "titulo", "Tools", "GameFontHighlightLeft", 12, {227/255, 186/255, 4/255}) + PixelUtil.SetPoint(titleBarTools_TitleLabel, "center", titleBarTools , "center", 0, 0) + PixelUtil.SetPoint(titleBarTools_TitleLabel, "top", titleBarTools , "top", 0, -5) + + --check if the window isn't out of screen + pluginContainerFrame:SetScript("OnShow", function() + C_Timer.After(1, function() + local right = pluginContainerFrame:GetRight() + if (right and right > GetScreenWidth() + 500) then + pluginContainerFrame:ClearAllPoints() + pluginContainerFrame:SetPoint("center", UIParent, "center", 0, 0) + LibWindow.SavePosition(pluginContainerFrame) + Details:Msg("detected options panel out of screen, position has reset") end end) - - f.Debug = false - function f.DebugMsg (...) - if (f.Debug) then - print("[Details! Debug]", ...) - end + end) + + pluginContainerFrame:SetScript("OnHide", function() + end) + + pluginContainerFrame:SetScript("OnMouseDown", function(self, button) + if (button == "RightButton") then + pluginContainerFrame.ClosePlugin() end - + end) - - function f.OnMenuClick (_, _, pluginAbsName, callRefresh) + pluginContainerFrame.Debug = false + function pluginContainerFrame.DebugMsg(...) + if (pluginContainerFrame.Debug) then + print("[Details! Debug]", ...) + end + end - --get the plugin - local pluginObject = _detalhes:GetPlugin (pluginAbsName) + local getPluginObject = function(pluginAbsoluteName) + local pluginObject = Details:GetPlugin(pluginAbsoluteName) if (not pluginObject) then - for index, plugin in ipairs(f.EmbedPlugins) do - if (plugin.real_name == pluginAbsName) then + for index, plugin in ipairs(pluginContainerFrame.EmbedPlugins) do + if (plugin.real_name == pluginAbsoluteName) then pluginObject = plugin end end - + if (not pluginObject) then - f.DebugMsg ("Plugin not found") + pluginContainerFrame.DebugMsg("Plugin not found") return end end + return pluginObject + end - --hide or show plugin windows - for index, plugin in ipairs(f.EmbedPlugins) do - if (plugin ~= pluginObject) then + local hideOtherPluginFrames = function(pluginObject) + for index, thisPluginObject in ipairs(pluginContainerFrame.EmbedPlugins) do + if (thisPluginObject ~= pluginObject) then --hide this plugin - if (plugin.Frame:IsShown()) then - plugin.Frame:Hide() + if (thisPluginObject.Frame:IsShown()) then + thisPluginObject.Frame:Hide() end end end + end + local highlightPluginButton = function(pluginAbsoluteName) + for index, button in ipairs(pluginContainerFrame.MenuButtons) do + button:Show() + + if (button.PluginAbsName == pluginAbsoluteName) then + button:SetTemplate(detailsFramework:GetTemplate("button", "DETAILS_PLUGINPANEL_BUTTONSELECTED_TEMPLATE")) + else + button:SetTemplate(detailsFramework:GetTemplate("button", "DETAILS_PLUGINPANEL_BUTTON_TEMPLATE")) + end + end + end + + local highlightPluginButtonOnBreakdownWindow = function(pluginAbsoluteName) + ---@type breakdownwindow + local breakdownWindowFrame = Details.BreakdownWindowFrame + + for index, button in ipairs(breakdownWindowFrame.RegisteredPluginButtons) do + ---@cast button df_button + button:Show() + + if (button.PluginAbsName == pluginAbsoluteName) then + button:SetTemplate(detailsFramework:GetTemplate("button", "DETAILS_PLUGINPANEL_BUTTONSELECTED_TEMPLATE")) + else + button:SetTemplate(detailsFramework:GetTemplate("button", "DETAILS_PLUGINPANEL_BUTTON_TEMPLATE")) + end + end + end + + function pluginContainerFrame.OnMenuClickFromBreakdownWindow(_, _, pluginAbsoluteName, callRefresh) + local pluginObject = getPluginObject(pluginAbsoluteName) + if (not pluginObject) then + return + end + + --hide other plugin windows + hideOtherPluginFrames(pluginObject) + + ---@type breakdownwindow + local breakdownWindowFrame = Details.BreakdownWindowFrame --re set the point of the frame within the main plugin window - f.RefreshFrame (pluginObject.__var_Frame) - C_Timer.After(0.016, function() - f.RefreshFrame (pluginObject.__var_Frame) + pluginContainerFrame.RefreshFrame(pluginObject.Frame, breakdownWindowFrame) + C_Timer.After(0, function() + pluginContainerFrame.RefreshFrame(pluginObject.Frame, breakdownWindowFrame) end) --show the plugin window @@ -595,20 +625,43 @@ end --highlight the plugin button on the menu - for index, button in ipairs(f.MenuButtons) do - button:Show() - - if (button.PluginAbsName == pluginAbsName) then - --emphatizate this button - button:SetTemplate(_detalhes.gump:GetTemplate("button", "DETAILS_PLUGINPANEL_BUTTONSELECTED_TEMPLATE")) - else - --make this button regular - button:SetTemplate(_detalhes.gump:GetTemplate("button", "DETAILS_PLUGINPANEL_BUTTON_TEMPLATE")) - end + highlightPluginButtonOnBreakdownWindow(pluginAbsoluteName) + + --check if the plugin has a callback for when showing the frame + if (pluginObject.__OnClickFromOptionsCallback) then + --safe run the plugin callback + DetailsFramework:QuickDispatch(pluginObject.__OnClickFromOptionsCallback) end + Details222.BreakdownWindow.OnShowPluginFrame(pluginObject) + return true + end + + function pluginContainerFrame.OnMenuClick(_, _, pluginAbsoluteName, callRefresh) + local pluginObject = getPluginObject(pluginAbsoluteName) + if (not pluginObject) then + return + end + + --hide other plugin windows + hideOtherPluginFrames(pluginObject) + + --re set the point of the frame within the main plugin window + pluginContainerFrame.RefreshFrame(pluginObject.__var_Frame) + C_Timer.After(0, function() + pluginContainerFrame.RefreshFrame(pluginObject.__var_Frame) + end) + + --show the plugin window + if (pluginObject.RefreshWindow and callRefresh) then + DetailsFramework:QuickDispatch(pluginObject.RefreshWindow) + end + + --highlight the plugin button on the menu + highlightPluginButton(pluginAbsoluteName) + --show the container - f:Show() + pluginContainerFrame:Show() --check if the plugin has a callback for when showing the frame if (pluginObject.__OnClickFromOptionsCallback) then @@ -618,67 +671,80 @@ return true end - - function f.CreatePluginMenuButton (pluginObject, isUtility) - --create the button - local newButton = _detalhes.gump:CreateButton(f, f.OnMenuClick, f.MenuButtonWidth, f.MenuButtonHeight, pluginObject.__name, pluginObject.real_name, true) + + ---create a button fro the plugin be selected in the options panel + ---@param self details + ---@param pluginObject any + ---@param bIsUtility any + ---@param parent frame + ---@param onClickFunc function + ---@param width number + ---@param height number + ---@return button + function Details:CreatePluginMenuButton(pluginObject, bIsUtility, parent, onClickFunc, width, height) + local newButton = detailsFramework:CreateButton(parent, onClickFunc, width, height, pluginObject.__name, pluginObject.real_name, true) newButton.PluginAbsName = pluginObject.real_name newButton.PluginName = pluginObject.__name - newButton.IsUtility = isUtility - - --add a template - newButton:SetTemplate(_detalhes.gump:GetTemplate("button", "DETAILS_PLUGINPANEL_BUTTON_TEMPLATE")) + newButton.IsUtility = bIsUtility + + newButton:SetTemplate(detailsFramework:GetTemplate("button", "DETAILS_PLUGINPANEL_BUTTON_TEMPLATE")) newButton:SetText(pluginObject.__name) newButton.textsize = 10 - - --set icon - newButton:SetIcon (pluginObject.__icon, nil, nil, nil, pluginObject.__iconcoords, pluginObject.__iconcolor, 4) - - --add it to menu table - tinsert(f.MenuButtons, newButton) - + newButton:SetIcon(pluginObject.__icon, nil, nil, nil, pluginObject.__iconcoords, pluginObject.__iconcolor, 4) + return newButton end - local on_hide = function(self) + local onHide = function(self) DetailsPluginContainerWindow.ClosePlugin() end - local setup_frame_functions = function(frame) + local setupFrameFunctions = function(frame) frame:SetScript("OnMouseDown", nil) frame:SetScript("OnMouseUp", nil) - --frame:SetScript("OnHide", on_hide) - frame:HookScript ("OnHide", on_hide) + frame:HookScript("OnHide", onHide) end - - function f.RefreshFrame (frame) + + function pluginContainerFrame.RefreshFrame(frame, parent) frame:EnableMouse(false) - frame:SetSize(f.FrameWidth, f.FrameHeight) + frame:SetSize(pluginContainerFrame.FrameWidth, pluginContainerFrame.FrameHeight) frame:ClearAllPoints() - PixelUtil.SetPoint(frame, "topleft", f, "topleft", 0, 0) + PixelUtil.SetPoint(frame, "topleft", parent or pluginContainerFrame, "topleft", 0, 0) + frame:SetParent(parent or pluginContainerFrame) frame:Show() end - --a plugin request to be embed into the main plugin window - function f.EmbedPlugin(pluginObject, frame, isUtility, callback) - + ---a plugin has request to be embed into the main plugin window + ---@param pluginObject table can be the plugin object or any frame + ---@param frame frame any frame + ---@param bIsUtility boolean if true, the plugin is in fact a regular panel in the options panel + ---@param callback function a callback to run when the plugin is clicked + function pluginContainerFrame.EmbedPlugin(pluginObject, frame, bIsUtility, callback) --check if the plugin has a frame if (not pluginObject.Frame) then - f.DebugMsg ("plugin doesn't have a frame.") + pluginContainerFrame.DebugMsg("plugin doesn't have a frame.") return end --create a button for this plugin - local newMenuButtom = f.CreatePluginMenuButton(pluginObject, isUtility) + local pluginButton = Details:CreatePluginMenuButton(pluginObject, bIsUtility, pluginContainerFrame, pluginContainerFrame.OnMenuClick, pluginContainerFrame.MenuButtonWidth, pluginContainerFrame.MenuButtonHeight) + --add it to menu table + table.insert(pluginContainerFrame.MenuButtons, pluginButton) - --utility is true when the object isn't a real plugin, but instead a tool frame from the main addon being embed on this panel - if (isUtility) then - pluginObject.__var_Utility = true - end pluginObject.__var_Frame = frame + --create a button to be hosted in the player breakdown window + if (not bIsUtility) then + local breakdownWindowFrame = Details.BreakdownWindowFrame + local breakdownButton = Details:CreatePluginMenuButton(pluginObject, bIsUtility, breakdownWindowFrame.BreakdownPluginSelectionFrame, pluginContainerFrame.OnMenuClickFromBreakdownWindow, pluginContainerFrame.MenuButtonWidth, pluginContainerFrame.MenuButtonHeight) + breakdownWindowFrame.RegisterPluginButton(breakdownButton) + else + --utility is true when the object isn't a real plugin, but instead a tool frame from the main addon being embed on this panel + pluginObject.__var_Utility = true + end + --sort buttons alphabetically, put utilities at the end - table.sort (f.MenuButtons, function(t1, t2) + table.sort(pluginContainerFrame.MenuButtons, function(t1, t2) if (t1.IsUtility and t2.IsUtility) then return t1.PluginName < t2.PluginName elseif (t1.IsUtility) then @@ -692,107 +758,100 @@ --reset the buttons points local addingTools = false - for index, button in ipairs(f.MenuButtons) do + for index, button in ipairs(pluginContainerFrame.MenuButtons) do button:ClearAllPoints() PixelUtil.SetPoint(button, "center", menuBackground, "center", 0, 0) if (button.IsUtility) then - --add -20 to add a gap between plugins and utilities - if (not addingTools) then --add the header addingTools = true - 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) + --add -20 to add a gap between plugins and utilities + PixelUtil.SetPoint(titleBarTools, "topleft", menuBackground, "topleft", 2, pluginContainerFrame.MenuY +((index-1) * -pluginContainerFrame.MenuButtonHeight ) - index - 20) + PixelUtil.SetPoint(titleBarTools, "topright", menuBackground, "topright", -2, pluginContainerFrame.MenuY +((index-1) * -pluginContainerFrame.MenuButtonHeight ) - index - 20) end - PixelUtil.SetPoint(button, "top", menuBackground, "top", 0, f.MenuY + ( (index-1) * -f.MenuButtonHeight ) - index - 40) + PixelUtil.SetPoint(button, "top", menuBackground, "top", 0, pluginContainerFrame.MenuY +((index-1) * -pluginContainerFrame.MenuButtonHeight ) - index - 40) else - PixelUtil.SetPoint(button, "top", menuBackground, "top", 0, f.MenuY + ( (index-1) * -f.MenuButtonHeight ) - index) + PixelUtil.SetPoint(button, "top", menuBackground, "top", 0, pluginContainerFrame.MenuY +((index-1) * -pluginContainerFrame.MenuButtonHeight ) - index) end end --format the plugin main frame - f.RefreshFrame(frame) - setup_frame_functions(frame) + pluginContainerFrame.RefreshFrame(frame) + setupFrameFunctions(frame) --save the callback function for when clicking in the button from the options panel pluginObject.__OnClickFromOptionsCallback = callback --add the plugin to embed table - tinsert(f.EmbedPlugins, pluginObject) - frame:SetParent(f) + table.insert(pluginContainerFrame.EmbedPlugins, pluginObject) + frame:SetParent(pluginContainerFrame) - f.DebugMsg("plugin added", pluginObject.__name) + pluginContainerFrame.DebugMsg("plugin added", pluginObject.__name) end - function f.OpenPlugin (pluginObject) - --just simulate a click on the menu button - f.OnMenuClick (_, _, pluginObject.real_name) + function pluginContainerFrame.OpenPlugin(pluginObject) + --simulate a click on the menu button + pluginContainerFrame.OnMenuClick(_, _, pluginObject.real_name) end - - function f.ClosePlugin() - --hide all embed plugins - for index, plugin in ipairs(f.EmbedPlugins) do + + ---hide all embed plugins + function pluginContainerFrame.ClosePlugin() + for index, plugin in ipairs(pluginContainerFrame.EmbedPlugins) do plugin.Frame:Hide() end --hide the main frame - f:Hide() + pluginContainerFrame:Hide() end - + --[=[ Function to be used on macros to open a plugin, signature: - Details:OpenPlugin (PLUGIN_ABSOLUTE_NAME) - Details:OpenPlugin (PluginObject) - Details:OpenPlugin ("Plugin Name") - - Example: /run Details:OpenPlugin ("Time Line") + Details:OpenPlugin(PLUGIN_ABSOLUTE_NAME) + Details:OpenPlugin(PluginObject) + Details:OpenPlugin("Plugin Name") + + Example: /run Details:OpenPlugin("Time Line") --]=] - - function _detalhes:OpenPlugin (wildcard) - local originalName = wildcard - - if (type(wildcard) == "string") then - + + ---function used when the user uses the macro command /run Details:OpenPlugin("Plugin Name") + ---@param wildCard any + ---@return any + function Details:OpenPlugin(wildCard) + local originalName = wildCard + + if (type(wildCard) == "string") then --check if passed a plugin absolute name - local pluginObject = _detalhes:GetPlugin (wildcard) + local pluginObject = Details:GetPlugin(wildCard) if (pluginObject) then - f.OpenPlugin (pluginObject) + pluginContainerFrame.OpenPlugin(pluginObject) return true end - + --check if passed a plugin name, remove spaces and make it lower case - wildcard = string.lower(wildcard) - wildcard = wildcard:gsub("%s", "") - - for index, pluginInfoTable in ipairs(_detalhes.ToolBar.Menu) do - local pluginName = pluginInfoTable [1] + wildCard = string.lower(wildCard) + wildCard = wildCard:gsub("%s", "") + + for index, pluginInfoTable in ipairs(Details.ToolBar.Menu) do + local pluginName = pluginInfoTable[1] pluginName = string.lower(pluginName) pluginName = pluginName:gsub("%s", "") - - if (pluginName == wildcard) then - local pluginObject = pluginInfoTable [3] - f.OpenPlugin (pluginObject) + + if (pluginName == wildCard) then + local pluginObject = pluginInfoTable[3] + pluginContainerFrame.OpenPlugin(pluginObject) return true end end - + --check if passed a plugin object - elseif (type(wildcard) == "table") then - if (wildcard.__name) then - f.OpenPlugin (wildcard) + elseif (type(wildCard) == "table") then + if (wildCard.__name) then + pluginContainerFrame.OpenPlugin(wildCard) return true end end - - Details:Msg("|cFFFF7700plugin not found|r:|cFFFFFF00", (originalName or wildcard), "|rcheck if it is enabled in the addons control panel.") --localize-me + + Details:Msg("|cFFFF7700plugin not found|r:|cFFFFFF00",(originalName or wildCard), "|rcheck if it is enabled in the addons control panel.") --localize-me end - - - end - - - - - ---stop auto complete: doe enda endb + end \ No newline at end of file diff --git a/core/plugins_statusbar.lua b/core/plugins_statusbar.lua index 995f21f4..6ba0a714 100644 --- a/core/plugins_statusbar.lua +++ b/core/plugins_statusbar.lua @@ -896,18 +896,20 @@ do --1 sec tick function Details:ClockPluginTick(force) for index, childObject in ipairs(Clock.childs) do + ---@type instance local instance = childObject.instance if (childObject.enabled and instance:IsEnabled()) then - if (instance.showing and ((instance:GetSegmentId() ~= DETAILS_SEGMENTID_OVERALL) or (instance:GetSegmentId() == DETAILS_SEGMENTID_OVERALL and not Details.in_combat) or force)) then - + ---@type combat + local combatObject = instance:GetCombat() + if (combatObject and ((instance:GetSegmentId() ~= DETAILS_SEGMENTID_OVERALL) or (instance:GetSegmentId() == DETAILS_SEGMENTID_OVERALL and not Details.in_combat) or force)) then local timeType = childObject.options.timeType if (timeType == 1) then - local combatTime = instance.showing:GetCombatTime() + local combatTime = combatObject:GetCombatTime() local minutos, segundos = math.floor(combatTime/60), math.floor(combatTime%60) childObject.text:SetText(minutos .. "m " .. segundos .. "s") elseif (timeType == 2) then - local combatTime = instance.showing:GetCombatTime() + local combatTime = combatObject:GetCombatTime() childObject.text:SetText(combatTime .. "s") elseif (timeType == 3) then @@ -922,7 +924,7 @@ do end local lastFight = Details:GetCombat(segmentId) - local currentCombatTime = instance.showing:GetCombatTime() + local currentCombatTime = combatObject:GetCombatTime() if (lastFight) then childObject.text:SetText(currentCombatTime - lastFight:GetCombatTime() .. "s") @@ -1016,7 +1018,8 @@ do Details:RegisterEvent(Clock, "COMBAT_PLAYER_LEAVE", Clock.PlayerLeaveCombat) Details:RegisterEvent(Clock, "DETAILS_INSTANCE_CHANGESEGMENT", Details.ClockPluginTickOnSegment) Details:RegisterEvent(Clock, "DETAILS_DATA_SEGMENTREMOVED", Details.ClockPluginTick) - Details:RegisterEvent(Clock, "DETAILS_DATA_RESET", Clock.DataReset) + Details:RegisterEvent(Clock, "DETAILS_DATA_RESET", Clock.PlayerLeaveCombat) + Details:RegisterEvent(Clock, "DETAILS_DATA_SEGMENTREMOVED", Clock.PlayerLeaveCombat) end ---------BUILT-IN THREAT PLUGIN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/frames/window_breakdown/breakdown_spells_genericframes.lua b/frames/window_breakdown/breakdown_spells_genericframes.lua index 59384c11..e999422a 100644 --- a/frames/window_breakdown/breakdown_spells_genericframes.lua +++ b/frames/window_breakdown/breakdown_spells_genericframes.lua @@ -12,5 +12,588 @@ local _GetSpellInfo = Details.GetSpellInfo local GameTooltip = GameTooltip local IsShiftKeyDown = IsShiftKeyDown local DF = DetailsFramework -local tinsert = tinsert +local tinsert = table.insert +local damageClass = Details.atributo_damage + +local spellsTab = DetailsSpellBreakdownTab +local headerContainerType = spellsTab.headerContainerType + +local CONST_BAR_HEIGHT = 20 +local CONST_SPELLSCROLL_LINEHEIGHT = 20 +local CONST_TARGET_TEXTURE = [[Interface\MINIMAP\TRACKING\Target]] +local CONST_SPELLBLOCK_DEFAULT_COLOR = {.4, .4, .4, 1} +local CONST_SPELLBLOCK_HEADERTEXT_COLOR = {.9, .8, 0, 1} +local CONST_SPELLBLOCK_HEADERTEXT_SIZE = 11 + +---onEnter function for the generic bars, set the alpha of the bar to one +---@param self breakdowngenericbar +local onEnterGenericBar = function(self) --~onenter ~genericbaronenter + self:SetAlpha(1) + + if (self.bIsFromLeftScroll) then + ---@type instance + local instanceObject = spellsTab.GetInstance() + local mainAttribute, subAttribute = instanceObject:GetDisplay() + + ---@type actordamage + local currentActor = spellsTab.GetActor() + + ---@type combat + local currentCombat = instanceObject:GetCombat() + + ---@type actorcontainer + local actorContainer = currentCombat:GetContainer(DETAILS_ATTRIBUTE_DAMAGE) + + if (mainAttribute == DETAILS_ATTRIBUTE_DAMAGE) then + if (subAttribute == DETAILS_SUBATTRIBUTE_DAMAGETAKEN) then + local aggressorActor = actorContainer:GetActor(self.actorName) + ---@type {topValue: number, data: {key1: spellid, key2: number, key3: actorname}[]} + local spellList = damageClass.BuildDamageTakenSpellListFromAgressor(currentActor, aggressorActor) + spellsTab.GenericScrollFrameRight:RefreshMe(spellList) + + elseif (subAttribute == DETAILS_SUBATTRIBUTE_FRIENDLYFIRE) then + --currentActor is the player which inflicted the damage to other players + --self.actorName is the name of the actor in the hovered bar + local spellList = damageClass.BuildFriendlySpellListFromAgressor(currentActor, self.actorName) + spellsTab.GenericScrollFrameRight:RefreshMe(spellList) + end + end + end + + --when hovered over, it need to detect which data is shown and call a function within a class to generate the data to show in the right scroll +end + +--onLeave function for the generic bars, set the alpha of the bar to 0.9 +---@param self breakdowngenericbar +local onLeaveGenericBar = function(self) --~onleave ~genericbaronleave + self:SetAlpha(0.9) +end + +---get a generic bar from the scroll box, if it doesn't exist, return nil +---@param scrollFrame table +---@param lineIndex number +---@return breakdownphasebar +local getGenericBar = function(scrollFrame, lineIndex) + ---@type breakdowngenericbar + local genericBar = scrollFrame:GetLine(lineIndex) + + --reset header alignment + genericBar:ResetFramesToHeaderAlignment() + + --reset columns, hiding them + genericBar.Icon:Hide() + for inLineIndex = 1, #genericBar.InLineTexts do + genericBar.InLineTexts[inLineIndex]:SetText("") + end + + return genericBar +end + +---@param scrollFrame table +---@param scrollData table +---@param offset number +---@param totalLines number +local refreshGenericRightScrollFunc = function(scrollFrame, scrollData, offset, totalLines) --~refreshgeneric ~refreshfunc ~refresh ~refreshg ~updategenericbar + local lineIndex = 1 + local combatTime = scrollData.combatTime + local totalValue = scrollData.totalValue + + for i = 1, totalLines do + local index = i + offset + local spellData = scrollData[index] + + if (spellData) then + local spellId = spellData.spellId + local spellTotal = spellData.total + local petName = spellData.petName + local spellSchool = spellData.spellScholl + + local spellName, _, spellIcon = _GetSpellInfo(spellId) + + --get a bar from the second generic scroll frame + local genericBar = getGenericBar(scrollFrame, i) + genericBar.statusBar:SetValue(spellTotal / scrollFrame.topValue * 100) + + local r, g, b = Details:GetSpellSchoolColor(spellSchool) + genericBar.statusBar:SetStatusBarColor(r, g, b, 1) + + ---@type number + local textIndex = 1 + + if (scrollData.headersAllowed.icon) then + ---@type texturetable + genericBar.Icon:Show() + genericBar.Icon:SetTexture(spellIcon) + genericBar.Icon:SetTexCoord(.1, .9, .1, .9) + genericBar.Icon:SetSize(CONST_SPELLSCROLL_LINEHEIGHT-2, CONST_SPELLSCROLL_LINEHEIGHT-2) + genericBar:AddFrameToHeaderAlignment(genericBar.Icon) + end + + if (scrollData.headersAllowed.rank) then + ---@type fontstring + local fontString = genericBar.InLineTexts[textIndex] + genericBar:AddFrameToHeaderAlignment(fontString) + fontString:SetText(index) + textIndex = textIndex + 1 + end + + if (scrollData.headersAllowed.name) then + ---@type fontstring + local fontString = genericBar.InLineTexts[textIndex] + genericBar:AddFrameToHeaderAlignment(fontString) + if (petName ~= "") then + --remove the owner name from the pet name + petName = petName:gsub((" <.*"), "") + spellName = spellName .. " (" .. petName .. ")" + end + fontString:SetText(spellName) + textIndex = textIndex + 1 + genericBar.actorName = spellName + end + + if (scrollData.headersAllowed.amount) then + ---@type fontstring + local fontString = genericBar.InLineTexts[textIndex] + genericBar:AddFrameToHeaderAlignment(fontString) + fontString:SetText(Details:Format(spellTotal)) + textIndex = textIndex + 1 + end + + if (scrollData.headersAllowed.persecond) then + ---@type fontstring + local fontString = genericBar.InLineTexts[textIndex] + genericBar:AddFrameToHeaderAlignment(fontString) + fontString:SetText(Details:Format(spellTotal / combatTime)) + textIndex = textIndex + 1 + end + + if (scrollData.headersAllowed.percent) then + ---@type fontstring + local fontString = genericBar.InLineTexts[textIndex] + genericBar:AddFrameToHeaderAlignment(fontString) + fontString:SetText(string.format("%.1f", spellTotal / totalValue * 100) .. "%") + textIndex = textIndex + 1 + end + + genericBar:Show() + + genericBar:AlignWithHeader(scrollFrame.Header, "left") + + lineIndex = lineIndex + 1 + if (lineIndex > totalLines) then + break + end + + --set the amount + --genericBar.InLineTexts[2]:SetText(Details:ToK(spellTotal)) + + --set the amount percent + --genericBar.InLineTexts[3]:SetText(Details:ToK(spellTotal / totalValue * 100)) + end + end +end + +---@param scrollFrame table +---@param scrollData table +---@param offset number +---@param totalLines number +local refreshGenericLeftScrollFunc = function(scrollFrame, scrollData, offset, totalLines) --~refreshgeneric ~refreshfunc ~refresh ~refreshg ~updategenericbar + local lineIndex = 1 + local combatTime = scrollData.combatTime + local totalValue = scrollData.totalValue + + for i = 1, totalLines do + local index = i + offset + local dataTable = scrollData[index] + + if (dataTable) then + local genericBar = getGenericBar(scrollFrame, lineIndex) + genericBar.statusBar:SetValue(dataTable.total / scrollFrame.topValue * 100) + + local spellSchool = dataTable.spellScholl + local className = dataTable.class + + if (spellSchool) then + local r, g, b = Details:GetSpellSchoolColor(spellSchool) + genericBar.statusBar:SetStatusBarColor(r, g, b, 1) + + else + local red, green, blue = Details:GetClassColor(className) + genericBar.statusBar:SetStatusBarColor(red, green, blue, 1) + end + + ---@type number + local textIndex = 1 + + if (scrollData.headersAllowed.icon) then + ---@type texturetable + local dataIcon = dataTable.icon + genericBar.Icon:Show() + genericBar.Icon:SetTexture(dataIcon.texture) + genericBar.Icon:SetTexCoord(dataIcon.coords.left, dataIcon.coords.right, dataIcon.coords.top, dataIcon.coords.bottom) + genericBar.Icon:SetSize(CONST_SPELLSCROLL_LINEHEIGHT-2, CONST_SPELLSCROLL_LINEHEIGHT-2) + genericBar:AddFrameToHeaderAlignment(genericBar.Icon) + end + + if (scrollData.headersAllowed.rank) then + ---@type fontstring + local fontString = genericBar.InLineTexts[textIndex] + genericBar:AddFrameToHeaderAlignment(fontString) + fontString:SetText(index) + textIndex = textIndex + 1 + end + + if (scrollData.headersAllowed.name) then + ---@type fontstring + local fontString = genericBar.InLineTexts[textIndex] + genericBar:AddFrameToHeaderAlignment(fontString) + local nameWithoutRealm = DF:RemoveRealmName(dataTable.name) + fontString:SetText(nameWithoutRealm or dataTable.name) + textIndex = textIndex + 1 + genericBar.actorName = dataTable.name + end + + if (scrollData.headersAllowed.amount) then + ---@type fontstring + local fontString = genericBar.InLineTexts[textIndex] + genericBar:AddFrameToHeaderAlignment(fontString) + fontString:SetText(Details:Format(dataTable.total)) + textIndex = textIndex + 1 + end + + if (scrollData.headersAllowed.persecond) then + ---@type fontstring + local fontString = genericBar.InLineTexts[textIndex] + genericBar:AddFrameToHeaderAlignment(fontString) + fontString:SetText(Details:Format(dataTable.total / combatTime)) + textIndex = textIndex + 1 + end + + if (scrollData.headersAllowed.percent) then + ---@type fontstring + local fontString = genericBar.InLineTexts[textIndex] + genericBar:AddFrameToHeaderAlignment(fontString) + fontString:SetText(string.format("%.1f", dataTable.total / totalValue * 100) .. "%") + textIndex = textIndex + 1 + end + + genericBar:AlignWithHeader(scrollFrame.Header, "left") + + lineIndex = lineIndex + 1 + if (lineIndex > totalLines) then + break + end + end + end +end + + +---create a genericbar within the generic scroll +---@param self breakdowngenericscrollframe +---@param index number +---@return breakdowngenericbar +local createGenericBar = function(self, index) --~create ~generic ~creategeneric ~genericbar + ---@type breakdowngenericbar + local genericBar = CreateFrame("button", self:GetName() .. "GenericBarButton" .. index, self) + genericBar.index = index + + --size and positioning + genericBar:SetHeight(CONST_SPELLSCROLL_LINEHEIGHT) + local y = (index-1) * CONST_SPELLSCROLL_LINEHEIGHT * -1 + (1 * -index) - 15 + genericBar:SetPoint("topleft", self, "topleft", 0, y) + genericBar:SetPoint("topright", self, "topright", 0, y) + + genericBar:EnableMouse(true) + + genericBar:SetAlpha(0.9) + genericBar:SetFrameStrata("HIGH") + genericBar:SetScript("OnEnter", onEnterGenericBar) + genericBar:SetScript("OnLeave", onLeaveGenericBar) + + DF:Mixin(genericBar, DF.HeaderFunctions) + + ---@type breakdownspellbarstatusbar + local statusBar = CreateFrame("StatusBar", "$parentStatusBar", genericBar) + statusBar:SetAllPoints() + statusBar:SetAlpha(0.8) + statusBar:SetMinMaxValues(0, 100) + statusBar:SetValue(50) + statusBar:EnableMouse(false) + statusBar:SetFrameLevel(genericBar:GetFrameLevel() - 1) + genericBar.statusBar = statusBar + + ---@type texture this is the statusbar texture + local statusBarTexture = statusBar:CreateTexture("$parentTexture", "artwork") + statusBarTexture:SetTexture(SharedMedia:Fetch("statusbar", "Details Hyanda")) + statusBar:SetStatusBarTexture(statusBarTexture) + statusBar:SetStatusBarColor(1, 1, 1, 1) + + ---@type texture shown when the mouse hoverover this bar + local hightlightTexture = statusBar:CreateTexture("$parentTextureHighlight", "highlight") + hightlightTexture:SetColorTexture(1, 1, 1, 0.2) + hightlightTexture:SetAllPoints() + statusBar.highlightTexture = hightlightTexture + + ---@type texture background texture + local backgroundTexture = statusBar:CreateTexture("$parentTextureBackground", "border") + backgroundTexture:SetAllPoints() + backgroundTexture:SetColorTexture(.05, .05, .05) + backgroundTexture:SetAlpha(1) + statusBar.backgroundTexture = backgroundTexture + + --create an icon + ---@type texture + local icon = statusBar:CreateTexture("$parentTexture", "overlay") + icon:SetPoint("left", statusBar, "left", 0, 0) + icon:SetSize(CONST_SPELLSCROLL_LINEHEIGHT-2, CONST_SPELLSCROLL_LINEHEIGHT-2) + icon:SetTexCoord(.1, .9, .1, .9) + genericBar.Icon = icon + + genericBar:AddFrameToHeaderAlignment(icon) + + genericBar.InLineTexts = {} + + for i = 1, 5 do + ---@type fontstring + local fontString = genericBar:CreateFontString("$parentFontString" .. i, "overlay", "GameFontHighlightSmall") + fontString:SetJustifyH("left") + fontString:SetTextColor(1, 1, 1, 1) + fontString:SetNonSpaceWrap(true) + fontString:SetWordWrap(false) + genericBar["lineText" .. i] = fontString + genericBar.InLineTexts[i] = fontString + fontString:SetTextColor(1, 1, 1, 1) + genericBar:AddFrameToHeaderAlignment(fontString) + end + + genericBar:AlignWithHeader(self.Header, "left") + + return genericBar +end + +---create two generic containers, these containers hold bars that can show any type of data +---an example is damage taken in the left container and the spells which caused the damage in the right container +---@param tabFrame tabframe +---@return breakdowngenericscrollframe, breakdowngenericscrollframe +function spellsTab.CreateGenericContainers(tabFrame) --~create ~generic ~creategenericcontainer ~creategenericscroll ~creategeneric + local defaultAmountOfLines = 50 + + --create a container for the scrollframe + local optionsLeftScroll = { + width = Details.breakdown_spell_tab.genericcontainer_width, + height = Details.breakdown_spell_tab.genericcontainer_height, + is_locked = Details.breakdown_spell_tab.genericcontainer_islocked, + can_move = false, + can_move_children = false, + use_top_resizer = true, + use_right_resizer = true, + use_bottom_resizer = true, + use_left_resizer = true, + } + + --create a container for the scrollframe + local optionsRightScroll = { + width = Details.breakdown_spell_tab.genericcontainer_right_width, + height = Details.breakdown_spell_tab.genericcontainer_right_height, + is_locked = Details.breakdown_spell_tab.genericcontainer_islocked, + can_move = false, + can_move_children = false, + use_top_resizer = true, + use_right_resizer = true, + use_bottom_resizer = true, + use_left_resizer = true, + } + + ---@type df_framecontainer + local leftContainer = DF:CreateFrameContainer(tabFrame, optionsLeftScroll, tabFrame:GetName() .. "GenericScrollContainerLeft") + leftContainer:SetPoint("topleft", tabFrame, "topleft", 0, 0) + leftContainer:SetFrameLevel(tabFrame:GetFrameLevel()+1) + spellsTab.GenericContainerFrameLeft = leftContainer + + ---@type df_framecontainer + local rightContainer = DF:CreateFrameContainer(tabFrame, optionsRightScroll, tabFrame:GetName() .. "GenericScrollContainerRight") + rightContainer:SetPoint("topleft", leftContainer, "topright", 30, 0) + rightContainer:SetFrameLevel(tabFrame:GetFrameLevel()+1) + spellsTab.GenericContainerFrameRight = rightContainer + + --when a setting is changed in the container, it will call this function, it is registered below with SetSettingChangedCallback() + local settingChangedCallbackFunction_Left = function(frameContainer, settingName, settingValue) + if (frameContainer:IsShown()) then + if (settingName == "height") then + ---@type number + local currentHeight = frameContainer.ScrollFrame:GetHeight() + Details.breakdown_spell_tab.genericcontainer_height = settingValue + frameContainer.ScrollFrame:SetNumFramesShown(math.floor(currentHeight / CONST_SPELLSCROLL_LINEHEIGHT) - 2) + + elseif (settingName == "width") then + Details.breakdown_spell_tab.genericcontainer_width = settingValue + + elseif (settingName == "is_locked") then + Details.breakdown_spell_tab.genericcontainer_islocked = settingValue + end + end + end + leftContainer:SetSettingChangedCallback(settingChangedCallbackFunction_Left) + + --when a setting is changed in the container, it will call this function, it is registered below with SetSettingChangedCallback() + local settingChangedCallbackFunction_Right = function(frameContainer, settingName, settingValue) + if (frameContainer:IsShown()) then + if (settingName == "height") then + ---@type number + local currentHeight = frameContainer.ScrollFrame:GetHeight() + Details.breakdown_spell_tab.genericcontainer_right_height = settingValue + frameContainer.ScrollFrame:SetNumFramesShown(math.floor(currentHeight / CONST_SPELLSCROLL_LINEHEIGHT) - 2) + + elseif (settingName == "width") then + Details.breakdown_spell_tab.genericcontainer_right_width = settingValue + + elseif (settingName == "is_locked") then + Details.breakdown_spell_tab.genericcontainer_islocked = settingValue + end + end + end + rightContainer:SetSettingChangedCallback(settingChangedCallbackFunction_Right) + + --create the left scrollframe + local genericScrollFrameLeft = DF:CreateScrollBox(leftContainer, "$parentGenericScrollLeft", refreshGenericLeftScrollFunc, {}, Details.breakdown_spell_tab.genericcontainer_width, Details.breakdown_spell_tab.genericcontainer_height, defaultAmountOfLines, CONST_SPELLSCROLL_LINEHEIGHT) + DF:ReskinSlider(genericScrollFrameLeft) + genericScrollFrameLeft:SetBackdrop({}) + genericScrollFrameLeft:SetAllPoints() + leftContainer:RegisterChildForDrag(genericScrollFrameLeft) + leftContainer.ScrollFrame = genericScrollFrameLeft + genericScrollFrameLeft.DontHideChildrenOnPreRefresh = false + tabFrame.GenericScrollFrameLeft = genericScrollFrameLeft + spellsTab.GenericScrollFrameLeft = genericScrollFrameLeft + + --create the right scrollframe + local genericScrollFrameRight = DF:CreateScrollBox(rightContainer, "$parentGenericScrollRight", refreshGenericRightScrollFunc, {}, Details.breakdown_spell_tab.genericcontainer_right_width, Details.breakdown_spell_tab.genericcontainer_right_height, defaultAmountOfLines, CONST_SPELLSCROLL_LINEHEIGHT) + DF:ReskinSlider(genericScrollFrameRight) + genericScrollFrameRight:SetBackdrop({}) + genericScrollFrameRight:SetAllPoints() + rightContainer:RegisterChildForDrag(genericScrollFrameRight) + rightContainer.ScrollFrame = genericScrollFrameRight + genericScrollFrameRight.DontHideChildrenOnPreRefresh = false + tabFrame.GenericScrollFrameRight = genericScrollFrameRight + spellsTab.GenericScrollFrameRight = genericScrollFrameRight + + function genericScrollFrameLeft:RefreshMe(data) --~refreshme (generic) ~refreshg + --get which column is currently selected and the sort order + local columnIndex, order, key = genericScrollFrameLeft.Header:GetSelectedColumn() + genericScrollFrameLeft.SortKey = key + + ---@type string + local keyToSort = key + + if (order == "DESC") then + table.sort(data, + function(t1, t2) + return t1[keyToSort] > t2[keyToSort] + end) + genericScrollFrameLeft.topValue = data[1] and data[1][keyToSort] or 0.00001 + else + table.sort(data, + function(t1, t2) + return t1[keyToSort] < t2[keyToSort] + end) + genericScrollFrameLeft.topValue = data[#data] and data[#data][keyToSort] or 0.00001 + end + + genericScrollFrameLeft:SetData(data) + genericScrollFrameLeft:Refresh() + + --clear the right scrollframe + genericScrollFrameRight:SetData({}) + genericScrollFrameRight:Refresh() + end + + function genericScrollFrameRight:RefreshMe(data) --~refreshme (generic) ~refreshg + --get which column is currently selected and the sort order + local columnIndex, order, key = genericScrollFrameRight.Header:GetSelectedColumn() + genericScrollFrameRight.SortKey = key + + ---@type string + local keyToSort = key + + if (order == "DESC") then + table.sort(data, + function(t1, t2) + return t1[keyToSort] > t2[keyToSort] + end) + genericScrollFrameRight.topValue = data[1] and data[1][keyToSort] or 0.00001 + else + table.sort(data, + function(t1, t2) + return t1[keyToSort] < t2[keyToSort] + end) + genericScrollFrameRight.topValue = data[#data] and data[#data][keyToSort] or 0.00001 + end + + genericScrollFrameRight:SetData(data) + genericScrollFrameRight:Refresh() + end + + --~header + local headerOptions = { + padding = 2, + header_height = 14, + + reziser_shown = true, + reziser_width = 2, + reziser_color = {.5, .5, .5, 0.7}, + reziser_max_width = 246, + + header_click_callback = spellsTab.OnAnyColumnHeaderClickCallback, + + header_backdrop_color = {0.1, 0.1, 0.1, 0.4}, + text_color = {1, 1, 1, 0.823}, + } + + local headerOptionsRight = { + padding = 2, + header_height = 14, + + reziser_shown = true, + reziser_width = 2, + reziser_color = {.5, .5, .5, 0.7}, + reziser_max_width = 210, + + header_click_callback = spellsTab.OnAnyColumnHeaderClickCallback, + + header_backdrop_color = {0.1, 0.1, 0.1, 0.4}, + text_color = {1, 1, 1, 0.823}, + } + + ---@type df_headerframe + local headerLeft = DetailsFramework:CreateHeader(leftContainer, spellsTab.genericContainerLeftColumnData, headerOptions) + headerLeft:SetPoint("topleft", genericScrollFrameLeft, "topleft", 0, 1) + headerLeft:SetColumnSettingChangedCallback(spellsTab.OnHeaderColumnOptionChanged) + genericScrollFrameLeft.Header = headerLeft + + ---@type df_headerframe + local headerRight = DetailsFramework:CreateHeader(rightContainer, spellsTab.genericContainerRightColumnData, headerOptionsRight) + headerRight:SetPoint("topleft", genericScrollFrameRight, "topleft", 0, 1) + headerRight:SetColumnSettingChangedCallback(spellsTab.OnHeaderColumnOptionChanged) + genericScrollFrameRight.Header = headerRight + + --cache the type of these headers + headerContainerType[headerLeft] = "generic_left" + headerContainerType[headerRight] = "generic_right" + + --create the scroll lines + for i = 1, defaultAmountOfLines do + local lineFrame = genericScrollFrameLeft:CreateLine(createGenericBar) + lineFrame.bIsFromLeftScroll = true + end + + --create the scroll lines + for i = 1, defaultAmountOfLines do + local lineFrame = genericScrollFrameRight:CreateLine(createGenericBar) + lineFrame:Hide() + lineFrame.bIsFromRightScroll = true + end + + --need to create the second scroll frame to show the details about the spelltable/actor hovered over + + return genericScrollFrameLeft, genericScrollFrameRight +end \ No newline at end of file diff --git a/frames/window_breakdown/breakdown_spells_phaseframes.lua b/frames/window_breakdown/breakdown_spells_phaseframes.lua new file mode 100644 index 00000000..eee80ba8 --- /dev/null +++ b/frames/window_breakdown/breakdown_spells_phaseframes.lua @@ -0,0 +1,396 @@ + +local addonName, Details222 = ... +local breakdownWindow = Details.BreakdownWindow +local Loc = LibStub("AceLocale-3.0"):GetLocale("Details") +local SharedMedia = LibStub:GetLibrary("LibSharedMedia-3.0") +local unpack = unpack +local GetTime = GetTime +local CreateFrame = CreateFrame +local GetSpellLink = GetSpellLink +local GetSpellInfo = GetSpellInfo +local _GetSpellInfo = Details.GetSpellInfo +local GameTooltip = GameTooltip +local IsShiftKeyDown = IsShiftKeyDown +local DF = DetailsFramework +local tinsert = table.insert + +local spellsTab = DetailsSpellBreakdownTab +local headerContainerType = spellsTab.headerContainerType + +local CONST_BAR_HEIGHT = 20 +local CONST_SPELLSCROLL_LINEHEIGHT = 20 +local CONST_TARGET_TEXTURE = [[Interface\MINIMAP\TRACKING\Target]] +local CONST_SPELLBLOCK_DEFAULT_COLOR = {.4, .4, .4, 1} +local CONST_SPELLBLOCK_HEADERTEXT_COLOR = {.9, .8, 0, 1} +local CONST_SPELLBLOCK_HEADERTEXT_SIZE = 11 + + +---create a targetbar within the target scroll +---@param self breakdownphasescrollframe +---@param index number +---@return breakdownphasebar +function spellsTab.CreatePhaseBar(self, index) --~create ~createphase ~phasebar + ---@type breakdownphasebar + local phaseBar = CreateFrame("button", self:GetName() .. "PhaseBarButton" .. index, self) + phaseBar.index = index + + --size and positioning + phaseBar:SetHeight(CONST_SPELLSCROLL_LINEHEIGHT) + local y = (index-1) * CONST_SPELLSCROLL_LINEHEIGHT * -1 + (1 * -index) - 15 + phaseBar:SetPoint("topleft", self, "topleft", 1, y) + phaseBar:SetPoint("topright", self, "topright", -1, y) + + phaseBar:EnableMouse(true) + + phaseBar:SetAlpha(0.823) + phaseBar:SetFrameStrata("HIGH") + phaseBar:SetScript("OnEnter", nil) + phaseBar:SetScript("OnLeave", nil) + + DF:Mixin(phaseBar, DF.HeaderFunctions) + + ---@type breakdownspellbarstatusbar + local statusBar = CreateFrame("StatusBar", "$parentStatusBar", phaseBar) + statusBar:SetAllPoints() + statusBar:SetAlpha(0.5) + statusBar:SetMinMaxValues(0, 100) + statusBar:SetValue(50) + statusBar:EnableMouse(false) + statusBar:SetFrameLevel(phaseBar:GetFrameLevel() - 1) + phaseBar.statusBar = statusBar + + ---@type texture this is the statusbar texture + local statusBarTexture = statusBar:CreateTexture("$parentTexture", "artwork") + statusBarTexture:SetTexture(SharedMedia:Fetch("statusbar", "Details Hyanda")) + statusBar:SetStatusBarTexture(statusBarTexture) + statusBar:SetStatusBarColor(1, 1, 1, 1) + + ---@type texture shown when the mouse hoverover this bar + local hightlightTexture = statusBar:CreateTexture("$parentTextureHighlight", "highlight") + hightlightTexture:SetColorTexture(1, 1, 1, 0.2) + hightlightTexture:SetAllPoints() + statusBar.highlightTexture = hightlightTexture + + ---@type texture background texture + local backgroundTexture = statusBar:CreateTexture("$parentTextureBackground", "border") + backgroundTexture:SetAllPoints() + backgroundTexture:SetColorTexture(.05, .05, .05) + backgroundTexture:SetAlpha(1) + statusBar.backgroundTexture = backgroundTexture + + --create an icon + ---@type texture + local icon = statusBar:CreateTexture("$parentTexture", "overlay") + icon:SetPoint("left", statusBar, "left", 0, 0) + icon:SetSize(CONST_SPELLSCROLL_LINEHEIGHT-2, CONST_SPELLSCROLL_LINEHEIGHT-2) + icon:SetTexCoord(.1, .9, .1, .9) + phaseBar.Icon = icon + + phaseBar:AddFrameToHeaderAlignment(icon) + + phaseBar.InLineTexts = {} + + for i = 1, 5 do + ---@type fontstring + local fontString = phaseBar:CreateFontString("$parentFontString" .. i, "overlay", "GameFontHighlightSmall") + fontString:SetJustifyH("left") + fontString:SetTextColor(1, 1, 1, 1) + fontString:SetNonSpaceWrap(true) + fontString:SetWordWrap(false) + phaseBar["lineText" .. i] = fontString + phaseBar.InLineTexts[i] = fontString + fontString:SetTextColor(1, 1, 1, 1) + phaseBar:AddFrameToHeaderAlignment(fontString) + end + + phaseBar:AlignWithHeader(self.Header, "left") + + return phaseBar +end + +---get a spell bar from the scroll box, if it doesn't exist, return nil +---@param scrollFrame table +---@param lineIndex number +---@return breakdownphasebar +local getPhaseBar = function(scrollFrame, lineIndex) + ---@type breakdownphasebar + local phaseBar = scrollFrame:GetLine(lineIndex) + + --reset header alignment + phaseBar:ResetFramesToHeaderAlignment() + + spellsTab.UpdateBarSettings(phaseBar) + + --reset columns, hiding them + phaseBar.Icon:Hide() + for inLineIndex = 1, #phaseBar.InLineTexts do + phaseBar.InLineTexts[inLineIndex]:SetText("") + end + + return phaseBar +end + +---@param scrollFrame table +---@param scrollData table +---@param offset number +---@param totalLines number +local refreshPhaseFunc = function(scrollFrame, scrollData, offset, totalLines) --~refreshphases ~refreshfunc ~refresh ~refreshp ~updatephasebar + local lineIndex = 1 + local formatFunc = Details:GetCurrentToKFunction() + local phaseElapsedTime = scrollData.phaseElapsed + + for i = 1, totalLines do + local index = i + offset + local dataTable = scrollData[index] + + if (dataTable) then + local phaseBar = getPhaseBar(scrollFrame, lineIndex) + + phaseBar.statusBar:SetValue(100) + + local totalDone = dataTable.amountDone + local phaseName = dataTable.phaseName + local phaseNameFormatted = "Phase: " .. phaseName + local amountDoneFormatted = formatFunc(nil, totalDone) + local positionWithInPhase = math.floor(dataTable.positionWithInPhase) + local percentDone = string.format("%.1f", dataTable.percentDone) + + local elapsedTime = phaseElapsedTime[phaseName] + local phaseDps = formatFunc(nil, totalDone / elapsedTime) + + phaseBar.Icon:Show() + phaseBar.Icon:SetTexture([[Interface\Garrison\orderhall-missions-mechanic9]]) + phaseBar.Icon:SetTexCoord(11/64, 53/64, 11/64, 53/64) + phaseBar.Icon:SetSize(CONST_SPELLSCROLL_LINEHEIGHT-2, CONST_SPELLSCROLL_LINEHEIGHT-2) + phaseBar:AddFrameToHeaderAlignment(phaseBar.Icon) + + for inLineIndex = 1, #phaseBar.InLineTexts do + phaseBar.InLineTexts[inLineIndex]:SetText("") + end + + local text1 = phaseBar.InLineTexts[1] + phaseBar:AddFrameToHeaderAlignment(text1) + text1:SetText(phaseNameFormatted) + + local text2 = phaseBar.InLineTexts[2] + phaseBar:AddFrameToHeaderAlignment(text2) + text2:SetText("#" .. positionWithInPhase) + + local text3 = phaseBar.InLineTexts[3] + phaseBar:AddFrameToHeaderAlignment(text3) + text3:SetText(amountDoneFormatted) + + local text4 = phaseBar.InLineTexts[4] + phaseBar:AddFrameToHeaderAlignment(text4) + text4:SetText(phaseDps) + + local text5 = phaseBar.InLineTexts[5] + phaseBar:AddFrameToHeaderAlignment(text5) + text5:SetText(percentDone .. "%") + + lineIndex = lineIndex + 1 + end + end +end + +---create a container to show value per phase +---@param tabFrame tabframe +---@return breakdownphasescrollframe +function spellsTab.CreatePhasesContainer(tabFrame) --~phase ~createphasecontainer ~createphasescroll + ---@type width + local width = Details.breakdown_spell_tab.phasecontainer_width + ---@type height + local height = Details.breakdown_spell_tab.phasecontainer_height + + local defaultAmountOfLines = 10 + + --create a container for the scrollframe + local options = { + width = Details.breakdown_spell_tab.phasecontainer_width, + height = Details.breakdown_spell_tab.phasecontainer_height, + is_locked = Details.breakdown_spell_tab.phasecontainer_islocked, + can_move = false, + can_move_children = false, + use_top_resizer = true, + use_right_resizer = true, + use_left_resizer = true, + use_bottom_resizer = true, + } + + ---@type df_framecontainer + local container = DF:CreateFrameContainer(tabFrame, options, tabFrame:GetName() .. "PhaseScrollContainer") + container:SetPoint("topleft", spellsTab.GetTargetScrollContainer(), "topright", 26, 0) + container:SetFrameLevel(tabFrame:GetFrameLevel() + 10) + spellsTab.PhaseContainerFrame = container + + local settingChangedCallbackFunction = function(frameContainer, settingName, settingValue) + if (frameContainer:IsShown()) then + if (settingName == "height") then + ---@type number + local currentHeight = spellsTab.GetPhaseScrollFrame():GetHeight() + Details.breakdown_spell_tab.phasecontainer_height = settingValue + local lineAmount = math.floor(currentHeight / CONST_SPELLSCROLL_LINEHEIGHT) + spellsTab.GetPhaseScrollFrame():SetNumFramesShown(lineAmount) + + elseif (settingName == "width") then + Details.breakdown_spell_tab.phasecontainer_width = settingValue + + elseif (settingName == "is_locked") then + Details.breakdown_spell_tab.phasecontainer_islocked = settingValue + end + end + end + container:SetSettingChangedCallback(settingChangedCallbackFunction) + + ---@type breakdownphasescrollframe not sure is this is correct + local phaseScrollFrame = DF:CreateScrollBox(container, "$parentPhaseScroll", refreshPhaseFunc, {}, width, height, defaultAmountOfLines, CONST_SPELLSCROLL_LINEHEIGHT) + DF:ReskinSlider(phaseScrollFrame) + + phaseScrollFrame:SetBackdrop({}) + phaseScrollFrame:SetAllPoints() + + container:RegisterChildForDrag(phaseScrollFrame) + + phaseScrollFrame.DontHideChildrenOnPreRefresh = false + tabFrame.PhaseScrollFrame = phaseScrollFrame + spellsTab.PhaseScrollFrame = phaseScrollFrame + + spellsTab.ApplyStandardBackdrop(container, phaseScrollFrame) + + function phaseScrollFrame:RefreshMe() --~refreshme (phases) ~refreshmep + --get the value of the top 1 ranking spell + ---@type actor + local actorObject = spellsTab.GetActor() + ---@type combat + local combatObject = spellsTab.GetCombat() + local actorName = actorObject:Name() + ---@type instance + local instanceObject = spellsTab.GetInstance() + + local mainAttribute = instanceObject:GetDisplay() + + local data = { + --playerObject = playerObject, + --attribute = attribute, + --combatObject = combatObject, + combatTime = combatObject:GetCombatTime(), + } + + local playerPhases = {} + local totalDamage = 0 + local phaseElapsed = {} + + local phasesInfo = combatObject:GetPhases() + + if (not phasesInfo) then + spellsTab.PhaseContainerFrame:Hide() + return + end + + if (#phasesInfo == 1) then + --if there's only one phase, then there's no need to show phases + spellsTab.PhaseContainerFrame:Hide() + return + else + spellsTab.PhaseContainerFrame:Show() + end + + if (#phasesInfo >= 1) then + --get phase elapsed time + for i = 1, #phasesInfo do + local thisPhase = phasesInfo[i] + local phaseName = thisPhase[1] + local startTime = thisPhase[2] + + local nextPhase = phasesInfo[i + 1] + if (nextPhase) then + --if there's a next phase, use it's start time as end time to calcule elapsed time + local endTime = nextPhase[2] + local elapsedTime = endTime - startTime + phaseElapsed[phaseName] = (phaseElapsed[phaseName] or 0) + elapsedTime + else + --if there's no next phase, use the combat end time as end time to calcule elapsed time + local endTime = combatObject:GetCombatTime() + local elapsedTime = endTime - startTime + phaseElapsed[phaseName] = (phaseElapsed[phaseName] or 0) + elapsedTime + end + end + + --get damage info + local dataTable = mainAttribute == 1 and phasesInfo.damage or phasesInfo.heal + for phaseName, playersTable in pairs(dataTable) do --each phase + local allPlayers = {} --all players for this phase + for playerName, amount in pairs(playersTable) do + tinsert(allPlayers, {playerName, amount}) + totalDamage = totalDamage + amount + end + table.sort(allPlayers, function(a, b) + return a[2] > b[2] + end) + + local myRank = 0 + for i = 1, #allPlayers do + if (allPlayers[i][1] == actorName) then + myRank = i + break + end + end + + tinsert(playerPhases, {phaseName, playersTable[actorName] or 0, myRank, (playersTable[actorName] or 0) / totalDamage * 100}) + end + end + + table.sort(playerPhases, function(a, b) return a[1] < b[1] end) + + for i = 1, #playerPhases do + data[#data+1] = { + phaseName = playerPhases[i][1], + amountDone = playerPhases[i][2], + positionWithInPhase = playerPhases[i][3], + percentDone = playerPhases[i][4], + } + end + + data.totalDamage = totalDamage + data.phaseElapsed = phaseElapsed + + phaseScrollFrame:SetData(data) + phaseScrollFrame:Refresh() + end + + --~header + local headerOptions = { + padding = 2, + header_height = 14, + + reziser_shown = true, + reziser_width = 2, + reziser_color = {.5, .5, .5, 0.7}, + reziser_max_width = 246, + + header_click_callback = spellsTab.OnAnyColumnHeaderClickCallback, + + header_backdrop_color = {0.1, 0.1, 0.1, 0.4}, + text_color = {1, 1, 1, 0.823}, + } + + ---@type df_headerframe + local header = DetailsFramework:CreateHeader(container, spellsTab.phaseContainerColumnData, headerOptions) + phaseScrollFrame.Header = header + phaseScrollFrame.Header:SetPoint("topleft", phaseScrollFrame, "topleft", 0, 1) + phaseScrollFrame.Header:SetColumnSettingChangedCallback(spellsTab.OnHeaderColumnOptionChanged) + + --cache the type of this container + headerContainerType[phaseScrollFrame.Header] = "phases" + + --create the scroll lines + for i = 1, defaultAmountOfLines do + phaseScrollFrame:CreateLine(spellsTab.CreatePhaseBar) + end + + tabFrame.phases = container:CreateFontString(nil, "overlay", "QuestFont_Large") + tabFrame.phases:SetPoint("bottomleft", container, "topleft", 2, 2) + tabFrame.phases:SetText("Phases:") --localize-me + + return phaseScrollFrame +end \ No newline at end of file diff --git a/frames/window_breakdown/breakdown_spells_spellframes.lua b/frames/window_breakdown/breakdown_spells_spellframes.lua index 656944c9..389d7a92 100644 --- a/frames/window_breakdown/breakdown_spells_spellframes.lua +++ b/frames/window_breakdown/breakdown_spells_spellframes.lua @@ -12,7 +12,7 @@ local _GetSpellInfo = Details.GetSpellInfo local GameTooltip = GameTooltip local IsShiftKeyDown = IsShiftKeyDown local DF = DetailsFramework -local tinsert = tinsert +local tinsert = table.insert local spellsTab = DetailsSpellBreakdownTab @@ -31,7 +31,7 @@ local spellBlockContainerSettings = { local headerContainerType = spellsTab.headerContainerType local formatPetName = function(petName, spellName, ownerName) - --petName is raw (with the owner name) + --remove the owner name from the pet name local petNameWithoutOwner = petName:gsub((" <.*"), "") local texture = [[Interface\AddOns\Details\images\classes_small]] @@ -557,7 +557,7 @@ function spellsTab.CreateSpellBlock(spellBlockContainer, index) --~breakdownspel Details.FadeHandler.Fader(spellBlock.overlay, 1) --hide --report button, also only shown when the spell block is hovered over - spellBlock.reportButton = Details.gump:NewDetailsButton(spellBlock, nil, nil, Details.Reportar, Details.playerDetailWindow, 10 + index, 16, 16, + spellBlock.reportButton = Details.gump:NewDetailsButton(spellBlock, nil, nil, Details.Reportar, Details.BreakdownWindowFrame, 10 + index, 16, 16, "Interface\\COMMON\\VOICECHAT-ON", "Interface\\COMMON\\VOICECHAT-ON", "Interface\\COMMON\\VOICECHAT-ON", "Interface\\COMMON\\VOICECHAT-ON", nil, "DetailsJanelaInfoReport1") Details.FadeHandler.Fader(spellBlock.reportButton, 1) --hide spellBlock.reportButton:SetScript("OnEnter", onEnterInfoReport) @@ -1146,7 +1146,6 @@ local refreshSpellsFunc = function(scrollFrame, scrollData, offset, totalLines) local headerTable = spellsTab.spellsHeaderData --todo: when swapping sort orders, close already expanded spells - local lineIndex = 1 for i = 1, totalLines do local index = i + offset diff --git a/frames/window_breakdown/breakdown_spells_targetframes.lua b/frames/window_breakdown/breakdown_spells_targetframes.lua index 7f230444..d8b1133a 100644 --- a/frames/window_breakdown/breakdown_spells_targetframes.lua +++ b/frames/window_breakdown/breakdown_spells_targetframes.lua @@ -12,4 +12,544 @@ local _GetSpellInfo = Details.GetSpellInfo local GameTooltip = GameTooltip local IsShiftKeyDown = IsShiftKeyDown local DF = DetailsFramework -local tinsert = tinsert \ No newline at end of file +local tinsert = table.insert + +local spellsTab = DetailsSpellBreakdownTab +local headerContainerType = spellsTab.headerContainerType + +local CONST_BAR_HEIGHT = 20 +local CONST_SPELLSCROLL_LINEHEIGHT = 20 +local CONST_TARGET_TEXTURE = [[Interface\MINIMAP\TRACKING\Target]] +local CONST_SPELLBLOCK_DEFAULT_COLOR = {.4, .4, .4, 1} +local CONST_SPELLBLOCK_HEADERTEXT_COLOR = {.9, .8, 0, 1} +local CONST_SPELLBLOCK_HEADERTEXT_SIZE = 11 + +---get a target bar from the scroll box, if it doesn't exist, return nil +---@param scrollFrame table +---@param lineIndex number +---@return breakdowntargetbar +local getTargetBar = function(scrollFrame, lineIndex) + ---@type breakdowntargetbar + local targetBar = scrollFrame:GetLine(lineIndex) + + --reset header alignment + targetBar:ResetFramesToHeaderAlignment() + + spellsTab.UpdateBarSettings(targetBar) + + --reset columns, hiding them + targetBar.Icon:Hide() + for inLineIndex = 1, #targetBar.InLineTexts do + targetBar.InLineTexts[inLineIndex]:SetText("") + end + + return targetBar +end + + +---update a line using the data passed +---@param targetBar breakdowntargetbar +---@param index number spell position (from best to wrost) +---@param combatObject combat +---@param scrollFrame table +---@param headerTable table +---@param bkTargetData breakdowntargettable +---@param totalValue number +---@param topValue number the amount done of the first target, used to calculate the length of the statusbar +---@param sortKey string +local updateTargetBar = function(targetBar, index, combatObject, scrollFrame, headerTable, bkTargetData, totalValue, topValue, sortKey) --~target ~update ~targetbar ~updatetargetbar + --scrollFrame is defined as a table which is false, scrollFrame is a frame + + local textIndex = 1 + + for headerIndex = 1, #headerTable do + ---@type number + local value + + targetBar.bkTargetData = bkTargetData + value = bkTargetData.total + + ---@type number + local combatTime = combatObject:GetCombatTime() + + local actorContainer = combatObject:GetContainer(spellsTab.mainAttribute) + local targetActorObject = actorContainer:GetActor(bkTargetData.name) + + targetBar.statusBar.backgroundTexture:SetAlpha(Details.breakdown_spell_tab.spellbar_background_alpha) + + --statusbar size by percent + if (topValue > 0) then + targetBar.statusBar:SetValue(bkTargetData[sortKey] / topValue * 100) + else + targetBar.statusBar:SetValue(0) + end + + --statusbar color + targetBar.statusBar:SetStatusBarColor(1, 1, 1, 1) + targetBar.combatTime = combatTime + targetBar.actorName = bkTargetData.name + + ---@type fontstring + local text = targetBar.InLineTexts[textIndex] + local header = headerTable[headerIndex] + + if (header.name == "icon") then --ok + targetBar.Icon:Show() + + if (targetActorObject) then + Details.SetClassIcon(targetActorObject, targetBar.Icon, spellsTab.GetInstance(), targetActorObject:Class()) + else + targetBar.Icon:SetTexture([[Interface\AddOns\Details\images\classes_small_alpha]]) + ---@type {key1: number, key2: number, key3: number, key4: number} + local texCoords = Details.class_coords["ENEMY"] + targetBar.Icon:SetTexCoord(unpack(texCoords)) + end + + targetBar:AddFrameToHeaderAlignment(targetBar.Icon) + + elseif (header.name == "rank") then --ok + text:SetText(index) + targetBar:AddFrameToHeaderAlignment(text) + targetBar.rank = index + textIndex = textIndex + 1 + + elseif (header.name == "name") then --ok + local noRealmName = DF:RemoveRealmName(bkTargetData.name) + local noOwnerName = noRealmName:gsub((" <.*"), "") + text:SetText(noOwnerName) + targetBar.name = bkTargetData.name + targetBar:AddFrameToHeaderAlignment(text) + textIndex = textIndex + 1 + + elseif (header.name == "amount") then --ok + text:SetText(Details:Format(value)) + targetBar:AddFrameToHeaderAlignment(text) + textIndex = textIndex + 1 + + elseif (header.name == "percent") then --ok + targetBar.percent = value / totalValue * 100 --totalValue is nil + ---@type string + local percentFormatted = string.format("%.1f", targetBar.percent) .. "%" + text:SetText(percentFormatted) + + targetBar:AddFrameToHeaderAlignment(text) + textIndex = textIndex + 1 + + elseif (header.name == "overheal" and bkTargetData.overheal) then + if (bkTargetData.overheal > 0) then + local totalHeal = bkTargetData.overheal + value + text:SetText(string.format("%.1f", bkTargetData.overheal / totalHeal * 100) .. "%") + else + text:SetText("0%") + end + targetBar:AddFrameToHeaderAlignment(text) + textIndex = textIndex + 1 + + elseif (header.name == "absorbed") then + text:SetText(Details:Format(bkTargetData.absorbed or 0)) + targetBar:AddFrameToHeaderAlignment(text) + textIndex = textIndex + 1 + end + end + + targetBar:AlignWithHeader(scrollFrame.Header, "left") +end + +---refresh the data shown in the spells scroll box +---@param scrollFrame table +---@param scrollData breakdowntargettablelist +---@param offset number +---@param totalLines number +local refreshTargetsFunc = function(scrollFrame, scrollData, offset, totalLines) --~refresh ~target ~refreshtargets + ---@type number + local topValue = scrollFrame.topValue + ---@type number + local totalValue = scrollData.totalValue + ---@type actor + local actorObject = spellsTab.GetActor() + ---@type string + local actorName = actorObject:Name() + ---@type combat + local combatObject = spellsTab.GetCombat() + ---@type instance + local instanceObject = spellsTab.GetInstance() + + ---@type number + local mainAttribute = spellsTab.mainAttribute + + local sortKey = scrollFrame.SortKey + local headerTable = spellsTab.targetsHeaderData + + local lineIndex = 1 + + for i = 1, totalLines do + local index = i + offset + + ---@type breakdowntargettable + local bkTargetData = scrollData[index] + if (bkTargetData) then + ---called mainSpellBar because it is the line that shows the sum of all spells merged (if any) + ---@type breakdowntargetbar + local targetBar = getTargetBar(scrollFrame, lineIndex) + do + if (targetBar) then + lineIndex = lineIndex + 1 + updateTargetBar(targetBar, index, combatObject, scrollFrame, headerTable, bkTargetData, totalValue, topValue, sortKey) + end + end + + if (lineIndex > totalLines) then + break + end + end + end +end + + +---create the target container +---@param tabFrame tabframe +---@return breakdowntargetscrollframe +function spellsTab.CreateTargetContainer(tabFrame) --~create ~target ~createtargetcontainer ~createtargetscroll ~createtarget + ---@type width + local width = Details.breakdown_spell_tab.targetcontainer_width + ---@type height + local height = Details.breakdown_spell_tab.targetcontainer_height + + local defaultAmountOfLines = 50 + + --create a container for the scrollframe + local options = { + width = Details.breakdown_spell_tab.targetcontainer_width, + height = Details.breakdown_spell_tab.targetcontainer_height, + is_locked = Details.breakdown_spell_tab.targetcontainer_islocked, + can_move = false, + can_move_children = false, + use_top_resizer = true, + use_right_resizer = true, + } + + ---@type df_framecontainer + local container = DF:CreateFrameContainer(tabFrame, options, tabFrame:GetName() .. "TargetScrollContainer") + container:SetPoint("topleft", spellsTab.GetSpellScrollContainer(), "bottomleft", 0, -25) + container:SetFrameLevel(tabFrame:GetFrameLevel() + 10) + spellsTab.TargetsContainerFrame = container + + local settingChangedCallbackFunction = function(frameContainer, settingName, settingValue) + if (frameContainer:IsShown()) then + if (settingName == "height") then + ---@type number + local currentHeight = spellsTab.GetTargetScrollFrame():GetHeight() + Details.breakdown_spell_tab.targetcontainer_height = settingValue + --the -0.1 is the avoid the random fraction of 1.9999999990 to 2.0000000001 + local lineAmount = currentHeight / CONST_SPELLSCROLL_LINEHEIGHT - 0.1 + lineAmount = math.floor(lineAmount) + spellsTab.GetTargetScrollFrame():SetNumFramesShown(lineAmount) + + elseif (settingName == "width") then + Details.breakdown_spell_tab.targetcontainer_width = settingValue + + elseif (settingName == "is_locked") then + Details.breakdown_spell_tab.targetcontainer_islocked = settingValue + end + end + end + container:SetSettingChangedCallback(settingChangedCallbackFunction) + + --create the scrollframe similar to scrollframe used in the spellscrollframe + --replace this with a framework scrollframe + ---@type breakdowntargetscrollframe + local targetScrollFrame = DF:CreateScrollBox(container, "$parentTargetScroll", refreshTargetsFunc, {}, width, height, defaultAmountOfLines, CONST_SPELLSCROLL_LINEHEIGHT) + DF:ReskinSlider(targetScrollFrame) + targetScrollFrame:SetBackdrop({}) + targetScrollFrame:SetAllPoints() + + container:RegisterChildForDrag(targetScrollFrame) + + targetScrollFrame.DontHideChildrenOnPreRefresh = false + tabFrame.TargetScrollFrame = targetScrollFrame + spellsTab.TargetScrollFrame = targetScrollFrame + + spellsTab.ApplyStandardBackdrop(container, targetScrollFrame) + + ---@param data breakdowntargettablelist + function targetScrollFrame:RefreshMe(data) --~refreshme (targets) ~refreshmet + --get which column is currently selected and the sort order + local columnIndex, order, key = targetScrollFrame.Header:GetSelectedColumn() + targetScrollFrame.SortKey = key + + ---@type string + local keyToSort = key + + if (order == "DESC") then + table.sort(data, + function(t1, t2) + return t1[keyToSort] > t2[keyToSort] + end) + targetScrollFrame.topValue = data[1] and data[1][keyToSort] + else + table.sort(data, + function(t1, t2) + return t1[keyToSort] < t2[keyToSort] + end) + targetScrollFrame.topValue = data[#data] and data[#data][keyToSort] + end + + if (key == "overheal") then + data.totalValue = data.totalValueOverheal + end + --default: data.totalValue + --data.totalValueOverheal + + targetScrollFrame:SetData(data) + targetScrollFrame:Refresh() + end + + --~header + local headerOptions = { + padding = 2, + header_height = 14, + + reziser_shown = true, + reziser_width = 2, + reziser_color = {.5, .5, .5, 0.7}, + reziser_max_width = 246, + + header_click_callback = spellsTab.OnAnyColumnHeaderClickCallback, + + header_backdrop_color = {0.1, 0.1, 0.1, 0.4}, + text_color = {1, 1, 1, 0.823}, + } + + ---@type df_headerframe + local header = DetailsFramework:CreateHeader(container, spellsTab.targetContainerColumnData, headerOptions) + targetScrollFrame.Header = header + targetScrollFrame.Header:SetPoint("topleft", targetScrollFrame, "topleft", 0, 1) + targetScrollFrame.Header:SetColumnSettingChangedCallback(spellsTab.OnHeaderColumnOptionChanged) + + --cache the type of this container + headerContainerType[targetScrollFrame.Header] = "targets" + + --create the scroll lines + for i = 1, defaultAmountOfLines do + targetScrollFrame:CreateLine(spellsTab.CreateTargetBar) + end + + tabFrame.targets = targetScrollFrame:CreateFontString(nil, "overlay", "QuestFont_Large") + tabFrame.targets:SetPoint("bottomleft", container, "topleft", 2, 2) + tabFrame.targets:SetText(Loc ["STRING_TARGETS"] .. ":") + + return targetScrollFrame +end + + +---@param targetBar breakdowntargetbar +local onEnterBreakdownTargetBar = function(targetBar) + targetBar:SetAlpha(1) + + ---@type string @the name of the target + local targetName = targetBar.actorName + + Details:FormatCooltipForSpells() + GameCooltip:SetOwner(targetBar, "bottom", "top", 4, -5) + GameCooltip:SetOption("MinWidth", math.max(230, targetBar:GetWidth() * 0.98)) + + --build a list of spells which the target was hit by + local spellsSortedResult = {} + local total = 0 + + ---@type actor + local actorObject = spellsTab.GetActor() + + ---@type combat + local combatObject = spellsTab.GetCombat() + + ---@type instance + local instanceObject = spellsTab.GetInstance() + + ---@type number + local mainAttribute = instanceObject:GetDisplay() + + ---@type spellcontainer + local spellContainer = actorObject:GetSpellContainer("spell") + + local targetScrollFrame = spellsTab.GetTargetScrollFrame() + + ---@type number, string, string + local columnIndex, order, key = targetScrollFrame.Header:GetSelectedColumn() + + ---@type string the label shown at the top of the tooltip + local labelTooltipTitle = Loc ["STRING_DAMAGE_FROM"] + + local targetTableName = "targets" + if (mainAttribute == DETAILS_ATTRIBUTE_HEAL) then + if (key == "total") then + labelTooltipTitle = Loc ["STRING_HEALING_FROM"] + + elseif (key == "overheal") then + targetTableName = "targets_overheal" + labelTooltipTitle = Loc ["STRING_OVERHEALED"] + end + end + + --this part kinda belong top damage or healing class, shouldn't be here + + ---@type number, spelltable + for spellId, spellTable in spellContainer:ListActors() do + if (spellTable.isReflection) then + ---@type string, number + for spellTargetName in pairs(spellTable.targets) do + if (spellTargetName == targetName) then + for reflectedSpellId, reflectedAmount in pairs(spellTable.extra) do + local spellName, _, spellIcon = _GetSpellInfo(reflectedSpellId) + table.insert(spellsSortedResult, {reflectedSpellId, reflectedAmount, spellName .. " (|cFFCCBBBBreflected|r)", spellIcon}) + total = total + reflectedAmount + end + end + end + else + for spellTargetName, amount in pairs(spellTable[targetTableName]) do + if (spellTargetName == targetName) then + local spellName, _, spellIcon = _GetSpellInfo(spellId) + table.insert(spellsSortedResult, {spellId, amount, spellName, spellIcon}) + total = total + amount + end + end + end + end + + --add pets + local petArray = actorObject:GetPets() + for _, petName in ipairs(petArray) do + local petActorObject = combatObject(mainAttribute, petName) + if (petActorObject) then + ---@type spellcontainer + local petSpellContainer = petActorObject:GetSpellContainer("spell") + + ---@type number, spelltable + for spellId, spellTable in petSpellContainer:ListActors() do + for spellTargetName, amount in pairs(spellTable[targetTableName]) do + if (spellTargetName == targetName) then + local spellName, _, spellIcon = _GetSpellInfo(spellId) + table.insert(spellsSortedResult, {spellId, amount, spellName .. " (" .. petName:gsub((" <.*"), "") .. ")", spellIcon}) + total = total + amount + end + end + end + end + end + + table.sort(spellsSortedResult, Details.Sort2) + + --need to change is this is a healing + Details:AddTooltipSpellHeaderText(labelTooltipTitle .. ":", {1, 0.9, 0.0, 1}, 1, Details.tooltip_spell_icon.file, unpack(Details.tooltip_spell_icon.coords)) + Details:AddTooltipHeaderStatusbar(1, 1, 1, 1) + + ---@type tablesize + local iconSize = Details.tooltip.icon_size + ---@type tablecoords + local iconBorder = Details.tooltip.icon_border_texcoord + + local topValue = spellsSortedResult[1] and spellsSortedResult[1][2] + + if (topValue) then + for index, tabela in ipairs(spellsSortedResult) do + local spellId, amount, spellName, spellIcon = unpack(tabela) + if (amount < 1) then + break + end + GameCooltip:AddLine(spellName, Details:Format(amount) .. " (" .. string.format("%.1f", amount / total * 100) .. "%)") + GameCooltip:AddIcon(spellIcon, nil, nil, iconSize.W + 4, iconSize.H + 4, iconBorder.L, iconBorder.R, iconBorder.T, iconBorder.B) + Details:AddTooltipBackgroundStatusbar(false, amount / topValue * 100) + end + end + + GameCooltip:Show() +end + +---@param self breakdowntargetbar +local onLeaveBreakdownTargetBar = function(self) + self:SetAlpha(0.9) + GameCooltip:Hide() +end + +---create a targetbar within the target scroll +---@param self breakdowntargetscrollframe +---@param index number +---@return breakdowntargetbar +function spellsTab.CreateTargetBar(self, index) --~create ~target ~createtarget ~targetbar + ---@type breakdowntargetbar + local targetBar = CreateFrame("button", self:GetName() .. "TargetBarButton" .. index, self) + targetBar.index = index + + --size and positioning + targetBar:SetHeight(CONST_SPELLSCROLL_LINEHEIGHT) + local y = (index-1) * CONST_SPELLSCROLL_LINEHEIGHT * -1 + (1 * -index) - 15 + targetBar:SetPoint("topleft", self, "topleft", 1, y) + targetBar:SetPoint("topright", self, "topright", -1, y) + targetBar:EnableMouse(true) + + targetBar:SetAlpha(0.823) + targetBar:SetFrameStrata("HIGH") + targetBar:SetScript("OnEnter", onEnterBreakdownTargetBar) + targetBar:SetScript("OnLeave", onLeaveBreakdownTargetBar) + + DF:Mixin(targetBar, DF.HeaderFunctions) + + ---@type breakdownspellbarstatusbar + local statusBar = CreateFrame("StatusBar", "$parentStatusBar", targetBar) + statusBar:SetAllPoints() + statusBar:SetAlpha(0.5) + statusBar:SetMinMaxValues(0, 100) + statusBar:SetValue(50) + statusBar:EnableMouse(false) + statusBar:SetFrameLevel(targetBar:GetFrameLevel() - 1) + targetBar.statusBar = statusBar + + ---@type texture this is the statusbar texture + local statusBarTexture = statusBar:CreateTexture("$parentTexture", "artwork") + statusBarTexture:SetTexture(SharedMedia:Fetch("statusbar", "Details Hyanda")) + statusBar:SetStatusBarTexture(statusBarTexture) + statusBar:SetStatusBarColor(1, 1, 1, 1) + + ---@type texture shown when the mouse hoverover this bar + local hightlightTexture = statusBar:CreateTexture("$parentTextureHighlight", "highlight") + hightlightTexture:SetColorTexture(1, 1, 1, 0.2) + hightlightTexture:SetAllPoints() + statusBar.highlightTexture = hightlightTexture + + ---@type texture background texture + local backgroundTexture = statusBar:CreateTexture("$parentTextureBackground", "border") + backgroundTexture:SetAllPoints() + backgroundTexture:SetColorTexture(.05, .05, .05) + backgroundTexture:SetAlpha(1) + statusBar.backgroundTexture = backgroundTexture + + --create an icon + ---@type texture + local icon = statusBar:CreateTexture("$parentTexture", "overlay") + icon:SetPoint("left", statusBar, "left", 0, 0) + icon:SetSize(CONST_SPELLSCROLL_LINEHEIGHT-2, CONST_SPELLSCROLL_LINEHEIGHT-2) + icon:SetTexCoord(.1, .9, .1, .9) + targetBar.Icon = icon + + targetBar:AddFrameToHeaderAlignment(icon) + + targetBar.InLineTexts = {} + + for i = 1, 5 do + ---@type fontstring + local fontString = targetBar:CreateFontString("$parentFontString" .. i, "overlay", "GameFontHighlightSmall") + fontString:SetJustifyH("left") + fontString:SetTextColor(1, 1, 1, 1) + fontString:SetNonSpaceWrap(true) + fontString:SetWordWrap(false) + targetBar["lineText" .. i] = fontString + targetBar.InLineTexts[i] = fontString + fontString:SetTextColor(1, 1, 1, 1) + targetBar:AddFrameToHeaderAlignment(fontString) + end + + targetBar:AlignWithHeader(self.Header, "left") + + return targetBar +end \ No newline at end of file diff --git a/frames/window_breakdown/window_playerbreakdown.lua b/frames/window_breakdown/window_playerbreakdown.lua index 69745bb8..114339eb 100644 --- a/frames/window_breakdown/window_playerbreakdown.lua +++ b/frames/window_breakdown/window_playerbreakdown.lua @@ -3,13 +3,12 @@ local Details = _G.Details local Loc = _G.LibStub("AceLocale-3.0"):GetLocale ( "Details" ) local SharedMedia = _G.LibStub:GetLibrary("LibSharedMedia-3.0") local UIParent = UIParent -local gump = Details.gump local _ local addonName, Details222 = ... --remove warnings in the code local ipairs = ipairs -local tinsert = tinsert +local tinsert = table.insert local tremove = tremove local type = type local unpack = _G.unpack @@ -17,20 +16,26 @@ local PixelUtil = PixelUtil local UISpecialFrames = UISpecialFrames local CreateFrame = _G.CreateFrame local detailsFramework = DetailsFramework +local breakdownWindowFrame = Details.BreakdownWindowFrame -local subAttributes = Details.sub_atributos -local breakdownWindow = Details.playerDetailWindow +---@type button[] +breakdownWindowFrame.RegisteredPluginButtons = {} -local SummaryWidgets = {} -local CurrentTab = "Summary" +---register a plugin button to be shown in the breakdown window +---@param button button +function breakdownWindowFrame.RegisterPluginButton(button) + table.insert(breakdownWindowFrame.RegisteredPluginButtons, button) +end -local PLAYER_DETAILS_WINDOW_WIDTH = 890 -local PLAYER_DETAILS_WINDOW_HEIGHT = 574 +local PLAYER_DETAILS_WINDOW_WIDTH = 925 +local PLAYER_DETAILS_WINDOW_HEIGHT = 620 local PLAYER_DETAILS_STATUSBAR_HEIGHT = 20 local PLAYER_DETAILS_STATUSBAR_ALPHA = 1 +---@type button[] Details.player_details_tabs = {} -breakdownWindow.currentTabsInUse = {} +---@type button[] +breakdownWindowFrame.currentTabsInUse = {} Details222.BreakdownWindow.BackdropSettings = { backdrop = {edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true}, @@ -38,12 +43,63 @@ Details222.BreakdownWindow.BackdropSettings = { backdropbordercolor = {0, 0, 0, 0.7}, } +--create a base frame which will hold the scrollbox and plugin buttons +local breakdownSideMenu = CreateFrame("frame", "DetailsBreakdownLeftMenuFrame", breakdownWindowFrame, "BackdropTemplate") +breakdownWindowFrame.BreakdownSideMenuFrame = breakdownSideMenu + +--create a frame to hold plugin buttons +local pluginsFrame = CreateFrame("frame", "DetailsBreakdownLeftMenuPluginsFrame", breakdownSideMenu, "BackdropTemplate") +breakdownWindowFrame.BreakdownPluginSelectionFrame = pluginsFrame + +--create the frame to hold tab buttons +local tabButtonsFrame = CreateFrame("frame", "DetailsBreakdownTabsFrame", breakdownWindowFrame, "BackdropTemplate") +breakdownWindowFrame.BreakdownTabsFrame = tabButtonsFrame + +local summaryWidgets = {} +local currentTab = "Summary" +local subAttributes = Details.sub_atributos + +function Details222.BreakdownWindow.OnShowPluginFrame(pluginObject) + --need to selected the selected tab and hide its content + for index = 1, #Details.player_details_tabs do + local tabButton = Details.player_details_tabs[index] + tabButton.frame:Hide() + end + breakdownWindowFrame.BreakdownTabsFrame:Hide() + breakdownWindowFrame.shownPluginObject = pluginObject + + breakdownWindowFrame.classIcon:Hide() + breakdownWindowFrame.closeButton:Hide() + breakdownWindowFrame.actorName:Hide() + breakdownWindowFrame.attributeName:Hide() + breakdownWindowFrame.avatar:Hide() + breakdownWindowFrame.avatar_bg:Hide() + breakdownWindowFrame.avatar_attribute:Hide() + breakdownWindowFrame.avatar_nick:Hide() +end + +function Details222.BreakdownWindow.HidePluginFrame() + if (breakdownWindowFrame.shownPluginObject) then + breakdownWindowFrame.shownPluginObject.Frame:Hide() + breakdownWindowFrame.shownPluginObject = nil + end + + breakdownWindowFrame.classIcon:Show() + breakdownWindowFrame.closeButton:Show() + breakdownWindowFrame.actorName:Show() + breakdownWindowFrame.attributeName:Show() + breakdownWindowFrame.avatar:Show() + breakdownWindowFrame.avatar_bg:Show() + breakdownWindowFrame.avatar_attribute:Show() + breakdownWindowFrame.avatar_nick:Show() +end + ------------------------------------------------------------------------------------------------------------------------------ --self = instancia --jogador = classe_damage ou classe_heal function Details:GetBreakdownTabsInUse() - return breakdownWindow.currentTabsInUse + return breakdownWindowFrame.currentTabsInUse end function Details:GetBreakdownTabByName(tabName, tablePool) @@ -58,31 +114,33 @@ end --return the combat being used to show the data in the opened breakdown window function Details:GetCombatFromBreakdownWindow() - return breakdownWindow.instancia and breakdownWindow.instancia.showing + ---@type instance + local instance = breakdownWindowFrame.instancia + return instance:GetCombat() end ---return the window that requested to open the player breakdown window ---@return instance function Details:GetActiveWindowFromBreakdownWindow() - return breakdownWindow.instancia + return breakdownWindowFrame.instancia end --return if the breakdown window is showing damage or heal function Details:GetDisplayTypeFromBreakdownWindow() - return breakdownWindow.atributo, breakdownWindow.sub_atributo + return breakdownWindowFrame.atributo, breakdownWindowFrame.sub_atributo end --return the actor object in use by the breakdown window function Details:GetActorObjectFromBreakdownWindow() - return breakdownWindow.jogador + return breakdownWindowFrame.jogador end function Details:GetBreakdownWindow() - return Details.playerDetailWindow + return Details.BreakdownWindowFrame end function Details:IsBreakdownWindowOpen() - return breakdownWindow.ativo + return breakdownWindowFrame.ativo end ---open the breakdown window @@ -116,11 +174,14 @@ function Details:OpenBreakdownWindow(instanceObject, actorObject, bFromAttribute end --Details.info_jogador armazena o jogador que esta sendo mostrado na janela de detalhes - if (breakdownWindow.jogador and breakdownWindow.jogador == actorObject and instanceObject and breakdownWindow.atributo and mainAttribute == breakdownWindow.atributo and subAttribute == breakdownWindow.sub_atributo and not bIsRefresh) then - Details:CloseBreakdownWindow() --se clicou na mesma barra ent�o fecha a janela de detalhes - return + if (breakdownWindowFrame.jogador and breakdownWindowFrame.jogador == actorObject and instanceObject and breakdownWindowFrame.atributo and mainAttribute == breakdownWindowFrame.atributo and subAttribute == breakdownWindowFrame.sub_atributo and not bIsRefresh) then + if (not breakdownWindowFrame.shownPluginObject) then + Details:CloseBreakdownWindow() --clicked in the same player bar, close the window + return + end + end - elseif (not actorObject) then + if (not actorObject) then Details:CloseBreakdownWindow() return end @@ -129,115 +190,121 @@ function Details:OpenBreakdownWindow(instanceObject, actorObject, bFromAttribute Details.PlayerBreakdown.CreatePlayerListFrame() Details.PlayerBreakdown.CreateDumpDataFrame() - if (not breakdownWindow.bHasInitialized) then - local infoNumPoints = breakdownWindow:GetNumPoints() + --show the frame containing the tab buttons + breakdownWindowFrame.BreakdownTabsFrame:Show() + + --hide the plugin if any is shown + Details222.BreakdownWindow.HidePluginFrame() + + if (not breakdownWindowFrame.bHasInitialized) then + local infoNumPoints = breakdownWindowFrame:GetNumPoints() for i = 1, infoNumPoints do - local point1, anchorObject, point2, x, y = breakdownWindow:GetPoint(i) + local point1, anchorObject, point2, x, y = breakdownWindowFrame:GetPoint(i) if (not anchorObject) then - breakdownWindow:ClearAllPoints() + breakdownWindowFrame:ClearAllPoints() end end - breakdownWindow:SetUserPlaced(false) - breakdownWindow:SetDontSavePosition(true) + breakdownWindowFrame:SetUserPlaced(false) + breakdownWindowFrame:SetDontSavePosition(true) local okay, errorText = pcall(function() - breakdownWindow:SetPoint("center", UIParent, "center", 0, 0) + breakdownWindowFrame:SetPoint("center", UIParent, "center", 0, 0) end) if (not okay) then - breakdownWindow:ClearAllPoints() - breakdownWindow:SetPoint("center", UIParent, "center", 0, 0) + breakdownWindowFrame:ClearAllPoints() + breakdownWindowFrame:SetPoint("center", UIParent, "center", 0, 0) end - breakdownWindow.bHasInitialized = true + breakdownWindowFrame.bHasInitialized = true end - if (not breakdownWindow.RightSideBar) then + if (not breakdownWindowFrame.RightSideBar) then --breakdownWindow:CreateRightSideBar() end --todo: all portuguese keys to english - breakdownWindow.ativo = true --sinaliza o addon que a janela esta aberta - breakdownWindow.atributo = mainAttribute --instancia.atributo -> grava o atributo (damage, heal, etc) - breakdownWindow.sub_atributo = subAttribute --instancia.sub_atributo -> grava o sub atributo (damage done, dps, damage taken, etc) - breakdownWindow.jogador = actorObject --de qual jogador (objeto classe_damage) - breakdownWindow.instancia = instanceObject --salva a refer�ncia da inst�ncia que pediu o breakdownWindow - breakdownWindow.target_text = Loc ["STRING_TARGETS"] .. ":" - breakdownWindow.target_member = "total" - breakdownWindow.target_persecond = false - breakdownWindow.mostrando = nil + breakdownWindowFrame.ativo = true --sinaliza o addon que a janela esta aberta + breakdownWindowFrame.atributo = mainAttribute --instancia.atributo -> grava o atributo (damage, heal, etc) + breakdownWindowFrame.sub_atributo = subAttribute --instancia.sub_atributo -> grava o sub atributo (damage done, dps, damage taken, etc) + breakdownWindowFrame.jogador = actorObject --de qual jogador (objeto classe_damage) + breakdownWindowFrame.instancia = instanceObject --salva a refer�ncia da inst�ncia que pediu o breakdownWindow + breakdownWindowFrame.target_text = Loc ["STRING_TARGETS"] .. ":" + breakdownWindowFrame.target_member = "total" + breakdownWindowFrame.target_persecond = false + breakdownWindowFrame.mostrando = nil - local nome = breakdownWindow.jogador.nome --nome do jogador - local atributo_nome = subAttributes[breakdownWindow.atributo].lista [breakdownWindow.sub_atributo] .. " " .. Loc ["STRING_ACTORFRAME_REPORTOF"] --// nome do atributo // precisa ser o sub atributo correto??? + local playerName = breakdownWindowFrame.jogador:Name() + local atributo_nome = subAttributes[breakdownWindowFrame.atributo].lista [breakdownWindowFrame.sub_atributo] .. " " .. Loc ["STRING_ACTORFRAME_REPORTOF"] --// nome do atributo // precisa ser o sub atributo correto??? --removendo o nome da realm do jogador - if (nome:find("-")) then - nome = nome:gsub(("-.*"), "") + if (playerName:find("-")) then + playerName = playerName:gsub(("-.*"), "") end - if (breakdownWindow.instancia.atributo == 1 and breakdownWindow.instancia.sub_atributo == 6) then --enemy - atributo_nome = subAttributes [breakdownWindow.atributo].lista [1] .. " " .. Loc ["STRING_ACTORFRAME_REPORTOF"] + if (breakdownWindowFrame.instancia.atributo == 1 and breakdownWindowFrame.instancia.sub_atributo == 6) then --enemy + atributo_nome = subAttributes [breakdownWindowFrame.atributo].lista [1] .. " " .. Loc ["STRING_ACTORFRAME_REPORTOF"] end - breakdownWindow.actorName:SetText(nome) --found it - breakdownWindow.attributeName:SetText(atributo_nome) + breakdownWindowFrame.actorName:SetText(playerName) --found it + breakdownWindowFrame.attributeName:SetText(atributo_nome) local serial = actorObject.serial local avatar if (serial ~= "") then - avatar = NickTag:GetNicknameTable (serial) + avatar = NickTag:GetNicknameTable(serial) end - if (avatar and avatar [1]) then - breakdownWindow.actorName:SetText((not Details.ignore_nicktag and avatar [1]) or nome) + if (avatar and avatar[1]) then + breakdownWindowFrame.actorName:SetText((not Details.ignore_nicktag and avatar[1]) or playerName) end - if (avatar and avatar [2]) then - breakdownWindow.avatar:SetTexture(avatar [2]) - breakdownWindow.avatar_bg:SetTexture(avatar [4]) - if (avatar [5]) then - breakdownWindow.avatar_bg:SetTexCoord(unpack(avatar [5])) + if (avatar and avatar[2]) then + breakdownWindowFrame.avatar:SetTexture(avatar[2]) + breakdownWindowFrame.avatar_bg:SetTexture(avatar[4]) + if (avatar[5]) then + breakdownWindowFrame.avatar_bg:SetTexCoord(unpack(avatar[5])) end - if (avatar [6]) then - breakdownWindow.avatar_bg:SetVertexColor(unpack(avatar [6])) + if (avatar[6]) then + breakdownWindowFrame.avatar_bg:SetVertexColor(unpack(avatar[6])) end - breakdownWindow.avatar_nick:SetText(avatar [1] or nome) - breakdownWindow.avatar_attribute:SetText(atributo_nome) + breakdownWindowFrame.avatar_nick:SetText(avatar[1] or playerName) + breakdownWindowFrame.avatar_attribute:SetText(atributo_nome) - breakdownWindow.avatar_attribute:SetPoint("CENTER", breakdownWindow.avatar_nick, "CENTER", 0, 14) - breakdownWindow.avatar:Show() - breakdownWindow.avatar_bg:Show() - breakdownWindow.avatar_bg:SetAlpha(.65) - breakdownWindow.avatar_nick:Show() - breakdownWindow.avatar_attribute:Show() - breakdownWindow.actorName:Hide() - breakdownWindow.attributeName:Hide() + breakdownWindowFrame.avatar_attribute:SetPoint("CENTER", breakdownWindowFrame.avatar_nick, "CENTER", 0, 14) + breakdownWindowFrame.avatar:Show() + breakdownWindowFrame.avatar_bg:Show() + breakdownWindowFrame.avatar_bg:SetAlpha(.65) + breakdownWindowFrame.avatar_nick:Show() + breakdownWindowFrame.avatar_attribute:Show() + breakdownWindowFrame.actorName:Hide() + breakdownWindowFrame.attributeName:Hide() else - breakdownWindow.avatar:Hide() - breakdownWindow.avatar_bg:Hide() - breakdownWindow.avatar_nick:Hide() - breakdownWindow.avatar_attribute:Hide() + breakdownWindowFrame.avatar:Hide() + breakdownWindowFrame.avatar_bg:Hide() + breakdownWindowFrame.avatar_nick:Hide() + breakdownWindowFrame.avatar_attribute:Hide() - breakdownWindow.actorName:Show() - breakdownWindow.attributeName:Show() + breakdownWindowFrame.actorName:Show() + breakdownWindowFrame.attributeName:Show() end - breakdownWindow.attributeName:SetPoint("bottomleft", breakdownWindow.actorName, "topleft", 0, 2) + breakdownWindowFrame.attributeName:SetPoint("bottomleft", breakdownWindowFrame.actorName, "topleft", 0, 2) ---@type string - local actorClass = actorObject.classe --classe not registered because it should be renamed to english 'class' + local actorClass = actorObject:Class() if (not actorClass) then actorClass = "monster" end - breakdownWindow.classIcon:SetTexture("Interface\\AddOns\\Details\\images\\classes") --top left - breakdownWindow.SetClassIcon(actorObject, actorClass) + breakdownWindowFrame.classIcon:SetTexture("Interface\\AddOns\\Details\\images\\classes") --top left + breakdownWindowFrame.SetClassIcon(actorObject, actorClass) - Details.FadeHandler.Fader(breakdownWindow, 0) + Details.FadeHandler.Fader(breakdownWindowFrame, 0) Details:UpdateBreakdownPlayerList() Details:InitializeAurasTab() Details:InitializeCompareTab() @@ -247,7 +314,7 @@ function Details:OpenBreakdownWindow(instanceObject, actorObject, bFromAttribute local tabsReplaced = {} local tabReplacedAmount = 0 - Details:Destroy(breakdownWindow.currentTabsInUse) + Details:Destroy(breakdownWindowFrame.currentTabsInUse) for index = 1, #Details.player_details_tabs do local tab = Details.player_details_tabs[index] @@ -261,8 +328,8 @@ function Details:OpenBreakdownWindow(instanceObject, actorObject, bFromAttribute if (tab.replaces) then local attributeList = tab.replaces.attributes - if (attributeList[breakdownWindow.atributo]) then - if (attributeList[breakdownWindow.atributo][breakdownWindow.sub_atributo]) then + if (attributeList[breakdownWindowFrame.atributo]) then + if (attributeList[breakdownWindowFrame.atributo][breakdownWindowFrame.sub_atributo]) then local tabReplaced, tabIndex = Details:GetBreakdownTabByName(tab.replaces.tabNameToReplace, tabsShown) if (tabReplaced and tabIndex < index) then tabReplaced:Hide() @@ -271,8 +338,8 @@ function Details:OpenBreakdownWindow(instanceObject, actorObject, bFromAttribute tremove(tabsShown, tabIndex) tinsert(tabsShown, tabIndex, tab) - if (tabReplaced.tabname == breakdownWindow.selectedTab) then - breakdownWindow.selectedTab = tab.tabname + if (tabReplaced.tabname == breakdownWindowFrame.selectedTab) then + breakdownWindowFrame.selectedTab = tab.tabname end tabReplaced.replaced = true @@ -294,20 +361,20 @@ function Details:OpenBreakdownWindow(instanceObject, actorObject, bFromAttribute end tabsShown = newTabsShown - breakdownWindow.currentTabsInUse = newTabsShown + breakdownWindowFrame.currentTabsInUse = newTabsShown - breakdownWindow:ShowTabs() + breakdownWindowFrame:ShowTabs() Details222.BreakdownWindow.CurrentDefaultTab = nil local shownTab for index = 1, #tabsShown do local tabButton = tabsShown[index] - if (tabButton:condition(breakdownWindow.jogador, breakdownWindow.atributo, breakdownWindow.sub_atributo)) then + if (tabButton:condition(breakdownWindowFrame.jogador, breakdownWindowFrame.atributo, breakdownWindowFrame.sub_atributo)) then if (tabButton.IsDefaultTab) then Details222.BreakdownWindow.CurrentDefaultTab = tabButton end - if (breakdownWindow.selectedTab == tabButton.tabname) then + if (breakdownWindowFrame.selectedTab == tabButton.tabname) then tabButton:DoClick() tabButton:OnShowFunc() shownTab = tabButton @@ -323,17 +390,17 @@ function Details:OpenBreakdownWindow(instanceObject, actorObject, bFromAttribute end function Details:CloseBreakdownWindow() - if (breakdownWindow.ativo) then - Details.FadeHandler.Fader(breakdownWindow, 1) + if (breakdownWindowFrame.ativo) then + Details.FadeHandler.Fader(breakdownWindowFrame, 1) - breakdownWindow.ativo = false --sinaliza o addon que a janela esta agora fechada - breakdownWindow.jogador = nil - breakdownWindow.atributo = nil - breakdownWindow.sub_atributo = nil - breakdownWindow.instancia = nil + breakdownWindowFrame.ativo = false --sinaliza o addon que a janela esta agora fechada + breakdownWindowFrame.jogador = nil + breakdownWindowFrame.atributo = nil + breakdownWindowFrame.sub_atributo = nil + breakdownWindowFrame.instancia = nil - breakdownWindow.actorName:SetText("") - breakdownWindow.attributeName:SetText("") + breakdownWindowFrame.actorName:SetText("") + breakdownWindowFrame.attributeName:SetText("") --iterate all tabs and clear caches local tabsInUse = Details:GetBreakdownTabsInUse() @@ -345,32 +412,33 @@ function Details:CloseBreakdownWindow() end function Details.PlayerBreakdown.CreateDumpDataFrame() - breakdownWindow.dumpDataFrame = CreateFrame("frame", "$parentDumpTableFrame", DetailsBreakdownWindowPlayerScrollBox, "BackdropTemplate") - breakdownWindow.dumpDataFrame:SetPoint("topleft", DetailsBreakdownWindowPlayerScrollBox, "topleft", 0, 0) - breakdownWindow.dumpDataFrame:SetPoint("bottomright", DetailsBreakdownWindowPlayerScrollBox, "bottomright", 0, 0) - breakdownWindow.dumpDataFrame:SetFrameLevel(DetailsBreakdownWindowPlayerScrollBox:GetFrameLevel() + 10) - detailsFramework:ApplyStandardBackdrop(breakdownWindow.dumpDataFrame, true) - breakdownWindow.dumpDataFrame:Hide() + local playerSelectionScrollFrame = DetailsBreakdownWindowPlayerScrollBox + breakdownWindowFrame.dumpDataFrame = CreateFrame("frame", "$parentDumpTableFrame", playerSelectionScrollFrame, "BackdropTemplate") + breakdownWindowFrame.dumpDataFrame:SetPoint("topleft", playerSelectionScrollFrame, "topleft", 0, 0) + breakdownWindowFrame.dumpDataFrame:SetPoint("bottomright", playerSelectionScrollFrame, "bottomright", 0, 0) + breakdownWindowFrame.dumpDataFrame:SetFrameLevel(playerSelectionScrollFrame:GetFrameLevel() + 10) + detailsFramework:ApplyStandardBackdrop(breakdownWindowFrame.dumpDataFrame, true) + breakdownWindowFrame.dumpDataFrame:Hide() --create a details framework special lua editor - breakdownWindow.dumpDataFrame.luaEditor = detailsFramework:NewSpecialLuaEditorEntry(breakdownWindow.dumpDataFrame, 1, 1, "text", "$parentCodeEditorWindow") - breakdownWindow.dumpDataFrame.luaEditor:SetPoint("topleft", breakdownWindow.dumpDataFrame, "topleft", 2, -2) - breakdownWindow.dumpDataFrame.luaEditor:SetPoint("bottomright", breakdownWindow.dumpDataFrame, "bottomright", -2, 2) - breakdownWindow.dumpDataFrame.luaEditor:SetFrameLevel(breakdownWindow.dumpDataFrame:GetFrameLevel()+1) - breakdownWindow.dumpDataFrame.luaEditor:SetBackdrop({}) + breakdownWindowFrame.dumpDataFrame.luaEditor = detailsFramework:NewSpecialLuaEditorEntry(breakdownWindowFrame.dumpDataFrame, 1, 1, "text", "$parentCodeEditorWindow") + breakdownWindowFrame.dumpDataFrame.luaEditor:SetPoint("topleft", breakdownWindowFrame.dumpDataFrame, "topleft", 2, -2) + breakdownWindowFrame.dumpDataFrame.luaEditor:SetPoint("bottomright", breakdownWindowFrame.dumpDataFrame, "bottomright", -2, 2) + breakdownWindowFrame.dumpDataFrame.luaEditor:SetFrameLevel(breakdownWindowFrame.dumpDataFrame:GetFrameLevel()+1) + breakdownWindowFrame.dumpDataFrame.luaEditor:SetBackdrop({}) --hide the scroll bar DetailsBreakdownWindowPlayerScrollBoxDumpTableFrameCodeEditorWindowScrollBar:Hide() end -function breakdownWindow:CreateRightSideBar() --not enabled - breakdownWindow.RightSideBar = CreateFrame("frame", nil, breakdownWindow, "BackdropTemplate") - breakdownWindow.RightSideBar:SetWidth(20) - breakdownWindow.RightSideBar:SetPoint("topleft", breakdownWindow, "topright", 1, 0) - breakdownWindow.RightSideBar:SetPoint("bottomleft", breakdownWindow, "bottomright", 1, 0) +function breakdownWindowFrame:CreateRightSideBar() --not enabled + breakdownWindowFrame.RightSideBar = CreateFrame("frame", nil, breakdownWindowFrame, "BackdropTemplate") + breakdownWindowFrame.RightSideBar:SetWidth(20) + breakdownWindowFrame.RightSideBar:SetPoint("topleft", breakdownWindowFrame, "topright", 1, 0) + breakdownWindowFrame.RightSideBar:SetPoint("bottomleft", breakdownWindowFrame, "bottomright", 1, 0) local rightSideBarAlpha = 0.75 - detailsFramework:ApplyStandardBackdrop(breakdownWindow.RightSideBar) + detailsFramework:ApplyStandardBackdrop(breakdownWindowFrame.RightSideBar) local toggleMergePlayerSpells = function() Details.merge_player_abilities = not Details.merge_player_abilities @@ -380,11 +448,11 @@ function breakdownWindow:CreateRightSideBar() --not enabled Details:OpenBreakdownWindow(instanceObject, playerObject) end - local mergePlayerSpellsCheckbox = detailsFramework:CreateSwitch(breakdownWindow, toggleMergePlayerSpells, Details.merge_player_abilities, _, _, _, _, _, _, _, _, _, _, detailsFramework:GetTemplate("switch", "OPTIONS_CHECKBOX_BRIGHT_TEMPLATE")) + local mergePlayerSpellsCheckbox = detailsFramework:CreateSwitch(breakdownWindowFrame, toggleMergePlayerSpells, Details.merge_player_abilities, _, _, _, _, _, _, _, _, _, _, detailsFramework:GetTemplate("switch", "OPTIONS_CHECKBOX_BRIGHT_TEMPLATE")) mergePlayerSpellsCheckbox:SetAsCheckBox() - mergePlayerSpellsCheckbox:SetPoint("bottom", breakdownWindow.RightSideBar, "bottom", 0, 2) + mergePlayerSpellsCheckbox:SetPoint("bottom", breakdownWindowFrame.RightSideBar, "bottom", 0, 2) - local mergePlayerSpellsLabel = breakdownWindow.RightSideBar:CreateFontString(nil, "overlay", "GameFontNormal") + local mergePlayerSpellsLabel = breakdownWindowFrame.RightSideBar:CreateFontString(nil, "overlay", "GameFontNormal") mergePlayerSpellsLabel:SetText("Merge Player Spells") detailsFramework:SetFontRotation(mergePlayerSpellsLabel, 90) mergePlayerSpellsLabel:SetPoint("center", mergePlayerSpellsCheckbox.widget, "center", -6, mergePlayerSpellsCheckbox:GetHeight()/2 + mergePlayerSpellsLabel:GetStringWidth() / 2) @@ -398,11 +466,11 @@ function breakdownWindow:CreateRightSideBar() --not enabled Details:OpenBreakdownWindow(instanceObject, playerObject) --toggle Details:OpenBreakdownWindow(instanceObject, playerObject) end - local mergePetSpellsCheckbox = detailsFramework:CreateSwitch(breakdownWindow, toggleMergePetSpells, Details.merge_pet_abilities, _, _, _, _, _, _, _, _, _, _, detailsFramework:GetTemplate("switch", "OPTIONS_CHECKBOX_BRIGHT_TEMPLATE")) + local mergePetSpellsCheckbox = detailsFramework:CreateSwitch(breakdownWindowFrame, toggleMergePetSpells, Details.merge_pet_abilities, _, _, _, _, _, _, _, _, _, _, detailsFramework:GetTemplate("switch", "OPTIONS_CHECKBOX_BRIGHT_TEMPLATE")) mergePetSpellsCheckbox:SetAsCheckBox(true) - mergePetSpellsCheckbox:SetPoint("bottom", breakdownWindow.RightSideBar, "bottom", 0, 160) + mergePetSpellsCheckbox:SetPoint("bottom", breakdownWindowFrame.RightSideBar, "bottom", 0, 160) - local mergePetSpellsLabel = breakdownWindow.RightSideBar:CreateFontString(nil, "overlay", "GameFontNormal") + local mergePetSpellsLabel = breakdownWindowFrame.RightSideBar:CreateFontString(nil, "overlay", "GameFontNormal") mergePetSpellsLabel:SetText("Merge Pet Spells") detailsFramework:SetFontRotation(mergePetSpellsLabel, 90) mergePetSpellsLabel:SetPoint("center", mergePetSpellsCheckbox.widget, "center", -6, mergePetSpellsCheckbox:GetHeight()/2 + mergePetSpellsLabel:GetStringWidth() / 2) @@ -467,60 +535,60 @@ end ---set the class or spec icon for the actor displayed ---@param actorObject actor ---@param class string -function breakdownWindow.SetClassIcon(actorObject, class) +function breakdownWindowFrame.SetClassIcon(actorObject, class) if (actorObject.spellicon) then - breakdownWindow.classIcon:SetTexture(actorObject.spellicon) - breakdownWindow.classIcon:SetTexCoord(.1, .9, .1, .9) + breakdownWindowFrame.classIcon:SetTexture(actorObject.spellicon) + breakdownWindowFrame.classIcon:SetTexCoord(.1, .9, .1, .9) elseif (actorObject.spec) then - breakdownWindow.classIcon:SetTexture([[Interface\AddOns\Details\images\spec_icons_normal_alpha]]) - breakdownWindow.classIcon:SetTexCoord(unpack(_detalhes.class_specs_coords [actorObject.spec])) + breakdownWindowFrame.classIcon:SetTexture([[Interface\AddOns\Details\images\spec_icons_normal_alpha]]) + breakdownWindowFrame.classIcon:SetTexCoord(unpack(_detalhes.class_specs_coords [actorObject.spec])) else local coords = CLASS_ICON_TCOORDS[class] if (coords) then - breakdownWindow.classIcon:SetTexture([[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-CLASSES]]) + breakdownWindowFrame.classIcon:SetTexture([[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-CLASSES]]) local l, r, t, b = unpack(coords) - breakdownWindow.classIcon:SetTexCoord(l+0.01953125, r-0.01953125, t+0.01953125, b-0.01953125) + breakdownWindowFrame.classIcon:SetTexCoord(l+0.01953125, r-0.01953125, t+0.01953125, b-0.01953125) else local c = _detalhes.class_coords ["MONSTER"] - breakdownWindow.classIcon:SetTexture("Interface\\AddOns\\Details\\images\\classes") - breakdownWindow.classIcon:SetTexCoord(c[1], c[2], c[3], c[4]) + breakdownWindowFrame.classIcon:SetTexture("Interface\\AddOns\\Details\\images\\classes") + breakdownWindowFrame.classIcon:SetTexCoord(c[1], c[2], c[3], c[4]) end end end function Details:SetBreakdownWindowBackgroundTexture(texture) - breakdownWindow.backgroundTexture:SetTexture(texture) + breakdownWindowFrame.backgroundTexture:SetTexture(texture) end --search key: ~create ~inicio ~start function Details:CreateBreakdownWindow() - table.insert(UISpecialFrames, breakdownWindow:GetName()) - breakdownWindow.extra_frames = {} - breakdownWindow.Loaded = true - Details.playerDetailWindow = breakdownWindow + table.insert(UISpecialFrames, breakdownWindowFrame:GetName()) + breakdownWindowFrame.extra_frames = {} + breakdownWindowFrame.Loaded = true + Details.BreakdownWindowFrame = breakdownWindowFrame - breakdownWindow:SetWidth(PLAYER_DETAILS_WINDOW_WIDTH) - breakdownWindow:SetHeight(PLAYER_DETAILS_WINDOW_HEIGHT) - breakdownWindow:SetFrameStrata("HIGH") - breakdownWindow:SetToplevel(true) - breakdownWindow:EnableMouse(true) - breakdownWindow:SetResizable(true) - breakdownWindow:SetMovable(true) - breakdownWindow:SetClampedToScreen(true) + breakdownWindowFrame:SetWidth(PLAYER_DETAILS_WINDOW_WIDTH) + breakdownWindowFrame:SetHeight(PLAYER_DETAILS_WINDOW_HEIGHT) + breakdownWindowFrame:SetFrameStrata("HIGH") + breakdownWindowFrame:SetToplevel(true) + breakdownWindowFrame:EnableMouse(true) + breakdownWindowFrame:SetResizable(true) + breakdownWindowFrame:SetMovable(true) + breakdownWindowFrame:SetClampedToScreen(true) --make the window movable - if (not breakdownWindow.registeredLibWindow) then + if (not breakdownWindowFrame.registeredLibWindow) then local LibWindow = LibStub("LibWindow-1.1") - breakdownWindow.registeredLibWindow = true + breakdownWindowFrame.registeredLibWindow = true if (LibWindow) then - breakdownWindow.libWindowTable = breakdownWindow.libWindowTable or {} - LibWindow.RegisterConfig(breakdownWindow, breakdownWindow.libWindowTable) - LibWindow.RestorePosition(breakdownWindow) - LibWindow.MakeDraggable(breakdownWindow) - LibWindow.SavePosition(breakdownWindow) + breakdownWindowFrame.libWindowTable = breakdownWindowFrame.libWindowTable or {} + LibWindow.RegisterConfig(breakdownWindowFrame, breakdownWindowFrame.libWindowTable) + LibWindow.RestorePosition(breakdownWindowFrame) + LibWindow.MakeDraggable(breakdownWindowFrame) + LibWindow.SavePosition(breakdownWindowFrame) - breakdownWindow:SetScript("OnMouseDown", function(self, button) + breakdownWindowFrame:SetScript("OnMouseDown", function(self, button) if (button == "RightButton") then Details:CloseBreakdownWindow() end @@ -528,97 +596,96 @@ function Details:CreateBreakdownWindow() end end - detailsFramework:ApplyStandardBackdrop(breakdownWindow) + detailsFramework:ApplyStandardBackdrop(breakdownWindowFrame) --background - breakdownWindow.backgroundTexture = breakdownWindow:CreateTexture("$parent", "background", nil, -3) - breakdownWindow.backgroundTexture:SetAllPoints() - breakdownWindow.backgroundTexture:Hide() + breakdownWindowFrame.backgroundTexture = breakdownWindowFrame:CreateTexture("$parent", "background", nil, -3) + breakdownWindowFrame.backgroundTexture:SetAllPoints() + breakdownWindowFrame.backgroundTexture:Hide() --host the textures and fontstring of the default frame of the player breakdown window --what is the summary window: is the frame where all the widgets for the summary tab are created - breakdownWindow.SummaryWindowWidgets = CreateFrame("frame", "DetailsBreakdownWindowSummaryWidgets", breakdownWindow, "BackdropTemplate") - local SWW = breakdownWindow.SummaryWindowWidgets + breakdownWindowFrame.SummaryWindowWidgets = CreateFrame("frame", "DetailsBreakdownWindowSummaryWidgets", breakdownWindowFrame, "BackdropTemplate") + local SWW = breakdownWindowFrame.SummaryWindowWidgets SWW:SetAllPoints() - table.insert(SummaryWidgets, SWW) --where SummaryWidgets is declared: at the header of the file, what is the purpose of this table? - breakdownWindow.SummaryWindowWidgets:Hide() + table.insert(summaryWidgets, SWW) --where SummaryWidgets is declared: at the header of the file, what is the purpose of this table? + breakdownWindowFrame.SummaryWindowWidgets:Hide() - detailsFramework:CreateScaleBar(breakdownWindow, Details.player_details_window) - breakdownWindow:SetScale(Details.player_details_window.scale) + detailsFramework:CreateScaleBar(breakdownWindowFrame, Details.player_details_window) + breakdownWindowFrame:SetScale(Details.player_details_window.scale) --class icon - breakdownWindow.classIcon = breakdownWindow:CreateTexture(nil, "overlay", nil, 1) - breakdownWindow.classIcon:SetPoint("topleft", breakdownWindow, "topleft", 2, -17) - breakdownWindow.classIcon:SetSize(54, 54) - breakdownWindow.classIcon:SetAlpha(0.7) + breakdownWindowFrame.classIcon = breakdownWindowFrame:CreateTexture(nil, "overlay", nil, 1) + breakdownWindowFrame.classIcon:SetPoint("topleft", breakdownWindowFrame, "topleft", 2, -17) + breakdownWindowFrame.classIcon:SetSize(54, 54) + breakdownWindowFrame.classIcon:SetAlpha(0.7) --close button - breakdownWindow.closeButton = CreateFrame("Button", nil, breakdownWindow, "UIPanelCloseButton") - breakdownWindow.closeButton:SetSize(20, 20) - breakdownWindow.closeButton:SetPoint("TOPRIGHT", breakdownWindow, "TOPRIGHT", -5, -4) - breakdownWindow.closeButton:SetFrameLevel(breakdownWindow:GetFrameLevel()+5) - breakdownWindow.closeButton:GetNormalTexture():SetDesaturated(true) - breakdownWindow.closeButton:GetNormalTexture():SetVertexColor(.6, .6, .6) - breakdownWindow.closeButton:SetScript("OnClick", function(self) + breakdownWindowFrame.closeButton = CreateFrame("Button", nil, breakdownWindowFrame, "UIPanelCloseButton") + breakdownWindowFrame.closeButton:SetSize(20, 20) + breakdownWindowFrame.closeButton:SetPoint("TOPRIGHT", breakdownWindowFrame, "TOPRIGHT", -5, -4) + breakdownWindowFrame.closeButton:SetFrameLevel(breakdownWindowFrame:GetFrameLevel()+5) + breakdownWindowFrame.closeButton:GetNormalTexture():SetDesaturated(true) + breakdownWindowFrame.closeButton:GetNormalTexture():SetVertexColor(.6, .6, .6) + breakdownWindowFrame.closeButton:SetScript("OnClick", function(self) Details:CloseBreakdownWindow() end) --title - detailsFramework:NewLabel(breakdownWindow, breakdownWindow, nil, "titleText", Loc ["STRING_PLAYER_DETAILS"], "GameFontHighlightLeft", 12, {227/255, 186/255, 4/255}) - breakdownWindow.titleText:SetPoint("center", breakdownWindow, "center") - breakdownWindow.titleText:SetPoint("top", breakdownWindow, "top", 0, -6) + detailsFramework:NewLabel(breakdownWindowFrame, breakdownWindowFrame, nil, "titleText", Loc ["STRING_PLAYER_DETAILS"], "GameFontHighlightLeft", 12, {227/255, 186/255, 4/255}) + breakdownWindowFrame.titleText:SetPoint("center", breakdownWindowFrame, "center") + breakdownWindowFrame.titleText:SetPoint("top", breakdownWindowFrame, "top", 0, -6) --create the texts shown on the window do - breakdownWindow.actorName = breakdownWindow:CreateFontString(nil, "overlay", "QuestFont_Large") - breakdownWindow.actorName:SetPoint("left", breakdownWindow.classIcon, "right", 20, -7) + breakdownWindowFrame.actorName = breakdownWindowFrame:CreateFontString(nil, "overlay", "QuestFont_Large") + breakdownWindowFrame.actorName:SetPoint("left", breakdownWindowFrame.classIcon, "right", 20, -7) - breakdownWindow.attributeName = breakdownWindow:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall") + breakdownWindowFrame.attributeName = breakdownWindowFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall") + breakdownWindowFrame.avatar = breakdownWindowFrame:CreateTexture(nil, "overlay") + breakdownWindowFrame.avatar_bg = breakdownWindowFrame:CreateTexture(nil, "overlay") + breakdownWindowFrame.avatar_attribute = breakdownWindowFrame:CreateFontString(nil, "overlay", "GameFontHighlightSmall") + breakdownWindowFrame.avatar_nick = breakdownWindowFrame:CreateFontString(nil, "overlay", "QuestFont_Large") + breakdownWindowFrame.avatar:SetDrawLayer("overlay", 3) + breakdownWindowFrame.avatar_bg:SetDrawLayer("overlay", 2) + breakdownWindowFrame.avatar_nick:SetDrawLayer("overlay", 4) - breakdownWindow.avatar = breakdownWindow:CreateTexture(nil, "overlay") - breakdownWindow.avatar_bg = breakdownWindow:CreateTexture(nil, "overlay") - breakdownWindow.avatar_attribute = breakdownWindow:CreateFontString(nil, "overlay", "GameFontHighlightSmall") - breakdownWindow.avatar_nick = breakdownWindow:CreateFontString(nil, "overlay", "QuestFont_Large") - breakdownWindow.avatar:SetDrawLayer("overlay", 3) - breakdownWindow.avatar_bg:SetDrawLayer("overlay", 2) - breakdownWindow.avatar_nick:SetDrawLayer("overlay", 4) + breakdownWindowFrame.avatar:SetPoint("TOPLEFT", breakdownWindowFrame, "TOPLEFT", 60, -10) + breakdownWindowFrame.avatar_bg:SetPoint("TOPLEFT", breakdownWindowFrame, "TOPLEFT", 60, -12) + breakdownWindowFrame.avatar_bg:SetSize(275, 60) - breakdownWindow.avatar:SetPoint("TOPLEFT", breakdownWindow, "TOPLEFT", 60, -10) - breakdownWindow.avatar_bg:SetPoint("TOPLEFT", breakdownWindow, "TOPLEFT", 60, -12) - breakdownWindow.avatar_bg:SetSize(275, 60) + breakdownWindowFrame.avatar_nick:SetPoint("TOPLEFT", breakdownWindowFrame, "TOPLEFT", 195, -54) - breakdownWindow.avatar_nick:SetPoint("TOPLEFT", breakdownWindow, "TOPLEFT", 195, -54) - - breakdownWindow.avatar:Hide() - breakdownWindow.avatar_bg:Hide() - breakdownWindow.avatar_nick:Hide() + breakdownWindowFrame.avatar:Hide() + breakdownWindowFrame.avatar_bg:Hide() + breakdownWindowFrame.avatar_nick:Hide() end --statusbar - local statusBar = CreateFrame("frame", nil, breakdownWindow, "BackdropTemplate") - statusBar:SetPoint("bottomleft", breakdownWindow, "bottomleft") - statusBar:SetPoint("bottomright", breakdownWindow, "bottomright") + local statusBar = CreateFrame("frame", nil, breakdownWindowFrame, "BackdropTemplate") + statusBar:SetPoint("bottomleft", breakdownWindowFrame, "bottomleft") + statusBar:SetPoint("bottomright", breakdownWindowFrame, "bottomright") statusBar:SetHeight(PLAYER_DETAILS_STATUSBAR_HEIGHT) detailsFramework:ApplyStandardBackdrop(statusBar) statusBar:SetAlpha(PLAYER_DETAILS_STATUSBAR_ALPHA) - breakdownWindow.statusBar = statusBar + breakdownWindowFrame.statusBar = statusBar statusBar.Text = detailsFramework:CreateLabel(statusBar) statusBar.Text:SetPoint("left", 2, 0) --create the gradients in the top and bottom side of the breakdown window local gradientStartColor = Details222.ColorScheme.GetColorFor("gradient-background") - local gradientUp = detailsFramework:CreateTexture(breakdownWindow, {gradient = "vertical", fromColor = gradientStartColor, toColor = {0, 0, 0, 0.2}}, 1, 68, "artwork", {0, 1, 0, 1}) + local gradientUp = detailsFramework:CreateTexture(breakdownWindowFrame, {gradient = "vertical", fromColor = gradientStartColor, toColor = {0, 0, 0, 0.2}}, 1, 68, "artwork", {0, 1, 0, 1}) gradientUp:SetPoint("tops", 1, 1) local gradientHeight = 481 - local gradientDown = detailsFramework:CreateTexture(breakdownWindow, {gradient = "vertical", fromColor = "transparent", toColor = {0, 0, 0, 0.7}}, 1, gradientHeight, "border", {0, 1, 0, 1}) - gradientDown:SetPoint("bottomleft", breakdownWindow.statusBar, "topleft", 1, 1) - gradientDown:SetPoint("bottomright", breakdownWindow.statusBar, "topright", -1, 1) + local gradientDown = detailsFramework:CreateTexture(breakdownWindowFrame, {gradient = "vertical", fromColor = "transparent", toColor = {0, 0, 0, 0.7}}, 1, gradientHeight, "border", {0, 1, 0, 1}) + gradientDown:SetPoint("bottomleft", breakdownWindowFrame.statusBar, "topleft", 1, 1) + gradientDown:SetPoint("bottomright", breakdownWindowFrame.statusBar, "topright", -1, 1) - function breakdownWindow:SetStatusbarText(text, fontSize, fontColor) + function breakdownWindowFrame:SetStatusbarText(text, fontSize, fontColor) if (not text) then - breakdownWindow:SetStatusbarText("Details! Damage Meter | Use '/details stats' for statistics", 10, "gray") + breakdownWindowFrame:SetStatusbarText("Details! Damage Meter | Use '/details stats' for statistics", 10, "gray") return end statusBar.Text.text = text @@ -627,28 +694,28 @@ function Details:CreateBreakdownWindow() end --set default text - breakdownWindow:SetStatusbarText() + breakdownWindowFrame:SetStatusbarText() -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --tabs ~tabs - function breakdownWindow:ShowTabs() + function breakdownWindowFrame:ShowTabs() local tabsShown = 0 local secondRowIndex = 1 - local breakLine = 6 --the tab it'll start the second line + local breakLine = 7 --the tab it'll start the second line local tablePool = Details:GetBreakdownTabsInUse() for index = 1, #tablePool do local tabButton = tablePool[index] - if (tabButton:condition(breakdownWindow.jogador, breakdownWindow.atributo, breakdownWindow.sub_atributo) and not tabButton.replaced) then + if (tabButton:condition(breakdownWindowFrame.jogador, breakdownWindowFrame.atributo, breakdownWindowFrame.sub_atributo) and not tabButton.replaced) then --test if can show the tutorial for the comparison tab if (tabButton.tabname == "Compare") then --Details:SetTutorialCVar ("DETAILS_INFO_TUTORIAL1", false) if (not Details:GetTutorialCVar("DETAILS_INFO_TUTORIAL1")) then Details:SetTutorialCVar ("DETAILS_INFO_TUTORIAL1", true) - local alert = CreateFrame("frame", "DetailsInfoPopUp1", breakdownWindow, "DetailsHelpBoxTemplate") + local alert = CreateFrame("frame", "DetailsInfoPopUp1", breakdownWindowFrame, "DetailsHelpBoxTemplate") alert.ArrowUP:Show() alert.ArrowGlowUP:Show() alert.Text:SetText(Loc ["STRING_INFO_TUTORIAL_COMPARISON1"]) @@ -663,25 +730,25 @@ function Details:CreateBreakdownWindow() tabButton:ClearAllPoints() --get the button width - local buttonTemplate = gump:GetTemplate("button", "DETAILS_TAB_BUTTON_TEMPLATE") + local buttonTemplate = detailsFramework:GetTemplate("button", "DETAILS_TAB_BUTTON_TEMPLATE") local buttonWidth = buttonTemplate.width + 1 --pixelutil might not be compatible with classic wow if (PixelUtil) then PixelUtil.SetSize(tabButton, buttonTemplate.width, buttonTemplate.height) if (tabsShown >= breakLine) then --next row of icons - PixelUtil.SetPoint(tabButton, "bottomright", breakdownWindow, "topright", -514 + (buttonWidth * (secondRowIndex)), -50) + PixelUtil.SetPoint(tabButton, "bottomright", breakdownWindowFrame, "topright", -613 + (buttonWidth * (secondRowIndex)), -48) secondRowIndex = secondRowIndex + 1 else - PixelUtil.SetPoint(tabButton, "bottomright", breakdownWindow, "topright", -514 + (buttonWidth * tabsShown), -69) + PixelUtil.SetPoint(tabButton, "bottomright", breakdownWindowFrame, "topright", -613 + (buttonWidth * tabsShown), -69) end else tabButton:SetSize(buttonTemplate.width, buttonTemplate.height) if (tabsShown >= breakLine) then --next row of icons - tabButton:SetPoint("bottomright", breakdownWindow, "topright", -514 + (buttonWidth * (secondRowIndex)), -50) + tabButton:SetPoint("bottomright", breakdownWindowFrame, "topright", -613 + (buttonWidth * (secondRowIndex)), -48) secondRowIndex = secondRowIndex + 1 else - tabButton:SetPoint("bottomright", breakdownWindow, "topright", -514 + (buttonWidth * tabsShown), -69) + tabButton:SetPoint("bottomright", breakdownWindowFrame, "topright", -613 + (buttonWidth * tabsShown), -69) end end @@ -693,14 +760,14 @@ function Details:CreateBreakdownWindow() end if (tabsShown < 2) then - tablePool[1]:SetPoint("bottomleft", breakdownWindow.container_barras, "topleft", 490 - (94 * (1-0)), 1) + tablePool[1]:SetPoint("bottomleft", breakdownWindowFrame.container_barras, "topleft", 490 - (94 * (1-0)), 1) end --selected by default tablePool[1]:Click() end - breakdownWindow:SetScript("OnHide", function(self) + breakdownWindowFrame:SetScript("OnHide", function(self) Details:CloseBreakdownWindow() for _, tab in ipairs(Details.player_details_tabs) do tab:Hide() @@ -708,11 +775,11 @@ function Details:CreateBreakdownWindow() end end) - breakdownWindow.tipo = 1 --tipo da janela // 1 = janela normal - return breakdownWindow + breakdownWindowFrame.tipo = 1 --tipo da janela // 1 = janela normal + return breakdownWindowFrame end -breakdownWindow.selectedTab = "Summary" +breakdownWindowFrame.selectedTab = "Summary" function Details:CreatePlayerDetailsTab(tabName, locName, conditionFunc, fillFunc, tabOnClickFunc, onCreateFunc, iconSettings, replace, bIsDefaultTab) --~tab if (not tabName) then @@ -720,8 +787,8 @@ function Details:CreatePlayerDetailsTab(tabName, locName, conditionFunc, fillFun end --create a button to select the tab - local tabButton = detailsFramework:CreateButton(breakdownWindow, function()end, 20, 20, locName, nil, nil, nil, nil, breakdownWindow:GetName() .. "TabButton" .. tabName .. math.random(1, 1000), nil, "DETAILS_TAB_BUTTON_TEMPLATE") - tabButton:SetFrameLevel(breakdownWindow:GetFrameLevel()+1) + local tabButton = detailsFramework:CreateButton(breakdownWindowFrame.BreakdownTabsFrame, function()end, 20, 20, locName, nil, nil, nil, nil, breakdownWindowFrame:GetName() .. "TabButton" .. tabName .. math.random(1, 1000), nil, "DETAILS_TAB_BUTTON_TEMPLATE") + tabButton:SetFrameLevel(breakdownWindowFrame.BreakdownTabsFrame:GetFrameLevel()+1) tabButton:Hide() if (tabName == "Summary") then @@ -737,10 +804,10 @@ function Details:CreatePlayerDetailsTab(tabName, locName, conditionFunc, fillFun tabButton.last_actor = {} --need to double check is this getting cleared ---@type tabframe - local tabFrame = CreateFrame("frame", breakdownWindow:GetName() .. "TabFrame" .. tabName .. math.random(1, 10000), breakdownWindow, "BackdropTemplate") - tabFrame:SetFrameLevel(breakdownWindow:GetFrameLevel()+1) - tabFrame:SetPoint("topleft", breakdownWindow, "topleft", 0, -70) - tabFrame:SetPoint("bottomright", breakdownWindow, "bottomright", -1, 20) + local tabFrame = CreateFrame("frame", breakdownWindowFrame:GetName() .. "TabFrame" .. tabName .. math.random(1, 10000), breakdownWindowFrame, "BackdropTemplate") + tabFrame:SetFrameLevel(breakdownWindowFrame:GetFrameLevel()+1) + tabFrame:SetPoint("topleft", breakdownWindowFrame, "topleft", 1, -70) + tabFrame:SetPoint("bottomright", breakdownWindowFrame, "bottomright", -1, 20) tabFrame:Hide() DetailsFramework:ApplyStandardBackdrop(tabFrame) @@ -808,7 +875,7 @@ function Details:CreatePlayerDetailsTab(tabName, locName, conditionFunc, fillFun end self:SetTemplate("DETAILS_TAB_BUTTONSELECTED_TEMPLATE") - breakdownWindow.selectedTab = self.tabname + breakdownWindowFrame.selectedTab = self.tabname end if (not tabOnClickFunc) then @@ -841,14 +908,14 @@ function Details:CreatePlayerDetailsTab(tabName, locName, conditionFunc, fillFun end tabButton:SetScript("PostClick", function(self) - CurrentTab = self.tabname or self.MyObject.tabname + currentTab = self.tabname or self.MyObject.tabname - if (CurrentTab ~= "Summary") then - for _, widget in ipairs(SummaryWidgets) do + if (currentTab ~= "Summary") then + for _, widget in ipairs(summaryWidgets) do widget:Hide() end else - for _, widget in ipairs(SummaryWidgets) do + for _, widget in ipairs(summaryWidgets) do widget:Show() end end diff --git a/frames/window_breakdown/window_playerbreakdown_compare.lua b/frames/window_breakdown/window_playerbreakdown_compare.lua index 91cac3ac..369e71de 100644 --- a/frames/window_breakdown/window_playerbreakdown_compare.lua +++ b/frames/window_breakdown/window_playerbreakdown_compare.lua @@ -34,7 +34,7 @@ local IconTexCoord = {5/64, 59/64, 5/64, 59/64} local Loc = LibStub("AceLocale-3.0"):GetLocale( "Details" ) local SharedMedia = LibStub:GetLibrary("LibSharedMedia-3.0") -local info = Details.playerDetailWindow +local breakdownWindowFrame = Details.BreakdownWindowFrame local fill_compare_targets = function(self, player, other_players, target_pool) local offset = _G.FauxScrollFrame_GetOffset(self) @@ -324,7 +324,7 @@ local fill_compare_actors = function(self, player, other_players) --main player pets for petIndex, petName in ipairs(player:Pets()) do - local petActor = info.instancia.showing [player.tipo]:PegarCombatente (nil, petName) + local petActor = breakdownWindowFrame.instancia.showing [player.tipo]:PegarCombatente (nil, petName) if (petActor) then for _spellid, _skill in pairs(petActor:GetActorSpells()) do spells_sorted [#spells_sorted+1] = {_skill, _skill.total, petName} @@ -359,7 +359,7 @@ local fill_compare_actors = function(self, player, other_players) end --player 2 pets for petIndex, petName in ipairs(other_players [1]:Pets()) do - local petActor = info.instancia.showing [player.tipo]:PegarCombatente (nil, petName) + local petActor = breakdownWindowFrame.instancia.showing [player.tipo]:PegarCombatente (nil, petName) if (petActor) then for _spellid, _skill in pairs(petActor:GetActorSpells()) do player_2_spells_sorted [#player_2_spells_sorted+1] = {_skill, _skill.total, petName} @@ -401,7 +401,7 @@ local fill_compare_actors = function(self, player, other_players) end --player 3 pets for petIndex, petName in ipairs(other_players [2]:Pets()) do - local petActor = info.instancia.showing [player.tipo]:PegarCombatente (nil, petName) + local petActor = breakdownWindowFrame.instancia.showing [player.tipo]:PegarCombatente (nil, petName) if (petActor) then for _spellid, _skill in pairs(petActor:GetActorSpells()) do player_3_spells_sorted [#player_3_spells_sorted+1] = {_skill, _skill.total, petName} @@ -462,7 +462,7 @@ local fill_compare_actors = function(self, player, other_players) if (not spell and petName and player_2) then for _petIndex, _petName in ipairs(player_2:Pets()) do if (_petName:gsub(" <.*", "") == petName:gsub(" <.*", "")) then - local petActor = info.instancia.showing [player.tipo]:PegarCombatente (nil, _petName) + local petActor = breakdownWindowFrame.instancia.showing [player.tipo]:PegarCombatente (nil, _petName) spell = petActor and petActor.spells._ActorTable [spellid] name = name .. " (|cFFCCBBBB" .. _petName:gsub(" <.*", "") .. "|r)" end @@ -541,7 +541,7 @@ local fill_compare_actors = function(self, player, other_players) if (not spell and petName and player_3) then for _petIndex, _petName in ipairs(player_3:Pets()) do if (_petName:gsub(" <.*", "") == petName:gsub(" <.*", "")) then - local petActor = info.instancia.showing [player.tipo]:PegarCombatente (nil, _petName) + local petActor = breakdownWindowFrame.instancia.showing [player.tipo]:PegarCombatente (nil, _petName) spell = petActor and petActor.spells._ActorTable [spellid] local name, _, icon = _GetSpellInfo(spellid) name = name .. " (|cFFCCBBBB" .. _petName:gsub(" <.*", "") .. "|r)" @@ -971,7 +971,7 @@ local on_enter = function(self) local critical = bar1[3][3] ---@type combat - local combatObject = info.instancia.showing + local combatObject = breakdownWindowFrame.instancia.showing local player1_misc = combatObject(4, player1) local player2_misc = combatObject(4, player2) @@ -1470,7 +1470,7 @@ local compare_create = function(tab, frame) bar.righttext2:SetJustifyH("right") bar.righttext2:SetTextColor(1, 1, 1, 1) - tinsert(parent.bars, {spellicon, bar, {0, 0, 0}}) + table.insert(parent.bars, {spellicon, bar, {0, 0, 0}}) end local create_tooltip = function(name) @@ -1675,7 +1675,7 @@ local compare_create = function(tab, frame) bar.bg = bg_line1 local object = {spellicon, bar} - tinsert(tooltip.bars, object) + table.insert(tooltip.bars, object) return object end @@ -1899,7 +1899,7 @@ function Details:InitializeCompareTab() Loc ["STRING_INFO_TAB_COMPARISON"], --[2] localized name function(tabOBject, playerObject) --[3] condition - if (info.atributo > 2) then + if (breakdownWindowFrame.atributo > 2) then return false end @@ -1917,11 +1917,11 @@ function Details:InitializeCompareTab() tabOBject.player = playerObject tabOBject.spells_amt = my_spells_total - if (not info.instancia.showing) then + if (not breakdownWindowFrame.instancia.showing) then return false end - for index, actor in ipairs(info.instancia.showing [info.atributo]._ActorTable) do + for index, actor in ipairs(breakdownWindowFrame.instancia.showing [breakdownWindowFrame.atributo]._ActorTable) do if (actor.classe == class and actor ~= playerObject) then local same_spells = 0 @@ -1934,7 +1934,7 @@ function Details:InitializeCompareTab() local match_percentage = same_spells / math.max(my_spells_total, 0.000001) * 100 if (match_percentage > 30) then - tinsert(tabOBject.players, actor) + table.insert(tabOBject.players, actor) end end end diff --git a/frames/window_breakdown/window_playerbreakdown_list.lua b/frames/window_breakdown/window_playerbreakdown_list.lua index c2ff960f..69c81eba 100644 --- a/frames/window_breakdown/window_playerbreakdown_list.lua +++ b/frames/window_breakdown/window_playerbreakdown_list.lua @@ -1,22 +1,223 @@ - local Details = _G.Details - local detailsFramework = _G.DetailsFramework - local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true) - local addonName, Details222 = ... +local Details = _G.Details +local detailsFramework = _G.DetailsFramework +local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true) +local addonName, Details222 = ... - local breakdownWindowPlayerList = {} +local breakdownWindowPlayerList = {} - local unpack = table.unpack or unpack - local C_Timer = _G.C_Timer - local tinsert = _G.tinsert +local unpack = table.unpack or unpack +local C_Timer = _G.C_Timer +local tinsert = table.insert +local CreateFrame = CreateFrame +local GetSpecializationInfoByID = GetSpecializationInfoByID - local scrollbox_size = {215, 405} - local scrollbox_lines = 23 - local player_line_height = 21.7 - local scrollbox_line_backdrop_color = {0.2, 0.2, 0.2, 0.5} - local scrollbox_line_backdrop_color_selected = {.6, .6, .1, 0.7} - local scrollbox_line_backdrop_color_highlight = {.9, .9, .9, 0.5} - local player_scroll_size = {195, 288} +local scrollbox_size = {215, 405} +local scrollbox_lines = 19 +local player_line_height = 21.7 +local scrollbox_line_backdrop_color = {0.2, 0.2, 0.2, 0.5} +local scrollbox_line_backdrop_color_selected = {.6, .6, .1, 0.7} +local scrollbox_line_backdrop_color_highlight = {.9, .9, .9, 0.5} +local player_scroll_size = {195, 288} +local player_scroll_y = -166 + +function breakdownWindowPlayerList.CreatePlayerListFrame() + ---@type breakdownwindow + local breakdownWindowFrame = Details.BreakdownWindowFrame + ---@type frame + local breakdownSideMenu = breakdownWindowFrame.BreakdownSideMenuFrame + ---@type frame + local pluginsFrame = breakdownWindowFrame.BreakdownPluginSelectionFrame + + breakdownSideMenu:SetSize(scrollbox_size[1], scrollbox_size[2]) + breakdownSideMenu:SetPoint("topright", breakdownWindowFrame, "topleft", 0, 0) + breakdownSideMenu:SetPoint("bottomright", breakdownWindowFrame, "bottomleft", 0, 0) + detailsFramework:ApplyStandardBackdrop(breakdownSideMenu) + breakdownSideMenu.RightEdge:Hide() + + pluginsFrame:SetPoint("topleft", breakdownSideMenu, "topleft", 0, 0) + pluginsFrame:SetPoint("bottomright", breakdownSideMenu, "topright", 0, player_scroll_y + 26) + + --pluginsFrame:SetSize(player_scroll_size[1], player_scroll_y + 26) + + detailsFramework:ApplyStandardBackdrop(pluginsFrame) + + local refreshPluginButtons = function() + for i = 1, #breakdownWindowFrame.RegisteredPluginButtons do + ---@type button + local pluginButton = breakdownWindowFrame.RegisteredPluginButtons[i] + pluginButton:Show() + pluginButton:ClearAllPoints() + + if (i == 1) then + pluginButton:SetPoint("topleft", pluginsFrame, "topleft", 2, -2) + else + pluginButton:SetPoint("topleft", breakdownWindowFrame.RegisteredPluginButtons[i - 1], "bottomleft", 0, -2) + end + end + end + + refreshPluginButtons() + + + local refreshScrollFunc = function(self, data, offset, totalLines) + --update the scroll + local topResult = data[1] + if (topResult) then + topResult = topResult.total + end + + ---@type combat + local combatObject = Details:GetCombatFromBreakdownWindow() + local encounterId = combatObject:GetEncounterCleuID() + local difficultyId = combatObject:GetDifficulty() + + for i = 1, totalLines do --~refresh + local index = i + offset + local playerObject = data[index] + if (playerObject) then + local line = self:GetLine(i) + line.playerObject = playerObject + line.combatObject = combatObject + line.index = index + line:UpdateLine(topResult, encounterId, difficultyId) + end + end + end + + local lineOnClick = function(self) + if (self.playerObject ~= Details:GetActorObjectFromBreakdownWindow() or breakdownWindowFrame.shownPluginObject) then + Details:OpenBreakdownWindow(Details:GetActiveWindowFromBreakdownWindow(), self.playerObject) + breakdownWindowFrame.playerScrollBox:Refresh() + end + end + + local lineOnEnter = function(self) + self:SetBackdropColor(unpack(scrollbox_line_backdrop_color_highlight)) + self.specIcon:SetBlendMode("ADD") + self.roleIcon:SetBlendMode("ADD") + end + + local lineOnLeave = function(self) + if (self.isSelected) then + self:SetBackdropColor(unpack(scrollbox_line_backdrop_color_selected)) + else + self:SetBackdropColor(unpack(scrollbox_line_backdrop_color)) + end + self.specIcon:SetBlendMode("BLEND") + self.roleIcon:SetBlendMode("BLEND") + end + + local updatePlayerLine = function(self, topResult, encounterId, difficultyId) --~update + local playerSelected = Details:GetActorObjectFromBreakdownWindow() + if (playerSelected and playerSelected == self.playerObject) then + self:SetBackdropColor(unpack(scrollbox_line_backdrop_color_selected)) + self.isSelected = true + else + self:SetBackdropColor(unpack(scrollbox_line_backdrop_color)) + self.isSelected = nil + end + + local specRole + + --adjust the player icon + if (self.playerObject.spellicon) then + self.specIcon:SetTexture(self.playerObject.spellicon) + self.specIcon:SetTexCoord(.1, .9, .1, .9) + else + local specIcon, L, R, T, B = Details:GetSpecIcon(self.playerObject.spec, false) + + if (specIcon) then + self.specIcon:SetTexture(specIcon) + self.specIcon:SetTexCoord(L, R, T, B) + + if (DetailsFramework.IsTimewalkWoW()) then + specRole = "NONE" + else + ---@type number + local spec = self.playerObject.spec + if (spec) then + specRole = select(5, GetSpecializationInfoByID(self.playerObject.spec)) + end + end + else + self.specIcon:SetTexture("") + end + end + + --adjust the role icon + if (specRole) then + local roleIcon, L, R, T, B = Details:GetRoleIcon(specRole) + if (roleIcon) then + self.roleIcon:SetTexture(roleIcon) + self.roleIcon:SetTexCoord(L, R, T, B) + else + self.roleIcon:SetTexture("") + end + else + self.roleIcon:SetTexture("") + end + + local playerGear = openRaidLib and openRaidLib.GetUnitGear(self.playerObject.nome) + + --do not show the role icon + self.roleIcon:SetTexture("") --not in use + + --set the player name + self.playerName:SetText(Details:GetOnlyName(self.playerObject.nome)) + self.rankText:SetText(self.index) --not in use + + --set the player class name + --self.className:SetText(string.lower(_G.UnitClass(self.playerObject.nome) or self.playerObject:Class())) --not in use + + --item level + self.itemLevelText:SetText(self.playerObject.ilvl or (playerGear and playerGear.ilevel) or "0") + + local actorSpecId = self.playerObject.spec + local actorTotal = self.playerObject.total + local combatObject = self.combatObject + + --warcraftlogs percentile + if (self.playerObject.tipo == DETAILS_ATTRIBUTE_DAMAGE) then + local actorDPS = self.playerObject.total / combatObject:GetCombatTime() + + local parsePercent = Details222.WarcraftLogs.GetDamageParsePercent(encounterId, difficultyId, actorSpecId, actorDPS) + if (parsePercent) then + parsePercent = math.floor(parsePercent) + local colorName = Details222.WarcraftLogs.GetParseColor(parsePercent) + self.percentileText:SetTextColor(detailsFramework:ParseColors(colorName)) + self.percentileText:SetText(math.floor(parsePercent)) + self.percentileText.alpha = 1 + else + parsePercent = Details222.ParsePercent.GetPercent(DETAILS_ATTRIBUTE_DAMAGE, difficultyId, encounterId, actorSpecId, actorDPS) + if (parsePercent) then + parsePercent = math.floor(parsePercent) + local colorName = Details222.WarcraftLogs.GetParseColor(parsePercent) + self.percentileText:SetTextColor(detailsFramework:ParseColors(colorName)) + self.percentileText:SetText(math.floor(parsePercent)) + self.percentileText.alpha = 1 + else + self.percentileText:SetText("#.def") + self.percentileText:SetAlpha(0.25) + end + end + else + self.percentileText:SetText("#.def") + self.percentileText:SetAlpha(0.25) + end + + --set the statusbar + local r, g, b = self.playerObject:GetClassColor() + self.totalStatusBar:SetStatusBarColor(r, g, b, 1) + self.totalStatusBar:SetMinMaxValues(0, topResult) + self.totalStatusBar:SetValue(actorTotal) + end + + --get a Details! window + local lowerInstanceId = Details:GetLowerInstanceNumber() + local fontFile + local fontSize + local fontOutline --header setup local headerTable = { @@ -29,385 +230,235 @@ padding = 2, } - function breakdownWindowPlayerList.CreatePlayerListFrame() - local f = _G.DetailsBreakdownWindow + if (lowerInstanceId) then + local instance = Details:GetInstance(lowerInstanceId) + if (instance) then + fontFile = instance.row_info.font_face + fontSize = instance.row_info.font_size + fontOutline = instance.row_info.textL_outline + end + end - local refreshScrollFunc = function(self, data, offset, totalLines) - --update the scroll - local topResult = data[1] - if (topResult) then - topResult = topResult.total - end + local createPlayerLine = function(self, index) + --create a new line + local line = CreateFrame("button", "$parentLine" .. index, self, "BackdropTemplate") + detailsFramework:Mixin(line, detailsFramework.HeaderFunctions) - ---@type combat - local combatObject = Details:GetCombatFromBreakdownWindow() - local encounterId = combatObject:GetEncounterCleuID() - local difficultyId = combatObject:GetDifficulty() + local upFrame = CreateFrame("frame", nil, line) + upFrame:SetFrameLevel(line:GetFrameLevel()+2) + upFrame:SetAllPoints() - for i = 1, totalLines do --~refresh - local index = i + offset - local playerObject = data[index] - if (playerObject) then - local line = self:GetLine(i) - line.playerObject = playerObject - line.combatObject = combatObject - line.index = index - line:UpdateLine(topResult, encounterId, difficultyId) + --set its parameters + line:SetPoint("topleft", self, "topleft", 1, -((index) * (player_line_height+1)) - 1) + line:SetSize(scrollbox_size[1]-2, player_line_height) + --line:SetSize(scrollbox_size[1]-19, player_line_height) + line:RegisterForClicks("LeftButtonDown", "RightButtonDown") + + line:SetScript("OnEnter", lineOnEnter) + line:SetScript("OnLeave", lineOnLeave) + line:SetScript("OnClick", lineOnClick) + + detailsFramework:ApplyStandardBackdrop(line) + + local specIcon = upFrame:CreateTexture("$parentSpecIcon", "artwork") + specIcon:SetSize(headerTable[1].width - 1, headerTable[1].width - 1) + specIcon:SetAlpha(0.71) + + local roleIcon = upFrame:CreateTexture("$parentRoleIcon", "overlay") + roleIcon:SetSize((player_line_height-2) / 2, (player_line_height-2) / 2) + roleIcon:SetAlpha(0.71) + + local playerName = detailsFramework:CreateLabel(upFrame, "", 11, "white", "GameFontNormal") + if (fontFile) then + playerName.fontface = fontFile + end + if (fontSize) then + playerName.fontsize = fontSize + end + if (fontOutline) then + playerName.outline = fontOutline + end + + --~create + playerName.textcolor = {1, 1, 1, .9} + + local className = detailsFramework:CreateLabel(upFrame, "", "GameFontNormal") + className.textcolor = {.95, .8, .2, 0} + className.textsize = 9 + + local itemLevelText = detailsFramework:CreateLabel(upFrame, "", "GameFontNormal") + itemLevelText.textcolor = {1, 1, 1, .7} + itemLevelText.textsize = 11 + + local percentileText = detailsFramework:CreateLabel(upFrame, "", "GameFontNormal") + percentileText.textcolor = {1, 1, 1, .7} + percentileText.textsize = 11 + + local rankText = detailsFramework:CreateLabel(upFrame, "", "GameFontNormal") + rankText.textcolor = {.3, .3, .3, .7} + rankText.textsize = fontSize + + local totalStatusBar = CreateFrame("statusbar", nil, line) + totalStatusBar:SetSize(scrollbox_size[1]-player_line_height, 4) + totalStatusBar:SetMinMaxValues(0, 100) + totalStatusBar:SetStatusBarTexture([[Interface\AddOns\Details\images\bar_skyline]]) + totalStatusBar:SetFrameLevel(line:GetFrameLevel()+1) + totalStatusBar:SetAlpha(0.5) + + --setup anchors + --specIcon:SetPoint("topleft", line, "topleft", 0, 0) + --roleIcon:SetPoint("topleft", specIcon, "topright", 2, 0) + --playerName:SetPoint("topleft", specIcon, "topright", 2, -3) + --className:SetPoint("topleft", roleIcon, "bottomleft", 0, -2) + --rankText:SetPoint("right", line, "right", -2, 0) + totalStatusBar:SetPoint("bottomleft", specIcon, "bottomright", 0, 0) + + line.specIcon = specIcon + line.roleIcon = roleIcon + line.playerName = playerName + line.className = className + line.rankText = rankText + line.totalStatusBar = totalStatusBar + line.itemLevelText = itemLevelText + line.percentileText = percentileText + + line:AddFrameToHeaderAlignment(specIcon) + line:AddFrameToHeaderAlignment(playerName) + line:AddFrameToHeaderAlignment(itemLevelText) + line:AddFrameToHeaderAlignment(percentileText) + + line:AlignWithHeader(breakdownWindowFrame.Header, "left") + + line.UpdateLine = updatePlayerLine + + return line + end + + ---@type width + local width = player_scroll_size[1] + 22 + ---@type height + local height = player_scroll_size[2] + + local playerScroll = detailsFramework:CreateScrollBox(breakdownSideMenu, "DetailsBreakdownWindowPlayerScrollBox", refreshScrollFunc, {}, width, height, scrollbox_lines, player_line_height) + detailsFramework:ReskinSlider(playerScroll) + playerScroll.ScrollBar:ClearAllPoints() + playerScroll.ScrollBar:SetPoint("topright", playerScroll, "topright", -2, -37) + playerScroll.ScrollBar:SetPoint("bottomright", playerScroll, "bottomright", -2, 17) + playerScroll.ScrollBar:Hide() + playerScroll:SetPoint("topleft", breakdownSideMenu, "topleft", 0, player_scroll_y) + playerScroll:SetPoint("bottomright", breakdownSideMenu, "bottomright", -1, 0) + playerScroll:SetBackdrop({}) + playerScroll:SetBackdropColor(0, 0, 0, 0) + playerScroll:SetBackdropBorderColor(0, 0, 0, 0) + breakdownWindowFrame.playerScrollBox = playerScroll + + --need to be created before + breakdownWindowFrame.Header = DetailsFramework:CreateHeader(playerScroll, headerTable, headerOptions) + breakdownWindowFrame.Header:SetPoint("topleft", playerScroll, "topleft", 0, -1) + breakdownWindowFrame.Header:SetPoint("topright", playerScroll, "topright", 0, -1) + breakdownWindowFrame.Header:SetAlpha(0.823) + + detailsFramework:ApplyStandardBackdrop(breakdownWindowFrame.Header) + breakdownWindowFrame.Header.__background:SetColorTexture(.60, .60, .60) + + local playerSelectionLabel = detailsFramework:CreateLabel(playerScroll, "Click to select a player", 14) + playerSelectionLabel:SetPoint("bottom", breakdownWindowFrame.Header, "top", 0, 1) + + --create the scrollbox lines + for i = 1, scrollbox_lines do + playerScroll:CreateLine(createPlayerLine) + end + + local classIds = { + WARRIOR = 1, + PALADIN = 2, + HUNTER = 3, + ROGUE = 4, + PRIEST = 5, + DEATHKNIGHT = 6, + SHAMAN = 7, + MAGE = 8, + WARLOCK = 9, + MONK = 10, + DRUID = 11, + DEMONHUNTER = 12, + EVOKER = 13, + } + + ---get the player list from the segment and build a table compatible with the scroll box + ---@return actor[] + function breakdownWindowPlayerList.BuildPlayerList() + ---@type combat + local combatObject = Details:GetCombatFromBreakdownWindow() + ---@type {key1: actor, key2: number, key3: number}[] + local playerTable = {} + + if (combatObject) then + local displayType = Details:GetDisplayTypeFromBreakdownWindow() + local containerType = displayType == 1 and DETAILS_ATTRIBUTE_DAMAGE or DETAILS_ATTRIBUTE_HEAL + ---@type actorcontainer + local actorContainer = combatObject:GetContainer(containerType) + + for index, actorObject in actorContainer:ListActors() do + ---@cast actorObject actor + if (actorObject:IsPlayer() and actorObject:IsGroupPlayer()) then + local unitClassID = classIds[actorObject:Class()] or 13 + local unitName = actorObject:Name() + local playerPosition = (((unitClassID or 0) + 128) ^ 4) + tonumber(string.byte(unitName, 1) .. "" .. string.byte(unitName, 2)) + + ---@type {key1: actor, key2: number, key3: number} + local data = {actorObject, playerPosition, actorObject.total} + tinsert(playerTable, data) end end end - local lineOnClick = function(self) - if (self.playerObject ~= Details:GetActorObjectFromBreakdownWindow()) then - Details:OpenBreakdownWindow(Details:GetActiveWindowFromBreakdownWindow(), self.playerObject) - f.playerScrollBox:Refresh() - end + table.sort(playerTable, detailsFramework.SortOrder3) + + ---@type actor[] + local resultTable = {} + for i = 1, #playerTable do + ---@type actor + local actor = playerTable[i][1] + resultTable[#resultTable+1] = actor end - local lineOnEnter = function(self) - self:SetBackdropColor(unpack(scrollbox_line_backdrop_color_highlight)) - self.specIcon:SetBlendMode("ADD") - self.roleIcon:SetBlendMode("ADD") + return resultTable + end + + local updatePlayerList = function() + ---@type actor[] + local playerList = breakdownWindowPlayerList.BuildPlayerList() + playerScroll:SetData(playerList) + playerScroll:Refresh() + playerScroll:Show() + end + + function Details:UpdateBreakdownPlayerList() + --run the update on the next tick + C_Timer.After(0, updatePlayerList) + end + + breakdownWindowFrame:HookScript("OnShow", function() + Details:UpdateBreakdownPlayerList() + end) + + breakdownWindowFrame:HookScript("OnHide", function() + for lineIndex, line in ipairs(breakdownWindowFrame.playerScrollBox:GetLines()) do + line.playerObject = nil + line.combatObject = nil end + end) - local lineOnLeave = function(self) - if (self.isSelected) then - self:SetBackdropColor(unpack(scrollbox_line_backdrop_color_selected)) - else - self:SetBackdropColor(unpack(scrollbox_line_backdrop_color)) - end - self.specIcon:SetBlendMode("BLEND") - self.roleIcon:SetBlendMode("BLEND") - end + local gradientStartColor = Details222.ColorScheme.GetColorFor("gradient-background") + local gradientBelow = DetailsFramework:CreateTexture(breakdownWindowFrame.playerScrollBox, + {gradient = "vertical", fromColor = gradientStartColor, toColor = "transparent"}, 1, 90, "artwork", {0, 1, 0, 1}) + gradientBelow:SetPoint("bottoms", 1, 1) +end - local updatePlayerLine = function(self, topResult, encounterId, difficultyId) --~update - local playerSelected = Details:GetActorObjectFromBreakdownWindow() - if (playerSelected and playerSelected == self.playerObject) then - self:SetBackdropColor(unpack(scrollbox_line_backdrop_color_selected)) - self.isSelected = true - else - self:SetBackdropColor(unpack(scrollbox_line_backdrop_color)) - self.isSelected = nil - end - - local specRole - - --adjust the player icon - if (self.playerObject.spellicon) then - self.specIcon:SetTexture(self.playerObject.spellicon) - self.specIcon:SetTexCoord(.1, .9, .1, .9) - else - local specIcon, L, R, T, B = Details:GetSpecIcon(self.playerObject.spec, false) - - if (specIcon) then - self.specIcon:SetTexture(specIcon) - self.specIcon:SetTexCoord(L, R, T, B) - - if (DetailsFramework.IsTimewalkWoW()) then - specRole = "NONE" - else - ---@type number - local spec = self.playerObject.spec - if (spec) then - specRole = select(5, _G.GetSpecializationInfoByID(self.playerObject.spec)) - end - end - else - self.specIcon:SetTexture("") - end - end - - --adjust the role icon - if (specRole) then - local roleIcon, L, R, T, B = Details:GetRoleIcon(specRole) - if (roleIcon) then - self.roleIcon:SetTexture(roleIcon) - self.roleIcon:SetTexCoord(L, R, T, B) - else - self.roleIcon:SetTexture("") - end - else - self.roleIcon:SetTexture("") - end - - local playerGear = openRaidLib and openRaidLib.GetUnitGear(self.playerObject.nome) - - --do not show the role icon - self.roleIcon:SetTexture("") --not in use - - --set the player name - self.playerName:SetText(Details:GetOnlyName(self.playerObject.nome)) - self.rankText:SetText(self.index) --not in use - - --set the player class name - --self.className:SetText(string.lower(_G.UnitClass(self.playerObject.nome) or self.playerObject:Class())) --not in use - - --item level - self.itemLevelText:SetText(self.playerObject.ilvl or (playerGear and playerGear.ilevel) or "0") - - local actorSpecId = self.playerObject.spec - local actorTotal = self.playerObject.total - local combatObject = self.combatObject - - --warcraftlogs percentile - if (self.playerObject.tipo == DETAILS_ATTRIBUTE_DAMAGE) then - local actorDPS = self.playerObject.total / combatObject:GetCombatTime() - - local parsePercent = Details222.WarcraftLogs.GetDamageParsePercent(encounterId, difficultyId, actorSpecId, actorDPS) - if (parsePercent) then - parsePercent = math.floor(parsePercent) - local colorName = Details222.WarcraftLogs.GetParseColor(parsePercent) - self.percentileText:SetTextColor(detailsFramework:ParseColors(colorName)) - self.percentileText:SetText(math.floor(parsePercent)) - self.percentileText.alpha = 1 - else - parsePercent = Details222.ParsePercent.GetPercent(DETAILS_ATTRIBUTE_DAMAGE, difficultyId, encounterId, actorSpecId, actorDPS) - if (parsePercent) then - parsePercent = math.floor(parsePercent) - local colorName = Details222.WarcraftLogs.GetParseColor(parsePercent) - self.percentileText:SetTextColor(detailsFramework:ParseColors(colorName)) - self.percentileText:SetText(math.floor(parsePercent)) - self.percentileText.alpha = 1 - else - self.percentileText:SetText("#.def") - self.percentileText:SetAlpha(0.25) - end - end - else - self.percentileText:SetText("#.def") - self.percentileText:SetAlpha(0.25) - end - - --set the statusbar - local r, g, b = self.playerObject:GetClassColor() - self.totalStatusBar:SetStatusBarColor(r, g, b, 1) - self.totalStatusBar:SetMinMaxValues(0, topResult) - self.totalStatusBar:SetValue(actorTotal) - end - - --get a Details! window - local lowerInstanceId = Details:GetLowerInstanceNumber() - local fontFile - local fontSize - local fontOutline - - if (lowerInstanceId) then - local instance = Details:GetInstance(lowerInstanceId) - if (instance) then - fontFile = instance.row_info.font_face - fontSize = instance.row_info.font_size - fontOutline = instance.row_info.textL_outline - end - end - - local createPlayerLine = function(self, index) - --create a new line - local line = _G.CreateFrame("button", "$parentLine" .. index, self, "BackdropTemplate") - detailsFramework:Mixin(line, detailsFramework.HeaderFunctions) - - local upFrame = CreateFrame("frame", nil, line) - upFrame:SetFrameLevel(line:GetFrameLevel()+2) - upFrame:SetAllPoints() - - --set its parameters - line:SetPoint("topleft", self, "topleft", 1, -((index) * (player_line_height+1)) - 1) - line:SetSize(scrollbox_size[1], player_line_height) - --line:SetSize(scrollbox_size[1]-19, player_line_height) - line:RegisterForClicks("LeftButtonDown", "RightButtonDown") - - line:SetScript("OnEnter", lineOnEnter) - line:SetScript("OnLeave", lineOnLeave) - line:SetScript("OnClick", lineOnClick) - - detailsFramework:ApplyStandardBackdrop(line) - - local specIcon = upFrame:CreateTexture("$parentSpecIcon", "artwork") - specIcon:SetSize(headerTable[1].width - 1, headerTable[1].width - 1) - specIcon:SetAlpha(0.71) - - local roleIcon = upFrame:CreateTexture("$parentRoleIcon", "overlay") - roleIcon:SetSize((player_line_height-2) / 2, (player_line_height-2) / 2) - roleIcon:SetAlpha(0.71) - - local playerName = detailsFramework:CreateLabel(upFrame, "", 11, "white", "GameFontNormal") - if (fontFile) then - playerName.fontface = fontFile - end - if (fontSize) then - playerName.fontsize = fontSize - end - if (fontOutline) then - playerName.outline = fontOutline - end - - --~create - playerName.textcolor = {1, 1, 1, .9} - - local className = detailsFramework:CreateLabel(upFrame, "", "GameFontNormal") - className.textcolor = {.95, .8, .2, 0} - className.textsize = 9 - - local itemLevelText = detailsFramework:CreateLabel(upFrame, "", "GameFontNormal") - itemLevelText.textcolor = {1, 1, 1, .7} - itemLevelText.textsize = 11 - - local percentileText = detailsFramework:CreateLabel(upFrame, "", "GameFontNormal") - percentileText.textcolor = {1, 1, 1, .7} - percentileText.textsize = 11 - - local rankText = detailsFramework:CreateLabel(upFrame, "", "GameFontNormal") - rankText.textcolor = {.3, .3, .3, .7} - rankText.textsize = fontSize - - local totalStatusBar = CreateFrame("statusbar", nil, line) - totalStatusBar:SetSize(scrollbox_size[1]-player_line_height, 4) - totalStatusBar:SetMinMaxValues(0, 100) - totalStatusBar:SetStatusBarTexture([[Interface\AddOns\Details\images\bar_skyline]]) - totalStatusBar:SetFrameLevel(line:GetFrameLevel()+1) - totalStatusBar:SetAlpha(0.5) - - --setup anchors - --specIcon:SetPoint("topleft", line, "topleft", 0, 0) - --roleIcon:SetPoint("topleft", specIcon, "topright", 2, 0) - --playerName:SetPoint("topleft", specIcon, "topright", 2, -3) - --className:SetPoint("topleft", roleIcon, "bottomleft", 0, -2) - --rankText:SetPoint("right", line, "right", -2, 0) - totalStatusBar:SetPoint("bottomleft", specIcon, "bottomright", 0, 0) - - line.specIcon = specIcon - line.roleIcon = roleIcon - line.playerName = playerName - line.className = className - line.rankText = rankText - line.totalStatusBar = totalStatusBar - line.itemLevelText = itemLevelText - line.percentileText = percentileText - - line:AddFrameToHeaderAlignment(specIcon) - line:AddFrameToHeaderAlignment(playerName) - line:AddFrameToHeaderAlignment(itemLevelText) - line:AddFrameToHeaderAlignment(percentileText) - - line:AlignWithHeader(f.Header, "left") - - line.UpdateLine = updatePlayerLine - - return line - end - - local playerScroll = detailsFramework:CreateScrollBox(f, "$parentPlayerScrollBox", refreshScrollFunc, {}, player_scroll_size[1] + 22, player_scroll_size[2], scrollbox_lines, player_line_height) - detailsFramework:ReskinSlider(playerScroll) - playerScroll.ScrollBar:ClearAllPoints() - playerScroll.ScrollBar:SetPoint("topright", playerScroll, "topright", -2, -37) - playerScroll.ScrollBar:SetPoint("bottomright", playerScroll, "bottomright", -2, 17) - playerScroll.ScrollBar:Hide() - playerScroll:SetPoint("topright", f, "topleft", -1, 0) - playerScroll:SetPoint("bottomright", f, "bottomleft", -1, 0) - playerScroll:SetBackdrop({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true}) - playerScroll:SetBackdropColor(0, 0, 0, 0.2) - playerScroll:SetBackdropBorderColor(0, 0, 0, 1) - f.playerScrollBox = playerScroll - - --need to be created before - f.Header = DetailsFramework:CreateHeader(f, headerTable, headerOptions) - f.Header:SetPoint("topleft", playerScroll, "topleft", 0, -1) - f.Header:SetPoint("topright", playerScroll, "topright", 0, -1) - - detailsFramework:ApplyStandardBackdrop(f.Header) - f.Header.__background:SetColorTexture(.60, .60, .60) - - local playerSelectionLabel = detailsFramework:CreateLabel(playerScroll, "Click to select a player", 14) - playerSelectionLabel:SetPoint("bottom", playerScroll, "bottom", 0, 7) - - --create the scrollbox lines - for i = 1, scrollbox_lines do - playerScroll:CreateLine(createPlayerLine) - end - - local classIds = { - WARRIOR = 1, - PALADIN = 2, - HUNTER = 3, - ROGUE = 4, - PRIEST = 5, - DEATHKNIGHT = 6, - SHAMAN = 7, - MAGE = 8, - WARLOCK = 9, - MONK = 10, - DRUID = 11, - DEMONHUNTER = 12, - EVOKER = 13, - } - - --get the player list from the segment and build a table compatible with the scroll box - function breakdownWindowPlayerList.BuildPlayerList() - ---@type combat - local combatObject = Details:GetCombatFromBreakdownWindow() - local playerTable = {} - - if (combatObject) then - local displayType = Details:GetDisplayTypeFromBreakdownWindow() - local containerType = displayType == 1 and DETAILS_ATTRIBUTE_DAMAGE or DETAILS_ATTRIBUTE_HEAL - ---@type actorcontainer - local actorContainer = combatObject:GetContainer(containerType) - - for index, actorObject in actorContainer:ListActors() do - if (actorObject:IsPlayer() and actorObject:IsGroupPlayer()) then - local unitClassID = classIds[actorObject:Class()] or 13 - local unitName = actorObject:Name() - local playerPosition = (((unitClassID or 0) + 128) ^ 4) + tonumber(string.byte(unitName, 1) .. "" .. string.byte(unitName, 2)) - - ---@type {key1: actor, key2: number, key3: number} - local data = {actorObject, playerPosition, actorObject.total} - tinsert(playerTable, data) - end - end - end - - table.sort(playerTable, detailsFramework.SortOrder3) - - local resultTable = {} - for i = 1, #playerTable do - resultTable[#resultTable+1] = playerTable[i][1] - end - - return resultTable - end - - local updatePlayerList = function() - local playerList = breakdownWindowPlayerList.BuildPlayerList() - playerScroll:SetData(playerList) - playerScroll:Refresh() - playerScroll:Show() - end - - function Details:UpdateBreakdownPlayerList() - --run the update on the next tick - C_Timer.After(0, updatePlayerList) - --DF.Schedules.RunNextTick(updatePlayerList) - end - - f:HookScript("OnShow", function() - Details:UpdateBreakdownPlayerList() - end) - - f:HookScript("OnHide", function() - for lineIndex, line in ipairs(f.playerScrollBox:GetLines()) do - line.playerObject = nil - line.combatObject = nil - end - end) - - local gradientStartColor = Details222.ColorScheme.GetColorFor("gradient-background") - local gradientBelow = DetailsFramework:CreateTexture(f.playerScrollBox, - {gradient = "vertical", fromColor = gradientStartColor, toColor = "transparent"}, 1, 90, "artwork", {0, 1, 0, 1}) - gradientBelow:SetPoint("bottoms", 1, 1) - end - - function Details.PlayerBreakdown.CreatePlayerListFrame() - if (not Details.PlayerBreakdown.playerListFrameCreated) then - breakdownWindowPlayerList.CreatePlayerListFrame() - Details.PlayerBreakdown.playerListFrameCreated = true - end - end \ No newline at end of file +function Details.PlayerBreakdown.CreatePlayerListFrame() + if (not Details.PlayerBreakdown.playerListFrameCreated) then + breakdownWindowPlayerList.CreatePlayerListFrame() + Details.PlayerBreakdown.playerListFrameCreated = true + end +end \ No newline at end of file diff --git a/frames/window_breakdown/window_playerbreakdown_spells.lua b/frames/window_breakdown/window_playerbreakdown_spells.lua index ef82772d..1f09ffd1 100644 --- a/frames/window_breakdown/window_playerbreakdown_spells.lua +++ b/frames/window_breakdown/window_playerbreakdown_spells.lua @@ -14,7 +14,7 @@ local _GetSpellInfo = Details.GetSpellInfo local GameTooltip = GameTooltip local IsShiftKeyDown = IsShiftKeyDown local DF = DetailsFramework -local tinsert = tinsert +local tinsert = table.insert ---@type breakdownspelltab local spellsTab = {} @@ -97,9 +97,9 @@ function spellsTab.GetPhaseScrollFrame() return spellsTab.PhaseScrollFrame end ----@return breakdowngenericscrollframe +---@return breakdowngenericscrollframe, breakdowngenericscrollframe function spellsTab.GetGenericScrollFrame() - return spellsTab.GenericScrollFrame + return spellsTab.GenericScrollFrameLeft, spellsTab.GenericScrollFrameRight end ---@return df_framecontainer @@ -122,9 +122,9 @@ function spellsTab.GetPhaseScrollContainer() return spellsTab.PhaseContainerFrame end ----@return df_framecontainer +---@return df_framecontainer leftContainer, df_framecontainer rightContainer function spellsTab.GetGenericScrollContainer() - return spellsTab.GenericContainerFrame + return spellsTab.GenericContainerFrameLeft, spellsTab.GenericContainerFrameRight end function spellsTab.GetScrollFrameByContainerType(containerType) @@ -137,8 +137,13 @@ function spellsTab.GetScrollFrameByContainerType(containerType) elseif (containerType == "phases") then return spellsTab.GetPhaseScrollFrame() - elseif (containerType == "generic") then - return spellsTab.GetGenericScrollFrame() + elseif (containerType == "generic_left") then + local scrollFrameLeft = spellsTab.GetGenericScrollFrame() + return scrollFrameLeft + + elseif (containerType == "generic_right") then + local _, scrollFrameRight = spellsTab.GetGenericScrollFrame() + return scrollFrameRight end end @@ -147,7 +152,8 @@ function spellsTab.OnProfileChange() spellsTab.UpdateHeadersSettings("spells") spellsTab.UpdateHeadersSettings("targets") spellsTab.UpdateHeadersSettings("phases") - spellsTab.UpdateHeadersSettings("generic") + spellsTab.UpdateHeadersSettings("generic_left") + spellsTab.UpdateHeadersSettings("generic_right") end ------------------------------------------------------------------------------------------------------------------------------------------------ @@ -206,6 +212,7 @@ local targetContainerColumnData = { {name = "overheal", label = "overheal", key = "overheal", width = 70, align = "left", enabled = true, canSort = true, sortKey = "total", dataType = "number", order = "DESC", offset = columnOffset, attribute = DETAILS_ATTRIBUTE_HEAL}, {name = "percent", label = "%", key = "total", width = 50, align = "left", enabled = true, canSort = true, offset = columnOffset, order = "DESC", dataType = "number"}, } +spellsTab.targetContainerColumnData = targetContainerColumnData local phaseContainerColumnData = { {name = "icon", width = 22, label = "", align = "left", enabled = true, offset = columnOffset}, @@ -215,19 +222,32 @@ local phaseContainerColumnData = { {name = "persecond", label = "ps", key = "total", width = 44, align = "left", enabled = true, canSort = true, sortKey = "ps", dataType = "number", order = "DESC", offset = columnOffset}, {name = "percent", label = "%", key = "total", width = 44, align = "left", enabled = true, canSort = true, sortKey = "total", dataType = "number", order = "DESC", offset = columnOffset}, } +spellsTab.phaseContainerColumnData = phaseContainerColumnData --generic container can show data from any attribute -local genericContainerColumnData = { +local genericContainerLeftColumnData = { {name = "icon", width = 22, label = "", align = "left", enabled = true, offset = columnOffset}, - {name = "name", label = "name", width = 200, align = "left", enabled = true, offset = columnOffset}, {name = "rank", label = "#", width = 30, align = "left", enabled = true, offset = columnOffset}, + {name = "name", label = "name", width = 200, align = "left", enabled = true, offset = columnOffset}, {name = "amount", label = "total", key = "total", width = 50, align = "left", enabled = true, canSort = true, sortKey = "total", dataType = "number", order = "DESC", offset = columnOffset, selected = true}, {name = "persecond", label = "ps", key = "total", width = 50, align = "left", enabled = true, canSort = true, sortKey = "ps", dataType = "number", order = "DESC", offset = columnOffset}, {name = "percent", label = "%", key = "total", width = 50, align = "left", enabled = true, canSort = true, sortKey = "total", dataType = "number", order = "DESC", offset = columnOffset}, } +spellsTab.genericContainerLeftColumnData = genericContainerLeftColumnData + +--generic container can show data from any attribute +local genericContainerRightColumnData = { + {name = "icon", width = 22, label = "", align = "left", enabled = true, offset = columnOffset}, + {name = "rank", label = "#", width = 30, align = "left", enabled = true, offset = columnOffset}, + {name = "name", label = "name", width = 190, align = "left", enabled = true, offset = columnOffset}, + {name = "amount", label = "total", key = "total", width = 50, align = "left", enabled = true, canSort = true, sortKey = "total", dataType = "number", order = "DESC", offset = columnOffset, selected = true}, + {name = "persecond", label = "ps", key = "total", width = 50, align = "left", enabled = true, canSort = true, sortKey = "total", dataType = "number", order = "DESC", offset = columnOffset}, + {name = "percent", label = "%", key = "total", width = 50, align = "left", enabled = true, canSort = true, sortKey = "total", dataType = "number", order = "DESC", offset = columnOffset}, +} +spellsTab.genericContainerRightColumnData = genericContainerRightColumnData ---get the header settings from details saved variables and the container column data ----@param containerType "spells"|"targets"|"phases"|"generic" +---@param containerType "spells"|"targets"|"phases"|"generic_left"|"generic_right ---@return headercolumndatabase ---@return columndata function spellsTab.GetHeaderSettings(containerType) @@ -247,9 +267,25 @@ function spellsTab.GetHeaderSettings(containerType) settings = Details.breakdown_spell_tab.phasecontainer_headers containerColumnData = phaseContainerColumnData - elseif (containerType == "generic") then + elseif (containerType == "generic_left") then settings = Details.breakdown_spell_tab.genericcontainer_headers - containerColumnData = genericContainerColumnData + containerColumnData = genericContainerLeftColumnData + + --as the generic data is received, it may have which columns can be shown + if (spellsTab.headersAllowed) then + for index, columnData in ipairs(containerColumnData) do + local newEnabledState = spellsTab.headersAllowed[columnData.name] or false + columnData.enabled = newEnabledState + --check if the settings already has the data, and then set the header enabled value to follow the headersAllowed table + if (settings[columnData.name]) then + settings[columnData.name].enabled = newEnabledState + end + end + end + + elseif (containerType == "generic_right") then + settings = Details.breakdown_spell_tab.genericcontainer_headers_right + containerColumnData = genericContainerRightColumnData --as the generic data is received, it may have which columns can be shown if (spellsTab.headersAllowed) then @@ -274,7 +310,7 @@ end ---@param columnName string ---@param value any function spellsTab.OnHeaderColumnOptionChanged(headerFrame, optionName, columnName, value) - ---@type "spells"|"targets"|"phases"|"generic" + ---@type "spells"|"targets"|"phases"|"generic_left"|"generic_right" local containerType = headerContainerType[headerFrame] ---@type headercolumndatabase local settings = spellsTab.GetHeaderSettings(containerType) @@ -283,14 +319,14 @@ function spellsTab.OnHeaderColumnOptionChanged(headerFrame, optionName, columnNa spellsTab.UpdateHeadersSettings(containerType) end -local onAnyColumnHeaderClickCallback = function() +function spellsTab.OnAnyColumnHeaderClickCallback() local instance = spellsTab.GetInstance() instance:RefreshWindow(true) end ---copy settings from the ColumnInfo table which doesn't exists in the details profile ---this is called when the profile changes or when the tab is opened with a different actor than before ----@param containerType "spells"|"targets"|"phases"|"generic" +---@param containerType "spells"|"targets"|"phases"|"generic_left"|"generic_right" function spellsTab.UpdateHeadersSettings(containerType) ---details table which hold the settings for a container header local settings, containerColumnData = spellsTab.GetHeaderSettings(containerType) @@ -350,7 +386,11 @@ function spellsTab.UpdateHeadersSettings(containerType) spellsTab.phasesHeaderData = spellsTab.BuildHeaderTable(containerType) spellsTab.GetPhaseScrollFrame().Header:SetHeaderTable(spellsTab.phasesHeaderData) - elseif (containerType == "generic") then + elseif (containerType == "generic_left") then + spellsTab.genericHeaderData = spellsTab.BuildHeaderTable(containerType) + spellsTab.GetGenericScrollFrame().Header:SetHeaderTable(spellsTab.genericHeaderData) + + elseif (containerType == "generic_right") then spellsTab.genericHeaderData = spellsTab.BuildHeaderTable(containerType) spellsTab.GetGenericScrollFrame().Header:SetHeaderTable(spellsTab.genericHeaderData) end @@ -358,7 +398,7 @@ end ---get the header settings from details profile and build a header table using the table which store all headers columns information ---the data for each header is stored on 'spellContainerColumnInfo' and 'targetContainerColumnInfo' variables ----@param containerType "spells"|"targets"|"phases"|"generic" +---@param containerType "spells"|"targets"|"phases"|"generic_left"|"generic_right" ---@return {name: string, width: number, text: string, align: string}[] function spellsTab.BuildHeaderTable(containerType) ---@type headercolumndata[] @@ -479,7 +519,8 @@ function spellsTab.OnShownTab() spellsTab.UpdateHeadersSettings("spells") spellsTab.UpdateHeadersSettings("targets") spellsTab.UpdateHeadersSettings("phases") - spellsTab.UpdateHeadersSettings("generic") + spellsTab.UpdateHeadersSettings("generic_left") + spellsTab.UpdateHeadersSettings("generic_right") end ---called when the tab is getting created, run only once @@ -500,7 +541,7 @@ function spellsTab.OnCreateTabCallback(tabButton, tabFrame) --~init --create phases container spellsTab.CreatePhasesContainer(tabFrame) --create generic container - spellsTab.CreateGenericContainer(tabFrame) + spellsTab.CreateGenericContainers(tabFrame) --create the report buttons for each container --spellsTab.CreateReportButtons(tabFrame) @@ -523,1221 +564,6 @@ function spellsTab.OnCreateTabCallback(tabButton, tabFrame) --~init --]=] end ---------------------------------------------------------------------------------------------------- ---Targets - - ----get a target bar from the scroll box, if it doesn't exist, return nil ----@param scrollFrame table ----@param lineIndex number ----@return breakdowntargetbar -local getTargetBar = function(scrollFrame, lineIndex) - ---@type breakdowntargetbar - local targetBar = scrollFrame:GetLine(lineIndex) - - --reset header alignment - targetBar:ResetFramesToHeaderAlignment() - - spellsTab.UpdateBarSettings(targetBar) - - --reset columns, hiding them - targetBar.Icon:Hide() - for inLineIndex = 1, #targetBar.InLineTexts do - targetBar.InLineTexts[inLineIndex]:SetText("") - end - - return targetBar -end - - ----update a line using the data passed ----@param targetBar breakdowntargetbar ----@param index number spell position (from best to wrost) ----@param combatObject combat ----@param scrollFrame table ----@param headerTable table ----@param bkTargetData breakdowntargettable ----@param totalValue number ----@param topValue number the amount done of the first target, used to calculate the length of the statusbar ----@param sortKey string -local updateTargetBar = function(targetBar, index, combatObject, scrollFrame, headerTable, bkTargetData, totalValue, topValue, sortKey) --~target ~update ~targetbar ~updatetargetbar - --scrollFrame is defined as a table which is false, scrollFrame is a frame - - local textIndex = 1 - - for headerIndex = 1, #headerTable do - ---@type number - local value - - targetBar.bkTargetData = bkTargetData - value = bkTargetData.total - - ---@type number - local combatTime = combatObject:GetCombatTime() - - local actorContainer = combatObject:GetContainer(spellsTab.mainAttribute) - local targetActorObject = actorContainer:GetActor(bkTargetData.name) - - targetBar.statusBar.backgroundTexture:SetAlpha(Details.breakdown_spell_tab.spellbar_background_alpha) - - --statusbar size by percent - if (topValue > 0) then - targetBar.statusBar:SetValue(bkTargetData[sortKey] / topValue * 100) - else - targetBar.statusBar:SetValue(0) - end - - --statusbar color - targetBar.statusBar:SetStatusBarColor(1, 1, 1, 1) - targetBar.combatTime = combatTime - targetBar.actorName = bkTargetData.name - - ---@type fontstring - local text = targetBar.InLineTexts[textIndex] - local header = headerTable[headerIndex] - - if (header.name == "icon") then --ok - targetBar.Icon:Show() - - if (targetActorObject) then - Details.SetClassIcon(targetActorObject, targetBar.Icon, spellsTab.GetInstance(), targetActorObject:Class()) - else - targetBar.Icon:SetTexture([[Interface\AddOns\Details\images\classes_small_alpha]]) - ---@type {key1: number, key2: number, key3: number, key4: number} - local texCoords = Details.class_coords["ENEMY"] - targetBar.Icon:SetTexCoord(unpack(texCoords)) - end - - targetBar:AddFrameToHeaderAlignment(targetBar.Icon) - - elseif (header.name == "rank") then --ok - text:SetText(index) - targetBar:AddFrameToHeaderAlignment(text) - targetBar.rank = index - textIndex = textIndex + 1 - - elseif (header.name == "name") then --ok - text:SetText(DF:RemoveRealmName(bkTargetData.name)) - targetBar.name = bkTargetData.name - targetBar:AddFrameToHeaderAlignment(text) - textIndex = textIndex + 1 - - elseif (header.name == "amount") then --ok - text:SetText(Details:Format(value)) - targetBar:AddFrameToHeaderAlignment(text) - textIndex = textIndex + 1 - - elseif (header.name == "percent") then --ok - targetBar.percent = value / totalValue * 100 --totalValue is nil - ---@type string - local percentFormatted = string.format("%.1f", targetBar.percent) .. "%" - text:SetText(percentFormatted) - - targetBar:AddFrameToHeaderAlignment(text) - textIndex = textIndex + 1 - - elseif (header.name == "overheal" and bkTargetData.overheal) then - if (bkTargetData.overheal > 0) then - local totalHeal = bkTargetData.overheal + value - text:SetText(string.format("%.1f", bkTargetData.overheal / totalHeal * 100) .. "%") - else - text:SetText("0%") - end - targetBar:AddFrameToHeaderAlignment(text) - textIndex = textIndex + 1 - - elseif (header.name == "absorbed") then - text:SetText(Details:Format(bkTargetData.absorbed or 0)) - targetBar:AddFrameToHeaderAlignment(text) - textIndex = textIndex + 1 - end - end - - targetBar:AlignWithHeader(scrollFrame.Header, "left") -end - ----refresh the data shown in the spells scroll box ----@param scrollFrame table ----@param scrollData breakdowntargettablelist ----@param offset number ----@param totalLines number -local refreshTargetsFunc = function(scrollFrame, scrollData, offset, totalLines) --~refresh ~target ~refreshtargets - ---@type number - local topValue = scrollFrame.topValue - ---@type number - local totalValue = scrollData.totalValue - ---@type actor - local actorObject = spellsTab.GetActor() - ---@type string - local actorName = actorObject:Name() - ---@type combat - local combatObject = spellsTab.GetCombat() - ---@type instance - local instanceObject = spellsTab.GetInstance() - - ---@type number - local mainAttribute = spellsTab.mainAttribute - - local sortKey = scrollFrame.SortKey - local headerTable = spellsTab.targetsHeaderData - - local lineIndex = 1 - - for i = 1, totalLines do - local index = i + offset - - ---@type breakdowntargettable - local bkTargetData = scrollData[index] - if (bkTargetData) then - ---called mainSpellBar because it is the line that shows the sum of all spells merged (if any) - ---@type breakdowntargetbar - local targetBar = getTargetBar(scrollFrame, lineIndex) - do - if (targetBar) then - lineIndex = lineIndex + 1 - updateTargetBar(targetBar, index, combatObject, scrollFrame, headerTable, bkTargetData, totalValue, topValue, sortKey) - end - end - - if (lineIndex > totalLines) then - break - end - end - end -end - ----create a targetbar within the target scroll ----@param self breakdownphasescrollframe ----@param index number ----@return breakdownphasebar -function spellsTab.CreatePhaseBar(self, index) --~create ~createphase ~phasebar - ---@type breakdownphasebar - local phaseBar = CreateFrame("button", self:GetName() .. "PhaseBarButton" .. index, self) - phaseBar.index = index - - --size and positioning - phaseBar:SetHeight(CONST_SPELLSCROLL_LINEHEIGHT) - local y = (index-1) * CONST_SPELLSCROLL_LINEHEIGHT * -1 + (1 * -index) - 15 - phaseBar:SetPoint("topleft", self, "topleft", 1, y) - phaseBar:SetPoint("topright", self, "topright", -1, y) - - phaseBar:EnableMouse(true) - - phaseBar:SetAlpha(0.823) - phaseBar:SetFrameStrata("HIGH") - phaseBar:SetScript("OnEnter", nil) - phaseBar:SetScript("OnLeave", nil) - - DF:Mixin(phaseBar, DF.HeaderFunctions) - - ---@type breakdownspellbarstatusbar - local statusBar = CreateFrame("StatusBar", "$parentStatusBar", phaseBar) - statusBar:SetAllPoints() - statusBar:SetAlpha(0.5) - statusBar:SetMinMaxValues(0, 100) - statusBar:SetValue(50) - statusBar:EnableMouse(false) - statusBar:SetFrameLevel(phaseBar:GetFrameLevel() - 1) - phaseBar.statusBar = statusBar - - ---@type texture this is the statusbar texture - local statusBarTexture = statusBar:CreateTexture("$parentTexture", "artwork") - statusBarTexture:SetTexture(SharedMedia:Fetch("statusbar", "Details Hyanda")) - statusBar:SetStatusBarTexture(statusBarTexture) - statusBar:SetStatusBarColor(1, 1, 1, 1) - - ---@type texture shown when the mouse hoverover this bar - local hightlightTexture = statusBar:CreateTexture("$parentTextureHighlight", "highlight") - hightlightTexture:SetColorTexture(1, 1, 1, 0.2) - hightlightTexture:SetAllPoints() - statusBar.highlightTexture = hightlightTexture - - ---@type texture background texture - local backgroundTexture = statusBar:CreateTexture("$parentTextureBackground", "border") - backgroundTexture:SetAllPoints() - backgroundTexture:SetColorTexture(.05, .05, .05) - backgroundTexture:SetAlpha(1) - statusBar.backgroundTexture = backgroundTexture - - --create an icon - ---@type texture - local icon = statusBar:CreateTexture("$parentTexture", "overlay") - icon:SetPoint("left", statusBar, "left", 0, 0) - icon:SetSize(CONST_SPELLSCROLL_LINEHEIGHT-2, CONST_SPELLSCROLL_LINEHEIGHT-2) - icon:SetTexCoord(.1, .9, .1, .9) - phaseBar.Icon = icon - - phaseBar:AddFrameToHeaderAlignment(icon) - - phaseBar.InLineTexts = {} - - for i = 1, 5 do - ---@type fontstring - local fontString = phaseBar:CreateFontString("$parentFontString" .. i, "overlay", "GameFontHighlightSmall") - fontString:SetJustifyH("left") - fontString:SetTextColor(1, 1, 1, 1) - fontString:SetNonSpaceWrap(true) - fontString:SetWordWrap(false) - phaseBar["lineText" .. i] = fontString - phaseBar.InLineTexts[i] = fontString - fontString:SetTextColor(1, 1, 1, 1) - phaseBar:AddFrameToHeaderAlignment(fontString) - end - - phaseBar:AlignWithHeader(self.Header, "left") - - return phaseBar -end - ----get a generic bar from the scroll box, if it doesn't exist, return nil ----@param scrollFrame table ----@param lineIndex number ----@return breakdownphasebar -local getGenericBar = function(scrollFrame, lineIndex) - ---@type breakdowngenericbar - local genericBar = scrollFrame:GetLine(lineIndex) - - --reset header alignment - genericBar:ResetFramesToHeaderAlignment() - - --reset columns, hiding them - genericBar.Icon:Hide() - for inLineIndex = 1, #genericBar.InLineTexts do - genericBar.InLineTexts[inLineIndex]:SetText("") - end - - return genericBar -end - ----get a spell bar from the scroll box, if it doesn't exist, return nil ----@param scrollFrame table ----@param lineIndex number ----@return breakdownphasebar -local getPhaseBar = function(scrollFrame, lineIndex) - ---@type breakdownphasebar - local phaseBar = scrollFrame:GetLine(lineIndex) - - --reset header alignment - phaseBar:ResetFramesToHeaderAlignment() - - spellsTab.UpdateBarSettings(phaseBar) - - --reset columns, hiding them - phaseBar.Icon:Hide() - for inLineIndex = 1, #phaseBar.InLineTexts do - phaseBar.InLineTexts[inLineIndex]:SetText("") - end - - return phaseBar -end - ----@param scrollFrame table ----@param scrollData table ----@param offset number ----@param totalLines number -local refreshGenericFunc = function(scrollFrame, scrollData, offset, totalLines) --~refreshgeneric ~refreshfunc ~refresh ~refreshg ~updategenericbar - local lineIndex = 1 - local combatTime = scrollData.combatTime - local totalValue = scrollData.totalValue - - for i = 1, totalLines do - local index = i + offset - local dataTable = scrollData[index] - - if (dataTable) then - local genericBar = getGenericBar(scrollFrame, lineIndex) - genericBar.statusBar:SetValue(dataTable.total / scrollFrame.topValue * 100) - - ---@type number - local textIndex = 1 - - if (scrollData.headersAllowed.icon) then - ---@type texturetable - local dataIcon = dataTable.icon - genericBar.Icon:Show() - genericBar.Icon:SetTexture(dataIcon.texture) - genericBar.Icon:SetTexCoord(dataIcon.coords.left, dataIcon.coords.right, dataIcon.coords.top, dataIcon.coords.bottom) - genericBar.Icon:SetSize(CONST_SPELLSCROLL_LINEHEIGHT-2, CONST_SPELLSCROLL_LINEHEIGHT-2) - genericBar:AddFrameToHeaderAlignment(genericBar.Icon) - end - - if (scrollData.headersAllowed.name) then - ---@type fontstring - local fontString = genericBar.InLineTexts[textIndex] - genericBar:AddFrameToHeaderAlignment(fontString) - local nameWithoutRealm = DF:RemoveRealmName(dataTable.name) - fontString:SetText(nameWithoutRealm or dataTable.name) - textIndex = textIndex + 1 - end - - if (scrollData.headersAllowed.rank) then - ---@type fontstring - local fontString = genericBar.InLineTexts[textIndex] - genericBar:AddFrameToHeaderAlignment(fontString) - fontString:SetText(index) - textIndex = textIndex + 1 - end - - if (scrollData.headersAllowed.amount) then - ---@type fontstring - local fontString = genericBar.InLineTexts[textIndex] - genericBar:AddFrameToHeaderAlignment(fontString) - fontString:SetText(Details:Format(dataTable.total)) - textIndex = textIndex + 1 - end - - if (scrollData.headersAllowed.persecond) then - ---@type fontstring - local fontString = genericBar.InLineTexts[textIndex] - genericBar:AddFrameToHeaderAlignment(fontString) - fontString:SetText(Details:Format(dataTable.total / combatTime)) - textIndex = textIndex + 1 - end - - if (scrollData.headersAllowed.percent) then - ---@type fontstring - local fontString = genericBar.InLineTexts[textIndex] - genericBar:AddFrameToHeaderAlignment(fontString) - fontString:SetText(string.format("%.1f", dataTable.total / totalValue * 100) .. "%") - textIndex = textIndex + 1 - end - - lineIndex = lineIndex + 1 - if (lineIndex > totalLines) then - break - end - end - end -end - - ----@param scrollFrame table ----@param scrollData table ----@param offset number ----@param totalLines number -local refreshPhaseFunc = function(scrollFrame, scrollData, offset, totalLines) --~refreshphases ~refreshfunc ~refresh ~refreshp ~updatephasebar - local lineIndex = 1 - local formatFunc = Details:GetCurrentToKFunction() - local phaseElapsedTime = scrollData.phaseElapsed - - for i = 1, totalLines do - local index = i + offset - local dataTable = scrollData[index] - - if (dataTable) then - local phaseBar = getPhaseBar(scrollFrame, lineIndex) - - phaseBar.statusBar:SetValue(100) - - local totalDone = dataTable.amountDone - local phaseName = dataTable.phaseName - local phaseNameFormatted = "Phase: " .. phaseName - local amountDoneFormatted = formatFunc(nil, totalDone) - local positionWithInPhase = math.floor(dataTable.positionWithInPhase) - local percentDone = string.format("%.1f", dataTable.percentDone) - - local elapsedTime = phaseElapsedTime[phaseName] - local phaseDps = formatFunc(nil, totalDone / elapsedTime) - - phaseBar.Icon:Show() - phaseBar.Icon:SetTexture([[Interface\Garrison\orderhall-missions-mechanic9]]) - phaseBar.Icon:SetTexCoord(11/64, 53/64, 11/64, 53/64) - phaseBar.Icon:SetSize(CONST_SPELLSCROLL_LINEHEIGHT-2, CONST_SPELLSCROLL_LINEHEIGHT-2) - phaseBar:AddFrameToHeaderAlignment(phaseBar.Icon) - - for inLineIndex = 1, #phaseBar.InLineTexts do - phaseBar.InLineTexts[inLineIndex]:SetText("") - end - - local text1 = phaseBar.InLineTexts[1] - phaseBar:AddFrameToHeaderAlignment(text1) - text1:SetText(phaseNameFormatted) - - local text2 = phaseBar.InLineTexts[2] - phaseBar:AddFrameToHeaderAlignment(text2) - text2:SetText("#" .. positionWithInPhase) - - local text3 = phaseBar.InLineTexts[3] - phaseBar:AddFrameToHeaderAlignment(text3) - text3:SetText(amountDoneFormatted) - - local text4 = phaseBar.InLineTexts[4] - phaseBar:AddFrameToHeaderAlignment(text4) - text4:SetText(phaseDps) - - local text5 = phaseBar.InLineTexts[5] - phaseBar:AddFrameToHeaderAlignment(text5) - text5:SetText(percentDone .. "%") - - lineIndex = lineIndex + 1 - end - end -end - ----create a container to show value per phase ----@param tabFrame tabframe ----@return breakdownphasescrollframe -function spellsTab.CreatePhasesContainer(tabFrame) --~phase ~createphasecontainer ~createphasescroll - ---@type width - local width = Details.breakdown_spell_tab.phasecontainer_width - ---@type height - local height = Details.breakdown_spell_tab.phasecontainer_height - - local defaultAmountOfLines = 10 - - --create a container for the scrollframe - local options = { - width = Details.breakdown_spell_tab.phasecontainer_width, - height = Details.breakdown_spell_tab.phasecontainer_height, - is_locked = Details.breakdown_spell_tab.phasecontainer_islocked, - can_move = false, - can_move_children = false, - use_top_resizer = true, - use_right_resizer = true, - use_left_resizer = true, - use_bottom_resizer = true, - } - - ---@type df_framecontainer - local container = DF:CreateFrameContainer(tabFrame, options, tabFrame:GetName() .. "PhaseScrollContainer") - container:SetPoint("topleft", spellsTab.GetTargetScrollContainer(), "topright", 26, 0) - container:SetFrameLevel(tabFrame:GetFrameLevel() + 10) - spellsTab.PhaseContainerFrame = container - - local settingChangedCallbackFunction = function(frameContainer, settingName, settingValue) - if (frameContainer:IsShown()) then - if (settingName == "height") then - ---@type number - local currentHeight = spellsTab.GetPhaseScrollFrame():GetHeight() - Details.breakdown_spell_tab.phasecontainer_height = settingValue - local lineAmount = math.floor(currentHeight / CONST_SPELLSCROLL_LINEHEIGHT) - spellsTab.GetPhaseScrollFrame():SetNumFramesShown(lineAmount) - - elseif (settingName == "width") then - Details.breakdown_spell_tab.phasecontainer_width = settingValue - - elseif (settingName == "is_locked") then - Details.breakdown_spell_tab.phasecontainer_islocked = settingValue - end - end - end - container:SetSettingChangedCallback(settingChangedCallbackFunction) - - ---@type breakdownphasescrollframe not sure is this is correct - local phaseScrollFrame = DF:CreateScrollBox(container, "$parentPhaseScroll", refreshPhaseFunc, {}, width, height, defaultAmountOfLines, CONST_SPELLSCROLL_LINEHEIGHT) - DF:ReskinSlider(phaseScrollFrame) - - phaseScrollFrame:SetBackdrop({}) - phaseScrollFrame:SetAllPoints() - - container:RegisterChildForDrag(phaseScrollFrame) - - phaseScrollFrame.DontHideChildrenOnPreRefresh = false - tabFrame.PhaseScrollFrame = phaseScrollFrame - spellsTab.PhaseScrollFrame = phaseScrollFrame - - spellsTab.ApplyStandardBackdrop(container, phaseScrollFrame) - - function phaseScrollFrame:RefreshMe() --~refreshme (phases) ~refreshmep - --get the value of the top 1 ranking spell - ---@type actor - local actorObject = spellsTab.GetActor() - ---@type combat - local combatObject = spellsTab.GetCombat() - local actorName = actorObject:Name() - ---@type instance - local instanceObject = spellsTab.GetInstance() - - local mainAttribute = instanceObject:GetDisplay() - - local data = { - --playerObject = playerObject, - --attribute = attribute, - --combatObject = combatObject, - combatTime = combatObject:GetCombatTime(), - } - - local playerPhases = {} - local totalDamage = 0 - local phaseElapsed = {} - - local phasesInfo = combatObject:GetPhases() - - if (not phasesInfo) then - spellsTab.PhaseContainerFrame:Hide() - return - end - - if (#phasesInfo == 1) then - --if there's only one phase, then there's no need to show phases - spellsTab.PhaseContainerFrame:Hide() - return - else - spellsTab.PhaseContainerFrame:Show() - end - - if (#phasesInfo >= 1) then - --get phase elapsed time - for i = 1, #phasesInfo do - local thisPhase = phasesInfo[i] - local phaseName = thisPhase[1] - local startTime = thisPhase[2] - - local nextPhase = phasesInfo[i + 1] - if (nextPhase) then - --if there's a next phase, use it's start time as end time to calcule elapsed time - local endTime = nextPhase[2] - local elapsedTime = endTime - startTime - phaseElapsed[phaseName] = (phaseElapsed[phaseName] or 0) + elapsedTime - else - --if there's no next phase, use the combat end time as end time to calcule elapsed time - local endTime = combatObject:GetCombatTime() - local elapsedTime = endTime - startTime - phaseElapsed[phaseName] = (phaseElapsed[phaseName] or 0) + elapsedTime - end - end - - --get damage info - local dataTable = mainAttribute == 1 and phasesInfo.damage or phasesInfo.heal - for phaseName, playersTable in pairs(dataTable) do --each phase - local allPlayers = {} --all players for this phase - for playerName, amount in pairs(playersTable) do - tinsert(allPlayers, {playerName, amount}) - totalDamage = totalDamage + amount - end - table.sort(allPlayers, function(a, b) - return a[2] > b[2] - end) - - local myRank = 0 - for i = 1, #allPlayers do - if (allPlayers[i][1] == actorName) then - myRank = i - break - end - end - - tinsert(playerPhases, {phaseName, playersTable[actorName] or 0, myRank, (playersTable[actorName] or 0) / totalDamage * 100}) - end - end - - table.sort(playerPhases, function(a, b) return a[1] < b[1] end) - - for i = 1, #playerPhases do - data[#data+1] = { - phaseName = playerPhases[i][1], - amountDone = playerPhases[i][2], - positionWithInPhase = playerPhases[i][3], - percentDone = playerPhases[i][4], - } - end - - data.totalDamage = totalDamage - data.phaseElapsed = phaseElapsed - - phaseScrollFrame:SetData(data) - phaseScrollFrame:Refresh() - end - - --~header - local headerOptions = { - padding = 2, - header_height = 14, - - reziser_shown = true, - reziser_width = 2, - reziser_color = {.5, .5, .5, 0.7}, - reziser_max_width = 246, - - header_click_callback = onAnyColumnHeaderClickCallback, - - header_backdrop_color = {0.1, 0.1, 0.1, 0.4}, - text_color = {1, 1, 1, 0.823}, - } - - ---@type df_headerframe - local header = DetailsFramework:CreateHeader(container, phaseContainerColumnData, headerOptions) - phaseScrollFrame.Header = header - phaseScrollFrame.Header:SetPoint("topleft", phaseScrollFrame, "topleft", 0, 1) - phaseScrollFrame.Header:SetColumnSettingChangedCallback(spellsTab.OnHeaderColumnOptionChanged) - - --cache the type of this container - headerContainerType[phaseScrollFrame.Header] = "phases" - - --create the scroll lines - for i = 1, defaultAmountOfLines do - phaseScrollFrame:CreateLine(spellsTab.CreatePhaseBar) - end - - tabFrame.phases = container:CreateFontString(nil, "overlay", "QuestFont_Large") - tabFrame.phases:SetPoint("bottomleft", container, "topleft", 2, 2) - tabFrame.phases:SetText("Phases:") --localize-me - - return phaseScrollFrame -end - ----create a genericbar within the generic scroll ----@param self breakdowngenericscrollframe ----@param index number ----@return breakdowngenericbar -function spellsTab.CreateGenericBar(self, index) --~create ~generic ~creategeneric ~genericbar - ---@type breakdowngenericbar - local genericBar = CreateFrame("button", self:GetName() .. "GenericBarButton" .. index, self) - genericBar.index = index - - --size and positioning - genericBar:SetHeight(CONST_SPELLSCROLL_LINEHEIGHT) - local y = (index-1) * CONST_SPELLSCROLL_LINEHEIGHT * -1 + (1 * -index) - 15 - genericBar:SetPoint("topleft", self, "topleft", 0, y) - genericBar:SetPoint("topright", self, "topright", 0, y) - - genericBar:EnableMouse(true) - - genericBar:SetAlpha(0.9) - genericBar:SetFrameStrata("HIGH") - genericBar:SetScript("OnEnter", nil) --onEnterBreakdownGenericBar - genericBar:SetScript("OnLeave", nil) --onLeaveBreakdownGenericBar - - DF:Mixin(genericBar, DF.HeaderFunctions) - - ---@type breakdownspellbarstatusbar - local statusBar = CreateFrame("StatusBar", "$parentStatusBar", genericBar) - statusBar:SetAllPoints() - statusBar:SetAlpha(0.5) - statusBar:SetMinMaxValues(0, 100) - statusBar:SetValue(50) - statusBar:EnableMouse(false) - statusBar:SetFrameLevel(genericBar:GetFrameLevel() - 1) - genericBar.statusBar = statusBar - - ---@type texture this is the statusbar texture - local statusBarTexture = statusBar:CreateTexture("$parentTexture", "artwork") - statusBarTexture:SetTexture(SharedMedia:Fetch("statusbar", "Details Hyanda")) - statusBar:SetStatusBarTexture(statusBarTexture) - statusBar:SetStatusBarColor(1, 1, 1, 1) - - ---@type texture shown when the mouse hoverover this bar - local hightlightTexture = statusBar:CreateTexture("$parentTextureHighlight", "highlight") - hightlightTexture:SetColorTexture(1, 1, 1, 0.2) - hightlightTexture:SetAllPoints() - statusBar.highlightTexture = hightlightTexture - - ---@type texture background texture - local backgroundTexture = statusBar:CreateTexture("$parentTextureBackground", "border") - backgroundTexture:SetAllPoints() - backgroundTexture:SetColorTexture(.05, .05, .05) - backgroundTexture:SetAlpha(1) - statusBar.backgroundTexture = backgroundTexture - - --create an icon - ---@type texture - local icon = statusBar:CreateTexture("$parentTexture", "overlay") - icon:SetPoint("left", statusBar, "left", 0, 0) - icon:SetSize(CONST_SPELLSCROLL_LINEHEIGHT-2, CONST_SPELLSCROLL_LINEHEIGHT-2) - icon:SetTexCoord(.1, .9, .1, .9) - genericBar.Icon = icon - - genericBar:AddFrameToHeaderAlignment(icon) - - genericBar.InLineTexts = {} - - for i = 1, 5 do - ---@type fontstring - local fontString = genericBar:CreateFontString("$parentFontString" .. i, "overlay", "GameFontHighlightSmall") - fontString:SetJustifyH("left") - fontString:SetTextColor(1, 1, 1, 1) - fontString:SetNonSpaceWrap(true) - fontString:SetWordWrap(false) - genericBar["lineText" .. i] = fontString - genericBar.InLineTexts[i] = fontString - fontString:SetTextColor(1, 1, 1, 1) - genericBar:AddFrameToHeaderAlignment(fontString) - end - - genericBar:AlignWithHeader(self.Header, "left") - - return genericBar -end - ----create the generic container, this container hold bars that can show any type of data ----@param tabFrame tabframe ----@return breakdowngenericscrollframe -function spellsTab.CreateGenericContainer(tabFrame) --~create ~generic ~creategenericcontainer ~creategenericscroll ~creategeneric - ---@type width - local width = Details.breakdown_spell_tab.genericcontainer_width - ---@type height - local height = Details.breakdown_spell_tab.genericcontainer_height - - local defaultAmountOfLines = 50 - - --create a container for the scrollframe - local options = { - width = Details.breakdown_spell_tab.genericcontainer_width, - height = Details.breakdown_spell_tab.genericcontainer_height, - is_locked = Details.breakdown_spell_tab.genericcontainer_islocked, - can_move = false, - can_move_children = false, - use_top_resizer = true, - use_right_resizer = true, - use_bottom_resizer = true, - use_left_resizer = true, - } - - ---@type df_framecontainer - local container = DF:CreateFrameContainer(tabFrame, options, tabFrame:GetName() .. "GenericScrollContainer") - container:SetPoint("topleft", tabFrame, "topleft", 0, 0) - container:SetFrameLevel(tabFrame:GetFrameLevel()+1) - spellsTab.GenericContainerFrame = container - - --when a setting is changed in the container, it will call this function, it is registered below with SetSettingChangedCallback() - local settingChangedCallbackFunction = function(frameContainer, settingName, settingValue) - if (frameContainer:IsShown()) then - if (settingName == "height") then - ---@type number - local currentHeight = spellsTab.GetGenericScrollFrame():GetHeight() - Details.breakdown_spell_tab.genericcontainer_height = settingValue - spellsTab.GetGenericScrollFrame():SetNumFramesShown(math.floor(currentHeight / CONST_SPELLSCROLL_LINEHEIGHT) - 2) - - elseif (settingName == "width") then - Details.breakdown_spell_tab.genericcontainer_width = settingValue - - elseif (settingName == "is_locked") then - Details.breakdown_spell_tab.genericcontainer_islocked = settingValue - end - - spellsTab.GetSpellBlockContainer():SendSettingChangedCallback("UpdateSize", -1) - end - end - container:SetSettingChangedCallback(settingChangedCallbackFunction) - - --create a scrollframe - local genericScrollFrame = DF:CreateScrollBox(container, "$parentGenericScroll", refreshGenericFunc, {}, width, height, defaultAmountOfLines, CONST_SPELLSCROLL_LINEHEIGHT) - DF:ReskinSlider(genericScrollFrame) - genericScrollFrame:SetBackdrop({}) - genericScrollFrame:SetAllPoints() - - container:RegisterChildForDrag(genericScrollFrame) - - genericScrollFrame.DontHideChildrenOnPreRefresh = false - tabFrame.GenericScrollFrame = genericScrollFrame - spellsTab.GenericScrollFrame = genericScrollFrame - - --settingChangedCallbackFunction(container, "height", Details.breakdown_spell_tab.genericcontainer_height) - - function genericScrollFrame:RefreshMe(data) --~refreshme (generic) ~refreshg - --get which column is currently selected and the sort order - local columnIndex, order, key = genericScrollFrame.Header:GetSelectedColumn() - genericScrollFrame.SortKey = key - - ---@type string - local keyToSort = key - - if (order == "DESC") then - table.sort(data, - function(t1, t2) - return t1[keyToSort] > t2[keyToSort] - end) - genericScrollFrame.topValue = data[1] and data[1][keyToSort] - else - table.sort(data, - function(t1, t2) - return t1[keyToSort] < t2[keyToSort] - end) - genericScrollFrame.topValue = data[#data] and data[#data][keyToSort] - end - - genericScrollFrame:SetData(data) - genericScrollFrame:Refresh() - end - - --~header - local headerOptions = { - padding = 2, - header_height = 14, - - reziser_shown = true, - reziser_width = 2, - reziser_color = {.5, .5, .5, 0.7}, - reziser_max_width = 246, - - header_click_callback = onAnyColumnHeaderClickCallback, - - header_backdrop_color = {0.1, 0.1, 0.1, 0.4}, - text_color = {1, 1, 1, 0.823}, - } - - ---@type df_headerframe - local header = DetailsFramework:CreateHeader(container, genericContainerColumnData, headerOptions) - genericScrollFrame.Header = header - genericScrollFrame.Header:SetPoint("topleft", genericScrollFrame, "topleft", 0, 1) - genericScrollFrame.Header:SetColumnSettingChangedCallback(spellsTab.OnHeaderColumnOptionChanged) - - --cache the type of this container - headerContainerType[genericScrollFrame.Header] = "generic" - - --create the scroll lines - for i = 1, defaultAmountOfLines do - genericScrollFrame:CreateLine(spellsTab.CreateGenericBar) - end - - --need to create the second scroll frame to show the details about the spelltable/actor hovered over - - return genericScrollFrame -end - ----create the target container ----@param tabFrame tabframe ----@return breakdowntargetscrollframe -function spellsTab.CreateTargetContainer(tabFrame) --~create ~target ~createtargetcontainer ~createtargetscroll ~createtarget - ---@type width - local width = Details.breakdown_spell_tab.targetcontainer_width - ---@type height - local height = Details.breakdown_spell_tab.targetcontainer_height - - local defaultAmountOfLines = 50 - - --create a container for the scrollframe - local options = { - width = Details.breakdown_spell_tab.targetcontainer_width, - height = Details.breakdown_spell_tab.targetcontainer_height, - is_locked = Details.breakdown_spell_tab.targetcontainer_islocked, - can_move = false, - can_move_children = false, - use_top_resizer = true, - use_right_resizer = true, - } - - ---@type df_framecontainer - local container = DF:CreateFrameContainer(tabFrame, options, tabFrame:GetName() .. "TargetScrollContainer") - container:SetPoint("topleft", spellsTab.GetSpellScrollContainer(), "bottomleft", 0, -25) - container:SetFrameLevel(tabFrame:GetFrameLevel() + 10) - spellsTab.TargetsContainerFrame = container - - local settingChangedCallbackFunction = function(frameContainer, settingName, settingValue) - if (frameContainer:IsShown()) then - if (settingName == "height") then - ---@type number - local currentHeight = spellsTab.GetTargetScrollFrame():GetHeight() - Details.breakdown_spell_tab.targetcontainer_height = settingValue - --the -0.1 is the avoid the random fraction of 1.9999999990 to 2.0000000001 - local lineAmount = currentHeight / CONST_SPELLSCROLL_LINEHEIGHT - 0.1 - lineAmount = math.floor(lineAmount) - spellsTab.GetTargetScrollFrame():SetNumFramesShown(lineAmount) - - elseif (settingName == "width") then - Details.breakdown_spell_tab.targetcontainer_width = settingValue - - elseif (settingName == "is_locked") then - Details.breakdown_spell_tab.targetcontainer_islocked = settingValue - end - end - end - container:SetSettingChangedCallback(settingChangedCallbackFunction) - - --create the scrollframe similar to scrollframe used in the spellscrollframe - --replace this with a framework scrollframe - ---@type breakdowntargetscrollframe - local targetScrollFrame = DF:CreateScrollBox(container, "$parentTargetScroll", refreshTargetsFunc, {}, width, height, defaultAmountOfLines, CONST_SPELLSCROLL_LINEHEIGHT) - DF:ReskinSlider(targetScrollFrame) - targetScrollFrame:SetBackdrop({}) - targetScrollFrame:SetAllPoints() - - container:RegisterChildForDrag(targetScrollFrame) - - targetScrollFrame.DontHideChildrenOnPreRefresh = false - tabFrame.TargetScrollFrame = targetScrollFrame - spellsTab.TargetScrollFrame = targetScrollFrame - - spellsTab.ApplyStandardBackdrop(container, targetScrollFrame) - - ---@param data breakdowntargettablelist - function targetScrollFrame:RefreshMe(data) --~refreshme (targets) ~refreshmet - --get which column is currently selected and the sort order - local columnIndex, order, key = targetScrollFrame.Header:GetSelectedColumn() - targetScrollFrame.SortKey = key - - ---@type string - local keyToSort = key - - if (order == "DESC") then - table.sort(data, - function(t1, t2) - return t1[keyToSort] > t2[keyToSort] - end) - targetScrollFrame.topValue = data[1] and data[1][keyToSort] - else - table.sort(data, - function(t1, t2) - return t1[keyToSort] < t2[keyToSort] - end) - targetScrollFrame.topValue = data[#data] and data[#data][keyToSort] - end - - if (key == "overheal") then - data.totalValue = data.totalValueOverheal - end - --default: data.totalValue - --data.totalValueOverheal - - targetScrollFrame:SetData(data) - targetScrollFrame:Refresh() - end - - --~header - local headerOptions = { - padding = 2, - header_height = 14, - - reziser_shown = true, - reziser_width = 2, - reziser_color = {.5, .5, .5, 0.7}, - reziser_max_width = 246, - - header_click_callback = onAnyColumnHeaderClickCallback, - - header_backdrop_color = {0.1, 0.1, 0.1, 0.4}, - text_color = {1, 1, 1, 0.823}, - } - - ---@type df_headerframe - local header = DetailsFramework:CreateHeader(container, targetContainerColumnData, headerOptions) - targetScrollFrame.Header = header - targetScrollFrame.Header:SetPoint("topleft", targetScrollFrame, "topleft", 0, 1) - targetScrollFrame.Header:SetColumnSettingChangedCallback(spellsTab.OnHeaderColumnOptionChanged) - - --cache the type of this container - headerContainerType[targetScrollFrame.Header] = "targets" - - --create the scroll lines - for i = 1, defaultAmountOfLines do - targetScrollFrame:CreateLine(spellsTab.CreateTargetBar) - end - - tabFrame.targets = targetScrollFrame:CreateFontString(nil, "overlay", "QuestFont_Large") - tabFrame.targets:SetPoint("bottomleft", container, "topleft", 2, 2) - tabFrame.targets:SetText(Loc ["STRING_TARGETS"] .. ":") - - return targetScrollFrame -end - - - - - - ----@param targetBar breakdowntargetbar -local onEnterBreakdownTargetBar = function(targetBar) - targetBar:SetAlpha(1) - - ---@type string @the name of the target - local targetName = targetBar.actorName - - Details:FormatCooltipForSpells() - GameCooltip:SetOwner(targetBar, "bottom", "top", 4, -5) - GameCooltip:SetOption("MinWidth", math.max(230, targetBar:GetWidth() * 0.98)) - - --build a list of spells which the target was hit by - local spellsSortedResult = {} - local total = 0 - - ---@type actor - local actorObject = spellsTab.GetActor() - - ---@type combat - local combatObject = spellsTab.GetCombat() - - ---@type instance - local instanceObject = spellsTab.GetInstance() - - ---@type number - local mainAttribute = instanceObject:GetDisplay() - - ---@type spellcontainer - local spellContainer = actorObject:GetSpellContainer("spell") - - local targetScrollFrame = spellsTab.GetTargetScrollFrame() - - ---@type number, string, string - local columnIndex, order, key = targetScrollFrame.Header:GetSelectedColumn() - - ---@type string the label shown at the top of the tooltip - local labelTooltipTitle = Loc ["STRING_DAMAGE_FROM"] - - local targetTableName = "targets" - if (mainAttribute == DETAILS_ATTRIBUTE_HEAL) then - if (key == "total") then - labelTooltipTitle = Loc ["STRING_HEALING_FROM"] - - elseif (key == "overheal") then - targetTableName = "targets_overheal" - labelTooltipTitle = Loc ["STRING_OVERHEALED"] - end - end - - --this part kinda belong top damage or healing class, shouldn't be here - - ---@type number, spelltable - for spellId, spellTable in spellContainer:ListActors() do - if (spellTable.isReflection) then - ---@type string, number - for spellTargetName, amount in pairs(spellTable.targets) do - if (spellTargetName == targetName) then - for reflectedSpellId, reflectedAmount in pairs(spellTable.extra) do - local spellName, _, spellIcon = _GetSpellInfo(reflectedSpellId) - table.insert(spellsSortedResult, {reflectedSpellId, reflectedAmount, spellName .. " (|cFFCCBBBBreflected|r)", spellIcon}) - total = total + reflectedAmount - end - end - end - else - for spellTargetName, amount in pairs(spellTable[targetTableName]) do - if (spellTargetName == targetName) then - local spellName, _, spellIcon = _GetSpellInfo(spellId) - table.insert(spellsSortedResult, {spellId, amount, spellName, spellIcon}) - total = total + amount - end - end - end - end - - --add pets - local petArray = actorObject:GetPets() - for _, petName in ipairs(petArray) do - local petActorObject = combatObject(mainAttribute, petName) - if (petActorObject) then - ---@type spellcontainer - local petSpellContainer = petActorObject:GetSpellContainer("spell") - - ---@type number, spelltable - for spellId, spellTable in petSpellContainer:ListActors() do - for spellTargetName, amount in pairs(spellTable[targetTableName]) do - if (spellTargetName == targetName) then - local spellName, _, spellIcon = _GetSpellInfo(spellId) - table.insert(spellsSortedResult, {spellId, amount, spellName .. " (" .. petName:gsub((" <.*"), "") .. ")", spellIcon}) - total = total + amount - end - end - end - end - end - - table.sort(spellsSortedResult, Details.Sort2) - - --need to change is this is a healing - Details:AddTooltipSpellHeaderText(labelTooltipTitle .. ":", {1, 0.9, 0.0, 1}, 1, Details.tooltip_spell_icon.file, unpack(Details.tooltip_spell_icon.coords)) - Details:AddTooltipHeaderStatusbar(1, 1, 1, 1) - - ---@type tablesize - local iconSize = Details.tooltip.icon_size - ---@type tablecoords - local iconBorder = Details.tooltip.icon_border_texcoord - - local topValue = spellsSortedResult[1] and spellsSortedResult[1][2] - - if (topValue) then - for index, tabela in ipairs(spellsSortedResult) do - local spellId, amount, spellName, spellIcon = unpack(tabela) - if (amount < 1) then - break - end - GameCooltip:AddLine(spellName, Details:Format(amount) .. " (" .. string.format("%.1f", amount / total * 100) .. "%)") - GameCooltip:AddIcon(spellIcon, nil, nil, iconSize.W + 4, iconSize.H + 4, iconBorder.L, iconBorder.R, iconBorder.T, iconBorder.B) - Details:AddTooltipBackgroundStatusbar(false, amount / topValue * 100) - end - end - - GameCooltip:Show() -end - ----@param self breakdowntargetbar -local onLeaveBreakdownTargetBar = function(self) - self:SetAlpha(0.9) - GameCooltip:Hide() -end - ----create a targetbar within the target scroll ----@param self breakdowntargetscrollframe ----@param index number ----@return breakdowntargetbar -function spellsTab.CreateTargetBar(self, index) --~create ~target ~createtarget ~targetbar - ---@type breakdowntargetbar - local targetBar = CreateFrame("button", self:GetName() .. "TargetBarButton" .. index, self) - targetBar.index = index - - --size and positioning - targetBar:SetHeight(CONST_SPELLSCROLL_LINEHEIGHT) - local y = (index-1) * CONST_SPELLSCROLL_LINEHEIGHT * -1 + (1 * -index) - 15 - targetBar:SetPoint("topleft", self, "topleft", 1, y) - targetBar:SetPoint("topright", self, "topright", -1, y) - targetBar:EnableMouse(true) - - targetBar:SetAlpha(0.823) - targetBar:SetFrameStrata("HIGH") - targetBar:SetScript("OnEnter", onEnterBreakdownTargetBar) - targetBar:SetScript("OnLeave", onLeaveBreakdownTargetBar) - - DF:Mixin(targetBar, DF.HeaderFunctions) - - ---@type breakdownspellbarstatusbar - local statusBar = CreateFrame("StatusBar", "$parentStatusBar", targetBar) - statusBar:SetAllPoints() - statusBar:SetAlpha(0.5) - statusBar:SetMinMaxValues(0, 100) - statusBar:SetValue(50) - statusBar:EnableMouse(false) - statusBar:SetFrameLevel(targetBar:GetFrameLevel() - 1) - targetBar.statusBar = statusBar - - ---@type texture this is the statusbar texture - local statusBarTexture = statusBar:CreateTexture("$parentTexture", "artwork") - statusBarTexture:SetTexture(SharedMedia:Fetch("statusbar", "Details Hyanda")) - statusBar:SetStatusBarTexture(statusBarTexture) - statusBar:SetStatusBarColor(1, 1, 1, 1) - - ---@type texture shown when the mouse hoverover this bar - local hightlightTexture = statusBar:CreateTexture("$parentTextureHighlight", "highlight") - hightlightTexture:SetColorTexture(1, 1, 1, 0.2) - hightlightTexture:SetAllPoints() - statusBar.highlightTexture = hightlightTexture - - ---@type texture background texture - local backgroundTexture = statusBar:CreateTexture("$parentTextureBackground", "border") - backgroundTexture:SetAllPoints() - backgroundTexture:SetColorTexture(.05, .05, .05) - backgroundTexture:SetAlpha(1) - statusBar.backgroundTexture = backgroundTexture - - --create an icon - ---@type texture - local icon = statusBar:CreateTexture("$parentTexture", "overlay") - icon:SetPoint("left", statusBar, "left", 0, 0) - icon:SetSize(CONST_SPELLSCROLL_LINEHEIGHT-2, CONST_SPELLSCROLL_LINEHEIGHT-2) - icon:SetTexCoord(.1, .9, .1, .9) - targetBar.Icon = icon - - targetBar:AddFrameToHeaderAlignment(icon) - - targetBar.InLineTexts = {} - - for i = 1, 5 do - ---@type fontstring - local fontString = targetBar:CreateFontString("$parentFontString" .. i, "overlay", "GameFontHighlightSmall") - fontString:SetJustifyH("left") - fontString:SetTextColor(1, 1, 1, 1) - fontString:SetNonSpaceWrap(true) - fontString:SetWordWrap(false) - targetBar["lineText" .. i] = fontString - targetBar.InLineTexts[i] = fontString - fontString:SetTextColor(1, 1, 1, 1) - targetBar:AddFrameToHeaderAlignment(fontString) - end - - targetBar:AlignWithHeader(self.Header, "left") - - return targetBar -end - - function spellsTab.UpdateBarSettings(bar) if (bar.statusBar) then bar.statusBar:SetAlpha(Details.breakdown_spell_tab.statusbar_alpha) --could be moved to when the bar is updated @@ -1747,8 +573,6 @@ function spellsTab.UpdateBarSettings(bar) end end - - ----------------------------------------------------------------------------------------------------------------------- --> create the new tab function Details.InitializeSpellBreakdownTab() @@ -1799,15 +623,19 @@ function Details.InitializeSpellBreakdownTab() spellsTab.GetSpellScrollContainer():Show() spellsTab.GetPhaseScrollContainer():Show() spellsTab.GetTargetScrollContainer():Show() + spellsTab.GetSpellBlockContainer():Show() --hide the generic container - spellsTab.GetGenericScrollContainer():Hide() + local genericScrollContainerLeft, genericScrollContainerRight = spellsTab.GetGenericScrollContainer() + genericScrollContainerLeft:Hide() + genericScrollContainerRight:Hide() --refresh the data spellsTab.GetSpellScrollFrame():RefreshMe(data) spellsTab.GetPhaseScrollFrame():RefreshMe(data) end + ---called right after the OnReceiveSpellData() call ---@param data breakdowntargettablelist ---@param actorObject actor ---@param combatObject combat @@ -1831,9 +659,13 @@ function Details.InitializeSpellBreakdownTab() spellsTab.mainAttribute = mainAttribute spellsTab.subAttribute = subAttribute + spellsTab.currentActor = actorObject + spellsTab.combatObject = combatObject + spellsTab.instance = instance + if (spellsTab.headersAllowed ~= data.headersAllowed) then --refresh the header frame - spellsTab.UpdateHeadersSettings("generic") + spellsTab.UpdateHeadersSettings("generic_left") --bug: now allowing to sort end @@ -1841,9 +673,12 @@ function Details.InitializeSpellBreakdownTab() spellsTab.GetSpellScrollContainer():Hide() spellsTab.GetPhaseScrollContainer():Hide() spellsTab.GetTargetScrollContainer():Hide() + spellsTab.GetSpellBlockContainer():Hide() --show the generic scroll - spellsTab.GetGenericScrollContainer():Show() + local genericScrollContainerLeft, genericScrollContainerRight = spellsTab.GetGenericScrollContainer() + genericScrollContainerLeft:Show() + genericScrollContainerRight:Show() --refresh the data spellsTab.GetGenericScrollFrame():RefreshMe(data) @@ -1963,7 +798,7 @@ function spellsTab.monta_relatorio(botao) --deprecated? Loc ["STRING_ACTORFRAME_SPELLDETAILS"] .. ": " .. nome} for i = 1, 5 do - local caixa = Details.playerDetailWindow.grupos_detalhes[i] + local caixa = Details.BreakdownWindowFrame.grupos_detalhes[i] if (caixa.bg:IsShown()) then local linha = "" @@ -2043,7 +878,7 @@ function spellsTab.monta_relatorio(botao) --deprecated? report_lines = {"Details! " .. Loc ["STRING_ACTORFRAME_REPORTTO"] .. " " .. Details.sub_atributos [mainSection].lista [subSection].. " " .. Loc ["STRING_ACTORFRAME_REPORTOF"] .. " " .. player.nome, Loc ["STRING_ACTORFRAME_SPELLDETAILS"] .. ": " .. nome} - local caixa = Details.playerDetailWindow.grupos_detalhes[botao] + local caixa = Details.BreakdownWindowFrame.grupos_detalhes[botao] local linha = "" local nome2 = caixa.nome2:GetText() --golpes diff --git a/frames/window_options2.lua b/frames/window_options2.lua index a40576a7..ec79d199 100644 --- a/frames/window_options2.lua +++ b/frames/window_options2.lua @@ -44,6 +44,7 @@ function Details.options.InitializeOptionsWindow(instance) f.real_name = "DETAILS_OPTIONS" f.__icon = [[Interface\Scenarios\ScenarioIcon-Interact]] _G.DetailsPluginContainerWindow.EmbedPlugin(f, f, true) + f.sectionFramesContainer = {} DF:ApplyStandardBackdrop(f) diff --git a/frames/window_options2_sections.lua b/frames/window_options2_sections.lua index 6c872784..eeeafc32 100644 --- a/frames/window_options2_sections.lua +++ b/frames/window_options2_sections.lua @@ -37,13 +37,11 @@ local LDBIcon = LDB and _G.LibStub("LibDBIcon-1.0", true) local addonName, Details222 = ... local _ = nil local unpack = _G.unpack -local tinsert = _G.tinsert +local tinsert = table.insert local startX = 200 local startY = -40 local heightSize = 540 -local optionsWidth, optionsHeight = 1100, 650 -local mainHeightSize = 800 local presetVersion = 3 --templates @@ -56,7 +54,6 @@ local options_button_template = DF:GetTemplate("button", "OPTIONS_BUTTON_TEMPLAT local subSectionTitleTextTemplate = DF:GetTemplate("font", "ORANGE_FONT_TEMPLATE") local font_select_icon, font_select_texcoord = [[Interface\AddOns\Details\images\icons]], {472/512, 513/512, 186/512, 230/512} -local texture_select_icon, texture_select_texcoord = [[Interface\AddOns\Details\images\icons]], {472/512, 513/512, 186/512, 230/512} --store the current instance being edited local currentInstance diff --git a/functions/profiles.lua b/functions/profiles.lua index 78cc6e1a..8b20dd4b 100644 --- a/functions/profiles.lua +++ b/functions/profiles.lua @@ -1454,12 +1454,16 @@ local default_global_data = { genericcontainer_height = 311 + 140 + 30, genericcontainer_islocked = true, + genericcontainer_right_width = 403, + genericcontainer_right_height = 460, + spellbar_background_alpha = 0.92, spellcontainer_headers = {}, --store information about active headers and their sizes (spells) targetcontainer_headers = {}, --store information about active headers and their sizes (target) phasecontainer_headers = {}, --store information about active headers and their sizes (phases) - genericcontainer_headers = {}, --store information about active headers and their sizes (generic) + genericcontainer_headers = {}, --store information about active headers and their sizes (generic left) + genericcontainer_headers_right = {}, --store information about active headers and their sizes (generic right) spellcontainer_header_height = 20, spellcontainer_header_fontsize = 10, @@ -2009,7 +2013,7 @@ function Details.ShowImportProfileConfirmation(message, callback) promptFrame:SetScript("OnDragStart", function() promptFrame:StartMoving() end) promptFrame:SetScript("OnDragStop", function() promptFrame:StopMovingOrSizing() end) promptFrame:SetScript("OnMouseDown", function(self, button) if (button == "RightButton") then promptFrame.EntryBox:ClearFocus() promptFrame:Hide() end end) - tinsert(UISpecialFrames, "DetailsImportProfileDialog") + table.insert(UISpecialFrames, "DetailsImportProfileDialog") detailsFramework:CreateTitleBar(promptFrame, "Import Profile Confirmation") detailsFramework:ApplyStandardBackdrop(promptFrame) diff --git a/functions/slash.lua b/functions/slash.lua index ebc75a64..64e00490 100644 --- a/functions/slash.lua +++ b/functions/slash.lua @@ -276,6 +276,7 @@ function SlashCmdList.DETAILS (msg, editbox) local combatObject = tremove(Details.tabela_historico.tabelas, segmentToErase) if (combatObject) then Details:DestroyCombat(combatObject) + Details:SendEvent("DETAILS_DATA_SEGMENTREMOVED") Details:Msg("segment removed.") collectgarbage() else @@ -1362,6 +1363,8 @@ function SlashCmdList.DETAILS (msg, editbox) local pastCombat = segmentHistory [i] if (pastCombat and pastCombat ~= newCombat) then Details:DestroyCombat(pastCombat) + --send the event segment removed + Details:SendEvent("DETAILS_DATA_SEGMENTREMOVED") segmentHistory [i] = nil end end diff --git a/startup.lua b/startup.lua index e908b584..4f24c160 100644 --- a/startup.lua +++ b/startup.lua @@ -99,8 +99,8 @@ function Details:StartMeUp() Details.MicroButtonAlert:Hide() --actor details window - Details.playerDetailWindow = Details:CreateBreakdownWindow() - Details.FadeHandler.Fader(Details.playerDetailWindow, 1) + Details.BreakdownWindowFrame = Details:CreateBreakdownWindow() + Details.FadeHandler.Fader(Details.BreakdownWindowFrame, 1) --copy and paste window Details:CreateCopyPasteWindow()