local Details = _G.Details local tocName, Details222 = ... 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 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 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()) ---@type combat local combatObjectOverall = Details.tabela_overall combatObjectOverall.overall_refreshed = true combatObjectOverall.__call = Details.call_combate 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 function Details:RestoreMetatables() --called from Details222.LoadSavedVariables.CombatSegments() --restore actor containers indexes e metatables --segment container setmetatable(Details.tabela_historico, Details.historico) ---@type combat local overallCombatObject = Details.tabela_overall ---@type combat[] local segmentsTable = Details:GetCombatSegments() --retore the call "combat()" functionality for _, combatObject in ipairs(segmentsTable) do combatObject.__call = Details.call_combate end --true if the overall data was saved and restored local bHadOverallDataSaved = overallCombatObject.overall_refreshed if (not bHadOverallDataSaved) then overallCombatObject.start_time = GetTime() overallCombatObject.end_time = GetTime() end overallCombatObject.segments_added = overallCombatObject.segments_added or {} local bIsInInstance = IsInInstance() --inicia a recupera��o das tabelas e montagem do overall if (#segmentsTable > 0) then for index, thisCombatObject in ipairs(segmentsTable) 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:GetDate() == 0) then overallCombatObject:SetDate(thisCombatObject:GetDate() or 0) end --overall data finished time local thisCombatDateStart, thisCombaDateEnd = thisCombatObject:GetDate() local overallDateStart, overallDateEnd = overallCombatObject:GetDate() overallCombatObject:SetDate(nil, thisCombaDateEnd or overallDateEnd) --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 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 --overall data segments added local dateStart, dateEnd = thisCombatObject:GetDate() table.insert(overallCombatObject.segments_added, {name = thisCombatObject:GetCombatName(false, true), elapsed = thisCombatObject:GetCombatTime(), clock = dateStart}) end --ghost container (container for custom displays, this is not a real container) if (thisCombatObject[5]) then Details.refresh:r_container_combatentes(thisCombatObject[5]) end local damageActorContainer = thisCombatObject[classTypeDamage] local healActorContainer = thisCombatObject[classTypeHeal] local resourcesActorContainer = thisCombatObject[classTypeEnergy] local utilityActorContainer = thisCombatObject[classTypeUtility] --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) 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 --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 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 Details.refresh:r_atributo_damage(actorObject) end 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 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 end end --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 end end end function Details:DoInstanceCleanup() for _, instanceObject in ipairs(Details.tabela_instancias) do ---@cast instanceObject instance if (instanceObject.StatusBar.left) then instanceObject.StatusBarSaved = { ["left"] = instanceObject.StatusBar.left.real_name or "NONE", ["center"] = instanceObject.StatusBar.center.real_name or "NONE", ["right"] = instanceObject.StatusBar.right.real_name or "NONE", } instanceObject.StatusBarSaved.options = { [instanceObject.StatusBarSaved.left] = instanceObject.StatusBar.left.options, [instanceObject.StatusBarSaved.center] = instanceObject.StatusBar.center.options, [instanceObject.StatusBarSaved.right] = instanceObject.StatusBar.right.options } end --erase all widgets frames instanceObject.scroll = nil instanceObject.baseframe = nil instanceObject.bgframe = nil instanceObject.bgdisplay = nil instanceObject.freeze_icon = nil instanceObject.freeze_texto = nil instanceObject.barras = nil instanceObject.showing = nil instanceObject.agrupada_a = nil instanceObject.grupada_pos = nil instanceObject.agrupado = nil instanceObject._version = nil instanceObject.h_baixo = nil instanceObject.h_esquerda = nil instanceObject.h_direita = nil instanceObject.h_cima = nil instanceObject.break_snap_button = nil instanceObject.alert = nil instanceObject.StatusBar = nil instanceObject.consolidateFrame = nil instanceObject.consolidateButtonTexture = nil instanceObject.consolidateButton = nil instanceObject.lastIcon = nil instanceObject.firstIcon = nil instanceObject.menu_attribute_string = nil instanceObject.wait_for_plugin_created = nil instanceObject.waiting_raid_plugin = nil instanceObject.waiting_pid = nil end --unused instances for _, instanceObject in ipairs(Details.unused_instances) do ---@cast instanceObject instance if (instanceObject.StatusBar.left) then instanceObject.StatusBarSaved = { ["left"] = instanceObject.StatusBar.left.real_name or "NONE", ["center"] = instanceObject.StatusBar.center.real_name or "NONE", ["right"] = instanceObject.StatusBar.right.real_name or "NONE", } instanceObject.StatusBarSaved.options = { [instanceObject.StatusBarSaved.left] = instanceObject.StatusBar.left.options, [instanceObject.StatusBarSaved.center] = instanceObject.StatusBar.center.options, [instanceObject.StatusBarSaved.right] = instanceObject.StatusBar.right.options } end --erase all widgets frames instanceObject.scroll = nil instanceObject.baseframe = nil instanceObject.bgframe = nil instanceObject.bgdisplay = nil instanceObject.freeze_icon = nil instanceObject.freeze_texto = nil instanceObject.barras = nil instanceObject.showing = nil instanceObject.agrupada_a = nil instanceObject.grupada_pos = nil instanceObject.agrupado = nil instanceObject._version = nil instanceObject.h_baixo = nil instanceObject.h_esquerda = nil instanceObject.h_direita = nil instanceObject.h_cima = nil instanceObject.break_snap_button = nil instanceObject.alert = nil instanceObject.StatusBar = nil instanceObject.consolidateFrame = nil instanceObject.consolidateButtonTexture = nil instanceObject.consolidateButton = nil instanceObject.lastIcon = nil instanceObject.firstIcon = nil instanceObject.menu_attribute_string = nil instanceObject.wait_for_plugin_created = nil instanceObject.waiting_raid_plugin = nil instanceObject.waiting_pid = nil end end ---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 segmentsTable = Details:GetCombatSegments() or {} local bOverallAdded if (not Details.overall_clear_logout) then table.insert(segmentsTable, Details.tabela_overall) bOverallAdded = true end for _, combatObject in ipairs(segmentsTable) do ---@cast combatObject combat for _, actorContainer in ipairs(combatObject) do ---@cast actorContainer actorcontainer for _, actorObject in ipairs(actorContainer._ActorTable) do ---@cast actorObject actor actorObject.owner = nil end end end if (bOverallAdded) then table.remove(segmentsTable, #segmentsTable) end end function Details:DoClassesCleanup() ---@type combat[] local segmentsTable = Details:GetCombatSegments() or {} local bOverallAdded = false if (not Details.overall_clear_logout) then --add the overall segment to the cleanup within the other segments --it is removed after the cleanup table.insert(segmentsTable, Details.tabela_overall) bOverallAdded = true end for index, combatObject in ipairs(segmentsTable) do ---@cast combatObject combat for classType, actorContainer in ipairs(combatObject) do ---@cast actorContainer actorcontainer for _, actorObject in ipairs(actorContainer._ActorTable) do --low level loop for performance ---@cast actorObject actor actorObject.displayName = nil actorObject.minha_barra = nil if (classType == classTypeDamage) then Details.clear:c_atributo_damage(actorObject) elseif (classType == classTypeHeal) then Details.clear:c_atributo_heal(actorObject) elseif (classType == classTypeEnergy) then Details.clear:c_atributo_energy(actorObject) elseif (classType == classTypeUtility) then Details.clear:c_atributo_misc(actorObject) end end end end if (bOverallAdded) then --remove the overall segment from the regular segments table.remove(segmentsTable, #segmentsTable) end end function Details:DoContainerCleanup() ---@type combat[] local segmentsTable = Details:GetCombatSegments() or {} local bOverallAdded if (not Details.overall_clear_logout) then table.insert(segmentsTable, Details.tabela_overall) bOverallAdded = true end for _, combatObject in ipairs(segmentsTable) do ---@cast combatObject combat Details.clear:c_combate(combatObject) for _, actorContainer in ipairs(combatObject) do ---@cast actorContainer actorcontainer Details.clear:c_container_combatentes(actorContainer) end end if (bOverallAdded) then table.remove(segmentsTable, #segmentsTable) end end function Details:DoContainerIndexCleanup() ---@type combat[] local segmentsTable = Details:GetCombatSegments() or {} local bOverallAdded if (not Details.overall_clear_logout) then table.insert(segmentsTable, Details.tabela_overall) bOverallAdded = true end for _, combatObject in ipairs(segmentsTable) do for _, actorContainer in ipairs(combatObject) do Details.clear:c_container_combatentes_index(actorContainer) end end if (bOverallAdded) then table.remove(segmentsTable, #segmentsTable) end end --limpa indexes e metatables function Details:PrepareTablesForSave() Details.clear_ungrouped = true --clear instances Details:DoInstanceCleanup() Details:DoClassesCleanup() Details:DoContainerCleanup() --clear combats ---@type combat[] local combatTables = {} ---@type combat[] local segmentsTable = Details:GetCombatSegments() or {} for i = #segmentsTable, 1, -1 do ---@type combat local combatObject = segmentsTable[i] if (combatObject.__destroyed) then table.remove(segmentsTable, i) end end --remove segments marked as 'trash' for i = #segmentsTable, 1, -1 do ---@type combat local combatObject = segmentsTable[i] if (combatObject:IsTrash()) then table.remove(segmentsTable, i) end end segmentsTable = Details:GetCombatSegments() or {} --remove segments > of the segment limit to save if (Details.segments_amount_to_save and Details.segments_amount_to_save < Details.segments_amount) then for i = Details.segments_amount, Details.segments_amount_to_save + 1, -1 do if (segmentsTable[i]) then table.remove(segmentsTable, i) end end end --clear overall segment if (Details.overall_clear_logout) then Details.tabela_overall = nil _detalhes_database.tabela_overall = nil else ---@type combat local overallCombatObject = Details.tabela_overall --this is a cleanup for overall data (overall) if (Details.clear_ungrouped) then --deal with actor which could potentially be removed from the database for containerId = 1, DETAILS_COMBAT_AMOUNT_CONTAINERS do local actorContainer = overallCombatObject:GetContainer(containerId) local actorTable = actorContainer:GetActorTable() for actorIndex = #actorTable, 1, -1 do ---@type actor local actorObject = actorTable[actorIndex] 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 --find orphans, finding orphans should be done when deleting an actor, it should iterate among the actor pets and delete them as well --now deal with pets without owners (overall) for containerId = 1, DETAILS_COMBAT_AMOUNT_CONTAINERS do local actorContainer = overallCombatObject:GetContainer(containerId) local actorTable = actorContainer:GetActorTable() 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 for i, combatObject in ipairs(segmentsTable) do ---@cast combatObject combat combatTables[#combatTables+1] = combatObject end --this is a cleanup for combat stored in the segment list for combatIndex, combatObject in ipairs(combatTables) do ---@cast combatObject combat --clear the time data (chart data) - if the option to cleanup on logout is enabled if (Details.clear_graphic) then Details:Destroy(combatObject.TimeData) combatObject.TimeData = {} end local bIsBossEncounter = combatObject.is_boss if (bIsBossEncounter) then if (combatObject.pvp) then bIsBossEncounter = false end end if (not combatObject.is_mythic_dungeon_segment and Details.clear_ungrouped) then for i = 1, DETAILS_COMBAT_AMOUNT_CONTAINERS do ---@type actorcontainer local actorContainer = combatObject:GetContainer(i) if (actorContainer) then local actorTable = actorContainer:GetActorTable() for o = #actorTable, 1, -1 do ---@type actor local actorObject = actorTable[o] 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 else if (combatObject.is_mythic_dungeon_segment) then for i = 1, DETAILS_COMBAT_AMOUNT_CONTAINERS do ---@type actorcontainer local actorContainer = combatObject:GetContainer(i) if (actorContainer) then local actorTable = actorContainer:GetActorTable() for o = #actorTable, 1, -1 do ---@type actor local actorObject = actorTable[o] for funcName in pairs(Details222.Mixins.ActorMixin) do actorObject[funcName] = nil end end end end end end end --panic mode (in case the player disconnets during a boss encounter, drop all tables to speedup the login and login back process) if (Details.segments_panic_mode and Details.can_panic_mode) then if (Details.tabela_vigente.is_boss) then Details.tabela_historico = Details.historico:CreateNewSegmentDatabase() end end --clear all segments on logoff if (Details.data_cleanup_logout) then Details.tabela_historico = Details.historico:CreateNewSegmentDatabase() Details.tabela_overall = nil _detalhes_database.tabela_overall = nil end --clear customs Details.clear:c_atributo_custom() --clear owners Details:RemoveOwnerFromPets() --clear container indexes Details:DoContainerIndexCleanup() end function Details:reset_window(instancia) if (instancia.segmento == -1) then instancia.showing[instancia.atributo].need_refresh = true instancia.v_barras = true instancia:ResetaGump() instancia:RefreshMainWindow(true) end end ---start/restart the internal garbage collector runtime ~garbage ---@param bShouldForceCollect boolean if true, the garbage collector will run regardless of the time interval ---@param lastEvent unixtime no call is passing lastEvent at the moment function Details222.GarbageCollector.RestartInternalGarbageCollector(bShouldForceCollect, lastEvent) --print("d! debug: running garbage collector...") if (not bShouldForceCollect) then local thisTime = Details222.GarbageCollector.lastCollectTime + Details222.GarbageCollector.intervalTime if (thisTime > Details._tempo + 1) then return 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 Details.Schedules.After(5, Details222.GarbageCollector.RestartInternalGarbageCollector, bShouldForceCollect, lastEvent) return end end end end if (Details.debug) then if (bShouldForceCollect) then --Details:Msg("(debug) collecting garbage with forced state:", bShouldForceCollect) else --Details:Msg("(debug) collecting garbage.") end end --cleanup all the parser caches Details:ClearParserCache() --cleanup lines which isn't shown but has an actor attached to for instanceId, instanceObject in Details:ListInstances() do if (instanceObject.barras and instanceObject.barras[1]) then for i, lineRow in ipairs(instanceObject.barras) do if (not lineRow:IsShown()) then lineRow.minha_tabela = nil end end end end --print("d! debug: RunGarbageCollector() Start") ---@type number local amountActorRemoved = Details222.GarbageCollector.RunGarbageCollector(lastEvent) --print("d! debug: RunGarbageCollector() Ended, cleanup:", amountActorRemoved, "actors.") --139 actor removed, but don't remove anything (/reload it remove again) --UpdateAddOnMemoryUsage() --local memoryUsage = GetAddOnMemoryUsage("Details") --print("Memory:", floor(memoryUsage)/1000, "MBytes") --refresh nas janelas if (amountActorRemoved > 0) then Details:InstanceCallDetailsFunc(Details.reset_window) end --cleanup backlisted pets within the handler of actor containers Details222.PetContainer.DoMaintenance() Details:ClearCCPetsBlackList() --cleanup spec cache Details:ResetSpecCache() --cleanup the shield cache Details:Destroy(Details.ShieldCache) --set the time of the last run Details222.GarbageCollector.lastCollectTime = Details._tempo if (Details.debug) then --Details:Msg("(debug) executing: collectgarbage().") --collectgarbage() end end ---check all the actors and remove the ones which are not in use ---@param combatObject combat ---@param overriteInterval unixtime ---@return integer local collectGarbage = function(combatObject, overriteInterval) --amount of actors removed local amountCleaned = 0 --do not collect things in a mythic+ dungeon segment if (combatObject.is_mythic_dungeon_run_id or combatObject.is_mythic_dungeon_segment) then return amountCleaned end if (combatObject.__destroyed) then Details:Msg("a deleted combat object was found on g2.collector, please report this bug on discord:") Details:Msg("combat destroyed by:", combatObject.__destroyedBy) return 0 end ---@type number local _tempo = _time() ---@type number for containerId = 1, 4 do ---@type actorcontainer local actorContainer = combatObject:GetContainer(containerId) ---@type table local actorList = actorContainer:GetActorTable() for actorIndex = #actorList, 1, -1 do ---@type actor local actorObject = actorList[actorIndex] 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 ---@type unixtime local lastSeenEventTime = actorObject.last_event ---@type number local nextGarbageCollection if (overriteInterval) then nextGarbageCollection = lastSeenEventTime + overriteInterval else nextGarbageCollection = lastSeenEventTime + Details222.GarbageCollector.intervalTime end if (nextGarbageCollection - 1 < _tempo) then canCollect = true end if (canCollect) then amountCleaned = amountCleaned + 1 if (containerId == 1 or containerId == 2) then --damage or healing Details222.TimeMachine.RemoveActor(actorObject) end --remove the actor from the container Details:DestroyActor(actorObject, actorContainer, combatObject) --a window showing 'Auras & Void Zones' did not refreshed and had an actor pointing to here end end end actorContainer:Cleanup() if (amountCleaned > 0) then --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() --refresh the breakdown window if (Details.BreakdownWindowFrame:IsShown()) then Details222.BreakdownWindow.RefreshPlayerScroll() end end actorContainer.need_refresh = true end --end of containerId loop return amountCleaned end --end of collectGarbage function ---run the garbage collector ---@param overriteLastEvent unixtime function Details222.GarbageCollector.RunGarbageCollector(overriteLastEvent) ---@type number local amountRemoved = 0 ---@type combat local currentCombat = Details:GetCurrentCombat() --create a list of all combats except the current one ---@type table local segmentsTable = Details:GetCombatSegments() --collect destroyed combat objects local bGotSegmentsRemoved = false for i = #segmentsTable, 1, -1 do local combatObject = segmentsTable[i] if (combatObject ~= currentCombat) then if (combatObject.__destroyed) then table.remove(segmentsTable, i) bGotSegmentsRemoved = true end end end if (bGotSegmentsRemoved) then Details:SendEvent("DETAILS_DATA_SEGMENTREMOVED") end ---@type table local segmentsList = {} --add all segments except the current one for _, combatObject in ipairs(segmentsTable) do if (combatObject ~= currentCombat) then segmentsList[#segmentsList+1] = combatObject end end --add the current segment at the end of the list segmentsList[#segmentsList+1] = currentCombat --collect the garbage for i, combatObject in ipairs(segmentsList) do if (combatObject.__destroyed) then Details:Msg("a deleted combat object was found by the g.collector, please report this bug on discord:") Details:Msg("combat destroyed by:", combatObject.__destroyedBy) end local removedActors = collectGarbage(combatObject, overriteLastEvent) if (i == #segmentsList) then --print("current segment removed:", removedActors, "actors.") end amountRemoved = amountRemoved + removedActors end ---@type combat local overallCombatObject = Details.tabela_overall amountRemoved = amountRemoved + collectGarbage(overallCombatObject, overriteLastEvent) if (amountRemoved > 0) then Details:InstanceCallDetailsFunc(Details.ScheduleUpdate) Details:RefreshMainWindow(-1) 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