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.

281 lines
10 KiB

-- Upvalues
local R = Rarity
-- Lua API
local table = table
-- WOW API
local C_Calendar = C_Calendar
local GetContainerNumSlots = _G.C_Container.GetContainerNumSlots
local GetContainerItemID = _G.C_Container.GetContainerItemID
local GetContainerItemInfo = _G.C_Container.GetContainerItemInfo
local GetNumSavedInstances = GetNumSavedInstances
local GetSavedInstanceInfo = GetSavedInstanceInfo
local GetNumRandomDungeons = GetNumRandomDungeons
local GetLFGRandomDungeonInfo = GetLFGRandomDungeonInfo
local GetLFGDungeonInfo = GetLFGDungeonInfo
local GetLFGDungeonRewards = GetLFGDungeonRewards
local GetStatistic = GetStatistic
local UnitName = UnitName
local UnitGUID = UnitGUID
local InCombatLockdown = InCombatLockdown
local GetAchievementNumCriteria = GetAchievementNumCriteria
-- Constants
local NUM_BAG_SLOTS = _G.NUM_BAG_SLOTS
local BOSS_DEAD = _G.BOSS_DEAD
-- Why is this so inconsistently named? Does it have a special meaning?
local rarity_stats = {}
-------------------------------------------------------------------------------------
-- Scan your bags to see if you are in possession of any of the items we want. This is used for BOSS and FISHING methods,
-- and also works as a second line of defense in case other methods fail to notice the item.
-------------------------------------------------------------------------------------
function R:ScanBags()
table.wipe(Rarity.bagitems)
for i = 0, NUM_BAG_SLOTS do
local numSlots = GetContainerNumSlots(i)
if numSlots then
for ii = 1, numSlots do
local id = GetContainerItemID(i, ii)
if id then
local containerItemInfo = GetContainerItemInfo(i, ii)
local qty = containerItemInfo.stackCount
if qty and qty > 0 then
if not Rarity.bagitems[id] then
Rarity.bagitems[id] = 0
end
Rarity.bagitems[id] = Rarity.bagitems[id] + qty
end
end
end
end
end
end
function R:ScanCalendar(reason)
self:Debug("Scanning calendar (" .. reason .. ")")
table.wipe(Rarity.holiday_textures)
local dateInfo = C_DateAndTime.GetCurrentCalendarTime() -- This is the CURRENT date (always "today")
local month, day, year = dateInfo.month, dateInfo.monthDay, dateInfo.year
local monthInfo = C_Calendar.GetMonthInfo() -- This is the CALENDAR date (as selected)
local curMonth, curYear = monthInfo.month, monthInfo.year -- It should be noted that this is the calendar's "current" month... the name may be misleading, but I'll keep it as it was
local monthOffset = -12 * (curYear - year) + month - curMonth
local numEvents = C_Calendar.GetNumDayEvents(monthOffset, day)
local numLoaded = 0
for i = 1, numEvents, 1 do
local CalendarDayEvent = C_Calendar.GetDayEvent(monthOffset, day, i)
local calendarType, texture = CalendarDayEvent.calendarType, CalendarDayEvent.iconTexture
if calendarType == "HOLIDAY" and texture ~= nil then
Rarity.holiday_textures[texture] = true
end
end
end
function R:ScanInstanceLocks(reason)
self:Debug("Scanning instance locks (" .. reason .. ")")
local scanTip = Rarity.GUI.scanTip
table.wipe(Rarity.lockouts)
local savedInstances = GetNumSavedInstances()
for i = 1, savedInstances do
local instanceName, instanceID, instanceReset, instanceDifficulty, locked, extended, instanceIDMostSig =
GetSavedInstanceInfo(i)
-- Legacy code (deprecated)
if instanceReset > 0 then
scanTip:ClearLines()
scanTip:SetInstanceLockEncountersComplete(i)
for line = 2, scanTip:NumLines() do
local txtRight = _G["__Rarity_ScanTipTextRight" .. line]:GetText()
if txtRight then
if txtRight == BOSS_DEAD then
self.lockouts[_G["__Rarity_ScanTipTextLeft" .. line]:GetText()] = true
end
end
end
end
-- Detailed lockouts saving (stub - I'm leaving the legacy code above untouched, even if it's partly identical)
if instanceReset > 0 then -- Lockout isn't expired -> Scan it and store the defeated encounter names
scanTip:ClearLines()
scanTip:SetInstanceLockEncountersComplete(i)
for line = 2, scanTip:NumLines() do
local txtRight = _G["__Rarity_ScanTipTextRight" .. line]:GetText()
if txtRight then
if txtRight == BOSS_DEAD then
local encounterName = _G["__Rarity_ScanTipTextLeft" .. line]:GetText()
self.lockouts[encounterName] = true
-- Create containers if this is the first lockout for a given instance
self.lockouts_detailed[encounterName] = self.lockouts_detailed[encounterName] or {}
self.lockouts_detailed[encounterName][instanceDifficulty] = self.lockouts_detailed[encounterName][instanceDifficulty]
or {}
-- Add this lockout to the container
self.lockouts_detailed[encounterName][instanceDifficulty] = true
end
end
end
end
end
table.wipe(Rarity.lockouts_holiday)
local num = GetNumRandomDungeons()
for i = 1, num do
local dungeonID, name = GetLFGRandomDungeonInfo(i)
local _, _, _, _, _, _, _, _, _, _, _, _, _, desc, isHoliday = GetLFGDungeonInfo(dungeonID)
if isHoliday and dungeonID ~= 828 then -- 828 = ??
local doneToday = GetLFGDungeonRewards(dungeonID)
self.lockouts_holiday[dungeonID] = doneToday
end
end
-- This code lists every LFG dungeon ID in the game (up through 1000)
-- for instanceID = 0, 1000 do
-- local dungeonName, typeId, subtypeId, minLvl, maxLvl, recLvl, minRecLvl, maxRecLvl, expansionId, groupId, textureName, difficulty, maxPlayers, dungeonDesc, isHoliday = GetLFGDungeonInfo(instanceID)
-- if dungeonName then
-- self:Print("instanceID = " .. instanceID .. " Name = " .. dungeonName .. " typeID = " .. tostring(typeId) .. " minLvl = " .. minLvl .. " maxLvl = " .. maxLvl .. " recLvl = " .. recLvl .. " groupId = " .. tostring(groupId) .." maxPlayers = " .. tostring(maxPlayers))
-- end
-- end
end
-- TODO: Does this really belong here? I don't think so...
function R:BuildStatistics(reason)
self:ProfileStart2()
-- self:Debug("Building statistics table ("..reason..")")
local tbl = {}
Rarity.lastStatCount = 0
for k, v in pairs(R.stats_to_scan) do
local s = GetStatistic(k)
tbl[k] = (tonumber(s or "0") or 0)
if not Rarity.db.profile.accountWideStatistics then
Rarity.db.profile.accountWideStatistics = {}
end
local charName = UnitName("player")
local charGuid = UnitGUID("player")
if charName and charGuid then
if not Rarity.db.profile.accountWideStatistics[charGuid] then
Rarity.db.profile.accountWideStatistics[charGuid] = {}
end
Rarity.db.profile.accountWideStatistics[charGuid].playerName = charName
Rarity.db.profile.accountWideStatistics[charGuid].server = GetRealmName() or ""
if not Rarity.db.profile.accountWideStatistics[charGuid].statistics then
Rarity.db.profile.accountWideStatistics[charGuid].statistics = {}
end
Rarity.db.profile.accountWideStatistics[charGuid].statistics[k] = (tonumber(s or "0") or 0)
end
Rarity.lastStatCount = Rarity.lastStatCount + 1
end
self:ProfileStop2("BuildStatistics: %fms")
return tbl
end
function R:ScanStatistics(reason)
if InCombatLockdown() then
return
end -- Don't do this during combat as it has a tendency to run too long
self:ProfileStart2()
-- self:Debug("Scanning statistics ("..reason..")")
if rarity_stats == nil or (Rarity.lastStatCount or 0) <= 0 then
self:Debug("Building initial statistics table")
rarity_stats = self:BuildStatistics(reason)
end
local newStats = self:BuildStatistics(reason)
for kk, vv in pairs(Rarity.items_with_stats) do
if type(vv) == "table" then
if
(vv.requiresHorde and R.Caching:IsHorde())
or (vv.requiresAlliance and not R.Caching:IsHorde())
or (not vv.requiresHorde and not vv.requiresAlliance)
then
if vv.statisticId and type(vv.statisticId) == "table" then
local count = 0
local totalCrossAccount = 0
for kkk, vvv in pairs(vv.statisticId) do
local newAmount = newStats[vvv] or 0
local oldAmount = rarity_stats[vvv] or 0
count = count + newAmount
-- Count up the total for this statistic across the entire account
if Rarity.db.profile.accountWideStatistics then
for playerGuid, playerData in pairs(Rarity.db.profile.accountWideStatistics) do
if playerData.statistics then
totalCrossAccount = totalCrossAccount
+ (Rarity.db.profile.accountWideStatistics[playerGuid].statistics[vvv] or 0)
end
end
end
-- One of the statistics has gone up; add one attempt for this item
if newAmount > oldAmount then
R:Debug("Statistics indicate a new attempt for " .. vv.name)
vv.attempts = (vv.attempts or 0) + 1
self:OutputAttempts(vv, true)
end
end
-- We've never seen any attempts for this yet; update to this player's statistic total
if count > 0 and (vv.attempts or 0) <= 0 then
-- We seem to have gathered more attempts on this character than accounted for yet; update to new total
vv.attempts = count
self:OutputAttempts(vv, true)
elseif count > 0 and count > (vv.attempts or 0) and vv.doNotUpdateToHighestStat ~= true then -- Some items don't want us doing this (generally when Blizzard has a statistic overcounting bug)
R:Debug(
"Statistics for " .. vv.name .. " are higher than current amount. Updating to " .. count
)
vv.attempts = count
self:OutputAttempts(vv, true)
end
-- Cross-account statistic total is higher than the one we have; update to new total
if totalCrossAccount > (vv.attempts or 0) and vv.doNotUpdateToHighestStat ~= true then
R:Debug(
"Account-wide statistics for "
.. vv.name
.. " are higher than current amount. Updating to "
.. totalCrossAccount
)
vv.attempts = totalCrossAccount
self:OutputAttempts(vv, true)
end
end
end
end
end
-- Done with scan; update our saved table to the current scan
rarity_stats = newStats
if self.db.profile.debugMode then
R.stats = rarity_stats
end
-- Scan rare NPC achievements
table.wipe(Rarity.ach_npcs_isKilled)
table.wipe(Rarity.ach_npcs_achId)
for k, v in pairs(self.db.profile.achNpcs) do
local count = GetAchievementNumCriteria(v)
for i = 1, count do
local description, type, completed = GetAchievementCriteriaInfo(v, i)
Rarity.ach_npcs_achId[description] = v
if completed then
Rarity.ach_npcs_isKilled[description] = true
end
end
end
self:ProfileStop2("ScanStatistics: %fms")
end