You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
387 lines
12 KiB
387 lines
12 KiB
local _, addonTable = ...
|
|
|
|
local Collections = {}
|
|
|
|
-- Locals
|
|
local archfragments = {}
|
|
|
|
-- Upvalues
|
|
local R = Rarity
|
|
local CONSTANTS = addonTable.constants
|
|
|
|
-- Lua APIs
|
|
local pairs = pairs
|
|
local type = type
|
|
local select = select
|
|
local tonumber = tonumber
|
|
|
|
-- WOW APIs
|
|
local PlayerHasToy = PlayerHasToy
|
|
local InCombatLockdown = InCombatLockdown
|
|
local C_TransmogCollection = C_TransmogCollection
|
|
local C_MountJournal = C_MountJournal
|
|
local C_PetJournal = C_PetJournal
|
|
local GetNumCompanions = GetNumCompanions
|
|
local GetCompanionInfo = GetCompanionInfo
|
|
local GetAchievementInfo = GetAchievementInfo
|
|
local GetNumArchaeologyRaces = GetNumArchaeologyRaces
|
|
local GetNumArtifactsByRace = GetNumArtifactsByRace
|
|
local GetArtifactInfoByRace = GetArtifactInfoByRace
|
|
local IsQuestComplete = _G.C_QuestLog.IsComplete
|
|
local GetArchaeologyRaceInfo = GetArchaeologyRaceInfo
|
|
local GetActiveArtifactByRace = GetActiveArtifactByRace
|
|
|
|
function Collections:ScanTransmog(reason)
|
|
self = Rarity
|
|
self:Debug("Scanning transmog (" .. (reason or "") .. ")")
|
|
|
|
for k, v in pairs(R.db.profile.groups) do
|
|
if type(v) == "table" then
|
|
for kk, vv in pairs(v) do
|
|
if type(vv) == "table" then
|
|
if vv.itemId and not vv.repeatable and select(2, C_TransmogCollection.GetItemInfo(vv.itemId)) then -- Don't scan for items that aren't gear that have a transmog collection appearance
|
|
if C_TransmogCollection.PlayerHasTransmog(vv.itemId) then -- You have the appearance of the item you're tracking
|
|
vv.known = true
|
|
vv.enabled = false
|
|
vv.found = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function Collections:ScanToys(reason)
|
|
self = Rarity
|
|
self:Debug("Scanning toys (" .. (reason or "") .. ")")
|
|
|
|
-- Load the Collections add-on if needed
|
|
if not Rarity.toysScanned then
|
|
if not ToyBox_OnLoad then
|
|
self:Debug("Loading Blizzard_Collections addon so the ToyBox can be scanned")
|
|
UIParentLoadAddOn("Blizzard_Collections")
|
|
end
|
|
end
|
|
|
|
-- Scan all Rarity items to see if we already have a toy
|
|
Rarity.toysScanned = true
|
|
for k, v in pairs(R.db.profile.groups) do
|
|
if type(v) == "table" then
|
|
for kk, vv in pairs(v) do
|
|
if type(vv) == "table" then
|
|
if vv.itemId and not vv.repeatable then
|
|
if PlayerHasToy(vv.itemId) then
|
|
vv.known = true
|
|
vv.enabled = false
|
|
vv.found = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function Collections:ScanExistingItems(reason)
|
|
self = Rarity
|
|
-- Don't allow this scan in combat; it takes too long and the script will receive a "script ran too long" error
|
|
-- Under normal conditions this shouldn't be called during combat, except during the 5-minute final init, or
|
|
-- if the user is messing around with Options in combat.
|
|
if InCombatLockdown() then
|
|
return
|
|
end
|
|
|
|
self:Debug("Scanning for existing items (" .. reason .. ")")
|
|
self:ProfileStart()
|
|
|
|
-- Scans need to index by spellId, creatureId, achievementId, raceId, itemId (for toys), statisticId (which is a table; for stats)
|
|
|
|
-- Mounts (pre-7.0)
|
|
if C_MountJournal.GetMountInfo ~= nil then
|
|
-- Mounts (7.0+)
|
|
for id = 1, C_MountJournal.GetNumMounts() do
|
|
local creatureName, spellId, icon, active, isUsable, sourceType, isFavorite, isFactionSpecific, faction, hideOnChar, isCollected =
|
|
C_MountJournal.GetMountInfo(id)
|
|
local creatureDisplayID, descriptionText, sourceText, isSelfMount, mountType =
|
|
C_MountJournal.GetMountInfoExtra(id)
|
|
|
|
Rarity.mount_sources[spellId] = sourceText
|
|
|
|
if isCollected then
|
|
for k, v in pairs(R.db.profile.groups) do
|
|
if type(v) == "table" then
|
|
for kk, vv in pairs(v) do
|
|
if type(vv) == "table" then
|
|
if vv.spellId and vv.spellId == spellId then
|
|
vv.known = true
|
|
end
|
|
if vv.spellId and vv.spellId == spellId and not vv.repeatable then
|
|
vv.enabled = false
|
|
vv.found = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else
|
|
for i, id in pairs(C_MountJournal.GetMountIDs()) do
|
|
local _, spellId, _, _, _, _, _, _, _, _, isCollected = C_MountJournal.GetMountInfoByID(id)
|
|
local _, _, sourceText = C_MountJournal.GetMountInfoExtraByID(id)
|
|
|
|
Rarity.mount_sources[spellId] = sourceText
|
|
|
|
if isCollected then
|
|
for k, v in pairs(R.db.profile.groups) do
|
|
if type(v) == "table" then
|
|
for kk, vv in pairs(v) do
|
|
if type(vv) == "table" then
|
|
if vv.spellId and vv.spellId == spellId then
|
|
vv.known = true
|
|
end
|
|
if vv.spellId and vv.spellId == spellId and not vv.repeatable then
|
|
vv.enabled = false
|
|
vv.found = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Companions that this character learned
|
|
for id = 1, GetNumCompanions("CRITTER") do
|
|
local spellId = select(3, GetCompanionInfo("CRITTER", id))
|
|
for k, v in pairs(R.db.profile.groups) do
|
|
if type(v) == "table" then
|
|
for kk, vv in pairs(v) do
|
|
if type(vv) == "table" then
|
|
if vv.spellId and vv.spellId == spellId and not vv.repeatable then
|
|
vv.enabled = false
|
|
vv.found = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Battle pets across your account
|
|
if C_PetJournal.SetFlagFilter ~= nil then -- Pre-7.0
|
|
C_PetJournal.SetFlagFilter(_G.LE_PET_JOURNAL_FLAG_COLLECTED, true)
|
|
C_PetJournal.SetFlagFilter(_G.LE_PET_JOURNAL_FLAG_FAVORITES, false)
|
|
C_PetJournal.SetFlagFilter(_G.LE_PET_JOURNAL_FLAG_NOT_COLLECTED, true)
|
|
C_PetJournal.AddAllPetTypesFilter()
|
|
C_PetJournal.AddAllPetSourcesFilter()
|
|
else -- 7.0+
|
|
C_PetJournal.SetFilterChecked(_G.LE_PET_JOURNAL_FLAG_COLLECTED, true)
|
|
C_PetJournal.SetFilterChecked(_G.LE_PET_JOURNAL_FLAG_FAVORITES, false)
|
|
C_PetJournal.SetFilterChecked(_G.LE_PET_JOURNAL_FLAG_NOT_COLLECTED, true)
|
|
C_PetJournal.SetAllPetTypesChecked(true)
|
|
C_PetJournal.SetAllPetSourcesChecked(true)
|
|
end
|
|
local total, numOwnedPets = C_PetJournal.GetNumPets()
|
|
for i = 1, total do
|
|
local petID, speciesID, owned, customName, level, favorite, isRevoked, speciesName, icon, petType, companionID, tooltip, description, isWild, canBattle, isTradeable, isUnique, obtainable =
|
|
C_PetJournal.GetPetInfoByIndex(i)
|
|
Rarity.pet_sources[companionID] = tooltip
|
|
if owned then
|
|
for k, v in pairs(R.db.profile.groups) do
|
|
if type(v) == "table" then
|
|
for kk, vv in pairs(v) do
|
|
if type(vv) == "table" then
|
|
if vv.creatureId and vv.creatureId == companionID then
|
|
vv.known = true
|
|
end
|
|
if vv.creatureId and vv.creatureId == companionID and not vv.repeatable then
|
|
vv.enabled = false
|
|
vv.found = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Achievements
|
|
for k, v in pairs(R.db.profile.groups) do
|
|
if type(v) == "table" then
|
|
for kk, vv in pairs(v) do
|
|
if type(vv) == "table" then
|
|
if vv.achievementId and tonumber(vv.achievementId) then
|
|
local IDNumber, Name, Points, Completed, Month, Day, Year, Description, Flags, Image, RewardText, isGuildAch =
|
|
GetAchievementInfo(vv.achievementId)
|
|
if Completed and not vv.repeatable then
|
|
vv.enabled = false
|
|
vv.found = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Scan all archaeology races and set any item attempts to the number of solves for that race
|
|
-- (if we've never seen attempts for the race before)
|
|
local s = 0
|
|
for x = 1, GetNumArchaeologyRaces() do
|
|
local c = GetNumArtifactsByRace(x)
|
|
local a = 0
|
|
for y = 1, c do
|
|
local t = select(10, GetArtifactInfoByRace(x, y))
|
|
a = a + t
|
|
s = s + t
|
|
end
|
|
|
|
for k, v in pairs(self.db.profile.groups) do
|
|
if type(v) == "table" then
|
|
for kk, vv in pairs(v) do
|
|
if type(vv) == "table" then
|
|
if vv.enabled ~= false then
|
|
if vv.method == CONSTANTS.DETECTION_METHODS.ARCH and vv.raceId ~= nil then
|
|
if vv.raceId == x then
|
|
-- We've never seen any attempts for this race yet, so set our attempts to this character's current amount
|
|
if a > (vv.attempts or 0) then
|
|
vv.attempts = a
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Scan all items for Obtained Quest IDs and mark completed if the quest is completed
|
|
for k, v in pairs(R.db.profile.groups) do
|
|
if type(v) == "table" then
|
|
for kk, vv in pairs(v) do
|
|
if type(vv) == "table" then
|
|
if vv.obtainedQuestId and tonumber(vv.obtainedQuestId) then
|
|
if IsQuestComplete(tonumber(vv.obtainedQuestId)) then
|
|
vv.enabled = false
|
|
vv.found = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
self:ProfileStop("ScanExistingItems: Mounts/Pets/Achievements/Archaeology took %fms")
|
|
|
|
-- Other scans
|
|
self:ScanStatistics(reason)
|
|
self:ProfileStart2() -- Statistics does its own profiling
|
|
|
|
Rarity.Collections:ScanToys(reason)
|
|
self:ProfileStop2("Toys took %fms")
|
|
self:ProfileStart2()
|
|
|
|
Rarity.Collections:ScanTransmog(reason)
|
|
self:ProfileStop2("Transmog took %fms")
|
|
self:ProfileStart2()
|
|
|
|
self:ScanCalendar(reason)
|
|
self:ProfileStop2("Calendar took %fms")
|
|
self:ProfileStart2()
|
|
|
|
self:ScanInstanceLocks(reason)
|
|
self:ProfileStop2("Instances took %fms")
|
|
|
|
self:ProfileStop("ScanExistingItems: Total time %fms")
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------
|
|
-- Archaeology detection. Basically we look to see if you spent any fragments, and rescan your projects if so.
|
|
-------------------------------------------------------------------------------------
|
|
|
|
function R:ScanAllArch(event)
|
|
self:UnregisterEvent("RESEARCH_ARTIFACT_HISTORY_READY")
|
|
self:ScanArchFragments(event)
|
|
self:ScanArchProjects(event)
|
|
end
|
|
|
|
function R:ScanArchFragments(event)
|
|
local scan = false
|
|
if GetNumArchaeologyRaces() == 0 then
|
|
return
|
|
end
|
|
for race_id = 1, GetNumArchaeologyRaces() do
|
|
local _, _, _, currencyAmount = GetArchaeologyRaceInfo(race_id)
|
|
local diff = currencyAmount - (archfragments[race_id] or 0)
|
|
archfragments[race_id] = currencyAmount
|
|
if diff < 0 then
|
|
-- We solved an artifact. If any of our items depend on this race ID, increment their attempt count.
|
|
for k, v in pairs(self.db.profile.groups) do
|
|
if type(v) == "table" then
|
|
for kk, vv in pairs(v) do
|
|
if type(vv) == "table" then
|
|
if vv.enabled ~= false then
|
|
local found = false
|
|
if vv.method == CONSTANTS.DETECTION_METHODS.ARCH and vv.raceId ~= nil then
|
|
if vv.raceId == race_id then
|
|
found = true
|
|
end
|
|
end
|
|
if found then
|
|
if vv.attempts == nil then
|
|
vv.attempts = 1
|
|
else
|
|
vv.attempts = vv.attempts + 1
|
|
end
|
|
self:OutputAttempts(vv)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
scan = true
|
|
end
|
|
end
|
|
|
|
-- We solved an artifact; scan projects
|
|
if scan then
|
|
-- Scan now, and later. The server takes a while to decide on the next project. The time it takes varies considerably.
|
|
self:ScanArchProjects(event)
|
|
self:ScheduleTimer(function()
|
|
R:ScanArchProjects("SOLVED AN ARTIFACT - DELAYED 1")
|
|
end, 2)
|
|
self:ScheduleTimer(function()
|
|
R:ScanArchProjects("SOLVED AN ARTIFACT - DELAYED 2")
|
|
end, 5)
|
|
self:ScheduleTimer(function()
|
|
R:ScanArchProjects("SOLVED AN ARTIFACT - DELAYED 3")
|
|
end, 10)
|
|
self:ScheduleTimer(function()
|
|
R:ScanArchProjects("SOLVED AN ARTIFACT - DELAYED 4")
|
|
end, 20)
|
|
end
|
|
end
|
|
|
|
function R:ScanArchProjects(reason)
|
|
self:Debug("Scanning archaeology projects (%s)", reason)
|
|
if GetNumArchaeologyRaces() == 0 then
|
|
return
|
|
end
|
|
for race_id = 1, GetNumArchaeologyRaces() do
|
|
local name = GetActiveArtifactByRace(race_id)
|
|
if Rarity.architems[name] then
|
|
-- We started a project we were looking for!
|
|
local id = Rarity.architems[name].itemId
|
|
if id then
|
|
self:OnItemFound(id, Rarity.items[id])
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
Rarity.Collections = Collections
|
|
return Collections
|
|
|