Files
coa-details/functions/pack.lua
T
2024-05-20 13:13:52 -07:00

1924 lines
72 KiB
Lua

if (true) then
--return
end
local Details = _G.Details
local bit = _G.bit
local DETAILS_ATTRIBUTE_DAMAGE = _G.DETAILS_ATTRIBUTE_DAMAGE
local DF = _G.DetailsFramework
local tonumber = _G.tonumber
local select = _G.select
local strsplit = _G.strsplit
local floor = _G.floor
local tremove = _G.tremove
local UnitName = _G.UnitName
local tinsert = tinsert
local IsInRaid = _G.IsInRaid
local GetNumGroupMembers = _G.GetNumGroupMembers
local GetRaidRosterInfo = _G.GetRaidRosterInfo
local unpack = _G.unpack
local IsInGroup = _G.IsInGroup
local addonName, Details222 = ...
Details.packFunctions = {}
--lookup actor information tables
local actorInformation = {}
local actorInformationIndexes = {}
local actorDamageInfo = {}
local actorHealInfo = {}
local actorUtilityInfo = {}
--flags
local REACTION_HOSTILE = 0x00000040
local IS_GROUP_OBJECT = 0x00000007
local REACTION_FRIENDLY = 0x00000010
local OBJECT_TYPE_MASK = 0x0000FC00
local OBJECT_TYPE_OBJECT = 0x00004000
local OBJECT_TYPE_PETGUARDIAN = 0x00003000
local OBJECT_TYPE_GUARDIAN = 0x00002000
local OBJECT_TYPE_PET = 0x00001000
local OBJECT_TYPE_NPC = 0x00000800
local OBJECT_TYPE_PLAYER = 0x00000400
local INDEX_EXPORT_FLAG = 1
local INDEX_COMBAT_START_TIME = 2
local INDEX_COMBAT_END_TIME = 3
local INDEX_COMBAT_START_DATE = 4
local INDEX_COMBAT_END_DATE = 5
local INDEX_COMBAT_NAME = 6
local TOTAL_INDEXES_FOR_COMBAT_INFORMATION = 6
local entitySerialCounter = 0
local isDebugging = false
function Details.packFunctions.GetAllData()
local combat = Details:GetCurrentCombat()
local packedData = Details.packFunctions.PackCombatData(combat, 0x1B)
--local packedData = Details.packFunctions.PackCombatData(combat, 0x13)
return packedData
end
--debug
function Details.packFunctions.GetAllDataDebug()
local combat = Details:GetCurrentCombat()
local packedData = Details.packFunctions.PackCombatData(combat, 0x13)
--unpack data
Details.packFunctions.DeployPackedCombatData(packedData)
end
--pack the combat
function Details.packFunctions.PackCombatData(combatObject, flags)
--0x1 damage
--0x2 healing
--0x4 energy
--0x8 misc
--0x10 no combat header
Details:Destroy(actorInformation)
Details:Destroy(actorInformationIndexes)
Details:Destroy(actorDamageInfo)
Details:Destroy(actorHealInfo)
Details:Destroy(actorUtilityInfo)
--reset the serial counter
entitySerialCounter = 0
local isBossEncouter = combatObject.is_boss
local startDate, endDate = combatObject:GetDate()
local startCombatTime = combatObject:GetStartTime() or 0
local endCombatTime = combatObject:GetEndTime() or 0
local combatInfo = {
floor(startCombatTime), --1
floor(endCombatTime), --2
startDate, --3
endDate, --4
isBossEncouter and isBossEncouter.encounter or "Unknown Enemy" --5
}
--if there's no combat information, indexes for combat data is zero
if (bit.band(flags, 0x10) ~= 0) then
TOTAL_INDEXES_FOR_COMBAT_INFORMATION = 0
end
if (bit.band(flags, 0x1) ~= 0) then
---print("pack damage")
Details.packFunctions.PackDamage(combatObject)
end
if (bit.band(flags, 0x2) ~= 0) then
--print("pack heal")
Details.packFunctions.PackHeal(combatObject)
end
if (bit.band(flags, 0x8) ~= 0) then
--print("pack utility")
Details.packFunctions.PackUtility(combatObject)
end
--prepare data to send over network
local exportedString = flags .. ","
--add the combat info
if (bit.band(flags, 0x10) == 0) then
for index, data in ipairs(combatInfo) do
exportedString = exportedString .. data .. ","
end
end
--add the actor references table
for index, data in ipairs(actorInformation) do
exportedString = exportedString .. data .. ","
end
--add the damage actors data
if (bit.band(flags, 0x1) ~= 0) then
exportedString = exportedString .. "!D" .. ","
for index, data in ipairs(actorDamageInfo) do
exportedString = exportedString .. data .. ","
end
end
--add the heal actors data
if (bit.band(flags, 0x2) ~= 0) then
exportedString = exportedString .. "!H" .. ","
for index, data in ipairs(actorHealInfo) do
exportedString = exportedString .. data .. ","
end
end
--add the utility actors data
if (bit.band(flags, 0x8) ~= 0) then
exportedString = exportedString .. "!U" .. ","
for index, data in ipairs(actorUtilityInfo) do
exportedString = exportedString .. data .. ","
end
end
--main stuff
--print("finished export (debug):", exportedString) --debug
--print("uncompressed (debug):", format("%.2f", #exportedString/1024), "KBytes")
--if true then return exportedString end
if (isDebugging) then
print(exportedString)
end
--Details:Dump({exportedString})
--print("EXPORTING STRING FINAL:", exportedString)
--compress
local LibDeflate = _G.LibStub:GetLibrary("LibDeflate")
local dataCompressed = LibDeflate:CompressDeflate(exportedString, {level = 9})
local dataEncoded = LibDeflate:EncodeForWoWAddonChannel(dataCompressed)
--print("encoded for WowAddonChannel (debug):", format("%.2f", #dataEncoded/1024), "KBytes")
return dataEncoded
end
local function CreateGUID(realmID, guidType, unk1, unk2, uid)
if guidType == 0 then
return string.format("0x%02X%01X%03X%03X%07X", realmID, guidType, unk1, unk2, uid)
elseif guidType == 4 then
return string.format("0x%02X%01X%07X%06X", realmID, guidType, unk1, uid)
else
return string.format("0x%02X%01X%03X%04X%06X", realmID, guidType, unk1, unk2, uid)
end
end
function Details.packFunctions.CreateNPCGUID(realmID, unk1, npcID, spawnID)
return CreateGUID(realmID, 3, unk1, npcID, spawnID)
end
function Details.packFunctions.CreatePlayerGUID(realmID, unk1, unk2, uid)
return CreateGUID(realmID, 0, unk1, unk2, uid)
end
function Details.packFunctions.CreatePetGUID(realmID, petID, uid)
return CreateGUID(realmID, 4, petID, uid)
end
function Details.packFunctions.CreateVehicleGUID(realmID, unk1, npcID, spawnID)
return CreateGUID(realmID, 5, unk1, npcID, spawnID)
end
function Details.packFunctions.GenerateSerialNumber()
local serialNumber = entitySerialCounter
entitySerialCounter = entitySerialCounter + 1
return serialNumber
end
--[[
actor flag IDs
1: player friendly
2: player enemy
3: enemy npc pet
4: enemy npc non-pet
5: friendly npc pet
6: friendly non-npc
7: unknown entity type
]]
local packActorFlag = function(actor)
if (actor.grupo) then
--it's a player in the group
return 1
end
local flag = actor.flag_original or 0
--check hostility
if (bit.band(flag, REACTION_HOSTILE) ~= 0) then
--is hostile
if (bit.band(flag, OBJECT_TYPE_PLAYER) == 0) then
--isn't a player
if (bit.band(flag, OBJECT_TYPE_PETGUARDIAN) ~= 0) then
--is pet
return 3
else
--is enemy npc
return 4
end
else
--is enemy player
return 2
end
else
--is friendly
if (bit.band(flag, OBJECT_TYPE_PLAYER) == 0) then
--is player
return 1
else
--isn't a player
if (bit.band(flag, OBJECT_TYPE_PETGUARDIAN) ~= 0) then
--is friendly pet
return 5
else
--is a friendly entity, most likely a npc
return 6
end
end
end
return 7
end
local unpackActorFlag = function(flag)
--convert to integer
flag = tonumber(flag)
if (flag == 1) then --player
return 0x511
elseif (flag == 2) then --enemy player
return 0x548
elseif (flag == 3) then --enemy pet with player or AI controller
return 0x1A48
elseif (flag == 4) then --enemy npc
return 0xA48
elseif (flag == 5) then --friendly pet
return 0x1914
elseif (flag == 6) then --friendly npc
return 0xA14
elseif (flag == 7) then --unknown entity
return 0x4A28
end
end
local isActorInGroup = function(class, flag)
if (bit.band(flag, IS_GROUP_OBJECT) ~= 0 and class ~= "UNKNOW" and class ~= "UNGROUPPLAYER" and class ~= "PET") then
return true
end
return false
end
--[[
actor class IDs
1-12: player class Id
20: "PET"
21: "UNKNOW"
22: "UNGROUPPLAYER"
23: "ENEMY"
24: "MONSTER"
]]
local detailsClassIndexToFileName = {
[20] = "PET",
[21] = "UNKNOW",
[22] = "UNGROUPPLAYER",
[23] = "ENEMY",
[24] = "MONSTER",
}
local packActorClass = function(actor)
local classId = DF.ClassFileNameToIndex[actor.classe]
if (classId) then
return classId
elseif (classId == "PET") then
return 20
elseif (classId == "UNKNOW") then
return 21
elseif (classId == "UNGROUPPLAYER") then
return 22
elseif (classId == "ENEMY") then
return 23
elseif (classId == "MONSTER") then
return 24
end
return 21
end
local unpackActorClass = function(classId)
--convert to integer
classId = tonumber(classId)
local classFileName = DF.ClassIndexToFileName[classId]
if (not classFileName) then
classFileName = detailsClassIndexToFileName[classId]
end
return classFileName
end
--[[
actor serial
creature: C12345 (numbers are the npcId)
player: P
--]]
local packActorSerial = function(actor)
local serial = actor.serial
if serial == "" then
return "C12345"
end
if (GUIDIsNPC(serial) == 3) then
local npcId = GetCreatureIDFromGUID(serial) or 0
return "C" .. npcId
elseif (GUIDIsPlayer(serial) == 0) then
return "P"
end
end
local unpackActorSerial = function(serialNumber)
--player serial
if (serialNumber:match("^P")) then
return Details.packfunctions.CreatePlayerGUID(0, 0, 0, Details.packFunctions.GenerateSerialNumber())
elseif (serialNumber:match("^C")) then
return Details.packfunctions.CreateNPCGUID(0, 0, serialNumber:gsub("C", ""), Details.packFunctions.GenerateSerialNumber())
end
end
function Details.packFunctions.AddActorInformation(actor)
--the next index to use on the actor info table
local currentIndex = #actorInformation + 1
--calculate where this actor will be placed on the combatData table
local indexOnCombatDataTable = TOTAL_INDEXES_FOR_COMBAT_INFORMATION + currentIndex + 1
--add the actor start information index
actorInformationIndexes[actor.nome] = indexOnCombatDataTable
--index 1: actor name
actorInformation[currentIndex] = actor.nome or "unnamed" --[1]
--index 2: actor flag
actorInformation[currentIndex + 1] = packActorFlag(actor) --[2]
--index 3: actor serial
actorInformation[currentIndex + 2] = packActorSerial(actor) or "" --[3]
--index 4: actor class
actorInformation[currentIndex + 3] = packActorClass(actor) --[4]
--index 5: actor spec
actorInformation[currentIndex + 4] = actor.spec or 0 --[5]
return indexOnCombatDataTable
end
function Details.packFunctions.RetriveActorInformation(combatData, index)
--name [1]
local actorName = combatData[index]
if (not actorName) then
return
end
--flag [2]
local actorFlag = combatData[index + 1]
actorFlag = unpackActorFlag(actorFlag)
--serial [3]
local serialNumber = combatData[index + 2]
serialNumber = unpackActorSerial(serialNumber)
--class[4]
local class = combatData[index + 3]
class = unpackActorClass(class)
--spec[5]
local spec = tonumber(combatData[index + 4])
--return the values
return actorName, actorFlag, serialNumber, class, spec
end
--pack damage passes the player damage info + pets the player own
--each player will also send an enemy, the enemy will be in order of raidIndex of the player
function Details.packFunctions.PackDamage(combatObject)
if (isDebugging) then
print("PackDamage(): start.")
end
--store actorObjects to pack
local actorsToPack = {}
--get the player object from the combat > damage container
local playerName = Details.playername
local playerObject = combatObject:GetActor(DETAILS_ATTRIBUTE_DAMAGE, playerName)
if (not playerObject) then
if (isDebugging) then
print("PackDamage(): return | no player object.")
end
return
end
tinsert(actorsToPack, playerObject)
--get the list of pets the player own
local playerPets = playerObject.pets
for _, petName in ipairs(playerPets) do
local petObject = combatObject:GetActor(DETAILS_ATTRIBUTE_DAMAGE, petName)
if (petObject) then
tinsert(actorsToPack, petObject)
end
end
local playerIndex = _G.UnitInRaid("player")
if (not playerIndex) then --no player index
if (isDebugging) then
print("PackDamage(): return | no player index found.")
end
return
end
--get all npc enemies and sort them by their respaw id
local allActors = combatObject[DETAILS_ATTRIBUTE_DAMAGE]._ActorTable
local allEnemies = {} --this have subtables, format: {actorObject, spawnId}
for i = 1, #allActors do
--get the actor object
local actor = allActors[i]
--check if is an enemy or neutral
if (actor:IsNeutralOrEnemy()) then
--get the spawnId
local spawnId = GetCreatureSpawnIDFromGUID(actor.serial)
if (spawnId) then
--first index is the actorObject, the second index is the spawnId to sort enemies
tinsert(allEnemies, {actor, spawnId})
end
end
end
--sort enemies by their spawnId
table.sort(allEnemies, Details.Sort2)
local allPlayerNames = {}
for i = 1, 20 do
local name, _, subgroup = GetRaidRosterInfo(i)
if (name) then --maybe the group has less than 20 players
name = _G.Ambiguate(name, "none")
if (name and subgroup <= 4) then
tinsert(allPlayerNames, name)
end
end
end
table.sort(allPlayerNames, function(t1, t2) return t1 < t2 end)
local playerName = UnitName("player")
for i = 1, #allPlayerNames do
if (playerName == allPlayerNames[i]) then
playerIndex = i
break
end
end
--this is the enemy that this player has to send
local enemyObjectToSend = allEnemies[playerIndex] and allEnemies[playerIndex][1]
if (enemyObjectToSend) then
tinsert(actorsToPack, enemyObjectToSend)
end
--add the actors to actor information table
for _, actorObject in ipairs(actorsToPack) do
--check if already has the actor information
local indexToActorInfo = actorInformationIndexes[actorObject.nome] --actor name
if (not indexToActorInfo) then
--need to add the actor general information into the actor information table
indexToActorInfo = Details.packFunctions.AddActorInformation(actorObject)
end
end
for i = 1, #actorsToPack do
--get the actor object
local actor = actorsToPack[i]
local indexToActorInfo = actorInformationIndexes[actor.nome]
--where the information of this actor starts
local currentIndex = #actorDamageInfo + 1
--[1] index where is stored the this actor info like name, class, spec, etc
actorDamageInfo[currentIndex] = indexToActorInfo --[1]
--[2 - 6]
actorDamageInfo [currentIndex + 1] = floor(actor.total) --[2]
actorDamageInfo [currentIndex + 2] = floor(actor.totalabsorbed) --[3]
actorDamageInfo [currentIndex + 3] = floor(actor.damage_taken) --[4]
actorDamageInfo [currentIndex + 4] = floor(actor.friendlyfire_total) --[5]
actorDamageInfo [currentIndex + 5] = floor(actor.total_without_pet) --[6]
local spellContainer = actor.spells._ActorTable
--reserve an index to tell the length of spells
actorDamageInfo [#actorDamageInfo + 1] = 0
local reservedSpellSizeIndex = #actorDamageInfo
local totalSpellIndexes = 0
for spellId, spellInfo in pairs(spellContainer) do
local spellDamage = spellInfo.total
local spellHits = spellInfo.counter
local spellTargets = spellInfo.targets
actorDamageInfo [#actorDamageInfo + 1] = floor(spellId)
actorDamageInfo [#actorDamageInfo + 1] = floor(spellDamage)
actorDamageInfo [#actorDamageInfo + 1] = floor(spellHits)
totalSpellIndexes = totalSpellIndexes + 3
--build targets
local targetsSize = Details.packFunctions.CountTableEntriesValid(spellTargets) * 2
actorDamageInfo [#actorDamageInfo + 1] = targetsSize
totalSpellIndexes = totalSpellIndexes + 1
for actorName, damageDone in pairs(spellTargets) do
actorDamageInfo [#actorDamageInfo + 1] = actorName
actorDamageInfo [#actorDamageInfo + 1] = floor(damageDone)
totalSpellIndexes = totalSpellIndexes + 2
end
end
--amount of indexes spells are using
actorDamageInfo[reservedSpellSizeIndex] = totalSpellIndexes
end
if (isDebugging) then
print("PackDamage(): done.")
end
end
--------------------------------------------------------------------------------------------------------------------------------
--unpack
--@currentCombat: details! combat object
--@combatData: array with strings with combat information
--@tablePosition: first index of the first damage actor
function Details.packFunctions.UnPackDamage(currentCombat, combatData, tablePosition)
if (isDebugging) then
print("UnPackDamage(): start.")
end
--get the damage container
local damageContainer = currentCombat[DETAILS_ATTRIBUTE_DAMAGE]
--loop from 1 to 199, the amount of actors store is unknown
--todo: it's only unpacking the first actor from the table, e.g. theres izimode and eye of corruption, after export it only shows the eye of corruption
--table position does not move forward
for i = 1, 199 do
--actor information index in the combatData table
--this index gives the position where the actor name, class, spec are stored
local actorReference = tonumber(combatData[tablePosition]) --[1]
local actorName, actorFlag, serialNumber, class, spec = Details.packFunctions.RetriveActorInformation(combatData, actorReference)
if (isDebugging) then
print("UnPackDamage(): Retrivied Data From " .. (actorReference or "nil") .. ":", actorName, actorFlag, serialNumber, class, spec)
end
--check if all damage actors has been processed
--if there's no actor name it means it reached the end
if (not actorName) then
if (isDebugging) then
print("UnPackDamage(): break damage, end index:", i, (actorReference or "nil"), "tablePosition:", tablePosition, "value:", combatData[tablePosition])
end
break
end
--get or create the actor object
local actorObject = damageContainer:GetOrCreateActor(serialNumber, actorName, actorFlag, true)
--set the actor class, spec and group
actorObject.classe = class
actorObject:SetSpecId(spec)
actorObject.grupo = isActorInGroup(class, actorFlag)
actorObject.flag_original = actorFlag
--copy back the base damage
actorObject.total = tonumber(combatData[tablePosition+1]) --[2]
actorObject.totalabsorbed = tonumber(combatData[tablePosition+2]) --[3]
actorObject.damage_taken = tonumber(combatData[tablePosition+3]) --[4]
actorObject.friendlyfire_total = tonumber(combatData[tablePosition+4]) --[5]
actorObject.total_without_pet = tonumber(combatData[tablePosition+5]) --[6]
tablePosition = tablePosition + 6 --increase table position
--copy back the actor spells
--amount of indexes used to store spells for this actor
local spellsSize = tonumber(combatData [tablePosition]) --[7]
if (isDebugging) then
print("spell size unpack:", spellsSize)
end
tablePosition = tablePosition + 1
local newTargetsTable = {}
local spellIndex = tablePosition
while(spellIndex < tablePosition + spellsSize) do
local spellId = tonumber(combatData [spellIndex]) --[1]
local spellDamage = tonumber(combatData [spellIndex+1]) --[2]
local spellHits = tonumber(combatData [spellIndex+2]) --[3]
local targetsSize = tonumber(combatData[spellIndex+3]) --[4]
local targetTable = Details.packFunctions.UnpackTable(combatData, spellIndex+3, true)
local spellObject = actorObject.spells:GetOrCreateSpell(spellId, true) --this one need some translation
spellObject.total = spellDamage
spellObject.counter = spellHits
spellObject.targets = targetTable
for targetName, amount in pairs(spellObject.targets) do
newTargetsTable[targetName] = (newTargetsTable[targetName] or 0) + amount
end
spellIndex = spellIndex + targetsSize + 4
end
actorObject.targets = newTargetsTable
tablePosition = tablePosition + spellsSize --increase table position
end
if (isDebugging) then
print("UnPackDamage(): done.")
end
return tablePosition
end
function Details.packFunctions.PackHeal(combatObject)
if (isDebugging) then
print("PackHeal(): start.")
end
--store actorObjects to pack
local actorsToPack = {}
--get the player object from the combat > damage container
local playerName = Details.playername
local playerObject = combatObject:GetActor(DETAILS_ATTRIBUTE_HEAL, playerName)
if (not playerObject) then
if (isDebugging) then
print("PackHeal(): return | no player object.")
end
return
end
tinsert(actorsToPack, playerObject)
--get the list of pets the player own
local playerPets = playerObject.pets
for _, petName in ipairs(playerPets) do
local petObject = combatObject:GetActor(DETAILS_ATTRIBUTE_HEAL, petName)
if (petObject) then
tinsert(actorsToPack, petObject)
end
end
local playerIndex = UnitInRaid("player")
if (not playerIndex) then --no player index
if (isDebugging) then
print("PackHeal(): return | no player index found.")
end
return
end
--get all npc enemies and sort them by their respaw id
local allActors = combatObject[DETAILS_ATTRIBUTE_HEAL]._ActorTable
local allEnemies = {} --this have subtables, format: {actorObject, spawnId}
for i = 1, #allActors do
--get the actor object
local actor = allActors[i]
--check if is an enemy or neutral
if (actor:IsNeutralOrEnemy()) then
--get the spawnId
local spawnId = GetCreatureSpawnIDFromGUID(actor.serial)
if (spawnId) then
--first index is the actorObject, the second index is the spawnId to sort enemies
tinsert(allEnemies, {actor, spawnId})
end
end
end
--sort enemies by their spawnId
table.sort(allEnemies, Details.Sort2)
local allPlayerNames = {}
for i = 1, 20 do
local name, _, subgroup = GetRaidRosterInfo(i)
if (name) then --maybe the group has less than 20 players
name = Ambiguate(name, "none")
if (name and subgroup <= 4) then
tinsert(allPlayerNames, name)
end
end
end
table.sort(allPlayerNames, function(t1, t2) return t1 < t2 end)
local playerName = UnitName("player")
for i = 1, #allPlayerNames do
if (playerName == allPlayerNames[i]) then
playerIndex = i
break
end
end
--this is the enemy that this player has to send
local enemyObjectToSend = allEnemies[playerIndex] and allEnemies[playerIndex][1]
if (enemyObjectToSend) then
tinsert(actorsToPack, enemyObjectToSend)
end
--add the actors to actor information table
for _, actorObject in ipairs(actorsToPack) do
--check if already has the actor information
local indexToActorInfo = actorInformationIndexes[actorObject.nome] --actor name
if (not indexToActorInfo) then
--need to add the actor general information into the actor information table
indexToActorInfo = Details.packFunctions.AddActorInformation(actorObject)
end
end
for i = 1, #actorsToPack do
--get the actor object
local actor = actorsToPack[i]
local indexToActorInfo = actorInformationIndexes[actor.nome]
--where the information of this actor starts
local currentIndex = #actorHealInfo + 1
--[1] index where is stored the this actor info like name, class, spec, etc
actorHealInfo[currentIndex] = indexToActorInfo --[1]
--[2 - 6]
actorHealInfo [currentIndex + 1] = floor(actor.total) --[2]
actorHealInfo [currentIndex + 2] = floor(actor.totalabsorb) --[3]
actorHealInfo [currentIndex + 3] = floor(actor.totalover) --[4]
actorHealInfo [currentIndex + 4] = floor(actor.healing_taken) --[5]
actorHealInfo [currentIndex + 5] = floor(actor.totalover_without_pet) --[6]
local spellContainer = actor.spells._ActorTable
--reserve an index to tell the length of spells
actorHealInfo [#actorHealInfo + 1] = 0
local reservedSpellSizeIndex = #actorHealInfo
local totalSpellIndexes = 0
for spellId, spellInfo in pairs(spellContainer) do
local spellHealingDone = spellInfo.total
local spellHits = spellInfo.counter
local spellTargets = spellInfo.targets
actorHealInfo [#actorHealInfo + 1] = floor(spellId)
actorHealInfo [#actorHealInfo + 1] = floor(spellHealingDone)
actorHealInfo [#actorHealInfo + 1] = floor(spellHits)
totalSpellIndexes = totalSpellIndexes + 3
--build targets
local targetsSize = Details.packFunctions.CountTableEntriesValid(spellTargets) * 2
actorHealInfo [#actorHealInfo + 1] = targetsSize
totalSpellIndexes = totalSpellIndexes + 1
for actorName, healingDone in pairs(spellTargets) do
actorHealInfo [#actorHealInfo + 1] = actorName
actorHealInfo [#actorHealInfo + 1] = floor(healingDone)
totalSpellIndexes = totalSpellIndexes + 2
end
end
--amount of indexes spells are using
actorHealInfo[reservedSpellSizeIndex] = totalSpellIndexes
end
if (isDebugging) then
print("PackHeal(): done.")
end
end
--------------------------------------------------------------------------------------------------------------------------------
--unpack
function Details.packFunctions.UnPackHeal(currentCombat, combatData, tablePosition)
if (isDebugging) then
print("UnPackHeal(): start.")
end
--get the healing container
local healContainer = currentCombat[DETAILS_ATTRIBUTE_HEAL]
--loop from 1 to 199, the amount of actors store is unknown
--todo: it's only unpacking the first actor from the table, e.g. theres izimode and eye of corruption, after export it only shows the eye of corruption
--table position does not move forward
for i = 1, 199 do
--actor information index in the combatData table
--this index gives the position where the actor name, class, spec are stored
local actorReference = tonumber(combatData[tablePosition]) --[1]
local actorName, actorFlag, serialNumber, class, spec = Details.packFunctions.RetriveActorInformation(combatData, actorReference)
if (isDebugging) then
print("UnPackHeal(): Retrivied Data From " .. (actorReference or "nil") .. ":", actorName, actorFlag, serialNumber, class, spec)
end
--check if all healing actors has been processed
--if there's no actor name it means it reached the end
if (not actorName) then
if (isDebugging) then
print("UnPackHeal(): break | Heal loop has been stopped", "index:", i, "tablePosition:", tablePosition, "value:", combatData[tablePosition])
end
break
end
--get or create the actor object
local actorObject = healContainer:GetOrCreateActor(serialNumber, actorName, actorFlag, true)
--set the actor class, spec and group
actorObject.classe = class
actorObject:SetSpecId(spec)
actorObject.grupo = isActorInGroup(class, actorFlag)
actorObject.flag_original = actorFlag
--copy the base healing
actorObject.total = tonumber(combatData[tablePosition+1]) --[2]
actorObject.totalabsorb = tonumber(combatData[tablePosition+2]) --[3]
actorObject.totalover = tonumber(combatData[tablePosition+3]) --[4]
actorObject.healing_taken = tonumber(combatData[tablePosition+4]) --[5]
actorObject.totalover_without_pet = tonumber(combatData[tablePosition+5]) --[6]
tablePosition = tablePosition + 6
--copy back the actor spells
--amount of indexes used to store spells for this actor
local spellsSize = tonumber(combatData [tablePosition]) --[7]
if (isDebugging) then
print("spell size unpack:", spellsSize)
end
tablePosition = tablePosition + 1
local newTargetsTable = {}
local spellIndex = tablePosition
while(spellIndex < tablePosition + spellsSize) do
local spellId = tonumber(combatData [spellIndex]) --[1]
local spellHealingDone = tonumber(combatData [spellIndex+1]) --[2]
local spellHits = tonumber(combatData [spellIndex+2]) --[3]
local targetsSize = tonumber(combatData[spellIndex+3]) --[4]
local targetTable = Details.packFunctions.UnpackTable(combatData, spellIndex+3, true)
local spellObject = actorObject.spells:GetOrCreateSpell(spellId, true) --this one need some translation
spellObject.total = spellHealingDone
spellObject.counter = spellHits
spellObject.targets = targetTable
for targetName, amount in pairs(spellObject.targets) do
newTargetsTable[targetName] = (newTargetsTable[targetName] or 0) + amount
end
spellIndex = spellIndex + targetsSize + 4
end
actorObject.targets = newTargetsTable
tablePosition = tablePosition + spellsSize --increase table position
end
if (isDebugging) then
print("UnPackHeal(): done.")
end
return tablePosition
end
--------------------------------------------------------------------------------------------------
--pack utility data
--pack utility passes the player utility info + pets the player own
--each player will also send an enemy, the enemy will be in order of raidIndex of the player
function Details.packFunctions.PackUtility(combatObject)
if (isDebugging) then
print("PackUtility(): start.")
end
--store actorObjects to pack
local actorsToPack = {}
--get the player object from the combat > utility container
local playerName = Details.playername
local playerObject = combatObject:GetActor(DETAILS_ATTRIBUTE_MISC, playerName)
if (not playerObject) then
if (isDebugging) then
print("PackUtility(): return | no player object.")
end
return
end
tinsert(actorsToPack, playerObject)
--get the list of pets the player own
local playerPets = playerObject.pets
for _, petName in ipairs(playerPets) do
local petObject = combatObject:GetActor(DETAILS_ATTRIBUTE_MISC, petName)
if (petObject) then
tinsert(actorsToPack, petObject)
end
end
local playerIndex = _G.UnitInRaid("player")
if (not playerIndex) then --no player index
if (isDebugging) then
print("PackUtility(): return | no player index found.")
end
return
end
--get all npc enemies and sort them by their respaw id
local allActors = combatObject[DETAILS_ATTRIBUTE_MISC]._ActorTable
local allEnemies = {} --this have subtables, format: {actorObject, spawnId}
for i = 1, #allActors do
--get the actor object
local actor = allActors[i]
--check if is an enemy or neutral
if (actor:IsNeutralOrEnemy()) then
--get the spawnId
local spawnId = GetCreatureSpawnIDFromGUID(actor.serial)
if (spawnId) then
--first index is the actorObject, the second index is the spawnId to sort enemies
tinsert(allEnemies, {actor, spawnId})
end
end
end
--sort enemies by their spawnId
table.sort(allEnemies, Details.Sort2)
local allPlayerNames = {}
for i = 1, 20 do
local name, _, subgroup = GetRaidRosterInfo(i)
if (name) then --maybe the group has less than 20 players
name = _G.Ambiguate(name, "none")
if (name and subgroup <= 4) then
tinsert(allPlayerNames, name)
end
end
end
table.sort(allPlayerNames, function(t1, t2) return t1 < t2 end)
local playerName = UnitName("player")
for i = 1, #allPlayerNames do
if (playerName == allPlayerNames[i]) then
playerIndex = i
break
end
end
--this is the enemy that this player has to send
local enemyObjectToSend = allEnemies[playerIndex] and allEnemies[playerIndex][1]
if (enemyObjectToSend) then
tinsert(actorsToPack, enemyObjectToSend)
end
--add the actors to actor information table
for _, actorObject in ipairs(actorsToPack) do
--check if already has the actor information
local indexToActorInfo = actorInformationIndexes[actorObject.nome] --actor name
if (not indexToActorInfo) then
--need to add the actor general information into the actor information table
indexToActorInfo = Details.packFunctions.AddActorInformation(actorObject)
end
end
for i = 1, #actorsToPack do
--get the actor object
local actor = actorsToPack[i]
local indexToActorInfo = actorInformationIndexes[actor.nome]
--where the information of this actor starts
local currentIndex = #actorUtilityInfo + 1
--[1] index where is stored the actor info like name, class, spec, etc
actorUtilityInfo[currentIndex] = indexToActorInfo --[1]
--[=[
interrupt_spells._ActorTable [spellId] = {
[2139] = {
["id"] = 2139,
["interrompeu_oque"] = {
[337110] = 1,
},
["targets"] = {
["Baroness Frieda"] = 1,
},
["counter"] = 1,
},
}
cooldowns_defensive
cooldowns_defensive_targets
["cooldowns_defensive_spells"] = {
["_ActorTable"] = {
[45438] = {
["id"] = 45438,
["targets"] = {
["Relune-Tichondrius"] = 1,
},
["counter"] = 1,
},
},
["tipo"] = 9,
},
cc_break
cc_break_oque
cc_break_targets
["cc_break_spells"] = {
["_ActorTable"] = {
[42223] = {
["cc_break_oque"] = {
[197214] = 2,
},
["id"] = 42223,
["targets"] = {
["Castellan Niklaus"] = 1,
["Baroness Frieda"] = 1,
},
["cc_break"] = 2,
["counter"] = 0,
},
},
},
["cc_done_spells"] = {
["_ActorTable"] = {
[127797] = {
["id"] = 127797,
["targets"] = {
["Castellan Niklaus"] = 1,
["Lord Stavros"] = 1,
["Baroness Frieda"] = 1,
},
["counter"] = 3,
},
},
["tipo"] = 9,
},
["dispell_spells"] = {
["_ActorTable"] = {
[77130] = {
["targets"] = {
["Magicgreenie-BleedingHollow"] = 1,
},
["id"] = 77130,
["dispell_oque"] = {
[337110] = 1,
},
["dispell"] = 1,
["counter"] = 0,
},
},
["tipo"] = 9,
},
ress
ress_targets
["ress_spells"] = {
["_ActorTable"] = {
[212048] = {
["id"] = 212048,
["ress"] = 7,
["targets"] = {
["Freezerbeef-Illidan"] = 1,
["Jilkari-ThoriumBrotherhood"] = 1,
["Ditador"] = 1,
["Caller-Thrall"] = 1,
["Thebappo-Tichondrius"] = 1,
["Superskourge-Area52"] = 1,
["Rorschak-Area52"] = 1,
},
["counter"] = 0,
},
},
["tipo"] = 9,
},
--]=]
--cooldowns, pack player cooldowns used
actorUtilityInfo [#actorUtilityInfo + 1] = "C"
local cooldownContainer = actor.cooldowns_defensive_spells and actor.cooldowns_defensive_spells._ActorTable
local totalSpellIndexes = 0
if (cooldownContainer) then
--reserve an index to tell the length of spells
actorUtilityInfo [#actorUtilityInfo + 1] = 0
local reservedSpellSizeIndex = #actorUtilityInfo
for spellId, spellInfo in pairs(cooldownContainer) do
local spellCounter = spellInfo.counter
local spellTargets = spellInfo.targets
actorUtilityInfo [#actorUtilityInfo + 1] = floor(spellId)
actorUtilityInfo [#actorUtilityInfo + 1] = floor(spellCounter)
totalSpellIndexes = totalSpellIndexes + 2
--build targets
local targetsSize = Details.packFunctions.CountTableEntriesValid(spellTargets) * 2
actorUtilityInfo [#actorUtilityInfo + 1] = targetsSize
totalSpellIndexes = totalSpellIndexes + 1
for actorName, totalDone in pairs(spellTargets) do
actorUtilityInfo [#actorUtilityInfo + 1] = actorName
actorUtilityInfo [#actorUtilityInfo + 1] = floor(totalDone)
totalSpellIndexes = totalSpellIndexes + 2
end
end
--amount of indexes spells are using
actorUtilityInfo[reservedSpellSizeIndex] = totalSpellIndexes
else
actorUtilityInfo [#actorUtilityInfo + 1] = 0
end
--interrupts, pack player interrupts
actorUtilityInfo [#actorUtilityInfo + 1] = "I"
local interruptsContainer = actor.interrupt_spells and actor.interrupt_spells._ActorTable
local totalSpellIndexes = 0
if (interruptsContainer) then
--reserve an index to tell the length of spells
actorUtilityInfo [#actorUtilityInfo + 1] = 0
local reservedSpellSizeIndex = #actorUtilityInfo
for spellId, spellInfo in pairs(interruptsContainer) do
local spellCounter = spellInfo.counter
local spellTargets = spellInfo.targets
local whatGotInterrupted = spellInfo.interrompeu_oque
actorUtilityInfo [#actorUtilityInfo + 1] = floor(spellId)
actorUtilityInfo [#actorUtilityInfo + 1] = floor(spellCounter) --spellCounter is nil
totalSpellIndexes = totalSpellIndexes + 2
--build targets
local targetsSize = Details.packFunctions.CountTableEntriesValid(spellTargets) * 2
actorUtilityInfo [#actorUtilityInfo + 1] = targetsSize
totalSpellIndexes = totalSpellIndexes + 1
for actorName, totalDone in pairs(spellTargets) do
actorUtilityInfo [#actorUtilityInfo + 1] = actorName
actorUtilityInfo [#actorUtilityInfo + 1] = floor(totalDone)
totalSpellIndexes = totalSpellIndexes + 2
end
--build what was interrupted by the spell
local interruptedSize = Details.packFunctions.CountTableEntriesValid(whatGotInterrupted) * 2
actorUtilityInfo [#actorUtilityInfo + 1] = interruptedSize
totalSpellIndexes = totalSpellIndexes + 1
for spellId, totalDone in pairs(whatGotInterrupted) do
actorUtilityInfo [#actorUtilityInfo + 1] = spellId
actorUtilityInfo [#actorUtilityInfo + 1] = floor(totalDone)
totalSpellIndexes = totalSpellIndexes + 2
end
end
--amount of indexes spells are using
actorUtilityInfo[reservedSpellSizeIndex] = totalSpellIndexes
else
actorUtilityInfo [#actorUtilityInfo + 1] = 0
end
--cc break, pack player crowd control breaks
actorUtilityInfo [#actorUtilityInfo + 1] = "B"
local ccBreakContainer = actor.cc_break_spells and actor.cc_break_spells._ActorTable
local totalSpellIndexes = 0
if (ccBreakContainer) then
--reserve an index to tell the length of spells
actorUtilityInfo [#actorUtilityInfo + 1] = 0
local reservedSpellSizeIndex = #actorUtilityInfo
for spellId, spellInfo in pairs(ccBreakContainer) do
local spellCounter = spellInfo.cc_break
local spellTargets = spellInfo.targets
local whatGotCCBroken = spellInfo.cc_break_oque
actorUtilityInfo [#actorUtilityInfo + 1] = floor(spellId)
actorUtilityInfo [#actorUtilityInfo + 1] = floor(spellCounter)
totalSpellIndexes = totalSpellIndexes + 2
--build targets
local targetsSize = Details.packFunctions.CountTableEntriesValid(spellTargets) * 2
actorUtilityInfo [#actorUtilityInfo + 1] = targetsSize
totalSpellIndexes = totalSpellIndexes + 1
for actorName, totalDone in pairs(spellTargets) do
actorUtilityInfo [#actorUtilityInfo + 1] = actorName
actorUtilityInfo [#actorUtilityInfo + 1] = floor(totalDone)
totalSpellIndexes = totalSpellIndexes + 2
end
--build what was interrupted by the spell
local ccBrokenSize = Details.packFunctions.CountTableEntriesValid(whatGotCCBroken) * 2
actorUtilityInfo [#actorUtilityInfo + 1] = ccBrokenSize
totalSpellIndexes = totalSpellIndexes + 1
for spellId, totalDone in pairs(whatGotCCBroken) do
actorUtilityInfo [#actorUtilityInfo + 1] = spellId
actorUtilityInfo [#actorUtilityInfo + 1] = floor(totalDone)
totalSpellIndexes = totalSpellIndexes + 2
end
end
--amount of indexes spells are using
actorUtilityInfo[reservedSpellSizeIndex] = totalSpellIndexes
else
actorUtilityInfo [#actorUtilityInfo + 1] = 0
end
--dispel, pack player dispels done
actorUtilityInfo [#actorUtilityInfo + 1] = "D"
local dispelsContainer = actor.dispell_spells and actor.dispell_spells._ActorTable
local totalSpellIndexes = 0
if (dispelsContainer) then
--reserve an index to tell the length of spells
actorUtilityInfo [#actorUtilityInfo + 1] = 0
local reservedSpellSizeIndex = #actorUtilityInfo
for spellId, spellInfo in pairs(dispelsContainer) do
local spellTotal = spellInfo.dispell
local spellTargets = spellInfo.targets
local whatGotDispelled = spellInfo.dispell_oque
actorUtilityInfo [#actorUtilityInfo + 1] = floor(spellId)
actorUtilityInfo [#actorUtilityInfo + 1] = floor(spellTotal)
totalSpellIndexes = totalSpellIndexes + 2
--build targets
local targetsSize = Details.packFunctions.CountTableEntriesValid(spellTargets) * 2
actorUtilityInfo [#actorUtilityInfo + 1] = targetsSize
totalSpellIndexes = totalSpellIndexes + 1
for actorName, totalDone in pairs(spellTargets) do
actorUtilityInfo [#actorUtilityInfo + 1] = actorName
actorUtilityInfo [#actorUtilityInfo + 1] = floor(totalDone)
totalSpellIndexes = totalSpellIndexes + 2
end
--build what was dispelled by the spell
local dispelsSize = Details.packFunctions.CountTableEntriesValid(whatGotDispelled) * 2
actorUtilityInfo [#actorUtilityInfo + 1] = dispelsSize
totalSpellIndexes = totalSpellIndexes + 1
for spellId, totalDone in pairs(whatGotDispelled) do
actorUtilityInfo [#actorUtilityInfo + 1] = spellId
actorUtilityInfo [#actorUtilityInfo + 1] = floor(totalDone)
totalSpellIndexes = totalSpellIndexes + 2
end
end
--amount of indexes spells are using
actorUtilityInfo[reservedSpellSizeIndex] = totalSpellIndexes
else
actorUtilityInfo [#actorUtilityInfo + 1] = 0
end
--ress, pack player ress performed
actorUtilityInfo [#actorUtilityInfo + 1] = "R"
local ressContainer = actor.ress_spells and actor.ress_spells._ActorTable
local totalSpellIndexes = 0
if (ressContainer) then
--reserve an index to tell the length of spells
actorUtilityInfo [#actorUtilityInfo + 1] = 0
local reservedSpellSizeIndex = #actorUtilityInfo
for spellId, spellInfo in pairs(ressContainer) do
local spellTotal = spellInfo.ress
local spellTargets = spellInfo.targets
actorUtilityInfo [#actorUtilityInfo + 1] = floor(spellId)
actorUtilityInfo [#actorUtilityInfo + 1] = floor(spellTotal)
totalSpellIndexes = totalSpellIndexes + 2
--build targets
local targetsSize = Details.packFunctions.CountTableEntriesValid(spellTargets) * 2
actorUtilityInfo [#actorUtilityInfo + 1] = targetsSize
totalSpellIndexes = totalSpellIndexes + 1
for actorName, totalDone in pairs(spellTargets) do
actorUtilityInfo [#actorUtilityInfo + 1] = actorName
actorUtilityInfo [#actorUtilityInfo + 1] = floor(totalDone)
totalSpellIndexes = totalSpellIndexes + 2
end
end
--amount of indexes spells are using
actorUtilityInfo[reservedSpellSizeIndex] = totalSpellIndexes
else
actorUtilityInfo [#actorUtilityInfo + 1] = 0
end
end
if (isDebugging) then
print("PackUtility(): done.")
end
end
function Details.packFunctions.UnPackUtility(currentCombat, combatData, tablePosition)
if (isDebugging) then
print("UnPackUtility(): start.")
end
--get the utility container
local utilityContainer = currentCombat[DETAILS_ATTRIBUTE_MISC]
--loop from 1 to 199, the amount of actors store is unknown
--todo: it's only unpacking the first actor from the table, e.g. theres izimode and eye of corruption, after export it only shows the eye of corruption
--table position does not move forward
for i = 1, 199 do
--actor information index in the combatData table
--this index gives the position where the actor name, class, spec are stored
local actorReference = tonumber(combatData[tablePosition]) --[1]
local actorName, actorFlag, serialNumber, class, spec = Details.packFunctions.RetriveActorInformation(combatData, actorReference)
if (isDebugging) then
print("UnPackUtility(): Retrivied Data From " .. (actorReference or "nil") .. ":", actorName, actorFlag, serialNumber, class, spec)
end
--check if all utility actors has been processed
--if there's no actor name it means it reached the end
if (not actorName) then
if (isDebugging) then
print("UnPackUtiliyu(): break | Utility loop has been stopped", "index:", i, "tablePosition:", tablePosition, "value:", combatData[tablePosition])
end
break
end
--get or create the actor object
local actorObject = utilityContainer:GetOrCreateActor(serialNumber, actorName, actorFlag, true)
--set the actor class, spec and group
actorObject.classe = class
actorObject:SetSpecId(spec)
actorObject.grupo = isActorInGroup(class, actorFlag)
actorObject.flag_original = actorFlag
--finished utility actor setup
--C - cooldowns
--I - interrupts
--B - cc break
--D - dispels
--R - ress
--copy back the actor cooldowns spells
tablePosition = tablePosition + 1
tablePosition = tablePosition + 1
--amount of indexes used to store cooldowns spells for this actor
local spellsSize = tonumber(combatData[tablePosition]) --[7]
if (isDebugging) then
print("cooldowns size unpack:", spellsSize)
end
tablePosition = tablePosition + 1
--check if there's cooldown data
if (spellsSize > 0) then
local newTotal = 0
local newTargetsTable = {}
local spellIndex = tablePosition
while(spellIndex < tablePosition + spellsSize) do
local spellId = tonumber(combatData[spellIndex]) --[1]
local spellTotal = tonumber(combatData[spellIndex+1]) --[2]
local targetsSize = tonumber(combatData[spellIndex+2]) --[3]
local targetTable = Details.packFunctions.UnpackTable(combatData, spellIndex+2, true)
if (not actorObject.cooldowns_defensive_spells) then
actorObject.cooldowns_defensive_spells = Details.container_habilidades:NovoContainer(Details.container_type.CONTAINER_MISC_CLASS)
end
local spellObject = actorObject.cooldowns_defensive_spells:GetOrCreateSpell(spellId, true)
spellObject.counter = spellTotal
spellObject.targets = targetTable
for targetName, amount in pairs(spellObject.targets) do
newTargetsTable[targetName] = (newTargetsTable[targetName] or 0) + amount
newTotal = newTotal + amount
end
spellIndex = spellIndex + targetsSize + 3
end
actorObject.cooldowns_defensive = newTotal
actorObject.cooldowns_defensive_targets = newTargetsTable
tablePosition = tablePosition + spellsSize --increase table position
end
--copy back the actor interrupts spells
--tablePosition = tablePosition + 1
local startInterrupt = combatData[tablePosition]
tablePosition = tablePosition + 1
--amount of indexes used to store interrupt spells for this actor
local spellsSize = tonumber(combatData[tablePosition]) --[7]
if (isDebugging) then
print("interrupt size unpack:", spellsSize)
end
tablePosition = tablePosition + 1
if (spellsSize > 0) then
local newTotal = 0
local newTargetsTable = {}
local newTargetWhatTable = {}
local spellIndex = tablePosition
while(spellIndex < tablePosition + spellsSize) do
local spellId = tonumber(combatData[spellIndex]) --[1]
local spellTotal = tonumber(combatData[spellIndex+1]) --[2]
local targetsSize = tonumber(combatData[spellIndex+2]) --[3]
local targetTable = Details.packFunctions.UnpackTable(combatData, spellIndex+2, true)
if (not actorObject.interrupt_spells) then
actorObject.interrupt_spells = Details.container_habilidades:NovoContainer(Details.container_type.CONTAINER_MISC_CLASS)
end
local spellObject = actorObject.interrupt_spells:GetOrCreateSpell(spellId, true)
spellObject.counter = spellTotal
spellObject.targets = targetTable
for targetName, amount in pairs(spellObject.targets) do
newTargetsTable[targetName] = (newTargetsTable[targetName] or 0) + amount
newTotal = newTotal + amount
end
--interrupt what
spellIndex = spellIndex + targetsSize + 3
local interruptWhatTableSize = combatData[spellIndex]
local interruptWhatTable = Details.packFunctions.UnpackTable(combatData, spellIndex, true) --table[index] is nil
spellObject.interrompeu_oque = interruptWhatTable
for targetName, amount in pairs(spellObject.targets) do
newTargetWhatTable[targetName] = (newTargetWhatTable[targetName] or 0) + amount
end
spellIndex = spellIndex + interruptWhatTableSize + 1
end
actorObject.interrupt = newTotal
actorObject.interrupt_targets = newTargetsTable
actorObject.interrompeu_oque = newTargetWhatTable
tablePosition = tablePosition + spellsSize --increase table position
end
--copy back the actor cc break spells
--tablePosition = tablePosition + 1
local startCCBreak = combatData[tablePosition]
tablePosition = tablePosition + 1
--amount of indexes used to store cc break spells for this actor
local spellsSize = tonumber(combatData[tablePosition]) --[7]
if (isDebugging) then
print("cc break size unpack:", spellsSize)
end
tablePosition = tablePosition + 1
if (spellsSize > 0) then
local newTotal = 0
local newTargetsTable = {}
local newTargetWhatTable = {}
local spellIndex = tablePosition
while(spellIndex < tablePosition + spellsSize) do
local spellId = tonumber(combatData[spellIndex]) --[1]
local spellTotal = tonumber(combatData[spellIndex+1]) --[2]
local targetsSize = tonumber(combatData[spellIndex+2]) --[3]
local targetTable = Details.packFunctions.UnpackTable(combatData, spellIndex+2, true)
if (not actorObject.cc_break_spells) then
actorObject.cc_break_spells = Details.container_habilidades:NovoContainer(Details.container_type.CONTAINER_MISC_CLASS)
end
local spellObject = actorObject.cc_break_spells:GetOrCreateSpell(spellId, true)
spellObject.cc_break = spellTotal
spellObject.targets = targetTable
for targetName, amount in pairs(spellObject.targets) do
newTargetsTable[targetName] = (newTargetsTable[targetName] or 0) + amount
newTotal = newTotal + amount
end
--cc broke what
spellIndex = spellIndex + targetsSize + 3
local ccBrokeWhatTableSize = combatData[spellIndex]
local ccBrokeWhatTable = Details.packFunctions.UnpackTable(combatData, spellIndex, true)
spellObject.cc_break_oque = ccBrokeWhatTable
for targetName, amount in pairs(spellObject.cc_break_oque) do
newTargetWhatTable[targetName] = (newTargetWhatTable[targetName] or 0) + amount
end
spellIndex = spellIndex + ccBrokeWhatTableSize + 1
end
actorObject.cc_break = newTotal
actorObject.cc_break_targets = newTargetsTable
actorObject.cc_break_oque = newTargetWhatTable
tablePosition = tablePosition + spellsSize --increase table position
end
--copy back the actor dispel spells
--tablePosition = tablePosition + 1
tablePosition = tablePosition + 1
--amount of indexes used to store dispel spells for this actor
local spellsSize = tonumber(combatData[tablePosition]) --[7]
if (isDebugging) then
print("dispel size unpack:", spellsSize)
end
tablePosition = tablePosition + 1
if (spellsSize > 0) then
local newTotal = 0
local newTargetsTable = {}
local newTargetWhatTable = {}
local spellIndex = tablePosition
while(spellIndex < tablePosition + spellsSize) do
local spellId = tonumber(combatData[spellIndex]) --[1]
local spellTotal = tonumber(combatData[spellIndex+1]) --[2]
local targetsSize = tonumber(combatData[spellIndex+2]) --[3]
local targetTable = Details.packFunctions.UnpackTable(combatData, spellIndex+2, true)
if (not actorObject.dispell_spells) then
actorObject.dispell_spells = Details.container_habilidades:NovoContainer(Details.container_type.CONTAINER_MISC_CLASS)
end
local spellObject = actorObject.dispell_spells:GetOrCreateSpell(spellId, true)
spellObject.dispell = spellTotal
spellObject.targets = targetTable
for targetName, amount in pairs(spellObject.targets) do
newTargetsTable[targetName] = (newTargetsTable[targetName] or 0) + amount
newTotal = newTotal + amount
end
spellIndex = spellIndex + targetsSize + 3
--dispel what
local dispelWhatTableSize = combatData[spellIndex]
local dispelWhatTable = Details.packFunctions.UnpackTable(combatData, spellIndex, true)
spellObject.dispell_oque = dispelWhatTable
for spellId, amount in pairs(spellObject.dispell_oque) do
newTargetWhatTable[spellId] = (newTargetWhatTable[spellId] or 0) + amount
end
spellIndex = spellIndex + dispelWhatTableSize + 1
end
actorObject.dispell = newTotal
actorObject.dispell_targets = newTargetsTable
actorObject.dispell_oque = newTargetWhatTable
tablePosition = tablePosition + spellsSize --increase table position
end
--ress
--ress_targets
--ress_spells
--copy back the actor ress spells
--tablePosition = tablePosition + 1
tablePosition = tablePosition + 1
--amount of indexes used to store ress spells for this actor
local spellsSize = tonumber(combatData[tablePosition]) --[7]
if (isDebugging) then
print("ress size unpack:", spellsSize)
end
tablePosition = tablePosition + 1
if (spellsSize > 0) then
local newTotal = 0
local newTargetsTable = {}
local spellIndex = tablePosition
while(spellIndex < tablePosition + spellsSize) do
local spellId = tonumber(combatData[spellIndex]) --[1]
local spellTotal = tonumber(combatData[spellIndex+1]) --[2]
local targetsSize = tonumber(combatData[spellIndex+2]) --[3]
local targetTable = Details.packFunctions.UnpackTable(combatData, spellIndex+2, true)
if (not actorObject.ress_spells) then
actorObject.ress_spells = Details.container_habilidades:NovoContainer(Details.container_type.CONTAINER_MISC_CLASS)
end
local spellObject = actorObject.ress_spells:GetOrCreateSpell(spellId, true)
spellObject.ress = spellTotal
spellObject.targets = targetTable
for targetName, amount in pairs(spellObject.targets) do
newTargetsTable[targetName] = (newTargetsTable[targetName] or 0) + amount
newTotal = newTotal + amount
end
spellIndex = spellIndex + targetsSize + 3
end
actorObject.ress = newTotal
actorObject.ress_targets = newTargetsTable
tablePosition = tablePosition + spellsSize --increase table position
end
end
if (isDebugging) then
print("UnPackUtility(): done.")
end
return tablePosition
end
--this function does the same as the function above but does not create a new combat, it just add new information
function Details.packFunctions.DeployPackedCombatData(packedCombatData)
if (isDebugging) then
print("DeployPackedCombatData(): start.")
end
local LibDeflate = _G.LibStub:GetLibrary("LibDeflate")
local dataCompressed = LibDeflate:DecodeForWoWAddonChannel(packedCombatData)
local combatDataString = LibDeflate:DecompressDeflate(dataCompressed)
if (isDebugging) then
print(combatDataString)
end
local function count(text, pattern)
return select(2, text:gsub(pattern, ""))
end
local combatData = {}
local amountOfIndexes = count(combatDataString, ",") + 1
while (amountOfIndexes > 0) do
local splitPart = {strsplit(",", combatDataString, 4000)}
if (#splitPart == 4000 and amountOfIndexes > 4000) then
for i = 1, 3999 do
combatData[#combatData+1] = splitPart[i]
end
--get get part that couldn't be read this loop
combatDataString = splitPart[4000]
amountOfIndexes = amountOfIndexes - 3999
else
for i = 1, #splitPart do
combatData[#combatData+1] = splitPart[i]
end
amountOfIndexes = amountOfIndexes - #splitPart
end
end
local flags = tonumber(combatData[INDEX_EXPORT_FLAG])
local tablePosition
if (bit.band(flags, 0x10) ~= 0) then
tablePosition = 2
TOTAL_INDEXES_FOR_COMBAT_INFORMATION = 0 --there's no combat info, data starts after the dataFlag on position [1]
else
tablePosition = TOTAL_INDEXES_FOR_COMBAT_INFORMATION + 1
end
--get the current combat
local currentCombat = Details:GetCurrentCombat()
--check if this export has included damage info
if (bit.band(flags, 0x1) ~= 0) then
--find the index where the damage information start
for i = tablePosition, #combatData do
if (combatData[i] == "!D") then
tablePosition = i + 1
break
end
end
if (isDebugging) then
print("DeployPackedCombatData(): data has damage info, Damage Index:", tablePosition)
end
--unpack damage
tablePosition = Details.packFunctions.UnPackDamage(currentCombat, combatData, tablePosition)
end
if (bit.band(flags, 0x2) ~= 0) then
--find the index where the heal information start
for i = tablePosition, #combatData do
if (combatData[i] == "!H") then
tablePosition = i + 1
break
end
end
if (isDebugging) then
print("DeployPackedCombatData(): data has healing info, Heal Index:", tablePosition)
end
--unpack heal
Details.packFunctions.UnPackHeal(currentCombat, combatData, tablePosition)
end
if (bit.band(flags, 0x8) ~= 0) then
--find the index where the utility information start
for i = tablePosition, #combatData do
if (combatData[i] == "!U") then
tablePosition = i + 1
break
end
end
if (isDebugging) then
print("DeployPackedCombatData(): data has utility info, Utility Index:", tablePosition)
end
--unpack utility
Details.packFunctions.UnPackUtility(currentCombat, combatData, tablePosition)
end
if (bit.band(flags, 0x10) == 0) then
--set the start and end of combat time and date
currentCombat:SetStartTime(combatData[INDEX_COMBAT_START_TIME])
currentCombat:SetEndTime(combatData[INDEX_COMBAT_END_TIME])
currentCombat:SetDate(combatData[INDEX_COMBAT_START_DATE], combatData[INDEX_COMBAT_END_DATE])
currentCombat.enemy = combatData[INDEX_COMBAT_NAME]
end
--refresh container
currentCombat[DETAILS_ATTRIBUTE_DAMAGE]:Remap()
currentCombat[DETAILS_ATTRIBUTE_HEAL]:Remap()
--refresh damage taken
do
local damageContainer = currentCombat[DETAILS_ATTRIBUTE_DAMAGE]
local allActors = damageContainer._ActorTable
for i = 1, #allActors do --reset damage taken table
local actor = allActors[i]
actor.damage_taken = 0
actor.damage_from = {}
end
for i = 1, #allActors do
local actor = allActors[i]
for targetName, amount in pairs(actor.targets) do
local actorIndex = damageContainer._NameIndexTable[targetName]
if (actorIndex) then
local targetActor = allActors[actorIndex]
if (targetActor) then
targetActor.damage_taken = targetActor.damage_taken + amount
targetActor.damage_from[actor.nome] = (targetActor.damage_from[actor.nome] or 0) + amount
end
end
end
end
end
--refresh healing taken
do
local healingContainer = currentCombat[DETAILS_ATTRIBUTE_HEAL]
local allActors = healingContainer._ActorTable
for i = 1, #allActors do --reset healing taken table
local actor = allActors[i]
actor.healing_taken = 0
actor.healing_from = {}
end
for i = 1, #allActors do
local actor = allActors[i]
for targetName, amount in pairs(actor.targets) do
local actorIndex = healingContainer._NameIndexTable[targetName]
if (actorIndex) then
local targetActor = allActors[actorIndex]
if (targetActor) then
targetActor.healing_taken = targetActor.healing_taken + amount
targetActor.healing_from[actor.nome] = (targetActor.healing_from[actor.nome] or 0) + amount
end
end
end
end
end
--refresh windows
currentCombat[DETAILS_ATTRIBUTE_DAMAGE].need_refresh = true
currentCombat[DETAILS_ATTRIBUTE_HEAL].need_refresh = true
end
--get the amount of entries of a hash table
function Details.packFunctions.CountTableEntries(hasTable)
local amount = 0
for _ in pairs(hasTable) do
amount = amount + 1
end
return amount
end
--get the amount of entries and check for validation
function Details.packFunctions.CountTableEntriesValid(hasTable)
local amount = 0
for actorName, _ in pairs(hasTable) do
--if (actorInformationIndexes[actorName]) then
amount = amount + 1
--end
end
return amount
end
--stract some indexes of a table
local selectIndexes = function(table, startIndex, amountIndexes)
local values = {}
for i = startIndex, amountIndexes do
values[#values+1] = tonumber(table[i]) or 0
end
return unpack(values)
end
function Details.packFunctions.UnpackTable(table, index, isPair, valueAsTable, amountOfValues)
local result = {}
local reservedIndexes = tonumber(table[index])
local indexStart = index+1
local indexEnd = reservedIndexes+index
if (isPair) then
amountOfValues = amountOfValues or 2
for i = indexStart, indexStart + reservedIndexes - 1, amountOfValues do
if (valueAsTable) then
local key = tonumber(table[i])
result[key] = {selectIndexes(table, i+1, amountOfValues-1)}
else
local key = table[i]
local value = tonumber(table[i+1])
result[key] = value
end
end
else
for i = indexStart, indexEnd do
local value = tonumber(table[i])
result[#result+1] = value
end
end
return result
end