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_FILTER_COLLECTED , true )
C_PetJournal.SetFilterChecked ( _G.LE_PET_JOURNAL_FILTER_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 : 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