From a2c5e926c9c5e5b070ef4001d0bc7b84c5977000 Mon Sep 17 00:00:00 2001 From: Tercio Jose Date: Wed, 14 Jun 2023 18:43:33 -0300 Subject: [PATCH] More bug fixes for destroyed combats; TimeData code modernizations --- Definitions.lua | 1 + Libs/DF/charts.lua | 234 +++++++++++++++++++-- Libs/DF/fw.lua | 20 +- Libs/DF/mixins.lua | 71 +++++-- Libs/LibLuaServer/LuaServerDefinitions.lua | 8 +- classes/class_combat.lua | 12 +- classes/class_instance.lua | 28 ++- classes/container_segments.lua | 39 ++-- functions/timedata.lua | 175 ++++++++------- 9 files changed, 446 insertions(+), 142 deletions(-) diff --git a/Definitions.lua b/Definitions.lua index 4b1a8b17..dca03186 100644 --- a/Definitions.lua +++ b/Definitions.lua @@ -43,6 +43,7 @@ ---@field totals {key1: table, key2: table, key3: table, key3: table} ---@field totals_grupo {key1: table, key2: table, key3: table, key3: table} ---@field __destroyed boolean +---@field GetTimeData fun(dataName: string) : table ---@field GetPhases fun(combat: combat) : table ---@field GetCombatTime fun(combat) : number ---@field GetDeaths fun(combat) : table --get the table which contains the deaths of the combat diff --git a/Libs/DF/charts.lua b/Libs/DF/charts.lua index 1c511a4f..453bc836 100644 --- a/Libs/DF/charts.lua +++ b/Libs/DF/charts.lua @@ -1,19 +1,30 @@ -local DF = _G["DetailsFramework"] -if (not DF or not DetailsFrameworkCanLoad) then +local detailsFramework = _G["DetailsFramework"] +if (not detailsFramework or not DetailsFrameworkCanLoad) then return end +local CreateFrame = CreateFrame +local unpack = unpack local _ ----@class df_chart: frame, data ----@field _dataInfo data +---@class df_chartshared: table +---@field yAxisLine line the vertical line which can be anchored in the left or right side of the frame, if the chart is a multi chart, this line is shared by all charts +---@field xAxisLine line +---@field lineThickness number +---@field yAxisLabels fontstring[] +---@field xAxisLabels fontstring[] +---@field SetAxisColor fun(self: df_chartmulti, red: number|string|table|nil, green: number|nil, blue: number|nil, alpha: number|nil) : boolean set the color of both axis lines +---@field SetAxisThickness fun(self: df_chartmulti, thickness: number) : boolean set the thickness of both axis lines + +---@class df_chart: frame, df_data, df_value, df_chartshared +---@field _dataInfo df_data +---@field color number[] red green blue alpha ---@field nextLine number ---@field minValue number ---@field maxValue number ----@field lineThickness number ----@field data table ----@field lines table +---@field data number[] +---@field lines line[] ---@field ChartFrameConstructor fun(self: df_chart) set the default values for the chart frame ---@field GetLine fun(self: df_chart) : line return a line and also internally handle next line ---@field GetLines fun(self: df_chart) : line[] return a table with all lines already created @@ -24,14 +35,126 @@ local _ ---@field OnSizeChanged fun(self: df_chart) ---@field HideLines fun(self: df_chart) hide all lines already created ---@field Reset fun(self: df_chart) hide all lines and reset the next line to 1 +---@field SetColor fun(self: df_chart, r: number|string|table|nil, g: number|nil, b: number|nil, a: number|nil) set the color for the lines ---@field SetLineThickness fun(self: df_chart, thickness: number) set the line thickness ---@field CalcYAxisPointForValue fun(self: df_chart, value: number) ---@field UpdateFrameSizeCache fun(self: df_chart) +---@class df_chartmulti : df_chart, df_chartshared +---@field chartFrames df_chart[] +---@field nextChartselframe number +---@field biggestDataValue number +---@field MultiChartFrameConstructor fun(self: df_chartmulti) +---@field GetCharts fun(self: df_chartmulti) : df_chart[] +---@field GetChart fun(self: df_chartmulti) : df_chart +---@field AddData fun(self: df_chartmulti, data: table, red: number|string|table|nil, green: number|nil, blue: number|nil, alpha: number|nil) +---@field GetAmountCharts fun(self: df_chartmulti): number +---@field HideCharts fun(self: df_chartmulti) +---@field Reset fun(self: df_chartmulti) +---@field SetChartsMinMaxValues fun(self: df_chartmulti, minValue: number, maxValue: number) +---@field SetMaxDataSize fun(self: df_chartmulti, dataSize: number) +---@field GetMaxDataSize fun(self: df_chartmulti) +---@field SetLineThickness fun(self: df_chart, thickness: number) set the line thickness for all chart frames +---@field Plot fun(self: df_chartmulti) +detailsFramework.ChartFrameSharedMixin = { + ---set the color of both axis lines + ---@param self df_chart|df_chartmulti + ---@param red any + ---@param green number|nil + ---@param blue number|nil + ---@param alpha number|nil + ---@return boolean bColorChanged return true if the color was set, false if the axis lines are not created yet + SetAxisColor = function(self, red, green, blue, alpha) + if (not self.yAxisLine) then + return false + end + red, green, blue, alpha = detailsFramework:ParseColors(red, green, blue, alpha) + self.yAxisLine:SetColorTexture(red, green, blue, alpha) + self.xAxisLine:SetColorTexture(red, green, blue, alpha) + return true + end, + ---set the thickness of both axis lines + ---@param self df_chart|df_chartmulti + ---@param thickness number + ---@return boolean bThicknessChanged return true if the thickness was set, false if the axis lines are not created yet + SetAxisThickness = function(self, thickness) + if (not self.yAxisLine) then + return false + end + self.yAxisLine:SetThickness(thickness) + self.xAxisLine:SetThickness(thickness) + return true + end, +} -local ChartFrameMixin = { +--> functions shared by both single and multi chart frames + +---create the x and y axis lines with their labels +---@param self df_chart|df_chartmulti +---@param whichSide "left"|"right" +---@param thickness number +---@param amountYLabels number +---@param amountXLabels number +---@param red any +---@param green number|nil +---@param blue number|nil +---@param alpha number|nil +---@return boolean +local createAxysLines = function(self, whichSide, thickness, amountYLabels, amountXLabels, red, green, blue, alpha) + if (self.axisCreated) then + return false + end + + self.yAxisLabels = {} + self.xAxisLabels = {} + + --this is the vertical line which can be anchored in the left or right side of the frame, it separates the chart lines from the measurements texts + ---@type line + local yAxisLine = self:CreateLine("$parentYAxisLine", "overlay") + self.yAxisLine = yAxisLine + + --and the horizontal line which is always anchored in the bottom of the frame + ---@type line + local xAxisLine = self:CreateLine("$parentXAxisLine", "overlay") + self.xAxisLine = xAxisLine + + red, green, blue, alpha = detailsFramework:ParseColors(red, green, blue, alpha) + + self:SetAxisColor(red, green, blue, alpha) + self:SetAxisThickness(thickness) + + --create the labels in the vertical axis line + for i = 1, amountYLabels do + local label = self:CreateFontString("$parentYAxisLabel" .. i, "overlay", "GameFontNormal") + label:SetJustifyH("right") + label:SetTextColor(red, green, blue, alpha) + table.insert(self.yAxisLabels, label) + end + + --create the labels in the horizontal axis line + for i = 1, amountXLabels do + local label = self:CreateFontString("$parentXAxisLabel" .. i, "overlay", "GameFontNormal") + label:SetJustifyH("left") + label:SetTextColor(red, green, blue, alpha) + table.insert(self.xAxisLabels, label) + end + + yAxisLine:SetStartPoint("topleft", self, "topleft", 0, 0) + yAxisLine:SetEndPoint("bottomleft", self, "bottomleft", 0, 0) + yAxisLine:Hide() + + xAxisLine:SetStartPoint("bottomleft", self, "bottomleft", 0, 0) + xAxisLine:SetEndPoint("bottomright", self, "bottomright", 0, 0) + xAxisLine:Hide() + + self.axisCreated = true + + return true +end + +detailsFramework.ChartFrameMixin = { ---set the default values for the chart frame ---@param self df_chart ChartFrameConstructor = function(self) @@ -41,19 +164,38 @@ local ChartFrameMixin = { self.lineThickness = 1 self.data = {} self.lines = {} + self.color = {1, 1, 1, 1} --OnSizeChanged self:SetScript("OnSizeChanged", self.OnSizeChanged) end, + ---set the color for the lines + ---@param self df_chart + ---@param r number + ---@param g number + ---@param b number + ---@param a number|nil + SetColor = function(self, r, g, b, a) + r, g, b, a = detailsFramework:ParseColors(r, g, b, a) + self.color[1] = r + self.color[2] = g + self.color[3] = b + self.color[4] = a or 1 + end, + ---internally handle next line ---@param self df_chart GetLine = function(self) + ---@type line local line = self.lines[self.nextLine] + if (not line) then + ---@type line line = self:CreateLine(nil, "overlay") self.lines[self.nextLine] = line end + self.nextLine = self.nextLine + 1 line:Show() return line @@ -160,8 +302,8 @@ local ChartFrameMixin = { for i = 1, maxLines do local line = self:GetLine() - line:SetColorTexture(1, 1, 1, 1) - line:SetThickness(1) + line:SetColorTexture(unpack(self.color)) + line:SetThickness(self.lineThickness) --the start point starts where the latest point finished line:SetStartPoint("bottomleft", currentXPoint, currentYPoint) @@ -185,9 +327,10 @@ local createChartFrame = function(parent, name) ---@type df_chart local chartFrame = CreateFrame("frame", name, parent, "BackdropTemplate") - DF:Mixin(chartFrame, DF.DataMixin) - DF:Mixin(chartFrame, DF.ValueMixin) - DF:Mixin(chartFrame, ChartFrameMixin) + detailsFramework:Mixin(chartFrame, detailsFramework.DataMixin) + detailsFramework:Mixin(chartFrame, detailsFramework.ValueMixin) + detailsFramework:Mixin(chartFrame, detailsFramework.ChartFrameMixin) + detailsFramework:Mixin(chartFrame, detailsFramework.ChartFrameSharedMixin) chartFrame:DataConstructor() chartFrame:ValueConstructor() @@ -205,22 +348,35 @@ local createChartFrame = function(parent, name) return chartFrame end -function DF:CreateGraphicLineFrame(parent, name) +function detailsFramework:CreateGraphicLineFrame(parent, name) ---@type df_chart local newGraphicFrame = createChartFrame(parent, name) return newGraphicFrame end -local MultiChartFrameMixin = { +detailsFramework.MultiChartFrameMixin = { MultiChartFrameConstructor = function(self) self.nextChartselframe = 1 self.biggestDataValue = 0 + self.lineThickness = 1 self.chartFrames = {} end, - AddData = function(self, data) + CreateAxisLines = function(self, whichSide, thickness, amountYLabels, amountXLabels, red, green, blue, alpha) + createAxysLines(self, whichSide, thickness, amountYLabels, amountXLabels, red, green, blue, alpha) + end, + + ---add a new chart data and create a new chart frame if necessary to the multi chart + ---@param self df_chartmulti + ---@param data table + ---@param red number|string|table|nil + ---@param green number|nil + ---@param blue number|nil + ---@param alpha number|nil + AddData = function(self, data, red, green, blue, alpha) assert(type(data) == "table", "MultiChartFrame:AddData() usage: AddData(table)") local chartFrame = self:GetChart() + chartFrame:SetColor(red, green, blue, alpha) chartFrame:SetData(data) self:SetMaxValueIfBigger(chartFrame:GetMaxValue()) @@ -230,7 +386,9 @@ local MultiChartFrameMixin = { self:SetMaxDataSize(dataAmount) end, - --internally handle next line + ---internally handle next line + ---@param self df_chartmulti + ---@return df_chart GetChart = function(self) local chartFrame = self.chartFrames[self.nextChartFrame] if (not chartFrame) then @@ -244,14 +402,22 @@ local MultiChartFrameMixin = { return chartFrame end, + ---get all charts added to the multi chart frame + ---@param self df_chartmulti + ---@return df_chart[] GetCharts = function(self) return self.chartFrames end, + ---get the amount of charts added to the multi chart frame + ---@param self df_chartmulti + ---@return number GetAmountCharts = function(self) return self.nextChartFrame - 1 end, + ---hide all charts + ---@param self df_chartmulti HideCharts = function(self) local charts = self:GetCharts() for i = 1, #charts do @@ -260,11 +426,17 @@ local MultiChartFrameMixin = { end end, + ---reset the multi chart frame + ---@param self df_chartmulti Reset = function(self) self:HideCharts() self.nextChartFrame = 1 end, + ---set the min and max values of all charts + ---@param self df_chartmulti + ---@param minValue number + ---@param maxValue number SetChartsMinMaxValues = function(self, minValue, maxValue) local allCharts = self:GetCharts() for i = 1, self:GetAmountCharts() do @@ -273,14 +445,29 @@ local MultiChartFrameMixin = { end end, + ---set the max data size of all charts + ---@param self df_chartmulti + ---@param dataSize number SetMaxDataSize = function(self, dataSize) - self.biggestDataValue = max(self.biggestDataValue, dataSize) + self.biggestDataValue = math.max(self.biggestDataValue, dataSize) end, + ---get the max data size of all charts + ---@param self df_chartmulti + ---@return number GetMaxDataSize = function(self) return self.biggestDataValue end, + ---@param self df_chartmulti + ---@param value number + SetLineThickness = function(self, value) + assert(type(value) == "number", "number expected on :SetLineThickness(number)") + self.lineThickness = value + end, + + ---draw all the charts added to the multi chart frame + ---@param self df_chartmulti Plot = function(self) local minValue, maxValue = self:GetMinMaxValues() self:SetChartsMinMaxValues(minValue, maxValue) @@ -292,6 +479,7 @@ local MultiChartFrameMixin = { local allCharts = self:GetCharts() for i = 1, self:GetAmountCharts() do local chartFrame = allCharts[i] + chartFrame:SetLineThickness(self.lineThickness) chartFrame:SetLineWidth(eachLineWidth) chartFrame:Plot() end @@ -301,14 +489,16 @@ local MultiChartFrameMixin = { ---create a chart frame object with support to multi lines ---@param parent frame ---@param name string|nil ----@return df_chart -function DF:CreateGraphicMultiLineFrame(parent, name) +---@return df_chartmulti +function detailsFramework:CreateGraphicMultiLineFrame(parent, name) name = name or ("DetailsMultiChartFrameID" .. math.random(1, 10000000)) + ---@type df_chartmulti local chartFrame = CreateFrame("frame", name, parent, "BackdropTemplate") - DF:Mixin(chartFrame, DF.ValueMixin) - DF:Mixin(chartFrame, MultiChartFrameMixin) + detailsFramework:Mixin(chartFrame, detailsFramework.ValueMixin) + detailsFramework:Mixin(chartFrame, detailsFramework.MultiChartFrameMixin) + detailsFramework:Mixin(chartFrame, detailsFramework.ChartFrameSharedMixin) chartFrame:ValueConstructor() chartFrame:MultiChartFrameConstructor() diff --git a/Libs/DF/fw.lua b/Libs/DF/fw.lua index 757d6991..3ba7decc 100644 --- a/Libs/DF/fw.lua +++ b/Libs/DF/fw.lua @@ -1,6 +1,6 @@ -local dversion = 438 +local dversion = 439 local major, minor = "DetailsFramework-1.0", dversion local DF, oldminor = LibStub:NewLibrary(major, minor) @@ -5358,3 +5358,21 @@ end ----------------------------------------------------------------------------------------------------------------------------------------------------------- + +---receives an object and print debug info about its visibility +---use to know why a frame is not showing +---@param UIObject any +function DF:DebugVisibility(UIObject) + local bIsShown = UIObject:IsShown() + print("Is Shown:", bIsShown and "|cFF00FF00true|r" or "|cFFFF0000false|r") + + local bIsVisible = UIObject:IsVisible() + print("Is Visible:", bIsVisible and "|cFF00FF00true|r" or "|cFFFF0000false|r") + + local width, height = UIObject:GetSize() + print("Width:", width > 0 and "|cFF00FF00" .. width .. "|r" or "|cFFFF00000|r") + print("Height:", height > 0 and "|cFF00FF00" .. height .. "|r" or "|cFFFF00000|r") + + local numPoints = UIObject:GetNumPoints() + print("Num Points:", numPoints > 0 and "|cFF00FF00" .. numPoints .. "|r" or "|cFFFF00000|r") +end \ No newline at end of file diff --git a/Libs/DF/mixins.lua b/Libs/DF/mixins.lua index 123e6c5a..0ebe41a3 100644 --- a/Libs/DF/mixins.lua +++ b/Libs/DF/mixins.lua @@ -717,18 +717,22 @@ detailsFramework.SortFunctions = { end } ----@class data : table ----@field data table +---@class df_data : table +---@field _dataInfo {data: table, dataCurrentIndex: number, callbacks: function[]} +---@field callbacks table ---@field dataCurrentIndex number ----@field callbacks table ----@field DataConstructor fun(self: data) ----@field AddDataChangeCallback fun(self: data, callback: function, ...: any) ----@field RemoveDataChangeCallback fun(self: data, callback: function) ----@field GetData fun(self: data) ----@field SetData fun(self: data, data: table) ----@field GetDataNextValue fun(self: data) : any ----@field ResetDataIndex fun(self: data) - +---@field DataConstructor fun(self: df_data) +---@field AddDataChangeCallback fun(self: df_data, callback: function, ...: any) +---@field RemoveDataChangeCallback fun(self: df_data, callback: function) +---@field GetData fun(self: df_data) +---@field GetDataSize fun(self: df_data) : number +---@field GetDataFirstValue fun(self: df_data) : any +---@field GetDataLastValue fun(self: df_data) : any +---@field GetDataMinMaxValues fun(self: df_data) : number, number +---@field GetDataMinMaxValueFromSubTable fun(self: df_data, key: string) : number, number when data uses sub tables, get the min max values from a specific index or key, if the value stored is number, return the min and max values +---@field SetData fun(self: df_data, data: table) +---@field GetDataNextValue fun(self: df_data) : any +---@field ResetDataIndex fun(self: df_data) ---mixin to use with DetailsFramework:Mixin(table, detailsFramework.DataMixin) ---add 'data' to a table, this table can be used to store data for the object @@ -822,6 +826,7 @@ detailsFramework.DataMixin = { end, ---get the min and max values from the data table, if the value stored is number, return the min and max values + ---could be used together with SetMinMaxValues from the df_value mixin ---@param self table ---@return number, number GetDataMinMaxValues = function(self) @@ -865,45 +870,85 @@ detailsFramework.DataMixin = { end, } +---@class df_value : table +---@field minValue number +---@field maxValue number +---@field ValueConstructor fun(self: df_value) +---@field SetMinMaxValues fun(self: df_value, minValue: number, maxValue: number) +---@field GetMinMaxValues fun(self: df_value) : number, number +---@field GetMinValue fun(self: df_value) : number +---@field GetMaxValue fun(self: df_value) : number +---@field SetMinValue fun(self: df_value, minValue: number) +---@field SetMinValueIfLower fun(self: df_value, ...: number) +---@field SetMaxValue fun(self: df_value, maxValue: number) +---@field SetMaxValueIfBigger fun(self: df_value, ...: number) + ---mixin to use with DetailsFramework:Mixin(table, detailsFramework.ValueMixin) ---add support to min value and max value into a table or object ---@class DetailsFramework.ValueMixin detailsFramework.ValueMixin = { + ---initialize the value table + ---@param self table ValueConstructor = function(self) self.minValue = 0 self.maxValue = 1 end, + ---set the min and max values + ---@param self table + ---@param minValue number + ---@param maxValue number SetMinMaxValues = function(self, minValue, maxValue) self.minValue = minValue self.maxValue = maxValue end, + ---get the min and max values + ---@param self table + ---@return number, number GetMinMaxValues = function(self) return self.minValue, self.maxValue end, + ---get the min value + ---@param self table + ---@return number GetMinValue = function(self) return self.minValue end, + ---get the max value + ---@param self table + ---@return number GetMaxValue = function(self) return self.maxValue end, + ---set the min value + ---@param self table + ---@param minValue number SetMinValue = function(self, minValue) self.minValue = minValue end, + ---set the min value if one of the values passed is lower than the current min value + ---@param self table + ---@param ... number SetMinValueIfLower = function(self, ...) - self.minValue = min(self.minValue, ...) + self.minValue = math.min(self.minValue, ...) end, + ---set the max value + ---@param self table + ---@param maxValue number SetMaxValue = function(self, maxValue) self.maxValue = maxValue end, + ---set the max value if one of the values passed is bigger than the current max value + ---@param self table + ---@param ... number SetMaxValueIfBigger = function(self, ...) - self.maxValue = max(self.maxValue, ...) + self.maxValue = math.max(self.maxValue, ...) end, } \ No newline at end of file diff --git a/Libs/LibLuaServer/LuaServerDefinitions.lua b/Libs/LibLuaServer/LuaServerDefinitions.lua index 026ad499..35630a83 100644 --- a/Libs/LibLuaServer/LuaServerDefinitions.lua +++ b/Libs/LibLuaServer/LuaServerDefinitions.lua @@ -196,9 +196,13 @@ ---@field Stop fun(self: animation) ---@class line : uiobject ----@field SetStartPoint fun(self: line, point: anchorpoint, relativeFrame: uiobject, relativePoint: anchorpoint, xOffset: number, yOffset: number) ----@field SetEndPoint fun(self: line, point: anchorpoint, relativeFrame: uiobject, relativePoint: anchorpoint, xOffset: number, yOffset: number) +---@field GetEndPoint fun(self: line) : relativePoint: anchorpoint, relativeTo: anchorpoint, offsetX: number, offsetY: number +---@field GetStartPoint fun(self: line) : relativePoint: anchorpoint, relativeTo: anchorpoint, offsetX: number, offsetY: number +---@field GetThickness fun(self: line) : number +---@field SetStartPoint fun(self: line, point: anchorpoint, relativeFrame: uiobject|number, relativePoint: anchorpoint|number, xOffset: number|nil, yOffset: number|nil) +---@field SetEndPoint fun(self: line, point: anchorpoint, relativeFrame: uiobject|number, relativePoint: anchorpoint|number, xOffset: number|nil, yOffset: number|nil) ---@field SetColorTexture fun(self: line, red: number, green: number, blue: number, alpha: number) +---@field SetThickness fun(self: line, thickness: number) ---@class frame : uiobject ---@field CreateLine fun(self: frame, name: string|nil, drawLayer: drawlayer, templateName: string|nil, subLevel: number|nil) : line diff --git a/classes/class_combat.lua b/classes/class_combat.lua index da01a19a..1068c144 100644 --- a/classes/class_combat.lua +++ b/classes/class_combat.lua @@ -67,10 +67,10 @@ --api functions --combat (container type, actor name) - Details.call_combate = function(self, class_type, name) - local container = self[class_type] - local index_mapa = container._NameIndexTable [name] - local actor = container._ActorTable [index_mapa] + Details.call_combate = function(self, classType, actorName) + local container = self[classType] + local index_mapa = container._NameIndexTable[actorName] + local actor = container._ActorTable[index_mapa] return actor end classCombat.__call = Details.call_combate @@ -81,7 +81,7 @@ end --set the combat date - function classCombat:SetDate (started, ended) + function classCombat:SetDate(started, ended) if (started and type(started) == "string") then self.data_inicio = started end @@ -95,7 +95,7 @@ return self.TimeData[name] end - function classCombat:GetContainer (attribute) + function classCombat:GetContainer(attribute) return self [attribute] end diff --git a/classes/class_instance.lua b/classes/class_instance.lua index d0b8f2f0..8376a8ab 100644 --- a/classes/class_instance.lua +++ b/classes/class_instance.lua @@ -16,6 +16,9 @@ local _UnitName = UnitName --wow api locals local _UnitIsPlayer = UnitIsPlayer --wow api locals local _UnitGroupRolesAssigned = DetailsFramework.UnitGroupRolesAssigned --wow api locals +local segmentClass = Details.historico +local combatClass = Details.combate + local _detalhes = _G.Details local _ local addonName, Details222 = ... @@ -217,11 +220,30 @@ local instanceMixins = { ---@type segmentid local segmentId = instance:GetSegmentId() if (segmentId == DETAILS_SEGMENTID_OVERALL) then - instance.showing = Details:GetOverallCombat() + ---@type combat + local combatObject = Details:GetOverallCombat() + if (combatObject.__destroyed) then + combatObject = combatClass:NovaTabela() + end + instance.showing = combatObject + elseif (segmentId == DETAILS_SEGMENTID_CURRENT) then - instance.showing = Details:GetCurrentCombat() + ---@type combat + local combatObject = Details:GetCurrentCombat() + if (combatObject.__destroyed) then + combatObject = combatClass:NovaTabela(nil, Details.tabela_overall) + end + instance.showing = combatObject + else - instance.showing = Details:GetCombat(segmentId) + ---@type combat + local combatObject = Details:GetCombat(segmentId) + if (combatObject.__destroyed) then + table.remove(Details:GetCombatSegments(), segmentId) + combatObject = combatClass:NovaTabela() + table.insert(Details:GetCombatSegments(), segmentId, combatObject) + end + instance.showing = combatObject end ---@type combat diff --git a/classes/container_segments.lua b/classes/container_segments.lua index 34a4dc76..7597ffb8 100644 --- a/classes/container_segments.lua +++ b/classes/container_segments.lua @@ -314,7 +314,6 @@ function segmentClass:AddCombat(combatObject) for _, actorObject in containerHeal:ListActors() do ---@cast actorObject actor - --clear last events table actorObject.last_events_table = nil Details222.TimeMachine.RemoveActor(actorObject) end @@ -344,8 +343,10 @@ function segmentClass:AddCombat(combatObject) end end + local segmentsTable = Details.tabela_historico.tabelas + --check if the segment table is full - if (#segmentTable > maxSegmentsAllowed) then + if (#segmentsTable > maxSegmentsAllowed) then ---@type combat local combatObjectToBeRemoved ---@type number @@ -357,7 +358,7 @@ function segmentClass:AddCombat(combatObject) local bossId = combatObject.is_boss and combatObject.is_boss.id ---@type combat - local oldestSegment = segmentTable[#segmentTable] + local oldestSegment = segmentsTable[#segmentsTable] local oldestBossId = oldestSegment.is_boss and oldestSegment.is_boss.id if (Details.zone_type == "raid" and bossId and oldestBossId and bossId == oldestBossId) then @@ -367,9 +368,9 @@ function segmentClass:AddCombat(combatObject) local shorterSegmentId local minTime = 99999 - for segmentId = 4, #segmentTable do + for segmentId = 4, #segmentsTable do ---@type combat - local thisCombatObject = segmentTable[segmentId] + local thisCombatObject = segmentsTable[segmentId] if (thisCombatObject.is_boss and thisCombatObject.is_boss.id == bossId and thisCombatObject:GetCombatTime() < minTime and not thisCombatObject.is_boss.killed) then shorterCombatObject = thisCombatObject shorterSegmentId = segmentId @@ -385,8 +386,8 @@ function segmentClass:AddCombat(combatObject) --if couldn't find a boss to remove, then remove the oldest segment if (not combatObjectToBeRemoved) then - combatObjectToBeRemoved = segmentTable[#segmentTable] - segmentIdToBeRemoved = #segmentTable + combatObjectToBeRemoved = segmentsTable[#segmentsTable] + segmentIdToBeRemoved = #segmentsTable end --check time machine @@ -398,14 +399,17 @@ function segmentClass:AddCombat(combatObject) end --remove it + segmentsTable = Details.tabela_historico.tabelas ---@type combat - local combatObjectRemoved = table.remove(segmentTable, segmentIdToBeRemoved) + local combatObjectRemoved = table.remove(segmentsTable, segmentIdToBeRemoved) if (combatObjectRemoved) then Details:DestroyCombat(combatObjectRemoved) Details:SendEvent("DETAILS_DATA_SEGMENTREMOVED") end end + Details:InstanceCall(function(instanceObject) instanceObject:RefreshCombat() end) + --update the combat shown on all instances Details:InstanciaCallFunction(Details.AtualizaSegmentos_AfterCombat, self) end @@ -499,15 +503,19 @@ function segmentClass:ResetAllCombatData() --empty temporary tables Details.atributo_damage:ClearTempTables() - for _, combatObject in ipairs(Details.tabela_historico.tabelas) do - ---@cast combatObject combat - Details:DestroyCombat(combatObject) + for i = #Details.tabela_historico.tabelas, 1, -1 do + ---@type combat + local combtaObjectRemoved = table.remove(Details.tabela_historico.tabelas, i) + Details:DestroyCombat(combtaObjectRemoved) 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) + if (Details.tabela_vigente == Details.tabela_historico.tabelas[1]) then + table.remove(Details.tabela_historico.tabelas, 1) + end Details:SendEvent("DETAILS_DATA_SEGMENTREMOVED") end @@ -525,15 +533,16 @@ function segmentClass:ResetAllCombatData() -- novo container de historico Details.tabela_historico = segmentClass:CreateNewSegmentDatabase() --joga fora a tabela antiga e cria uma nova - --novo container para armazenar pets - Details.tabela_pets = Details.container_pets:NovoContainer() - Details:UpdateContainerCombatentes() - Details.container_pets:BuscarPets() -- nova tabela do overall e current Details.tabela_overall = combatClass:NovaTabela() --joga fora a tabela antiga e cria uma nova -- cria nova tabela do combate atual Details.tabela_vigente = combatClass:NovaTabela(nil, Details.tabela_overall) + --novo container para armazenar pets + Details.tabela_pets = Details.container_pets:NovoContainer() + Details:UpdateContainerCombatentes() + Details.container_pets:BuscarPets() + ---@type instance[] local allInstances = Details:GetAllInstances() diff --git a/functions/timedata.lua b/functions/timedata.lua index 129ff1c9..14fc99f1 100644 --- a/functions/timedata.lua +++ b/functions/timedata.lua @@ -7,16 +7,30 @@ --create a namespace Details222.TimeCapture = {} - --mantain the enabled time captures - Details.timeContainer = {} - Details.timeContainer.Exec = {} + ---@class timedataexec : table + ---@field func function + ---@field data table + ---@field attributes table + ---@field is_user boolean + + ---mantain the enabled time captures + ---@class timedatacontainer : table + ---@field Exec timedataexec[] + + ---@class timedatasaved : {key1: string, key2: function, key3: table, key4: string, key5: string, key6: string, key7: boolean} + ---@field do_not_save boolean + + do + ---@type timedatacontainer + local timeContainer = {} + Details.timeContainer = timeContainer + Details.timeContainer.Exec = {} + end ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --local pointers local ipairs = ipairs - local _math_floor = math.floor - local _pcall = pcall - local time = time + local pcall = pcall ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --constants @@ -29,44 +43,47 @@ local INDEX_ICON = 6 local INDEX_ENABLED = 7 - local DEFAULT_USER_MATRIX = {max_value = 0, last_value = 0} + local DEFAULT_USER_MATRIX = { + max_value = 0, + last_value = 0 + } ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --register and unregister captures function Details:TimeDataUpdate (index_or_name, name, func, matrix, author, version, icon, is_enabled) - - local this_capture + local thisCapture if (type(index_or_name) == "number") then - this_capture = Details.savedTimeCaptures [index_or_name] + thisCapture = Details.savedTimeCaptures[index_or_name] else - for index, t in ipairs(Details.savedTimeCaptures) do - if (t [INDEX_NAME] == index_or_name) then - this_capture = t + for index, timeDataSaved in ipairs(Details.savedTimeCaptures) do + ---@cast timeDataSaved timedatasaved + if (timeDataSaved [INDEX_NAME] == index_or_name) then + thisCapture = timeDataSaved end end end - if (not this_capture) then + if (not thisCapture) then return false end - if (this_capture.do_not_save) then + if (thisCapture.do_not_save) then return Details:Msg("This capture belongs to a plugin and cannot be edited.") end - this_capture [INDEX_NAME] = name or this_capture [INDEX_NAME] - this_capture [INDEX_FUNCTION] = func or this_capture [INDEX_FUNCTION] - this_capture [INDEX_MATRIX] = matrix or this_capture [INDEX_MATRIX] - this_capture [INDEX_AUTHOR] = author or this_capture [INDEX_AUTHOR] - this_capture [INDEX_VERSION] = version or this_capture [INDEX_VERSION] - this_capture [INDEX_ICON] = icon or this_capture [INDEX_ICON] + thisCapture[INDEX_NAME] = name or thisCapture[INDEX_NAME] + thisCapture[INDEX_FUNCTION] = func or thisCapture[INDEX_FUNCTION] + thisCapture[INDEX_MATRIX] = matrix or thisCapture[INDEX_MATRIX] + thisCapture[INDEX_AUTHOR] = author or thisCapture[INDEX_AUTHOR] + thisCapture[INDEX_VERSION] = version or thisCapture[INDEX_VERSION] + thisCapture[INDEX_ICON] = icon or thisCapture[INDEX_ICON] if (is_enabled ~= nil) then - this_capture [INDEX_ENABLED] = is_enabled + thisCapture[INDEX_ENABLED] = is_enabled else - this_capture [INDEX_ENABLED] = this_capture [INDEX_ENABLED] + thisCapture[INDEX_ENABLED] = thisCapture[INDEX_ENABLED] end if (_G.DetailsOptionsWindow and _G.DetailsOptionsWindow:IsShown()) then @@ -74,41 +91,40 @@ end return true - end --matrix = table containing {max_value = 0, last_value = 0} - function Details:TimeDataRegister(name, func, matrix, author, version, icon, is_enabled, force_no_save) + function Details:TimeDataRegister(timeDataName, callbackFunc, matrix, author, version, icon, bIsEnabled, bForceNoSave) --check name - if (not name) then + if (not timeDataName) then return "Couldn't register the time capture, name was nil." end --check if the name already exists for index, t in ipairs(Details.savedTimeCaptures) do - if (t [INDEX_NAME] == name) then + if (t [INDEX_NAME] == timeDataName) then return "Couldn't register the time capture, name already registred." end end --check function - if (not func) then + if (not callbackFunc) then return "Couldn't register the time capture, invalid function." end local no_save = nil --passed a function means that this isn't came from a user --so the plugin register the capture every time it loads. - if (type(func) == "function") then + if (type(callbackFunc) == "function") then no_save = true --this a custom capture from a user, so we register a default user table for matrix - elseif (type(func) == "string") then + elseif (type(callbackFunc) == "string") then matrix = DEFAULT_USER_MATRIX end - if (not no_save and force_no_save) then + if (not no_save and bForceNoSave) then no_save = true end @@ -121,27 +137,26 @@ version = version or "v1.0" icon = icon or [[Interface\InventoryItems\WoWUnknownItem01]] - tinsert(Details.savedTimeCaptures, {name, func, matrix, author, version, icon, is_enabled, do_not_save = no_save}) + table.insert(Details.savedTimeCaptures, {timeDataName, callbackFunc, matrix, author, version, icon, bIsEnabled, do_not_save = no_save}) if (_G.DetailsOptionsWindow and _G.DetailsOptionsWindow:IsShown()) then DetailsOptionsWindowTab17UserTimeCapturesFillPanel.MyObject:Refresh() end return true - end --unregister function Details:TimeDataUnregister (name) if (type(name) == "number") then - tremove(Details.savedTimeCaptures, name) + table.remove(Details.savedTimeCaptures, name) if (_G.DetailsOptionsWindow and _G.DetailsOptionsWindow:IsShown()) then DetailsOptionsWindowTab17UserTimeCapturesFillPanel.MyObject:Refresh() end else for index, t in ipairs(Details.savedTimeCaptures) do if (t [INDEX_NAME] == name) then - tremove(Details.savedTimeCaptures, index) + table.remove(Details.savedTimeCaptures, index) if (_G.DetailsOptionsWindow and _G.DetailsOptionsWindow:IsShown()) then DetailsOptionsWindowTab17UserTimeCapturesFillPanel.MyObject:Refresh() end @@ -154,16 +169,19 @@ --cleanup when logout function Details:TimeDataCleanUpTemporary() + ---@type timedatasaved[] local newData = {} - for index, t in ipairs(Details.savedTimeCaptures) do - if (not t.do_not_save) then - tinsert(newData, t) + + for index, timeDataSaved in ipairs(Details.savedTimeCaptures) do + if (not timeDataSaved.do_not_save) then + table.insert(newData, timeDataSaved) end end + Details.savedTimeCaptures = newData end - local tick_time = 0 + local tickTime = 0 --starting a combat function Details:TimeDataCreateChartTables() @@ -171,54 +189,58 @@ local chartTables = {} --drop the last capture exec table without wiping + ---@type timedataexec local exec = {} + Details.timeContainer.Exec = exec Details:SendEvent("COMBAT_CHARTTABLES_CREATING") --build the exec table - for index, t in ipairs(Details.savedTimeCaptures) do - if (t[INDEX_ENABLED]) then + for index, chartData in ipairs(Details.savedTimeCaptures) do + if (chartData[INDEX_ENABLED]) then local data = {} - chartTables[t[INDEX_NAME]] = data + chartTables[chartData[INDEX_NAME]] = data - if (type(t[INDEX_FUNCTION]) == "string") then + if (type(chartData[INDEX_FUNCTION]) == "string") then --user - local func, errortext = loadstring(t[INDEX_FUNCTION]) + local func, errortext = loadstring(chartData[INDEX_FUNCTION]) if (func) then DetailsFramework:SetEnvironment(func) - tinsert(exec, {func = func, data = data, attributes = Details.CopyTable(t[INDEX_MATRIX]), is_user = true}) + ---@type timedataexec + local timeDataTable = {func = func, data = data, attributes = Details.CopyTable(chartData[INDEX_MATRIX]), is_user = true} + table.insert(exec, timeDataTable) else Details:Msg("|cFFFF9900error compiling script for time data (charts)|r: ", errortext) end else --plugin - local func = t[INDEX_FUNCTION] + local func = chartData[INDEX_FUNCTION] DetailsFramework:SetEnvironment(func) - tinsert(exec, {func = func, data = data, attributes = Details.CopyTable(t[INDEX_MATRIX])}) + ---@type timedataexec + local timeDataTable = {func = func, data = data, attributes = Details.CopyTable(chartData[INDEX_MATRIX])} + table.insert(exec, timeDataTable) end - end end Details:SendEvent("COMBAT_CHARTTABLES_CREATED") - tick_time = 0 + tickTime = 0 --return the capture table the to combat object return chartTables end - local exec_user_func = function(func, attributes, data, this_second) - - local okey, result = _pcall (func, attributes) + local execUserFunc = function(func, attributes, data, thisSecond) + local okey, result = pcall(func, attributes) if (not okey) then Details:Msg("|cFFFF9900error on chart script function|r:", result) result = 0 end local current = result - attributes.last_value - data [this_second] = current + data[thisSecond] = current if (current > attributes.max_value) then attributes.max_value = current @@ -226,27 +248,20 @@ end attributes.last_value = result - end function Details:TimeDataTick() - - tick_time = tick_time + 1 - - for index, t in ipairs(Details.timeContainer.Exec) do - - if (t.is_user) then + tickTime = tickTime + 1 + for index, timeDataTable in ipairs(Details.timeContainer.Exec) do + ---@cast timeDataTable timedataexec + if (timeDataTable.is_user) then --by a user - exec_user_func (t.func, t.attributes, t.data, tick_time) - + execUserFunc(timeDataTable.func, timeDataTable.attributes, timeDataTable.data, tickTime) else --by a plugin - t.func (t.attributes, t.data, tick_time) - + timeDataTable.func(timeDataTable.attributes, timeDataTable.data, tickTime) end - end - end ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -262,7 +277,7 @@ if (not combatTime or combatTime == 0) then return 0 else - return ToKFunctions [Details.minimap.text_format] (_, combat.totals_grupo[1] / combatTime) + return ToKFunctions[Details.minimap.text_format](_, combat.totals_grupo[1] / combatTime) end end, -- raid hps [2] @@ -272,7 +287,7 @@ if (not combatTime or combatTime == 0) then return 0 else - return ToKFunctions [Details.minimap.text_format] (_, combat.totals_grupo[2] / combatTime) + return ToKFunctions[Details.minimap.text_format](_, combat.totals_grupo[2] / combatTime) end end } @@ -280,7 +295,7 @@ local get_combat_time = function() local combat_time = Details.tabela_vigente:GetCombatTime() - local minutos, segundos = _math_floor(combat_time / 60), _math_floor(combat_time % 60) + local minutos, segundos = math.floor(combat_time / 60), math.floor(combat_time % 60) if (segundos < 10) then segundos = "0" .. segundos end @@ -288,8 +303,8 @@ end local get_damage_position = function() - local damage_container = Details.tabela_vigente [1] - damage_container:SortByKey ("total") + local damage_container = Details.tabela_vigente[1] + damage_container:SortByKey("total") local pos = 1 for index, actor in ipairs(damage_container._ActorTable) do @@ -305,8 +320,8 @@ end local get_heal_position = function() - local heal_container = Details.tabela_vigente [2] - heal_container:SortByKey ("total") + local heal_container = Details.tabela_vigente[2] + heal_container:SortByKey("total") local pos = 1 for index, actor in ipairs(heal_container._ActorTable) do @@ -322,8 +337,8 @@ end local get_damage_diff = function() - local damage_container = Details.tabela_vigente [1] - damage_container:SortByKey ("total") + local damage_container = Details.tabela_vigente[1] + damage_container:SortByKey("total") local first local first_index @@ -348,18 +363,18 @@ if (second) then local diff = first.total - second.total - return "+" .. ToKFunctions [Details.minimap.text_format] (_, diff) + return "+" .. ToKFunctions[Details.minimap.text_format] (_, diff) else return "0" end else - local player = damage_container._NameIndexTable [Details.playername] + local player = damage_container._NameIndexTable[Details.playername] if (player) then - player = damage_container._ActorTable [player] + player = damage_container._ActorTable[player] local diff = first.total - player.total - return "-" .. ToKFunctions [Details.minimap.text_format] (_, diff) + return "-" .. ToKFunctions[Details.minimap.text_format](_, diff) else - return ToKFunctions [Details.minimap.text_format] (_, first.total) + return ToKFunctions[Details.minimap.text_format](_, first.total) end end else