diff --git a/boot.lua b/boot.lua index 8ae762fa..d90b3e47 100644 --- a/boot.lua +++ b/boot.lua @@ -6,8 +6,8 @@ local addonName, Details222 = ... local version, build, date, tocversion = GetBuildInfo() - _detalhes.build_counter = 10282 - _detalhes.alpha_build_counter = 10282 --if this is higher than the regular counter, use it instead + _detalhes.build_counter = 10283 + _detalhes.alpha_build_counter = 10283 --if this is higher than the regular counter, use it instead _detalhes.dont_open_news = true _detalhes.game_version = version _detalhes.userversion = version .. " " .. _detalhes.build_counter diff --git a/classes/class_damage.lua b/classes/class_damage.lua index 0696789a..12eb11eb 100644 --- a/classes/class_damage.lua +++ b/classes/class_damage.lua @@ -5101,12 +5101,154 @@ function atributo_damage:MontaDetalhesDamageDone (spellId, spellLine, instance) end 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) --spell damage chart --events: 1 2 3 4 5 6 7 8 15 + local spellTable = esta_magia + + local blockId = 6 + local thatRectangle66 = Details222.BreakdownWindow.GetBlockIndex(blockId) + thatRectangle66 = thatRectangle66:GetFrame() + + --hide all textures created + if (thatRectangle66.ChartTextures) then + for i = 1, #thatRectangle66.ChartTextures do + thatRectangle66.ChartTextures[i]:Hide() + end + end + + local chartData = Details222.TimeCapture.GetChartDataFromSpell(spellTable) + if (chartData and instance) then + local width, height = thatRectangle66:GetSize() + --reset which texture is the next to be used + thatRectangle66.nextChartTextureId = 1 + + local amountOfTimeStamps = 12 + + if (not thatRectangle66.timeStamps) then + thatRectangle66.timeStamps = {} + for i = 1, amountOfTimeStamps do + thatRectangle66.timeStamps[i] = thatRectangle66:CreateFontString(nil, "overlay", "GameFontNormal") + thatRectangle66.timeStamps[i]:SetPoint("topleft", thatRectangle66, "topleft", 2 + (i - 1) * (width / amountOfTimeStamps), -2) + DetailsFramework:SetFontSize(thatRectangle66.timeStamps[i], 9) + end + end + + if (not thatRectangle66.bloodLustIndicators) then + thatRectangle66.bloodLustIndicators = {} + for i = 1, 2 do + local thisIndicator = thatRectangle66:CreateTexture(nil, "artwork", nil, 4) + thisIndicator:SetColorTexture(0.0980392, 0.0980392, 0.439216) + thatRectangle66.bloodLustIndicators[#thatRectangle66.bloodLustIndicators+1] = thisIndicator + end + end + + for i = 1, #thatRectangle66.bloodLustIndicators do + thatRectangle66.bloodLustIndicators[i]:Hide() + end + + if (not thatRectangle66.ChartTextures) then + thatRectangle66.ChartTextures = {} + function thatRectangle66:GetChartTexture() + local thisTexture = thatRectangle66.ChartTextures[thatRectangle66.nextChartTextureId] + if (not thisTexture) then + thisTexture = thatRectangle66:CreateTexture(nil, "artwork", nil, 5) + thisTexture:SetColorTexture(1, 1, 1, 0.65) + thatRectangle66.ChartTextures[thatRectangle66.nextChartTextureId] = thisTexture + end + thatRectangle66.nextChartTextureId = thatRectangle66.nextChartTextureId + 1 + + return thisTexture + end + end + + --elapsed combat time + local combatObject = instance:GetShowingCombat() + local combatTime = math.floor(combatObject:GetCombatTime()) + thatRectangle66.timeStamps[1]:SetText(DetailsFramework:IntegerToTimer(0)) + for i = 2, #thatRectangle66.timeStamps do + local timePerSegment = combatTime / #thatRectangle66.timeStamps + thatRectangle66.timeStamps[i]:SetText(DetailsFramework:IntegerToTimer(i * timePerSegment)) + end + --compute the width oif each texture + local textureWidth = width / combatTime + --compute the max height of a texture can have + local maxValue = 0 + local numData = 0 + + --need to put the data in order FIRST + --each damage then need to be parsed + + local dataInOrder = {} + + local CONST_INDEX_TIMESTAMP = 1 + local CONST_INDEX_DAMAGEDONE = 2 + local CONST_INDEX_EVENTDAMAGE = 3 + + for timeStamp, value in pairs(chartData) do + dataInOrder[#dataInOrder+1] = {timeStamp, value} + dataInOrder[#dataInOrder+1] = {timeStamp, value} + dataInOrder[#dataInOrder+1] = {timeStamp, value} + numData = numData + 1 + end + + table.sort(dataInOrder, function(t1, t2) return t1[CONST_INDEX_TIMESTAMP] < t2[CONST_INDEX_TIMESTAMP] end) + local damageDoneByTime = dataInOrder + + --parser the damage done + local currentTotalDamage = 0 + + for i = 1, #damageDoneByTime do + local damageEvent = damageDoneByTime[i] + + local atTime = damageEvent[CONST_INDEX_TIMESTAMP] + local totalDamageUntilHere = damageEvent[CONST_INDEX_DAMAGEDONE] --raw damage + + local spellDamage = totalDamageUntilHere - currentTotalDamage + currentTotalDamage = currentTotalDamage + spellDamage + + damageEvent[CONST_INDEX_EVENTDAMAGE] = spellDamage + + maxValue = math.max(spellDamage, maxValue) + end + + --build the chart + for i = 1, #damageDoneByTime do + --for timeStamp, value in pairs(chartData) do --as it is pairs the data is scattered + local damageEvent = damageDoneByTime[i] + local timeStamp = damageEvent[CONST_INDEX_TIMESTAMP] + local damageDone = damageEvent[CONST_INDEX_EVENTDAMAGE] + + local thisTexture = thatRectangle66:GetChartTexture() + thisTexture:SetWidth(textureWidth) + + local texturePosition = textureWidth * timeStamp + + thisTexture:SetPoint("bottomleft", thatRectangle66, "bottomleft", 1 + texturePosition, 1) + + local percentFromPeak = damageDone / maxValue --normalized + thisTexture:SetHeight(math.min(percentFromPeak * height, height - 15)) + thisTexture:Show() + + --print("DEBUG", 7 , "Peak:", percentFromPeak, "position:", texturePosition, "damage done:", damageDone) --debug + end + + --show bloodlust indicators, member .bloodlust is not guarantted + if (combatObject.bloodlust) then + --bloodlust not being added into the combat object, probably a bug on Parser + local bloodlustDuration = 40 + for i = 1, #combatObject.bloodlust do + thatRectangle66.bloodLustIndicators[i]:Show() + thatRectangle66.bloodLustIndicators[i]:SetSize(bloodlustDuration / combatTime * width, height - 2) + thatRectangle66.bloodLustIndicators[i]:SetPoint("bottomleft", thatRectangle66, "bottomleft", 0, 0) + end + end + + DetailsPlayerDetailsWindow_DetalheInfoBG_bg_end6:Hide() + thatRectangle66:SetShown(true) + end _table_sort(data, Details.Sort1) diff --git a/core/control.lua b/core/control.lua index 37f1ca73..f5a7e564 100644 --- a/core/control.lua +++ b/core/control.lua @@ -365,6 +365,8 @@ Details:CatchRaidDebuffUptime ("DEBUFF_UPTIME_IN") Details:UptadeRaidMembersCache() + Details222.TimeCapture.StartCombatTimer(Details.tabela_vigente) + --we already have boss information? build .is_boss table if (Details.encounter_table.id and Details.encounter_table ["start"] >= GetTime() - 3 and not Details.encounter_table ["end"]) then local encounter_table = Details.encounter_table @@ -480,6 +482,8 @@ Details:CatchRaidDebuffUptime ("DEBUFF_UPTIME_OUT") Details:CloseEnemyDebuffsUptime() + Details222.TimeCapture.StopCombat() + --check if this isn't a boss and try to find a boss in the segment if (not Details.tabela_vigente.is_boss) then diff --git a/core/parser.lua b/core/parser.lua index 45b174cc..52fbb272 100755 --- a/core/parser.lua +++ b/core/parser.lua @@ -3608,7 +3608,7 @@ local SPELL_POWER_PAIN = SPELL_POWER_PAIN or (PowerEnum and PowerEnum.Pain) or 1 --main actor local este_jogador = energy_cache [actorName] if (not este_jogador) then --pode ser um desconhecido ou um pet - este_jogador, meu_dono, actorName = _current_energy_container:PegarCombatente (UnitGUID(unitID), actorName, 0x514, true) + este_jogador, meu_dono, actorName = _current_energy_container:PegarCombatente (UnitGUID(unitID), actorName, 0x514, true) --global leak energy_cache [actorName] = este_jogador end este_jogador.alternatepower = este_jogador.alternatepower + addPower diff --git a/frames/window_playerbreakdown.lua b/frames/window_playerbreakdown.lua index f50b9477..c0d2b8ff 100644 --- a/frames/window_playerbreakdown.lua +++ b/frames/window_playerbreakdown.lua @@ -6,6 +6,7 @@ local SharedMedia = LibStub:GetLibrary("LibSharedMedia-3.0") local gump = _detalhes.gump local _ +local addonName, Details222 = ... --lua locals --local _string_len = string.len local _math_floor = math.floor @@ -609,8 +610,13 @@ local detalhes_inforeport_onleave = function(self) Details.FadeHandler.Fader(self, "IN") end +local getFrameFromDetailInfoBlock = function(self) + return self.bg +end + function gump:CriaDetalheInfo(index) local spellInfoBlock = {} + spellInfoBlock.GetFrame = getFrameFromDetailInfoBlock spellInfoBlock.bg = CreateFrame("StatusBar", "DetailsPlayerDetailsWindow_DetalheInfoBG" .. index, _detalhes.playerDetailWindow.container_detalhes, "BackdropTemplate") spellInfoBlock.bg:SetStatusBarTexture("Interface\\AddOns\\Details\\images\\bar_detalhes2") @@ -674,6 +680,12 @@ end --determina qual a pocis�o que a barra de detalhes vai ocupar ------------------------------------------------------------------------------------------------------------------------------ +--namespace +Details222.BreakdownWindow = {} +function Details222.BreakdownWindow.GetBlockIndex(index) + return Details.playerDetailWindow.grupos_detalhes[index] +end + function gump:SetaDetalheInfoAltura(index, xmod, ymod) local spellInfoBlock = _detalhes.playerDetailWindow.grupos_detalhes[index] --local janela = _detalhes.playerDetailWindow.container_detalhes diff --git a/functions/timedata.lua b/functions/timedata.lua index 1c10629f..0dbe5cf4 100644 --- a/functions/timedata.lua +++ b/functions/timedata.lua @@ -4,6 +4,9 @@ local Loc = LibStub("AceLocale-3.0"):GetLocale ( "Details" ) local addonName, Details222 = ... + --create a namespace + Details222.TimeCapture = {} + --mantain the enabled time captures _detalhes.timeContainer = {} _detalhes.timeContainer.Exec = {} @@ -532,3 +535,88 @@ end end + + +------------------------------------------------------------------------------------------------------ +--regular spell timers +Details222.TimeCapture.Timers = {} +local damageContainer +local healingContainer +local timeElapsed = 0 + +local combatTimeTicker = function() + timeElapsed = timeElapsed + 1 +end + +local damageCapture = function(tickerObject) + local actorObject = tickerObject.ActorObject + if (not actorObject) then + tickerObject.ActorObject = damageContainer:GetActor(tickerObject.unitName) + if (not actorObject) then + return + end + end + + for spellId, spellTable in pairs(actorObject.spells._ActorTable) do + local totalDamage = spellTable.total + if (totalDamage) then + if (not spellTable.ChartData) then + spellTable.ChartData = {} + end + spellTable.ChartData[timeElapsed] = totalDamage + end + end +end + +function Details222.TimeCapture.StartCombatTimer(combatObject) + timeElapsed = 0 + damageContainer = combatObject[1] + healingContainer = combatObject[2] + + Details222.TimeCapture.CombatObject = combatObject + Details222.TimeCapture.CombatTimeTicker = C_Timer.NewTicker(1, combatTimeTicker) + + --debug: starting only for the player + Details222.TimeCapture.Start(UnitName("player"), DETAILS_ATTRIBUTE_DAMAGE) +end + +--combat ended on Details! end +function Details222.TimeCapture.StopCombat() + local combatTimeTickerObject = Details222.TimeCapture.CombatTimeTicker + if (combatTimeTickerObject and not combatTimeTickerObject:IsCancelled()) then + combatTimeTickerObject:Cancel() + Details222.TimeCapture.CombatTimeTicker = nil + end + + Details222.TimeCapture.StopAllUnitTimers() +end + +--start a capture for a specific unit +function Details222.TimeCapture.Start(unitName, attribute) + local tickerObject = C_Timer.NewTicker(3, damageCapture) + tickerObject.unitName = unitName + Details222.TimeCapture.Timers[unitName] = tickerObject +end + +function Details222.TimeCapture.StopAllUnitTimers() + for unitName, tickerObject in pairs(Details222.TimeCapture.Timers) do + if (not tickerObject:IsCancelled()) then --why do I need to stop here, it's stopping in the unit itself right below + tickerObject:Cancel() + end + Details222.TimeCapture.Stop(unitName) + end + wipe(Details222.TimeCapture.Timers) +end + +--can be a manual stop or from the stop all unit frames (function above) +function Details222.TimeCapture.Stop(unitName) + local tickerObject = Details222.TimeCapture.Timers[unitName] + if (tickerObject and not tickerObject:IsCancelled()) then + tickerObject:Cancel() + Details222.TimeCapture.Timers[unitName] = nil + end +end + +function Details222.TimeCapture.GetChartDataFromSpell(spellTable) + return spellTable.ChartData +end \ No newline at end of file