--Damage Class --a damage object is created inside an actor container --an actor container is created inside a combat object --combat objects has 4 actor containers: damage, healing, energy, utility --these containers are indexed within the combat object table: combatObject[1] = damage container, combatObject[2] = healing container, combatObject[3] = energy container, combatObject[4] = utility container --damage object local Details = _G.Details local Loc = LibStub("AceLocale-3.0"):GetLocale ( "Details" ) local Translit = LibStub("LibTranslit-1.0") local gump = Details.gump local _ = nil local detailsFramework = DetailsFramework local addonName, Details222 = ... ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --local pointers local format = string.format --lua local local _math_floor = math.floor --lua local local _table_sort = table.sort --lua local local tinsert = table.insert --lua local local setmetatable = setmetatable --lua local local _getmetatable = getmetatable --lua local local ipairs = ipairs --lua local local pairs = pairs --lua local local _math_min = math.min --lua local local _math_max = math.max --lua local local abs = math.abs --lua local local bitBand = bit.band --lua local local unpack = unpack --lua local local type = type --lua local local GameTooltip = GameTooltip --api local local IsInRaid = IsInRaid --api local local IsInGroup = IsInGroup --api local local GetSpellInfo = GetSpellInfo --api local local _GetSpellInfo = Details.getspellinfo --details api local stringReplace = Details.string.replace --details api --show more information about spells local debugmode = false ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --constants local spellContainerClass = Details.container_habilidades local damageClass = Details.atributo_damage local atributo_misc = Details.atributo_misc local container_damage = Details.container_type.CONTAINER_DAMAGE_CLASS local modo_GROUP = Details.modos.group local modo_ALL = Details.modos.all local class_type = Details.atributos.dano local ToKFunctions = Details.ToKFunctions local SelectedToKFunction = ToKFunctions[1] local UsingCustomLeftText = false local UsingCustomRightText = false local FormatTooltipNumber = ToKFunctions[8] local TooltipMaximizedMethod = 1 --local CLASS_ICON_TCOORDS = _G.CLASS_ICON_TCOORDS local is_player_class = Details.player_class Details.tooltip_key_overlay1 = {1, 1, 1, .2} Details.tooltip_key_overlay2 = {1, 1, 1, .5} Details.tooltip_key_size_width = 24 Details.tooltip_key_size_height = 10 local enemies_background = {value = 100, color = {0.1960, 0.1960, 0.1960, 0.8697}, texture = "Interface\\AddOns\\Details\\images\\bar_background2"} local headerColor = {1, 0.9, 0.0, 1} local breakdownWindowFrame = Details.BreakdownWindowFrame local keyName local OBJECT_TYPE_PLAYER = 0x00000400 local ntable = {} --temp local vtable = {} --temp local tooltip_void_zone_temp = {} --temp local bs_table = {} --temp local bs_index_table = {} --temp local bs_tooltip_table local frags_tooltip_table local tooltip_temp_table = {} local OBJECT_TYPE_FRIENDLY_NPC = 0x00000A18 local ignoredEnemyNpcsTable = Details.IgnoredEnemyNpcsTable --damage mixin local damageClassMixin = {} ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --exported functions function Details:CreateActorLastEventTable() --[[exported]] local t = { {}, {}, {}, {}, {}, {}, {}, {} } t.n = 1 return t end function damageClass:CreateFFTable(targetName) --[[exported]] local newTable = {total = 0, spells = {}} self.friendlyfire[targetName] = newTable return newTable end function Details:CreateActorAvoidanceTable(noOverall) --[[exported]] if (noOverall) then local avoidanceTable = {["ALL"] = 0, ["DODGE"] = 0, ["PARRY"] = 0, ["HITS"] = 0, ["ABSORB"] = 0, --quantas vezes foi dodge, parry, quandos hits tomou, quantos absorbs teve ["FULL_HIT"] = 0, ["FULL_ABSORBED"] = 0, ["PARTIAL_ABSORBED"] = 0, --full hit full absorbed and partial absortion ["FULL_HIT_AMT"] = 0, ["PARTIAL_ABSORB_AMT"] = 0, ["ABSORB_AMT"] = 0, ["FULL_ABSORB_AMT"] = 0, --amounts ["BLOCKED_HITS"] = 0, ["BLOCKED_AMT"] = 0, --amount of hits blocked - amout of damage mitigated } return avoidanceTable else local avoidanceTable = { overall = {["ALL"] = 0, ["DODGE"] = 0, ["PARRY"] = 0, ["HITS"] = 0, ["ABSORB"] = 0, --quantas vezes foi dodge, parry, quandos hits tomou, quantos absorbs teve ["FULL_HIT"] = 0, ["FULL_ABSORBED"] = 0, ["PARTIAL_ABSORBED"] = 0, --full hit full absorbed and partial absortion ["FULL_HIT_AMT"] = 0, ["PARTIAL_ABSORB_AMT"] = 0, ["ABSORB_AMT"] = 0, ["FULL_ABSORB_AMT"] = 0, --amounts ["BLOCKED_HITS"] = 0, ["BLOCKED_AMT"] = 0, --amount of hits blocked - amout of damage mitigated } } return avoidanceTable end end function Details.SortGroup(container, keyName2) --[[exported]] keyName = keyName2 return _table_sort(container, Details.SortKeyGroup) end function Details.SortKeyGroup (table1, table2) --[[exported]] if (table1.grupo and table2.grupo) then return table1[keyName] > table2[keyName] elseif (table1.grupo and not table2.grupo) then return true elseif (not table1.grupo and table2.grupo) then return false else return table1[keyName] > table2[keyName] end end function Details.SortKeySimple(table1, table2) --[[exported]] return table1[keyName] > table2[keyName] end ---sort by real time dps ---@param actor1 actor ---@param actor2 actor ---@return boolean function Details.SortByRealTimeDps(actor1, actor2) return (actor1.last_dps_realtime or 0) > (actor2.last_dps_realtime or 0) end function Details:ContainerSort (container, amount, keyName2) --[[exported]] keyName = keyName2 _table_sort(container, Details.SortKeySimple) if (amount) then for i = amount, 1, -1 do --de tr�s pra frente if (container[i][keyName] < 1) then amount = amount-1 else break end end return amount end end ---return true if the actor is a friendly npc ---@return boolean function Details:IsFriendlyNpc() --[[exported]] local flag = self.flag_original if (flag) then if (bitBand(flag, 0x00000008) ~= 0) then if (bitBand(flag, 0x00000010) ~= 0) then if (bitBand(flag, 0x00000800) ~= 0) then return true end end end end return false end function Details:IsEnemy() --[[exported]] if (self.flag_original) then if (bitBand(self.flag_original, 0x00000060) ~= 0) then local npcId = Details:GetNpcIdFromGuid(self.serial) if (ignoredEnemyNpcsTable[npcId]) then return false end return true end end return false end function Details:GetSpellList() --[[exported]] return self.spells._ActorTable end function Details:GetTimeInCombat(petOwner) --[[exported]] if (petOwner) then if (Details.time_type == 1 or not petOwner.grupo) then return self:Tempo() elseif (Details.time_type == 2 or Details.use_realtimedps) then return self:GetCombatTime() end else if (Details.time_type == 1) then return self:Tempo() elseif (Details.time_type == 2 or Details.use_realtimedps) then return self:GetCombatTime() end end end --enemies(sort function) local sortEnemies = function(t1, t2) local a = bitBand(t1.flag_original, 0x00000060) local b = bitBand(t2.flag_original, 0x00000060) if (a ~= 0 and b ~= 0) then local npcid1 = Details:GetNpcIdFromGuid(t1.serial) local npcid2 = Details:GetNpcIdFromGuid(t2.serial) if (not ignoredEnemyNpcsTable[npcid1] and not ignoredEnemyNpcsTable[npcid2]) then return t1.damage_taken > t2.damage_taken elseif (ignoredEnemyNpcsTable[npcid1] and not ignoredEnemyNpcsTable[npcid2]) then return false elseif (not ignoredEnemyNpcsTable[npcid1] and ignoredEnemyNpcsTable[npcid2]) then return true else return t1.damage_taken > t2.damage_taken end elseif (a ~= 0 and b == 0) then return true elseif (a == 0 and b ~= 0) then return false end return false end function Details:ContainerSortEnemies (container, amount, keyName2) --[[exported]] keyName = keyName2 _table_sort(container, sortEnemies) local total = 0 for index, player in ipairs(container) do local npcid1 = Details:GetNpcIdFromGuid(player.serial) --p rint (player.nome, npcid1, ignored_enemy_npcs [npcid1]) if (bitBand(player.flag_original, 0x00000060) ~= 0 and not ignoredEnemyNpcsTable [npcid1]) then --� um inimigo total = total + player [keyName] else amount = index-1 break end end return amount, total end function Details:TooltipForCustom (barra) --[[exported]] GameCooltip:AddLine(Loc ["STRING_LEFT_CLICK_SHARE"]) return true end --[[ Void Zone Sort]] local void_zone_sort = function(t1, t2) if (t1.damage == t2.damage) then return t1.nome <= t2.nome else return t1.damage > t2.damage end end function Details.Sort1(table1, table2) --[[exported]] return table1[1] > table2[1] end function Details.Sort2(table1, table2) --[[exported]] return table1[2] > table2[2] end function Details.Sort3(table1, table2) --[[exported]] return table1[3] > table2[3] end function Details.Sort4(table1, table2) --[[exported]] return table1[4] > table2[4] end function Details.Sort4Reverse(table1, table2) --[[exported]] if (not table2) then return true end return table1[4] < table2[4] end function Details:GetBarColor(actor) --[[exported]] actor = actor or self if (actor.monster) then return unpack(Details.class_colors.ENEMY) elseif (actor.customColor) then return unpack(actor.customColor) elseif (actor.spellicon) then return 0.729, 0.917, 1 elseif (actor.owner) then return unpack(Details.class_colors[actor.owner.classe or "UNKNOW"]) elseif (actor.arena_team and Details.color_by_arena_team) then if (actor.arena_team == 0) then return unpack(Details.class_colors.ARENA_GREEN) else return unpack(Details.class_colors.ARENA_YELLOW) end else if (not is_player_class[actor.classe] and actor.flag_original and bitBand(actor.flag_original, 0x00000020) ~= 0) then --neutral return unpack(Details.class_colors.NEUTRAL) elseif (actor.color) then return unpack(actor.color) else return unpack(Details.class_colors[actor.classe or "UNKNOW"]) end end end function Details:GetSpellLink(spellid) --[[exported]] if (type(spellid) ~= "number") then return spellid end if (spellid == 1) then --melee return GetSpellLink(6603) elseif (spellid == 2) then --autoshot return GetSpellLink(75) elseif (spellid > 10) then return GetSpellLink(spellid) else local spellname = _GetSpellInfo(spellid) return spellname end end function Details:GameTooltipSetSpellByID(spellId) --[[exported]] if (spellId == 1) then GameTooltip:SetSpellByID(6603) elseif (spellId == 2) then GameTooltip:SetSpellByID(75) elseif (spellId > 10) then GameTooltip:SetSpellByID(spellId) else GameTooltip:SetSpellByID(spellId) end end ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --class ~constructor ---create a new actorObject and set the metatable to the actor prototype ---this function is called from within an actorContainer when it needs to create a new actorObject for a new actor ---actorObject is a ordinary table with the actor attributes and a metatable to inherit the functions from Details object ---@return table function damageClass:NovaTabela() --create new actorObject local alphabetical = Details:GetOrderNumber() --constructor: creates a table with the actor attributes and then set the metatable to the actor prototype local newDamageActor = { --type of the actor tipo = class_type, --total: amount of damage done total = alphabetical, total_extra = 0, --totalabsorbed: amount of damage done absorbed by shields totalabsorbed = alphabetical, --total_without_pet: amount of damage done without pet damage total_without_pet = alphabetical, --custom: used by custom scripts, works more like a cache custom = 0, --damage_taken: amount of damage the actor took during the combat damage_taken = alphabetical, --damage_from: table with actor names as keys and boolean true as value damage_from = {}, --dps_started: is false until this actor does damage dps_started = false, --last_event: the time when the actor as last edited by a damage effect: suffered damage, did damage last_event = 0, --on_hold: if the actor is idle, doing nothing during combat, on_hold is true on_hold = false, --delay: the time when the actor went idle delay = 0, --caches last_value = nil, last_dps = 0, --cache of the latest dps value calculated for this actor last_dps_realtime = 0, --cache of the latest real time dps value calculated for this actor --start_time: the time when the actor started to do damage start_time = 0, --end_time: the time when the actor stopped to do damage end_time = nil, --table indexed with pet names pets = {}, --table where key is the raid target flags and the value is the damage done to that target raid_targets = {}, --friendlyfire_total: amount of damage done to friendly players friendlyfire_total = 0, --friendlyfire: table where key is a player name and value is a table with .total: damage inflicted and .spells a table with spell names as keys and damage done as value friendlyfire = {}, --targets: table where key is the target name (actor name) and the value is the amount of damage done to that target targets = {}, --spells: spell container spells = spellContainerClass:NovoContainer(container_damage) } setmetatable(newDamageActor, damageClass) detailsFramework:Mixin(newDamageActor, Details222.Mixins.ActorMixin) detailsFramework:Mixin(newDamageActor, damageClassMixin) return newDamageActor end ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --special cases ---calculate real time dps for each actor within the passed table ---@param tableWithActors actor[] ---@return number function damageClass:RefreshDpsRealTime(tableWithActors) local totalRealTime = 0 local timeSample = Details222.CurrentDPS.GetTimeSample() for _, actorObject in ipairs(tableWithActors) do ---@cast actorObject actordamage ---@type details_currentdps_actorcache local realTimeDPS = Details222.CurrentDPS.Cache[actorObject.serial] if (realTimeDPS) then realTimeDPS = realTimeDPS.totalDamage / timeSample actorObject.last_dps_realtime = realTimeDPS totalRealTime = totalRealTime + realTimeDPS end end return totalRealTime end --dps (calculate dps for actors) ---@param tableWithActors table ---@param combatTime combattime ---@return number, number function damageClass:ContainerRefreshDps(tableWithActors, combatTime) local total = 0 local totalRealTime = 0 local bIsEffectiveTime = Details.time_type == 2 local bOrderDpsByRealTime = Details.CurrentDps.CanSortByRealTimeDps() local timeSample = Details222.CurrentDPS.GetTimeSample() if (bIsEffectiveTime or not Details:CaptureGet("damage")) then for _, actorObject in ipairs(tableWithActors) do ---@cast actorObject actordamage if (actorObject.grupo) then actorObject.last_dps = actorObject.total / combatTime else actorObject.last_dps = actorObject.total / actorObject:Tempo() end if (bOrderDpsByRealTime) then ---@type details_currentdps_actorcache local realTimeDPS = Details222.CurrentDPS.Cache[actorObject.serial] if (realTimeDPS) then realTimeDPS = realTimeDPS.totalDamage / timeSample actorObject.last_dps_realtime = realTimeDPS totalRealTime = totalRealTime + realTimeDPS end end total = total + actorObject.last_dps end else for _, actorObject in ipairs(tableWithActors) do actorObject.last_dps = actorObject.total / actorObject:Tempo() total = total + actorObject.last_dps if (bOrderDpsByRealTime) then local realTimeDPS = Details222.CurrentDPS.Cache[actorObject.serial] or 0 actorObject.last_dps_realtime = realTimeDPS totalRealTime = totalRealTime + realTimeDPS end end end return total, totalRealTime end ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --damage taken by spell local byspell_tooltip_background = {value = 100, color = {0.1960, 0.1960, 0.1960, 0.9097}, texture = [[Interface\AddOns\Details\images\bar_background_dark]]} function Details:ToolTipBySpell (instance, tabela, thisLine, keydown) local GameCooltip = GameCooltip local combat = instance.showing local from_spell = tabela [1] --spellid local from_spellname if (from_spell) then from_spellname = select(1, GetSpellInfo(from_spell)) end --get a list of all damage actors local AllDamageCharacters = combat:GetActorList (DETAILS_ATTRIBUTE_DAMAGE) --hold the targets local Targets = {} local total = 0 local top = 0 local is_custom_spell = false for _, spellcustom in ipairs(Details.savedCustomSpells) do if (spellcustom[1] == from_spell) then is_custom_spell = true end end for index, character in ipairs(AllDamageCharacters) do if (is_custom_spell) then for playername, ff_table in pairs(character.friendlyfire) do if (ff_table.spells [from_spell]) then local damage_actor = combat (1, playername) local heal_actor = combat (2, playername) if ((damage_actor or heal_actor) and ( (damage_actor and damage_actor:IsPlayer()) or (heal_actor and heal_actor:IsPlayer()))) then local got for index, t in ipairs(Targets) do if (t[1] == playername) then t[2] = t[2] + ff_table.spells [from_spell] total = total + ff_table.spells [from_spell] if (t[2] > top) then top = t[2] end got = true break end end if (not got) then Targets [#Targets+1] = {playername, ff_table.spells [from_spell]} total = total + ff_table.spells [from_spell] if (ff_table.spells [from_spell] > top) then top = ff_table.spells [from_spell] end end end end end else for playername, ff_table in pairs(character.friendlyfire) do for spellid, amount in pairs(ff_table.spells) do local spellname = select(1, GetSpellInfo(spellid)) if (spellname == from_spellname) then local damage_actor = combat (1, playername) local heal_actor = combat (2, playername) if ((damage_actor or heal_actor) and ( (damage_actor and damage_actor:IsPlayer()) or (heal_actor and heal_actor:IsPlayer()))) then local got for index, t in ipairs(Targets) do if (t[1] == playername) then t[2] = t[2] + amount total = total + amount if (t[2] > top) then top = t[2] end got = true break end end if (not got) then Targets [#Targets+1] = {playername, amount} total = total + amount if (amount > top) then top = amount end end end end end end end --search actors which used the spell shown in the bar local spell = character.spells._ActorTable [from_spell] if (spell) then for targetname, amount in pairs(spell.targets) do local got = false local damage_actor = combat (1, targetname) local heal_actor = combat (2, targetname) if ( (damage_actor or heal_actor) and ( (damage_actor and damage_actor:IsPlayer()) or (heal_actor and heal_actor:IsPlayer()) ) ) then for index, t in ipairs(Targets) do if (t[1] == targetname) then t[2] = t[2] + amount total = total + amount if (t[2] > top) then top = t[2] end got = true break end end if (not got) then Targets [#Targets+1] = {targetname, amount} total = total + amount if (amount > top) then top = amount end end end end end if (not is_custom_spell) then for spellid, spell in pairs(character.spells._ActorTable) do if (spellid ~= from_spell) then local spellname = select(1, GetSpellInfo(spellid)) if (spellname == from_spellname) then for targetname, amount in pairs(spell.targets) do local got = false local damage_actor = combat (1, targetname) local heal_actor = combat (2, targetname) if ( (damage_actor or heal_actor) and ( (damage_actor and damage_actor:IsPlayer()) or (heal_actor and heal_actor:IsPlayer()) ) ) then for index, t in ipairs(Targets) do if (t[1] == targetname) then t[2] = t[2] + amount total = total + amount if (t[2] > top) then top = t[2] end got = true break end end if (not got) then Targets [#Targets+1] = {targetname, amount} total = total + amount if (amount > top) then top = amount end end end end end end end end end table.sort (Targets, Details.Sort2) bs_tooltip_table = Targets bs_tooltip_table.damage_total = total GameCooltip:SetOption("StatusBarTexture", "Interface\\AddOns\\Details\\images\\bar_serenity") local spellname, _, spellicon = select(1, _GetSpellInfo(from_spell)) GameCooltip:AddLine(spellname .. " " .. Loc ["STRING_CUSTOM_ATTRIBUTE_DAMAGE"], nil, nil, headerColor, nil, 10) GameCooltip:AddIcon (spellicon, 1, 1, 14, 14, 0.078125, 0.921875, 0.078125, 0.921875) GameCooltip:AddIcon ([[Interface\AddOns\Details\images\key_shift]], 1, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay2) Details:AddTooltipHeaderStatusbar (1, 1, 1, 0.5) local top = Targets[1] and Targets[1][2] local lineHeight = Details.tooltip.line_height for index, t in ipairs(Targets) do GameCooltip:AddLine(Details:GetOnlyName(t[1]), Details:ToK(t[2]) .. " (" .. format("%.1f", t[2]/total*100) .. "%)") local class, _, _, _, _, r, g, b = Details:GetClass(t[1]) GameCooltip:AddStatusBar (t[2]/top*100, 1, r, g, b, 0.8, false, byspell_tooltip_background) if (class) then local specID = Details:GetSpec(t[1]) if (specID) then local texture, l, r, t, b = Details:GetSpecIcon (specID, false) GameCooltip:AddIcon (texture, 1, 1, lineHeight, lineHeight, l, r, t, b) else local texture, l, r, t, b = Details:GetClassIcon(class) GameCooltip:AddIcon ("Interface\\AddOns\\Details\\images\\classes_small_alpha", 1, 1, lineHeight, lineHeight, l, r, t, b) end elseif (t[1] == Loc ["STRING_TARGETS_OTHER1"]) then GameCooltip:AddIcon ("Interface\\AddOns\\Details\\images\\classes_small_alpha", 1, 1, lineHeight, lineHeight, 0.25, 0.49609375, 0.75, 1) end end GameCooltip:AddLine(" ") Details:AddTooltipReportLineText() GameCooltip:SetOption("YSpacingMod", 0) GameCooltip:SetOwner(thisLine) GameCooltip:Show() end local function RefreshBarraBySpell (tabela, barra, instancia) damageClass:AtualizarBySpell (tabela, tabela.minha_barra, barra.colocacao, instancia) end local on_switch_DTBS_show = function(instance) instance:TrocaTabela(instance, true, 1, 8) return true end local DTBS_search_code = [[ ---@type combat, table, instance local combatObject, instanceContainer, instanceObject = ... --declade the values to return local totalDamage, topDamage, amount = 0, 0, 0 ---@type {key1: actorname, key2: number, key3: actor}[] local damageTakenFrom = {} local spellId = @SPELLID@ local spellName if (spellId) then spellName = select(1, GetSpellInfo(spellId)) end ---@type actorcontainer local damageContainer = combatObject:GetContainer(DETAILS_ATTRIBUTE_DAMAGE) ---@type actorcontainer local healContainer = combatObject:GetContainer(DETAILS_ATTRIBUTE_HEAL) local bIsCustomSpell = false for _, customSpellObject in ipairs(Details.savedCustomSpells) do if (customSpellObject[1] == spellId) then bIsCustomSpell = true end end for index, actorObject in damageContainer:ListActors() do ---@cast actorObject actordamage --> handle friendly fire spell damage taken if (actorObject:IsPlayer()) then if (bIsCustomSpell) then --if the spell has been modified, check only by its spellId, as it can't get other spells with the same name for playerName, friendlyFireTable in pairs(actorObject.friendlyfire) do ---@cast friendlyFireTable friendlyfiretable if (friendlyFireTable.spells[spellId]) then ---@type actordamage local damageActor = damageContainer:GetActor(playerName) ---@type actorheal local healingActor = healContainer:GetActor(playerName) if ((damageActor and damageActor:IsPlayer()) or (healingActor and healingActor:IsPlayer())) then local got for index, damageTakenTable in ipairs(damageTakenFrom) do if (damageTakenTable[1] == playerName) then damageTakenTable[2] = damageTakenTable[2] + friendlyFireTable.spells[spellId] if (damageTakenTable[2] > topDamage) then topDamage = damageTakenTable[2] end got = true break end end if (not got) then ---@type {key1: actorname, key2: number, key3: actor} local damageTakenTable = {playerName, friendlyFireTable.spells[spellId], damageActor or healingActor} damageTakenFrom[#damageTakenFrom+1] = damageTakenTable if (friendlyFireTable.spells[spellId] > topDamage) then topDamage = friendlyFireTable.spells[spellId] end end end end end else for playerName, friendlyFireTable in pairs(actorObject.friendlyfire) do ---@cast friendlyFireTable friendlyfiretable for ffSpellId, damageAmount in pairs(friendlyFireTable.spells) do local ffSpellName = select(1, GetSpellInfo(ffSpellId)) if (ffSpellName == spellName) then ---@type actordamage local damageActor = damageContainer:GetActor(playerName) ---@type actorheal local healingActor = healContainer:GetActor(playerName) if ((damageActor and damageActor:IsPlayer()) or (healingActor and healingActor:IsPlayer())) then local got for index, damageTakenTable in ipairs(damageTakenFrom) do if (damageTakenTable[1] == playerName) then damageTakenTable[2] = damageTakenTable[2] + damageAmount if (damageTakenTable[2] > topDamage) then topDamage = damageTakenTable[2] end got = true break end end if (not got) then ---@type {key1: actorname, key2: number, key3: actor} local damageTakenTable = {playerName, damageAmount, damageActor or healingActor} damageTakenFrom[#damageTakenFrom+1] = damageTakenTable if (damageAmount > topDamage) then topDamage = damageAmount end end end end end end end end --> handle regular damage taken from spells ---@type spelltable local spellTable = actorObject:GetSpell(spellId) if (spellTable) then for targetName, damageAmount in pairs(spellTable.targets) do local got = false ---@type actordamage local damageActor = damageContainer:GetActor(targetName) ---@type actorheal local healingActor = healContainer:GetActor(targetName) if ((damageActor and damageActor:IsPlayer()) or (healingActor and healingActor:IsPlayer())) then for index, damageTakenTable in ipairs(damageTakenFrom) do if (damageTakenTable[1] == targetName) then damageTakenTable[2] = damageTakenTable[2] + damageAmount if (damageTakenTable[2] > topDamage) then topDamage = damageTakenTable[2] end got = true break end end if (not got) then ---@type {key1: actorname, key2: number, key3: actor} local damageTakenTable = {targetName, damageAmount, damageActor or healingActor} damageTakenFrom[#damageTakenFrom+1] = damageTakenTable if (damageAmount > topDamage) then topDamage = damageAmount end end end end end if (not bIsCustomSpell) then for thisSpellId, spellTable in pairs(actorObject.spells._ActorTable) do if (thisSpellId ~= spellId) then --this is invalid local spellname = select(1, GetSpellInfo(thisSpellId)) if (spellname == spellName) then for targetName, damageAmount in pairs(spellTable.targets) do local got = false ---@type actordamage local damageActor = damageContainer:GetActor(targetName) ---@type actorheal local healingActor = healContainer:GetActor(targetName) if ((damageActor and damageActor:IsPlayer()) or (healingActor and healingActor:IsPlayer())) then for index, damageTakenTable in ipairs(damageTakenFrom) do if (damageTakenTable[1] == targetName) then damageTakenTable[2] = damageTakenTable[2] + damageAmount if (damageTakenTable[2] > topDamage) then topDamage = damageTakenTable[2] end got = true break end end if (not got) then ---@type {key1: actorname, key2: number, key3: actor} local damageTakenTable = {targetName, damageAmount, damageActor or healingActor} damageTakenFrom[#damageTakenFrom+1] = damageTakenTable if (damageAmount > topDamage) then topDamage = damageAmount end end end end end end end end end table.sort(damageTakenFrom, Details.Sort2) for index, damageTakenTable in ipairs(damageTakenFrom) do instanceContainer:AddValue(damageTakenTable[3], damageTakenTable[2]) --actorObject, amountDamage totalDamage = totalDamage + damageTakenTable[2] --amountDamage amount = amount + 1 end return totalDamage, topDamage, amount ]] local function ShowDTBSInWindow (spell, instance) --for hold shift key and click, show players which took damage from this spell local spellname, _, icon = _GetSpellInfo(spell [1]) local custom_name = spellname .. " - " .. Loc ["STRING_CUSTOM_DTBS"] .. "" --check if already exists for index, CustomObject in ipairs(Details.custom) do if (CustomObject:GetName() == custom_name) then --fix for not saving funcs on logout if (not CustomObject.OnSwitchShow) then CustomObject.OnSwitchShow = on_switch_DTBS_show end return instance:TrocaTabela(instance.segmento, 5, index) end end --create a custom for this spell local new_custom_object = { name = custom_name, icon = icon, attribute = false, author = Details.playername, desc = spellname .. " " .. Loc ["STRING_CUSTOM_DTBS"], source = false, target = false, script = false, tooltip = false, temp = true, notooltip = true, OnSwitchShow = on_switch_DTBS_show, } local new_code = DTBS_search_code new_code = new_code:gsub("@SPELLID@", spell [1]) new_custom_object.script = new_code tinsert(Details.custom, new_custom_object) setmetatable(new_custom_object, Details.atributo_custom) new_custom_object.__index = Details.atributo_custom return instance:TrocaTabela(instance.segmento, 5, #Details.custom) end local DTBS_format_name = function(player_name) return Details:GetOnlyName(player_name) end local DTBS_format_amount = function(amount) return Details:ToK(amount) .. " (" .. format("%.1f", amount / bs_tooltip_table.damage_total * 100) .. "%)" end function damageClass:ReportSingleDTBSLine (spell, instance, ShiftKeyDown, ControlKeyDown) if (ControlKeyDown) then local spellname, _, spellicon = _GetSpellInfo(spell[1]) return Details:OpenAuraPanel (spell[1], spellname, spellicon) elseif (ShiftKeyDown) then return ShowDTBSInWindow (spell, instance) end local spelllink = Details:GetSpellLink(spell [1]) local report_table = {"Details!: " .. Loc ["STRING_CUSTOM_DTBS"] .. " " .. spelllink} Details:FormatReportLines(report_table, bs_tooltip_table, DTBS_format_name, DTBS_format_amount) return Details:Reportar(report_table, {_no_current = true, _no_inverse = true, _custom = true}) end function damageClass:AtualizarBySpell(tabela, whichRowLine, colocacao, instance) tabela ["byspell"] = true --marca que esta tabela � uma tabela de frags, usado no controla na hora de montar o tooltip local thisLine = instance.barras [whichRowLine] --pega a refer�ncia da barra na janela if (not thisLine) then print("DEBUG: problema com "..whichRowLine .. " " .. colocacao) return end thisLine.minha_tabela = tabela local spellName, _, spellIcon = _GetSpellInfo(tabela[1]) tabela.nome = spellName --evita dar erro ao redimencionar a janela tabela.minha_barra = whichRowLine thisLine.colocacao = colocacao if (not _getmetatable (tabela)) then setmetatable(tabela, {__call = RefreshBarraBySpell}) tabela._custom = true end local total = instance.showing.totals.by_spell local porcentagem if (instance.row_info.percent_type == 1) then porcentagem = format("%.1f", tabela [2] / total * 100) elseif (instance.row_info.percent_type == 2) then porcentagem = format("%.1f", tabela [2] / instance.top * 100) end thisLine.lineText1:SetText(colocacao .. ". " .. spellName) local bars_show_data = instance.row_info.textR_show_data local spell_damage = tabela[2] -- spell_damage passar por uma ToK function, precisa ser number if (not bars_show_data [1]) then spell_damage = tabela[2] --damage taken by spell n�o tem PS, ent�o � obrigado a passar o dano total end if (not bars_show_data[3]) then porcentagem = "" else porcentagem = porcentagem .. "%" end local bars_brackets = instance:GetBarBracket() if (instance.use_multi_fontstrings) then instance:SetInLineTexts(thisLine, "", (spell_damage and SelectedToKFunction(_, spell_damage) or ""), porcentagem) else thisLine.lineText4:SetText((spell_damage and SelectedToKFunction(_, spell_damage) or "") .. bars_brackets[1] .. porcentagem .. bars_brackets[2]) end thisLine.lineText1:SetTextColor(1, 1, 1, 1) thisLine.lineText2:SetTextColor(1, 1, 1, 1) thisLine.lineText3:SetTextColor(1, 1, 1, 1) thisLine.lineText4:SetTextColor(1, 1, 1, 1) thisLine.lineText1:SetSize(thisLine:GetWidth() - thisLine.lineText4:GetStringWidth() - 20, 15) if (colocacao == 1) then thisLine:SetValue(100) else thisLine:SetValue(tabela[2] / instance.top * 100) end if (thisLine.hidden or thisLine.fading_in or thisLine.faded) then Details.FadeHandler.Fader(thisLine, "out") end if (instance.row_info.texture_class_colors) then if (tabela [3] > 1) then local r, g, b = Details:GetSpellSchoolColor(tabela[3]) thisLine.textura:SetVertexColor(r, g, b) else local r, g, b = Details:GetSpellSchoolColor(0) thisLine.textura:SetVertexColor(r, g, b) end end thisLine.icone_classe:SetTexture(spellIcon) thisLine.icone_classe:SetTexCoord(0.078125, 0.921875, 0.078125, 0.921875) thisLine.icone_classe:SetVertexColor(1, 1, 1) if(thisLine.mouse_over and not instance.baseframe.isMoving) then local classIcon = thisLine:GetClassIcon() thisLine.iconHighlight:SetTexture(classIcon:GetTexture()) thisLine.iconHighlight:SetTexCoord(classIcon:GetTexCoord()) thisLine.iconHighlight:SetVertexColor(classIcon:GetVertexColor()) end end ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --frags function Details:ToolTipFrags (instancia, frag, thisLine, keydown) local name = frag [1] local GameCooltip = GameCooltip --mantendo a fun��o o mais low level poss�vel local damage_container = instancia.showing [1] local frag_actor = damage_container._ActorTable [damage_container._NameIndexTable [ name ]] if (frag_actor) then local damage_taken_table = {} local took_damage_from = frag_actor.damage_from local total_damage_taken = frag_actor.damage_taken local total = 0 for aggressor, _ in pairs(took_damage_from) do local damager_actor = damage_container._ActorTable [damage_container._NameIndexTable [ aggressor ]] if (damager_actor and not damager_actor.owner) then --checagem por causa do total e do garbage collector que n�o limpa os names que deram dano local target_amount = damager_actor.targets [name] if (target_amount) then damage_taken_table [#damage_taken_table+1] = {aggressor, target_amount, damager_actor.classe} total = total + target_amount end end end _table_sort(damage_taken_table, Details.Sort2) Details:AddTooltipSpellHeaderText (Loc ["STRING_DAMAGE_FROM"], headerColor, #damage_taken_table, [[Interface\Addons\Details\images\icons]], 0.126953125, 0.1796875, 0, 0.0546875) Details:AddTooltipHeaderStatusbar (1, 1, 1, 0.5) GameCooltip:AddIcon ([[Interface\AddOns\Details\images\key_shift]], 1, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay2) local min = 6 local ismaximized = false --always maximized if (true or keydown == "shift" or TooltipMaximizedMethod == 2 or TooltipMaximizedMethod == 3) then min = 99 ismaximized = true end if (ismaximized) then GameCooltip:AddIcon ([[Interface\AddOns\Details\images\key_shift]], 1, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay2) else GameCooltip:AddIcon ([[Interface\AddOns\Details\images\key_shift]], 1, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay1) end local top = damage_taken_table[1] and damage_taken_table[1][2] frags_tooltip_table = damage_taken_table frags_tooltip_table.damage_total = total local lineHeight = Details.tooltip.line_height if (#damage_taken_table > 0) then for i = 1, math.min (min, #damage_taken_table) do local t = damage_taken_table [i] GameCooltip:AddLine(Details:GetOnlyName(t[1]), FormatTooltipNumber (_, t[2]) .. " (" .. format("%.1f", t[2] / total * 100) .. "%)") local classe = t[3] if (not classe) then classe = "UNKNOW" end if (classe == "UNKNOW") then GameCooltip:AddIcon ("Interface\\LFGFRAME\\LFGROLE_BW", nil, nil, lineHeight, lineHeight, .25, .5, 0, 1) else local specID = Details:GetSpec(t[1]) if (specID) then local texture, l, r, t, b = Details:GetSpecIcon (specID, false) GameCooltip:AddIcon (texture, 1, 1, lineHeight, lineHeight, l, r, t, b) else GameCooltip:AddIcon ([[Interface\AddOns\Details\images\classes_small_alpha]], nil, nil, lineHeight, lineHeight, unpack(Details.class_coords [classe])) end end local _, _, _, _, _, r, g, b = Details:GetClass(t[1]) GameCooltip:AddStatusBar (t[2] / top * 100, 1, r, g, b, 1, false, enemies_background) end else GameCooltip:AddLine(Loc ["STRING_NO_DATA"], nil, 1, "white") GameCooltip:AddIcon (instancia.row_info.icon_file, nil, nil, 14, 14, unpack(Details.class_coords ["UNKNOW"])) end GameCooltip:AddLine(" ") Details:AddTooltipReportLineText() GameCooltip:SetOption("StatusBarTexture", "Interface\\AddOns\\Details\\images\\bar_serenity") GameCooltip:ShowCooltip() end end local function RefreshBarraFrags (tabela, barra, instancia) damageClass:AtualizarFrags(tabela, tabela.minha_barra, barra.colocacao, instancia) end function damageClass:AtualizarFrags(tabela, whichRowLine, colocacao, instancia) tabela ["frags"] = true --marca que esta tabela � uma tabela de frags, usado no controla na hora de montar o tooltip local thisLine = instancia.barras [whichRowLine] --pega a refer�ncia da barra na janela if (not thisLine) then print("DEBUG: problema com "..whichRowLine.." "..rank) return end local previousData = thisLine.minha_tabela thisLine.minha_tabela = tabela tabela.nome = tabela [1] --evita dar erro ao redimencionar a janela tabela.minha_barra = whichRowLine thisLine.colocacao = colocacao if (not _getmetatable (tabela)) then setmetatable(tabela, {__call = RefreshBarraFrags}) tabela._custom = true end local total = instancia.showing.totals.frags_total local porcentagem if (instancia.row_info.percent_type == 1) then porcentagem = format("%.1f", tabela [2] / total * 100) elseif (instancia.row_info.percent_type == 2) then porcentagem = format("%.1f", tabela [2] / instancia.top * 100) end thisLine.lineText1:SetText(colocacao .. ". " .. tabela [1]) local bars_show_data = instancia.row_info.textR_show_data local bars_brackets = instancia:GetBarBracket() local total_frags = tabela [2] if (not bars_show_data [1]) then total_frags = "" end if (not bars_show_data [3]) then porcentagem = "" else porcentagem = porcentagem .. "%" end -- if (instancia.use_multi_fontstrings) then instancia:SetInLineTexts(thisLine, "", total_frags, porcentagem) else thisLine.lineText4:SetText(total_frags .. bars_brackets[1] .. porcentagem .. bars_brackets[2]) end thisLine.lineText1:SetSize(thisLine:GetWidth() - thisLine.lineText4:GetStringWidth() - 20, 15) if (colocacao == 1) then thisLine:SetValue(100) else thisLine:SetValue(tabela [2] / instancia.top * 100) end thisLine.lineText1:SetTextColor(1, 1, 1, 1) thisLine.lineText4:SetTextColor(1, 1, 1, 1) if (thisLine.hidden or thisLine.fading_in or thisLine.faded) then Details.FadeHandler.Fader(thisLine, "out") end Details:SetBarColors(thisLine, instancia, unpack(Details.class_colors [tabela [3]])) if (tabela [3] == "UNKNOW" or tabela [3] == "UNGROUPPLAYER" or tabela [3] == "ENEMY") then thisLine.icone_classe:SetTexture([[Interface\AddOns\Details\images\classes_plus]]) thisLine.icone_classe:SetTexCoord(0.50390625, 0.62890625, 0, 0.125) thisLine.icone_classe:SetVertexColor(1, 1, 1) else thisLine.icone_classe:SetTexture(instancia.row_info.icon_file) thisLine.icone_classe:SetTexCoord(unpack(Details.class_coords [tabela [3]])) thisLine.icone_classe:SetVertexColor(1, 1, 1) end if (thisLine.mouse_over and not instancia.baseframe.isMoving) then --precisa atualizar o tooltip --gump:UpdateTooltip(whichRowLine, thisLine, instancia)if(thisLine.mouse_over and not instancia.baseframe.isMoving) then local classIcon = thisLine:GetClassIcon() thisLine.iconHighlight:SetTexture(classIcon:GetTexture()) thisLine.iconHighlight:SetTexCoord(classIcon:GetTexCoord()) thisLine.iconHighlight:SetVertexColor(classIcon:GetVertexColor()) end end ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --void zones local on_switch_AVZ_show = function(instance) instance:TrocaTabela(instance, true, 1, 7) return true end local AVZ_search_code = [[ --get the parameters passed local combat, instance_container, instance = ... --declade the values to return local total, top, amount = 0, 0, 0 local actor_name = "@ACTORNAME@" local actor = combat (4, actor_name) if (not actor) then return 0, 0, 0 end local damage_actor = combat (1, actor.damage_twin) local habilidade local alvos if (damage_actor) then habilidade = damage_actor.spells._ActorTable [actor.damage_spellid] end if (habilidade) then alvos = habilidade.targets end local container = actor.debuff_uptime_targets local tooltip_void_zone_temp = {} for target_name, debuff_table in pairs(container) do if (alvos) then local damage_alvo = alvos [target_name] if (damage_alvo) then debuff_table.damage = damage_alvo else debuff_table.damage = 0 end else debuff_table.damage = 0 end end local i = 1 for target_name, debuff_table in pairs(container) do local t = tooltip_void_zone_temp [i] if (not t) then t = {} tinsert(tooltip_void_zone_temp, t) end local target_actor = combat (1, target_name) or combat (2, target_name) or combat (4, target_name) t[1] = target_name t[2] = debuff_table.damage t[3] = debuff_table t[4] = target_actor i = i + 1 end --sort no container: table.sort (tooltip_void_zone_temp, Details.sort_tooltip_void_zones) for index, t in ipairs(tooltip_void_zone_temp) do instance_container:AddValue (t[4], t[2]) local custom_actor = instance_container:GetActorTable(t[4]) custom_actor.uptime = t[3].uptime total = total + t[2] amount = amount + 1 if (t[2] > top) then top = t[2] end end return total, top, amount ]] local AVZ_total_code = [[ local value, top, total, combat, instance, custom_actor = ... local uptime = custom_actor.uptime or 0 local minutos, segundos = floor(uptime / 60), floor(uptime % 60) if (minutos > 0) then uptime = "" .. minutos .. "m " .. segundos .. "s" .. "" else uptime = "" .. segundos .. "s" .. "" end return Details:ToK2(value) .. " - " .. uptime .. " " ]] local function ShowVoidZonesInWindow (actor, instance) local spellid = tooltip_void_zone_temp.spellid local spellname, _, icon = _GetSpellInfo(spellid) local custom_name = spellname .. " - " .. Loc ["STRING_ATTRIBUTE_DAMAGE_DEBUFFS_REPORT"] .. "" --check if already exists for index, CustomObject in ipairs(Details.custom) do if (CustomObject:GetName() == custom_name) then --fix for not saving funcs on logout if (not CustomObject.OnSwitchShow) then CustomObject.OnSwitchShow = on_switch_AVZ_show end return instance:TrocaTabela(instance.segmento, 5, index) end end --create a custom for this spell local new_custom_object = { name = custom_name, icon = icon, attribute = false, author = Details.playername, desc = spellname .. " " .. Loc ["STRING_ATTRIBUTE_DAMAGE_DEBUFFS_REPORT"], source = false, target = false, script = false, tooltip = false, temp = true, notooltip = true, OnSwitchShow = on_switch_AVZ_show, } local new_code = AVZ_search_code new_code = new_code:gsub("@ACTORNAME@", actor.nome) new_custom_object.script = new_code local new_total_code = AVZ_total_code new_total_code = new_total_code:gsub("@ACTORNAME@", actor.nome) new_total_code = new_total_code:gsub("@SPELLID@", spellid) new_custom_object.total_script = new_total_code tinsert(Details.custom, new_custom_object) setmetatable(new_custom_object, Details.atributo_custom) new_custom_object.__index = Details.atributo_custom return instance:TrocaTabela(instance.segmento, 5, #Details.custom) end function damageClass:ReportSingleVoidZoneLine (actor, instance, ShiftKeyDown, ControlKeyDown) local spellid = tooltip_void_zone_temp.spellid if (ControlKeyDown) then local spellname, _, spellicon = _GetSpellInfo(spellid) return Details:OpenAuraPanel (spellid, spellname, spellicon) elseif (ShiftKeyDown) then return ShowVoidZonesInWindow (actor, instance) end local spelllink = Details:GetSpellLink(spellid) local report_table = {"Details!: " .. spelllink .. " " .. Loc ["STRING_ATTRIBUTE_DAMAGE_DEBUFFS_REPORT"]} local t = {} for index, void_table in ipairs(tooltip_void_zone_temp) do --ir� reportar dano zero tamb�m if (void_table[1] and type(void_table[1]) == "string" and void_table[2] and void_table[3] and type(void_table[3]) == "table") then local actor_table = {Details:GetOnlyName(void_table[1])} local m, s = _math_floor(void_table[3].uptime / 60), _math_floor(void_table[3].uptime % 60) if (m > 0) then actor_table [2] = FormatTooltipNumber (_, void_table[3].damage) .. " (" .. m .. "m " .. s .. "s" .. ")" else actor_table [2] = FormatTooltipNumber (_, void_table[3].damage) .. " (" .. s .. "s" .. ")" end t [#t+1] = actor_table end end Details:FormatReportLines (report_table, t) return Details:Reportar (report_table, {_no_current = true, _no_inverse = true, _custom = true}) end local sort_tooltip_void_zones = function(tabela1, tabela2) if (tabela1 [2] > tabela2 [2]) then return true elseif (tabela1 [2] == tabela2 [2]) then if (tabela1[1] ~= "" and tabela2[1] ~= "") then return tabela1 [3].uptime > tabela2 [3].uptime elseif (tabela1[1] ~= "") then return true elseif (tabela2[1] ~= "") then return false end else return false end end Details.sort_tooltip_void_zones = sort_tooltip_void_zones function Details:ToolTipVoidZones (instancia, actor, barra, keydown) local damage_actor = instancia.showing[1]:PegarCombatente (_, actor.damage_twin) local habilidade local alvos if (damage_actor) then habilidade = damage_actor.spells._ActorTable [actor.damage_spellid] end if (habilidade) then alvos = habilidade.targets end local container = actor.debuff_uptime_targets for target_name, debuff_table in pairs(container) do if (alvos) then local damage_alvo = alvos [target_name] if (damage_alvo) then debuff_table.damage = damage_alvo else debuff_table.damage = 0 end else debuff_table.damage = 0 end end for i = 1, #tooltip_void_zone_temp do local t = tooltip_void_zone_temp [i] t[1] = "" t[2] = 0 t[3] = 0 end local i = 1 for target_name, debuff_table in pairs(container) do local t = tooltip_void_zone_temp [i] if (not t) then t = {} tinsert(tooltip_void_zone_temp, t) end t[1] = target_name t[2] = debuff_table.damage t[3] = debuff_table i = i + 1 end --sort no container: _table_sort(tooltip_void_zone_temp, sort_tooltip_void_zones) --monta o cooltip local GameCooltip = GameCooltip local spellname, _, spellicon = _GetSpellInfo(actor.damage_spellid) Details:AddTooltipSpellHeaderText (spellname .. " " .. Loc ["STRING_VOIDZONE_TOOLTIP"], headerColor, #tooltip_void_zone_temp, spellicon, 0.078125, 0.921875, 0.078125, 0.921875) Details:AddTooltipHeaderStatusbar (1, 1, 1, 0.5) GameCooltip:AddIcon ([[Interface\AddOns\Details\images\key_shift]], 1, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay2) --for target_name, debuff_table in pairs(container) do local first = tooltip_void_zone_temp [1] and tooltip_void_zone_temp [1][3] if (type(first) == "table") then first = first.damage end tooltip_void_zone_temp.spellid = actor.damage_spellid tooltip_void_zone_temp.current_actor = actor local lineHeight = Details.tooltip.line_height for index, t in ipairs(tooltip_void_zone_temp) do if (t[3] == 0) then break end local debuff_table = t[3] local minutos, segundos = _math_floor(debuff_table.uptime / 60), _math_floor(debuff_table.uptime % 60) if (minutos > 0) then GameCooltip:AddLine(Details:GetOnlyName(t[1]), FormatTooltipNumber (_, debuff_table.damage) .. " (" .. minutos .. "m " .. segundos .. "s" .. ")") else GameCooltip:AddLine(Details:GetOnlyName(t[1]), FormatTooltipNumber (_, debuff_table.damage) .. " (" .. segundos .. "s" .. ")") end local classe = Details:GetClass(t[1]) if (classe) then local specID = Details:GetSpec(t[1]) if (specID) then local texture, l, r, t, b = Details:GetSpecIcon (specID, false) GameCooltip:AddIcon (texture, 1, 1, lineHeight, lineHeight, l, r, t, b) else GameCooltip:AddIcon ([[Interface\AddOns\Details\images\classes_small_alpha]], nil, nil, lineHeight, lineHeight, unpack(Details.class_coords [classe])) end else GameCooltip:AddIcon ("Interface\\LFGFRAME\\LFGROLE_BW", nil, nil, lineHeight, lineHeight, .25, .5, 0, 1) end local _, _, _, _, _, r, g, b = Details:GetClass(t[1]) if (first == 0) then first = 0.0000000001 end GameCooltip:AddStatusBar (debuff_table.damage / first * 100, 1, r, g, b, 1, false, enemies_background) --Details:AddTooltipBackgroundStatusbar() end GameCooltip:AddLine(" ") Details:AddTooltipReportLineText() GameCooltip:SetOption("StatusBarTexture", "Interface\\AddOns\\Details\\images\\bar_serenity") GameCooltip:ShowCooltip() end local function RefreshBarraVoidZone (tabela, barra, instancia) tabela:AtualizarVoidZone (tabela.minha_barra, barra.colocacao, instancia) end function atributo_misc:AtualizarVoidZone (whichRowLine, colocacao, instancia) --pega a refer�ncia da barra na janela local thisLine = instancia.barras[whichRowLine] if (not thisLine) then print("DEBUG: problema com "..whichRowLine.." "..rank) return end self._refresh_window = RefreshBarraVoidZone local previousData = thisLine.minha_tabela thisLine.minha_tabela = self self.minha_barra = whichRowLine thisLine.colocacao = colocacao local total = instancia.showing.totals.voidzone_damage local combat_time = instancia.showing:GetCombatTime() local dps = _math_floor(self.damage / combat_time) local formated_damage = SelectedToKFunction(_, self.damage) local formated_dps = SelectedToKFunction(_, dps) local porcentagem if (instancia.row_info.percent_type == 1) then total = max(total, 0.0001) porcentagem = format("%.1f", self.damage / total * 100) elseif (instancia.row_info.percent_type == 2) then local top = max(instancia.top, 0.0001) porcentagem = format("%.1f", self.damage / top * 100) end local bars_show_data = instancia.row_info.textR_show_data local bars_brackets = instancia:GetBarBracket() local bars_separator = instancia:GetBarSeparator() if (not bars_show_data [1]) then formated_damage = "" end if (not bars_show_data [2]) then formated_dps = "" end if (not bars_show_data [3]) then porcentagem = "" else porcentagem = porcentagem .. "%" end local rightText = formated_damage .. bars_brackets[1] .. formated_dps .. bars_separator .. porcentagem .. bars_brackets[2] if (UsingCustomRightText) then thisLine.lineText4:SetText(stringReplace(instancia.row_info.textR_custom_text, formated_damage, formated_dps, porcentagem, self, instancia.showing, instancia, rightText)) else if (instancia.use_multi_fontstrings) then instancia:SetInLineTexts(thisLine, formated_damage, formated_dps, porcentagem) else thisLine.lineText4:SetText(rightText) end end thisLine.lineText1:SetText(colocacao .. ". " .. self.nome) thisLine.lineText1:SetSize(thisLine:GetWidth() - thisLine.lineText4:GetStringWidth() - 20, 15) thisLine.lineText1:SetTextColor(1, 1, 1, 1) thisLine.lineText4:SetTextColor(1, 1, 1, 1) thisLine:SetValue(100) if (thisLine.hidden or thisLine.fading_in or thisLine.faded) then Details.FadeHandler.Fader(thisLine, "out") end local _, _, icon = GetSpellInfo(self.damage_spellid) local spellSchoolColor = Details.spells_school[self.spellschool] and Details.spells_school[self.spellschool].decimals if (not spellSchoolColor) then spellSchoolColor = Details.spells_school[1] end Details:SetBarColors(thisLine, instancia, unpack(spellSchoolColor)) thisLine.icone_classe:SetTexture(icon) thisLine.icone_classe:SetTexCoord(0.078125, 0.921875, 0.078125, 0.921875) thisLine.icone_classe:SetVertexColor(1, 1, 1) if (thisLine.mouse_over and not instancia.baseframe.isMoving) then local classIcon = thisLine:GetClassIcon() thisLine.iconHighlight:SetTexture(classIcon:GetTexture()) thisLine.iconHighlight:SetTexCoord(classIcon:GetTexCoord()) thisLine.iconHighlight:SetVertexColor(classIcon:GetVertexColor()) --need call a refresh function end end ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --main refresh function ---@param instanceObject instance ---@param combatObject combat ---@param bForceUpdate boolean ---@param bExportData boolean function damageClass:RefreshWindow(instanceObject, combatObject, bForceUpdate, bExportData) ---@type actorcontainer local damageContainer = combatObject[class_type] --o que esta sendo mostrado -> [1] - dano [2] - cura --pega o container com ._NameIndexTable ._ActorTable --not have something to show if (#damageContainer._ActorTable < 1) then if (Details.debug and false) then Details.showing_ActorTable_Timer = Details.showing_ActorTable_Timer or 0 if (time() > Details.showing_ActorTable_Timer) then Details:Msg("(debug) nothing to show -> #showing._ActorTable < 1") Details.showing_ActorTable_Timer = time() + 5 end end --colocado isso recentemente para fazer as barras de dano sumirem na troca de atributo return Details:HideBarsNotInUse(instanceObject, damageContainer), "", 0, 0 end --total local total = 0 --top actor #1 instanceObject.top = 0 local isUsingCache = false local subAttribute = instanceObject.sub_atributo local actorTableContent = damageContainer._ActorTable local amount = #actorTableContent local windowMode = instanceObject.modo --pega qual a sub key que ser� usada --sub keys if (bExportData) then if (type(bExportData) == "boolean") then if (subAttribute == 1) then --DAMAGE DONE keyName = "total" elseif (subAttribute == 2) then --DPS keyName = "last_dps" elseif (subAttribute == 3) then --DAMAGE TAKEN keyName = "damage_taken" if (Details.damage_taken_everything) then windowMode = modo_ALL end elseif (subAttribute == 4) then --FRIENDLY FIRE keyName = "friendlyfire_total" elseif (subAttribute == 5) then --FRAGS keyName = "frags" elseif (subAttribute == 6) then --ENEMIES keyName = "enemies" elseif (subAttribute == 7) then --AURAS VOIDZONES keyName = "voidzones" elseif (subAttribute == 8) then --BY SPELL keyName = "damage_taken_by_spells" end else keyName = bExportData.key windowMode = bExportData.modo end elseif (instanceObject.atributo == 5) then --custom keyName = "custom" total = combatObject.totals [instanceObject.customName] else if (subAttribute == 1) then --DAMAGE DONE keyName = "total" elseif (subAttribute == 2) then --DPS keyName = "last_dps" elseif (subAttribute == 3) then --DAMAGE TAKEN keyName = "damage_taken" if (Details.damage_taken_everything) then windowMode = modo_ALL end elseif (subAttribute == 4) then --FRIENDLY FIRE keyName = "friendlyfire_total" elseif (subAttribute == 5) then --FRAGS keyName = "frags" elseif (subAttribute == 6) then --ENEMIES keyName = "enemies" elseif (subAttribute == 7) then --AURAS VOIDZONES keyName = "voidzones" elseif (subAttribute == 8) then --BY SPELL keyName = "damage_taken_by_spells" end end if (keyName == "frags") then local frags = instanceObject.showing.frags local frags_total_kills = 0 local index = 0 for fragName, fragAmount in pairs(frags) do local fragged_actor = damageContainer._NameIndexTable [fragName] --get index if (fragged_actor) then fragged_actor = damageContainer._ActorTable [fragged_actor] --get object if (fragged_actor) then index = index + 1 local actor_classe = fragged_actor.classe if (fragged_actor and fragged_actor.monster) then actor_classe = "ENEMY" elseif (not actor_classe) then actor_classe = "UNGROUPPLAYER" end if (ntable [index]) then ntable [index] [1] = fragName ntable [index] [2] = fragAmount ntable [index] [3] = actor_classe else ntable [index] = {fragName, fragAmount, actor_classe} end frags_total_kills = frags_total_kills + fragAmount end end end local tsize = #ntable if (index < tsize) then for i = index+1, tsize do ntable [i][2] = 0 end end instanceObject.top = 0 if (tsize > 0) then _table_sort(ntable, Details.Sort2) instanceObject.top = ntable [1][2] end total = index if (bExportData) then local export = {} for i = 1, index do export [i] = {ntable[i][1], ntable[i][2], ntable[i][3]} end return export end if (total < 1) then instanceObject:EsconderScrollBar() return Details:EndRefresh(instanceObject, total, combatObject, damageContainer) --retorna a tabela que precisa ganhar o refresh end combatObject.totals.frags_total = frags_total_kills instanceObject:RefreshScrollBar(total) local whichRowLine = 1 local lineContainer = instanceObject.barras for i = instanceObject.barraS[1], instanceObject.barraS[2], 1 do damageClass:AtualizarFrags(ntable[i], whichRowLine, i, instanceObject) whichRowLine = whichRowLine+1 end return Details:EndRefresh(instanceObject, total, combatObject, damageContainer) --retorna a tabela que precisa ganhar o refresh elseif (keyName == "damage_taken_by_spells") then local bs_index, total = 0, 0 Details:Destroy(bs_index_table) local combat = combatObject local AllDamageCharacters = combat:GetActorList (DETAILS_ATTRIBUTE_DAMAGE) --do a loop amoung the actors for index, character in ipairs(AllDamageCharacters) do --is the actor a player? if (character:IsPlayer()) then for source_name, _ in pairs(character.damage_from) do local source = combat (1, source_name) if (source) then --came from an enemy if (not source:IsPlayer()) then local AllSpells = source:GetSpellList() for spellid, spell in pairs(AllSpells) do local on_player = spell.targets [character.nome] if (on_player and on_player >= 1) then local spellname = _GetSpellInfo(spellid) if (spellname) then local has_index = bs_index_table [spellname] local this_spell if (has_index) then this_spell = bs_table [has_index] else bs_index = bs_index + 1 this_spell = bs_table [bs_index] if (this_spell) then this_spell [1] = spellid this_spell [2] = 0 this_spell [3] = spell.spellschool or Details.spell_school_cache [select(1, GetSpellInfo(spellid))] or 1 bs_index_table [spellname] = bs_index else this_spell = {spellid, 0, spell.spellschool or Details.spell_school_cache [select(1, GetSpellInfo(spellid))] or 1} bs_table [bs_index] = this_spell bs_index_table [spellname] = bs_index end end this_spell [2] = this_spell [2] + on_player total = total + on_player else error("error - no spell id for DTBS " .. spellid) end end end elseif (source:IsGroupPlayer()) then -- friendly fire local AllSpells = source.friendlyfire [character.nome] and source.friendlyfire [character.nome].spells if (AllSpells) then -- se n�o existir pode ter vindo de um pet, talvez for spellid, on_player in pairs(AllSpells) do if (on_player and on_player >= 1) then local spellname = _GetSpellInfo(spellid) if (spellname) then local has_index = bs_index_table [spellname] local this_spell if (has_index) then this_spell = bs_table [has_index] else bs_index = bs_index + 1 this_spell = bs_table [bs_index] if (this_spell) then this_spell [1] = spellid this_spell [2] = 0 this_spell [3] = Details.spell_school_cache [select(1, GetSpellInfo(spellid))] or 1 bs_index_table [spellname] = bs_index else this_spell = {spellid, 0, Details.spell_school_cache [select(1, GetSpellInfo(spellid))] or 1} bs_table [bs_index] = this_spell bs_index_table [spellname] = bs_index end end this_spell [2] = this_spell [2] + on_player total = total + on_player else error("error - no spell id for DTBS friendly fire " .. spellid) end end end end end end end end end local tsize = #bs_table if (bs_index < tsize) then for i = bs_index+1, tsize do bs_table [i][2] = 0 end end instanceObject.top = 0 if (tsize > 0) then _table_sort(bs_table, Details.Sort2) instanceObject.top = bs_table [1][2] end local total2 = bs_index if (bExportData) then local export = {} for i = 1, bs_index do -- spellid, total, spellschool export [i] = {spellid = bs_table[i][1], damage = bs_table[i][2], spellschool = bs_table[i][3]} end return total, "damage", instanceObject.top, bs_index, export end if (bs_index < 1) then instanceObject:EsconderScrollBar() return Details:EndRefresh(instanceObject, bs_index, combatObject, damageContainer) --retorna a tabela que precisa ganhar o refresh end combatObject.totals.by_spell = total instanceObject:RefreshScrollBar(bs_index) local whichRowLine = 1 local lineContainer = instanceObject.barras for i = instanceObject.barraS[1], instanceObject.barraS[2], 1 do damageClass:AtualizarBySpell (bs_table[i], whichRowLine, i, instanceObject) whichRowLine = whichRowLine+1 end return Details:EndRefresh(instanceObject, bs_index, combatObject, damageContainer) elseif (keyName == "voidzones") then local index = 0 local misc_container = combatObject [4] local voidzone_damage_total = 0 for _, actor in ipairs(misc_container._ActorTable) do if (actor.boss_debuff) then index = index + 1 --pega no container de dano o actor respons�vel por aplicar o debuff local twin_damage_actor = damageContainer._NameIndexTable [actor.damage_twin] or damageContainer._NameIndexTable ["[*] " .. actor.damage_twin] if (twin_damage_actor) then local index = twin_damage_actor twin_damage_actor = damageContainer._ActorTable [twin_damage_actor] local spell = twin_damage_actor.spells._ActorTable [actor.damage_spellid] if (spell) then --fix spell, sometimes there is two spells with the same name, one is the cast and other is the debuff if (spell.total == 0 and not actor.damage_spellid_fixed) then local curname = _GetSpellInfo(actor.damage_spellid) for spellid, spelltable in pairs(twin_damage_actor.spells._ActorTable) do if (spelltable.total > spell.total) then local name = _GetSpellInfo(spellid) if (name == curname) then actor.damage_spellid = spellid spell = spelltable end end end actor.damage_spellid_fixed = true end actor.damage = spell.total voidzone_damage_total = voidzone_damage_total + spell.total elseif (not actor.damage_spellid_fixed) then --not --fix spell, if the spellid passed for debuff uptime is actully the spell id of a ability and not if the aura it self actor.damage_spellid_fixed = true local found = false for spellid, spelltable in pairs(twin_damage_actor.spells._ActorTable) do local name = _GetSpellInfo(spellid) if (actor.damage_twin:find(name)) then actor.damage = spelltable.total voidzone_damage_total = voidzone_damage_total + spelltable.total actor.damage_spellid = spellid found = true break end end if (not found) then actor.damage = 0 end else actor.damage = 0 end else actor.damage = 0 end vtable [index] = actor end end local tsize = #vtable if (index < tsize) then for i = index+1, tsize do vtable [i] = nil end end if (tsize > 0 and vtable[1]) then _table_sort(vtable, void_zone_sort) instanceObject.top = vtable [1].damage end total = index if (bExportData) then for _, t in ipairs(vtable) do t.report_name = Details:GetSpellLink(t.damage_spellid) end return voidzone_damage_total, "damage", instanceObject.top, total, vtable, "report_name" end if (total < 1) then instanceObject:EsconderScrollBar() return Details:EndRefresh(instanceObject, total, combatObject, damageContainer) --retorna a tabela que precisa ganhar o refresh end combatObject.totals.voidzone_damage = voidzone_damage_total instanceObject:RefreshScrollBar(total) local whichRowLine = 1 local lineContainer = instanceObject.barras for i = instanceObject.barraS[1], instanceObject.barraS[2], 1 do vtable[i]:AtualizarVoidZone (whichRowLine, i, instanceObject) whichRowLine = whichRowLine+1 end return Details:EndRefresh(instanceObject, total, combatObject, damageContainer) --retorna a tabela que precisa ganhar o refresh else --/run Details:Dump(Details:GetCurrentCombat():GetActor(1, "Injured Steelspine 1")) if (keyName == "enemies") then amount, total = Details:ContainerSortEnemies (actorTableContent, amount, "damage_taken") --remove actors with zero damage taken local newAmount = 0 for i = 1, #actorTableContent do if (actorTableContent[i].damage_taken < 1) then newAmount = i-1 break end end --if all units shown are enemies and all have damage taken, check if newAmount is zero and #conteudo has value bigger than 0 if (newAmount == 0 and #actorTableContent > 0) then amount = amount else amount = newAmount end --keyName = "damage_taken" --result of the first actor instanceObject.top = actorTableContent[1] and actorTableContent[1][keyName] elseif (windowMode == DETAILS_MODE_ALL) then --mostrando ALL --faz o sort da categoria e retorna o amount corrigido if (subAttribute == 2) then local combat_time = instanceObject.showing:GetCombatTime() total = damageClass:ContainerRefreshDps(actorTableContent, combat_time) else --pega o total ja aplicado na tabela do combate total = combatObject.totals[class_type] end amount = Details:ContainerSort(actorTableContent, amount, keyName) --grava o total instanceObject.top = actorTableContent[1][keyName] elseif (windowMode == DETAILS_MODE_GROUP) then --mostrando GROUP if (Details.in_combat and instanceObject.segmento == 0 and not bExportData) then isUsingCache = true end if (isUsingCache) then actorTableContent = Details.cache_damage_group if (#actorTableContent < 1) then if (Details.debug and false) then Details.showing_ActorTable_Timer2 = Details.showing_ActorTable_Timer2 or 0 if (time() > Details.showing_ActorTable_Timer2) then Details:Msg("(debug) nothing to show -> #conteudo < 1 (using cache)") Details.showing_ActorTable_Timer2 = time()+5 end end return Details:HideBarsNotInUse(instanceObject, damageContainer), "", 0, 0 end local bOrderDpsByRealTime = Details.CurrentDps.CanSortByRealTimeDps() if (subAttribute == 2) then --dps local combatTime = combatObject:GetCombatTime() local realTimeTotal = 0 total, realTimeTotal = damageClass:ContainerRefreshDps(actorTableContent, combatTime) if (bOrderDpsByRealTime) then total = realTimeTotal end elseif (subAttribute == 1) then --damage done if (bOrderDpsByRealTime) then total = damageClass:RefreshDpsRealTime(actorTableContent) end end if (bOrderDpsByRealTime) then _table_sort(actorTableContent, Details.SortByRealTimeDps) if (actorTableContent[1]["last_dps_realtime"] < 1) then amount = 0 else instanceObject.top = actorTableContent[1].last_dps_realtime amount = #actorTableContent end else _table_sort(actorTableContent, Details.SortKeySimple) if (actorTableContent[1][keyName] < 1) then amount = 0 else instanceObject.top = actorTableContent[1][keyName] amount = #actorTableContent end if (subAttribute ~= 2) then --other than dps because dps already did the iteration and the total is already calculated for i = 1, amount do total = total + actorTableContent[i][keyName] end end end else if (subAttribute == 2) then --dps local combatTime = combatObject:GetCombatTime() damageClass:ContainerRefreshDps(actorTableContent, combatTime) end _table_sort(actorTableContent, Details.SortKeyGroup) end -- if (not isUsingCache) then for index, player in ipairs(actorTableContent) do if (player.grupo) then --� um player e esta em grupo if (player[keyName] < 1) then --dano menor que 1, interromper o loop amount = index - 1 break end total = total + player[keyName] else amount = index-1 break end end instanceObject.top = actorTableContent[1] and actorTableContent[1][keyName] end end end --refaz o mapa do container if (not isUsingCache) then damageContainer:remapear() end if (bExportData) then return total, keyName, instanceObject.top, amount end if (amount < 1) then --n�o h� barras para mostrar if (bForceUpdate) then if (instanceObject.modo == 2) then --group for i = 1, instanceObject.rows_fit_in_window do Details.FadeHandler.Fader(instanceObject.barras [i], "in", Details.fade_speed) end end end instanceObject:EsconderScrollBar() --precisaria esconder a scroll bar if (Details.debug and false) then Details.showing_ActorTable_Timer2 = Details.showing_ActorTable_Timer2 or 0 if (time() > Details.showing_ActorTable_Timer2) then Details:Msg("(debug) nothing to show -> amount < 1") Details.showing_ActorTable_Timer2 = time()+5 end end return Details:EndRefresh(instanceObject, total, combatObject, damageContainer) --retorna a tabela que precisa ganhar o refresh end instanceObject:RefreshScrollBar(amount) local whichRowLine = 1 local lineContainer = instanceObject.barras local percentageType = instanceObject.row_info.percent_type local barsShowData = instanceObject.row_info.textR_show_data local barsBrackets = instanceObject:GetBarBracket() local barsSeparator = instanceObject:GetBarSeparator() local baseframe = instanceObject.baseframe local useAnimations = Details.is_using_row_animations and (not baseframe.isStretching and not bForceUpdate and not baseframe.isResizing) if (total == 0) then total = 0.00000001 end local myPos local following = instanceObject.following.enabled and subAttribute ~= 6 if (following) then if (isUsingCache) then local pname = Details.playername for i, actor in ipairs(actorTableContent) do if (actor.nome == pname) then myPos = i break end end else myPos = damageContainer._NameIndexTable [Details.playername] end end local combatTime = instanceObject.showing:GetCombatTime() UsingCustomLeftText = instanceObject.row_info.textL_enable_custom_text UsingCustomRightText = instanceObject.row_info.textR_enable_custom_text local useTotalBar = false if (instanceObject.total_bar.enabled) then useTotalBar = true if (instanceObject.total_bar.only_in_group and (not IsInGroup() and not IsInRaid())) then useTotalBar = false end if (subAttribute > 4) then --enemies, frags, void zones useTotalBar = false end end if (subAttribute == 2) then --dps instanceObject.player_top_dps = actorTableContent [1].last_dps instanceObject.player_top_dps_threshold = instanceObject.player_top_dps - (instanceObject.player_top_dps * 0.65) end local totalBarIsShown if (instanceObject.bars_sort_direction == 1) then --top to bottom if (useTotalBar and instanceObject.barraS[1] == 1) then whichRowLine = 2 local iterLast = instanceObject.barraS[2] if (iterLast == instanceObject.rows_fit_in_window) then iterLast = iterLast - 1 end local row1 = lineContainer [1] row1.minha_tabela = nil row1.lineText1:SetText(Loc ["STRING_TOTAL"]) if (instanceObject.use_multi_fontstrings) then row1.lineText2:SetText("") row1.lineText3:SetText(Details:ToK2(total)) row1.lineText4:SetText(Details:ToK(total / combatTime)) else row1.lineText4:SetText(Details:ToK2(total) .. " (" .. Details:ToK(total / combatTime) .. ")") end row1:SetValue(100) local r, g, b = unpack(instanceObject.total_bar.color) row1.textura:SetVertexColor(r, g, b) row1.icone_classe:SetTexture(instanceObject.total_bar.icon) row1.icone_classe:SetTexCoord(0.0625, 0.9375, 0.0625, 0.9375) Details.FadeHandler.Fader(row1, "out") totalBarIsShown = true if (following and myPos and myPos+1 > instanceObject.rows_fit_in_window and instanceObject.barraS[2] < myPos+1) then for i = instanceObject.barraS[1], iterLast-1, 1 do if (actorTableContent[i]) then actorTableContent[i]:RefreshLine(instanceObject, lineContainer, whichRowLine, i, total, subAttribute, bForceUpdate, keyName, combatTime, percentageType, useAnimations, barsShowData, barsBrackets, barsSeparator) whichRowLine = whichRowLine+1 end end actorTableContent[myPos]:RefreshLine(instanceObject, lineContainer, whichRowLine, myPos, total, subAttribute, bForceUpdate, keyName, combatTime, percentageType, useAnimations, barsShowData, barsBrackets, barsSeparator) whichRowLine = whichRowLine+1 else for i = instanceObject.barraS[1], iterLast, 1 do if (actorTableContent[i]) then actorTableContent[i]:RefreshLine(instanceObject, lineContainer, whichRowLine, i, total, subAttribute, bForceUpdate, keyName, combatTime, percentageType, useAnimations, barsShowData, barsBrackets, barsSeparator) whichRowLine = whichRowLine+1 end end end else if (following and myPos and myPos > instanceObject.rows_fit_in_window and instanceObject.barraS[2] < myPos) then for i = instanceObject.barraS[1], instanceObject.barraS[2]-1, 1 do if (actorTableContent[i]) then actorTableContent[i]:RefreshLine(instanceObject, lineContainer, whichRowLine, i, total, subAttribute, bForceUpdate, keyName, combatTime, percentageType, useAnimations, barsShowData, barsBrackets, barsSeparator) whichRowLine = whichRowLine+1 end end actorTableContent[myPos]:RefreshLine(instanceObject, lineContainer, whichRowLine, myPos, total, subAttribute, bForceUpdate, keyName, combatTime, percentageType, useAnimations, barsShowData, barsBrackets, barsSeparator) whichRowLine = whichRowLine+1 else for i = instanceObject.barraS[1], instanceObject.barraS[2], 1 do if (actorTableContent[i]) then actorTableContent[i]:RefreshLine(instanceObject, lineContainer, whichRowLine, i, total, subAttribute, bForceUpdate, keyName, combatTime, percentageType, useAnimations, barsShowData, barsBrackets, barsSeparator) whichRowLine = whichRowLine+1 end end end end elseif (instanceObject.bars_sort_direction == 2) then --bottom to top if (useTotalBar and instanceObject.barraS[1] == 1) then whichRowLine = 2 local iter_last = instanceObject.barraS[2] if (iter_last == instanceObject.rows_fit_in_window) then iter_last = iter_last - 1 end local row1 = lineContainer [1] row1.minha_tabela = nil row1.lineText1:SetText(Loc ["STRING_TOTAL"]) if (instanceObject.use_multi_fontstrings) then row1.lineText2:SetText("") row1.lineText3:SetText(Details:ToK2(total)) row1.lineText4:SetText(Details:ToK(total / combatTime)) else row1.lineText4:SetText(Details:ToK2(total) .. " (" .. Details:ToK(total / combatTime) .. ")") end row1:SetValue(100) local r, g, b = unpack(instanceObject.total_bar.color) row1.textura:SetVertexColor(r, g, b) row1.icone_classe:SetTexture(instanceObject.total_bar.icon) row1.icone_classe:SetTexCoord(0.0625, 0.9375, 0.0625, 0.9375) Details.FadeHandler.Fader(row1, "out") totalBarIsShown = true if (following and myPos and myPos+1 > instanceObject.rows_fit_in_window and instanceObject.barraS[2] < myPos+1) then actorTableContent[myPos]:RefreshLine(instanceObject, lineContainer, whichRowLine, myPos, total, subAttribute, bForceUpdate, keyName, combatTime, percentageType, useAnimations, barsShowData, barsBrackets, barsSeparator) whichRowLine = whichRowLine+1 for i = iter_last-1, instanceObject.barraS[1], -1 do if (actorTableContent[i]) then actorTableContent[i]:RefreshLine(instanceObject, lineContainer, whichRowLine, i, total, subAttribute, bForceUpdate, keyName, combatTime, percentageType, useAnimations, barsShowData, barsBrackets, barsSeparator) whichRowLine = whichRowLine+1 end end else for i = iter_last, instanceObject.barraS[1], -1 do if (actorTableContent[i]) then actorTableContent[i]:RefreshLine(instanceObject, lineContainer, whichRowLine, i, total, subAttribute, bForceUpdate, keyName, combatTime, percentageType, useAnimations, barsShowData, barsBrackets, barsSeparator) whichRowLine = whichRowLine+1 end end end else if (following and myPos and myPos > instanceObject.rows_fit_in_window and instanceObject.barraS[2] < myPos) then actorTableContent[myPos]:RefreshLine(instanceObject, lineContainer, whichRowLine, myPos, total, subAttribute, bForceUpdate, keyName, combatTime, percentageType, useAnimations, barsShowData, barsBrackets, barsSeparator) whichRowLine = whichRowLine+1 for i = instanceObject.barraS[2]-1, instanceObject.barraS[1], -1 do if (actorTableContent[i]) then actorTableContent[i]:RefreshLine(instanceObject, lineContainer, whichRowLine, i, total, subAttribute, bForceUpdate, keyName, combatTime, percentageType, useAnimations, barsShowData, barsBrackets, barsSeparator) whichRowLine = whichRowLine+1 end end else for i = instanceObject.barraS[2], instanceObject.barraS[1], -1 do if (actorTableContent[i]) then actorTableContent[i]:RefreshLine(instanceObject, lineContainer, whichRowLine, i, total, subAttribute, bForceUpdate, keyName, combatTime, percentageType, useAnimations, barsShowData, barsBrackets, barsSeparator) whichRowLine = whichRowLine+1 end end end end end if (totalBarIsShown) then instanceObject:RefreshScrollBar(amount + 1) else instanceObject:RefreshScrollBar(amount) end if (useAnimations) then instanceObject:PerformAnimations(whichRowLine - 1) end --beta, hidar barras n�o usadas durante um refresh for�ado if (bForceUpdate) then if (instanceObject.modo == 2) then --group for i = whichRowLine, instanceObject.rows_fit_in_window do Details.FadeHandler.Fader(instanceObject.barras [i], "in", Details.fade_speed) end end end Details.LastFullDamageUpdate = Details._tempo instanceObject:AutoAlignInLineFontStrings() return Details:EndRefresh(instanceObject, total, combatObject, damageContainer) --retorna a tabela que precisa ganhar o refresh end --[[exported]] function Details:AutoAlignInLineFontStrings() --if this instance is using in line texts, check the min distance and the length of strings to make them more spread appart if (self.use_multi_fontstrings and self.use_auto_align_multi_fontstrings) then local maxStringLength_StringFour = 0 local maxStringLength_StringThree = 0 local profileOffsetString3 = self.fontstrings_text3_anchor local profileOffsetString2 = self.fontstrings_text2_anchor local profileYOffset = self.row_info.text_yoffset Details.CacheInLineMaxDistance = Details.CacheInLineMaxDistance or {} Details.CacheInLineMaxDistance[self:GetId()] = Details.CacheInLineMaxDistance[self:GetId()] or {[2] = profileOffsetString2, [3] = profileOffsetString3} --space between string4 and string3 (usually dps is 4 and total value is 3) for lineId = 1, self:GetNumLinesShown() do local thisLine = self:GetLine(lineId) --check strings 3 and 4 if (thisLine.lineText4:GetText() ~= "" and thisLine.lineText3:GetText() ~= "") then --the length of the far right string determines the space between it and the next string in the left local stringLength = thisLine.lineText4:GetStringWidth() maxStringLength_StringFour = stringLength > maxStringLength_StringFour and stringLength or maxStringLength_StringFour end --check strings 2 and 3 if (thisLine.lineText2:GetText() ~= "" and thisLine.lineText3:GetText() ~= "") then --the length of the middle string determines the space between it and the next string in the left local stringLength = thisLine.lineText3:GetStringWidth() maxStringLength_StringThree = stringLength > maxStringLength_StringThree and stringLength or maxStringLength_StringThree end end --if the length bigger than the min distance? calculate for string4 to string3 distance if ((maxStringLength_StringFour > 0) and (maxStringLength_StringFour + 5 > profileOffsetString3)) then local newOffset = maxStringLength_StringFour + 5 --check if the current needed min distance is bigger than the distance stored in the cache local currentCacheMaxValue = Details.CacheInLineMaxDistance[self:GetId()][3] if (currentCacheMaxValue < newOffset) then currentCacheMaxValue = newOffset Details.CacheInLineMaxDistance[self:GetId()][3] = currentCacheMaxValue else --if not, use the distance value cached to avoid jittering in the string newOffset = currentCacheMaxValue end --update the lines for lineId = 1, self:GetNumLinesShown() do local thisLine = self:GetLine(lineId) thisLine.lineText3:SetPoint("right", thisLine.statusbar, "right", -newOffset, profileYOffset) end end --check if there's length in the third string, also the third string cannot have a length if the second string is empty if (maxStringLength_StringThree > 0) then local newOffset = maxStringLength_StringThree + maxStringLength_StringFour + 14 if (newOffset >= profileOffsetString2) then --check if the current needed min distance is bigger than the distance stored in the cache local currentCacheMaxValue = Details.CacheInLineMaxDistance[self:GetId()][2] if (currentCacheMaxValue < newOffset) then currentCacheMaxValue = newOffset Details.CacheInLineMaxDistance[self:GetId()][2] = currentCacheMaxValue else --if not, use the distance value cached to avoid jittering in the string newOffset = currentCacheMaxValue end --update the lines for lineId = 1, self:GetNumLinesShown() do local thisLine = self:GetLine(lineId) thisLine.lineText2:SetPoint("right", thisLine.statusbar, "right", -newOffset, profileYOffset) end end end --reduce the size of the actor name string based on the total size of all strings in the right side for lineId = 1, self:GetNumLinesShown() do local thisLine = self:GetLine(lineId) --check if there's something showing in this line --check if the line is shown and if the text exists for sanitization if (thisLine.minha_tabela and thisLine:IsShown() and thisLine.lineText1:GetText()) then local playerNameFontString = thisLine.lineText1 local text2 = thisLine.lineText2 local text3 = thisLine.lineText3 local text4 = thisLine.lineText4 local totalWidth = text2:GetStringWidth() + text3:GetStringWidth() + text4:GetStringWidth() totalWidth = totalWidth + 40 - self.fontstrings_text_limit_offset DetailsFramework:TruncateTextSafe(playerNameFontString, self.cached_bar_width - totalWidth) --this avoid truncated strings with ... --these commented lines are for to create a cache and store the name already truncated there to safe performance --local truncatedName = playerNameFontString:GetText() --local actorObject = thisLine.minha_tabela --actorObject.name_cached = truncatedName --actorObject.name_cached_time = GetTime() end end end end --handle internal details! events local eventListener = Details:CreateEventListener() eventListener:RegisterEvent("COMBAT_PLAYER_ENTER", function() if (Details.CacheInLineMaxDistance) then Details:Destroy(Details.CacheInLineMaxDistance) for i = 1, 10 do C_Timer.After(i, function() Details:Destroy(Details.CacheInLineMaxDistance) end) end end end) local actor_class_color_r, actor_class_color_g, actor_class_color_b -- ~texts --[[exported]] function Details:SetInLineTexts(thisLine, valueText, perSecondText, percentText) --set defaults local instance = self valueText = valueText or "" perSecondText = perSecondText or "" percentText = percentText or "" if ((Details.use_realtimedps or (Details.combat_log.evoker_show_realtimedps and Details.playerspecid == 1473)) and Details.in_combat) then --real time if (thisLine:GetActor()) then local actorSerial = thisLine:GetActor().serial local currentDps = Details.CurrentDps.GetCurrentDps(actorSerial) if (currentDps and currentDps > 0) then currentDps = Details:ToK2(currentDps) end perSecondText = currentDps end end --check if the instance is showing total, dps and percent local instanceSettings = instance.row_info if (not instanceSettings.textR_show_data[3]) then --percent text disabled on options panel local attributeId = instance:GetDisplay() if (attributeId ~= 5) then --not custom percentText = "" end end --parse information if (percentText ~= "") then --has percent text thisLine.lineText4:SetText(percentText) if (perSecondText ~= "") then --has dps? thisLine.lineText3:SetText(perSecondText) --set dps thisLine.lineText2:SetText(valueText) --set amount else thisLine.lineText3:SetText(valueText) --set amount thisLine.lineText2:SetText("") --clear end else --no percent text if (perSecondText ~= "") then --has dps and no percent thisLine.lineText4:SetText(perSecondText) --set dps thisLine.lineText3:SetText(valueText) --set amount thisLine.lineText2:SetText("") --clear else --no dps and not percent thisLine.lineText4:SetText(valueText) --set dps thisLine.lineText3:SetText("") --clear thisLine.lineText2:SetText("") --clear end end end -- ~atualizar ~barra ~update function damageClass:RefreshLine(instanceObject, lineContainer, whichRowLine, rank, total, subAttribute, bForceRefresh, keyName, combatTime, percentageType, bUseAnimations, bars_show_data, bars_brackets, bars_separator) local thisLine = lineContainer[whichRowLine] if (not thisLine) then print("DEBUG: problema com "..whichRowLine.." "..rank) return end local previousData = thisLine.minha_tabela thisLine.minha_tabela = self --store references self.minha_barra = thisLine --store references thisLine.colocacao = rank self.colocacao = rank local damageTotal = self.total --total damage of this actor local dps local percentString local percentNumber --calc the percent amount base on the percent type if (percentageType == 1) then percentString = format("%.1f", self[keyName] / total * 100) elseif (percentageType == 2) then percentString = format("%.1f", self[keyName] / instanceObject.top * 100) end local currentCombat = Details:GetCurrentCombat() --calculate the actor dps if ((Details.time_type == 2 and self.grupo) or not Details:CaptureGet("damage") or instanceObject.segmento == -1 or Details.use_realtimedps) then if (Details.use_realtimedps and Details.in_combat) then local currentDps = self.last_dps_realtime if (currentDps) then dps = currentDps end end if (not dps) then if (instanceObject.segmento == -1 and combatTime == 0) then local actor = currentCombat(1, self.nome) if (actor) then local combatTime = actor:Tempo() dps = damageTotal / combatTime self.last_dps = dps else dps = damageTotal / combatTime self.last_dps = dps end else dps = damageTotal / combatTime self.last_dps = dps end end else if (not self.on_hold) then dps = damageTotal/self:Tempo() --calcula o dps deste objeto self.last_dps = dps --salva o dps dele else if (self.last_dps == 0) then --n�o calculou o dps dele ainda mas entrou em standby dps = damageTotal/self:Tempo() self.last_dps = dps else dps = self.last_dps end end end --right text if (subAttribute == 1) then --damage done dps = _math_floor(dps) local formatedDamage = SelectedToKFunction(_, damageTotal) local formatedDps = SelectedToKFunction(_, dps) thisLine.ps_text = formatedDps if (not bars_show_data[1]) then formatedDamage = "" end if (not bars_show_data[2]) then formatedDps = "" end if (not bars_show_data[3]) then percentString = "" else percentString = percentString .. "%" end local rightText = formatedDamage .. bars_brackets[1] .. formatedDps .. bars_separator .. percentString .. bars_brackets[2] if (UsingCustomRightText) then thisLine.lineText4:SetText(stringReplace(instanceObject.row_info.textR_custom_text, formatedDamage, formatedDps, percentString, self, instanceObject.showing, instanceObject, rightText)) else if (instanceObject.use_multi_fontstrings) then instanceObject:SetInLineTexts(thisLine, formatedDamage, formatedDps, percentString) else thisLine.lineText4:SetText(rightText) end end if (Details.CurrentDps.CanSortByRealTimeDps()) then percentNumber = _math_floor((self.last_dps_realtime / instanceObject.top) * 100) else percentNumber = _math_floor((damageTotal/instanceObject.top) * 100) end elseif (subAttribute == 2) then --dps local raw_dps = dps dps = _math_floor(dps) local formated_damage = SelectedToKFunction(_, damageTotal) local formated_dps = SelectedToKFunction(_, dps) thisLine.ps_text = formated_dps local diff_from_topdps if (rank > 1) then diff_from_topdps = instanceObject.player_top_dps - raw_dps end local rightText if (diff_from_topdps) then local threshold = diff_from_topdps / instanceObject.player_top_dps_threshold * 100 if (threshold < 100) then threshold = abs(threshold - 100) else threshold = 5 end local rr, gg, bb = Details:percent_color ( threshold ) rr, gg, bb = Details:hex (_math_floor(rr*255)), Details:hex (_math_floor(gg*255)), "28" local color_percent = "" .. rr .. gg .. bb .. "" if (not bars_show_data [1]) then formated_dps = "" end if (not bars_show_data [2]) then color_percent = "" else color_percent = bars_brackets[1] .. "|cFFFF4444-|r|cFF" .. color_percent .. SelectedToKFunction(_, _math_floor(diff_from_topdps)) .. "|r" .. bars_brackets[2] end rightText = formated_dps .. color_percent else local icon = " |TInterface\\GROUPFRAME\\UI-Group-LeaderIcon:14:14:0:0:16:16:0:16:0:16|t " if (not bars_show_data [1]) then formated_dps = "" end if (not bars_show_data [2]) then icon = "" end rightText = formated_dps .. icon end if (UsingCustomRightText) then thisLine.lineText4:SetText(stringReplace(instanceObject.row_info.textR_custom_text, formated_dps, formated_damage, percentString, self, instanceObject.showing, instanceObject, rightText)) else if (instanceObject.use_multi_fontstrings) then --instance:SetInLineTexts(thisLine, formated_damage, formated_dps, porcentagem) instanceObject:SetInLineTexts(thisLine, rightText) else thisLine.lineText4:SetText(rightText) end end percentNumber = _math_floor((dps/instanceObject.top) * 100) elseif (subAttribute == 3) then --damage taken local dtps = self.damage_taken / combatTime local formated_damage_taken = SelectedToKFunction(_, self.damage_taken) local formated_dtps = SelectedToKFunction(_, dtps) thisLine.ps_text = formated_dtps if (not bars_show_data [1]) then formated_damage_taken = "" end if (not bars_show_data [2]) then formated_dtps = "" end if (not bars_show_data [3]) then percentString = "" else percentString = percentString .. "%" end local rightText = formated_damage_taken .. bars_brackets[1] .. formated_dtps .. bars_separator .. percentString .. bars_brackets[2] if (UsingCustomRightText) then thisLine.lineText4:SetText(stringReplace(instanceObject.row_info.textR_custom_text, formated_damage_taken, formated_dtps, percentString, self, instanceObject.showing, instanceObject, rightText)) else if (instanceObject.use_multi_fontstrings) then instanceObject:SetInLineTexts(thisLine, formated_damage_taken, formated_dtps, percentString) else thisLine.lineText4:SetText(rightText) end end percentNumber = _math_floor((self.damage_taken/instanceObject.top) * 100) elseif (subAttribute == 4) then --friendly fire local formated_friendly_fire = SelectedToKFunction(_, self.friendlyfire_total) if (not bars_show_data [1]) then formated_friendly_fire = "" end if (not bars_show_data [3]) then percentString = "" else percentString = percentString .. "%" end local rightText = formated_friendly_fire .. bars_brackets[1] .. percentString .. bars_brackets[2] if (UsingCustomRightText) then thisLine.lineText4:SetText(stringReplace(instanceObject.row_info.textR_custom_text, formated_friendly_fire, "", percentString, self, instanceObject.showing, instanceObject, rightText)) else if (instanceObject.use_multi_fontstrings) then instanceObject:SetInLineTexts(thisLine, "", formated_friendly_fire, percentString) else thisLine.lineText4:SetText(rightText) end end percentNumber = _math_floor((self.friendlyfire_total/instanceObject.top) * 100) elseif (subAttribute == 6) then --enemies local dtps = self.damage_taken / combatTime local formatedDamageTaken = SelectedToKFunction(_, self.damage_taken) local formatedDtps = SelectedToKFunction(_, dtps) thisLine.ps_text = formatedDtps if (not bars_show_data [1]) then formatedDamageTaken = "" end if (not bars_show_data [2]) then formatedDtps = "" end if (not bars_show_data [3]) then percentString = "" else percentString = percentString .. "%" end local rightText = formatedDamageTaken .. bars_brackets[1] .. formatedDtps .. bars_separator .. percentString .. bars_brackets[2] if (UsingCustomRightText) then thisLine.lineText4:SetText(stringReplace(instanceObject.row_info.textR_custom_text, formatedDamageTaken, formatedDtps, percentString, self, instanceObject.showing, instanceObject, rightText)) else if (instanceObject.use_multi_fontstrings) then instanceObject:SetInLineTexts(thisLine, formatedDamageTaken, formatedDtps, percentString) else thisLine.lineText4:SetText(rightText) end end percentNumber = _math_floor((self.damage_taken/instanceObject.top) * 100) end --need tooltip update? if (thisLine.mouse_over and not instanceObject.baseframe.isMoving) then gump:UpdateTooltip(whichRowLine, thisLine, instanceObject) end if (self.need_refresh) then self.need_refresh = false bForceRefresh = true end actor_class_color_r, actor_class_color_g, actor_class_color_b = self:GetBarColor() return self:RefreshLineValue(thisLine, instanceObject, previousData, bForceRefresh, percentNumber, bUseAnimations, total, instanceObject.top) end ---show an extra statusbar on the line, after the main statusbar ---@param thisLine table ---@param amount valueamount ---@param extraAmount valueamount ---@param totalAmount valueamount ---@param topAmount valueamount ---@param instanceObject instance ---@param onEnterFunc function? ---@param onLeaveFunc function? function Details:ShowExtraStatusbar(thisLine, amount, extraAmount, totalAmount, topAmount, instanceObject, onEnterFunc, onLeaveFunc) local extraStatusbar = thisLine.extraStatusbar if (extraAmount and extraAmount > 0 and instanceObject.atributo == 1 and instanceObject.sub_atributo == 1) then local initialOffset = 0 local icon_offset_x, icon_offset_y = unpack(instanceObject.row_info.icon_offset) local bIsUsingBarStartAfterIcon = instanceObject.row_info.start_after_icon if (bIsUsingBarStartAfterIcon) then initialOffset = thisLine.icone_classe:GetWidth() + icon_offset_x end local statusBarWidth = thisLine.statusbar:GetWidth() local percent = amount / topAmount local fillTheGapWidth = percent * 4 local startExtraStatusbarOffset = percent * statusBarWidth local extraStatusbarWidth = statusBarWidth * (extraAmount / topAmount) extraStatusbar:ClearAllPoints() extraStatusbar:SetHeight(thisLine:GetHeight()) if (bIsUsingBarStartAfterIcon) then extraStatusbar:SetPoint("topleft", thisLine.icone_classe, "topright", startExtraStatusbarOffset - fillTheGapWidth, 0) else extraStatusbar:SetPoint("topleft", thisLine, "topleft", (statusBarWidth * percent) - fillTheGapWidth, 0) end extraStatusbar:SetWidth(extraStatusbarWidth) extraStatusbar:SetFrameLevel(thisLine:GetFrameLevel() + 1) extraStatusbar.OnEnterCallback = onEnterFunc extraStatusbar.OnLeaveCallback = onLeaveFunc if (Details.combat_log.evoker_calc_damage) then extraStatusbar:SetAlpha(0.8) extraStatusbar.defaultAlpha = 0.8 else extraStatusbar:SetAlpha(0.1) extraStatusbar.defaultAlpha = 0.1 end extraStatusbar:Show() else extraStatusbar:Hide() end end --when the script detect the extrastatusbar need to be show, it will call this function local handleShowExtraStatusbar = function(thisLine, self, instance, previousData, isForceRefresh, percent, bUseAnimations, totalValue, topValue) if (self.spec == 1473 and self.augmentedSpellsContainer) then --prepare the extra bar to show the damage prediction to augmented evoker local onEnterFunc = damageClass.PredictedAugSpellsOnEnter local onLeaveFunc = damageClass.PredictedAugSpellsOnLeave Details:ShowExtraStatusbar(thisLine, self.total, self.total_extra, totalValue, topValue, instance, onEnterFunc, onLeaveFunc) thisLine.extraStatusbar.augmentedSpellsContainer = self.augmentedSpellsContainer thisLine.extraStatusbar.actorName = self:Name() ---@cast instance instance thisLine.extraStatusbar.instanceId = instance:GetId() else Details:ShowExtraStatusbar(thisLine, self.total, self.total_extra, totalValue, topValue, instance) end end function Details:RefreshLineValue(thisLine, instance, previousData, isForceRefresh, percent, bUseAnimations, totalValue, topValue) --[[exported]] thisLine.extraStatusbar:Hide() if (thisLine.colocacao == 1) then thisLine.animacao_ignorar = true if (not previousData or previousData ~= thisLine.minha_tabela or isForceRefresh) then thisLine:SetValue(100) if (thisLine.hidden or thisLine.fading_in or thisLine.faded) then Details.FadeHandler.Fader(thisLine, "out") end return self:RefreshBarra(thisLine, instance) else return end else if (thisLine.hidden or thisLine.fading_in or thisLine.faded) then --setando o valor mesmo com anima��es pq o barra esta hidada com o value do �ltimo actor que ela mostrou if (bUseAnimations and self.spec ~= 1473) then thisLine.animacao_fim = percent thisLine:SetValue(percent) else thisLine:SetValue(percent) thisLine.animacao_ignorar = true end Details.FadeHandler.Fader(thisLine, "out") if (self.total_extra and self.total_extra > 0) then handleShowExtraStatusbar(thisLine, self, instance, previousData, isForceRefresh, percent, bUseAnimations, totalValue, topValue) end return self:RefreshBarra(thisLine, instance) else --agora esta comparando se a tabela da barra � diferente da tabela na atualiza��o anterior if (not previousData or previousData ~= thisLine.minha_tabela or isForceRefresh) then --aqui diz se a barra do jogador mudou de posi��o ou se ela apenas ser� atualizada if (bUseAnimations and self.spec ~= 1473) then thisLine.animacao_fim = percent else thisLine:SetValue(percent) thisLine.animacao_ignorar = true end thisLine.last_value = percent --reseta o ultimo valor da barra if (self.total_extra and self.total_extra > 0) then handleShowExtraStatusbar(thisLine, self, instance, previousData, isForceRefresh, percent, bUseAnimations, totalValue, topValue) end return self:RefreshBarra(thisLine, instance) elseif (percent ~= thisLine.last_value) then --continua mostrando a mesma tabela ent�o compara a porcentagem --apenas atualizar if (bUseAnimations and self.spec ~= 1473) then thisLine.animacao_fim = percent else thisLine:SetValue(percent) end thisLine.last_value = percent if (self.total_extra and self.total_extra > 0) then Details:ShowExtraStatusbar(thisLine, self.total, self.total_extra, totalValue, topValue, instance) end return self:RefreshBarra(thisLine, instance) else if (self.total_extra and self.total_extra > 0) then handleShowExtraStatusbar(thisLine, self, instance, previousData, isForceRefresh, percent, bUseAnimations, totalValue, topValue) end end end end end local setLineTextSize = function(line, instance) if (instance.bars_inverted) then line.lineText4:SetSize(instance.cached_bar_width - line.lineText1:GetStringWidth() - 20, 15) else line.lineText1:SetSize(instance.cached_bar_width - line.lineText4:GetStringWidth() - 20, 15) end end function Details:SetBarLeftText(bar, instance, enemy, arenaEnemy, arenaAlly, usingCustomLeftText) --[[exported]] local barNumber = "" if (instance.row_info.textL_show_number) then barNumber = bar.colocacao .. ". " end --translate cyrillic alphabet to western alphabet by Vardex (https://github.com/Vardex May 22, 2019) if (instance.row_info.textL_translit_text) then self.displayName = Translit:Transliterate(self.displayName, "!") end if (enemy) then if (arenaEnemy) then if (instance.row_info.show_arena_role_icon) then --show arena role icon local sizeOffset = instance.row_info.arena_role_icon_size_offset local leftText = barNumber .. "|TInterface\\LFGFRAME\\UI-LFG-ICON-ROLES:" .. (instance.row_info.height + sizeOffset)..":"..(instance.row_info.height + sizeOffset) .. ":0:0:256:256:" .. Details.role_texcoord [self.role or "NONE"] .. "|t " .. self.displayName if (usingCustomLeftText) then bar.lineText1:SetText(stringReplace(instance.row_info.textL_custom_text, bar.colocacao, self.displayName, "|TInterface\\LFGFRAME\\UI-LFG-ICON-ROLES:" .. (instance.row_info.height + sizeOffset)..":"..(instance.row_info.height + sizeOffset) .. ":0:0:256:256:" .. Details.role_texcoord [self.role or "NONE"] .. "|t ", self, instance.showing, instance, leftText)) else bar.lineText1:SetText(leftText) end else --don't show arena role icon local leftText = barNumber .. self.displayName if (usingCustomLeftText) then bar.lineText1:SetText(stringReplace(instance.row_info.textL_custom_text, bar.colocacao, self.displayName, " ", self, instance.showing, instance, leftText)) else bar.lineText1:SetText(leftText) end end else if (instance.row_info.show_faction_icon) then local sizeOffset = instance.row_info.faction_icon_size_offset if (Details.faction_against == "Horde") then local leftText = barNumber .. "|TInterface\\AddOns\\Details\\images\\icones_barra:" .. (instance.row_info.height + sizeOffset)..":"..(instance.row_info.height + sizeOffset) .. ":0:0:256:32:0:32:0:32|t"..self.displayName if (usingCustomLeftText) then bar.lineText1:SetText(stringReplace(instance.row_info.textL_custom_text, bar.colocacao, self.displayName, "|TInterface\\AddOns\\Details\\images\\icones_barra:" .. (instance.row_info.height + sizeOffset)..":"..(instance.row_info.height + sizeOffset) .. ":0:0:256:32:0:32:0:32|t", self, instance.showing, instance, leftText)) else bar.lineText1:SetText(leftText) --seta o texto da esqueda -- HORDA end else --alliance local leftText = barNumber .. "|TInterface\\AddOns\\Details\\images\\icones_barra:" .. (instance.row_info.height + sizeOffset)..":"..(instance.row_info.height + sizeOffset) .. ":0:0:256:32:32:64:0:32|t"..self.displayName if (usingCustomLeftText) then bar.lineText1:SetText(stringReplace(instance.row_info.textL_custom_text, bar.colocacao, self.displayName, "|TInterface\\AddOns\\Details\\images\\icones_barra:" .. (instance.row_info.height + sizeOffset)..":"..(instance.row_info.height + sizeOffset) .. ":0:0:256:32:32:64:0:32|t", self, instance.showing, instance, leftText)) else bar.lineText1:SetText(leftText) --seta o texto da esqueda -- ALLY end end else --don't show faction icon local leftText = barNumber .. self.displayName if (usingCustomLeftText) then bar.lineText1:SetText(stringReplace(instance.row_info.textL_custom_text, bar.colocacao, self.displayName, " ", self, instance.showing, instance, leftText)) else bar.lineText1:SetText(leftText) end end end else if (arenaAlly and instance.row_info.show_arena_role_icon) then local sizeOffset = instance.row_info.arena_role_icon_size_offset local leftText = barNumber .. "|TInterface\\LFGFRAME\\UI-LFG-ICON-ROLES:" .. (instance.row_info.height + sizeOffset)..":"..(instance.row_info.height + sizeOffset) .. ":0:0:256:256:" .. Details.role_texcoord [self.role or "NONE"] .. "|t " .. self.displayName if (usingCustomLeftText) then bar.lineText1:SetText(stringReplace(instance.row_info.textL_custom_text, bar.colocacao, self.displayName, "|TInterface\\LFGFRAME\\UI-LFG-ICON-ROLES:" .. (instance.row_info.height + sizeOffset)..":"..(instance.row_info.height + sizeOffset) .. ":0:0:256:256:" .. Details.role_texcoord [self.role or "NONE"] .. "|t ", self, instance.showing, instance, leftText)) else bar.lineText1:SetText(leftText) end else local leftText = barNumber .. self.displayName if (usingCustomLeftText) then bar.lineText1:SetText(stringReplace(instance.row_info.textL_custom_text, bar.colocacao, self.displayName, "", self, instance.showing, instance, leftText)) else bar.lineText1:SetText(leftText) --seta o texto da esqueda end end end setLineTextSize (bar, instance) end function Details:SetBarColors(bar, instance, r, g, b, a) --[[exported]] --~colors a = a or 1 if (instance.row_info.texture_class_colors) then if (self.classe == "UNGROUPPLAYER") then if (self.spec) then local specId, specName, specDescription, specIcon, specRole, specClass = DetailsFramework.GetSpecializationInfoByID(self.spec) if (specClass) then self.classe = specClass end end end bar.textura:SetVertexColor(r, g, b, a) end if (instance.row_info.texture_background_class_color) then bar.background:SetVertexColor(r, g, b, a) end if (instance.row_info.textL_class_colors) then bar.lineText1:SetTextColor(r, g, b, a) end if (instance.row_info.textR_class_colors) then bar.lineText2:SetTextColor(r, g, b, a) bar.lineText3:SetTextColor(r, g, b, a) bar.lineText4:SetTextColor(r, g, b, a) end if (instance.row_info.backdrop.use_class_colors) then --get the alpha from the border color local alpha = instance.row_info.backdrop.color[4] bar.lineBorder:SetVertexColor(r, g, b, alpha) end end ---set the icon of the actor spec, class, pet, enemy, custom icom, spellicon, etc. ---@param self actor ---@param texture texture ---@param instance instance ---@param class string function Details:SetClassIcon(texture, instance, class) --[[exported]] --~icons local customIcon if (Details.immersion_unit_special_icons) then customIcon = Details.Immersion.GetIcon(self.aID) end --set the size offset of the icon local iconSizeOffset = instance.row_info.icon_size_offset local iconSize = instance.row_info.height local newIconSize = iconSize + iconSizeOffset texture:SetSize(newIconSize, newIconSize) if (customIcon) then texture:SetTexture(customIcon[1]) texture:SetTexCoord(unpack(customIcon[2])) texture:SetVertexColor(1, 1, 1) elseif (self.spellicon) then texture:SetTexture(self.spellicon) texture:SetTexCoord(0.078125, 0.921875, 0.078125, 0.921875) elseif (class == "UNKNOW") then texture:SetTexture([[Interface\AddOns\Details\images\classes_plus]]) texture:SetTexCoord(0.50390625, 0.62890625, 0, 0.125) texture:SetVertexColor(1, 1, 1) elseif (class == "UNGROUPPLAYER") then if (self.spec) then if (instance and instance.row_info.use_spec_icons) then if (self.spec and Details.class_specs_coords[self.spec]) then texture:SetTexture(instance.row_info.spec_file) texture:SetTexCoord(unpack(Details.class_specs_coords[self.spec])) texture:SetVertexColor(1, 1, 1) return end end end local localizedClass, englishClass if (self.serial ~= "") then localizedClass, englishClass = GetPlayerInfoByGUID(self.serial) end if (englishClass) then texture:SetTexture(instance.row_info.icon_file or [[Interface\AddOns\Details\images\classes_small]]) texture:SetTexCoord(unpack(Details.class_coords[englishClass])) texture:SetVertexColor(1, 1, 1) return end if (self.enemy) then if (Details.faction_against == "Horde") then texture:SetTexture("Interface\\ICONS\\Achievement_Character_Troll_Male") texture:SetTexCoord(0.05, 0.95, 0.05, 0.95) else texture:SetTexture("Interface\\ICONS\\Achievement_Character_Nightelf_Female") texture:SetTexCoord(0.05, 0.95, 0.05, 0.95) end else if (Details.faction_against == "Horde") then texture:SetTexture("Interface\\ICONS\\Achievement_Character_Nightelf_Female") texture:SetTexCoord(0.05, 0.95, 0.05, 0.95) else texture:SetTexture("Interface\\ICONS\\Achievement_Character_Troll_Male") texture:SetTexCoord(0.05, 0.95, 0.05, 0.95) end end texture:SetVertexColor(1, 1, 1) elseif (class == "PET") then texture:SetTexture(instance and instance.row_info.icon_file or [[Interface\AddOns\Details\images\classes_small]]) texture:SetTexCoord(0.25, 0.49609375, 0.75, 1) actor_class_color_r, actor_class_color_g, actor_class_color_b = DetailsFramework:ParseColors(actor_class_color_r, actor_class_color_g, actor_class_color_b) texture:SetVertexColor(actor_class_color_r, actor_class_color_g, actor_class_color_b) else if (instance and instance.row_info.use_spec_icons) then if (self.spec and Details.class_specs_coords[self.spec]) then texture:SetTexture(instance.row_info.spec_file) texture:SetTexCoord(unpack(Details.class_specs_coords[self.spec])) texture:SetVertexColor(1, 1, 1) else texture:SetTexture(instance.row_info.icon_file or [[Interface\AddOns\Details\images\classes_small]]) texture:SetTexCoord(unpack(Details.class_coords[class])) texture:SetVertexColor(1, 1, 1) end else texture:SetTexture(instance and instance.row_info.icon_file or [[Interface\AddOns\Details\images\classes_small]]) texture:SetTexCoord(unpack(Details.class_coords[class])) texture:SetVertexColor(1, 1, 1) end end end function Details:RefreshBarra(thisLine, instance, fromResize) --[[exported]] local class, enemy, arenaEnemy, arenaAlly = self.classe, self.enemy, self.arena_enemy, self.arena_ally if (not class) then Details:Msg("Warning, actor without a class:", self.nome, self.flag_original, self.serial) self.classe = "UNKNOW" class = "UNKNOW" end if (fromResize) then actor_class_color_r, actor_class_color_g, actor_class_color_b = self:GetBarColor() end --icon self:SetClassIcon(thisLine.icone_classe, instance, class) if(thisLine.mouse_over) then local classIcon = thisLine:GetClassIcon() thisLine.iconHighlight:SetTexture(classIcon:GetTexture()) thisLine.iconHighlight:SetTexCoord(classIcon:GetTexCoord()) thisLine.iconHighlight:SetVertexColor(classIcon:GetVertexColor()) end --texture color self:SetBarColors(thisLine, instance, actor_class_color_r, actor_class_color_g, actor_class_color_b) --left text self:SetBarLeftText(thisLine, instance, enemy, arenaEnemy, arenaAlly, UsingCustomLeftText) end ---comment ---@param self table extraStatusbar frame function damageClass.PredictedAugSpellsOnEnter(self) if (Details.show_aug_predicted_spell_damage) then ---@type spellcontainer local spellContainer = self.augmentedSpellsContainer GameCooltip:Preset(2) ---@type instance local instanceObject = Details:GetInstance(self.instanceId) ---@type combat local combatObject = instanceObject:GetCombat() for spellId, spellTable in spellContainer:ListSpells() do local spellName, _, spellTexture = GetSpellInfo(spellId) if (spellName) then GameCooltip:AddLine(spellName, Details:Format(spellTable.total)) GameCooltip:AddIcon(spellTexture, 1, 1, 14, 14) local spellsAugmented = {} --the damage sources are added into the targets table for recycling ---@type table local sources = spellTable.targets for sourceName, sourceAmount in pairs(sources) do spellsAugmented[#spellsAugmented+1] = {sourceName, sourceAmount} end table.sort(spellsAugmented, Details.Sort2) for i = 1, math.min(#spellsAugmented, 5) do local sourceName, sourceAmount = unpack(spellsAugmented[i]) GameCooltip:AddLine(sourceName, Details:Format(sourceAmount), 1, "yellow", "yellow", 10) local actorObject = combatObject:GetActor(1, sourceName) if (actorObject) then local actorIcon = Details:GetActorIcon(actorObject) if (actorIcon) then GameCooltip:AddIcon(actorIcon.texture, 1, 1, 14, 14, actorIcon.coords.left, actorIcon.coords.right, actorIcon.coords.top, actorIcon.coords.bottom) else GameCooltip:AddIcon([[Interface\COMMON\Indicator-Gray]], 1, 1, 14, 14) end end end end end else ---@type instance local instanceObject = Details:GetInstance(self.instanceId) ---@type combat local combatObject = instanceObject:GetCombat() local combatTime = combatObject:GetCombatTime() ---@type actorname local actorName = self.actorName ---@type actorcontainer local utilityContainer = combatObject:GetContainer(DETAILS_ATTRIBUTE_MISC) local buffUptimeTable = {} --for each actor in the container for _, actorObject in utilityContainer:ListActors() do ---@type spellcontainer local receivedBuffs = actorObject.received_buffs_spells if (receivedBuffs and actorObject:IsPlayer() and actorObject:IsGroupPlayer()) then for sourceNameSpellId, spellTable in receivedBuffs:ListSpells() do local sourceName, spellId = strsplit("@", sourceNameSpellId) if (sourceName == actorName) then spellId = tonumber(spellId) local spellName, _, spellIcon = Details.GetSpellInfo(spellId) if (spellName) then sourceName = detailsFramework:RemoveRealmName(sourceName) local targetName = actorObject:Name() targetName = detailsFramework:RemoveRealmName(targetName) local uptime = spellTable.uptime or 0 buffUptimeTable[#buffUptimeTable+1] = {spellId, uptime, sourceName, targetName, actorObject:Class()} end end end end end table.sort(buffUptimeTable, Details.Sort2) Details:FormatCooltipForSpells() Details:AddTooltipSpellHeaderText(Loc ["STRING_SPELLS"], headerColor, #buffUptimeTable, Details.tooltip_spell_icon.file, unpack(Details.tooltip_spell_icon.coords)) Details:AddTooltipHeaderStatusbar(.1, .1, .1, 0.834) local iconSize = 22 local iconBorderInfo = Details.tooltip.icon_border_texcoord local combatTimeMinutes, combatTimeSeconds = math.floor(combatTime / 60), math.floor(combatTime % 60) GameCooltip:AddLine("Combat Time", combatTimeMinutes .. "m " .. combatTimeSeconds .. "s" .. " (" .. format("%.1f", 100) .. "%)") GameCooltip:AddIcon([[Interface\TARGETINGFRAME\UnitFrameIcons]], nil, nil, iconSize, iconSize, iconBorderInfo.L, iconBorderInfo.R, iconBorderInfo.T, iconBorderInfo.B) Details:AddTooltipBackgroundStatusbar(false, 100, true, "green") if (#buffUptimeTable > 0) then for i = 1, min(30, #buffUptimeTable) do local uptimeTable = buffUptimeTable[i] local spellId = uptimeTable[1] local uptime = uptimeTable[2] local sourceName = uptimeTable[3] local targetName = uptimeTable[4] local targetClass = uptimeTable[5] local uptimePercent = uptime / combatTime * 100 if (uptime > 0 and uptimePercent < 99.5) then local spellName, _, spellIcon = _GetSpellInfo(spellId) if (sourceName) then targetName = detailsFramework:AddClassColorToText(targetName, targetClass) targetName = detailsFramework:AddClassIconToText(targetName, targetName, targetClass) spellName = spellName .. " [" .. targetName .. "]" end if (uptime <= combatTime) then local minutes, seconds = math.floor(uptime / 60), math.floor(uptime % 60) if (minutes > 0) then GameCooltip:AddLine(spellName, minutes .. "m " .. seconds .. "s" .. " (" .. format("%.1f", uptimePercent) .. "%)") Details:AddTooltipBackgroundStatusbar(false, uptimePercent, true, sourceName and "green") else GameCooltip:AddLine(spellName, seconds .. "s" .. " (" .. format("%.1f", uptimePercent) .. "%)") Details:AddTooltipBackgroundStatusbar(false, uptimePercent, true, sourceName and "green") end GameCooltip:AddIcon(spellIcon, nil, nil, iconSize, iconSize, iconBorderInfo.L, iconBorderInfo.R, iconBorderInfo.T, iconBorderInfo.B) end end end else GameCooltip:AddLine(Loc ["STRING_NO_SPELL"]) end end GameCooltip:AddLine("feature under test, can't disable atm") GameCooltip:AddIcon([[Interface\BUTTONS\UI-GROUPLOOT-PASS-DOWN]], nil, nil, 16, 16) --GameCooltip:SetOption("LeftBorderSize", -5) --GameCooltip:SetOption("RightBorderSize", 5) --GameCooltip:SetOption("RightTextMargin", 0) GameCooltip:SetOption("VerticalOffset", 0) --GameCooltip:SetOption("AlignAsBlizzTooltip", true) GameCooltip:SetOption("AlignAsBlizzTooltipFrameHeightOffset", 0) GameCooltip:SetOption("LineHeightSizeOffset", 0) GameCooltip:SetOption("VerticalPadding", 0) GameCooltip:ShowCooltip(self, "tooltip") end function damageClass.PredictedAugSpellsOnLeave(self) GameCooltip:Hide() --extraStatusbar.defaultAlpha end --------------------------------------------- // TOOLTIPS // --------------------------------------------- ---------TOOLTIPS BIFURCA��O -- ~tooltip function damageClass:ToolTip (instance, numero, barra, keydown) --seria possivel aqui colocar o icone da classe dele? if (instance.atributo == 5) then --custom return self:TooltipForCustom(barra) else if (instance.sub_atributo == 1 or instance.sub_atributo == 2) then --damage done or Dps or enemy return self:ToolTip_DamageDone(instance, numero, barra, keydown) elseif (instance.sub_atributo == 3) then --damage taken return self:ToolTip_DamageTaken(instance, numero, barra, keydown) elseif (instance.sub_atributo == 6) then --enemies return self:ToolTip_Enemies(instance, numero, barra, keydown) elseif (instance.sub_atributo == 4) then --friendly fire return self:ToolTip_FriendlyFire(instance, numero, barra, keydown) end end end --tooltip locals local r, g, b local barAlha = .6 ---------DAMAGE DONE & DPS function damageClass:ToolTip_DamageDone (instancia, numero, barra, keydown) local owner = self.owner if (owner and owner.classe) then r, g, b = unpack(Details.class_colors [owner.classe]) else if (not Details.class_colors [self.classe]) then return print("Details!: error class not found:", self.classe, "for", self.nome) end r, g, b = unpack(Details.class_colors [self.classe]) end local combatObject = instancia:GetShowingCombat() --habilidades local icon_size = Details.tooltip.icon_size local icon_border = Details.tooltip.icon_border_texcoord do --TOP HABILIDADES --get variables --local ActorDamage = self.total_without_pet --mostrando os pets no tooltip local ActorDamage = self.total local ActorDamageWithPet = self.total if (ActorDamage == 0) then ActorDamage = 0.00000001 end local ActorSkillsContainer = self.spells._ActorTable local ActorSkillsSortTable = {} local reflectionSpells = {} --get time type local meu_tempo if (Details.time_type == 1 or not self.grupo) then meu_tempo = self:Tempo() elseif (Details.time_type == 2 or Details.use_realtimedps) then meu_tempo = instancia.showing:GetCombatTime() end --add actor spells for _spellid, _skill in pairs(ActorSkillsContainer) do ActorSkillsSortTable [#ActorSkillsSortTable+1] = {_spellid, _skill.total, _skill.total/meu_tempo} if (_skill.isReflection) then reflectionSpells[#reflectionSpells+1] = _skill end end --add actor pets for petIndex, petName in ipairs(self:Pets()) do local petActor = instancia.showing[class_type]:PegarCombatente (nil, petName) if (petActor) then for _spellid, _skill in pairs(petActor:GetActorSpells()) do ActorSkillsSortTable [#ActorSkillsSortTable+1] = {_spellid, _skill.total, _skill.total/meu_tempo, petName:gsub((" <.*"), "")} end end end --sort table.sort(ActorSkillsSortTable, Details.Sort2) --TOP INIMIGOS --get variables local ActorTargetsSortTable = {} --add for targetName, amount in pairs(self.targets) do local targetActorObject = combatObject(DETAILS_ATTRIBUTE_DAMAGE, targetName) local npcId = targetActorObject and targetActorObject.aID npcId = tonumber(npcId or 0) ActorTargetsSortTable[#ActorTargetsSortTable+1] = {targetName, amount, npcId} end --sort table.sort(ActorTargetsSortTable, Details.Sort2) --tooltip stuff local tooltip_max_abilities = Details.tooltip.tooltip_max_abilities local is_maximized = false if (keydown == "shift" or TooltipMaximizedMethod == 2 or TooltipMaximizedMethod == 3) then tooltip_max_abilities = 99 is_maximized = true end --MOSTRA HABILIDADES Details:AddTooltipSpellHeaderText (Loc ["STRING_SPELLS"], headerColor, #ActorSkillsSortTable, Details.tooltip_spell_icon.file, unpack(Details.tooltip_spell_icon.coords)) if (is_maximized) then --highlight shift key GameCooltip:AddIcon ([[Interface\AddOns\Details\images\key_shift]], 1, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay2) Details:AddTooltipHeaderStatusbar (r, g, b, 1) else GameCooltip:AddIcon ([[Interface\AddOns\Details\images\key_shift]], 1, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay1) Details:AddTooltipHeaderStatusbar (r, g, b, barAlha) end local topAbility = ActorSkillsSortTable [1] and ActorSkillsSortTable [1][2] or 0.0001 if (#ActorSkillsSortTable > 0) then for i = 1, _math_min(tooltip_max_abilities, #ActorSkillsSortTable) do local SkillTable = ActorSkillsSortTable [i] local spellID = SkillTable [1] local totalDamage = SkillTable [2] local totalDPS = SkillTable [3] local petName = SkillTable [4] local nome_magia, _, icone_magia = _GetSpellInfo(spellID) if (petName) then if (not nome_magia) then spellID = spellID or "spellId?" nome_magia = "|cffffaa00" .. spellID .. " " .. " (|cFFCCBBBB" .. petName .. "|r)" else nome_magia = nome_magia .. " (|cFFCCBBBB" .. petName .. "|r)" end end local percent = format("%.1f", totalDamage/ActorDamage*100) if (string.len(percent) < 4) then percent = percent .. "0" end if (instancia.sub_atributo == 1 or instancia.sub_atributo == 6) then GameCooltip:AddLine(nome_magia, FormatTooltipNumber (_, totalDamage) .." ("..percent.."%)") else GameCooltip:AddLine(nome_magia, FormatTooltipNumber (_, _math_floor(totalDPS)) .." ("..percent.."%)") end GameCooltip:AddIcon (icone_magia, nil, nil, icon_size.W + 4, icon_size.H + 4, icon_border.L, icon_border.R, icon_border.T, icon_border.B) Details:AddTooltipBackgroundStatusbar (false, totalDamage/topAbility*100) end else GameCooltip:AddLine(Loc ["STRING_NO_SPELL"]) end --spell reflected if (#reflectionSpells > 0) then --small blank space Details:AddTooltipSpellHeaderText ("", headerColor, 1, false, 0.1, 0.9, 0.1, 0.9, true) --add a space Details:AddTooltipSpellHeaderText ("Spells Reflected", headerColor, 1, select(3, _GetSpellInfo(reflectionSpells[1].id)), 0.1, 0.9, 0.1, 0.9) --localize-me Details:AddTooltipHeaderStatusbar (r, g, b, barAlha) for i = 1, #reflectionSpells do local _spell = reflectionSpells[i] local extraInfo = _spell.extra for spellId, damageDone in pairs(extraInfo) do local spellName, _, spellIcon = _GetSpellInfo(spellId) if (spellName) then GameCooltip:AddLine(spellName, FormatTooltipNumber (_, damageDone) .. " (" .. _math_floor(damageDone / self.total * 100) .. "%)") Details:AddTooltipBackgroundStatusbar (false, damageDone / self.total * 100) GameCooltip:AddIcon (spellIcon, 1, 1, icon_size.W, icon_size.H, 0.1, 0.9, 0.1, 0.9) end end end end --targets (enemies) local topEnemy = ActorTargetsSortTable[1] and ActorTargetsSortTable[1][2] or 0 if (instancia.sub_atributo == 1 or instancia.sub_atributo == 6) then --small blank space Details:AddTooltipSpellHeaderText("", headerColor, 1, false, 0.1, 0.9, 0.1, 0.9, true) Details:AddTooltipSpellHeaderText(Loc ["STRING_TARGETS"], headerColor, #ActorTargetsSortTable, [[Interface\Addons\Details\images\icons]], 0, 0.03125, 0.126953125, 0.15625) local max_targets = Details.tooltip.tooltip_max_targets local is_maximized = false if (keydown == "ctrl" or TooltipMaximizedMethod == 2 or TooltipMaximizedMethod == 4) then max_targets = 99 is_maximized = true end if (is_maximized) then --highlight GameCooltip:AddIcon([[Interface\AddOns\Details\images\key_ctrl]], 1, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay2) Details:AddTooltipHeaderStatusbar(r, g, b, 1) else GameCooltip:AddIcon([[Interface\AddOns\Details\images\key_ctrl]], 1, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay1) Details:AddTooltipHeaderStatusbar(r, g, b, barAlha) end for i = 1, math.min(max_targets, #ActorTargetsSortTable) do local enemyTable = ActorTargetsSortTable[i] GameCooltip:AddLine(enemyTable[1], FormatTooltipNumber(_, enemyTable[2]) .." ("..format("%.1f", enemyTable[2] / ActorDamageWithPet * 100).."%)") local portraitTexture-- = Details222.Textures.GetPortraitTextureForNpcID(enemyTable[3]) --disabled atm if (portraitTexture) then GameCooltip:AddIcon(portraitTexture, 1, 1, icon_size.W, icon_size.H) else GameCooltip:AddIcon([[Interface\PetBattles\PetBattle-StatIcons]], nil, nil, icon_size.W, icon_size.H, 0, 0.5, 0, 0.5, {.7, .7, .7, 1}, nil, true) end Details:AddTooltipBackgroundStatusbar(false, enemyTable[2] / topEnemy * 100) end end end --PETS local instance = instancia local combatObject = instance:GetShowingCombat() local myPets = self.pets if (#myPets > 0) then --teve ajudantes local petAmountWithSameName = {} --armazena a quantidade de pets iguais local petDamageTable = {} --armazena o dano total de cada objeto --small blank space Details:AddTooltipSpellHeaderText("", headerColor, 1, false, 0.1, 0.9, 0.1, 0.9, true) for index, petName in ipairs(myPets) do if (not petAmountWithSameName[petName]) then petAmountWithSameName[petName] = 1 local damageContainer = combatObject:GetContainer(DETAILS_ATTRIBUTE_DAMAGE) local petActorObject = damageContainer:GetActor(petName) if (petActorObject) then local petDamageDone = petActorObject.total_without_pet local petSpells = petActorObject:GetSpellList() local petSpellsSorted = {} --local timeInCombat = petActorObject:GetTimeInCombat(self) local timeInCombat = 0 if (Details.time_type == 1 or not self.grupo) then timeInCombat = petActorObject:Tempo() elseif (Details.time_type == 2 or Details.use_realtimedps) then timeInCombat = petActorObject:GetCombatTime() end petDamageTable[#petDamageTable+1] = {petName, petActorObject.total_without_pet, petActorObject.total_without_pet / timeInCombat} for spellId, spellTable in pairs(petSpells) do local spellName, rank, spellIcon = _GetSpellInfo(spellId) tinsert(petSpellsSorted, {spellId, spellTable.total, spellTable.total / petDamageDone * 100, {spellName, rank, spellIcon}}) end table.sort(petSpellsSorted, Details.Sort2) local petTargets = {} petSpells = petActorObject.targets for targetName, spellDamageDone in pairs(petSpells) do tinsert(petTargets, {targetName, spellDamageDone, spellDamageDone / petDamageDone * 100}) end table.sort(petTargets,Details.Sort2) end else petAmountWithSameName[petName] = petAmountWithSameName[petName] + 1 end end local petHeaderAdded = false table.sort(petDamageTable, Details.Sort2) local ismaximized = false if (keydown == "alt" or TooltipMaximizedMethod == 2 or TooltipMaximizedMethod == 5) then ismaximized = true end local topPetDamageDone = petDamageTable[1] and petDamageTable[1][2] or 0 for index, damageTable in ipairs(petDamageTable) do if (damageTable [2] > 0 and (index <= Details.tooltip.tooltip_max_pets or ismaximized)) then if (not petHeaderAdded) then petHeaderAdded = true Details:AddTooltipSpellHeaderText(Loc ["STRING_PETS"], headerColor, #petDamageTable, [[Interface\COMMON\friendship-heart]], 0.21875, 0.78125, 0.09375, 0.6875) if (ismaximized) then GameCooltip:AddIcon ([[Interface\AddOns\Details\images\key_alt]], 1, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay2) Details:AddTooltipHeaderStatusbar(r, g, b, 1) else GameCooltip:AddIcon ([[Interface\AddOns\Details\images\key_alt]], 1, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay1) Details:AddTooltipHeaderStatusbar(r, g, b, barAlha) end end local petName = damageTable[1] local petDamageDone = damageTable[2] local petDPS = damageTable[3] petName = damageTable[1]:gsub(("%s%<.*"), "") if (instancia.sub_atributo == 1) then GameCooltip:AddLine(petName, FormatTooltipNumber(_, petDamageDone) .. " (" .. math.floor(petDamageDone/self.total*100) .. "%)") else GameCooltip:AddLine(petName, FormatTooltipNumber(_, math.floor(petDPS)) .. " (" .. math.floor(petDamageDone/self.total*100) .. "%)") end Details:AddTooltipBackgroundStatusbar(false, petDamageDone / topPetDamageDone * 100) GameCooltip:AddIcon([[Interface\AddOns\Details\images\classes_small_alpha]], 1, 1, icon_size.W, icon_size.H, 0.25/2, 0.49609375/2, 0.75/2, 1/2) end end end --~Phases local segment = instancia:GetShowingCombat() if (segment and self.grupo) then local bossInfo = segment:GetBossInfo() local phasesInfo = segment:GetPhases() if (bossInfo and phasesInfo) then if (#phasesInfo > 1) then --small blank space Details:AddTooltipSpellHeaderText ("", headerColor, 1, false, 0.1, 0.9, 0.1, 0.9, true) Details:AddTooltipSpellHeaderText ("Damage by Encounter Phase", headerColor, 1, [[Interface\Garrison\orderhall-missions-mechanic8]], 11/64, 53/64, 11/64, 53/64) --localize-me Details:AddTooltipHeaderStatusbar (r, g, b, barAlha) local playerPhases = {} local totalDamage = 0 for phase, playersTable in pairs(phasesInfo.damage) 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] == self.nome) then myRank = i break end end tinsert(playerPhases, {phase, playersTable [self.nome] or 0, myRank, (playersTable [self.nome] or 0) / totalDamage * 100}) end table.sort (playerPhases, function(a, b) return a[1] < b[1] end) for i = 1, #playerPhases do --[1] Phase Number [2] Amount Done [3] Rank [4] Percent GameCooltip:AddLine("|cFFF0F0F0Phase|r " .. playerPhases [i][1], FormatTooltipNumber (_, playerPhases [i][2]) .. " (|cFFFFFF00#" .. playerPhases [i][3] .. "|r, " .. format("%.1f", playerPhases [i][4]) .. "%)") GameCooltip:AddIcon ([[Interface\Garrison\orderhall-missions-mechanic9]], 1, 1, 14, 14, 11/64, 53/64, 11/64, 53/64) Details:AddTooltipBackgroundStatusbar() end end end end return true end local on_switch_show_enemies = function(instance) instance:TrocaTabela(instance, true, 1, 6) return true end local on_switch_show_frags = function(instance) instance:TrocaTabela(instance, true, 1, 5) return true end local ENEMIES_format_name = function(player) if (player == 0) then return false end return Details:GetOnlyName(player.nome) end local ENEMIES_format_amount = function(amount) if (amount <= 0) then return false end return Details:ToK(amount) .. " (" .. format("%.1f", amount / tooltip_temp_table.damage_total * 100) .. "%)" end function damageClass:ReportEnemyDamageTaken (actor, instance, ShiftKeyDown, ControlKeyDown, fromFrags) --can open the breakdown window now --this function is deprecated if (ShiftKeyDown) then local inimigo = actor.nome local custom_name = inimigo .. " -" .. Loc ["STRING_CUSTOM_ENEMY_DT"] --procura se j� tem um custom: for index, CustomObject in ipairs(Details.custom) do if (CustomObject:GetName() == custom_name) then --fix for not saving funcs on logout if (not CustomObject.OnSwitchShow) then CustomObject.OnSwitchShow = fromFrags and on_switch_show_frags or on_switch_show_enemies end return instance:TrocaTabela(instance.segmento, 5, index) end end --criar um custom para este actor. local new_custom_object = { name = custom_name, icon = [[Interface\ICONS\Pet_Type_Undead]], attribute = "damagedone", author = Details.playername, desc = inimigo .. " Damage Taken", source = "[raid]", target = inimigo, script = false, tooltip = false, temp = true, OnSwitchShow = fromFrags and on_switch_show_frags or on_switch_show_enemies, } tinsert(Details.custom, new_custom_object) setmetatable(new_custom_object, Details.atributo_custom) new_custom_object.__index = Details.atributo_custom return instance:TrocaTabela(instance.segmento, 5, #Details.custom) end if (true) then return end local report_table = {"Details!: " .. actor.nome .. " - " .. Loc ["STRING_ATTRIBUTE_DAMAGE_TAKEN"]} Details:FormatReportLines (report_table, tooltip_temp_table, ENEMIES_format_name, ENEMIES_format_amount) return Details:Reportar (report_table, {_no_current = true, _no_inverse = true, _custom = true}) end local FRAGS_format_name = function(player_name) return Details:GetOnlyName(player_name) end local FRAGS_format_amount = function(amount) return Details:ToK(amount) .. " (" .. format("%.1f", amount / frags_tooltip_table.damage_total * 100) .. "%)" end function damageClass:ReportSingleFragsLine (frag, instance, ShiftKeyDown, ControlKeyDown) if (not frags_tooltip_table) then --some cases a friendly object is getting threat as neutral, example is Druid's Efflorescense return end if (ShiftKeyDown) then return damageClass:ReportEnemyDamageTaken (frag, instance, ShiftKeyDown, ControlKeyDown, true) end local report_table = {"Details!: " .. frag [1] .. " - " .. Loc ["STRING_ATTRIBUTE_DAMAGE_TAKEN"]} Details:FormatReportLines (report_table, frags_tooltip_table, FRAGS_format_name, FRAGS_format_amount) return Details:Reportar (report_table, {_no_current = true, _no_inverse = true, _custom = true}) end function damageClass:ToolTip_Enemies (instancia, numero, barra, keydown) local owner = self.owner if (owner and owner.classe) then r, g, b = unpack(Details.class_colors [owner.classe]) else r, g, b = unpack(Details.class_colors [self.classe]) end local combat = instancia:GetShowingCombat() local enemy_name = self:name() Details:Destroy(tooltip_temp_table) --fix for translit bug report, 'player' is nil --enemy damage taken local i = 1 local damage_taken = 0 for _, actor in ipairs(combat[1]._ActorTable) do if (actor.grupo and actor.targets [self.nome]) then local t = tooltip_temp_table [i] if (not t) then tooltip_temp_table [i] = {} t = tooltip_temp_table [i] end t [1] = actor t [2] = actor.targets [enemy_name] or 0 damage_taken = damage_taken + t [2] i = i + 1 end end for o = i, #tooltip_temp_table do local t = tooltip_temp_table [o] t[2] = 0 t[1] = 0 end _table_sort(tooltip_temp_table, Details.Sort2) -- enemy damage taken Details:AddTooltipSpellHeaderText (Loc ["STRING_DAMAGE_TAKEN_FROM"], headerColor, i-1, [[Interface\Buttons\UI-MicroStream-Red]], 0.1875, 0.8125, 0.15625, 0.78125) GameCooltip:AddIcon ([[Interface\AddOns\Details\images\key_shift]], 1, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay2) Details:AddTooltipHeaderStatusbar (1, 1, 1, 0.5) --build the tooltip local top = (tooltip_temp_table [1] and tooltip_temp_table [1][2]) or 0 tooltip_temp_table.damage_total = damage_taken local lineHeight = Details.tooltip.line_height for o = 1, i-1 do local player = tooltip_temp_table [o][1] local total = tooltip_temp_table [o][2] local player_name = Details:GetOnlyName(player:name()) GameCooltip:AddLine(player_name .. " ", FormatTooltipNumber (_, total) .." (" .. format("%.1f", (total / damage_taken) * 100) .. "%)") local classe = player:class() if (not classe) then classe = "UNKNOW" end if (classe == "UNKNOW") then GameCooltip:AddIcon ("Interface\\LFGFRAME\\LFGROLE_BW", nil, nil, lineHeight, lineHeight, .25, .5, 0, 1) else local specID = player.spec if (specID) then local texture, l, r, t, b = Details:GetSpecIcon (specID, false) GameCooltip:AddIcon (texture, 1, 1, lineHeight, lineHeight, l, r, t, b) else GameCooltip:AddIcon (instancia.row_info.icon_file, nil, nil, lineHeight, lineHeight, unpack(Details.class_coords [classe])) end end local r, g, b = unpack(Details.class_colors [classe]) GameCooltip:AddStatusBar (total/top*100, 1, r, g, b, 1, false, enemies_background) end GameCooltip:SetOption("StatusBarTexture", "Interface\\AddOns\\Details\\images\\bar_serenity") --damage done and heal GameCooltip:AddLine(" ") GameCooltip:AddLine(Loc ["STRING_ATTRIBUTE_DAMAGE_ENEMIES_DONE"], FormatTooltipNumber (_, _math_floor(self.total))) local half = 0.00048828125 GameCooltip:AddIcon (instancia:GetSkinTexture(), 1, 1, 14, 14, 0.005859375 + half, 0.025390625 - half, 0.3623046875, 0.3818359375) GameCooltip:AddStatusBar (0, 1, r, g, b, 1, false, enemies_background) local heal_actor = instancia.showing (2, self.nome) if (heal_actor) then GameCooltip:AddLine(Loc ["STRING_ATTRIBUTE_HEAL_ENEMY"], FormatTooltipNumber (_, _math_floor(heal_actor.heal_enemy_amt))) else GameCooltip:AddLine(Loc ["STRING_ATTRIBUTE_HEAL_ENEMY"], 0) end GameCooltip:AddIcon (instancia:GetSkinTexture(), 1, 1, 14, 14, 0.037109375 + half, 0.056640625 - half, 0.3623046875, 0.3818359375) GameCooltip:AddStatusBar (0, 1, r, g, b, 1, false, enemies_background) GameCooltip:AddLine(" ") Details:AddTooltipReportLineText() GameCooltip:SetOption("YSpacingMod", 0) return true end ---------DAMAGE TAKEN function damageClass:ToolTip_DamageTaken(instance, numero, barra, keydown) --if the object has a owner, it's a pet local owner = self.owner if (owner and owner.classe) then r, g, b = unpack(Details.class_colors[owner.classe]) else r, g, b = unpack(Details.class_colors[self.classe]) end local damageTakenFrom = self.damage_from local totalDamageTaken = self.damage_taken local actorName = self:Name() local combatObject = instance:GetShowingCombat() local damageContainer = combatObject:GetContainer(DETAILS_ATTRIBUTE_DAMAGE) ---@type {key1:actorname, key2:valueamount, key3:class, key4:actor} local damageTakenDataSorted = {} local mainAttribute, subAttribute = instance:GetDisplay() if (subAttribute == DETAILS_SUBATTRIBUTE_ENEMIES) then for _, actorObject in damageContainer:ListActors() do if (actorObject:IsGroupPlayer() and actorObject.targets[actorName]) then damageTakenDataSorted [#damageTakenDataSorted+1] = { actorName, actorObject.targets[actorName], actorObject:Class(), actorObject } end end else for enemyName, _ in pairs(damageTakenFrom) do --who damaged the player --get the aggressor local enemyActorObject = damageContainer:GetActor(enemyName) if (enemyActorObject) then ---@type {key1:actorname, key2:valueamount, key3:class, key4:actor} local damageTakenTable local damageInflictedByThisEnemy = enemyActorObject.targets[actorName] if (damageInflictedByThisEnemy) then if (enemyActorObject:IsPlayer() or enemyActorObject:IsNeutralOrEnemy()) then damageTakenTable = {enemyName, damageInflictedByThisEnemy, enemyActorObject:Class(), enemyActorObject} damageTakenDataSorted[#damageTakenDataSorted+1] = damageTakenTable end end --special cases - monk stagger if (enemyName == actorName and self:Class() == "MONK") then local friendlyFire = enemyActorObject.friendlyfire[enemyName] if (friendlyFire and friendlyFire.total > 0) then local staggerDamage = friendlyFire.spells[124255] or 0 if (staggerDamage > 0) then if (damageTakenTable) then damageTakenTable[2] = damageTakenTable[2] + staggerDamage else damageTakenDataSorted[#damageTakenDataSorted+1] = {enemyName, staggerDamage, "MONK", enemyActorObject} end end end end end end end local maxDataAllowed = #damageTakenDataSorted if (maxDataAllowed > 10) then maxDataAllowed = 10 end local bIsMaximized = false if (keydown == "shift" or TooltipMaximizedMethod == 2 or TooltipMaximizedMethod == 3 or instance.sub_atributo == 6 or Details.damage_taken_everything) then maxDataAllowed = #damageTakenDataSorted bIsMaximized = true end if (subAttribute == DETAILS_SUBATTRIBUTE_ENEMIES) then Details:AddTooltipSpellHeaderText(Loc ["STRING_DAMAGE_TAKEN_FROM"], headerColor, #damageTakenDataSorted, [[Interface\Buttons\UI-MicroStream-Red]], 0.1875, 0.8125, 0.15625, 0.78125) else Details:AddTooltipSpellHeaderText(Loc ["STRING_FROM"], headerColor, #damageTakenDataSorted, [[Interface\Addons\Details\images\icons]], 0.126953125, 0.1796875, 0, 0.0546875) end if (bIsMaximized) then --highlight GameCooltip:AddIcon([[Interface\AddOns\Details\images\key_shift]], 1, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay2) if (subAttribute == DETAILS_SUBATTRIBUTE_ENEMIES) then GameCooltip:AddStatusBar(100, 1, 0.7, g, b, 1) else Details:AddTooltipHeaderStatusbar(r, g, b, 1) end else GameCooltip:AddIcon([[Interface\AddOns\Details\images\key_shift]], 1, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay1) if (subAttribute == DETAILS_SUBATTRIBUTE_ENEMIES) then GameCooltip:AddStatusBar(100, 1, 0.7, 0, 0, barAlha) else Details:AddTooltipHeaderStatusbar(r, g, b, barAlha) end end local iconSize = Details.tooltip.icon_size local iconBorderTexCoord = Details.tooltip.icon_border_texcoord -- create a full list of incoming damage, before adding any lines to the tooltip, so we can sort them appropriately ---@class cooltip_icon ---@field key1 textureid ---@field key2 number 1 for main tooltip frame, 2 for the secondary frame ---@field key3 number 1 for the left side, 2 for the right size ---@field key4 width ---@field key5 height ---@field key6 coordleft ---@field key7 coordright ---@field key8 coordtop ---@field key9 coordbottom ---@type {key1:valueamount, key2:table, key3:cooltip_icon} local lines_to_add = {} for i = 1, maxDataAllowed do local enemyActorObject = damageTakenDataSorted[i][4] --only shows damage from enemies or from the player it self --the player it self can only be placed on the list by the iteration above --the iteration doesnt check friendly fire for all actors, only a few cases like Monk Stagger if (enemyActorObject:IsNeutralOrEnemy() or enemyActorObject:Name() == self:Name()) then ---@type {key1:spellid, key2:valueamount, key:actorname} local spellTargetDamageList = {} for spellId, spellTable in pairs(enemyActorObject.spells._ActorTable) do local damageOnTarget = spellTable.targets[self:Name()] if (damageOnTarget) then tinsert(spellTargetDamageList, {spellId, damageOnTarget, enemyActorObject:Name()}) end end --friendly fire local friendlyFire = enemyActorObject.friendlyfire[self:Name()] if (friendlyFire) then for spellId, valueAmount in pairs(friendlyFire.spells) do table.insert(spellTargetDamageList, {spellId, valueAmount, enemyActorObject:Name()}) end end for _, spell in ipairs(spellTargetDamageList) do local spellId, valueAmount, thisActorName = unpack(spell) local spellName, _, spellIcon = _GetSpellInfo(spellId) local addTextArgs = {spellName .. " (|cFFFFFF00" .. thisActorName .. "|r)", Details:Format(valueAmount) .. " (" .. string.format("%.1f", (valueAmount / totalDamageTaken) * 100) .. "%)"} ---@type cooltip_icon local addIconArgs = {spellIcon, 1, 1, iconSize.W, iconSize.H, iconBorderTexCoord.L, iconBorderTexCoord.R, iconBorderTexCoord.T, iconBorderTexCoord.B} tinsert(lines_to_add, { valueAmount, addTextArgs, addIconArgs }) end else ---@type actorname, valueamount, class, actor local thisAggrossorTable = damageTakenDataSorted[i] local actorName = thisAggrossorTable[1] local amount = thisAggrossorTable[2] local class = thisAggrossorTable[3] local actorObject = thisAggrossorTable[4] ---@type {key1:actorname, key2:string, key3:nil, key4:color} local addLineArgs ---@type cooltip_icon local addIconArgs local aggressorName = Details:GetOnlyName(actorName) if (bIsMaximized and actorName:find(Details.playername)) then addLineArgs = {aggressorName, Details:Format(amount) .. " ("..string.format("%.1f", (amount / totalDamageTaken) * 100) .. "%)", nil, "yellow"} else addLineArgs = {aggressorName, Details:Format(amount) .. " ("..string.format("%.1f", (amount / totalDamageTaken) * 100) .. "%)"} end if (not class) then class = "UNKNOW" end if (class == "UNKNOW") then addIconArgs = {"Interface\\LFGFRAME\\LFGROLE_BW", nil, nil, iconSize.W, iconSize.H, .25, .5, 0, 1} else addIconArgs= {instance.row_info.icon_file, nil, nil, iconSize.W, iconSize.H, unpack(Details.class_coords [class])} end tinsert(lines_to_add, {amount, addLineArgs, addIconArgs}) end end table.sort(lines_to_add, Details.Sort1) for _, line in ipairs(lines_to_add) do GameCooltip:AddLine(unpack(line[2])) GameCooltip:AddIcon(unpack(line[3])) Details:AddTooltipBackgroundStatusbar() end if (subAttribute == DETAILS_SUBATTRIBUTE_ENEMIES) then GameCooltip:AddLine(" ") GameCooltip:AddLine(Loc ["STRING_ATTRIBUTE_DAMAGE_DONE"], FormatTooltipNumber (_, _math_floor(self.total))) local half = 0.00048828125 GameCooltip:AddIcon (instance:GetSkinTexture(), 1, 1, iconSize.W, iconSize.H, 0.005859375 + half, 0.025390625 - half, 0.3623046875, 0.3818359375) Details:AddTooltipBackgroundStatusbar() local heal_actor = instance.showing (2, self.nome) if (heal_actor) then GameCooltip:AddLine(Loc ["STRING_ATTRIBUTE_HEAL_DONE"], FormatTooltipNumber (_, _math_floor(heal_actor.heal_enemy_amt))) else GameCooltip:AddLine(Loc ["STRING_ATTRIBUTE_HEAL_DONE"], 0) end GameCooltip:AddIcon (instance:GetSkinTexture(), 1, 1, iconSize.W, iconSize.H, 0.037109375 + half, 0.056640625 - half, 0.3623046875, 0.3818359375) Details:AddTooltipBackgroundStatusbar() end return true end ---------FRIENDLY FIRE function damageClass:ToolTip_FriendlyFire (instancia, numero, barra, keydown) local owner = self.owner if (owner and owner.classe) then r, g, b = unpack(Details.class_colors [owner.classe]) else r, g, b = unpack(Details.class_colors [self.classe]) end local FriendlyFire = self.friendlyfire local FriendlyFireTotal = self.friendlyfire_total local combat = instancia:GetShowingCombat() local tabela_do_combate = instancia.showing local showing = tabela_do_combate [class_type] local icon_size = Details.tooltip.icon_size local icon_border = Details.tooltip.icon_border_texcoord local lineHeight = Details.tooltip.line_height local DamagedPlayers = {} local Skills = {} for target_name, ff_table in pairs(FriendlyFire) do local actor = combat (1, target_name) if (actor) then DamagedPlayers [#DamagedPlayers+1] = {target_name, ff_table.total, actor.classe} for spellid, amount in pairs(ff_table.spells) do Skills [spellid] = (Skills [spellid] or 0) + amount end end end _table_sort(DamagedPlayers, Details.Sort2) Details:AddTooltipSpellHeaderText (Loc ["STRING_TARGETS"], headerColor, #DamagedPlayers, Details.tooltip_target_icon.file, unpack(Details.tooltip_target_icon.coords)) local ismaximized = false if (keydown == "shift" or TooltipMaximizedMethod == 2 or TooltipMaximizedMethod == 3) then GameCooltip:AddIcon ([[Interface\AddOns\Details\images\key_shift]], 1, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay2) Details:AddTooltipHeaderStatusbar (r, g, b, 1) ismaximized = true else GameCooltip:AddIcon ([[Interface\AddOns\Details\images\key_shift]], 1, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay1) Details:AddTooltipHeaderStatusbar (r, g, b, barAlha) end local max_abilities = Details.tooltip.tooltip_max_abilities if (ismaximized) then max_abilities = 99 end for i = 1, _math_min(max_abilities, #DamagedPlayers) do local classe = DamagedPlayers[i][3] if (not classe) then classe = "UNKNOW" end GameCooltip:AddLine(Details:GetOnlyName(DamagedPlayers[i][1]), FormatTooltipNumber (_, DamagedPlayers[i][2]).." ("..format("%.1f", DamagedPlayers[i][2]/FriendlyFireTotal*100).."%)") GameCooltip:AddIcon ("Interface\\AddOns\\Details\\images\\espadas", nil, nil, lineHeight, lineHeight) Details:AddTooltipBackgroundStatusbar() if (classe == "UNKNOW") then GameCooltip:AddIcon ("Interface\\AddOns\\Details\\images\\classes_small", nil, nil, lineHeight, lineHeight, unpack(Details.class_coords ["UNKNOW"])) else local specID = Details:GetSpec(DamagedPlayers[i][1]) if (specID) then local texture, l, r, t, b = Details:GetSpecIcon (specID, false) GameCooltip:AddIcon (texture, 1, 1, lineHeight, lineHeight, l, r, t, b) else GameCooltip:AddIcon ("Interface\\AddOns\\Details\\images\\classes_small", nil, nil, lineHeight, lineHeight, unpack(Details.class_coords [classe])) end end end Details:AddTooltipSpellHeaderText (Loc ["STRING_SPELLS"], headerColor, 1, Details.tooltip_spell_icon.file, unpack(Details.tooltip_spell_icon.coords)) local ismaximized = false if (keydown == "ctrl" or TooltipMaximizedMethod == 2 or TooltipMaximizedMethod == 4) then GameCooltip:AddIcon ([[Interface\AddOns\Details\images\key_ctrl]], 1, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay2) Details:AddTooltipHeaderStatusbar (r, g, b, 1) ismaximized = true else GameCooltip:AddIcon ([[Interface\AddOns\Details\images\key_ctrl]], 1, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay1) Details:AddTooltipHeaderStatusbar (r, g, b, barAlha) end local max_abilities2 = Details.tooltip.tooltip_max_abilities if (ismaximized) then max_abilities2 = 99 end --spells usadas no friendly fire local SpellsInOrder = {} for spellID, amount in pairs(Skills) do SpellsInOrder [#SpellsInOrder+1] = {spellID, amount} end _table_sort(SpellsInOrder, Details.Sort2) for i = 1, _math_min(max_abilities2, #SpellsInOrder) do local nome, _, icone = _GetSpellInfo(SpellsInOrder[i][1]) GameCooltip:AddLine(nome, FormatTooltipNumber (_, SpellsInOrder[i][2]).." ("..format("%.1f", SpellsInOrder[i][2]/FriendlyFireTotal*100).."%)") GameCooltip:AddIcon (icone, nil, nil, icon_size.W, icon_size.H, icon_border.L, icon_border.R, icon_border.T, icon_border.B) Details:AddTooltipBackgroundStatusbar() end return true end --------------------------------------------- // JANELA DETALHES // --------------------------------------------- ---------DETALHES BIFURCA��O ~detalhes ~detailswindow ~bi function damageClass:MontaInfo() 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) --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 (breakdownWindowFrame.sub_atributo == 3) then return self:MontaDetalhesDamageTaken (spellid, barra, instancia) elseif (breakdownWindowFrame.sub_atributo == 4) then return self:MontaDetalhesFriendlyFire (spellid, barra, instancia) elseif (breakdownWindowFrame.sub_atributo == 6) then if (bitBand(self.flag_original, 0x00000400) ~= 0) then --� um jogador 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 = breakdownWindowFrame.instancia ---@type combat local combatObject = instance:GetCombat() ---@type string local actorName = actorObject:Name() ---@type number local friendlyFireTotal = actorObject.friendlyfire_total ---@type table local damagedPlayers = actorObject.friendlyfire --players which got hit by this actor ---@type actorcontainer local damageContainer = combatObject:GetContainer(class_type) local resultTable = {} 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, class: string} local ffTable = {name = targetName, total = amountOfFriendlyFire, icon = iconTable, class = targetActorObject:Class()} resultTable[#resultTable+1] = ffTable end end end resultTable.totalValue = friendlyFireTotal resultTable.combatTime = combatObject:GetCombatTime() resultTable.headersAllowed = friendlyFireHeadersAllowed 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 FriendlyFireTotal = self.friendlyfire_total local DamagedPlayers = {} local Skills = {} 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}) for spellid, amount in pairs(ff_table.spells) do Skills [spellid] = (Skills [spellid] or 0) + amount end end end _table_sort(DamagedPlayers, Details.Sort2) local amt = #DamagedPlayers gump:JI_AtualizaContainerBarras (amt) local FirstPlaceDamage = DamagedPlayers [1] and DamagedPlayers [1][2] or 0 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 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 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 local SkillTable = {} for spellid, amt in pairs(Skills) do local nome, _, icone = _GetSpellInfo(spellid) SkillTable [#SkillTable+1] = {nome, amt, amt/FriendlyFireTotal*100, icone} end _table_sort(SkillTable, Details.Sort2) 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) 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 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() ---@type combat local combatObject = Details:GetCombatFromBreakdownWindow() --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 --iterate among the pets of the aggressorActor and get the spells casted by them ---@type table local petTable = aggressorActor.pets 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") 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 end return resultTable end ------ Damage Taken local damageTakenHeadersAllowed = {icon = true, name = true, rank = true, amount = true, persecond = true, percent = true} function damageClass:MontaInfoDamageTaken() ---@type actordamage local actorObject = self ---@type instance local instance = breakdownWindowFrame.instancia ---@type combat local combatObject = instance:GetCombat() ---@type string local actorName = actorObject:Name() ---@type number local damageTakenTotal = actorObject.damage_taken ---@type table local damageTakenFrom = actorObject.damage_from ---@type actorcontainer local damageContainer = combatObject:GetContainer(class_type) local resultTable = {} ---@type string for aggressorName in pairs(damageTakenFrom) do local aggressorActor = damageContainer:GetActor(aggressorName) if (aggressorActor) then ---@type table local targets = aggressorActor:GetTargets() ---@type number|nil local amountOfDamage = targets[actorName] if (amountOfDamage) then ---@type texturetable local iconTable = Details:GetActorIcon(aggressorActor) ---@type {name: string, amount: number, icon: texturetable} local damageTakenTable = {name = aggressorName, total = amountOfDamage, icon = iconTable, class = aggressorActor:Class()} resultTable[#resultTable+1] = damageTakenTable end end end resultTable.totalValue = damageTakenTotal resultTable.combatTime = combatObject:GetCombatTime() resultTable.headersAllowed = damageTakenHeadersAllowed Details222.BreakdownWindow.SendGenericData(resultTable, actorObject, combatObject, instance) end --[[exported]] function Details:UpdadeInfoBar(row, index, spellId, name, value, formattedValue, max, percent, icon, detalhes, texCoords, spellSchool, class) if (index == 1) then row.textura:SetValue(100) else max = math.max(max, 0.001) row.textura:SetValue(value / max * 100) end if (type(index) == "number") then if (debugmode) then row.lineText1:SetText(index .. ". " .. name .. " (" .. spellId .. ")") else row.lineText1:SetText(index .. ". " .. name) end else row.lineText1:SetText(name) end row.lineText1.text = row.lineText1:GetText() if (formattedValue) then row.lineText4:SetText(formattedValue .. " (" .. format("%.1f", percent) .."%)") end row.lineText1:SetSize(row:GetWidth() - row.lineText4:GetStringWidth() - 40, 15) if (icon) then row.icone:SetTexture(icon) if (icon == "Interface\\AddOns\\Details\\images\\classes_small") then row.icone:SetTexCoord(0.25, 0.49609375, 0.75, 1) else row.icone:SetTexCoord(0, 1, 0, 1) end else row.icone:SetTexture("") end if (not row.IconUpBorder) then row.IconUpBorder = CreateFrame("frame", nil, row,"BackdropTemplate") row.IconUpBorder:SetAllPoints(row.icone) row.IconUpBorder:SetBackdrop({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1}) row.IconUpBorder:SetBackdropBorderColor(0, 0, 0, 0.75) end if (texCoords) then row.icone:SetTexCoord(unpack(texCoords)) else local iconBorder = Details.tooltip.icon_border_texcoord row.icone:SetTexCoord(iconBorder.L, iconBorder.R, iconBorder.T, iconBorder.B) end row.minha_tabela = self row.show = spellId row:Show() if (spellSchool) then local schoolColor = Details.spells_school[spellSchool] if (schoolColor and schoolColor.decimals) then row.textura:SetStatusBarColor(schoolColor.decimals[1], schoolColor.decimals[2], schoolColor.decimals[3]) else row.textura:SetStatusBarColor(1, 1, 1) end elseif (class) then local color = Details.class_colors[class] if (color and class ~= "UNKNOW") then row.textura:SetStatusBarColor(unpack(color)) else row.textura:SetStatusBarColor(1, 1, 1) end else if (spellId == 98021) then --spirit linkl row.textura:SetStatusBarColor(1, 0.4, 0.4) else row.textura:SetStatusBarColor(1, 1, 1) end end 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 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 breakdownWindowFrame.mostrando) then breakdownWindowFrame.mostrando = row end end else if (row.on_focus) then row.textura:SetStatusBarColor(1, 1, 1, 1) --volta a cor antiga row:SetAlpha(.9) --volta a alfa antiga row.on_focus = false end end end end local wipeSpellCache = function() --deprecated Details:Destroy(Details222.PlayerBreakdown.DamageSpellsCache) end local addToSpellCache = function(unitGUID, spellName, spellTable) --deprecated local unitSpellCache = Details222.PlayerBreakdown.DamageSpellsCache[unitGUID] if (not unitSpellCache) then unitSpellCache = {} Details222.PlayerBreakdown.DamageSpellsCache[unitGUID] = unitSpellCache end local spellCache = Details222.PlayerBreakdown.DamageSpellsCache[unitGUID][spellName] if (not spellCache) then spellCache = {} Details222.PlayerBreakdown.DamageSpellsCache[unitGUID][spellName] = spellCache end table.insert(spellCache, spellTable) end local getSpellDetails = function(unitGUID, spellName) --deprecated local unitCachedSpells = Details222.PlayerBreakdown.DamageSpellsCache[unitGUID] local spellsTableForSpellName = unitCachedSpells and unitCachedSpells[spellName] if (spellsTableForSpellName) then --should always be valid if (#spellsTableForSpellName > 1) then local t = spellsTableForSpellName local spellId = t[1].id local newSpellTable = Details222.DamageSpells.CreateSpellTable(spellId) newSpellTable.n_min = 99999999 newSpellTable.c_min = 99999999 newSpellTable.n_max = 0 newSpellTable.c_max = 0 for i = 1, #t do for key, value in pairs(t[i]) do if (type(value) == "number") then if (key == "n_min" or key == "c_min") then if (value < newSpellTable[key]) then newSpellTable[key] = value end elseif (key == "n_max" or key == "c_max") then if (value > newSpellTable[key]) then newSpellTable[key] = value end elseif (key ~= "id" and key ~= "spellschool") then newSpellTable[key] = (newSpellTable[key] or 0) + value end end end end return newSpellTable else --there's only one table, so return the first return spellsTableForSpellName[1] end end end --[=[ current: passando todas as spells para o breakdown, até mesmo as spells que não tem merge é enviado a spell total e a a spellTable logo em seguida isso forma uma array com o dobro do tamanho e spells duplicadas passar as spells repetidas em uma segunda array? não passar nada e deixar o sistema aprender sozinho, como o sistema vai saber que precisa por uma arrow na linha? (para expandi-la) --]=] ------ Damage Done & Dps function damageClass:MontaInfoDamageDone() --I guess this fills the list of spells in the topleft scrollBar in the summary tab --the goal of this function is to build a list of spells the actor used and send the data to Details! which will delivery to the summary tab actived --so the script only need to build the list of spells and send it to Details! ---@type actor local actorObject = self ---@type instance local instance = breakdownWindowFrame.instancia ---@type combat local combatObject = instance:GetCombat() ---@type number local diff = combatObject:GetDifficulty() ---@type string local playerName = actorObject:Name() local attribute, subAttribute = instance:GetDisplay() --guild ranking on a boss --check if is a raid encounter and if is heroic or mythic do if (diff and (diff == 15 or diff == 16)) then local db = Details.OpenStorage() if (db) then local bestRank, encounterTable = Details.storage:GetBestFromPlayer(diff, combatObject:GetBossInfo().id, "damage", playerName, true) if (bestRank) then --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", "") .. ")" breakdownWindowFrame:SetStatusbarText (text1, 10, "gray") else breakdownWindowFrame:SetStatusbarText() end else breakdownWindowFrame:SetStatusbarText() end else breakdownWindowFrame:SetStatusbarText() end end ---@type breakdownspelldatalist local breakdownSpellDataList = {} ---@type number local totalDamageWithoutPet = actorObject.total_without_pet ---@type number local actorTotal = actorObject.total ---@type table local actorSpells = actorObject:GetSpellList() wipeSpellCache() --get time local actorCombatTime if (Details.time_type == 1 or not actorObject.grupo) then actorCombatTime = actorObject:Tempo() elseif (Details.time_type == 2 or Details.use_realtimedps) then actorCombatTime = breakdownWindowFrame.instancia.showing:GetCombatTime() end --actor spells ---@type table local alreadyAdded = {} local bShouldMergePlayerSpells = Details.breakdown_spell_tab.nest_players_spells_with_same_name ---@type number, spelltable for spellId, spellTable in pairs(actorSpells) do spellTable.ChartData = nil --~ChartData ---@type string local spellName = _GetSpellInfo(spellId) if (spellName) then ---@type number in which index the spell with the same name was stored local index = alreadyAdded[spellName] if (index and bShouldMergePlayerSpells) then ---@type spelltableadv local bkSpellData = breakdownSpellDataList[index] bkSpellData.spellTables[#bkSpellData.spellTables+1] = spellTable ---@type bknesteddata local nestedData = {spellId = spellId, spellTable = spellTable, actorName = "", value = 0} bkSpellData.nestedData[#bkSpellData.nestedData+1] = nestedData bkSpellData.bCanExpand = true else ---@type spelltableadv local bkSpellData = { id = spellId, spellschool = spellTable.spellschool, bIsExpanded = Details222.BreakdownWindow.IsSpellExpanded(spellId), bCanExpand = false, spellTables = {spellTable}, nestedData = {{spellId = spellId, spellTable = spellTable, actorName = "", value = 0}}, } detailsFramework:Mixin(bkSpellData, Details.SpellTableMixin) breakdownSpellDataList[#breakdownSpellDataList+1] = bkSpellData alreadyAdded[spellName] = #breakdownSpellDataList end end end --pets spells local bShouldMergeSpellsWithThePet = Details.breakdown_spell_tab.nest_pet_spells_by_caster local bShouldMergePetSpells = Details.breakdown_spell_tab.nest_pet_spells_by_name local actorPets = actorObject:GetPets() for _, petName in ipairs(actorPets) do ---@type actor local petActor = combatObject(DETAILS_ATTRIBUTE_DAMAGE, petName) if (petActor) then --PET --get the amount of spells the pet used, if the pet used only one there`s no reason to nest one spell with the pet local petSpellContainer = petActor:GetSpellContainer("spell") if (bShouldMergeSpellsWithThePet and petSpellContainer:HasTwoOrMoreSpells()) then ---@type spelltableadv local bkSpellData = { bIsActorHeader = true, --tag this spelltable as an actor header, when the actor is the header it will nest the spells use by this actor actorName = petName, npcId = petActor.aID, id = 0, spellschool = 0, bIsExpanded = Details222.BreakdownWindow.IsSpellExpanded(petName), spellTables = {}, --populated below with the spells the pet used nestedData = {}, --there's none data here in the main bar as the first bar is the pet name bCanExpand = true, actorIcon = [[Interface\AddOns\Details\images\pets\pet_icon_1]], } detailsFramework:Mixin(bkSpellData, Details.SpellTableMixin) --output breakdownSpellDataList[#breakdownSpellDataList+1] = bkSpellData --fill here the spellTables using the actor abilities --all these spells belong to the current actor in the loop for spellId, spellTable in petSpellContainer:ListSpells() do local spellName, _, spellIcon = GetSpellInfo(spellId) if (spellName) then bkSpellData.spellTables[#bkSpellData.spellTables+1] = spellTable ---@type bknesteddata local nestedData = {spellId = spellId, spellTable = spellTable, actorName = petName, value = 0, bIsActorHeader = true} --value to be defined bkSpellData.nestedData[#bkSpellData.nestedData+1] = nestedData end end else local spells = petActor:GetSpellList() --all these spells belong to the current pet in the loop for spellId, spellTable in pairs(spells) do ---@cast spellId number ---@cast spellTable spelltable spellTable.ChartData = nil --PET ---@type string local spellName = _GetSpellInfo(spellId) if (spellName) then ---@type number in which index the spell with the same name was stored local index = alreadyAdded[spellName] if (index and bShouldMergePetSpells) then --PET ---@type spelltableadv local bkSpellData = breakdownSpellDataList[index] bkSpellData.spellTables[#bkSpellData.spellTables+1] = spellTable ---@type bknesteddata local nestedData = {spellId = spellId, spellTable = spellTable, actorName = petName, value = 0} bkSpellData.nestedData[#bkSpellData.nestedData+1] = nestedData bkSpellData.bCanExpand = true else --PET ---@type spelltableadv local bkSpellData = { id = spellId, actorName = petName, npcId = petActor.aID, spellschool = spellTable.spellschool, bIsExpanded = Details222.BreakdownWindow.IsSpellExpanded(spellId), bCanExpand = false, spellTables = {spellTable}, nestedData = {{spellId = spellId, spellTable = spellTable, actorName = petName, value = 0}}, } detailsFramework:Mixin(bkSpellData, Details.SpellTableMixin) breakdownSpellDataList[#breakdownSpellDataList+1] = bkSpellData alreadyAdded[spellName] = #breakdownSpellDataList end end end end end end --copy the keys from the spelltable and add them to the spelltableadv --repeated spells will be summed for i = 1, #breakdownSpellDataList do ---@type spelltableadv local bkSpellData = breakdownSpellDataList[i] Details.SpellTableMixin.SumSpellTables(bkSpellData.spellTables, bkSpellData) --Details:Destroy(bkSpellData, "spellTables") --temporary fix for BuildSpellTargetFromBreakdownSpellData, that function need to use bkSpellData.nestedData end breakdownSpellDataList.totalValue = actorTotal breakdownSpellDataList.combatTime = actorCombatTime Details:Destroy(alreadyAdded) --send to the breakdown window Details222.BreakdownWindow.SendSpellData(breakdownSpellDataList, actorObject, combatObject, instance) --targets ---an array of breakdowntargettable ---@type breakdowntargettablelist local targetList = {} local targetTotalValue = 0 local targetsTable = self:GetTargets() for targetName, amount in pairs(targetsTable) do ---@class breakdowntargettable local bkTargetData = { name = targetName, total = amount, overheal = 0, } targetTotalValue = targetTotalValue + amount tinsert(targetList, bkTargetData) end targetList.totalValue = targetTotalValue targetList.combatTime = actorCombatTime Details222.BreakdownWindow.SendTargetData(targetList, actorObject, combatObject, instance) if 1 then return end --to be deprecated and removed: --gump:JI_AtualizaContainerBarras (#actorSpellsSorted + 1) local max_ = breakdownSpellDataList[1] and breakdownSpellDataList[1][2] or 0 --dano que a primeiro magia vez local barra --aura bar if (false) then --disabled for now barra = allLines [1] if (not barra) then barra = gump:CriaNovaBarraInfo1 (instance, 1) end self:UpdadeInfoBar(barra, "", -51, "Auras", max_, false, max_, 100, [[Interface\BUTTONS\UI-GroupLoot-DE-Up]], true, nil, nil) barra.textura:SetStatusBarColor(Details.gump:ParseColors("purple")) end --spell bars for index, tabela in ipairs(breakdownSpellDataList) do --index = index + 1 --with the aura bar index = index barra = allLines [index] if (not barra) then barra = gump:CriaNovaBarraInfo1 (instance, index) end barra.other_actor = tabela [6] local name = tabela[4] 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 local formated_value = SelectedToKFunction(_, _math_floor(tabela[2])) self:UpdadeInfoBar(barra, index, tabela[1], name, tabela[2], formated_value, max_, tabela[3], tabela[5], true, nil, tabela [7]) end self:FocusLock(barra, tabela[1]) end --targets if (instance.sub_atributo == DETAILS_SUBATTRIBUTE_ENEMIES) then local totalDamageTaken = self.damage_taken local damageTakenFrom = self.damage_from local combatObject = instance:GetShowingCombat() local damageContainer = combatObject:GetContainer(DETAILS_ATTRIBUTE_DAMAGE) local barras = breakdownWindowFrame.barras2 local enemyTable = {} local targetName = self:Name() local enemyActorObject for enemyName in pairs(damageTakenFrom) do enemyActorObject = damageContainer:GetActor(enemyName) if (enemyActorObject) then local damageDoneToTarget = enemyActorObject.targets[targetName] if (damageDoneToTarget) then local npcId = DetailsFramework:GetNpcIdFromGuid(enemyActorObject:GetGUID()) enemyTable[#enemyTable+1] = {enemyName, damageDoneToTarget, damageDoneToTarget / totalDamageTaken * 100, enemyActorObject:Class(), npcId} end end end local enemyAmount = #enemyTable if (enemyAmount < 1) then return true end gump:JI_AtualizaContainerAlvos(enemyAmount) table.sort(enemyTable, Details.Sort2) local topDamage = enemyTable[1] and enemyTable[1][2] or 0 local thisLine for index, thisEnemyTable in ipairs(enemyTable) do thisLine = barras[index] if (not thisLine) then --se a barra n�o existir, criar ela ent�o thisLine = gump:CriaNovaBarraInfo2 (instance, index) thisLine.textura:SetStatusBarColor(1, 1, 1, 1) --isso aqui � a parte da sele��o e descele��o end if (index == 1) then thisLine.textura:SetValue(100) else thisLine.textura:SetValue(thisEnemyTable[2] / topDamage * 100) end thisLine.lineText1:SetText(index .. ". " .. Details:GetOnlyName(thisEnemyTable[1])) --left text thisLine.lineText4:SetText(Details:comma_value (thisEnemyTable[2]) .. " (" .. format("%.1f", thisEnemyTable[3]) .. "%)") --right text thisLine.icone:SetTexture([[Interface\AddOns\Details\images\classes_small_alpha]]) --class icon local texCoords = Details.class_coords[thisEnemyTable[4]] if (not texCoords) then texCoords = Details.class_coords["UNKNOW"] end thisLine.icone:SetTexCoord(unpack(texCoords)) local color = Details.class_colors[thisEnemyTable[4]] if (color) then thisLine.textura:SetStatusBarColor(unpack(color)) else thisLine.textura:SetStatusBarColor(1, 1, 1) end Details:name_space_info(thisLine) if (thisLine.mouse_over) then --atualizar o tooltip if (thisLine.isAlvo) then GameTooltip:Hide() GameTooltip:SetOwner(thisLine, "ANCHOR_TOPRIGHT") if (not thisLine.minha_tabela:MontaTooltipDamageTaken(thisLine, index)) then return end GameTooltip:Show() end end thisLine.minha_tabela = self --grava o jogador na tabela thisLine.nome_inimigo = thisEnemyTable[1] --salva o nome do inimigo na barra --isso � necess�rio? -- no rank do spell id colocar o que? thisLine.spellid = "enemies" thisLine:Show() --mostra a barra end else local combatObject = instance:GetShowingCombat() local damageContainer = combatObject:GetContainer(DETAILS_ATTRIBUTE_DAMAGE) local allActorTargets = {} --table with actor names and damage done which the player caused damage to local targetsTable = self.targets for targetName, damageDone in pairs(targetsTable) do tinsert(allActorTargets, {targetName, damageDone, damageDone / totalDamageWithoutPet * 100}) end table.sort(allActorTargets, Details.Sort2) local enemyAmount = #allActorTargets if (enemyAmount < 1) then return end gump:JI_AtualizaContainerAlvos(enemyAmount) local topDamage = allActorTargets[1] and allActorTargets[1][2] or 0 local barra for index, targetTable in ipairs(allActorTargets) do barra = breakdownWindowFrame.barras2[index] if (not barra) then barra = gump:CriaNovaBarraInfo2(instance, index) barra.textura:SetStatusBarColor(1, 1, 1, 1) end if (index == 1) then barra.textura:SetValue(100) else barra.textura:SetValue(targetTable[2] / topDamage * 100) end local targetName = targetTable[1] local targetActorObject = damageContainer:GetActor(targetName) if (targetActorObject) then local npcId = DetailsFramework:GetNpcIdFromGuid(targetActorObject:GetGUID()) local portraitTexture -- = Details222.Textures.GetPortraitTextureForNpcID(npcId) disabled if (portraitTexture) then Details222.Textures.FormatPortraitAsTexture(portraitTexture, barra.icone) else targetActorObject:SetClassIcon(barra.icone, instance, targetActorObject.classe) end else barra.icone:SetTexture([[Interface\AddOns\Details\images\classes_small_alpha]]) --CLASSE local texCoords = Details.class_coords ["ENEMY"] barra.icone:SetTexCoord(unpack(texCoords)) end barra.textura:SetStatusBarColor(1, 0.8, 0.8) barra.textura:SetStatusBarColor(1, 1, 1, 1) barra.lineText1:SetText(index .. ". " .. Details:GetOnlyName(targetName)) 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]) .. "%)") end if (barra.mouse_over) then --atualizar o tooltip if (barra.isAlvo) then if (not barra.minha_tabela:MontaTooltipAlvos (barra, index, instance)) then return end end end barra.minha_tabela = self --grava o jogador na tabela barra.nome_inimigo = targetTable [1] --salva o nome do inimigo na barra --isso � necess�rio? -- no rank do spell id colocar o que? barra.spellid = targetTable[5] barra:Show() end end end ------ Detalhe Info Friendly Fire function damageClass:MontaDetalhesFriendlyFire (nome, barra) local barras = breakdownWindowFrame.barras3 local instancia = breakdownWindowFrame.instancia 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 local ff_table = self.friendlyfire [nome] --assumindo que nome � o nome do Alvo que tomou dano // bastaria pegar a tabela de habilidades dele if (not ff_table) then return end local total = ff_table.total local minhas_magias = {} for spellid, amount in pairs(ff_table.spells) do --da foreach em cada spellid do container local nome, _, icone = _GetSpellInfo(spellid) tinsert(minhas_magias, {spellid, amount, amount / total * 100, nome, icone}) end _table_sort(minhas_magias, Details.Sort2) local max_ = minhas_magias[1] and minhas_magias[1][2] or 0 --dano que a primeiro magia vez local lastIndex = 1 local barra for index, tabela in ipairs(minhas_magias) do lastIndex = index barra = barras [index] if (not barra) then --se a barra n�o existir, criar ela ent�o barra = gump:CriaNovaBarraInfo3 (instancia, index) barra.textura:SetStatusBarColor(1, 1, 1, 1) --isso aqui � a parte da sele��o e descele��o end barra.show = tabela[1] if (index == 1) then barra.textura:SetValue(100) else barra.textura:SetValue(tabela[2]/max_*100) --muito mais rapido... end barra.lineText1:SetText(index..instancia.divisores.colocacao..tabela[4]) --seta o texto da esqueda barra.lineText4:SetText(Details:comma_value (tabela[2]) .. " " .. instancia.divisores.abre .. format("%.1f", tabela[3]) .. "%" .. instancia.divisores.fecha) --seta o texto da direita barra.icone:SetTexture(tabela[5]) barra.icone:SetTexCoord(0, 1, 0, 1) barra:Show() --mostra a barra if (index == 15) then break end end for i = lastIndex+1, #barras do barras[i]:Hide() end end -- detalhes info enemies function damageClass:MontaDetalhesEnemy (spellid, barra) local container = breakdownWindowFrame.instancia.showing[1] local barras = breakdownWindowFrame.barras3 local instancia = breakdownWindowFrame.instancia local other_actor = barra.other_actor if (other_actor) then self = other_actor end if (barra.lineText1:IsTruncated()) then Details:CooltipPreset(2) GameCooltip:SetOption("FixedWidth", nil) GameCooltip:AddLine(barra.lineText1.text) GameCooltip:SetOwner(barra, "bottomleft", "topleft", 5, -10) GameCooltip:ShowCooltip() end local spell = self.spells:PegaHabilidade (spellid) local targets = spell.targets local target_pool = {} for target_name, amount in pairs(targets) do local classe local this_actor = breakdownWindowFrame.instancia.showing (1, target_name) if (this_actor) then classe = this_actor.classe or "UNKNOW" else classe = "UNKNOW" end target_pool [#target_pool+1] = {target_name, amount, classe} end _table_sort(target_pool, Details.Sort2) local max_ = target_pool [1] and target_pool [1][2] or 0 local lastIndex = 1 local barra for index, tabela in ipairs(target_pool) do lastIndex = index barra = barras [index] if (not barra) then --se a barra n�o existir, criar ela ent�o barra = gump:CriaNovaBarraInfo3 (instancia, index) barra.textura:SetStatusBarColor(1, 1, 1, 1) --isso aqui � a parte da sele��o e descele��o end barra.show = tabela[1] if (index == 1) then barra.textura:SetValue(100) else barra.textura:SetValue(tabela[2]/max_*100) --muito mais rapido... end barra.lineText1:SetText(index .. ". " .. Details:GetOnlyName(tabela [1])) --seta o texto da esqueda Details:name_space_info (barra) if (spell.total > 0) then barra.lineText4:SetText(Details:comma_value (tabela[2]) .." (".. format("%.1f", tabela[2] / spell.total * 100) .."%)") --seta o texto da direita else barra.lineText4:SetText(tabela[2] .." (0%)") --seta o texto da direita end local texCoords = Details.class_coords [tabela[3]] if (not texCoords) then texCoords = Details.class_coords ["UNKNOW"] end local color = Details.class_colors [tabela[3]] if (color) then barra.textura:SetStatusBarColor(unpack(color)) else barra.textura:SetStatusBarColor(1, 1, 1, 1) end barra.icone:SetTexture("Interface\\AddOns\\Details\\images\\classes_small_alpha") barra.icone:SetTexCoord(unpack(texCoords)) barra:Show() --mostra a barra if (index == 15) then break end end for i = lastIndex+1, #barras do barras[i]:Hide() end end ------ Detalhe Info Damage Taken function damageClass:MontaDetalhesDamageTaken (nome, barra) local barras = breakdownWindowFrame.barras3 local instancia = breakdownWindowFrame.instancia 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]] if (not este_agressor ) then return end local conteudo = este_agressor.spells._ActorTable --pairs[] com os IDs das magias local actor = breakdownWindowFrame.jogador.nome local total = este_agressor.targets [actor] or 0 local minhas_magias = {} for spellid, tabela in pairs(conteudo) do --da foreach em cada spellid do container local este_alvo = tabela.targets [actor] if (este_alvo) then --esta magia deu dano no actor local spell_nome, rank, icone = _GetSpellInfo(spellid) tinsert(minhas_magias, {spellid, este_alvo, este_alvo/total*100, spell_nome, icone}) end end _table_sort(minhas_magias, Details.Sort2) --local amt = #minhas_magias --gump:JI_AtualizaContainerBarras (amt) local max_ = minhas_magias[1] and minhas_magias[1][2] or 0 --dano que a primeiro magia vez local lastIndex = 1 local barra for index, tabela in ipairs(minhas_magias) do lastIndex = index barra = barras [index] if (not barra) then --se a barra n�o existir, criar ela ent�o barra = gump:CriaNovaBarraInfo3 (instancia, index) barra.textura:SetStatusBarColor(1, 1, 1, 1) --isso aqui � a parte da sele��o e descele��o end barra.show = tabela[1] if (index == 1) then barra.textura:SetValue(100) else barra.textura:SetValue(tabela[2]/max_*100) end barra.lineText1:SetText(index .. "." .. tabela[4]) --seta o texto da esqueda Details:name_space_info (barra) barra.lineText4:SetText(Details:comma_value (tabela[2]) .." ".. instancia.divisores.abre ..format("%.1f", tabela[3]) .."%".. instancia.divisores.fecha) --seta o texto da direita barra.icone:SetTexture(tabela[5]) barra.icone:SetTexCoord(0, 1, 0, 1) barra:Show() --mostra a barra if (index == 15) then break end end for i = lastIndex+1, #barras do barras[i]:Hide() end end ------ Detalhe Info Damage Done e Dps --local defenses_table = {c = {117/255, 58/255, 0/255}, p = 0} --local normal_table = {c = {255/255, 180/255, 0/255, 0.5}, p = 0} --local critical_table = {c = {249/255, 74/255, 45/255, 0.5}, p = 0} local defenses_table = {c = {1, 1, 1, 0.5}, p = 0} local normal_table = {c = {1, 1, 1, 0.5}, p = 0} local critical_table = {c = {1, 1, 1, 0.5}, p = 0} local data_table = {} local t1, t2, t3, t4 = {}, {}, {}, {} local function FormatSpellString(str) return (string.gsub(str, "%d+", function(spellID) local name, _, icon = GetSpellInfo(spellID); return string.format("|T%s:16|t", icon); end)); end local MontaDetalhesBuffProcs = function(actor, row, instance) instance = instance or breakdownWindowFrame.instancia local spec = actor.spec if (spec) then local mainAuras = Details.important_auras [spec] if (mainAuras) then local miscActor = instance:GetShowingCombat():GetActor(4, actor:name()) if (miscActor and miscActor.buff_uptime_spells) then --get the auras local added = 0 for i = 1, #mainAuras do local spellID = mainAuras [i] local spellObject = miscActor.buff_uptime_spells._ActorTable [spellID] if (spellObject) then local spellName, spellIcon = GetSpellInfo(spellID) local spellUptime = spellObject.uptime local spellApplies = spellObject.appliedamt local spellRefreshes = spellObject.refreshamt gump:SetaDetalheInfoTexto(i, 100, FormatSpellString ("" .. spellID .. " " .. spellName), "Activations: " .. spellApplies, " ", "Refreshes: " .. spellRefreshes, " ", "Uptime: " .. spellUptime .. "s") added = added + 1 end end for i = added + 1, 5 do gump:HidaDetalheInfo (i) end return end end end for i = 1, 5 do gump:HidaDetalheInfo (i) end end ---called from the spell breakdown when a spellbar is hovered over ---@param spellBar breakdownspellbar ---@param spellBlockContainer breakdownspellblockframe ---@param blockIndex number ---@param summaryBlock breakdownspellblock ---@param spellId number ---@param combatTime number ---@param actorName string ---@param spellTable spelltableadv ---@param trinketData trinketdata ---@param combatObject combat function damageClass:BuildSpellDetails(spellBar, spellBlockContainer, blockIndex, summaryBlock, spellId, combatTime, actorName, spellTable, trinketData, combatObject) ---@type number local totalHits = spellTable.counter --damage section showing damage done sub section blockIndex = blockIndex + 1 do --update the texts in the summary block local blockLine1, blockLine2, blockLine3 = summaryBlock:GetLines() local totalCasts = spellBar.amountCasts > 0 and spellBar.amountCasts or "(?)" blockLine1.leftText:SetText(Loc ["STRING_CAST"] .. ": " .. totalCasts) --total amount of casts if (trinketData[spellId] and combatObject.trinketProcs) then local trinketProcData = combatObject.trinketProcs[actorName] if (trinketProcData) then local trinketProc = trinketProcData[spellId] if (trinketProc) then blockLine1.leftText:SetText("Procs: " .. trinketProc.total) end end elseif (Details.GetItemSpellInfo(spellId)) then blockLine1.leftText:SetText("Uses: " .. totalCasts) end blockLine1.rightText:SetText(Loc ["STRING_HITS"]..": " .. totalHits) --hits and uptime blockLine2.leftText:SetText(Loc ["STRING_DAMAGE"]..": " .. Details:Format(spellTable.total)) --total damage blockLine2.rightText:SetText(Details:GetSpellSchoolFormatedName(spellTable.spellschool)) --spell school blockLine3.leftText:SetText(Loc ["STRING_AVERAGE"] .. ": " .. Details:Format(spellBar.average)) --average damage if (spellBar.perSecond and spellBar.perSecond > 0) then blockLine3.rightText:SetText(Loc ["STRING_DPS"] .. ": " .. Details:CommaValue(spellBar.perSecond)) --dps else blockLine3.rightText:SetText(Loc ["STRING_DPS"] .. ": " .. Details:CommaValue(spellTable.total / combatTime)) --dps end end local emporwerSpell = spellTable.e_total if (emporwerSpell) then local empowerLevelSum = spellTable.e_total --total sum of empower levels local empowerAmount = spellTable.e_amt --amount of casts with empower local empowerAmountPerLevel = spellTable.e_lvl --{[1] = 4; [2] = 9; [3] = 15} local empowerDamagePerLevel = spellTable.e_dmg --{[1] = 54548745, [2] = 74548745} ---@type breakdownspellblock local empowerBlock = spellBlockContainer:GetBlock(blockIndex) blockIndex = blockIndex + 1 local level1AverageDamage = "0" local level2AverageDamage = "0" local level3AverageDamage = "0" local level4AverageDamage = "0" local level5AverageDamage = "0" if (empowerDamagePerLevel[1]) then level1AverageDamage = Details:Format(empowerDamagePerLevel[1] / empowerAmountPerLevel[1]) end if (empowerDamagePerLevel[2]) then level2AverageDamage = Details:Format(empowerDamagePerLevel[2] / empowerAmountPerLevel[2]) end if (empowerDamagePerLevel[3]) then level3AverageDamage = Details:Format(empowerDamagePerLevel[3] / empowerAmountPerLevel[3]) end if (empowerDamagePerLevel[4]) then level4AverageDamage = Details:Format(empowerDamagePerLevel[4] / empowerAmountPerLevel[4]) end if (empowerDamagePerLevel[5]) then level5AverageDamage = Details:Format(empowerDamagePerLevel[5] / empowerAmountPerLevel[5]) end empowerBlock:Show() empowerBlock:SetValue(100) empowerBlock.sparkTexture:SetPoint("left", empowerBlock, "left", empowerBlock:GetWidth() + Details.breakdown_spell_tab.blockspell_spark_offset, 0) empowerBlock:SetColor(0.200, 0.576, 0.498, 0.6) local blockLine1, blockLine2, blockLine3 = empowerBlock:GetLines() blockLine1.leftText:SetText("Spell Empower Average Level: " .. string.format("%.2f", empowerLevelSum / empowerAmount)) if (level1AverageDamage ~= "0") then blockLine2.leftText:SetText("#1 Avg: " .. level1AverageDamage .. " (" .. (empowerAmountPerLevel[1] or 0) .. ")") end if (level2AverageDamage ~= "0") then blockLine2.centerText:SetText("#2 Avg: " .. level2AverageDamage .. " (" .. (empowerAmountPerLevel[2] or 0) .. ")") end if (level3AverageDamage ~= "0") then blockLine2.rightText:SetText("#3 Avg: " .. level3AverageDamage .. " (" .. (empowerAmountPerLevel[3] or 0) .. ")") end if (level4AverageDamage ~= "0") then blockLine3.leftText:SetText("#4 Avg: " .. level4AverageDamage .. " (" .. (empowerAmountPerLevel[4] or 0) .. ")") end if (level5AverageDamage ~= "0") then blockLine3.rightText:SetText("#5 Avg: " .. level5AverageDamage .. " (" .. (empowerAmountPerLevel[5] or 0) .. ")") end end --check if there's normal hits and build the block ---@type number local normalHitsAmt = spellTable.n_amt if (normalHitsAmt > 0) then ---@type breakdownspellblock local normalHitsBlock = spellBlockContainer:GetBlock(blockIndex) normalHitsBlock:Show() blockIndex = blockIndex + 1 local percent = normalHitsAmt / math.max(totalHits, 0.0001) * 100 normalHitsBlock:SetValue(percent) normalHitsBlock.sparkTexture:SetPoint("left", normalHitsBlock, "left", percent / 100 * normalHitsBlock:GetWidth() + Details.breakdown_spell_tab.blockspell_spark_offset, 0) local blockLine1, blockLine2, blockLine3 = normalHitsBlock:GetLines() blockLine1.leftText:SetText(Loc ["STRING_NORMAL_HITS"]) blockLine1.rightText:SetText(normalHitsAmt .. " [|cFFC0C0C0" .. string.format("%.1f", normalHitsAmt / math.max(totalHits, 0.0001) * 100) .. "%|r]") blockLine2.leftText:SetText(Loc ["STRING_MINIMUM_SHORT"] .. ": " .. Details:CommaValue(spellTable.n_min)) blockLine2.rightText:SetText(Loc ["STRING_MAXIMUM_SHORT"] .. ": " .. Details:CommaValue(spellTable.n_max)) local normalAverage = spellTable.n_total / math.max(normalHitsAmt, 0.0001) blockLine3.leftText:SetText(Loc ["STRING_AVERAGE"] .. ": " .. Details:CommaValue(normalAverage)) local tempo = (combatTime * spellTable.n_total) / math.max(spellTable.total, 0.001) local normalAveragePercent = spellBar.average / normalAverage * 100 local normalTempoPercent = normalAveragePercent * tempo / 100 blockLine3.rightText:SetText(Loc ["STRING_DPS"] .. ": " .. Details:CommaValue(spellTable.n_total / normalTempoPercent)) end ---@type number local criticalHitsAmt = spellTable.c_amt if (criticalHitsAmt > 0) then ---@type breakdownspellblock local critHitsBlock = spellBlockContainer:GetBlock(blockIndex) critHitsBlock:Show() blockIndex = blockIndex + 1 local percent = Details.SpellTableMixin.GetCritPercent(spellTable) critHitsBlock:SetValue(percent) critHitsBlock.sparkTexture:SetPoint("left", critHitsBlock, "left", percent / 100 * critHitsBlock:GetWidth() + Details.breakdown_spell_tab.blockspell_spark_offset, 0) local blockLine1, blockLine2, blockLine3 = critHitsBlock:GetLines() blockLine1.leftText:SetText(Loc ["STRING_CRITICAL_HITS"]) blockLine1.rightText:SetText(criticalHitsAmt .. " [|cFFC0C0C0" .. string.format("%.1f", criticalHitsAmt / math.max(totalHits, 0.0001) * 100) .. "%|r]") blockLine2.leftText:SetText(Loc ["STRING_MINIMUM_SHORT"] .. ": " .. Details:CommaValue(spellTable.c_min)) blockLine2.rightText:SetText(Loc ["STRING_MAXIMUM_SHORT"] .. ": " .. Details:CommaValue(spellTable.c_max)) local critAverage = Details.SpellTableMixin.GetCritAverage(spellTable) blockLine3.leftText:SetText(Loc ["STRING_AVERAGE"] .. ": " .. Details:CommaValue(critAverage)) local tempo = (combatTime * spellTable.c_total) / math.max(spellTable.total, 0.001) local critAveragePercent = spellBar.average / critAverage * 100 local critTempoPercent = critAveragePercent * tempo / 100 blockLine3.rightText:SetText(Loc ["STRING_DPS"] .. ": " .. Details:CommaValue(spellTable.c_total / critTempoPercent)) end --missing hits local semiDodgeAmount = spellTable.g_amt + spellTable.b_amt --glancing and blocking local fullDodgeAmount = spellTable["DODGE"] or 0 local parryAmount = spellTable["PARRY"] or 0 local missedHitsAmount = spellTable["MISS"] or 0 local hitErrorsAmount = parryAmount + fullDodgeAmount + missedHitsAmount if (semiDodgeAmount > 0 or hitErrorsAmount > 0) then ---@type breakdownspellblock local defensesBlock = spellBlockContainer:GetBlock(blockIndex) defensesBlock:Show() blockIndex = blockIndex + 1 local percent = (semiDodgeAmount + hitErrorsAmount) / spellTable.counter * 100 defensesBlock:SetValue(percent) defensesBlock.sparkTexture:SetPoint("left", defensesBlock, "left", percent / 100 * defensesBlock:GetWidth() + Details.breakdown_spell_tab.blockspell_spark_offset, 0) local blockLine1, blockLine2, blockLine3 = defensesBlock:GetLines() blockLine1.leftText:SetText(Loc ["STRING_DEFENSES"]) blockLine1.rightText:SetText((semiDodgeAmount + hitErrorsAmount) .. " / " .. format("%.1f", percent) .. "%") if (missedHitsAmount > 0) then blockLine2.leftText:SetText("Miss" .. ": " .. missedHitsAmount) end if (parryAmount > 0) then blockLine2.centerText:SetText(Loc ["STRING_PARRY"] .. ": " .. parryAmount) end if (fullDodgeAmount > 0) then blockLine2.rightText:SetText(Loc ["STRING_DODGE"] .. ": " .. fullDodgeAmount) end if (spellTable.b_amt > 0) then blockLine3.leftText:SetText(Loc ["STRING_BLOCKED"] .. ": " .. spellTable.b_amt) end if (spellTable.g_amt > 0) then blockLine3.rightText:SetText(Loc ["STRING_GLANCING"] .. ": " .. spellTable.g_amt) end end --[=[ percent Loc ["STRING_GLANCING"] .. ": " .. math.floor(spellTable.g_amt / spellTable.counter * 100) .. "%" Loc ["STRING_BLOCKED"] .. ": " .. math.floor(spellTable.b_amt / spellTable.counter * 100) .. "%" --]=] if (trinketData[spellId]) then ---@type trinketdata local trinketInfo = trinketData[spellId] local minTime = trinketInfo.minTime local maxTime = trinketInfo.maxTime local average = trinketInfo.averageTime ---@type breakdownspellblock local trinketBlock = spellBlockContainer:GetBlock(blockIndex) trinketBlock:Show() trinketBlock:SetValue(100) trinketBlock.sparkTexture:SetPoint("left", trinketBlock, "left", trinketBlock:GetWidth() + Details.breakdown_spell_tab.blockspell_spark_offset, 0) blockIndex = blockIndex + 1 local blockLine1, blockLine2, blockLine3 = trinketBlock:GetLines() blockLine1.leftText:SetText("Trinket Info") blockLine1.rightText:SetText("PPM: " .. string.format("%.2f", average / 60)) if (minTime == 9999999) then blockLine2.leftText:SetText("Min Time: " .. _G["UNKNOWN"]) else blockLine2.leftText:SetText("Min Time: " .. math.floor(minTime)) end blockLine2.rightText:SetText("Max Time: " .. math.floor(maxTime)) end end --this build p the 6 rectangle boxes in the right side of the breakdown window summary tab function damageClass:MontaDetalhesDamageDone (spellId, spellLine, instance) --this should be ~deprecated with the new breakdown tab print("MontaDetalhesDamageDone - deprecated", debugstack()) local spellTable if (spellLine.other_actor) then spellTable = spellLine.other_actor.spells._ActorTable [spellId] --self = spellLine.other_actor else spellTable = self.spells._ActorTable [spellId] end if (spellId == -51) then return MontaDetalhesBuffProcs(self, spellLine, instance) end if (not spellTable) then return end local spellName, _, icone = _GetSpellInfo(spellId) local bShouldMergePlayerAbilities = Details.merge_player_abilities local bShouldMergePetAbilities = Details.merge_pet_abilities if (bShouldMergePlayerAbilities or bShouldMergePetAbilities) then local mergedSpellTable = getSpellDetails(self:GetGUID(), spellName) --it's not merging if (mergedSpellTable) then spellTable = mergedSpellTable end end Details.BreakdownWindowFrame.spell_icone:SetTexture(icone) local total = self.total local meu_tempo if (Details.time_type == 1 or not self.grupo) then meu_tempo = self:Tempo() elseif (Details.time_type == 2 or Details.use_realtimedps) then meu_tempo = breakdownWindowFrame.instancia.showing:GetCombatTime() end local total_hits = spellTable.counter local index = 1 local data = data_table Details:Destroy(t1) Details:Destroy(t2) Details:Destroy(t3) Details:Destroy(t4) Details:Destroy(data) --GERAL local media = 0 if (total_hits > 0) then media = spellTable.total/total_hits end local this_dps = nil if (spellTable.counter > spellTable.c_amt) then this_dps = Loc ["STRING_DPS"] .. ": " .. Details:comma_value (spellTable.total/meu_tempo) else this_dps = Loc ["STRING_DPS"] .. ": " .. Loc ["STRING_SEE_BELOW"] end local spellschool, schooltext = spellTable.spellschool, "" if (spellschool) then local t = Details.spells_school [spellschool] if (t and t.name) then schooltext = t.formated end end local hits_string = "" .. total_hits local cast_string = Loc ["STRING_CAST"] .. ": " 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 / breakdownWindowFrame.instancia.showing:GetCombatTime() * 100) .. "% uptime)|r" end local amountOfCasts = breakdownWindowFrame.instancia.showing:GetSpellCastAmount(self:Name(), spellName) if (amountOfCasts == 0) then amountOfCasts = "(|cFFFFFF00?|r)" end cast_string = cast_string .. amountOfCasts end if (spellTable.e_total) then cast_string = Loc ["STRING_CAST"] .. ": " .. "|cFFFFFF00" .. spellTable.e_total .. "|r" end gump:SetaDetalheInfoTexto( index, 100, cast_string, Loc ["STRING_DAMAGE"]..": "..Details:ToK(spellTable.total), schooltext, --offhand, Loc ["STRING_AVERAGE"] .. ": " .. Details:comma_value (media), this_dps, Loc ["STRING_HITS"]..": " .. hits_string ) --NORMAL local normal_hits = spellTable.n_amt if (normal_hits > 0) then local normal_dmg = spellTable.n_total local media_normal = normal_dmg/normal_hits local T = (meu_tempo*normal_dmg)/ max(spellTable.total, 0.001) local P = media/media_normal*100 T = P*T/100 normal_table.p = normal_hits/total_hits*100 data[#data+1] = t1 t1[1] = spellTable.n_amt t1[2] = normal_table t1[3] = Loc ["STRING_NORMAL_HITS"] t1[4] = Loc ["STRING_MINIMUM_SHORT"] .. ": " .. Details:comma_value (spellTable.n_min) t1[5] = Loc ["STRING_MAXIMUM_SHORT"] .. ": " .. Details:comma_value (spellTable.n_max) t1[6] = Loc ["STRING_AVERAGE"] .. ": " .. Details:comma_value (media_normal) t1[7] = Loc ["STRING_DPS"] .. ": " .. Details:comma_value (normal_dmg/T) t1[8] = normal_hits .. " [|cFFC0C0C0" .. format("%.1f", normal_hits/max(total_hits, 0.0001)*100) .. "%|r]" t1[9] = "" end --CRITICO if (spellTable.c_amt > 0) then local media_critico = spellTable.c_total/spellTable.c_amt local T = (meu_tempo*spellTable.c_total)/spellTable.total local P = media/max(media_critico, 0.0001)*100 T = P*T/100 local crit_dps = spellTable.c_total/T if (not crit_dps) then crit_dps = 0 end critical_table.p = spellTable.c_amt/total_hits*100 data[#data+1] = t2 t2[1] = spellTable.c_amt t2[2] = critical_table t2[3] = Loc ["STRING_CRITICAL_HITS"] t2[4] = Loc ["STRING_MINIMUM_SHORT"] .. ": " .. Details:comma_value (spellTable.c_min) t2[5] = Loc ["STRING_MAXIMUM_SHORT"] .. ": " .. Details:comma_value (spellTable.c_max) t2[6] = Loc ["STRING_AVERAGE"] .. ": " .. Details:comma_value (media_critico) t2[7] = Loc ["STRING_DPS"] .. ": " .. Details:comma_value (crit_dps) t2[8] = spellTable.c_amt .. " [|cFFC0C0C0" .. format("%.1f", spellTable.c_amt/total_hits*100) .. "%|r]" t2[9] = "" end --Outros erros: GLACING, resisted, blocked, absorbed local outros_desvios = spellTable.g_amt + spellTable.b_amt local parry = spellTable ["PARRY"] or 0 local dodge = spellTable ["DODGE"] or 0 local misses = spellTable ["MISS"] or 0 local erros = parry + dodge + misses if (outros_desvios > 0 or erros > 0) then local porcentagem_defesas = (outros_desvios + erros) / total_hits * 100 data[#data+1] = t3 defenses_table.p = porcentagem_defesas t3[1] = outros_desvios+erros t3[2] = defenses_table t3[3] = Loc ["STRING_DEFENSES"] t3[4] = Loc ["STRING_GLANCING"] .. ": " .. _math_floor(spellTable.g_amt/spellTable.counter*100) .. "%" t3[5] = Loc ["STRING_PARRY"] .. ": " .. parry t3[6] = Loc ["STRING_DODGE"] .. ": " .. dodge t3[7] = Loc ["STRING_BLOCKED"] .. ": " .. _math_floor(spellTable.b_amt/spellTable.counter*100) t3[8] = (outros_desvios+erros) .. " / " .. format("%.1f", porcentagem_defesas) .. "%" t3[9] = "MISS" .. ": " .. misses end --~empowered if (spellTable.e_total) then local empowerLevelSum = spellTable.e_total --total sum of empower levels local empowerAmount = spellTable.e_amt --amount of casts with empower local empowerAmountPerLevel = spellTable.e_lvl --{[1] = 4; [2] = 9; [3] = 15} local empowerDamagePerLevel = spellTable.e_dmg --{[1] = 54548745, [2] = 74548745} data[#data+1] = t4 local level1AverageDamage = "0" local level2AverageDamage = "0" local level3AverageDamage = "0" local level4AverageDamage = "0" local level5AverageDamage = "0" if (empowerDamagePerLevel[1]) then level1AverageDamage = Details:ToK(empowerDamagePerLevel[1] / empowerAmountPerLevel[1]) end if (empowerDamagePerLevel[2]) then level2AverageDamage = Details:ToK(empowerDamagePerLevel[2] / empowerAmountPerLevel[2]) end if (empowerDamagePerLevel[3]) then level3AverageDamage = Details:ToK(empowerDamagePerLevel[3] / empowerAmountPerLevel[3]) end if (empowerDamagePerLevel[4]) then level4AverageDamage = Details:ToK(empowerDamagePerLevel[4] / empowerAmountPerLevel[4]) end if (empowerDamagePerLevel[5]) then level5AverageDamage = Details:ToK(empowerDamagePerLevel[5] / empowerAmountPerLevel[5]) end t4[1] = 0 t4[2] = {p = 100, c = {0.200, 0.576, 0.498, 0.6}} t4[3] = "Spell Empower Average Level: " .. format("%.2f", empowerLevelSum / empowerAmount) t4[4] = "" t4[5] = "" t4[6] = "" t4[10] = "" t4[11] = "" if (level1AverageDamage ~= "0") then t4[4] = "Level 1 Avg: " .. level1AverageDamage .. " (" .. (empowerAmountPerLevel[1] or 0) .. ")" end if (level2AverageDamage ~= "0") then t4[6] = "Level 2 Avg: " .. level2AverageDamage .. " (" .. (empowerAmountPerLevel[2] or 0) .. ")" end if (level3AverageDamage ~= "0") then t4[11] = "Level 3 Avg: " .. level3AverageDamage .. " (" .. (empowerAmountPerLevel[3] or 0) .. ")" end if (level4AverageDamage ~= "0") then t4[10] = "Level 4 Avg: " .. level4AverageDamage .. " (" .. (empowerAmountPerLevel[4] or 0) .. ")" end if (level5AverageDamage ~= "0") then t4[5] = "Level 5 Avg: " .. level5AverageDamage .. " (" .. (empowerAmountPerLevel[5] or 0) .. ")" end end --Details:BuildPlayerDetailsSpellChart() --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 local spellTable = spellTable local blockId = 6 if false then --debug the stuff for the chart damage done in the 6th spellblock --GetBlockIndex doesn't exists anymore 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, 5 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() 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]:SetAlpha(0.46) thatRectangle66.bloodLustIndicators[i]:SetSize(bloodlustDuration / combatTime * width, height - 2) thatRectangle66.bloodLustIndicators[i]:SetPoint("bottomleft", thatRectangle66, "bottomleft", 0, 0) end end DetailsBreakdownWindow_DetalheInfoBG_bg_end6:Hide() thatRectangle66:SetShown(true) end end _table_sort(data, Details.Sort1) for index, tabela in ipairs(data) do gump:SetaDetalheInfoTexto(index+1, tabela[2], tabela[3], tabela[4], tabela[5], tabela[6], tabela[7], tabela[8], tabela[9], tabela[10], tabela[11], tabela[12]) end for i = #data+2, 5 do gump:HidaDetalheInfo(i) end end function Details:BuildPlayerDetailsSpellChart() local playerDetailSmallChart = DetailsPlayerDetailSmallChart if (not playerDetailSmallChart) then playerDetailSmallChart = CreateFrame("frame", "DetailsPlayerDetailSmallChart", breakdownWindowFrame,"BackdropTemplate") DetailsFramework:ApplyStandardBackdrop(playerDetailSmallChart) playerDetailSmallChart.Lines = {} for i = 1, 200 do local texture = playerDetailSmallChart:CreateTexture(nil, "artwork") texture:SetColorTexture(1, 1, 1, 1) tinsert(playerDetailSmallChart.Lines, texture) end --Details.BreakdownWindowFrame.grupos_detalhes [index] function playerDetailSmallChart.ShowChart (parent, combatObject, cleuData, playerName, targetName, spellId, ...) local tokenIdList = {} local eventList = {} --build the list of tokens for i = 1, select("#", ... ) do local tokenId = select(i, ...) tokenIdList [tokenId] = true end --check which lines can be added local index = 1 local peakValue = 0 for i = 1, cleuData.n -1 do local event = cleuData [i] if (event [2]) then --index 2 = token local playerNameFilter = playerName and playerName == event [3] local targetNameFilter = targetName and targetName == event [4] local spellIdFilter = spellId and spellId == event [5] if (playerNameFilter or targetNameFilter or spellIdFilter) then eventList [index] = cleuData [i] if (peakValue < cleuData [i] [6]) then peakValue = cleuData [i] [6] end index = index + 1 end end end --200 lines, adjust the mini chart playerDetailSmallChart:SetPoint("topleft", parent, "topleft") playerDetailSmallChart:SetPoint("bottomright", parent, "bottomright") --update lines local width = playerDetailSmallChart:GetWidth() local combatTime = combatObject:GetCombatTime() local secondsPerBar = combatTime / 200 local barWidth = width / 200 local barHeight = playerDetailSmallChart:GetHeight() local currentTime = eventList [1][1] local currentIndex = 1 local eventAmount = #eventList for i = 1, #playerDetailSmallChart.Lines do playerDetailSmallChart.Lines [i]:SetWidth(width / 200) playerDetailSmallChart.Lines [i]:SetHeight(1) for o = currentIndex, eventAmount do if (eventList [o][1] <= currentTime + secondsPerBar or eventList [o][1] >= currentTime) then playerDetailSmallChart.Lines [i]:SetPoint("bottomleft", playerDetailSmallChart, "bottomleft", barWidth * (i - 1), 0) playerDetailSmallChart.Lines [i]:SetWidth(barWidth) playerDetailSmallChart.Lines [i]:SetHeight(eventList [o][6] / peakValue * barHeight) else currentIndex = o break end end currentTime = currentTime + secondsPerBar end end end end function damageClass:MontaTooltipDamageTaken (thisLine, index) local aggressor = breakdownWindowFrame.instancia.showing [1]:PegarCombatente (_, thisLine.nome_inimigo) local container = aggressor.spells._ActorTable local habilidades = {} local total = 0 for spellid, spell in pairs(container) do for target_name, amount in pairs(spell.targets) do if (target_name == self.nome) then total = total + amount habilidades [#habilidades+1] = {spellid, amount} end end end _table_sort(habilidades, Details.Sort2) GameTooltip:AddLine(index..". "..thisLine.nome_inimigo) GameTooltip:AddLine(Loc ["STRING_DAMAGE_TAKEN_FROM2"]..":") GameTooltip:AddLine(" ") for index, tabela in ipairs(habilidades) do local nome, _, icone = _GetSpellInfo(tabela[1]) if (index < 8) then GameTooltip:AddDoubleLine (index..". |T"..icone..":0|t "..nome, Details:comma_value (tabela[2]).." ("..format("%.1f", tabela[2]/total*100).."%)", 1, 1, 1, 1, 1, 1) else GameTooltip:AddDoubleLine (index..". "..nome, Details:comma_value (tabela[2]).." ("..format("%.1f", tabela[2]/total*100).."%)", .65, .65, .65, .65, .65, .65) end end return true --GameTooltip:AddDoubleLine (meus_danos[i][4][1]..": ", meus_danos[i][2].." (".._cstr("%.1f", meus_danos[i][3]).."%)", 1, 1, 1, 1, 1, 1) end function damageClass:MontaTooltipAlvos (thisLine, index, instancia) --~deprecated local inimigo = thisLine.nome_inimigo local habilidades = {} local total = self.total local i = 1 Details:FormatCooltipForSpells() GameCooltip:SetOwner(thisLine, "bottom", "top", 4, -2) GameCooltip:SetOption("MinWidth", _math_max (230, thisLine:GetWidth()*0.98)) for spellid, spell in pairs(self.spells._ActorTable) do if (spell.isReflection) then for target_name, amount in pairs(spell.targets) do if (target_name == inimigo) then for reflectedSpellId, amount in pairs(spell.extra) do local spellName, _, spellIcon = _GetSpellInfo(reflectedSpellId) local t = habilidades [i] if (not t) then habilidades [i] = {} t = habilidades [i] end t[1], t[2], t[3] = spellName .. " (|cFFCCBBBBreflected|r)", amount, spellIcon i = i + 1 end end end else for target_name, amount in pairs(spell.targets) do if (target_name == inimigo) then local nome, _, icone = _GetSpellInfo(spellid) local t = habilidades [i] if (not t) then habilidades [i] = {} t = habilidades [i] end t[1], t[2], t[3] = nome, amount, icone i = i + 1 end end end end --add pets for _, PetName in ipairs(self.pets) do local PetActor = instancia.showing (class_type, PetName) if (PetActor) then local PetSkillsContainer = PetActor.spells._ActorTable for _spellid, _skill in pairs(PetSkillsContainer) do local alvos = _skill.targets for target_name, amount in pairs(alvos) do if (target_name == inimigo) then local t = habilidades [i] if (not t) then habilidades [i] = {} t = habilidades [i] end local nome, _, icone = _GetSpellInfo(_spellid) t[1], t[2], t[3] = nome .. " (" .. PetName:gsub((" <.*"), "") .. ")", amount, icone i = i + 1 end end end end end _table_sort(habilidades, Details.Sort2) --get time type local meu_tempo if (Details.time_type == 1 or not self.grupo) then meu_tempo = self:Tempo() elseif (Details.time_type == 2 or Details.use_realtimedps) then meu_tempo = breakdownWindowFrame.instancia.showing:GetCombatTime() end 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)) Details:AddTooltipHeaderStatusbar (1, 1, 1, 1) else Details:AddTooltipSpellHeaderText (Loc ["STRING_DAMAGE_FROM"] .. ":", {1, 0.9, 0.0, 1}, 1, Details.tooltip_spell_icon.file, unpack(Details.tooltip_spell_icon.coords)) Details:AddTooltipHeaderStatusbar (1, 1, 1, 1) end local icon_size = Details.tooltip.icon_size local icon_border = Details.tooltip.icon_border_texcoord local topSpellDamage = habilidades[1] and habilidades[1][2] if (topSpellDamage) then for index, tabela in ipairs(habilidades) do if (tabela [2] < 1) then break end if (is_dps) then --GameCooltip:AddDoubleLine (index..". |T"..tabela[3]..":0|t "..tabela[1], Details:comma_value ( _math_floor(tabela[2] / meu_tempo) ).." (".._cstr("%.1f", tabela[2]/total*100).."%)", 1, 1, 1, 1, 1, 1) GameCooltip:AddLine(tabela[1], Details:comma_value ( _math_floor(tabela[2] / meu_tempo) ).." ("..format("%.1f", tabela[2]/total*100).."%)") else --GameCooltip:AddDoubleLine (index..". |T"..tabela[3]..":0|t " .. tabela[1], SelectedToKFunction(_, tabela[2]) .. " (".._cstr("%.1f", tabela[2]/total*100).."%)", 1, 1, 1, 1, 1, 1) GameCooltip:AddLine(tabela[1], SelectedToKFunction(_, tabela[2]) .. " ("..format("%.1f", tabela[2]/total*100).."%)") end GameCooltip:AddIcon (tabela[3], nil, nil, icon_size.W + 4, icon_size.H + 4, icon_border.L, icon_border.R, icon_border.T, icon_border.B) Details:AddTooltipBackgroundStatusbar (false, tabela[2] / topSpellDamage * 100) end end GameCooltip:Show() return true end --controls the activity time of the actor function damageClass:GetOrChangeActivityStatus(activityStatus) if (activityStatus == nil) then --if no value passed, return the current activity status return self.dps_started elseif (activityStatus) then self.dps_started = true Details222.TimeMachine.AddActor(self) else self.dps_started = false Details222.TimeMachine.RemoveActor(self) end end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --core functions --clear cache tables when resetting data function damageClass:ClearCacheTables() for i = #ntable, 1, -1 do ntable [i] = nil end for i = #vtable, 1, -1 do vtable [i] = nil end for i = #bs_table, 1, -1 do bs_table [i] = nil end if (bs_tooltip_table) then Details:Destroy(bs_tooltip_table) end if (frags_tooltip_table) then Details:Destroy(frags_tooltip_table) end Details:Destroy(bs_index_table) Details:Destroy(tooltip_temp_table) Details:Destroy(tooltip_void_zone_temp) end --atualize a funcao de abreviacao function damageClass:UpdateSelectedToKFunction() SelectedToKFunction = ToKFunctions [Details.ps_abbreviation] FormatTooltipNumber = ToKFunctions [Details.tooltip.abbreviation] TooltipMaximizedMethod = Details.tooltip.maximize_method headerColor = Details.tooltip.header_text_color end --diminui o total das tabelas do combate function damageClass:subtract_total (combat_table) combat_table.totals [class_type] = combat_table.totals [class_type] - self.total if (self.grupo) then combat_table.totals_grupo [class_type] = combat_table.totals_grupo [class_type] - self.total end end function damageClass:add_total (combat_table) combat_table.totals [class_type] = combat_table.totals [class_type] + self.total if (self.grupo) then combat_table.totals_grupo [class_type] = combat_table.totals_grupo [class_type] + self.total end end ---sum the passed actor into a combat, if the combat isn't passed, it will use the overall combat ---the function returns the actor that was created of found in the combat passed ---@param actorObject actor ---@param bRefreshActor boolean|nil ---@param combatObject combat|nil ---@return actor function damageClass:AddToCombat(actorObject, bRefreshActor, combatObject) --check if there's a custom combat, if not just use the overall container combatObject = combatObject or Details.tabela_overall --same as Details:GetCombat(DETAILS_SEGMENTID_OVERALL) --check if the combatObject has an actor with the same name, if not, just create one new local actorContainer = combatObject[DETAILS_ATTRIBUTE_DAMAGE] --same as combatObject:GetContainer(DETAILS_ATTRIBUTE_DAMAGE) local overallActor = actorContainer._ActorTable[actorContainer._NameIndexTable[actorObject.nome]] --same as actorContainer:GetActor(actorObject:Name()) if (not overallActor) then overallActor = actorContainer:GetOrCreateActor(actorObject.serial, actorObject.nome, actorObject.flag_original, true) overallActor.classe = actorObject.classe overallActor:SetSpecId(actorObject.spec) overallActor.isTank = actorObject.isTank overallActor.pvp = actorObject.pvp overallActor.boss = actorObject.boss overallActor.start_time = time() - 3 overallActor.end_time = time() end overallActor.displayName = actorObject.displayName or actorObject.nome overallActor.boss_fight_component = actorObject.boss_fight_component or overallActor.boss_fight_component overallActor.fight_component = actorObject.fight_component or overallActor.fight_component overallActor.grupo = actorObject.grupo or overallActor.grupo --check if need to restore meta tables and indexes for this actor if (bRefreshActor) then --this call will reenable the metatable, __index and set the metatable on the .spells container Details.refresh:r_atributo_damage(actorObject) end --elapsed time local endTime = actorObject.end_time if (not actorObject.end_time) then endTime = time() end local tempo = endTime - actorObject.start_time overallActor.start_time = overallActor.start_time - tempo --pets (add unique pet names) for _, petName in ipairs(actorObject.pets) do --same as actorObject:GetPets() DetailsFramework.table.addunique(overallActor.pets, petName) end ---@cast actorObject actordamage --sum total damage overallActor.total = overallActor.total + actorObject.total overallActor.total_extra = overallActor.total_extra + actorObject.total_extra overallActor.totalabsorbed = overallActor.totalabsorbed + actorObject.totalabsorbed --sum total damage without pet overallActor.total_without_pet = overallActor.total_without_pet + actorObject.total_without_pet --sum total damage taken overallActor.damage_taken = overallActor.damage_taken + actorObject.damage_taken --sum friendly fire overallActor.friendlyfire_total = overallActor.friendlyfire_total + actorObject.friendlyfire_total --sum total damage on the combatObject passed combatObject.totals[1] = combatObject.totals[1] + actorObject.total if (actorObject.grupo) then combatObject.totals_grupo[1] = combatObject.totals_grupo[1] + actorObject.total end --copy damage taken from for aggressorName, _ in pairs(actorObject.damage_from) do overallActor.damage_from[aggressorName] = true end --copy targets for targetName, amount in pairs(actorObject.targets) do overallActor.targets[targetName] = (overallActor.targets[targetName] or 0) + amount end --copy raid targets for flag, amount in pairs(actorObject.raid_targets) do overallActor.raid_targets = overallActor.raid_targets or {} overallActor.raid_targets[flag] = (overallActor.raid_targets[flag] or 0) + amount end ---@type spellcontainer local overallSpellsContainer = overallActor.spells --same as overallActor:GetSpellContainer("spell") --copy spell table for spellId, spellTable in pairs(actorObject.spells._ActorTable) do --same as overallSpellsContainer:GetRawSpellTable() --var name has 'overall' but this function accepts any combat table local overallSpellTable = overallSpellsContainer:GetOrCreateSpell(spellId, true) --sum spell targets for targetName, amount in pairs(spellTable.targets) do overallSpellTable.targets[targetName] = (overallSpellTable.targets[targetName] or 0) + amount end --refresh and add extra values for extraSpellId, amount in pairs(spellTable.extra) do overallSpellTable.extra[extraSpellId] = (overallSpellTable.extra[extraSpellId] or 0) + amount end overallSpellTable.spellschool = spellTable.spellschool --sum all values of the spelltable which can be summed for key, value in pairs(spellTable) do if (type(value) == "number") then if (key ~= "id" and key ~= "spellschool") then if (not overallSpellTable [key]) then overallSpellTable [key] = 0 end if (key == "n_min" or key == "c_min") then if (overallSpellTable [key] > value) then overallSpellTable [key] = value end elseif (key == "n_max" or key == "c_max") then if (overallSpellTable [key] < value) then overallSpellTable [key] = value end else overallSpellTable [key] = overallSpellTable [key] + value end end --empowered spells elseif(key == "e_dmg" or key == "e_lvl") then if (not overallSpellTable[key]) then overallSpellTable[key] = {} end for empowermentLevel, empowermentValue in pairs(spellTable[key]) do overallSpellTable[key][empowermentLevel] = empowermentValue end end end end if (actorObject.augmentedSpellsContainer) then local overallAugmentedSpellsContainer = overallActor.augmentedSpellsContainer or spellContainerClass:CreateSpellContainer(Details.container_type.CONTAINER_DAMAGE_CLASS) overallActor.augmentedSpellsContainer = overallAugmentedSpellsContainer for spellId, spellTable in pairs(actorObject.augmentedSpellsContainer._ActorTable) do --same as actorObject.augmentedSpellsContainer:GetRawSpellTable() local overallSpellTable = overallAugmentedSpellsContainer:GetOrCreateSpell(spellId, true) overallSpellTable.total = overallSpellTable.total + spellTable.total for targetName, amount in pairs(spellTable.targets) do overallSpellTable.targets[targetName] = (overallSpellTable.targets[targetName] or 0) + amount end end end --copy the friendly fire container for targetName, friendlyFireTable in pairs(actorObject.friendlyfire) do --get or create the friendly fire table in the overall data local friendlyFireOverall = overallActor.friendlyfire[targetName] or overallActor:CreateFFTable(targetName) --sum the total friendlyFireOverall.total = friendlyFireOverall.total + friendlyFireTable.total --sum spells for friendlyFireSpellId, amount in pairs(friendlyFireTable.spells) do friendlyFireOverall.spells[friendlyFireSpellId] = (friendlyFireOverall.spells[friendlyFireSpellId] or 0) + amount end end return overallActor end --actor 1 is who will receive the sum from actor2 function Details.SumDamageActors(actor1, actor2, actorContainer) --not called anywhere, can be deprecated --general actor1.total = actor1.total + actor2.total actor1.damage_taken = actor1.damage_taken + actor2.damage_taken actor1.totalabsorbed = actor1.totalabsorbed + actor2.totalabsorbed actor1.total_without_pet = actor1.total_without_pet + actor2.total_without_pet actor1.friendlyfire_total = actor1.friendlyfire_total + actor2.friendlyfire_total --damage taken from for actorName in pairs(actor2.damage_from) do actor1.damage_from[actorName] = true --add the damage done to actor2 into the damage done to target1 if (actorContainer) then --get the actor that caused the damage on actor2 local actorObject = actorContainer:GetActor(actorName) if (actorObject) then local damageToActor2 = (actorObject.targets[actor2.nome]) or 0 actorObject.targets[actor1.nome] = (actorObject.targets[actor1.nome] or 0) + damageToActor2 end end end --targets for actorName, damageDone in pairs(actor2.targets) do actor1.targets[actorName] = (actor1.targets[actorName] or 0) + damageDone end --pets for i = 1, #actor2.pets do DetailsFramework.table.addunique(actor1.pets, actor2.pets[i]) end --raid targets for raidTargetFlag, damageDone in pairs(actor2.raid_targets) do actor1.raid_targets[raidTargetFlag] = (actor1.raid_targets[raidTargetFlag] or 0) + damageDone end --friendly fire for actorName, ffTable in pairs(actor2.friendlyfire) do actor1.friendlyfire[actorName] = actor1.friendlyfire[actorName] or actor1:CreateFFTable(actorName) actor1.friendlyfire[actorName].total = actor1.friendlyfire[actorName].total + ffTable.total for spellId, damageDone in pairs(ffTable.spells) do actor1.friendlyfire[actorName].spells[spellId] = (actor1.friendlyfire[actorName].spells[spellId] or 0) + damageDone end end --spells local ignoredKeys = { id = true, spellschool = true, } local actor1Spells = actor1.spells for spellId, spellTable in pairs(actor2.spells._ActorTable) do local actor1Spell = actor1Spells:GetOrCreateSpell(spellId, true, "DAMAGE_DONE") --genetal spell attributes for key, value in pairs(spellTable) do if (type(value) == "number") then if (not ignoredKeys[key]) then if (key == "n_min" or key == "c_min") then if (actor1Spell[key] > value) then actor1Spell[key] = value end elseif (key == "n_max" or key == "c_max") then if (actor1Spell[key] < value) then actor1Spell[key] = value end else actor1Spell[key] = actor1Spell[key] + value end end end end --spell targets for targetName, damageDone in pairs(spellTable) do actor1Spell.targets[targetName] = (actor1Spell.targets[targetName] or 0) + damageDone end end end damageClass.__add = function(tabela1, tabela2) --tempo decorrido local tempo = (tabela2.end_time or time()) - tabela2.start_time tabela1.start_time = tabela1.start_time - tempo --total de dano tabela1.total = tabela1.total + tabela2.total tabela1.totalabsorbed = tabela1.totalabsorbed + tabela2.totalabsorbed --total de dano sem o pet tabela1.total_without_pet = tabela1.total_without_pet + tabela2.total_without_pet --total de dano que o cara levou tabela1.damage_taken = tabela1.damage_taken + tabela2.damage_taken --total do friendly fire causado tabela1.friendlyfire_total = tabela1.friendlyfire_total + tabela2.friendlyfire_total --soma o damage_from for nome, _ in pairs(tabela2.damage_from) do tabela1.damage_from [nome] = true end --pets (add unique pet names) for _, petName in ipairs(tabela2.pets) do local hasPet = false for i = 1, #tabela1.pets do if (tabela1.pets[i] == petName) then hasPet = true break end end if (not hasPet) then tabela1.pets [#tabela1.pets+1] = petName end end --soma os containers de alvos for target_name, amount in pairs(tabela2.targets) do tabela1.targets [target_name] = (tabela1.targets [target_name] or 0) + amount end --soma o container de raid targets for flag, amount in pairs(tabela2.raid_targets) do tabela1.raid_targets [flag] = (tabela1.raid_targets [flag] or 0) + amount end --soma o container de habilidades for spellid, habilidade in pairs(tabela2.spells._ActorTable) do --pega a habilidade no primeiro ator local habilidade_tabela1 = tabela1.spells:PegaHabilidade (spellid, true, "SPELL_DAMAGE", false) --soma os alvos for target_name, amount in pairs(habilidade.targets) do habilidade_tabela1.targets[target_name] = (habilidade_tabela1.targets [target_name] or 0) + amount end --soma os extras for spellId, amount in pairs(habilidade.extra) do habilidade_tabela1.extra = (habilidade_tabela1.extra [spellId] or 0) + amount end --soma os valores da habilidade for key, value in pairs(habilidade) do if (type(value) == "number") then if (key ~= "id" and key ~= "spellschool") then if (not habilidade_tabela1 [key]) then habilidade_tabela1 [key] = 0 end if (key == "n_min" or key == "c_min") then if (habilidade_tabela1 [key] > value) then habilidade_tabela1 [key] = value end elseif (key == "n_max" or key == "c_max") then if (habilidade_tabela1 [key] < value) then habilidade_tabela1 [key] = value end else habilidade_tabela1 [key] = habilidade_tabela1 [key] + value end end elseif(key == "e_dmg" or key == "e_lvl") then if (not habilidade_tabela1[key]) then habilidade_tabela1[key] = {} end for empowermentLevel, empowermentValue in pairs(habilidade[key]) do habilidade_tabela1[key][empowermentLevel] = habilidade_tabela1[key][empowermentValue] or 0 + empowermentValue end end end end --soma o container de friendly fire for target_name, ff_table in pairs(tabela2.friendlyfire) do --pega o ator ff no ator principal local friendlyFire_tabela1 = tabela1.friendlyfire [target_name] or tabela1:CreateFFTable (target_name) --soma o total friendlyFire_tabela1.total = friendlyFire_tabela1.total + ff_table.total --soma as habilidades for spellid, amount in pairs(ff_table.spells) do friendlyFire_tabela1.spells [spellid] = (friendlyFire_tabela1.spells [spellid] or 0) + amount end end return tabela1 end damageClass.__sub = function(tabela1, tabela2) --tempo decorrido local tempo = (tabela2.end_time or time()) - tabela2.start_time tabela1.start_time = tabela1.start_time + tempo --total de dano tabela1.total = tabela1.total - tabela2.total tabela1.totalabsorbed = tabela1.totalabsorbed - tabela2.totalabsorbed --total de dano sem o pet tabela1.total_without_pet = tabela1.total_without_pet - tabela2.total_without_pet --total de dano que o cara levou tabela1.damage_taken = tabela1.damage_taken - tabela2.damage_taken --total do friendly fire causado tabela1.friendlyfire_total = tabela1.friendlyfire_total - tabela2.friendlyfire_total --reduz os containers de alvos for target_name, amount in pairs(tabela2.targets) do local alvo_tabela1 = tabela1.targets [target_name] if (alvo_tabela1) then tabela1.targets [target_name] = tabela1.targets [target_name] - amount end end --reduz o container de raid targets for flag, amount in pairs(tabela2.raid_targets) do if (tabela1.raid_targets [flag]) then tabela1.raid_targets [flag] = _math_max (tabela1.raid_targets [flag] - amount, 0) end end --reduz o container de habilidades for spellid, habilidade in pairs(tabela2.spells._ActorTable) do --get the spell from the first actor local habilidade_tabela1 = tabela1.spells:PegaHabilidade (spellid, true, "SPELL_DAMAGE", false) --subtract targets for target_name, amount in pairs(habilidade.targets) do local alvo_tabela1 = habilidade_tabela1.targets [target_name] if (alvo_tabela1) then habilidade_tabela1.targets [target_name] = habilidade_tabela1.targets [target_name] - amount end end --subtract extra table for spellId, amount in pairs(habilidade.extra) do local extra_tabela1 = habilidade_tabela1.extra [spellId] if (extra_tabela1) then habilidade_tabela1.extra [spellId] = habilidade_tabela1.extra [spellId] - amount end end --subtrai os valores da habilidade for key, value in pairs(habilidade) do if (type(value) == "number") then if (key ~= "id" and key ~= "spellschool") then if (not habilidade_tabela1 [key]) then habilidade_tabela1 [key] = 0 end if (key == "n_min" or key == "c_min") then if (habilidade_tabela1 [key] > value) then habilidade_tabela1 [key] = value end elseif (key == "n_max" or key == "c_max") then if (habilidade_tabela1 [key] < value) then habilidade_tabela1 [key] = value end else habilidade_tabela1 [key] = habilidade_tabela1 [key] - value end end end end end --reduz o container de friendly fire for target_name, ff_table in pairs(tabela2.friendlyfire) do --pega o ator ff no ator principal local friendlyFire_tabela1 = tabela1.friendlyfire [target_name] if (friendlyFire_tabela1) then friendlyFire_tabela1.total = friendlyFire_tabela1.total - ff_table.total for spellid, amount in pairs(ff_table.spells) do if (friendlyFire_tabela1.spells [spellid]) then friendlyFire_tabela1.spells [spellid] = friendlyFire_tabela1.spells [spellid] - amount end end end end return tabela1 end function Details.refresh:r_atributo_damage(actorObject) detailsFramework:Mixin(actorObject, Details222.Mixins.ActorMixin) detailsFramework:Mixin(actorObject, damageClassMixin) setmetatable(actorObject, Details.atributo_damage) actorObject.__index = Details.atributo_damage --restore metatable for the spell container Details.refresh:r_container_habilidades(actorObject.spells) if (actorObject.augmentedSpellsContainer) then Details.refresh:r_container_habilidades(actorObject.augmentedSpellsContainer) end end function Details.clear:c_atributo_damage (este_jogador) este_jogador.__index = nil este_jogador.links = nil este_jogador.minha_barra = nil Details.clear:c_container_habilidades (este_jogador.spells) end --[[ --enemy damage done i = 1 local enemy = combat (1, enemy_name) if (enemy) then local damage_done = 0 --get targets for target_name, amount in pairs(enemy.targets) do local player = combat (1, target_name) if (player and player.grupo) then local t = tooltip_temp_table [i] if (not t) then tooltip_temp_table [i] = {} t = tooltip_temp_table [i] end t [1] = player t [2] = amount damage_done = damage_done + amount i = i + 1 end end --first clenup for o = i, #tooltip_temp_table do local t = tooltip_temp_table [o] t[2] = 0 t[1] = 0 end _table_sort(tooltip_temp_table, Details.Sort2) --enemy damage taken Details:AddTooltipSpellHeaderText (Loc ["STRING_ATTRIBUTE_DAMAGE"], headerColor, i-1, true) GameCooltip:AddIcon ([=[Interface\Buttons\UI-MicroStream-Green]=], 2, 1, 14, 14, 0.1875, 0.8125, 0.15625, 0.78125) GameCooltip:AddIcon ([=[Interface\AddOns\Details\images\key_shift]=], 2, 2, Details.tooltip_key_size_width, Details.tooltip_key_size_height, 0, 1, 0, 0.640625, Details.tooltip_key_overlay2) GameCooltip:AddStatusBar (100, 2, 0.7, g, b, 1) --build the tooltip for o = 1, i-1 do local player = tooltip_temp_table [o][1] local total = tooltip_temp_table [o][2] local player_name = player:name() if (player_name:find(Details.playername)) then GameCooltip:AddLine(player_name .. ": ", FormatTooltipNumber (_, total) .. " (" .. _cstr ("%.1f", (total / damage_done) * 100) .. "%)", 2, "yellow") else GameCooltip:AddLine(player_name .. ": ", FormatTooltipNumber (_, total) .." (" .. _cstr ("%.1f", (total / damage_done) * 100) .. "%)", 2) end local classe = player:class() if (not classe) then classe = "UNKNOW" end if (classe == "UNKNOW") then GameCooltip:AddIcon ("Interface\\LFGFRAME\\LFGROLE_BW", 2, nil, 14, 14, .25, .5, 0, 1) else GameCooltip:AddIcon (instancia.row_info.icon_file, 2, nil, 14, 14, _unpack(Details.class_coords [classe])) end Details:AddTooltipBackgroundStatusbar (2) end end --clean up for o = 1, #tooltip_temp_table do local t = tooltip_temp_table [o] t[2] = 0 t[1] = 0 end --]]