15edd25de7
- won't sync dps / hps from encounters from old raid tiers. - won't sync encounters without the .servertime time stamp. - core version bump up, so details will auto ignore comms from old databases without the .servertime member on the encounter table.
1859 lines
54 KiB
Lua
1859 lines
54 KiB
Lua
local _detalhes = _G._detalhes
|
|
local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
|
|
|
|
local UnitName = UnitName
|
|
local UnitGUID = UnitGUID
|
|
local UnitGroupRolesAssigned = UnitGroupRolesAssigned
|
|
local select = select
|
|
local floor = floor
|
|
|
|
local GetNumGroupMembers = GetNumGroupMembers
|
|
local ItemUpgradeInfo = LibStub ("LibItemUpgradeInfo-1.0")
|
|
local LibGroupInSpecT = LibStub ("LibGroupInSpecT-1.1")
|
|
|
|
local storageDebug = false
|
|
local store_instances = _detalhes.InstancesToStoreData
|
|
|
|
function _detalhes:UpdateGears()
|
|
|
|
_detalhes:UpdateParser()
|
|
_detalhes:UpdateControl()
|
|
_detalhes:UpdateCombat()
|
|
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------
|
|
--> chat hooks
|
|
|
|
_detalhes.chat_embed = _detalhes:CreateEventListener()
|
|
_detalhes.chat_embed.startup = true
|
|
|
|
_detalhes.chat_embed.hook_settabname = function (frame, name, doNotSave)
|
|
if (not doNotSave) then
|
|
if (_detalhes.chat_tab_embed.enabled and _detalhes.chat_tab_embed.tab_name ~= "") then
|
|
if (_detalhes.chat_tab_embed_onframe == frame) then
|
|
_detalhes.chat_tab_embed.tab_name = name
|
|
_detalhes:DelayOptionsRefresh (_detalhes:GetInstance(1))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
_detalhes.chat_embed.hook_closetab = function (frame, fallback)
|
|
if (_detalhes.chat_tab_embed.enabled and _detalhes.chat_tab_embed.tab_name ~= "") then
|
|
if (_detalhes.chat_tab_embed_onframe == frame) then
|
|
_detalhes.chat_tab_embed.enabled = false
|
|
_detalhes.chat_tab_embed.tab_name = ""
|
|
_detalhes.chat_tab_embed_onframe = nil
|
|
_detalhes:DelayOptionsRefresh (_detalhes:GetInstance(1))
|
|
_detalhes.chat_embed:ReleaseEmbed()
|
|
end
|
|
end
|
|
end
|
|
hooksecurefunc ("FCF_SetWindowName", _detalhes.chat_embed.hook_settabname)
|
|
hooksecurefunc ("FCF_Close", _detalhes.chat_embed.hook_closetab)
|
|
|
|
function _detalhes.chat_embed:SetTabSettings (tab_name, is_enabled, is_single)
|
|
|
|
local current_enabled_state = _detalhes.chat_tab_embed.enabled
|
|
local current_name = _detalhes.chat_tab_embed.tab_name
|
|
|
|
tab_name = tab_name or _detalhes.chat_tab_embed.tab_name
|
|
if (is_enabled == nil) then
|
|
is_enabled = _detalhes.chat_tab_embed.enabled
|
|
end
|
|
if (is_single == nil) then
|
|
is_single = _detalhes.chat_tab_embed.single_window
|
|
end
|
|
|
|
_detalhes.chat_tab_embed.tab_name = tab_name or ""
|
|
_detalhes.chat_tab_embed.enabled = is_enabled
|
|
_detalhes.chat_tab_embed.single_window = is_single
|
|
|
|
if (current_name ~= tab_name) then
|
|
--> rename the tab on chat frame
|
|
local ChatFrame = _detalhes.chat_embed:GetTab (current_name)
|
|
if (ChatFrame) then
|
|
FCF_SetWindowName (ChatFrame, tab_name, false)
|
|
end
|
|
end
|
|
|
|
if (is_enabled) then
|
|
--> was disabled, so we need to save the current window positions.
|
|
if (not current_enabled_state) then
|
|
local window1 = _detalhes:GetInstance (1)
|
|
if (window1) then
|
|
window1:SaveMainWindowPosition()
|
|
if (window1.libwindow) then
|
|
local pos = window1:CreatePositionTable()
|
|
_detalhes.chat_tab_embed.w1_pos = pos
|
|
end
|
|
end
|
|
local window2 = _detalhes:GetInstance (2)
|
|
if (window2) then
|
|
window2:SaveMainWindowPosition()
|
|
if (window2.libwindow) then
|
|
local pos = window2:CreatePositionTable()
|
|
_detalhes.chat_tab_embed.w2_pos = pos
|
|
end
|
|
end
|
|
end
|
|
|
|
--> need to make the embed
|
|
_detalhes.chat_embed:DoEmbed()
|
|
else
|
|
--> need to release the frame
|
|
if (current_enabled_state) then
|
|
_detalhes.chat_embed:ReleaseEmbed()
|
|
end
|
|
end
|
|
end
|
|
|
|
function _detalhes.chat_embed:CheckChatEmbed (is_startup)
|
|
if (_detalhes.chat_tab_embed.enabled) then
|
|
_detalhes.chat_embed:DoEmbed (is_startup)
|
|
end
|
|
end
|
|
|
|
--dom
|
|
-- /run _detalhes.chat_embed:SetTabSettings ("Dano", true, false)
|
|
-- /run _detalhes.chat_embed:SetTabSettings (nil, false, false)
|
|
-- /dump _detalhes.chat_tab_embed.tab_name
|
|
|
|
function _detalhes.chat_embed:DelayedChatEmbed (is_startup)
|
|
_detalhes.chat_embed.startup = nil
|
|
_detalhes.chat_embed:DoEmbed()
|
|
end
|
|
|
|
function _detalhes.chat_embed:DoEmbed (is_startup)
|
|
if (_detalhes.chat_embed.startup and not is_startup) then
|
|
if (_detalhes.AddOnStartTime + 5 < GetTime()) then
|
|
_detalhes.chat_embed.startup = nil
|
|
else
|
|
return
|
|
end
|
|
end
|
|
if (is_startup) then
|
|
return _detalhes.chat_embed:ScheduleTimer ("DelayedChatEmbed", 5)
|
|
end
|
|
local tabname = _detalhes.chat_tab_embed.tab_name
|
|
|
|
if (_detalhes.chat_tab_embed.enabled and tabname ~= "") then
|
|
local ChatFrame, ChatFrameTab, ChatFrameBackground = _detalhes.chat_embed:GetTab (tabname)
|
|
|
|
if (not ChatFrame) then
|
|
FCF_OpenNewWindow (tabname)
|
|
ChatFrame, ChatFrameTab, ChatFrameBackground = _detalhes.chat_embed:GetTab (tabname)
|
|
end
|
|
|
|
if (ChatFrame) then
|
|
for index, t in pairs (ChatFrame.messageTypeList) do
|
|
ChatFrame_RemoveMessageGroup (ChatFrame, t)
|
|
ChatFrame.messageTypeList [index] = nil
|
|
end
|
|
|
|
_detalhes.chat_tab_embed_onframe = ChatFrame
|
|
|
|
if (_detalhes.chat_tab_embed.single_window) then
|
|
--> only one window
|
|
local window1 = _detalhes:GetInstance (1)
|
|
|
|
window1:UngroupInstance()
|
|
window1.baseframe:ClearAllPoints()
|
|
|
|
window1.baseframe:SetParent (ChatFrame)
|
|
window1.rowframe:SetParent (window1.baseframe)
|
|
window1.rowframe:ClearAllPoints()
|
|
window1.rowframe:SetAllPoints()
|
|
|
|
local y_up = window1.toolbar_side == 1 and -20 or 0
|
|
local y_down = (window1.show_statusbar and 14 or 0) + (window1.toolbar_side == 2 and 20 or 0)
|
|
|
|
window1.baseframe:SetPoint ("topleft", ChatFrameBackground, "topleft", 0, y_up)
|
|
window1.baseframe:SetPoint ("bottomright", ChatFrameBackground, "bottomright", 0, y_down)
|
|
|
|
window1:LockInstance (true)
|
|
window1:SaveMainWindowPosition()
|
|
|
|
local window2 = _detalhes:GetInstance (2)
|
|
if (window2 and window2.baseframe) then
|
|
if (window2.baseframe:GetParent() == ChatFrame) then
|
|
--> need to detach
|
|
_detalhes.chat_embed:ReleaseEmbed (true)
|
|
end
|
|
end
|
|
|
|
else
|
|
--> window #1 and #2
|
|
local window1 = _detalhes:GetInstance (1)
|
|
local window2 = _detalhes:GetInstance (2)
|
|
if (not window2) then
|
|
window2 = _detalhes:CriarInstancia()
|
|
end
|
|
|
|
window1:UngroupInstance()
|
|
window2:UngroupInstance()
|
|
window1.baseframe:ClearAllPoints()
|
|
window2.baseframe:ClearAllPoints()
|
|
|
|
window1.baseframe:SetParent (ChatFrame)
|
|
window2.baseframe:SetParent (ChatFrame)
|
|
window1.rowframe:SetParent (window1.baseframe)
|
|
window2.rowframe:SetParent (window2.baseframe)
|
|
|
|
window1:LockInstance (true)
|
|
window2:LockInstance (true)
|
|
|
|
local statusbar_enabled1 = window1.show_statusbar
|
|
local statusbar_enabled2 = window2.show_statusbar
|
|
|
|
table.wipe (window1.snap); table.wipe (window2.snap)
|
|
window1.snap [3] = 2; window2.snap [1] = 1;
|
|
window1.horizontalSnap = true; window2.horizontalSnap = true
|
|
|
|
local y_up = window1.toolbar_side == 1 and -20 or 0
|
|
local y_down = (window1.show_statusbar and 14 or 0) + (window1.toolbar_side == 2 and 20 or 0)
|
|
|
|
local width = ChatFrameBackground:GetWidth() / 2
|
|
local height = ChatFrameBackground:GetHeight() - y_down + y_up
|
|
|
|
window1.baseframe:SetSize (width, height)
|
|
window2.baseframe:SetSize (width, height)
|
|
|
|
window1.baseframe:SetPoint ("topleft", ChatFrameBackground, "topleft", 0, y_up)
|
|
window2.baseframe:SetPoint ("topright", ChatFrameBackground, "topright", 0, y_up)
|
|
|
|
window1:SaveMainWindowPosition()
|
|
window2:SaveMainWindowPosition()
|
|
|
|
-- /dump ChatFrame3Background:GetSize()
|
|
--[[
|
|
_detalhes.move_janela_func (window1.baseframe, true, window1)
|
|
_detalhes.move_janela_func (window1.baseframe, false, window1)
|
|
_detalhes.move_janela_func (window2.baseframe, true, window2)
|
|
_detalhes.move_janela_func (window2.baseframe, false, window2)
|
|
--]]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function _detalhes.chat_embed:ReleaseEmbed (second_window)
|
|
--> release
|
|
local window1 = _detalhes:GetInstance (1)
|
|
local window2 = _detalhes:GetInstance (2)
|
|
|
|
if (second_window) then
|
|
window2.baseframe:ClearAllPoints()
|
|
window2.baseframe:SetParent (UIParent)
|
|
window2.rowframe:SetParent (UIParent)
|
|
window2.baseframe:SetPoint ("center", UIParent, "center", 200, 0)
|
|
window2.rowframe:SetPoint ("center", UIParent, "center", 200, 0)
|
|
window2:LockInstance (false)
|
|
window2:SaveMainWindowPosition()
|
|
|
|
local previous_pos = _detalhes.chat_tab_embed.w2_pos
|
|
if (previous_pos) then
|
|
window2:RestorePositionFromPositionTable (previous_pos)
|
|
end
|
|
return
|
|
end
|
|
|
|
window1.baseframe:ClearAllPoints()
|
|
window1.baseframe:SetParent (UIParent)
|
|
window1.rowframe:SetParent (UIParent)
|
|
window1.baseframe:SetPoint ("center", UIParent, "center")
|
|
window1.rowframe:SetPoint ("center", UIParent, "center")
|
|
window1:LockInstance (false)
|
|
window1:SaveMainWindowPosition()
|
|
|
|
local previous_pos = _detalhes.chat_tab_embed.w1_pos
|
|
if (previous_pos) then
|
|
window1:RestorePositionFromPositionTable (previous_pos)
|
|
end
|
|
|
|
if (not _detalhes.chat_tab_embed.single_window and window2) then
|
|
window2.baseframe:ClearAllPoints()
|
|
window2.baseframe:SetParent (UIParent)
|
|
window2.rowframe:SetParent (UIParent)
|
|
window2.baseframe:SetPoint ("center", UIParent, "center", 200, 0)
|
|
window2.rowframe:SetPoint ("center", UIParent, "center", 200, 0)
|
|
window2:LockInstance (false)
|
|
window2:SaveMainWindowPosition()
|
|
|
|
local previous_pos = _detalhes.chat_tab_embed.w2_pos
|
|
if (previous_pos) then
|
|
window2:RestorePositionFromPositionTable (previous_pos)
|
|
end
|
|
end
|
|
end
|
|
|
|
function _detalhes.chat_embed:GetTab (tabname)
|
|
tabname = tabname or _detalhes.chat_tab_embed.tab_name
|
|
for i = 1, 20 do
|
|
local tabtext = _G ["ChatFrame" .. i .. "TabText"]
|
|
if (tabtext) then
|
|
if (tabtext:GetText() == tabname) then
|
|
return _G ["ChatFrame" .. i], _G ["ChatFrame" .. i .. "Tab"], _G ["ChatFrame" .. i .. "Background"], i
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--[[
|
|
--create a tab on chat
|
|
--FCF_OpenNewWindow(name)
|
|
--rename it? perhaps need to hook
|
|
--FCF_SetWindowName(chatFrame, name, true) --FCF_SetWindowName(3, "DDD", true)
|
|
--/run local chatFrame = _G["ChatFrame3"]; FCF_SetWindowName(chatFrame, "DDD", true)
|
|
|
|
--FCF_SetWindowName(frame, name, doNotSave)
|
|
--API SetChatWindowName(frame:GetID(), name); -- set when doNotSave is false
|
|
|
|
-- need to store the chat frame reference
|
|
-- hook set window name and check if the rename was on our window
|
|
|
|
--FCF_Close
|
|
-- ^ when the window is closed
|
|
--]]
|
|
|
|
------------------------------------------------------------------------------------------------------------
|
|
|
|
function _detalhes:SetDeathLogLimit (limit)
|
|
|
|
if (limit and type (limit) == "number" and limit >= 8) then
|
|
_detalhes.deadlog_events = limit
|
|
|
|
local combat = _detalhes.tabela_vigente
|
|
|
|
local wipe = table.wipe
|
|
for player_name, event_table in pairs (combat.player_last_events) do
|
|
if (limit > #event_table) then
|
|
for i = #event_table + 1, limit do
|
|
event_table [i] = {}
|
|
end
|
|
else
|
|
event_table.n = 1
|
|
for _, t in ipairs (event_table) do
|
|
wipe (t)
|
|
end
|
|
end
|
|
end
|
|
|
|
_detalhes:UpdateParserGears()
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------
|
|
|
|
function _detalhes:TrackSpecsNow (track_everything)
|
|
|
|
local spelllist = _detalhes.SpecSpellList
|
|
|
|
if (not track_everything) then
|
|
for _, actor in _detalhes.tabela_vigente[1]:ListActors() do
|
|
if (actor:IsPlayer()) then
|
|
for spellid, spell in pairs (actor:GetSpellList()) do
|
|
if (spelllist [spell.id]) then
|
|
actor.spec = spelllist [spell.id]
|
|
_detalhes.cached_specs [actor.serial] = actor.spec
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
for _, actor in _detalhes.tabela_vigente[2]:ListActors() do
|
|
if (actor:IsPlayer()) then
|
|
for spellid, spell in pairs (actor:GetSpellList()) do
|
|
if (spelllist [spell.id]) then
|
|
actor.spec = spelllist [spell.id]
|
|
_detalhes.cached_specs [actor.serial] = actor.spec
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else
|
|
local combatlist = {}
|
|
for _, combat in ipairs (_detalhes.tabela_historico.tabelas) do
|
|
tinsert (combatlist, combat)
|
|
end
|
|
tinsert (combatlist, _detalhes.tabela_vigente)
|
|
tinsert (combatlist, _detalhes.tabela_overall)
|
|
|
|
for _, combat in ipairs (combatlist) do
|
|
for _, actor in combat[1]:ListActors() do
|
|
if (actor:IsPlayer()) then
|
|
for spellid, spell in pairs (actor:GetSpellList()) do
|
|
if (spelllist [spell.id]) then
|
|
actor.spec = spelllist [spell.id]
|
|
_detalhes.cached_specs [actor.serial] = actor.spec
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
for _, actor in combat[2]:ListActors() do
|
|
if (actor:IsPlayer()) then
|
|
for spellid, spell in pairs (actor:GetSpellList()) do
|
|
if (spelllist [spell.id]) then
|
|
actor.spec = spelllist [spell.id]
|
|
_detalhes.cached_specs [actor.serial] = actor.spec
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
function _detalhes:ResetSpecCache (forced)
|
|
|
|
local isininstance = IsInInstance()
|
|
|
|
if (forced or (not isininstance and not _detalhes.in_group)) then
|
|
table.wipe (_detalhes.cached_specs)
|
|
|
|
if (_detalhes.track_specs) then
|
|
local my_spec = GetSpecialization()
|
|
if (type (my_spec) == "number") then
|
|
local spec_number = GetSpecializationInfo (my_spec)
|
|
if (type (spec_number) == "number") then
|
|
local pguid = UnitGUID (_detalhes.playername)
|
|
if (pguid) then
|
|
_detalhes.cached_specs [pguid] = spec_number
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
elseif (_detalhes.in_group and not isininstance) then
|
|
table.wipe (_detalhes.cached_specs)
|
|
|
|
if (_detalhes.track_specs) then
|
|
if (IsInRaid()) then
|
|
local c_combat_dmg = _detalhes.tabela_vigente [1]
|
|
local c_combat_heal = _detalhes.tabela_vigente [2]
|
|
for i = 1, GetNumGroupMembers(), 1 do
|
|
local name = GetUnitName ("raid" .. i, true)
|
|
local index = c_combat_dmg._NameIndexTable [name]
|
|
if (index) then
|
|
local actor = c_combat_dmg._ActorTable [index]
|
|
if (actor and actor.grupo and actor.spec) then
|
|
_detalhes.cached_specs [actor.serial] = actor.spec
|
|
end
|
|
else
|
|
index = c_combat_heal._NameIndexTable [name]
|
|
if (index) then
|
|
local actor = c_combat_heal._ActorTable [index]
|
|
if (actor and actor.grupo and actor.spec) then
|
|
_detalhes.cached_specs [actor.serial] = actor.spec
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
function _detalhes:SetWindowUpdateSpeed (interval, nosave)
|
|
if (not interval) then
|
|
interval = _detalhes.update_speed
|
|
end
|
|
|
|
if (not nosave) then
|
|
_detalhes.update_speed = interval
|
|
end
|
|
|
|
_detalhes:CancelTimer (_detalhes.atualizador)
|
|
_detalhes.atualizador = _detalhes:ScheduleRepeatingTimer ("AtualizaGumpPrincipal", interval, -1)
|
|
end
|
|
|
|
function _detalhes:SetUseAnimations (enabled, nosave)
|
|
if (enabled == nil) then
|
|
enabled = _detalhes.use_row_animations
|
|
end
|
|
|
|
if (not nosave) then
|
|
_detalhes.use_row_animations = enabled
|
|
end
|
|
|
|
_detalhes.is_using_row_animations = enabled
|
|
end
|
|
|
|
function _detalhes:HavePerformanceProfileEnabled()
|
|
return _detalhes.performance_profile_enabled
|
|
end
|
|
|
|
_detalhes.PerformanceIcons = {
|
|
["RaidFinder"] = {icon = [[Interface\PvPRankBadges\PvPRank15]], color = {1, 1, 1, 1}},
|
|
["Raid15"] = {icon = [[Interface\PvPRankBadges\PvPRank15]], color = {1, .8, 0, 1}},
|
|
["Raid30"] = {icon = [[Interface\PvPRankBadges\PvPRank15]], color = {1, .8, 0, 1}},
|
|
["Mythic"] = {icon = [[Interface\PvPRankBadges\PvPRank15]], color = {1, .4, 0, 1}},
|
|
["Battleground15"] = {icon = [[Interface\PvPRankBadges\PvPRank07]], color = {1, 1, 1, 1}},
|
|
["Battleground40"] = {icon = [[Interface\PvPRankBadges\PvPRank07]], color = {1, 1, 1, 1}},
|
|
["Arena"] = {icon = [[Interface\PvPRankBadges\PvPRank12]], color = {1, 1, 1, 1}},
|
|
["Dungeon"] = {icon = [[Interface\PvPRankBadges\PvPRank01]], color = {1, 1, 1, 1}},
|
|
}
|
|
|
|
function _detalhes:CheckForPerformanceProfile()
|
|
|
|
local type = _detalhes:GetPerformanceRaidType()
|
|
|
|
local profile = _detalhes.performance_profiles [type]
|
|
|
|
if (profile and profile.enabled) then
|
|
_detalhes:SetWindowUpdateSpeed (profile.update_speed, true)
|
|
_detalhes:SetUseAnimations (profile.use_row_animations, true)
|
|
_detalhes:CaptureSet (profile.damage, "damage")
|
|
_detalhes:CaptureSet (profile.heal, "heal")
|
|
_detalhes:CaptureSet (profile.energy, "energy")
|
|
_detalhes:CaptureSet (profile.miscdata, "miscdata")
|
|
_detalhes:CaptureSet (profile.aura, "aura")
|
|
|
|
if (not _detalhes.performance_profile_lastenabled or _detalhes.performance_profile_lastenabled ~= type) then
|
|
_detalhes:InstanceAlert (Loc ["STRING_OPTIONS_PERFORMANCE_PROFILE_LOAD"] .. type, {_detalhes.PerformanceIcons [type].icon, 14, 14, false, 0, 1, 0, 1, unpack (_detalhes.PerformanceIcons [type].color)} , 5, {_detalhes.empty_function})
|
|
end
|
|
|
|
_detalhes.performance_profile_enabled = type
|
|
_detalhes.performance_profile_lastenabled = type
|
|
else
|
|
_detalhes:SetWindowUpdateSpeed (_detalhes.update_speed)
|
|
_detalhes:SetUseAnimations (_detalhes.use_row_animations)
|
|
_detalhes:CaptureSet (_detalhes.capture_real ["damage"], "damage")
|
|
_detalhes:CaptureSet (_detalhes.capture_real ["heal"], "heal")
|
|
_detalhes:CaptureSet (_detalhes.capture_real ["energy"], "energy")
|
|
_detalhes:CaptureSet (_detalhes.capture_real ["miscdata"], "miscdata")
|
|
_detalhes:CaptureSet (_detalhes.capture_real ["aura"], "aura")
|
|
_detalhes.performance_profile_enabled = nil
|
|
end
|
|
|
|
end
|
|
|
|
function _detalhes:GetPerformanceRaidType()
|
|
|
|
local name, type, difficulty, difficultyName, maxPlayers, playerDifficulty, isDynamicInstance, mapID, instanceGroupSize = GetInstanceInfo()
|
|
|
|
if (type == "none") then
|
|
return nil
|
|
end
|
|
|
|
if (type == "pvp") then
|
|
if (maxPlayers == 40) then
|
|
return "Battleground40"
|
|
elseif (maxPlayers == 15) then
|
|
return "Battleground15"
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
|
|
if (type == "arena") then
|
|
return "Arena"
|
|
end
|
|
|
|
if (type == "raid") then
|
|
--mythic
|
|
if (difficulty == 15) then
|
|
return "Mythic"
|
|
end
|
|
|
|
--raid finder
|
|
if (difficulty == 7) then
|
|
return "RaidFinder"
|
|
end
|
|
|
|
--flex
|
|
if (difficulty == 14) then
|
|
if (GetNumGroupMembers() > 15) then
|
|
return "Raid30"
|
|
else
|
|
return "Raid15"
|
|
end
|
|
end
|
|
|
|
--normal heroic
|
|
if (maxPlayers == 10) then
|
|
return "Raid15"
|
|
elseif (maxPlayers == 25) then
|
|
return "Raid30"
|
|
end
|
|
end
|
|
|
|
if (type == "party") then
|
|
return "Dungeon"
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
|
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> background tasks
|
|
|
|
|
|
local background_tasks = {}
|
|
local task_timers = {
|
|
["LOW"] = 30,
|
|
["MEDIUM"] = 18,
|
|
["HIGH"] = 10,
|
|
}
|
|
|
|
function _detalhes:RegisterBackgroundTask (name, func, priority, ...)
|
|
|
|
assert (type (self) == "table", "RegisterBackgroundTask 'self' must be a table.")
|
|
assert (type (name) == "string", "RegisterBackgroundTask param #1 must be a string.")
|
|
if (type (func) == "string") then
|
|
assert (type (self [func]) == "function", "RegisterBackgroundTask param #2 function not found on main object.")
|
|
else
|
|
assert (type (func) == "function", "RegisterBackgroundTask param #2 expect a function or function name.")
|
|
end
|
|
|
|
priority = priority or "LOW"
|
|
priority = string.upper (priority)
|
|
if (not task_timers [priority]) then
|
|
priority = "LOW"
|
|
end
|
|
|
|
if (background_tasks [name]) then
|
|
background_tasks [name].func = func
|
|
background_tasks [name].priority = priority
|
|
background_tasks [name].args = {...}
|
|
background_tasks [name].args_amt = select ("#", ...)
|
|
background_tasks [name].object = self
|
|
return
|
|
else
|
|
background_tasks [name] = {func = func, lastexec = time(), priority = priority, nextexec = time() + task_timers [priority] * 60, args = {...}, args_amt = select ("#", ...), object = self}
|
|
end
|
|
end
|
|
|
|
function _detalhes:UnregisterBackgroundTask (name)
|
|
background_tasks [name] = nil
|
|
end
|
|
|
|
function _detalhes:DoBackgroundTasks()
|
|
if (_detalhes:GetZoneType() ~= "none" or _detalhes:InGroup()) then
|
|
return
|
|
end
|
|
|
|
local t = time()
|
|
|
|
for taskName, taskTable in pairs (background_tasks) do
|
|
if (t > taskTable.nextexec) then
|
|
if (type (taskTable.func) == "string") then
|
|
taskTable.object [taskTable.func] (taskTable.object, unpack (taskTable.args, 1, taskTable.args_amt))
|
|
else
|
|
taskTable.func (unpack (taskTable.args, 1, taskTable.args_amt))
|
|
end
|
|
|
|
taskTable.nextexec = random (30, 120) + t + (task_timers [taskTable.priority] * 60)
|
|
end
|
|
end
|
|
end
|
|
|
|
_detalhes.background_tasks_loop = _detalhes:ScheduleRepeatingTimer ("DoBackgroundTasks", 120)
|
|
|
|
|
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> storage stuff ~storage
|
|
|
|
--global database
|
|
_detalhes.storage = {}
|
|
|
|
function _detalhes.storage:OpenRaidStorage()
|
|
--> check if the storage is already loaded
|
|
if (not IsAddOnLoaded ("Details_DataStorage")) then
|
|
local loaded, reason = LoadAddOn ("Details_DataStorage")
|
|
if (not loaded) then
|
|
return
|
|
end
|
|
end
|
|
|
|
--> get the storage table
|
|
local db = DetailsDataStorage
|
|
|
|
if (not db and _detalhes.CreateStorageDB) then
|
|
db = _detalhes:CreateStorageDB()
|
|
if (not db) then
|
|
return
|
|
end
|
|
elseif (not db) then
|
|
return
|
|
end
|
|
|
|
return db
|
|
end
|
|
|
|
function _detalhes.storage:GetBestFromGuild (diff, encounter_id, role)
|
|
local db = _detalhes.storage:OpenRaidStorage()
|
|
|
|
local best = 0
|
|
local bestplayername
|
|
local onencounter
|
|
|
|
if (not role) then
|
|
role = "damage"
|
|
end
|
|
role = string.lower (role)
|
|
if (role == "damager") then
|
|
role = "damage"
|
|
elseif (role == "healer") then
|
|
role = "healing"
|
|
end
|
|
|
|
local table = db [diff]
|
|
if (table) then
|
|
local encounters = table [encounter_id]
|
|
if (encounters) then
|
|
for index, encounter in ipairs (encounters) do
|
|
|
|
local players = encounter [role]
|
|
if (players) then
|
|
for playername, t in pairs (players) do
|
|
if (t[1] > best) then
|
|
best = t [1]
|
|
bestplayername = playername
|
|
onencounter = encounter
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return best, bestplayername, onencounter
|
|
end
|
|
|
|
function _detalhes.storage:GetBestFromPlayer (diff, encounter_id, role, playername)
|
|
local db = _detalhes.storage:OpenRaidStorage()
|
|
|
|
local best
|
|
local onencounter
|
|
|
|
if (not role) then
|
|
role = "damage"
|
|
end
|
|
role = string.lower (role)
|
|
if (role == "damager") then
|
|
role = "damage"
|
|
elseif (role == "healer") then
|
|
role = "healing"
|
|
end
|
|
|
|
local table = db [diff]
|
|
if (table) then
|
|
local encounters = table [encounter_id]
|
|
if (encounters) then
|
|
for index, encounter in ipairs (encounters) do
|
|
local player = encounter [role] and encounter [role] [playername]
|
|
if (player) then
|
|
if (best) then
|
|
if (player[1] > best[1]) then
|
|
onencounter = encounter
|
|
best = player
|
|
end
|
|
else
|
|
onencounter = encounter
|
|
best = player
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return best, onencounter
|
|
end
|
|
|
|
function _detalhes.storage:DBGuildSync()
|
|
|
|
_detalhes:SendGuildData ("GS", "R")
|
|
|
|
end
|
|
|
|
local OnlyFromCurrentRaidTier = true
|
|
local encounter_is_current_tier = function (encounterID)
|
|
if (OnlyFromCurrentRaidTier) then
|
|
local mapID = _detalhes:GetInstanceIdFromEncounterId (encounterID)
|
|
if (mapID) then
|
|
if (_detalhes.current_raid_tier_mapid ~= mapID) then
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
local have_encounter = function (db, ID)
|
|
local minTime = ID - 120
|
|
local maxTime = ID + 120
|
|
|
|
for diff, diffTable in pairs (db or {}) do
|
|
if (type (diffTable) == "table") then
|
|
for encounterID, encounterTable in pairs (diffTable) do
|
|
for index, encounter in ipairs (encounterTable) do
|
|
--check if the encounter fits in the timespam window
|
|
if (encounter.time >= minTime and encounter.time <= maxTime) then
|
|
return true
|
|
end
|
|
if (encounter.servertime) then
|
|
if (encounter.servertime >= minTime and encounter.servertime <= maxTime) then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local have_recent_requested_encounter = function (ID)
|
|
local minTime = ID - 120
|
|
local maxTime = ID + 120
|
|
|
|
for requestedID, _ in pairs (_detalhes.RecentRequestedIDs) do
|
|
if (requestedID >= minTime and requestedID <= maxTime) then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
--remote call RoS
|
|
function _detalhes.storage:GetIDsToGuildSync()
|
|
local db = _detalhes.storage:OpenRaidStorage()
|
|
local IDs = {}
|
|
|
|
--build the encounter ID list
|
|
for diff, diffTable in pairs (db or {}) do
|
|
if (type (diffTable) == "table") then
|
|
for encounterID, encounterTable in pairs (diffTable) do
|
|
if (encounter_is_current_tier (encounterID)) then
|
|
for index, encounter in ipairs (encounterTable) do
|
|
if (encounter.servertime) then
|
|
tinsert (IDs, encounter.servertime)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg ("(debug) [RoS-EncounterSync] sending " .. #IDs .. " IDs.")
|
|
end
|
|
|
|
return IDs
|
|
end
|
|
|
|
|
|
--local call RoC - received the encounter IDS - need to know which fights is missing
|
|
function _detalhes.storage:CheckMissingIDsToGuildSync (IDsList)
|
|
local db = _detalhes.storage:OpenRaidStorage()
|
|
|
|
if (type (IDsList) ~= "table") then
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg ("(debug) [RoS-EncounterSync] RoC IDsList isn't a table.")
|
|
end
|
|
return
|
|
end
|
|
|
|
--this will prevent to request the same fight from multiple people
|
|
_detalhes.RecentRequestedIDs = _detalhes.RecentRequestedIDs or {}
|
|
|
|
--store the IDs which need to be sync
|
|
local RequestIDs = {}
|
|
|
|
--check missing IDs
|
|
for index, ID in ipairs (IDsList) do
|
|
if (not have_encounter (db, ID)) then
|
|
if (not have_recent_requested_encounter (ID)) then
|
|
tinsert (RequestIDs, ID)
|
|
_detalhes.RecentRequestedIDs [ID] = true
|
|
end
|
|
end
|
|
end
|
|
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg ("(debug) [RoC-EncounterSync] RoS found " .. #RequestIDs .. " encounters out dated.")
|
|
end
|
|
|
|
return RequestIDs
|
|
end
|
|
|
|
--remote call RoS - build the encounter list from the IDsList
|
|
function _detalhes.storage:BuildEncounterDataToGuildSync (IDsList)
|
|
local db = _detalhes.storage:OpenRaidStorage()
|
|
|
|
if (type (IDsList) ~= "table") then
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg ("(debug) [RoS-EncounterSync] IDsList isn't a table.")
|
|
end
|
|
return
|
|
end
|
|
|
|
local EncounterList = {}
|
|
local CurrentTable = {}
|
|
tinsert (EncounterList, CurrentTable)
|
|
|
|
local AmtToSend = 0
|
|
local MaxAmount = 0
|
|
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg ("(debug) [RoS-EncounterSync] the client requested " .. #IDsList .. " encounters.")
|
|
end
|
|
|
|
for index, ID in ipairs (IDsList) do
|
|
|
|
for diff, diffTable in pairs (db or {}) do
|
|
if (type (diffTable) == "table") then
|
|
for encounterID, encounterTable in pairs (diffTable) do
|
|
for index, encounter in ipairs (encounterTable) do
|
|
|
|
if (ID == encounter.time or ID == encounter.servertime) then --> the time here is always exactly
|
|
--send this encounter
|
|
CurrentTable [diff] = CurrentTable [diff] or {}
|
|
CurrentTable [diff] [encounterID] = CurrentTable [diff] [encounterID] or {}
|
|
|
|
tinsert (CurrentTable [diff] [encounterID], encounter)
|
|
|
|
AmtToSend = AmtToSend + 1
|
|
MaxAmount = MaxAmount + 1
|
|
|
|
if (MaxAmount == 3) then
|
|
CurrentTable = {}
|
|
tinsert (EncounterList, CurrentTable)
|
|
MaxAmount = 0
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg ("(debug) [RoS-EncounterSync] sending " .. AmtToSend .. " encounters.")
|
|
end
|
|
|
|
return EncounterList
|
|
end
|
|
|
|
|
|
--local call RoC - add the fights to the client db
|
|
function _detalhes.storage:AddGuildSyncData (data, source)
|
|
local db = _detalhes.storage:OpenRaidStorage()
|
|
|
|
local AddedAmount = 0
|
|
_detalhes.LastGuildSyncReceived = GetTime()
|
|
|
|
for diff, diffTable in pairs (data) do
|
|
if (type (diff) == "number" and type (diffTable) == "table") then
|
|
for encounterID, encounterTable in pairs (diffTable) do
|
|
if (type (encounterID) == "number" and type (encounterTable) == "table") then
|
|
for index, encounter in ipairs (encounterTable) do
|
|
--validate the encounter
|
|
if (type (encounter.servertime) == "number" and type (encounter.time) == "number" and type (encounter.guild) == "string" and type (encounter.date) == "string" and type (encounter.healing) == "table" and type (encounter.elapsed) == "number" and type (encounter.damage) == "table") then
|
|
--check if the encounter is from the current raiding tier
|
|
if (encounter_is_current_tier (encounterID)) then
|
|
--check if this encounter already has been added from another sync
|
|
if (not have_encounter (db, encounter.servertime)) then
|
|
db [diff] = db [diff] or {}
|
|
db [diff] [encounterID] = db [diff] [encounterID] or {}
|
|
|
|
tinsert (db [diff] [encounterID], encounter)
|
|
|
|
if (_G.DetailsRaidHistoryWindow and _G.DetailsRaidHistoryWindow:IsShown()) then
|
|
_G.DetailsRaidHistoryWindow:Refresh()
|
|
end
|
|
|
|
AddedAmount = AddedAmount + 1
|
|
else
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg ("(debug) [RoS-EncounterSync] received a duplicated encounter table.")
|
|
end
|
|
end
|
|
else
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg ("(debug) [RoS-EncounterSync] received an old tier encounter.")
|
|
end
|
|
end
|
|
else
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg ("(debug) [RoS-EncounterSync] received an invalid encounter table.")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg ("(debug) [RoS-EncounterSync] added " .. AddedAmount .. " to database.")
|
|
end
|
|
|
|
if (_G.DetailsRaidHistoryWindow and _G.DetailsRaidHistoryWindow:IsShown()) then
|
|
_G.DetailsRaidHistoryWindow:UpdateDropdowns()
|
|
_G.DetailsRaidHistoryWindow:Refresh()
|
|
end
|
|
end
|
|
|
|
function _detalhes.storage:ListDiffs()
|
|
local db = _detalhes.storage:OpenRaidStorage()
|
|
local t = {}
|
|
for diff, _ in pairs (db) do
|
|
tinsert (t, diff)
|
|
end
|
|
return t
|
|
end
|
|
|
|
function _detalhes.storage:ListEncounters (diff)
|
|
local db = _detalhes.storage:OpenRaidStorage()
|
|
|
|
local t = {}
|
|
if (diff) then
|
|
local table = db [diff]
|
|
if (table) then
|
|
for encounter_id, _ in pairs (table) do
|
|
tinsert (t, {diff, encounter_id})
|
|
end
|
|
end
|
|
else
|
|
for diff, table in pairs (db) do
|
|
for encounter_id, _ in pairs (table) do
|
|
tinsert (t, {diff, encounter_id})
|
|
end
|
|
end
|
|
end
|
|
|
|
return t
|
|
end
|
|
|
|
function _detalhes.storage:GetPlayerData (diff, encounter_id, playername)
|
|
local db = _detalhes.storage:OpenRaidStorage()
|
|
|
|
local t = {}
|
|
assert (type (playername) == "string", "PlayerName must be a string.")
|
|
|
|
|
|
if (not diff) then
|
|
for diff, table in pairs (db) do
|
|
if (encounter_id) then
|
|
local encounters = table [encounter_id]
|
|
if (encounters) then
|
|
for i = 1, #encounters do
|
|
local encounter = encounters [i]
|
|
local player = encounter.healing [playername] or encounter.damage [playername]
|
|
if (player) then
|
|
tinsert (t, player)
|
|
end
|
|
end
|
|
end
|
|
else
|
|
for encounter_id, encounters in pairs (table) do
|
|
for i = 1, #encounters do
|
|
local encounter = encounters [i]
|
|
local player = encounter.healing [playername] or encounter.damage [playername]
|
|
if (player) then
|
|
tinsert (t, player)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else
|
|
local table = db [diff]
|
|
if (table) then
|
|
if (encounter_id) then
|
|
local encounters = table [encounter_id]
|
|
if (encounters) then
|
|
for i = 1, #encounters do
|
|
local encounter = encounters [i]
|
|
local player = encounter.healing [playername] or encounter.damage [playername]
|
|
if (player) then
|
|
tinsert (t, player)
|
|
end
|
|
end
|
|
end
|
|
else
|
|
for encounter_id, encounters in pairs (table) do
|
|
for i = 1, #encounters do
|
|
local encounter = encounters [i]
|
|
local player = encounter.healing [playername] or encounter.damage [playername]
|
|
if (player) then
|
|
tinsert (t, player)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return t
|
|
end
|
|
|
|
function _detalhes.storage:GetEncounterData (diff, encounter_id, guild)
|
|
local db = _detalhes.storage:OpenRaidStorage()
|
|
|
|
if (not diff) then
|
|
return db
|
|
end
|
|
|
|
local data = db [diff]
|
|
|
|
assert (data, "Difficulty not found. Use: 14, 15 or 16.")
|
|
assert (type (encounter_id) == "number", "EncounterId must be a number.")
|
|
|
|
data = data [encounter_id]
|
|
|
|
local t = {}
|
|
|
|
if (not data) then
|
|
return t
|
|
end
|
|
|
|
for i = 1, #data do
|
|
local encounter = data [i]
|
|
|
|
if (guild) then
|
|
if (encounter.guild == guild) then
|
|
tinsert (t, encounter)
|
|
end
|
|
else
|
|
tinsert (t, encounter)
|
|
end
|
|
end
|
|
|
|
return t
|
|
end
|
|
|
|
function _detalhes:StoreEncounter (combat)
|
|
|
|
combat = combat or _detalhes.tabela_vigente
|
|
|
|
if (not combat) then
|
|
if (_detalhes.debug) then
|
|
print ("|cFFFFFF00Details! Storage|r: combat not found.")
|
|
end
|
|
return
|
|
end
|
|
|
|
local name, type, difficulty, difficultyName, maxPlayers, playerDifficulty, isDynamicInstance, mapID, instanceGroupSize = GetInstanceInfo()
|
|
|
|
if (not store_instances [mapID]) then
|
|
if (_detalhes.debug) then
|
|
print ("|cFFFFFF00Details! Storage|r: instance not allowed.")
|
|
end
|
|
return
|
|
end
|
|
|
|
local boss_info = combat:GetBossInfo()
|
|
local encounter_id = boss_info and boss_info.id
|
|
|
|
if (not encounter_id) then
|
|
if (_detalhes.debug) then
|
|
print ("|cFFFFFF00Details! Storage|r: encounter ID not found.")
|
|
end
|
|
return
|
|
end
|
|
|
|
local diff = combat:GetDifficulty()
|
|
|
|
--> check for heroic and mythic
|
|
if (storageDebug or (diff == 15 or diff == 16)) then --test on raid finder ' or diff == 17' -- normal mode: diff == 14 or
|
|
|
|
--> check the guild name
|
|
local match = 0
|
|
local guildName = select (1, GetGuildInfo ("player"))
|
|
local raid_size = GetNumGroupMembers() or 0
|
|
|
|
if (guildName) then
|
|
for i = 1, raid_size do
|
|
local gName = select (1, GetGuildInfo ("raid" .. i)) or ""
|
|
if (gName == guildName) then
|
|
match = match + 1
|
|
end
|
|
end
|
|
|
|
if (match < raid_size * 0.75 and not storageDebug) then
|
|
if (_detalhes.debug) then
|
|
print ("|cFFFFFF00Details! Storage|r: can't save the encounter, need at least 75% of players be from your guild.")
|
|
end
|
|
return
|
|
end
|
|
else
|
|
if (_detalhes.debug) then
|
|
print ("|cFFFFFF00Details! Storage|r: can't save the encounter, need at least 75% of players be from your guild.")
|
|
end
|
|
return
|
|
end
|
|
|
|
--> check if the storage is already loaded
|
|
if (not IsAddOnLoaded ("Details_DataStorage")) then
|
|
local loaded, reason = LoadAddOn ("Details_DataStorage")
|
|
if (not loaded) then
|
|
if (_detalhes.debug) then
|
|
print ("|cFFFFFF00Details! Storage|r: can't save the encounter, couldn't load DataStorage, may be the addon is disabled.")
|
|
end
|
|
return
|
|
end
|
|
end
|
|
|
|
--> get the storage table
|
|
local db = DetailsDataStorage
|
|
|
|
if (not db and _detalhes.CreateStorageDB) then
|
|
db = _detalhes:CreateStorageDB()
|
|
if (not db) then
|
|
return
|
|
end
|
|
elseif (not db) then
|
|
return
|
|
end
|
|
|
|
local diff_storage = db [diff]
|
|
if (not diff_storage) then
|
|
db [diff] = {}
|
|
diff_storage = db [diff]
|
|
end
|
|
|
|
local encounter_database = diff_storage [encounter_id]
|
|
if (not encounter_database) then
|
|
diff_storage [encounter_id] = {}
|
|
encounter_database = diff_storage [encounter_id]
|
|
end
|
|
|
|
local this_combat_data = {
|
|
damage = {},
|
|
healing = {},
|
|
date = date ("%H:%M %d/%m/%y"),
|
|
time = time(),
|
|
servertime = GetServerTime(),
|
|
elapsed = combat:GetCombatTime(),
|
|
guild = guildName,
|
|
}
|
|
|
|
local damage_container_hash = combat [1]._NameIndexTable
|
|
local damage_container_pool = combat [1]._ActorTable
|
|
|
|
local healing_container_hash = combat [2]._NameIndexTable
|
|
local healing_container_pool = combat [2]._ActorTable
|
|
|
|
for i = 1, GetNumGroupMembers() do
|
|
|
|
local role = UnitGroupRolesAssigned ("raid" .. i)
|
|
|
|
if (UnitIsInMyGuild ("raid" .. i)) then
|
|
if (role == "DAMAGER" or role == "TANK") then
|
|
local player_name, player_realm = UnitName ("raid" .. i)
|
|
if (player_realm and player_realm ~= "") then
|
|
player_name = player_name .. "-" .. player_realm
|
|
end
|
|
|
|
local _, _, class = UnitClass (player_name)
|
|
|
|
local damage_actor = damage_container_pool [damage_container_hash [player_name]]
|
|
if (damage_actor) then
|
|
local guid = UnitGUID (player_name) or UnitGUID (UnitName ("raid" .. i))
|
|
this_combat_data.damage [player_name] = {floor (damage_actor.total), _detalhes.item_level_pool [guid] and _detalhes.item_level_pool [guid].ilvl or 0, class or 0}
|
|
end
|
|
elseif (role == "HEALER") then
|
|
local player_name, player_realm = UnitName ("raid" .. i)
|
|
if (player_realm and player_realm ~= "") then
|
|
player_name = player_name .. "-" .. player_realm
|
|
end
|
|
|
|
local _, _, class = UnitClass (player_name)
|
|
|
|
local heal_actor = healing_container_pool [healing_container_hash [player_name]]
|
|
if (heal_actor) then
|
|
local guid = UnitGUID (player_name) or UnitGUID (UnitName ("raid" .. i))
|
|
this_combat_data.healing [player_name] = {floor (heal_actor.total), _detalhes.item_level_pool [guid] and _detalhes.item_level_pool [guid].ilvl or 0, class or 0}
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
tinsert (encounter_database, this_combat_data)
|
|
|
|
print ("|cFFFFFF00Details! Storage|r: encounter saved!")
|
|
|
|
local myrole = UnitGroupRolesAssigned ("player")
|
|
local mybest, onencounter = _detalhes.storage:GetBestFromPlayer (diff, encounter_id, myrole, _detalhes.playername)
|
|
|
|
--print (myrole, mybest and mybest[1], mybest and mybest[2], mybest and mybest[3], onencounter and onencounter.date)
|
|
|
|
if (mybest) then
|
|
local d_one = 0
|
|
if (myrole == "DAMAGER" or myrole == "TANK") then
|
|
d_one = combat (1, _detalhes.playername) and combat (1, _detalhes.playername).total
|
|
elseif (myrole == "HEALER") then
|
|
d_one = combat (2, _detalhes.playername) and combat (2, _detalhes.playername).total
|
|
end
|
|
|
|
if (mybest[1] > d_one) then
|
|
print (Loc ["STRING_DETAILS1"] .. format (Loc ["STRING_SCORE_NOTBEST"], _detalhes:comma_value (d_one), _detalhes:comma_value (mybest[1]), onencounter.date, mybest[2]))
|
|
else
|
|
print (Loc ["STRING_DETAILS1"] .. format (Loc ["STRING_SCORE_BEST"], _detalhes:comma_value (d_one)))
|
|
end
|
|
end
|
|
|
|
--guild best
|
|
local amount, playerName, encounterObject = _detalhes.storage:GetBestFromGuild (diff, encounter_id, myrole)
|
|
if (amount > 0) then
|
|
--> player got the high score on his guild
|
|
|
|
end
|
|
|
|
local lower_instance = _detalhes:GetLowerInstanceNumber()
|
|
if (lower_instance) then
|
|
local instance = _detalhes:GetInstance (lower_instance)
|
|
if (instance) then
|
|
local my_role = UnitGroupRolesAssigned ("player")
|
|
if (my_role == "TANK") then
|
|
my_role = "DAMAGER"
|
|
end
|
|
local raid_name = GetInstanceInfo()
|
|
local func = {_detalhes.OpenRaidHistoryWindow, _detalhes, raid_name, encounter_id, diff, my_role, guildName, 2, UnitName ("player")}
|
|
local icon = {[[Interface\AddOns\Details\images\icons]], 16, 16, false, 434/512, 466/512, 243/512, 273/512}
|
|
instance:InstanceAlert ("Boss Defeated, Open History! ", icon, 40, func, true)
|
|
end
|
|
end
|
|
else
|
|
if (_detalhes.debug) then
|
|
print ("|cFFFFFF00Details! Storage|r: raid difficulty must be heroic or mythic.")
|
|
end
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> inspect stuff
|
|
|
|
_detalhes.ilevel = {}
|
|
local ilvl_core = _detalhes:CreateEventListener()
|
|
ilvl_core.amt_inspecting = 0
|
|
_detalhes.ilevel.core = ilvl_core
|
|
|
|
ilvl_core:RegisterEvent ("GROUP_ONENTER", "OnEnter")
|
|
ilvl_core:RegisterEvent ("GROUP_ONLEAVE", "OnLeave")
|
|
ilvl_core:RegisterEvent ("COMBAT_PLAYER_ENTER", "EnterCombat")
|
|
ilvl_core:RegisterEvent ("COMBAT_PLAYER_LEAVE", "LeaveCombat")
|
|
ilvl_core:RegisterEvent ("ZONE_TYPE_CHANGED", "ZoneChanged")
|
|
|
|
local inspecting = {}
|
|
ilvl_core.forced_inspects = {}
|
|
|
|
function ilvl_core:HasQueuedInspec (unitName)
|
|
local guid = UnitGUID (unitName)
|
|
if (guid) then
|
|
return ilvl_core.forced_inspects [guid]
|
|
end
|
|
end
|
|
|
|
local inspect_frame = CreateFrame ("frame")
|
|
inspect_frame:RegisterEvent ("INSPECT_READY")
|
|
|
|
local two_hand = {
|
|
["INVTYPE_2HWEAPON"] = true,
|
|
["INVTYPE_RANGED"] = true,
|
|
["INVTYPE_RANGEDRIGHT"] = true,
|
|
}
|
|
|
|
local MAX_INSPECT_AMOUNT = 1
|
|
local MIN_ILEVEL_TO_STORE = 50
|
|
local LOOP_TIME = 7
|
|
|
|
--if the item is an artifact off-hand, get the item level of the main hand
|
|
local artifact_offhands = {
|
|
["133959"] = true, --mage fire
|
|
["128293"] = true, --dk frost
|
|
["127830"] = true, --dh havoc
|
|
["128831"] = true, --dh vengeance
|
|
["128859"] = true, --druid feral
|
|
["128822"] = true, --druid guardian
|
|
["133948"] = true, --monk ww
|
|
["133958"] = true, --priest shadow
|
|
["128869"] = true, --rogue assassination
|
|
["134552"] = true, --rogue outlaw
|
|
["128479"] = true, --rogue subtlety
|
|
["128936"] = true, --shaman elemental
|
|
["128873"] = true, --shaman en
|
|
["128934"] = true, --shaman resto
|
|
}
|
|
|
|
--if the artifact has its main piece as the offhand, when scaning the main hand get the ilevel of the off-hand.
|
|
local offhand_ismain = {
|
|
["137246"] = true, --warlock demo / spine of thalkiel
|
|
["128288"] = true, --warrior prot / scaleshard
|
|
["128867"] = true, --paladin prot / oathseeker
|
|
}
|
|
|
|
function _detalhes:IlvlFromNetwork (player, realm, core, ilvl)
|
|
local guid = UnitGUID (player .. "-" .. realm)
|
|
if (not guid) then
|
|
guid = UnitGUID (player)
|
|
if (not guid) then
|
|
return
|
|
end
|
|
end
|
|
|
|
_detalhes.item_level_pool [guid] = {name = player, ilvl = ilvl, time = time()}
|
|
end
|
|
|
|
--> test
|
|
--/run _detalhes.ilevel:CalcItemLevel ("player", UnitGUID("player"), true)
|
|
--/run wipe (_detalhes.item_level_pool)
|
|
function ilvl_core:CalcItemLevel (unitid, guid, shout)
|
|
|
|
if (type (unitid) == "table") then
|
|
shout = unitid [3]
|
|
guid = unitid [2]
|
|
unitid = unitid [1]
|
|
end
|
|
|
|
if (CheckInteractDistance (unitid, 1)) then
|
|
|
|
--> 16 = all itens including main and off hand
|
|
local item_amount = 16
|
|
local item_level = 0
|
|
local failed = 0
|
|
|
|
for equip_id = 1, 17 do
|
|
|
|
if (equip_id ~= 4) then --shirt slot
|
|
local item = GetInventoryItemLink (unitid, equip_id)
|
|
if (item) then
|
|
local _, _, itemRarity, iLevel, _, _, _, _, equipSlot = GetItemInfo (item)
|
|
if (iLevel) then
|
|
|
|
--local _, _, _, _, _, _, _, _, _, _, _, upgradeTypeID, _, numBonusIDs, bonusID1, bonusID2 = strsplit (":", item)
|
|
--> upgrades handle by LibItemUpgradeInfo-1.0
|
|
--> http://www.wowace.com/addons/libitemupgradeinfo-1-0/
|
|
|
|
if (equip_id == 16) then --main hand
|
|
local itemId = select (2, strsplit (":", item))
|
|
--print (itemId, offhand_ismain [itemId], UnitName (unitid))
|
|
--128867 nil Lithedora EmeraldDream
|
|
if (offhand_ismain [itemId]) then
|
|
local offHand = GetInventoryItemLink (unitid, 17)
|
|
if (offHand) then
|
|
local iName, _, itemRarity, offHandILevel, _, _, _, _, equipSlot = GetItemInfo (offHand)
|
|
if (offHandILevel) then
|
|
item = offHand
|
|
iLevel = offHandILevel
|
|
end
|
|
end
|
|
end
|
|
|
|
elseif (equip_id == 17) then --off-hand
|
|
local itemId = select (2, strsplit (":", item))
|
|
if (artifact_offhands [itemId]) then
|
|
local mainHand = GetInventoryItemLink (unitid, 16)
|
|
if (mainHand) then
|
|
local iName, _, itemRarity, mainHandILevel, _, _, _, _, equipSlot = GetItemInfo (mainHand)
|
|
if (iLevel) then
|
|
item = mainHand
|
|
iLevel = mainHandILevel
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if (ItemUpgradeInfo) then
|
|
local ilvl = ItemUpgradeInfo:GetUpgradedItemLevel (item)
|
|
item_level = item_level + (ilvl or iLevel)
|
|
else
|
|
item_level = item_level + iLevel
|
|
end
|
|
|
|
--> timewarped
|
|
--[[
|
|
if (upgradeTypeID == "512" and bonusID1 == "615") then
|
|
item_level = item_level + 660
|
|
if (bonusID2 == "656") then
|
|
item_level = item_level + 15
|
|
end
|
|
else
|
|
item_level = item_level + iLevel
|
|
end
|
|
--]]
|
|
|
|
--> 16 = main hand 17 = off hand
|
|
--> if using a two-hand, ignore the off hand slot
|
|
if (equip_id == 16 and two_hand [equipSlot]) then
|
|
item_amount = 15
|
|
break
|
|
end
|
|
end
|
|
else
|
|
failed = failed + 1
|
|
if (failed > 2) then
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local average = item_level / item_amount
|
|
--print (UnitName (unitid), "ILVL:", average, unitid, "items:", item_amount)
|
|
|
|
--> register
|
|
if (average > 0) then
|
|
if (shout) then
|
|
_detalhes:Msg (name .. " item level: " .. average)
|
|
end
|
|
|
|
if (average > MIN_ILEVEL_TO_STORE) then
|
|
local name = _detalhes:GetCLName (unitid)
|
|
_detalhes.item_level_pool [guid] = {name = name, ilvl = average, time = time()}
|
|
end
|
|
end
|
|
|
|
local spec = GetInspectSpecialization (unitid)
|
|
if (spec and spec ~= 0) then
|
|
_detalhes.cached_specs [guid] = spec
|
|
end
|
|
|
|
--------------------------------------------------------------------------------------------------------
|
|
|
|
local talents = {}
|
|
for i = 1, 7 do
|
|
for o = 1, 3 do
|
|
local talentID, name, texture, selected, available = GetTalentInfo (i, o, 1, true, unitid)
|
|
if (selected) then
|
|
tinsert (talents, talentID)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
if (talents [1]) then
|
|
_detalhes.cached_talents [guid] = talents
|
|
--print (UnitName (unitid), "talents:", unpack (talents))
|
|
end
|
|
|
|
--------------------------------------------------------------------------------------------------------
|
|
|
|
if (ilvl_core.forced_inspects [guid]) then
|
|
if (type (ilvl_core.forced_inspects [guid].callback) == "function") then
|
|
local okey, errortext = pcall (ilvl_core.forced_inspects[guid].callback, guid, unitid, ilvl_core.forced_inspects[guid].param1, ilvl_core.forced_inspects[guid].param2)
|
|
if (not okey) then
|
|
_detalhes:Msg ("Error on QueryInspect callback: " .. errortext)
|
|
end
|
|
end
|
|
ilvl_core.forced_inspects [guid] = nil
|
|
end
|
|
|
|
--------------------------------------------------------------------------------------------------------
|
|
|
|
end
|
|
end
|
|
_detalhes.ilevel.CalcItemLevel = ilvl_core.CalcItemLevel
|
|
|
|
inspect_frame:SetScript ("OnEvent", function (self, event, ...)
|
|
local guid = select (1, ...)
|
|
|
|
if (inspecting [guid]) then
|
|
local unitid, cancel_tread = inspecting [guid] [1], inspecting [guid] [2]
|
|
inspecting [guid] = nil
|
|
ilvl_core.amt_inspecting = ilvl_core.amt_inspecting - 1
|
|
|
|
ilvl_core:CancelTimer (cancel_tread)
|
|
|
|
--> do inspect stuff
|
|
if (unitid) then
|
|
local t = {unitid, guid}
|
|
--ilvl_core:ScheduleTimer ("CalcItemLevel", 0.5, t)
|
|
ilvl_core:ScheduleTimer ("CalcItemLevel", 0.5, t)
|
|
ilvl_core:ScheduleTimer ("CalcItemLevel", 2, t)
|
|
ilvl_core:ScheduleTimer ("CalcItemLevel", 4, t)
|
|
ilvl_core:ScheduleTimer ("CalcItemLevel", 8, t)
|
|
end
|
|
end
|
|
end)
|
|
|
|
function ilvl_core:InspectTimeOut (guid)
|
|
inspecting [guid] = nil
|
|
ilvl_core.amt_inspecting = ilvl_core.amt_inspecting - 1
|
|
end
|
|
|
|
function ilvl_core:ReGetItemLevel (t)
|
|
local unitid, guid, is_forced, try_number = unpack (t)
|
|
return ilvl_core:GetItemLevel (unitid, guid, is_forced, try_number)
|
|
end
|
|
|
|
function ilvl_core:GetItemLevel (unitid, guid, is_forced, try_number)
|
|
|
|
--> ddouble check
|
|
if (not is_forced and (UnitAffectingCombat ("player") or InCombatLockdown())) then
|
|
return
|
|
end
|
|
if (not unitid or not CanInspect (unitid) or not CheckInteractDistance (unitid, 1)) then
|
|
if (is_forced) then
|
|
try_number = try_number or 0
|
|
if (try_number > 18) then
|
|
return
|
|
else
|
|
try_number = try_number + 1
|
|
end
|
|
ilvl_core:ScheduleTimer ("ReGetItemLevel", 3, {unitid, guid, is_forced, try_number})
|
|
end
|
|
return
|
|
end
|
|
|
|
inspecting [guid] = {unitid, ilvl_core:ScheduleTimer ("InspectTimeOut", 12, guid)}
|
|
ilvl_core.amt_inspecting = ilvl_core.amt_inspecting + 1
|
|
|
|
NotifyInspect (unitid)
|
|
end
|
|
|
|
local NotifyInspectHook = function (unitid)
|
|
local unit = unitid:gsub ("%d+", "")
|
|
|
|
if ((IsInRaid() or IsInGroup()) and (_detalhes:GetZoneType() == "raid" or _detalhes:GetZoneType() == "party")) then
|
|
local guid = UnitGUID (unitid)
|
|
local name = _detalhes:GetCLName (unitid)
|
|
if (guid and name and not inspecting [guid]) then
|
|
for i = 1, GetNumGroupMembers() do
|
|
if (name == _detalhes:GetCLName (unit .. i)) then
|
|
unitid = unit .. i
|
|
break
|
|
end
|
|
end
|
|
|
|
inspecting [guid] = {unitid, ilvl_core:ScheduleTimer ("InspectTimeOut", 12, guid)}
|
|
ilvl_core.amt_inspecting = ilvl_core.amt_inspecting + 1
|
|
end
|
|
end
|
|
end
|
|
hooksecurefunc ("NotifyInspect", NotifyInspectHook)
|
|
|
|
function ilvl_core:Reset()
|
|
ilvl_core.raid_id = 1
|
|
ilvl_core.amt_inspecting = 0
|
|
|
|
for guid, t in pairs (inspecting) do
|
|
ilvl_core:CancelTimer (t[2])
|
|
inspecting [guid] = nil
|
|
end
|
|
end
|
|
|
|
function ilvl_core:QueryInspect (unitName, callback, param1)
|
|
local unitid
|
|
|
|
if (IsInRaid()) then
|
|
for i = 1, GetNumGroupMembers() do
|
|
if (GetUnitName ("raid" .. i, true) == unitName) then
|
|
unitid = "raid" .. i
|
|
break
|
|
end
|
|
end
|
|
elseif (IsInGroup()) then
|
|
for i = 1, GetNumGroupMembers()-1 do
|
|
if (GetUnitName ("party" .. i, true) == unitName) then
|
|
unitid = "party" .. i
|
|
break
|
|
end
|
|
end
|
|
else
|
|
unitid = unitName
|
|
end
|
|
|
|
if (not unitid) then
|
|
return false
|
|
end
|
|
|
|
local guid = UnitGUID (unitid)
|
|
if (not guid) then
|
|
return false
|
|
elseif (ilvl_core.forced_inspects [guid]) then
|
|
return true
|
|
end
|
|
|
|
if (inspecting [guid]) then
|
|
return true
|
|
end
|
|
|
|
ilvl_core.forced_inspects [guid] = {callback = callback, param1 = param1}
|
|
ilvl_core:GetItemLevel (unitid, guid, true)
|
|
|
|
if (ilvl_core.clear_queued_list) then
|
|
ilvl_core:CancelTimer (ilvl_core.clear_queued_list)
|
|
end
|
|
ilvl_core.clear_queued_list = ilvl_core:ScheduleTimer ("ClearQueryInspectQueue", 60)
|
|
|
|
return true
|
|
end
|
|
|
|
function ilvl_core:ClearQueryInspectQueue()
|
|
wipe (ilvl_core.forced_inspects)
|
|
ilvl_core.clear_queued_list = nil
|
|
end
|
|
|
|
function ilvl_core:Loop()
|
|
if (ilvl_core.amt_inspecting >= MAX_INSPECT_AMOUNT) then
|
|
return
|
|
end
|
|
|
|
local members_amt = GetNumGroupMembers()
|
|
if (ilvl_core.raid_id > members_amt) then
|
|
ilvl_core.raid_id = 1
|
|
end
|
|
|
|
local unitid
|
|
if (IsInRaid()) then
|
|
unitid = "raid" .. ilvl_core.raid_id
|
|
elseif (IsInGroup()) then
|
|
unitid = "party" .. ilvl_core.raid_id
|
|
else
|
|
return
|
|
end
|
|
|
|
local guid = UnitGUID (unitid)
|
|
if (not guid) then
|
|
ilvl_core.raid_id = ilvl_core.raid_id + 1
|
|
return
|
|
end
|
|
|
|
if (inspecting [guid]) then
|
|
return
|
|
end
|
|
|
|
local ilvl_table = _detalhes.ilevel:GetIlvl (guid)
|
|
if (ilvl_table and ilvl_table.time + 3600 > time()) then
|
|
ilvl_core.raid_id = ilvl_core.raid_id + 1
|
|
return
|
|
end
|
|
|
|
ilvl_core:GetItemLevel (unitid, guid)
|
|
ilvl_core.raid_id = ilvl_core.raid_id + 1
|
|
end
|
|
|
|
function ilvl_core:EnterCombat()
|
|
if (ilvl_core.loop_process) then
|
|
ilvl_core:CancelTimer (ilvl_core.loop_process)
|
|
ilvl_core.loop_process = nil
|
|
end
|
|
end
|
|
|
|
local can_start_loop = function()
|
|
if ((_detalhes:GetZoneType() ~= "raid" and _detalhes:GetZoneType() ~= "party") or ilvl_core.loop_process or _detalhes.in_combat or not _detalhes.track_item_level) then
|
|
return false
|
|
end
|
|
return true
|
|
end
|
|
|
|
function ilvl_core:LeaveCombat()
|
|
if (can_start_loop()) then
|
|
ilvl_core:Reset()
|
|
ilvl_core.loop_process = ilvl_core:ScheduleRepeatingTimer ("Loop", LOOP_TIME)
|
|
end
|
|
end
|
|
|
|
function ilvl_core:ZoneChanged (zone_type)
|
|
if (can_start_loop()) then
|
|
ilvl_core:Reset()
|
|
ilvl_core.loop_process = ilvl_core:ScheduleRepeatingTimer ("Loop", LOOP_TIME)
|
|
end
|
|
end
|
|
|
|
function ilvl_core:OnEnter()
|
|
if (IsInRaid()) then
|
|
_detalhes:SentMyItemLevel()
|
|
end
|
|
|
|
if (can_start_loop()) then
|
|
ilvl_core:Reset()
|
|
ilvl_core.loop_process = ilvl_core:ScheduleRepeatingTimer ("Loop", LOOP_TIME)
|
|
end
|
|
end
|
|
|
|
function ilvl_core:OnLeave()
|
|
if (ilvl_core.loop_process) then
|
|
ilvl_core:CancelTimer (ilvl_core.loop_process)
|
|
ilvl_core.loop_process = nil
|
|
end
|
|
end
|
|
|
|
--> ilvl API
|
|
function _detalhes.ilevel:IsTrackerEnabled()
|
|
return _detalhes.track_item_level
|
|
end
|
|
function _detalhes.ilevel:TrackItemLevel (bool)
|
|
if (type (bool) == "boolean") then
|
|
if (bool) then
|
|
_detalhes.track_item_level = true
|
|
if (can_start_loop()) then
|
|
ilvl_core:Reset()
|
|
ilvl_core.loop_process = ilvl_core:ScheduleRepeatingTimer ("Loop", LOOP_TIME)
|
|
end
|
|
else
|
|
_detalhes.track_item_level = false
|
|
if (ilvl_core.loop_process) then
|
|
ilvl_core:CancelTimer (ilvl_core.loop_process)
|
|
ilvl_core.loop_process = nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function _detalhes.ilevel:GetPool()
|
|
return _detalhes.item_level_pool
|
|
end
|
|
|
|
function _detalhes.ilevel:GetIlvl (guid)
|
|
return _detalhes.item_level_pool [guid]
|
|
end
|
|
|
|
function _detalhes.ilevel:GetInOrder()
|
|
local order = {}
|
|
|
|
for guid, t in pairs (_detalhes.item_level_pool) do
|
|
order [#order+1] = {t.name, t.ilvl or 0, t.time}
|
|
end
|
|
|
|
table.sort (order, _detalhes.Sort2)
|
|
|
|
return order
|
|
end
|
|
|
|
function _detalhes:GetTalents (guid)
|
|
return _detalhes.cached_talents [guid]
|
|
end
|
|
|
|
function _detalhes:GetSpec (guid)
|
|
return _detalhes.cached_specs [guid]
|
|
end
|
|
|
|
if (LibGroupInSpecT) then
|
|
function _detalhes:LibGroupInSpecT_UpdateReceived (event, guid, unitid, info)
|
|
--> update talents
|
|
local talents = _detalhes.cached_talents [guid] or {}
|
|
local i = 1
|
|
for talentId, _ in pairs (info.talents) do
|
|
talents [i] = talentId
|
|
i = i + 1
|
|
end
|
|
_detalhes.cached_talents [guid] = talents
|
|
|
|
--> update spec
|
|
if (info.global_spec_id and info.global_spec_id ~= 0) then
|
|
if (not _detalhes.class_specs_coords [info.global_spec_id]) then
|
|
print ("Details! Spec Id Invalid:", info.global_spec_id, info.name)
|
|
else
|
|
_detalhes.cached_specs [guid] = info.global_spec_id
|
|
end
|
|
end
|
|
|
|
--print ("LibGroupInSpecT Received from", info.name, info.global_spec_id)
|
|
end
|
|
LibGroupInSpecT.RegisterCallback (_detalhes, "GroupInSpecT_Update", "LibGroupInSpecT_UpdateReceived")
|
|
end
|
|
|