|
|
|
|
|
|
|
|
|
|
|
|
|
|
local Details = _G.Details
|
|
|
|
|
local textAlpha = 0.9
|
|
|
|
|
local AceLocale = LibStub("AceLocale-3.0")
|
|
|
|
|
local L = AceLocale:GetLocale ( "Details" )
|
|
|
|
|
local addonName, Details222 = ...
|
|
|
|
|
|
|
|
|
|
local on_deathrecap_line_enter = function(self)
|
|
|
|
|
if (self.spellid) then
|
|
|
|
|
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
|
|
|
|
Details:GameTooltipSetSpellByID (self.spellid)
|
|
|
|
|
self:SetBackdropColor(.3, .3, .3, .2)
|
|
|
|
|
GameTooltip:Show()
|
|
|
|
|
self.backgroundTextureOverlay:Show()
|
|
|
|
|
self.timeAt:SetAlpha(1)
|
|
|
|
|
self.sourceName:SetAlpha(1)
|
|
|
|
|
self.amount:SetAlpha(1)
|
|
|
|
|
self.lifePercent:SetAlpha(1)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local on_deathrecap_line_leave = function(self)
|
|
|
|
|
GameTooltip:Hide()
|
|
|
|
|
self:SetBackdropColor(.3, .3, .3, 0)
|
|
|
|
|
self.backgroundTextureOverlay:Hide()
|
|
|
|
|
self.timeAt:SetAlpha(textAlpha)
|
|
|
|
|
self.sourceName:SetAlpha(textAlpha)
|
|
|
|
|
self.amount:SetAlpha(textAlpha)
|
|
|
|
|
self.lifePercent:SetAlpha(textAlpha)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local create_deathrecap_line = function(parent, n)
|
|
|
|
|
local line = CreateFrame("frame", "DetailsDeathRecapLine" .. n, parent, "BackdropTemplate")
|
|
|
|
|
line:SetPoint("topleft", parent, "topleft", 10, (-24 * n) - 17)
|
|
|
|
|
line:SetPoint("topright", parent, "topright", -10, (-24 * n) - 17)
|
|
|
|
|
line:SetScript("OnEnter", on_deathrecap_line_enter)
|
|
|
|
|
line:SetScript("OnLeave", on_deathrecap_line_leave)
|
|
|
|
|
|
|
|
|
|
line:SetSize(300, 21)
|
|
|
|
|
|
|
|
|
|
local timeAt = line:CreateFontString(nil, "overlay", "GameFontNormal")
|
|
|
|
|
local backgroundTexture = line:CreateTexture(nil, "border")
|
|
|
|
|
local backgroundTextureOverlay = line:CreateTexture(nil, "artwork")
|
|
|
|
|
local spellIcon = line:CreateTexture(nil, "overlay")
|
|
|
|
|
local spellIconBorder = line:CreateTexture(nil, "overlay")
|
|
|
|
|
spellIcon:SetDrawLayer("overlay", 1)
|
|
|
|
|
spellIconBorder:SetDrawLayer("overlay", 2)
|
|
|
|
|
local sourceName = line:CreateFontString(nil, "overlay", "GameFontNormal")
|
|
|
|
|
local amount = line:CreateFontString(nil, "overlay", "GameFontNormal")
|
|
|
|
|
local lifePercent = line:CreateFontString(nil, "overlay", "GameFontNormal")
|
|
|
|
|
local lifeStatusBar = line:CreateTexture(nil, "border", nil, -3)
|
|
|
|
|
|
|
|
|
|
--grave icon
|
|
|
|
|
local graveIcon = line:CreateTexture(nil, "overlay")
|
|
|
|
|
graveIcon:SetTexture([[Interface\MINIMAP\POIIcons]])
|
|
|
|
|
graveIcon:SetTexCoord(146/256, 160/256, 0/512, 18/512)
|
|
|
|
|
graveIcon:SetPoint("left", line, "left", 11, 0)
|
|
|
|
|
graveIcon:SetSize(14, 18)
|
|
|
|
|
|
|
|
|
|
--spell icon
|
|
|
|
|
spellIcon:SetSize(19, 19)
|
|
|
|
|
spellIconBorder:SetTexture([[Interface\ENCOUNTERJOURNAL\LootTab]])
|
|
|
|
|
spellIconBorder:SetTexCoord(6/256, 38/256, 49/128, 81/128)
|
|
|
|
|
spellIconBorder:SetSize(20, 20)
|
|
|
|
|
spellIconBorder:SetPoint("topleft", spellIcon, "topleft", 0, 0)
|
|
|
|
|
|
|
|
|
|
--locations
|
|
|
|
|
timeAt:SetPoint("left", line, "left", 2, 0)
|
|
|
|
|
spellIcon:SetPoint("left", line, "left", 50, 0)
|
|
|
|
|
sourceName:SetPoint("left", line, "left", 82, 0)
|
|
|
|
|
amount:SetPoint("left", line, "left", 240, 0)
|
|
|
|
|
lifePercent:SetPoint("left", line, "left", 320, 0)
|
|
|
|
|
|
|
|
|
|
--text colors
|
|
|
|
|
Details.gump:SetFontColor(amount, "red")
|
|
|
|
|
Details.gump:SetFontColor(timeAt, "gray")
|
|
|
|
|
Details.gump:SetFontColor(sourceName, "yellow")
|
|
|
|
|
|
|
|
|
|
Details.gump:SetFontSize(sourceName, 10)
|
|
|
|
|
|
|
|
|
|
--text alpha
|
|
|
|
|
timeAt:SetAlpha(textAlpha)
|
|
|
|
|
sourceName:SetAlpha(textAlpha)
|
|
|
|
|
amount:SetAlpha(textAlpha)
|
|
|
|
|
lifePercent:SetAlpha(textAlpha)
|
|
|
|
|
|
|
|
|
|
--text setup
|
|
|
|
|
amount:SetWidth(85)
|
|
|
|
|
amount:SetJustifyH("right")
|
|
|
|
|
lifePercent:SetWidth(42)
|
|
|
|
|
lifePercent:SetJustifyH("right")
|
|
|
|
|
|
|
|
|
|
--life statusbar
|
|
|
|
|
lifeStatusBar:SetPoint("topleft", line, "topleft")
|
|
|
|
|
lifeStatusBar:SetPoint("bottomleft", line, "bottomleft")
|
|
|
|
|
lifeStatusBar:SetColorTexture(0.5, 0.5, 0.5, 0.4)
|
|
|
|
|
|
|
|
|
|
backgroundTexture:SetTexture([[Interface\AddOns\Details\images\deathrecap_background]])
|
|
|
|
|
backgroundTexture:SetTexCoord(0, 1, 0, 1)
|
|
|
|
|
backgroundTexture:SetVertexColor(.1, .1, .1, .3)
|
|
|
|
|
|
|
|
|
|
--top border
|
|
|
|
|
local TopFader = line:CreateTexture(nil, "border")
|
|
|
|
|
TopFader:SetTexture([[Interface\AddOns\Details\images\deathrecap_background_top]])
|
|
|
|
|
TopFader:SetTexCoord(0, 1, 0, 1)
|
|
|
|
|
TopFader:SetVertexColor(.1, .1, .1, .3)
|
|
|
|
|
TopFader:SetPoint("bottomleft", backgroundTexture, "topleft", 0, -0)
|
|
|
|
|
TopFader:SetPoint("bottomright", backgroundTexture, "topright", 0, -0)
|
|
|
|
|
TopFader:SetHeight(32)
|
|
|
|
|
TopFader:Hide()
|
|
|
|
|
line.TopFader = TopFader
|
|
|
|
|
|
|
|
|
|
if (n == 10) then
|
|
|
|
|
--bottom fader
|
|
|
|
|
local backgroundTexture2 = line:CreateTexture(nil, "border")
|
|
|
|
|
backgroundTexture2:SetTexture([[Interface\AddOns\Details\images\deathrecap_background_bottom]])
|
|
|
|
|
backgroundTexture2:SetTexCoord(0, 1, 0, 1)
|
|
|
|
|
backgroundTexture2:SetVertexColor(.1, .1, .1, .3)
|
|
|
|
|
backgroundTexture2:SetPoint("topleft", backgroundTexture, "bottomleft", 0, 0)
|
|
|
|
|
backgroundTexture2:SetPoint("topright", backgroundTexture, "bottomright", 0, 0)
|
|
|
|
|
backgroundTexture2:SetHeight(32)
|
|
|
|
|
|
|
|
|
|
Details.gump:SetFontSize(amount, 14)
|
|
|
|
|
Details.gump:SetFontSize(lifePercent, 14)
|
|
|
|
|
backgroundTexture:SetVertexColor(.2, .1, .1, .3)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
backgroundTexture:SetPoint("topleft", 0, 1)
|
|
|
|
|
backgroundTexture:SetPoint("bottomright", 0, -1)
|
|
|
|
|
backgroundTexture:SetDesaturated(true)
|
|
|
|
|
backgroundTextureOverlay:SetTexture([[Interface\AdventureMap\AdventureMap]])
|
|
|
|
|
backgroundTextureOverlay:SetTexCoord(460/1024, 659/1024, 330/1024, 350/1024)
|
|
|
|
|
backgroundTextureOverlay:SetAllPoints()
|
|
|
|
|
backgroundTextureOverlay:SetDesaturated(true)
|
|
|
|
|
backgroundTextureOverlay:SetAlpha(0.5)
|
|
|
|
|
backgroundTextureOverlay:Hide()
|
|
|
|
|
|
|
|
|
|
line.timeAt = timeAt
|
|
|
|
|
line.spellIcon = spellIcon
|
|
|
|
|
line.sourceName = sourceName
|
|
|
|
|
line.amount = amount
|
|
|
|
|
line.lifePercent = lifePercent
|
|
|
|
|
line.backgroundTexture = backgroundTexture
|
|
|
|
|
line.backgroundTextureOverlay = backgroundTextureOverlay
|
|
|
|
|
line.graveIcon = graveIcon
|
|
|
|
|
line.lifeStatusBar = lifeStatusBar
|
|
|
|
|
|
|
|
|
|
if (n == 10) then
|
|
|
|
|
graveIcon:Show()
|
|
|
|
|
line.timeAt:Hide()
|
|
|
|
|
else
|
|
|
|
|
graveIcon:Hide()
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return line
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local OpenDetailsDeathRecapAtSegment = function(segment)
|
|
|
|
|
Details.OpenDetailsDeathRecap (segment, RecapID)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Details.BuildDeathTableFromRecap (recapID)
|
|
|
|
|
local events = DeathRecap_GetEvents (recapID)
|
|
|
|
|
|
|
|
|
|
--check if it is a valid recap
|
|
|
|
|
if (not events or #events <= 0) then
|
|
|
|
|
DeathRecapFrame.Unavailable:Show()
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--build an death log using details format
|
|
|
|
|
ArtificialDeathLog = {
|
|
|
|
|
{}, --deathlog events
|
|
|
|
|
(events [1] and events [1].timestamp) or (DeathRecapFrame and DeathRecapFrame.DeathTimeStamp) or 0, --time of death
|
|
|
|
|
UnitName ("player"),
|
|
|
|
|
select(2, UnitClass("player")),
|
|
|
|
|
UnitHealthMax ("player"),
|
|
|
|
|
"0m 0s", --formated fight time
|
|
|
|
|
["dead"] = true,
|
|
|
|
|
["last_cooldown"] = false,
|
|
|
|
|
["dead_at"] = 0,
|
|
|
|
|
n = 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for i = 1, #events do
|
|
|
|
|
local evtData = events [i]
|
|
|
|
|
local spellId, spellName, texture = DeathRecapFrame_GetEventInfo ( evtData )
|
|
|
|
|
|
|
|
|
|
local ev = {
|
|
|
|
|
true,
|
|
|
|
|
spellId or 0,
|
|
|
|
|
evtData.amount or 0,
|
|
|
|
|
evtData.timestamp or 0, --?
|
|
|
|
|
evtData.currentHP or 0,
|
|
|
|
|
evtData.sourceName or "--x--x--",
|
|
|
|
|
evtData.absorbed or 0,
|
|
|
|
|
evtData.school or 0,
|
|
|
|
|
false,
|
|
|
|
|
evtData.overkill,
|
|
|
|
|
not spellId and {spellId, spellName, texture},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tinsert(ArtificialDeathLog[1], ev)
|
|
|
|
|
ArtificialDeathLog.n = ArtificialDeathLog.n + 1
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return ArtificialDeathLog
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Details.GetDeathRecapFromChat()
|
|
|
|
|
local chat1 = ChatFrame1
|
|
|
|
|
local recapIDFromChat
|
|
|
|
|
if (chat1) then
|
|
|
|
|
local numLines = chat1:GetNumMessages()
|
|
|
|
|
for i = numLines, 1, -1 do
|
|
|
|
|
local text = chat1:GetMessageInfo (i)
|
|
|
|
|
if (text) then
|
|
|
|
|
if (text:find("Hdeath:%d")) then
|
|
|
|
|
local recapID = text:match ("|Hdeath:(%d+)|h")
|
|
|
|
|
if (recapID) then
|
|
|
|
|
recapIDFromChat = tonumber(recapID)
|
|
|
|
|
end
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if (recapIDFromChat) then
|
|
|
|
|
Details.OpenDetailsDeathRecap (nil, recapIDFromChat, true)
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Details.OpenDetailsDeathRecap (segment, RecapID, fromChat)
|
|
|
|
|
if (not Details.death_recap.enabled) then
|
|
|
|
|
if (Details.DeathRecap and Details.DeathRecap.Lines) then
|
|
|
|
|
for i = 1, 10 do
|
|
|
|
|
Details.DeathRecap.Lines [i]:Hide()
|
|
|
|
|
end
|
|
|
|
|
for i, button in ipairs(Details.DeathRecap.Segments) do
|
|
|
|
|
button:Hide()
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--hide blizzard death recap
|
|
|
|
|
DeathRecapFrame.Recap1:Hide()
|
|
|
|
|
DeathRecapFrame.Recap2:Hide()
|
|
|
|
|
DeathRecapFrame.Recap3:Hide()
|
|
|
|
|
DeathRecapFrame.Recap4:Hide()
|
|
|
|
|
DeathRecapFrame.Recap5:Hide()
|
|
|
|
|
|
|
|
|
|
--create details death recap if not existant
|
|
|
|
|
if (not Details.DeathRecap) then
|
|
|
|
|
Details.DeathRecap = CreateFrame("frame", "DetailsDeathRecap", DeathRecapFrame, "BackdropTemplate")
|
|
|
|
|
Details.DeathRecap:SetAllPoints()
|
|
|
|
|
|
|
|
|
|
DeathRecapFrame.Title:SetText(DeathRecapFrame.Title:GetText() .. " (by Details!)")
|
|
|
|
|
|
|
|
|
|
--lines
|
|
|
|
|
Details.DeathRecap.Lines = {}
|
|
|
|
|
for i = 1, 10 do
|
|
|
|
|
Details.DeathRecap.Lines [i] = create_deathrecap_line (Details.DeathRecap, i)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--segments
|
|
|
|
|
Details.DeathRecap.Segments = {}
|
|
|
|
|
for i = 5, 1, -1 do
|
|
|
|
|
local segmentButton = CreateFrame("button", "DetailsDeathRecapSegmentButton" .. i, Details.DeathRecap, "BackdropTemplate")
|
|
|
|
|
|
|
|
|
|
segmentButton:SetSize(16, 20)
|
|
|
|
|
segmentButton:SetPoint("topright", DeathRecapFrame, "topright", (-abs(i-6) * 22) - 10, -5)
|
|
|
|
|
|
|
|
|
|
local text = segmentButton:CreateFontString(nil, "overlay", "GameFontNormal")
|
|
|
|
|
segmentButton.text = text
|
|
|
|
|
text:SetText("#" .. i)
|
|
|
|
|
text:SetPoint("center")
|
|
|
|
|
Details.gump:SetFontColor(text, "silver")
|
|
|
|
|
|
|
|
|
|
segmentButton:SetScript("OnClick", function()
|
|
|
|
|
OpenDetailsDeathRecapAtSegment (i)
|
|
|
|
|
end)
|
|
|
|
|
tinsert(Details.DeathRecap.Segments, i, segmentButton)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
for i = 1, 10 do
|
|
|
|
|
Details.DeathRecap.Lines[i]:Hide()
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--segment to use
|
|
|
|
|
local death = Details.tabela_vigente.last_events_tables
|
|
|
|
|
|
|
|
|
|
--see if this segment has a death for the player
|
|
|
|
|
local foundPlayer = false
|
|
|
|
|
for index = #death, 1, -1 do
|
|
|
|
|
if (death [index] [3] == Details.playername) then
|
|
|
|
|
foundPlayer = true
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--in case a combat has been created after the player death, the death won't be at the current segment
|
|
|
|
|
if (not foundPlayer) then
|
|
|
|
|
local segmentsTable = Details:GetCombatSegments()
|
|
|
|
|
for i = 1, 2 do
|
|
|
|
|
local segment = segmentsTable [1]
|
|
|
|
|
if (segment and segment ~= Details.tabela_vigente) then
|
|
|
|
|
if (Details.tabela_vigente.start_time - 3 < segment.end_time) then
|
|
|
|
|
death = segment.last_events_tables
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--segments
|
|
|
|
|
if (Details.death_recap.show_segments) then
|
|
|
|
|
local last_index = 0
|
|
|
|
|
local buttonsInUse = {}
|
|
|
|
|
local segmentsTable = Details:GetCombatSegments()
|
|
|
|
|
|
|
|
|
|
for i, button in ipairs(Details.DeathRecap.Segments) do
|
|
|
|
|
if (segmentsTable[i]) then
|
|
|
|
|
button:Show()
|
|
|
|
|
table.insert(buttonsInUse, button)
|
|
|
|
|
Details.gump:SetFontColor(button.text, "silver")
|
|
|
|
|
last_index = i
|
|
|
|
|
else
|
|
|
|
|
button:Hide()
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local buttonsInUse2 = {}
|
|
|
|
|
for i = #buttonsInUse, 1, -1 do
|
|
|
|
|
table.insert(buttonsInUse2, buttonsInUse[i])
|
|
|
|
|
end
|
|
|
|
|
for i = 1, #buttonsInUse2 do
|
|
|
|
|
local button = buttonsInUse2 [i]
|
|
|
|
|
button:ClearAllPoints()
|
|
|
|
|
button:SetPoint("topright", DeathRecapFrame, "topright", (-i * 22) - 10, -5)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if (not segment) then
|
|
|
|
|
Details.gump:SetFontColor(Details.DeathRecap.Segments [1].text, "orange")
|
|
|
|
|
else
|
|
|
|
|
Details.gump:SetFontColor(Details.DeathRecap.Segments [segment].text, "orange")
|
|
|
|
|
death = segmentsTable[segment] and segmentsTable[segment].last_events_tables
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
for i, button in ipairs(Details.DeathRecap.Segments) do
|
|
|
|
|
button:Hide()
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--if couldn't find the requested log from details!, so, import the log from the blizzard death recap
|
|
|
|
|
--or if the player cliced on the chat link for the recap
|
|
|
|
|
local ArtificialDeathLog
|
|
|
|
|
if (not death or RecapID) then
|
|
|
|
|
if (segment) then
|
|
|
|
|
--nop, the player requested a death log from details it self but the log does not exists
|
|
|
|
|
DeathRecapFrame.Unavailable:Show()
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--get the death events from the blizzard's recap
|
|
|
|
|
ArtificialDeathLog = Details.BuildDeathTableFromRecap (RecapID)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
DeathRecapFrame.Unavailable:Hide()
|
|
|
|
|
|
|
|
|
|
--get the relevance config
|
|
|
|
|
local relevanceTime = Details.death_recap.relevance_time
|
|
|
|
|
|
|
|
|
|
local t
|
|
|
|
|
if (ArtificialDeathLog) then
|
|
|
|
|
t = ArtificialDeathLog
|
|
|
|
|
else
|
|
|
|
|
for index = #death, 1, -1 do
|
|
|
|
|
if (death [index] [3] == Details.playername) then
|
|
|
|
|
t = death [index]
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if (t) then
|
|
|
|
|
local events = t [1]
|
|
|
|
|
local timeOfDeath = t [2]
|
|
|
|
|
|
|
|
|
|
local BiggestDamageHits = {}
|
|
|
|
|
for i = #events, 1, -1 do
|
|
|
|
|
tinsert(BiggestDamageHits, events [i])
|
|
|
|
|
end
|
|
|
|
|
table.sort (BiggestDamageHits, function(t1, t2)
|
|
|
|
|
return t1[3] > t2[3]
|
|
|
|
|
end)
|
|
|
|
|
for i = #BiggestDamageHits, 1, -1 do
|
|
|
|
|
if (BiggestDamageHits [i][4] + relevanceTime < timeOfDeath) then
|
|
|
|
|
tremove(BiggestDamageHits, i)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--check if the event which killed the player is in the list, or addit to BiggestDamageHits
|
|
|
|
|
local hitKill
|
|
|
|
|
for i = #events, 1, -1 do
|
|
|
|
|
local event = events [i]
|
|
|
|
|
local evType = event [1]
|
|
|
|
|
if (type(evType) == "boolean" and evType) then
|
|
|
|
|
hitKill = event
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if (hitKill) then
|
|
|
|
|
local haveHitKill = false
|
|
|
|
|
for index, t in ipairs(BiggestDamageHits) do
|
|
|
|
|
if (t == hitKill) then
|
|
|
|
|
haveHitKill = true
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if (not haveHitKill) then
|
|
|
|
|
tinsert(BiggestDamageHits, 1, hitKill)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--check if there's at least 10 big events, if not fill with smaller events
|
|
|
|
|
if (#BiggestDamageHits < 10) then
|
|
|
|
|
for i = #events, 1, -1 do
|
|
|
|
|
local event = events [i]
|
|
|
|
|
local evType = event [1]
|
|
|
|
|
if (type(evType) == "boolean" and evType) then
|
|
|
|
|
local alreadyHave = false
|
|
|
|
|
for index, t in ipairs(BiggestDamageHits) do
|
|
|
|
|
if (t == event) then
|
|
|
|
|
alreadyHave = true
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if (not alreadyHave) then
|
|
|
|
|
tinsert(BiggestDamageHits, event)
|
|
|
|
|
if (#BiggestDamageHits == 10) then
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
--cut table to show only 10 events
|
|
|
|
|
while (#BiggestDamageHits > 10) do
|
|
|
|
|
tremove(BiggestDamageHits, 11)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if (#BiggestDamageHits == 0) then
|
|
|
|
|
if (not fromChat) then
|
|
|
|
|
Details.GetDeathRecapFromChat()
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
table.sort (BiggestDamageHits, function(t1, t2)
|
|
|
|
|
return t1[4] > t2[4]
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
local events = BiggestDamageHits
|
|
|
|
|
|
|
|
|
|
local maxHP = t [5]
|
|
|
|
|
local lineIndex = 10
|
|
|
|
|
|
|
|
|
|
--for i = #events, 1, -1 do
|
|
|
|
|
for i, event in ipairs(events) do
|
|
|
|
|
local event = events [i]
|
|
|
|
|
|
|
|
|
|
local evType = event [1]
|
|
|
|
|
local hp = min (floor(event [5] / maxHP * 100), 100)
|
|
|
|
|
local spellName, _, spellIcon = Details.GetSpellInfo(event [2])
|
|
|
|
|
local amount = event [3]
|
|
|
|
|
local eventTime = event [4]
|
|
|
|
|
local source = event [6]
|
|
|
|
|
local overkill = event [10] or 0
|
|
|
|
|
|
|
|
|
|
local customSpellInfo = event [11]
|
|
|
|
|
|
|
|
|
|
if (type(evType) == "boolean" and evType) then
|
|
|
|
|
|
|
|
|
|
local line = Details.DeathRecap.Lines [lineIndex]
|
|
|
|
|
if (line) then
|
|
|
|
|
line.timeAt:SetText(format("%.1f", eventTime - timeOfDeath) .. "s")
|
|
|
|
|
line.spellIcon:SetTexture(spellIcon or customSpellInfo and customSpellInfo [3] or "")
|
|
|
|
|
line.TopFader:Hide()
|
|
|
|
|
--line.spellIcon:SetTexCoord(.1, .9, .1, .9)
|
|
|
|
|
--line.sourceName:SetText("|cFFC6B0D9" .. source .. "|r")
|
|
|
|
|
|
|
|
|
|
--parse source and cut the length of the string after setting the spellname and source
|
|
|
|
|
local sourceClass = Details:GetClass(source)
|
|
|
|
|
local sourceSpec = Details:GetSpec(source)
|
|
|
|
|
|
|
|
|
|
if (not sourceClass) then
|
|
|
|
|
local combat = Details:GetCurrentCombat()
|
|
|
|
|
if (combat) then
|
|
|
|
|
local sourceActor = combat:GetActor(1, source)
|
|
|
|
|
if (sourceActor) then
|
|
|
|
|
sourceClass = sourceActor.classe
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if (not sourceSpec) then
|
|
|
|
|
local combat = Details:GetCurrentCombat()
|
|
|
|
|
if (combat) then
|
|
|
|
|
local sourceActor = combat:GetActor(1, source)
|
|
|
|
|
if (sourceActor) then
|
|
|
|
|
sourceSpec = sourceActor.spec
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--remove real name or owner name
|
|
|
|
|
source = Details:GetOnlyName(source)
|
|
|
|
|
--remove owner name
|
|
|
|
|
source = source:gsub((" <.*"), "")
|
|
|
|
|
|
|
|
|
|
--if a player?
|
|
|
|
|
if (Details.player_class [sourceClass]) then
|
|
|
|
|
source = Details:AddClassOrSpecIcon (source, sourceClass, sourceSpec, 16, true)
|
|
|
|
|
|
|
|
|
|
elseif (sourceClass == "PET") then
|
|
|
|
|
source = Details:AddClassOrSpecIcon (source, sourceClass)
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--remove the dot signal from the spell name
|
|
|
|
|
if (not spellName) then
|
|
|
|
|
spellName = customSpellInfo and customSpellInfo [2] or "*?*"
|
|
|
|
|
if (spellName:find(STRING_ENVIRONMENTAL_DAMAGE_FALLING)) then
|
|
|
|
|
if (UnitName ("player") == "Elphaba") then
|
|
|
|
|
spellName = "Gravity Won!, Elphaba..."
|
|
|
|
|
source = ""
|
|
|
|
|
else
|
|
|
|
|
source = "Gravity"
|
|
|
|
|
end
|
|
|
|
|
--/run for a,b in pairs(_G) do if (type(b)=="string" and b:find("Falling")) then print(a,b) end end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
spellName = spellName:gsub(L["STRING_DOT"], "")
|
|
|
|
|
spellName = spellName:gsub("[*] ", "")
|
|
|
|
|
source = source or ""
|
|
|
|
|
|
|
|
|
|
line.sourceName:SetText(spellName .. " (" .. "|cFFC6B0D9" .. source .. "|r" .. ")")
|
|
|
|
|
DetailsFramework:TruncateText (line.sourceName, 185)
|
|
|
|
|
|
|
|
|
|
if (amount > 1000) then
|
|
|
|
|
--line.amount:SetText("-" .. Details:ToK (amount))
|
|
|
|
|
line.amount:SetText("-" .. Details:comma_value(floor(amount)))
|
|
|
|
|
else
|
|
|
|
|
--line.amount:SetText("-" .. floor(amount))
|
|
|
|
|
line.amount:SetText("-" .. floor(amount))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
line.lifePercent:SetText(hp .. "%")
|
|
|
|
|
line.lifeStatusBar:SetWidth(line:GetWidth() * (hp/100))
|
|
|
|
|
|
|
|
|
|
line.spellid = event [2]
|
|
|
|
|
|
|
|
|
|
line:Show()
|
|
|
|
|
|
|
|
|
|
if (Details.death_recap.show_life_percent) then
|
|
|
|
|
line.lifePercent:Show()
|
|
|
|
|
line.amount:SetPoint("left", line, "left", 240, 0)
|
|
|
|
|
line.lifePercent:SetPoint("left", line, "left", 320, 0)
|
|
|
|
|
else
|
|
|
|
|
line.lifePercent:Hide()
|
|
|
|
|
line.amount:SetPoint("left", line, "left", 280, 0)
|
|
|
|
|
--line.lifePercent:SetPoint("left", line, "left", 320, 0)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
lineIndex = lineIndex - 1
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local lastLine = Details.DeathRecap.Lines [lineIndex + 1]
|
|
|
|
|
if (lastLine) then
|
|
|
|
|
lastLine.TopFader:Show()
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
DeathRecapFrame.Unavailable:Hide()
|
|
|
|
|
else
|
|
|
|
|
if (not fromChat) then
|
|
|
|
|
Details.GetDeathRecapFromChat()
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
hooksecurefunc (_G, "DeathRecap_LoadUI", function()
|
|
|
|
|
hooksecurefunc (_G, "DeathRecapFrame_OpenRecap", function(RecapID)
|
|
|
|
|
local currentCombat = Details:GetCurrentCombat()
|
|
|
|
|
--get the player current death and link the death table with the death recapID
|
|
|
|
|
local playerDeaths = currentCombat:GetPlayerDeaths(UnitName("player"))
|
|
|
|
|
if (playerDeaths) then
|
|
|
|
|
local latestDeath = playerDeaths[#playerDeaths]
|
|
|
|
|
if (latestDeath) then
|
|
|
|
|
latestDeath.RecapID = RecapID
|
|
|
|
|
|
|
|
|
|
--synchronize last events from Details! and Blizzard recap
|
|
|
|
|
local events = DeathRecap_GetEvents(recapID)
|
|
|
|
|
--death is event index 1 (the event that killed the player)
|
|
|
|
|
local evtData = events[1]
|
|
|
|
|
|
|
|
|
|
if (evtData) then
|
|
|
|
|
--recap by blizzard
|
|
|
|
|
local spellName = evtData.spellName
|
|
|
|
|
local spellId = evtData.spellId
|
|
|
|
|
local event = evtData.event
|
|
|
|
|
local environmentalType = evtData.environmentalType
|
|
|
|
|
local timeStamp = evtData.timestamp
|
|
|
|
|
local amountDamage = evtData.amount
|
|
|
|
|
local overkill = evtData.overkill
|
|
|
|
|
local absorbed = evtData.absorbed
|
|
|
|
|
local resisted = evtData.resisted
|
|
|
|
|
local blocked = evtData.blocked
|
|
|
|
|
local currentHp = evtData.currentHP
|
|
|
|
|
local hideCaster = evtData.hideCaster
|
|
|
|
|
local sourceName = evtData.sourceName
|
|
|
|
|
local casterPrestige = evtData.casterPrestige
|
|
|
|
|
local spellSchool = evtData.school
|
|
|
|
|
|
|
|
|
|
local spellId, spellName, texture = DeathRecapFrame_GetEventInfo(evtData)
|
|
|
|
|
local format = Details:GetCurrentToKFunction()
|
|
|
|
|
|
|
|
|
|
if (Details.death_recap.enabled) then
|
|
|
|
|
if (Details:GetZoneType() == "party" or Details:GetZoneType() == "raid") then
|
|
|
|
|
local msgText = "|cFFAAAAFFDeath Recap (Blizzard):"
|
|
|
|
|
print(msgText, "|T" .. texture .. ":16:16:0:0:64:64:5:59:5:59|t", GetSpellLink(spellId) or spellName, format(_, amountDamage or 0))
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--recap by Details!
|
|
|
|
|
--[=[
|
|
|
|
|
local deathEventsDetails = latestDeath[1]
|
|
|
|
|
for evIndex = #deathEventsDetails, 1, -1 do
|
|
|
|
|
local ev = deathEventsDetails[evIndex]
|
|
|
|
|
local evType = ev[1]
|
|
|
|
|
local spellId = ev[2]
|
|
|
|
|
local amount = ev[3]
|
|
|
|
|
--is a damage? true boolean
|
|
|
|
|
if (type(evType) == "boolean" and evType) then
|
|
|
|
|
local spellName, _, spellIcon = Details.GetSpellInfo(spellId)
|
|
|
|
|
if (spellName) then
|
|
|
|
|
--print("Killed by (Details!-Debug): ", spellName, "amount:", amount)
|
|
|
|
|
else
|
|
|
|
|
--print("Killed by (Details!-Debug): spell not found")
|
|
|
|
|
end
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
--]=]
|
|
|
|
|
|
|
|
|
|
--Details:Msg("the message above are debugs of an Alpha version of Details!")
|
|
|
|
|
|
|
|
|
|
--local whatKilledThePlayer = 0
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
Details.OpenDetailsDeathRecap(nil, RecapID)
|
|
|
|
|
end)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
--[=[ hooks not loaded at this point
|
|
|
|
|
Details:InstallHook(DETAILS_HOOK_DEATH, function(_, _, _, _, _, _, _, targetName)
|
|
|
|
|
if (targetName == UnitName("player")) then
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
end)
|
|
|
|
|
--]=]
|