diff --git a/Definitions.lua b/Definitions.lua index 88f23114..d987b3ee 100644 --- a/Definitions.lua +++ b/Definitions.lua @@ -327,12 +327,15 @@ ---@field amountCasts {[string]: table} ---@field end_time number ---@field start_time number +---@field overall_added boolean is true when the combat got added into the overall combat ---@field is_mythic_dungeon_trash boolean ---@field is_mythic_dungeon_run_id number ---@field is_mythic_dungeon_segment boolean ---@field trinketProcs table> ----@field GetPhases fun(combat: combat) : table ---@field alternate_power table +---@field totals {key1: table, key2: table, key3: table, key3: table} +---@field totals_grupo {key1: table, key2: table, key3: table, key3: table} +---@field GetPhases fun(combat: combat) : table ---@field GetCombatTime fun(combat) : number ---@field GetDeaths fun(combat) : table --get the table which contains the deaths of the combat ---@field GetStartTime fun(combat: combat) : number @@ -348,9 +351,9 @@ ---@field GetActor fun(combat: combat, attribute: number, playerName: string) : actor ---@field CreateAlternatePowerTable fun(combat: combat, actorName: string) : alternatepowertable ----@class actorcontainer : table ----@field _ActorTable table ----@field _NameIndexTable table +---@class actorcontainer : table contains two tables _ActorTable and _NameIndexTable, the _ActorTable contains the actors, the _NameIndexTable contains the index of the actors in the _ActorTable, making quick to reorder them without causing overhead +---@field _ActorTable table array of actors +---@field _NameIndexTable table [actorName] = actorIndex in the _ActorTable, actorcontainer:Remap() refreshes the _NameIndexTable ---@field GetActor fun(container: actorcontainer, actorName: string) get an actor by its name ---@field GetSpellSource fun(container: actorcontainer, spellId: number) get the first actor found which casted the spell ---@field GetAmount fun(container: actorcontainer, actorName: string, key: string) get the amount of actor[key] @@ -360,13 +363,16 @@ ---@field ListActors fun(container: actorcontainer) usage: for index, actorObject in container:ListActors() do ---@field RemoveActor fun(container: actorcontainer, actor: actor) remove an actor from the container ---@field GetType fun(container: actorcontainer) : number get the container type, 1 for damage, 2 for heal, 3 for energy, 4 for utility +---@field Remap fun(container: actorcontainer) refreshes the _NameIndexTable part of the container +---@field Cleanup fun(container: actorcontainer) remove all destroyed actors from the container ---@class spellcontainer : table ---@field _ActorTable table store [spellId] = spelltable ----@field GetSpell fun(container: spellcontainer, spellId: number) get a spell by its id +---@field GetSpell fun(container: spellcontainer, spellId: number) get a spell by its id, does not create if not found ---@field ListActors fun(container: spellcontainer) : any, any usage: for spellId, spelltable in container:ListActors() do ---@field ListSpells fun(container: spellcontainer) : any, any usage: for spellId, spelltable in container:ListActors() do ---@field HasTwoOrMoreSpells fun(container: spellcontainer) : boolean return true if the container has two or more spells +---@field GetOrCreateSpell fun(self: spellcontainer, spellId: number, bCanCreateSpellIfMissing: boolean|nil, cleuToken: string|nil) : spelltable ---@class friendlyfiretable : table ---@field total number total amount of friendly fire caused by the actor @@ -388,6 +394,7 @@ ---@field targets table store the [target name] = total value ---@field targets_overheal table ---@field targets_absorbs table +---@field extra table store extra data ---@field id number --spellid ---@field is_shield boolean --true if the spell is a shield ---@field successful_casted number successful casted times (only for enemies) @@ -413,15 +420,23 @@ ---@class targettable : {[string]: number} ---@class actor : table ----@field BuildSpellTargetFromBreakdownSpellData fun(actor: actor, bkSpellData: spelltableadv) : table ----@field BuildSpellTargetFromSpellTable fun(actor: actor, spellTable: spelltable) : table +---@field owner actor +---@field ownerName string name of the owner of the pet, a pet without an owner is considered an orphan and be suitable for garbage collection +---@field pets table +---@field arena_enemy boolean if true the actor is an enemy in an arena match +---@field start_time unixtime when this actor started to be tracked +---@field end_time number when this actor stopped to be tracked, end_time - start_time is the activity time of the actor +---@field displayName string actor name shown in the regular window +---@field pvp boolean indicates if the actor is a part of a pvp match +---@field flag_original number original actor flag from what was received in the combat log ---@field debuff_uptime_spells table ---@field buff_uptime_spells table ----@field spells table ----@field aID number|string +---@field spells spellcontainer +---@field aID number|string actorID is a realm-playername or npcID ---@field spellicon number|string ---@field cooldowns_defensive_spells table ----@field nome string +---@field nome string name of the actor +---@field isTank boolean if true the player had the spec TANK during the combat ---@field serial string ---@field spec number ---@field grupo boolean @@ -432,8 +447,10 @@ ---@field last_event unixtime ---@field total_without_pet number ---@field total number ----@field pets table ---@field targets targettable +---@field BuildSpellTargetFromBreakdownSpellData fun(actor: actor, bkSpellData: spelltableadv) : table +---@field BuildSpellTargetFromSpellTable fun(actor: actor, spellTable: spelltable) : table +---@field raid_targets table ---@field GetSpellContainer fun(actor: actor, containerType: "debuff"|"buff"|"spell"|"cooldowns") : spellcontainer ---@field Class fun(actor: actor) : string get the ingame class of the actor ---@field Spec fun(actor: actor) : string get the ingame spec of the actor @@ -446,12 +463,25 @@ ---@class actordamage : actor ---@field friendlyfire_total number ---@field friendlyfire friendlyfiretable ----@field damage_taken number amount of damage the actor took durent the segment +---@field damage_taken number amount of damage the actor took during the segment ---@field damage_from table store the name of the actors which damaged the actor, format: [actorName] = true +---@field totalabsorbed number amount of damage dealt by the actor by got absorbed by the target, this is a "ABSORB" type of miss but still counts as damage done ---@class actorheal : actor +---@field healing_taken number amount of healing the actor took during the segment +---@field totalover number amount of healing that was overhealed +---@field totalabsorb number amount of healing that was absorbed +---@field heal_enemy_amt number amount of healing done to enemies this included enemy to enemy heals +---@field totaldenied number amount of healing that was denied by the target - from cleu event SPELL_HEAL_ABSORBED +---@field totalover_without_pet number amount of healing that was overhealed without the pet healing +---@field healing_from table store the name of the actors which healed the actor, format: [actorName] = true +---@field heal_enemy table store the amount of healing done by each spell that landed into an enemy, format: [spellId] = healing done +---@field targets_overheal table [targetName] = overheal +---@field targets_absorbs table [targetName] = absorbs ----@class actorenergy : actor +---@class actorresource : actor +---@field powertype number power type of the actor +---@field alternatepower number alternate power of the actor ---@class actorutility : actor ---@field cc_break number amount of times the actor broke a cc @@ -462,6 +492,9 @@ ---@field cooldowns_defensive number amount of times the actor used a defensive cooldown ---@field buff_uptime number amount of time the actor had a buff ---@field debuff_uptime number amount of time the actor had a debuff +---@field cc_done number amount of times the actor applyed a crowdcontrol on a target +---@field cc_done_targets table [targetName] = amount of times the actor cc'd the target +---@field cc_done_spells spellcontainer --interrupt_targets interrupt_spells interrompeu_oque --cc_break_targets cc_break_spells cc_break_oque diff --git a/boot.lua b/boot.lua index b41e1a7f..2f67c9bd 100644 --- a/boot.lua +++ b/boot.lua @@ -20,7 +20,7 @@ Details.dont_open_news = true Details.game_version = version Details.userversion = version .. " " .. Details.build_counter - Details.realversion = 152 --core version, this is used to check API version for scripts and plugins (see alias below) + Details.realversion = 153 --core version, this is used to check API version for scripts and plugins (see alias below) Details.APIVersion = Details.realversion --core version Details.version = Details.userversion .. " (core " .. Details.realversion .. ")" --simple stirng to show to players @@ -67,6 +67,7 @@ Details222.PlayerBreakdown = { DamageSpellsCache = {} } + --namespace color Details222.ColorScheme = { ["gradient-background"] = {0.1215, 0.1176, 0.1294, 0.8}, @@ -74,6 +75,7 @@ function Details222.ColorScheme.GetColorFor(colorScheme) return Details222.ColorScheme[colorScheme] end + --namespace for damage spells (spellTable) Details222.DamageSpells = {} --namespace for texture @@ -93,6 +95,20 @@ Details222.BreakdownWindow = {} Details222.PlayerStats = {} Details222.LoadSavedVariables = {} + Details222.SaveVariables = {} + + Details222.Date = { + GetDateForLogs = function() + return _G.date("%Y-%m-%d %H:%M:%S") + end, + } + + Details222.ClassCache = {} + Details222.ClassCache.ByName = {} + Details222.ClassCache.ByGUID = {} + Details222.UnitIdCache = {} + + Details222.Actors = {} ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --initialization stuff @@ -1074,27 +1090,26 @@ do _G ["BINDING_NAME_DETAILS_SCROLL_UP"] = Loc ["STRING_KEYBIND_SCROLL_UP"] _G ["BINDING_NAME_DETAILS_SCROLL_DOWN"] = Loc ["STRING_KEYBIND_SCROLL_DOWN"] - _G ["BINDING_NAME_DETAILS_REPORT_WINDOW1"] = format(Loc ["STRING_KEYBIND_WINDOW_REPORT"], 1) - _G ["BINDING_NAME_DETAILS_REPORT_WINDOW2"] = format(Loc ["STRING_KEYBIND_WINDOW_REPORT"], 2) + _G ["BINDING_NAME_DETAILS_REPORT_WINDOW1"] = string.format(Loc ["STRING_KEYBIND_WINDOW_REPORT"], 1) + _G ["BINDING_NAME_DETAILS_REPORT_WINDOW2"] = string.format(Loc ["STRING_KEYBIND_WINDOW_REPORT"], 2) - _G ["BINDING_NAME_DETAILS_TOOGGLE_WINDOW1"] = format(Loc ["STRING_KEYBIND_TOGGLE_WINDOW"], 1) - _G ["BINDING_NAME_DETAILS_TOOGGLE_WINDOW2"] = format(Loc ["STRING_KEYBIND_TOGGLE_WINDOW"], 2) - _G ["BINDING_NAME_DETAILS_TOOGGLE_WINDOW3"] = format(Loc ["STRING_KEYBIND_TOGGLE_WINDOW"], 3) - _G ["BINDING_NAME_DETAILS_TOOGGLE_WINDOW4"] = format(Loc ["STRING_KEYBIND_TOGGLE_WINDOW"], 4) - _G ["BINDING_NAME_DETAILS_TOOGGLE_WINDOW5"] = format(Loc ["STRING_KEYBIND_TOGGLE_WINDOW"], 5) + _G ["BINDING_NAME_DETAILS_TOOGGLE_WINDOW1"] = string.format(Loc ["STRING_KEYBIND_TOGGLE_WINDOW"], 1) + _G ["BINDING_NAME_DETAILS_TOOGGLE_WINDOW2"] = string.format(Loc ["STRING_KEYBIND_TOGGLE_WINDOW"], 2) + _G ["BINDING_NAME_DETAILS_TOOGGLE_WINDOW3"] = string.format(Loc ["STRING_KEYBIND_TOGGLE_WINDOW"], 3) + _G ["BINDING_NAME_DETAILS_TOOGGLE_WINDOW4"] = string.format(Loc ["STRING_KEYBIND_TOGGLE_WINDOW"], 4) + _G ["BINDING_NAME_DETAILS_TOOGGLE_WINDOW5"] = string.format(Loc ["STRING_KEYBIND_TOGGLE_WINDOW"], 5) - _G ["BINDING_NAME_DETAILS_BOOKMARK1"] = format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 1) - _G ["BINDING_NAME_DETAILS_BOOKMARK2"] = format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 2) - _G ["BINDING_NAME_DETAILS_BOOKMARK3"] = format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 3) - _G ["BINDING_NAME_DETAILS_BOOKMARK4"] = format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 4) - _G ["BINDING_NAME_DETAILS_BOOKMARK5"] = format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 5) - _G ["BINDING_NAME_DETAILS_BOOKMARK6"] = format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 6) - _G ["BINDING_NAME_DETAILS_BOOKMARK7"] = format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 7) - _G ["BINDING_NAME_DETAILS_BOOKMARK8"] = format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 8) - _G ["BINDING_NAME_DETAILS_BOOKMARK9"] = format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 9) - _G ["BINDING_NAME_DETAILS_BOOKMARK10"] = format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 10) + _G ["BINDING_NAME_DETAILS_BOOKMARK1"] = string.format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 1) + _G ["BINDING_NAME_DETAILS_BOOKMARK2"] = string.format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 2) + _G ["BINDING_NAME_DETAILS_BOOKMARK3"] = string.format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 3) + _G ["BINDING_NAME_DETAILS_BOOKMARK4"] = string.format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 4) + _G ["BINDING_NAME_DETAILS_BOOKMARK5"] = string.format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 5) + _G ["BINDING_NAME_DETAILS_BOOKMARK6"] = string.format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 6) + _G ["BINDING_NAME_DETAILS_BOOKMARK7"] = string.format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 7) + _G ["BINDING_NAME_DETAILS_BOOKMARK8"] = string.format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 8) + _G ["BINDING_NAME_DETAILS_BOOKMARK9"] = string.format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 9) + _G ["BINDING_NAME_DETAILS_BOOKMARK10"] = string.format(Loc ["STRING_KEYBIND_BOOKMARK_NUMBER"], 10) --]=] - end if (select(4, GetBuildInfo()) >= 100000) then @@ -1109,10 +1124,6 @@ if (select(4, GetBuildInfo()) >= 100000) then end) end -Details222.ClassCache = {} -Details222.ClassCache.ByName = {} -Details222.ClassCache.ByGUID = {} - function Details222.ClassCache.GetClass(value) local className = Details222.ClassCache.ByName[value] or Details222.ClassCache.ByGUID[value] if (className) then @@ -1138,7 +1149,6 @@ function Details222.ClassCache.MakeCache() end end -Details222.UnitIdCache = {} Details222.UnitIdCache.Raid = { [1] = "raid1", [2] = "raid2", @@ -1238,6 +1248,17 @@ function Details:Destroy(object, key) end end +function Details:DestroyCombat(combatObject) + setmetatable(combatObject, nil) + combatObject.__index = nil + combatObject.__newindex = nil + combatObject.__call = nil + Details:Destroy(combatObject) + --leave a trace that the actor has been deleted + combatObject.__destroyed = true + combatObject.__destroyedBy = debugstack(2, 1, 0) +end + ---destroy the actor, also calls container:RemoveActor(actor) ---@param self details ---@param actorObject actor @@ -1248,109 +1269,119 @@ function Details:DestroyActor(actorObject, actorContainer, combatObject) local combatTotalsTable = combatObject.totals[containerType] --without group local combatTotalsTableInGroup = combatObject.totals_grupo[containerType] --with group - if (containerType == 1 or containerType == 2) then --damage|healing done - combatTotalsTable = combatTotalsTable - actorObject.total - if (actorObject.grupo) then - combatTotalsTableInGroup = combatTotalsTableInGroup - actorObject.total - end + if (not actorObject.ownerName) then --not a pet + if (containerType == 1 or containerType == 2) then --damage|healing done + combatTotalsTable = combatTotalsTable - actorObject.total + if (actorObject.grupo) then + combatTotalsTableInGroup = combatTotalsTableInGroup - actorObject.total + end - elseif (containerType == 3) then - if (actorObject.total and actorObject.total > 0) then - if (actorObject.powertype) then - combatTotalsTable[actorObject.powertype] = combatTotalsTable[actorObject.powertype] - actorObject.total - combatTotalsTableInGroup[actorObject.powertype] = combatTotalsTableInGroup[actorObject.powertype] - actorObject.total + elseif (containerType == 3) then + ---@cast actorObject actorresource + if (actorObject.total and actorObject.total > 0) then + if (actorObject.powertype) then + combatTotalsTable[actorObject.powertype] = combatTotalsTable[actorObject.powertype] - actorObject.total + combatTotalsTableInGroup[actorObject.powertype] = combatTotalsTableInGroup[actorObject.powertype] - actorObject.total + end + end + if (actorObject.alternatepower and actorObject.alternatepower > 0) then + combatTotalsTable.alternatepower = combatTotalsTable.alternatepower - actorObject.alternatepower + combatTotalsTableInGroup.alternatepower = combatTotalsTableInGroup.alternatepower - actorObject.alternatepower end - end - if (actorObject.alternatepower and actorObject.alternatepower > 0) then - combatTotalsTable.alternatepower = combatTotalsTable.alternatepower - actorObject.alternatepower - combatTotalsTableInGroup.alternatepower = combatTotalsTableInGroup.alternatepower - actorObject.alternatepower - end - elseif (containerType == 4) then - --decrease the amount of CC break from the combat totals - if (actorObject.cc_break and actorObject.cc_break > 0) then - if (combatTotalsTable.cc_break) then - combatTotalsTable.cc_break = combatTotalsTable.cc_break - actorObject.cc_break + elseif (containerType == 4) then + ---@cast actorObject actorutility + --decrease the amount of CC break from the combat totals + if (actorObject.cc_break and actorObject.cc_break > 0) then + if (combatTotalsTable.cc_break) then + combatTotalsTable.cc_break = combatTotalsTable.cc_break - actorObject.cc_break + end + if (combatTotalsTableInGroup.cc_break) then + combatTotalsTableInGroup.cc_break = combatTotalsTableInGroup.cc_break - actorObject.cc_break + end end - if (combatTotalsTableInGroup.cc_break) then - combatTotalsTableInGroup.cc_break = combatTotalsTableInGroup.cc_break - actorObject.cc_break - end - end - --decrease the amount of dispell from the combat totals - if (actorObject.dispell and actorObject.dispell > 0) then - if (combatTotalsTable.dispell) then - combatTotalsTable.dispell = combatTotalsTable.dispell - actorObject.dispell + --decrease the amount of dispell from the combat totals + if (actorObject.dispell and actorObject.dispell > 0) then + if (combatTotalsTable.dispell) then + combatTotalsTable.dispell = combatTotalsTable.dispell - actorObject.dispell + end + if (combatTotalsTableInGroup.dispell) then + combatTotalsTableInGroup.dispell = combatTotalsTableInGroup.dispell - actorObject.dispell + end end - if (combatTotalsTableInGroup.dispell) then - combatTotalsTableInGroup.dispell = combatTotalsTableInGroup.dispell - actorObject.dispell - end - end - --decrease the amount of interrupt from the combat totals - if (actorObject.interrupt and actorObject.interrupt > 0) then - if (combatTotalsTable.interrupt) then - combatTotalsTable.interrupt = combatTotalsTable.interrupt - actorObject.interrupt + --decrease the amount of interrupt from the combat totals + if (actorObject.interrupt and actorObject.interrupt > 0) then + if (combatTotalsTable.interrupt) then + combatTotalsTable.interrupt = combatTotalsTable.interrupt - actorObject.interrupt + end + if (combatTotalsTableInGroup.interrupt) then + combatTotalsTableInGroup.interrupt = combatTotalsTableInGroup.interrupt - actorObject.interrupt + end end - if (combatTotalsTableInGroup.interrupt) then - combatTotalsTableInGroup.interrupt = combatTotalsTableInGroup.interrupt - actorObject.interrupt - end - end - --decrease the amount of ress from the combat totals - if (actorObject.ress and actorObject.ress > 0) then - if (combatTotalsTable.ress) then - combatTotalsTable.ress = combatTotalsTable.ress - actorObject.ress + --decrease the amount of ress from the combat totals + if (actorObject.ress and actorObject.ress > 0) then + if (combatTotalsTable.ress) then + combatTotalsTable.ress = combatTotalsTable.ress - actorObject.ress + end + if (combatTotalsTableInGroup.ress) then + combatTotalsTableInGroup.ress = combatTotalsTableInGroup.ress - actorObject.ress + end end - if (combatTotalsTableInGroup.ress) then - combatTotalsTableInGroup.ress = combatTotalsTableInGroup.ress - actorObject.ress - end - end - --decrease the amount of dead from the combat totals - if (actorObject.dead and actorObject.dead > 0) then - if (combatTotalsTable.dead) then - combatTotalsTable.dead = combatTotalsTable.dead - actorObject.dead + --decrease the amount of dead from the combat totals + if (actorObject.dead and actorObject.dead > 0) then + if (combatTotalsTable.dead) then + combatTotalsTable.dead = combatTotalsTable.dead - actorObject.dead + end + if (combatTotalsTableInGroup.dead) then + combatTotalsTableInGroup.dead = combatTotalsTableInGroup.dead - actorObject.dead + end end - if (combatTotalsTableInGroup.dead) then - combatTotalsTableInGroup.dead = combatTotalsTableInGroup.dead - actorObject.dead - end - end - --decreate the amount of cooldowns used from the combat totals - if (actorObject.cooldowns_defensive and actorObject.cooldowns_defensive > 0) then - if (combatTotalsTable.cooldowns_defensive) then - combatTotalsTable.cooldowns_defensive = combatTotalsTable.cooldowns_defensive - actorObject.cooldowns_defensive + --decreate the amount of cooldowns used from the combat totals + if (actorObject.cooldowns_defensive and actorObject.cooldowns_defensive > 0) then + if (combatTotalsTable.cooldowns_defensive) then + combatTotalsTable.cooldowns_defensive = combatTotalsTable.cooldowns_defensive - actorObject.cooldowns_defensive + end + if (combatTotalsTableInGroup.cooldowns_defensive) then + combatTotalsTableInGroup.cooldowns_defensive = combatTotalsTableInGroup.cooldowns_defensive - actorObject.cooldowns_defensive + end end - if (combatTotalsTableInGroup.cooldowns_defensive) then - combatTotalsTableInGroup.cooldowns_defensive = combatTotalsTableInGroup.cooldowns_defensive - actorObject.cooldowns_defensive - end - end - --decrease the amount of buff uptime from the combat totals - if (actorObject.buff_uptime and actorObject.buff_uptime > 0) then - if (combatTotalsTable.buff_uptime) then - combatTotalsTable.buff_uptime = combatTotalsTable.buff_uptime - actorObject.buff_uptime + --decrease the amount of buff uptime from the combat totals + if (actorObject.buff_uptime and actorObject.buff_uptime > 0) then + if (combatTotalsTable.buff_uptime) then + combatTotalsTable.buff_uptime = combatTotalsTable.buff_uptime - actorObject.buff_uptime + end + if (combatTotalsTableInGroup.buff_uptime) then + combatTotalsTableInGroup.buff_uptime = combatTotalsTableInGroup.buff_uptime - actorObject.buff_uptime + end end - if (combatTotalsTableInGroup.buff_uptime) then - combatTotalsTableInGroup.buff_uptime = combatTotalsTableInGroup.buff_uptime - actorObject.buff_uptime - end - end - --decrease the amount of debuff uptime from the combat totals - if (actorObject.debuff_uptime and actorObject.debuff_uptime > 0) then - if (combatTotalsTable.debuff_uptime) then - combatTotalsTable.debuff_uptime = combatTotalsTable.debuff_uptime - actorObject.debuff_uptime - end - if (combatTotalsTableInGroup.debuff_uptime) then - combatTotalsTableInGroup.debuff_uptime = combatTotalsTableInGroup.debuff_uptime - actorObject.debuff_uptime + --decrease the amount of debuff uptime from the combat totals + if (actorObject.debuff_uptime and actorObject.debuff_uptime > 0) then + if (combatTotalsTable.debuff_uptime) then + combatTotalsTable.debuff_uptime = combatTotalsTable.debuff_uptime - actorObject.debuff_uptime + end + if (combatTotalsTableInGroup.debuff_uptime) then + combatTotalsTableInGroup.debuff_uptime = combatTotalsTableInGroup.debuff_uptime - actorObject.debuff_uptime + end end end end + local actorName = actorObject:Name() + combatObject:RemoveActorFromSpellCastTable(actorName) + setmetatable(actorObject, nil) actorObject.__index = nil actorObject.__newindex = nil - actorContainer:RemoveActor(actorObject) Details:Destroy(actorObject) + + --leave a trace that the actor has been deleted + actorObject.__destroyed = true + actorObject.__destroyedBy = debugstack(2, 1, 0) end \ No newline at end of file diff --git a/classes/class_combat.lua b/classes/class_combat.lua index 78c0b7c7..de3608bf 100644 --- a/classes/class_combat.lua +++ b/classes/class_combat.lua @@ -52,6 +52,11 @@ local class_type_e_energy = Details.atributos.e_energy local class_type_misc = Details.atributos.misc + local classTypeDamage = Details.atributos.dano + local classTypeHeal = Details.atributos.cura + local classTypeResource = Details.atributos.e_energy + local classTypeUtility = Details.atributos.misc + local REACTION_HOSTILE = 0x00000040 local CONTROL_PLAYER = 0x00000100 @@ -550,180 +555,176 @@ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --internals - function classCombat:CreateNewCombatTable() - return classCombat:NovaTabela() - end +function classCombat:CreateNewCombatTable() + return classCombat:NovaTabela() +end - ---class constructor - ---@param bTimeStarted boolean if true set the start time to now with GetTime - ---@param overallCombatObject combat - ---@param combatId number - ---@param ... unknown - ---@return combat - function classCombat:NovaTabela(bTimeStarted, overallCombatObject, combatId, ...) --~init - ---@type combat - local combatObject = {} +---class constructor +---@param bTimeStarted boolean if true set the start time to now with GetTime +---@param overallCombatObject combat +---@param combatId number +---@param ... unknown +---@return combat +function classCombat:NovaTabela(bTimeStarted, overallCombatObject, combatId, ...) --~init + ---@type combat + local combatObject = {} - combatObject[1] = classActorContainer:NovoContainer(Details.container_type.CONTAINER_DAMAGE_CLASS, combatObject, combatId) --Damage - combatObject[2] = classActorContainer:NovoContainer(Details.container_type.CONTAINER_HEAL_CLASS, combatObject, combatId) --Healing - combatObject[3] = classActorContainer:NovoContainer(Details.container_type.CONTAINER_ENERGY_CLASS, combatObject, combatId) --Energies - combatObject[4] = classActorContainer:NovoContainer(Details.container_type.CONTAINER_MISC_CLASS, combatObject, combatId) --Misc - combatObject[5] = classActorContainer:NovoContainer(Details.container_type.CONTAINER_DAMAGE_CLASS, combatObject, combatId) --place holder for customs + combatObject[1] = classActorContainer:NovoContainer(Details.container_type.CONTAINER_DAMAGE_CLASS, combatObject, combatId) --Damage + combatObject[2] = classActorContainer:NovoContainer(Details.container_type.CONTAINER_HEAL_CLASS, combatObject, combatId) --Healing + combatObject[3] = classActorContainer:NovoContainer(Details.container_type.CONTAINER_ENERGY_CLASS, combatObject, combatId) --Energies + combatObject[4] = classActorContainer:NovoContainer(Details.container_type.CONTAINER_MISC_CLASS, combatObject, combatId) --Misc + combatObject[5] = classActorContainer:NovoContainer(Details.container_type.CONTAINER_DAMAGE_CLASS, combatObject, combatId) --place holder for customs - setmetatable(combatObject, classCombat) + setmetatable(combatObject, classCombat) - Details.combat_counter = Details.combat_counter + 1 - combatObject.combat_counter = Details.combat_counter + Details.combat_counter = Details.combat_counter + 1 + combatObject.combat_counter = Details.combat_counter - --try discover if is a pvp combat - local who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags = ... - if (who_serial) then --aqui ir� identificar o boss ou o oponente - if (alvo_name and _bit_band (alvo_flags, REACTION_HOSTILE) ~= 0) then --tentando pegar o inimigo pelo alvo - combatObject.contra = alvo_name - if (_bit_band (alvo_flags, CONTROL_PLAYER) ~= 0) then - combatObject.pvp = true --o alvo � da fac��o oposta ou foi dado mind control - end - elseif (who_name and _bit_band (who_flags, REACTION_HOSTILE) ~= 0) then --tentando pegar o inimigo pelo who caso o mob � quem deu o primeiro hit - combatObject.contra = who_name - if (_bit_band (who_flags, CONTROL_PLAYER) ~= 0) then - combatObject.pvp = true --o who � da fac��o oposta ou foi dado mind control - end - else - combatObject.pvp = true --se ambos s�o friendly, seria isso um PVP entre jogadores da mesma fac��o? + --try discover if is a pvp combat + local who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags = ... + if (who_serial) then --aqui ir� identificar o boss ou o oponente + if (alvo_name and _bit_band (alvo_flags, REACTION_HOSTILE) ~= 0) then --tentando pegar o inimigo pelo alvo + combatObject.contra = alvo_name + if (_bit_band (alvo_flags, CONTROL_PLAYER) ~= 0) then + combatObject.pvp = true --o alvo � da fac��o oposta ou foi dado mind control + end + elseif (who_name and _bit_band (who_flags, REACTION_HOSTILE) ~= 0) then --tentando pegar o inimigo pelo who caso o mob � quem deu o primeiro hit + combatObject.contra = who_name + if (_bit_band (who_flags, CONTROL_PLAYER) ~= 0) then + combatObject.pvp = true --o who � da fac��o oposta ou foi dado mind control end - end - - --start/end time (duration) - combatObject.data_fim = 0 - combatObject.data_inicio = 0 - combatObject.tempo_start = _tempo - - ---store trinket procs - combatObject.trinketProcs = {} - - ---store the amount of casts of each player - ---@type table> - combatObject.amountCasts = {} - - --record deaths - combatObject.last_events_tables = {} - - --last events from players - combatObject.player_last_events = {} - - --players in the raid - combatObject.raid_roster = {} - combatObject.raid_roster_indexed = {} - - --frags - combatObject.frags = {} - combatObject.frags_need_refresh = false - - --alternate power - combatObject.alternate_power = {} - - --time data container - combatObject.TimeData = Details:TimeDataCreateCombatTables() - combatObject.PhaseData = {{1, 1}, damage = {}, heal = {}, damage_section = {}, heal_section = {}} --[1] phase number [2] phase started - - --for external plugin usage, these tables are guaranteed to be saved with the combat - combatObject.spells_cast_timeline = {} - combatObject.aura_timeline = {} - combatObject.cleu_timeline = {} - - --cleu events - combatObject.cleu_events = { - n = 1 --event counter - } - - --a tabela sem o tempo de inicio � a tabela descartavel do inicio do addon - if (bTimeStarted) then - --esta_tabela.start_time = _tempo - combatObject.start_time = GetTime() - combatObject.end_time = nil else - combatObject.start_time = 0 - combatObject.end_time = nil + combatObject.pvp = true --se ambos s�o friendly, seria isso um PVP entre jogadores da mesma fac��o? end - - -- o container ir� armazenar as classes de dano -- cria um novo container de indexes de seriais de jogadores --par�metro 1 classe armazenada no container, par�metro 2 = flag da classe - combatObject[1].need_refresh = true - combatObject[2].need_refresh = true - combatObject[3].need_refresh = true - combatObject[4].need_refresh = true - combatObject[5].need_refresh = true - - --isn't shadow deprecated? - if (overallCombatObject) then --link � a tabela de combate do overall - combatObject[1].shadow = overallCombatObject[1] - combatObject[2].shadow = overallCombatObject[2] - combatObject[3].shadow = overallCombatObject[3] - combatObject[4].shadow = overallCombatObject[4] - end - - combatObject.totals = { - 0, --dano - 0, --cura - {--e_energy - [0] = 0, --mana - [1] = 0, --rage - [3] = 0, --energy (rogues cat) - [6] = 0, --runepower (dk) - alternatepower = 0, - }, - {--misc - cc_break = 0, --armazena quantas quebras de CC - ress = 0, --armazena quantos pessoas ele reviveu - interrupt = 0, --armazena quantos interrupt a pessoa deu - dispell = 0, --armazena quantos dispell esta pessoa recebeu - dead = 0, --armazena quantas vezes essa pessia morreu - cooldowns_defensive = 0, --armazena quantos cooldowns a raid usou - buff_uptime = 0, --armazena quantos cooldowns a raid usou - debuff_uptime = 0 --armazena quantos cooldowns a raid usou - }, - - --avoid using this values bellow, they aren't updated by the parser, only on demand by a user interaction. - voidzone_damage = 0, - frags_total = 0, - --end - } - - combatObject.totals_grupo = { - 0, --dano - 0, --cura - {--e_energy - [0] = 0, --mana - [1] = 0, --rage - [3] = 0, --energy (rogues cat) - [6] = 0, --runepower (dk) - alternatepower = 0, - }, - {--misc - cc_break = 0, --armazena quantas quebras de CC - ress = 0, --armazena quantos pessoas ele reviveu - interrupt = 0, --armazena quantos interrupt a pessoa deu - dispell = 0, --armazena quantos dispell esta pessoa recebeu - dead = 0, --armazena quantas vezes essa oessia morreu - cooldowns_defensive = 0, --armazena quantos cooldowns a raid usou - buff_uptime = 0, - debuff_uptime = 0 - } - } - - return combatObject end + --start/end time (duration) + combatObject.data_fim = 0 + combatObject.data_inicio = 0 + combatObject.tempo_start = _tempo + + ---store trinket procs + combatObject.trinketProcs = {} + + ---store the amount of casts of each player + ---@type table> + combatObject.amountCasts = {} + + --record deaths + combatObject.last_events_tables = {} + + --last events from players + combatObject.player_last_events = {} + + --players in the raid + combatObject.raid_roster = {} + combatObject.raid_roster_indexed = {} + + --frags + combatObject.frags = {} + combatObject.frags_need_refresh = false + + --alternate power + combatObject.alternate_power = {} + + --time data container + combatObject.TimeData = Details:TimeDataCreateCombatTables() + combatObject.PhaseData = {{1, 1}, damage = {}, heal = {}, damage_section = {}, heal_section = {}} --[1] phase number [2] phase started + + --for external plugin usage, these tables are guaranteed to be saved with the combat + combatObject.spells_cast_timeline = {} + combatObject.aura_timeline = {} + combatObject.cleu_timeline = {} + + --cleu events + combatObject.cleu_events = { + n = 1 --event counter + } + + --a tabela sem o tempo de inicio � a tabela descartavel do inicio do addon + if (bTimeStarted) then + --esta_tabela.start_time = _tempo + combatObject.start_time = GetTime() + combatObject.end_time = nil + else + combatObject.start_time = 0 + combatObject.end_time = nil + end + + -- o container ir� armazenar as classes de dano -- cria um novo container de indexes de seriais de jogadores --par�metro 1 classe armazenada no container, par�metro 2 = flag da classe + combatObject[1].need_refresh = true + combatObject[2].need_refresh = true + combatObject[3].need_refresh = true + combatObject[4].need_refresh = true + combatObject[5].need_refresh = true + + combatObject.totals = { + 0, --dano + 0, --cura + {--e_energy + [0] = 0, --mana + [1] = 0, --rage + [3] = 0, --energy (rogues cat) + [6] = 0, --runepower (dk) + alternatepower = 0, + }, + {--misc + cc_break = 0, --armazena quantas quebras de CC + ress = 0, --armazena quantos pessoas ele reviveu + interrupt = 0, --armazena quantos interrupt a pessoa deu + dispell = 0, --armazena quantos dispell esta pessoa recebeu + dead = 0, --armazena quantas vezes essa pessia morreu + cooldowns_defensive = 0, --armazena quantos cooldowns a raid usou + buff_uptime = 0, --armazena quantos cooldowns a raid usou + debuff_uptime = 0 --armazena quantos cooldowns a raid usou + }, + + --avoid using this values bellow, they aren't updated by the parser, only on demand by a user interaction. + voidzone_damage = 0, + frags_total = 0, + --end + } + + combatObject.totals_grupo = { + 0, --dano + 0, --cura + {--e_energy + [0] = 0, --mana + [1] = 0, --rage + [3] = 0, --energy (rogues cat) + [6] = 0, --runepower (dk) + alternatepower = 0, + }, + {--misc + cc_break = 0, --armazena quantas quebras de CC + ress = 0, --armazena quantos pessoas ele reviveu + interrupt = 0, --armazena quantos interrupt a pessoa deu + dispell = 0, --armazena quantos dispell esta pessoa recebeu + dead = 0, --armazena quantas vezes essa oessia morreu + cooldowns_defensive = 0, --armazena quantos cooldowns a raid usou + buff_uptime = 0, + debuff_uptime = 0 + } + } + + return combatObject +end + ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --core - function classCombat:CreateLastEventsTable (player_name) - local t = {} + ---create the table which will contain the latest events of the player while alive + ---@param self combat + ---@param playerName string + ---@return table + function classCombat:CreateLastEventsTable(playerName) + local lastEventsTable = {} for i = 1, Details.deadlog_events do - t [i] = {} + lastEventsTable [i] = {} end - t.n = 1 - self.player_last_events [player_name] = t - return t + lastEventsTable.n = 1 + self.player_last_events[playerName] = lastEventsTable + return lastEventsTable end --trava o tempo dos jogadores ap�s o t�rmino do combate. @@ -760,11 +761,11 @@ end end - function classCombat:seta_data (tipo) + function classCombat:seta_data(tipo) if (tipo == Details._detalhes_props.DATA_TYPE_START) then - self.data_inicio = _date ("%H:%M:%S") + self.data_inicio = _date("%H:%M:%S") elseif (tipo == Details._detalhes_props.DATA_TYPE_END) then - self.data_fim = _date ("%H:%M:%S") + self.data_fim = _date("%H:%M:%S") end end @@ -773,18 +774,20 @@ self.end_time = GetTime() end - function Details.refresh:r_combate (tabela_combate, shadow) - setmetatable(tabela_combate, Details.combate) - tabela_combate.__index = Details.combate - tabela_combate.shadow = shadow + ---set combat metatable and class lookup + ---@self any + ---@param combatObject combat + function Details.refresh:r_combate(combatObject) + setmetatable(combatObject, Details.combate) + combatObject.__index = Details.combate end - function Details.clear:c_combate (tabela_combate) - --tabela_combate.__index = {} - tabela_combate.__index = nil - tabela_combate.__call = {} - tabela_combate._combat_table = nil - tabela_combate.shadow = nil + ---clear combat object + ---@self any + ---@param combatObject combat + function Details.clear:c_combate(combatObject) + combatObject.__index = nil + combatObject.__call = nil end classCombat.__sub = function(combate1, combate2) @@ -862,67 +865,76 @@ end - ---add combat2 data into combat1 - ---@param combate1 combat - ---@param combate2 combat + ---add combatToAdd into combatRecevingTheSum + ---@param combatRecevingTheSum combat + ---@param combatToAdd combat ---@return combat - classCombat.__add = function(combate1, combate2) - local all_containers = {combate2 [class_type_dano]._ActorTable, combate2 [class_type_cura]._ActorTable, combate2 [class_type_e_energy]._ActorTable, combate2 [class_type_misc]._ActorTable} - local custom_combat - if (combate1 ~= Details.tabela_overall) then - custom_combat = combate1 + classCombat.__add = function(combatRecevingTheSum, combatToAdd) + ---@type combat + local customCombat + if (combatRecevingTheSum ~= Details.tabela_overall) then + customCombat = combatRecevingTheSum end - for class_type, actor_container in ipairs(all_containers) do - for _, actor in ipairs(actor_container) do - local shadow + local bRefreshActor = false - if (class_type == class_type_dano) then - shadow = Details.atributo_damage:r_connect_shadow (actor, true, custom_combat) - elseif (class_type == class_type_cura) then - shadow = Details.atributo_heal:r_connect_shadow (actor, true, custom_combat) - elseif (class_type == class_type_e_energy) then - shadow = Details.atributo_energy:r_connect_shadow (actor, true, custom_combat) - elseif (class_type == class_type_misc) then - shadow = Details.atributo_misc:r_connect_shadow (actor, true, custom_combat) + for classType = 1, DETAILS_COMBAT_AMOUNT_CONTAINERS do + local actorContainer = combatToAdd[classType] + local actorTable = actorContainer._ActorTable + for _, actorObject in ipairs(actorTable) do + ---@cast actorObject actor + ---@type actor + local actorCreatedInTheReceivingCombat + + if (classType == classTypeDamage) then + actorCreatedInTheReceivingCombat = Details.atributo_damage:AddToCombat(actorObject, bRefreshActor, customCombat) + + elseif (classType == classTypeHeal) then + actorCreatedInTheReceivingCombat = Details.atributo_heal:AddToCombat(actorObject, bRefreshActor, customCombat) + + elseif (classType == classTypeResource) then + actorCreatedInTheReceivingCombat = Details.atributo_energy:r_connect_shadow(actorObject, true, customCombat) + + elseif (classType == classTypeUtility) then + actorCreatedInTheReceivingCombat = Details.atributo_misc:r_connect_shadow(actorObject, true, customCombat) end - shadow.boss_fight_component = actor.boss_fight_component or shadow.boss_fight_component - shadow.fight_component = actor.fight_component or shadow.fight_component - shadow.grupo = actor.grupo or shadow.grupo + actorCreatedInTheReceivingCombat.boss_fight_component = actorObject.boss_fight_component or actorCreatedInTheReceivingCombat.boss_fight_component + actorCreatedInTheReceivingCombat.fight_component = actorObject.fight_component or actorCreatedInTheReceivingCombat.fight_component + actorCreatedInTheReceivingCombat.grupo = actorObject.grupo or actorCreatedInTheReceivingCombat.grupo end end --alternate power - local overallPowerTable = combate1.alternate_power - for actorName, powerTable in pairs(combate2.alternate_power) do - local alternatePowerTable = overallPowerTable[actorName] - if (not alternatePowerTable) then - alternatePowerTable = combate1:CreateAlternatePowerTable(actorName) - end - alternatePowerTable.total = alternatePowerTable.total + powerTable.total - combate2.alternate_power[actorName].last = 0 + local overallPowerTable = combatRecevingTheSum.alternate_power + for actorName, powerTable in pairs(combatToAdd.alternate_power) do + local alternatePowerTable = overallPowerTable[actorName] + if (not alternatePowerTable) then + alternatePowerTable = combatRecevingTheSum:CreateAlternatePowerTable(actorName) end + alternatePowerTable.total = alternatePowerTable.total + powerTable.total + combatToAdd.alternate_power[actorName].last = 0 + end --cast amount - local combat1CastData = combate1.amountCasts - for actorName, castData in pairs(combate2.amountCasts) do - local playerCastTable = combat1CastData[actorName] - if (not playerCastTable) then - playerCastTable = {} - combat1CastData[actorName] = playerCastTable - end - for spellName, amountOfCasts in pairs(castData) do - local spellAmount = playerCastTable[spellName] - if (not spellAmount) then - spellAmount = 0 - playerCastTable[spellName] = spellAmount - end - playerCastTable[spellName] = spellAmount + amountOfCasts - end + local combat1CastData = combatRecevingTheSum.amountCasts + for actorName, castData in pairs(combatToAdd.amountCasts) do + local playerCastTable = combat1CastData[actorName] + if (not playerCastTable) then + playerCastTable = {} + combat1CastData[actorName] = playerCastTable end + for spellName, amountOfCasts in pairs(castData) do + local spellAmount = playerCastTable[spellName] + if (not spellAmount) then + spellAmount = 0 + playerCastTable[spellName] = spellAmount + end + playerCastTable[spellName] = spellAmount + amountOfCasts + end + end - return combate1 + return combatRecevingTheSum end function Details:UpdateCombat() diff --git a/classes/class_custom.lua b/classes/class_custom.lua index 0070cdf7..482c3bf6 100644 --- a/classes/class_custom.lua +++ b/classes/class_custom.lua @@ -1378,7 +1378,7 @@ desc = Loc ["STRING_CUSTOM_ACTIVITY_DPS_DESC"], source = false, target = false, - script_version = 3, + script_version = 4, total_script = [[ local value, top, total, combat, instance = ... local minutos, segundos = math.floor(value/60), math.floor(value%60) @@ -1389,26 +1389,24 @@ return string.format("%.1f", value/top*100) ]], script = [[ - --init: - local combat, instance_container, instance = ... + local combatObject, instanceContainer, instanceObject = ... local total, amount = 0, 0 - --get the misc actor container - local damage_container = combat:GetActorList ( DETAILS_ATTRIBUTE_DAMAGE ) + --get the damager actors + local listOfDamageActors = combatObject:GetActorList(DETAILS_ATTRIBUTE_DAMAGE) - --do the loop: - for _, player in ipairs( damage_container ) do - if (player.grupo) then - local activity = player:Tempo() + for _, actorObject in ipairs(listOfDamageActors) do + if (actorObject:IsGroupPlayer()) then + local activity = actorObject:Tempo() total = total + activity amount = amount + 1 --add amount to the player - instance_container:AddValue (player, activity) + instanceContainer:AddValue(actorObject, activity) end end --return: - return total, combat:GetCombatTime(), amount + return total, combatObject:GetCombatTime(), amount ]], tooltip = [[ @@ -1442,7 +1440,7 @@ desc = Loc ["STRING_CUSTOM_ACTIVITY_HPS_DESC"], source = false, target = false, - script_version = 2, + script_version = 3, total_script = [[ local value, top, total, combat, instance = ... local minutos, segundos = math.floor(value/60), math.floor(value%60) @@ -1453,26 +1451,24 @@ return string.format("%.1f", value/top*100) ]], script = [[ - --init: - local combat, instance_container, instance = ... - local total, top, amount = 0, 0, 0 + local combatObject, instanceContainer, instanceObject = ... + local total, amount = 0, 0 - --get the misc actor container - local damage_container = combat:GetActorList ( DETAILS_ATTRIBUTE_HEAL ) + --get the healing actors + local listOfHealingActors = combatObject:GetActorList(DETAILS_ATTRIBUTE_HEAL) - --do the loop: - for _, player in ipairs( damage_container ) do - if (player.grupo) then - local activity = player:Tempo() + for _, actorObject in ipairs(listOfHealingActors) do + if (actorObject:IsGroupPlayer()) then + local activity = actorObject:Tempo() total = total + activity amount = amount + 1 --add amount to the player - instance_container:AddValue (player, activity) + instanceContainer:AddValue (actorObject, activity) end end --return: - return total, combat:GetCombatTime(), amount + return total, combatObject:GetCombatTime(), amount ]], tooltip = [[ diff --git a/classes/class_damage.lua b/classes/class_damage.lua index c063707c..c9e8f639 100644 --- a/classes/class_damage.lua +++ b/classes/class_damage.lua @@ -1874,7 +1874,7 @@ function damageClass:RefreshWindow(instancia, combatObject, forcar, exportar, re elseif (keyName == "damage_taken_by_spells") then local bs_index, total = 0, 0 - Details:Destroy (bs_index_table) + Details:Destroy(bs_index_table) local combat = combatObject local AllDamageCharacters = combat:GetActorList (DETAILS_ATTRIBUTE_DAMAGE) @@ -6213,14 +6213,14 @@ end end if (bs_tooltip_table) then - Details:Destroy (bs_tooltip_table) + Details:Destroy(bs_tooltip_table) end if (frags_tooltip_table) then - Details:Destroy (frags_tooltip_table) + Details:Destroy(frags_tooltip_table) end - Details:Destroy (bs_index_table) - Details:Destroy (tooltip_temp_table) - Details:Destroy (tooltip_void_zone_temp) + Details:Destroy(bs_index_table) + Details:Destroy(tooltip_temp_table) + Details:Destroy(tooltip_void_zone_temp) end --atualize a funcao de abreviacao @@ -6245,237 +6245,161 @@ end end end - --restaura a tabela de last event - function damageClass:r_last_events_table (actor) - if (not actor) then - actor = self - end - --actor.last_events_table = Details:CreateActorLastEventTable() + ---sum the passed actor into a combat, if the combat isn't passed, it will use the overall combat + ---the function returns the actor that was created of found in the combat passed + ---@param actorObject actor + ---@param bRefreshActor boolean|nil + ---@param combatObject combat|nil + ---@return actor + function damageClass:AddToCombat(actorObject, bRefreshActor, combatObject) + --check if there's a custom combat, if not just use the overall container + combatObject = combatObject or Details.tabela_overall --same as Details:GetCombat(DETAILS_SEGMENTID_OVERALL) + + --check if the combatObject has an actor with the same name, if not, just create one new + local actorContainer = combatObject[DETAILS_ATTRIBUTE_DAMAGE] --same as combatObject:GetContainer(DETAILS_ATTRIBUTE_DAMAGE) + local overallActor = actorContainer._ActorTable[actorContainer._NameIndexTable[actorObject.nome]] --same as actorContainer:GetActor(actorObject:Name()) + + if (not overallActor) then + overallActor = actorContainer:GetOrCreateActor(actorObject.serial, actorObject.nome, actorObject.flag_original, true) + overallActor.classe = actorObject.classe + overallActor:SetSpecId(actorObject.spec) + overallActor.isTank = actorObject.isTank + overallActor.pvp = actorObject.pvp + overallActor.boss = actorObject.boss + overallActor.start_time = time() - 3 + overallActor.end_time = time() end - --restaura e liga o ator com a sua shadow durante a inicializa��o (startup function) - function damageClass:r_onlyrefresh_shadow (actor) - --criar uma shadow desse ator se ainda n�o tiver uma - local overall_dano = Details.tabela_overall [1] - local shadow = overall_dano._ActorTable [overall_dano._NameIndexTable [actor.nome]] + overallActor.displayName = actorObject.displayName or actorObject.nome + overallActor.boss_fight_component = actorObject.boss_fight_component or overallActor.boss_fight_component + overallActor.fight_component = actorObject.fight_component or overallActor.fight_component + overallActor.grupo = actorObject.grupo or overallActor.grupo - if (not shadow) then - shadow = overall_dano:PegarCombatente (actor.serial, actor.nome, actor.flag_original, true) - - shadow.classe = actor.classe - shadow:SetSpecId(actor.spec) - shadow.grupo = actor.grupo - shadow.pvp = actor.pvp - shadow.isTank = actor.isTank - shadow.boss = actor.boss - shadow.boss_fight_component = actor.boss_fight_component - shadow.fight_component = actor.fight_component - - shadow.start_time = time() - 3 - shadow.end_time = time() - end - - --restaura a meta e indexes ao ator - Details.refresh:r_atributo_damage (actor, shadow) - - --copia o container de alvos (captura de dados) - for target_name, amount in pairs(actor.targets) do - --cria e soma o valor do total - if (not shadow.targets [target_name]) then - shadow.targets [target_name] = 0 - end - end - - --copia o container de habilidades (captura de dados) - for spellid, habilidade in pairs(actor.spells._ActorTable) do - --cria e soma o valor - local habilidade_shadow = shadow.spells:PegaHabilidade (spellid, true, nil, true) - - --create the target value - for target_name, amount in pairs(habilidade.targets) do - if (not habilidade_shadow.targets [target_name]) then - habilidade_shadow.targets [target_name] = 0 - end - end - - --create the extra value - for spellId, amount in pairs(habilidade.extra) do - if (not habilidade_shadow.extra [spellId]) then - habilidade_shadow.extra [spellId] = 0 - end - end - - end - - --copia o container de friendly fire (captura de dados) - for target_name, ff_table in pairs(actor.friendlyfire) do - --cria ou pega a shadow - local friendlyFire_shadow = shadow.friendlyfire [target_name] or shadow:CreateFFTable (target_name) - --some as spells - for spellid, amount in pairs(ff_table.spells) do - friendlyFire_shadow.spells [spellid] = 0 - end - end - - return shadow + --check if need to restore meta tables and indexes for this actor + if (bRefreshActor) then + --this call will reenable the metatable, __index and set the metatable on the .spells container + Details.refresh:r_atributo_damage(actorObject) end - function damageClass:r_connect_shadow (actor, no_refresh, combat_object) + --elapsed time + local endTime = actorObject.end_time + if (not actorObject.end_time) then + endTime = time() + end - --check if there's a custom combat, if not just use the overall container - local host_combat = combat_object or Details.tabela_overall + local tempo = endTime - actorObject.start_time + overallActor.start_time = overallActor.start_time - tempo - --check if the host combat object has a shadow actor for this actor, if not, just create one new - local overall_dano = host_combat [1] - local shadow = overall_dano._ActorTable [overall_dano._NameIndexTable [actor.nome]] + --pets (add unique pet names) + for _, petName in ipairs(actorObject.pets) do --same as actorObject:GetPets() + DetailsFramework.table.addunique(overallActor.pets, petName) + end - if (not shadow) then - shadow = overall_dano:PegarCombatente (actor.serial, actor.nome, actor.flag_original, true) + ---@cast actorObject actordamage - shadow.classe = actor.classe - shadow:SetSpecId(actor.spec) - shadow.isTank = actor.isTank - shadow.grupo = actor.grupo - shadow.pvp = actor.pvp - shadow.boss = actor.boss - shadow.boss_fight_component = actor.boss_fight_component - shadow.fight_component = actor.fight_component + --sum total damage + overallActor.total = overallActor.total + actorObject.total + overallActor.totalabsorbed = overallActor.totalabsorbed + actorObject.totalabsorbed - shadow.start_time = time() - 3 - shadow.end_time = time() - end + --sum total damage without pet + overallActor.total_without_pet = overallActor.total_without_pet + actorObject.total_without_pet - shadow.displayName = actor.displayName or actor.nome + --sum total damage taken + overallActor.damage_taken = overallActor.damage_taken + actorObject.damage_taken - shadow.boss_fight_component = actor.boss_fight_component or shadow.boss_fight_component - shadow.fight_component = actor.fight_component or shadow.fight_component - shadow.grupo = actor.grupo or shadow.grupo + --sum friendly fire + overallActor.friendlyfire_total = overallActor.friendlyfire_total + actorObject.friendlyfire_total - --check if need to restore meta tables and indexes for this actor - if (not no_refresh) then - Details.refresh:r_atributo_damage (actor, shadow) + --sum total damage on the combatObject passed + combatObject.totals[1] = combatObject.totals[1] + actorObject.total + if (actorObject.grupo) then + combatObject.totals_grupo[1] = combatObject.totals_grupo[1] + actorObject.total + end + + --copy damage taken from + for aggressorName, _ in pairs(actorObject.damage_from) do + overallActor.damage_from[aggressorName] = true + end + + --copy targets + for targetName, amount in pairs(actorObject.targets) do + overallActor.targets[targetName] = (overallActor.targets[targetName] or 0) + amount + end + + --copy raid targets + for flag, amount in pairs(actorObject.raid_targets) do + overallActor.raid_targets = overallActor.raid_targets or {} + overallActor.raid_targets[flag] = (overallActor.raid_targets[flag] or 0) + amount + end + + ---@type spellcontainer + local overallSpellsContainer = overallActor.spells --same as overallActor:GetSpellContainer("spell") + + --copy spell table + for spellId, spellTable in pairs(actorObject.spells._ActorTable) do --same as overallSpellsContainer:GetRawSpellTable() + --var name has 'overall' but this function accepts any combat table + local overallSpellTable = overallSpellsContainer:GetOrCreateSpell(spellId, true) + + --sum spell targets + for targetName, amount in pairs(spellTable.targets) do + overallSpellTable.targets[targetName] = (overallSpellTable.targets[targetName] or 0) + amount end - --tempo decorrido (captura de dados) - local end_time = actor.end_time - if (not actor.end_time) then - end_time = time() - end + --refresh and add extra values + for extraSpellId, amount in pairs(spellTable.extra) do + overallSpellTable.extra[extraSpellId] = (overallSpellTable.extra[extraSpellId] or 0) + amount + end - local tempo = end_time - actor.start_time - shadow.start_time = shadow.start_time - tempo + overallSpellTable.spellschool = spellTable.spellschool - --pets (add unique pet names) - for _, petName in ipairs(actor.pets) do - local hasPet = false - for i = 1, #shadow.pets do - if (shadow.pets[i] == petName) then - hasPet = true - break + --sum all values of the spelltable which can be summed + for key, value in pairs(spellTable) do + if (type(value) == "number") then + if (key ~= "id" and key ~= "spellschool") then + if (not overallSpellTable [key]) then + overallSpellTable [key] = 0 + end + + if (key == "n_min" or key == "c_min") then + if (overallSpellTable [key] > value) then + overallSpellTable [key] = value + end + elseif (key == "n_max" or key == "c_max") then + if (overallSpellTable [key] < value) then + overallSpellTable [key] = value + end + else + overallSpellTable [key] = overallSpellTable [key] + value end end - if (not hasPet) then - shadow.pets [#shadow.pets+1] = petName + --empowered spells + elseif(key == "e_dmg" or key == "e_lvl") then + if (not overallSpellTable[key]) then + overallSpellTable[key] = {} + end + for empowermentLevel, empowermentValue in pairs(spellTable[key]) do + overallSpellTable[key][empowermentLevel] = empowermentValue end end - - --total de dano (captura de dados) - shadow.total = shadow.total + actor.total - shadow.totalabsorbed = shadow.totalabsorbed + actor.totalabsorbed - --total de dano sem o pet (captura de dados) - shadow.total_without_pet = shadow.total_without_pet + actor.total_without_pet - --total de dano que o ator sofreu (captura de dados) - shadow.damage_taken = shadow.damage_taken + actor.damage_taken - --total do friendly fire causado - shadow.friendlyfire_total = shadow.friendlyfire_total + actor.friendlyfire_total - - --total no combate overall (captura de dados) - host_combat.totals[1] = host_combat.totals[1] + actor.total - if (actor.grupo) then - host_combat.totals_grupo[1] = host_combat.totals_grupo[1] + actor.total - end - - --copia o damage_from (captura de dados) - for nome, _ in pairs(actor.damage_from) do - shadow.damage_from [nome] = true - end - - --copia o container de alvos (captura de dados) - for target_name, amount in pairs(actor.targets) do - shadow.targets [target_name] = (shadow.targets [target_name] or 0) + amount - end - - --copiar o container de raid targets - for flag, amount in pairs(actor.raid_targets) do - shadow.raid_targets = shadow.raid_targets or {} --deu invalido noutro dia - shadow.raid_targets [flag] = (shadow.raid_targets [flag] or 0) + amount - end - - --copia o container de habilidades (captura de dados) - for spellid, habilidade in pairs(actor.spells._ActorTable) do - --cria e soma o valor - local habilidade_shadow = shadow.spells:PegaHabilidade (spellid, true, nil, true) - - --refresh e soma os valores dos alvos - for target_name, amount in pairs(habilidade.targets) do - habilidade_shadow.targets [target_name] = (habilidade_shadow.targets [target_name] or 0) + amount - end - - --refresh and add extra values - for spellId, amount in pairs(habilidade.extra) do - habilidade_shadow.extra [spellId] = (habilidade_shadow.extra [spellId] or 0) + amount - end - - habilidade_shadow.spellschool = habilidade.spellschool - - --soma todos os demais valores - for key, value in pairs(habilidade) do - if (type(value) == "number") then - if (key ~= "id" and key ~= "spellschool") then - if (not habilidade_shadow [key]) then - habilidade_shadow [key] = 0 - end - - if (key == "n_min" or key == "c_min") then - if (habilidade_shadow [key] > value) then - habilidade_shadow [key] = value - end - elseif (key == "n_max" or key == "c_max") then - if (habilidade_shadow [key] < value) then - habilidade_shadow [key] = value - end - else - habilidade_shadow [key] = habilidade_shadow [key] + value - end - - end - elseif(key == "e_dmg" or key == "e_lvl") then - if (not habilidade_shadow[key]) then - habilidade_shadow[key] = {} - end - for empowermentLevel, empowermentValue in pairs(habilidade[key]) do - habilidade_shadow[key][empowermentLevel] = empowermentValue - end - end - end - end - - --copia o container de friendly fire (captura de dados) - for target_name, ff_table in pairs(actor.friendlyfire) do - --cria ou pega a shadow - local friendlyFire_shadow = shadow.friendlyfire [target_name] or shadow:CreateFFTable (target_name) - --soma o total - friendlyFire_shadow.total = friendlyFire_shadow.total + ff_table.total - --some as spells - for spellid, amount in pairs(ff_table.spells) do - friendlyFire_shadow.spells [spellid] = (friendlyFire_shadow.spells [spellid] or 0) + amount - end - end - - return shadow + end end + --copy the friendly fire container + for targetName, friendlyFireTable in pairs(actorObject.friendlyfire) do + --get or create the friendly fire table in the overall data + local friendlyFireOverall = overallActor.friendlyfire[targetName] or overallActor:CreateFFTable(targetName) + --sum the total + friendlyFireOverall.total = friendlyFireOverall.total + friendlyFireTable.total + --sum spells + for friendlyFireSpellId, amount in pairs(friendlyFireTable.spells) do + friendlyFireOverall.spells[friendlyFireSpellId] = (friendlyFireOverall.spells[friendlyFireSpellId] or 0) + amount + end + end + + return overallActor + end + --actor 1 is who will receive the sum from actor2 function Details.SumDamageActors(actor1, actor2, actorContainer) --general @@ -6765,20 +6689,19 @@ damageClass.__sub = function(tabela1, tabela2) return tabela1 end -function Details.refresh:r_atributo_damage (este_jogador, shadow) - --restaura metas do ator - detailsFramework:Mixin(este_jogador, Details222.Mixins.ActorMixin) - detailsFramework:Mixin(este_jogador, damageClassMixin) - - setmetatable(este_jogador, Details.atributo_damage) - este_jogador.__index = Details.atributo_damage - --restaura as metas dos containers - Details.refresh:r_container_habilidades (este_jogador.spells, shadow and shadow.spells) +function Details.refresh:r_atributo_damage(actorObject) + detailsFramework:Mixin(actorObject, Details222.Mixins.ActorMixin) + detailsFramework:Mixin(actorObject, damageClassMixin) + + setmetatable(actorObject, Details.atributo_damage) + actorObject.__index = Details.atributo_damage + + --restore metatable for the spell container + Details.refresh:r_container_habilidades(actorObject.spells) end function Details.clear:c_atributo_damage (este_jogador) este_jogador.__index = nil - este_jogador.shadow = nil este_jogador.links = nil este_jogador.minha_barra = nil diff --git a/classes/class_heal.lua b/classes/class_heal.lua index 70c64634..5e4b0d74 100644 --- a/classes/class_heal.lua +++ b/classes/class_heal.lua @@ -33,7 +33,7 @@ local detailsFramework = DetailsFramework local alvo_da_habilidade = _detalhes.alvo_da_habilidade local container_habilidades = _detalhes.container_habilidades local container_combatentes = _detalhes.container_combatentes -local atributo_heal = _detalhes.atributo_heal +local healingClass = _detalhes.atributo_heal local habilidade_cura = _detalhes.habilidade_cura local container_playernpc = _detalhes.container_type.CONTAINER_PLAYERNPC @@ -66,7 +66,7 @@ local headerColor = "yellow" local info = _detalhes.playerDetailWindow local keyName -function atributo_heal:NovaTabela (serial, nome, link) +function healingClass:NovaTabela (serial, nome, link) local alphabetical = _detalhes:GetOrderNumber(nome) --constructor @@ -109,7 +109,7 @@ function atributo_heal:NovaTabela (serial, nome, link) } detailsFramework:Mixin(thisActor, Details222.Mixins.ActorMixin) - setmetatable(thisActor, atributo_heal) + setmetatable(thisActor, healingClass) return thisActor end @@ -168,7 +168,7 @@ function _detalhes:ContainerSortHeal (container, amount, keyName2) end end -function atributo_heal:ContainerRefreshHps (container, combat_time) +function healingClass:ContainerRefreshHps (container, combat_time) local total = 0 @@ -191,7 +191,7 @@ function atributo_heal:ContainerRefreshHps (container, combat_time) return total end -function atributo_heal:ReportSingleDamagePreventedLine (actor, instancia) +function healingClass:ReportSingleDamagePreventedLine (actor, instancia) local barra = instancia.barras [actor.minha_barra] local reportar = {"Details!: " .. actor.nome .. " - " .. Loc ["STRING_ATTRIBUTE_HEAL_PREVENT"]} @@ -206,7 +206,7 @@ function atributo_heal:ReportSingleDamagePreventedLine (actor, instancia) return _detalhes:Reportar (reportar, {_no_current = true, _no_inverse = true, _custom = true}) end -function atributo_heal:RefreshWindow (instancia, tabela_do_combate, forcar, exportar) +function healingClass:RefreshWindow (instancia, tabela_do_combate, forcar, exportar) local showing = tabela_do_combate [class_type] --o que esta sendo mostrado -> [1] - dano [2] - cura @@ -285,7 +285,7 @@ function atributo_heal:RefreshWindow (instancia, tabela_do_combate, forcar, expo if (sub_atributo == 2) then --hps local combat_time = instancia.showing:GetCombatTime() - total = atributo_heal:ContainerRefreshHps (conteudo, combat_time) + total = healingClass:ContainerRefreshHps (conteudo, combat_time) else --pega o total ja aplicado na tabela do combate total = tabela_do_combate.totals [class_type] @@ -301,12 +301,11 @@ function atributo_heal:RefreshWindow (instancia, tabela_do_combate, forcar, expo end if (using_cache) then - conteudo = _detalhes.cache_healing_group if (sub_atributo == 2) then --hps local combat_time = instancia.showing:GetCombatTime() - atributo_heal:ContainerRefreshHps (conteudo, combat_time) + healingClass:ContainerRefreshHps (conteudo, combat_time) end if (#conteudo < 1) then @@ -329,7 +328,7 @@ function atributo_heal:RefreshWindow (instancia, tabela_do_combate, forcar, expo else if (sub_atributo == 2) then --hps local combat_time = instancia.showing:GetCombatTime() - atributo_heal:ContainerRefreshHps (conteudo, combat_time) + healingClass:ContainerRefreshHps (conteudo, combat_time) end _detalhes.SortGroupHeal (conteudo, keyName) @@ -587,7 +586,7 @@ end local actor_class_color_r, actor_class_color_g, actor_class_color_b --function atributo_heal:RefreshLine(instancia, whichRowLine, lugar, total, sub_atributo, forcar) -function atributo_heal:RefreshLine(instancia, barras_container, whichRowLine, lugar, total, sub_atributo, forcar, keyName, combat_time, percentage_type, use_animations, bars_show_data, bars_brackets, bars_separator) +function healingClass:RefreshLine(instancia, barras_container, whichRowLine, lugar, total, sub_atributo, forcar, keyName, combat_time, percentage_type, use_animations, bars_show_data, bars_brackets, bars_separator) local thisLine = instancia.barras[whichRowLine] --pega a refer�ncia da barra na janela @@ -867,7 +866,7 @@ function atributo_heal:RefreshLine(instancia, barras_container, whichRowLine, lu return self:RefreshBarra2 (thisLine, instancia, tabela_anterior, forcar, esta_porcentagem, whichRowLine, barras_container, use_animations) end -function atributo_heal:RefreshBarra2 (thisLine, instancia, tabela_anterior, forcar, esta_porcentagem, whichRowLine, barras_container, use_animations) +function healingClass:RefreshBarra2 (thisLine, instancia, tabela_anterior, forcar, esta_porcentagem, whichRowLine, barras_container, use_animations) --primeiro colocado if (thisLine.colocacao == 1) then @@ -936,7 +935,7 @@ function atributo_heal:RefreshBarra2 (thisLine, instancia, tabela_anterior, forc end -function atributo_heal:RefreshBarra(thisLine, instancia, from_resize) +function healingClass:RefreshBarra(thisLine, instancia, from_resize) local class, enemy, arena_enemy, arena_ally = self.classe, self.enemy, self.arena_enemy, self.arena_ally @@ -995,7 +994,7 @@ end ---------TOOLTIPS BIFURCA��O ~tooltip -function atributo_heal:ToolTip (instancia, numero, barra, keydown) +function healingClass:ToolTip (instancia, numero, barra, keydown) --seria possivel aqui colocar o icone da classe dele? if (instancia.atributo == 5) then --custom @@ -1019,7 +1018,7 @@ local r, g, b local barAlha = .6 ---------HEAL DENIED -function atributo_heal:ToolTip_HealingDenied (instancia, numero, barra, keydown) +function healingClass:ToolTip_HealingDenied (instancia, numero, barra, keydown) local owner = self.owner if (owner and owner.classe) then @@ -1212,7 +1211,7 @@ function atributo_heal:ToolTip_HealingDenied (instancia, numero, barra, keydown) end ---------HEALING TAKEN -function atributo_heal:ToolTip_HealingTaken (instancia, numero, barra, keydown) +function healingClass:ToolTip_HealingTaken (instancia, numero, barra, keydown) local owner = self.owner if (owner and owner.classe) then @@ -1301,7 +1300,7 @@ end ---------HEALING DONE / HPS / OVERHEAL local background_heal_vs_absorbs = {value = 100, color = {1, 1, 0, .25}, specialSpark = false, texture = [[Interface\AddOns\Details\images\bar4_glass]]} -function atributo_heal:ToolTip_HealingDone (instancia, numero, barra, keydown) +function healingClass:ToolTip_HealingDone (instancia, numero, barra, keydown) local owner = self.owner if (owner and owner.classe) then @@ -1656,7 +1655,7 @@ end --------------------------------------------- // JANELA DETALHES // --------------------------------------------- ---------- bifurca��o -function atributo_heal:MontaInfo() +function healingClass:MontaInfo() if (info.sub_atributo == 1 or info.sub_atributo == 2) then self:MontaInfoHealingDone() @@ -1731,7 +1730,7 @@ function atributo_heal:MontaInfo() end local healingTakenHeadersAllowed = {icon = true, name = true, rank = true, amount = true, persecond = true, percent = true} -function atributo_heal:MontaInfoHealTaken() +function healingClass:MontaInfoHealTaken() ---@type actor local actorObject = self ---@type instance @@ -1832,7 +1831,7 @@ function atributo_heal:MontaInfoHealTaken() end -function atributo_heal:MontaInfoOverHealing() --this should be deprecated now +function healingClass:MontaInfoOverHealing() --this should be deprecated now --pegar as habilidade de dar sort no heal local instancia = info.instancia @@ -1972,7 +1971,7 @@ function atributo_heal:MontaInfoOverHealing() --this should be deprecated now end end -function atributo_heal:MontaInfoHealingDone() +function healingClass:MontaInfoHealingDone() ---@type actor local actorObject = self ---@type instance @@ -2315,7 +2314,7 @@ function atributo_heal:MontaInfoHealingDone() end -function atributo_heal:MontaTooltipAlvos (thisLine, index, instancia) +function healingClass:MontaTooltipAlvos (thisLine, index, instancia) local inimigo = thisLine.nome_inimigo local container = self.spells._ActorTable @@ -2420,16 +2419,16 @@ function atributo_heal:MontaTooltipAlvos (thisLine, index, instancia) end -function atributo_heal:MontaDetalhes (spellid, barra) +function healingClass:MontaDetalhes (spellid, barra) --bifurga��es if (info.sub_atributo == 1 or info.sub_atributo == 2 or info.sub_atributo == 3) then return self:MontaDetalhesHealingDone (spellid, barra) elseif (info.sub_atributo == 4) then - atributo_heal:MontaDetalhesHealingTaken (spellid, barra) + healingClass:MontaDetalhesHealingTaken (spellid, barra) end end -function atributo_heal:MontaDetalhesHealingTaken (nome, barra) +function healingClass:MontaDetalhesHealingTaken (nome, barra) local barras = info.barras3 local instancia = info.instancia @@ -2503,7 +2502,7 @@ local critical_table = {c = {1, 1, 1, 0.4}, p = 0} local data_table = {} local t1, t2, t3, t4 = {}, {}, {}, {} -function atributo_heal:MontaDetalhesHealingDone (spellid, barra) +function healingClass:MontaDetalhesHealingDone (spellid, barra) --deprecated with the new breakdown window local esta_magia if (barra.other_actor) then @@ -2768,7 +2767,7 @@ function atributo_heal:MontaDetalhesHealingDone (spellid, barra) end --controla se o dps do jogador esta travado ou destravado -function atributo_heal:Iniciar (iniciar) +function healingClass:Iniciar (iniciar) if (iniciar == nil) then return self.iniciar_hps --retorna se o dps esta aberto ou fechado para este jogador elseif (iniciar) then @@ -2784,7 +2783,7 @@ end --core functions --atualize a funcao de abreviacao - function atributo_heal:UpdateSelectedToKFunction() + function healingClass:UpdateSelectedToKFunction() SelectedToKFunction = ToKFunctions [_detalhes.ps_abbreviation] FormatTooltipNumber = ToKFunctions [_detalhes.tooltip.abbreviation] TooltipMaximizedMethod = _detalhes.tooltip.maximize_method @@ -2792,269 +2791,193 @@ end end --subtract total from a combat table - function atributo_heal:subtract_total (combat_table) + function healingClass:subtract_total (combat_table) combat_table.totals [class_type] = combat_table.totals [class_type] - self.total if (self.grupo) then combat_table.totals_grupo [class_type] = combat_table.totals_grupo [class_type] - self.total end end - function atributo_heal:add_total (combat_table) + function healingClass:add_total (combat_table) combat_table.totals [class_type] = combat_table.totals [class_type] + self.total if (self.grupo) then combat_table.totals_grupo [class_type] = combat_table.totals_grupo [class_type] + self.total end end - --restaura a tabela de last event - function atributo_heal:r_last_events_table (actor) - if (not actor) then - actor = self - end - --actor.last_events_table = _detalhes:CreateActorLastEventTable() + ---sum the passed actor into a combat, if the combat isn't passed, it will use the overall combat + ---the function returns the actor that was created of found in the combat passed + ---@param actorObject actor + ---@param bRefreshActor boolean|nil + ---@param combatObject combat|nil + ---@return actor + function healingClass:AddToCombat(actorObject, bRefreshActor, combatObject) + --check if there's a custom combat, if not just use the overall container + combatObject = combatObject or _detalhes.tabela_overall --same as Details:GetCombat(DETAILS_SEGMENTID_OVERALL) + + --check if the combatObject has an actor with the same name, if not, just create one new + local actorContainer = combatObject[DETAILS_ATTRIBUTE_HEAL] --same as combatObject:GetContainer(DETAILS_ATTRIBUTE_HEAL) + local overallActor = actorContainer._ActorTable[actorContainer._NameIndexTable[actorObject.nome]] --same as actorContainer:GetActor(actorObject:Name()) + + if (not overallActor) then + overallActor = actorContainer:GetOrCreateActor(actorObject.serial, actorObject.nome, actorObject.flag_original, true) + overallActor.classe = actorObject.classe + overallActor:SetSpecId(actorObject.spec) + overallActor.pvp = actorObject.pvp + overallActor.isTank = actorObject.isTank + overallActor.boss = actorObject.boss + overallActor.start_time = time() - 3 + overallActor.end_time = time() end - --restaura e liga o ator com a sua shadow durante a inicializa��o - function atributo_heal:r_onlyrefresh_shadow (actor) + overallActor.displayName = actorObject.displayName or actorObject.nome + overallActor.boss_fight_component = actorObject.boss_fight_component or overallActor.boss_fight_component + overallActor.fight_component = actorObject.fight_component or overallActor.fight_component + overallActor.grupo = actorObject.grupo or overallActor.grupo - --criar uma shadow desse ator se ainda n�o tiver uma - local overall_cura = _detalhes.tabela_overall [2] - local shadow = overall_cura._ActorTable [overall_cura._NameIndexTable [actor.nome]] - - if (not shadow) then - shadow = overall_cura:PegarCombatente (actor.serial, actor.nome, actor.flag_original, true) - - shadow.classe = actor.classe - shadow:SetSpecId(actor.spec) - shadow.grupo = actor.grupo - shadow.pvp = actor.pvp - shadow.isTank = actor.isTank - shadow.boss = actor.boss - shadow.boss_fight_component = actor.boss_fight_component - shadow.fight_component = actor.fight_component - - shadow.start_time = time() - 3 - shadow.end_time = time() - end - - --restaura a meta e indexes ao ator - _detalhes.refresh:r_atributo_heal (actor, shadow) - - --copia o container de alvos (captura de dados) - for target_name, amount in pairs(actor.targets) do - shadow.targets [target_name] = 0 - end - for target_name, amount in pairs(actor.targets_overheal) do - shadow.targets_overheal [target_name] = 0 - end - for target_name, amount in pairs(actor.targets_absorbs) do - shadow.targets_absorbs [target_name] = 0 - end - - --copia o container de habilidades (captura de dados) - for spellid, habilidade in pairs(actor.spells._ActorTable) do - --cria e soma o valor - local habilidade_shadow = shadow.spells:PegaHabilidade (spellid, true, nil, true) - --refresh e soma os valores dos alvos - - for target_name, amount in pairs(habilidade.targets) do - if (not habilidade_shadow.targets [target_name]) then - habilidade_shadow.targets [target_name] = 0 - end - end - for target_name, amount in pairs(habilidade.targets_overheal) do - if (not habilidade_shadow.targets_overheal [target_name]) then - habilidade_shadow.targets_overheal [target_name] = 0 - end - end - for target_name, amount in pairs(habilidade.targets_absorbs) do - if (not habilidade_shadow.targets_absorbs [target_name]) then - habilidade_shadow.targets_absorbs [target_name] = 0 - end - end - - --copia o container de heal negado se ele existir - if (habilidade.heal_denied) then - --cria o container na shadow de ele n�o existir - habilidade_shadow.heal_denied = habilidade_shadow.heal_denied or {} - habilidade_shadow.heal_denied_healers = habilidade_shadow.heal_denied_healers or {} - --copia - for spellID, amount in pairs(habilidade.heal_denied) do - if (not habilidade_shadow.heal_denied [spellID]) then - habilidade_shadow.heal_denied [spellID] = 0 - end - end - for healerName, amount in pairs(habilidade.heal_denied_healers) do - if (not habilidade_shadow.heal_denied_healers [healerName]) then - habilidade_shadow.heal_denied_healers [healerName] = 0 - end - end - end - - end - - return shadow + --check if need to restore meta tables and indexes for this actor + if (bRefreshActor) then + --this call will reenable the metatable, __index and set the metatable on the .spells container + Details.refresh:r_atributo_heal(actorObject) end - function atributo_heal:r_connect_shadow (actor, no_refresh, combat_object) + --elapsed time + local endTime = actorObject.end_time + if (not actorObject.end_time) then + endTime = time() + end - local host_combat = combat_object or _detalhes.tabela_overall + local tempo = endTime - actorObject.start_time + overallActor.start_time = overallActor.start_time - tempo - --criar uma shadow desse ator se ainda n�o tiver uma - local overall_cura = host_combat [2] - local shadow = overall_cura._ActorTable [overall_cura._NameIndexTable [actor.nome]] + --pets (add unique pet names) + for _, petName in ipairs(actorObject.pets) do + DetailsFramework.table.addunique(overallActor.pets, petName) + end - if (not shadow) then - shadow = overall_cura:PegarCombatente (actor.serial, actor.nome, actor.flag_original, true) + ---@cast actorObject actorheal - shadow.classe = actor.classe - shadow:SetSpecId(actor.spec) - shadow.grupo = actor.grupo - shadow.pvp = actor.pvp - shadow.isTank = actor.isTank - shadow.boss = actor.boss - shadow.boss_fight_component = actor.boss_fight_component - shadow.fight_component = actor.fight_component + --total healing done and total overheal + overallActor.total = overallActor.total + actorObject.total + overallActor.totalover = overallActor.totalover + actorObject.totalover - shadow.start_time = time() - 3 - shadow.end_time = time() - end + --healing done by shields + overallActor.totalabsorb = overallActor.totalabsorb + actorObject.totalabsorb - --restaura a meta e indexes ao ator - if (not no_refresh) then - _detalhes.refresh:r_atributo_heal (actor, shadow) - end + --enemy healing done + overallActor.heal_enemy_amt = overallActor.heal_enemy_amt + actorObject.heal_enemy_amt - --tempo decorrido (captura de dados) - local end_time = actor.end_time - if (not actor.end_time) then - end_time = time() - end + --heal denied + overallActor.totaldenied = overallActor.totaldenied + actorObject.totaldenied - local tempo = end_time - actor.start_time - shadow.start_time = shadow.start_time - tempo + --healing done without pets + overallActor.total_without_pet = overallActor.total_without_pet + actorObject.total_without_pet + overallActor.totalover_without_pet = overallActor.totalover_without_pet + actorObject.totalover_without_pet - --pets (add unique pet names) - for _, petName in ipairs(actor.pets) do - DetailsFramework.table.addunique (shadow.pets, petName) + --healing taken + overallActor.healing_taken = overallActor.healing_taken + actorObject.healing_taken + + --total no combate overall (captura de dados) + combatObject.totals[2] = combatObject.totals[2] + actorObject.total + if (actorObject.grupo) then --same as Details:IsGroupPlayer() + combatObject.totals_grupo[2] = combatObject.totals_grupo[2] + actorObject.total + end + + --copy healing taken from + for healerName, _ in pairs(actorObject.healing_from) do + overallActor.healing_from[healerName] = true + end + + --copy enemy healing + for spellId, amount in pairs(actorObject.heal_enemy) do + overallActor.heal_enemy[spellId] = (overallActor.heal_enemy[spellId] or 0) + amount + end + + --copy target tables + for targetName, amount in pairs(actorObject.targets) do + overallActor.targets[targetName] = (overallActor.targets[targetName] or 0) + amount + end + + for targetName, amount in pairs(actorObject.targets_overheal) do + overallActor.targets_overheal[targetName] = (overallActor.targets_overheal[targetName] or 0) + amount + end + + for targetName, amount in pairs(actorObject.targets_absorbs) do + overallActor.targets_absorbs[targetName] = (overallActor.targets_absorbs[targetName] or 0) + amount + end + + ---@type spellcontainer + local overallSpellsContainer = overallActor.spells --same as overallActor:GetSpellContainer("spell") + + --copy spell table + for spellId, spellTable in pairs(actorObject.spells._ActorTable) do --same as overallSpellsContainer:GetRawSpellTable() + --var name has 'overall' but this function accepts any combat table + local overallSpellTable = overallSpellsContainer:GetOrCreateSpell(spellId, true) + + --sum spell targets + for targetName, amount in pairs(spellTable.targets) do + overallSpellTable.targets[targetName] = (overallSpellTable.targets[targetName] or 0) + amount end - --total de cura (captura de dados) - shadow.total = shadow.total + actor.total - --total de overheal (captura de dados) - shadow.totalover = shadow.totalover + actor.totalover - --total de absorbs (captura de dados) - shadow.totalabsorb = shadow.totalabsorb + actor.totalabsorb - --total de cura feita em inimigos (captura de dados) - shadow.heal_enemy_amt = shadow.heal_enemy_amt + actor.heal_enemy_amt - --total de heal negado - shadow.totaldenied = shadow.totaldenied + actor.totaldenied - --total sem pets (captura de dados) - shadow.total_without_pet = shadow.total_without_pet + actor.total_without_pet - shadow.totalover_without_pet = shadow.totalover_without_pet + actor.totalover_without_pet - --total de cura recebida (captura de dados) - shadow.healing_taken = shadow.healing_taken + actor.healing_taken + for targetName, amount in pairs(spellTable.targets_overheal) do + overallSpellTable.targets_overheal[targetName] = (overallSpellTable.targets_overheal[targetName] or 0) + amount + end - --total no combate overall (captura de dados) - host_combat.totals[2] = host_combat.totals[2] + actor.total - if (actor.grupo) then - host_combat.totals_grupo[2] = host_combat.totals_grupo[2] + actor.total + for targetName, amount in pairs(spellTable.targets_absorbs) do + overallSpellTable.targets_absorbs[targetName] = (overallSpellTable.targets_absorbs[targetName] or 0) + amount + end + + --copy heal denied if it exists + if (spellTable.heal_denied) then + overallSpellTable.heal_denied = overallSpellTable.heal_denied or {} + overallSpellTable.heal_denied_healers = overallSpellTable.heal_denied_healers or {} + --copy + for spellID, amount in pairs(spellTable.heal_denied) do + overallSpellTable.heal_denied[spellID] = (overallSpellTable.heal_denied[spellID] or 0) + amount end - - --copia o healing_from (captura de dados) - for nome, _ in pairs(actor.healing_from) do - shadow.healing_from [nome] = true + for healerName, amount in pairs(spellTable.heal_denied_healers) do + overallSpellTable.heal_denied_healers[healerName] = (overallSpellTable.heal_denied_healers[healerName] or 0) + amount end + end - --copia o heal_enemy (captura de dados) - for spellid, amount in pairs(actor.heal_enemy) do - if (shadow.heal_enemy [spellid]) then - shadow.heal_enemy [spellid] = shadow.heal_enemy [spellid] + amount - else - shadow.heal_enemy [spellid] = amount - end - end + overallSpellTable.spellschool = spellTable.spellschool - --copia o container de alvos (captura de dados) - for target_name, amount in pairs(actor.targets) do - shadow.targets [target_name] = (shadow.targets [target_name] or 0) + amount - end - for target_name, amount in pairs(actor.targets_overheal) do - shadow.targets_overheal [target_name] = (shadow.targets_overheal [target_name] or 0) + amount - end - for target_name, amount in pairs(actor.targets_absorbs) do - shadow.targets_absorbs [target_name] = (shadow.targets_absorbs [target_name] or 0) + amount - end - - --copia o container de habilidades (captura de dados) - for spellid, habilidade in pairs(actor.spells._ActorTable) do - --cria e soma o valor - local habilidade_shadow = shadow.spells:PegaHabilidade (spellid, true, nil, true) - - --refresh e soma os valores dos alvos - for target_name, amount in pairs(habilidade.targets) do - habilidade_shadow.targets [target_name] = (habilidade_shadow.targets [target_name] or 0) + amount - end - for target_name, amount in pairs(habilidade.targets_overheal) do - habilidade_shadow.targets_overheal [target_name] = (habilidade_shadow.targets_overheal [target_name] or 0) + amount - end - for target_name, amount in pairs(habilidade.targets_absorbs) do - habilidade_shadow.targets_absorbs [target_name] = (habilidade_shadow.targets_absorbs [target_name] or 0) + amount - end - - --copia o container de heal negado se ele existir - if (habilidade.heal_denied) then - --cria o container na shadow de ele n�o existir - habilidade_shadow.heal_denied = habilidade_shadow.heal_denied or {} - habilidade_shadow.heal_denied_healers = habilidade_shadow.heal_denied_healers or {} - --copia - for spellID, amount in pairs(habilidade.heal_denied) do - habilidade_shadow.heal_denied [spellID] = (habilidade_shadow.heal_denied [spellID] or 0) + amount + --sum all values of the spelltable which can be summed + for key, value in pairs(spellTable) do + if (type(value) == "number") then + if (key ~= "id" and key ~= "spellschool") then + if (not overallSpellTable[key]) then + overallSpellTable[key] = 0 end - for healerName, amount in pairs(habilidade.heal_denied_healers) do - habilidade_shadow.heal_denied_healers [healerName] = (habilidade_shadow.heal_denied_healers [healerName] or 0) + amount + + if (key == "n_min" or key == "c_min") then + if (overallSpellTable[key] > value) then + overallSpellTable[key] = value + end + elseif (key == "n_max" or key == "c_max") then + if (overallSpellTable[key] < value) then + overallSpellTable[key] = value + end + else + overallSpellTable[key] = overallSpellTable[key] + value end end - habilidade_shadow.spellschool = habilidade.spellschool - - --soma todos os demais valores - for key, value in pairs(habilidade) do - if (type(value) == "number") then - if (key ~= "id" and key ~= "spellschool") then - if (not habilidade_shadow [key]) then - habilidade_shadow [key] = 0 - end - - if (key == "n_min" or key == "c_min") then - if (habilidade_shadow [key] > value) then - habilidade_shadow [key] = value - end - elseif (key == "n_max" or key == "c_max") then - if (habilidade_shadow [key] < value) then - habilidade_shadow [key] = value - end - else - habilidade_shadow [key] = habilidade_shadow [key] + value - end - - end - elseif(key == "e_heal" or key == "e_lvl") then - if (not habilidade_shadow[key]) then - habilidade_shadow[key] = {} - end - for empowermentLevel, empowermentValue in pairs(habilidade[key]) do - habilidade_shadow[key][empowermentLevel] = empowermentValue - end - end + --empowered spells + elseif(key == "e_heal" or key == "e_lvl") then + if (not overallSpellTable[key]) then + overallSpellTable[key] = {} + end + for empowermentLevel, empowermentValue in pairs(spellTable[key]) do + overallSpellTable[key][empowermentLevel] = empowermentValue end - end - - return shadow + end end -atributo_heal.__add = function(tabela1, tabela2) + return overallActor + end +healingClass.__add = function(tabela1, tabela2) --tempo decorrido local tempo = (tabela2.end_time or time()) - tabela2.start_time tabela1.start_time = tabela1.start_time - tempo @@ -3092,13 +3015,13 @@ atributo_heal.__add = function(tabela1, tabela2) --somar o container de alvos for target_name, amount in pairs(tabela2.targets) do - tabela1.targets [target_name] = (tabela1.targets [target_name] or 0) + amount + tabela1.targets[target_name] = (tabela1.targets[target_name] or 0) + amount end for target_name, amount in pairs(tabela2.targets_overheal) do - tabela1.targets_overheal [target_name] = (tabela1.targets_overheal [target_name] or 0) + amount + tabela1.targets_overheal[target_name] = (tabela1.targets_overheal[target_name] or 0) + amount end for target_name, amount in pairs(tabela2.targets_absorbs) do - tabela1.targets_absorbs [target_name] = (tabela1.targets_absorbs [target_name] or 0) + amount + tabela1.targets_absorbs[target_name] = (tabela1.targets_absorbs[target_name] or 0) + amount end --soma o container de habilidades @@ -3107,26 +3030,25 @@ atributo_heal.__add = function(tabela1, tabela2) local habilidade_tabela1 = tabela1.spells:PegaHabilidade (spellid, true, "SPELL_HEAL", false) --soma os alvos for target_name, amount in pairs(habilidade.targets) do - habilidade_tabela1.targets = (habilidade_tabela1.targets [target_name] or 0) + amount + habilidade_tabela1.targets = (habilidade_tabela1.targets[target_name] or 0) + amount end for target_name, amount in pairs(habilidade.targets_overheal) do - habilidade_tabela1.targets_overheal = (habilidade_tabela1.targets_overheal [target_name] or 0) + amount + habilidade_tabela1.targets_overheal = (habilidade_tabela1.targets_overheal[target_name] or 0) + amount end for target_name, amount in pairs(habilidade.targets_absorbs) do - habilidade_tabela1.targets_absorbs = (habilidade_tabela1.targets_absorbs [target_name] or 0) + amount + habilidade_tabela1.targets_absorbs = (habilidade_tabela1.targets_absorbs[target_name] or 0) + amount end --copia o container de heal negado se ele existir if (habilidade.heal_denied) then - --cria o container na shadow de ele n�o existir habilidade_tabela1.heal_denied = habilidade_tabela1.heal_denied or {} habilidade_tabela1.heal_denied_healers = habilidade_tabela1.heal_denied_healers or {} --copia for spellID, amount in pairs(habilidade.heal_denied) do - habilidade_tabela1.heal_denied [spellID] = (habilidade_tabela1.heal_denied [spellID] or 0) + amount + habilidade_tabela1.heal_denied[spellID] = (habilidade_tabela1.heal_denied[spellID] or 0) + amount end for healerName, amount in pairs(habilidade.heal_denied_healers) do - habilidade_tabela1.heal_denied_healers [healerName] = (habilidade_tabela1.heal_denied_healers [healerName] or 0) + amount + habilidade_tabela1.heal_denied_healers[healerName] = (habilidade_tabela1.heal_denied_healers[healerName] or 0) + amount end end @@ -3163,7 +3085,7 @@ atributo_heal.__add = function(tabela1, tabela2) return tabela1 end -atributo_heal.__sub = function(tabela1, tabela2) +healingClass.__sub = function(tabela1, tabela2) --tempo decorrido local tempo = (tabela2.end_time or time()) - tabela2.start_time @@ -3235,7 +3157,6 @@ atributo_heal.__sub = function(tabela1, tabela2) --copia o container de heal negado se ele existir if (habilidade.heal_denied) then - --cria o container na shadow de ele n�o existir habilidade_tabela1.heal_denied = habilidade_tabela1.heal_denied or {} habilidade_tabela1.heal_denied_healers = habilidade_tabela1.heal_denied_healers or {} --copia @@ -3273,19 +3194,19 @@ atributo_heal.__sub = function(tabela1, tabela2) return tabela1 end -function _detalhes.refresh:r_atributo_heal(thisActor, shadow) - setmetatable(thisActor, atributo_heal) - thisActor.__index = atributo_heal +function Details.refresh:r_atributo_heal(thisActor) detailsFramework:Mixin(thisActor, Details222.Mixins.ActorMixin) - _detalhes.refresh:r_container_habilidades(thisActor.spells, shadow and shadow.spells) + setmetatable(thisActor, healingClass) + thisActor.__index = healingClass + + Details.refresh:r_container_habilidades(thisActor.spells) end -function _detalhes.clear:c_atributo_heal (este_jogador) +function Details.clear:c_atributo_heal (este_jogador) este_jogador.__index = nil - este_jogador.shadow = nil este_jogador.links = nil este_jogador.minha_barra = nil - _detalhes.clear:c_container_habilidades (este_jogador.spells) + Details.clear:c_container_habilidades (este_jogador.spells) end diff --git a/classes/class_resources.lua b/classes/class_resources.lua index 95627c16..b91d38e6 100644 --- a/classes/class_resources.lua +++ b/classes/class_resources.lua @@ -1552,7 +1552,6 @@ end function _detalhes.clear:c_atributo_energy (este_jogador) este_jogador.__index = nil - este_jogador.shadow = nil este_jogador.links = nil este_jogador.minha_barra = nil diff --git a/classes/class_spelldamage.lua b/classes/class_spelldamage.lua index fcc47b73..c83e0295 100644 --- a/classes/class_spelldamage.lua +++ b/classes/class_spelldamage.lua @@ -14,6 +14,7 @@ function Details.CreateSpellTable(spellId, cleuToken) end ---create a spelltable to store the damage of a spell +---@param self any ---@param spellId number ---@param link nil ---@param token string diff --git a/classes/class_spellresources.lua b/classes/class_spellresources.lua index 8b1e5276..e5848ae0 100644 --- a/classes/class_spellresources.lua +++ b/classes/class_spellresources.lua @@ -1,46 +1,24 @@ --- energy ability file local _detalhes = _G.Details local _ local addonName, Details222 = ... ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ---local pointers - - local setmetatable = setmetatable --lua local - local ipairs = ipairs --lua local - local _UnitAura = UnitAura --api local - ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ---constants - - local alvo_da_habilidade = _detalhes.alvo_da_habilidade local habilidade_energy = _detalhes.habilidade_e_energy - local container_combatentes = _detalhes.container_combatentes - local container_energy_target = _detalhes.container_type.CONTAINER_ENERGYTARGET_CLASS - local container_playernpc = _detalhes.container_type.CONTAINER_PLAYERNPC - ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ---internals function habilidade_energy:NovaTabela (id, link, token) - - local _newEnergySpell = { + local newSpellTable = { id = id, counter = 0, total = 0, totalover = 0, targets = {} } - - return _newEnergySpell + return newSpellTable end - function habilidade_energy:Add (serial, nome, flag, amount, who_nome, powertype, overpower) - + function habilidade_energy:Add(serial, nome, flag, amount, who_nome, powertype, overpower) self.counter = self.counter + 1 self.total = self.total + amount self.totalover = self.totalover + overpower - self.targets [nome] = (self.targets [nome] or 0) + amount - + self.targets[nome] = (self.targets[nome] or 0) + amount end diff --git a/classes/class_utility.lua b/classes/class_utility.lua index 5d5905e3..6444e86d 100644 --- a/classes/class_utility.lua +++ b/classes/class_utility.lua @@ -417,7 +417,7 @@ function atributo_misc:ReportSingleDeadLine (morte, instancia) end local default_len = _detalhes.fontstring_len:GetStringWidth() - Details:Destroy (report_table) + Details:Destroy(report_table) local report_array = report_table report_array[1] = {"Details! " .. Loc ["STRING_REPORT_SINGLE_DEATH"] .. " " .. morte [3] .. " " .. Loc ["STRING_ACTORFRAME_REPORTAT"] .. " " .. morte [6], "", "", ""} @@ -2814,9 +2814,7 @@ function _detalhes.refresh:r_atributo_misc(thisActor, shadow) end function _detalhes.clear:c_atributo_misc (este_jogador) - este_jogador.__index = nil - este_jogador.shadow = nil este_jogador.links = nil este_jogador.minha_barra = nil diff --git a/classes/container_actors.lua b/classes/container_actors.lua index 2b242d44..6365a247 100644 --- a/classes/container_actors.lua +++ b/classes/container_actors.lua @@ -37,7 +37,6 @@ local actorContainer = Details.container_combatentes - local alvo_da_habilidade = Details.alvo_da_habilidade local atributo_damage = Details.atributo_damage local atributo_heal = Details.atributo_heal local atributo_energy = Details.atributo_energy @@ -45,13 +44,9 @@ local container_damage = Details.container_type.CONTAINER_DAMAGE_CLASS local container_heal = Details.container_type.CONTAINER_HEAL_CLASS - local container_heal_target = Details.container_type.CONTAINER_HEALTARGET_CLASS - local container_friendlyfire = Details.container_type.CONTAINER_FRIENDLYFIRE - local container_damage_target = Details.container_type.CONTAINER_DAMAGETARGET_CLASS local container_energy = Details.container_type.CONTAINER_ENERGY_CLASS local container_energy_target = Details.container_type.CONTAINER_ENERGYTARGET_CLASS local container_misc = Details.container_type.CONTAINER_MISC_CLASS - local container_misc_target = Details.container_type.CONTAINER_MISCTARGET_CLASS local container_enemydebufftarget_target = Details.container_type.CONTAINER_ENEMYDEBUFFTARGET_CLASS local container_pets = {} @@ -74,32 +69,6 @@ local SPELLID_SANGUINE_HEAL = 226510 local sanguineActorName = GetSpellInfo(SPELLID_SANGUINE_HEAL) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ---api functions - ---[=[ -["AzeriteItemPowerDescription"] = 9, -["SellPrice"] = 11, -["CurrencyTotal"] = 14, -["GemSocket"] = 3, -["QuestObjective"] = 8, -["UnitName"] = 2, -["SpellName"] = 13, -["ItemEnchantmentPermanent"] = 15, -["RuneforgeLegendaryPowerDescription"] = 10, -["QuestPlayer"] = 18, -["Blank"] = 1, -["UnitOwner"] = 16, -["LearnableSpell"] = 6, -["ProfessionCraftingQuality"] = 12, -["UnitThreat"] = 7, -["QuestTitle"] = 17, -["ItemBinding"] = 20, -["NestedBlock"] = 19, -["AzeriteEssencePower"] = 5, -["AzeriteEssenceSlot"] = 4, -["None"] = 0, ---]=] ---attempt to get the owner of rogue's Akaari's Soul from Secrect Technique ---@param petGUID string @@ -382,9 +351,9 @@ end ---@param actorName string ---@return table|nil function actorContainer:GetActor(actorName) - local index = self._NameIndexTable [actorName] + local index = self._NameIndexTable[actorName] if (index) then - return self._ActorTable [index] + return self._ActorTable[index] end end @@ -486,11 +455,7 @@ end end if (not specId and Details.track_specs) then - Details:ScheduleTimer("GuessSpec", 2, {actorObject, nil, 1}) --- if (Details.streamer_config.quick_detection) then --- else --- Details:ScheduleTimer("GuessSpec", 3, {actorObject, nil, 1}) --- end + Details:ScheduleTimer("GuessSpec", 3, {actorObject, nil, 1}) end local _, engClass = UnitClass(actorName or "") @@ -608,7 +573,6 @@ end if (playerArenaInfo) then actorObject.role = playerArenaInfo.role - if (playerArenaInfo.role == "NONE") then local role = UnitGroupRolesAssigned and UnitGroupRolesAssigned(actorName) if (role and role ~= "NONE") then @@ -616,9 +580,9 @@ end end end else - local oponentes = GetNumArenaOpponentSpecs and GetNumArenaOpponentSpecs() or 5 + local amountOpponents = GetNumArenaOpponentSpecs and GetNumArenaOpponentSpecs() or 5 local found = false - for i = 1, oponentes do + for i = 1, amountOpponents do local name = GetUnitName("arena" .. i, true) if (name == actorName) then local spec = GetArenaOpponentSpec and GetArenaOpponentSpec(i) @@ -712,115 +676,13 @@ end end end - - - --Deprecated 4/3/2023 in favor of Details222.Pets.GetPetOwner - local find_pet_owner = function(petGUID, petName, petFlags, self) - if (not Details.tabela_vigente) then - return - end - - if (bIsDragonflight) then - pet_tooltip_frame:SetOwner(WorldFrame, "ANCHOR_NONE") - pet_tooltip_frame:SetHyperlink("unit:" .. (petGUID or "")) - local tooltipData = pet_tooltip_frame:GetTooltipData() - - if (tooltipData and tooltipData.lines[1]) then - if (tooltipData.lines[1].leftText == petName) then - for i = 2, #tooltipData.lines do - local tooltipLine = tooltipData.lines[i] - local args = tooltipLine.args - if (args) then - if (args[4] and args[4].field == "guid") then - local guidVal = args[4].guidVal - local guidCache = Details:GetParserPlayerCache() - if (guidCache[guidVal]) then - return petOwnerFound(guidCache[guidVal], petGUID, petName, petFlags, self, guidVal) - end - end - end - end - end - end - end - - Details.tabela_vigente.raid_roster_indexed = Details.tabela_vigente.raid_roster_indexed or {} - - local line1 = _G ["DetailsPetOwnerFinderTextLeft2"] - local text1 = line1 and line1:GetText() - if (text1 and text1 ~= "") then - --for _, playerName in ipairs(Details.tabela_vigente.raid_roster_indexed) do - for playerName, _ in pairs(Details.tabela_vigente.raid_roster) do - local pName = playerName - playerName = playerName:gsub("%-.*", "") --remove realm name - - --if the user client is in russian language - --make an attempt to remove declensions from the character's name - --this is equivalent to remove 's from the owner on enUS - if (CONST_CLIENT_LANGUAGE == "ruRU") then - if (find_name_declension (text1, playerName)) then - return petOwnerFound (pName, petGUID, petName, petFlags, self) - else - --print("not found declension (1):", pName, nome) - if (text1:find(playerName)) then - return petOwnerFound (pName, petGUID, petName, petFlags, self) - end - end - else - if (text1:find(playerName)) then - return petOwnerFound (pName, petGUID, petName, petFlags, self) - else - local ownerName = (string.match(text1, string.gsub(UNITNAME_TITLE_PET, "%%s", "(%.*)")) or string.match(text1, string.gsub(UNITNAME_TITLE_MINION, "%%s", "(%.*)")) or string.match(text1, string.gsub(UNITNAME_TITLE_GUARDIAN, "%%s", "(%.*)"))) - if (ownerName) then - if (Details.tabela_vigente.raid_roster[ownerName]) then - return petOwnerFound (ownerName, petGUID, petName, petFlags, self) - end - end - end - end - end - end - - local line2 = _G ["DetailsPetOwnerFinderTextLeft3"] - local text2 = line2 and line2:GetText() - if (text2 and text2 ~= "") then - for playerName, _ in pairs(Details.tabela_vigente.raid_roster) do - --for _, playerName in ipairs(Details.tabela_vigente.raid_roster_indexed) do - local pName = playerName - playerName = playerName:gsub("%-.*", "") --remove realm name - - if (CONST_CLIENT_LANGUAGE == "ruRU") then - if (find_name_declension (text2, playerName)) then - return petOwnerFound (pName, petGUID, petName, petFlags, self) - else - --print("not found declension (2):", pName, nome) - if (text2:find(playerName)) then - return petOwnerFound (pName, petGUID, petName, petFlags, self) - end - end - else - if (text2:find(playerName)) then - return petOwnerFound (pName, petGUID, petName, petFlags, self) - else - local ownerName = (string.match(text2, string.gsub(UNITNAME_TITLE_PET, "%%s", "(%.*)")) or string.match(text2, string.gsub(UNITNAME_TITLE_MINION, "%%s", "(%.*)")) or string.match(text2, string.gsub(UNITNAME_TITLE_GUARDIAN, "%%s", "(%.*)"))) - if (ownerName) then - if (Details.tabela_vigente.raid_roster[ownerName]) then - return petOwnerFound (ownerName, petGUID, petName, petFlags, self) - end - end - end - end - end - end - end - ---get an actor from the container, if the actor doesn't exists, and the bShouldCreateActor is true, create a new actor ---this function is an alias for PegarCombatente which is the function name is in portuguese ---@param actorSerial string ---@param actorName string ---@param actorFlags number ---@param bShouldCreateActor boolean - ---@return table + ---@return table|nil, table|nil, string|nil function actorContainer:GetOrCreateActor(actorSerial, actorName, actorFlags, bShouldCreateActor) return self:PegarCombatente(actorSerial, actorName, actorFlags, bShouldCreateActor) end @@ -829,249 +691,168 @@ end ---@param actorName string ---@param actorFlags number ---@param bShouldCreateActor boolean - ---@return table + ---@return table|nil, table|nil, string|nil function actorContainer:PegarCombatente(actorSerial, actorName, actorFlags, bShouldCreateActor) - --[[statistics]]-- _detalhes.statistics.container_calls = _detalhes.statistics.container_calls + 1 - - --verifica se � um pet, se for confere se tem o nome do dono, se n�o tiver, precisa por - local dono_do_pet + --need to check if the actor is a pet + local petOwnerObject actorSerial = actorSerial or "ns" - if (container_pets[actorSerial]) then --� um pet reconhecido - --[[statistics]]-- _detalhes.statistics.container_pet_calls = _detalhes.statistics.container_pet_calls + 1 - local petName, ownerName, ownerGUID, ownerFlag = Details.tabela_pets:PegaDono (actorSerial, actorName, actorFlags) + if (container_pets[actorSerial]) then --this is a registered pet + local petName, ownerName, ownerGUID, ownerFlag = Details.tabela_pets:PegaDono(actorSerial, actorName, actorFlags) if (petName and ownerName) then actorName = petName - dono_do_pet = self:PegarCombatente(ownerGUID, ownerName, ownerFlag, true) + petOwnerObject = self:PegarCombatente(ownerGUID, ownerName, ownerFlag, true) end - elseif (not petBlackList[actorSerial]) then --verifica se � um pet + elseif (not petBlackList[actorSerial]) then --check if is a pet petBlackList[actorSerial] = true --try to find the owner if (actorFlags and bitBand(actorFlags, OBJECT_TYPE_PETGUARDIAN) ~= 0) then - --[[statistics]]-- _detalhes.statistics.container_unknow_pet = _detalhes.statistics.container_unknow_pet + 1 local ownerName, ownerGUID, ownerFlags = Details222.Pets.GetPetOwner(actorSerial, actorName) if (ownerName and ownerGUID) then - local newPetName, ownerObject = petOwnerFound (ownerName, actorSerial, actorName, actorFlags, self, ownerGUID) + local newPetName, ownerObject = petOwnerFound(ownerName, actorSerial, actorName, actorFlags, self, ownerGUID) if (newPetName and ownerObject) then - actorName, dono_do_pet = newPetName, ownerObject + actorName, petOwnerObject = newPetName, ownerObject end end end end - --pega o index no mapa - local index = self._NameIndexTable[actorName] - --retorna o actor - if (index) then - return self._ActorTable[index], dono_do_pet, actorName + --get the actor index in the hash map + local actorIndex = self._NameIndexTable[actorName] + if (actorIndex) then + return self._ActorTable[actorIndex], petOwnerObject, actorName + end - --n�o achou, criar - elseif (bShouldCreateActor) then - local novo_objeto = self.funcao_de_criacao(_, actorSerial, actorName) - novo_objeto.nome = actorName - novo_objeto.flag_original = actorFlags - novo_objeto.serial = actorSerial + if (not bShouldCreateActor) then + return + end - --seta a classe default para desconhecido, assim nenhum objeto fica com classe nil - novo_objeto.classe = "UNKNOW" - local forceClass + ---@type actor + local newActor = self.funcao_de_criacao(_, actorSerial, actorName) + newActor.nome = actorName + newActor.flag_original = actorFlags + newActor.serial = actorSerial + newActor.classe = "UNKNOW" - --get the aID (actor id) - if (actorSerial:match("^C")) then - novo_objeto.aID = tostring(Details:GetNpcIdFromGuid(actorSerial)) + local forceClass - if (Details.immersion_special_units) then - local shouldBeInGroup, class = Details.Immersion.IsNpcInteresting(novo_objeto.aID) - novo_objeto.grupo = shouldBeInGroup - if (class) then - novo_objeto.classe = class - forceClass = novo_objeto.classe - end - end + --get the aID (actor id) + if (actorSerial:match("^C")) then + newActor.aID = tostring(Details:GetNpcIdFromGuid(actorSerial)) - elseif (actorSerial:match("^P")) then - novo_objeto.aID = actorSerial:gsub("Player%-", "") - - else - novo_objeto.aID = "" - end - - --check ownership - if (dono_do_pet and Details.immersion_pets_on_solo_play) then - if (UnitIsUnit("player", dono_do_pet.nome)) then - if (not Details.in_group) then - novo_objeto.grupo = true - end + --immersion stuff + if (Details.immersion_special_units) then + local shouldBeInGroup, class = Details.Immersion.IsNpcInteresting(newActor.aID) + newActor.grupo = shouldBeInGroup + if (class) then + newActor.classe = class + forceClass = newActor.classe end end - -- tipo do container - ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + elseif (actorSerial:match("^P")) then + newActor.aID = actorSerial:gsub("Player%-", "") - if (self.tipo == container_damage) then --CONTAINER DAMAGE - - local shouldScanOnce = getActorClass (novo_objeto, actorName, actorFlags, actorSerial) - - readActorFlag (novo_objeto, dono_do_pet, actorSerial, actorFlags, actorName, "damage") - - if (dono_do_pet) then - AddUnique (dono_do_pet.pets, actorName) - end - - if (self.shadow) then - if (novo_objeto.grupo and Details.in_combat) then - Details.cache_damage_group [#Details.cache_damage_group+1] = novo_objeto - end - end - - if (novo_objeto.classe == "UNGROUPPLAYER") then --is a player - if (bitBand (actorFlags, REACTION_HOSTILE ) ~= 0) then --is hostile - novo_objeto.enemy = true - end - - --try to guess his class - if (self.shadow) then --n�o executar 2x - Details:ScheduleTimer("GuessClass", 1, {novo_objeto, self, 1}) - end - - elseif (shouldScanOnce) then - - - end - - if (novo_objeto.isTank) then - novo_objeto.avoidance = Details:CreateActorAvoidanceTable() - end - - elseif (self.tipo == container_heal) then --CONTAINER HEALING - - local shouldScanOnce = getActorClass (novo_objeto, actorName, actorFlags, actorSerial) - readActorFlag (novo_objeto, dono_do_pet, actorSerial, actorFlags, actorName, "heal") - - if (dono_do_pet) then - AddUnique (dono_do_pet.pets, actorName) - end - - if (self.shadow) then - if (novo_objeto.grupo and Details.in_combat) then - Details.cache_healing_group [#Details.cache_healing_group+1] = novo_objeto - end - end - - if (novo_objeto.classe == "UNGROUPPLAYER") then --is a player - if (bitBand (actorFlags, REACTION_HOSTILE ) ~= 0) then --is hostile - novo_objeto.enemy = true - end - - --try to guess his class - if (self.shadow) then --n�o executar 2x - Details:ScheduleTimer("GuessClass", 1, {novo_objeto, self, 1}) - end - end - - - elseif (self.tipo == container_energy) then --CONTAINER ENERGY - - local shouldScanOnce = getActorClass (novo_objeto, actorName, actorFlags, actorSerial) - readActorFlag (novo_objeto, dono_do_pet, actorSerial, actorFlags, actorName, "energy") - - if (dono_do_pet) then - AddUnique (dono_do_pet.pets, actorName) - end - - if (novo_objeto.classe == "UNGROUPPLAYER") then --is a player - if (bitBand (actorFlags, REACTION_HOSTILE ) ~= 0) then --is hostile - novo_objeto.enemy = true - end - - --try to guess his class - if (self.shadow) then --n�o executar 2x - Details:ScheduleTimer("GuessClass", 1, {novo_objeto, self, 1}) - end - end - - elseif (self.tipo == container_misc) then --CONTAINER MISC - - local shouldScanOnce = getActorClass (novo_objeto, actorName, actorFlags, actorSerial) - readActorFlag (novo_objeto, dono_do_pet, actorSerial, actorFlags, actorName, "misc") - - if (dono_do_pet) then - AddUnique (dono_do_pet.pets, actorName) - end - - if (novo_objeto.classe == "UNGROUPPLAYER") then --is a player - if (bitBand (actorFlags, REACTION_HOSTILE ) ~= 0) then --is hostile - novo_objeto.enemy = true - end - - --try to guess his class - if (self.shadow) then --n�o executar 2x - Details:ScheduleTimer("GuessClass", 1, {novo_objeto, self, 1}) - end - end - - elseif (self.tipo == container_damage_target) then --CONTAINER ALVO DO DAMAGE - - elseif (self.tipo == container_energy_target) then --CONTAINER ALVOS DO ENERGY - - novo_objeto.mana = 0 - novo_objeto.e_rage = 0 - novo_objeto.e_energy = 0 - novo_objeto.runepower = 0 - - elseif (self.tipo == container_enemydebufftarget_target) then - - novo_objeto.uptime = 0 - novo_objeto.actived = false - novo_objeto.activedamt = 0 - - elseif (self.tipo == container_misc_target) then --CONTAINER ALVOS DO MISC - - - elseif (self.tipo == container_friendlyfire) then --CONTAINER FRIENDLY FIRE - - local shouldScanOnce = getActorClass (novo_objeto, actorName, actorSerial) - - end - - --sanguine affix - if (actorName == sanguineActorName) then - novo_objeto.grupo = true - end - - ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - -- grava o objeto no mapa do container - local size = #self._ActorTable+1 - self._ActorTable [size] = novo_objeto --grava na tabela de indexes - self._NameIndexTable [actorName] = size --grava no hash map o index deste jogador - - if (Details.is_in_battleground or Details.is_in_arena) then - novo_objeto.pvp = true - end - - if (Details.debug) then - if (Details.debug_chr and actorName:find(Details.debug_chr) and self.tipo == 1) then - local logLine = "" - local when = "[" .. date ("%H:%M:%S") .. format(".%4f", GetTime()-floor(GetTime())) .. "]" - local log = "actor created - class: " .. (novo_objeto.classe or "noclass") - local from = debugstack (2, 1, 0) - logLine = logLine .. when .. " " .. log .. " " .. from .. "\n" - - _detalhes_global.debug_chr_log = _detalhes_global.debug_chr_log .. logLine - end - end - - --only happens with npcs from immersion feature - if (forceClass) then - novo_objeto.classe = forceClass - end - - return novo_objeto, dono_do_pet, actorName else - return nil, nil, nil + newActor.aID = "" end + + --check ownership + if (petOwnerObject and Details.immersion_pets_on_solo_play) then + if (UnitIsUnit("player", petOwnerObject.nome)) then + if (not Details.in_group) then + newActor.grupo = true + end + end + end + + if (self.tipo == container_damage) then --containerType damage + local shouldScanOnce = getActorClass(newActor, actorName, actorFlags, actorSerial) + readActorFlag(newActor, petOwnerObject, actorSerial, actorFlags, actorName, "damage") + + if (petOwnerObject) then + AddUnique(petOwnerObject.pets, actorName) + end + + if (newActor.grupo and Details.in_combat) then + Details.cache_damage_group[#Details.cache_damage_group+1] = newActor + end + + if (newActor.isTank) then + newActor.avoidance = Details:CreateActorAvoidanceTable() + end + + elseif (self.tipo == container_heal) then --containerType healing + local shouldScanOnce = getActorClass(newActor, actorName, actorFlags, actorSerial) + readActorFlag(newActor, petOwnerObject, actorSerial, actorFlags, actorName, "heal") + + if (petOwnerObject) then + AddUnique(petOwnerObject.pets, actorName) + end + + if (newActor.grupo and Details.in_combat) then + Details.cache_healing_group[#Details.cache_healing_group+1] = newActor + end + + elseif (self.tipo == container_energy) then --containerType resources + local shouldScanOnce = getActorClass(newActor, actorName, actorFlags, actorSerial) + readActorFlag(newActor, petOwnerObject, actorSerial, actorFlags, actorName, "energy") + + if (petOwnerObject) then + AddUnique(petOwnerObject.pets, actorName) + end + + elseif (self.tipo == container_misc) then --containerType utility + local shouldScanOnce = getActorClass(newActor, actorName, actorFlags, actorSerial) + readActorFlag(newActor, petOwnerObject, actorSerial, actorFlags, actorName, "misc") + + if (petOwnerObject) then + AddUnique(petOwnerObject.pets, actorName) + end + + elseif (self.tipo == container_energy_target) then --deprecated + newActor.mana = 0 + newActor.e_rage = 0 + newActor.e_energy = 0 + newActor.runepower = 0 + print("111111111111111111") + + elseif (self.tipo == container_enemydebufftarget_target) then --deprecated + newActor.uptime = 0 + newActor.actived = false + newActor.activedamt = 0 + print("222222222222222222") + end + + --sanguine affix + if (actorName == sanguineActorName) then + newActor.grupo = true + end + + --enemy player + if (newActor.classe == "UNGROUPPLAYER") then --is a player + if (bitBand(actorFlags, REACTION_HOSTILE) ~= 0) then --is hostile + newActor.enemy = true + end + end + + --battleground + if (Details.is_in_battleground or Details.is_in_arena) then + newActor.pvp = true + end + + local nextActorIndex = #self._ActorTable+1 + self._ActorTable[nextActorIndex] = newActor + self._NameIndexTable[actorName] = nextActorIndex + + --only happens with npcs from immersion feature + if (forceClass) then + newActor.classe = forceClass + end + + return newActor, petOwnerObject, actorName end ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -1093,45 +874,23 @@ end container_pets = Details.tabela_pets.pets Details:UpdatePetsOnParser() end + function Details:ClearCCPetsBlackList() Details:Destroy(petBlackList) end - function actorContainer:FuncaoDeCriacao (tipo) - if (tipo == container_damage_target) then - return alvo_da_habilidade.NovaTabela - - elseif (tipo == container_damage) then + function actorContainer:FuncaoDeCriacao(tipo) + if (tipo == container_damage) then return atributo_damage.NovaTabela - elseif (tipo == container_heal_target) then - return alvo_da_habilidade.NovaTabela - elseif (tipo == container_heal) then return atributo_heal.NovaTabela - elseif (tipo == container_enemydebufftarget_target) then - return alvo_da_habilidade.NovaTabela - elseif (tipo == container_energy) then return atributo_energy.NovaTabela - elseif (tipo == container_energy_target) then - return alvo_da_habilidade.NovaTabela - elseif (tipo == container_misc) then return atributo_misc.NovaTabela - - elseif (tipo == container_misc_target) then - return alvo_da_habilidade.NovaTabela - - end - end - - --chama a fun��o para ser executada em todos os atores - function actorContainer:ActorCallFunction (funcao, ...) - for index, actor in ipairs(self._ActorTable) do - funcao (nil, actor, ...) end end @@ -1140,60 +899,81 @@ end return (t1 [bykey] or 0) > (t2 [bykey] or 0) end - function actorContainer:SortByKey (key) + function actorContainer:SortByKey(key) assert(type(key) == "string", "Container:SortByKey() expects a keyname on parameter 1.") bykey = key - tableSort (self._ActorTable, sort) + tableSort(self._ActorTable, sort) self:remapear() end - function actorContainer:Remap() - return self:remapear() - end - ---remove an actor from the container, by removing this way, the container does not need to be remapped ---@param self actorcontainer ---@param actorObject actor function actorContainer:RemoveActor(actorObject) local nameMap = self._NameIndexTable local actorList = self._ActorTable - local actorIndex = nameMap[actorObject.nome] - nameMap[actorObject.nome] = nil --actorObject.nome a nil value | Details/boot.lua"]:1374: in function `DestroyActor' | meta.lua"]:590: in function `PrepareTablesForSave' | savedata.lua"]:86 - table.remove(actorList, actorIndex) + + local actorName = actorObject.nome + if (actorName) then + local actorIndex = nameMap[actorObject.nome] + nameMap[actorObject.nome] = nil + if (actorObject == actorList[actorIndex]) then + table.remove(actorList, actorIndex) + end + end + + self:Remap() + end + + ---remove all destroyed actors from the container, must to be called after a possible DestroyActor() call + function actorContainer:Cleanup() + local actorList = self._ActorTable + for i = #actorList, 1, -1 do + local actorObject = actorList[i] + if (actorObject.__destroyed) then + table.remove(actorList, i) + end + end + self:Remap() + end + + function actorContainer:Remap() --alias + return self:remapear() end function actorContainer:remapear() - local namingMap = self._NameIndexTable + local namingMap = self._NameIndexTable or {} + Details:Destroy(namingMap) + local actorList = self._ActorTable for i = 1, #actorList do - namingMap[actorList[i].nome] = i - end - end - - function Details.refresh:r_container_combatentes (container, shadow) - --reconstr�i meta e indexes - setmetatable(container, Details.container_combatentes) - container.__index = Details.container_combatentes - container.funcao_de_criacao = actorContainer:FuncaoDeCriacao (container.tipo) - - --repara mapa - local mapa = {} - for i = 1, #container._ActorTable do - mapa [container._ActorTable[i].nome] = i + local playerName = actorList[i].nome + if (playerName) then + namingMap[playerName] = i + else + Details:Msg("actorContainer:Remap() found an actor without a name, playerName:", playerName, "__destroyed:", actorList[i].__destroyed) end - container._NameIndexTable = mapa + end - --seta a shadow - container.shadow = shadow + self._NameIndexTable = namingMap end - function Details.clear:c_container_combatentes (container) + function Details.refresh:r_container_combatentes(container) --runs on login from meta.lua + --set the metatable, __index and the function which will create new actors in the container + setmetatable(container, Details.container_combatentes) + container.__index = Details.container_combatentes + container.funcao_de_criacao = actorContainer:FuncaoDeCriacao(container.tipo) + + --rebuild the actor map + container:Remap() + end + + function Details.clear:c_container_combatentes(container) container.__index = nil - container.shadow = nil - --container._NameIndexTable = nil container.need_refresh = nil container.funcao_de_criacao = nil end - function Details.clear:c_container_combatentes_index (container) + + function Details.clear:c_container_combatentes_index(container) container._NameIndexTable = nil end diff --git a/classes/container_segments.lua b/classes/container_segments.lua index be614990..52bebaf3 100644 --- a/classes/container_segments.lua +++ b/classes/container_segments.lua @@ -354,8 +354,8 @@ function segmentClass:adicionar(combatObject) end --remove - tremove(segmentTable, 3) - Details:Destroy(thirdCombat) + thirdCombat = tremove(segmentTable, 3) + Details:DestroyCombat(thirdCombat) Details:SendEvent("DETAILS_DATA_SEGMENTREMOVED") end end @@ -420,8 +420,8 @@ function segmentClass:adicionar(combatObject) end --remove it - tremove(segmentTable, segmentIdRemoved) - Details:Destroy(combatObjectRemoved) + combatObjectRemoved = tremove(segmentTable, segmentIdRemoved) + Details:DestroyCombat(combatObjectRemoved) Details:SendEvent("DETAILS_DATA_SEGMENTREMOVED") end @@ -465,7 +465,7 @@ end function segmentClass:resetar_overall() Details:CloseBreakdownWindow() - Details:Destroy(Details.tabela_overall) + Details:DestroyCombat(Details.tabela_overall) Details.tabela_overall = combatClass:NovaTabela() for index, instanceObject in ipairs(Details:GetAllInstances()) do @@ -519,11 +519,11 @@ function segmentClass:resetar() for _, combatObject in ipairs(Details.tabela_historico.tabelas) do ---@cast combatObject combat - Details:Destroy(combatObject) + Details:DestroyCombat(combatObject) end - Details:Destroy(Details.tabela_vigente) - Details:Destroy(Details.tabela_overall) + Details:DestroyCombat(Details.tabela_vigente) + Details:DestroyCombat(Details.tabela_overall) Details:Destroy(Details.spellcache) if (Details.schedule_add_to_overall) then --deprecated @@ -542,12 +542,12 @@ function segmentClass:resetar() -- nova tabela do overall e current Details.tabela_overall = combatClass:NovaTabela() --joga fora a tabela antiga e cria uma nova -- cria nova tabela do combate atual - Details.tabela_vigente = combatClass:NovaTabela (nil, Details.tabela_overall) + Details.tabela_vigente = combatClass:NovaTabela(nil, Details.tabela_overall) --marca o addon como fora de combate Details.in_combat = false --zera o contador de combates - Details:NumeroCombate(0) + Details:GetOrSetCombatId(0) --clear caches Details:ClearSpellCache() diff --git a/classes/container_spells.lua b/classes/container_spells.lua index 34b50c5e..d056bd86 100644 --- a/classes/container_spells.lua +++ b/classes/container_spells.lua @@ -4,49 +4,68 @@ local _detalhes = _G.Details local _ local addonName, Details222 = ... ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ---local pointers +local setmetatable = setmetatable --lua local - local setmetatable = setmetatable --lua local +local spellContainerClass = _detalhes.container_habilidades ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ---constants - local classDamage = _detalhes.container_type.CONTAINER_DAMAGE_CLASS - local classHeal = _detalhes.container_type.CONTAINER_HEAL_CLASS - local classEnergy = _detalhes.container_type.CONTAINER_ENERGY_CLASS - local classUtility = _detalhes.container_type.CONTAINER_MISC_CLASS - local habilidade_dano = _detalhes.habilidade_dano - local habilidade_cura = _detalhes.habilidade_cura - local habilidade_e_energy = _detalhes.habilidade_e_energy - local habilidade_misc = _detalhes.habilidade_misc - local container_habilidades = _detalhes.container_habilidades +local classDamage = _detalhes.container_type.CONTAINER_DAMAGE_CLASS +local classHeal = _detalhes.container_type.CONTAINER_HEAL_CLASS +local classEnergy = _detalhes.container_type.CONTAINER_ENERGY_CLASS +local classUtility = _detalhes.container_type.CONTAINER_MISC_CLASS ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ---internals +local classDamageSpellTable = Details.habilidade_dano - function container_habilidades:NovoContainer (tipo_do_container) - local _newContainer = { - funcao_de_criacao = container_habilidades:FuncaoDeCriacao (tipo_do_container), - tipo = tipo_do_container, +local habilidade_cura = _detalhes.habilidade_cura +local habilidade_e_energy = _detalhes.habilidade_e_energy +local habilidade_misc = _detalhes.habilidade_misc + + + ---return a function from the class responsible for creating the new spelltable + ---@param containerType number @the container type to be created (1 damage 2 heal 3 resources 4 utility) + ---@return fun() : spelltable + function spellContainerClass:GetSpellTableFuncCreator(containerType) + if (containerType == classDamage) then + return classDamageSpellTable.NovaTabela + + elseif (containerType == classHeal) then + return habilidade_cura.NovaTabela + + elseif (containerType == classEnergy) then + return habilidade_e_energy.NovaTabela + + elseif (containerType == classUtility) then + return habilidade_misc.NovaTabela + end + + error("GetSpellTableFuncCreator: containerType is invalid: " .. tostring(containerType)) + end + + ---create a new spellcontainer + ---@param containerType number @the container type to be created (1 damage 2 heal 3 resources 4 utility) + ---@return spellcontainer + function spellContainerClass:NovoContainer(containerType) + ---@type spellcontainer + local spellContainer = { + funcao_de_criacao = spellContainerClass:GetSpellTableFuncCreator(containerType), + tipo = containerType, _ActorTable = {} } - setmetatable(_newContainer, container_habilidades) - - return _newContainer + setmetatable(spellContainer, spellContainerClass) + return spellContainer end ---get the spellTable for the passed spellId ---@param spellId number ---@return table - function container_habilidades:GetSpell(spellId) + function spellContainerClass:GetSpell(spellId) return self._ActorTable[spellId] end ---return a table containing keys as spellid and value as spelltable ---@return table - function container_habilidades:GetRawSpellTable() + function spellContainerClass:GetRawSpellTable() return self._ActorTable end @@ -54,7 +73,7 @@ local addonName, Details222 = ... ---@param spellId number ---@param key string ---@return any - function container_habilidades:GetAmount(spellId, key) + function spellContainerClass:GetAmount(spellId, key) local spell = self._ActorTable[spellId] if (spell) then return spell[key] @@ -64,22 +83,18 @@ local addonName, Details222 = ... ---return an iterator for all spellTables in this container ---@param self spellcontainer ---@return fun(table: table<, >, index?: ):, - function container_habilidades:ListActors() + function spellContainerClass:ListActors() return pairs(self._ActorTable) end --same as the function above, just an alias - function container_habilidades:ListSpells() + function spellContainerClass:ListSpells() return pairs(self._ActorTable) end - function container_habilidades:GetOrCreateSpell(id, shouldCreate, token) - return self:PegaHabilidade (id, shouldCreate, token) - end - ---return (boolean) if the container two or more spells within ---@return boolean - function container_habilidades:HasTwoOrMoreSpells() + function spellContainerClass:HasTwoOrMoreSpells() local count = 0 for _ in pairs(self._ActorTable) do count = count + 1 @@ -90,54 +105,42 @@ local addonName, Details222 = ... return false end + function spellContainerClass:GetOrCreateSpell(spellId, bCanCreateSpellIfMissing, cleuToken) + return self:PegaHabilidade(spellId, bCanCreateSpellIfMissing, cleuToken) + end - function container_habilidades:PegaHabilidade (id, criar, token) + ---create a new spelltable for the passed spellId + ---@param self any + ---@param spellId number + ---@param bCanCreateSpellIfMissing boolean + ---@param cleuToken string + ---@return spelltable|nil + function spellContainerClass:PegaHabilidade(spellId, bCanCreateSpellIfMissing, cleuToken) + ---@type spelltable + local spellTable = self._ActorTable [spellId] - local esta_habilidade = self._ActorTable [id] - - if (esta_habilidade) then - return esta_habilidade + if (spellTable) then + return spellTable else - if (criar) then - - local novo_objeto = self.funcao_de_criacao (nil, id, nil, token) - - self._ActorTable [id] = novo_objeto - - return novo_objeto + if (bCanCreateSpellIfMissing) then + ---@type spelltable + local newSpellTable = self.funcao_de_criacao(nil, spellId, nil, cleuToken) + self._ActorTable[spellId] = newSpellTable + return newSpellTable else return nil end end end - function container_habilidades:FuncaoDeCriacao (tipo) - if (tipo == classDamage) then - return habilidade_dano.NovaTabela - - elseif (tipo == classHeal) then - return habilidade_cura.NovaTabela - - elseif (tipo == classEnergy) then - return habilidade_e_energy.NovaTabela - - elseif (tipo == classUtility) then - return habilidade_misc.NovaTabela - - end + function _detalhes.refresh:r_container_habilidades(container) + setmetatable(container, _detalhes.container_habilidades) + container.__index = _detalhes.container_habilidades + local func_criacao = spellContainerClass:GetSpellTableFuncCreator(container.tipo) + container.funcao_de_criacao = func_criacao end - function _detalhes.refresh:r_container_habilidades (container, shadow) - --reconstr�i meta e indexes - setmetatable(container, _detalhes.container_habilidades) - container.__index = _detalhes.container_habilidades - local func_criacao = container_habilidades:FuncaoDeCriacao (container.tipo) - container.funcao_de_criacao = func_criacao - end - - function _detalhes.clear:c_container_habilidades (container) - --container.__index = {} + function _detalhes.clear:c_container_habilidades(container) container.__index = nil - container.shadow = nil container.funcao_de_criacao = nil end diff --git a/core/control.lua b/core/control.lua index 6fd1430a..9d4f6d7f 100644 --- a/core/control.lua +++ b/core/control.lua @@ -334,20 +334,19 @@ --re-lock nos tempos da tabela passada -- lock again last table times Details.tabela_vigente:TravarTempos() - local n_combate = Details:NumeroCombate (1) --aumenta o contador de combates -- combat number up + ---@type number + local combatCounter = Details:GetOrSetCombatId(1) --increate the combat counter by 1 --cria a nova tabela de combates -- create new table local ultimo_combate = Details.tabela_vigente - Details.tabela_vigente = Details.combate:NovaTabela (true, Details.tabela_overall, n_combate, ...) --cria uma nova tabela de combate + Details.tabela_vigente = Details.combate:NovaTabela (true, Details.tabela_overall, combatCounter, ...) --cria uma nova tabela de combate --flag this combat as being created Details.tabela_vigente.IsBeingCreated = true - Details.tabela_vigente.previous_combat = ultimo_combate - Details.tabela_vigente:seta_data (Details._detalhes_props.DATA_TYPE_START) --seta na tabela do combate a data do inicio do combate -- setup time data Details.in_combat = true --sinaliza ao addon que h� um combate em andamento -- in combat flag up - Details.tabela_vigente.combat_id = n_combate --grava o n�mero deste combate na tabela atual -- setup combat id on new table + Details.tabela_vigente.combat_id = combatCounter --grava o n�mero deste combate na tabela atual -- setup combat id on new table Details.last_combat_pre_pot_used = nil Details:FlagCurrentCombat() @@ -755,14 +754,14 @@ end local tempo_do_combate = Details.tabela_vigente:GetCombatTime() - local invalid_combat + + ---@type combat + local invalidCombat local zoneName, zoneType = GetInstanceInfo() if (not Details.tabela_vigente.discard_segment and (zoneType == "none" or tempo_do_combate >= Details.minimum_combat_time or not Details.tabela_historico.tabelas[1])) then - Details.tabela_historico:adicionar (Details.tabela_vigente) --move a tabela atual para dentro do hist�rico - --8.0.1 miss data isn't required at the moment, spells like akari's soul has been removed from the game - --Details:CanSendMissData() - + --combat accepted + Details.tabela_historico:adicionar(Details.tabela_vigente) --move a tabela atual para dentro do hist�rico if (Details.tabela_vigente.is_boss) then if (IsInRaid()) then local cleuID = Details.tabela_vigente.is_boss.id @@ -813,17 +812,19 @@ end else - invalid_combat = Details.tabela_vigente + --combat did not pass the filter and cannot be added into the segment history + invalidCombat = Details.tabela_vigente --tutorial about the combat time < then 'minimum_combat_time' local hasSeenTutorial = Details:GetTutorialCVar("MIN_COMBAT_TIME") if (not hasSeenTutorial) then - local lower_instance = Details:GetLowerInstanceNumber() - if (lower_instance) then - lower_instance = Details:GetInstance(lower_instance) - if (lower_instance) then - lower_instance:InstanceAlert ("combat ignored: less than 5 seconds.", {[[Interface\BUTTONS\UI-GROUPLOOT-PASS-DOWN]], 18, 18, false, 0, 1, 0, 1}, 20, {function() Details:Msg("combat ignored: elapsed time less than 5 seconds."); Details:Msg("add '|cFFFFFF00Details.minimum_combat_time = 2;|r' on Auto Run Code to change the minimum time.") end}) - Details:SetTutorialCVar ("MIN_COMBAT_TIME", true) + local lowerInstanceId = Details:GetLowerInstanceNumber() + if (lowerInstanceId) then + ---@type instance + local lowerInstanceObject = Details:GetInstance(lowerInstanceId) + if (lowerInstanceObject) then + lowerInstanceObject:InstanceAlert("combat ignored: less than 5 seconds.", {[[Interface\BUTTONS\UI-GROUPLOOT-PASS-DOWN]], 18, 18, false, 0, 1, 0, 1}, 20, {function() Details:Msg("combat ignored: elapsed time less than 5 seconds."); Details:Msg("add '|cFFFFFF00Details.minimum_combat_time = 2;|r' on Auto Run Code to change the minimum time.") end}) + Details:SetTutorialCVar("MIN_COMBAT_TIME", true) end end end @@ -832,28 +833,21 @@ if (not Details.tabela_historico.tabelas[1]) then Details.tabela_vigente = Details.tabela_vigente else - Details.tabela_vigente = Details.tabela_historico.tabelas[1] --pega a tabela do ultimo combate + Details.tabela_vigente = Details.tabela_historico.tabelas[1] --get the latest combat available in the segment history end if (Details.tabela_vigente:GetStartTime() == 0) then - --Details.tabela_vigente.start_time = Details._tempo - Details.tabela_vigente:SetStartTime (GetTime()) - --Details.tabela_vigente.end_time = Details._tempo - Details.tabela_vigente:SetEndTime (GetTime()) + Details.tabela_vigente:SetStartTime(GetTime()) + Details.tabela_vigente:SetEndTime(GetTime()) end Details.tabela_vigente.resincked = true - - --tabela foi descartada, precisa atualizar os baseframes // precisa atualizer todos ou apenas o overall? Details:InstanciaCallFunction(Details.AtualizarJanela) if (Details.solo) then - local esta_instancia = Details.tabela_instancias[Details.solo] - if (Details.SoloTables.CombatID == Details:NumeroCombate()) then --significa que o solo mode validou o combate, como matar um bixo muito low level com uma s� porrada + if (Details.SoloTables.CombatID == Details:GetOrSetCombatId()) then --significa que o solo mode validou o combate, como matar um bixo muito low level com uma s� porrada if (Details.SoloTables.CombatIDLast and Details.SoloTables.CombatIDLast ~= 0) then --volta os dados da luta anterior - Details.SoloTables.CombatID = Details.SoloTables.CombatIDLast - else if (Details.RefreshSolo) then Details:RefreshSolo() @@ -863,7 +857,7 @@ end end - Details:NumeroCombate (-1) + Details:GetOrSetCombatId(-1) end Details.host_of = nil @@ -877,19 +871,19 @@ Details.leaving_combat = false Details:OnCombatPhaseChanged() + Details:Destroy(Details.tabela_vigente.PhaseData.damage_section) Details:Destroy(Details.tabela_vigente.PhaseData.heal_section) - Details:Destroy(Details.cache_damage_group) Details:Destroy(Details.cache_healing_group) Details:UpdateParserGears() --hide / alpha in combat - for index, instancia in ipairs(Details.tabela_instancias) do - if (instancia.ativa) then - if (instancia.auto_switch_to_old) then - instancia:CheckSwitchOnCombatEnd() + for index, instance in ipairs(Details.tabela_instancias) do + if (instance.ativa) then + if (instance.auto_switch_to_old) then + instance:CheckSwitchOnCombatEnd() end end end @@ -907,9 +901,9 @@ Details:InstanceCall(Details.CheckPsUpdate) - if (invalid_combat) then + if (invalidCombat) then Details:SendEvent("COMBAT_INVALID") - Details:SendEvent("COMBAT_PLAYER_LEAVE", nil, invalid_combat) + Details:SendEvent("COMBAT_PLAYER_LEAVE", nil, invalidCombat) else Details:SendEvent("COMBAT_PLAYER_LEAVE", nil, Details.tabela_vigente) end @@ -917,7 +911,9 @@ Details:CheckForTextTimeCounter() Details.StoreSpells() Details:RunScheduledEventsAfterCombat() - end + + --issue: invalidCombat will be just floating around in memory if not destroyed + end --end of leaving combat function function Details:GetPlayersInArena() local aliados = GetNumGroupMembers() -- LE_PARTY_CATEGORY_HOME @@ -1566,15 +1562,18 @@ end end - --internal GetCombatId() version - function Details:NumeroCombate (flag) - if (flag == 0) then - Details.combat_id = 0 - elseif (flag) then - Details.combat_id = Details.combat_id + flag - end - return Details.combat_id + ---internal GetCombatId() version + ---@param self details + ---@param numberId number|nil if nil, return the current combat id, if 0 resets the id, if a number will add it to the current combat id + ---@return number + function Details:GetOrSetCombatId(numberId) + if (numberId == 0) then + Details.combat_id = 0 + elseif (numberId) then + Details.combat_id = Details.combat_id + numberId end + return Details.combat_id + end --tooltip fork / search key: ~tooltip local avatarPoint = {"bottomleft", "topleft", -3, -4} @@ -1801,7 +1800,7 @@ return end - local needRefresh = combatObject[self.atributo].need_refresh + local needRefresh = combatObject[self.atributo].need_refresh --erro de index nil value if (not needRefresh and not bForceRefresh) then return end diff --git a/core/gears.lua b/core/gears.lua index 680bbd95..949bd908 100644 --- a/core/gears.lua +++ b/core/gears.lua @@ -2175,7 +2175,7 @@ function ilvl_core:QueryInspect (unitName, callback, param1) end function ilvl_core:ClearQueryInspectQueue() - Details:Destroy (ilvl_core.forced_inspects) + Details:Destroy(ilvl_core.forced_inspects) ilvl_core.clear_queued_list = nil end diff --git a/core/meta.lua b/core/meta.lua index 340e9f0e..49402c5a 100644 --- a/core/meta.lua +++ b/core/meta.lua @@ -1,264 +1,242 @@ - local Details = _G.Details - local Details = Details - local tocName, Details222 = ... +local Details = _G.Details +local tocName, Details222 = ... ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ---local pointers - local _ - local pairs = pairs --lua local - local ipairs = ipairs --lua local - local rawget = rawget --lua local - local setmetatable = setmetatable --lua local - local _table_remove = table.remove --lua local - local _bit_band = bit.band --lua local - local _time = time --lua local +local _ +local pairs = pairs --lua local +local ipairs = ipairs --lua local +local rawget = rawget --lua local +local setmetatable = setmetatable --lua local +local _table_remove = table.remove --lua local +local _bit_band = bit.band --lua local +local _time = time --lua local - local _InCombatLockdown = InCombatLockdown --wow api local +local InCombatLockdown = InCombatLockdown --wow api local - local classDamage = Details.atributo_damage --details local - local classHeal = Details.atributo_heal --details local - local classEnergy = Details.atributo_energy --details local - local classUtility = Details.atributo_misc --details local +local classDamage = Details.atributo_damage --details local +local classHeal = Details.atributo_heal --details local +local classEnergy = Details.atributo_energy --details local +local classUtility = Details.atributo_misc --details local ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ---constants +local classTypeDamage = Details.atributos.dano +local classTypeHeal = Details.atributos.cura +local classTypeEnergy = Details.atributos.e_energy +local classTypeUtility = Details.atributos.misc - local classTypeDamage = Details.atributos.dano - local classTypeHeal = Details.atributos.cura - local classTypeEnergy = Details.atributos.e_energy - local classTypeUtility = Details.atributos.misc + --restore actor containers indexes e metatables + function Details:RestoreOverallMetatables() + local bIsInInstance = select(1, IsInInstance()) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ---core + ---@type combat + local combatObjectOverall = Details.tabela_overall + combatObjectOverall.overall_refreshed = true + combatObjectOverall.__call = Details.call_combate - ---wipe the naming list and rebuild it - ---@param actorContainer actorcontainer - local fullRemap = function(actorContainer) - local namingMap = actorContainer._NameIndexTable - Details:Destroy(namingMap) - for i = 1, #actorContainer._ActorTable do - local actorName = actorContainer._ActorTable[i].nome --so the actor got wiped, but the actor table is still there but without any members - namingMap[actorName] = i + Details.refresh:r_combate(combatObjectOverall) + + Details.refresh:r_container_combatentes(combatObjectOverall[classTypeDamage]) + Details.refresh:r_container_combatentes(combatObjectOverall[classTypeHeal]) + Details.refresh:r_container_combatentes(combatObjectOverall[classTypeEnergy]) + Details.refresh:r_container_combatentes(combatObjectOverall[classTypeUtility]) + Details.refresh:r_container_combatentes(combatObjectOverall[5]) --ghost container + + local todos_atributos = { + combatObjectOverall[classTypeDamage]._ActorTable, + combatObjectOverall[classTypeHeal]._ActorTable, + combatObjectOverall[classTypeEnergy]._ActorTable, + combatObjectOverall[classTypeUtility]._ActorTable + } + + for classType = 1, DETAILS_COMBAT_AMOUNT_CONTAINERS do + local actorContainer = combatObjectOverall[classType] + local actorTable = actorContainer._ActorTable + for i = 1, #actorTable do + ---@type actor + local thisActor = actorTable[i] + local actorName = thisActor.nome + + if (bIsInInstance and Details.remove_realm_from_name) then + thisActor.displayName = actorName:gsub(("%-.*"), "") + elseif (Details.remove_realm_from_name) then + thisActor.displayName = actorName:gsub(("%-.*"), "") --"%*" + else + thisActor.displayName = actorName + end + + if (classType == classTypeDamage) then + Details.refresh:r_atributo_damage(thisActor) + + elseif (classType == classTypeHeal) then + Details.refresh:r_atributo_heal(thisActor) + + elseif (classType == classTypeEnergy) then + Details.refresh:r_atributo_energy(thisActor) + + elseif (classType == classTypeUtility) then + Details.refresh:r_atributo_misc(thisActor) + end + + if (thisActor.ownerName) then + thisActor.owner = combatObjectOverall(classType, thisActor.ownerName) + if (not thisActor.owner) then + Details:Msg("found orphan pet (overall), owner not found: ", thisActor.ownerName, " - ", thisActor.nome) + end + end + end end end - --reaplica as tabelas no overall - function Details:RestoreOverallMetatables() - local is_in_instance = select(1, IsInInstance()) + --restore actor containers indexes e metatables + function Details:RestoreMetatables() --called from Details222.LoadSavedVariables.CombatSegments() + --pet table + setmetatable(Details.tabela_pets, Details.container_pets) - local combate = Details.tabela_overall - combate.overall_refreshed = true - combate.hasSaved = true + --segment container + setmetatable(Details.tabela_historico, Details.historico) - combate.__call = Details.call_combate + ---@type combat + local overallCombatObject = Details.tabela_overall - Details.refresh:r_combate (combate) + ---@type combat[] + local allSegments = Details.tabela_historico.tabelas - Details.refresh:r_container_combatentes (combate [classTypeDamage]) - Details.refresh:r_container_combatentes (combate [classTypeHeal]) - Details.refresh:r_container_combatentes (combate [classTypeEnergy]) - Details.refresh:r_container_combatentes (combate [classTypeUtility]) + --retore the call "combat()" functionality + for _, combatObject in ipairs(allSegments) do + combatObject.__call = Details.call_combate + end - Details.refresh:r_container_combatentes (combate [5]) --ghost container + --true if the overall data was saved and restored + local bHadOverallDataSaved = overallCombatObject.overall_refreshed - local todos_atributos = {combate [classTypeDamage]._ActorTable, combate [classTypeHeal]._ActorTable, combate [classTypeEnergy]._ActorTable, combate [classTypeUtility]._ActorTable} + if (not bHadOverallDataSaved) then + overallCombatObject.start_time = GetTime() + overallCombatObject.end_time = GetTime() + end - for class_type, atributo in ipairs(todos_atributos) do - for _, esta_classe in ipairs(atributo) do - local nome = esta_classe.nome + overallCombatObject.segments_added = overallCombatObject.segments_added or {} - if (is_in_instance and Details.remove_realm_from_name) then - esta_classe.displayName = nome:gsub(("%-.*"), "") - elseif (Details.remove_realm_from_name) then - esta_classe.displayName = nome:gsub(("%-.*"), "") --"%*" + local bIsInInstance = IsInInstance() + + --inicia a recupera��o das tabelas e montagem do overall + if (#allSegments > 0) then + for index, thisCombatObject in ipairs(allSegments) do + ---@cast thisCombatObject combat + + --set the metatable, __call and __index + Details.refresh:r_combate(thisCombatObject) + + --related to overall data + if (not bHadOverallDataSaved and thisCombatObject.overall_added) then + --overall data endTime + if (thisCombatObject.end_time and thisCombatObject.start_time) then + overallCombatObject.start_time = overallCombatObject.start_time - (thisCombatObject.end_time - thisCombatObject.start_time) + end + + --overall data startTime + if (overallCombatObject.data_inicio == 0) then + overallCombatObject.data_inicio = thisCombatObject.data_inicio or 0 + end + + --overall data finished time + overallCombatObject.data_fim = thisCombatObject.data_fim or overallCombatObject.data_fim + + --overall data enemy name + if (not Details.tabela_overall.overall_enemy_name) then + Details.tabela_overall.overall_enemy_name = thisCombatObject.is_boss and thisCombatObject.is_boss.name or thisCombatObject.enemy else - esta_classe.displayName = nome + if (Details.tabela_overall.overall_enemy_name ~= (thisCombatObject.is_boss and thisCombatObject.is_boss.name or thisCombatObject.enemy)) then + Details.tabela_overall.overall_enemy_name = "-- x -- x --" + end end - if (class_type == classTypeDamage) then - Details.refresh:r_atributo_damage (esta_classe) - - elseif (class_type == classTypeHeal) then - Details.refresh:r_atributo_heal (esta_classe) - - elseif (class_type == classTypeEnergy) then - Details.refresh:r_atributo_energy (esta_classe) - - elseif (class_type == classTypeUtility) then - Details.refresh:r_atributo_misc (esta_classe) - end - end - end - - for class_type, atributo in ipairs(todos_atributos) do - for _, esta_classe in ipairs(atributo) do - if (esta_classe.ownerName) then --nome do owner - esta_classe.owner = combate (class_type, esta_classe.ownerName) - end - end - end - end - - --reaplica indexes e metatables - function Details:RestoreMetatables() - --container de pets e hist�rico - Details.refresh:r_container_pets (Details.tabela_pets) - Details.refresh:r_historico (Details.tabela_historico) - - --tabelas dos combates - local combate_overall = Details.tabela_overall - local overall_dano = combate_overall [classTypeDamage] --damage atalho - local overall_cura = combate_overall [classTypeHeal] --heal atalho - local overall_energy = combate_overall [classTypeEnergy] --energy atalho - local overall_misc = combate_overall [classTypeUtility] --misc atalho - - local tabelas_do_historico = Details.tabela_historico.tabelas --atalho - - --recupera meta function - for _, combat_table in ipairs(tabelas_do_historico) do - combat_table.__call = Details.call_combate + --overall data segments added + local dateStart, dateEnd = thisCombatObject:GetDate() + table.insert(overallCombatObject.segments_added, {name = thisCombatObject:GetCombatName(true), elapsed = thisCombatObject:GetCombatTime(), clock = dateStart}) end - for i = #tabelas_do_historico-1, 1, -1 do - local combat = tabelas_do_historico [i] - combat.previous_combat = tabelas_do_historico [i+1] + --ghost container (container for custom displays, this is not a real container) + if (thisCombatObject[5]) then + Details.refresh:r_container_combatentes(thisCombatObject[5]) end - --tempo padrao do overall + local damageActorContainer = thisCombatObject[classTypeDamage] + local healActorContainer = thisCombatObject[classTypeHeal] + local resourcesActorContainer = thisCombatObject[classTypeEnergy] + local utilityActorContainer = thisCombatObject[classTypeUtility] - local overall_saved = combate_overall.overall_refreshed + --recupera a meta e indexes dos 4 container + Details.refresh:r_container_combatentes(damageActorContainer) + Details.refresh:r_container_combatentes(healActorContainer) + Details.refresh:r_container_combatentes(resourcesActorContainer) + Details.refresh:r_container_combatentes(utilityActorContainer) - if (not overall_saved) then - combate_overall.start_time = GetTime() - combate_overall.end_time = GetTime() - end + for classType = 1, DETAILS_COMBAT_AMOUNT_CONTAINERS do + local actorContainer = thisCombatObject[classType] + local actorTable = actorContainer._ActorTable + for i = 1, #actorTable do + ---@type actor + local actorObject = actorTable[i] + local actorName = actorObject.nome - local is_in_instance = select(1, IsInInstance()) + --set back the display name (isn't saved with the object) + if (bIsInInstance and Details.remove_realm_from_name) then + actorObject.displayName = actorName:gsub(("%-.*"), "") + elseif (Details.remove_realm_from_name) then + actorObject.displayName = actorName:gsub(("%-.*"), "") + else + actorObject.displayName = actorName + end - --inicia a recupera��o das tabelas e montagem do overall - if (#tabelas_do_historico > 0) then - for index, combate in ipairs(tabelas_do_historico) do - - combate.hasSaved = true - - --recupera a meta e indexes da tabela do combate - Details.refresh:r_combate (combate, combate_overall) - - --aumenta o tempo do combate do overall, seta as datas e os combates armazenados - if (not overall_saved and combate.overall_added) then - - if (combate.end_time and combate.start_time) then - combate_overall.start_time = combate_overall.start_time - (combate.end_time - combate.start_time) - end - -- - if (combate_overall.data_inicio == 0) then - combate_overall.data_inicio = combate.data_inicio or 0 - end - combate_overall.data_fim = combate.data_fim or combate_overall.data_fim - -- - if (not Details.tabela_overall.overall_enemy_name) then - Details.tabela_overall.overall_enemy_name = combate.is_boss and combate.is_boss.name or combate.enemy + if (classType == classTypeDamage) then + if (thisCombatObject.overall_added and not bHadOverallDataSaved) then + --add the actorObject into another combat, if does not exists there, create it, if exists sum the values + local bRefreshActor = true + classDamage:AddToCombat(actorObject, bRefreshActor, overallCombatObject) else - if (Details.tabela_overall.overall_enemy_name ~= (combate.is_boss and combate.is_boss.name or combate.enemy)) then - Details.tabela_overall.overall_enemy_name = "-- x -- x --" - end + Details.refresh:r_atributo_damage(actorObject) end - combate_overall.segments_added =combate_overall.segments_added or {} - local date_start, date_end = combate:GetDate() - tinsert(combate_overall.segments_added, {name = combate:GetCombatName(true), elapsed = combate:GetCombatTime(), clock = date_start}) + elseif (classType == classTypeHeal) then + if (thisCombatObject.overall_added and not bHadOverallDataSaved) then + local bRefreshActor = true + classHeal:AddToCombat(actorObject, bRefreshActor, overallCombatObject) + else + Details.refresh:r_atributo_heal(actorObject) + end - end - - --recupera a meta e indexes dos 4 container - Details.refresh:r_container_combatentes (combate [classTypeDamage], overall_dano) - Details.refresh:r_container_combatentes (combate [classTypeHeal], overall_cura) - Details.refresh:r_container_combatentes (combate [classTypeEnergy], overall_energy) - Details.refresh:r_container_combatentes (combate [classTypeUtility], overall_misc) - - --ghost container - if (combate[5]) then - Details.refresh:r_container_combatentes (combate [5], combate_overall [5]) - end - - --tabela com os 4 tabelas de jogadores - local todos_atributos = {combate [classTypeDamage]._ActorTable, combate [classTypeHeal]._ActorTable, combate [classTypeEnergy]._ActorTable, combate [classTypeUtility]._ActorTable} - - for class_type, atributo in ipairs(todos_atributos) do - for _, esta_classe in ipairs(atributo) do - - local nome = esta_classe.nome - - if (is_in_instance and Details.remove_realm_from_name) then - esta_classe.displayName = nome:gsub(("%-.*"), "") - elseif (Details.remove_realm_from_name) then - esta_classe.displayName = nome:gsub(("%-.*"), "") --%* - else - esta_classe.displayName = nome - end - - local shadow - - if (class_type == classTypeDamage) then - if (combate.overall_added and not overall_saved) then - shadow = classDamage:r_connect_shadow (esta_classe) - else - shadow = classDamage:r_onlyrefresh_shadow (esta_classe) - end - - elseif (class_type == classTypeHeal) then - if (combate.overall_added and not overall_saved) then - shadow = classHeal:r_connect_shadow (esta_classe) - else - shadow = classHeal:r_onlyrefresh_shadow (esta_classe) - end - - elseif (class_type == classTypeEnergy) then - if (combate.overall_added and not overall_saved) then - shadow = classEnergy:r_connect_shadow (esta_classe) - else - shadow = classEnergy:r_onlyrefresh_shadow (esta_classe) - end - - elseif (class_type == classTypeUtility) then - if (combate.overall_added and not overall_saved) then - shadow = classUtility:r_connect_shadow (esta_classe) - else - shadow = classUtility:r_onlyrefresh_shadow (esta_classe) - end - end + elseif (classType == classTypeEnergy) then + if (thisCombatObject.overall_added and not bHadOverallDataSaved) then + classEnergy:r_connect_shadow (actorObject) + else + classEnergy:r_onlyrefresh_shadow (actorObject) + end + elseif (classType == classTypeUtility) then + if (thisCombatObject.overall_added and not bHadOverallDataSaved) then + classUtility:r_connect_shadow (actorObject) + else + classUtility:r_onlyrefresh_shadow (actorObject) end end - - --reconstr�i a tabela dos pets - for class_type, atributo in ipairs(todos_atributos) do - for _, esta_classe in ipairs(atributo) do - if (esta_classe.ownerName) then --nome do owner - esta_classe.owner = combate (class_type, esta_classe.ownerName) - end - end - end - end - --fim end - --restaura last_events_table - local primeiro_combate = tabelas_do_historico [1] --primeiro combate - if (primeiro_combate) then - primeiro_combate [1]:ActorCallFunction (classDamage.r_last_events_table) - primeiro_combate [2]:ActorCallFunction (classHeal.r_last_events_table) + --link pets to owners + for class_type = 1, DETAILS_COMBAT_AMOUNT_CONTAINERS do + local actorContainer = thisCombatObject[class_type] + local actorTable = actorContainer._ActorTable + for i = 1, #actorTable do + ---@type actor + local actorObject = actorTable[i] + if (actorObject.ownerName) then --name of the pet owner + actorObject.owner = thisCombatObject(class_type, actorObject.ownerName) + --technically, if the owner isn't found, this is an orphan and it could be removed from the combat + end + end end - - local segundo_combate = tabelas_do_historico [2] --segundo combate - if (segundo_combate) then - segundo_combate [1]:ActorCallFunction (classDamage.r_last_events_table) - segundo_combate [2]:ActorCallFunction (classHeal.r_last_events_table) - end - + end end + end function Details:DoInstanceCleanup() for _, instanceObject in ipairs(Details.tabela_instancias) do @@ -357,18 +335,19 @@ end end - function Details:DoOwnerCleanup() + ---remove all .owner references from actors, this unlink pets from owners but still leave the actor.ownerName member to rebuild later + function Details:RemoveOwnerFromPets() ---@type combat[] local combatTables = Details.tabela_historico.tabelas or {} local bOverallAdded if (not Details.overall_clear_logout) then - tinsert(combatTables, Details.tabela_overall) + table.insert(combatTables, Details.tabela_overall) bOverallAdded = true end - for _, combat in ipairs(combatTables) do - ---@cast combat combat - for _, actorContainer in ipairs(combat) do + for _, combatObject in ipairs(combatTables) do + ---@cast combatObject combat + for _, actorContainer in ipairs(combatObject) do ---@cast actorContainer actorcontainer for _, actorObject in ipairs(actorContainer._ActorTable) do ---@cast actorObject actor @@ -378,7 +357,7 @@ end if (bOverallAdded) then - tremove(combatTables, #combatTables) + table.remove(combatTables, #combatTables) end end @@ -389,7 +368,7 @@ if (not Details.overall_clear_logout) then --add the overall segment to the cleanup within the other segments --it is removed after the cleanup - tinsert(combatTables, Details.tabela_overall) + table.insert(combatTables, Details.tabela_overall) bOverallAdded = true end @@ -421,7 +400,7 @@ if (bOverallAdded) then --remove the overall segment from the regular segments - tremove(combatTables, #combatTables) + table.remove(combatTables, #combatTables) end end @@ -430,7 +409,7 @@ local combatTables = Details.tabela_historico.tabelas or {} local bOverallAdded if (not Details.overall_clear_logout) then - tinsert(combatTables, Details.tabela_overall) + table.insert(combatTables, Details.tabela_overall) bOverallAdded = true end @@ -444,7 +423,7 @@ end if (bOverallAdded) then - tremove(combatTables, #combatTables) + table.remove(combatTables, #combatTables) end end @@ -453,7 +432,7 @@ local allSegments = Details.tabela_historico.tabelas or {} local bOverallAdded if (not Details.overall_clear_logout) then - tinsert(allSegments, Details.tabela_overall) + table.insert(allSegments, Details.tabela_overall) bOverallAdded = true end @@ -464,18 +443,18 @@ end if (bOverallAdded) then - tremove(allSegments, #allSegments) + table.remove(allSegments, #allSegments) end end - --limpa indexes, metatables e shadows + --limpa indexes e metatables function Details:PrepareTablesForSave() Details.clear_ungrouped = true --clear instances - Details:DoInstanceCleanup() --checked - Details:DoClassesCleanup() --checked - Details:DoContainerCleanup() --checked + Details:DoInstanceCleanup() + Details:DoClassesCleanup() + Details:DoContainerCleanup() --clear combats ---@type combat[] @@ -487,9 +466,9 @@ for i = #allSegments, 1, -1 do ---@type combat local combatObject = allSegments[i] - if (combatObject:IsTrash()) then + if (combatObject:IsTrash()) then --error, IsTrash is not a function, probably because the combat got destroyed table.remove(allSegments, i) - Details:Destroy(combatObject) + Details:DestroyCombat(combatObject) end end @@ -500,7 +479,7 @@ ---@type combat local combatObject = Details.tabela_historico.tabelas[i] table.remove(Details.tabela_historico.tabelas, i) - Details:Destroy(combatObject) + Details:DestroyCombat(combatObject) end end end @@ -509,13 +488,11 @@ if (Details.overall_clear_logout) then Details.tabela_overall = nil _detalhes_database.tabela_overall = nil - Details:Destroy(Details.tabela_overall) + Details:DestroyCombat(Details.tabela_overall) else ---@type combat local overallCombatObject = Details.tabela_overall - overallCombatObject.previous_combat = nil - --this is a cleanup for overall data (overall) if (Details.clear_ungrouped) then --deal with actor which could potentially be removed from the database @@ -525,10 +502,17 @@ for actorIndex = #actorTable, 1, -1 do ---@type actor local actorObject = actorTable[actorIndex] - if (not actorObject.grupo and not actorObject.boss and not actorObject.boss_fight_component and not actorObject.fight_component and not actorObject.pvp_component and not actorObject.arena_enemy and not actorObject.enemy) then + + for funcName in pairs(Details222.Mixins.ActorMixin) do + actorObject[funcName] = nil + end + + if (Details222.Actors.IsDisposable(actorObject) and not actorObject.owner) then + Details222.SaveVariables.LogEvent("actor removed " .. actorObject.nome .. " (disposable)") Details:DestroyActor(actorObject, actorContainer, overallCombatObject) end end + actorContainer:Cleanup() end end @@ -540,13 +524,15 @@ for actorIndex = #actorTable, 1, -1 do ---@type actor local actorObject = actorTable[actorIndex] - if (actorObject.owner) then + --does this pet owner got removed from the database? if (not actorObject.owner.serial) then + Details222.SaveVariables.LogEvent("actor removed " .. actorObject.nome .. " (owner not found)") Details:DestroyActor(actorObject, actorContainer, overallCombatObject) end end end + actorContainer:Cleanup() end end @@ -565,9 +551,6 @@ combatObject.TimeData = {} end - --clear the reference of the previous combat - combatObject.previous_combat = nil - local bIsBossEncounter = combatObject.is_boss if (bIsBossEncounter) then if (combatObject.pvp) then @@ -584,21 +567,31 @@ for o = #actorTable, 1, -1 do ---@type actor local actorObject = actorTable[o] - if (not actorObject.grupo and not actorObject.boss and not actorObject.boss_fight_component and not bIsBossEncounter and not actorObject.pvp_component and not actorObject.fight_component) then + + for funcName in pairs(Details222.Mixins.ActorMixin) do + actorObject[funcName] = nil + end + + if (not actorObject.owner and not actorObject.grupo and not actorObject.boss and not actorObject.boss_fight_component and not bIsBossEncounter and not actorObject.pvp_component and not actorObject.fight_component) then + Details222.SaveVariables.LogEvent("actor removed " .. actorObject.nome .. " (ungrouped)") Details:DestroyActor(actorObject, actorContainer, combatObject) end end + actorContainer:Cleanup() --find orphans for o = #actorTable, 1, -1 do ---@type actor local actorObject = actorTable[o] if (actorObject.owner) then + --does this pet owner got removed from the database? if (not actorObject.owner.serial) then + Details222.SaveVariables.LogEvent("actor removed " .. actorObject.nome .. " (orphan)") Details:DestroyActor(actorObject, actorContainer, combatObject) end end end + actorContainer:Cleanup() end end end @@ -622,7 +615,7 @@ Details.clear:c_atributo_custom() --clear owners - Details:DoOwnerCleanup() + Details:RemoveOwnerFromPets() --clear container indexes Details:DoContainerIndexCleanup() @@ -647,14 +640,14 @@ if (thisTime > Details._tempo + 1) then return - elseif (Details.in_combat or _InCombatLockdown() or Details:IsInInstance()) then + elseif (Details.in_combat or InCombatLockdown() or Details:IsInInstance()) then Details.Schedules.After(5, Details222.GarbageCollector.RestartInternalGarbageCollector, false, lastEvent) return end else if (type(bShouldForceCollect) ~= "boolean") then if (bShouldForceCollect == 1) then - if (Details.in_combat or _InCombatLockdown()) then + if (Details.in_combat or InCombatLockdown()) then Details.Schedules.After(5, Details222.GarbageCollector.RestartInternalGarbageCollector, bShouldForceCollect, lastEvent) return end @@ -745,7 +738,7 @@ ---@type actor local actorObject = actorList[actorIndex] - if (not actorObject.grupo and not actorObject.boss and not actorObject.fight_component and not actorObject.boss_fight_component) then + if (Details222.Actors.IsDisposable(actorObject) and not actorObject.owner) then local canCollect = false --check the time of the last seen event coming from the actor @@ -762,42 +755,37 @@ end if (nextGarbageCollection - 1 < _tempo) then - local owner = actorObject.owner --is the name or object? - if (owner) then - --local owner_actor = combatObject (tipo, owner.nome) - if (not owner.grupo and not owner.boss and not owner.boss_fight_component) then - canCollect = true - end - else - canCollect = true - end + canCollect = true end if (canCollect) then - local actorName = actorObject:Name() - combatObject:RemoveActorFromSpellCastTable(actorName) - - if (not actorObject.owner) then --not a pet - actorObject:subtract_total(combatObject) - end - amountCleaned = amountCleaned + 1 - if (containerId == 1 or containerId == 2) then --damage or healing Details.timeMachine:UnregisterActor(actorObject) end - --remove the actor from the container - tremove(actorList, actorIndex) + Details:DestroyActor(actorObject, actorContainer, combatObject) end end end + actorContainer:Cleanup() + if (amountCleaned > 0) then - fullRemap(combatObject[containerId]) - combatObject[containerId].need_refresh = true - --print(beforeCleanupAmountOfActors, "before cleanup, after:", #combatObject[1]._ActorTable) + --destroy orphans + local orphansCleaned = 0 + for actorIndex = #actorList, 1, -1 do + ---@type actor + local actorObject = actorList[actorIndex] + if (actorObject.owner and not actorObject.owner.serial) then + Details:DestroyActor(actorObject, actorContainer, combatObject) + orphansCleaned = orphansCleaned + 1 + end + end + actorContainer:Cleanup() end + + actorContainer.need_refresh = true end return amountCleaned @@ -846,4 +834,15 @@ end return amountRemoved + end + + ---return true if the actor is disposable, in other words, if it can be removed from the combat without affecting the results + ---@param actor actor + ---@return boolean + function Details222.Actors.IsDisposable(actor) + if (not actor.grupo and not actor.boss and not actor.boss_fight_component and not actor.fight_component and not actor.pvp_component and not actor.arena_enemy and not actor.enemy) then + return true + else + return false + end end \ No newline at end of file diff --git a/core/parser.lua b/core/parser.lua index e204b91e..6ea497bf 100755 --- a/core/parser.lua +++ b/core/parser.lua @@ -115,10 +115,9 @@ arenaHealth = {}, paladin_vivaldi_blessings = {}, track_hunter_frenzy = false, + rampage_cast_amount = {}, } - - --cache the data for passive trinkets procs local _trinket_data_cache = {} @@ -326,12 +325,13 @@ [45284] = 188196, --shaman lightining bolt overloaded [228361] = 228360, --shadow priest void erruption + + [401422] = 401428, --vessel of searing shadow (trinket) } --all totem --377461 382133 --377458 377459 - end local bitfield_debuffs = {} @@ -803,6 +803,11 @@ return end + --warlock corruption dot that never expires + if (spellId == 146739) 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) @@ -2623,87 +2628,74 @@ 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 - + --~crowd control ~ccdone + function parser:add_cc_done(token, time, sourceSerial, sourceName, sourceFlags, targetSerial, targetName, targetFlags, targetFlags2, spellId, spellName) _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 + ---@type actor + local sourceActor, ownerActor = misc_cache[sourceName] + 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 + sourceActor.last_event = _tempo - 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 = {} + if (not sourceActor.cc_done) then + sourceActor.cc_done = Details:GetOrderNumber() + sourceActor.cc_done_spells = container_habilidades:NovoContainer(container_misc) + sourceActor.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 + sourceActor.cc_done = sourceActor.cc_done + 1 + sourceActor.cc_done_targets[targetName] = (sourceActor.cc_done_targets[targetName] 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) + local spellTable = sourceActor.cc_done_spells._ActorTable[spellId] + if (not spellTable) then + spellTable = sourceActor.cc_done_spells:PegaHabilidade(spellId, true) end - - spell.targets [alvo_name] = (spell.targets [alvo_name] or 0) + 1 - spell.counter = spell.counter + 1 + spellTable.targets[targetName] = (spellTable.targets[targetName] or 0) + 1 + spellTable.counter = spellTable.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 = {} + if (ownerActor) then + if (not ownerActor.cc_done) then + ownerActor.cc_done = Details:GetOrderNumber() + ownerActor.cc_done_spells = container_habilidades:NovoContainer(container_misc) + ownerActor.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 + ownerActor.cc_done = ownerActor.cc_done + 1 + ownerActor.cc_done_targets[targetName] = (ownerActor.cc_done_targets[targetName] 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) + local ownerSpellTable = ownerActor.cc_done_spells._ActorTable[spellId] + if (not ownerSpellTable) then + ownerSpellTable = ownerActor.cc_done_spells:PegaHabilidade(spellId, true) end - spell.targets [alvo_name] = (spell.targets [alvo_name] or 0) + 1 - spell.counter = spell.counter + 1 + ownerSpellTable.targets[targetName] = (ownerSpellTable.targets[targetName] or 0) + 1 + ownerSpellTable.counter = ownerSpellTable.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 + if (not sourceActor.classe) then + if (sourceFlags and bitBand(sourceFlags, OBJECT_TYPE_PLAYER) ~= 0) then + if (sourceActor.classe == "UNKNOW" or sourceActor.classe == "UNGROUPPLAYER") then + ---@type actor + local damageActor = damage_cache [sourceSerial] + if (damageActor and (damageActor.classe ~= "UNKNOW" and damageActor.classe ~= "UNGROUPPLAYER")) then + sourceActor.classe = damageActor.classe + else + ---@type actor + local healingActor = healing_cache[sourceSerial] + if (healingActor and (healingActor.classe ~= "UNKNOW" and healingActor.classe ~= "UNGROUPPLAYER")) then + sourceActor.classe = healingActor.classe + end end end end @@ -3705,6 +3697,16 @@ local SPELL_POWER_PAIN = SPELL_POWER_PAIN or (PowerEnum and PowerEnum.Pain) or 1 castsByPlayer = {} _current_combat.amountCasts[sourceName] = castsByPlayer end + + --rampage cast spam + if (spellId == 184367 or spellId == 184707 or spellId == 201364) then --rampage spellIds (IDs from Retail - wow patch 10.1.0) + local latestRampageCastByPlayer = (cacheAnything.rampage_cast_amount[sourceName] or 0) + if (latestRampageCastByPlayer > time - 0.8) then + return + end + cacheAnything.rampage_cast_amount[sourceName] = time + end + local amountOfCasts = _current_combat.amountCasts[sourceName][spellName] or 0 amountOfCasts = amountOfCasts + 1 _current_combat.amountCasts[sourceName][spellName] = amountOfCasts @@ -4870,7 +4872,7 @@ local SPELL_POWER_PAIN = SPELL_POWER_PAIN or (PowerEnum and PowerEnum.Pain) or 1 end --reset spec cache if broadcaster requested if (_detalhes.streamer_config.reset_spec_cache) then - Details:Destroy (_detalhes.cached_specs) + Details:Destroy(_detalhes.cached_specs) end end @@ -5601,7 +5603,7 @@ local SPELL_POWER_PAIN = SPELL_POWER_PAIN or (PowerEnum and PowerEnum.Pain) or 1 Details:DispatchAutoRunCode("on_groupchange") - Details:Destroy (Details.trusted_characters) + Details:Destroy(Details.trusted_characters) C_Timer.After(5, Details.ScheduleSyncPlayerActorData) end @@ -5799,23 +5801,60 @@ local SPELL_POWER_PAIN = SPELL_POWER_PAIN or (PowerEnum and PowerEnum.Pain) or 1 _detalhes.listener:SetScript("OnEvent", _detalhes.OnEvent) - --logout function ~save ~logout + ---return the backup table with regular logs, error and backups /dumpt __details_backup._general_logs + function Details222.SaveVariables.GetBackupLogs() + ---@type {_general_logs: table, _exit_error: table, _instance_backup: table} + local backupTable = __details_backup + if (not backupTable) then + __details_backup = { --[[GLOBAL]] + _general_logs = {}, + _exit_error = {}, + _instance_backup = {}, + } + return __details_backup + end + + backupTable._general_logs = backupTable._general_logs or {} + backupTable._exit_error = backupTable._exit_error or {} + backupTable._instance_backup = backupTable._instance_backup or {} + + return backupTable + end + + function Details222.SaveVariables.LogEvent(...) + local args = {...} + local newArgs = {} + for index, value in ipairs(args) do + if (type(value) == "string" or type(value) == "number" or type(value) == "boolean") then + newArgs[index] = tostring(value) + end + end + + local currentDate = Details222.Date.GetDateForLogs() + local text = currentDate .. " | " .. table.concat(newArgs, ", ") + + local backupLogs = Details222.SaveVariables.GetBackupLogs() + table.insert(backupLogs._general_logs, 1, text) + table.remove(backupLogs._general_logs, 30) + end + + --logout function ~save ~logout ~savedata ---@type frame local databaseSaver = CreateFrame("frame") databaseSaver:RegisterEvent("PLAYER_LOGOUT") databaseSaver:SetScript("OnEvent", function(...) + --maximum amount of exit errors to be logged, new error are always added to the top of the list (index 1) + local exitErrorsMaxSize = 10 + --safe guard logs and user settings - __details_backup = __details_backup or { - _exit_error = {}, - _instance_backup = {}, - } + local backupLogs = Details222.SaveVariables.GetBackupLogs() ---@type table - local exitErrors = __details_backup._exit_error + local exitErrors = backupLogs._exit_error ---@param text string the error to be logged local addToExitErrors = function(text) - table.insert(exitErrors, 1, date() .. "|" .. text) + table.insert(exitErrors, 1, Details222.Date.GetDateForLogs() .. "|" .. text) table.remove(exitErrors, 10) end @@ -5840,16 +5879,16 @@ local SPELL_POWER_PAIN = SPELL_POWER_PAIN or (PowerEnum and PowerEnum.Pain) or 1 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|") + tinsert(_detalhes_global.exit_errors, 1, currentStep .. "|" .. Details222.Date.GetDateForLogs() .. "|" .. _detalhes.userversion .. "|Framework wasn't loaded|") return end local logSaverError = function(errortext) 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()) + tinsert(_detalhes_global.exit_errors, 1, currentStep .. "|" .. Details222.Date.GetDateForLogs() .. "|" .. _detalhes.userversion .. "|" .. errortext .. "|" .. debugstack()) + tremove(_detalhes_global.exit_errors, exitErrorsMaxSize) + addToExitErrors(currentStep .. "|" .. Details222.Date.GetDateForLogs() .. "|" .. _detalhes.userversion .. "|" .. errortext .. "|" .. debugstack()) end xpcall(writeLog, addToExitErrors) end @@ -5882,7 +5921,7 @@ local SPELL_POWER_PAIN = SPELL_POWER_PAIN or (PowerEnum and PowerEnum.Pain) or 1 xpcall(clearInstances, logSaverError) else tinsert(_detalhes_global.exit_errors, 1, "not _detalhes.tabela_instancias") - tremove(_detalhes_global.exit_errors, 6) + tremove(_detalhes_global.exit_errors, exitErrorsMaxSize) addToExitErrors("not _detalhes.tabela_instancias") end @@ -5926,12 +5965,12 @@ local SPELL_POWER_PAIN = SPELL_POWER_PAIN or (PowerEnum and PowerEnum.Pain) or 1 _detalhes_database.nick_tag_cache = Details.CopyTable(_detalhes_database.nick_tag_cache) end xpcall(saveNicktabCache, logSaverError) - end) + end) --end of saving data + + 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() @@ -6076,6 +6115,7 @@ local SPELL_POWER_PAIN = SPELL_POWER_PAIN or (PowerEnum and PowerEnum.Pain) or 1 Details:Destroy(dk_pets_cache.apoc) Details:Destroy(cacheAnything.paladin_vivaldi_blessings) + Details:Destroy(cacheAnything.rampage_cast_amount) cacheAnything.track_hunter_frenzy = Details.combat_log.track_hunter_frenzy diff --git a/core/plugins_solo.lua b/core/plugins_solo.lua index 3964fbc6..54913008 100644 --- a/core/plugins_solo.lua +++ b/core/plugins_solo.lua @@ -28,7 +28,7 @@ function _detalhes:UpdateSolo() local SoloInstance = _detalhes.tabela_instancias[_detalhes.solo] _detalhes.SoloTables.CombatIDLast = _detalhes.SoloTables.CombatID - _detalhes.SoloTables.CombatID = _detalhes:NumeroCombate() + _detalhes.SoloTables.CombatID = _detalhes:GetOrSetCombatId() _detalhes.SoloTables.Attribute = SoloInstance.atributo end diff --git a/core/util.lua b/core/util.lua index de52f4ee..50ffda58 100644 --- a/core/util.lua +++ b/core/util.lua @@ -526,7 +526,7 @@ return left..(num:reverse():gsub('(%d%d%d)','%1,'):reverse())..right end - Details:Destroy (_detalhes.ToKFunctions) + Details:Destroy(_detalhes.ToKFunctions) tinsert(_detalhes.ToKFunctions, _detalhes.NoToK) tinsert(_detalhes.ToKFunctions, _detalhes.ToK) @@ -659,7 +659,7 @@ return left..(num:reverse():gsub('(%d%d%d)','%1,'):reverse())..right end - Details:Destroy (_detalhes.ToKFunctions) + Details:Destroy(_detalhes.ToKFunctions) tinsert(_detalhes.ToKFunctions, _detalhes.NoToK) tinsert(_detalhes.ToKFunctions, _detalhes.ToK) diff --git a/frames/window_currentdps.lua b/frames/window_currentdps.lua index 2637a08b..7c47bd78 100644 --- a/frames/window_currentdps.lua +++ b/frames/window_currentdps.lua @@ -583,8 +583,8 @@ function Details:CreateCurrentDpsFrame(parent, name) DF:SetFontOutline (labelYellowTeam_DPS, Details.realtime_dps_meter.font_shadow) --wipe current data for arena - Details:Destroy (f.PlayerTeamBuffer) - Details:Destroy (f.YellowTeamBuffer) + Details:Destroy(f.PlayerTeamBuffer) + Details:Destroy(f.YellowTeamBuffer) --reset damage f.PlayerTeamDamage = 0 @@ -902,9 +902,9 @@ function Details:CreateCurrentDpsFrame(parent, name) function eventListener:ResetBuffer() if (f:IsShown()) then - Details:Destroy (f.PlayerTeamBuffer) - Details:Destroy (f.YellowTeamBuffer) - Details:Destroy (f.GroupBuffer) + Details:Destroy(f.PlayerTeamBuffer) + Details:Destroy(f.YellowTeamBuffer) + Details:Destroy(f.GroupBuffer) f.GroupTotalDamage = 0 f.PlayerTeamDamage = 0 f.YellowDamage = 0 diff --git a/frames/window_forge.lua b/frames/window_forge.lua index 15cb59e7..91545be1 100644 --- a/frames/window_forge.lua +++ b/frames/window_forge.lua @@ -105,10 +105,10 @@ function Details:OpenForge() f:SetScript("OnHide", function() for _, module in ipairs(all_modules) do if (module.data) then - Details:Destroy (module.data) + Details:Destroy(module.data) end end - Details:Destroy (spell_already_added) + Details:Destroy(spell_already_added) end) f.bg1 = f:CreateTexture(nil, "background") @@ -438,7 +438,7 @@ function Details:OpenForge() local filter_name = DetailsForgeAllSpellsNameFilter:GetText() local lower_FilterCaster = lower (filter_caster) local lower_FilterSpellName = lower (filter_name) - Details:Destroy (spell_already_added) + Details:Destroy(spell_already_added) local SpellPoll = Details.spell_pool for spellID, className in pairs(SpellPoll) do @@ -582,7 +582,7 @@ function Details:OpenForge() local lower_FilterSpellName = lower (filter_name) local lower_FilterEncounterName = lower (filter_encounter) - Details:Destroy (spell_already_added) + Details:Destroy(spell_already_added) local SpellPoll = Details.encounter_spell_pool for spellID, spellTable in pairs(SpellPoll) do diff --git a/frames/window_main.lua b/frames/window_main.lua index deba6ffc..185159ec 100644 --- a/frames/window_main.lua +++ b/frames/window_main.lua @@ -2302,7 +2302,7 @@ function icon_frame_events:EnterCombat() anim.icon_frame.icon_animation = nil anim.icon_frame = nil end - Details:Destroy (Details.icon_animations.load.in_use) + Details:Destroy(Details.icon_animations.load.in_use) end icon_frame_events:RegisterEvent("COMBAT_PLAYER_ENTER", "EnterCombat") @@ -3060,7 +3060,7 @@ function Details:InstanceAlert (msg, icon, timeInSeconds, clickfunc, doflash, fo end self.alert.button.func = nil - Details:Destroy (self.alert.button.func_param) + Details:Destroy(self.alert.button.func_param) if (clickfunc) then self.alert.button.func = clickfunc[1] @@ -5654,17 +5654,17 @@ function Details:SetIconAlpha(alpha, hide, noAnimations) end end -function Details:ToolbarMenuSetButtonsOptions(spacement, shadow) +function Details:ToolbarMenuSetButtonsOptions(spacement, iconShadows) if (type(spacement) ~= "number") then spacement = self.menu_icons.space end - if (type(shadow) ~= "boolean") then - shadow = self.menu_icons.shadow + if (type(iconShadows) ~= "boolean") then + iconShadows = self.menu_icons.shadow end self.menu_icons.space = spacement - self.menu_icons.shadow = shadow + self.menu_icons.shadow = iconShadows return self:ToolbarMenuSetButtons() end @@ -6339,7 +6339,7 @@ local buildSegmentTooltip = function(self, deltaTime) for i = Details.segments_amount, 1, -1 do if (i <= fill) then local thisCombat = Details.tabela_historico.tabelas[i] - if (thisCombat) then + if (thisCombat and not thisCombat.__destroyed) then local enemy = thisCombat.is_boss and thisCombat.is_boss.name local segmentInfoAdded = false segmentsUsed = segmentsUsed + 1 @@ -6622,7 +6622,7 @@ local buildSegmentTooltip = function(self, deltaTime) if (not segmentInfoAdded) then gameCooltip:AddLine(Loc["STRING_SEGMENT_ENEMY"] .. ":", enemy, 2, "white", "white") - local decorrido = thisCombat:GetCombatTime() + local decorrido = thisCombat:GetCombatTime() --attempt to call method 'GetCombatTime' (a nil value) local minutos, segundos = floor(decorrido/60), floor(decorrido%60) gameCooltip:AddLine(Loc["STRING_SEGMENTS_LIST_COMBATTIME"] .. ":", minutos.."m "..segundos.."s", 2, "white", "white") @@ -6632,11 +6632,16 @@ local buildSegmentTooltip = function(self, deltaTime) amountOfSegments = amountOfSegments + 1 else - gameCooltip:AddLine(Loc["STRING_SEGMENT_LOWER"] .. " #" .. i, _, 1, "gray") - gameCooltip:AddMenu(1, instance.TrocaTabela, i) - gameCooltip:AddIcon([[Interface\QUESTFRAME\UI-Quest-BulletPoint]], "main", "left", 16, 16, nil, nil, nil, nil, empty_segment_color) - gameCooltip:AddLine(Loc["STRING_SEGMENT_EMPTY"], _, 2) - gameCooltip:AddIcon([[Interface\CHARACTERFRAME\Disconnect-Icon]], 2, 1, 12, 12, 0.3125, 0.65625, 0.265625, 0.671875) + if (thisCombat and thisCombat.__destroyed) then + Details:Msg("a deleted combat object was found on the history table, please report this bug on discord:") + Details:Msg("combat destroyed by:", thisCombat.__destroyedBy) + else + gameCooltip:AddLine(Loc["STRING_SEGMENT_LOWER"] .. " #" .. i, _, 1, "gray") + gameCooltip:AddMenu(1, instance.TrocaTabela, i) + gameCooltip:AddIcon([[Interface\QUESTFRAME\UI-Quest-BulletPoint]], "main", "left", 16, 16, nil, nil, nil, nil, empty_segment_color) + gameCooltip:AddLine(Loc["STRING_SEGMENT_EMPTY"], _, 2) + gameCooltip:AddIcon([[Interface\CHARACTERFRAME\Disconnect-Icon]], 2, 1, 12, 12, 0.3125, 0.65625, 0.265625, 0.671875) + end end if (menuIndex) then diff --git a/frames/window_playerbreakdown_avoidance.lua b/frames/window_playerbreakdown_avoidance.lua index 8eba907b..3b0e1895 100644 --- a/frames/window_playerbreakdown_avoidance.lua +++ b/frames/window_playerbreakdown_avoidance.lua @@ -383,10 +383,11 @@ local avoidance_fill = function(tab, player, combat) local elapsed_time = combat:GetCombatTime() - local last_combat = combat.previous_combat + local last_combat = combat.previous_combat --this is always nil from 2023 may 26 if (not last_combat or not last_combat [1]) then last_combat = combat end + local last_actor = last_combat (1, player.nome) local n = player.nome if (n:find("-")) then diff --git a/frames/window_wa.lua b/frames/window_wa.lua index 35e4cd61..33a6fb0a 100644 --- a/frames/window_wa.lua +++ b/frames/window_wa.lua @@ -1961,7 +1961,7 @@ function _detalhes:OpenAuraPanel (spellid, spellname, spellicon, encounterid, tr spellname = select(1, GetSpellInfo(spellid)) end - Details:Destroy (empty_other_values) + Details:Destroy(empty_other_values) other_values = other_values or empty_other_values if (not DetailsAuraPanel or not DetailsAuraPanel.Initialized) then diff --git a/functions/bossmods.lua b/functions/bossmods.lua index 5372dde6..e923b765 100644 --- a/functions/bossmods.lua +++ b/functions/bossmods.lua @@ -133,8 +133,8 @@ function Details:CreateCallbackListeners() end current_encounter = false - Details:Destroy (current_table_dbm) - Details:Destroy (current_table_bigwigs) + Details:Destroy(current_table_dbm) + Details:Destroy(current_table_bigwigs) end end) event_frame:RegisterEvent("ENCOUNTER_START") diff --git a/functions/mixin.lua b/functions/mixin.lua index f2429bcc..52c7882d 100644 --- a/functions/mixin.lua +++ b/functions/mixin.lua @@ -5,11 +5,11 @@ local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true) local addonName, Details222 = ... local actorSpellContainers = { - "debuff", "buff", "spell", "cooldowns" + "debuff", "buff", "spell", "cooldowns", "crowdcontrol" } Details222.Mixins.ActorMixin = { - ---return a table containing the spellContainers names: 'debuff', 'buff', 'spell', 'cooldowns' + ---return a table containing the spellContainers names: 'debuff', 'buff', 'spell', 'cooldowns', 'crowdcontrol' ---@return string[] GetSpellContainerNames = function() return actorSpellContainers @@ -31,6 +31,10 @@ Details222.Mixins.ActorMixin = { elseif (containerType == "cooldowns") then return actor.cooldowns_defensive_spells + + elseif (containerType == "crowdcontrol") then + ---@cast actor actorutility + return actor.cc_done_spells end end, diff --git a/functions/mythicdungeon.lua b/functions/mythicdungeon.lua index 4651eae7..464c55af 100644 --- a/functions/mythicdungeon.lua +++ b/functions/mythicdungeon.lua @@ -809,7 +809,7 @@ function DetailsMythicPlusFrame.EventListener.OnDetailsEvent(contextObject, even --reset spec cache if broadcaster requested if (Details.streamer_config.reset_spec_cache) then - Details:Destroy (Details.cached_specs) + Details:Destroy(Details.cached_specs) end C_Timer.After(0.5, DetailsMythicPlusFrame.OnChallengeModeStart) diff --git a/functions/plater.lua b/functions/plater.lua index 9ecff4bb..5ed5a9a5 100644 --- a/functions/plater.lua +++ b/functions/plater.lua @@ -114,7 +114,7 @@ function Details:RefreshPlaterIntegration() if (Plater and Details.plater.realtime_dps_enabled or Details.plater.realtime_dps_player_enabled or Details.plater.damage_taken_enabled) then --wipe the cache - Details:Destroy (plater_integration_frame.DamageTaken) + Details:Destroy(plater_integration_frame.DamageTaken) --read cleu events plater_integration_frame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") diff --git a/functions/playerclass.lua b/functions/playerclass.lua index 33a9af46..b4501602 100644 --- a/functions/playerclass.lua +++ b/functions/playerclass.lua @@ -286,11 +286,11 @@ do ---@type actor, actorcontainer, number local actorObject, actorContainer, attempts = payload[1], payload[2], payload[3] - if (not actorObject) then + if (not actorObject or actorObject.__destroyed) then return false end - local spellContainerNames = actorObject:GetSpellContainerNames() + local spellContainerNames = actorObject:GetSpellContainerNames() --1x Details/functions/playerclass.lua:293: attempt to call method 'GetSpellContainerNames' (a nil value) for i = 1, #spellContainerNames do local spellContainer = actorObject:GetSpellContainer(spellContainerNames[i]) if (spellContainer) then @@ -348,7 +348,7 @@ do function Details:GuessSpec(payload) ---@type actor, actorcontainer, number local actorObject, actorContainer, attempts = payload[1], payload[2], payload[3] - if (not actorObject) then + if (not actorObject or actorObject.__destroyed) then return false end @@ -365,7 +365,7 @@ do if (not actorSpec) then local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true) if (openRaidLib) then - local unitInfo = openRaidLib.GetUnitInfo(actorObject:Name()) + local unitInfo = openRaidLib.GetUnitInfo(actorObject:Name()) --1x Details/functions/playerclass.lua:368: attempt to call method 'Name' (a nil value) if (unitInfo and unitInfo.specId and unitInfo.specId ~= 0) then actorSpec = unitInfo.specId end @@ -379,7 +379,7 @@ do --attempt to get from the spells the actor used in the current combat if (not actorSpec) then - local currentCombatObject = Details:GetCombat(DETAILS_SEGMENTID_CURRENT) + local currentCombatObject = Details:GetCurrentCombat() for containerId = 1, DETAILS_COMBAT_AMOUNT_CONTAINERS do if (actorSpec) then break @@ -472,9 +472,9 @@ do Details:ScheduleTimer("GuessSpec", 1, payload) --todo: replace schedule from ace3 and use our own end else - if (attempts and attempts < 10) then + if (attempts and attempts < 4) then payload[3] = attempts + 1 - Details:ScheduleTimer("GuessSpec", 3, payload) + Details:ScheduleTimer("GuessSpec", 4, payload) end end diff --git a/functions/slash.lua b/functions/slash.lua index 1754f73e..3fb2301b 100644 --- a/functions/slash.lua +++ b/functions/slash.lua @@ -275,7 +275,7 @@ function SlashCmdList.DETAILS (msg, editbox) local segmentToErase = tonumber(segmentId) local combatObject = tremove(Details.tabela_historico.tabelas, segmentToErase) if (combatObject) then - Details:Destroy(combatObject) + Details:DestroyCombat(combatObject) Details:Msg("segment removed.") collectgarbage() else @@ -1361,7 +1361,7 @@ function SlashCmdList.DETAILS (msg, editbox) for i = 25, 1, -1 do local pastCombat = segmentHistory [i] if (pastCombat and pastCombat ~= newCombat) then - Details:Destroy(pastCombat) + Details:DestroyCombat(pastCombat) segmentHistory [i] = nil end end @@ -1575,64 +1575,6 @@ function SlashCmdList.DETAILS (msg, editbox) elseif (msg == "survey") then Details.Survey.OpenSurveyPanel() - elseif (msg == "share") then - - local f = {} - - local elapsed = GetTime() - - local ignoredKeys = { - minha_barra = true, - __index = true, - shadow = true, - links = true, - __call = true, - _combat_table = true, - previous_combat = true, - owner = true, - } - - local keys = {} - - --copy from table2 to table1 overwriting values - function f.copy(t1, t2) - if (t1.Timer) then - t1, t2 = t1.t1, t1.t2 - end - for key, value in pairs(t2) do - if (not ignoredKeys [key] and type(value) ~= "function") then - if (key == "targets") then - t1 [key] = {} - - elseif (type(value) == "table") then - t1 [key] = t1 [key] or {} - - --print(key, value) - --local d = C_Timer.NewTimer(1, f.copy) - --d.t1 = t1 [key] - --d.t2 = t2 [key] - --d.Timer = true - - keys [key] = true - - f.copy(t1 [key], t2 [key]) - else - t1 [key] = value - end - end - end - return t1 - end - - --local copySegment = f.copy({}, _detalhes.tabela_vigente) - local copySegment = f.copy({}, Details.tabela_historico.tabelas [2]) - - --the segment received is raw and does not have metatables, need to refresh them - local zipData = Details:CompressData (copySegment, "print") - - --print(zipData) - --Details:Dump (keys) - Details:Dump ({zipData}) else --if (_detalhes.opened_windows < 1) then diff --git a/functions/spellcache.lua b/functions/spellcache.lua index c16dffe7..28c43462 100644 --- a/functions/spellcache.lua +++ b/functions/spellcache.lua @@ -253,6 +253,7 @@ do customItemList[388948] = {itemId = 193732} --trinket: Globe of Jagged Ice customItemList[381760] = {itemId = 193786, isPassive = true} --trinket: Mutated Magmammoth Scale (melee) customItemList[389839] = {itemId = 193757, isPassive = true} --trinket: Ruby Whelp Shell + customItemList[401428] = {itemId = 202615, isPassive = true} --trinket: Vessel of Searing Shadow end if (LIB_OPEN_RAID_SPELL_CUSTOM_NAMES) then @@ -392,11 +393,21 @@ do return end - local spellName, rank, spellIcon = GetSpellInfo(spellId) + --do nothing if the spell is already cached + local spellInfo = rawget(Details.spellcache, spellId) + if (spellInfo) then + return + end + + local spellName, rank, spellIcon = Details.GetSpellInfo(spellId) + if (not spellName) then + spellName, rank, spellIcon = GetSpellInfo(spellId) + end + if (spellName) then - rawset (Details.spellcache, spellId, {spellName .. Loc ["STRING_DOT"], rank, spellIcon}) + rawset(Details.spellcache, spellId, {spellName .. Loc ["STRING_DOT"], rank, spellIcon}) else - rawset (Details.spellcache, spellId, {"Unknown DoT Spell? " .. Loc ["STRING_DOT"], rank, [[Interface\InventoryItems\WoWUnknownItem01]]}) + rawset(Details.spellcache, spellId, {"Unknown DoT Spell? " .. Loc ["STRING_DOT"], rank, [[Interface\InventoryItems\WoWUnknownItem01]]}) end end end \ No newline at end of file