933c10771d
- Added an extra bar within the evoker damage bar, this new bar when hovered over shows the buff uptime of Ebon Might and Prescience on all players.
7237 lines
250 KiB
Lua
7237 lines
250 KiB
Lua
|
|
--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 <instance.thisLine> "..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 <instancia.thisLine> "..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 <instancia.thisLine> "..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 <instance.thisLine> "..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)
|
|
if (extraAmount and extraAmount > 0) then
|
|
local extraStatusbar = thisLine.extraStatusbar
|
|
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()
|
|
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<actorname, valueamount>
|
|
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()) 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: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<string, string>, 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<string, friendlyfiretable>
|
|
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<number, actorname>
|
|
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<string, boolean>
|
|
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<string, number>
|
|
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<number, spelltable>
|
|
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<string, number>
|
|
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
|
|
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
|
|
--]]
|