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.

425 lines
15 KiB

--[=[
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 isTimewalkWoW = function()
local gameVersion = GetBuildInfo()
if (gameVersion:match("%d") == "1" or gameVersion:match("%d") == "2") then
return true
end
end
--creates two tables, one with indexed talents and another with pairs values ([talentId] = true)
function openRaidLib.UnitInfoManager.GetPlayerTalentsAsPairsTable()
local talentsPairs = {}
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
return talentsPairs
end
function openRaidLib.UnitInfoManager.GetPlayerTalents()
local 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
return talents
end
function openRaidLib.UnitInfoManager.GetPlayerPvPTalents()
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
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.GearManager.GetPlayerItemLevel()
if (_G.GetAverageItemLevel) then
local _, _itemLevel = GetAverageItemLevel()
itemLevel = floor(_itemLevel)
else
itemLevel = 0
end
return itemLevel
end
--return an integer between zero and one hundret indicating the player gear durability
function openRaidLib.GearManager.GetPlayerGearDurability()
local durabilityTotalPercent, totalItems = 0, 0
for i = INVSLOT_FIRST_EQUIPPED, INVSLOT_LAST_EQUIPPED do
local durability, maxDurability = GetInventoryItemDurability(i)
if (durability and maxDurability) then
local itemDurability = durability / maxDurability * 100
durabilityTotalPercent = durabilityTotalPercent + itemDurability
totalItems = totalItems + 1
end
end
if (totalItems == 0) then
return 100
end
return floor(durabilityTotalPercent / totalItems)
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
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 = {}
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]
if (enchantAttribute) then --this slot can receive an enchat
--check if this slot is relevant for the class, some slots can have enchants only for Agility which won't matter for Priests as an example
--if the value is an integer it points to an attribute (int, dex, str), otherwise it's true (boolean)
local slotIsRelevant = true
if (type (enchantAttribute) == "number") then
if (specMainAttribute ~= enchantAttribute) then
slotIsRelevant = false
end
end
if (slotIsRelevant) then
--does the slot has any enchant?
if (not enchantId or enchantId == "0" or enchantId == "") then
slotsWithoutEnchant[#slotsWithoutEnchant+1] = equipmentSlotId
else
--convert to integer
local enchantIdInt = tonumber(enchantId)
if (enchantIdInt) then
--does the enchant is relevent for the character?
if (not LIB_OPEN_RAID_ENCHANT_IDS[enchantIdInt]) then
slotsWithoutEnchant[#slotsWithoutEnchant+1] = equipmentSlotId
end
else
--the enchat has an invalid id
slotsWithoutEnchant[#slotsWithoutEnchant+1] = equipmentSlotId
end
end
end
end
--> gems
local itemStatsTable = {}
--fill the table above with information about the item
GetItemStats(itemLink, itemStatsTable)
--check if the item has a socket
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 (not LIB_OPEN_RAID_GEM_IDS[gemId]) then
slotsWithoutGems[#slotsWithoutGems+1] = equipmentSlotId
end
end
end
end
end
return slotsWithoutGems, slotsWithoutEnchant
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)
cooldowns[#cooldowns+1] = cooldownSpellId
local timeLeft, charges, startTimeOffset, duration = openRaidLib.CooldownManager.GetPlayerCooldownStatus(cooldownSpellId)
cooldowns[#cooldowns+1] = timeLeft
cooldowns[#cooldowns+1] = charges
cooldowns[#cooldowns+1] = startTimeOffset
cooldowns[#cooldowns+1] = duration
cooldownsHash[cooldownSpellId] = {timeLeft, charges, startTimeOffset, duration, timeNow}
end
local canAddCooldown = function(cooldownInfo)
local needPetNpcId = cooldownInfo.pet
if (needPetNpcId) then
if (not playerHasPetOfNpcId(needPetNpcId)) then
return false
end
end
return true
end
--build a list with the local player cooldowns
--called only from SendAllPlayerCooldowns()
function openRaidLib.CooldownManager.GetPlayerCooldownList()
--get the player specId
local specId = openRaidLib.GetPlayerSpecId()
if (specId) then
--get the cooldowns for the specialization
local playerCooldowns = LIB_OPEN_RAID_COOLDOWNS_BY_SPEC[specId]
if (not playerCooldowns) then
openRaidLib.DiagnosticError("CooldownManager|GetPlayerCooldownList|can't find player cooldowns for specId:", specId)
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, cooldownType in pairs(playerCooldowns) do
--get all the information about this cooldow
local cooldownInfo = LIB_OPEN_RAID_COOLDOWNS_INFO[cooldownSpellId]
if (cooldownInfo) then
--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 isIgnoredByTalentId = false
if (ignoredByTalentId) then
if (talentsHash[ignoredByTalentId]) then
isIgnoredByTalentId = true
end
end
if (not isIgnoredByTalentId) 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
end
return cooldowns, cooldownsHash
else
return {}, {}
end
end
--check if a player cooldown is ready or if is in cooldown
--@spellId: the spellId to check for cooldown
function openRaidLib.CooldownManager.GetPlayerCooldownStatus(spellId)
--check if is a charge spell
local cooldownInfo = LIB_OPEN_RAID_COOLDOWNS_INFO[spellId]
if (cooldownInfo) then
if (cooldownInfo.charges and cooldownInfo.charges > 1) then
local chargesAvailable, chargesTotal, start, duration = GetSpellCharges(spellId)
if (chargesAvailable == chargesTotal) then
return 0, chargesTotal, 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 --time left, charges, startTime
end
else
local start, duration = GetSpellCooldown(spellId)
if (start == 0) then --cooldown is ready
return 0, 1, 0, 0 --time left, charges, startTime
else
local timeLeft = start + duration - GetTime()
local startTimeOffset = start - GetTime()
return ceil(timeLeft), 0, ceil(startTimeOffset), duration --time left, charges, startTime, duration
end
end
else
return openRaidLib.DiagnosticError("CooldownManager|GetPlayerCooldownStatus()|cooldownInfo not found|", 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,
}
}