-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local _detalhes = _G.Details
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 isERA = DetailsFramework.IsClassicWow ( )
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 = { }
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 ] = spellTable
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
}
--all totem
--377461 382133
--377458 377459
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
---@type trinketdata
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
if ( _current_combat.trinketProcs ) then
local playerTrinketData = _current_combat.trinketProcs [ sourceName ] or { }
_current_combat.trinketProcs [ sourceName ] = playerTrinketData
local trinketData = playerTrinketData [ spellId ] or { cooldown = 0 , total = 0 }
playerTrinketData [ spellId ] = trinketData
if ( trinketData.cooldown < time ) then
trinketData.cooldown = time + 20
trinketData.total = trinketData.total + 1
end
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 - 00001 A8313 , " Greater Fire Elemental " , 0x2112 , 0x0 , Creature - 0 - 4391 - 615 - 3107 - 28860 - 00001 A8258 , " Sartharion " , 0xa48 , 0x0 , Creature - 0 - 4391 - 615 - 3107 - 15438 - 00001 A8313 , Creature - 0 - 4391 - 615 - 3107 - 15439 - 00001 A8313 , 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 - 00001 A8313 , " Greater Fire Elemental " , 0x2112 , 0x0 , Creature - 0 - 4391 - 615 - 3107 - 28860 - 00001 A8258 , " Sartharion " , 0xa48 , 0x0 , 57984 , " Fire Blast " , 0x4 , Creature - 0 - 4391 - 615 - 3107 - 15438 - 00001 A8313 , Creature - 0 - 4391 - 615 - 3107 - 15439 - 00001 A8313 , 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 - 00001 A8313 , " Fire Elemental Totem " , 0x2112 , 0x0 , 0000000000000000 , nil , 0x80000000 , 0x80000000 , 32982 , " Fire Elemental Totem " , 0x1 , Creature - 0 - 4391 - 615 - 3107 - 15439 - 00001 A8313 , 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 - 00001 A8313 , " Fire Elemental Totem " , 0x2112 , 0x0 , Creature - 0 - 4391 - 615 - 3107 - 15438 - 00001 A8313 , " 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 or isERA ) 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
spellTable.spellschool = spellType
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
---comment: this function is called when a spell is casted
---@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 targetRaidFlags number
---@param spellId number
---@param spellName string
---@param spellType number
function parser : spellcast ( token , time , sourceSerial , sourceName , sourceFlags , targetSerial , targetName , targetFlags , targetRaidFlags , spellId , spellName , spellType )
--only capture if is in combat
if ( not _in_combat ) then
return
end
if ( not sourceName ) then
sourceName = " [*] " .. spellName
end
---@type actor, actor
local sourceActor , ownerActor = misc_cache [ sourceSerial ] or misc_cache_pets [ sourceSerial ] or misc_cache [ sourceName ] , misc_cache_petsOwners [ sourceSerial ]
if ( not sourceActor ) then
sourceActor , ownerActor , sourceName = _current_misc_container : PegarCombatente ( sourceSerial , sourceName , sourceFlags , true )
if ( ownerActor ) then
if ( sourceSerial ~= " " ) then
misc_cache_pets [ sourceSerial ] = sourceActor
misc_cache_petsOwners [ sourceSerial ] = ownerActor
end
if ( not misc_cache [ ownerActor.serial ] and ownerActor.serial ~= " " ) then
misc_cache [ ownerActor.serial ] = ownerActor
end
else
if ( sourceFlags ) then
misc_cache [ sourceName ] = sourceActor
end
end
end
------------------------------------------------------------------------------------------------
--build containers on the fly
--amount of casts by actors ~casts
local castsByPlayer = _current_combat.amountCasts [ sourceName ]
if ( not castsByPlayer ) then
castsByPlayer = { }
_current_combat.amountCasts [ sourceName ] = castsByPlayer
end
local amountOfCasts = _current_combat.amountCasts [ sourceName ] [ spellName ] or 0
amountOfCasts = amountOfCasts + 1
_current_combat.amountCasts [ sourceName ] [ spellName ] = amountOfCasts
--if (sourceSerial == UnitGUID("player")) then
-- print(sourceName, spellName, amountOfCasts)
--end
------------------------------------------------------------------------------------------------
--record cooldowns cast which can't track with buff applyed
--a player is the caster
if ( raid_members_cache [ sourceSerial ] ) then
--check if is a cooldown
local cooldownInfo = defensive_cooldowns [ spellId ]
if ( cooldownInfo ) then
if ( not targetName ) then
if ( cooldownInfo.type == 2 or cooldownInfo.type == 3 ) then
targetName = sourceName
elseif ( cooldownInfo.type == 4 ) then
targetName = Loc [ " STRING_RAID_WIDE " ]
else
targetName = " --x--x-- "
end
end
return parser : add_defensive_cooldown ( token , time , sourceSerial , sourceName , sourceFlags , targetSerial , targetName , targetFlags , targetRaidFlags , spellId , spellName )
end
else
--enemy successful casts (not interrupted)
if ( bitBand ( sourceFlags , 0x00000040 ) ~= 0 and sourceName ) then --byte 2 = 4 (enemy)
--damager
---@type actor
local enemyActorObject = damage_cache [ sourceSerial ]
if ( not enemyActorObject ) then
enemyActorObject = _current_damage_container : PegarCombatente ( sourceSerial , sourceName , sourceFlags , true )
end
if ( enemyActorObject ) then
--actor spells table
---@type spelltable
local spellTable = enemyActorObject.spells . _ActorTable [ spellId ]
if ( not spellTable ) then
spellTable = enemyActorObject.spells : PegaHabilidade ( spellId , true , token )
end
spellTable.successful_casted = spellTable.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 = sourceName
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
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
local okay , errorText = pcall ( function ( )
local mapChallengeModeID , mythicLevel , time , onTime , keystoneUpgradeLevels , practiceRun , oldOverallDungeonScore , newOverallDungeonScore , IsMapRecord , IsAffixRecord , PrimaryAffix , isEligibleForScore , members = C_ChallengeMode.GetCompletionInfo ( )
if ( mapChallengeModeID ) then
local statName = " mythicdungeoncompletedDF2 "
local mythicDungeonRuns = Details222.PlayerStats : GetStat ( statName )
mythicDungeonRuns = mythicDungeonRuns or { }
mythicDungeonRuns [ mapChallengeModeID ] = mythicDungeonRuns [ mapChallengeModeID ] or { }
mythicDungeonRuns [ mapChallengeModeID ] [ mythicLevel ] = mythicDungeonRuns [ mapChallengeModeID ] [ mythicLevel ] or { }
local currentRun = mythicDungeonRuns [ mapChallengeModeID ] [ mythicLevel ]
currentRun.completed = ( currentRun.completed or 0 ) + 1
currentRun.totalTime = ( currentRun.totalTime or 0 ) + time
if ( not currentRun.minTime or time < currentRun.minTime ) then
currentRun.minTime = time
end
currentRun.history = currentRun.history or { }
local day , month , year = tonumber ( date ( " %d " ) ) , tonumber ( date ( " %m " ) ) , tonumber ( date ( " %Y " ) )
local amountDeaths = C_ChallengeMode.GetDeathCount ( ) or 0
tinsert ( currentRun.history , { day = day , month = month , year = year , runTime = time , onTime = onTime , deaths = amountDeaths , affix = PrimaryAffix } )
Details222.PlayerStats : SetStat ( " mythicdungeoncompletedDF2 " , mythicDungeonRuns )
end
end )
if ( not okay ) then
_detalhes : Msg ( " something went wrong (0x7878): " , errorText )
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. \n If you just updated the addon, please reboot the game client. \n We 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.CloseBreakdownWindow ) then
tinsert ( _detalhes_global.exit_log , " 1 - Closing Janela Info. " )
currentStep = " Fecha Janela Info "
xpcall ( _detalhes.CloseBreakdownWindow , 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 )
local eraNamedSpellsToID = { }
-- ~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
function _detalhes . OnParserEventClassicEra ( )
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
if ( eraNamedSpellsToID [ token ] ) then
A1 = A2
end
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
if ( isERA ) then
eraNamedSpellsToID = {
[ " SPELL_PERIODIC_DAMAGE " ] = true ,
[ " SPELL_DAMAGE " ] = true ,
[ " SPELL_BUILDING_DAMAGE " ] = true ,
[ " DAMAGE_SHIELD " ] = true ,
[ " DAMAGE_SPLIT " ] = true ,
[ " SPELL_MISSED " ] = true ,
[ " SPELL_PERIODIC_MISSED " ] = true ,
[ " SPELL_BUILDING_MISSED " ] = true ,
[ " DAMAGE_SHIELD_MISSED " ] = true ,
[ " SPELL_HEAL " ] = true ,
[ " SPELL_PERIODIC_HEAL " ] = true ,
[ " SPELL_HEAL_ABSORBED " ] = true ,
[ " SPELL_ABSORBED " ] = true ,
[ " SPELL_AURA_APPLIED " ] = true ,
[ " SPELL_AURA_REMOVED " ] = true ,
[ " SPELL_AURA_REFRESH " ] = true ,
[ " SPELL_AURA_APPLIED_DOSE " ] = true ,
[ " SPELL_ENERGIZE " ] = true ,
[ " SPELL_PERIODIC_ENERGIZE " ] = true ,
[ " SPELL_CAST_SUCCESS " ] = true ,
[ " SPELL_DISPEL " ] = true ,
[ " SPELL_STOLEN " ] = true ,
[ " SPELL_AURA_BROKEN " ] = true ,
[ " SPELL_AURA_BROKEN_SPELL " ] = true ,
[ " SPELL_RESURRECT " ] = true ,
[ " SPELL_INTERRUPT " ] = true ,
}
_detalhes.parser_frame : SetScript ( " OnEvent " , _detalhes.OnParserEventClassicEra )
else
_detalhes.parser_frame : SetScript ( " OnEvent " , _detalhes.OnParserEvent )
end
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
if ( Details.combat_log . merge_critical_heals ) then
override_spellId [ 94472 ] = 81751 --disc priest attonement and crit. Crits use separate id.
override_spellId [ 281469 ] = 270501 --disc priest contrition attonement and crit. Crits use separate id.
override_spellId [ 388025 ] = 388024 --MW monk Ancient Teachings, heals from damage, crit and normal are separate.
override_spellId [ 389325 ] = 389328 --MW monk Awakened Faeline, ^
else
override_spellId [ 94472 ] = nil --disc priest attonement and crit. Crits use separate id.
override_spellId [ 281469 ] = nil --disc priest contrition attonement and crit. Crits use separate id.
override_spellId [ 388025 ] = nil --MW monk Ancient Teachings, heals from damage, crit and normal are separate.
override_spellId [ 389325 ] = nil --MW monk Awakened Faeline, ^
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
function Details : GetUnitId ( unitName )
unitName = unitName or self.nome
local openRaidLib = LibStub : GetLibrary ( " LibOpenRaid-1.0 " , true )
if ( openRaidLib ) then
local unitId = openRaidLib.GetUnitID ( unitName )
if ( unitId ) then
return unitId
end
end
if ( IsInRaid ( ) ) then
for i = 1 , GetNumGroupMembers ( ) do
local unitId = " raid " .. i
if ( GetUnitName ( unitId , true ) == unitName ) then
return unitId
end
end
elseif ( IsInGroup ( ) ) then
for i = 1 , GetNumGroupMembers ( ) - 1 do
local unitId = " party " .. i
if ( GetUnitName ( unitId , true ) == unitName ) then
return unitId
end
end
if ( UnitName ( " player " ) == unitName ) then
return " player "
end
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