You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1907 lines
73 KiB

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 = _G.tinsert
local IsInRaid = _G.IsInRaid
local GetNumGroupMembers = _G.GetNumGroupMembers
local GetRaidRosterInfo = _G.GetRaidRosterInfo
local unpack = _G.unpack
local IsInGroup = _G.IsInGroup
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
table.wipe(actorInformation)
table.wipe(actorInformationIndexes)
table.wipe(actorDamageInfo)
table.wipe(actorHealInfo)
table.wipe(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
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:match("^C") == "C") then
local npcId = tonumber(select(6, strsplit("-", serial)) or 0)
return "C" .. npcId
elseif (serial:match("^P") == "P") then
return "P"
elseif (serial == "") then
return "C12345"
end
end
local unpackActorSerial = function(serialNumber)
--player serial
if (serialNumber:match("^P")) then
return "Player-1-" .. Details.packFunctions.GenerateSerialNumber()
elseif (serialNumber:match("^C")) then
return "Creature-0-0-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 = UnitName("player")
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 = select(7, strsplit("-", actor.serial))
if (spawnId) then
--convert hex to number
spawnId = tonumber(spawnId:sub(1, 10), 16)
if (spawnId) then
--first index is the actorObject, the second index is the spawnId to sort enemies
tinsert(allEnemies, {actor, spawnId})
end
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 = UnitName("player")
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 = select(7, strsplit("-", actor.serial))
if (spawnId) then
--convert hex to number
spawnId = tonumber(spawnId:sub(1, 10), 16)
if (spawnId) then
--first index is the actorObject, the second index is the spawnId to sort enemies
tinsert(allEnemies, {actor, spawnId})
end
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 = UnitName("player")
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 = select(7, strsplit("-", actor.serial))
if (spawnId) then
--convert hex to number
spawnId = tonumber(spawnId:sub(1, 10), 16)
if (spawnId) then
--first index is the actorObject, the second index is the spawnId to sort enemies
tinsert(allEnemies, {actor, spawnId})
end
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