You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
6468 lines
235 KiB
6468 lines
235 KiB
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
local _detalhes = _G._detalhes
|
|
local Loc = LibStub("AceLocale-3.0"):GetLocale ( "Details" )
|
|
local DetailsFramework = DetailsFramework
|
|
|
|
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--local pointers
|
|
|
|
local UnitAffectingCombat = UnitAffectingCombat
|
|
local UnitHealth = UnitHealth
|
|
local UnitHealthMax = UnitHealthMax
|
|
local UnitGUID = UnitGUID
|
|
local IsInGroup = IsInGroup
|
|
local CombatLogGetCurrentEventInfo = CombatLogGetCurrentEventInfo
|
|
local GetTime = GetTime
|
|
local tonumber = tonumber
|
|
local tinsert = table.insert
|
|
local select = select
|
|
local bitBand = bit.band
|
|
local floor = math.floor
|
|
local ipairs = ipairs
|
|
local type = type
|
|
|
|
local meleeString = _G["MELEE"]
|
|
|
|
local _UnitGroupRolesAssigned = DetailsFramework.UnitGroupRolesAssigned
|
|
local _GetSpellInfo = _detalhes.getspellinfo
|
|
local isWOTLK = DetailsFramework.IsWotLKWow()
|
|
local _tempo = time()
|
|
local _, Details222 = ...
|
|
_ = nil
|
|
|
|
local shield_cache = _detalhes.ShieldCache --details local
|
|
local parser = _detalhes.parser --details local
|
|
|
|
local cc_spell_list = DetailsFramework.CrowdControlSpells
|
|
local container_habilidades = _detalhes.container_habilidades --details local
|
|
|
|
--localize the cooldown table from the framework
|
|
local defensive_cooldowns = DetailsFramework.CooldownsAllDeffensive --default from all game versions
|
|
|
|
if (LIB_OPEN_RAID_COOLDOWNS_INFO) then
|
|
--check if the cooldown is type 2 or 3 or 4 and add to the defensive_cooldowns table
|
|
for spellId, spellTable in pairs(LIB_OPEN_RAID_COOLDOWNS_INFO) do
|
|
if (spellTable.type == 2 or spellTable.type == 3 or spellTable.type == 4) then
|
|
defensive_cooldowns[spellId] = true
|
|
end
|
|
end
|
|
end
|
|
|
|
--cache the addition functions for each attribute
|
|
local _spell_damage_func = _detalhes.habilidade_dano.Add
|
|
local _spell_damageMiss_func = _detalhes.habilidade_dano.AddMiss
|
|
local _spell_heal_func = _detalhes.habilidade_cura.Add
|
|
local _spell_energy_func = _detalhes.habilidade_e_energy.Add
|
|
local _spell_utility_func = _detalhes.habilidade_misc.Add
|
|
|
|
--current combat and overall pointers
|
|
local _current_combat = _detalhes.tabela_vigente or {} --placeholder table
|
|
|
|
--total container pointers
|
|
local _current_total = _current_combat.totals
|
|
local _current_gtotal = _current_combat.totals_grupo
|
|
|
|
--actors container pointers
|
|
local _current_damage_container = _current_combat [1]
|
|
local _current_heal_container = _current_combat [2]
|
|
local _current_energy_container = _current_combat [3]
|
|
local _current_misc_container = _current_combat [4]
|
|
|
|
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--cache
|
|
local names_cache = {}
|
|
--damage
|
|
local damage_cache = setmetatable({}, _detalhes.weaktable)
|
|
local damage_cache_pets = setmetatable({}, _detalhes.weaktable)
|
|
local damage_cache_petsOwners = setmetatable({}, _detalhes.weaktable)
|
|
--heaing
|
|
local healing_cache = setmetatable({}, _detalhes.weaktable)
|
|
local banned_healing_spells = {
|
|
[326514] = true, --remove on 10.0 - Forgeborne Reveries - necrolords ability
|
|
}
|
|
--energy
|
|
local energy_cache = setmetatable({}, _detalhes.weaktable)
|
|
--misc
|
|
local misc_cache = setmetatable({}, _detalhes.weaktable)
|
|
local misc_cache_pets = setmetatable({}, _detalhes.weaktable)
|
|
local misc_cache_petsOwners = setmetatable({}, _detalhes.weaktable)
|
|
--party & raid members
|
|
local raid_members_cache = setmetatable({}, _detalhes.weaktable)
|
|
--tanks
|
|
local tanks_members_cache = setmetatable({}, _detalhes.weaktable)
|
|
--auto regen
|
|
local auto_regen_cache = setmetatable({}, _detalhes.weaktable)
|
|
--bitfield swap cache
|
|
local bitfield_swap_cache = {}
|
|
--damage and heal last events
|
|
local last_events_cache = {} --just initialize table (placeholder)
|
|
--hunter pet frenzy cache
|
|
local pet_frenzy_cache = {}
|
|
--npcId cache
|
|
local npcid_cache = {}
|
|
--enemy cast cache
|
|
local enemy_cast_cache = {}
|
|
--shield spellid cache
|
|
local shield_spellid_cache = {}
|
|
--pets
|
|
local container_pets = {} --just initialize table (placeholder)
|
|
--ignore deaths
|
|
local ignore_death_cache = {}
|
|
--cache
|
|
local cacheAnything = {
|
|
arenaHealth = {},
|
|
paladin_vivaldi_blessings = {},
|
|
track_hunter_frenzy = false,
|
|
}
|
|
|
|
|
|
|
|
--cache the data for passive trinkets procs
|
|
local _trinket_data_cache = {}
|
|
|
|
--spell containers for special cases
|
|
local monk_guard_talent = {} --guard talent for bm monks
|
|
|
|
--spell reflection
|
|
local reflection_damage = {} --self-inflicted damage
|
|
local reflection_debuffs = {} --self-inflicted debuffs
|
|
local reflection_events = {} --spell_missed reflected events
|
|
local reflection_auras = {} --active reflecting auras
|
|
local reflection_dispels = {} --active reflecting dispels
|
|
local reflection_spellid = {
|
|
--we can track which spell caused the reflection
|
|
--this is used to credit this aura as the one doing the damage
|
|
[23920] = true, --warrior spell reflection
|
|
[216890] = true, --warrior spell reflection (pvp talent)
|
|
[213915] = true, --warrior mass spell reflection
|
|
[212295] = true, --warlock nether ward
|
|
--check pally legendary
|
|
}
|
|
local reflection_dispelid = {
|
|
--some dispels also reflect, and we can track them
|
|
[122783] = true, --monk diffuse magic
|
|
|
|
--[205604] = true, --demon hunter reverse magic
|
|
--this last one is an odd one, like most dh spells is kindy buggy combatlog wise
|
|
--for now it doesn't fire SPELL_DISPEL events even when dispelling stuff (thanks blizzard)
|
|
--maybe someone can figure out something to track it... but for now it doesnt work
|
|
}
|
|
local reflection_ignore = {
|
|
--common self-harm spells that we know weren't reflected
|
|
--this list can be expanded
|
|
[111400] = true, --warlock burning rush
|
|
[124255] = true, --monk stagger
|
|
[196917] = true, --paladin light of the martyr
|
|
[217979] = true, --warlock health funnel
|
|
}
|
|
|
|
--army od the dead cache
|
|
local dk_pets_cache = {
|
|
army = {},
|
|
apoc = {},
|
|
}
|
|
|
|
local buffs_to_other_players = {
|
|
[10060] = true, --power infusion
|
|
}
|
|
|
|
local empower_cache = {}
|
|
|
|
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--constants
|
|
local container_misc = _detalhes.container_type.CONTAINER_MISC_CLASS
|
|
|
|
local OBJECT_TYPE_ENEMY = 0x00000040
|
|
local OBJECT_TYPE_PLAYER = 0x00000400
|
|
local OBJECT_TYPE_PETS = 0x00003000
|
|
local AFFILIATION_GROUP = 0x00000007
|
|
local REACTION_FRIENDLY = 0x00000010
|
|
|
|
local ENVIRONMENTAL_FALLING_NAME = Loc ["STRING_ENVIRONMENTAL_FALLING"]
|
|
local ENVIRONMENTAL_DROWNING_NAME = Loc ["STRING_ENVIRONMENTAL_DROWNING"]
|
|
local ENVIRONMENTAL_FATIGUE_NAME = Loc ["STRING_ENVIRONMENTAL_FATIGUE"]
|
|
local ENVIRONMENTAL_FIRE_NAME = Loc ["STRING_ENVIRONMENTAL_FIRE"]
|
|
local ENVIRONMENTAL_LAVA_NAME = Loc ["STRING_ENVIRONMENTAL_LAVA"]
|
|
local ENVIRONMENTAL_SLIME_NAME = Loc ["STRING_ENVIRONMENTAL_SLIME"]
|
|
|
|
local RAID_TARGET_FLAGS = {
|
|
[128] = true, --0x80 skull
|
|
[64] = true, --0x40 cross
|
|
[32] = true, --0x20 square
|
|
[16] = true, --0x10 moon
|
|
[8] = true, --0x8 triangle
|
|
[4] = true, --0x4 diamond
|
|
[2] = true, --0x2 circle
|
|
[1] = true, --0x1 star
|
|
}
|
|
|
|
--spellIds override
|
|
local override_spellId = {}
|
|
|
|
if (isWOTLK) then
|
|
override_spellId = {
|
|
--Scourge Strike
|
|
[55090] = 55271,
|
|
[55265] = 55271,
|
|
[55270] = 55271,
|
|
[70890] = 55271, --shadow
|
|
|
|
--Frost Strike
|
|
[49143] = 55268,
|
|
[51416] = 55268,
|
|
[51417] = 55268,
|
|
[51418] = 55268,
|
|
[51419] = 55268,
|
|
[66962] = 55268, --offhand
|
|
|
|
--Obliterate
|
|
[49020] = 51425,
|
|
[51423] = 51425,
|
|
[51424] = 51425,
|
|
[66974] = 51425, --offhand
|
|
|
|
--Death Strike
|
|
[49998] = 49924,
|
|
[49999] = 49924,
|
|
[45463] = 49924,
|
|
[49923] = 49924,
|
|
[66953] = 49924, --offhand
|
|
|
|
--Blood Strike
|
|
[45902] = 49930,
|
|
[49926] = 49930,
|
|
[49927] = 49930,
|
|
[49928] = 49930,
|
|
[49929] = 49930,
|
|
[66979] = 49930, --offhand
|
|
|
|
--Rune Strike
|
|
[6621] = 56815, --offhand
|
|
|
|
--Plague Strike
|
|
[45462] = 49921,
|
|
[49917] = 49921,
|
|
[49918] = 49921,
|
|
[49919] = 49921,
|
|
[49920] = 49921,
|
|
[66992] = 49921, --offhand
|
|
|
|
--Seal of Command
|
|
[20424] = 69403, --53739 and 53733
|
|
|
|
--odyn's fury warrior
|
|
[385062] = 385060,
|
|
[385061] = 385060,
|
|
|
|
--crushing blow
|
|
[335098] = 335097,
|
|
[335100] = 335097,
|
|
|
|
--charge warrior
|
|
[105771] = 126664,
|
|
|
|
--elemental stances
|
|
[377458] = 377459,
|
|
[377461] = 377459,
|
|
[382133] = 377459,
|
|
}
|
|
|
|
else --retail
|
|
override_spellId = {
|
|
[184707] = 218617, --warrior rampage
|
|
[184709] = 218617, --warrior rampage
|
|
[201364] = 218617, --warrior rampage
|
|
[201363] = 218617, --warrior rampage
|
|
[85384] = 96103, --warrior raging blow
|
|
[85288] = 96103, --warrior raging blow
|
|
[280849] = 5308, --warrior execute
|
|
[163558] = 5308, --warrior execute
|
|
[217955] = 5308, --warrior execute
|
|
[217956] = 5308, --warrior execute
|
|
[217957] = 5308, --warrior execute
|
|
[224253] = 5308, --warrior execute
|
|
[199850] = 199658, --warrior whirlwind
|
|
[190411] = 199658, --warrior whirlwind
|
|
[44949] = 199658, --warrior whirlwind
|
|
[199667] = 199658, --warrior whirlwind
|
|
[199852] = 199658, --warrior whirlwind
|
|
[199851] = 199658, --warrior whirlwind
|
|
|
|
[222031] = 199547, --deamonhunter ChaosStrike
|
|
[200685] = 199552, --deamonhunter Blade Dance
|
|
[391378] = 199552, --^
|
|
[391374] = 199552, --^
|
|
[210155] = 210153, --deamonhunter Death Sweep
|
|
[393055] = 210153, --^
|
|
[393054] = 210153, --^
|
|
[393035] = 337819, --demonhunter throw glaive
|
|
[227518] = 201428, --deamonhunter Annihilation
|
|
[187727] = 178741, --deamonhunter Immolation Aura
|
|
[201789] = 201628, --deamonhunter Fury of the Illidari
|
|
[225921] = 225919, --deamonhunter Fracture talent
|
|
|
|
[205164] = 205165, --death knight Crystalline Swords
|
|
|
|
[193315] = 197834, --rogue Saber Slash
|
|
[202822] = 202823, --rogue greed
|
|
[280720] = 282449, --rogue Secret Technique
|
|
[280719] = 282449, --rogue Secret Technique
|
|
[27576] = 5374, --rogue mutilate
|
|
|
|
[233496] = 233490, --warlock Unstable Affliction
|
|
[233497] = 233490, --warlock Unstable Affliction
|
|
[233498] = 233490, --warlock Unstable Affliction
|
|
[233499] = 233490, --warlock Unstable Affliction
|
|
|
|
[261947] = 261977, --monk fist of the white tiger talent
|
|
|
|
[32175] = 17364, -- shaman Stormstrike (from Turkar on github)
|
|
[32176] = 17364, -- shaman Stormstrike
|
|
[45284] = 188196, --shaman lightining bolt overloaded
|
|
|
|
[228361] = 228360, --shadow priest void erruption
|
|
}
|
|
end
|
|
|
|
local bitfield_debuffs = {}
|
|
for _, spellid in ipairs(_detalhes.BitfieldSwapDebuffsIDs) do
|
|
local spellname = GetSpellInfo(spellid)
|
|
if (spellname) then
|
|
bitfield_debuffs[spellname] = true
|
|
else
|
|
bitfield_debuffs[spellid] = true
|
|
end
|
|
end
|
|
|
|
for spellId in pairs(_detalhes.BitfieldSwapDebuffsSpellIDs) do
|
|
bitfield_debuffs [spellId] = true
|
|
end
|
|
|
|
Details.bitfield_debuffs_table = bitfield_debuffs
|
|
|
|
--tbc spell caches
|
|
local TBC_PrayerOfMendingCache = {}
|
|
local TBC_EarthShieldCache = {}
|
|
local TBC_JudgementOfLightCache = {
|
|
_damageCache = {}
|
|
}
|
|
|
|
--expose the override spells table to external scripts
|
|
_detalhes.OverridedSpellIds = override_spellId
|
|
|
|
--list of ignored npcs by the user
|
|
_detalhes.default_ignored_npcs = {
|
|
--DH Havoc Talent Fodder to the Flame
|
|
[169421] = true,
|
|
[169425] = true,
|
|
[168932] = true,
|
|
[169426] = true,
|
|
[169429] = true,
|
|
[169428] = true,
|
|
[169430] = true,
|
|
|
|
--Volatile Spark on razga'reth
|
|
[194999] = true,
|
|
}
|
|
|
|
local ignored_npcids = {}
|
|
|
|
--ignore soul link (damage from the warlock on his pet - current to demonology only)
|
|
local SPELLID_WARLOCK_SOULLINK = 108446
|
|
--brewmaster monk guard talent
|
|
local SPELLID_MONK_GUARD = 115295
|
|
|
|
--shaman earth shield (bcc)
|
|
local SPELLID_SHAMAN_EARTHSHIELD_HEAL = 379
|
|
local SPELLID_SHAMAN_EARTHSHIELD_BUFF_RANK1 = 974
|
|
local SPELLID_SHAMAN_EARTHSHIELD_BUFF_RANK2 = 32593
|
|
local SPELLID_SHAMAN_EARTHSHIELD_BUFF_RANK3 = 32594
|
|
local SHAMAN_EARTHSHIELD_BUFF = {
|
|
[SPELLID_SHAMAN_EARTHSHIELD_BUFF_RANK1] = true,
|
|
[SPELLID_SHAMAN_EARTHSHIELD_BUFF_RANK2] = true,
|
|
[SPELLID_SHAMAN_EARTHSHIELD_BUFF_RANK3] = true,
|
|
}
|
|
--holy priest prayer of mending (bcc)
|
|
local SPELLID_PRIEST_POM_BUFF = 41635
|
|
local SPELLID_PRIEST_POM_HEAL = 33110
|
|
local SPELLID_SANGUINE_HEAL = 226510
|
|
|
|
--spells with special treatment
|
|
local special_damage_spells = {
|
|
[98021] = true, --spirit link toten
|
|
[124255] = true, --stagger
|
|
[282449] = true, --akaari's soul rogue
|
|
[196917] = true, --light of the martyr
|
|
[388009] = true, --blessing of spring
|
|
[388012] = true, --blessing of summer
|
|
}
|
|
|
|
--damage spells to ignore
|
|
local damage_spells_to_ignore = {
|
|
--the damage that the warlock apply to its pet through soullink is ignored
|
|
--it is not useful for damage done or friendly fire
|
|
[SPELLID_WARLOCK_SOULLINK] = true,
|
|
}
|
|
|
|
--expose the ignore spells table to external scripts
|
|
_detalhes.SpellsToIgnore = damage_spells_to_ignore
|
|
|
|
--is parser allowed to replace spellIDs?
|
|
local is_using_spellId_override = false
|
|
|
|
--cache data for fast access during parsing
|
|
local _in_combat = false
|
|
local _current_encounter_id
|
|
local _in_resting_zone = false
|
|
local _global_combat_counter = 0
|
|
|
|
local _is_activity_time = false
|
|
|
|
---amount of events allowed to store in the table which records the latest events that happened to a player before his death, this value can also be retrieved with Details.deadlog_events
|
|
local _amount_of_last_events = 16
|
|
|
|
--map type
|
|
local _is_in_instance = false
|
|
|
|
--overheal for shields
|
|
local _use_shield_overheal = false
|
|
|
|
--hooks
|
|
local _hook_cooldowns = false
|
|
local _hook_deaths = false
|
|
local _hook_battleress = false
|
|
local _hook_interrupt = false
|
|
|
|
local _hook_cooldowns_container = _detalhes.hooks ["HOOK_COOLDOWN"]
|
|
local _hook_deaths_container = _detalhes.hooks ["HOOK_DEATH"]
|
|
local _hook_battleress_container = _detalhes.hooks ["HOOK_BATTLERESS"]
|
|
local _hook_interrupt_container = _detalhes.hooks ["HOOK_INTERRUPT"]
|
|
|
|
--regen overflow
|
|
local auto_regen_power_specs = {
|
|
[103] = Enum.PowerType.Energy, --druid feral
|
|
[259] = Enum.PowerType.Energy, --rogue ass
|
|
[260] = Enum.PowerType.Energy, --rogue outlaw
|
|
[261] = Enum.PowerType.Energy, --rogue sub
|
|
[254] = Enum.PowerType.Focus, --hunter mm
|
|
[253] = Enum.PowerType.Focus, --hunter bm
|
|
[255] = Enum.PowerType.Focus, --hunter survival
|
|
[268] = Enum.PowerType.Energy, --monk brewmaster
|
|
[269] = Enum.PowerType.Energy, --monk windwalker
|
|
}
|
|
|
|
local AUTO_REGEN_PRECISION = 2 --todo: replace the amount of wasted resource by the amount of time the player "sitted" at max power
|
|
|
|
--sanguine affix for m+
|
|
Details.SanguineHealActorName = GetSpellInfo(SPELLID_SANGUINE_HEAL)
|
|
|
|
--cache a spellName and the value is the spellId
|
|
--the container actor will use this name to create a fake player actor where its name is the spellName and the specIcon is the spellIcon
|
|
Details.SpecialSpellActorsName = {}
|
|
|
|
--add sanguine affix
|
|
if (not isWOTLK) then
|
|
if (Details.SanguineHealActorName) then
|
|
Details.SpecialSpellActorsName[Details.SanguineHealActorName] = SPELLID_SANGUINE_HEAL
|
|
end
|
|
end
|
|
|
|
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--internal functions
|
|
|
|
-----------------------------------------------------------------------------------------------------------------------------------------
|
|
--DAMAGE serach key: ~damage |
|
|
-----------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
--function parser:swing (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, amount, overkill, school, resisted, blocked, absorbed, critical, glacing, crushing, isoffhand)
|
|
-- return parser:spell_dmg (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, 1, _G["MELEE"], 00000001, amount, overkill, school, resisted, blocked, absorbed, critical, glacing, crushing, isoffhand)
|
|
--spellid, spellname, spelltype
|
|
--end
|
|
|
|
--function parser:range (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname, spelltype, amount, overkill, school, resisted, blocked, absorbed, critical, glacing, crushing, isoffhand)
|
|
-- return parser:spell_dmg (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname, spelltype, amount, overkill, school, resisted, blocked, absorbed, critical, glacing, crushing, isoffhand)
|
|
--end
|
|
|
|
local who_aggro = function(self)
|
|
if ((_detalhes.LastPullMsg or 0) + 30 > time()) then
|
|
_detalhes.WhoAggroTimer = nil
|
|
return
|
|
end
|
|
_detalhes.LastPullMsg = time()
|
|
|
|
local hitLine = self.HitBy or "|cFFFFBB00First Hit|r: *?*"
|
|
local targetLine = ""
|
|
|
|
if (Details.bossTargetAtPull) then
|
|
targetLine = " |cFFFFBB00Boss First Target|r: " .. Details.bossTargetAtPull
|
|
else
|
|
for i = 1, 5 do
|
|
local boss = UnitExists("boss" .. i)
|
|
if (boss) then
|
|
local target = UnitName ("boss" .. i .. "target")
|
|
if (target and type(target) == "string") then
|
|
targetLine = " |cFFFFBB00Boss First Target|r: " .. target
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
_detalhes:Msg(hitLine .. targetLine)
|
|
_detalhes.WhoAggroTimer = nil
|
|
Details.bossTargetAtPull = nil
|
|
end
|
|
|
|
local lastRecordFound = {id = 0, diff = 0, combatTime = 0}
|
|
|
|
_detalhes.PrintEncounterRecord = function(self)
|
|
--this block won't execute if the storage isn't loaded
|
|
--self is a timer reference from C_Timer
|
|
|
|
local encounterID = self.Boss
|
|
local diff = self.Diff
|
|
|
|
if (diff == 15 or diff == 16) then
|
|
|
|
local value, rank, combatTime = 0, 0, 0
|
|
|
|
if (encounterID == lastRecordFound.id and diff == lastRecordFound.diff) then
|
|
--is the same encounter, no need to find the value again.
|
|
value, rank, combatTime = lastRecordFound.value, lastRecordFound.rank, lastRecordFound.combatTime
|
|
else
|
|
local db = _detalhes.GetStorage()
|
|
|
|
local role = _UnitGroupRolesAssigned("player")
|
|
local isDamage = (role == "DAMAGER") or (role == "TANK") --or true
|
|
local bestRank, encounterTable = _detalhes.storage:GetBestFromPlayer (diff, encounterID, isDamage and "damage" or "healing", _detalhes.playername, true)
|
|
|
|
if (bestRank) then
|
|
local playerTable, onEncounter, rankPosition = _detalhes.storage:GetPlayerGuildRank (diff, encounterID, isDamage and "damage" or "healing", _detalhes.playername, true)
|
|
|
|
value = bestRank[1] or 0
|
|
rank = rankPosition or 0
|
|
combatTime = encounterTable.elapsed
|
|
|
|
--if found the result, cache the values so no need to search again next pull
|
|
lastRecordFound.value = value
|
|
lastRecordFound.rank = rank
|
|
lastRecordFound.id = encounterID
|
|
lastRecordFound.diff = diff
|
|
lastRecordFound.combatTime = combatTime
|
|
else
|
|
--if didn't found, no reason to search again on next pull
|
|
lastRecordFound.value = 0
|
|
lastRecordFound.rank = 0
|
|
lastRecordFound.combatTime = 0
|
|
lastRecordFound.id = encounterID
|
|
lastRecordFound.diff = diff
|
|
end
|
|
end
|
|
|
|
if (value and combatTime and value > 0 and combatTime > 0) then
|
|
_detalhes:Msg("|cFFFFBB00Your Best Score|r:", _detalhes:ToK2 ((value) / combatTime) .. " [|cFFFFFF00Guild Rank: " .. rank .. "|r]") --localize-me
|
|
end
|
|
|
|
if ((not combatTime or combatTime == 0) and not _detalhes.SyncWarning) then
|
|
_detalhes:Msg("|cFFFF3300you may need sync the rank within the guild, type '|cFFFFFF00/details rank|r'|r") --localize-me
|
|
_detalhes.SyncWarning = true
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
function parser:spell_dmg(token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, targetRaidFlags, spellId, spellName, spellType, amount, overkill, school, resisted, blocked, absorbed, critical, glacing, crushing, isoffhand, isreflected)
|
|
--early checks and fixes
|
|
if (sourceSerial == "") then
|
|
if (sourceFlags and bitBand(sourceFlags, OBJECT_TYPE_PETS) ~= 0) then
|
|
--pets must have a serial
|
|
return
|
|
end
|
|
end
|
|
|
|
--melee
|
|
if (token == "SWING_DAMAGE") then
|
|
spellId, spellName, spellType, amount, overkill, school, resisted, blocked, absorbed, critical, glacing, crushing, isoffhand = 1, meleeString, 00000001, spellId, spellName, spellType, amount, overkill, school, resisted, blocked, absorbed, critical
|
|
end
|
|
|
|
if (not targetName) then
|
|
--no target name, just quit
|
|
return
|
|
|
|
elseif (not sourceName) then
|
|
--no actor name, use spell name instead
|
|
sourceName = names_cache[spellName]
|
|
if (not sourceName) then
|
|
sourceName = "[*] " .. spellName
|
|
names_cache[spellName] = sourceName
|
|
end
|
|
sourceFlags = 0xa48
|
|
sourceSerial = ""
|
|
end
|
|
|
|
--check if the spell is in the backlist and return if true
|
|
if (damage_spells_to_ignore[spellId]) then
|
|
return
|
|
end
|
|
|
|
--spell reflection code by github user @m4tjz
|
|
if (sourceSerial == targetSerial and not reflection_ignore[spellId]) then --~reflect
|
|
--this spell could've been reflected, check it
|
|
if (reflection_events[sourceSerial] and reflection_events[sourceSerial][spellId] and time-reflection_events[sourceSerial][spellId].time > 3.5 and (not reflection_debuffs[sourceSerial] or (reflection_debuffs[sourceSerial] and not reflection_debuffs[sourceSerial][spellId]))) then
|
|
--here we check if we have to filter old reflection data
|
|
--we check for two conditions
|
|
--the first is to see if this is an old reflection
|
|
--if more than 3.5 seconds have past then we can say that it is old... but!
|
|
--the second condition is to see if there is an active debuff with the same spellid
|
|
--if there is one then we ignore the timer and skip this
|
|
--this should be cleared afterwards somehow... don't know how...
|
|
reflection_events[sourceSerial][spellId] = nil
|
|
if (next(reflection_events[sourceSerial]) == nil) then
|
|
--there should be some better way of handling this kind of filtering, any suggestion?
|
|
reflection_events[sourceSerial] = nil
|
|
end
|
|
end
|
|
|
|
local reflection = reflection_events[sourceSerial] and reflection_events[sourceSerial][spellId]
|
|
if (reflection) then
|
|
--if we still have the reflection data then we conclude it was reflected
|
|
|
|
--extend the duration of the timer to catch the rare channelling spells
|
|
reflection_events[sourceSerial][spellId].time = time
|
|
|
|
--crediting the source of the reflection aura
|
|
sourceSerial = reflection.who_serial
|
|
sourceName = reflection.who_name
|
|
sourceFlags = reflection.who_flags
|
|
|
|
--data of the aura that caused the reflection
|
|
--print("2", spellid, GetSpellInfo(spellid))
|
|
isreflected = spellId --which spell was reflected
|
|
spellId = reflection.spellid --which spell made the reflection
|
|
spellName = reflection.spellname
|
|
spellType = reflection.spelltype
|
|
|
|
return parser:spell_dmg(token,time,sourceSerial,sourceName,sourceFlags,targetSerial,targetName,targetFlags,targetRaidFlags,spellId,spellName,0x400,amount,-1,nil,nil,nil,nil,false,false,false,false, isreflected)
|
|
else
|
|
--saving information about this damage because it may occurred before a reflect event
|
|
reflection_damage[sourceSerial] = reflection_damage[sourceSerial] or {}
|
|
reflection_damage[sourceSerial][spellId] = {
|
|
amount = amount,
|
|
time = time,
|
|
}
|
|
end
|
|
end
|
|
|
|
--if the parser are allowed to replace spellIDs
|
|
if (is_using_spellId_override) then
|
|
spellId = override_spellId[spellId] or spellId
|
|
end
|
|
|
|
--npcId check for ignored npcs
|
|
local npcId = npcid_cache[targetSerial]
|
|
|
|
--target
|
|
if (not npcId) then
|
|
--this string manipulation is running on every event
|
|
npcId = tonumber(select(6, strsplit("-", targetSerial)) or 0)
|
|
npcid_cache[targetSerial] = npcId
|
|
end
|
|
|
|
if (ignored_npcids[npcId]) then
|
|
return
|
|
end
|
|
|
|
--source
|
|
npcId = npcid_cache[sourceSerial]
|
|
if (not npcId) then
|
|
npcId = tonumber(select(6, strsplit("-", sourceSerial)) or 0)
|
|
npcid_cache[sourceSerial] = npcId
|
|
end
|
|
|
|
if (ignored_npcids[npcId]) then
|
|
return
|
|
end
|
|
|
|
if (npcId == 24207) then --army of the dead
|
|
--check if this is a army or apoc pet
|
|
if (dk_pets_cache.army[sourceSerial]) then
|
|
local cachedName = names_cache[24207001]
|
|
if (not cachedName) then
|
|
sourceName = sourceName .. "|T237511:0|t"
|
|
names_cache[24207001] = sourceName
|
|
else
|
|
sourceName = cachedName
|
|
end
|
|
else
|
|
local cachedName = names_cache[24207002]
|
|
if (not cachedName) then
|
|
sourceName = sourceName .. "|T1392565:0|t"
|
|
names_cache[24207002] = sourceName
|
|
else
|
|
sourceName = cachedName
|
|
end
|
|
end
|
|
end
|
|
|
|
--avoid doing spellID checks on each iteration
|
|
if (special_damage_spells[spellId]) then
|
|
--stagger
|
|
if (spellId == 124255) then
|
|
return parser:MonkStagger_damage(token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, spellId, spellName, spellType, amount, overkill, school, resisted, blocked, absorbed, critical, glacing, crushing, isoffhand)
|
|
|
|
--spirit link toten
|
|
elseif (spellId == 98021) then
|
|
return parser:SLT_damage(token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, spellId, spellName, spellType, amount, overkill, school, resisted, blocked, absorbed, critical, glacing, crushing, isoffhand)
|
|
|
|
--rogue's secret technique | when akari's soul gives damage | dragonflight | --REMOVE ON 11.0 - maybe
|
|
elseif (spellId == 282449) then
|
|
--npcID
|
|
if (npcId == 144961) then
|
|
local ownerName, ownerGUID, ownerFlags = Details222.Pets.AkaarisSoulOwner(sourceSerial, sourceName)
|
|
if (ownerName and ownerGUID) then
|
|
sourceSerial = ownerGUID
|
|
sourceName = ownerName
|
|
sourceFlags = ownerFlags
|
|
end
|
|
end
|
|
|
|
--Light of the Martyr - paladin spell which causes damage to the caster it self
|
|
elseif (spellId == 196917) then -- or spellid == 183998 < healing part
|
|
return parser:LOTM_damage(token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, spellId, spellName, spellType, amount, overkill, school, resisted, blocked, absorbed, critical, glacing, crushing, isoffhand)
|
|
|
|
elseif (spellId == 388009 or spellId == 388012) then --damage from the paladin blessings of the seasons
|
|
local blessingSource = cacheAnything.paladin_vivaldi_blessings[sourceSerial]
|
|
if (blessingSource) then
|
|
sourceSerial, sourceName, sourceFlags = unpack(blessingSource)
|
|
end
|
|
end
|
|
end
|
|
|
|
--wrath of the lich king
|
|
if (isWOTLK) then
|
|
--is the target an enemy with judgement of light?
|
|
if (TBC_JudgementOfLightCache[targetName] and false) then
|
|
--store the player name which just landed a damage
|
|
TBC_JudgementOfLightCache._damageCache[sourceName] = {time, targetName}
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--check if need start an combat
|
|
if (not _in_combat) then --~startcombat ~combatstart
|
|
if ( token ~= "SPELL_PERIODIC_DAMAGE" and
|
|
(
|
|
(sourceFlags and bitBand(sourceFlags, AFFILIATION_GROUP) ~= 0 and UnitAffectingCombat(sourceName) )
|
|
or
|
|
(targetFlags and bitBand(targetFlags, AFFILIATION_GROUP) ~= 0 and UnitAffectingCombat(targetName) )
|
|
or
|
|
(not _detalhes.in_group and sourceFlags and bitBand(sourceFlags, AFFILIATION_GROUP) ~= 0)
|
|
)
|
|
) then
|
|
--avoid Fel Armor and Undulating Maneuvers to start a combat
|
|
if ((spellId == 387846 or spellId == 352561) and sourceName == _detalhes.playername) then
|
|
return
|
|
end
|
|
|
|
if (_detalhes.encounter_table.id and _detalhes.encounter_table["start"] >= GetTime() - 3 and _detalhes.announce_firsthit.enabled) then
|
|
local link
|
|
if (spellId <= 10) then
|
|
link = _GetSpellInfo(spellId)
|
|
else
|
|
link = _GetSpellInfo(spellId)
|
|
end
|
|
|
|
if (_detalhes.WhoAggroTimer) then
|
|
_detalhes.WhoAggroTimer:Cancel()
|
|
end
|
|
|
|
_detalhes.WhoAggroTimer = C_Timer.NewTimer(0.1, who_aggro)
|
|
_detalhes.WhoAggroTimer.HitBy = "|cFFFFFF00First Hit|r: " .. (link or "") .. " from " .. (sourceName or "Unknown")
|
|
print("debug:", _detalhes.WhoAggroTimer.HitBy)
|
|
end
|
|
|
|
_detalhes:EntrarEmCombate(sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags)
|
|
else
|
|
--entrar em combate se for dot e for do jogador e o ultimo combate ter sido a mais de 10 segundos atr�s
|
|
if (token == "SPELL_PERIODIC_DAMAGE" and sourceName == _detalhes.playername) then
|
|
--ignora burning rush se o jogador estiver fora de combate
|
|
--111400 warlock's burning rush
|
|
--368637 is buff from trinket "Scars of Fraternal Strife" which make the player bleed even out-of-combat
|
|
--371070 is "Iced Phial of Corrupting Rage" effect triggers randomly, even out-of-combat
|
|
if (spellId == 111400 or spellId == 371070 or spellId == 368637) then
|
|
return
|
|
end
|
|
|
|
--faz o calculo dos 10 segundos
|
|
if (_detalhes.last_combat_time + 10 < _tempo) then
|
|
_detalhes:EntrarEmCombate(sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--[[statistics]]-- _detalhes.statistics.damage_calls = _detalhes.statistics.damage_calls + 1
|
|
_current_damage_container.need_refresh = true
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--get actors
|
|
|
|
--source damager
|
|
local sourceActor, ownerActor = damage_cache[sourceSerial] or damage_cache_pets[sourceSerial] or damage_cache[sourceName], damage_cache_petsOwners[sourceSerial]
|
|
|
|
if (not sourceActor) then
|
|
sourceActor, ownerActor, sourceName = _current_damage_container:PegarCombatente(sourceSerial, sourceName, sourceFlags, true)
|
|
|
|
if (ownerActor) then --the actor is a pet
|
|
if (sourceSerial ~= "") then
|
|
--insert in the pet cache
|
|
damage_cache_pets[sourceSerial] = sourceActor
|
|
damage_cache_petsOwners[sourceSerial] = ownerActor
|
|
end
|
|
--check if the pet owner is already in the cache
|
|
if (not damage_cache[ownerActor.serial] and ownerActor.serial ~= "") then
|
|
damage_cache[ownerActor.serial] = ownerActor
|
|
end
|
|
else
|
|
--there's no owner actor
|
|
if (sourceFlags) then
|
|
if (sourceSerial ~= "") then
|
|
--insert the sourceActor into the cache
|
|
damage_cache[sourceSerial] = sourceActor
|
|
else
|
|
if (names_cache[spellName]) then --sourceName = "[*] " .. spellName
|
|
damage_cache[sourceName] = sourceActor
|
|
local _, _, spellIcon = _GetSpellInfo(spellId or 1)
|
|
sourceActor.spellicon = spellIcon
|
|
else
|
|
--_detalhes:Msg("Unknown actor with unknown serial ", spellname, who_name)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
elseif (ownerActor) then --has (sourceActor and ownerActor)
|
|
--sourceName is the name of the pet
|
|
local cachedPetName = names_cache[sourceSerial]
|
|
if (not cachedPetName) then
|
|
--add the owner name into the sourceName
|
|
sourceName = sourceName .. " <" .. ownerActor.nome .. ">"
|
|
names_cache[sourceSerial] = sourceName
|
|
else
|
|
sourceName = cachedPetName
|
|
end
|
|
end
|
|
|
|
if (not sourceActor) then
|
|
return
|
|
end
|
|
|
|
--target
|
|
local targetActor, targetOwner = damage_cache[targetSerial] or damage_cache_pets[targetSerial] or damage_cache[targetName], damage_cache_petsOwners[targetSerial]
|
|
|
|
if (not targetActor) then
|
|
targetActor, targetOwner, targetName = _current_damage_container:PegarCombatente(targetSerial, targetName, targetFlags, true)
|
|
if (targetOwner) then
|
|
if (targetSerial ~= "") then
|
|
--insert in the pet cache
|
|
damage_cache_pets[targetSerial] = targetActor
|
|
damage_cache_petsOwners[targetSerial] = targetOwner
|
|
end
|
|
--check if the pet owner is already in the cache
|
|
if (not damage_cache[targetOwner.serial] and targetOwner.serial ~= "") then
|
|
damage_cache[targetOwner.serial] = targetOwner
|
|
end
|
|
else
|
|
if (targetFlags and targetSerial ~= "") then --ter certeza que n�o � um pet
|
|
damage_cache [targetSerial] = targetActor
|
|
end
|
|
end
|
|
|
|
elseif (targetOwner) then
|
|
--sourceName is the name of the pet
|
|
local cachedPetName = names_cache[targetSerial]
|
|
if (not cachedPetName) then
|
|
--add the owner name into the sourceName
|
|
targetName = targetName .. " <" .. targetOwner.nome .. ">"
|
|
names_cache[targetSerial] = targetName
|
|
else
|
|
targetName = cachedPetName
|
|
end
|
|
end
|
|
|
|
if (not targetActor) then
|
|
local instanceName, _, _, _, _, _, _, instanceId = GetInstanceInfo()
|
|
Details:Msg("D! Report 0x885488", targetName, instanceName, instanceId, damage_cache[targetSerial] and "true")
|
|
return
|
|
end
|
|
|
|
--last event
|
|
sourceActor.last_event = _tempo
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--group checks and avoidance
|
|
|
|
if (absorbed) then
|
|
amount = absorbed + (amount or 0)
|
|
end
|
|
|
|
if (_is_in_instance) then
|
|
if (overkill and overkill > 0) then
|
|
overkill = overkill + 1
|
|
--if enabled it'll cut the amount of overkill from the last hit (which killed the actor)
|
|
--when disabled it'll show the total damage done for the latest hit
|
|
amount = amount - overkill
|
|
end
|
|
end
|
|
|
|
if (sourceActor.grupo and not sourceActor.arena_enemy and not sourceActor.enemy and not targetActor.arena_enemy) then --source = friendly player and not an enemy player
|
|
--dano to adversario estava caindo aqui por nao estar checando .enemy
|
|
_current_gtotal[1] = _current_gtotal[1] + amount
|
|
|
|
elseif (targetActor.grupo) then --source = arena enemy or friendly player
|
|
if (targetActor.arena_enemy) then
|
|
_current_gtotal[1] = _current_gtotal[1] + amount
|
|
end
|
|
|
|
--record avoidance only for tank actors
|
|
if (tanks_members_cache[targetSerial]) then
|
|
--monk's stagger
|
|
if (targetActor.classe == "MONK") then
|
|
if (absorbed) then
|
|
--the absorbed amount was staggered and should not be count as damage taken now
|
|
--this absorbed will hit the player with the stagger debuff
|
|
amount = (amount or 0) - absorbed
|
|
end
|
|
else
|
|
--advanced damage taken
|
|
--if advanced damage taken is enabled, the damage taken to tanks acts like the monk stuff above
|
|
if (_detalhes.damage_taken_everything) then
|
|
if (absorbed) then
|
|
amount = (amount or 0) - absorbed
|
|
end
|
|
end
|
|
end
|
|
|
|
--avoidance
|
|
local avoidance = targetActor.avoidance
|
|
if (not avoidance) then
|
|
targetActor.avoidance = _detalhes:CreateActorAvoidanceTable()
|
|
avoidance = targetActor.avoidance
|
|
end
|
|
|
|
local overall = avoidance.overall
|
|
|
|
local mob = avoidance [sourceName]
|
|
if (not mob) then --if isn't in the table, build on the fly
|
|
mob = _detalhes:CreateActorAvoidanceTable (true)
|
|
avoidance [sourceName] = mob
|
|
end
|
|
|
|
overall ["ALL"] = overall ["ALL"] + 1 --qualtipo de hit ou absorb
|
|
mob ["ALL"] = mob ["ALL"] + 1 --qualtipo de hit ou absorb
|
|
|
|
if (spellId < 3) then
|
|
--overall
|
|
overall ["HITS"] = overall ["HITS"] + 1
|
|
mob ["HITS"] = mob ["HITS"] + 1
|
|
end
|
|
|
|
if (blocked and blocked > 0) then
|
|
overall ["BLOCKED_HITS"] = overall ["BLOCKED_HITS"] + 1
|
|
mob ["BLOCKED_HITS"] = mob ["BLOCKED_HITS"] + 1
|
|
overall ["BLOCKED_AMT"] = overall ["BLOCKED_AMT"] + blocked
|
|
mob ["BLOCKED_AMT"] = mob ["BLOCKED_AMT"] + blocked
|
|
end
|
|
|
|
--absorbs status
|
|
if (absorbed) then
|
|
--aqui pode ser apenas absorb parcial
|
|
overall ["ABSORB"] = overall ["ABSORB"] + 1
|
|
overall ["PARTIAL_ABSORBED"] = overall ["PARTIAL_ABSORBED"] + 1
|
|
overall ["PARTIAL_ABSORB_AMT"] = overall ["PARTIAL_ABSORB_AMT"] + absorbed
|
|
overall ["ABSORB_AMT"] = overall ["ABSORB_AMT"] + absorbed
|
|
mob ["ABSORB"] = mob ["ABSORB"] + 1
|
|
mob ["PARTIAL_ABSORBED"] = mob ["PARTIAL_ABSORBED"] + 1
|
|
mob ["PARTIAL_ABSORB_AMT"] = mob ["PARTIAL_ABSORB_AMT"] + absorbed
|
|
mob ["ABSORB_AMT"] = mob ["ABSORB_AMT"] + absorbed
|
|
else
|
|
--adicionar aos hits sem absorbs
|
|
overall ["FULL_HIT"] = overall ["FULL_HIT"] + 1
|
|
overall ["FULL_HIT_AMT"] = overall ["FULL_HIT_AMT"] + amount
|
|
mob ["FULL_HIT"] = mob ["FULL_HIT"] + 1
|
|
mob ["FULL_HIT_AMT"] = mob ["FULL_HIT_AMT"] + amount
|
|
end
|
|
end
|
|
|
|
--record death log
|
|
local t = last_events_cache[targetName]
|
|
|
|
if (not t) then
|
|
t = _current_combat:CreateLastEventsTable(targetName)
|
|
end
|
|
|
|
local i = t.n
|
|
|
|
local thisEvent = t [i]
|
|
thisEvent[1] = true --true if this is a damage || false for healing
|
|
thisEvent[2] = spellId --spellid || false if this is a battle ress line
|
|
thisEvent[3] = amount --amount of damage or healing
|
|
thisEvent[4] = time --parser time
|
|
|
|
--current unit heal
|
|
if (targetActor.arena_enemy) then
|
|
--this is an arena enemy, get the heal with the unit Id
|
|
local unitId = _detalhes.arena_enemies[targetName]
|
|
if (not unitId) then
|
|
unitId = Details:GuessArenaEnemyUnitId(targetName)
|
|
end
|
|
if (unitId) then
|
|
thisEvent[5] = UnitHealth(unitId)
|
|
else
|
|
thisEvent[5] = cacheAnything.arenaHealth[targetName] or 100000
|
|
end
|
|
|
|
cacheAnything.arenaHealth[targetName] = thisEvent[5]
|
|
else
|
|
thisEvent[5] = UnitHealth(targetName)
|
|
end
|
|
|
|
thisEvent[6] = sourceName --source name
|
|
thisEvent[7] = absorbed
|
|
thisEvent[8] = spellType or school
|
|
thisEvent[9] = false
|
|
thisEvent[10] = overkill
|
|
thisEvent[11] = critical
|
|
thisEvent[12] = crushing
|
|
|
|
i = i + 1
|
|
|
|
if (i == _amount_of_last_events + 1) then
|
|
t.n = 1
|
|
else
|
|
t.n = i
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--~activity time
|
|
if (not sourceActor.dps_started and _is_activity_time) then
|
|
--register on time machine
|
|
sourceActor:Iniciar(true)
|
|
|
|
if (ownerActor and not ownerActor.dps_started) then
|
|
ownerActor:Iniciar(true)
|
|
if (ownerActor.end_time) then
|
|
ownerActor.end_time = nil
|
|
else
|
|
ownerActor.start_time = _tempo
|
|
end
|
|
end
|
|
|
|
if (sourceActor.end_time) then
|
|
sourceActor.end_time = nil
|
|
else
|
|
sourceActor.start_time = _tempo
|
|
end
|
|
|
|
--'player'
|
|
if (sourceActor.nome == _detalhes.playername and token ~= "SPELL_PERIODIC_DAMAGE") then
|
|
if (UnitAffectingCombat("player")) then
|
|
_detalhes:SendEvent("COMBAT_PLAYER_TIMESTARTED", nil, _current_combat, sourceActor)
|
|
end
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--firendly fire ~friendlyfire
|
|
local is_friendly_fire = false
|
|
|
|
if (_is_in_instance) then
|
|
if (bitfield_swap_cache [sourceSerial] or ownerActor and bitfield_swap_cache [ownerActor.serial]) then
|
|
if (targetActor.grupo or targetOwner and targetOwner.grupo) then
|
|
is_friendly_fire = true
|
|
end
|
|
else
|
|
if (bitfield_swap_cache [targetSerial] or targetOwner and bitfield_swap_cache [targetOwner.serial]) then
|
|
else
|
|
--Astral Nova explosion from Astral Bomb (Spectral Invoker - Algeth'ar Academy) should get friend zone here
|
|
if ((targetActor.grupo or targetOwner and targetOwner.grupo) and (sourceActor.grupo or ownerActor and ownerActor.grupo)) then
|
|
is_friendly_fire = true
|
|
end
|
|
end
|
|
end
|
|
else
|
|
if (
|
|
(bitBand(targetFlags, REACTION_FRIENDLY) ~= 0 and bitBand(sourceFlags, REACTION_FRIENDLY) ~= 0) or --ajdt d' brx
|
|
(raid_members_cache [targetSerial] and raid_members_cache [sourceSerial] and targetSerial:find("Player") and sourceSerial:find("Player")) --amrl
|
|
) then
|
|
is_friendly_fire = true
|
|
end
|
|
end
|
|
|
|
--double check for Astral Nova explosion (only inside AA dungeon)
|
|
if (spellId == 387848 and not is_friendly_fire) then
|
|
if ((targetActor.grupo or targetOwner and targetOwner.grupo) and (sourceActor.grupo or ownerActor and ownerActor.grupo)) then
|
|
is_friendly_fire = true
|
|
end
|
|
end
|
|
|
|
if (is_friendly_fire) then
|
|
if (sourceActor.grupo) then --se tiver ele n�o adiciona o evento l� em cima
|
|
local t = last_events_cache[targetName]
|
|
|
|
if (not t) then
|
|
t = _current_combat:CreateLastEventsTable(targetName)
|
|
end
|
|
|
|
local i = t.n
|
|
local thisEvent = t [i]
|
|
|
|
thisEvent[1] = true --true if this is a damage || false for healing
|
|
thisEvent[2] = spellId --spellid || false if this is a battle ress line
|
|
thisEvent[3] = amount --amount of damage or healing
|
|
thisEvent[4] = time --parser time
|
|
thisEvent[5] = UnitHealth (targetName) --current unit heal
|
|
thisEvent[6] = sourceName --source name
|
|
thisEvent[7] = absorbed
|
|
thisEvent[8] = spellType or school
|
|
thisEvent[9] = true
|
|
thisEvent[10] = overkill
|
|
i = i + 1
|
|
|
|
if (i == _amount_of_last_events+1) then
|
|
t.n = 1
|
|
else
|
|
t.n = i
|
|
end
|
|
end
|
|
|
|
sourceActor.friendlyfire_total = sourceActor.friendlyfire_total + amount
|
|
|
|
local friend = sourceActor.friendlyfire[targetName] or sourceActor:CreateFFTable(targetName)
|
|
|
|
friend.total = friend.total + amount
|
|
friend.spells[spellId] = (friend.spells[spellId] or 0) + amount
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--damage taken
|
|
--target
|
|
targetActor.damage_taken = targetActor.damage_taken + amount - (absorbed or 0) --adiciona o dano tomado
|
|
if (not targetActor.damage_from[sourceName]) then --adiciona a pool de dano tomado de quem
|
|
targetActor.damage_from[sourceName] = true
|
|
end
|
|
|
|
return true
|
|
else
|
|
_current_total[1] = _current_total[1] + amount
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--damage taken
|
|
--target
|
|
targetActor.damage_taken = targetActor.damage_taken + amount --adiciona o dano tomado
|
|
if (not targetActor.damage_from[sourceName]) then --adiciona a pool de dano tomado de quem
|
|
targetActor.damage_from[sourceName] = true
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--amount add
|
|
|
|
--actor owner (if any)
|
|
if (ownerActor) then --se for dano de um Pet
|
|
ownerActor.total = ownerActor.total + amount --e adiciona o dano ao pet
|
|
|
|
--add owner targets
|
|
ownerActor.targets [targetName] = (ownerActor.targets [targetName] or 0) + amount
|
|
|
|
ownerActor.last_event = _tempo
|
|
|
|
if (RAID_TARGET_FLAGS [targetRaidFlags]) then
|
|
--add the amount done for the owner
|
|
ownerActor.raid_targets [targetRaidFlags] = (ownerActor.raid_targets [targetRaidFlags] or 0) + amount
|
|
end
|
|
end
|
|
|
|
--raid targets
|
|
if (RAID_TARGET_FLAGS[targetRaidFlags]) then
|
|
sourceActor.raid_targets[targetRaidFlags] = (sourceActor.raid_targets[targetRaidFlags] or 0) + amount
|
|
end
|
|
|
|
--actor
|
|
sourceActor.total = sourceActor.total + amount
|
|
|
|
--actor without pets
|
|
sourceActor.total_without_pet = sourceActor.total_without_pet + amount
|
|
|
|
--actor targets
|
|
sourceActor.targets[targetName] = (sourceActor.targets[targetName] or 0) + amount
|
|
|
|
--actor spells table
|
|
local spellTable = sourceActor.spells._ActorTable[spellId]
|
|
if (not spellTable) then
|
|
spellTable = sourceActor.spells:PegaHabilidade(spellId, true, token)
|
|
spellTable.spellschool = spellType or school
|
|
if (_current_combat.is_boss and sourceFlags and bitBand(sourceFlags, OBJECT_TYPE_ENEMY) ~= 0) then
|
|
_detalhes.spell_school_cache[spellName] = spellType or school
|
|
end
|
|
|
|
if (isreflected) then
|
|
spellTable.isReflection = true
|
|
end
|
|
end
|
|
|
|
--empowerment data
|
|
if (empower_cache[sourceSerial]) then
|
|
local empowerSpellInfo = empower_cache[sourceSerial][spellName]
|
|
if (empowerSpellInfo) then
|
|
if (not empowerSpellInfo.counted_healing) then
|
|
--total of empowerment
|
|
spellTable.e_total = (spellTable.e_total or 0) + empowerSpellInfo.empowerLevel --usado para calcular o average empowerment
|
|
--total amount of empowerment
|
|
spellTable.e_amt = (spellTable.e_amt or 0) + 1 --usado para calcular o average empowerment
|
|
|
|
--amount of casts on each level
|
|
spellTable.e_lvl = spellTable.e_lvl or {}
|
|
spellTable.e_lvl[empowerSpellInfo.empowerLevel] = (spellTable.e_lvl[empowerSpellInfo.empowerLevel] or 0) + 1
|
|
|
|
empowerSpellInfo.counted_healing = true
|
|
end
|
|
|
|
--damage bracket
|
|
spellTable.e_dmg = spellTable.e_dmg or {}
|
|
spellTable.e_dmg[empowerSpellInfo.empowerLevel] = (spellTable.e_dmg[empowerSpellInfo.empowerLevel] or 0) + amount
|
|
end
|
|
end
|
|
|
|
if (_trinket_data_cache[spellId] and _in_combat) then
|
|
local thisData = _trinket_data_cache[spellId]
|
|
if (thisData.lastCombatId == _global_combat_counter) then
|
|
if (thisData.lastPlayerName == sourceName) then
|
|
if (thisData.lastActivation < (time - 40)) then
|
|
local cooldownTime = time - thisData.lastActivation
|
|
thisData.totalCooldownTime = thisData.totalCooldownTime + cooldownTime
|
|
thisData.activations = thisData.activations + 1
|
|
thisData.lastActivation = time
|
|
|
|
thisData.averageTime = floor(thisData.totalCooldownTime / thisData.activations)
|
|
if (cooldownTime < thisData.minTime) then
|
|
thisData.minTime = cooldownTime
|
|
end
|
|
|
|
if (cooldownTime > thisData.maxTime) then
|
|
thisData.maxTime = cooldownTime
|
|
end
|
|
end
|
|
end
|
|
else
|
|
thisData.lastCombatId = _global_combat_counter
|
|
thisData.lastActivation = time
|
|
thisData.lastPlayerName = sourceName
|
|
end
|
|
end
|
|
|
|
return _spell_damage_func(spellTable, targetSerial, targetName, targetFlags, amount, sourceName, resisted, blocked, absorbed, critical, glacing, token, isoffhand, isreflected)
|
|
end
|
|
|
|
--special behavior for monk stagger debuff periodic damage
|
|
--using it as a separate function to avoid the overhead of checking if the spell is stagger on every damage event
|
|
function parser:MonkStagger_damage(token, time, sourceSerial, sourceName, sourceFlags, alvo_serial, alvo_name, alvo_flags, spellId, spellname, spelltype, amount, overkill, school, resisted, blocked, absorbed, critical, glacing, crushing, isoffhand)
|
|
--tag the container to refresh
|
|
_current_damage_container.need_refresh = true
|
|
|
|
--get the monk damage object
|
|
local sourceActor, ownerActor = damage_cache[sourceSerial] or damage_cache_pets[sourceSerial] or damage_cache[sourceName], damage_cache_petsOwners[sourceSerial]
|
|
|
|
if (not sourceActor) then
|
|
sourceActor, ownerActor, sourceName = _current_damage_container:PegarCombatente(sourceSerial, sourceName, sourceFlags, true)
|
|
if (ownerActor) then --� um pet
|
|
if (sourceSerial ~= "") then
|
|
damage_cache_pets[sourceSerial] = sourceActor
|
|
damage_cache_petsOwners[sourceSerial] = ownerActor
|
|
end
|
|
--conferir se o dono j� esta no cache
|
|
if (not damage_cache[ownerActor.serial] and ownerActor.serial ~= "") then
|
|
damage_cache[ownerActor.serial] = ownerActor
|
|
end
|
|
else
|
|
if (sourceFlags) then --ter certeza que n�o � um pet
|
|
if (sourceSerial ~= "") then
|
|
damage_cache[sourceSerial] = sourceActor
|
|
else
|
|
if (sourceName:find("%[")) then --need to use the cache here
|
|
damage_cache[sourceName] = sourceActor
|
|
local _, _, icon = _GetSpellInfo(spellId or 1)
|
|
sourceActor.spellicon = icon
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
elseif (ownerActor) then --has (sourceActor and ownerActor)
|
|
--sourceName is the name of the pet
|
|
local cachedPetName = names_cache[sourceSerial]
|
|
if (not cachedPetName) then
|
|
--add the owner name into the sourceName
|
|
sourceName = sourceName .. " <" .. ownerActor.nome .. ">"
|
|
names_cache[sourceSerial] = sourceName
|
|
else
|
|
sourceName = cachedPetName
|
|
end
|
|
end
|
|
|
|
--last event
|
|
sourceActor.last_event = _tempo
|
|
|
|
--amount
|
|
amount = (amount or 0)
|
|
|
|
--damage taken
|
|
sourceActor.damage_taken = sourceActor.damage_taken + amount
|
|
if (not sourceActor.damage_from[sourceName]) then
|
|
sourceActor.damage_from[sourceName] = true
|
|
end
|
|
|
|
--friendly fire total
|
|
sourceActor.friendlyfire_total = sourceActor.friendlyfire_total + amount
|
|
--friendly fire from who
|
|
local friend = sourceActor.friendlyfire[sourceName] or sourceActor:CreateFFTable(sourceName)
|
|
friend.total = friend.total + amount
|
|
friend.spells[spellId] = (friend.spells[spellId] or 0) + amount
|
|
|
|
--record death log
|
|
local t = last_events_cache[sourceName]
|
|
|
|
if (not t) then
|
|
t = _current_combat:CreateLastEventsTable(sourceName)
|
|
end
|
|
|
|
local i = t.n
|
|
|
|
local this_event = t[i]
|
|
|
|
if (not this_event) then
|
|
return print("Parser Event Error -> Set to 16 DeathLogs and /reload", i, _amount_of_last_events)
|
|
end
|
|
|
|
this_event [1] = true --true if this is a damage || false for healing
|
|
this_event [2] = spellId --spellid || false if this is a battle ress line
|
|
this_event [3] = amount --amount of damage or healing
|
|
this_event [4] = time --parser time
|
|
this_event [5] = UnitHealth (sourceName) --current unit heal
|
|
this_event [6] = sourceName --source name
|
|
this_event [7] = absorbed
|
|
this_event [8] = school
|
|
this_event [9] = true --friendly fire
|
|
this_event [10] = overkill
|
|
|
|
i = i + 1
|
|
|
|
if (i == _amount_of_last_events+1) then
|
|
t.n = 1
|
|
else
|
|
t.n = i
|
|
end
|
|
|
|
--avoidance
|
|
local avoidance = sourceActor.avoidance
|
|
if (not avoidance) then
|
|
sourceActor.avoidance = _detalhes:CreateActorAvoidanceTable()
|
|
avoidance = sourceActor.avoidance
|
|
end
|
|
|
|
local overall = avoidance.overall
|
|
|
|
local mob = avoidance [sourceName]
|
|
if (not mob) then --if isn't in the table, build on the fly
|
|
mob = _detalhes:CreateActorAvoidanceTable (true)
|
|
avoidance [sourceName] = mob
|
|
end
|
|
|
|
overall ["ALL"] = overall ["ALL"] + 1 --qualtipo de hit ou absorb
|
|
mob ["ALL"] = mob ["ALL"] + 1 --qualtipo de hit ou absorb
|
|
|
|
if (blocked and blocked > 0) then
|
|
overall ["BLOCKED_HITS"] = overall ["BLOCKED_HITS"] + 1
|
|
mob ["BLOCKED_HITS"] = mob ["BLOCKED_HITS"] + 1
|
|
overall ["BLOCKED_AMT"] = overall ["BLOCKED_AMT"] + blocked
|
|
mob ["BLOCKED_AMT"] = mob ["BLOCKED_AMT"] + blocked
|
|
end
|
|
|
|
--absorbs status
|
|
if (absorbed) then
|
|
--aqui pode ser apenas absorb parcial
|
|
overall ["ABSORB"] = overall ["ABSORB"] + 1
|
|
overall ["PARTIAL_ABSORBED"] = overall ["PARTIAL_ABSORBED"] + 1
|
|
overall ["PARTIAL_ABSORB_AMT"] = overall ["PARTIAL_ABSORB_AMT"] + absorbed
|
|
overall ["ABSORB_AMT"] = overall ["ABSORB_AMT"] + absorbed
|
|
mob ["ABSORB"] = mob ["ABSORB"] + 1
|
|
mob ["PARTIAL_ABSORBED"] = mob ["PARTIAL_ABSORBED"] + 1
|
|
mob ["PARTIAL_ABSORB_AMT"] = mob ["PARTIAL_ABSORB_AMT"] + absorbed
|
|
mob ["ABSORB_AMT"] = mob ["ABSORB_AMT"] + absorbed
|
|
else
|
|
--adicionar aos hits sem absorbs
|
|
overall ["FULL_HIT"] = overall ["FULL_HIT"] + 1
|
|
overall ["FULL_HIT_AMT"] = overall ["FULL_HIT_AMT"] + amount
|
|
mob ["FULL_HIT"] = mob ["FULL_HIT"] + 1
|
|
mob ["FULL_HIT_AMT"] = mob ["FULL_HIT_AMT"] + amount
|
|
end
|
|
end
|
|
|
|
--special rule for LOTM
|
|
function parser:LOTM_damage (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, spelltype, amount, overkill, school, resisted, blocked, absorbed, critical, glacing, crushing, isoffhand)
|
|
|
|
if (absorbed) then
|
|
amount = absorbed + (amount or 0)
|
|
end
|
|
|
|
local healingActor = healing_cache [who_serial]
|
|
if (healingActor and healingActor.spells) then
|
|
healingActor.total = healingActor.total - (amount or 0)
|
|
|
|
local spellTable = healingActor.spells:GetSpell (183998)
|
|
if (spellTable) then
|
|
spellTable.anti_heal = (spellTable.anti_heal or 0) + amount
|
|
end
|
|
end
|
|
|
|
local t = last_events_cache [who_name]
|
|
|
|
if (not t) then
|
|
t = _current_combat:CreateLastEventsTable (who_name)
|
|
end
|
|
|
|
local i = t.n
|
|
|
|
local this_event = t [i]
|
|
|
|
if (not this_event) then
|
|
return print("Parser Event Error -> Set to 16 DeathLogs and /reload", i, _amount_of_last_events)
|
|
end
|
|
|
|
this_event [1] = true --true if this is a damage || false for healing
|
|
this_event [2] = spellid --spellid || false if this is a battle ress line
|
|
this_event [3] = amount --amount of damage or healing
|
|
this_event [4] = time --parser time
|
|
this_event [5] = UnitHealth (who_name) --current unit heal
|
|
this_event [6] = who_name --source name
|
|
this_event [7] = absorbed
|
|
this_event [8] = school
|
|
this_event [9] = true --friendly fire
|
|
this_event [10] = overkill
|
|
|
|
i = i + 1
|
|
|
|
if (i == _amount_of_last_events+1) then
|
|
t.n = 1
|
|
else
|
|
t.n = i
|
|
end
|
|
|
|
local damageActor = damage_cache [who_serial]
|
|
if (damageActor) then
|
|
--damage taken
|
|
damageActor.damage_taken = damageActor.damage_taken + amount
|
|
if (not damageActor.damage_from [who_name]) then --adiciona a pool de dano tomado de quem
|
|
damageActor.damage_from [who_name] = true
|
|
end
|
|
|
|
--friendly fire
|
|
damageActor.friendlyfire_total = damageActor.friendlyfire_total + amount
|
|
local friend = damageActor.friendlyfire [who_name] or damageActor:CreateFFTable (who_name)
|
|
friend.total = friend.total + amount
|
|
friend.spells [spellid] = (friend.spells [spellid] or 0) + amount
|
|
end
|
|
end
|
|
|
|
--special rule of SLT
|
|
function parser:SLT_damage (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, spelltype, amount, overkill, school, resisted, blocked, absorbed, critical, glacing, crushing, isoffhand)
|
|
|
|
--damager
|
|
local este_jogador, meu_dono = damage_cache [who_serial] or damage_cache_pets [who_serial] or damage_cache [who_name], damage_cache_petsOwners [who_serial]
|
|
|
|
if (not este_jogador) then --pode ser um desconhecido ou um pet
|
|
|
|
este_jogador, meu_dono, who_name = _current_damage_container:PegarCombatente (who_serial, who_name, who_flags, true)
|
|
|
|
if (meu_dono) then --� um pet
|
|
if (who_serial ~= "") then
|
|
damage_cache_pets [who_serial] = este_jogador
|
|
damage_cache_petsOwners [who_serial] = meu_dono
|
|
end
|
|
--conferir se o dono j� esta no cache
|
|
if (not damage_cache [meu_dono.serial] and meu_dono.serial ~= "") then
|
|
damage_cache [meu_dono.serial] = meu_dono
|
|
end
|
|
else
|
|
if (who_flags) then --ter certeza que n�o � um pet
|
|
if (who_serial ~= "") then
|
|
damage_cache [who_serial] = este_jogador
|
|
else
|
|
if (who_name:find("%[")) then
|
|
damage_cache [who_name] = este_jogador
|
|
local _, _, icon = _GetSpellInfo(spellid or 1)
|
|
este_jogador.spellicon = icon
|
|
else
|
|
--_detalhes:Msg("Unknown actor with unknown serial ", spellname, who_name)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
elseif (meu_dono) then
|
|
--� um pet
|
|
who_name = who_name .. " <" .. meu_dono.nome .. ">"
|
|
end
|
|
|
|
--his target
|
|
local jogador_alvo, alvo_dono = damage_cache [alvo_serial] or damage_cache_pets [alvo_serial] or damage_cache [alvo_name], damage_cache_petsOwners [alvo_serial]
|
|
|
|
if (not jogador_alvo) then
|
|
|
|
jogador_alvo, alvo_dono, alvo_name = _current_damage_container:PegarCombatente (alvo_serial, alvo_name, alvo_flags, true)
|
|
|
|
if (alvo_dono) then
|
|
if (alvo_serial ~= "") then
|
|
damage_cache_pets [alvo_serial] = jogador_alvo
|
|
damage_cache_petsOwners [alvo_serial] = alvo_dono
|
|
end
|
|
--conferir se o dono j� esta no cache
|
|
if (not damage_cache [alvo_dono.serial] and alvo_dono.serial ~= "") then
|
|
damage_cache [alvo_dono.serial] = alvo_dono
|
|
end
|
|
else
|
|
if (alvo_flags and alvo_serial ~= "") then --ter certeza que n�o � um pet
|
|
damage_cache [alvo_serial] = jogador_alvo
|
|
end
|
|
end
|
|
|
|
elseif (alvo_dono) then
|
|
--� um pet
|
|
alvo_name = alvo_name .. " <" .. alvo_dono.nome .. ">"
|
|
end
|
|
|
|
--last event
|
|
este_jogador.last_event = _tempo
|
|
|
|
--record death log
|
|
local t = last_events_cache [alvo_name]
|
|
|
|
if (not t) then
|
|
t = _current_combat:CreateLastEventsTable (alvo_name)
|
|
end
|
|
|
|
local i = t.n
|
|
|
|
local this_event = t [i]
|
|
|
|
if (not this_event) then
|
|
return print("Parser Event Error -> Set to 16 DeathLogs and /reload", i, _amount_of_last_events)
|
|
end
|
|
|
|
this_event [1] = true --true if this is a damage || false for healing
|
|
this_event [2] = spellid --spellid || false if this is a battle ress line
|
|
this_event [3] = amount --amount of damage or healing
|
|
this_event [4] = time --parser time
|
|
this_event [5] = UnitHealth (alvo_name) --current unit heal
|
|
this_event [6] = who_name --source name
|
|
this_event [7] = absorbed
|
|
this_event [8] = spelltype or school
|
|
this_event [9] = false
|
|
this_event [10] = overkill
|
|
|
|
i = i + 1
|
|
|
|
if (i == _amount_of_last_events+1) then
|
|
t.n = 1
|
|
else
|
|
t.n = i
|
|
end
|
|
end
|
|
|
|
--extra attacks - disabled
|
|
function parser:spell_dmg_extra_attacks(token, time, who_serial, who_name, who_flags, _, _, _, _, spellid, spellName, spelltype, arg1)
|
|
--print("this is even exists on ingame cleu?")
|
|
local este_jogador = damage_cache [who_serial]
|
|
if (not este_jogador) then
|
|
local meu_dono
|
|
este_jogador, meu_dono, who_name = _current_damage_container:PegarCombatente (who_serial, who_name, who_flags, true)
|
|
if (not este_jogador) then
|
|
return --just return if actor doen't exist yet
|
|
end
|
|
end
|
|
|
|
--actor spells table
|
|
local spell = este_jogador.spells._ActorTable[1] --melee damage
|
|
if (not spell) then
|
|
return
|
|
end
|
|
|
|
spell.extra["extra_attack"] = (spell.extra["extra_attack"] or 0) + 1
|
|
end
|
|
|
|
--function parser:swingmissed (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, missType, isOffHand, amountMissed)
|
|
function parser:swingmissed (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, missType, isOffHand, amountMissed) --, isOffHand, amountMissed, arg1
|
|
return parser:missed (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, 1, "Corpo-a-Corpo", 00000001, missType, isOffHand, amountMissed) --, isOffHand, amountMissed, arg1
|
|
end
|
|
|
|
function parser:rangemissed (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname, spelltype, missType, isOffHand, amountMissed) --, isOffHand, amountMissed, arg1
|
|
return parser:missed (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, 2, "Tiro-Autom�tico", 00000001, missType, isOffHand, amountMissed) --, isOffHand, amountMissed, arg1
|
|
end
|
|
|
|
-- ~miss
|
|
function parser:missed (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname, spelltype, missType, isOffHand, amountMissed, arg1, arg2, arg3)
|
|
|
|
|
|
--print(spellid, spellname, missType, amountMissed) --MISS
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--early checks and fixes
|
|
|
|
if (not alvo_name) then
|
|
--no target name, just quit
|
|
return
|
|
|
|
elseif (not who_name) then
|
|
--no actor name, use spell name instead
|
|
who_name = "[*] " .. spellname
|
|
who_flags = 0xa48
|
|
who_serial = ""
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--get actors
|
|
--todo tbc seems to not have misses? need further investigation
|
|
--print("MISS", "|", missType, "|", isOffHand, "|", amountMissed, "|", arg1)
|
|
--print(missType, who_name, spellname, amountMissed)
|
|
|
|
|
|
--'misser'
|
|
local este_jogador = damage_cache [who_serial]
|
|
if (not este_jogador) then
|
|
--este_jogador, meu_dono, who_name = _current_damage_container:PegarCombatente (nil, who_name)
|
|
local meu_dono
|
|
este_jogador, meu_dono, who_name = _current_damage_container:PegarCombatente (who_serial, who_name, who_flags, true)
|
|
if (not este_jogador) then
|
|
return --just return if actor doen't exist yet
|
|
end
|
|
end
|
|
|
|
este_jogador.last_event = _tempo
|
|
|
|
if (tanks_members_cache [alvo_serial]) then --only track tanks
|
|
|
|
local TargetActor = damage_cache [alvo_serial]
|
|
if (TargetActor) then
|
|
|
|
local avoidance = TargetActor.avoidance
|
|
|
|
if (not avoidance) then
|
|
TargetActor.avoidance = _detalhes:CreateActorAvoidanceTable()
|
|
avoidance = TargetActor.avoidance
|
|
end
|
|
|
|
local missTable = avoidance.overall [missType]
|
|
|
|
if (missTable) then
|
|
--overall
|
|
local overall = avoidance.overall
|
|
overall [missType] = missTable + 1 --adicionado a quantidade do miss
|
|
|
|
--from this mob
|
|
local mob = avoidance [who_name]
|
|
if (not mob) then --if isn't in the table, build on the fly
|
|
mob = _detalhes:CreateActorAvoidanceTable (true)
|
|
avoidance [who_name] = mob
|
|
end
|
|
|
|
mob [missType] = mob [missType] + 1
|
|
|
|
if (missType == "ABSORB") then --full absorb
|
|
overall ["ALL"] = overall ["ALL"] + 1 --qualtipo de hit ou absorb
|
|
overall ["FULL_ABSORBED"] = overall ["FULL_ABSORBED"] + 1 --amount
|
|
overall ["ABSORB_AMT"] = overall ["ABSORB_AMT"] + (amountMissed or 0)
|
|
overall ["FULL_ABSORB_AMT"] = overall ["FULL_ABSORB_AMT"] + (amountMissed or 0)
|
|
|
|
mob ["ALL"] = mob ["ALL"] + 1 --qualtipo de hit ou absorb
|
|
mob ["FULL_ABSORBED"] = mob ["FULL_ABSORBED"] + 1 --amount
|
|
mob ["ABSORB_AMT"] = mob ["ABSORB_AMT"] + (amountMissed or 0)
|
|
mob ["FULL_ABSORB_AMT"] = mob ["FULL_ABSORB_AMT"] + (amountMissed or 0)
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--amount add
|
|
|
|
if (missType == "ABSORB") then
|
|
if (token == "SWING_MISSED") then
|
|
este_jogador.totalabsorbed = este_jogador.totalabsorbed + amountMissed
|
|
--return parser:swing ("SWING_DAMAGE", time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, amountMissed, -1, 1, nil, nil, nil, false, false, false, false)
|
|
return parser:spell_dmg ("SWING_DAMAGE", time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, amountMissed, -1, 1, nil, nil, nil, false, false, false, false)
|
|
|
|
elseif (token == "RANGE_MISSED") then
|
|
este_jogador.totalabsorbed = este_jogador.totalabsorbed + amountMissed
|
|
--this can call the spell_dmg directly, no need for this proxy
|
|
--return parser:range ("RANGE_DAMAGE", time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname, spelltype, amountMissed, -1, 1, nil, nil, nil, false, false, false, false)
|
|
return parser:spell_dmg("RANGE_DAMAGE", time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname, spelltype, amountMissed, -1, 1, nil, nil, nil, false, false, false, false)
|
|
|
|
else
|
|
este_jogador.totalabsorbed = este_jogador.totalabsorbed + amountMissed
|
|
return parser:spell_dmg(token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname, spelltype, amountMissed, -1, 1, nil, nil, nil, false, false, false, false)
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--spell reflection
|
|
elseif (missType == "REFLECT" and reflection_auras[alvo_serial]) then --~reflect
|
|
--a reflect event and we have the reflecting aura data
|
|
if (reflection_damage[who_serial] and reflection_damage[who_serial][spellid] and time-reflection_damage[who_serial][spellid].time > 3.5 and (not reflection_debuffs[who_serial] or (reflection_debuffs[who_serial] and not reflection_debuffs[who_serial][spellid]))) then
|
|
--here we check if we have to filter old damage data
|
|
--we check for two conditions
|
|
--the first is to see if this is an old damage
|
|
--if more than 3.5 seconds have past then we can say that it is old... but!
|
|
--the second condition is to see if there is an active debuff with the same spellid
|
|
--if there is one then we ignore the timer and skip this
|
|
--this should be cleared afterwards somehow... don't know how...
|
|
reflection_damage[who_serial][spellid] = nil
|
|
if (next(reflection_damage[who_serial]) == nil) then
|
|
--there should be some better way of handling this kind of filtering, any suggestion?
|
|
reflection_damage[who_serial] = nil
|
|
end
|
|
end
|
|
local damage = reflection_damage[who_serial] and reflection_damage[who_serial][spellid]
|
|
local reflection = reflection_auras[alvo_serial]
|
|
if (damage) then
|
|
--damage ocurred first, so we have its data
|
|
local amount = reflection_damage[who_serial][spellid].amount
|
|
|
|
local isreflected = spellid --which spell was reflected
|
|
alvo_serial = reflection.who_serial
|
|
alvo_name = reflection.who_name
|
|
alvo_flags = reflection.who_flags
|
|
spellid = reflection.spellid
|
|
spellname = reflection.spellname
|
|
spelltype = reflection.spelltype
|
|
--crediting the source of the aura that caused the reflection
|
|
--also saying that the damage came from the aura that reflected the spell
|
|
|
|
reflection_damage[who_serial][spellid] = nil
|
|
if next(reflection_damage[who_serial]) == nil then
|
|
--this is so bad at clearing, there should be a better way of handling this
|
|
reflection_damage[who_serial] = nil
|
|
end
|
|
|
|
return parser:spell_dmg(token,time,alvo_serial,alvo_name,alvo_flags,who_serial,who_name,who_flags,nil,spellid,spellname,spelltype,amount,-1,nil,nil,nil,nil,false,false,false,false, isreflected)
|
|
else
|
|
--saving information about this reflect because it occurred before the damage event
|
|
reflection_events[who_serial] = reflection_events[who_serial] or {}
|
|
reflection_events[who_serial][spellid] = reflection
|
|
reflection_events[who_serial][spellid].time = time
|
|
end
|
|
|
|
else
|
|
--colocando aqui apenas pois ele confere o override dentro do damage
|
|
if (is_using_spellId_override) then
|
|
spellid = override_spellId [spellid] or spellid
|
|
end
|
|
|
|
--actor spells table
|
|
local spell = este_jogador.spells._ActorTable [spellid]
|
|
if (not spell) then
|
|
spell = este_jogador.spells:PegaHabilidade (spellid, true, token)
|
|
spell.spellschool = spelltype
|
|
if (_current_combat.is_boss and who_flags and bitBand(who_flags, OBJECT_TYPE_ENEMY) ~= 0) then
|
|
_detalhes.spell_school_cache [spellname] = spelltype
|
|
end
|
|
end
|
|
return _spell_damageMiss_func (spell, alvo_serial, alvo_name, alvo_flags, who_name, missType)
|
|
end
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-----------------------------------------------------------------------------------------------------------------------------------------
|
|
--SPELL_EMPOWER
|
|
-----------------------------------------------------------------------------------------------------------------------------------------
|
|
function parser:spell_empower(token, time, sourceGUID, sourceName, sourceFlags, targetGUID, targetName, targetFlags, targetRaidFlags, spellId, spellName, spellSchool, empowerLevel)
|
|
--empowerLevel only exists on _END and _INTERRUPT
|
|
|
|
if (token == "SPELL_EMPOWER_START" or token == "SPELL_EMPOWER_INTERRUPT") then
|
|
return
|
|
end
|
|
|
|
if (not empowerLevel) then
|
|
return
|
|
end
|
|
|
|
--early checks
|
|
if (not sourceGUID or not sourceName or not sourceFlags) then
|
|
return
|
|
end
|
|
|
|
--source damager, should this only register for Players?
|
|
if (sourceFlags and bitBand(sourceFlags, OBJECT_TYPE_PLAYER) == 0) then
|
|
return
|
|
end
|
|
|
|
local sourceObject = damage_cache[sourceGUID] or damage_cache[sourceName]
|
|
|
|
if (not sourceObject) then
|
|
sourceObject = _current_damage_container:PegarCombatente(sourceGUID, sourceName, sourceFlags, true)
|
|
end
|
|
|
|
if (not sourceObject) then
|
|
return
|
|
end
|
|
|
|
empower_cache[sourceGUID] = empower_cache[sourceGUID] or {}
|
|
local empowerTable = {
|
|
spellName = spellName,
|
|
empowerLevel = empowerLevel,
|
|
time = time,
|
|
counted_healing = false,
|
|
counted_damage = false,
|
|
}
|
|
empower_cache[sourceGUID][spellName] = empowerTable
|
|
end
|
|
--parser.spell_empower
|
|
--10/30 15:32:11.515 SPELL_EMPOWER_START,Player-4184-00242A35,"Isodrak-Valdrakken",0x514,0x0,Player-4184-00242A35,"Isodrak-Valdrakken",0x514,0x0,382266,"Fire Breath",0x4
|
|
--10/30 15:32:12.433 SPELL_EMPOWER_END,Player-4184-00242A35,"Isodrak-Valdrakken",0x514,0x0,0000000000000000,nil,0x80000000,0x80000000,382266,"Fire Breath",0x4,1
|
|
--10/30 15:33:45.970 SPELL_EMPOWER_INTERRUPT,Player-4184-00218B4F,"Minng-Valdrakken",0x512,0x0,0000000000000000,nil,0x80000000,0x80000000,382266,"Fire Breath",0x4,1
|
|
|
|
--10/30 15:34:47.249 SPELL_EMPOWER_START,Player-4184-0048EE5B,"Nezaland-Valdrakken",0x514,0x0,Player-4184-0048EE5B,"Nezaland-Valdrakken",0x514,0x0,382266,"Fire Breath",0x4
|
|
--357209 damage spell is different from the spell cast
|
|
|
|
-----------------------------------------------------------------------------------------------------------------------------------------
|
|
--SUMMON serach key: ~summon |
|
|
-----------------------------------------------------------------------------------------------------------------------------------------
|
|
function parser:summon(token, time, sourceSerial, sourceName, sourceFlags, petSerial, petName, petFlags, petRaidFlags, spellId, spellName)
|
|
--[[statistics]]-- _detalhes.statistics.pets_summons = _detalhes.statistics.pets_summons + 1
|
|
|
|
if (not sourceName) then
|
|
sourceName = "[*] " .. spellName
|
|
end
|
|
|
|
local npcId = tonumber(select(6, strsplit("-", petSerial)) or 0)
|
|
|
|
--differenciate army and apoc pets for DK
|
|
if (spellId == 42651) then --army of the dead
|
|
dk_pets_cache.army[petSerial] = sourceName
|
|
end
|
|
|
|
--If fire elemental totem on Wrath, then ignore the summon of the fire elemental totem itself and instead create the Greater Fire Elemental early.
|
|
--Greater Fire Elemental and Fire Elemental Totem have the same serial besides the npc id.
|
|
--There are cases where the Greater Fire Elemental could attack and the SWING_DAMAGE event happens before the spell_summon for it. Same frame.
|
|
--[[12/14 21:14:44.545 SPELL_SUMMON,Player-4384-03852552,"Toekruh-Mankrik",0x512,0x0,Creature-0-4391-615-3107-15439-00001A8313,"Fire Elemental Totem",0xa28,0x0,2894,"Fire Elemental Totem",0x1
|
|
12/14 21:14:44.545 SWING_DAMAGE,Creature-0-4391-615-3107-15438-00001A8313,"Greater Fire Elemental",0x2112,0x0,Creature-0-4391-615-3107-28860-00001A8258,"Sartharion",0xa48,0x0,Creature-0-4391-615-3107-15438-00001A8313,Creature-0-4391-615-3107-15439-00001A8313,4274,4274,0,0,0,-1,0,0,0,3261.68,530.04,155,3.3324,208,188,187,-1,4,0,0,0,nil,nil,nil
|
|
12/14 21:14:44.545 SPELL_CAST_SUCCESS,Creature-0-4391-615-3107-15438-00001A8313,"Greater Fire Elemental",0x2112,0x0,Creature-0-4391-615-3107-28860-00001A8258,"Sartharion",0xa48,0x0,57984,"Fire Blast",0x4,Creature-0-4391-615-3107-15438-00001A8313,Creature-0-4391-615-3107-15439-00001A8313,4274,4274,0,0,0,-1,0,0,0,3261.68,530.04,155,3.3324,208
|
|
12/14 21:14:44.545 SPELL_CAST_SUCCESS,Creature-0-4391-615-3107-15439-00001A8313,"Fire Elemental Totem",0x2112,0x0,0000000000000000,nil,0x80000000,0x80000000,32982,"Fire Elemental Totem",0x1,Creature-0-4391-615-3107-15439-00001A8313,Player-4384-03852552,3888,3888,0,0,0,-1,0,0,0,3257.01,531.82,155,5.1330,208
|
|
12/14 21:14:44.545 SPELL_SUMMON,Creature-0-4391-615-3107-15439-00001A8313,"Fire Elemental Totem",0x2112,0x0,Creature-0-4391-615-3107-15438-00001A8313,"Greater Fire Elemental",0x2112,0x0,32982,"Fire Elemental Totem",0x1
|
|
]]
|
|
|
|
if (isWOTLK) then
|
|
if (npcId == 15439) then
|
|
_detalhes.tabela_pets:Adicionar(petSerial:gsub("%-15439%-", "%-15438%-"), "Greater Fire Elemental", petFlags, sourceSerial, sourceName, sourceFlags)
|
|
elseif (npcId == 15438) then
|
|
return
|
|
end
|
|
end
|
|
|
|
--pet summon another pet
|
|
local petTable = container_pets[sourceSerial]
|
|
if (petTable) then
|
|
sourceName, sourceSerial, sourceFlags = petTable[1], petTable[2], petTable[3]
|
|
end
|
|
|
|
petTable = container_pets[petSerial]
|
|
if (petTable) then
|
|
sourceName, sourceSerial, sourceFlags = petTable[1], petTable[2], petTable[3]
|
|
end
|
|
|
|
_detalhes.tabela_pets:Adicionar(petSerial, petName, petFlags, sourceSerial, sourceName, sourceFlags)
|
|
end
|
|
|
|
-----------------------------------------------------------------------------------------------------------------------------------------
|
|
--HEALING serach key: ~healing |
|
|
-----------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
local ignored_shields = {
|
|
[142862] = true, -- Ancient Barrier (Malkorok)
|
|
[114556] = true, -- Purgatory (DK)
|
|
[115069] = true, -- Stance of the Sturdy Ox (Monk)
|
|
[20711] = true, -- Spirit of Redemption (Priest)
|
|
[184553] = true, --Soul Capacitor
|
|
}
|
|
|
|
local ignored_overheal = { --during refresh, some shield does not replace the old value for the new one
|
|
[47753] = true, -- Divine Aegis
|
|
[86273] = true, -- Illuminated Healing
|
|
[114908] = true, --Spirit Shell
|
|
[152118] = true, --Clarity of Will
|
|
}
|
|
|
|
function parser:heal_denied (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellidAbsorb, spellnameAbsorb, spellschoolAbsorb, serialHealer, nameHealer, flagsHealer, flags2Healer, spellidHeal, spellnameHeal, typeHeal, amountDenied)
|
|
|
|
if (not _in_combat) then
|
|
return
|
|
end
|
|
|
|
--check invalid serial against pets
|
|
if (who_serial == "") then
|
|
if (who_flags and bitBand(who_flags, OBJECT_TYPE_PETS) ~= 0) then --� um pet
|
|
return
|
|
end
|
|
end
|
|
|
|
--no name, use spellname
|
|
if (not who_name) then
|
|
who_name = "[*] " .. (spellnameHeal or "--unknown spell--")
|
|
end
|
|
|
|
--no target, just ignore
|
|
if (not alvo_name) then
|
|
return
|
|
end
|
|
|
|
--if no spellid
|
|
if (not spellidAbsorb) then
|
|
spellidAbsorb = 1
|
|
spellnameAbsorb = "unknown"
|
|
spellschoolAbsorb = 1
|
|
end
|
|
|
|
if (is_using_spellId_override) then
|
|
spellidAbsorb = override_spellId [spellidAbsorb] or spellidAbsorb
|
|
spellidHeal = override_spellId [spellidHeal] or spellidHeal
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--get actors
|
|
|
|
local este_jogador, meu_dono = healing_cache [who_serial]
|
|
if (not este_jogador) then --pode ser um desconhecido ou um pet
|
|
este_jogador, meu_dono, who_name = _current_heal_container:PegarCombatente (who_serial, who_name, who_flags, true)
|
|
if (not meu_dono and who_flags and who_serial ~= "") then --se n�o for um pet, adicionar no cache
|
|
healing_cache [who_serial] = este_jogador
|
|
end
|
|
end
|
|
|
|
local jogador_alvo, alvo_dono = healing_cache [alvo_serial]
|
|
if (not jogador_alvo) then
|
|
jogador_alvo, alvo_dono, alvo_name = _current_heal_container:PegarCombatente (alvo_serial, alvo_name, alvo_flags, true)
|
|
if (not alvo_dono and alvo_flags and also_serial ~= "") then
|
|
healing_cache [alvo_serial] = jogador_alvo
|
|
end
|
|
end
|
|
|
|
este_jogador.last_event = _tempo
|
|
|
|
------------------------------------------------
|
|
|
|
este_jogador.totaldenied = este_jogador.totaldenied + amountDenied
|
|
|
|
--actor spells table
|
|
local spell = este_jogador.spells._ActorTable [spellidAbsorb]
|
|
if (not spell) then
|
|
spell = este_jogador.spells:PegaHabilidade (spellidAbsorb, true, token)
|
|
if (_current_combat.is_boss and who_flags and bitBand(who_flags, OBJECT_TYPE_ENEMY) ~= 0) then
|
|
_detalhes.spell_school_cache [spellnameAbsorb] = spellschoolAbsorb or 1
|
|
end
|
|
end
|
|
|
|
--return spell:Add (alvo_serial, alvo_name, alvo_flags, cura_efetiva, who_name, absorbed, critical, overhealing)
|
|
return _spell_heal_func(spell, alvo_serial, alvo_name, alvo_flags, amountDenied, spellidHeal, token, nameHealer, overhealing)
|
|
|
|
end
|
|
|
|
function parser:heal_absorb(token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, targetFlags2, spellId, spellName, spellSchool, shieldOwnerSerial, shieldOwnerName, shieldOwnerFlags, shieldOwnerFlags2, shieldSpellId, shieldName, shieldType, amount)
|
|
if (isWOTLK) then
|
|
if (not amount) then
|
|
--melee
|
|
shieldOwnerSerial, shieldOwnerName, shieldOwnerFlags, shieldOwnerFlags2, shieldSpellId, shieldName, shieldType, amount = spellId, spellName, spellSchool, shieldOwnerSerial, shieldOwnerName, shieldOwnerFlags, shieldOwnerFlags2, shieldSpellId
|
|
end
|
|
return parser:heal(token, time, shieldOwnerSerial, shieldOwnerName, shieldOwnerFlags, targetSerial, targetName, targetFlags, targetFlags2, shieldSpellId, shieldName, shieldType, amount, 0, 0, nil, true)
|
|
else
|
|
--retail
|
|
if (type(shieldName) == "boolean") then
|
|
shieldOwnerSerial, shieldOwnerName, shieldOwnerFlags, shieldOwnerFlags2, shieldSpellId, shieldName, shieldType, amount = spellId, spellName, spellSchool, shieldOwnerSerial, shieldOwnerName, shieldOwnerFlags, shieldOwnerFlags2, shieldSpellId
|
|
end
|
|
end
|
|
|
|
if (ignored_shields[shieldSpellId]) then
|
|
return
|
|
|
|
elseif (shieldSpellId == 110913) then
|
|
--dark bargain
|
|
local max_health = UnitHealthMax(shieldOwnerName)
|
|
if ((amount or 0) > (max_health or 1) * 4) then
|
|
return
|
|
end
|
|
end
|
|
|
|
--diminuir o escudo nas tabelas de ShieldCache
|
|
if (_use_shield_overheal) then
|
|
local shieldsOnTarget = shield_cache[targetName]
|
|
if (shieldsOnTarget) then
|
|
local shieldsBySpellId = shieldsOnTarget[shieldSpellId]
|
|
if (shieldsBySpellId) then
|
|
local shieldAmount = shieldsBySpellId[shieldOwnerName]
|
|
if (shieldAmount) then
|
|
shieldsBySpellId[shieldOwnerName] = shieldAmount - amount
|
|
end
|
|
end
|
|
end
|
|
shield_spellid_cache[shieldSpellId] = true
|
|
end
|
|
|
|
--chamar a fun��o de cura pra contar a cura
|
|
return parser:heal(token, time, shieldOwnerSerial, shieldOwnerName, shieldOwnerFlags, targetSerial, targetName, targetFlags, targetFlags2, shieldSpellId, shieldName, shieldType, amount, 0, 0, nil, true)
|
|
end
|
|
|
|
function parser:heal(token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, targetFlags2, spellId, spellName, spellType, amount, overHealing, absorbed, critical, bIsShield)
|
|
--only capture heal if is in combat
|
|
if (not _in_combat) then
|
|
if (not _in_resting_zone) then --and not in a resting zone
|
|
return
|
|
end
|
|
end
|
|
|
|
--check invalid serial against pets
|
|
if (sourceSerial == "") then
|
|
if (sourceFlags and bitBand(sourceFlags, OBJECT_TYPE_PETS) ~= 0) then
|
|
--it's a pet without a serial number, ignore
|
|
return
|
|
end
|
|
end
|
|
|
|
--no target, no heal
|
|
if (not targetName) then
|
|
return
|
|
end
|
|
|
|
--check for banned spells
|
|
if (banned_healing_spells[spellId]) then
|
|
return
|
|
end
|
|
|
|
if (not sourceName) then
|
|
--no actor name, use spell name instead
|
|
sourceName = names_cache[spellName]
|
|
if (not sourceName) then
|
|
sourceName = "[*] " .. spellName
|
|
--cache the string manipulation
|
|
names_cache[spellName] = sourceName
|
|
end
|
|
end
|
|
|
|
if (spellId == 98021) then --spirit link toten
|
|
return parser:SLT_healing(token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, spellId, spellName, spellType, amount, overHealing, absorbed, critical, bIsShield)
|
|
end
|
|
|
|
if (is_using_spellId_override) then
|
|
spellId = override_spellId[spellId] or spellId
|
|
end
|
|
|
|
--sanguine ichor mythic dungeon affix (heal enemies)
|
|
if (spellId == SPELLID_SANGUINE_HEAL) then
|
|
sourceName = Details.SanguineHealActorName
|
|
sourceFlags = 0x518
|
|
sourceSerial = "Creature-0-3134-2289-28065-" .. SPELLID_SANGUINE_HEAL .. "-000164C698"
|
|
end
|
|
|
|
local effectiveHeal = absorbed
|
|
if (bIsShield) then
|
|
--shield has the correct amount of 'healing done'
|
|
effectiveHeal = amount
|
|
else
|
|
effectiveHeal = effectiveHeal + amount - overHealing
|
|
end
|
|
|
|
if (isWOTLK) then
|
|
--earth shield
|
|
if (spellId == SPELLID_SHAMAN_EARTHSHIELD_HEAL) then
|
|
--get the information of who placed the buff into this actor
|
|
local sourceData = TBC_EarthShieldCache[sourceName]
|
|
if (sourceData) then
|
|
sourceSerial, sourceName, sourceFlags = unpack(sourceData)
|
|
end
|
|
|
|
--prayer of mending
|
|
elseif (spellId == SPELLID_PRIEST_POM_HEAL) then
|
|
local sourceData = TBC_PrayerOfMendingCache[sourceName]
|
|
if (sourceData) then
|
|
sourceSerial, sourceName, sourceFlags = unpack(sourceData)
|
|
TBC_PrayerOfMendingCache[sourceName] = nil
|
|
end
|
|
|
|
elseif (spellId == 27163 and false) then --Judgement of Light (paladin) --disabled on 25 September 2022
|
|
--check if the hit was landed in the same cleu tick
|
|
|
|
local hitCache = TBC_JudgementOfLightCache._damageCache[sourceName]
|
|
if (hitCache) then
|
|
local timeLanded = hitCache[1]
|
|
local targetHit = hitCache[2]
|
|
|
|
if (timeLanded and timeLanded == time) then
|
|
local sourceData = TBC_JudgementOfLightCache[targetHit]
|
|
if (sourceData) then
|
|
--change the source of the healing
|
|
sourceSerial, sourceName, sourceFlags = unpack(sourceData)
|
|
--erase the hit time information
|
|
TBC_JudgementOfLightCache._damageCache[sourceName] = nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
_current_heal_container.need_refresh = true
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--get actors
|
|
|
|
--healer
|
|
local sourceActor, ownerActor = healing_cache[sourceSerial], nil
|
|
if (not sourceActor) then
|
|
sourceActor, ownerActor, sourceName = _current_heal_container:PegarCombatente(sourceSerial, sourceName, sourceFlags, true)
|
|
if (not ownerActor and sourceFlags and sourceSerial ~= "") then --if isn't a pet, add to the cache
|
|
healing_cache[sourceSerial] = sourceActor
|
|
end
|
|
end
|
|
|
|
--target
|
|
local targetActor, targetOwner = healing_cache[targetSerial], nil
|
|
if (not targetActor) then
|
|
targetActor, targetOwner, targetName = _current_heal_container:PegarCombatente(targetSerial, targetName, targetFlags, true)
|
|
if (not targetOwner and targetFlags and targetSerial ~= "") then --if isn't a pet, add to the cache
|
|
healing_cache[targetSerial] = targetActor
|
|
end
|
|
end
|
|
|
|
sourceActor.last_event = _tempo
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--an enemy healing enemy or an player actor healing a enemy
|
|
if (spellId == SPELLID_SANGUINE_HEAL) then --sanguine ichor (heal enemies)
|
|
sourceActor.grupo = true
|
|
|
|
elseif (bitBand(targetFlags, REACTION_FRIENDLY) == 0 and not _detalhes.is_in_arena and not _detalhes.is_in_battleground) then
|
|
if (not sourceActor.heal_enemy[spellId]) then
|
|
sourceActor.heal_enemy[spellId] = effectiveHeal
|
|
else
|
|
sourceActor.heal_enemy[spellId] = sourceActor.heal_enemy[spellId] + effectiveHeal
|
|
end
|
|
|
|
sourceActor.heal_enemy_amt = sourceActor.heal_enemy_amt + effectiveHeal
|
|
return true
|
|
end
|
|
|
|
--check if this is a mythic dungeon run
|
|
if (false) then
|
|
if (Details222.MythicPlus.IsMythicPlus()) then
|
|
if (bitBand(targetFlags, REACTION_FRIENDLY) == 0 and bitBand(sourceFlags, REACTION_FRIENDLY) == 0) then
|
|
--this is a enemy healing another enemy
|
|
--create or get an actor which the actor name is the spell name
|
|
local actorName = GetSpellInfo(spellId)
|
|
local spellActor = _current_heal_container:PegarCombatente(spellId, actorName, 0x514, true)
|
|
spellActor.grupo = true
|
|
spellActor.last_event = _tempo
|
|
spellActor.total = spellActor.total + effectiveHeal
|
|
spellActor.spellicon = GetSpellTexture(spellId)
|
|
spellActor.customColor = {0.5, 0.953, 0.082}
|
|
end
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--group checks
|
|
if (sourceActor.grupo and not targetActor.arena_enemy) then
|
|
_current_gtotal[2] = _current_gtotal[2] + effectiveHeal
|
|
end
|
|
|
|
if (targetActor.grupo) then
|
|
local t = last_events_cache[targetName]
|
|
|
|
if (not t) then
|
|
t = _current_combat:CreateLastEventsTable(targetName)
|
|
end
|
|
|
|
local i = t.n
|
|
|
|
local thisEvent = t[i]
|
|
|
|
thisEvent[1] = false --true if this is a damage || false for healing
|
|
thisEvent[2] = spellId --spellid || false if this is a battle ress line
|
|
thisEvent[3] = amount --amount of damage or healing
|
|
thisEvent[4] = time --parser time
|
|
|
|
--current unit heal
|
|
if (targetActor.arena_enemy) then
|
|
--this is an arena enemy, get the heal with the unit Id
|
|
local unitId = _detalhes.arena_enemies[targetName]
|
|
if (not unitId) then
|
|
unitId = Details:GuessArenaEnemyUnitId(targetName)
|
|
end
|
|
if (unitId) then
|
|
thisEvent[5] = UnitHealth(unitId)
|
|
else
|
|
thisEvent[5] = 0
|
|
end
|
|
else
|
|
thisEvent[5] = UnitHealth(targetName)
|
|
end
|
|
|
|
thisEvent[6] = sourceName
|
|
thisEvent[7] = bIsShield
|
|
thisEvent[8] = absorbed
|
|
|
|
i = i + 1
|
|
|
|
if (i == _amount_of_last_events + 1) then
|
|
t.n = 1
|
|
else
|
|
t.n = i
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--~activity time
|
|
if (not sourceActor.iniciar_hps and _is_activity_time) then
|
|
sourceActor:Iniciar (true) --inicia o hps do jogador
|
|
|
|
if (ownerActor and not ownerActor.iniciar_hps) then
|
|
ownerActor:Iniciar (true)
|
|
if (ownerActor.end_time) then
|
|
ownerActor.end_time = nil
|
|
else
|
|
--meu_dono:IniciarTempo (_tempo)
|
|
ownerActor.start_time = _tempo
|
|
end
|
|
end
|
|
|
|
if (sourceActor.end_time) then --o combate terminou, reabrir o tempo
|
|
sourceActor.end_time = nil
|
|
else
|
|
--este_jogador:IniciarTempo (_tempo)
|
|
sourceActor.start_time = _tempo
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--add amount
|
|
|
|
--actor target
|
|
if (effectiveHeal > 0) then
|
|
--combat total
|
|
_current_total[2] = _current_total[2] + effectiveHeal
|
|
|
|
--actor healing amount
|
|
sourceActor.total = sourceActor.total + effectiveHeal
|
|
sourceActor.total_without_pet = sourceActor.total_without_pet + effectiveHeal
|
|
|
|
--healing taken
|
|
targetActor.healing_taken = targetActor.healing_taken + effectiveHeal --adiciona o dano tomado
|
|
if (not targetActor.healing_from[sourceName]) then --adiciona a pool de dano tomado de quem
|
|
targetActor.healing_from[sourceName] = true
|
|
end
|
|
|
|
if (bIsShield) then
|
|
sourceActor.totalabsorb = sourceActor.totalabsorb + effectiveHeal
|
|
sourceActor.targets_absorbs[targetName] = (sourceActor.targets_absorbs[targetName] or 0) + effectiveHeal
|
|
end
|
|
|
|
--pet
|
|
if (ownerActor) then
|
|
ownerActor.total = ownerActor.total + effectiveHeal --heal do pet
|
|
ownerActor.targets[targetName] = (ownerActor.targets[targetName] or 0) + effectiveHeal
|
|
end
|
|
|
|
--target amount
|
|
sourceActor.targets[targetName] = (sourceActor.targets[targetName] or 0) + effectiveHeal
|
|
end
|
|
|
|
if (ownerActor) then
|
|
ownerActor.last_event = _tempo
|
|
end
|
|
|
|
if (overHealing > 0) then
|
|
sourceActor.totalover = sourceActor.totalover + overHealing
|
|
sourceActor.targets_overheal[targetName] = (sourceActor.targets_overheal[targetName] or 0) + overHealing
|
|
|
|
if (ownerActor) then
|
|
ownerActor.totalover = ownerActor.totalover + overHealing
|
|
end
|
|
end
|
|
|
|
--actor spells table
|
|
local spellTable = sourceActor.spells._ActorTable[spellId]
|
|
if (not spellTable) then
|
|
spellTable = sourceActor.spells:PegaHabilidade(spellId, true, token)
|
|
if (bIsShield) then
|
|
spellTable.is_shield = true
|
|
end
|
|
if (_current_combat.is_boss and sourceFlags and bitBand(sourceFlags, OBJECT_TYPE_ENEMY) ~= 0) then
|
|
_detalhes.spell_school_cache[spellName] = spellType
|
|
end
|
|
end
|
|
|
|
--empowerment data
|
|
if (empower_cache[sourceSerial]) then
|
|
local empowerSpellInfo = empower_cache[sourceSerial][spellName]
|
|
if (empowerSpellInfo) then
|
|
if (not empowerSpellInfo.counted_damage) then
|
|
--total of empowerment
|
|
spellTable.e_total = (spellTable.e_total or 0) + empowerSpellInfo.empowerLevel --used to calculate the average empowerment
|
|
--total amount of empowerment
|
|
spellTable.e_amt = (spellTable.e_amt or 0) + 1 --used to calculate the average empowerment
|
|
|
|
--amount of casts on each level
|
|
spellTable.e_lvl = spellTable.e_lvl or {}
|
|
spellTable.e_lvl[empowerSpellInfo.empowerLevel] = (spellTable.e_lvl[empowerSpellInfo.empowerLevel] or 0) + 1
|
|
|
|
empowerSpellInfo.counted_damage = true
|
|
end
|
|
|
|
--healing bracket
|
|
spellTable.e_heal = spellTable.e_heal or {}
|
|
spellTable.e_heal[empowerSpellInfo.empowerLevel] = (spellTable.e_heal[empowerSpellInfo.empowerLevel] or 0) + effectiveHeal
|
|
end
|
|
end
|
|
|
|
if (bIsShield) then
|
|
return _spell_heal_func(spellTable, targetSerial, targetName, targetFlags, effectiveHeal, sourceName, 0, nil, overHealing, true)
|
|
else
|
|
return _spell_heal_func(spellTable, targetSerial, targetName, targetFlags, effectiveHeal, sourceName, absorbed, critical, overHealing)
|
|
end
|
|
end
|
|
|
|
function parser:SLT_healing (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, spelltype, amount, overhealing, absorbed, critical, is_shield)
|
|
|
|
--get actors
|
|
local este_jogador, meu_dono = healing_cache [who_serial]
|
|
if (not este_jogador) then --pode ser um desconhecido ou um pet
|
|
este_jogador, meu_dono, who_name = _current_heal_container:PegarCombatente (who_serial, who_name, who_flags, true)
|
|
if (not meu_dono and who_flags and who_serial ~= "") then --se n�o for um pet, adicionar no cache
|
|
healing_cache [who_serial] = este_jogador
|
|
end
|
|
end
|
|
|
|
local jogador_alvo, alvo_dono = healing_cache [alvo_serial]
|
|
if (not jogador_alvo) then
|
|
jogador_alvo, alvo_dono, alvo_name = _current_heal_container:PegarCombatente (alvo_serial, alvo_name, alvo_flags, true)
|
|
if (not alvo_dono and alvo_flags and alvo_serial ~= "") then
|
|
healing_cache [alvo_serial] = jogador_alvo
|
|
end
|
|
end
|
|
|
|
este_jogador.last_event = _tempo
|
|
|
|
local t = last_events_cache [alvo_name]
|
|
|
|
if (not t) then
|
|
t = _current_combat:CreateLastEventsTable (alvo_name)
|
|
end
|
|
|
|
local i = t.n
|
|
|
|
local this_event = t [i]
|
|
|
|
this_event [1] = false --true if this is a damage || false for healing
|
|
this_event [2] = spellid --spellid || false if this is a battle ress line
|
|
this_event [3] = amount --amount of damage or healing
|
|
this_event [4] = time --parser time
|
|
this_event [5] = UnitHealth (alvo_name) --current unit heal
|
|
this_event [6] = who_name --source name
|
|
this_event [7] = is_shield
|
|
this_event [8] = absorbed
|
|
|
|
i = i + 1
|
|
|
|
if (i == _amount_of_last_events+1) then
|
|
t.n = 1
|
|
else
|
|
t.n = i
|
|
end
|
|
|
|
local spell = este_jogador.spells._ActorTable [spellid]
|
|
if (not spell) then
|
|
spell = este_jogador.spells:PegaHabilidade (spellid, true, token)
|
|
spell.neutral = true
|
|
end
|
|
|
|
return _spell_heal_func (spell, alvo_serial, alvo_name, alvo_flags, absorbed + amount - overhealing, who_name, absorbed, critical, overhealing, nil)
|
|
end
|
|
|
|
-----------------------------------------------------------------------------------------------------------------------------------------
|
|
--BUFFS & DEBUFFS search key: ~buff ~aura ~shield |
|
|
-----------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function parser:buff(token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, targetFlags2, spellId, spellName, spellschool, auraType, amount, arg1, arg2, arg3)
|
|
--not yet well know about unnamed buff casters
|
|
if (not targetName) then
|
|
targetName = "[*] Unknown shield target"
|
|
|
|
elseif (not sourceName) then
|
|
sourceName = names_cache[spellName]
|
|
if (not sourceName) then
|
|
sourceName = "[*] " .. spellName
|
|
names_cache[spellName] = sourceName
|
|
end
|
|
sourceFlags = 0xa48
|
|
sourceSerial = ""
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--spell reflection
|
|
if (reflection_spellid[spellId]) then --~reflect
|
|
--this is a spell reflect aura
|
|
--we save the info on who received this aura and from whom
|
|
--this will be used to credit this spell as the one doing the damage
|
|
reflection_auras[targetSerial] = {
|
|
who_serial = sourceSerial,
|
|
who_name = sourceName,
|
|
who_flags = sourceFlags,
|
|
spellid = spellId,
|
|
spellname = spellName,
|
|
spelltype = spellschool,
|
|
}
|
|
end
|
|
|
|
if (auraType == "BUFF") then
|
|
if (LIB_OPEN_RAID_BLOODLUST[spellId]) then --~bloodlust
|
|
if (_detalhes.playername == targetName) then
|
|
_current_combat.bloodlust = _current_combat.bloodlust or {}
|
|
_current_combat.bloodlust[#_current_combat.bloodlust+1] = _current_combat:GetCombatTime()
|
|
end
|
|
end
|
|
|
|
if (spellId == 388007 or spellId == 388011) then --buff: bleesing of the summer and winter
|
|
cacheAnything.paladin_vivaldi_blessings[targetSerial] = {sourceSerial, sourceName, sourceFlags}
|
|
|
|
elseif (spellId == 27827) then --spirit of redemption (holy ~priest) ~spirit
|
|
local deathLog = last_events_cache[targetName]
|
|
if (not deathLog) then
|
|
deathLog = _current_combat:CreateLastEventsTable(targetName)
|
|
end
|
|
|
|
local i = deathLog.n
|
|
local thisEvent = deathLog[i]
|
|
|
|
if (not thisEvent) then
|
|
return print("Parser Event Error -> Set to 16 DeathLogs and /reload", i, _amount_of_last_events)
|
|
end
|
|
|
|
thisEvent[1] = 5 --5 = buff aplication
|
|
thisEvent[2] = spellId --spellid
|
|
thisEvent[3] = 1
|
|
thisEvent[4] = time --parser time
|
|
thisEvent[5] = UnitHealth(targetName) --current unit heal
|
|
thisEvent[6] = sourceName --source name
|
|
thisEvent[7] = false
|
|
thisEvent[8] = false
|
|
thisEvent[9] = false
|
|
thisEvent[10] = false
|
|
|
|
i = i + 1
|
|
|
|
if (i == _amount_of_last_events+1) then
|
|
deathLog.n = 1
|
|
else
|
|
deathLog.n = i
|
|
end
|
|
|
|
C_Timer.After(0.05, function() --25/12/2022: enabled the delay to wait the combatlog dump damage events which will happen after the buff is applied
|
|
parser:dead("UNIT_DIED", time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags)
|
|
ignore_death_cache [sourceName] = true
|
|
end)
|
|
return
|
|
|
|
elseif (spellId == SPELLID_MONK_GUARD) then
|
|
--BfA monk talent
|
|
monk_guard_talent [sourceSerial] = amount
|
|
|
|
elseif (spellId == 272790 and cacheAnything.track_hunter_frenzy) then --hunter pet Frenzy quick fix for show the Frenzy uptime
|
|
if (pet_frenzy_cache[sourceName]) then
|
|
if (DetailsFramework:IsNearlyEqual(pet_frenzy_cache[sourceName], time, 0.2)) then
|
|
return
|
|
end
|
|
end
|
|
|
|
if (not _detalhes.in_combat) then
|
|
C_Timer.After(1, function()
|
|
if (_detalhes.in_combat) then
|
|
if (pet_frenzy_cache[sourceName]) then
|
|
if (DetailsFramework:IsNearlyEqual(pet_frenzy_cache[sourceName], time, 0.2)) then
|
|
return
|
|
end
|
|
end
|
|
return parser:add_buff_uptime(token, time, sourceSerial, sourceName, sourceFlags, sourceSerial, sourceName, sourceFlags, 0x0, spellId, spellName, "BUFF_UPTIME_IN")
|
|
end
|
|
end)
|
|
return
|
|
end
|
|
|
|
pet_frenzy_cache[sourceName] = time --when the buffIN happened
|
|
return parser:add_buff_uptime(token, time, sourceSerial, sourceName, sourceFlags, sourceSerial, sourceName, sourceFlags, 0x0, spellId, spellName, "BUFF_UPTIME_IN")
|
|
end
|
|
|
|
if (isWOTLK) then
|
|
if (SHAMAN_EARTHSHIELD_BUFF[spellId]) then
|
|
TBC_EarthShieldCache[targetName] = {sourceSerial, sourceName, sourceFlags}
|
|
|
|
elseif (spellId == SPELLID_PRIEST_POM_BUFF) then
|
|
TBC_PrayerOfMendingCache [targetName] = {sourceSerial, sourceName, sourceFlags}
|
|
|
|
elseif (spellId == 27163 and false) then --Judgement Of Light
|
|
TBC_JudgementOfLightCache[targetName] = {sourceSerial, sourceName, sourceFlags}
|
|
end
|
|
end
|
|
|
|
if (sourceName == targetName and raid_members_cache[sourceSerial] and _in_combat) then
|
|
--player itself
|
|
parser:add_buff_uptime(token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, targetFlags2, spellId, spellName, "BUFF_UPTIME_IN")
|
|
|
|
elseif (container_pets[sourceSerial] and container_pets[sourceSerial][2] == targetSerial) then
|
|
--pet putting an aura on its owner
|
|
parser:add_buff_uptime(token, time, targetSerial, targetName, targetFlags, targetSerial, targetName, targetFlags, targetFlags2, spellId, spellName, "BUFF_UPTIME_IN")
|
|
|
|
elseif (buffs_to_other_players[spellId]) then
|
|
--e.g. power infusion
|
|
parser:add_buff_uptime(token, time, targetSerial, targetName, targetFlags, targetSerial, targetName, targetFlags, targetFlags2, spellId, spellName, "BUFF_UPTIME_IN")
|
|
end
|
|
|
|
--healing done absorbs
|
|
if (_use_shield_overheal) then
|
|
if (shield_spellid_cache[spellId] and amount) then
|
|
if (not shield_cache[targetName]) then
|
|
shield_cache[targetName] = {}
|
|
shield_cache[targetName][spellId] = {}
|
|
shield_cache[targetName][spellId][sourceName] = amount
|
|
|
|
elseif (not shield_cache[targetName][spellId]) then
|
|
shield_cache[targetName][spellId] = {}
|
|
shield_cache[targetName][spellId][sourceName] = amount
|
|
|
|
else
|
|
shield_cache[targetName][spellId][sourceName] = amount
|
|
end
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--recording debuffs applied by player
|
|
|
|
elseif (auraType == "DEBUFF") then
|
|
if (isWOTLK) then --buff applied
|
|
if (spellId == 27162 and false) then --Judgement Of Light
|
|
--which player applied the judgement of light on this mob
|
|
TBC_JudgementOfLightCache[targetName] = {sourceSerial, sourceName, sourceFlags}
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--spell reflection
|
|
if (sourceSerial == targetSerial and not reflection_ignore[spellId]) then
|
|
--self-inflicted debuff that could've been reflected
|
|
--just saving it as a boolean to check for reflections
|
|
reflection_debuffs[sourceSerial] = reflection_debuffs[sourceSerial] or {}
|
|
reflection_debuffs[sourceSerial][spellId] = true
|
|
end
|
|
|
|
if (_in_combat) then
|
|
------------------------------------------------------------------------------------------------
|
|
--buff uptime
|
|
if (cc_spell_list [spellId]) then
|
|
parser:add_cc_done (token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, targetFlags2, spellId, spellName)
|
|
end
|
|
|
|
if ((bitfield_debuffs[spellName] or bitfield_debuffs[spellId]) and raid_members_cache[targetSerial]) then
|
|
bitfield_swap_cache[targetSerial] = true
|
|
end
|
|
|
|
if (raid_members_cache [sourceSerial]) then
|
|
--call record debuffs uptime
|
|
parser:add_debuff_uptime (token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, targetFlags2, spellId, spellName, "DEBUFF_UPTIME_IN")
|
|
|
|
elseif (raid_members_cache [targetSerial] and not raid_members_cache [sourceSerial]) then --alvo � da raide e who � alguem de fora da raide
|
|
parser:add_bad_debuff_uptime (token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, targetFlags2, spellId, spellName, spellschool, "DEBUFF_UPTIME_IN")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- ~crowd control ~ccdone
|
|
function parser:add_cc_done(token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname)
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--early checks and fixes
|
|
|
|
_current_misc_container.need_refresh = true
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--get actors
|
|
|
|
--main actor
|
|
local este_jogador, meu_dono = misc_cache [who_name]
|
|
if (not este_jogador) then --pode ser um desconhecido ou um pet
|
|
este_jogador, meu_dono, who_name = _current_misc_container:PegarCombatente (who_serial, who_name, who_flags, true)
|
|
if (not meu_dono) then --se n�o for um pet, adicionar no cache
|
|
misc_cache [who_name] = este_jogador
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--build containers on the fly
|
|
|
|
if (not este_jogador.cc_done) then
|
|
este_jogador.cc_done = _detalhes:GetOrderNumber()
|
|
este_jogador.cc_done_spells = container_habilidades:NovoContainer (container_misc)
|
|
este_jogador.cc_done_targets = {}
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--add amount
|
|
|
|
--update last event
|
|
este_jogador.last_event = _tempo
|
|
|
|
--add amount
|
|
este_jogador.cc_done = este_jogador.cc_done + 1
|
|
este_jogador.cc_done_targets [alvo_name] = (este_jogador.cc_done_targets [alvo_name] or 0) + 1
|
|
|
|
--actor spells table
|
|
local spell = este_jogador.cc_done_spells._ActorTable [spellid]
|
|
if (not spell) then
|
|
spell = este_jogador.cc_done_spells:PegaHabilidade (spellid, true)
|
|
end
|
|
|
|
spell.targets [alvo_name] = (spell.targets [alvo_name] or 0) + 1
|
|
spell.counter = spell.counter + 1
|
|
|
|
--add the crowd control for the pet owner
|
|
if (meu_dono) then
|
|
|
|
if (not meu_dono.cc_done) then
|
|
meu_dono.cc_done = _detalhes:GetOrderNumber()
|
|
meu_dono.cc_done_spells = container_habilidades:NovoContainer (container_misc)
|
|
meu_dono.cc_done_targets = {}
|
|
end
|
|
|
|
--add amount
|
|
meu_dono.cc_done = meu_dono.cc_done + 1
|
|
meu_dono.cc_done_targets [alvo_name] = (meu_dono.cc_done_targets [alvo_name] or 0) + 1
|
|
|
|
--actor spells table
|
|
local spell = meu_dono.cc_done_spells._ActorTable [spellid]
|
|
if (not spell) then
|
|
spell = meu_dono.cc_done_spells:PegaHabilidade (spellid, true)
|
|
end
|
|
|
|
spell.targets [alvo_name] = (spell.targets [alvo_name] or 0) + 1
|
|
spell.counter = spell.counter + 1
|
|
end
|
|
|
|
--verifica a classe
|
|
if (who_flags and bitBand(who_flags, OBJECT_TYPE_PLAYER) ~= 0) then
|
|
if (este_jogador.classe == "UNKNOW" or este_jogador.classe == "UNGROUPPLAYER") then
|
|
local damager_object = damage_cache [who_serial]
|
|
if (damager_object and (damager_object.classe ~= "UNKNOW" and damager_object.classe ~= "UNGROUPPLAYER")) then
|
|
este_jogador.classe = damager_object.classe
|
|
else
|
|
local healing_object = healing_cache [who_serial]
|
|
if (healing_object and (healing_object.classe ~= "UNKNOW" and healing_object.classe ~= "UNGROUPPLAYER")) then
|
|
este_jogador.classe = healing_object.classe
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function parser:buff_refresh(token, time, sourceSerial, sourceName, sourceFlags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellName, spellschool, tipo, amount)
|
|
if (not sourceName) then
|
|
sourceName = names_cache[spellName]
|
|
if (not sourceName) then
|
|
sourceName = "[*] " .. spellName
|
|
names_cache[spellName] = sourceName
|
|
end
|
|
sourceFlags = 0xa48
|
|
sourceSerial = ""
|
|
end
|
|
|
|
if (tipo == "BUFF") then
|
|
if (spellid == 272790 and cacheAnything.track_hunter_frenzy) then --hunter pet Frenzy spellid
|
|
local miscActorObject = misc_cache[sourceName]
|
|
if (miscActorObject) then
|
|
--fastest way to query utility spell data
|
|
local spellTable = miscActorObject.buff_uptime_spells and miscActorObject.buff_uptime_spells._ActorTable[spellid]
|
|
if (spellTable) then
|
|
if (spellTable.actived and pet_frenzy_cache[sourceName]) then
|
|
if (DetailsFramework:IsNearlyEqual(pet_frenzy_cache[sourceName], time, 0.2)) then
|
|
return
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
parser:add_buff_uptime(token, time, sourceSerial, sourceName, sourceFlags, sourceSerial, sourceName, sourceFlags, 0x0, spellid, spellName, "BUFF_UPTIME_REFRESH")
|
|
pet_frenzy_cache[sourceName] = time
|
|
return
|
|
end
|
|
|
|
if (sourceName == alvo_name and raid_members_cache [sourceSerial] and _in_combat) then
|
|
--call record buffs uptime
|
|
parser:add_buff_uptime (token, time, sourceSerial, sourceName, sourceFlags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellName, "BUFF_UPTIME_REFRESH")
|
|
|
|
elseif (container_pets [sourceSerial] and container_pets [sourceSerial][2] == alvo_serial) then
|
|
--um pet colocando uma aura do dono
|
|
parser:add_buff_uptime (token, time, alvo_serial, alvo_name, alvo_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellName, "BUFF_UPTIME_REFRESH")
|
|
|
|
elseif (buffs_to_other_players[spellid]) then
|
|
parser:add_buff_uptime(token, time, alvo_serial, alvo_name, alvo_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellName, "BUFF_UPTIME_REFRESH")
|
|
end
|
|
|
|
if (_use_shield_overheal) then
|
|
if (shield_spellid_cache[spellid] and amount) then
|
|
if (shield_cache[alvo_name] and shield_cache[alvo_name][spellid] and shield_cache[alvo_name][spellid][sourceName]) then
|
|
if (ignored_overheal[spellid]) then
|
|
shield_cache[alvo_name][spellid][sourceName] = amount --refresh gives the updated amount
|
|
return
|
|
end
|
|
|
|
--get the shield overheal
|
|
local overhealAmount = shield_cache[alvo_name][spellid][sourceName]
|
|
--set the new shield amount
|
|
shield_cache[alvo_name][spellid][sourceName] = amount
|
|
|
|
if (overhealAmount > 0) then
|
|
return parser:heal(token, time, sourceSerial, sourceName, sourceFlags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellName, nil, 0, ceil (overhealAmount), 0, nil, true)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--recording debuffs applied by player
|
|
|
|
elseif (tipo == "DEBUFF") then
|
|
if (isWOTLK) then --buff refresh
|
|
if (spellid == 27162 and false) then --Judgement Of Light
|
|
--which player applied the judgement of light on this mob
|
|
TBC_JudgementOfLightCache[alvo_name] = {sourceSerial, sourceName, sourceFlags}
|
|
end
|
|
end
|
|
|
|
if (_in_combat) then
|
|
------------------------------------------------------------------------------------------------
|
|
--buff uptime
|
|
if (raid_members_cache [sourceSerial]) then
|
|
--call record debuffs uptime
|
|
parser:add_debuff_uptime (token, time, sourceSerial, sourceName, sourceFlags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellName, "DEBUFF_UPTIME_REFRESH")
|
|
elseif (raid_members_cache [alvo_serial] and not raid_members_cache [sourceSerial]) then --alvo � da raide e o caster � inimigo
|
|
parser:add_bad_debuff_uptime (token, time, sourceSerial, sourceName, sourceFlags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellName, spellschool, "DEBUFF_UPTIME_REFRESH", amount)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- ~unbuff
|
|
function parser:unbuff(token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, alvo_flags2, spellid, spellName, spellSchool, tipo, amount)
|
|
if (not sourceName) then
|
|
sourceName = names_cache[spellName]
|
|
if (not sourceName) then
|
|
sourceName = "[*] " .. spellName
|
|
names_cache[spellName] = sourceName
|
|
end
|
|
sourceFlags = 0xa48
|
|
sourceSerial = ""
|
|
end
|
|
|
|
if (tipo == "BUFF") then
|
|
if (spellid == 272790 and cacheAnything.track_hunter_frenzy) then --hunter pet Frenzy spellid
|
|
if (not pet_frenzy_cache[sourceName]) then
|
|
return
|
|
end
|
|
parser:add_buff_uptime(token, time, sourceSerial, sourceName, sourceFlags, sourceSerial, sourceName, sourceFlags, 0x0, spellid, spellName, "BUFF_UPTIME_OUT")
|
|
pet_frenzy_cache[sourceName] = nil
|
|
return
|
|
end
|
|
|
|
if (sourceName == targetName and raid_members_cache [sourceSerial] and _in_combat) then
|
|
--call record buffs uptime
|
|
parser:add_buff_uptime (token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, alvo_flags2, spellid, spellName, "BUFF_UPTIME_OUT")
|
|
elseif (container_pets [sourceSerial] and container_pets [sourceSerial][2] == targetSerial) then
|
|
--um pet colocando uma aura do dono
|
|
parser:add_buff_uptime (token, time, targetSerial, targetName, targetFlags, targetSerial, targetName, targetFlags, alvo_flags2, spellid, spellName, "BUFF_UPTIME_OUT")
|
|
|
|
elseif (buffs_to_other_players[spellid]) then
|
|
parser:add_buff_uptime(token, time, targetSerial, targetName, targetFlags, targetSerial, targetName, targetFlags, alvo_flags2, spellid, spellName, "BUFF_UPTIME_OUT")
|
|
end
|
|
|
|
if (spellid == SPELLID_MONK_GUARD) then
|
|
--BfA monk talent
|
|
if (monk_guard_talent [sourceSerial]) then
|
|
local damage_prevented = monk_guard_talent [sourceSerial] - (amount or 0)
|
|
parser:heal (token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, alvo_flags2, spellid, spellName, spellSchool, damage_prevented, ceil (amount or 0), 0, 0, true)
|
|
end
|
|
|
|
elseif (spellid == 388007 or spellid == 388011) then --buff: bleesing of the summer
|
|
cacheAnything.paladin_vivaldi_blessings[targetSerial] = nil
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--shield overheal
|
|
if (_use_shield_overheal) then
|
|
if (shield_spellid_cache[spellid]) then
|
|
if (shield_cache [targetName] and shield_cache [targetName][spellid] and shield_cache [targetName][spellid][sourceName]) then
|
|
if (amount) then
|
|
-- o amount � o que sobrou do escudo
|
|
--local overheal = escudo [alvo_name][spellid][who_name] --usando o 'amount' passado pela função
|
|
--overheal não esta dando refresh quando um valor é adicionado ao escudo
|
|
shield_cache [targetName][spellid][sourceName] = 0
|
|
|
|
--can't use monk guard since its overheal is computed inside the unbuff
|
|
if (amount > 0 and spellid ~= SPELLID_MONK_GUARD) then
|
|
--removing the nil at the end before true for is_shield, I have no documentation change about it, not sure the reason why it was addded
|
|
return parser:heal (token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, alvo_flags2, spellid, spellName, nil, 0, ceil (amount), 0, 0, true) --0, 0, nil, true
|
|
else
|
|
return
|
|
end
|
|
end
|
|
|
|
shield_cache [targetName][spellid][sourceName] = 0
|
|
end
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--recording debuffs applied by player
|
|
elseif (tipo == "DEBUFF") then
|
|
if (isWOTLK) then --buff removed
|
|
if (spellid == 27162 and false) then --Judgement Of Light
|
|
TBC_JudgementOfLightCache[targetName] = nil
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--spell reflection
|
|
if (reflection_dispels[targetSerial] and reflection_dispels[targetSerial][spellid]) then
|
|
--debuff was dispelled by a reflecting dispel and could've been reflected
|
|
--save the data about whom dispelled who and the spell that was dispelled
|
|
local reflection = reflection_dispels[targetSerial][spellid]
|
|
reflection_events[sourceSerial] = reflection_events[sourceSerial] or {}
|
|
reflection_events[sourceSerial][spellid] = {
|
|
who_serial = reflection.who_serial,
|
|
who_name = reflection.who_name,
|
|
who_flags = reflection.who_flags,
|
|
spellid = reflection.spellid,
|
|
spellname = reflection.spellname,
|
|
spelltype = reflection.spelltype,
|
|
time = time,
|
|
}
|
|
reflection_dispels[targetSerial][spellid] = nil
|
|
if (next(reflection_dispels[targetSerial]) == nil) then
|
|
--suggestion on how to make this better?
|
|
reflection_dispels[targetSerial] = nil
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--spell reflection
|
|
if (reflection_debuffs[sourceSerial] and reflection_debuffs[sourceSerial][spellid]) then
|
|
--self-inflicted debuff was removed, so we just clear this data
|
|
reflection_debuffs[sourceSerial][spellid] = nil
|
|
if (next(reflection_debuffs[sourceSerial]) == nil) then
|
|
--better way of doing this? accepting suggestions
|
|
reflection_debuffs[sourceSerial] = nil
|
|
end
|
|
end
|
|
|
|
if (_in_combat) then
|
|
------------------------------------------------------------------------------------------------
|
|
--buff uptime
|
|
if (raid_members_cache [sourceSerial]) then
|
|
--call record debuffs uptime
|
|
parser:add_debuff_uptime (token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, alvo_flags2, spellid, spellName, "DEBUFF_UPTIME_OUT")
|
|
elseif (raid_members_cache [targetSerial] and not raid_members_cache [sourceSerial]) then --alvo � da raide e o caster � inimigo
|
|
parser:add_bad_debuff_uptime (token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, alvo_flags2, spellid, spellName, spellSchool, "DEBUFF_UPTIME_OUT")
|
|
end
|
|
|
|
if ((bitfield_debuffs[spellName] or bitfield_debuffs[spellid]) and targetSerial) then
|
|
bitfield_swap_cache[targetSerial] = nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-----------------------------------------------------------------------------------------------------------------------------------------
|
|
--MISC search key: ~buffuptime ~buffsuptime |
|
|
-----------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function parser:add_bad_debuff_uptime (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname, spellschool, in_out, stack_amount)
|
|
|
|
if (not alvo_name) then
|
|
--no target name, just quit
|
|
return
|
|
elseif (not who_name) then
|
|
--no actor name, use spell name instead
|
|
who_name = "[*] "..spellname
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--get actors
|
|
--nome do debuff ser� usado para armazenar o nome do ator
|
|
local este_jogador = misc_cache [spellname]
|
|
if (not este_jogador) then --pode ser um desconhecido ou um pet
|
|
este_jogador = _current_misc_container:PegarCombatente (who_serial, spellname, who_flags, true)
|
|
misc_cache [spellname] = este_jogador
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--build containers on the fly
|
|
|
|
if (not este_jogador.debuff_uptime) then
|
|
este_jogador.boss_debuff = true
|
|
este_jogador.damage_twin = who_name
|
|
este_jogador.spellschool = spellschool
|
|
este_jogador.damage_spellid = spellid
|
|
este_jogador.debuff_uptime = 0
|
|
este_jogador.debuff_uptime_spells = container_habilidades:NovoContainer (container_misc)
|
|
este_jogador.debuff_uptime_targets = {}
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--add amount
|
|
|
|
--update last event
|
|
este_jogador.last_event = _tempo
|
|
|
|
--actor target
|
|
local este_alvo = este_jogador.debuff_uptime_targets [alvo_name]
|
|
if (not este_alvo) then
|
|
este_alvo = _detalhes.atributo_misc:CreateBuffTargetObject()
|
|
este_jogador.debuff_uptime_targets [alvo_name] = este_alvo
|
|
end
|
|
|
|
if (in_out == "DEBUFF_UPTIME_IN") then
|
|
este_alvo.actived = true
|
|
este_alvo.activedamt = este_alvo.activedamt + 1
|
|
if (este_alvo.actived_at and este_alvo.actived) then
|
|
este_alvo.uptime = este_alvo.uptime + _tempo - este_alvo.actived_at
|
|
este_jogador.debuff_uptime = este_jogador.debuff_uptime + _tempo - este_alvo.actived_at
|
|
end
|
|
este_alvo.actived_at = _tempo
|
|
|
|
--death log
|
|
--record death log
|
|
local t = last_events_cache [alvo_name]
|
|
|
|
if (not t) then
|
|
t = _current_combat:CreateLastEventsTable (alvo_name)
|
|
end
|
|
|
|
local i = t.n
|
|
|
|
local this_event = t [i]
|
|
|
|
if (not this_event) then
|
|
return print("Parser Event Error -> Set to 16 DeathLogs and /reload", i, _amount_of_last_events)
|
|
end
|
|
|
|
this_event [1] = 4 --4 = debuff aplication
|
|
this_event [2] = spellid --spellid
|
|
this_event [3] = 1
|
|
this_event [4] = time --parser time
|
|
this_event [5] = UnitHealth (alvo_name) --current unit heal
|
|
this_event [6] = who_name --source name
|
|
this_event [7] = false
|
|
this_event [8] = false
|
|
this_event [9] = false
|
|
this_event [10] = false
|
|
|
|
i = i + 1
|
|
|
|
if (i == _amount_of_last_events+1) then
|
|
t.n = 1
|
|
else
|
|
t.n = i
|
|
end
|
|
|
|
elseif (in_out == "DEBUFF_UPTIME_REFRESH") then
|
|
if (este_alvo.actived_at and este_alvo.actived) then
|
|
este_alvo.uptime = este_alvo.uptime + _tempo - este_alvo.actived_at
|
|
este_jogador.debuff_uptime = este_jogador.debuff_uptime + _tempo - este_alvo.actived_at
|
|
end
|
|
este_alvo.actived_at = _tempo
|
|
este_alvo.actived = true
|
|
|
|
--death log
|
|
|
|
--local name, texture, count, debuffType, duration, expirationTime, caster, canStealOrPurge, nameplateShowPersonal, spellId = UnitAura (alvo_name, spellname, nil, "HARMFUL")
|
|
--UnitAura ("Kastfall", "Gulp Frog Toxin", nil, "HARMFUL")
|
|
|
|
--record death log
|
|
local t = last_events_cache [alvo_name]
|
|
|
|
if (not t) then
|
|
t = _current_combat:CreateLastEventsTable (alvo_name)
|
|
end
|
|
|
|
local i = t.n
|
|
|
|
local this_event = t [i]
|
|
|
|
if (not this_event) then
|
|
return print("Parser Event Error -> Set to 16 DeathLogs and /reload", i, _amount_of_last_events)
|
|
end
|
|
|
|
this_event [1] = 4 --4 = debuff aplication
|
|
this_event [2] = spellid --spellid
|
|
this_event [3] = stack_amount or 1
|
|
this_event [4] = time --parser time
|
|
this_event [5] = UnitHealth (alvo_name) --current unit heal
|
|
this_event [6] = who_name --source name
|
|
this_event [7] = false
|
|
this_event [8] = false
|
|
this_event [9] = false
|
|
this_event [10] = false
|
|
|
|
i = i + 1
|
|
|
|
if (i == _amount_of_last_events+1) then
|
|
t.n = 1
|
|
else
|
|
t.n = i
|
|
end
|
|
|
|
elseif (in_out == "DEBUFF_UPTIME_OUT") then
|
|
if (este_alvo.actived_at and este_alvo.actived) then
|
|
este_alvo.uptime = este_alvo.uptime + _detalhes._tempo - este_alvo.actived_at
|
|
este_jogador.debuff_uptime = este_jogador.debuff_uptime + _tempo - este_alvo.actived_at --token = actor misc object
|
|
end
|
|
|
|
este_alvo.activedamt = este_alvo.activedamt - 1
|
|
|
|
if (este_alvo.activedamt == 0) then
|
|
este_alvo.actived = false
|
|
este_alvo.actived_at = nil
|
|
else
|
|
este_alvo.actived_at = _tempo
|
|
end
|
|
end
|
|
end
|
|
|
|
-- ~debuff
|
|
function parser:add_debuff_uptime (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname, in_out)
|
|
------------------------------------------------------------------------------------------------
|
|
--early checks and fixes
|
|
|
|
_current_misc_container.need_refresh = true
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--get actors
|
|
local este_jogador = misc_cache [who_name]
|
|
if (not este_jogador) then --pode ser um desconhecido ou um pet
|
|
este_jogador = _current_misc_container:PegarCombatente (who_serial, who_name, who_flags, true)
|
|
misc_cache [who_name] = este_jogador
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--build containers on the fly
|
|
|
|
if (not este_jogador.debuff_uptime) then
|
|
este_jogador.debuff_uptime = 0
|
|
este_jogador.debuff_uptime_spells = container_habilidades:NovoContainer (container_misc)
|
|
este_jogador.debuff_uptime_targets = {}
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--add amount
|
|
|
|
--update last event
|
|
este_jogador.last_event = _tempo
|
|
|
|
--actor spells table
|
|
local spell = este_jogador.debuff_uptime_spells._ActorTable [spellid]
|
|
if (not spell) then
|
|
spell = este_jogador.debuff_uptime_spells:PegaHabilidade (spellid, true, "DEBUFF_UPTIME")
|
|
end
|
|
return _spell_utility_func (spell, alvo_serial, alvo_name, alvo_flags, who_name, este_jogador, "BUFF_OR_DEBUFF", in_out)
|
|
|
|
end
|
|
|
|
function parser:add_buff_uptime (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname, in_out)
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--early checks and fixes
|
|
|
|
_current_misc_container.need_refresh = true
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--get actors
|
|
local este_jogador = misc_cache [who_name]
|
|
if (not este_jogador) then --pode ser um desconhecido ou um pet
|
|
este_jogador = _current_misc_container:PegarCombatente (who_serial, who_name, who_flags, true)
|
|
misc_cache [who_name] = este_jogador
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--build containers on the fly
|
|
|
|
if (not este_jogador.buff_uptime) then
|
|
este_jogador.buff_uptime = 0
|
|
este_jogador.buff_uptime_spells = container_habilidades:NovoContainer (container_misc)
|
|
este_jogador.buff_uptime_targets = {}
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--add amount
|
|
|
|
--update last event
|
|
este_jogador.last_event = _tempo
|
|
|
|
--actor spells table
|
|
local spell = este_jogador.buff_uptime_spells._ActorTable [spellid]
|
|
if (not spell) then
|
|
spell = este_jogador.buff_uptime_spells:PegaHabilidade (spellid, true, "BUFF_UPTIME")
|
|
end
|
|
return _spell_utility_func (spell, alvo_serial, alvo_name, alvo_flags, who_name, este_jogador, "BUFF_OR_DEBUFF", in_out)
|
|
|
|
end
|
|
|
|
-----------------------------------------------------------------------------------------------------------------------------------------
|
|
--ENERGY serach key: ~energy |
|
|
-----------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
local PowerEnum = Enum and Enum.PowerType
|
|
|
|
local SPELL_POWER_MANA = SPELL_POWER_MANA or (PowerEnum and PowerEnum.Mana) or 0
|
|
local SPELL_POWER_RAGE = SPELL_POWER_RAGE or (PowerEnum and PowerEnum.Rage) or 1
|
|
local SPELL_POWER_FOCUS = SPELL_POWER_FOCUS or (PowerEnum and PowerEnum.Focus) or 2
|
|
local SPELL_POWER_ENERGY = SPELL_POWER_ENERGY or (PowerEnum and PowerEnum.Energy) or 3
|
|
local SPELL_POWER_COMBO_POINTS2 = SPELL_POWER_COMBO_POINTS or (PowerEnum and PowerEnum.ComboPoints) or 4
|
|
local SPELL_POWER_RUNES = SPELL_POWER_RUNES or (PowerEnum and PowerEnum.Runes) or 5
|
|
local SPELL_POWER_RUNIC_POWER = SPELL_POWER_RUNIC_POWER or (PowerEnum and PowerEnum.RunicPower) or 6
|
|
local SPELL_POWER_SOUL_SHARDS = SPELL_POWER_SOUL_SHARDS or (PowerEnum and PowerEnum.SoulShards) or 7
|
|
local SPELL_POWER_LUNAR_POWER = SPELL_POWER_LUNAR_POWER or (PowerEnum and PowerEnum.LunarPower) or 8
|
|
local SPELL_POWER_HOLY_POWER = SPELL_POWER_HOLY_POWER or (PowerEnum and PowerEnum.HolyPower) or 9
|
|
local SPELL_POWER_ALTERNATE_POWER = SPELL_POWER_ALTERNATE_POWER or (PowerEnum and PowerEnum.Alternate) or 10
|
|
local SPELL_POWER_MAELSTROM = SPELL_POWER_MAELSTROM or (PowerEnum and PowerEnum.Maelstrom) or 11
|
|
local SPELL_POWER_CHI = SPELL_POWER_CHI or (PowerEnum and PowerEnum.Chi) or 12
|
|
local SPELL_POWER_INSANITY = SPELL_POWER_INSANITY or (PowerEnum and PowerEnum.Insanity) or 13
|
|
local SPELL_POWER_OBSOLETE = SPELL_POWER_OBSOLETE or (PowerEnum and PowerEnum.Obsolete) or 14
|
|
local SPELL_POWER_OBSOLETE2 = SPELL_POWER_OBSOLETE2 or (PowerEnum and PowerEnum.Obsolete2) or 15
|
|
local SPELL_POWER_ARCANE_CHARGES = SPELL_POWER_ARCANE_CHARGES or (PowerEnum and PowerEnum.ArcaneCharges) or 16
|
|
local SPELL_POWER_FURY = SPELL_POWER_FURY or (PowerEnum and PowerEnum.Fury) or 17
|
|
local SPELL_POWER_PAIN = SPELL_POWER_PAIN or (PowerEnum and PowerEnum.Pain) or 18
|
|
|
|
local energy_types = {
|
|
[SPELL_POWER_MANA] = true,
|
|
[SPELL_POWER_RAGE] = true,
|
|
[SPELL_POWER_ENERGY] = true,
|
|
[SPELL_POWER_RUNIC_POWER] = true,
|
|
}
|
|
|
|
local resource_types = {
|
|
[SPELL_POWER_INSANITY] = true, --shadow priest
|
|
[SPELL_POWER_CHI] = true, --monk
|
|
[SPELL_POWER_HOLY_POWER] = true, --paladins
|
|
[SPELL_POWER_LUNAR_POWER] = true, --balance druids
|
|
[SPELL_POWER_SOUL_SHARDS] = true, --warlock affliction
|
|
[SPELL_POWER_COMBO_POINTS2] = true, --combo points
|
|
[SPELL_POWER_MAELSTROM] = true, --shamans
|
|
[SPELL_POWER_PAIN] = true, --demonhunter tank
|
|
[SPELL_POWER_RUNES] = true, --dk
|
|
[SPELL_POWER_ARCANE_CHARGES] = true, --mage
|
|
[SPELL_POWER_FURY] = true, --warrior demonhunter dps
|
|
}
|
|
|
|
local resource_power_type = {
|
|
[SPELL_POWER_COMBO_POINTS2] = SPELL_POWER_ENERGY, --combo points
|
|
[SPELL_POWER_SOUL_SHARDS] = SPELL_POWER_MANA, --warlock
|
|
[SPELL_POWER_LUNAR_POWER] = SPELL_POWER_MANA, --druid
|
|
[SPELL_POWER_HOLY_POWER] = SPELL_POWER_MANA, --paladin
|
|
[SPELL_POWER_INSANITY] = SPELL_POWER_MANA, --shadowpriest
|
|
[SPELL_POWER_MAELSTROM] = SPELL_POWER_MANA, --shaman
|
|
[SPELL_POWER_CHI] = SPELL_POWER_MANA, --monk
|
|
[SPELL_POWER_PAIN] = SPELL_POWER_ENERGY, --demonhuinter
|
|
[SPELL_POWER_RUNES] = SPELL_POWER_RUNIC_POWER, --dk
|
|
[SPELL_POWER_ARCANE_CHARGES] = SPELL_POWER_MANA, --mage
|
|
[SPELL_POWER_FURY] = SPELL_POWER_RAGE, --warrior
|
|
}
|
|
|
|
_detalhes.resource_strings = {
|
|
[SPELL_POWER_COMBO_POINTS2] = "Combo Point",
|
|
[SPELL_POWER_SOUL_SHARDS] = "Soul Shard",
|
|
[SPELL_POWER_LUNAR_POWER] = "Lunar Power",
|
|
[SPELL_POWER_HOLY_POWER] = "Holy Power",
|
|
[SPELL_POWER_INSANITY] = "Insanity",
|
|
[SPELL_POWER_MAELSTROM] = "Maelstrom",
|
|
[SPELL_POWER_CHI] = "Chi",
|
|
[SPELL_POWER_PAIN] = "Pain",
|
|
[SPELL_POWER_RUNES] = "Runes",
|
|
[SPELL_POWER_ARCANE_CHARGES] = "Arcane Charge",
|
|
[SPELL_POWER_FURY] = "Rage",
|
|
}
|
|
|
|
_detalhes.resource_icons = {
|
|
[SPELL_POWER_COMBO_POINTS2] = {file = [[Interface\PLAYERFRAME\ClassOverlayComboPoints]], coords = {58/128, 74/128, 25/64, 39/64}},
|
|
[SPELL_POWER_SOUL_SHARDS] = {file = [[Interface\PLAYERFRAME\UI-WARLOCKSHARD]], coords = {3/64, 17/64, 2/128, 16/128}},
|
|
[SPELL_POWER_LUNAR_POWER] = {file = [[Interface\PLAYERFRAME\DruidEclipse]], coords = {117/256, 140/256, 83/128, 115/128}},
|
|
[SPELL_POWER_HOLY_POWER] = {file = [[Interface\PLAYERFRAME\PALADINPOWERTEXTURES]], coords = {75/256, 94/256, 87/128, 100/128}},
|
|
[SPELL_POWER_INSANITY] = {file = [[Interface\PLAYERFRAME\Priest-ShadowUI]], coords = {119/256, 150/256, 61/128, 94/128}},
|
|
[SPELL_POWER_MAELSTROM] = {file = [[Interface\PLAYERFRAME\MonkNoPower]], coords = {0, 1, 0, 1}},
|
|
[SPELL_POWER_CHI] = {file = [[Interface\PLAYERFRAME\MonkLightPower]], coords = {0, 1, 0, 1}},
|
|
[SPELL_POWER_PAIN] = {file = [[Interface\PLAYERFRAME\Deathknight-Energize-Blood]], coords = {0, 1, 0, 1}},
|
|
[SPELL_POWER_RUNES] = {file = [[Interface\PLAYERFRAME\UI-PlayerFrame-Deathknight-SingleRune]], coords = {0, 1, 0, 1}},
|
|
[SPELL_POWER_ARCANE_CHARGES] = {file = [[Interface\PLAYERFRAME\MageArcaneCharges]], coords = {68/256, 90/256, 68/128, 91/128}},
|
|
[SPELL_POWER_FURY] = {file = [[Interface\PLAYERFRAME\UI-PlayerFrame-Deathknight-Blood-On]], coords = {0, 1, 0, 1}},
|
|
}
|
|
|
|
local alternatePowerEnableFrame = CreateFrame("frame")
|
|
local alternatePowerMonitorFrame = CreateFrame("frame")
|
|
alternatePowerEnableFrame:RegisterEvent("UNIT_POWER_BAR_SHOW")
|
|
alternatePowerEnableFrame:RegisterEvent("ENCOUNTER_END")
|
|
alternatePowerEnableFrame.IsRunning = false
|
|
|
|
--alternate power will only run when the encounter has a alternate power bar
|
|
alternatePowerEnableFrame:SetScript("OnEvent", function(self, event)
|
|
if (event == "UNIT_POWER_BAR_SHOW") then
|
|
alternatePowerMonitorFrame:RegisterEvent("UNIT_POWER_UPDATE") -- 8.0
|
|
alternatePowerEnableFrame.IsRunning = true
|
|
|
|
elseif (alternatePowerEnableFrame.IsRunning and (event == "ENCOUNTER_END" or event == "PLAYER_REGEN_ENABLED")) then
|
|
alternatePowerMonitorFrame:UnregisterEvent("UNIT_POWER_UPDATE")
|
|
alternatePowerEnableFrame.IsRunning = false
|
|
end
|
|
end)
|
|
|
|
local onUnitPowerUpdate = function(self, event, unitID, powerType)
|
|
if (powerType == "ALTERNATE") then
|
|
local actorName = _detalhes:GetCLName(unitID)
|
|
if (actorName) then
|
|
local power = _current_combat.alternate_power[actorName]
|
|
if (not power) then
|
|
power = _current_combat:CreateAlternatePowerTable(actorName)
|
|
end
|
|
|
|
local currentPower = UnitPower(unitID, 10)
|
|
if (currentPower and currentPower > power.last) then
|
|
local addPower = currentPower - power.last
|
|
power.total = power.total + addPower
|
|
|
|
--main actor
|
|
local actorObject = energy_cache[actorName]
|
|
if (not actorObject) then
|
|
--as alternate power bars does not trigger for pets, this is guaranteed to be a player actor
|
|
actorObject = _current_energy_container:PegarCombatente(UnitGUID(unitID), actorName, 0x514, true)
|
|
energy_cache[actorName] = actorObject
|
|
end
|
|
|
|
actorObject.alternatepower = actorObject.alternatepower + addPower
|
|
_current_energy_container.need_refresh = true
|
|
end
|
|
|
|
power.last = currentPower or 0
|
|
end
|
|
end
|
|
end
|
|
|
|
alternatePowerMonitorFrame:SetScript("OnEvent", onUnitPowerUpdate)
|
|
|
|
---this function captures when the energy of a unit is at its max capacity on classes which auto regenerates it's power such like Rogues
|
|
---staying at max capacity prevents it to generate more energy and causes a power overflow
|
|
local regen_power_overflow_check = function()
|
|
if (not _in_combat) then
|
|
return
|
|
end
|
|
|
|
for playerName, powerType in pairs(auto_regen_cache) do
|
|
local currentPower = UnitPower(playerName, powerType) or 0
|
|
local maxPower = UnitPowerMax(playerName, powerType) or 1
|
|
|
|
if (currentPower == maxPower) then
|
|
--power overflow
|
|
local energyObject = energy_cache[playerName]
|
|
if (energyObject) then
|
|
energyObject.passiveover = energyObject.passiveover + AUTO_REGEN_PRECISION
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- ~energy ~resource
|
|
function parser:energize (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname, spelltype, amount, overpower, powertype, altpower)
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--early checks and fixes
|
|
if (not who_name) then
|
|
who_name = "[*] "..spellname
|
|
elseif (not alvo_name) then
|
|
return
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--check if is energy or resource
|
|
|
|
--Details:Dump({token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname, spelltype, amount, overpower, powertype, altpower})
|
|
|
|
--get resource type
|
|
local is_resource, resource_amount, resource_id = resource_power_type [powertype], amount, powertype
|
|
|
|
--check if is valid
|
|
if (not energy_types [powertype] and not is_resource) then
|
|
return
|
|
|
|
elseif (is_resource) then
|
|
powertype = is_resource
|
|
amount = 0
|
|
end
|
|
|
|
overpower = overpower or 0
|
|
|
|
--[[statistics]]-- _detalhes.statistics.energy_calls = _detalhes.statistics.energy_calls + 1
|
|
|
|
_current_energy_container.need_refresh = true
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--get actors
|
|
|
|
--main actor
|
|
local este_jogador, meu_dono = energy_cache [who_name] --meu_dono is always nil
|
|
if (not este_jogador) then --pode ser um desconhecido ou um pet
|
|
este_jogador, meu_dono, who_name = _current_energy_container:PegarCombatente (who_serial, who_name, who_flags, true)
|
|
este_jogador.powertype = powertype
|
|
if (meu_dono) then
|
|
meu_dono.powertype = powertype
|
|
end
|
|
if (not meu_dono) then --se n�o for um pet, adicionar no cache
|
|
--does pet generates energy to its owner in any circustance?
|
|
energy_cache [who_name] = este_jogador
|
|
end
|
|
end
|
|
|
|
if (not este_jogador.powertype) then
|
|
este_jogador.powertype = powertype
|
|
end
|
|
|
|
--target
|
|
local jogador_alvo, alvo_dono = energy_cache [alvo_name]
|
|
if (not jogador_alvo) then
|
|
jogador_alvo, alvo_dono, alvo_name = _current_energy_container:PegarCombatente (alvo_serial, alvo_name, alvo_flags, true)
|
|
jogador_alvo.powertype = powertype
|
|
if (alvo_dono) then
|
|
alvo_dono.powertype = powertype
|
|
end
|
|
if (not alvo_dono) then
|
|
energy_cache [alvo_name] = jogador_alvo
|
|
end
|
|
end
|
|
|
|
if (jogador_alvo.powertype ~= este_jogador.powertype) then
|
|
--print("error: different power types: who -> ", este_jogador.powertype, " target -> ", jogador_alvo.powertype)
|
|
return
|
|
end
|
|
|
|
este_jogador.last_event = _tempo
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--amount add
|
|
|
|
if (not is_resource) then
|
|
|
|
--amount = amount - overpower
|
|
|
|
--add to targets
|
|
este_jogador.targets [alvo_name] = (este_jogador.targets [alvo_name] or 0) + amount
|
|
|
|
--add to combat total
|
|
_current_total [3] [powertype] = _current_total [3] [powertype] + amount
|
|
|
|
if (este_jogador.grupo) then
|
|
_current_gtotal [3] [powertype] = _current_gtotal [3] [powertype] + amount
|
|
end
|
|
|
|
--regen produced amount
|
|
este_jogador.total = este_jogador.total + amount
|
|
este_jogador.totalover = este_jogador.totalover + overpower
|
|
|
|
--target regenerated amount
|
|
jogador_alvo.received = jogador_alvo.received + amount
|
|
|
|
--owner
|
|
if (meu_dono) then
|
|
meu_dono.total = meu_dono.total + amount
|
|
end
|
|
|
|
--actor spells table
|
|
local spellTable = este_jogador.spells._ActorTable[spellid]
|
|
if (not spellTable) then
|
|
spellTable = este_jogador.spells:PegaHabilidade(spellid, true, token)
|
|
end
|
|
|
|
--return spell:Add (alvo_serial, alvo_name, alvo_flags, amount, who_name, powertype)
|
|
return _spell_energy_func (spellTable, alvo_serial, alvo_name, alvo_flags, amount, who_name, powertype, overpower)
|
|
else
|
|
--is a resource
|
|
este_jogador.resource = este_jogador.resource + resource_amount
|
|
este_jogador.resource_type = resource_id
|
|
end
|
|
end
|
|
|
|
|
|
|
|
-----------------------------------------------------------------------------------------------------------------------------------------
|
|
--MISC search key: ~cooldown |
|
|
-----------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function parser:add_defensive_cooldown(token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, targetFlags2, spellId, spellName)
|
|
------------------------------------------------------------------------------------------------
|
|
--early checks and fixes
|
|
|
|
_current_misc_container.need_refresh = true
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--get actors
|
|
|
|
--main actor
|
|
local sourceActor, ownerActor = misc_cache[sourceName], nil
|
|
if (not sourceActor) then
|
|
sourceActor, ownerActor, sourceName = _current_misc_container:PegarCombatente(sourceSerial, sourceName, sourceFlags, true)
|
|
if (not ownerActor) then
|
|
misc_cache[sourceName] = sourceActor
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--build containers on the fly
|
|
if (not sourceActor.cooldowns_defensive) then
|
|
sourceActor.cooldowns_defensive = _detalhes:GetOrderNumber(sourceName)
|
|
sourceActor.cooldowns_defensive_targets = {}
|
|
sourceActor.cooldowns_defensive_spells = container_habilidades:NovoContainer(container_misc)
|
|
end
|
|
|
|
--local targetActor, targetOwner = damage_cache[targetSerial] or damage_cache_pets[targetSerial] or damage_cache[targetName], damage_cache_petsOwners[targetSerial]
|
|
--sourceActor, ownerActor, sourceName
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--add amount
|
|
|
|
--actor cooldowns used
|
|
sourceActor.cooldowns_defensive = sourceActor.cooldowns_defensive + 1
|
|
|
|
--combat totals
|
|
_current_total[4].cooldowns_defensive = _current_total[4].cooldowns_defensive + 1
|
|
|
|
if (sourceActor.grupo) then
|
|
_current_gtotal[4].cooldowns_defensive = _current_gtotal[4].cooldowns_defensive + 1
|
|
|
|
if (sourceName == targetName) then
|
|
--[=[
|
|
local damage_actor = damage_cache[sourceSerial]
|
|
if (not damage_actor) then
|
|
damage_actor = _current_damage_container:PegarCombatente(sourceSerial, sourceName, sourceFlags, true)
|
|
if (sourceFlags) then
|
|
damage_cache[sourceSerial] = damage_actor
|
|
end
|
|
end
|
|
--]=]
|
|
|
|
--last events
|
|
local t = last_events_cache[sourceName]
|
|
|
|
if (not t) then
|
|
t = _current_combat:CreateLastEventsTable(sourceName)
|
|
end
|
|
|
|
local i = t.n
|
|
local thisEvent = t [i]
|
|
|
|
thisEvent[1] = 1 --true if this is a damage || false for healing || 1 for cooldown
|
|
thisEvent[2] = spellId --spellid || false if this is a battle ress line
|
|
thisEvent[3] = 1 --amount of damage or healing
|
|
thisEvent[4] = time
|
|
thisEvent[5] = UnitHealth(sourceName)
|
|
thisEvent[6] = sourceName
|
|
|
|
i = i + 1
|
|
if (i == _amount_of_last_events+1) then
|
|
t.n = 1
|
|
else
|
|
t.n = i
|
|
end
|
|
|
|
sourceActor.last_cooldown = {time, spellId}
|
|
end
|
|
end
|
|
|
|
--update last event
|
|
sourceActor.last_event = _tempo
|
|
|
|
--actor targets
|
|
sourceActor.cooldowns_defensive_targets[targetName] = (sourceActor.cooldowns_defensive_targets [targetName] or 0) + 1
|
|
|
|
--actor spells table
|
|
local spellTable = sourceActor.cooldowns_defensive_spells._ActorTable[spellId]
|
|
if (not spellTable) then
|
|
spellTable = sourceActor.cooldowns_defensive_spells:PegaHabilidade(spellId, true, token)
|
|
end
|
|
|
|
if (_hook_cooldowns) then
|
|
--send event to registred functions
|
|
for i = 1, #_hook_cooldowns_container do
|
|
local successful, errorText = pcall(_hook_cooldowns_container[i], nil, token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, spellId, spellName)
|
|
if (not successful) then
|
|
_detalhes:Msg("error occurred on a cooldown hook function:", errorText)
|
|
end
|
|
end
|
|
end
|
|
|
|
return _spell_utility_func(spellTable, targetSerial, targetName, targetFlags, sourceName, token, "BUFF_OR_DEBUFF", "COOLDOWN")
|
|
end
|
|
|
|
--serach key: ~interrupts
|
|
---comment: this function is called when a spell is interrupted
|
|
---@param token string
|
|
---@param time number
|
|
---@param sourceSerial string
|
|
---@param sourceName string
|
|
---@param sourceFlags number
|
|
---@param targetSerial string
|
|
---@param targetName string
|
|
---@param targetFlags number
|
|
---@param targetFlags2 number
|
|
---@param spellId number
|
|
---@param spellName string
|
|
---@param spellType number
|
|
---@param extraSpellID number
|
|
---@param extraSpellName string
|
|
---@param extraSchool number
|
|
function parser:interrupt(token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, targetFlags2, spellId, spellName, spellType, extraSpellID, extraSpellName, extraSchool)
|
|
--quake affix from mythic+
|
|
if (spellId == 240448) then
|
|
return
|
|
end
|
|
|
|
if (not sourceName) then
|
|
sourceName = "[*] "..spellName
|
|
|
|
elseif (not targetName) then
|
|
return
|
|
end
|
|
|
|
_current_misc_container.need_refresh = true
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--get actors
|
|
--main actor
|
|
local sourceActor, ownerActor = misc_cache[sourceName], nil
|
|
if (not sourceActor) then
|
|
sourceActor, ownerActor, sourceName = _current_misc_container:PegarCombatente(sourceSerial, sourceName, sourceFlags, true)
|
|
if (not ownerActor) then
|
|
misc_cache[sourceName] = sourceActor
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--build containers on the fly
|
|
if (not sourceActor.interrupt) then
|
|
sourceActor.interrupt = _detalhes:GetOrderNumber(sourceName)
|
|
sourceActor.interrupt_targets = {}
|
|
sourceActor.interrupt_spells = container_habilidades:NovoContainer(container_misc)
|
|
sourceActor.interrompeu_oque = {}
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--add amount
|
|
|
|
--actor interrupt amount
|
|
sourceActor.interrupt = sourceActor.interrupt + 1
|
|
|
|
--combat totals
|
|
_current_total[4].interrupt = _current_total[4].interrupt + 1
|
|
|
|
if (sourceActor.grupo) then
|
|
_current_gtotal[4].interrupt = _current_gtotal[4].interrupt + 1
|
|
end
|
|
|
|
--update last event
|
|
sourceActor.last_event = _tempo
|
|
|
|
--spells interrupted
|
|
sourceActor.interrompeu_oque[extraSpellID] = (sourceActor.interrompeu_oque[extraSpellID] or 0) + 1
|
|
|
|
--actor targets
|
|
sourceActor.interrupt_targets[targetName] = (sourceActor.interrupt_targets[targetName] or 0) + 1
|
|
|
|
--actor spells table
|
|
local spell = sourceActor.interrupt_spells._ActorTable[spellId]
|
|
if (not spell) then
|
|
spell = sourceActor.interrupt_spells:PegaHabilidade(spellId, true, token)
|
|
end
|
|
_spell_utility_func(spell, targetSerial, targetName, targetFlags, sourceName, token, extraSpellID, extraSpellName)
|
|
|
|
--verifica se tem dono e adiciona o interrupt para o dono
|
|
if (ownerActor) then
|
|
if (not ownerActor.interrupt) then
|
|
ownerActor.interrupt = _detalhes:GetOrderNumber(sourceName)
|
|
ownerActor.interrupt_targets = {}
|
|
ownerActor.interrupt_spells = container_habilidades:NovoContainer(container_misc)
|
|
ownerActor.interrompeu_oque = {}
|
|
end
|
|
|
|
-- adiciona ao total
|
|
ownerActor.interrupt = ownerActor.interrupt + 1
|
|
|
|
-- adiciona aos alvos
|
|
ownerActor.interrupt_targets[targetName] = (ownerActor.interrupt_targets[targetName] or 0) + 1
|
|
|
|
-- update last event
|
|
ownerActor.last_event = _tempo
|
|
|
|
-- spells interrupted
|
|
ownerActor.interrompeu_oque[extraSpellID] = (ownerActor.interrompeu_oque[extraSpellID] or 0) + 1
|
|
|
|
--pet interrupt
|
|
if (_hook_interrupt) then
|
|
for _, func in ipairs(_hook_interrupt_container) do
|
|
func(nil, token, time, ownerActor.serial, ownerActor.nome, ownerActor.flag_original, targetSerial, targetName, targetFlags, spellId, spellName, spellType, extraSpellID, extraSpellName, extraSchool)
|
|
end
|
|
end
|
|
else
|
|
--player interrupt
|
|
if (_hook_interrupt) then
|
|
for _, func in ipairs(_hook_interrupt_container) do
|
|
func(nil, token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, spellId, spellName, spellType, extraSpellID, extraSpellName, extraSchool)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--search key: ~spellcast ~castspell ~cast
|
|
function parser:spellcast (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname, spelltype)
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--early checks and fixes
|
|
|
|
--only capture if is in combat
|
|
if (not _in_combat) then
|
|
return
|
|
end
|
|
|
|
if (not who_name) then
|
|
who_name = "[*] " .. spellname
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--get actors
|
|
|
|
--main actor
|
|
|
|
local este_jogador, meu_dono = misc_cache [who_serial] or misc_cache_pets [who_serial] or misc_cache [who_name], misc_cache_petsOwners [who_serial]
|
|
--local este_jogador = misc_cache [who_name]
|
|
|
|
if (not este_jogador) then
|
|
|
|
este_jogador, meu_dono, who_name = _current_misc_container:PegarCombatente (who_serial, who_name, who_flags, true)
|
|
|
|
if (meu_dono) then --� um pet
|
|
if (who_serial ~= "") then
|
|
misc_cache_pets [who_serial] = este_jogador
|
|
misc_cache_petsOwners [who_serial] = meu_dono
|
|
end
|
|
|
|
--conferir se o dono j� esta no cache
|
|
if (not misc_cache [meu_dono.serial] and meu_dono.serial ~= "") then
|
|
misc_cache [meu_dono.serial] = meu_dono
|
|
end
|
|
else
|
|
if (who_flags) then
|
|
misc_cache [who_name] = este_jogador
|
|
end
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--build containers on the fly
|
|
local spell_cast = este_jogador.spell_cast
|
|
if (not spell_cast) then
|
|
este_jogador.spell_cast = {[spellid] = 1}
|
|
else
|
|
spell_cast [spellid] = (spell_cast [spellid] or 0) + 1
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--record cooldowns cast which can't track with buff applyed.
|
|
|
|
--foi um jogador que castou
|
|
if (raid_members_cache [who_serial]) then
|
|
--check if is a cooldown :D
|
|
if (defensive_cooldowns [spellid]) then
|
|
--usou cooldown
|
|
if (not alvo_name) then
|
|
if (DetailsFramework.CooldownsDeffense [spellid]) then
|
|
alvo_name = who_name
|
|
|
|
elseif (DetailsFramework.CooldownsRaid [spellid]) then
|
|
alvo_name = Loc ["STRING_RAID_WIDE"]
|
|
|
|
else
|
|
alvo_name = "--x--x--"
|
|
end
|
|
end
|
|
return parser:add_defensive_cooldown (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname)
|
|
end
|
|
|
|
else
|
|
--enemy successful casts (not interrupted)
|
|
if (bitBand(who_flags, 0x00000040) ~= 0 and who_name) then --byte 2 = 4 (enemy)
|
|
--damager
|
|
local este_jogador = damage_cache [who_serial]
|
|
if (not este_jogador) then
|
|
este_jogador = _current_damage_container:PegarCombatente (who_serial, who_name, who_flags, true)
|
|
end
|
|
|
|
if (este_jogador) then
|
|
--actor spells table
|
|
local spell = este_jogador.spells._ActorTable [spellid] --line where the actor was nil
|
|
if (not spell) then
|
|
spell = este_jogador.spells:PegaHabilidade (spellid, true, token)
|
|
end
|
|
spell.successful_casted = spell.successful_casted + 1
|
|
end
|
|
|
|
--add the spellId in the enemy_cast_cache table to store the time the enemy successfully cast a spell
|
|
--check if the spell is in the table
|
|
local enemyName = who_name
|
|
|
|
if (not enemy_cast_cache[time]) then
|
|
enemy_cast_cache[time] = {enemyName, spellid, 1}
|
|
else
|
|
enemy_cast_cache[time][3] = enemy_cast_cache[time][3] + 1
|
|
end
|
|
end
|
|
return
|
|
end
|
|
end
|
|
|
|
|
|
--serach key: ~dispell
|
|
function parser:dispell (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname, spelltype, extraSpellID, extraSpellName, extraSchool, auraType)
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--early checks and fixes
|
|
|
|
--esta dando erro onde o nome � NIL, fazendo um fix para isso
|
|
if (not who_name) then
|
|
who_name = "[*] "..extraSpellName
|
|
end
|
|
if (not alvo_name) then
|
|
alvo_name = "[*] "..spellid
|
|
end
|
|
|
|
_current_misc_container.need_refresh = true
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--get actors]
|
|
local este_jogador, meu_dono = misc_cache [who_name]
|
|
if (not este_jogador) then --pode ser um desconhecido ou um pet
|
|
este_jogador, meu_dono, who_name = _current_misc_container:PegarCombatente (who_serial, who_name, who_flags, true)
|
|
if (not meu_dono) then --se n�o for um pet, adicionar no cache
|
|
misc_cache [who_name] = este_jogador
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--build containers on the fly
|
|
|
|
if (not este_jogador.dispell) then
|
|
--constr�i aqui a tabela dele
|
|
este_jogador.dispell = _detalhes:GetOrderNumber(who_name)
|
|
este_jogador.dispell_targets = {}
|
|
este_jogador.dispell_spells = container_habilidades:NovoContainer (container_misc)
|
|
este_jogador.dispell_oque = {}
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--spell reflection
|
|
if (reflection_dispelid[spellid]) then
|
|
--this aura could've been reflected to the caster after the dispel
|
|
--save data about whom was dispelled by who and what spell it was
|
|
reflection_dispels[alvo_serial] = reflection_dispels[alvo_serial] or {}
|
|
reflection_dispels[alvo_serial][extraSpellID] = {
|
|
who_serial = who_serial,
|
|
who_name = who_name,
|
|
who_flags = who_flags,
|
|
spellid = spellid,
|
|
spellname = spellname,
|
|
spelltype = spelltype,
|
|
}
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--add amount
|
|
|
|
--last event update
|
|
este_jogador.last_event = _tempo
|
|
|
|
--total dispells in combat
|
|
_current_total [4].dispell = _current_total [4].dispell + 1
|
|
|
|
if (este_jogador.grupo) then
|
|
_current_gtotal [4].dispell = _current_gtotal [4].dispell + 1
|
|
end
|
|
|
|
--actor dispell amount
|
|
este_jogador.dispell = este_jogador.dispell + 1
|
|
|
|
--dispell what
|
|
if (extraSpellID) then
|
|
este_jogador.dispell_oque [extraSpellID] = (este_jogador.dispell_oque [extraSpellID] or 0) + 1
|
|
end
|
|
|
|
--actor targets
|
|
este_jogador.dispell_targets [alvo_name] = (este_jogador.dispell_targets [alvo_name] or 0) + 1
|
|
|
|
--actor spells table
|
|
local spell = este_jogador.dispell_spells._ActorTable [spellid]
|
|
if (not spell) then
|
|
spell = este_jogador.dispell_spells:PegaHabilidade (spellid, true, token)
|
|
end
|
|
_spell_utility_func (spell, alvo_serial, alvo_name, alvo_flags, who_name, token, extraSpellID, extraSpellName)
|
|
|
|
--verifica se tem dono e adiciona o interrupt para o dono
|
|
if (meu_dono) then
|
|
if (not meu_dono.dispell) then
|
|
meu_dono.dispell = _detalhes:GetOrderNumber(who_name)
|
|
meu_dono.dispell_targets = {}
|
|
meu_dono.dispell_spells = container_habilidades:NovoContainer (container_misc)
|
|
meu_dono.dispell_oque = {}
|
|
end
|
|
|
|
meu_dono.dispell = meu_dono.dispell + 1
|
|
|
|
meu_dono.dispell_targets [alvo_name] = (meu_dono.dispell_targets [alvo_name] or 0) + 1
|
|
|
|
meu_dono.last_event = _tempo
|
|
|
|
if (extraSpellID) then
|
|
meu_dono.dispell_oque [extraSpellID] = (meu_dono.dispell_oque [extraSpellID] or 0) + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
--serach key: ~ress
|
|
function parser:ress (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname)
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--early checks and fixes
|
|
|
|
if (bitBand(who_flags, AFFILIATION_GROUP) == 0) then
|
|
return
|
|
end
|
|
|
|
--do not register ress if not in combat
|
|
if (not Details.in_combat) then
|
|
return
|
|
end
|
|
|
|
_current_misc_container.need_refresh = true
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--get actors
|
|
|
|
--main actor
|
|
local este_jogador, meu_dono = misc_cache [who_name]
|
|
if (not este_jogador) then --pode ser um desconhecido ou um pet
|
|
este_jogador, meu_dono, who_name = _current_misc_container:PegarCombatente (who_serial, who_name, who_flags, true)
|
|
if (not meu_dono) then --se n�o for um pet, adicionar no cache
|
|
misc_cache [who_name] = este_jogador
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--build containers on the fly
|
|
|
|
if (not este_jogador.ress) then
|
|
este_jogador.ress = _detalhes:GetOrderNumber(who_name)
|
|
este_jogador.ress_targets = {}
|
|
este_jogador.ress_spells = container_habilidades:NovoContainer (container_misc) --cria o container das habilidades usadas para interromper
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--add amount
|
|
|
|
--update last event
|
|
este_jogador.last_event = _tempo
|
|
|
|
--combat ress total
|
|
_current_total [4].ress = _current_total [4].ress + 1
|
|
|
|
if (este_jogador.grupo) then
|
|
_current_combat.totals_grupo[4].ress = _current_combat.totals_grupo[4].ress+1
|
|
end
|
|
|
|
--add ress amount
|
|
este_jogador.ress = este_jogador.ress + 1
|
|
|
|
--add battle ress
|
|
if (UnitAffectingCombat(who_name)) then
|
|
--procura a �ltima morte do alvo na tabela do combate:
|
|
for i = 1, #_current_combat.last_events_tables do
|
|
if (_current_combat.last_events_tables [i] [3] == alvo_name) then
|
|
|
|
local deadLog = _current_combat.last_events_tables [i] [1]
|
|
local jaTem = false
|
|
for _, evento in ipairs(deadLog) do
|
|
if (evento [1] and not evento[3]) then
|
|
jaTem = true
|
|
end
|
|
end
|
|
|
|
if (not jaTem) then
|
|
tinsert(_current_combat.last_events_tables [i] [1], 1, {
|
|
2,
|
|
spellid,
|
|
1,
|
|
time,
|
|
UnitHealth (alvo_name),
|
|
who_name
|
|
})
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
if (_hook_battleress) then
|
|
for _, func in ipairs(_hook_battleress_container) do
|
|
func (nil, token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname)
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
--actor targets
|
|
este_jogador.ress_targets [alvo_name] = (este_jogador.ress_targets [alvo_name] or 0) + 1
|
|
|
|
--actor spells table
|
|
local spell = este_jogador.ress_spells._ActorTable [spellid]
|
|
if (not spell) then
|
|
spell = este_jogador.ress_spells:PegaHabilidade (spellid, true, token)
|
|
end
|
|
return _spell_utility_func (spell, alvo_serial, alvo_name, alvo_flags, who_name, token, extraSpellID, extraSpellName)
|
|
end
|
|
|
|
--serach key: ~cc
|
|
function parser:break_cc (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname, spelltype, extraSpellID, extraSpellName, extraSchool, auraType)
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--early checks and fixes
|
|
if (not cc_spell_list [spellid]) then
|
|
return
|
|
--print("NO CC:", spellid, spellname, extraSpellID, extraSpellName)
|
|
end
|
|
|
|
if (bitBand(who_flags, AFFILIATION_GROUP) == 0) then
|
|
return
|
|
end
|
|
|
|
if (not spellname) then
|
|
spellname = "Melee"
|
|
end
|
|
|
|
if (not alvo_name) then
|
|
--no target name, just quit
|
|
return
|
|
|
|
elseif (not who_name) then
|
|
--no actor name, use spell name instead
|
|
who_name = "[*] " .. spellname
|
|
who_flags = 0xa48
|
|
who_serial = ""
|
|
end
|
|
|
|
_current_misc_container.need_refresh = true
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--get actors
|
|
|
|
local este_jogador, meu_dono = misc_cache [who_name]
|
|
if (not este_jogador) then --pode ser um desconhecido ou um pet
|
|
este_jogador, meu_dono, who_name = _current_misc_container:PegarCombatente (who_serial, who_name, who_flags, true)
|
|
if (not meu_dono) then --se n�o for um pet, adicionar no cache
|
|
misc_cache [who_name] = este_jogador
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--build containers on the fly
|
|
|
|
if (not este_jogador.cc_break) then
|
|
--constr�i aqui a tabela dele
|
|
este_jogador.cc_break = _detalhes:GetOrderNumber(who_name)
|
|
este_jogador.cc_break_targets = {}
|
|
este_jogador.cc_break_spells = container_habilidades:NovoContainer (container_misc)
|
|
este_jogador.cc_break_oque = {}
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--add amount
|
|
|
|
--update last event
|
|
este_jogador.last_event = _tempo
|
|
|
|
--combat cc break total
|
|
_current_total [4].cc_break = _current_total [4].cc_break + 1
|
|
|
|
if (este_jogador.grupo) then
|
|
_current_combat.totals_grupo[4].cc_break = _current_combat.totals_grupo[4].cc_break+1
|
|
end
|
|
|
|
--add amount
|
|
este_jogador.cc_break = este_jogador.cc_break + 1
|
|
|
|
--broke what
|
|
este_jogador.cc_break_oque [spellid] = (este_jogador.cc_break_oque [spellid] or 0) + 1
|
|
|
|
--actor targets
|
|
este_jogador.cc_break_targets [alvo_name] = (este_jogador.cc_break_targets [alvo_name] or 0) + 1
|
|
|
|
--actor spells table
|
|
local spell = este_jogador.cc_break_spells._ActorTable [extraSpellID]
|
|
if (not spell) then
|
|
spell = este_jogador.cc_break_spells:PegaHabilidade (extraSpellID, true, token)
|
|
end
|
|
return _spell_utility_func (spell, alvo_serial, alvo_name, alvo_flags, who_name, token, spellid, spellname)
|
|
end
|
|
|
|
--serach key: ~dead ~death ~morte
|
|
---when a player dies, save the events that lead to his death
|
|
---this is used to show the last events before the player died under the Deaths display
|
|
---the first index of the table which hold a single event tells the type of event happened, there are the types:
|
|
---boolean true: the player took damage
|
|
---boolean false: the player received heal from someone
|
|
---number 1: the player used a cooldown
|
|
---number 2: the player received a battle res
|
|
---number 3: tell which was the latest cooldown used by the player
|
|
---number 4: debuff the player received
|
|
---number 5: buff the player received
|
|
---number 6: emeny casted a spell
|
|
---@param token string
|
|
---@param time number
|
|
---@param sourceSerial string
|
|
---@param sourceName string
|
|
---@param sourceFlags number
|
|
---@param targetSerial string
|
|
---@param targetName string
|
|
---@param targetFlags number
|
|
function parser:dead (token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags)
|
|
--early checks and fixes
|
|
if (not targetName) then
|
|
return
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------
|
|
--build dead
|
|
|
|
local damageActor = _current_damage_container:GetActor(targetName)
|
|
--check for outsiders
|
|
if (_in_combat and targetFlags and (not damageActor or (bitBand(targetFlags, 0x00000008) ~= 0 and not damageActor.grupo))) then
|
|
--frags
|
|
if (_detalhes.only_pvp_frags and (bitBand(targetFlags, 0x00000400) == 0 or (bitBand(targetFlags, 0x00000040) == 0 and bitBand(targetFlags, 0x00000020) == 0))) then --byte 2 = 4 (HOSTILE) byte 3 = 4 (OBJECT_TYPE_PLAYER)
|
|
return
|
|
end
|
|
|
|
if (not _current_combat.frags [targetName]) then
|
|
_current_combat.frags [targetName] = 1
|
|
else
|
|
_current_combat.frags [targetName] = _current_combat.frags [targetName] + 1
|
|
end
|
|
|
|
_current_combat.frags_need_refresh = true
|
|
|
|
--player death
|
|
elseif (not UnitIsFeignDeath(targetName)) then
|
|
if (
|
|
--player in your group
|
|
(bitBand(targetFlags, AFFILIATION_GROUP) ~= 0 or (damageActor and damageActor.grupo)) and
|
|
--must be a player
|
|
bitBand(targetFlags, OBJECT_TYPE_PLAYER) ~= 0 and
|
|
--must be in combat
|
|
_in_combat
|
|
) then
|
|
if (ignore_death_cache[targetName]) then
|
|
ignore_death_cache[targetName] = nil
|
|
return
|
|
end
|
|
|
|
local bIsMythicRun = false
|
|
--check if this is a mythic+ run for overall deaths
|
|
local mythicLevel = C_ChallengeMode and C_ChallengeMode.GetActiveKeystoneInfo() --classic wow doesn't not have C_ChallengeMode API
|
|
if (mythicLevel and type(mythicLevel) == "number" and mythicLevel >= 2) then --several checks to be future proof
|
|
bIsMythicRun = true
|
|
end
|
|
|
|
_current_misc_container.need_refresh = true
|
|
|
|
--combat totals
|
|
_current_total [4].dead = _current_total [4].dead + 1
|
|
_current_gtotal [4].dead = _current_gtotal [4].dead + 1
|
|
|
|
--main actor no container de misc que ir� armazenar a morte
|
|
local thisPlayer, meu_dono = misc_cache [targetName]
|
|
if (not thisPlayer) then --pode ser um desconhecido ou um pet
|
|
thisPlayer, meu_dono, sourceName = _current_misc_container:PegarCombatente (targetSerial, targetName, targetFlags, true)
|
|
if (not meu_dono) then --se n�o for um pet, adicionar no cache
|
|
misc_cache [targetName] = thisPlayer
|
|
end
|
|
end
|
|
|
|
--table where the events will be placed in order, other events will also be added, for example, the last cooldown used by the player
|
|
local eventsBeforePlayerDeath = {}
|
|
|
|
--get the table where is registered the last events before the player died
|
|
local recordedEvents = last_events_cache[targetName]
|
|
if (not recordedEvents) then
|
|
recordedEvents = _current_combat:CreateLastEventsTable(targetName)
|
|
end
|
|
|
|
--during a regular combat, 99.9% of the events aren't used by the death log
|
|
--hence the process of getting data for the death log is made as fast as it can be
|
|
--when a death occurs, the death log data is then parsed and built, the next 200 lines does this processing
|
|
|
|
--lesses index = older / higher index = newer
|
|
|
|
--[=[
|
|
eventTable [1] = type of the event
|
|
eventTable [2] = spellId --spellid or false if this is a battle ress event
|
|
eventTable [3] = amount --amount of damage or healing
|
|
eventTable [4] = time --unix time
|
|
eventTable [5] = player health when the event happened
|
|
eventTable [6] = name of the actor which caused this event
|
|
eventTable [7] = absorbed
|
|
eventTable [8] = spell school
|
|
eventTable [9] = friendly fire
|
|
eventTable [10] = amount of overkill damage
|
|
--]=]
|
|
|
|
--get the index of the last event recorded
|
|
local lastIndex = recordedEvents.n
|
|
|
|
if (lastIndex < _amount_of_last_events+1 and not recordedEvents[lastIndex][4]) then
|
|
--the last events table amount of indexes is less than the amount of events to store
|
|
for i = 1, lastIndex-1 do
|
|
if (recordedEvents[i][4] and recordedEvents[i][4]+_amount_of_last_events > time) then
|
|
tinsert(eventsBeforePlayerDeath, recordedEvents[i])
|
|
end
|
|
end
|
|
else
|
|
--go from the index where the last event was stored to the end of the table
|
|
for i = lastIndex, _amount_of_last_events do
|
|
if (recordedEvents[i][4] and recordedEvents[i][4]+_amount_of_last_events > time) then
|
|
tinsert(eventsBeforePlayerDeath, recordedEvents[i])
|
|
end
|
|
end
|
|
|
|
--go from the start of the table to the index where the last event minus 1 was stored
|
|
for i = 1, lastIndex-1 do
|
|
if (recordedEvents[i][4] and recordedEvents[i][4]+_amount_of_last_events > time) then
|
|
tinsert(eventsBeforePlayerDeath, recordedEvents[i])
|
|
end
|
|
end
|
|
end
|
|
|
|
local bHadDeathEvent = false
|
|
local firstEventTime
|
|
local lastEventTime
|
|
|
|
if (eventsBeforePlayerDeath[1]) then
|
|
bHadDeathEvent = true
|
|
firstEventTime = eventsBeforePlayerDeath[1][4]
|
|
lastEventTime = eventsBeforePlayerDeath[#eventsBeforePlayerDeath][4]
|
|
end
|
|
|
|
--enemy_cast_cache store the time of the event as key and a table as value
|
|
--the value has [1] = enemyName, [2] = spellid, [3] = amount of casts on that time (in case many enemies casted the same spell at the same time)
|
|
--enemy_cast_cache[time] = {enemyName, spellId, 1}
|
|
local enemyCastCache = enemy_cast_cache
|
|
|
|
--as multiple enemies can have casted the same spell at the same time, iterate over the enemyCastCache and merge the casts that happened really close to each other
|
|
--transfer the casts that happened within the the events window of the player death to a new indexed table
|
|
local enemyCastCacheIndexed = {}
|
|
if (bHadDeathEvent) then
|
|
for time, enemyCastTable in pairs(enemyCastCache) do
|
|
if (time >= firstEventTime and time <= lastEventTime) then
|
|
enemyCastCacheIndexed[#enemyCastCacheIndexed+1] = {time, unpack(enemyCastTable)} --time, enemyName, spellId, amount of casts
|
|
end
|
|
end
|
|
end
|
|
|
|
--sort enemy casts events to place earlier casts in the first indexes of the table
|
|
table.sort(enemyCastCacheIndexed, function(t1, t2) return t1[1] < t2[1] end)
|
|
|
|
--iterate among the enemy cast events and remove cast events that are too close to each other
|
|
for i = #enemyCastCacheIndexed, 1, -1 do
|
|
local previousEnemyCastEvent = enemyCastCacheIndexed[i-1]
|
|
if (previousEnemyCastEvent) then
|
|
local nextEnemyCastEvent = enemyCastCacheIndexed[i]
|
|
if (previousEnemyCastEvent[1]+0.1 > nextEnemyCastEvent[1]) then
|
|
if (previousEnemyCastEvent[3] == nextEnemyCastEvent[3]) then
|
|
enemyCastCacheIndexed[i] = nil
|
|
--as the event got removed, add a cast event to the previous event
|
|
previousEnemyCastEvent[4] = previousEnemyCastEvent[4] + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--iterage among eventsBeforePlayerDeath and add the enemy casts events that happened within the last events time window
|
|
local currentEnemyCastIndex = 1
|
|
for i = 1, #eventsBeforePlayerDeath do
|
|
local eventTable = eventsBeforePlayerDeath[i]
|
|
local eventTime = eventTable[4]
|
|
|
|
for enemyCastEventIndex = currentEnemyCastIndex, #enemyCastCacheIndexed do
|
|
local enemyCastEvent = enemyCastCacheIndexed[enemyCastEventIndex]
|
|
if (enemyCastEvent) then
|
|
local enemyCastTime = enemyCastEvent[1]
|
|
local enemyName = enemyCastEvent[2]
|
|
local spellId = enemyCastEvent[3]
|
|
local castAmount = enemyCastEvent[4]
|
|
|
|
if (enemyCastTime+0.1 > eventTime and enemyCastTime+0.1 - eventTime < 0.3) then
|
|
--create a new event to show the cast and add it to the list of events before death
|
|
local eventType = 6 --cast
|
|
local newEventTable = {}
|
|
newEventTable[1] = eventType
|
|
newEventTable[2] = spellId --spellId
|
|
newEventTable[3] = castAmount --amount of casts
|
|
newEventTable[4] = enemyCastTime --when the event happened using unix time
|
|
newEventTable[5] = 0 --player health when the event happened
|
|
newEventTable[6] = enemyName --source name
|
|
--print("addin enemy cast event", alvo_name, i, enemyCastTime+0.1, ">", eventTime)
|
|
tinsert(eventsBeforePlayerDeath, i, newEventTable)
|
|
currentEnemyCastIndex = enemyCastEventIndex + 1
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if (thisPlayer.last_cooldown) then
|
|
--create a new event to show the latest cooldown the player used before death and add it to the list of events before death
|
|
local eventType = 3 --last cooldown used
|
|
local eventTable = {}
|
|
eventTable[1] = eventType
|
|
eventTable[2] = thisPlayer.last_cooldown[2] --spellId
|
|
eventTable[3] = 0 --amount of damage or healing but in this case is 0
|
|
eventTable[4] = thisPlayer.last_cooldown[1] --when the event happened using unix time
|
|
eventTable[5] = 0 --player health when the event happened
|
|
eventTable[6] = targetName --source name
|
|
eventsBeforePlayerDeath[#eventsBeforePlayerDeath+1] = eventTable
|
|
else
|
|
--no last cooldown found so just add a last cooldown used event with no spellId and time 0
|
|
local eventTable = {}
|
|
eventTable [1] = 3 --true if this is a damage || false for healing || 1 for cooldown usage || 2 for last cooldown
|
|
eventTable [2] = 0 --spellId
|
|
eventTable [3] = 0 --amount of damage or healing but in this case is 0
|
|
eventTable [4] = 0 --when the event happened using unix time
|
|
eventTable [5] = 0 --player health when the event happened
|
|
eventTable [6] = targetName --source name
|
|
eventsBeforePlayerDeath[#eventsBeforePlayerDeath+1] = eventTable
|
|
end
|
|
|
|
local maxHealth
|
|
if (thisPlayer.arena_enemy) then
|
|
--this is an arena enemy, get the heal with the unit Id
|
|
local unitId = _detalhes.arena_enemies[thisPlayer.nome]
|
|
if (not unitId) then
|
|
unitId = Details:GuessArenaEnemyUnitId(thisPlayer.nome)
|
|
end
|
|
if (unitId) then
|
|
maxHealth = UnitHealthMax(unitId)
|
|
end
|
|
|
|
if (not maxHealth) then
|
|
maxHealth = 0
|
|
end
|
|
else
|
|
maxHealth = UnitHealthMax(thisPlayer.nome)
|
|
end
|
|
|
|
local playerDeathTable
|
|
local combatElapsedTime = GetTime() - _current_combat:GetStartTime()
|
|
|
|
do
|
|
local minutes, seconds = floor(combatElapsedTime / 60), floor(combatElapsedTime % 60)
|
|
|
|
playerDeathTable = {
|
|
eventsBeforePlayerDeath, --table
|
|
time, --number unix time
|
|
thisPlayer.nome, --string player name
|
|
thisPlayer.classe, --string player class
|
|
maxHealth, --number max health
|
|
minutes .. "m " .. seconds .. "s", --time of death as string
|
|
["dead"] = true,
|
|
["last_cooldown"] = thisPlayer.last_cooldown,
|
|
["dead_at"] = combatElapsedTime,
|
|
}
|
|
end
|
|
|
|
tinsert(_current_combat.last_events_tables, #_current_combat.last_events_tables+1, playerDeathTable)
|
|
|
|
--check if this is a mythic+ run for overall deaths
|
|
if (bIsMythicRun) then
|
|
--more checks for integrity
|
|
if (_detalhes.tabela_overall and _detalhes.tabela_overall.last_events_tables) then
|
|
--this is a mythic dungeon run, add the death to overall data
|
|
--need to adjust the time of death, since this will show all deaths in the mythic run
|
|
--first copy the table
|
|
local overallDeathTable = DetailsFramework.table.copy({}, playerDeathTable)
|
|
|
|
--get the elapsed time
|
|
local mythicPlusElapsedTime = GetTime() - _detalhes.tabela_overall:GetStartTime()
|
|
local minutes, seconds = floor(mythicPlusElapsedTime/60), floor(mythicPlusElapsedTime % 60)
|
|
|
|
overallDeathTable[6] = minutes .. "m " .. seconds .. "s"
|
|
overallDeathTable.dead_at = mythicPlusElapsedTime
|
|
|
|
--save data about the mythic run in the deathTable which goes in the regular segment
|
|
--confused? 'playerDeathTable' is added into the '_current_combat.last_events_tables' ~20 above on a tinsert
|
|
playerDeathTable["mythic_plus"] = true
|
|
playerDeathTable["mythic_plus_dead_at"] = mythicPlusElapsedTime
|
|
playerDeathTable["mythic_plus_dead_at_string"] = overallDeathTable[6]
|
|
|
|
--now add the death table into the overall data (this is the regular overall data, not the mythic plus overall data)
|
|
tinsert(_detalhes.tabela_overall.last_events_tables, #_detalhes.tabela_overall.last_events_tables + 1, overallDeathTable)
|
|
end
|
|
end
|
|
|
|
if (_hook_deaths) then
|
|
--send event to registred functions
|
|
for _, func in ipairs(_hook_deaths_container) do
|
|
local successful, errortext = pcall(func, nil, token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, playerDeathTable, thisPlayer.last_cooldown, combatElapsedTime, maxHealth, playerDeathTable["mythic_plus_dead_at"] or 0)
|
|
if (not successful) then
|
|
_detalhes:Msg("error occurred on a death hook function:", errortext)
|
|
end
|
|
end
|
|
end
|
|
|
|
--remove the player death events from the cache
|
|
last_events_cache[targetName] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
function parser:environment(token, time, sourceSerial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, env_type, amount)
|
|
local spelId
|
|
|
|
if (env_type == "Falling") then
|
|
who_name = ENVIRONMENTAL_FALLING_NAME
|
|
spelId = 3
|
|
elseif (env_type == "Drowning") then
|
|
who_name = ENVIRONMENTAL_DROWNING_NAME
|
|
spelId = 4
|
|
elseif (env_type == "Fatigue") then
|
|
who_name = ENVIRONMENTAL_FATIGUE_NAME
|
|
spelId = 5
|
|
elseif (env_type == "Fire") then
|
|
who_name = ENVIRONMENTAL_FIRE_NAME
|
|
spelId = 6
|
|
elseif (env_type == "Lava") then
|
|
who_name = ENVIRONMENTAL_LAVA_NAME
|
|
spelId = 7
|
|
elseif (env_type == "Slime") then
|
|
who_name = ENVIRONMENTAL_SLIME_NAME
|
|
spelId = 8
|
|
end
|
|
|
|
return parser:spell_dmg(token, time, sourceSerial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spelId or 1, env_type, 00000003, amount, -1, 1)
|
|
end
|
|
|
|
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--core
|
|
|
|
function parser:WipeSourceCache()
|
|
wipe (monk_guard_talent)
|
|
end
|
|
|
|
local token_list = {
|
|
-- neutral
|
|
["SPELL_SUMMON"] = parser.summon,
|
|
--["SPELL_CAST_FAILED"] = parser.spell_fail
|
|
}
|
|
|
|
--[==[@debug@
|
|
Details.token_list = token_list
|
|
--@end-debug@]==]
|
|
|
|
--serach key: ~capture
|
|
|
|
_detalhes.capture_types = {"damage", "heal", "energy", "miscdata", "aura", "spellcast"}
|
|
_detalhes.capture_schedules = {}
|
|
|
|
function _detalhes:CaptureIsAllEnabled()
|
|
for _, _thisType in ipairs(_detalhes.capture_types) do
|
|
if (not _detalhes.capture_real [_thisType]) then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function _detalhes:CaptureIsEnabled (capture)
|
|
if (_detalhes.capture_real [capture]) then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function _detalhes:CaptureRefresh()
|
|
for _, _thisType in ipairs(_detalhes.capture_types) do
|
|
if (_detalhes.capture_current [_thisType]) then
|
|
_detalhes:CaptureEnable (_thisType)
|
|
else
|
|
_detalhes:CaptureDisable (_thisType)
|
|
end
|
|
end
|
|
end
|
|
|
|
function _detalhes:CaptureGet(capture_type)
|
|
return _detalhes.capture_real [capture_type]
|
|
end
|
|
|
|
function _detalhes:CaptureSet (on_off, capture_type, real, time)
|
|
|
|
if (on_off == nil) then
|
|
on_off = _detalhes.capture_real [capture_type]
|
|
end
|
|
|
|
if (real) then
|
|
--hard switch
|
|
_detalhes.capture_real [capture_type] = on_off
|
|
_detalhes.capture_current [capture_type] = on_off
|
|
else
|
|
--soft switch
|
|
_detalhes.capture_current [capture_type] = on_off
|
|
if (time) then
|
|
local schedule_id = math.random(1, 10000000)
|
|
local new_schedule = _detalhes:ScheduleTimer("CaptureTimeout", time, {capture_type, schedule_id})
|
|
tinsert(_detalhes.capture_schedules, {new_schedule, schedule_id})
|
|
end
|
|
end
|
|
|
|
_detalhes:CaptureRefresh()
|
|
end
|
|
|
|
function _detalhes:CancelAllCaptureSchedules()
|
|
for i = 1, #_detalhes.capture_schedules do
|
|
local schedule_table, schedule_id = unpack(_detalhes.capture_schedules[i])
|
|
_detalhes:CancelTimer(schedule_table)
|
|
end
|
|
wipe(_detalhes.capture_schedules)
|
|
end
|
|
|
|
function _detalhes:CaptureTimeout (table)
|
|
local capture_type, schedule_id = unpack(table)
|
|
_detalhes.capture_current [capture_type] = _detalhes.capture_real [capture_type]
|
|
_detalhes:CaptureRefresh()
|
|
|
|
for index, table in ipairs(_detalhes.capture_schedules) do
|
|
local id = table [2]
|
|
if (schedule_id == id) then
|
|
tremove(_detalhes.capture_schedules, index)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
function _detalhes:CaptureDisable (capture_type)
|
|
|
|
capture_type = string.lower(capture_type)
|
|
|
|
if (capture_type == "damage") then
|
|
token_list ["SPELL_PERIODIC_DAMAGE"] = nil
|
|
token_list ["SPELL_EXTRA_ATTACKS"] = nil
|
|
token_list ["SPELL_DAMAGE"] = nil
|
|
token_list ["SWING_DAMAGE"] = nil
|
|
token_list ["RANGE_DAMAGE"] = nil
|
|
token_list ["DAMAGE_SHIELD"] = nil
|
|
token_list ["DAMAGE_SPLIT"] = nil
|
|
token_list ["RANGE_MISSED"] = nil
|
|
token_list ["SWING_MISSED"] = nil
|
|
token_list ["SPELL_MISSED"] = nil
|
|
token_list ["SPELL_BUILDING_MISSED"] = nil
|
|
token_list ["SPELL_PERIODIC_MISSED"] = nil
|
|
token_list ["DAMAGE_SHIELD_MISSED"] = nil
|
|
token_list ["ENVIRONMENTAL_DAMAGE"] = nil
|
|
token_list ["SPELL_BUILDING_DAMAGE"] = nil
|
|
token_list ["SPELL_EMPOWER_START"] = nil
|
|
token_list ["SPELL_EMPOWER_END"] = nil
|
|
token_list ["SPELL_EMPOWER_INTERRUPT"] = nil
|
|
|
|
elseif (capture_type == "heal") then
|
|
token_list ["SPELL_HEAL"] = nil
|
|
token_list ["SPELL_PERIODIC_HEAL"] = nil
|
|
token_list ["SPELL_HEAL_ABSORBED"] = nil
|
|
token_list ["SPELL_ABSORBED"] = nil
|
|
|
|
elseif (capture_type == "aura") then
|
|
token_list ["SPELL_AURA_APPLIED"] = parser.buff
|
|
token_list ["SPELL_AURA_REMOVED"] = parser.unbuff
|
|
token_list ["SPELL_AURA_REFRESH"] = parser.buff_refresh
|
|
token_list ["SPELL_AURA_APPLIED_DOSE"] = parser.buff_refresh
|
|
|
|
elseif (capture_type == "energy") then
|
|
token_list ["SPELL_ENERGIZE"] = nil
|
|
token_list ["SPELL_PERIODIC_ENERGIZE"] = nil
|
|
|
|
elseif (capture_type == "spellcast") then
|
|
token_list ["SPELL_CAST_SUCCESS"] = nil
|
|
|
|
elseif (capture_type == "miscdata") then
|
|
-- dispell
|
|
token_list ["SPELL_DISPEL"] = nil
|
|
token_list ["SPELL_STOLEN"] = nil
|
|
-- cc broke
|
|
token_list ["SPELL_AURA_BROKEN"] = nil
|
|
token_list ["SPELL_AURA_BROKEN_SPELL"] = nil
|
|
-- ress
|
|
token_list ["SPELL_RESURRECT"] = nil
|
|
-- interrupt
|
|
token_list ["SPELL_INTERRUPT"] = nil
|
|
-- dead
|
|
token_list ["UNIT_DIED"] = nil
|
|
token_list ["UNIT_DESTROYED"] = nil
|
|
|
|
end
|
|
end
|
|
|
|
--SPELL_DRAIN --need research
|
|
--SPELL_LEECH --need research
|
|
--SPELL_PERIODIC_DRAIN --need research
|
|
--SPELL_PERIODIC_LEECH --need research
|
|
--SPELL_DISPEL_FAILED --need research
|
|
--SPELL_BUILDING_HEAL --need research
|
|
|
|
|
|
function _detalhes:CaptureEnable (capture_type)
|
|
|
|
capture_type = string.lower(capture_type)
|
|
--retail
|
|
if (capture_type == "damage") then
|
|
token_list ["SPELL_PERIODIC_DAMAGE"] = parser.spell_dmg
|
|
token_list ["SPELL_EXTRA_ATTACKS"] = nil --parser.spell_dmg_extra_attacks
|
|
token_list ["SPELL_DAMAGE"] = parser.spell_dmg
|
|
token_list ["SPELL_BUILDING_DAMAGE"] = parser.spell_dmg
|
|
token_list ["SWING_DAMAGE"] = parser.spell_dmg --parser.swing
|
|
token_list ["RANGE_DAMAGE"] = parser.spell_dmg --parser.range
|
|
token_list ["DAMAGE_SHIELD"] = parser.spell_dmg
|
|
token_list ["DAMAGE_SPLIT"] = parser.spell_dmg
|
|
token_list ["RANGE_MISSED"] = parser.rangemissed
|
|
token_list ["SWING_MISSED"] = parser.swingmissed
|
|
token_list ["SPELL_MISSED"] = parser.missed
|
|
token_list ["SPELL_PERIODIC_MISSED"] = parser.missed
|
|
token_list ["SPELL_BUILDING_MISSED"] = parser.missed
|
|
token_list ["DAMAGE_SHIELD_MISSED"] = parser.missed
|
|
token_list ["ENVIRONMENTAL_DAMAGE"] = parser.environment
|
|
|
|
token_list ["SPELL_EMPOWER_START"] = parser.spell_empower --evoker only
|
|
token_list ["SPELL_EMPOWER_END"] = parser.spell_empower --evoker only
|
|
token_list ["SPELL_EMPOWER_INTERRUPT"] = parser.spell_empower --evoker only
|
|
|
|
elseif (capture_type == "heal") then
|
|
token_list ["SPELL_HEAL"] = parser.heal
|
|
token_list ["SPELL_PERIODIC_HEAL"] = parser.heal
|
|
token_list ["SPELL_HEAL_ABSORBED"] = parser.heal_denied
|
|
token_list ["SPELL_ABSORBED"] = parser.heal_absorb
|
|
|
|
elseif (capture_type == "aura") then
|
|
token_list ["SPELL_AURA_APPLIED"] = parser.buff
|
|
token_list ["SPELL_AURA_REMOVED"] = parser.unbuff
|
|
token_list ["SPELL_AURA_REFRESH"] = parser.buff_refresh
|
|
token_list ["SPELL_AURA_APPLIED_DOSE"] = parser.buff_refresh
|
|
|
|
elseif (capture_type == "energy") then
|
|
token_list ["SPELL_ENERGIZE"] = parser.energize
|
|
token_list ["SPELL_PERIODIC_ENERGIZE"] = parser.energize
|
|
|
|
elseif (capture_type == "spellcast") then
|
|
token_list ["SPELL_CAST_SUCCESS"] = parser.spellcast
|
|
|
|
elseif (capture_type == "miscdata") then
|
|
-- dispell
|
|
token_list ["SPELL_DISPEL"] = parser.dispell
|
|
token_list ["SPELL_STOLEN"] = parser.dispell
|
|
-- cc broke
|
|
token_list ["SPELL_AURA_BROKEN"] = parser.break_cc
|
|
token_list ["SPELL_AURA_BROKEN_SPELL"] = parser.break_cc
|
|
-- ress
|
|
token_list ["SPELL_RESURRECT"] = parser.ress
|
|
-- interrupt
|
|
token_list ["SPELL_INTERRUPT"] = parser.interrupt
|
|
-- dead
|
|
token_list ["UNIT_DIED"] = parser.dead
|
|
token_list ["UNIT_DESTROYED"] = parser.dead
|
|
|
|
end
|
|
end
|
|
|
|
parser.original_functions = {
|
|
["spell_dmg"] = parser.spell_dmg,
|
|
["spell_dmg_extra_attacks"] = nil, --parser.spell_dmg_extra_attacks,
|
|
["swing"] = parser.spell_dmg, --parser.swing,
|
|
["range"] = parser.spell_dmg, --parser.range,
|
|
["rangemissed"] = parser.rangemissed,
|
|
["swingmissed"] = parser.swingmissed,
|
|
["missed"] = parser.missed,
|
|
["environment"] = parser.environment,
|
|
["heal"] = parser.heal,
|
|
["heal_absorb"] = parser.heal_absorb,
|
|
["heal_denied"] = parser.heal_denied,
|
|
["buff"] = parser.buff,
|
|
["unbuff"] = parser.unbuff,
|
|
["buff_refresh"] = parser.buff_refresh,
|
|
["energize"] = parser.energize,
|
|
["spellcast"] = parser.spellcast,
|
|
["dispell"] = parser.dispell,
|
|
["break_cc"] = parser.break_cc,
|
|
["ress"] = parser.ress,
|
|
["interrupt"] = parser.interrupt,
|
|
["dead"] = parser.dead,
|
|
["spell_empower"] = parser.spell_empower,
|
|
}
|
|
|
|
function parser:SetParserFunction (token, func)
|
|
if (parser.original_functions [token]) then
|
|
if (type(func) == "function") then
|
|
parser [token] = func
|
|
else
|
|
parser [token] = parser.original_functions [token]
|
|
end
|
|
parser:RefreshFunctions()
|
|
else
|
|
return _detalhes:Msg("Invalid Token for SetParserFunction.")
|
|
end
|
|
end
|
|
|
|
local all_parser_tokens = {
|
|
["SPELL_PERIODIC_DAMAGE"] = "spell_dmg",
|
|
["SPELL_EXTRA_ATTACKS"] = nil, --"spell_dmg_extra_attacks",
|
|
["SPELL_DAMAGE"] = "spell_dmg",
|
|
["SPELL_BUILDING_DAMAGE"] = "spell_dmg",
|
|
["SWING_DAMAGE"] = "spell_dmg", --"swing"
|
|
["RANGE_DAMAGE"] = "spell_dmg", --"range",
|
|
["DAMAGE_SHIELD"] = "spell_dmg",
|
|
["DAMAGE_SPLIT"] = "spell_dmg",
|
|
["RANGE_MISSED"] = "rangemissed",
|
|
["SWING_MISSED"] = "swingmissed",
|
|
["SPELL_MISSED"] = "missed",
|
|
["SPELL_PERIODIC_MISSED"] = "missed",
|
|
["SPELL_BUILDING_MISSED"] = "missed",
|
|
["DAMAGE_SHIELD_MISSED"] = "missed",
|
|
["ENVIRONMENTAL_DAMAGE"] = "environment",
|
|
|
|
["SPELL_HEAL"] = "heal",
|
|
["SPELL_PERIODIC_HEAL"] = "heal",
|
|
["SPELL_HEAL_ABSORBED"] = "heal_denied",
|
|
["SPELL_ABSORBED"] = "heal_absorb",
|
|
|
|
["SPELL_AURA_APPLIED"] = "buff",
|
|
["SPELL_AURA_REMOVED"] = "unbuff",
|
|
["SPELL_AURA_REFRESH"] = "buff_refresh",
|
|
["SPELL_AURA_APPLIED_DOSE"] = "buff_refresh",
|
|
["SPELL_ENERGIZE"] = "energize",
|
|
["SPELL_PERIODIC_ENERGIZE"] = "energize",
|
|
|
|
["SPELL_CAST_SUCCESS"] = "spellcast",
|
|
["SPELL_DISPEL"] = "dispell",
|
|
["SPELL_STOLEN"] = "dispell",
|
|
["SPELL_AURA_BROKEN"] = "break_cc",
|
|
["SPELL_AURA_BROKEN_SPELL"] = "break_cc",
|
|
["SPELL_RESURRECT"] = "ress",
|
|
["SPELL_INTERRUPT"] = "interrupt",
|
|
["UNIT_DIED"] = "dead",
|
|
["UNIT_DESTROYED"] = "dead",
|
|
}
|
|
|
|
function parser:RefreshFunctions()
|
|
for CLUE_ID, token in pairs(all_parser_tokens) do
|
|
if (token_list [CLUE_ID]) then --not disabled
|
|
token_list [CLUE_ID] = parser [token]
|
|
end
|
|
end
|
|
end
|
|
|
|
function _detalhes:CallWipe (from_slash)
|
|
Details:Msg("Wipe has been called by your raid leader.")
|
|
|
|
if (_detalhes.wipe_called) then
|
|
if (from_slash) then
|
|
return _detalhes:Msg(Loc ["STRING_WIPE_ERROR1"])
|
|
else
|
|
return
|
|
end
|
|
elseif (not _detalhes.encounter_table.id) then
|
|
if (from_slash) then
|
|
return _detalhes:Msg(Loc ["STRING_WIPE_ERROR2"])
|
|
else
|
|
return
|
|
end
|
|
end
|
|
|
|
local eTable = _detalhes.encounter_table
|
|
|
|
--finish the encounter
|
|
local successful_ended = _detalhes.parser_functions:ENCOUNTER_END (eTable.id, eTable.name, eTable.diff, eTable.size, 0)
|
|
|
|
if (successful_ended) then
|
|
--we wiped
|
|
_detalhes.wipe_called = true
|
|
|
|
--cancel the on going captures schedules
|
|
_detalhes:CancelAllCaptureSchedules()
|
|
|
|
--disable it
|
|
_detalhes:CaptureSet (false, "damage", false)
|
|
_detalhes:CaptureSet (false, "energy", false)
|
|
_detalhes:CaptureSet (false, "aura", false)
|
|
_detalhes:CaptureSet (false, "energy", false)
|
|
_detalhes:CaptureSet (false, "spellcast", false)
|
|
|
|
if (from_slash) then
|
|
if (UnitIsGroupLeader ("player")) then
|
|
_detalhes:SendHomeRaidData ("WI")
|
|
end
|
|
end
|
|
|
|
local lower_instance = _detalhes:GetLowerInstanceNumber()
|
|
if (lower_instance) then
|
|
lower_instance = _detalhes:GetInstance(lower_instance)
|
|
lower_instance:InstanceAlert (Loc ["STRING_WIPE_ALERT"], {[[Interface\CHARACTERFRAME\UI-StateIcon]], 18, 18, false, 0.5, 1, 0, 0.5}, 4)
|
|
end
|
|
else
|
|
if (from_slash) then
|
|
return _detalhes:Msg(Loc ["STRING_WIPE_ERROR3"])
|
|
else
|
|
return
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
-- PARSER
|
|
--serach key: ~parser ~events ~start ~inicio
|
|
function _detalhes:FlagCurrentCombat()
|
|
if (_detalhes.is_in_battleground) then
|
|
_detalhes.tabela_vigente.pvp = true
|
|
_detalhes.tabela_vigente.is_pvp = {name = _detalhes.zone_name, mapid = _detalhes.zone_id}
|
|
|
|
elseif (_detalhes.is_in_arena) then
|
|
_detalhes.tabela_vigente.arena = true
|
|
_detalhes.tabela_vigente.is_arena = {name = _detalhes.zone_name, zone = _detalhes.zone_name, mapid = _detalhes.zone_id}
|
|
end
|
|
end
|
|
|
|
function _detalhes:GetZoneType()
|
|
return _detalhes.zone_type
|
|
end
|
|
|
|
function _detalhes.parser_functions:ZONE_CHANGED_NEW_AREA(...)
|
|
return Details.Schedules.After(1, Details.Check_ZONE_CHANGED_NEW_AREA)
|
|
end
|
|
|
|
--~zone ~area
|
|
function _detalhes:Check_ZONE_CHANGED_NEW_AREA()
|
|
local zoneName, zoneType, _, _, _, _, _, zoneMapID = GetInstanceInfo()
|
|
|
|
_detalhes.zone_type = zoneType
|
|
_detalhes.zone_id = zoneMapID
|
|
_detalhes.zone_name = zoneName
|
|
|
|
_in_resting_zone = IsResting()
|
|
|
|
parser:WipeSourceCache()
|
|
|
|
_is_in_instance = false
|
|
|
|
if (zoneType == "party" or zoneType == "raid") then
|
|
_is_in_instance = true
|
|
end
|
|
|
|
if (_detalhes.last_zone_type ~= zoneType) then
|
|
_detalhes:SendEvent("ZONE_TYPE_CHANGED", nil, zoneType)
|
|
_detalhes.last_zone_type = zoneType
|
|
|
|
for index, instancia in ipairs(_detalhes.tabela_instancias) do
|
|
if (instancia.ativa) then
|
|
instancia:AdjustAlphaByContext(true)
|
|
end
|
|
end
|
|
end
|
|
|
|
_detalhes.time_type = _detalhes.time_type_original
|
|
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg("(debug) zone change:", _detalhes.zone_name, "is a", _detalhes.zone_type, "zone.")
|
|
end
|
|
|
|
if (_detalhes.is_in_arena and zoneType ~= "arena") then
|
|
_detalhes:LeftArena()
|
|
end
|
|
|
|
--check if the player left a battleground
|
|
if (_detalhes.is_in_battleground and zoneType ~= "pvp") then
|
|
_detalhes.pvp_parser_frame:StopBgUpdater()
|
|
_detalhes.is_in_battleground = nil
|
|
_detalhes.time_type = _detalhes.time_type_original
|
|
end
|
|
|
|
if (zoneType == "pvp") then --battlegrounds
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg("(debug) zone type is now 'pvp'.")
|
|
end
|
|
|
|
if(not _detalhes.is_in_battleground and _detalhes.overall_clear_pvp) then
|
|
_detalhes.tabela_historico:resetar_overall()
|
|
end
|
|
|
|
_detalhes.is_in_battleground = true
|
|
|
|
if (_in_combat and not _current_combat.pvp) then
|
|
_detalhes:SairDoCombate()
|
|
end
|
|
|
|
if (not _in_combat) then
|
|
_detalhes:EntrarEmCombate()
|
|
end
|
|
|
|
_current_combat.pvp = true
|
|
_current_combat.is_pvp = {name = zoneName, mapid = zoneMapID}
|
|
|
|
if (_detalhes.use_battleground_server_parser) then
|
|
if (_detalhes.time_type == 1) then
|
|
_detalhes.time_type_original = 1
|
|
_detalhes.time_type = 2
|
|
end
|
|
_detalhes.pvp_parser_frame:StartBgUpdater()
|
|
else
|
|
if (_detalhes.force_activity_time_pvp) then
|
|
_detalhes.time_type_original = _detalhes.time_type
|
|
_detalhes.time_type = 1
|
|
end
|
|
end
|
|
|
|
Details.lastBattlegroundStartTime = GetTime()
|
|
|
|
elseif (zoneType == "arena") then
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg("(debug) zone type is now 'arena'.")
|
|
end
|
|
|
|
if (_detalhes.force_activity_time_pvp) then
|
|
_detalhes.time_type_original = _detalhes.time_type
|
|
_detalhes.time_type = 1
|
|
end
|
|
|
|
if (not _detalhes.is_in_arena) then
|
|
if (_detalhes.overall_clear_pvp) then
|
|
_detalhes.tabela_historico:resetar_overall()
|
|
end
|
|
--reset spec cache if broadcaster requested
|
|
if (_detalhes.streamer_config.reset_spec_cache) then
|
|
wipe (_detalhes.cached_specs)
|
|
end
|
|
end
|
|
|
|
_detalhes.is_in_arena = true
|
|
_detalhes:EnteredInArena()
|
|
|
|
else
|
|
local inInstance = IsInInstance()
|
|
if ((zoneType == "raid" or zoneType == "party") and inInstance) then
|
|
_detalhes:CheckForAutoErase (zoneMapID)
|
|
|
|
--if the current raid is current tier raid, pre-load the storage database
|
|
if (zoneType == "raid") then
|
|
if (_detalhes.InstancesToStoreData [zoneMapID]) then
|
|
_detalhes.ScheduleLoadStorage()
|
|
end
|
|
end
|
|
end
|
|
|
|
if (_detalhes:IsInInstance()) then
|
|
_detalhes.last_instance = zoneMapID
|
|
end
|
|
|
|
--if (_current_combat.pvp) then
|
|
-- _current_combat.pvp = false
|
|
--end
|
|
end
|
|
|
|
_is_activity_time = _detalhes.time_type == 1
|
|
|
|
_detalhes:DispatchAutoRunCode("on_zonechanged")
|
|
_detalhes:SchedulePetUpdate(7)
|
|
_detalhes:CheckForPerformanceProfile()
|
|
end
|
|
|
|
function _detalhes.parser_functions:PLAYER_ENTERING_WORLD ()
|
|
return _detalhes.parser_functions:ZONE_CHANGED_NEW_AREA()
|
|
end
|
|
|
|
-- ~encounter
|
|
--ENCOUNTER START
|
|
function _detalhes.parser_functions:ENCOUNTER_START(...)
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg("(debug) |cFFFFFF00ENCOUNTER_START|r event triggered.")
|
|
end
|
|
|
|
if (not isWOTLK) then
|
|
C_Timer.After(1, function()
|
|
if (Details.show_warning_id1) then
|
|
if (Details.show_warning_id1_amount < 2) then
|
|
Details.show_warning_id1_amount = Details.show_warning_id1_amount + 1
|
|
--Details:Msg("|cFFFFFF00you might find differences on damage done, this is due to a bug in the game client, nothing related to Details! itself (" .. Details.show_warning_id1_amount .. " / 10).")
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
Details222.Perf.WindowUpdate = 0
|
|
Details222.Perf.WindowUpdateC = true
|
|
|
|
_detalhes.latest_ENCOUNTER_END = _detalhes.latest_ENCOUNTER_END or 0
|
|
if (_detalhes.latest_ENCOUNTER_END + 10 > GetTime()) then
|
|
return
|
|
end
|
|
|
|
--leave the current combat when the encounter start, if is doing a mythic plus dungeons, check if the options allows to create a dedicated segment for the boss fight
|
|
if ((_in_combat and not _detalhes.tabela_vigente.is_boss) and (not _detalhes.MythicPlus.Started or _detalhes.mythic_plus.boss_dedicated_segment)) then
|
|
_detalhes:SairDoCombate()
|
|
end
|
|
|
|
local encounterID, encounterName, difficultyID, raidSize = select(1, ...)
|
|
local zoneName, _, _, _, _, _, _, zoneMapID = GetInstanceInfo()
|
|
|
|
if (_detalhes.InstancesToStoreData[zoneMapID]) then
|
|
Details.current_exp_raid_encounters[encounterID] = true
|
|
end
|
|
|
|
if (not _detalhes.WhoAggroTimer and _detalhes.announce_firsthit.enabled) then
|
|
_detalhes.WhoAggroTimer = C_Timer.NewTimer(0.1, who_aggro)
|
|
for i = 1, 5 do
|
|
local boss = UnitExists("boss" .. i)
|
|
if (boss) then
|
|
local targetName = UnitName ("boss" .. i .. "target")
|
|
if (targetName and type(targetName) == "string") then
|
|
Details.bossTargetAtPull = targetName
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if (IsInGuild() and IsInRaid() and _detalhes.announce_damagerecord.enabled and _detalhes.StorageLoaded) then
|
|
_detalhes.TellDamageRecord = C_Timer.NewTimer(0.6, _detalhes.PrintEncounterRecord)
|
|
_detalhes.TellDamageRecord.Boss = encounterID
|
|
_detalhes.TellDamageRecord.Diff = difficultyID
|
|
end
|
|
|
|
_current_encounter_id = encounterID
|
|
_detalhes.boss1_health_percent = 1
|
|
|
|
local dbm_mod, dbm_time = _detalhes.encounter_table.DBM_Mod, _detalhes.encounter_table.DBM_ModTime
|
|
wipe(_detalhes.encounter_table)
|
|
|
|
_detalhes.encounter_table.phase = 1
|
|
|
|
--store the encounter time inside the encounter table for the encounter plugin
|
|
_detalhes.encounter_table.start = GetTime()
|
|
_detalhes.encounter_table ["end"] = nil
|
|
-- local encounterID = Details.encounter_table.id
|
|
_detalhes.encounter_table.id = encounterID
|
|
_detalhes.encounter_table.name = encounterName
|
|
_detalhes.encounter_table.diff = difficultyID
|
|
_detalhes.encounter_table.size = raidSize
|
|
_detalhes.encounter_table.zone = zoneName
|
|
_detalhes.encounter_table.mapid = zoneMapID
|
|
|
|
if (dbm_mod and dbm_time == time()) then --pode ser time() � usado no start pra saber se foi no mesmo segundo.
|
|
_detalhes.encounter_table.DBM_Mod = dbm_mod
|
|
end
|
|
|
|
local encounter_start_table = _detalhes:GetEncounterStartInfo (zoneMapID, encounterID)
|
|
if (encounter_start_table) then
|
|
if (encounter_start_table.delay) then
|
|
if (type(encounter_start_table.delay) == "function") then
|
|
local delay = encounter_start_table.delay()
|
|
if (delay) then
|
|
--_detalhes.encounter_table ["start"] = time() + delay
|
|
_detalhes.encounter_table ["start"] = GetTime() + delay
|
|
end
|
|
else
|
|
--_detalhes.encounter_table ["start"] = time() + encounter_start_table.delay
|
|
_detalhes.encounter_table ["start"] = GetTime() + encounter_start_table.delay
|
|
end
|
|
end
|
|
if (encounter_start_table.func) then
|
|
encounter_start_table:func()
|
|
end
|
|
end
|
|
|
|
local encounter_table, boss_index = _detalhes:GetBossEncounterDetailsFromEncounterId (zoneMapID, encounterID)
|
|
if (encounter_table) then
|
|
_detalhes.encounter_table.index = boss_index
|
|
end
|
|
|
|
_detalhes:SendEvent("COMBAT_ENCOUNTER_START", nil, ...)
|
|
end
|
|
|
|
|
|
|
|
--ENCOUNRTER_END
|
|
function _detalhes.parser_functions:ENCOUNTER_END(...)
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg("(debug) |cFFFFFF00ENCOUNTER_END|r event triggered.")
|
|
end
|
|
|
|
Details222.Perf.WindowUpdateC = false
|
|
|
|
if (not isWOTLK) then
|
|
C_Timer.After(1, function()
|
|
if (Details.show_warning_id1) then
|
|
if (Details.show_warning_id1_amount < 2) then
|
|
Details.show_warning_id1_amount = Details.show_warning_id1_amount + 1
|
|
--Details:Msg("|cFFFFFF00you may find differences on damage done, this is due to a bug in the game client, nothing related to Details! itself (" .. Details.show_warning_id1_amount .. " / 10).")
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
_current_encounter_id = nil
|
|
|
|
local _, instanceType = GetInstanceInfo() --let's make sure it isn't a dungeon
|
|
if (_detalhes.zone_type == "party" or instanceType == "party") then
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg("(debug) the zone type is 'party', ignoring ENCOUNTER_END.")
|
|
end
|
|
end
|
|
|
|
local encounterID, encounterName, difficultyID, raidSize, endStatus = select(1, ...)
|
|
|
|
if (not _detalhes.encounter_table.start) then
|
|
Details:Msg("encounter table without start time.")
|
|
return
|
|
end
|
|
|
|
_detalhes.latest_ENCOUNTER_END = _detalhes.latest_ENCOUNTER_END or 0
|
|
if (_detalhes.latest_ENCOUNTER_END + 15 > GetTime()) then
|
|
return
|
|
end
|
|
|
|
_detalhes.latest_ENCOUNTER_END = GetTime()
|
|
_detalhes.encounter_table ["end"] = GetTime() -- 0.351
|
|
|
|
local _, _, _, _, _, _, _, zoneMapID = GetInstanceInfo()
|
|
|
|
if (_in_combat) then
|
|
if (endStatus == 1) then
|
|
_detalhes.encounter_table.kill = true
|
|
_detalhes:SairDoCombate (true, {encounterID, encounterName, difficultyID, raidSize, endStatus}) --killed
|
|
else
|
|
_detalhes.encounter_table.kill = false
|
|
_detalhes:SairDoCombate (false, {encounterID, encounterName, difficultyID, raidSize, endStatus}) --wipe
|
|
end
|
|
else
|
|
if ((_detalhes.tabela_vigente:GetEndTime() or 0) + 2 >= _detalhes.encounter_table ["end"]) then
|
|
_detalhes.tabela_vigente:SetStartTime (_detalhes.encounter_table ["start"])
|
|
_detalhes.tabela_vigente:SetEndTime (_detalhes.encounter_table ["end"])
|
|
_detalhes:RefreshMainWindow(-1, true)
|
|
end
|
|
end
|
|
|
|
--tag item level of all players
|
|
local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true)
|
|
local allPlayersGear = openRaidLib and openRaidLib.GetAllUnitsGear()
|
|
|
|
local status = xpcall(function()
|
|
for actorIndex, actorObject in Details:GetCurrentCombat():GetContainer(DETAILS_ATTRIBUTE_DAMAGE):ListActors() do
|
|
local gearInfo = allPlayersGear and allPlayersGear[actorObject:Name()]
|
|
if (gearInfo) then
|
|
actorObject.ilvl = gearInfo.ilevel
|
|
end
|
|
end
|
|
end, geterrorhandler())
|
|
|
|
if (not status) then
|
|
Details:Msg("ilvl error:", status)
|
|
end
|
|
|
|
_detalhes:SendEvent("COMBAT_ENCOUNTER_END", nil, ...)
|
|
|
|
wipe(_detalhes.encounter_table)
|
|
wipe(dk_pets_cache.army)
|
|
wipe(dk_pets_cache.apoc)
|
|
wipe(empower_cache)
|
|
|
|
return true
|
|
end
|
|
|
|
function _detalhes.parser_functions:UNIT_PET(...)
|
|
_detalhes.container_pets:Unpet(...)
|
|
_detalhes:SchedulePetUpdate(1)
|
|
end
|
|
|
|
local autoSwapDynamicOverallData = function(instance, inCombat)
|
|
local mainDisplayGroup, subDisplay = instance:GetDisplay()
|
|
local customDisplayAttributeId = 5
|
|
|
|
--entering in combat, swap to dynamic overall damage
|
|
if (inCombat) then
|
|
if (mainDisplayGroup == DETAILS_ATTRIBUTE_DAMAGE and subDisplay == DETAILS_SUBATTRIBUTE_DAMAGEDONE) then
|
|
local segment = instance:GetSegment()
|
|
if (segment == DETAILS_SEGMENTID_OVERALL) then
|
|
local dynamicOverallDataCustomID = Details222.GetCustomDisplayIDByName(Loc["STRING_CUSTOM_DYNAMICOVERAL"])
|
|
instance:SetDisplay(segment, customDisplayAttributeId, dynamicOverallDataCustomID)
|
|
end
|
|
end
|
|
else
|
|
--leaving combat
|
|
if (mainDisplayGroup == customDisplayAttributeId) then
|
|
local dynamicOverallDataCustomID = Details222.GetCustomDisplayIDByName(Loc["STRING_CUSTOM_DYNAMICOVERAL"])
|
|
if (subDisplay == dynamicOverallDataCustomID) then
|
|
local segment = instance:GetSegment()
|
|
if (segment == DETAILS_SEGMENTID_OVERALL) then
|
|
instance:SetDisplay(true, DETAILS_ATTRIBUTE_DAMAGE, DETAILS_SUBATTRIBUTE_DAMAGEDONE)
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
|
|
function _detalhes.parser_functions:PLAYER_REGEN_DISABLED(...)
|
|
C_Timer.After(0, function()
|
|
if (not Details.bossTargetAtPull) then
|
|
if (UnitExists("boss1")) then
|
|
local bossTarget = UnitName("boss1target")
|
|
if (bossTarget) then
|
|
Details.bossTargetAtPull = bossTarget
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
if (Details.auto_swap_to_dynamic_overall) then
|
|
Details:InstanceCall(autoSwapDynamicOverallData, true)
|
|
end
|
|
|
|
Details.combat_id_global = Details.combat_id_global + 1
|
|
_global_combat_counter = Details.combat_id_global
|
|
|
|
_trinket_data_cache = Details:GetTrinketData()
|
|
|
|
if (_detalhes.zone_type == "pvp" and not _detalhes.use_battleground_server_parser) then
|
|
if (_in_combat) then
|
|
_detalhes:SairDoCombate()
|
|
end
|
|
_detalhes:EntrarEmCombate()
|
|
end
|
|
|
|
if (not _detalhes:CaptureGet("damage")) then
|
|
_detalhes:EntrarEmCombate()
|
|
end
|
|
|
|
--essa parte do solo mode ainda sera usada?
|
|
if (_detalhes.solo and _detalhes.PluginCount.SOLO > 0) then --solo mode
|
|
local esta_instancia = _detalhes.tabela_instancias[_detalhes.solo]
|
|
esta_instancia.atualizando = true
|
|
end
|
|
|
|
for index, instancia in ipairs(_detalhes.tabela_instancias) do
|
|
if (instancia.ativa) then --1 = none, we doesn't need to call
|
|
instancia:AdjustAlphaByContext(true)
|
|
end
|
|
end
|
|
|
|
_detalhes:DispatchAutoRunCode("on_entercombat")
|
|
|
|
_detalhes.tabela_vigente.CombatStartedAt = GetTime()
|
|
end
|
|
|
|
--in case the player left the raid during the encounter
|
|
--this function clear the encounter_id from the cache
|
|
local checkIfEncounterIsDone = function()
|
|
if (not _current_encounter_id) then
|
|
return
|
|
end
|
|
|
|
if (IsInRaid()) then
|
|
--raid
|
|
local inCombat = false
|
|
for i = 1, GetNumGroupMembers() do
|
|
if (UnitAffectingCombat("raid" .. i)) then
|
|
inCombat = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if (not inCombat) then
|
|
_current_encounter_id = nil
|
|
end
|
|
|
|
elseif (IsInGroup()) then
|
|
--party (dungeon)
|
|
local inCombat = false
|
|
for i = 1, GetNumGroupMembers() -1 do
|
|
if (UnitAffectingCombat("party" .. i)) then
|
|
inCombat = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if (not inCombat) then
|
|
_current_encounter_id = nil
|
|
end
|
|
|
|
else
|
|
_current_encounter_id = nil
|
|
end
|
|
end
|
|
|
|
--this function is guaranteed to run after a combat is done
|
|
--can also run when the player leaves combat state (regen enabled)
|
|
function _detalhes:RunScheduledEventsAfterCombat(OnRegenEnabled)
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg("(debug) running scheduled events after combat end.")
|
|
end
|
|
|
|
TBC_JudgementOfLightCache = {
|
|
_damageCache = {}
|
|
}
|
|
|
|
--when the user requested data from the storage but is in combat lockdown
|
|
if (_detalhes.schedule_storage_load) then
|
|
_detalhes.schedule_storage_load = nil
|
|
_detalhes.ScheduleLoadStorage()
|
|
end
|
|
|
|
--store a boss encounter when out of combat since it might need to load the storage
|
|
if (_detalhes.schedule_store_boss_encounter) then
|
|
if (not _detalhes.logoff_saving_data) then
|
|
local successful, errortext = pcall(Details.Database.StoreEncounter)
|
|
if (not successful) then
|
|
_detalhes:Msg("error occurred on Details.Database.StoreEncounter():", errortext)
|
|
end
|
|
end
|
|
_detalhes.schedule_store_boss_encounter = nil
|
|
end
|
|
|
|
if (Details.schedule_store_boss_encounter_wipe) then
|
|
if (not _detalhes.logoff_saving_data) then
|
|
local successful, errortext = pcall(Details.Database.StoreWipe)
|
|
if (not successful) then
|
|
_detalhes:Msg("error occurred on Details.Database.StoreWipe():", errortext)
|
|
end
|
|
end
|
|
Details.schedule_store_boss_encounter_wipe = nil
|
|
end
|
|
|
|
--when a large amount of data has been removed and the player is in combat, schedule to run the hard garbage collector (the blizzard one, not the details! internal)
|
|
if (_detalhes.schedule_hard_garbage_collect) then
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg("(debug) found schedule collectgarbage().")
|
|
end
|
|
_detalhes.schedule_hard_garbage_collect = false
|
|
collectgarbage()
|
|
end
|
|
|
|
for index, instancia in ipairs(_detalhes.tabela_instancias) do
|
|
if (instancia.ativa) then --1 = none, we doesn't need to call
|
|
instancia:AdjustAlphaByContext(true)
|
|
end
|
|
end
|
|
|
|
if (not OnRegenEnabled) then
|
|
wipe(bitfield_swap_cache)
|
|
wipe(empower_cache)
|
|
_detalhes:DispatchAutoRunCode("on_leavecombat")
|
|
end
|
|
|
|
if (_detalhes.solo and _detalhes.PluginCount.SOLO > 0) then --code too old and I don't have documentation for it
|
|
if (_detalhes.SoloTables.Plugins [_detalhes.SoloTables.Mode].Stop) then
|
|
_detalhes.SoloTables.Plugins [_detalhes.SoloTables.Mode].Stop()
|
|
end
|
|
end
|
|
|
|
--[=[ code maintenance: disabled deprecated code Feb 2022
|
|
|
|
--deprecated shcedules
|
|
do
|
|
if (_detalhes.schedule_add_to_overall and #_detalhes.schedule_add_to_overall > 0) then --deprecated (combat are now added immediatelly since there's no script run too long)
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg("(debug) adding ", #_detalhes.schedule_add_to_overall, "combats in queue to overall data.")
|
|
end
|
|
|
|
for i = #_detalhes.schedule_add_to_overall, 1, -1 do
|
|
local CombatToAdd = tremove(_detalhes.schedule_add_to_overall, i)
|
|
if (CombatToAdd) then
|
|
_detalhes.historico:adicionar_overall (CombatToAdd)
|
|
end
|
|
end
|
|
end
|
|
|
|
if (_detalhes.schedule_mythicdungeon_trash_merge) then --deprecated (combat are now added immediatelly since there's no script run too long)
|
|
_detalhes.schedule_mythicdungeon_trash_merge = nil
|
|
DetailsMythicPlusFrame.MergeTrashCleanup (true)
|
|
end
|
|
|
|
if (_detalhes.schedule_mythicdungeon_endtrash_merge) then --deprecated (combat are now added immediatelly since there's no script run too long)
|
|
_detalhes.schedule_mythicdungeon_endtrash_merge = nil
|
|
DetailsMythicPlusFrame.MergeRemainingTrashAfterAllBossesDone()
|
|
end
|
|
|
|
if (_detalhes.schedule_mythicdungeon_overallrun_merge) then --deprecated (combat are now added immediatelly since there's no script run too long)
|
|
_detalhes.schedule_mythicdungeon_overallrun_merge = nil
|
|
DetailsMythicPlusFrame.MergeSegmentsOnEnd()
|
|
end
|
|
|
|
if (_detalhes.schedule_flag_boss_components) then --deprecated (combat are now added immediatelly since there's no script run too long)
|
|
_detalhes.schedule_flag_boss_components = false
|
|
_detalhes:FlagActorsOnBossFight()
|
|
end
|
|
|
|
if (_detalhes.schedule_remove_overall) then --deprecated (combat are now added immediatelly since there's no script run too long)
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg("(debug) found schedule overall data clean up.")
|
|
end
|
|
_detalhes.schedule_remove_overall = false
|
|
_detalhes.tabela_historico:resetar_overall()
|
|
end
|
|
|
|
if (_detalhes.wipe_called and false) then --disabled
|
|
_detalhes.wipe_called = nil
|
|
_detalhes:CaptureSet (nil, "damage", true)
|
|
_detalhes:CaptureSet (nil, "energy", true)
|
|
_detalhes:CaptureSet (nil, "aura", true)
|
|
_detalhes:CaptureSet (nil, "energy", true)
|
|
_detalhes:CaptureSet (nil, "spellcast", true)
|
|
|
|
_detalhes:CaptureSet (false, "damage", false, 10)
|
|
_detalhes:CaptureSet (false, "energy", false, 10)
|
|
_detalhes:CaptureSet (false, "aura", false, 10)
|
|
_detalhes:CaptureSet (false, "energy", false, 10)
|
|
_detalhes:CaptureSet (false, "spellcast", false, 10)
|
|
end
|
|
end
|
|
|
|
--]=]
|
|
|
|
|
|
end
|
|
|
|
function _detalhes.parser_functions:CHALLENGE_MODE_START(...)
|
|
--send mythic dungeon start event
|
|
if (_detalhes.debug) then
|
|
print("parser event", "CHALLENGE_MODE_START", ...)
|
|
end
|
|
|
|
local zoneName, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize = GetInstanceInfo()
|
|
if (difficultyID == 8) then
|
|
_detalhes:SendEvent("COMBAT_MYTHICDUNGEON_START")
|
|
end
|
|
end
|
|
|
|
function _detalhes.parser_functions:CHALLENGE_MODE_COMPLETED(...)
|
|
--send mythic dungeon end event
|
|
local zoneName, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize = GetInstanceInfo()
|
|
if (difficultyID == 8) then
|
|
_detalhes:SendEvent("COMBAT_MYTHICDUNGEON_END")
|
|
end
|
|
end
|
|
|
|
function _detalhes.parser_functions:PLAYER_REGEN_ENABLED(...)
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg("(debug) |cFFFFFF00PLAYER_REGEN_ENABLED|r event triggered.")
|
|
|
|
--print("combat lockdown:", InCombatLockdown())
|
|
--print("affecting combat:", UnitAffectingCombat("player"))
|
|
|
|
--if (_current_encounter_id and IsInInstance()) then
|
|
--print("has a encounter ID")
|
|
--print("player is dead:", UnitHealth ("player") < 1)
|
|
--end
|
|
end
|
|
|
|
if (Details.auto_swap_to_dynamic_overall) then
|
|
Details:InstanceCall(autoSwapDynamicOverallData, false)
|
|
end
|
|
|
|
--elapsed combat time
|
|
Details.LatestCombatDone = GetTime()
|
|
|
|
local currentCombat = Details:GetCurrentCombat()
|
|
currentCombat.CombatEndedAt = GetTime()
|
|
currentCombat.TotalElapsedCombatTime = currentCombat.CombatEndedAt - (currentCombat.CombatStartedAt or 0)
|
|
|
|
C_Timer.After(10, checkIfEncounterIsDone)
|
|
|
|
--playing alone, just finish the combat right now
|
|
if (not IsInGroup() and not IsInRaid()) then
|
|
currentCombat.playing_solo = true
|
|
Details:SairDoCombate()
|
|
else
|
|
--is in a raid or party group
|
|
C_Timer.After(1, function()
|
|
if (IsInRaid()) then
|
|
local inCombat = false
|
|
for i = 1, GetNumGroupMembers() do
|
|
if (UnitAffectingCombat("raid" .. i)) then
|
|
inCombat = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if (not inCombat) then
|
|
Details:RunScheduledEventsAfterCombat(true)
|
|
end
|
|
|
|
elseif (IsInGroup()) then
|
|
local inCombat = false
|
|
for i = 1, GetNumGroupMembers() -1 do
|
|
if (UnitAffectingCombat("party" .. i)) then
|
|
inCombat = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if (not inCombat) then
|
|
Details:RunScheduledEventsAfterCombat(true)
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
end
|
|
|
|
function _detalhes.parser_functions:PLAYER_TALENT_UPDATE()
|
|
if (IsInGroup() or IsInRaid()) then
|
|
if (_detalhes.SendTalentTimer and not _detalhes.SendTalentTimer:IsCancelled()) then
|
|
_detalhes.SendTalentTimer:Cancel()
|
|
end
|
|
_detalhes.SendTalentTimer = C_Timer.NewTimer(11, function()
|
|
_detalhes:SendCharacterData()
|
|
end)
|
|
end
|
|
end
|
|
|
|
function _detalhes.parser_functions:PLAYER_SPECIALIZATION_CHANGED()
|
|
--some parts of details! does call this function, check first for past expansions
|
|
if (DetailsFramework.IsTimewalkWoW()) then
|
|
return
|
|
end
|
|
|
|
local specIndex = DetailsFramework.GetSpecialization()
|
|
if (specIndex) then
|
|
local specID = DetailsFramework.GetSpecializationInfo(specIndex)
|
|
if (specID and specID ~= 0) then
|
|
local guid = UnitGUID("player")
|
|
if (guid) then
|
|
_detalhes.cached_specs [guid] = specID
|
|
end
|
|
end
|
|
end
|
|
|
|
if (IsInGroup() or IsInRaid()) then
|
|
if (_detalhes.SendTalentTimer and not _detalhes.SendTalentTimer:IsCancelled()) then
|
|
_detalhes.SendTalentTimer:Cancel()
|
|
end
|
|
_detalhes.SendTalentTimer = C_Timer.NewTimer(11, function()
|
|
_detalhes:SendCharacterData()
|
|
end)
|
|
end
|
|
end
|
|
|
|
--this is mostly triggered when the player enters in a dual against another player
|
|
function _detalhes.parser_functions:UNIT_FACTION(unit)
|
|
if (true) then
|
|
--disable until figure out how to make this work properlly
|
|
--at the moment this event is firing at bgs, arenas, etc making horde icons to show at random
|
|
return
|
|
end
|
|
|
|
--check if outdoors
|
|
--unit was nil, nameplate might bug here, it should track after the event
|
|
if (_detalhes.zone_type == "none" and unit) then
|
|
local serial = UnitGUID(unit)
|
|
--the serial is valid and isn't THE player and the serial is from a player?
|
|
if (serial and serial ~= UnitGUID("player") and serial:find("Player")) then
|
|
_detalhes.duel_candidates[serial] = GetTime()
|
|
|
|
local playerName = _detalhes:GetCLName(unit)
|
|
|
|
--check if the player is inside the current combat and flag the objects
|
|
if (playerName and _current_combat) then
|
|
local enemyPlayer1 = _current_combat:GetActor(1, playerName)
|
|
local enemyPlayer2 = _current_combat:GetActor(2, playerName)
|
|
local enemyPlayer3 = _current_combat:GetActor(3, playerName)
|
|
local enemyPlayer4 = _current_combat:GetActor(4, playerName)
|
|
if (enemyPlayer1) then
|
|
--set to show when the player is solo play
|
|
enemyPlayer1.grupo = true
|
|
enemyPlayer1.enemy = true
|
|
|
|
if (IsInGroup()) then
|
|
--broadcast the enemy to group members so they can "watch" the damage
|
|
end
|
|
end
|
|
|
|
if (enemyPlayer2) then
|
|
enemyPlayer2.grupo = true
|
|
enemyPlayer2.enemy = true
|
|
end
|
|
|
|
if (enemyPlayer3) then
|
|
enemyPlayer3.grupo = true
|
|
enemyPlayer3.enemy = true
|
|
end
|
|
|
|
if (enemyPlayer4) then
|
|
enemyPlayer4.grupo = true
|
|
enemyPlayer4.enemy = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function _detalhes.parser_functions:ROLE_CHANGED_INFORM(...)
|
|
if (_detalhes.last_assigned_role ~= _UnitGroupRolesAssigned("player")) then
|
|
_detalhes:CheckSwitchOnLogon (true)
|
|
_detalhes.last_assigned_role = _UnitGroupRolesAssigned("player")
|
|
end
|
|
end
|
|
|
|
function _detalhes.parser_functions:PLAYER_ROLES_ASSIGNED(...)
|
|
if (_detalhes.last_assigned_role ~= _UnitGroupRolesAssigned("player")) then
|
|
_detalhes:CheckSwitchOnLogon (true)
|
|
_detalhes.last_assigned_role = _UnitGroupRolesAssigned("player")
|
|
end
|
|
end
|
|
|
|
function _detalhes:InGroup()
|
|
return _detalhes.in_group
|
|
end
|
|
|
|
function _detalhes.parser_functions:GROUP_ROSTER_UPDATE(...)
|
|
if (not _detalhes.in_group) then
|
|
_detalhes.in_group = IsInGroup() or IsInRaid()
|
|
|
|
if (_detalhes.in_group) then
|
|
--player entered in a group, cleanup and set the new enviromnent
|
|
Details222.GarbageCollector.RestartInternalGarbageCollector(true)
|
|
Details:WipePets()
|
|
Details:SchedulePetUpdate(1)
|
|
Details:InstanceCall(Details.AdjustAlphaByContext)
|
|
|
|
Details:CheckSwitchOnLogon()
|
|
Details:CheckVersion()
|
|
Details:SendEvent("GROUP_ONENTER")
|
|
|
|
Details:DispatchAutoRunCode("on_groupchange")
|
|
|
|
wipe (Details.trusted_characters)
|
|
C_Timer.After(5, Details.ScheduleSyncPlayerActorData)
|
|
end
|
|
|
|
else
|
|
_detalhes.in_group = IsInGroup() or IsInRaid()
|
|
|
|
if (not _detalhes.in_group) then
|
|
--player left the group, run routines to cleanup the environment
|
|
Details222.GarbageCollector.RestartInternalGarbageCollector(true)
|
|
Details:WipePets()
|
|
Details:SchedulePetUpdate(1)
|
|
wipe(Details.details_users)
|
|
Details:InstanceCall(Details.AdjustAlphaByContext)
|
|
Details:CheckSwitchOnLogon()
|
|
Details:SendEvent("GROUP_ONLEAVE")
|
|
Details:DispatchAutoRunCode("on_groupchange")
|
|
wipe(Details.trusted_characters)
|
|
else
|
|
--player is still in a group
|
|
_detalhes:SchedulePetUpdate(2)
|
|
|
|
--send char data
|
|
if (_detalhes.SendCharDataOnGroupChange and not _detalhes.SendCharDataOnGroupChange:IsCancelled()) then
|
|
return
|
|
end
|
|
|
|
_detalhes.SendCharDataOnGroupChange = C_Timer.NewTimer(11, function()
|
|
_detalhes:SendCharacterData()
|
|
_detalhes.SendCharDataOnGroupChange = nil
|
|
end)
|
|
end
|
|
end
|
|
|
|
_detalhes:SchedulePetUpdate(6)
|
|
end
|
|
|
|
function _detalhes.parser_functions:START_TIMER(...) --~timer
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg("(debug) found a timer.")
|
|
end
|
|
|
|
local _, zoneType = GetInstanceInfo()
|
|
|
|
--check if the player is inside an arena
|
|
if (zoneType == "arena") then
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg("(debug) timer is an arena countdown.")
|
|
end
|
|
|
|
_detalhes:StartArenaSegment(...)
|
|
|
|
--check if the player is inside a battleground
|
|
elseif (zoneType == "battleground") then
|
|
if (Details.debug) then
|
|
Details:Msg("(debug) timer is a battleground countdown.")
|
|
end
|
|
|
|
local _, timeSeconds = select(1, ...)
|
|
|
|
if (Details.start_battleground) then
|
|
Details.Schedules.Cancel(Details.start_battleground)
|
|
end
|
|
|
|
--create new schedule
|
|
Details.start_battleground = Details.Schedules.NewTimer(timeSeconds, Details.CreateBattlegroundSegment)
|
|
Details.Schedules.SetName(Details.start_battleground, "Battleground Start Timer")
|
|
end
|
|
end
|
|
|
|
function Details:CreateBattlegroundSegment()
|
|
if (_in_combat) then
|
|
_detalhes.tabela_vigente.discard_segment = true
|
|
Details:EndCombat()
|
|
end
|
|
|
|
Details.lastBattlegroundStartTime = GetTime()
|
|
Details:StartCombat()
|
|
|
|
if (Details.debug) then
|
|
Details:Msg("(debug) a battleground has started.")
|
|
end
|
|
end
|
|
|
|
--~load
|
|
local start_details = function()
|
|
if (not _detalhes.gump) then
|
|
--failed to load the framework
|
|
|
|
if (not _detalhes.instance_load_failed) then
|
|
_detalhes:CreatePanicWarning()
|
|
end
|
|
_detalhes.instance_load_failed.text:SetText("Framework for Details! isn't loaded.\nIf you just updated the addon, please reboot the game client.\nWe apologize for the inconvenience and thank you for your comprehension.")
|
|
|
|
return
|
|
end
|
|
|
|
--cooltip
|
|
if (not _G.GameCooltip) then
|
|
_detalhes.popup = _G.GameCooltip
|
|
else
|
|
_detalhes.popup = _G.GameCooltip
|
|
end
|
|
|
|
--check group
|
|
_detalhes.in_group = IsInGroup() or IsInRaid()
|
|
|
|
--write into details object all basic keys and default profile
|
|
_detalhes:ApplyBasicKeys()
|
|
--check if is first run, update keys for character and global data
|
|
_detalhes:LoadGlobalAndCharacterData()
|
|
|
|
--details updated and not reopened the game client
|
|
if (_detalhes.FILEBROKEN) then
|
|
return
|
|
end
|
|
|
|
--load all the saved combats
|
|
_detalhes:LoadCombatTables()
|
|
|
|
--load the profiles
|
|
_detalhes:LoadConfig()
|
|
|
|
_detalhes:UpdateParserGears()
|
|
|
|
--load auto run code
|
|
Details:StartAutoRun()
|
|
|
|
Details.isLoaded = true
|
|
end
|
|
|
|
function Details.IsLoaded()
|
|
return Details.isLoaded
|
|
end
|
|
|
|
function _detalhes.parser_functions:ADDON_LOADED(...)
|
|
local addon_name = select(1, ...)
|
|
if (addon_name == "Details") then
|
|
start_details()
|
|
end
|
|
end
|
|
|
|
local playerLogin = CreateFrame("frame")
|
|
playerLogin:RegisterEvent("PLAYER_LOGIN")
|
|
playerLogin:SetScript("OnEvent", function()
|
|
Details:StartMeUp()
|
|
end)
|
|
|
|
function _detalhes.parser_functions:PET_BATTLE_OPENING_START(...)
|
|
_detalhes.pet_battle = true
|
|
for index, instance in ipairs(_detalhes.tabela_instancias) do
|
|
if (instance.ativa) then
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg("(debug) hidding windows for Pet Battle.")
|
|
end
|
|
instance:SetWindowAlphaForCombat(true, true, 0)
|
|
end
|
|
end
|
|
end
|
|
|
|
function _detalhes.parser_functions:PET_BATTLE_CLOSE(...)
|
|
_detalhes.pet_battle = false
|
|
for index, instance in ipairs(_detalhes.tabela_instancias) do
|
|
if (instance.ativa) then
|
|
if (_detalhes.debug) then
|
|
_detalhes:Msg("(debug) Pet Battle finished, calling AdjustAlphaByContext().")
|
|
end
|
|
instance:AdjustAlphaByContext(true)
|
|
end
|
|
end
|
|
end
|
|
|
|
function _detalhes.parser_functions:UNIT_NAME_UPDATE(...)
|
|
_detalhes:SchedulePetUpdate(5)
|
|
end
|
|
|
|
function Details.parser_functions:PLAYER_TARGET_CHANGED(...)
|
|
Details:SendEvent("PLAYER_TARGET")
|
|
end
|
|
|
|
local parser_functions = _detalhes.parser_functions
|
|
|
|
function _detalhes:OnEvent(event, ...)
|
|
local func = parser_functions[event]
|
|
if (func) then
|
|
return func(nil, ...)
|
|
end
|
|
end
|
|
|
|
_detalhes.listener:SetScript("OnEvent", _detalhes.OnEvent)
|
|
|
|
--logout function ~save ~logout
|
|
local saver = CreateFrame("frame", nil, UIParent)
|
|
saver:RegisterEvent("PLAYER_LOGOUT")
|
|
saver:SetScript("OnEvent", function(...)
|
|
__details_backup = __details_backup or {
|
|
_exit_error = {},
|
|
_instance_backup = {},
|
|
}
|
|
local exitErrors = __details_backup._exit_error
|
|
|
|
local addToExitErrors = function(text)
|
|
table.insert(exitErrors, 1, date() .. "|" .. text)
|
|
table.remove(exitErrors, 10)
|
|
end
|
|
|
|
local currentStep = ""
|
|
|
|
--save the time played on this class, run protected
|
|
local savePlayTimeClass, savePlayTimeError = pcall(function()
|
|
Details.SavePlayTimeOnClass()
|
|
end)
|
|
|
|
if (not savePlayTimeClass) then
|
|
addToExitErrors("Saving Play Time: " .. savePlayTimeError)
|
|
end
|
|
|
|
--SAVINGDATA = true
|
|
_detalhes_global.exit_log = {}
|
|
_detalhes_global.exit_errors = _detalhes_global.exit_errors or {}
|
|
|
|
currentStep = "Checking the framework integrity"
|
|
|
|
if (not _detalhes.gump) then
|
|
--failed to load the framework
|
|
tinsert(_detalhes_global.exit_log, "The framework wasn't in Details member 'gump'.")
|
|
tinsert(_detalhes_global.exit_errors, 1, currentStep .. "|" .. date() .. "|" .. _detalhes.userversion .. "|Framework wasn't loaded|")
|
|
return
|
|
end
|
|
|
|
local saver_error = function(errortext)
|
|
--if the error log cause an error?
|
|
local writeLog = function()
|
|
_detalhes_global = _detalhes_global or {}
|
|
tinsert(_detalhes_global.exit_errors, 1, currentStep .. "|" .. date() .. "|" .. _detalhes.userversion .. "|" .. errortext .. "|" .. debugstack())
|
|
tremove(_detalhes_global.exit_errors, 6)
|
|
addToExitErrors(currentStep .. "|" .. date() .. "|" .. _detalhes.userversion .. "|" .. errortext .. "|" .. debugstack())
|
|
end
|
|
xpcall(writeLog, addToExitErrors)
|
|
end
|
|
|
|
_detalhes.saver_error_func = saver_error
|
|
_detalhes.logoff_saving_data = true
|
|
|
|
--close info window
|
|
if (_detalhes.FechaJanelaInfo) then
|
|
tinsert(_detalhes_global.exit_log, "1 - Closing Janela Info.")
|
|
currentStep = "Fecha Janela Info"
|
|
xpcall(_detalhes.FechaJanelaInfo, saver_error)
|
|
end
|
|
|
|
--do not save window pos
|
|
if (_detalhes.tabela_instancias) then
|
|
local clearInstances = function()
|
|
currentStep = "Dealing With Instances"
|
|
tinsert(_detalhes_global.exit_log, "2 - Clearing user place from instances.")
|
|
for id, instance in _detalhes:ListInstances() do
|
|
if (id) then
|
|
tinsert(_detalhes_global.exit_log, " - " .. id .. " has baseFrame: " .. (instance.baseframe and "yes" or "no") .. ".")
|
|
if (instance.baseframe) then
|
|
instance.baseframe:SetUserPlaced (false)
|
|
instance.baseframe:SetDontSavePosition (true)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
xpcall(clearInstances, saver_error)
|
|
else
|
|
tinsert(_detalhes_global.exit_errors, 1, "not _detalhes.tabela_instancias")
|
|
tremove(_detalhes_global.exit_errors, 6)
|
|
addToExitErrors("not _detalhes.tabela_instancias")
|
|
end
|
|
|
|
--leave combat start save tables
|
|
if (_detalhes.in_combat and _detalhes.tabela_vigente) then
|
|
tinsert(_detalhes_global.exit_log, "3 - Leaving current combat.")
|
|
currentStep = "Leaving Current Combat"
|
|
xpcall(_detalhes.SairDoCombate, saver_error)
|
|
_detalhes.can_panic_mode = true
|
|
end
|
|
|
|
if (_detalhes.CheckSwitchOnLogon and _detalhes.tabela_instancias and _detalhes.tabela_instancias[1] and getmetatable(_detalhes.tabela_instancias[1])) then
|
|
tinsert(_detalhes_global.exit_log, "4 - Reversing switches.")
|
|
currentStep = "Check Switch on Logon"
|
|
xpcall(_detalhes.CheckSwitchOnLogon, saver_error)
|
|
end
|
|
|
|
if (_detalhes.wipe_full_config) then
|
|
tinsert(_detalhes_global.exit_log, "5 - Is a full config wipe.")
|
|
addToExitErrors("true: _detalhes.wipe_full_config")
|
|
_detalhes_global = nil
|
|
_detalhes_database = nil
|
|
return
|
|
end
|
|
|
|
--save the config
|
|
tinsert(_detalhes_global.exit_log, "6 - Saving Config.")
|
|
currentStep = "Saving Config"
|
|
xpcall(_detalhes.SaveConfig, saver_error)
|
|
|
|
tinsert(_detalhes_global.exit_log, "7 - Saving Profiles.")
|
|
currentStep = "Saving Profile"
|
|
xpcall(_detalhes.SaveProfile, saver_error)
|
|
|
|
--save the nicktag cache
|
|
tinsert(_detalhes_global.exit_log, "8 - Saving nicktag cache.")
|
|
|
|
local saveNicktabCache = function()
|
|
_detalhes_database.nick_tag_cache = Details.CopyTable(_detalhes_database.nick_tag_cache)
|
|
end
|
|
xpcall(saveNicktabCache, saver_error)
|
|
end)
|
|
|
|
-- ~parserstart ~startparser ~cleu ~parser
|
|
function _detalhes.OnParserEvent()
|
|
local time, token, hidding, who_serial, who_name, who_flags, who_flags2, target_serial, target_name, target_flags, target_flags2, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12 = CombatLogGetCurrentEventInfo()
|
|
|
|
local func = token_list[token]
|
|
if (func) then
|
|
return func(nil, token, time, who_serial, who_name, who_flags, target_serial, target_name, target_flags, target_flags2, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)
|
|
end
|
|
end
|
|
_detalhes.parser_frame:SetScript("OnEvent", _detalhes.OnParserEvent)
|
|
|
|
function _detalhes:UpdateParser()
|
|
_tempo = _detalhes._tempo
|
|
end
|
|
|
|
function _detalhes:UpdatePetsOnParser()
|
|
container_pets = _detalhes.tabela_pets.pets
|
|
end
|
|
|
|
function Details:GetActorFromCache(value)
|
|
return damage_cache[value] or damage_cache_pets[value] or damage_cache_petsOwners[value]
|
|
end
|
|
|
|
function _detalhes:PrintParserCacheIndexes()
|
|
local amount = 0
|
|
for n, nn in pairs(damage_cache) do
|
|
amount = amount + 1
|
|
end
|
|
print("parser damage_cache", amount)
|
|
|
|
amount = 0
|
|
for n, nn in pairs(damage_cache_pets) do
|
|
amount = amount + 1
|
|
end
|
|
print("parser damage_cache_pets", amount)
|
|
|
|
amount = 0
|
|
for n, nn in pairs(damage_cache_petsOwners) do
|
|
amount = amount + 1
|
|
end
|
|
print("parser damage_cache_petsOwners", amount)
|
|
|
|
amount = 0
|
|
for n, nn in pairs(healing_cache) do
|
|
amount = amount + 1
|
|
end
|
|
print("parser healing_cache", amount)
|
|
|
|
amount = 0
|
|
for n, nn in pairs(energy_cache) do
|
|
amount = amount + 1
|
|
end
|
|
print("parser energy_cache", amount)
|
|
|
|
amount = 0
|
|
for n, nn in pairs(misc_cache) do
|
|
amount = amount + 1
|
|
end
|
|
print("parser misc_cache", amount)
|
|
print("group damage", #_detalhes.cache_damage_group)
|
|
print("group damage", #_detalhes.cache_healing_group)
|
|
end
|
|
|
|
function _detalhes:GetActorsOnDamageCache()
|
|
return _detalhes.cache_damage_group
|
|
end
|
|
|
|
function _detalhes:GetActorsOnHealingCache()
|
|
return _detalhes.cache_healing_group
|
|
end
|
|
|
|
function _detalhes:ClearParserCache() --~wipe
|
|
wipe(damage_cache)
|
|
wipe(damage_cache_pets)
|
|
wipe(damage_cache_petsOwners)
|
|
wipe(healing_cache)
|
|
wipe(energy_cache)
|
|
wipe(misc_cache)
|
|
wipe(misc_cache_pets)
|
|
wipe(misc_cache_petsOwners)
|
|
wipe(npcid_cache)
|
|
wipe(enemy_cast_cache)
|
|
wipe(empower_cache)
|
|
|
|
wipe(ignore_death_cache)
|
|
|
|
wipe(reflection_damage)
|
|
wipe(reflection_debuffs)
|
|
wipe(reflection_events)
|
|
wipe(reflection_auras)
|
|
wipe(reflection_dispels)
|
|
|
|
wipe(dk_pets_cache.army)
|
|
wipe(dk_pets_cache.apoc)
|
|
|
|
wipe(cacheAnything.paladin_vivaldi_blessings)
|
|
|
|
cacheAnything.track_hunter_frenzy = Details.combat_log.track_hunter_frenzy
|
|
|
|
if (Details.combat_log.merge_gemstones_1007) then
|
|
--ring powers merged, https://gist.github.com/ljosberinn/65abe150133ff3a08cd70f840f7dd019 (by Gerrit Alex - WCL)
|
|
override_spellId[403225] = 404884 --Flame Licked Stone
|
|
override_spellId[404974] = 404884 --Shining Obsidian Stone
|
|
override_spellId[405220] = 404884 --Pestilent Plague Stone
|
|
override_spellId[405221] = 404884 --Pestilent Plague Stone
|
|
override_spellId[405209] = 404884 --Humming Arcane Stone
|
|
override_spellId[403391] = 404884 --Freezing Ice Stone
|
|
override_spellId[404911] = 404884 --Desirous Blood Stone
|
|
override_spellId[404941] = 404884 --Shining Obsidian Stone
|
|
override_spellId[403087] = 404884 --Storm Infused Stone
|
|
override_spellId[403273] = 404884 --Fel Flame via Entropic Fel Stone
|
|
override_spellId[403171] = 404884 --Uncontainable Charge via Echoing Thunder Stone
|
|
override_spellId[405235] = 404884 --Wild Spirit Stone
|
|
override_spellId[403381] = 404884 --Deluging Water Stone
|
|
override_spellId[405118] = 404884 --Exuding Steam Stone
|
|
override_spellId[403408] = 404884 --Exuding Steam Stone
|
|
override_spellId[403336] = 404884 --Indomitable Earth Stone
|
|
override_spellId[403392] = 404884 --Cold Frost Stone
|
|
override_spellId[403376] = 404884 --Gleaming Iron Stone
|
|
override_spellId[403253] = 404884 --Raging Magma Stone
|
|
override_spellId[403257] = 404884 --Searing Smokey Stone
|
|
else
|
|
override_spellId[403225] = nil --Flame Licked Stone
|
|
override_spellId[404974] = nil --Shining Obsidian Stone
|
|
override_spellId[405220] = nil --Pestilent Plague Stone
|
|
override_spellId[405221] = nil --Pestilent Plague Stone
|
|
override_spellId[405209] = nil --Humming Arcane Stone
|
|
override_spellId[403391] = nil --Freezing Ice Stone
|
|
override_spellId[404911] = nil --Desirous Blood Stone
|
|
override_spellId[404941] = nil --Shining Obsidian Stone
|
|
override_spellId[403087] = nil --Storm Infused Stone
|
|
override_spellId[403273] = nil --Fel Flame via Entropic Fel Stone
|
|
override_spellId[403171] = nil --Uncontainable Charge via Echoing Thunder Stone
|
|
override_spellId[405235] = nil --Wild Spirit Stone
|
|
override_spellId[403381] = nil --Deluging Water Stone
|
|
override_spellId[405118] = nil --Exuding Steam Stone
|
|
override_spellId[403408] = nil --Exuding Steam Stone
|
|
override_spellId[403336] = nil --Indomitable Earth Stone
|
|
override_spellId[403392] = nil --Cold Frost Stone
|
|
override_spellId[403376] = nil --Gleaming Iron Stone
|
|
override_spellId[403253] = nil --Raging Magma Stone
|
|
override_spellId[403257] = nil --Searing Smokey Stone
|
|
end
|
|
|
|
damage_cache = setmetatable({}, _detalhes.weaktable)
|
|
damage_cache_pets = setmetatable({}, _detalhes.weaktable)
|
|
damage_cache_petsOwners = setmetatable({}, _detalhes.weaktable)
|
|
|
|
healing_cache = setmetatable({}, _detalhes.weaktable)
|
|
|
|
energy_cache = setmetatable({}, _detalhes.weaktable)
|
|
|
|
misc_cache = setmetatable({}, _detalhes.weaktable)
|
|
misc_cache_pets = setmetatable({}, _detalhes.weaktable)
|
|
misc_cache_petsOwners = setmetatable({}, _detalhes.weaktable)
|
|
end
|
|
|
|
function parser:RevomeActorFromCache(actor_serial, actor_name)
|
|
if (actor_name) then
|
|
damage_cache[actor_name] = nil
|
|
damage_cache_pets[actor_name] = nil
|
|
damage_cache_petsOwners[actor_name] = nil
|
|
healing_cache[actor_serial] = nil
|
|
energy_cache[actor_name] = nil
|
|
misc_cache[actor_name] = nil
|
|
misc_cache_pets[actor_name] = nil
|
|
misc_cache_petsOwners[actor_name] = nil
|
|
end
|
|
|
|
if (actor_serial) then
|
|
damage_cache[actor_serial] = nil
|
|
damage_cache_pets[actor_serial] = nil
|
|
damage_cache_petsOwners[actor_serial] = nil
|
|
healing_cache[actor_serial] = nil
|
|
energy_cache[actor_serial] = nil
|
|
misc_cache[actor_serial] = nil
|
|
misc_cache_pets[actor_serial] = nil
|
|
misc_cache_petsOwners[actor_serial] = nil
|
|
end
|
|
end
|
|
|
|
function _detalhes:UptadeRaidMembersCache()
|
|
wipe(raid_members_cache)
|
|
wipe(tanks_members_cache)
|
|
wipe(auto_regen_cache)
|
|
wipe(bitfield_swap_cache)
|
|
wipe(empower_cache)
|
|
|
|
local groupRoster = _detalhes.tabela_vigente.raid_roster
|
|
|
|
if (IsInRaid()) then
|
|
local unitIdCache = Details222.UnitIdCache.Raid
|
|
|
|
for i = 1, GetNumGroupMembers() do
|
|
local unitId = unitIdCache[i]
|
|
local unitName = GetUnitName(unitId, true)
|
|
local unitGUID = UnitGUID(unitId)
|
|
|
|
local _, unitClass = UnitClass(unitId)
|
|
Details222.ClassCache.ByName[unitName] = unitClass
|
|
Details222.ClassCache.ByGUID[unitGUID] = unitClass
|
|
|
|
raid_members_cache[unitGUID] = unitName
|
|
groupRoster[unitName] = unitGUID
|
|
|
|
local role = _UnitGroupRolesAssigned(unitName)
|
|
if (role == "TANK") then
|
|
tanks_members_cache[unitGUID] = true
|
|
end
|
|
|
|
if (auto_regen_power_specs[_detalhes.cached_specs[unitGUID]]) then
|
|
auto_regen_cache[unitName] = auto_regen_power_specs[_detalhes.cached_specs[unitGUID]]
|
|
end
|
|
end
|
|
|
|
elseif (IsInGroup()) then
|
|
local unitIdCache = Details222.UnitIdCache.Party
|
|
for i = 1, GetNumGroupMembers()-1 do
|
|
local unitId = unitIdCache[i]
|
|
|
|
local unitName = GetUnitName(unitId, true)
|
|
local unitGUID = UnitGUID(unitId)
|
|
|
|
raid_members_cache[unitGUID] = unitName
|
|
groupRoster[unitName] = unitGUID
|
|
|
|
local role = _UnitGroupRolesAssigned(unitName)
|
|
if (role == "TANK") then
|
|
tanks_members_cache[unitGUID] = true
|
|
end
|
|
|
|
if (auto_regen_power_specs[_detalhes.cached_specs[unitGUID]]) then
|
|
auto_regen_cache[unitName] = auto_regen_power_specs[_detalhes.cached_specs[unitGUID]]
|
|
end
|
|
end
|
|
|
|
--player
|
|
local playerName = GetUnitName("player", true)
|
|
local playerGUID = UnitGUID("player")
|
|
|
|
raid_members_cache[playerGUID] = playerName
|
|
groupRoster[playerName] = playerGUID
|
|
|
|
local role = _UnitGroupRolesAssigned(playerName)
|
|
if (role == "TANK") then
|
|
tanks_members_cache[playerGUID] = true
|
|
end
|
|
|
|
if (auto_regen_power_specs[_detalhes.cached_specs[playerGUID]]) then
|
|
auto_regen_cache[playerName] = auto_regen_power_specs[_detalhes.cached_specs[playerGUID]]
|
|
end
|
|
else
|
|
local playerName = GetUnitName("player", true)
|
|
local playerGUID = UnitGUID("player")
|
|
|
|
raid_members_cache[playerGUID] = playerName
|
|
groupRoster[playerName] = playerGUID
|
|
|
|
local role = _UnitGroupRolesAssigned(playerName)
|
|
if (role == "TANK") then
|
|
tanks_members_cache[playerGUID] = true
|
|
else
|
|
local spec = DetailsFramework.GetSpecialization()
|
|
if (spec and spec ~= 0) then
|
|
if (DetailsFramework.GetSpecializationRole (spec) == "TANK") then
|
|
tanks_members_cache[playerGUID] = true
|
|
end
|
|
end
|
|
end
|
|
|
|
if (auto_regen_power_specs[_detalhes.cached_specs[playerGUID]]) then
|
|
auto_regen_cache[playerName] = auto_regen_power_specs[_detalhes.cached_specs[playerGUID]]
|
|
end
|
|
end
|
|
|
|
local orderNames = {}
|
|
for playerName in pairs(groupRoster) do
|
|
orderNames[#orderNames+1] = playerName
|
|
end
|
|
table.sort(orderNames, function(name1, name2)
|
|
return string.len(name1) > string.len(name2)
|
|
end)
|
|
_detalhes.tabela_vigente.raid_roster_indexed = orderNames
|
|
|
|
if (_detalhes.iam_a_tank) then
|
|
tanks_members_cache[UnitGUID("player")] = true
|
|
end
|
|
end
|
|
|
|
---return true or false
|
|
---@param unitGUID string
|
|
---@return boolean
|
|
function Details:IsATank(unitGUID)
|
|
return tanks_members_cache[unitGUID] or false
|
|
end
|
|
|
|
---returns the unit name
|
|
---@param unitGUID string
|
|
---@return string
|
|
function Details:IsInCache(unitGUID)
|
|
return raid_members_cache[unitGUID]
|
|
end
|
|
|
|
---return the internal raid members cache, containing the unitGUID as key and the unitName as value
|
|
---@return table
|
|
function Details:GetParserPlayerCache()
|
|
return raid_members_cache
|
|
end
|
|
|
|
--serach key: ~cache
|
|
function _detalhes:UpdateParserGears()
|
|
--refresh combat tables
|
|
_current_combat = _detalhes.tabela_vigente
|
|
|
|
--last events pointer
|
|
last_events_cache = _current_combat.player_last_events
|
|
_amount_of_last_events = _detalhes.deadlog_events
|
|
|
|
_use_shield_overheal = _detalhes.parser_options.shield_overheal
|
|
_is_activity_time = _detalhes.time_type == 1
|
|
shield_spellid_cache = _detalhes.shield_spellid_cache
|
|
|
|
--refresh total containers
|
|
_current_total = _current_combat.totals
|
|
_current_gtotal = _current_combat.totals_grupo
|
|
|
|
--refresh actors containers
|
|
_current_damage_container = _current_combat[1]
|
|
_current_heal_container = _current_combat[2]
|
|
_current_energy_container = _current_combat[3]
|
|
_current_misc_container = _current_combat[4]
|
|
|
|
--refresh data capture options
|
|
--_recording_self_buffs = _detalhes.RecordPlayerSelfBuffs --can be deprecated
|
|
--_recording_healing = _detalhes.RecordHealingDone --can be deprecated
|
|
--_recording_took_damage = _detalhes.RecordRealTimeTookDamage
|
|
--_recording_ability_with_buffs = _detalhes.RecordPlayerAbilityWithBuffs --can be deprecated
|
|
_in_combat = _detalhes.in_combat
|
|
|
|
wipe(ignored_npcids)
|
|
|
|
--fill it with the default npcs ignored
|
|
for npcId in pairs(_detalhes.default_ignored_npcs) do
|
|
ignored_npcids[npcId] = true
|
|
end
|
|
|
|
--fill it with the npcs the user ignored
|
|
for npcId in pairs(_detalhes.npcid_ignored) do
|
|
ignored_npcids[npcId] = true
|
|
end
|
|
ignored_npcids[0] = nil
|
|
|
|
if (_in_combat) then
|
|
if (Details.parser_options.energy_overflow) then
|
|
if (not Details.AutoRegenThread or Details.AutoRegenThread:IsCancelled()) then
|
|
Details.AutoRegenThread = C_Timer.NewTicker(AUTO_REGEN_PRECISION / 10, regen_power_overflow_check) --at the moment, runs 5 times per second
|
|
end
|
|
end
|
|
else
|
|
if (Details.AutoRegenThread and not Details.AutoRegenThread:IsCancelled()) then
|
|
Details.AutoRegenThread:Cancel()
|
|
Details.AutoRegenThread = nil
|
|
end
|
|
end
|
|
|
|
if (_detalhes.hooks["HOOK_COOLDOWN"].enabled) then
|
|
_hook_cooldowns = true
|
|
else
|
|
_hook_cooldowns = false
|
|
end
|
|
|
|
if (_detalhes.hooks["HOOK_DEATH"].enabled) then
|
|
_hook_deaths = true
|
|
else
|
|
_hook_deaths = false
|
|
end
|
|
|
|
if (_detalhes.hooks["HOOK_BATTLERESS"].enabled) then
|
|
_hook_battleress = true
|
|
else
|
|
_hook_battleress = false
|
|
end
|
|
|
|
if (_detalhes.hooks["HOOK_INTERRUPT"].enabled) then
|
|
_hook_interrupt = true
|
|
else
|
|
_hook_interrupt = false
|
|
end
|
|
|
|
is_using_spellId_override = _detalhes.override_spellids
|
|
|
|
return _detalhes:ClearParserCache()
|
|
end
|
|
|
|
function _detalhes.DumpIgnoredNpcs()
|
|
return ignored_npcids
|
|
end
|
|
|
|
|
|
|
|
--serach key: ~api
|
|
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--details api functions
|
|
|
|
--number of combat
|
|
function Details:GetCombatId()
|
|
return Details.combat_id
|
|
end
|
|
|
|
--if in combat
|
|
function Details:IsInCombat()
|
|
return _in_combat
|
|
end
|
|
|
|
function Details:IsInEncounter()
|
|
return Details.encounter_table.id and true or false
|
|
end
|
|
|
|
function Details:GetAllActors(_combat, _actorname)
|
|
return Details:GetActor(_combat, 1, _actorname), Details:GetActor(_combat, 2, _actorname), Details:GetActor(_combat, 3, _actorname), Details:GetActor(_combat, 4, _actorname)
|
|
end
|
|
|
|
--get player
|
|
function Details:GetPlayer(_actorname, _combat, _attribute)
|
|
return Details:GetActor(_combat, _attribute, _actorname)
|
|
end
|
|
|
|
--get an actor
|
|
function Details:GetActor(combat, attribute, actorName)
|
|
if (not combat) then
|
|
combat = "current" --current combat
|
|
end
|
|
|
|
if (not attribute) then
|
|
attribute = 1 --damage
|
|
end
|
|
|
|
if (not actorName) then
|
|
actorName = Details.playername
|
|
end
|
|
|
|
if (combat == 0 or combat == "current") then
|
|
local actor = Details.tabela_vigente(attribute, actorName)
|
|
if (actor) then
|
|
return actor
|
|
else
|
|
return nil
|
|
end
|
|
|
|
elseif (combat == -1 or combat == "overall") then
|
|
local actor = Details.tabela_overall(attribute, actorName)
|
|
if (actor) then
|
|
return actor
|
|
else
|
|
return nil
|
|
end
|
|
|
|
elseif (type(combat) == "number") then
|
|
local combatTables = Details.tabela_historico.tabelas[combat]
|
|
if (combatTables) then
|
|
local actor = combatTables(attribute, actorName)
|
|
if (actor) then
|
|
return actor
|
|
else
|
|
return nil
|
|
end
|
|
else
|
|
return nil
|
|
end
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
|
|
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--battleground parser
|
|
|
|
_detalhes.pvp_parser_frame:SetScript("OnEvent", function(self, event)
|
|
self:ReadPvPData()
|
|
end)
|
|
|
|
function _detalhes:BgScoreUpdate()
|
|
RequestBattlefieldScoreData()
|
|
end
|
|
|
|
--start the virtual parser
|
|
function _detalhes.pvp_parser_frame:StartBgUpdater()
|
|
_detalhes.pvp_parser_frame:RegisterEvent("UPDATE_BATTLEFIELD_SCORE")
|
|
|
|
if (_detalhes.pvp_parser_frame.ticker) then
|
|
Details.Schedules.Cancel(_detalhes.pvp_parser_frame.ticker)
|
|
end
|
|
|
|
_detalhes.pvp_parser_frame.ticker = Details.Schedules.NewTicker(10, Details.BgScoreUpdate)
|
|
Details.Schedules.SetName(_detalhes.pvp_parser_frame.ticker, "Battleground Updater")
|
|
end
|
|
|
|
--stop the virtual parser
|
|
function _detalhes.pvp_parser_frame:StopBgUpdater()
|
|
_detalhes.pvp_parser_frame:UnregisterEvent("UPDATE_BATTLEFIELD_SCORE")
|
|
Details.Schedules.Cancel(_detalhes.pvp_parser_frame.ticker)
|
|
_detalhes.pvp_parser_frame.ticker = nil
|
|
end
|
|
|
|
function _detalhes.pvp_parser_frame:ReadPvPData()
|
|
local players = GetNumBattlefieldScores()
|
|
|
|
for i = 1, players do
|
|
local name, killingBlows, honorableKills, deaths, honorGained, faction, race, rank, class, classToken, damageDone, healingDone, bgRating, ratingChange, preMatchMMR, mmrChange, talentSpec
|
|
if (isWOTLK) then
|
|
name, killingBlows, honorableKills, deaths, honorGained, faction, rank, race, class, classToken, damageDone, healingDone, bgRating, ratingChange, preMatchMMR, mmrChange, talentSpec = GetBattlefieldScore(i)
|
|
else
|
|
name, killingBlows, honorableKills, deaths, honorGained, faction, race, class, classToken, damageDone, healingDone, bgRating, ratingChange, preMatchMMR, mmrChange, talentSpec = GetBattlefieldScore(i)
|
|
end
|
|
|
|
--damage done
|
|
local actor = _detalhes.tabela_vigente(1, name)
|
|
if (actor) then
|
|
if (damageDone == 0) then
|
|
damageDone = damageDone + _detalhes:GetOrderNumber()
|
|
end
|
|
actor.total = damageDone
|
|
actor.classe = classToken or "UNKNOW"
|
|
|
|
elseif (name ~= "Unknown" and type(name) == "string" and string.len(name) > 1) then
|
|
local guid = UnitGUID(name)
|
|
if (guid) then
|
|
local flag
|
|
if (_detalhes.faction_id == faction) then --is from the same faction
|
|
flag = 0x514
|
|
else
|
|
flag = 0x548
|
|
end
|
|
|
|
actor = _current_damage_container:PegarCombatente (guid, name, flag, true)
|
|
actor.total = _detalhes:GetOrderNumber()
|
|
actor.classe = classToken or "UNKNOW"
|
|
|
|
if (flag == 0x548) then
|
|
--oponent
|
|
actor.enemy = true
|
|
end
|
|
end
|
|
end
|
|
|
|
--healing done
|
|
local actor = _detalhes.tabela_vigente(2, name)
|
|
if (actor) then
|
|
if (healingDone == 0) then
|
|
healingDone = healingDone + _detalhes:GetOrderNumber()
|
|
end
|
|
actor.total = healingDone
|
|
actor.classe = classToken or "UNKNOW"
|
|
|
|
elseif (name ~= "Unknown" and type(name) == "string" and string.len(name) > 1) then
|
|
local guid = UnitGUID(name)
|
|
if (guid) then
|
|
local flag
|
|
if (_detalhes.faction_id == faction) then --is from the same faction
|
|
flag = 0x514
|
|
else
|
|
flag = 0x548
|
|
end
|
|
|
|
actor = _current_heal_container:PegarCombatente (guid, name, flag, true)
|
|
actor.total = _detalhes:GetOrderNumber()
|
|
actor.classe = classToken or "UNKNOW"
|
|
|
|
if (flag == 0x548) then
|
|
--oponent
|
|
actor.enemy = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|