diff --git a/Details.toc b/Details.toc index 481ad8ab..d6088c30 100644 --- a/Details.toc +++ b/Details.toc @@ -67,7 +67,7 @@ frames\window_copy.lua frames\window_options2.lua frames\window_options2_sections.lua frames\window_api.lua -#frames\window_cdtracker.lua +frames\window_cdtracker.lua frames\window_playerbreakdown.lua frames\window_playerbreakdown_list.lua frames\window_report.lua diff --git a/Libs/DF/fw.lua b/Libs/DF/fw.lua index acc4593a..7bd6f4b5 100644 --- a/Libs/DF/fw.lua +++ b/Libs/DF/fw.lua @@ -1,6 +1,6 @@ -local dversion = 220 +local dversion = 221 local major, minor = "DetailsFramework-1.0", dversion local DF, oldminor = LibStub:NewLibrary (major, minor) @@ -3509,6 +3509,30 @@ DF.AlliedRaceList = { [41] = "MagharOrc", } +local slotIdToIcon = { + [1] = "Interface\\ICONS\\" .. "INV_Helmet_29", --head + [2] = "Interface\\ICONS\\" .. "INV_Jewelry_Necklace_07", --neck + [3] = "Interface\\ICONS\\" .. "INV_Shoulder_25", --shoulder + [5] = "Interface\\ICONS\\" .. "INV_Chest_Cloth_08", --chest + [6] = "Interface\\ICONS\\" .. "INV_Belt_15", --waist + [7] = "Interface\\ICONS\\" .. "INV_Pants_08", --legs + [8] = "Interface\\ICONS\\" .. "INV_Boots_Cloth_03", --feet + [9] = "Interface\\ICONS\\" .. "INV_Bracer_07", --wrist + [10] = "Interface\\ICONS\\" .. "INV_Gauntlets_17", --hands + [11] = "Interface\\ICONS\\" .. "INV_Jewelry_Ring_22", --finger 1 + [12] = "Interface\\ICONS\\" .. "INV_Jewelry_Ring_22", --finger 2 + [13] = "Interface\\ICONS\\" .. "INV_Jewelry_Talisman_07", --trinket 1 + [14] = "Interface\\ICONS\\" .. "INV_Jewelry_Talisman_07", --trinket 2 + [15] = "Interface\\ICONS\\" .. "INV_Misc_Cape_19", --back + [16] = "Interface\\ICONS\\" .. "INV_Sword_39", --main hand + [17] = "Interface\\ICONS\\" .. "INV_Sword_39", --off hand +} + +function DF:GetArmorIconByArmorSlot(equipSlotId) + return slotIdToIcon[equipSlotId] or "" +end + + --> store and return a list of character races, always return the non-localized value DF.RaceCache = {} function DF:GetCharacterRaceList (fullList) diff --git a/Libs/DF/spells.lua b/Libs/DF/spells.lua index ca86db2d..54663ffe 100644 --- a/Libs/DF/spells.lua +++ b/Libs/DF/spells.lua @@ -879,9 +879,7 @@ for specId, cooldownTable in pairs (DF.CooldownsBySpec) do end DF.CooldownToClass [spellId] = DF.SpecIds [spellId] - end - end function DF:FindClassForCooldown (spellId) @@ -900,6 +898,15 @@ end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ --consumables +DF.WeaponEnchantIds = { + [6188] = true, --shadowcore oil + [6190] = true, --embalmer's oil + [6201] = true, --weighted + [6200] = true, --sharpened + [5400] = true, --flametongue + [5401] = true, --windfury +} + DF.FlaskIDs = { --Shadowlands [307185] = true, --Spectral Flask of Power diff --git a/Libs/LibRaidStatus/LibRaidStatus.lua b/Libs/LibRaidStatus/LibRaidStatus.lua new file mode 100644 index 00000000..28cecb3c --- /dev/null +++ b/Libs/LibRaidStatus/LibRaidStatus.lua @@ -0,0 +1,1292 @@ +--terminei de fazer o onDead e onAlive events +--repair precisa registrar isso e mandar na comm e a comm precisa receber e atualizar na lista +--terminei de fazer o ondeath e oalive; comm nao aceita comm do proprio jogador; tem que ver se o cooldown passa a data certin pro player quando ele casta pq a comm nao vai passar +--terminei de fazer a restruturação da comm dos cooldowns, agora não existe mais o comando _FULL, cooldowns sempre são mandados separadamente + +local major = "LibRaidStatus-1.0" +local CONST_LIB_VERSION = 4 +LIB_RAID_STATUS_CAN_LOAD = false + +--declae the library within the LibStub + local libStub = _G.LibStub + local raidStatusLib = libStub:NewLibrary(major, CONST_LIB_VERSION) + if (not raidStatusLib) then + return + end + + LIB_RAID_STATUS_CAN_LOAD = true + +--default values + raidStatusLib.inGroup = false + raidStatusLib.CanReceiveComms = false + + --print failures (when the function return an error) results to chat + local CONST_DIAGNOSTIC_ERRORS = true + --print the data to be sent and data received from comm + local CONST_DIAGNOSTIC_COMM = true + + local CONST_COMM_PREFIX = "LRS" + local CONST_COMM_COOLDOWNUPDATE_PREFIX = "U" + local CONST_COMM_COOLDOWNFULLLIST_PREFIX = "C" + local CONST_COMM_GEARINFO_FULL_PREFIX = "G" + local CONST_COMM_GEARINFO_DURABILITY_PREFIX = "R" + local CONST_COMM_PLAYER_DEAD_PREFIX = "D" + local CONST_COMM_PLAYER_ALIVE_PREFIX = "A" + + local CONST_ONE_SECOND = 1.0 + local CONST_TWO_SECONDS = 2.0 + local CONST_THREE_SECONDS = 3.0 + local CONST_FRACTION_OF_A_SECOND = 0.01 + + local CONST_COOLDOWN_CHECK_INTERVAL = CONST_THREE_SECONDS + local CONST_COOLDOWN_TIMELEFT_HAS_CHANGED = CONST_THREE_SECONDS + + local diagnosticError = function(msg, ...) + if (CONST_DIAGNOSTIC_ERRORS) then + print("|cFFFF9922raidStatusLib|r:", msg, ...) + end + end + + local diagnosticComm = function(msg, ...) + if (CONST_DIAGNOSTIC_COMM) then + print("|cFFFF9922raidStatusLib|r:", msg, ...) + end + end + + --return the current specId of the player + function raidStatusLib.GetPlayerSpecId() + local spec = GetSpecialization() + if (spec) then + local specId = GetSpecializationInfo(spec) + if (specId and specId > 0) then + return specId + end + end + end + + function raidStatusLib.UpdatePlayerAliveStatus(onLogin) + if (UnitIsDeadOrGhost("player")) then + if (raidStatusLib.playerAlive) then + raidStatusLib.playerAlive = false + + --trigger event if this isn't from login + if (not onLogin) then + raidStatusLib.internalCallback.TriggerEvent("onPlayerDeath") + end + end + else + if (not raidStatusLib.playerAlive) then + raidStatusLib.playerAlive = true + + --trigger event if this isn't from login + if (not onLogin) then + raidStatusLib.internalCallback.TriggerEvent("onPlayerRess") + end + end + end + end + + --creates two tables, one with indexed talents and another with pairs values ([talentId] = true) + function raidStatusLib.GetPlayerTalents() + local talentsPairs = {} + local talentsIndex = {} + for i = 1, 7 do + for o = 1, 3 do + local talentId, _, _, selected = GetTalentInfo(i, o, 1) + if (selected) then + talentsPairs[talentId] = true + talentsIndex[#talentsIndex+1] = talentId + break + end + end + end + return talentsPairs, talentsIndex + end + + --simple non recursive table copy + function raidStatusLib.TCopy(tableToReceive, tableToCopy) + for key, value in pairs(tableToCopy) do + tableToReceive[key] = value + end + end + + --transform a table index a string dividing values with a comma + --@table: an indexed table with unknown size + function raidStatusLib.PackTable(table) + local tableSize = #table + local newString = "" .. tableSize .. "," + for i = 1, tableSize do + newString = newString .. table[i] .. "," + end + + newString = newString:gsub(",$", "") + return newString + end + + --stract some indexes of a table + local selectIndexes = function(table, startIndex, amountIndexes) + local values = {} + for i = startIndex, startIndex+amountIndexes do + values[#values+1] = tonumber(table[i]) or 0 + end + return values + end + + --return is a number is almost equal to another within a tolerance range + function raidStatusLib.isNearlyEqual(value1, value2, tolerance) + tolerance = tolerance or CONST_FRACTION_OF_A_SECOND + return abs(value1 - value2) <= tolerance + end + + --return true if the lib is allowed to receive comms from other players + function raidStatusLib.IsCommAllowed() + return raidStatusLib.CanReceiveComms + end + + --transform a string table into a regular table + --@table: a table with unknown values + --@index: where in the table is the information we want + --@isPair: if true treat the table as pairs(), ipairs() otherwise + --@valueAsTable: return {value1, value2, value3} + --@amountOfValues: for the parameter above + function raidStatusLib.UnpackTable(table, index, isPair, valueIsTable, amountOfValues) + local result = {} + local reservedIndexes = table[index] + local indexStart = index+1 + local indexEnd = reservedIndexes+index + + if (isPair) then + amountOfValues = amountOfValues or 2 + for i = indexStart, indexEnd, amountOfValues do + if (valueIsTable) then + local key = tonumber(table[i]) + local values = selectIndexes(table, i+1, 1) + result[key] = values + else + local key = tonumber(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 + + --returns if the player is in group + function raidStatusLib.IsInGroup() + local inParty = IsInGroup() + local inRaid = IsInRaid() + return inParty or inRaid + end + + +-------------------------------------------------------------------------------------------------------------------------------- +--> ~comms + raidStatusLib.commHandler = {} + + function raidStatusLib.commHandler.OnReceiveComm(self, event, prefix, text, channel, sender, target, zoneChannelID, localID, name, instanceID) + --check if the data belong to us + if (prefix == CONST_COMM_PREFIX) then + --check if the lib can receive comms + if (not raidStatusLib.IsCommAllowed()) then + return + end + + sender = Ambiguate(sender, "none") + + --don't receive comms from the player it self + local playerName = UnitName("player") + if (playerName == sender) then + --return --commented for debug + end + + local data = text + local LibDeflate = LibStub:GetLibrary("LibDeflate") + local dataCompressed = LibDeflate:DecodeForWoWAddonChannel(data) + data = LibDeflate:DecompressDeflate(dataCompressed) + + --get the first byte of the data, it indicates what type of data was transmited + local dataTypePrefix = data:match("^.") + --get the table with functions regitered for this type of data + local callbackTable = raidStatusLib.commHandler.commCallback[dataTypePrefix] + --convert to table + local dataAsTable = {strsplit(",", data)} + --remove the first index (prefix) + tremove(dataAsTable, 1) + --trigger callbacks + for i = 1, #callbackTable do + callbackTable[i](dataAsTable, sender) + end + end + end + + C_ChatInfo.RegisterAddonMessagePrefix(CONST_COMM_PREFIX) + raidStatusLib.commHandler.eventFrame = CreateFrame("frame") + raidStatusLib.commHandler.eventFrame:RegisterEvent("CHAT_MSG_ADDON") + raidStatusLib.commHandler.eventFrame:SetScript("OnEvent", raidStatusLib.commHandler.OnReceiveComm) + + raidStatusLib.commHandler.commCallback = { + --when transmiting + [CONST_COMM_COOLDOWNFULLLIST_PREFIX] = {}, --all cooldowns of a player + [CONST_COMM_COOLDOWNUPDATE_PREFIX] = {}, --an update of a single cooldown + [CONST_COMM_GEARINFO_FULL_PREFIX] = {}, --an update of gear information + [CONST_COMM_GEARINFO_DURABILITY_PREFIX] = {}, --an update of the player gear durability + [CONST_COMM_PLAYER_DEAD_PREFIX] = {}, --player is dead + [CONST_COMM_PLAYER_ALIVE_PREFIX] = {}, --player is alive + } + + function raidStatusLib.commHandler.RegisterComm(prefix, func) + --the table for the prefix need to be declared at the 'raidStatusLib.commHandler.commCallback' table + tinsert(raidStatusLib.commHandler.commCallback[prefix], func) + end + + function raidStatusLib.commHandler.SendCommData(data) + local LibDeflate = LibStub:GetLibrary("LibDeflate") + local dataCompressed = LibDeflate:CompressDeflate(data, {level = 9}) + local dataEncoded = LibDeflate:EncodeForWoWAddonChannel(dataCompressed) + + if (IsInGroup() and not IsInRaid()) then --in party only + C_ChatInfo.SendAddonMessage(CONST_COMM_PREFIX, dataEncoded, IsInGroup(LE_PARTY_CATEGORY_INSTANCE) and "INSTANCE_CHAT" or "PARTY") + + elseif (IsInRaid()) then + C_ChatInfo.SendAddonMessage(CONST_COMM_PREFIX, dataEncoded, IsInRaid(LE_PARTY_CATEGORY_INSTANCE) and "INSTANCE_CHAT" or "RAID") + end + end + + + +-------------------------------------------------------------------------------------------------------------------------------- +--> ~schedule ~timers + + raidStatusLib.Schedules = { + registeredUniqueTimers = {} + } + + --run a scheduled function with its payload + local triggerScheduledTick = function(tickerObject) + local payload = tickerObject.payload + local callback = tickerObject.callback + + local result, errortext = pcall(callback, _G.unpack(payload)) + if (not result) then + print("raidStatusLib: error on scheduler:", tickerObject.scheduleName, tickerObject.stack, errortext) + end + + if (tickerObject.isUnique) then + local namespace = tickerObject.namespace + local scheduleName = tickerObject.scheduleName + raidStatusLib.Schedules.CancelUniqueTimer(namespace, scheduleName) + end + + return result + end + + --create a new schedule + function raidStatusLib.Schedules.NewTimer(time, callback, ...) + local payload = {...} + local newTimer = C_Timer.NewTimer(time, triggerScheduledTick) + newTimer.payload = payload + newTimer.callback = callback + newTimer.stack = debugstack() + return newTimer + end + + --create an unique schedule + --if a schedule already exists, cancels it and make a new + function raidStatusLib.Schedules.NewUniqueTimer(time, callback, namespace, scheduleName, ...) + raidStatusLib.Schedules.CancelUniqueTimer(namespace, scheduleName) + + local newTimer = raidStatusLib.Schedules.NewTimer(time, callback, ...) + newTimer.namespace = namespace + newTimer.scheduleName = scheduleName + newTimer.stack = debugstack() + newTimer.isUnique = true + + local registeredUniqueTimers = raidStatusLib.Schedules.registeredUniqueTimers + registeredUniqueTimers[namespace] = registeredUniqueTimers[namespace] or {} + registeredUniqueTimers[namespace][scheduleName] = newTimer + end + + --cancel an unique schedule + function raidStatusLib.Schedules.CancelUniqueTimer(namespace, scheduleName) + local registeredUniqueTimers = raidStatusLib.Schedules.registeredUniqueTimers + local currentSchedule = registeredUniqueTimers[namespace] and registeredUniqueTimers[namespace][scheduleName] + + if (currentSchedule) then + if (not currentSchedule._cancelled) then + currentSchedule:Cancel() + end + registeredUniqueTimers[namespace][scheduleName] = nil + end + end + + --cancel all unique timers + function raidStatusLib.Schedules.CancelAllUniqueTimers() + local registeredUniqueTimers = raidStatusLib.Schedules.registeredUniqueTimers + for namespace, schedulesTable in pairs(registeredUniqueTimers) do + for scheduleName, timerObject in pairs (schedulesTable) do + if (timerObject and not timerObject._cancelled) then + timerObject:Cancel() + end + end + end + table.wipe(registeredUniqueTimers) + end + + +-------------------------------------------------------------------------------------------------------------------------------- +--> ~public ~callbacks +--these are the events where other addons can register and receive calls + local allPublicCallbacks = { + "CooldownListUpdate", + "CooldownListWiped", + "CooldownUpdate", + "OnPlayerDeath", + "OnPlayerRess", + "GearListWiped", + "GearUpdate", + "GearDurabilityUpdate", + } + + --save build the table to avoid lose registered events on older versions + raidStatusLib.publicCallback = raidStatusLib.publicCallback or {} + raidStatusLib.publicCallback.events = raidStatusLib.publicCallback.events or {} + for _, callbackName in ipairs(allPublicCallbacks) do + raidStatusLib.publicCallback.events[callbackName] = raidStatusLib.publicCallback.events[callbackName] or {} + end + + local checkRegisterDataIntegrity = function(addonObject, event, callbackMemberName) + --check of integrity + if (type(addonObject) == "string") then + addonObject = _G[addonObject] + end + + if (type(addonObject) ~= "table") then + return 1 + end + + if (not raidStatusLib.publicCallback.events[event]) then + return 2 + + elseif (not addonObject[callbackMemberName]) then + return 3 + end + + return true + end + + --call the registered function within the addon namespace + --payload is sent together within the call + function raidStatusLib.publicCallback.TriggerCallback(event, ...) + local callbacks = raidStatusLib.publicCallback.events[event] + + for i = 1, #callbacks do + local addonObject = callbacks[i][1] + local functionName = callbacks[i][2] + local func = addonObject[functionName] + + if (func) then + --using pcall at the moment, should get a better caller in the future + local okay, errorMessage = pcall(func, ...) + if (not okay) then + print("error:", errorMessage) + end + end + end + end + + function raidStatusLib.RegisterCallback(addonObject, event, callbackMemberName) + --check of integrity + local integrity = checkRegisterDataIntegrity(addonObject, event, callbackMemberName) + if (integrity and type(integrity) ~= "boolean") then + return integrity + end + + --register + tinsert(raidStatusLib.publicCallback.events[event], {addonObject, callbackMemberName}) + return true + end + + function raidStatusLib.UnregisterCallback(addonObject, event, callbackMemberName) + --check of integrity + local integrity = checkRegisterDataIntegrity(addonObject, event, callbackMemberName) + if (integrity and type(integrity) ~= "boolean") then + return integrity + end + + for i = 1, #raidStatusLib.publicCallback.events[event] do + local registeredCallback = raidStatusLib.publicCallback.events[event][i] + if (registeredCallback[1] == addonObject and registeredCallback[2] == callbackMemberName) then + tremove(raidStatusLib.publicCallback.events[event], i) + break + end + end + end + +-------------------------------------------------------------------------------------------------------------------------------- +--> ~internal ~callbacks +--internally, each module can register events through the internal callback to be notified when something happens in the game + + raidStatusLib.internalCallback = {} + raidStatusLib.internalCallback.events = { + ["onEnterGroup"] = {}, + ["onLeaveGroup"] = {}, + ["playerCast"] = {}, + ["onEnterWorld"] = {}, + ["talentUpdate"] = {}, + ["onPlayerDeath"] = {}, + ["onPlayerRess"] = {}, + } + + raidStatusLib.internalCallback.RegisterCallback = function(event, func) + tinsert(raidStatusLib.internalCallback.events[event], func) + end + + raidStatusLib.internalCallback.UnRegisterCallback = function(event, func) + local container = raidStatusLib.internalCallback.events[event] + for i = 1, #container do + if (container[i] == func) then + tremove(container, i) + break + end + end + end + + function raidStatusLib.internalCallback.TriggerEvent(event, ...) + local container = raidStatusLib.internalCallback.events[event] + for i = 1, #container do + container[i](event, ...) + end + end + + --create the frame for receiving game events + local eventFrame = _G.RaidStatusLibFrame + if (not eventFrame) then + eventFrame = CreateFrame("frame", "RaidStatusLibFrame", UIParent) + end + + local eventFunctions = { + --check if the player joined a group + ["GROUP_ROSTER_UPDATE"] = function() + local eventTriggered = false + if (raidStatusLib.IsInGroup()) then + if (not raidStatusLib.inGroup) then + raidStatusLib.inGroup = true + raidStatusLib.internalCallback.TriggerEvent("onEnterGroup") + eventTriggered = true + end + else + if (raidStatusLib.inGroup) then + raidStatusLib.inGroup = false + raidStatusLib.internalCallback.TriggerEvent("onLeaveGroup") + eventTriggered = true + end + end + + if (not eventTriggered and raidStatusLib.IsInGroup()) then --the player didn't left or enter a group + --the group has changed, trigger a long timer to send full data + --as the timer is unique, a new change to the group will replace and refresh the time + --using random time, players won't trigger all at the same time + local randomTime = 4.0 + math.random(1.0, 4.5) + raidStatusLib.Schedules.NewUniqueTimer(randomTime, raidStatusLib.mainControl.SendFullData, "mainControl", "sendFullData_Schedule") + end + end, + + ["UNIT_SPELLCAST_SUCCEEDED"] = function(...) + local unitId, castGUID, spellId = ... + C_Timer.After(0.1, function() + raidStatusLib.internalCallback.TriggerEvent("playerCast", spellId) + end) + end, + + ["PLAYER_ENTERING_WORLD"] = function(...) + raidStatusLib.internalCallback.TriggerEvent("onEnterWorld") + end, + + --["PLAYER_SPECIALIZATION_CHANGED"] = function(...) end, --on changing spec, the talent_update event is also triggered + ["PLAYER_TALENT_UPDATE"] = function(...) + raidStatusLib.internalCallback.TriggerEvent("talentUpdate") + end, + + ["PLAYER_DEAD"] = function(...) + raidStatusLib.UpdatePlayerAliveStatus() + end, + ["PLAYER_ALIVE"] = function(...) + raidStatusLib.UpdatePlayerAliveStatus() + end, + ["PLAYER_UNGHOST"] = function(...) + raidStatusLib.UpdatePlayerAliveStatus() + end, + + ["PLAYER_REGEN_DISABLED"] = function(...) + + end, + + ["PLAYER_REGEN_ENABLED"] = function(...) + + end, + } + + eventFrame:RegisterEvent("GROUP_ROSTER_UPDATE") + eventFrame:RegisterUnitEvent("UNIT_SPELLCAST_SUCCEEDED", "player") + eventFrame:RegisterEvent("PLAYER_ENTERING_WORLD") + eventFrame:RegisterEvent("PLAYER_REGEN_DISABLED") + eventFrame:RegisterEvent("PLAYER_REGEN_ENABLED") + --eventFrame:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED") + eventFrame:RegisterEvent("PLAYER_TALENT_UPDATE") + eventFrame:RegisterEvent("PLAYER_DEAD") + eventFrame:RegisterEvent("PLAYER_ALIVE") + eventFrame:RegisterEvent("PLAYER_UNGHOST") + + eventFrame:SetScript("OnEvent", function(self, event, ...) + eventFunctions[event](...) + end) + + + +-------------------------------------------------------------------------------------------------------------------------------- +--> ~main ~control + + raidStatusLib.mainControl = { + playerAliveStatus = {}, + } + + --send full data (all data available) + function raidStatusLib.mainControl.SendFullData() + + --send cooldown data + raidStatusLib.cooldownManager.SendAllCooldowns() + + --send gear data + raidStatusLib.gearManager.SendAllGearInfo() + end + + raidStatusLib.mainControl.onEnterWorld = function() + --update the alive status of the player + raidStatusLib.UpdatePlayerAliveStatus(true) + + --the game client is fully loadded and all information is available + if (raidStatusLib.IsInGroup()) then + raidStatusLib.Schedules.NewUniqueTimer(1.0, raidStatusLib.mainControl.SendFullData, "mainControl", "sendFullData_Schedule") + raidStatusLib.CanReceiveComms = true + end + end + + raidStatusLib.mainControl.OnEnterGroup = function() + --the player entered in a group + --schedule to send data + raidStatusLib.Schedules.NewUniqueTimer(1.0, raidStatusLib.mainControl.SendFullData, "mainControl", "sendFullData_Schedule") + raidStatusLib.CanReceiveComms = true + end + + raidStatusLib.mainControl.OnLeftGroup = function() + --the player left a group + --wipe group data (each module registers the OnLeftGroup) + + --cancel all schedules + raidStatusLib.Schedules.CancelAllUniqueTimers() + + --wipe alive status + table.wipe(raidStatusLib.mainControl.playerAliveStatus) + + --toggle off comms + raidStatusLib.CanReceiveComms = false + end + + raidStatusLib.mainControl.OnPlayerDeath = function() + local playerName = UnitName("player") + raidStatusLib.mainControl.playerAliveStatus[playerName] = false + + local dataToSend = CONST_COMM_PLAYER_DEAD_PREFIX + raidStatusLib.commHandler.SendCommData(dataToSend) + diagnosticComm("OnPlayerDeath| " .. dataToSend) --debug + + raidStatusLib.publicCallback.TriggerCallback("OnPlayerDeath", playerName) + end + + raidStatusLib.mainControl.OnPlayerRess = function() + local playerName = UnitName("player") + raidStatusLib.mainControl.playerAliveStatus[playerName] = true + + local dataToSend = CONST_COMM_PLAYER_ALIVE_PREFIX + raidStatusLib.commHandler.SendCommData(dataToSend) + diagnosticComm("OnPlayerRess| " .. dataToSend) --debug + + raidStatusLib.publicCallback.TriggerCallback("OnPlayerRess", playerName) + end + + raidStatusLib.internalCallback.RegisterCallback("onEnterWorld", raidStatusLib.mainControl.onEnterWorld) + raidStatusLib.internalCallback.RegisterCallback("onEnterGroup", raidStatusLib.mainControl.OnEnterGroup) + raidStatusLib.internalCallback.RegisterCallback("onLeaveGroup", raidStatusLib.mainControl.OnLeftGroup) + raidStatusLib.internalCallback.RegisterCallback("onPlayerDeath", raidStatusLib.mainControl.OnPlayerDeath) + raidStatusLib.internalCallback.RegisterCallback("onPlayerRess", raidStatusLib.mainControl.OnPlayerRess) + + --a player in the group died + raidStatusLib.commHandler.RegisterComm(CONST_COMM_PLAYER_DEAD_PREFIX, function(data, sourceName) + raidStatusLib.mainControl.playerAliveStatus[sourceName] = false + raidStatusLib.publicCallback.TriggerCallback("OnPlayerDeath", sourceName) + end) + + --a player in the group is now alive + raidStatusLib.commHandler.RegisterComm(CONST_COMM_PLAYER_ALIVE_PREFIX, function(data, sourceName) + raidStatusLib.mainControl.playerAliveStatus[sourceName] = true + raidStatusLib.publicCallback.TriggerCallback("OnPlayerRess", sourceName) + end) + +-------------------------------------------------------------------------------------------------------------------------------- +--> ~cooldowns + raidStatusLib.cooldownManager = { + playerData = {}, --stores the list of cooldowns each player has sent + playerCurrentCooldowns = {}, + cooldownTickers = {}, --store C_Timer.NewTicker + } + + --check if a cooldown has changed or done + local cooldownTimeLeftCheck = function(tickerObject) + local spellId = tickerObject.spellId + tickerObject.cooldownTimeLeft = tickerObject.cooldownTimeLeft - CONST_COOLDOWN_CHECK_INTERVAL + local timeLeft, charges = raidStatusLib.cooldownManager.GetCooldownStatus(spellId) + + --is the spell ready to use? + if (timeLeft == 0) then + --it's ready + raidStatusLib.cooldownManager.SendCooldownUpdate(spellId, 0, charges) + raidStatusLib.cooldownManager.cooldownTickers[spellId] = nil + tickerObject:Cancel() + else + --check if the time left has changed + if (not raidStatusLib.isNearlyEqual(tickerObject.cooldownTimeLeft, timeLeft, CONST_COOLDOWN_TIMELEFT_HAS_CHANGED)) then + --there's a deviation, send a comm to communicate the change in the time left + raidStatusLib.cooldownManager.SendCooldownUpdate(spellId, timeLeft, charges) + tickerObject.cooldownTimeLeft = timeLeft + end + end + end + + --after a spell is casted by the player, start a ticker to check its cooldown + local cooldownStartTicker = function(spellId, cooldownTimeLeft) + local existingTicker = raidStatusLib.cooldownManager.cooldownTickers[spellId] + if (existingTicker) then + --is a ticker already exists, might be the cooldown of a charge + --if the ticker isn't about to expire, just keep the timer + --when the ticker finishes it'll check again for charges + if (existingTicker.startTime + existingTicker.cooldownTime - GetTime() > 2) then + return + end + + --cancel the existing ticker + if (not existingTicker._cancelled) then + existingTicker:Cancel() + end + end + + --create a new ticker + local maxTicks = ceil(cooldownTimeLeft / CONST_COOLDOWN_CHECK_INTERVAL) + local newTicker = C_Timer.NewTicker(CONST_COOLDOWN_CHECK_INTERVAL, cooldownTimeLeftCheck, maxTicks) + + --store the ticker + raidStatusLib.cooldownManager.cooldownTickers[spellId] = newTicker + newTicker.spellId = spellId + newTicker.cooldownTimeLeft = cooldownTimeLeft + newTicker.startTime = GetTime() + newTicker.endTime = GetTime() + cooldownTimeLeft + end + + local cooldownGetUnitTable = function(unitName, shouldWipe) + local unitCooldownTable = raidStatusLib.cooldownManager.playerData[unitName] + --check if the unit has a cooldownTable + if (not unitCooldownTable) then + unitCooldownTable = {} + raidStatusLib.cooldownManager.playerData[unitName] = unitCooldownTable + else + --as the unit could have changed a talent or spec, wipe the table before using it + if (shouldWipe) then + table.wipe(unitCooldownTable) + end + end + + return unitCooldownTable + end + + --update a single spell time and charges + --called when the player casted a cooldown and when received a cooldown update from another player + local singleCooldownUpdate = function(unitName, spellId, newTimeLeft, newCharges) + local unitCooldownTable = cooldownGetUnitTable(unitName) + local spellIdTable = unitCooldownTable[spellId] or {} + spellIdTable[1] = newTimeLeft + spellIdTable[2] = newCharges + unitCooldownTable[spellId] = spellIdTable + end + + function raidStatusLib.cooldownManager.GetCooldownTable() + return raidStatusLib.cooldownManager.playerData + end + + function raidStatusLib.cooldownManager.GetPlayerCooldownTable(playerName) + return raidStatusLib.cooldownManager.playerData[playerName] + end + + function raidStatusLib.cooldownManager.OnPlayerCast(event, spellId) + --player casted a spell, check if the spell is registered as cooldown + local playerSpec = raidStatusLib.GetPlayerSpecId() + if (playerSpec) then + if (LIB_RAID_STATUS_COOLDOWNS_BY_SPEC[playerSpec] and LIB_RAID_STATUS_COOLDOWNS_BY_SPEC[playerSpec][spellId]) then + --get the cooldown time for this spell + local timeLeft, charges = raidStatusLib.cooldownManager.GetCooldownStatus(spellId) + + local playerName = UnitName("player") + + --update the time left + singleCooldownUpdate(playerName, spellId, timeLeft, charges) + + --trigger a public callback + raidStatusLib.publicCallback.TriggerCallback("CooldownUpdate", playerName, spellId, timeLeft, charges, raidStatusLib.cooldownManager.playerData) + + --send to comm + raidStatusLib.cooldownManager.SendCooldownUpdate(spellId, timeLeft, charges) + + --create a timer to monitor the time of this cooldown + --as there's just a few of them to monitor, there's no issue on creating one timer per spell + cooldownStartTicker(spellId, timeLeft) + end + end + end + raidStatusLib.internalCallback.RegisterCallback("playerCast", raidStatusLib.cooldownManager.OnPlayerCast) + + --received a cooldown update from another unit (sent by the function above) + raidStatusLib.commHandler.RegisterComm(CONST_COMM_COOLDOWNUPDATE_PREFIX, function(data, sourceName) + --get data + local dataAsArray = data + local spellId = tonumber(dataAsArray[2]) + local cooldownTimer = tonumber(dataAsArray[3]) + local charges = tonumber(dataAsArray[4]) + + --check integraty + if (not spellId or spellId == 0) then + return diagnosticError("cooldownManager|comm received|spellId is invalid") + + elseif (not cooldownTimer) then + return diagnosticError("cooldownManager|comm received|cooldownTimer is invalid") + + elseif (not charges) then + return diagnosticError("cooldownManager|comm received|charges is invalid") + end + + --update + singleCooldownUpdate(sourceName, spellId, cooldownTimer, charges) + + --trigger a public callback + raidStatusLib.publicCallback.TriggerCallback("CooldownUpdate", sourceName, spellId, cooldownTimer, charges, raidStatusLib.cooldownManager.playerData) + end) + + --when the player is ressed while in a group, send the cooldown list + function raidStatusLib.cooldownManager.OnPlayerRess() + --check if is in group + if (raidStatusLib.IsInGroup()) then + raidStatusLib.Schedules.NewUniqueTimer(1.0 + math.random(0.0, 6.0), raidStatusLib.cooldownManager.SendAllCooldowns, "cooldownManager", "sendAllCooldowns_Schedule") + end + end + raidStatusLib.internalCallback.RegisterCallback("onPlayerRess", raidStatusLib.cooldownManager.OnPlayerRess) + + --clear data stored + function raidStatusLib.cooldownManager.EraseData() + table.wipe(raidStatusLib.cooldownManager.playerData) + end + + function raidStatusLib.cooldownManager.OnLeaveGroup() + --clear the data + raidStatusLib.cooldownManager.EraseData() + + --trigger a public callback + raidStatusLib.publicCallback.TriggerCallback("CooldownListWiped", raidStatusLib.cooldownManager.playerData) + end + raidStatusLib.internalCallback.RegisterCallback("onLeaveGroup", raidStatusLib.cooldownManager.OnLeaveGroup) + + --adds a list of cooldowns for another player in the group + --this is called from the received cooldown list from comm + function raidStatusLib.cooldownManager.AddUnitCooldownsList(unitName, cooldownsTable) + local unitCooldownTable = cooldownGetUnitTable(unitName, true) + raidStatusLib.TCopy(unitCooldownTable, cooldownsTable) + + --trigger a public callback + raidStatusLib.publicCallback.TriggerCallback("CooldownListUpdate", unitName, raidStatusLib.cooldownManager.playerData) + end + + --check if a player cooldown is ready or if is in cooldown + --@spellId: the spellId to check for cooldown + function raidStatusLib.cooldownManager.GetCooldownStatus(spellId) + --check if is a charge spell + local cooldownInfo = LIB_RAID_STATUS_COOLDOWNS_INFO[spellId] + if (cooldownInfo.charges and cooldownInfo.charges > 1) then + local chargesAvailable, chargesTotal, start, duration = GetSpellCharges(spellId) + + if (chargesAvailable == chargesTotal) then + return 0, chargesTotal --all charges are ready to use + else + --return the time to the next charge + local timeLeft = start + duration - GetTime() + return ceil(timeLeft), chargesAvailable + end + + else + local start, duration = GetSpellCooldown(spellId) + if (start == 0) then --cooldown is ready + return 0, 1 + else + local timeLeft = start + duration - GetTime() + return ceil(timeLeft), 0 + end + end + end + + --send to comm all cooldowns available for the player + function raidStatusLib.cooldownManager.SendAllCooldowns() + --get the full cooldown list + local playerCooldownList = raidStatusLib.cooldownManager.GetPlayerCooldownList() + local dataToSend = CONST_COMM_COOLDOWNFULLLIST_PREFIX .. "," + --pack + + local playerCooldownString = raidStatusLib.PackTable(playerCooldownList) + dataToSend = dataToSend .. playerCooldownString + + --send the data + raidStatusLib.commHandler.SendCommData(dataToSend) + diagnosticComm("SendAllCooldowns| " .. dataToSend) --debug + end + + --send to comm a specific cooldown that was just used, a charge got available or its cooldown is over (ready to use) + function raidStatusLib.cooldownManager.SendCooldownUpdate(spellId, cooldownTimeLeft, charges) + local dataToSend = CONST_COMM_COOLDOWNUPDATE_PREFIX .. "," .. spellId .. "," .. cooldownTimeLeft .. "," .. charges + raidStatusLib.commHandler.SendCommData(dataToSend) + diagnosticComm("SendCooldownUpdate| " .. dataToSend) --debug + end + + --triggered when the lib receives a full list of cooldowns from another player in the raid + --@data: table received from comm + --@source: player name + function raidStatusLib.cooldownManager.OnReceiveCooldowns(data, source) + --unpack the table as a pairs table + local unpackedTable = raidStatusLib.UnpackTable(data, 1, true, true, 3) + --add the list of cooldowns + raidStatusLib.cooldownManager.AddUnitCooldownsList(source, unpackedTable) + end + raidStatusLib.commHandler.RegisterComm(CONST_COMM_COOLDOWNFULLLIST_PREFIX, raidStatusLib.cooldownManager.OnReceiveCooldowns) + + + + --build a list with the local player cooldowns + function raidStatusLib.cooldownManager.GetPlayerCooldownList() + --get the player specId + local specId = raidStatusLib.GetPlayerSpecId() + if (specId) then + --get the cooldowns for the specialization + local playerCooldowns = LIB_RAID_STATUS_COOLDOWNS_BY_SPEC[specId] + if (not playerCooldowns) then + diagnosticError("cooldownManager|GetPlayerCooldownList|can't find player cooldowns for specId:", specId) + return {} + end + + local cooldowns = {} + local talentsHash, talentsIndex = raidStatusLib.GetPlayerTalents() + + for cooldownSpellId, cooldownType in pairs(playerCooldowns) do + --get all the information about this cooldow + local cooldownInfo = LIB_RAID_STATUS_COOLDOWNS_INFO[cooldownSpellId] + if (cooldownInfo) then + --does this cooldown is based on a talent? + local talentId = cooldownInfo.talent + if (talentId) then + --check if the player has the talent selected + if (talentsHash[talentId]) then + cooldowns[#cooldowns+1] = cooldownSpellId + local timeLeft, charges = raidStatusLib.cooldownManager.GetCooldownStatus(cooldownSpellId) + cooldowns[#cooldowns+1] = timeLeft + cooldowns[#cooldowns+1] = charges + end + else + cooldowns[#cooldowns+1] = cooldownSpellId + local timeLeft, charges = raidStatusLib.cooldownManager.GetCooldownStatus(cooldownSpellId) + cooldowns[#cooldowns+1] = timeLeft + cooldowns[#cooldowns+1] = charges + end + end + end + return cooldowns + else + return {} + end + end + +-------------------------------------------------------------------------------------------------------------------------------- +--> ~equipment + + raidStatusLib.gearManager = { + --structure: + --[playerName] = {ilevel = 100, durability = 100, weaponEnchant = 0, noGems = {}, noEnchants = {}} + playerData = {}, + } + + function raidStatusLib.gearManager.GetGearTable() + return raidStatusLib.gearManager.playerData + end + + function raidStatusLib.gearManager.GetPlayerGearTable(playerName, createNew) + local playerGearInfo = raidStatusLib.gearManager.playerData[playerName] + if (not playerGearInfo and createNew) then + playerGearInfo = { + ilevel = 0, + durability = 0, + weaponEnchant = 0, + noGems = {}, + noEnchants = {}, + } + raidStatusLib.gearManager.playerData[playerName] = playerGearInfo + end + return playerGearInfo + end + + --return an integer between zero and one hundret indicating the player gear durability + function raidStatusLib.gearManager.GetGearDurability() + 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 + + --clear data stored + function raidStatusLib.gearManager.EraseData() + table.wipe(raidStatusLib.gearManager.playerData) + end + + function raidStatusLib.gearManager.OnLeaveGroup() + --clear the data + raidStatusLib.gearManager.EraseData() + + --trigger a public callback + raidStatusLib.publicCallback.TriggerCallback("GearListWiped", raidStatusLib.gearManager.playerData) + end + raidStatusLib.internalCallback.RegisterCallback("onLeaveGroup", raidStatusLib.gearManager.OnLeaveGroup) + + --when the player is ressed while in a group, send the cooldown list + function raidStatusLib.gearManager.OnPlayerRess() + --check if is in group + if (raidStatusLib.IsInGroup()) then + raidStatusLib.Schedules.NewUniqueTimer(1.0 + math.random(0.0, 6.0), raidStatusLib.gearManager.SendDurability, "gearManager", "sendDurability_Schedule") + end + end + raidStatusLib.internalCallback.RegisterCallback("onPlayerRess", raidStatusLib.gearManager.OnPlayerRess) + + --send only the gear durability + function raidStatusLib.gearManager.SendDurability() + local dataToSend = CONST_COMM_GEARINFO_DURABILITY_PREFIX .. "," + local playerGearDurability = raidStatusLib.gearManager.GetGearDurability() + + dataToSend = dataToSend .. playerGearDurability + + --send the data + raidStatusLib.commHandler.SendCommData(dataToSend) + diagnosticComm("SendGearDurabilityData| " .. dataToSend) --debug + end + + function raidStatusLib.gearManager.OnReceiveGearDurability(data, source) + local durability = tonumber(data[1]) + raidStatusLib.gearManager.UpdateUnitGearDurability(source, durability) + end + raidStatusLib.commHandler.RegisterComm(CONST_COMM_GEARINFO_DURABILITY_PREFIX, raidStatusLib.gearManager.OnReceiveGearDurability) + + --on receive the durability (sent when the player get a ress) + function raidStatusLib.gearManager.UpdateUnitGearDurability(playerName, durability) + local playerGearInfo = raidStatusLib.gearManager.GetPlayerGearTable(playerName) + if (playerGearInfo) then + playerGearInfo.durability = durability + raidStatusLib.publicCallback.TriggerCallback("GearDurabilityUpdate", playerName, durability, raidStatusLib.gearManager.GetGearTable()) + end + end + + --get gear information from what the player has equipped at the moment + function raidStatusLib.gearManager.GetPlayerGearInfo() + + --get the player class and specId + local _, playerClass = UnitClass("player") + local specId = raidStatusLib.GetPlayerSpecId() + --get which attribute the spec uses + local specMainAttribute = raidStatusLib.specAttribute[playerClass][specId] --1 int, 2 dex, 3 str + + if (not specId or not specMainAttribute) then + return {0, 0, 0, {}, {}} + end + + --item level + local _, itemLevel = GetAverageItemLevel() + itemLevel = floor(itemLevel) + + --repair status + local gearDurability = raidStatusLib.gearManager.GetGearDurability() + + --get weapon enchant + local weaponEnchant = 0 + local _, _, _, mainHandEnchantId, _, _, _, offHandEnchantId = GetWeaponEnchantInfo() + if (LIB_RAID_STATUS_WEAPON_ENCHANT_IDS[mainHandEnchantId]) then + weaponEnchant = 1 + + elseif(LIB_RAID_STATUS_WEAPON_ENCHANT_IDS[offHandEnchantId]) then + weaponEnchant = 1 + end + + --enchants and gems + --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_RAID_STATUS_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_RAID_STATUS_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_RAID_STATUS_GEM_IDS[gemId]) then + slotsWithoutGems[#slotsWithoutGems+1] = equipmentSlotId + + end + end + end + end + end --end of enchants and gems + + --build the table with the gear information + local playerGearInfo = {} + playerGearInfo[#playerGearInfo+1] = itemLevel --[1] + playerGearInfo[#playerGearInfo+1] = gearDurability --[2] + playerGearInfo[#playerGearInfo+1] = weaponEnchant --[3] + playerGearInfo[#playerGearInfo+1] = slotsWithoutEnchant --[4] + playerGearInfo[#playerGearInfo+1] = slotsWithoutGems --[5] + + --update the player table + raidStatusLib.gearManager.AddUnitGearInfoList(UnitName("player"), itemLevel, gearDurability, weaponEnchant, slotsWithoutEnchant, slotsWithoutGems) + + return playerGearInfo + end + + --when received the gear update from another player, store it and trigger a callback + function raidStatusLib.gearManager.AddUnitGearInfoList(playerName, itemLevel, durability, weaponEnchant, noEnchantTable, noGemsTable) + local playerGearInfo = raidStatusLib.gearManager.GetPlayerGearTable(playerName, true) + + playerGearInfo.ilevel = itemLevel + playerGearInfo.durability = durability + playerGearInfo.weaponEnchant = weaponEnchant + playerGearInfo.noGems = noGemsTable + playerGearInfo.noEnchants = noEnchantTable + + raidStatusLib.publicCallback.TriggerCallback("GearUpdate", playerName, playerGearInfo, raidStatusLib.gearManager.GetGearTable()) + end + + --triggered when the lib receives a gear information from another player in the raid + --@data: table received from comm + --@source: player name + function raidStatusLib.gearManager.OnReceiveGearFullInfo(data, source) + local itemLevel = tonumber(data[1]) + local durability = tonumber(data[2]) + local weaponEnchant = tonumber(data[3]) + + local noEnchantTableSize = tonumber(data[4]) + local noGemsTableIndex = tonumber(noEnchantTableSize + 5) + local noGemsTableSize = data[noGemsTableIndex] + + --raidStatusLib.UnpackTable(table, index, isPair, valueIsTable, amountOfValues) + + --unpack the enchant data as a ipairs table + local noEnchantTableUnpacked = raidStatusLib.UnpackTable(data, 4, false, false, noEnchantTableSize) + --unpack the enchant data as a ipairs table + local noGemsTableUnpacked = raidStatusLib.UnpackTable(data, noGemsTableIndex, false, false, noGemsTableSize) + + --add to the list of gear information + raidStatusLib.gearManager.AddUnitGearInfoList(source, itemLevel, durability, weaponEnchant, noEnchantTableUnpacked, noGemsTableUnpacked) + end + raidStatusLib.commHandler.RegisterComm(CONST_COMM_GEARINFO_FULL_PREFIX, raidStatusLib.gearManager.OnReceiveGearFullInfo) + + function raidStatusLib.gearManager.SendAllGearInfo() + --get gear information, gear info has 4 indexes: + --[1] int item level + --[2] int durability + --[3] int weapon enchant + --[3] table with integers of equipSlot without enchant + --[4] table with integers of equipSlot which has a gem slot but the slot is empty + + local dataToSend = CONST_COMM_GEARINFO_FULL_PREFIX .. "," + local playerGearInfo = raidStatusLib.gearManager.GetPlayerGearInfo() + + dataToSend = dataToSend .. playerGearInfo[1] .. "," --item level + dataToSend = dataToSend .. playerGearInfo[2] .. "," --durability + dataToSend = dataToSend .. playerGearInfo[3] .. "," --weapon enchant + dataToSend = dataToSend .. raidStatusLib.PackTable(playerGearInfo[4]) .. "," --slots without enchant + dataToSend = dataToSend .. raidStatusLib.PackTable(playerGearInfo[5]) -- slots with empty gem sockets + + --send the data + raidStatusLib.commHandler.SendCommData(dataToSend) + diagnosticComm("SendGearFullData| " .. dataToSend) --debug + end + + +-------------------------------------------------------------------------------------------------------------------------------- +--> ~player general info + +raidStatusLib.playerInfoManager = {} + +function raidStatusLib.playerInfoManager.GetPlayerInfo() + local playerInfo = {} + --name + playerInfo[1] = UnitName("player") + + --spec + + --talents + + --renown + + --conduits + +end + + + + +-------------------------------------------------------------------------------------------------------------------------------- +--> data + +--which is the main attribute of each spec +--1 Intellect +--2 Agility +--3 Strenth +raidStatusLib.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, + } +} \ No newline at end of file diff --git a/Libs/LibRaidStatus/LibRaidStatus.toc b/Libs/LibRaidStatus/LibRaidStatus.toc new file mode 100644 index 00000000..063bfa59 --- /dev/null +++ b/Libs/LibRaidStatus/LibRaidStatus.toc @@ -0,0 +1,5 @@ +## Interface: 90002 +## Title: Library Raid Status +## Notes: This is a library used by addons. + +lib.xml diff --git a/Libs/LibRaidStatus/ThingsToMantain.lua b/Libs/LibRaidStatus/ThingsToMantain.lua new file mode 100644 index 00000000..a1b9b70e --- /dev/null +++ b/Libs/LibRaidStatus/ThingsToMantain.lua @@ -0,0 +1,789 @@ + +--data which main need maintenance over time + +if (not LIB_RAID_STATUS_CAN_LOAD) then + return +end + +--which gear slots can be enchanted on the latest retail version of the game +--when the value is a number, the slot only receives enchants for a specific attribute +LIB_RAID_STATUS_ENCHANT_SLOTS = { + --[INVSLOT_NECK] = true, + + [INVSLOT_BACK] = true, --for all + [INVSLOT_CHEST] = true, --for all + [INVSLOT_FINGER1] = true, --for all + [INVSLOT_FINGER2] = true, --for all + [INVSLOT_MAINHAND] = true, --for all + + [INVSLOT_FEET] = 2, --agility only + [INVSLOT_WRIST] = 1, --intellect only + [INVSLOT_HAND] = 3, --strenth only +} + +-- how to get the enchantId: +-- local itemLink = GetInventoryItemLink("player", slotId) +-- local enchandId = select (3, strsplit(":", itemLink)) +-- print("enchantId:", enchandId) +LIB_RAID_STATUS_ENCHANT_IDS = { + --FEET + --[6207] = INVSLOT_FEET, --[Enchant Boots - Speed of Soul] + [6211] = INVSLOT_FEET, --[Enchant Boots - Eternal Agility] + 15 agi + [6212] = INVSLOT_FEET, --[Enchant Boots - Agile Soulwalker] + 10 agi + + --WRIST + --[6222] = INVSLOT_WRIST, [Enchant Bracers - Shaded Hearthing] + [6219] = INVSLOT_WRIST, --[Enchant Bracers - Illuminated Soul] + 10 int + [6220] = INVSLOT_WRIST, --[Enchant Bracers - Eternal Intellect] + 15 int + + --HAND + --[6205] = INVSLOT_HAND, --[Enchant Gloves - Shadowlands Gathering] + [6209] = INVSLOT_HAND, --[Enchant Gloves - Strength of Soul] +10 str + [6210] = INVSLOT_HAND, --[Enchant Gloves - Eternal Strength] +15 str + + --FINGER + [6164] = INVSLOT_FINGER1, --[Enchant Ring - Tenet of Critical Strike] +16 + [6166] = INVSLOT_FINGER1, --[Enchant Ring - Tenet of Haste] +16 + [6168] = INVSLOT_FINGER1, --[Enchant Ring - Tenet of Mastery] +16 + [6170] = INVSLOT_FINGER1, --[Enchant Ring - Tenet of Versatility] +16 + + --BACK + [6202] = INVSLOT_BACK, --[Enchant Cloak - Fortified Speed] +20 stam +30 speed + [6203] = INVSLOT_BACK, --[Enchant Cloak - Fortified Avoidance] +20 stam +30 avoidance + [6204] = INVSLOT_BACK, --[Enchant Cloak - Fortified Leech] + [6208] = INVSLOT_BACK, --[Enchant Cloak - Soul Vitality] + + --CHEST + [6213] = INVSLOT_CHEST, --[Enchant Chest - Eternal Bulwark] +25 armor +20 agi or str + [6214] = INVSLOT_CHEST, --[Enchant Chest - Eternal Skirmish] +20 agi or str +more white damage + [6217] = INVSLOT_CHEST, --[Enchant Chest - Eternal Bounds] +20 int + 6% mana + [6216] = INVSLOT_CHEST, --[Enchant Chest - Sacred Stats] +20 all stats + [6230] = INVSLOT_CHEST, --[Enchant Chest - Eternal Stats] +30 all stats + + --MAINHAND + [6223] = INVSLOT_MAINHAND, --[Enchant Weapon - Lightless Force] + shadow wave damage + [6226] = INVSLOT_MAINHAND, --[Enchant Weapon - Eternal Grace] + burst of healing done + [6227] = INVSLOT_MAINHAND, --[Enchant Weapon - Ascended Vigor] + healing received increased + [6228] = INVSLOT_MAINHAND, --[Enchant Weapon - Sinful Revelation] + 6% bleed damage + [6229] = INVSLOT_MAINHAND, --[Enchant Weapon - Celestial Guidance] + 5% agility +} + +-- how to get the gemId: +-- local itemLink = GetInventoryItemLink("player", slotId) +-- local gemId = select (4, strsplit(":", itemLink)) +-- print("gemId:", gemId) +LIB_RAID_STATUS_GEM_IDS = { + [173126] = true, --Straddling Jewel Doublet (green, +12 speed) + [173125] = true, --Revitalizing Jewel Doublet (green, +100 health) + [173130] = true, --Masterful Jewel Cluster (blue, master) + [173129] = true, --Versatile Jewel Cluster (blue, versatility) + [173127] = true, --Deadly Jewel Cluster (blue, crit) + [173128] = true, --Quick Jewel Cluster (blue, haste) +} + +LIB_RAID_STATUS_WEAPON_ENCHANT_IDS = { + [6188] = true, --shadowcore oil + [6190] = true, --embalmer's oil + [6201] = true, --weighted + [6200] = true, --sharpened + [5400] = true, --flametongue + [5401] = true, --windfury +} + +LIB_RAID_STATUS_COOLDOWNS_BY_SPEC = { + -- 1 attack cooldown + -- 2 personal defensive cooldown + -- 3 targetted defensive cooldown + -- 4 raid defensive cooldown + -- 5 personal utility cooldown + + --Shadowlands 9.0.2 revision by Juliana Maison + + --MAGE + --arcane + [62] = { + [12042] = 1, --Arcane Power + [55342] = 1, --Mirror Image + [45438] = 2, --Ice Block + [12051] = 5, --Evocation + [110960] = 5, --Greater Invisibility + [235450] = 5, --Prismatic Barrier + }, + --fire + [63] = { + [190319] = 1, --Combustion + [55342] = 1, --Mirror Image + [45438] = 2, --Ice Block + [66] = 5, --Invisibility + [235313] = 5, --Blazing Barrier + }, + --frost + [64] = { + [12472] = 1, --Icy Veins + [205021] = 1, --Ray of Frost (talent) + [55342] = 1, --Mirror Image + [45438] = 2, --Ice Block + [66] = 5, --Invisibility + [235219] = 5, --Cold Snap + [11426] = 5, --Ice Barrier + [113724] = 5, --Ring of Frost (talent) + }, + + --PRIEST + --discipline + [256] = { + [10060] = 1, --Power Infusion + [34433] = 1, --Shadowfiend + [123040] = 1, --Mindbender + [33206] = 3, --Pain Suppression + [62618] = 4, --Power Word: Barrier + [271466] = 4, --Luminous Barrier (talent) + [109964] = 4, --Spirit Shell (talent) + [47536] = 5, --Rapture + [19236] = 5, --Desperate Prayer + [8122] = 5, --Psychic Scream + }, + --holy + [257] = { + [10060] = 1, --Power Infusion + [200183] = 2, --Apotheosis + [47788] = 3, --Guardian Spirit + [64844] = 4, --Divine Hymn + [64901] = 4, --Symbol of Hope + [265202] = 4, --Holy Word: Salvation (talent) + [88625] = 5, --Holy Word: Chastise + [34861] = 5, --Holy Word: Sanctify + [2050] = 5, --Holy Word: Serenity + [19236] = 5, --Desperate Prayer + [8122] = 5, --Psychic Scream + }, + --shadow priest + [258] = { + [10060] = 1, --Power Infusion + [34433] = 1, --Shadowfiend + [200174] = 1, --Mindbender + [205385] = 1, --Shadow Clash + [193223] = 1, --Surrender to Madness + [47585] = 2, --Dispersion + [15286] = 4, --Vampiric Embrace + [19236] = 5, --Desperate Prayer + [64044] = 5, --Psychic Horror + [8122] = 5, --Psychic Scream + [205369] = 5, --Mind Bomb + }, + + --ROGUE + --assassination + [259] = { + [79140] = 1, --Vendetta + [1856] = 2, --Vanish + [5277] = 2, --Evasion + [31224] = 2, --Cloak of Shadows + [2094] = 5, --Blind + [185311] = 5, --Crimson Vial + [114018] = 5, --Shroud of Concealment + }, + --outlaw + [260] = { + [13750] = 1, --Adrenaline Rush + [51690] = 1, --Killing Spree (talent) + [199754] = 2, --Riposte + [31224] = 2, --Cloak of Shadows + [5277] = 2, --Evasion + [1856] = 2, --Vanish + [2094] = 5, --Blind + [185311] = 5, --Crimson Vial + [114018] = 5, --Shroud of Concealment + [343142] = 5, --Dreadblades + }, + --subtlety + [261] = { + [121471] = 1, --Shadow Blades + [31224] = 2, --Cloak of Shadows + [1856] = 2, --Vanish + [5277] = 2, --Evasion + [2094] = 5, --Blind + [185311] = 5, --Crimson Vial + [114018] = 5, --Shroud of Concealment + }, + + --WARLOCK + --affliction + [265] = { + [205180] = 1, --Summon Darkglare + [342601] = 1, --Ritual of Doom + [113860] = 1, --Dark Soul: Misery (talent) + [104773] = 2, --Unending Resolve + [108416] = 2, --Dark Pact (talent) + [30283] = 5, --Shadowfury + [6789] = 5, --Mortal Coil (talent) + [333889] = 5, --Fel Domination + }, + --demonology + [266] = { + [265187] = 1, --Summon Demonic Tyrant + [342601] = 1, --Ritual of Doom + [267171] = 1, --Demonic Strength (talent) + [111898] = 1, --Grimoire: Felguard (talent) + [267217] = 1, --Nether Portal (talent) + + [104773] = 2, --Unending Resolve + [108416] = 2, --Dark Pact (talent) + + [30283] = 5, --Shadowfury + [6789] = 5, --Mortal Coil (talent) + [5484] = 5, --Howl of Terror (talent) + [333889] = 5, --Fel Domination + }, + --destruction + [267] = { + [1122] = 1, --Summon Infernal + [342601] = 1, --Ritual of Doom + [113858] = 1, --Dark Soul: Instability (talent) + [104773] = 2, --Unending Resolve + [108416] = 2, --Dark Pact (talent) + [6789] = 5, --Mortal Coil (talent) + [30283] = 5, --Shadowfury + [333889] = 5, --Fel Domination + }, + + --WARRIOR + --Arms + [71] = { + [107574] = 1, --Avatar (talent) + [227847] = 1, --Bladestorm + [152277] = 1, --Ravager (talent) + [118038] = 2, --Die by the Sword + [97462] = 4, --Rallying Cry + [64382] = 5, --Shattering Throw + [18499] = 5, --Berserker Rage + [5246] = 5, --Intimidating Shout + }, + --Fury + [72] = { + [1719] = 1, --Recklessness + [46924] = 1, --Bladestorm (talent) + [184364] = 2, --Enraged Regeneration + [97462] = 4, --Rallying Cry + [64382] = 5, --Shattering Throw + [18499] = 5, --Berserker Rage + [5246] = 5, --Intimidating Shout + }, + --Protection + [73] = { + [228920] = 1, --Ravager (talent) + [107574] = 1, --Avatar + [12975] = 2, --Last Stand + [871] = 2, --Shield Wall + [97462] = 4, --Rallying Cry + [64382] = 5, --Shattering Throw + [18499] = 5, --Berserker Rage + [5246] = 5, --Intimidating Shout + }, + + --PALADIN + --holy + [65] = { + [31884] = 1, --Avenging Wrath + [216331] = 1, --Avenging Crusader (talent) + [498] = 2, --Divine Protection + [642] = 2, --Divine Shield + [105809] = 2, --Holy Avenger (talent) + [152262] = 2, --Seraphim + [633] = 3, --Lay on Hands + [1022] = 3, --Blessing of Protection + [6940] = 3, --Blessing of Sacrifice + [31821] = 4, --Aura Mastery + [1044] = 5, --Blessing of Freedom + [853] = 5, --Hammer of Justice + [115750] = 5, --Blinding Light (talent) + }, + + --protection + [66] = { + [31884] = 1, --Avenging Wrath + [327193] = 1, --Moment of Glory (talent) + [31850] = 2, --Ardent Defender + [86659] = 2, --Guardian of Ancient Kings + [105809] = 2, --Holy Avenger (talent) + [152262] = 2, --Seraphim + [1022] = 3, --Blessing of Protection + [204018] = 3, --Blessing of Spellwarding (talent) + [6940] = 3, --Blessing of Sacrifice + [1044] = 5, --Blessing of Freedom + [853] = 5, --Hammer of Justice + [115750] = 5, --Blinding Light (talent) + }, + + --retribution + [70] = { + [31884] = 1, --Avenging Wrath + [231895] = 1, --Crusade (talent) + [205191] = 2, --Eye for an Eye (talent) + [184662] = 2, --Shield of Vengeance + [642] = 2, --Divine Shield + [1022] = 3, --Blessing of Protection + [6940] = 3, --Blessing of Sacrifice + [633] = 3, --Lay on Hands + [1044] = 5, --Blessing of Freedom + [853] = 5, --Hammer of Justice + [115750] = 5, --Blinding Light (talent) + }, + + --DEMON HUNTER + --havoc + [577] = { + [200166] = 1, --Metamorphosis + [198589] = 2, --Blur + [196555] = 2, --Netherwalk (talent) + [196718] = 4, --Darkness + [188501] = 5, --Spectral Sight + [179057] = 5, --Chaos Nova + [211881] = 5, --Fel Eruption (talent) + }, + --vengeance + [581] = { + [320341] = 1, --Bulk Extraction (talent) + [187827] = 2, --Metamorphosis + [204021] = 2, --Fiery Brand + [263648] = 2, --Soul Barrier (talent) + [207684] = 5, --Sigil of Misery + [202137] = 5, --Sigil of Silence + [202138] = 5, --Sigil of Chains (talent) + [188501] = 5, --Spectral Sight + }, + + --DEATH KNIGHT + --unholy + [252] = { + [275699] = 1, --Apocalypse + [42650] = 1, --Army of the Dead + [49206] = 1, --Summon Gargoyle (talent) + [207289] = 1, --Unholy Assault (talent) + [48707] = 2, --Anti-magic Shell + [48792] = 2, --Icebound Fortitude + [48743] = 2, --Death Pact (talent) + [51052] = 4, --Anti-magic Zone + [108194] = 5, --Asphyxiate (talent) + [287081] = 5, --Lichborne + [212552] = 5, --Wraith walk (talent) + + }, + --frost + [251] = { + [152279] = 1, --Breath of Sindragosa (talent) + [47568] = 1, --Empower Rune Weapon + [279302] = 1, --Frostwyrm's Fury + [48707] = 2, --Anti-magic Shell + [48792] = 2, --Icebound Fortitude + [48743] = 2, --Death Pact (talent) + [51052] = 4, --Anti-magic Zone + [207167] = 5, --Blinding Sleet (talent) + [108194] = 5, --Asphyxiate (talent) + [287081] = 5, --Lichborne + [212552] = 5, --Wraith walk (talent) + }, + --blood + [250] = { + [49028] = 1, --Dancing Rune Weapon + [48707] = 2, --Anti-magic Shell + [48743] = 2, --Death Pact (talent) + [219809] = 2, --Tombstone (talent) + [55233] = 2, --Vampiric Blood + [48792] = 2, --Icebound Fortitude + [51052] = 4, --Anti-magic Zone + [108199] = 5, --Gorefiend's Grasp + [221562] = 5, --Asphyxiate + [212552] = 5, --Wraith walk (talent) + }, + + --DRUID + --Balance + [102] = { + [194223] = 1, --Celestial Alignment + [102560] = 1, --Incarnation: Chosen of Elune (talent) + [22812] = 2, --Barkskin + [108238] = 2, --Renewal (talent) + [29166] = 3, --Innervate + [77761] = 4, --Stampeding Roar + [99] = 5, --Incapacitating Roar + [319454] = 5, --Heart of the Wild (talent) + [132469] = 5, --Typhoon + [78675] = 5, --Solar Beam + }, + --Feral + [103] = { + [106951] = 1, --Berserk + [102543] = 1, --Incarnation: King of the Jungle (talent) + [22812] = 2, --Barkskin + [61336] = 2, --Survival Instincts + [108238] = 2, --Renewal (talent) + [77764] = 4, --Stampeding Roar + [132469] = 5, --Typhoon + [319454] = 5, --Heart of the Wild (talent) + }, + --Guardian + [104] = { + [106951] = 1, --Berserk + [204066] = 1, --Lunar Beam + [22812] = 2, --Barkskin + [61336] = 2, --Survival Instincts + [102558] = 2, --Incarnation: Guardian of Ursoc (talent) + [108238] = 2, --Renewal (talent) + [77761] = 4, --Stampeding Roar + [132469] = 5, --Typhoon + [99] = 5, --Incapacitating Roar + [319454] = 5, --Heart of the Wild (talent) + }, + --Restoration + [105] = { + + [22812] = 2, --Barkskin + [108238] = 2, --Renewal (talent) + [33891] = 2, --Incarnation: Tree of Life (talent) + [102342] = 3, --Ironbark + [29166] = 3, --Innervate + [203651] = 3, --Overgrowth (talent) + [740] = 4, --Tranquility + [197721] = 4, --Flourish (talent) + [77761] = 4, --Stampeding Roar + [319454] = 5, --Heart of the Wild (talent) + [102793] = 5, --Ursol's Vortex + }, + + --HUNTER + --beast mastery + [253] = { + [193530] = 1, --Aspect of the Wild + [19574] = 1, --Bestial Wrath + [201430] = 1, --Stampede (talent) + [186265] = 2, --Aspect of the Turtle + [109304] = 2, --Exhilaration + [199483] = 2, --Camouflage (talent) + [186257] = 5, --Aspect of the cheetah + [19577] = 5, --Intimidation + [109248] = 5, --Binding Shot (talent) + [187650] = 5, --Freezing Trap + }, + --marksmanship + [254] = { + [193526] = 1, --Trueshot + [260402] = 1, --Double tap + [186265] = 2, --Aspect of the Turtle + [199483] = 2, --Camouflage (talent) + [109304] = 2, --Exhilaration + [281195] = 2, --Survival of the Fittest + [186257] = 5, --Aspect of the cheetah + [187650] = 5, --Freezing Trap + }, + --survival + [255] = { + [266779] = 1, --Coordinated Assault + [186265] = 2, --Aspect of the Turtle + [199483] = 2, --Camouflage (talent) + [109304] = 2, --Exhilaration + [186289] = 5, --Aspect of the eagle + [19577] = 5, --Intimidation + [187650] = 5, --Freezing Trap + }, + + --MONK + --brewmaster + [268] = { + [132578] = 1, --Invoke Niuzao, the Black Ox + [115080] = 1, --Touch of Death + [115203] = 2, --Fortifying Brew + [115399] = 2, --Black Ox brew (talent) + [115176] = 2, --Zen Meditation + [122278] = 2, --Dampen Harm (talent) + [116844] = 5, --Ring of peace (talent) + [119381] = 5, --Leg Sweep + }, + --windwalker + [269] = { + [137639] = 1, --Storm, Earth, and Fire + [123904] = 1, --Invoke Xuen, the White Tiger + [152173] = 1, --Serenity (talent) + [115080] = 1, --Touch of Death + [115203] = 2, --Fortifying Brew + [122470] = 2, --Touch of Karma + [122278] = 2, --Dampen Harm (talent) + [122783] = 2, --Diffuse Magic (talent) + [116844] = 5, --Ring of peace (talent) + [119381] = 5, --Leg Sweep + }, + --mistweaver + [270] = { + [115080] = 1, --Touch of Death + [122278] = 2, --Dampen Harm (talent) + [243435] = 2, --Fortifying Brew + [122783] = 2, --Diffuse Magic (talent) + [116849] = 3, --Life Cocoon + [322118] = 4, --Invoke Yulon, the Jade serpent +-- [198664] = 4, --Invoke Chi-Ji, the Red Crane (talent) + [115310] = 4, --Revival + [116844] = 5, --Ring of peace (talent) + [197908] = 5, --Mana tea (talent) + [119381] = 5, --Leg Sweep + }, + + --SHAMAN + --elemental + [262] = { + [198067] = 1, --Fire Elemental + [192249] = 1, --Storm Elemental (talent) + [114050] = 1, --Ascendance (talent) + [108271] = 2, --Astral Shift + [108281] = 4, --Ancestral Guidance (talent) + [198103] = 2, --Earth Elemental + [79206] = 5, --Spiritwalkers grace + [65992] = 5, --Tremor Totem + [192058] = 5, --Capacitor Totem + [192077] = 5, --Wind Rush Totem (talent) + }, + --enhancement + [263] = { + [51533] = 1, --Feral Spirit + [114051] = 1, --Ascendance (talent) + [108271] = 2, --Astral Shift + [198103] = 2, --Earth Elemental + [65992] = 5, --Tremor Totem + [192058] = 5, --Capacitor Totem + + }, + --restoration + [264] = { + [108271] = 2, --Astral Shift + [114052] = 2, --Ascendance (talent) + [98008] = 4, --Spirit Link Totem + [108280] = 4, --Healing Tide Totem + [16191] = 4, --Mana Tide Totem + [207399] = 4, --Ancestral Protection Totem (talent) + [198103] = 2, --Earth Elemental + [65992] = 5, --Tremor Totem + }, +} + +--tells the duration, requirements and cooldown +--information about a cooldown is mainly get from tooltips +--if talent is required, use the command: +--/dump GetTalentInfo (talentTier, talentColumn, 1) +--example: to get the second talent of the last talent line, use: /dump GetTalentInfo (7, 2, 1) +LIB_RAID_STATUS_COOLDOWNS_INFO = { + --> paladin + [31884] = {cooldown = 120, duration = 20, talent = false, charges = 1, class = "PALADIN", type = 1}, --Avenging Wrath + [216331] = {cooldown = 120, duration = 20, talent = 22190, charges = 1, class = "PALADIN", type = 1}, --Avenging Crusader (talent) + [498] = {cooldown = 60, duration = 8, talent = false, charges = 1, class = "PALADIN", type = 2}, --Divine Protection + [642] = {cooldown = 300, duration = 8, talent = false, charges = 1, class = "PALADIN", type = 2}, --Divine Shield + [105809] = {cooldown = 90, duration = 20, talent = 22164, charges = 1, class = "PALADIN", type = 2}, --Holy Avenger (talent) + [152262] = { cooldown = 45, duration = 15, talent = 17601, charges = 1, class = "PALADIN", type = 2}, --Seraphim + [633] = {cooldown = 600, duration = false, talent = false, charges = 1, class = "PALADIN", type = 3}, --Lay on Hands + [1022] = {cooldown = 300, duration = 10, talent = false, charges = 1, class = "PALADIN", type = 3}, --Blessing of Protection + [6940] = {cooldown = 120, duration = 12, talent = false, charges = 1, class = "PALADIN", type = 3}, --Blessing of Sacrifice + [31821] = {cooldown = 180, duration = 8, talent = false, charges = 1, class = "PALADIN", type = 4}, --Aura Mastery + [1044] = {cooldown = 25, duration = 8, talent = false, charges = 1, class = "PALADIN", type = 5}, --Blessing of Freedom + [853] = {cooldown = 60, duration = 6, talent = false, charges = 1, class = "PALADIN", type = 5}, --Hammer of Justice + [115750] = {cooldown = 90, duration = 6, talent = 21811, charges = 1, class = "PALADIN", type = 5}, --Blinding Light(talent) + [327193] = {cooldown = 90, duration = 15, talent = 23468, charges = 1, class = "PALADIN", type = 1}, --Moment of Glory (talent) + [31850] = {cooldown = 120, duration = 8, talent = false, charges = 1, class = "PALADIN", type = 2}, --Ardent Defender + [86659] = {cooldown = 300, duration = 8, talent = false, charges = 1, class = "PALADIN", type = 2}, --Guardian of Ancient Kings + [204018] = {cooldown = 180, duration = 10, talent = 22435, charges = 1, class = "PALADIN", type = 3}, --Blessing of Spellwarding (talent) + [231895] = {cooldown = 120, duration = 25, talent = 22215, charges = 1, class = "PALADIN", type = 1}, --Crusade (talent) + [205191] = {cooldown = 60, duration = 10, talent = 22183, charges = 1, class = "PALADIN", type = 2}, --Eye for an Eye (talent) + [184662] = {cooldown = 120, duration = 15, talent = false, charges = 1, class = "PALADIN", type = 2}, --Shield of Vengeance + + --> warrior + [107574] = {cooldown = 90, duration = 20, talent = 22397, charges = 1, class = "WARRIOR", type = 1}, --Avatar + [227847] = {cooldown = 90, duration = 5, talent = false, charges = 1, class = "WARRIOR", type = 1}, --Bladestorm + [152277] = {cooldown = 60, duration = 6, talent = 21667, charges = 1, class = "WARRIOR", type = 1}, --Ravager (talent) + [118038] = {cooldown = 180, duration = 8, talent = false, charges = 1, class = "WARRIOR", type = 2}, --Die by the Sword + [97462] = {cooldown = 180, duration = 10, talent = false, charges = 1, class = "WARRIOR", type = 4}, --Rallying Cry + [1719] = {cooldown = 90, duration = 10, talent = false, charges = 1, class = "WARRIOR", type = 1}, --Recklessness + [46924] = {cooldown = 60, duration = 4, talent = 22400, charges = 1, class = "WARRIOR", type = 1}, --Bladestorm (talent) + [184364] = {cooldown = 120, duration = 8, talent = false, charges = 1, class = "WARRIOR", type = 2}, --Enraged Regeneration + [228920] = {cooldown = 60, duration = 6, talent = 23099, charges = 1, class = "WARRIOR", type = 1}, --Ravager (talent) + [12975] = {cooldown = 180, duration = 15, talent = false, charges = 1, class = "WARRIOR", type = 2}, --Last Stand + [871] = {cooldown = 8, duration = 240, talent = false, charges = 1, class = "WARRIOR", type = 2}, --Shield Wall + [64382] = {cooldown = 180, duration = false, talent = false, charges = 1, class = "WARRIOR", type = 5}, --Shattering Throw + [5246] = {cooldown = 90, duration = 8, talent = false, charges = 1, class = "WARRIOR", type = 5}, --Intimidating Shout + + + --> warlock + [205180] = {cooldown = 180, duration = 20, talent = false, charges = 1, class = "WARLOCK", type = 1}, --Summon Darkglare + [342601] = {cooldown = 3600, duration = false, talent = false, charges = 1, class = "WARLOCK", type = 1}, --Ritual of Doom + [113860] = {cooldown = 120, duration = 20, talent = 19293, charges = 1, class = "WARLOCK", type = 1}, --Dark Soul: Misery (talent) + [104773] = {cooldown = 180, duration = 8, talent = false, charges = 1, class = "WARLOCK", type = 2}, --Unending Resolve + [108416] = {cooldown = 60, duration = 20, talent = 19286, charges = 1, class = "WARLOCK", type = 2}, --Dark Pact (talent) + [265187] = {cooldown = 90, duration = 15, talent = false, charges = 1, class = "WARLOCK", type = 1}, --Summon Demonic Tyrant + [111898] = {cooldown = 120, duration = 15, talent = 21717, charges = 1, class = "WARLOCK", type = 1}, --Grimoire: Felguard (talent) + [267171] = {cooldown = 60, duration = false, talent = 23138, charges = 1, class = "WARLOCK", type = 1}, --Demonic Strength (talent) + [267217] = {cooldown = 180, duration = 20, talent = 23091, charges = 1, class = "WARLOCK", type = 1}, --Nether Portal + [1122] = {cooldown = 180, duration = 30, talent = false, charges = 1, class = "WARLOCK", type = 1}, --Summon Infernal + [113858] = {cooldown = 120, duration = 20, talent = 23092, charges = 1, class = "WARLOCK", type = 1}, --Dark Soul: Instability (talent) + [30283] = {cooldown = 60, duration = 3, talent = false, charges = 1, class = "WARLOCK", type = 5}, --Shadowfury + [333889] = {cooldown = 180, duration = 15, talent = false, charges = 1, class = "WARLOCK", type = 5}, --Fel Domination + + --> shaman + [198067] = {cooldown = 150, duration = 30, talent = false, charges = 1, class = "SHAMAN", type = 1}, --Fire Elemental + [192249] = {cooldown = 150, duration = 30, talent = 19272, charges = 1, class = "SHAMAN", type = 1}, --Storm Elemental (talent) + [108271] = {cooldown = 90, duration = 8, talent = false, charges = 1, class = "SHAMAN", type = 2}, --Astral Shift + [108281] = {cooldown = 120, duration = 10, talent = 22172, charges = 1, class = "SHAMAN", type = 4}, --Ancestral Guidance (talent) + [51533] = {cooldown = 120, duration = 15, talent = false, charges = 1, class = "SHAMAN", type = 1}, --Feral Spirit + [114050] = {cooldown = 180, duration = 15, talent = 21675, charges = 1, class = "SHAMAN", type = 1}, --Ascendance (talent) + [114051] = {cooldown = 180, duration = 15, talent = 21972, charges = 1, class = "SHAMAN", type = 1}, --Ascendance (talent) + [114052] = {cooldown = 180, duration = 15, talent = 22359, charges = 1, class = "SHAMAN", type = 2}, --Ascendance (talent) + [98008] = {cooldown = 180, duration = 6, talent = false, charges = 1, class = "SHAMAN", type = 4}, --Spirit Link Totem + [108280] = {cooldown = 180, duration = 10, talent = false, charges = 1, class = "SHAMAN", type = 4}, --Healing Tide Totem + [207399] = {cooldown = 240, duration = 30, talent = 22323, charges = 1, class = "SHAMAN", type = 4}, --Ancestral Protection Totem (talent) + [16191] = {cooldown = 180, duration = 8, talent = false, charges = 1, class = "SHAMAN", type = 4}, --Mana Tide Totem + [198103] = {cooldown = 300, duration = 60, talent = false, charges = 1, class = "SHAMAN", type = 2}, --Earth Elemental + [192058] = {cooldown = 60, duration = false, talent = false, charges = 1, class = "SHAMAN", type = 5}, --Capacitor Totem + [65992] = {cooldown = 60, duration = 10, talent = false, charges = 1, class = "SHAMAN", type = 5}, --Tremor Totem + [192077] = {cooldown = 120, duration = 15, talent = 21966, charges = 1, class = "SHAMAN", type = 5}, --Wind Rush Totem (talent) + + --> monk + [132578] = {cooldown = 180, duration = 25, talent = false, charges = 1, class = "MONK", type = 1}, --Invoke Niuzao, the Black Ox + [115080] = {cooldown = 180, duration = false, talent = false, charges = 1, class = "MONK", type = 1}, --Touch of Death + [115203] = {cooldown = 420, duration = 15, talent = false, charges = 1, class = "MONK", type = 2}, --Fortifying Brew + [115176] = {cooldown = 300, duration = 8, talent = false, charges = 1, class = "MONK", type = 2}, --Zen Meditation + [115399] = {cooldown = 120, duration = false, talent = 19992, charges = 1, class = "MONK", type = 2}, --Black Ox brew (talent) + [122278] = {cooldown = 120, duration = 10, talent = 20175, charges = 1, class = "MONK", type = 2}, --Dampen Harm (talent) + [137639] = {cooldown = 90, duration = 15, talent = false, charges = 1, class = "MONK", type = 1}, --Storm, Earth, and Fire + [123904] = {cooldown = 120, duration = 24, talent = false, charges = 1, class = "MONK", type = 1}, --Invoke Xuen, the White Tiger + [152173] = {cooldown = 90, duration = 12, talent = 21191, charges = 1, class = "MONK", type = 1}, --Serenity (talent) + [122470] = {cooldown = 90, duration = 6, talent = false, charges = 1, class = "MONK", type = 2}, --Touch of Karma + [322118] = {cooldown = 180, duration = 25, talent = false, charges = 1, class = "MONK", type = 4}, --Invoke Yulon, the Jade serpent +-- [198664] = {cooldown = 180, duration = 25, talent = 22214, charges = 1, class = "MONK", type = 4}, --Invoke Chi-Ji, the Red Crane (talent) + [243435] = {cooldown = 90, duration = 15, talent = false, charges = 1, class = "MONK", type = 2}, --Fortifying Brew + [122783] = {cooldown = 90, duration = 6, talent = 20173, charges = 1, class = "MONK", type = 2}, --Diffuse Magic (talent) + [116849] = {cooldown = 120, duration = 12, talent = false, charges = 1, class = "MONK", type = 3}, --Life Cocoon + [115310] = {cooldown = 180, duration = false, talent = false, charges = 1, class = "MONK", type = 4}, --Revival + [197908] = {cooldown = 90, duration = 10, talent = 22166, charges = 1, class = "MONK", type = 5}, --Mana tea (talent) + [116844] = {cooldown = 45, duration = 5, talent = 19995, charges = 1, class = "MONK", type = 5}, --Ring of peace (talent) + [119381] = {cooldown = 50, duration = 3, talent = false, charges = 1, class = "MONK", type = 5}, --Leg Sweep + + --> hunter + [193530] = {cooldown = 120, duration = 20, talent = false, charges = 1, class = "HUNTER", type = 1}, --Aspect of the Wild + [19574] = {cooldown = 90, duration = 12, talent = false, charges = 1, class = "HUNTER", type = 1}, --Bestial Wrath + [201430] = {cooldown = 180, duration = 12, talent = 23044, charges = 1, class = "HUNTER", type = 1}, --Stampede (talent) + [193526] = {cooldown = 180, duration = 15, talent = false, charges = 1, class = "HUNTER", type = 1}, --Trueshot + [199483] = {cooldown = 60, duration = 60, talent = 23100, charges = 1, class = "HUNTER", type = 2}, --Camouflage (talent) + [281195] = {cooldown = 180, duration = 6, talent = false, charges = 1, class = "HUNTER", type = 2}, --Survival of the Fittest + [266779] = {cooldown = 120, duration = 20, talent = false, charges = 1, class = "HUNTER", type = 1}, --Coordinated Assault + [186265] = {cooldown = 180, duration = 8, talent = false, charges = 1, class = "HUNTER", type = 2}, --Aspect of the Turtle + [109304] = {cooldown = 120, duration = false, talent = false, charges = 1, class = "HUNTER", type = 2}, --Exhilaration + [186257] = {cooldown = 144, duration = 14, talent = false, charges = 1, class = "HUNTER", type = 5}, --Aspect of the cheetah + [19577] = {cooldown = 60, duration = 5, talent = false, charges = 1, class = "HUNTER", type = 5}, --Intimidation + [109248] = {cooldown = 45, duration = 10, talent = 22499, charges = 1, class = "HUNTER", type = 5}, --Binding Shot (talent) + [187650] = {cooldown = 25, duration = 60, talent = false, charges = 1, class = "HUNTER", type = 5}, --Freezing Trap + [186289] = {cooldown = 72, duration = 15, talent = false, charges = 1, class = "HUNTER", type = 5}, --Aspect of the eagle + + --> druid + [194223] = {cooldown = 180, duration = 20, talent = false, charges = 1, class = "DRUID", type = 1}, --Celestial Alignment + [102560] = {cooldown = 180, duration = 30, talent = 21702, charges = 1, class = "DRUID", type = 1}, --Incarnation: Chosen of Elune (talent) + [22812] = {cooldown = 60, duration = 12, talent = false, charges = 1, class = "DRUID", type = 2}, --Barkskin + [108238] = {cooldown = 90, duration = false, talent = 18570, charges = 1, class = "DRUID", type = 2}, --Renewal (talent) + [29166] = {cooldown = 180, duration = 12, talent = false, charges = 1, class = "DRUID", type = 3}, --Innervate + [78675] = {cooldown = 60, duration = 8, talent = false, charges = 1, class = "DRUID", type = 5}, --Solar Beam + [106951] = {cooldown = 180, duration = 15, talent = false, charges = 1, class = "DRUID", type = 1}, --Berserk + [102543] = {cooldown = 30, duration = 180, talent = 21704, charges = 1, class = "DRUID", type = 1}, --Incarnation: King of the Jungle (talent) + [61336] = {cooldown = 120, duration = 6, talent = false, charges = 2, class = "DRUID", type = 2}, --Survival Instincts (2min feral 4min guardian, same spellid) + [77764] = {cooldown = 120, duration = 8, talent = false, charges = 1, class = "DRUID", type = 4}, --Stampeding Roar (utility) + [102558] = {cooldown = 180, duration = 30, talent = 22388, charges = 1, class = "DRUID", type = 2}, --Incarnation: Guardian of Ursoc (talent) + [33891] = {cooldown = 180, duration = 30, talent = 22421, charges = 1, class = "DRUID", type = 2}, --Incarnation: Tree of Life (talent) + [102342] = {cooldown = 60, duration = 12, talent = false, charges = 1, class = "DRUID", type = 3}, --Ironbark + [203651] = {cooldown = 60, duration = false, talent = 22422, charges = 1, class = "DRUID", type = 3}, --Overgrowth (talent) + [740] = {cooldown = 180, duration = 8, talent = false, charges = 1, class = "DRUID", type = 4}, --Tranquility + [197721] = {cooldown = 90, duration = 8, talent = 22404, charges = 1, class = "DRUID", type = 4}, --Flourish (talent) + [132469] = {cooldown = 30, duration = false, talent = false, charges = 1, class = "DRUID", type = 5}, --Typhoon + [319454] = {cooldown = 300, duration = 45, talent = 18577, charges = 1, class = "DRUID", type = 5}, --Heart of the Wild (talent) + + --> death knight + [275699] = {cooldown = 90, duration = 15, talent = false, charges = 1, class = "DEATHKNIGHT", type = 1}, --Apocalypse + [42650] = {cooldown = 480, duration = 30, talent = false, charges = 1, class = "DEATHKNIGHT", type = 1}, --Army of the Dead + [49206] = {cooldown = 180, duration = 30, talent = 22110, charges = 1, class = "DEATHKNIGHT", type = 1}, --Summon Gargoyle (talent) + [207289] = {cooldown = 78, duration = 12, talent = 22538, charges = 1, class = "DEATHKNIGHT", type = 1}, --Unholy Assault (talent) + [48743] = {cooldown = 120, duration = 15, talent = 23373, charges = 1, class = "DEATHKNIGHT", type = 2}, --Death Pact (talent) + [48707] = {cooldown = 60, duration = 10, talent = 23373, charges = 1, class = "DEATHKNIGHT", type = 2}, --Anti-magic Shell + [152279] = {cooldown = 120, duration = 5, talent = 22537, charges = 1, class = "DEATHKNIGHT", type = 1}, --Breath of Sindragosa (talent) + [47568] = {cooldown = 120, duration = 20, talent = false, charges = 1, class = "DEATHKNIGHT", type = 1}, --Empower Rune Weapon + [279302] = {cooldown = 120, duration = 10, talent = 22535, charges = 1, class = "DEATHKNIGHT", type = 1}, --Frostwyrm's Fury (talent) + [49028] = {cooldown = 120, duration = 8, talent = false, charges = 1, class = "DEATHKNIGHT", type = 1}, --Dancing Rune Weapon + [55233] = {cooldown = 90, duration = 10, talent = false, charges = 1, class = "DEATHKNIGHT", type = 2}, --Vampiric Blood + [48792] = {cooldown = 120, duration = 8, talent = false, charges = 1, class = "DEATHKNIGHT", type = 2}, --Icebound Fortitude + [51052] = {cooldown = 120, duration = 10, talent = false, charges = 1, class = "DEATHKNIGHT", type = 4}, --Anti-magic Zone + [219809] = {cooldown = 60, duration = 8, talent = 23454, charges = 1, class = "DEATHKNIGHT", type = 2}, --Tombstone (talent) + [108199] = {cooldown = 120, duration = false, talent = false, charges = 1, class = "DEATHKNIGHT", type = 5}, --Gorefiend's Grasp + [207167] = {cooldown = 60, duration = 5, talent = 22519, charges = 1, class = "DEATHKNIGHT", type = 5}, --Blinding Sleet (talent) + [108194] = {cooldown = 45, duration = 4, talent = 22520, charges = 1, class = "DEATHKNIGHT", type = 5}, --Asphyxiate (talent) + [221562] = {cooldown = 45, duration = 5, talent = false, charges = 1, class = "DEATHKNIGHT", type = 5}, --Asphyxiate + + --> demon hunter + [200166] = {cooldown = 240, duration = 30, talent = false, charges = 1, class = "DEMONHUNTER", type = 1}, --Metamorphosis + [198589] = {cooldown = 60, duration = 10, talent = false, charges = 1, class = "DEMONHUNTER", type = 2}, --Blur + [196555] = {cooldown = 120, duration = 5, talent = 21865, charges = 1, class = "DEMONHUNTER", type = 2}, --Netherwalk (talent) + [196718] = {cooldown = 180, duration = 8, talent = false, charges = 1, class = "DEMONHUNTER", type = 4}, --Darkness + [187827] = {cooldown = 180, duration = 15, talent = false, charges = 1, class = "DEMONHUNTER", type = 2}, --Metamorphosis + [196718] = {cooldown = 180, duration = 8, talent = false, charges = 1, class = "DEMONHUNTER", type = 4}, --Darkness + [188501] = {cooldown = 30, duration = 10, talent = false, charges = 1, class = "DEMONHUNTER", type = 5}, --Spectral Sight + [179057] = {cooldown = 60, duration = 2, talent = false, charges = 1, class = "DEMONHUNTER", type = 5}, --Chaos Nova + [211881] = {cooldown = 30, duration = 4, talent = 22767, charges = 1, class = "DEMONHUNTER", type = 5}, --Fel Eruption (talent) + [320341] = {cooldown = 90, duration = false, talent = 21902, charges = 1, class = "DEMONHUNTER", type = 1}, --Bulk Extraction (talent) + [204021] = {cooldown = 60, duration = 10, talent = false, charges = 1, class = "DEMONHUNTER", type = 2}, --Fiery Brand + [263648] = {cooldown = 30, duration = 12, talent = 22768, charges = 1, class = "DEMONHUNTER", type = 2}, --Soul Barrier (talent) + [207684] = {cooldown = 90, duration = 12, talent = false, charges = 1, class = "DEMONHUNTER", type = 5}, --Sigil of Misery + [202137] = {cooldown = 60, duration = 8, talent = false, charges = 1, class = "DEMONHUNTER", type = 5}, --Sigil of Silence + [202138] = {cooldown = 90, duration = 6, talent = 22511, charges = 1, class = "DEMONHUNTER", type = 5}, --Sigil of Chains (talent) + + --> mage + [12042] = {cooldown = 90, duration = 10, talent = false, charges = 1, class = "MAGE", type = 1}, --Arcane Power + [12051] = {cooldown = 90, duration = 6, talent = false, charges = 1, class = "MAGE", type = 1}, --Evocation + [110960] = {cooldown = 120, duration = 20, talent = false, charges = 1, class = "MAGE", type = 2}, --Greater Invisibility + [235450] = {cooldown = 25, duration = 60, talent = false, charges = 1, class = "MAGE", type = 5}, --Prismatic Barrier + [235313] = {cooldown = 25, duration = 60, talent = false, charges = 1, class = "MAGE", type = 5}, --Blazing Barrier + [11426] = {cooldown = 25, duration = 60, talent = false, charges = 1, class = "MAGE", type = 5}, --Ice Barrier + [190319] = {cooldown = 120, duration = 10, talent = false, charges = 1, class = "MAGE", type = 1}, --Combustion + [55342] = {cooldown = 120, duration = 40, talent = 22445, charges = 1, class = "MAGE", type = 1}, --Mirror Image + [66] = {cooldown = 300, duration = 20, talent = false, charges = 1, class = "MAGE", type = 2}, --Invisibility + [12472] = {cooldown = 180, duration = 20, talent = false, charges = 1, class = "MAGE", type = 1}, --Icy Veins + [205021] = {cooldown = 78, duration = 5, talent = 22309, charges = 1, class = "MAGE", type = 1}, --Ray of Frost (talent) + [45438] = {cooldown = 240, duration = 10, talent = false, charges = 1, class = "MAGE", type = 2}, --Ice Block + [235219] = {cooldown = 300, duration = false, talent = false, charges = 1, class = "MAGE", type = 5}, --Cold Snap + [113724] = {cooldown = 45, duration = 10, talent = 22471, charges = 1, class = "MAGE", type = 5}, --Ring of Frost (talent) + + --> priest + [10060] = {cooldown = 120, duration = 20, talent = false, charges = 1, class = "PRIEST", type = 1}, --Power Infusion + [34433] = {cooldown = 180, duration = 15, talent = false, charges = 1, class = "PRIEST", type = 1}, --Shadowfiend + [123040] = {cooldown = 60, duration = 12, talent = 22094, charges = 1, class = "PRIEST", type = 1}, --Mindbender (talent) + [33206] = {cooldown = 180, duration = 8, talent = false, charges = 1, class = "PRIEST", type = 3}, --Pain Suppression + [62618] = {cooldown = 180, duration = 10, talent = false, charges = 1, class = "PRIEST", type = 4}, --Power Word: Barrier + [271466] = {cooldown = 180, duration = 10, talent = 21184, charges = 1, class = "PRIEST", type = 4}, --Luminous Barrier (talent) + [47536] = {cooldown = 90, duration = 10, talent = false, charges = 1, class = "PRIEST", type = 5}, --Rapture + [19236] = {cooldown = 90, duration = 10, talent = false, charges = 1, class = "PRIEST", type = 5}, --Desperate Prayer + [200183] = {cooldown = 120, duration = 20, talent = 21644, charges = 1, class = "PRIEST", type = 2}, --Apotheosis (talent) + [47788] = {cooldown = 180, duration = 10, talent = false, charges = 1, class = "PRIEST", type = 3}, --Guardian Spirit + [64844] = {cooldown = 180, duration = 8, talent = false, charges = 1, class = "PRIEST", type = 4}, --Divine Hymn + [64901] = {cooldown = 300, duration = 6, talent = false, charges = 1, class = "PRIEST", type = 4}, --Symbol of Hope + [265202] = {cooldown = 720, duration = false, talent = 23145, charges = 1, class = "PRIEST", type = 4}, --Holy Word: Salvation (talent) + [109964] = {cooldown = 60, duration = 12, talent = 21184, charges = 1, class = "PRIEST", type = 4}, --Spirit Shell (talent) + [8122] = {cooldown = 60, duration = 8, talent = false, charges = 1, class = "PRIEST", type = 5}, --Psychic Scream + [200174] = {cooldown = 60, duration = 15, talent = 21719, charges = 1, class = "PRIEST", type = 1}, --Mindbender (talent) + [193223] = {cooldown = 240, duration = 60, talent = 21979, charges = 1, class = "PRIEST", type = 1}, --Surrender to Madness (talent) + [47585] = {cooldown = 120, duration = 6, talent = false, charges = 1, class = "PRIEST", type = 2}, --Dispersion + [15286] = {cooldown = 120, duration = 15, talent = false, charges = 1, class = "PRIEST", type = 4}, --Vampiric Embrace + + --> rogue + [79140] = {cooldown = 120, duration = 20, talent = false, charges = 1, class = "ROGUE", type = 1}, --Vendetta + [1856] = {cooldown = 120, duration = 3, talent = false, charges = 1, class = "ROGUE", type = 2}, --Vanish + [5277] = {cooldown = 120, duration = 10, talent = false, charges = 1, class = "ROGUE", type = 2}, --Evasion + [31224] = {cooldown = 120, duration = 5, talent = false, charges = 1, class = "ROGUE", type = 2}, --Cloak of Shadows + [2094] = {cooldown = 120, duration = 60, talent = false, charges = 1, class = "ROGUE", type = 5}, --Blind + [114018] = {cooldown = 360, duration = 15, talent = false, charges = 1, class = "ROGUE", type = 5}, --Shroud of Concealment + [185311] = {cooldown = 30, duration = 15, talent = false, charges = 1, class = "ROGUE", type = 5}, --Crimson Vial + [13750] = {cooldown = 180, duration = 20, talent = false, charges = 1, class = "ROGUE", type = 1}, --Adrenaline Rush + [51690] = {cooldown = 120, duration = 2, talent = 23175, charges = 1, class = "ROGUE", type = 1}, --Killing Spree (talent) + [199754] = {cooldown = 120, duration = 10, talent = false, charges = 1, class = "ROGUE", type = 2}, --Riposte + [121471] = {cooldown = 180, duration = 20, talent = false, charges = 1, class = "ROGUE", type = 1}, --Shadow Blades + [343142] = {cooldown = 90, duration = 10, talent = 19250, charges = 1, class = "ROGUE", type = 5}, --Dreadblades + [121471] = {cooldown = 180, duration = 20, talent = false, charges = 1, class = "ROGUE", type = 1}, --Shadow Blades +} \ No newline at end of file diff --git a/Libs/LibRaidStatus/docs.txt b/Libs/LibRaidStatus/docs.txt new file mode 100644 index 00000000..123748f5 --- /dev/null +++ b/Libs/LibRaidStatus/docs.txt @@ -0,0 +1,99 @@ + +Functions: + +local playerGearInfo = raidStatusLib.gearManager.GetPlayerGearTable(playerName) +playerGearInfo = { + .durability = number + .ilevel = number + .noGems = {socketId} + .noEnchants = {socketId} +} + + + +Callbacks available + +"CooldownListUpdate": triggers when the lib received a list of cooldowns from another player in the group. + +function MyAddonObject.OnReceiveCooldownListUpdate(unitName, cooldownTable) + --foreach player in the cooldown table + for unitName, playerCooldownTable in pairs(cooldownTable) do + for spellId, cooldownInfoTable in pairs(playerCooldownTable) do + --if timeLeft is zero, the spell is ready + local timeLeft = cooldownInfoTable[1] + --in some cases the spell is on cooldown but there's a charge to use + local charges = cooldownInfoTable[2] + end + end + + --get the cooldowns for the unit which got the cooldown update + local unitCooldownTable = cooldownTable[unitName] + for spellId, cooldownInfoTable in pairs(unitCooldownTable) do + --if timeLeft is zero, the spell is ready + local timeLeft = cooldownInfoTable[1] + --in some cases the spell is on cooldown but there's a charge to use + local charges = cooldownInfoTable[2] + end +end +raidStatusLib.RegisterCallback(MyAddonObject, "CooldownListUpdate", "OnReceiveCooldownListUpdate") + + +"CooldownUpdate": triggered when any unit in the group used a cooldown or the timeleft got an update + +function MyAddonObject.OnReceiveCooldownUpdate(unitName, spellId, cooldownTimeLeft, charges, playerCooldownTable) + local unitCooldowns = cooldownTable[unitName] + local cooldownTimeLeft2 = unitCooldowns[spellId] + print("is iqual:", cooldownTimeLeft == cooldownTimeLeft2) + + --get the cooldowns for the unit which got the cooldown update + for spellId, cooldownInfoTable in pairs(playerCooldownTable) do + --if timeLeft is zero, the spell is ready + local timeLeft = cooldownInfoTable[1] + --in some cases the spell is on cooldown but there's a charge to use + local charges = cooldownInfoTable[2] + end +end +raidStatusLib.RegisterCallback(MyAddonObject, "CooldownUpdate", "OnReceiveCooldownUpdate") + + +"CooldownListWiped": when the list of cooldowns get a wipe, usually when the player leave the group + +function MyAddonObject.OnCooldownListWipe(cooldownTable) + print ("is nil:", next(cooldownTable)) +end +raidStatusLib.RegisterCallback(MyAddonObject, "CooldownListWiped", "OnCooldownListWipe") + + +"GearDurabilityUpdate": when a player in the group revives, the gear durability is sent + +function MyAddonObject.OnGearDurabilityUpdate(playerName, durability, gearTable) + print(playerName .. " durability is now " .. durability) +end +raidStatusLib.RegisterCallback(MyAddonObject, "GearDurabilityUpdate", "OnGearDurabilityUpdate") + + +"GearUpdate": when received an update from a player with all information about the gear + +function MyAddonObject.OnGearUpdate(playerName, playerGearInfo, gearTable) + local itemLevelNumber = playerGearInfo.ilevel + local durabilityNumber = playerGearInfo.durability + --hasWeaponEnchant is 1 have enchant or 0 is don't + local hasWeaponEnchantNumber = playerGearInfo.weaponEnchant + local noEnchantTable = playerGearInfo.noEnchants + local noGemsTable = playerGearInfo.noGems + + for index, slotIdWithoutEnchant in ipairs (noEnchantTable) do + end + + for index, slotIdWithEmptyGemSocket in ipairs (noGemsTable) do + end +end +raidStatusLib.RegisterCallback(MyAddonObject, "GearUpdate", "OnGearUpdate") + + +"GearListWiped": when the list of gear get a wipe, usually when the player leave the group + +function MyAddonObject.OnGearListWiped(gearTable) + print ("is nil:", next(gearTable)) +end +raidStatusLib.RegisterCallback(MyAddonObject, "GearListWiped", "OnGearListWiped") diff --git a/Libs/LibRaidStatus/lib.xml b/Libs/LibRaidStatus/lib.xml new file mode 100644 index 00000000..a5d0a4ee --- /dev/null +++ b/Libs/LibRaidStatus/lib.xml @@ -0,0 +1,5 @@ + +