----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- local _detalhes = _G._detalhes local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" ) local SharedMedia = LibStub:GetLibrary("LibSharedMedia-3.0") local _tempo = time() local _ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --> local pointers local _math_floor = math.floor --lua local local _math_max = math.max --lua local local ipairs = ipairs --lua local local pairs = pairs --lua local local _table_wipe = table.wipe --lua local local _bit_band = bit.band --lua local local _GetInstanceInfo = GetInstanceInfo --wow api local local _UnitExists = UnitExists --wow api local local _UnitGUID = UnitGUID --wow api local local _UnitName = UnitName --wow api local local _GetTime = GetTime local _IsAltKeyDown = IsAltKeyDown local _IsShiftKeyDown = IsShiftKeyDown local _IsControlKeyDown = IsControlKeyDown local atributo_damage = Details.atributo_damage --details local local atributo_heal = Details.atributo_heal --details local local atributo_energy = Details.atributo_energy --details local local atributo_misc = Details.atributo_misc --details local local atributo_custom = Details.atributo_custom --details local local info = Details.playerDetailWindow --details local local UnitGroupRolesAssigned = DetailsFramework.UnitGroupRolesAssigned ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --> constants local modo_GROUP = Details.modos.group local modo_ALL = Details.modos.all local class_type_dano = Details.atributos.dano local OBJECT_TYPE_PETS = 0x00003000 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --> details api functions --> try to find the opponent of last fight, can be called during a fight as well function Details:FindEnemy() local ZoneName, InstanceType, DifficultyID, _, _, _, _, ZoneMapID = _GetInstanceInfo() local in_instance = IsInInstance() --> garrison returns party as instance type. if ((InstanceType == "party" or InstanceType == "raid") and in_instance) then if (InstanceType == "party") then if (Details:GetBossNames (Details.zone_id)) then return Loc ["STRING_SEGMENT_TRASH"] end else return Loc ["STRING_SEGMENT_TRASH"] end end for _, actor in ipairs (Details.tabela_vigente[class_type_dano]._ActorTable) do if (not actor.grupo and not actor.owner and not actor.nome:find ("[*]") and _bit_band (actor.flag_original, 0x00000060) ~= 0) then --> 0x20+0x40 neutral + enemy reaction for name, _ in pairs (actor.targets) do if (name == Details.playername) then return actor.nome else local _target_actor = Details.tabela_vigente (class_type_dano, name) if (_target_actor and _target_actor.grupo) then return actor.nome end end end end end for _, actor in ipairs (Details.tabela_vigente[class_type_dano]._ActorTable) do if (actor.grupo and not actor.owner) then for target_name, _ in pairs (actor.targets) do return target_name end end end return Loc ["STRING_UNKNOW"] end -- try get the current encounter name during the encounter local boss_found_not_registered = function (t, ZoneName, ZoneMapID, DifficultyID) local boss_table = { index = 0, name = t[1], encounter = t[1], zone = ZoneName, mapid = ZoneMapID, diff = DifficultyID, diff_string = select (4, GetInstanceInfo()), ej_instance_id = t[5], id = t[2], bossimage = t[4], } Details.tabela_vigente.is_boss = boss_table end local boss_found = function (index, name, zone, mapid, diff, encounterid) local mapID = C_Map.GetBestMapForUnit ("player") local ejid if (mapID) then ejid = DetailsFramework.EncounterJournal.EJ_GetInstanceForMap (mapID) end if (not mapID) then --print ("Details! exeption handled: zone has no map") return end if (ejid == 0) then ejid = Details:GetInstanceEJID() end local boss_table = { index = index, name = name, encounter = name, zone = zone, mapid = mapid, diff = diff, diff_string = select (4, GetInstanceInfo()), ej_instance_id = ejid, id = encounterid, } if (not Details:IsRaidRegistered (mapid) and Details.zone_type == "raid") then local boss_list = Details:GetCurrentDungeonBossListFromEJ() if (boss_list) then local ActorsContainer = Details.tabela_vigente [class_type_dano]._ActorTable if (ActorsContainer) then for index, Actor in ipairs (ActorsContainer) do if (not Actor.grupo) then if (boss_list [Actor.nome]) then Actor.boss = true boss_table.bossimage = boss_list [Actor.nome][4] break end end end end end end Details.tabela_vigente.is_boss = boss_table if (Details.in_combat and not Details.leaving_combat) then --> catch boss function if any local bossFunction, bossFunctionType = Details:GetBossFunction (ZoneMapID, BossIndex) if (bossFunction) then if (_bit_band (bossFunctionType, 0x1) ~= 0) then --realtime Details.bossFunction = bossFunction Details.tabela_vigente.bossFunction = Details:ScheduleTimer ("bossFunction", 1) end end if (Details.zone_type ~= "raid") then local endType, endData = Details:GetEncounterEnd (ZoneMapID, BossIndex) if (endType and endData) then if (Details.debug) then Details:Msg ("(debug) setting boss end type to:", endType) end Details.encounter_end_table.type = endType Details.encounter_end_table.killed = {} Details.encounter_end_table.data = {} if (type (endData) == "table") then if (Details.debug) then Details:Msg ("(debug) boss type is table:", endType) end if (endType == 1 or endType == 2) then for _, npcID in ipairs (endData) do Details.encounter_end_table.data [npcID] = false end end else if (endType == 1 or endType == 2) then Details.encounter_end_table.data [endData] = false end end end end end --> we the boss was found during the combat table creation, we must postpone the event trigger if (not Details.tabela_vigente.IsBeingCreated) then Details:SendEvent ("COMBAT_BOSS_FOUND", nil, index, name) Details:CheckFor_SuppressedWindowsOnEncounterFound() end return boss_table end function Details:ReadBossFrames() if (Details.tabela_vigente.is_boss) then return --no need to check end if (Details.encounter_table.name) then local encounter_table = Details.encounter_table return boss_found (encounter_table.index, encounter_table.name, encounter_table.zone, encounter_table.mapid, encounter_table.diff, encounter_table.id) end for index = 1, 5, 1 do if (_UnitExists ("boss"..index)) then local guid = _UnitGUID ("boss"..index) if (guid) then local serial = Details:GetNpcIdFromGuid (guid) if (serial) then local ZoneName, _, DifficultyID, _, _, _, _, ZoneMapID = _GetInstanceInfo() local BossIds = Details:GetBossIds (ZoneMapID) if (BossIds) then local BossIndex = BossIds [serial] if (BossIndex) then if (Details.debug) then Details:Msg ("(debug) boss found:",Details:GetBossName (ZoneMapID, BossIndex)) end return boss_found (BossIndex, Details:GetBossName (ZoneMapID, BossIndex), ZoneName, ZoneMapID, DifficultyID) end end end end end end end --try to get the encounter name after the encounter (can be called during the combat as well) function Details:FindBoss (noJournalSearch) if (Details.encounter_table.name) then local encounter_table = Details.encounter_table return boss_found (encounter_table.index, encounter_table.name, encounter_table.zone, encounter_table.mapid, encounter_table.diff, encounter_table.id) end local ZoneName, InstanceType, DifficultyID, _, _, _, _, ZoneMapID = _GetInstanceInfo() local BossIds = Details:GetBossIds (ZoneMapID) if (BossIds) then local BossIndex = nil local ActorsContainer = Details.tabela_vigente [class_type_dano]._ActorTable if (ActorsContainer) then for index, Actor in ipairs (ActorsContainer) do if (not Actor.grupo) then local serial = Details:GetNpcIdFromGuid (Actor.serial) if (serial) then BossIndex = BossIds [serial] if (BossIndex) then Actor.boss = true return boss_found (BossIndex, Details:GetBossName (ZoneMapID, BossIndex), ZoneName, ZoneMapID, DifficultyID) end end end end end end noJournalSearch = true --> disabling the scan on encounter journal if (not noJournalSearch) then local in_instance = IsInInstance() --> garrison returns party as instance type. if ((InstanceType == "party" or InstanceType == "raid") and in_instance) then local boss_list = Details:GetCurrentDungeonBossListFromEJ() if (boss_list) then local ActorsContainer = Details.tabela_vigente [class_type_dano]._ActorTable if (ActorsContainer) then for index, Actor in ipairs (ActorsContainer) do if (not Actor.grupo) then if (boss_list [Actor.nome]) then Actor.boss = true return boss_found_not_registered (boss_list [Actor.nome], ZoneName, ZoneMapID, DifficultyID) end end end end end end end return false end ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --> internal functions -- Details.statistics = {container_calls = 0, container_pet_calls = 0, container_unknow_pet = 0, damage_calls = 0, heal_calls = 0, absorbs_calls = 0, energy_calls = 0, pets_summons = 0} function Details:StartCombat(...) return Details:EntrarEmCombate (...) end -- ~start ~inicio ~novo �ovo function Details:EntrarEmCombate (...) if (Details.debug) then Details:Msg ("(debug) |cFFFFFF00started a new combat|r|cFFFF7700", Details.encounter_table and Details.encounter_table.name or "") --local from = debugstack (2, 1, 0) --print (from) end if (not Details.tabela_historico.tabelas[1]) then Details.tabela_overall = Details.combate:NovaTabela() Details:InstanciaCallFunction (Details.ResetaGump, nil, -1) --> reseta scrollbar, iterators, rodap�, etc Details:InstanciaCallFunction (Details.InstanciaFadeBarras, -1) --> esconde todas as barras Details:InstanciaCallFunction (Details.AtualizaSegmentos) --> atualiza o showing end --> re-lock nos tempos da tabela passada -- lock again last table times Details.tabela_vigente:TravarTempos() local n_combate = Details:NumeroCombate (1) --aumenta o contador de combates -- combat number up --> cria a nova tabela de combates -- create new table local ultimo_combate = Details.tabela_vigente Details.tabela_vigente = Details.combate:NovaTabela (true, Details.tabela_overall, n_combate, ...) --cria uma nova tabela de combate --> flag this combat as being created Details.tabela_vigente.IsBeingCreated = true Details.tabela_vigente.previous_combat = ultimo_combate Details.tabela_vigente:seta_data (Details._detalhes_props.DATA_TYPE_START) --seta na tabela do combate a data do inicio do combate -- setup time data Details.in_combat = true --sinaliza ao addon que h� um combate em andamento -- in combat flag up Details.tabela_vigente.combat_id = n_combate --> grava o n�mero deste combate na tabela atual -- setup combat id on new table Details.last_combat_pre_pot_used = nil Details:FlagCurrentCombat() --> � o timer que ve se o jogador ta em combate ou n�o -- check if any party or raid members are in combat Details.tabela_vigente.verifica_combate = Details:ScheduleRepeatingTimer ("EstaEmCombate", 1) Details:ClearCCPetsBlackList() _table_wipe (Details.encounter_end_table) _table_wipe (Details.pets_ignored) _table_wipe (Details.pets_no_owner) Details.container_pets:BuscarPets() _table_wipe (Details.cache_damage_group) _table_wipe (Details.cache_healing_group) Details:UpdateParserGears() --> get all buff already applied before the combat start Details:CatchRaidBuffUptime ("BUFF_UPTIME_IN") Details:CatchRaidDebuffUptime ("DEBUFF_UPTIME_IN") Details:UptadeRaidMembersCache() --> we already have boss information? build .is_boss table if (Details.encounter_table.id and Details.encounter_table ["start"] >= GetTime() - 3 and not Details.encounter_table ["end"]) then local encounter_table = Details.encounter_table --> boss_found will trigger "COMBAT_BOSS_FOUND" event, but at this point of the combat creation is safe to send it boss_found (encounter_table.index, encounter_table.name, encounter_table.zone, encounter_table.mapid, encounter_table.diff, encounter_table.id) else --> if we don't have this infor right now, lets check in few seconds dop if (Details.EncounterInformation [Details.zone_id]) then Details:ScheduleTimer ("ReadBossFrames", 1) Details:ScheduleTimer ("ReadBossFrames", 30) end end --> if the window is showing current segment, switch it for the new combat --> also if the window has auto current, jump to current segment Details:InstanciaCallFunction (Details.TrocaSegmentoAtual, Details.tabela_vigente.is_boss and true) --> clear hosts and make the cloud capture stuff Details.host_of = nil Details.host_by = nil if (Details.in_group and Details.cloud_capture) then if (Details:IsInInstance() or Details.debug) then if (not Details:CaptureIsAllEnabled()) then Details:ScheduleSendCloudRequest() --if (Details.debug) then -- Details:Msg ("(debug) requesting a cloud server.") --end end else --if (Details.debug) then -- Details:Msg ("(debug) isn't inside a registred instance", Details:IsInInstance()) --end end else --if (Details.debug) then -- Details:Msg ("(debug) isn't in group or cloud is turned off", Details.in_group, Details.cloud_capture) --end end --> hide / alpha / switch in combat for index, instancia in ipairs (Details.tabela_instancias) do if (instancia.ativa) then instancia:CheckSwitchOnCombatStart (true) end end Details:InstanceCall (Details.CheckPsUpdate) --> combat creation is completed, remove the flag Details.tabela_vigente.IsBeingCreated = nil Details:SendEvent ("COMBAT_PLAYER_ENTER", nil, Details.tabela_vigente, Details.encounter_table and Details.encounter_table.id) if (Details.tabela_vigente.is_boss) then --> the encounter was found through encounter_start event Details:SendEvent ("COMBAT_BOSS_FOUND", nil, Details.tabela_vigente.is_boss.index, Details.tabela_vigente.is_boss.name) end Details:CheckSwitchToCurrent() Details:CheckForTextTimeCounter (true) --> stop bar testing if any Details:StopTestBarUpdate() end function Details:DelayedSyncAlert() local lower_instance = Details:GetLowerInstanceNumber() if (lower_instance) then lower_instance = Details:GetInstance (lower_instance) if (lower_instance) then if (not lower_instance:HaveInstanceAlert()) then lower_instance:InstanceAlert (Loc ["STRING_EQUILIZING"], {[[Interface\COMMON\StreamCircle]], 22, 22, true}, 5, {function() end}) end end end end function Details:ScheduleSyncPlayerActorData() if ((IsInGroup() or IsInRaid()) and (Details.zone_type == "party" or Details.zone_type == "raid")) then --> do not sync if in battleground or arena Details:SendCharacterData() end end function Details:EndCombat() return Details:SairDoCombate() end -- ~end ~leave function Details:SairDoCombate (bossKilled, from_encounter_end) if (Details.debug) then Details:Msg ("(debug) |cFFFFFF00ended a combat|r|cFFFF7700", Details.encounter_table and Details.encounter_table.name or "") end --> in case of something somehow someway call to close the same combat a second time. if (Details.tabela_vigente == Details.last_closed_combat) then return end Details.last_closed_combat = Details.tabela_vigente --if (Details.statistics) then -- for k, v in pairs (Details.statistics) do -- print (k, v) -- end --end Details.leaving_combat = true Details.last_combat_time = _tempo Details:CatchRaidBuffUptime ("BUFF_UPTIME_OUT") Details:CatchRaidDebuffUptime ("DEBUFF_UPTIME_OUT") Details:CloseEnemyDebuffsUptime() --> check if this isn't a boss and try to find a boss in the segment if (not Details.tabela_vigente.is_boss) then --> if this is a mythic+ dungeon, do not scan for encounter journal boss names in the actor list Details:FindBoss() --> still didn't find the boss if (not Details.tabela_vigente.is_boss) then local ZoneName, _, DifficultyID, _, _, _, _, ZoneMapID = _GetInstanceInfo() local findboss = Details:GetRaidBossFindFunction (ZoneMapID) if (findboss) then local BossIndex = findboss() if (BossIndex) then boss_found (BossIndex, Details:GetBossName (ZoneMapID, BossIndex), ZoneName, ZoneMapID, DifficultyID) end end end end if (Details.tabela_vigente.bossFunction) then Details:CancelTimer (Details.tabela_vigente.bossFunction) Details.tabela_vigente.bossFunction = nil end --> finaliza a checagem se esta ou n�o no combate -- finish combat check if (Details.tabela_vigente.verifica_combate) then Details:CancelTimer (Details.tabela_vigente.verifica_combate) Details.tabela_vigente.verifica_combate = nil end --> lock timers Details.tabela_vigente:TravarTempos() --> get waste shields if (Details.close_shields) then Details:CloseShields (Details.tabela_vigente) end --> salva hora, minuto, segundo do fim da luta Details.tabela_vigente:seta_data (Details._detalhes_props.DATA_TYPE_END) Details.tabela_vigente:seta_tempo_decorrido() --> drop last events table to garbage collector Details.tabela_vigente.player_last_events = {} --> flag instance type local _, InstanceType = _GetInstanceInfo() Details.tabela_vigente.instance_type = InstanceType if (not Details.tabela_vigente.is_boss and from_encounter_end and type (from_encounter_end) == "table") then local encounterID, encounterName, difficultyID, raidSize, endStatus = unpack (from_encounter_end) if (encounterID) then local ZoneName, InstanceType, DifficultyID, DifficultyName, _, _, _, ZoneMapID = GetInstanceInfo() local mapID = C_Map.GetBestMapForUnit ("player") if (not mapID) then mapID = 0 end local ejid = DetailsFramework.EncounterJournal.EJ_GetInstanceForMap (mapID) if (ejid == 0) then ejid = Details:GetInstanceEJID() end local _, boss_index = Details:GetBossEncounterDetailsFromEncounterId (ZoneMapID, encounterID) Details.tabela_vigente.is_boss = { index = boss_index or 0, name = encounterName, encounter = encounterName, zone = ZoneName, mapid = ZoneMapID, diff = DifficultyID, diff_string = DifficultyName, ej_instance_id = ejid or 0, id = encounterID, } end end --> tag as a mythic dungeon segment, can be any type of segment, this tag also avoid the segment to be tagged as trash local mythicLevel = C_ChallengeMode and C_ChallengeMode.GetActiveKeystoneInfo() if (mythicLevel and mythicLevel >= 2) then Details.tabela_vigente.is_mythic_dungeon_segment = true Details.tabela_vigente.is_mythic_dungeon_run_id = Details.mythic_dungeon_id end --> send item level after a combat if is in raid or party group C_Timer.After (1, Details.ScheduleSyncPlayerActorData) --if this segment isn't a boss fight if (not Details.tabela_vigente.is_boss) then if (Details.tabela_vigente.is_pvp or Details.tabela_vigente.is_arena) then Details:FlagActorsOnPvPCombat() end if (Details.tabela_vigente.is_arena) then Details.tabela_vigente.enemy = "[" .. ARENA .. "] " .. Details.tabela_vigente.is_arena.name end local in_instance = IsInInstance() --> garrison returns party as instance type. if ((InstanceType == "party" or InstanceType == "raid") and in_instance) then if (InstanceType == "party") then if (Details.tabela_vigente.is_mythic_dungeon_segment) then --setted just above --is inside a mythic+ dungeon and this is not a boss segment, so tag it as a dungeon mythic+ trash segment local zoneName, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize = GetInstanceInfo() Details.tabela_vigente.is_mythic_dungeon_trash = { ZoneName = zoneName, MapID = instanceMapID, Level = Details.MythicPlus.Level, EJID = Details.MythicPlus.ejID, } else --> tag the combat as trash clean up Details.tabela_vigente.is_trash = true end else Details.tabela_vigente.is_trash = true end else if (not in_instance) then if (Details.world_combat_is_trash) then Details.tabela_vigente.is_temporary = true end end end if (not Details.tabela_vigente.enemy) then local enemy = Details:FindEnemy() if (enemy and Details.debug) then Details:Msg ("(debug) enemy found", enemy) end Details.tabela_vigente.enemy = enemy end if (Details.debug) then -- Details:Msg ("(debug) forcing equalize actors behavior.") -- Details:EqualizeActorsSchedule (Details.host_of) end --> verifica memoria Details:FlagActorsOnCommonFight() --fight_component --Details:CheckMemoryAfterCombat() -- 7.2.5 is doing some weird errors even out of combat else --this segment is a boss fight if (not InCombatLockdown() and not UnitAffectingCombat ("player")) then else --Details.schedule_flag_boss_components = true end --calling here without checking for combat since the does not ran too long for scripts Details:FlagActorsOnBossFight() local boss_id = Details.encounter_table.id if (bossKilled) then Details.tabela_vigente.is_boss.killed = true --> add to storage if (not InCombatLockdown() and not UnitAffectingCombat ("player") and not Details.logoff_saving_data) then local successful, errortext = pcall (Details.Database.StoreEncounter) if (not successful) then Details:Msg ("error occurred on Details.Database.StoreEncounter():", errortext) end else Details.schedule_store_boss_encounter = true end Details:SendEvent ("COMBAT_BOSS_DEFEATED", nil, Details.tabela_vigente) Details:CheckFor_TrashSuppressionOnEncounterEnd() else Details:SendEvent ("COMBAT_BOSS_WIPE", nil, Details.tabela_vigente) --> add to storage if (not InCombatLockdown() and not UnitAffectingCombat ("player") and not Details.logoff_saving_data) then local successful, errortext = pcall (Details.Database.StoreWipe) if (not successful) then Details:Msg ("error occurred on Details.Database.StoreWipe():", errortext) end else Details.schedule_store_boss_encounter_wipe = true end end --if (Details:GetBossDetails (Details.tabela_vigente.is_boss.mapid, Details.tabela_vigente.is_boss.index) or ) then Details.tabela_vigente.is_boss.index = Details.tabela_vigente.is_boss.index or 1 Details.tabela_vigente.enemy = Details.tabela_vigente.is_boss.encounter if (Details.tabela_vigente.instance_type == "raid") then Details.last_encounter2 = Details.last_encounter Details.last_encounter = Details.tabela_vigente.is_boss.name if (Details.pre_pot_used) then Details.last_combat_pre_pot_used = Details.CopyTable (Details.pre_pot_used) end if (Details.pre_pot_used and Details.announce_prepots.enabled) then Details:Msg (Details.pre_pot_used or "") Details.pre_pot_used = nil end end if (from_encounter_end) then if (Details.encounter_table.start) then Details.tabela_vigente:SetStartTime (Details.encounter_table.start) end Details.tabela_vigente:SetEndTime (Details.encounter_table ["end"] or GetTime()) end --> encounter boss function local bossFunction, bossFunctionType = Details:GetBossFunction (Details.tabela_vigente.is_boss.mapid or 0, Details.tabela_vigente.is_boss.index or 0) if (bossFunction) then if (_bit_band (bossFunctionType, 0x2) ~= 0) then --end of combat if (not Details.logoff_saving_data) then local successful, errortext = pcall (bossFunction, Details.tabela_vigente) if (not successful) then Details:Msg ("error occurred on Encounter Boss Function:", errortext) end end end end if (Details.tabela_vigente.instance_type == "raid") then --> schedule captures off Details:CaptureSet (false, "damage", false, 15) Details:CaptureSet (false, "energy", false, 15) Details:CaptureSet (false, "aura", false, 15) Details:CaptureSet (false, "energy", false, 15) Details:CaptureSet (false, "spellcast", false, 15) if (Details.debug) then Details:Msg ("(debug) freezing parser for 15 seconds.") end end --> schedule sync Details:EqualizeActorsSchedule (Details.host_of) if (Details:GetEncounterEqualize (Details.tabela_vigente.is_boss.mapid, Details.tabela_vigente.is_boss.index)) then Details:ScheduleTimer ("DelayedSyncAlert", 3) end --else -- if (Details.debug) then -- Details:EqualizeActorsSchedule (Details.host_of) -- end --end end if (Details.solo) then --> debuffs need a checkup, not well functional right now Details.CloseSoloDebuffs() end local tempo_do_combate = Details.tabela_vigente:GetCombatTime() local invalid_combat local zoneName, zoneType = GetInstanceInfo() if (not Details.tabela_vigente.discard_segment and (zoneType == "none" or tempo_do_combate >= Details.minimum_combat_time or not Details.tabela_historico.tabelas[1])) then Details.tabela_historico:adicionar (Details.tabela_vigente) --move a tabela atual para dentro do hist�rico --8.0.1 miss data isn't required at the moment, spells like akari's soul has been removed from the game --Details:CanSendMissData() if (Details.tabela_vigente.is_boss) then if (IsInRaid()) then local cleuID = Details.tabela_vigente.is_boss.id local diff = Details.tabela_vigente.is_boss.diff if (cleuID and diff == 16) then -- 16 mythic local raidData = Details.raid_data --get or build mythic raid data table local mythicRaidData = raidData.mythic_raid_data if (not mythicRaidData) then mythicRaidData = {} raidData.mythic_raid_data = mythicRaidData end --get or build a table for this cleuID mythicRaidData [cleuID] = mythicRaidData [cleuID] or {wipes = 0, kills = 0, best_try = 1, longest = 0, try_history = {}} local cleuIDData = mythicRaidData [cleuID] --store encounter data for plugins and weakauras if (Details.tabela_vigente:GetCombatTime() > cleuIDData.longest) then cleuIDData.longest = Details.tabela_vigente:GetCombatTime() end if (Details.tabela_vigente.is_boss.killed) then cleuIDData.kills = cleuIDData.kills + 1 cleuIDData.best_try = 0 tinsert (cleuIDData.try_history, {0, Details.tabela_vigente:GetCombatTime()}) --print ("KILL", "best try", cleuIDData.best_try, "amt kills", cleuIDData.kills, "wipes", cleuIDData.wipes, "longest", cleuIDData.longest) else cleuIDData.wipes = cleuIDData.wipes + 1 if (Details.boss1_health_percent and Details.boss1_health_percent < cleuIDData.best_try) then cleuIDData.best_try = Details.boss1_health_percent tinsert (cleuIDData.try_history, {Details.boss1_health_percent, Details.tabela_vigente:GetCombatTime()}) end --print ("WIPE", "best try", cleuIDData.best_try, "amt kills", cleuIDData.kills, "wipes", cleuIDData.wipes, "longest", cleuIDData.longest) end end end -- end --the combat is valid, see if the user is sharing data with somebody if (Details.shareData) then local zipData = Details:CompressData (Details.tabela_vigente, "comm") if (zipData) then print ("has zip data") end end else invalid_combat = Details.tabela_vigente --> tutorial about the combat time < then 'minimum_combat_time' local hasSeenTutorial = Details:GetTutorialCVar ("MIN_COMBAT_TIME") if (not hasSeenTutorial) then local lower_instance = Details:GetLowerInstanceNumber() if (lower_instance) then lower_instance = Details:GetInstance (lower_instance) if (lower_instance) then lower_instance:InstanceAlert ("combat ignored: less than 5 seconds.", {[[Interface\BUTTONS\UI-GROUPLOOT-PASS-DOWN]], 18, 18, false, 0, 1, 0, 1}, 20, {function() Details:Msg ("combat ignored: elapsed time less than 5 seconds."); Details:Msg ("add '|cFFFFFF00Details.minimum_combat_time = 2;|r' on Auto Run Code to change the minimum time.") end}) Details:SetTutorialCVar ("MIN_COMBAT_TIME", true) end end end --in case of a forced discard segment, just check a second time if we have a previous combat. if (not Details.tabela_historico.tabelas[1]) then Details.tabela_vigente = Details.tabela_vigente else Details.tabela_vigente = Details.tabela_historico.tabelas[1] --> pega a tabela do ultimo combate end if (Details.tabela_vigente:GetStartTime() == 0) then --Details.tabela_vigente.start_time = Details._tempo Details.tabela_vigente:SetStartTime (_GetTime()) --Details.tabela_vigente.end_time = Details._tempo Details.tabela_vigente:SetEndTime (_GetTime()) end Details.tabela_vigente.resincked = true --> tabela foi descartada, precisa atualizar os baseframes // precisa atualizer todos ou apenas o overall? Details:InstanciaCallFunction (Details.AtualizarJanela) if (Details.solo) then local esta_instancia = Details.tabela_instancias[Details.solo] if (Details.SoloTables.CombatID == Details:NumeroCombate()) then --> significa que o solo mode validou o combate, como matar um bixo muito low level com uma s� porrada if (Details.SoloTables.CombatIDLast and Details.SoloTables.CombatIDLast ~= 0) then --> volta os dados da luta anterior Details.SoloTables.CombatID = Details.SoloTables.CombatIDLast else if (Details.RefreshSolo) then Details:RefreshSolo() end Details.SoloTables.CombatID = nil end end end Details:NumeroCombate (-1) end Details.host_of = nil Details.host_by = nil if (Details.cloud_process) then Details:CancelTimer (Details.cloud_process) end Details.in_combat = false Details.leaving_combat = false Details:OnCombatPhaseChanged() _table_wipe (Details.tabela_vigente.PhaseData.damage_section) _table_wipe (Details.tabela_vigente.PhaseData.heal_section) _table_wipe (Details.cache_damage_group) _table_wipe (Details.cache_healing_group) Details:UpdateParserGears() --> hide / alpha in combat for index, instancia in ipairs (Details.tabela_instancias) do if (instancia.ativa) then if (instancia.auto_switch_to_old) then instancia:CheckSwitchOnCombatEnd() end end end Details.pre_pot_used = nil --> do not wipe the encounter table if is in the argus encounter ~REMOVE on 8.0 if (Details.encounter_table and Details.encounter_table.id ~= 2092) then _table_wipe (Details.encounter_table) else if (Details.debug) then Details:Msg ("(debug) in argus encounter, cannot wipe the encounter table.") end end Details:InstanceCall (Details.CheckPsUpdate) if (invalid_combat) then Details:SendEvent ("COMBAT_INVALID") Details:SendEvent ("COMBAT_PLAYER_LEAVE", nil, invalid_combat) else Details:SendEvent ("COMBAT_PLAYER_LEAVE", nil, Details.tabela_vigente) end Details:CheckForTextTimeCounter() Details.StoreSpells() Details:RunScheduledEventsAfterCombat() end function Details:GetPlayersInArena() local aliados = GetNumGroupMembers() -- LE_PARTY_CATEGORY_HOME for i = 1, aliados-1 do local role = UnitGroupRolesAssigned and UnitGroupRolesAssigned("party" .. i) or "DAMAGER" if (role ~= "NONE" and UnitExists("party" .. i)) then local name = GetUnitName ("party" .. i, true) Details.arena_table [name] = {role = role} end end local role = UnitGroupRolesAssigned and UnitGroupRolesAssigned("player") or "DAMAGER" if (role ~= "NONE") then local name = GetUnitName ("player", true) Details.arena_table [name] = {role = role} end --enemies local enemiesAmount = GetNumArenaOpponentSpecs and GetNumArenaOpponentSpecs() or 5 table.wipe(_detalhes.arena_enemies) for i = 1, enemiesAmount do local enemyName = _G.GetUnitName("arena" .. i, true) if (enemyName) then _detalhes.arena_enemies[enemyName] = "arena" .. i end end end local string_arena_enemyteam_damage = [[ local combat = Details:GetCombat ("current") local total = 0 for _, actor in combat[1]:ListActors() do if (actor.arena_enemy) then total = total + actor.total end end return total ]] local string_arena_myteam_damage = [[ local combat = Details:GetCombat ("current") local total = 0 for _, actor in combat[1]:ListActors() do if (actor.arena_ally) then total = total + actor.total end end return total ]] local string_arena_enemyteam_heal = [[ local combat = Details:GetCombat ("current") local total = 0 for _, actor in combat[2]:ListActors() do if (actor.arena_enemy) then total = total + actor.total end end return total ]] local string_arena_myteam_heal = [[ local combat = Details:GetCombat ("current") local total = 0 for _, actor in combat[2]:ListActors() do if (actor.arena_ally) then total = total + actor.total end end return total ]] function Details:CreateArenaSegment() Details:GetPlayersInArena() Details.arena_begun = true Details.start_arena = nil if (Details.in_combat) then Details:SairDoCombate() end --> registra os gr�ficos Details:TimeDataRegister ("Your Team Damage", string_arena_myteam_damage, nil, "Details!", "v1.0", [[Interface\ICONS\Ability_DualWield]], true, true) Details:TimeDataRegister ("Enemy Team Damage", string_arena_enemyteam_damage, nil, "Details!", "v1.0", [[Interface\ICONS\Ability_DualWield]], true, true) Details:TimeDataRegister ("Your Team Healing", string_arena_myteam_heal, nil, "Details!", "v1.0", [[Interface\ICONS\Ability_DualWield]], true, true) Details:TimeDataRegister ("Enemy Team Healing", string_arena_enemyteam_heal, nil, "Details!", "v1.0", [[Interface\ICONS\Ability_DualWield]], true, true) --> inicia um novo combate Details:EntrarEmCombate() --> sinaliza que esse combate � arena Details.tabela_vigente.arena = true Details.tabela_vigente.is_arena = {name = Details.zone_name, zone = Details.zone_name, mapid = Details.zone_id} Details:SendEvent("COMBAT_ARENA_START") end function Details:StartArenaSegment(...) if (Details.debug) then Details:Msg("(debug) starting a new arena segment.") end local _, timeSeconds = select(1, ...) if (Details.start_arena) then Details:CancelTimer(Details.start_arena, true) end Details.start_arena = Details:ScheduleTimer("CreateArenaSegment", timeSeconds) Details:GetPlayersInArena() end function Details:EnteredInArena() if (Details.debug) then Details:Msg ("(debug) the player EnteredInArena().") end Details.arena_begun = false Details:GetPlayersInArena() end function Details:LeftArena() if (Details.debug) then Details:Msg ("(debug) player LeftArena().") end Details.is_in_arena = false Details.arena_begun = false if (Details.start_arena) then Details:CancelTimer (Details.start_arena, true) end Details:TimeDataUnregister ("Your Team Damage") Details:TimeDataUnregister ("Enemy Team Damage") Details:TimeDataUnregister ("Your Team Healing") Details:TimeDataUnregister ("Enemy Team Healing") Details:SendEvent ("COMBAT_ARENA_END") end local validSpells = { [220893] = {class = "ROGUE", spec = 261, maxPercent = 0.075, container = 1, commID = "MISSDATA_ROGUE_SOULRIP"}, --[11366] = {class = "MAGE", spec = 63, maxPercent = 0.9, container = 1, commID = "MISSDATA_ROGUE_SOULRIP"}, } function Details:CanSendMissData() if (not IsInRaid() and not IsInGroup()) then return end local _, playerClass = UnitClass ("player") local specIndex = DetailsFramework.GetSpecialization() local playerSpecID if (specIndex) then playerSpecID = DetailsFramework.GetSpecializationInfo (specIndex) end if (playerSpecID and playerClass) then for spellID, t in pairs (validSpells) do if (playerClass == t.class and playerSpecID == t.spec) then Details:SendMissData (spellID, t.container, Details.network.ids [t.commID]) end end end return false end function Details:SendMissData (spellID, containerType, commID) local combat = Details.tabela_vigente if (combat) then local damageActor = combat (containerType, Details.playername) if (damageActor) then local spell = damageActor.spells:GetSpell (spellID) if (spell) then local data = { [1] = containerType, [2] = spellID, [3] = spell.total, [4] = spell.counter } if (Details.debug) then Details:Msg ("(debug) sending miss data packet:", spellID, containerType, commID) end Details:SendRaidOrPartyData (commID, data) end end end end function Details.HandleMissData (playerName, data) local combat = Details.tabela_vigente if (Details.debug) then Details:Msg ("(debug) miss data received from:", playerName, "spellID:", data [2], data [3], data [4]) end if (combat) then local containerType = data[1] if (type (containerType) ~= "number" or containerType < 1 or containerType > 4) then return end local damageActor = combat (containerType, playerName) if (damageActor) then local spellID = data[2] --a spellID has been passed? if (not spellID or type (spellID) ~= "number") then return end local validateSpell = validSpells [spellID] if (not validateSpell) then --is a valid spell? return end --does the target player fit in the spell requirement on OUR end? local class, spec, maxPercent = validateSpell.class, validateSpell.spec, validateSpell.maxPercent if (class ~= damageActor.classe or spec ~= damageActor.spec) then return end local total, counter = data[3], data[4] if (type (total) ~= "number" or type (counter) ~= "number") then return end if (total > (damageActor.total * maxPercent)) then return end local spellObject = damageActor.spells:PegaHabilidade (spellID, true) if (spellObject) then if (spellObject.total < total and total > 0 and damageActor.nome ~= Details.playername) then local difference = total - spellObject.total if (difference > 0) then spellObject.total = total spellObject.counter = counter damageActor.total = damageActor.total + difference combat [containerType].need_refresh = true if (Details.debug) then Details:Msg ("(debug) miss data successful added from:", playerName, data [2], "difference:", difference) end end end end end end end function Details:MakeEqualizeOnActor (player, realm, receivedActor) if (true) then --> disabled for testing return end local combat = Details:GetCombat ("current") local damage, heal, energy, misc = Details:GetAllActors ("current", player) if (not damage and not heal and not energy and not misc) then --> try adding server name damage, heal, energy, misc = Details:GetAllActors ("current", player.."-"..realm) if (not damage and not heal and not energy and not misc) then --> not found any actor object, so we need to create local actorName if (realm ~= GetRealmName()) then actorName = player.."-"..realm else actorName = player end local guid = Details:FindGUIDFromName (player) -- 0x512 normal party -- 0x514 normal raid if (guid) then damage = combat [1]:PegarCombatente (guid, actorName, 0x514, true) heal = combat [2]:PegarCombatente (guid, actorName, 0x514, true) energy = combat [3]:PegarCombatente (guid, actorName, 0x514, true) misc = combat [4]:PegarCombatente (guid, actorName, 0x514, true) if (Details.debug) then Details:Msg ("(debug) equalize received actor:", actorName, damage, heal) end else if (Details.debug) then Details:Msg ("(debug) equalize couldn't get guid for player ",player) end end end end combat[1].need_refresh = true combat[2].need_refresh = true combat[3].need_refresh = true combat[4].need_refresh = true if (damage) then if (damage.total < receivedActor [1][1]) then if (Details.debug) then Details:Msg (player .. " damage before: " .. damage.total .. " damage received: " .. receivedActor [1][1]) end damage.total = receivedActor [1][1] end if (damage.damage_taken < receivedActor [1][2]) then damage.damage_taken = receivedActor [1][2] end if (damage.friendlyfire_total < receivedActor [1][3]) then damage.friendlyfire_total = receivedActor [1][3] end end if (heal) then if (heal.total < receivedActor [2][1]) then heal.total = receivedActor [2][1] end if (heal.totalover < receivedActor [2][2]) then heal.totalover = receivedActor [2][2] end if (heal.healing_taken < receivedActor [2][3]) then heal.healing_taken = receivedActor [2][3] end end if (energy) then if (energy.mana and (receivedActor [3][1] > 0 and energy.mana < receivedActor [3][1])) then energy.mana = receivedActor [3][1] end if (energy.e_rage and (receivedActor [3][2] > 0 and energy.e_rage < receivedActor [3][2])) then energy.e_rage = receivedActor [3][2] end if (energy.e_energy and (receivedActor [3][3] > 0 and energy.e_energy < receivedActor [3][3])) then energy.e_energy = receivedActor [3][3] end if (energy.runepower and (receivedActor [3][4] > 0 and energy.runepower < receivedActor [3][4])) then energy.runepower = receivedActor [3][4] end end if (misc) then if (misc.interrupt and (receivedActor [4][1] > 0 and misc.interrupt < receivedActor [4][1])) then misc.interrupt = receivedActor [4][1] end if (misc.dispell and (receivedActor [4][2] > 0 and misc.dispell < receivedActor [4][2])) then misc.dispell = receivedActor [4][2] end end end function Details:EqualizePets() --> check for pets without owner for _, actor in ipairs (Details.tabela_vigente[1]._ActorTable) do --> have flag and the flag tell us he is a pet if (actor.flag_original and bit.band (actor.flag_original, OBJECT_TYPE_PETS) ~= 0) then --> do not have owner and he isn't on owner container if (not actor.owner and not Details.tabela_pets.pets [actor.serial]) then Details:SendPetOwnerRequest (actor.serial, actor.nome) end end end end function Details:EqualizeActorsSchedule (host_of) --> store pets sent through 'needpetowner' Details.sent_pets = Details.sent_pets or {n = time()} if (Details.sent_pets.n+20 < time()) then _table_wipe (Details.sent_pets) Details.sent_pets.n = time() end --> pet equilize disabled on details 1.4.0 --Details:ScheduleTimer ("EqualizePets", 1+math.random()) --> do not equilize if there is any disabled capture --if (Details:CaptureIsAllEnabled()) then Details:ScheduleTimer ("EqualizeActors", 2+math.random()+math.random() , host_of) --end end function Details:EqualizeActors (host_of) --> Disabling the sync. Since WoD combatlog are sent between player on phased zones during encounters. if (not host_of or true) then --> full disabled for testing return end if (Details.debug) then Details:Msg ("(debug) sending equilize actor data") end local damage, heal, energy, misc if (host_of) then damage, heal, energy, misc = Details:GetAllActors ("current", host_of) else damage, heal, energy, misc = Details:GetAllActors ("current", Details.playername) end if (damage) then damage = {damage.total or 0, damage.damage_taken or 0, damage.friendlyfire_total or 0} else damage = {0, 0, 0} end if (heal) then heal = {heal.total or 0, heal.totalover or 0, heal.healing_taken or 0} else heal = {0, 0, 0} end if (energy) then energy = {energy.mana or 0, energy.e_rage or 0, energy.e_energy or 0, energy.runepower or 0} else energy = {0, 0, 0, 0} end if (misc) then misc = {misc.interrupt or 0, misc.dispell or 0} else misc = {0, 0} end local data = {damage, heal, energy, misc} --> envia os dados do proprio host pra ele antes if (host_of) then Details:SendRaidDataAs (Details.network.ids.CLOUD_EQUALIZE, host_of, nil, data) Details:EqualizeActors() else Details:SendRaidData (Details.network.ids.CLOUD_EQUALIZE, data) end end function Details:FlagActorsOnPvPCombat() for class_type, container in ipairs (Details.tabela_vigente) do for _, actor in ipairs (container._ActorTable) do actor.pvp_component = true end end end function Details:FlagActorsOnBossFight() for class_type, container in ipairs (Details.tabela_vigente) do for _, actor in ipairs (container._ActorTable) do actor.boss_fight_component = true end end end local fight_component = function (energy_container, misc_container, name) local on_energy = energy_container._ActorTable [energy_container._NameIndexTable [name]] if (on_energy) then on_energy.fight_component = true end local on_misc = misc_container._ActorTable [misc_container._NameIndexTable [name]] if (on_misc) then on_misc.fight_component = true end end function Details:FlagActorsOnCommonFight() local damage_container = Details.tabela_vigente [1] local healing_container = Details.tabela_vigente [2] local energy_container = Details.tabela_vigente [3] local misc_container = Details.tabela_vigente [4] local mythicDungeonRun = Details.tabela_vigente.is_mythic_dungeon_segment for class_type, container in ipairs ({damage_container, healing_container}) do for _, actor in ipairs (container._ActorTable) do if (mythicDungeonRun) then actor.fight_component = true end if (actor.grupo) then if (class_type == 1 or class_type == 2) then for target_name, amount in pairs (actor.targets) do local target_object = container._ActorTable [container._NameIndexTable [target_name]] if (target_object) then target_object.fight_component = true fight_component (energy_container, misc_container, target_name) end end if (class_type == 1) then for damager_actor, _ in pairs (actor.damage_from) do local target_object = container._ActorTable [container._NameIndexTable [damager_actor]] if (target_object) then target_object.fight_component = true fight_component (energy_container, misc_container, damager_actor) end end elseif (class_type == 2) then for healer_actor, _ in pairs (actor.healing_from) do local target_object = container._ActorTable [container._NameIndexTable [healer_actor]] if (target_object) then target_object.fight_component = true fight_component (energy_container, misc_container, healer_actor) end end end end end end end end function Details:AtualizarJanela (instancia, _segmento) if (_segmento) then --> apenas atualizar janelas que estejam mostrando o segmento solicitado if (_segmento == instancia.segmento) then instancia:TrocaTabela (instancia, instancia.segmento, instancia.atributo, instancia.sub_atributo, true) end else if (instancia.modo == modo_GROUP or instancia.modo == modo_ALL) then instancia:TrocaTabela (instancia, instancia.segmento, instancia.atributo, instancia.sub_atributo, true) end end end function Details:PostponeInstanceToCurrent (instance) if ( not instance.last_interaction or ( (instance.ativa) and (instance.last_interaction+3 < _tempo) and (not DetailsReportWindow or not DetailsReportWindow:IsShown()) and (not Details.playerDetailWindow:IsShown()) ) ) then instance._postponing_current = nil if (instance.segmento == 0) then return Details:TrocaSegmentoAtual (instance) else return end end if (instance.is_interacting and instance.last_interaction < _tempo) then instance.last_interaction = _tempo end instance._postponing_current = Details:ScheduleTimer ("PostponeInstanceToCurrent", 1, instance) end function Details:TrocaSegmentoAtual (instancia, is_encounter) if (instancia.segmento == 0 and instancia.baseframe and instancia.ativa) then if (not is_encounter) then if (instancia.is_interacting) then if (not instancia.last_interaction or instancia.last_interaction < _tempo) then instancia.last_interaction = _tempo or time() end end if ((instancia.last_interaction and (instancia.last_interaction+3 > Details._tempo)) or (DetailsReportWindow and DetailsReportWindow:IsShown()) or (Details.playerDetailWindow:IsShown())) then --> postpone instancia._postponing_current = Details:ScheduleTimer ("PostponeInstanceToCurrent", 1, instancia) return end end --print ("==> Changing the Segment now! - control.lua 1220") instancia.last_interaction = _tempo - 4 --pode setar, completou o ciclo instancia._postponing_current = nil instancia.showing = Details.tabela_vigente instancia:ResetaGump() Details.FadeHandler.Fader (instancia, "in", nil, "barras") end end function Details:SetTrashSuppression (n) assert (type (n) == "number", "SetTrashSuppression expects a number on index 1.") if (n < 0) then n = 0 end Details.instances_suppress_trash = n end function Details:CheckFor_SuppressedWindowsOnEncounterFound() for _, instance in Details:ListInstances() do if (instance.ativa and instance.baseframe and (not instance.last_interaction or instance.last_interaction > _tempo) and instance.segmento == 0) then Details:TrocaSegmentoAtual (instance, true) end end end function Details:CheckFor_EnabledTrashSuppression() if (Details.HasTrashSuppression and Details.HasTrashSuppression > _tempo) then self.last_interaction = Details.HasTrashSuppression end end function Details:SetTrashSuppressionAfterEncounter() Details:InstanceCall ("CheckFor_EnabledTrashSuppression") end function Details:CheckFor_TrashSuppressionOnEncounterEnd() if (Details.instances_suppress_trash > 0) then Details.HasTrashSuppression = _tempo + Details.instances_suppress_trash --> delaying in 3 seconds for other stuff like auto open windows after combat. Details:ScheduleTimer ("SetTrashSuppressionAfterEncounter", 3) end end --> internal GetCombatId() version function Details:NumeroCombate (flag) if (flag == 0) then Details.combat_id = 0 elseif (flag) then Details.combat_id = Details.combat_id + flag end return Details.combat_id end --> tooltip fork / search key: ~tooltip local avatarPoint = {"bottomleft", "topleft", -3, -4} local backgroundPoint = {{"bottomleft", "topleft", 0, -3}, {"bottomright", "topright", 0, -3}} local textPoint = {"left", "right", -11, -5} local avatarTexCoord = {0, 1, 0, 1} local backgroundColor = {0, 0, 0, 0.6} local avatarTextColor = {1, 1, 1, 1} function Details:AddTooltipReportLineText() GameCooltip:AddLine (Loc ["STRING_CLICK_REPORT_LINE1"], Loc ["STRING_CLICK_REPORT_LINE2"]) GameCooltip:AddStatusBar (100, 1, 0, 0, 0, 0.8) end function Details:AddTooltipBackgroundStatusbar (side, value, useSpark) Details.tooltip.background [4] = 0.8 Details.tooltip.icon_size.W = Details.tooltip.line_height Details.tooltip.icon_size.H = Details.tooltip.line_height value = value or 100 if (not side) then local r, g, b, a = unpack (Details.tooltip.background) GameCooltip:AddStatusBar (value, 1, r, g, b, a, useSpark, {value = 100, color = {.21, .21, .21, 0.8}, texture = [[Interface\AddOns\Details\images\bar_serenity]]}) else GameCooltip:AddStatusBar (value, 2, unpack (Details.tooltip.background)) end end function Details:AddTooltipHeaderStatusbar (r, g, b, a) local r, g, b, a, statusbarGlow, backgroundBar = unpack (Details.tooltip.header_statusbar) GameCooltip:AddStatusBar (100, 1, r, g, b, a, statusbarGlow, backgroundBar, "Skyline") end -- /run local a,b=Details.tooltip.header_statusbar,0.3;a[1]=b;a[2]=b;a[3]=b;a[4]=0.8; function Details:AddTooltipSpellHeaderText (headerText, headerColor, amount, iconTexture, L, R, T, B, separator) if (separator and separator == true) then GameCooltip:AddLine ("", "", nil, nil, 1, 1, 1, 1, 8) return end if (Details.tooltip.show_amount) then GameCooltip:AddLine (headerText, "x" .. amount .. "", nil, headerColor, 1, 1, 1, .4, Details.tooltip.fontsize_title) else GameCooltip:AddLine (headerText, nil, nil, headerColor, nil, Details.tooltip.fontsize_title) end if (iconTexture) then GameCooltip:AddIcon (iconTexture, 1, 1, 14, 14, L or 0, R or 1, T or 0, B or 1) end end local bgColor, borderColor = {0, 0, 0, 0.8}, {0, 0, 0, 0} --{0.37, 0.37, 0.37, .75}, {.30, .30, .30, .3} function Details:FormatCooltipForSpells() local GameCooltip = GameCooltip GameCooltip:Reset() GameCooltip:SetType ("tooltip") GameCooltip:SetOption ("StatusBarTexture", [[Interface\AddOns\Details\images\bar_background]]) GameCooltip:SetOption ("TextSize", Details.tooltip.fontsize) GameCooltip:SetOption ("TextFont", Details.tooltip.fontface) GameCooltip:SetOption ("TextColor", Details.tooltip.fontcolor) GameCooltip:SetOption ("TextColorRight", Details.tooltip.fontcolor_right) GameCooltip:SetOption ("TextShadow", Details.tooltip.fontshadow and "OUTLINE") GameCooltip:SetOption ("LeftBorderSize", -5) GameCooltip:SetOption ("RightBorderSize", 5) GameCooltip:SetOption ("RightTextMargin", 0) GameCooltip:SetOption ("VerticalOffset", 9) GameCooltip:SetOption ("AlignAsBlizzTooltip", true) GameCooltip:SetOption ("AlignAsBlizzTooltipFrameHeightOffset", -8) GameCooltip:SetOption ("LineHeightSizeOffset", 4) GameCooltip:SetOption ("VerticalPadding", -4) GameCooltip:SetBackdrop (1, Details.cooltip_preset2_backdrop, bgColor, borderColor) end function Details:BuildInstanceBarTooltip (frame) local GameCooltip = GameCooltip Details:FormatCooltipForSpells() GameCooltip:SetOption ("MinWidth", _math_max (230, self.baseframe:GetWidth()*0.98)) local myPoint = Details.tooltip.anchor_point local anchorPoint = Details.tooltip.anchor_relative local x_Offset = Details.tooltip.anchor_offset[1] local y_Offset = Details.tooltip.anchor_offset[2] if (Details.tooltip.anchored_to == 1) then GameCooltip:SetHost (frame, myPoint, anchorPoint, x_Offset, y_Offset) else GameCooltip:SetHost (DetailsTooltipAnchor, myPoint, anchorPoint, x_Offset, y_Offset) end end function Details:MontaTooltip (frame, whichRowLine, keydown) self:BuildInstanceBarTooltip (frame) local GameCooltip = GameCooltip local esta_barra = self.barras [whichRowLine] --> barra que o mouse passou em cima e ir� mostrar o tooltip local objeto = esta_barra.minha_tabela --> pega a referencia da tabela --> retorna a classe_damage ou classe_heal if (not objeto) then --> a barra n�o possui um objeto return false end --verifica por tooltips especiais: if (objeto.dead) then --> � uma barra de dead return Details:ToolTipDead (self, objeto, esta_barra, keydown) --> inst�ncia, [morte], barra elseif (objeto.byspell) then return Details:ToolTipBySpell (self, objeto, esta_barra, keydown) elseif (objeto.frags) then return Details:ToolTipFrags (self, objeto, esta_barra, keydown) elseif (objeto.boss_debuff) then return Details:ToolTipVoidZones (self, objeto, esta_barra, keydown) end local t = objeto:ToolTip (self, whichRowLine, esta_barra, keydown) --> inst�ncia, n� barra, objeto barra, keydown if (t) then if (objeto.serial and objeto.serial ~= "") then local avatar = NickTag:GetNicknameTable (objeto.serial, true) if (avatar and not Details.ignore_nicktag) then if (avatar [2] and avatar [4] and avatar [1]) then GameCooltip:SetBannerImage (1, avatar [2], 80, 40, avatarPoint, avatarTexCoord, nil) --> overlay [2] avatar path GameCooltip:SetBannerImage (2, avatar [4], 200, 55, backgroundPoint, avatar [5], avatar [6]) --> background GameCooltip:SetBannerText (1, (not Details.ignore_nicktag and avatar [1]) or objeto.nome, textPoint, avatarTextColor, 14, SharedMedia:Fetch ("font", Details.tooltip.fontface)) --> text [1] nickname end else --if (Details.remove_realm_from_name and objeto.displayName:find ("%*")) then -- GameCooltip:SetBannerImage (1, [[Interface\AddOns\Details\images\background]], 20, 30, avatarPoint, avatarTexCoord, {0, 0, 0, 0}) --> overlay [2] avatar path -- GameCooltip:SetBannerImage (2, [[Interface\PetBattles\Weather-BurntEarth]], 160, 30, {{"bottomleft", "topleft", 0, -5}, {"bottomright", "topright", 0, -5}}, {0.12, 0.88, 1, 0}, {0, 0, 0, 0.1}) --> overlay [2] avatar path {0, 0, 0, 0} -- GameCooltip:SetBannerText (1, objeto.nome, {"left", "left", 11, -8}, {1, 1, 1, 0.7}, 10, SharedMedia:Fetch ("font", Details.tooltip.fontface)) --> text [1] nickname --end end end GameCooltip:ShowCooltip() end end function Details.gump:UpdateTooltip (whichRowLine, esta_barra, instancia) if (_IsShiftKeyDown()) then return instancia:MontaTooltip (esta_barra, whichRowLine, "shift") elseif (_IsControlKeyDown()) then return instancia:MontaTooltip (esta_barra, whichRowLine, "ctrl") elseif (_IsAltKeyDown()) then return instancia:MontaTooltip (esta_barra, whichRowLine, "alt") else return instancia:MontaTooltip (esta_barra, whichRowLine) end end function Details:EndRefresh (instancia, total, combatTable, showing) Details:EsconderBarrasNaoUsadas (instancia, showing) end function Details:EsconderBarrasNaoUsadas (instancia, showing) --> primeira atualiza��o ap�s uma mudan�a de segmento --> verifica se h� mais barras sendo mostradas do que o necess�rio -------------------- if (instancia.v_barras) then --print ("mostrando", instancia.rows_showing, instancia.rows_created) for barra_numero = instancia.rows_showing+1, instancia.rows_created do Details.FadeHandler.Fader (instancia.barras[barra_numero], "in") end instancia.v_barras = false if (instancia.rows_showing == 0 and instancia:GetSegment() == -1) then -- -1 overall data if (not instancia:IsShowingOverallDataWarning()) then local tutorial = Details:GetTutorialCVar ("OVERALLDATA_WARNING1") or 0 if ((type (tutorial) == "number") and (tutorial < 60)) then Details:SetTutorialCVar ("OVERALLDATA_WARNING1", tutorial + 1) instancia:ShowOverallDataWarning (true) end end else if (instancia:IsShowingOverallDataWarning()) then instancia:ShowOverallDataWarning (false) end end end return showing end --> call update functions function Details:RefreshAllMainWindows (forcar) local combatTable = self.showing --the the segment does not have a valid combat, freeze the window if (not combatTable) then if (not self.freezed) then return self:Freeze() end return end local need_refresh = combatTable[self.atributo].need_refresh if (not need_refresh and not forcar) then return --> n�o precisa de refresh --else --combatTable[self.atributo].need_refresh = false end if (self.atributo == 1) then --> damage return atributo_damage:RefreshWindow(self, combatTable, forcar, nil, need_refresh) elseif (self.atributo == 2) then --> heal return atributo_heal:RefreshWindow(self, combatTable, forcar, nil, need_refresh) elseif (self.atributo == 3) then --> energy return atributo_energy:RefreshWindow(self, combatTable, forcar, nil, need_refresh) elseif (self.atributo == 4) then --> outros return atributo_misc:RefreshWindow(self, combatTable, forcar, nil, need_refresh) elseif (self.atributo == 5) then --> ocustom return atributo_custom:RefreshWindow(self, combatTable, forcar, nil, need_refresh) end end function Details:ForceRefresh() self:RefreshMainWindow(true) end function Details:RefreshMainWindow(instance, forceRefresh) if (not instance or type(instance) == "boolean") then forceRefresh = instance instance = self end if (not forceRefresh) then Details.LastUpdateTick = Details._tempo end if (instance == -1) then --update for index, instance in ipairs(Details.tabela_instancias) do if (instance.ativa) then if (instance.modo == modo_GROUP or instance.modo == modo_ALL) then instance:RefreshAllMainWindows(forceRefresh) --print("all instances got updates") end end end --flag windows as no need update next tick for index, instance in ipairs(Details.tabela_instancias) do if (instance.ativa and instance.showing) then if (instance.modo == modo_GROUP or instance.modo == modo_ALL) then if (instance.atributo <= 4) then instance.showing [instance.atributo].need_refresh = false end end end end if (not forceRefresh) then --update player details window if opened if (info.ativo) then --print("info.jogador:MontaInfo()") return info.jogador:MontaInfo() end end return else if (not instance.ativa) then --print("instance not actived", instance.RefreshMainWindow, 1+nil) return end end if (instance.modo == modo_ALL or instance.modo == modo_GROUP) then --print("updating all instances...") return instance:RefreshAllMainWindows (forceRefresh) end end ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --> core function Details:AutoEraseConfirm() local panel = _G.DetailsEraseDataConfirmation if (not panel) then panel = CreateFrame("frame", "DetailsEraseDataConfirmation", UIParent, "BackdropTemplate") panel:SetSize(400, 85) panel:SetBackdrop({bgFile = [[Interface\AddOns\Details\images\background]], tile = true, tileSize = 16, edgeFile = [[Interface\AddOns\Details\images\border_2]], edgeSize = 12}) panel:SetPoint("center", UIParent) panel:SetBackdropColor(0, 0, 0, 0.4) DetailsFramework:ApplyStandardBackdrop(panel) panel:SetScript("OnMouseDown", function (self, button) if (button == "RightButton") then panel:Hide() end end) --[=[ create 3 options - overall data only - current data only - both --=]=] local text = Details.gump:CreateLabel (panel, Loc ["STRING_OPTIONS_CONFIRM_ERASE"], nil, nil, "GameFontNormal") text:SetPoint ("center", panel, "center") text:SetPoint ("top", panel, "top", 0, -10) local no = Details.gump:CreateButton (panel, function() panel:Hide() end, 90, 20, Loc ["STRING_NO"]) no:SetPoint ("bottomleft", panel, "bottomleft", 30, 10) no:InstallCustomTexture (nil, nil, nil, nil, true) local yes = Details.gump:CreateButton (panel, function() panel:Hide(); Details.tabela_historico:resetar() end, 90, 20, Loc ["STRING_YES"]) yes:SetPoint ("bottomright", panel, "bottomright", -30, 10) yes:InstallCustomTexture (nil, nil, nil, nil, true) end panel:Show() end function Details:CheckForAutoErase (mapid) if (Details.last_instance_id ~= mapid) then Details.tabela_historico:resetar_overall() if (Details.segments_auto_erase == 2) then --ask Details:ScheduleTimer ("AutoEraseConfirm", 1) elseif (Details.segments_auto_erase == 3) then --erase Details.tabela_historico:resetar() end else if (_tempo > Details.last_instance_time + 21600) then --6 hours if (Details.segments_auto_erase == 2) then --ask Details:ScheduleTimer ("AutoEraseConfirm", 1) elseif (Details.segments_auto_erase == 3) then --erase Details.tabela_historico:resetar() end end end Details.last_instance_id = mapid Details.last_instance_time = _tempo --Details.last_instance_time = 0 --debug end function Details:UpdateControl() _tempo = Details._tempo end