--[=[
This file has the functions to get player information
Dumping them here , make the code of the main file smaller
--]=]
if ( not LIB_OPEN_RAID_CAN_LOAD ) then
return
end
local openRaidLib = LibStub : GetLibrary ( " LibOpenRaid-1.0 " )
local CONST_TALENT_VERSION_CLASSIC = 1
local CONST_TALENT_VERSION_LEGION = 4
local CONST_TALENT_VERSION_DRAGONFLIGHT = 5
local CONST_BTALENT_VERSION_COVENANTS = 9
local CONST_SPELLBOOK_CLASSSPELLS_TABID = 2
local CONST_SPELLBOOK_GENERAL_TABID = 1
local CONST_ISITEM_BY_TYPEID = {
[ 10 ] = true , --healing items
[ 11 ] = true , --attack items
[ 12 ] = true , --utility items
}
local GetInventoryItemLink = GetInventoryItemLink
-- TWW compat
-- TODO: Remove when TWW is released
local GetItemStats = C_Item.GetItemStats
local GetSpellInfo = GetSpellInfo or function ( spellID )
if not spellID then return nil end
local spellInfo = C_Spell.GetSpellInfo ( spellID )
if spellInfo then
return spellInfo.name , nil , spellInfo.iconID , spellInfo.castTime , spellInfo.minRange ,
spellInfo.maxRange , spellInfo.spellID , spellInfo.originalIconID
end
end
local GetSpellCooldown = GetSpellCooldown or C_Spell.GetSpellCooldown
local GetDetailedItemLevelInfo = GetDetailedItemLevelInfo or C_Item.GetDetailedItemLevelInfo
local GetSpellTabInfo = GetSpellTabInfo or ( function ( tabLine )
if not tabLine then return nil end
local skillLine = C_SpellBook.GetSpellBookSkillLineInfo ( tabLine )
if skillLine then
return skillLine.name , skillLine.iconID , skillLine.itemIndexOffset ,
skillLine.numSpellBookItems , skillLine.isGuild , skillLine.specID
end
end )
local GetSpellBookItemInfo = GetSpellBookItemInfo or C_SpellBook.GetSpellBookItemType
local IsPassiveSpell = IsPassiveSpell or C_SpellBook.IsSpellBookItemPassive
local GetNumSpellTabs = GetNumSpellTabs or C_SpellBook.GetNumSpellBookSkillLines
local spellBookPlayerEnum = Enum.SpellBookSpellBank and Enum.SpellBookSpellBank . Player or " player "
local HasPetSpells = HasPetSpells or C_SpellBook.HasPetSpells
local GetOverrideSpell = C_SpellBook.GetOverrideSpell or C_Spell.GetOverrideSpell
local GetSpellBookItemName = GetSpellBookItemName or C_SpellBook.GetSpellBookItemName
local spellBookPetEnum = Enum.SpellBookSpellBank and Enum.SpellBookSpellBank . Pet or " pet "
local GetSpellCharges = GetSpellCharges or function ( spellId )
local chargesInfo = C_Spell.GetSpellCharges ( spellId )
if ( chargesInfo ) then
return chargesInfo.currentCharges , chargesInfo.maxCharges , chargesInfo.cooldownStartTime , chargesInfo.cooldownDuration , chargesInfo.chargeModRate
end
end
local _ , _ , _ , buildInfo = GetBuildInfo ( )
local isTimewalkWoW = function ( )
if ( buildInfo < 40000 ) then
return true
end
end
local IsTWWExpansion = function ( )
if ( buildInfo >= 110000 ) then
return true
end
end
local IsDragonflight = function ( ) --and beyond
return buildInfo >= 100000
end
local IsShadowlands = function ( )
local versionString , revision , launchDate , gameVersion = GetBuildInfo ( )
if ( gameVersion >= 90000 and gameVersion < 100000 ) then
return true
end
end
--information about the player character to send, each expansion has its own system and data can be different
--it's always a number
function openRaidLib . UnitInfoManager . GetPlayerInfo1 ( )
if ( IsShadowlands ( ) ) then
--return the renown level within the player covenant
local renown = C_CovenantSanctumUI.GetRenownLevel ( ) or 1
return renown
end
return 0
end
--information about the player character to send, each expansion has its own system and data can be different
--it's always a number
function openRaidLib . UnitInfoManager . GetPlayerInfo2 ( )
if ( IsShadowlands ( ) ) then
--return which covenant the player picked
local covenant = C_Covenants.GetActiveCovenantID ( ) or 0
return covenant
end
return 0
end
--default player class-spec talent system
function openRaidLib . GetTalentVersion ( )
local _ , _ , _ , buildInfo = GetBuildInfo ( )
if ( buildInfo >= 1 and buildInfo <= 40000 ) then --vanilla tbc wotlk cataclysm
return CONST_TALENT_VERSION_CLASSIC
end
if ( buildInfo >= 70000 and buildInfo <= 100000 ) then --legion bfa shadowlands
return CONST_TALENT_VERSION_LEGION
end
if ( buildInfo >= 100000 and buildInfo <= 200000 ) then --dragonflight
return CONST_TALENT_VERSION_DRAGONFLIGHT
end
end
--secondary talent tree, can be a legendary weapon talent tree, covenant talent tree, etc...
function openRaidLib . GetBorrowedTalentVersion ( )
if ( IsShadowlands ( ) ) then
return CONST_BTALENT_VERSION_COVENANTS
end
end
local getDragonflightTalentsExportedString = function ( )
local exportStream = ExportUtil.MakeExportDataStream ( )
local configId = C_ClassTalents.GetActiveConfigID ( )
if ( configId ) then
local configInfo = C_Traits.GetConfigInfo ( configId )
local currentSpecID = PlayerUtil.GetCurrentSpecID ( )
local treeInfo = C_Traits.GetTreeInfo ( configId , configInfo.treeIDs [ 1 ] )
local treeHash = C_Traits.GetTreeHash ( treeInfo.ID )
local serializationVersion = C_Traits.GetLoadoutSerializationVersion ( )
end
end
local getDragonflightTalentsAsIndexTable = function ( )
local allTalents = { }
local configId = C_ClassTalents.GetActiveConfigID ( )
if ( not configId ) then
return allTalents
end
local configInfo = C_Traits.GetConfigInfo ( configId )
for treeIndex , treeId in ipairs ( configInfo.treeIDs ) do
local treeNodes = C_Traits.GetTreeNodes ( treeId )
for nodeIdIndex , treeNodeID in ipairs ( treeNodes ) do
local traitNodeInfo = C_Traits.GetNodeInfo ( configId , treeNodeID )
if ( traitNodeInfo ) then
local activeEntry = traitNodeInfo.activeEntry
if ( activeEntry ) then
local entryId = activeEntry.entryID
local rank = activeEntry.rank
if ( rank > 0 ) then
--get the entry info
local traitEntryInfo = C_Traits.GetEntryInfo ( configId , entryId )
local definitionId = traitEntryInfo.definitionID
--definition info
if ( definitionId ) then
local traitDefinitionInfo = C_Traits.GetDefinitionInfo ( definitionId )
local spellId = traitDefinitionInfo.overriddenSpellID or traitDefinitionInfo.spellID
local spellName , _ , spellTexture = GetSpellInfo ( spellId )
if ( spellName ) then
allTalents [ # allTalents + 1 ] = spellId
end
end
end
end
end
end
end
return allTalents
end
--creates two tables, one with indexed talents and another with pairs values ([talentId] = true)
function openRaidLib . UnitInfoManager . GetPlayerTalentsAsPairsTable ( )
local talentsPairs = { }
local talentVersion = openRaidLib.GetTalentVersion ( )
if ( talentVersion == CONST_TALENT_VERSION_DRAGONFLIGHT ) then
local allTalents = getDragonflightTalentsAsIndexTable ( )
for i = 1 , # allTalents do
local spellId = allTalents [ i ]
talentsPairs [ spellId ] = true
end
elseif ( talentVersion == CONST_TALENT_VERSION_LEGION ) then
for i = 1 , 7 do
for o = 1 , 3 do
local talentId , _ , _ , selected = GetTalentInfo ( i , o , 1 )
if ( selected ) then
talentsPairs [ talentId ] = true
break
end
end
end
end
return talentsPairs
end
function openRaidLib . UnitInfoManager . GetPlayerTalents ( )
local talents = { }
local talentVersion = openRaidLib.GetTalentVersion ( )
if ( talentVersion == CONST_TALENT_VERSION_DRAGONFLIGHT ) then
talents = getDragonflightTalentsAsIndexTable ( )
elseif ( talentVersion == CONST_TALENT_VERSION_LEGION ) then
talents = { 0 , 0 , 0 , 0 , 0 , 0 , 0 }
for talentTier = 1 , 7 do
for talentColumn = 1 , 3 do
local talentId , name , texture , selected , available = GetTalentInfo ( talentTier , talentColumn , 1 )
if ( selected ) then
talents [ talentTier ] = talentId
break
end
end
end
end
return talents
end
function openRaidLib . UnitInfoManager . GetPlayerPvPTalents ( )
if ( IsDragonflight ( ) ) then
return { }
end
local talentsPvP = { 0 , 0 , 0 }
local talentList = C_SpecializationInfo.GetAllSelectedPvpTalentIDs ( )
for talentIndex , talentId in ipairs ( talentList ) do
local doesExists = GetPvpTalentInfoByID ( talentId )
if ( doesExists ) then
talentsPvP [ talentIndex ] = talentId
end
end
return talentsPvP
end
--return the current specId of the player
function openRaidLib . GetPlayerSpecId ( )
if ( isTimewalkWoW ( ) ) then
return 0
end
local spec = GetSpecialization ( )
if ( spec ) then
local specId = GetSpecializationInfo ( spec )
if ( specId and specId > 0 ) then
return specId
end
end
end
--borrowed talent tree from shadowlands
function openRaidLib . UnitInfoManager . GetPlayerConduits ( )
local conduits = { }
local soulbindID = C_Soulbinds.GetActiveSoulbindID ( )
if ( soulbindID ~= 0 ) then
local soulbindData = C_Soulbinds.GetSoulbindData ( soulbindID )
if ( soulbindData ~= 0 ) then
local tree = soulbindData.tree
local nodes = tree.nodes
table.sort ( nodes , function ( t1 , t2 ) return t1.row < t2.row end )
local C_Soulbinds_GetConduitCollectionData = C_Soulbinds.GetConduitCollectionData
for nodeId , nodeInfo in ipairs ( nodes ) do
--check if the node is a conduit placed by the player
if ( nodeInfo.state == Enum.SoulbindNodeState . Selected ) then
local conduitId = nodeInfo.conduitID
local conduitRank = nodeInfo.conduitRank
if ( conduitId and conduitRank ) then
--have spell id when it's a default conduit from the game
local spellId = nodeInfo.spellID
--have conduit id when is a conduid placed by the player
local conduitId = nodeInfo.conduitID
if ( spellId == 0 ) then
--is player conduit
spellId = C_Soulbinds.GetConduitSpellID ( nodeInfo.conduitID , nodeInfo.conduitRank )
conduits [ # conduits + 1 ] = spellId
local collectionData = C_Soulbinds_GetConduitCollectionData ( conduitId )
conduits [ # conduits + 1 ] = collectionData and collectionData.conduitItemLevel or 0
else
--is default conduit
conduits [ # conduits + 1 ] = spellId
conduits [ # conduits + 1 ] = 0
end
end
end
end
end
end
return conduits
end
function openRaidLib . UnitInfoManager . GetPlayerBorrowedTalents ( )
local borrowedTalentVersion = openRaidLib.GetBorrowedTalentVersion ( )
if ( borrowedTalentVersion == CONST_BTALENT_VERSION_COVENANTS ) then
return openRaidLib.UnitInfoManager . GetPlayerConduits ( )
end
return { }
end
function openRaidLib . GearManager . GetPlayerItemLevel ( )
if ( _G.GetAverageItemLevel ) then
local _ , itemLevel = GetAverageItemLevel ( )
itemLevel = floor ( itemLevel )
return itemLevel
else
return 0
end
end
--return an integer between zero and one hundret indicating the player gear durability
function openRaidLib . GearManager . GetPlayerGearDurability ( )
local durabilityTotalPercent , totalItems = 0 , 0
--hold the lowest item durability of all the player gear
--this prevent the case where the player has an average of 80% durability but an item with 15% durability
local lowestGearDurability = 100
for i = INVSLOT_FIRST_EQUIPPED , INVSLOT_LAST_EQUIPPED do
local durability , maxDurability = GetInventoryItemDurability ( i )
if ( durability and maxDurability ) then
local itemDurability = durability / maxDurability * 100
if ( itemDurability < lowestGearDurability ) then
lowestGearDurability = itemDurability
end
durabilityTotalPercent = durabilityTotalPercent + itemDurability
totalItems = totalItems + 1
end
end
if ( totalItems == 0 ) then
return 100 , lowestGearDurability
end
return floor ( durabilityTotalPercent / totalItems ) , lowestGearDurability
end
function openRaidLib . GearManager . GetPlayerWeaponEnchant ( )
local weaponEnchant = 0
local _ , _ , _ , mainHandEnchantId , _ , _ , _ , offHandEnchantId = GetWeaponEnchantInfo ( )
if ( LIB_OPEN_RAID_WEAPON_ENCHANT_IDS [ mainHandEnchantId ] ) then
weaponEnchant = 1
elseif ( LIB_OPEN_RAID_WEAPON_ENCHANT_IDS [ offHandEnchantId ] ) then
weaponEnchant = 1
end
return weaponEnchant , mainHandEnchantId or 0 , offHandEnchantId or 0
end
function openRaidLib . GearManager . GetPlayerGemsAndEnchantInfo ( )
--hold equipmentSlotId of equipment with a gem socket but it's empty
local slotsWithoutGems = { }
--hold equipmentSlotId of equipments without an enchant
local slotsWithoutEnchant = { }
local gearWithEnchantIds = { }
for equipmentSlotId = 1 , 17 do
local itemLink = GetInventoryItemLink ( " player " , equipmentSlotId )
if ( itemLink ) then
--get the information from the item
local _ , itemId , enchantId , gemId1 , gemId2 , gemId3 , gemId4 , suffixId , uniqueId , levelOfTheItem , specId , upgradeInfo , instanceDifficultyId , numBonusIds , restLink = strsplit ( " : " , itemLink )
local gemsIds = { gemId1 , gemId2 , gemId3 , gemId4 }
--enchant
--check if the slot can receive enchat and if the equipment has an enchant
local enchantAttribute = LIB_OPEN_RAID_ENCHANT_SLOTS [ equipmentSlotId ]
local nEnchantId = 0
if ( enchantAttribute ) then --this slot can receive an enchant
if ( enchantId and enchantId ~= " " ) then
local number = tonumber ( enchantId )
nEnchantId = number
gearWithEnchantIds [ # gearWithEnchantIds + 1 ] = nEnchantId
else
gearWithEnchantIds [ # gearWithEnchantIds + 1 ] = 0
end
--6400 and above is dragonflight enchantId number space
if ( nEnchantId < 6300 and not LIB_OPEN_RAID_DEATHKNIGHT_RUNEFORGING_ENCHANT_IDS [ nEnchantId ] ) then
slotsWithoutEnchant [ # slotsWithoutEnchant + 1 ] = equipmentSlotId
end
end
--gems
--local itemStatsTable = {}
--fill the table above with information about the item
--GetItemStats(itemLink, itemStatsTable) --deprecated in 10.2.5
local itemStatsTable = GetItemStats ( itemLink )
--check if the item has a socket
if ( itemStatsTable ) then
if ( itemStatsTable.EMPTY_SOCKET_PRISMATIC ) then
--check if the socket is empty
for i = 1 , itemStatsTable.EMPTY_SOCKET_PRISMATIC do
local gemId = tonumber ( gemsIds [ i ] )
if ( not gemId or gemId == 0 ) then
slotsWithoutGems [ # slotsWithoutGems + 1 ] = equipmentSlotId
--check if the gem is not a valid gem (deprecated gem)
elseif ( gemId < 180000 ) then
slotsWithoutGems [ # slotsWithoutGems + 1 ] = equipmentSlotId
end
end
end
end
end
end
return slotsWithoutGems , slotsWithoutEnchant
end
function openRaidLib . GearManager . BuildPlayerEquipmentList ( )
local equipmentList = { }
local debug
for equipmentSlotId = 1 , 17 do
local itemLink = GetInventoryItemLink ( " player " , equipmentSlotId )
if ( itemLink ) then
--local itemStatsTable = {}
local itemID , enchantID , gemID1 , gemID2 , gemID3 , gemID4 , suffixID , uniqueID , linkLevel , specializationID , modifiersMask , itemContext = select ( 2 , strsplit ( " : " , itemLink ) )
itemID = tonumber ( itemID )
local effectiveILvl , isPreview , baseILvl = GetDetailedItemLevelInfo ( itemLink )
if ( not effectiveILvl ) then
openRaidLib.mainControl . scheduleUpdatePlayerData ( )
effectiveILvl = 0
openRaidLib.__errors [ # openRaidLib.__errors + 1 ] = " Fail to get Item Level: " .. ( itemID or " invalid itemID " ) .. " " .. ( itemLink and itemLink : gsub ( " |H " , " " ) or " invalid itemLink " )
end
local itemStatsTable = GetItemStats ( itemLink )
--GetItemStats(itemLink, itemStatsTable)
local gemSlotsAvailable = itemStatsTable and itemStatsTable.EMPTY_SOCKET_PRISMATIC or 0
local noPrefixItemLink = itemLink : gsub ( " ^|c%x%x%x%x%x%x%x%x|Hitem " , " " )
local linkTable = { strsplit ( " : " , noPrefixItemLink ) }
local numModifiers = linkTable [ 14 ]
numModifiers = numModifiers and tonumber ( numModifiers ) or 0
for i = # linkTable , 14 + numModifiers + 1 , - 1 do
tremove ( linkTable , i )
end
local newItemLink = table.concat ( linkTable , " : " )
newItemLink = newItemLink
equipmentList [ # equipmentList + 1 ] = { equipmentSlotId , gemSlotsAvailable , effectiveILvl , newItemLink }
if ( equipmentSlotId == 2 ) then
debug = { itemLink : gsub ( " |H " , " " ) , newItemLink }
end
end
end
--[[ debug
local str = " "
for i = 1 , # equipmentList do
local t = equipmentList [ i ]
local s = t [ 1 ] .. " , " .. t [ 2 ] .. " , " .. t [ 3 ] .. " , " .. t [ 4 ]
str = str .. s
end
table.insert ( debug , str )
dumpt ( debug )
--]]
return equipmentList
end
local playerHasPetOfNpcId = function ( npcId )
if ( UnitExists ( " pet " ) and UnitHealth ( " pet " ) >= 1 ) then
local guid = UnitGUID ( " pet " )
if ( guid ) then
local split = { strsplit ( " - " , guid ) }
local playerPetNpcId = tonumber ( split [ 6 ] )
if ( playerPetNpcId ) then
if ( npcId == playerPetNpcId ) then
return true
end
end
end
end
end
local addCooldownToTable = function ( cooldowns , cooldownsHash , cooldownSpellId , timeNow )
local timeLeft , charges , startTimeOffset , duration , auraDuration = openRaidLib.CooldownManager . GetPlayerCooldownStatus ( cooldownSpellId )
cooldowns [ # cooldowns + 1 ] = cooldownSpellId
cooldowns [ # cooldowns + 1 ] = timeLeft
cooldowns [ # cooldowns + 1 ] = charges
cooldowns [ # cooldowns + 1 ] = startTimeOffset
cooldowns [ # cooldowns + 1 ] = duration
cooldowns [ # cooldowns + 1 ] = auraDuration
cooldownsHash [ cooldownSpellId ] = { timeLeft , charges , startTimeOffset , duration , timeNow , auraDuration }
end
local canAddCooldown = function ( cooldownInfo )
local petNpcIdNeeded = cooldownInfo.pet
if ( petNpcIdNeeded ) then
if ( not playerHasPetOfNpcId ( petNpcIdNeeded ) ) then
return false
end
end
return true
end
local getSpellListAsHashTableFromSpellBook = function ( )
local completeListOfSpells = { }
--this line might not be compatible with classic
local specId , specName , _ , specIconTexture = GetSpecializationInfo ( GetSpecialization ( ) )
--local classNameLoc, className, classId = UnitClass("player") --not in use
local locPlayerRace , playerRace , playerRaceId = UnitRace ( " player " )
--Enum.SpellBookSkillLineIndex
--["OffSpecStart"] = 4,
--["Class"] = 2,
--["General"] = 1,
--["MainSpec"] = 3,
--get racials from the general tab
local generalIndex = Enum.SpellBookSkillLineIndex and Enum.SpellBookSkillLineIndex . General or CONST_SPELLBOOK_GENERAL_TABID
local tabName , tabTexture , offset , numSpells , isGuild , offspecId = GetSpellTabInfo ( generalIndex ) --CONST_SPELLBOOK_GENERAL_TABID
if ( not offset ) then
return completeListOfSpells
end
offset = offset + 1
local tabEnd = offset + numSpells
for entryOffset = offset , tabEnd - 1 do
local spellType , spellId = GetSpellBookItemInfo ( entryOffset , spellBookPlayerEnum )
local spellData = LIB_OPEN_RAID_COOLDOWNS_INFO [ spellId ] --from the cooldowns table
if ( spellData ) then
local raceId = spellData.raceid
if ( raceId ) then
if ( type ( raceId ) == " table " ) then
if ( raceId [ playerRaceId ] ) then
spellId = GetOverrideSpell ( spellId )
local spellName = GetSpellInfo ( spellId )
local bIsPassive = IsPassiveSpell ( spellId , spellBookPlayerEnum )
if ( spellName and not bIsPassive ) then
completeListOfSpells [ spellId ] = true
end
end
elseif ( type ( raceId ) == " number " ) then
if ( raceId == playerRaceId ) then
spellId = GetOverrideSpell ( spellId )
local spellName = GetSpellInfo ( spellId )
local bIsPassive = IsPassiveSpell ( spellId , spellBookPlayerEnum )
if ( spellName and not bIsPassive ) then
completeListOfSpells [ spellId ] = true
end
end
end
end
end
end
--get spells from the Spec spellbook
for i = 1 , GetNumSpellTabs ( ) do --called "lines" in new v11 api
local tabName , tabTexture , offset , numSpells , isGuild , offspecId = GetSpellTabInfo ( i )
if ( tabTexture == specIconTexture ) then
offset = offset + 1
local tabEnd = offset + numSpells
for entryOffset = offset , tabEnd - 1 do
local spellType , spellId = GetSpellBookItemInfo ( entryOffset , spellBookPlayerEnum )
if ( spellId ) then
if ( spellType == " SPELL " or spellType == 1 ) then
--print(tabName, tabTexture == specIconTexture, offset, tabEnd,spellType, spellId)
spellId = GetOverrideSpell ( spellId )
local spellName = GetSpellInfo ( spellId )
local bIsPassive = IsPassiveSpell ( spellId , spellBookPlayerEnum )
if LIB_OPEN_RAID_MULTI_OVERRIDE_SPELLS [ spellId ] then
for _ , overrideSpellId in pairs ( LIB_OPEN_RAID_MULTI_OVERRIDE_SPELLS [ spellId ] ) do
completeListOfSpells [ overrideSpellId ] = true
end
elseif ( spellName and not bIsPassive ) then
completeListOfSpells [ spellId ] = true
end
end
end
end
end
end
--get class shared spells from the spell book
local tabName , tabTexture , offset , numSpells , isGuild , offspecId = GetSpellTabInfo ( CONST_SPELLBOOK_CLASSSPELLS_TABID )
offset = offset + 1
local tabEnd = offset + numSpells
for entryOffset = offset , tabEnd - 1 do
local spellType , spellId = GetSpellBookItemInfo ( entryOffset , spellBookPlayerEnum )
if ( spellId ) then
if ( spellType == " SPELL " ) then
spellId = GetOverrideSpell ( spellId )
local spellName = GetSpellInfo ( spellId )
local bIsPassive = IsPassiveSpell ( spellId , spellBookPlayerEnum )
if LIB_OPEN_RAID_MULTI_OVERRIDE_SPELLS [ spellId ] then
for _ , overrideSpellId in pairs ( LIB_OPEN_RAID_MULTI_OVERRIDE_SPELLS [ spellId ] ) do
completeListOfSpells [ overrideSpellId ] = true
end
elseif ( spellName and not bIsPassive ) then
completeListOfSpells [ spellId ] = true
else
if ( not spellName ) then
--print("no spellname")
--print(GetSpellInfo(spellId))
elseif ( bIsPassive ) then
--print("is passive")
--print(GetSpellInfo(spellId))
end
end
end
end
end
local getNumPetSpells = function ( )
--'HasPetSpells' contradicts the name and return the amount of pet spells available instead of a boolean
return HasPetSpells ( )
end
--get pet spells from the pet spellbook
local numPetSpells = getNumPetSpells ( )
if ( numPetSpells ) then
for i = 1 , numPetSpells do
local spellName , _ , unmaskedSpellId = GetSpellBookItemName ( i , spellBookPetEnum )
if ( unmaskedSpellId ) then
unmaskedSpellId = GetOverrideSpell ( unmaskedSpellId )
local bIsPassive = IsPassiveSpell ( unmaskedSpellId , spellBookPetEnum )
if ( spellName and not bIsPassive ) then
completeListOfSpells [ unmaskedSpellId ] = true
end
end
end
end
--dumpt(completeListOfSpells)
return completeListOfSpells
end
local updateCooldownAvailableList = function ( )
table.wipe ( LIB_OPEN_RAID_PLAYERCOOLDOWNS )
local _ , playerClass = UnitClass ( " player " )
local locPlayerRace , playerRace , playerRaceId = UnitRace ( " player " )
local spellBookSpellList = getSpellListAsHashTableFromSpellBook ( )
--build a list of all spells assigned as cooldowns for the player class
for spellID , spellData in pairs ( LIB_OPEN_RAID_COOLDOWNS_INFO ) do
--type 10 is an item cooldown and does not have a class or race id
local passRaceId = false
local raceId = spellData.raceid
if ( raceId ) then
if ( type ( raceId ) == " table " ) then
if ( raceId [ playerRaceId ] ) then
passRaceId = true
end
elseif ( type ( raceId ) == " number " ) then
if ( raceId == playerRaceId ) then
passRaceId = true
end
end
end
if ( spellData.class == playerClass or passRaceId or CONST_ISITEM_BY_TYPEID [ spellData.type ] ) then --need to implement here to get the racial as racial cooldowns does not carry a class
--type 10 is an item cooldown and does not have a spellbook entry
if ( spellBookSpellList [ spellID ] or CONST_ISITEM_BY_TYPEID [ spellData.type ] ) then
LIB_OPEN_RAID_PLAYERCOOLDOWNS [ spellID ] = spellData
end
end
end
end
--build a list with the local player cooldowns
--called only from SendAllPlayerCooldowns()
function openRaidLib . CooldownManager . GetPlayerCooldownList ( )
--update the list of cooldowns the player has available
if ( IsDragonflight ( ) ) then
--this fill the global LIB_OPEN_RAID_PLAYERCOOLDOWNS
updateCooldownAvailableList ( )
--get the player specId
local specId = openRaidLib.GetPlayerSpecId ( )
if ( specId ) then
--get the cooldowns for the specializationid
local playerCooldowns = LIB_OPEN_RAID_PLAYERCOOLDOWNS
if ( not playerCooldowns ) then
openRaidLib.DiagnosticError ( " CooldownManager|GetPlayerCooldownList|LIB_OPEN_RAID_PLAYERCOOLDOWNS is nil " )
return { } , { }
end
local cooldowns = { } --table to ship on comm
local cooldownsHash = { } --table with [spellId] = cooldownInfo
local talentsHash = openRaidLib.UnitInfoManager . GetPlayerTalentsAsPairsTable ( )
local timeNow = GetTime ( )
for cooldownSpellId , cooldownInfo in pairs ( playerCooldowns ) do
--does this cooldown is based on a talent?
local talentId = cooldownInfo.talent
--check if the player has a talent which makes this cooldown unavailable
local ignoredByTalentId = cooldownInfo.ignoredIfTalent
local bIsIgnoredByTalentId = false
if ( ignoredByTalentId ) then
if ( talentsHash [ ignoredByTalentId ] ) then
bIsIgnoredByTalentId = true
end
end
if ( not bIsIgnoredByTalentId ) then
if ( talentId ) then
--check if the player has the talent selected
if ( talentsHash [ talentId ] ) then
if ( canAddCooldown ( cooldownInfo ) ) then
addCooldownToTable ( cooldowns , cooldownsHash , cooldownSpellId , timeNow )
end
end
else
if ( canAddCooldown ( cooldownInfo ) ) then
addCooldownToTable ( cooldowns , cooldownsHash , cooldownSpellId , timeNow )
end
end
end
end
return cooldowns , cooldownsHash
else
return { } , { }
end
end
return { } , { }
end
--aura frame handles only UNIT_AURA events to grab the duration of the buff placed by the aura
local bIsNewUnitAuraAvailable = C_UnitAuras and C_UnitAuras.GetAuraDataBySlot and true
local auraSpellID
local auraDurationTime
local auraUnitId
local handleBuffAura = function ( aura )
local auraInfo = C_UnitAuras.GetAuraDataByAuraInstanceID ( auraUnitId , aura.auraInstanceID )
if ( auraInfo ) then
local spellId = auraInfo.spellId
if ( auraSpellID == spellId ) then
auraSpellID = nil
auraDurationTime = auraInfo.duration
return true
end
end
end
local getAuraDuration = function ( spellId , unitId )
--some auras does not have the same spellId of the cast as the spell for its aura duration
--in these cases, it's necessary to declare the buff spellId which tells the duration of the effect by adding 'durationSpellId = spellId' within the cooldown data
if ( not LIB_OPEN_RAID_PLAYERCOOLDOWNS [ spellId ] ) then
--local spellname = GetSpellInfo(spellId)
--print("spell not found:", spellname)
return 0
end
local customBuffDuration = LIB_OPEN_RAID_PLAYERCOOLDOWNS [ spellId ] . durationSpellId
--spellId = customBuffDuration or spellId --can't replace the spellId by customBuffDurationSpellId has it wount be found in LIB_OPEN_RAID_PLAYERCOOLDOWNS
if ( bIsNewUnitAuraAvailable ) then
local bUsePackedAura = true
auraSpellID = customBuffDuration or spellId
auraDurationTime = 0 --reset duration
auraUnitId = unitId or " player "
AuraUtil.ForEachAura ( auraUnitId , " HELPFUL " , nil , handleBuffAura , bUsePackedAura ) --check auras to find a buff for the spellId
if ( auraDurationTime == 0 ) then --if the buff wasn't found, attempt to get the duration from the file
return LIB_OPEN_RAID_PLAYERCOOLDOWNS [ spellId ] . duration or 0
end
return auraDurationTime
else
--this is classic
end
end
---get the duration of a buff placed by a spell
---@param spellId number
---@param unitId string?
---@return number duration
function openRaidLib . CooldownManager . GetSpellBuffDuration ( spellId , unitId )
return getAuraDuration ( spellId , unitId )
end
---check if a player cooldown is ready or if is in cooldown
---@spellId: the spellId to check for cooldown
---@return number timeLeft
---@return number charges
---@return number startTimeOffset
---@return number duration
---@return number buffDuration
function openRaidLib . CooldownManager . GetPlayerCooldownStatus ( spellId )
--check if is a charge spell
local spellData = LIB_OPEN_RAID_COOLDOWNS_INFO [ spellId ]
if ( spellData ) then
local buffDuration = getAuraDuration ( spellId )
local chargesAvailable , chargesTotal , start , duration = GetSpellCharges ( spellId )
if chargesAvailable then
if ( chargesAvailable == chargesTotal ) then
return 0 , chargesTotal , 0 , 0 , 0 --all charges are ready to use
else
--return the time to the next charge
local timeLeft = start + duration - GetTime ( )
local startTimeOffset = start - GetTime ( )
return ceil ( timeLeft ) , chargesAvailable , startTimeOffset , duration , buffDuration
end
else
if ( IsTWWExpansion ( ) ) then
local spellCooldownInfo = GetSpellCooldown ( spellId )
local start = spellCooldownInfo.startTime
local duration = spellCooldownInfo.duration
if ( start == 0 ) then --cooldown is ready
return 0 , 1 , 0 , 0 , 0 --time left, charges, startTime
else
local timeLeft = start + duration - GetTime ( )
local startTimeOffset = start - GetTime ( )
return ceil ( timeLeft ) , 0 , ceil ( startTimeOffset ) , duration , buffDuration --time left, charges, startTime, duration, buffDuration
end
else
local start , duration = GetSpellCooldown ( spellId )
if ( start == 0 ) then --cooldown is ready
return 0 , 1 , 0 , 0 , 0 --time left, charges, startTime
else
local timeLeft = start + duration - GetTime ( )
local startTimeOffset = start - GetTime ( )
return ceil ( timeLeft ) , 0 , ceil ( startTimeOffset ) , duration , buffDuration --time left, charges, startTime, duration, buffDuration
end
end
end
else
return openRaidLib.DiagnosticError ( " CooldownManager|GetPlayerCooldownStatus()|cooldownInfo not found| " , spellId )
end
end
do
--make new namespace
openRaidLib.AuraTracker = { }
do if ( false ) then --do not load this section as it isn't in use
function openRaidLib . AuraTracker . ScanCallback ( auraInfo )
if ( auraInfo ) then
local spellId = auraInfo.spellId
if ( spellId ) then
local unitId = openRaidLib.AuraTracker . CurrentUnitId
local thisUnitAuras = openRaidLib.AuraTracker . CurrentAuras [ unitId ]
thisUnitAuras [ spellId ] = true
openRaidLib.AuraTracker . AurasFoundOnScan [ spellId ] = true
end
end
end
function openRaidLib . AuraTracker . ScanUnitAuras ( unitId )
local maxCount = nil
local bUsePackedAura = true
openRaidLib.AuraTracker . CurrentUnitId = unitId
openRaidLib.AuraTracker . AurasFoundOnScan = { }
--code of 'ForEachAura' has been updated to use the latest API available
AuraUtil.ForEachAura ( unitId , " HELPFUL " , maxCount , openRaidLib.AuraTracker . ScanCallback , bUsePackedAura )
local thisUnitAuras = openRaidLib.AuraTracker . CurrentAuras [ unitId ]
for spellId in pairs ( thisUnitAuras ) do
if ( not openRaidLib.AuraTracker . AurasFoundOnScan [ spellId ] ) then
--aura removed
openRaidLib.internalCallback . TriggerEvent ( " unitAuraRemoved " , unitId , spellId )
end
end
end
--run when the open raid lib loads
function openRaidLib . AuraTracker . StartScanUnitAuras ( unitId ) --this function isn't getting called (was called from Entering World event)
openRaidLib.AuraTracker . CurrentAuras = {
[ unitId ] = { } --storing using the unitId as key, won't work for any other unit other than the "player"
}
local auraFrameEvent = CreateFrame ( " frame " )
auraFrameEvent : RegisterUnitEvent ( " UNIT_AURA " , unitId )
auraFrameEvent : SetScript ( " OnEvent " , function ( )
openRaidLib.AuraTracker . ScanUnitAuras ( unitId )
end )
end
end end
--test case:
local debugModule = { }
function debugModule . AuraRemoved ( event , unitId , spellId )
local spellName = GetSpellInfo ( spellId )
--print("aura removed:", unitId, spellId, spellName)
end
openRaidLib.internalCallback . RegisterCallback ( " unitAuraRemoved " , debugModule.AuraRemoved )
end
do
local getUnitName = function ( unitId )
local unitName , realmName = UnitName ( unitId )
if ( unitName ) then
if ( realmName and realmName ~= " " ) then
unitName = unitName .. " - " .. realmName
end
return unitName
end
end
local predicateFunc = function ( spellIdToFind , casterName , _ , name , icon , applications , dispelName , duration , expirationTime , sourceUnitId , isStealable , nameplateShowPersonal , spellId , canApplyAura , isBossAura , isFromPlayerOrPlayerPet , nameplateShowAll , timeMod , applications )
if ( spellIdToFind == spellId and UnitExists ( sourceUnitId ) ) then
if ( casterName == getUnitName ( sourceUnitId ) ) then
return true
end
end
end
---find the duration of a debuff by passing the spellId and the caster name
---@param unitId unit
---@param spellId spellid
---@param casterName actorname
---@return auraduration|nil auraDuration
---@return number|nil expirationTime
function openRaidLib . AuraTracker . FindBuffDuration ( unitId , casterName , spellId )
local name , texture , count , buffType , duration , expirationTime = AuraUtil.FindAura ( predicateFunc , unitId , " HELPFUL " , spellId , casterName )
if ( name ) then
return duration , expirationTime
end
end
---find the duration of a buff placed by a unit
---@param targetString string
---@param casterString string
---@param spellId number
function openRaidLib . AuraTracker . FindBuffDurationByUnitName ( targetString , casterString , spellId )
local targetName = Ambiguate ( targetString , " none " )
local casterName = Ambiguate ( casterString , " none " )
return openRaidLib.AuraTracker . FindBuffDuration ( targetName , casterName , spellId )
end
end
--which is the main attribute of each spec
--1 Intellect
--2 Agility
--3 Strenth
openRaidLib.specAttribute = {
[ " DEMONHUNTER " ] = {
[ 577 ] = 2 ,
[ 581 ] = 2 ,
} ,
[ " DEATHKNIGHT " ] = {
[ 250 ] = 3 ,
[ 251 ] = 3 ,
[ 252 ] = 3 ,
} ,
[ " WARRIOR " ] = {
[ 71 ] = 3 ,
[ 72 ] = 3 ,
[ 73 ] = 3 ,
} ,
[ " MAGE " ] = {
[ 62 ] = 1 ,
[ 63 ] = 1 ,
[ 64 ] = 1 ,
} ,
[ " ROGUE " ] = {
[ 259 ] = 2 ,
[ 260 ] = 2 ,
[ 261 ] = 2 ,
} ,
[ " DRUID " ] = {
[ 102 ] = 1 ,
[ 103 ] = 2 ,
[ 104 ] = 2 ,
[ 105 ] = 1 ,
} ,
[ " HUNTER " ] = {
[ 253 ] = 2 ,
[ 254 ] = 2 ,
[ 255 ] = 2 ,
} ,
[ " SHAMAN " ] = {
[ 262 ] = 1 ,
[ 263 ] = 2 ,
[ 264 ] = 1 ,
} ,
[ " PRIEST " ] = {
[ 256 ] = 1 ,
[ 257 ] = 1 ,
[ 258 ] = 1 ,
} ,
[ " WARLOCK " ] = {
[ 265 ] = 1 ,
[ 266 ] = 1 ,
[ 267 ] = 1 ,
} ,
[ " PALADIN " ] = {
[ 65 ] = 1 ,
[ 66 ] = 3 ,
[ 70 ] = 3 ,
} ,
[ " MONK " ] = {
[ 268 ] = 2 ,
[ 269 ] = 2 ,
[ 270 ] = 1 ,
} ,
[ " EVOKER " ] = {
[ 1467 ] = 1 , --Devastation
[ 1468 ] = 1 , --Preservation
[ 1473 ] = 1 , --Augmentation
} ,
}