Compare commits
57 commits
Author | SHA1 | Date | |
---|---|---|---|
5f7cfc7610 | |||
da5111170f | |||
4cee09a6d4 | |||
be3b33f3e4 | |||
4a80527bf5 | |||
53974a8640 | |||
ba5151792f | |||
20156e6f94 | |||
0b3278e883 | |||
0fefdb710d | |||
2c5c8735cb | |||
64af7e3bc2 | |||
4262c0cdb6 | |||
691540a108 | |||
754ad92e27 | |||
8309a33c8f | |||
130467f864 | |||
2b214a8943 | |||
79ba491c9a | |||
d7efdbe934 | |||
ad62d9af11 | |||
b59717d06c | |||
d47828edf5 | |||
2417f3b9fe | |||
d6ba74dca0 | |||
65d7743bd6 | |||
79b2b215ce | |||
f8f20f2229 | |||
a4d74ac126 | |||
d607cdb3b6 | |||
8f02f9760e | |||
cb2d4649ce | |||
aea18de7ed | |||
8cb8121d7b | |||
c63388354c | |||
99b095a519 | |||
7d360afb1c | |||
50edab43d8 | |||
9b31a2f28f | |||
3a5412ba73 | |||
10449cd7cb | |||
a512d4cbb8 | |||
460807d179 | |||
1905d59705 | |||
c17d902b62 | |||
fca9fd3c50 | |||
73a4d7b9fd | |||
af1693d562 | |||
4f7dce48b5 | |||
24682f9b5f | |||
6cd2ee2e21 | |||
070a1641ef | |||
4d11c25c2c | |||
934b03bed9 | |||
2106926a1e | |||
0004b1c785 | |||
c15bb5c8d5 |
14 changed files with 675 additions and 166 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
.hg
|
||||
.hgignore
|
||||
.hgtags
|
1
.pkgmeta
1
.pkgmeta
|
@ -8,6 +8,7 @@ externals:
|
|||
Libs/AceConfig-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk
|
||||
Libs/AceDB-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceDB-3.0
|
||||
Libs/AceEvent-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceEvent-3.0
|
||||
Libs/AceLocale-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceLocale-3.0
|
||||
Libs/LibBabble-Zone-3.0: svn://svn.wowace.com/wow/libbabble-zone-3-0/mainline/trunk
|
||||
Libs/LibQTip-1.0: svn://svn.wowace.com/wow/libqtip-1-0/mainline/trunk
|
||||
Libs/LibDBIcon-1.0: svn://svn.wowace.com/wow/libdbicon-1-0/mainline/trunk/LibDBIcon-1.0
|
786
ChoreTracker.lua
786
ChoreTracker.lua
|
@ -1,7 +1,16 @@
|
|||
ChoreTracker = LibStub('AceAddon-3.0'):NewAddon('ChoreTracker', 'AceConsole-3.0', 'AceEvent-3.0')
|
||||
local core = ChoreTracker
|
||||
local LQT, LDB, LDBIcon, LBZ
|
||||
local db, tooltip, zones, trackedInstances, vpResetTime
|
||||
local LQT, LDB, LDBIcon
|
||||
|
||||
-- Localization
|
||||
local L = LibStub('AceLocale-3.0'):GetLocale('ChoreTracker')
|
||||
|
||||
-- Get localized instances
|
||||
local Z = LibStub('LibBabble-Zone-3.0'):GetLookupTable()
|
||||
|
||||
--
|
||||
local CURRENT_MAX_LEVEL = 85
|
||||
local MAX_VALOR_POINTS = 1000
|
||||
|
||||
local defaults = {
|
||||
global = {},
|
||||
|
@ -9,219 +18,508 @@ local defaults = {
|
|||
minimap = {
|
||||
hide = false,
|
||||
},
|
||||
instances = {},
|
||||
sortType = 1,
|
||||
sortDirection = 1,
|
||||
currentOnTop = false,
|
||||
showServer = false,
|
||||
showTotalVp = true,
|
||||
instances = {
|
||||
[Z['Dragon Soul']] = { abbreviation = 'DS', enable = true, removed = false, },
|
||||
[Z['Baradin Hold']] = { abbreviation = 'BH', enable = true, removed = false, },
|
||||
[Z['Firelands']] = { abbreviation = 'FL', enable = true, removed = false, },
|
||||
[Z['The Bastion of Twilight']] = { abbreviation = 'BoT', enable = false, removed = false, },
|
||||
[Z['Blackwing Descent']] = { abbreviation = 'BWD', enable = false, removed = false, },
|
||||
[Z['Throne of the Four Winds']] = { abbreviation = '4W', enable = false, removed = false, },
|
||||
},
|
||||
lfrs = {}
|
||||
},
|
||||
}
|
||||
|
||||
-- Setup LFR Defaults
|
||||
local RFDungeonCount = GetNumRFDungeons()
|
||||
|
||||
for i = 1, RFDungeonCount do
|
||||
id, instanceName = GetRFDungeonInfo(i)
|
||||
|
||||
defaults.profile.lfrs[instanceName] = { enable = true, removed = false, }
|
||||
defaults.profile.lfrs[instanceName].abbreviation = string.sub(instanceName, 0, 1)
|
||||
end
|
||||
|
||||
local options = {
|
||||
name = 'ChoreTracker',
|
||||
type = 'group',
|
||||
args = {
|
||||
minimap = {
|
||||
name = 'Hide Minimap Icon',
|
||||
desc = 'Removes the icon from your minimap.',
|
||||
type = 'toggle',
|
||||
get = function(info) return db.profile.minimap.hide end,
|
||||
set = function(info, value) db.profile.minimap.hide = value LDBIcon[value and 'Hide' or 'Show'](LDBIcon, 'ChoreTracker') end,
|
||||
}
|
||||
}
|
||||
general = {
|
||||
name = L['Settings'],
|
||||
type = 'group',
|
||||
order = 1,
|
||||
args = {
|
||||
minimap = {
|
||||
name = L['Hide Minimap Icon'],
|
||||
desc = L['Removes the icon from your minimap.'],
|
||||
type = 'toggle',
|
||||
order = 1,
|
||||
get = function(info) return core.db.profile.minimap.hide end,
|
||||
set = function(info, value) core.db.profile.minimap.hide = value LDBIcon[value and 'Hide' or 'Show'](LDBIcon, 'ChoreTracker') end,
|
||||
},
|
||||
verticalHeader = {
|
||||
name = L['Vertical Sorting'],
|
||||
type = 'header',
|
||||
order = 2,
|
||||
},
|
||||
currentOnTop = {
|
||||
name = L['Current Character On Top'],
|
||||
desc = L['Place the character you are currently logged in as on the top of the list.'],
|
||||
type = 'toggle',
|
||||
width = 'full',
|
||||
order = 3,
|
||||
get = function(info) return core.db.profile.currentOnTop end,
|
||||
set = function(info, value) core.db.profile.currentOnTop = value end,
|
||||
},
|
||||
sortType = {
|
||||
name = L['Sort Field'],
|
||||
desc = L['Field to sort the tooltip by.'],
|
||||
type = 'select',
|
||||
order = 5,
|
||||
values = { L['Character'], L['Valor Points'], L['Class'] },
|
||||
get = function(info) return core.db.profile.sortType end,
|
||||
set = function(info, value) core.db.profile.sortType = value end,
|
||||
},
|
||||
sortingDirection = {
|
||||
name = L['Sorting Direction'],
|
||||
desc = L['Which direction to sort.'],
|
||||
type = 'select',
|
||||
order = 6,
|
||||
values = { L['Ascending'], L['Descending'] },
|
||||
get = function(info) return core.db.profile.sortDirection end,
|
||||
set = function(info, value) core.db.profile.sortDirection = value end,
|
||||
},
|
||||
otherHeader = {
|
||||
name = '',
|
||||
type = 'header',
|
||||
order = 20,
|
||||
},
|
||||
showServer = {
|
||||
name = L['Show Server'],
|
||||
desc = L['Show the server abbreviation next to a character name in the list.'],
|
||||
type = 'toggle',
|
||||
width = 'full',
|
||||
order = 21,
|
||||
get = function(info) return core.db.profile.showServer end,
|
||||
set = function(info, value) core.db.profile.showServer = value end,
|
||||
},
|
||||
showTotalVp = {
|
||||
name = L['Show Total VP'],
|
||||
desc = L['Show the total valor points for all characters in the tooltip.'],
|
||||
type = 'toggle',
|
||||
width = 'full',
|
||||
order = 22,
|
||||
get = function(info) return core.db.profile.showTotalVp end,
|
||||
set = function(info, value) core.db.profile.showTotalVp = value end,
|
||||
},
|
||||
},
|
||||
},
|
||||
instances = {
|
||||
name = L['Instances'],
|
||||
type = 'group',
|
||||
order = 20,
|
||||
args = { },
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
local classColors = {}
|
||||
local flagColors = {}
|
||||
|
||||
function core:OnInitialize()
|
||||
-- Prepare the database if necessary
|
||||
db = LibStub('AceDB-3.0'):New('ChoreTrackerDB', defaults, 'Default')
|
||||
self.db = LibStub('AceDB-3.0'):New('ChoreTrackerDB', defaults, 'Default')
|
||||
|
||||
local level = UnitLevel('player')
|
||||
local realm = GetRealmName()
|
||||
local name = UnitName('player')
|
||||
if db.global[realm] == nil then
|
||||
db.global[realm] = {}
|
||||
self.character = {
|
||||
name = UnitName('player'),
|
||||
level = UnitLevel('player'),
|
||||
class = UnitClass('player'),
|
||||
realm = GetRealmName(),
|
||||
}
|
||||
self.character.class = self.character.class:lower():gsub("%s*(.-)%s*", "%1")
|
||||
|
||||
if self.db.global[self.character.realm] == nil then
|
||||
self.db.global[self.character.realm] = {}
|
||||
end
|
||||
|
||||
if db.global[realm][name] == nil and level == 85 then
|
||||
db.global[realm][name] = {}
|
||||
if self.db.global[self.character.realm][self.character.name] == nil and self.character.level == CURRENT_MAX_LEVEL then
|
||||
self.db.global[self.character.realm][self.character.name] = {}
|
||||
|
||||
local class = UnitClass('player')
|
||||
class = class:lower()
|
||||
if class == 'deathknight' then
|
||||
class = 'death knight'
|
||||
end
|
||||
|
||||
db.global[realm][name].class = class
|
||||
db.global[realm][name].valorPoints = {
|
||||
valorPoints = 0,
|
||||
self.db.global[self.character.realm][self.character.name].class = self.character.class
|
||||
self.db.global[self.character.realm][self.character.name].valorPoints = {
|
||||
total = 0,
|
||||
points = 0,
|
||||
resetTime = 0,
|
||||
}
|
||||
db.global[realm][name].lockouts = {}
|
||||
self.db.global[self.character.realm][self.character.name].lockouts = {}
|
||||
end
|
||||
|
||||
-- Register events (here for now; track data regardless of whether it is displayed?)
|
||||
local level = UnitLevel('player')
|
||||
if level == 85 then
|
||||
self:RegisterEvent('CALENDAR_UPDATE_EVENT_LIST','GetNextVPReset')
|
||||
self:RegisterEvent('UPDATE_INSTANCE_INFO', 'UpdateChores')
|
||||
self:RegisterEvent('CHAT_MSG_CURRENCY', 'UpdateChores')
|
||||
|
||||
if self.db.global[self.character.realm][self.character.name] ~= nil then
|
||||
if self.db.global[self.character.realm][self.character.name].lfrs == nil and self.character.level == CURRENT_MAX_LEVEL then
|
||||
self.db.global[self.character.realm][self.character.name].lfrs = {}
|
||||
end
|
||||
end
|
||||
|
||||
-- Get calendar events information
|
||||
OpenCalendar()
|
||||
|
||||
-- Reset data if necessary
|
||||
core:ResetInstances()
|
||||
core:ResetValorPoints()
|
||||
|
||||
-- Add LFR stuff to profile if it isn't there already
|
||||
core:LFRProfileUpdate()
|
||||
end
|
||||
|
||||
function core:OnEnable()
|
||||
LQT = LibStub('LibQTip-1.0')
|
||||
LBZ = LibStub('LibBabble-Zone-3.0')
|
||||
|
||||
self.instanceInfoTime = false
|
||||
self.vpResetTime = false
|
||||
|
||||
-- Setup font strings for later. (RAID_CLASS_COLORS always indexed in English?)
|
||||
for class,color in pairs(RAID_CLASS_COLORS) do
|
||||
self.fontObjects = { }
|
||||
for class, color in pairs(RAID_CLASS_COLORS) do
|
||||
class = class:lower()
|
||||
if class == 'deathknight' then
|
||||
class = 'death knight'
|
||||
end
|
||||
|
||||
classColors[class] = CreateFont('ClassFont' .. class)
|
||||
classColors[class]:CopyFontObject(GameTooltipText)
|
||||
classColors[class]:SetTextColor(color.r, color.g, color.b)
|
||||
self.fontObjects[class] = CreateFont('ClassFont' .. class)
|
||||
self.fontObjects[class]:CopyFontObject(GameTooltipText)
|
||||
self.fontObjects[class]:SetTextColor(color.r, color.g, color.b)
|
||||
end
|
||||
|
||||
flagColors['green'] = CreateFont('FlagFontGreen')
|
||||
flagColors['green']:CopyFontObject(GameTooltipText)
|
||||
flagColors['green']:SetTextColor(0, 255, 0)
|
||||
self.fontObjects['green'] = CreateFont('FlagFontGreen')
|
||||
self.fontObjects['green']:CopyFontObject(GameTooltipText)
|
||||
self.fontObjects['green']:SetTextColor(0, 255, 0)
|
||||
|
||||
flagColors['red'] = CreateFont('FlagFontRed')
|
||||
flagColors['red']:CopyFontObject(GameTooltipText)
|
||||
flagColors['red']:SetTextColor(255, 0, 0)
|
||||
self.fontObjects['red'] = CreateFont('FlagFontRed')
|
||||
self.fontObjects['red']:CopyFontObject(GameTooltipText)
|
||||
self.fontObjects['red']:SetTextColor(255, 0, 0)
|
||||
|
||||
-- Setup instance stuff for options
|
||||
core:DrawInstanceOptions()
|
||||
|
||||
-- Add options to Interface Panel
|
||||
LibStub('AceConfigRegistry-3.0'):RegisterOptionsTable('ChoreTracker', options)
|
||||
local ACD = LibStub('AceConfigDialog-3.0')
|
||||
ACD:AddToBlizOptions('ChoreTracker', 'ChoreTracker')
|
||||
options.args.profile = LibStub('AceDBOptions-3.0'):GetOptionsTable(self.db)
|
||||
|
||||
-- Setup LDB
|
||||
LDB = LibStub('LibDataBroker-1.1'):NewDataObject('ChoreTracker', {
|
||||
type = 'data source',
|
||||
text = 'ChoreTracker',
|
||||
icon = 'Interface\\AddOns\\ChoreTracker\\icon',
|
||||
OnClick = function() LibStub("AceConfigDialog-3.0"):Open("ChoreTracker") end,
|
||||
OnEnter = function(self)
|
||||
local columnCount = 2
|
||||
for instance,abbreviation in pairs(trackedInstances) do
|
||||
columnCount = columnCount + 1
|
||||
end
|
||||
tooltip = LQT:Acquire('ChoreTrackerTooltip', columnCount, 'LEFT', 'CENTER', 'RIGHT')
|
||||
|
||||
OnClick = function(self, button)
|
||||
if button == 'RightButton' then
|
||||
if LibStub("AceConfigDialog-3.0").OpenFrames['ChoreTracker'] then
|
||||
LibStub('AceConfigDialog-3.0'):Close('ChoreTracker')
|
||||
else
|
||||
LibStub('AceConfigDialog-3.0'):Open('ChoreTracker')
|
||||
end
|
||||
else
|
||||
-- Cycle through our sort options
|
||||
if core.db.profile.sortType == 1 then
|
||||
core.db.profile.sortType = 2
|
||||
core:DrawTooltip()
|
||||
elseif core.db.profile.sortType == 2 then
|
||||
core.db.profile.sortType = 3
|
||||
core:DrawTooltip()
|
||||
else
|
||||
core.db.profile.sortType = 1
|
||||
core:DrawTooltip()
|
||||
end
|
||||
end
|
||||
end,
|
||||
OnEnter = function(self)
|
||||
core:DrawTooltip()
|
||||
|
||||
tooltip:SmartAnchorTo(self)
|
||||
tooltip:Show()
|
||||
core.tooltip:SmartAnchorTo(self)
|
||||
core.tooltip:Show()
|
||||
end,
|
||||
OnLeave = function(self)
|
||||
LQT:Release(tooltip)
|
||||
tooltip = nil
|
||||
LQT:Release(core.tooltip)
|
||||
core.tooltip = nil
|
||||
end,
|
||||
})
|
||||
|
||||
-- Deal with minimap
|
||||
LDBIcon = LibStub('LibDBIcon-1.0')
|
||||
LDBIcon:Register('ChoreTracker', LDB, db.profile.minimap)
|
||||
LDBIcon:Register('ChoreTracker', LDB, self.db.profile.minimap)
|
||||
|
||||
if db.profile.minimap.hide then
|
||||
if self.db.profile.minimap.hide then
|
||||
LDBIcon:Hide('ChoreTracker')
|
||||
else
|
||||
LDBIcon:Show('ChoreTracker')
|
||||
end
|
||||
|
||||
-- Get instances
|
||||
zones = LBZ:GetLookupTable()
|
||||
-- Register events
|
||||
if self.character.level == CURRENT_MAX_LEVEL then
|
||||
self:RegisterEvent('PLAYER_ENTERING_WORLD')
|
||||
|
||||
self:RegisterEvent('CALENDAR_UPDATE_EVENT_LIST')
|
||||
|
||||
self:RegisterEvent('LFG_UPDATE_RANDOM_INFO')
|
||||
self:RegisterEvent('LFG_LOCK_INFO_RECEIVED')
|
||||
self:RegisterEvent('UPDATE_INSTANCE_INFO')
|
||||
|
||||
self:RegisterEvent('CURRENCY_DISPLAY_UPDATE')
|
||||
self:RegisterEvent('CHAT_MSG_CURRENCY')
|
||||
self:RegisterEvent('INSTANCE_ENCOUNTER_ENGAGE_UNIT')
|
||||
end
|
||||
|
||||
trackedInstances = {
|
||||
[zones['Baradin Hold']] = 'BH',
|
||||
[zones['Firelands']] = 'FL',
|
||||
[zones['The Bastion of Twilight']] = 'BoT',
|
||||
[zones['Blackwing Descent']] = 'BWD',
|
||||
[zones['Throne of the Four Winds']] = '4W',
|
||||
}
|
||||
-- Get calendar events information
|
||||
OpenCalendar()
|
||||
|
||||
-- Add options to Interface Panel
|
||||
LibStub('AceConfigRegistry-3.0'):RegisterOptionsTable('ChoreTracker', options)
|
||||
local ACD = LibStub('AceConfigDialog-3.0')
|
||||
ACD:AddToBlizOptions('ChoreTracker', 'ChoreTracker')
|
||||
-- Reset data if necessary
|
||||
core:ResetRaidLockouts()
|
||||
core:ResetValorPoints()
|
||||
core:ResetLFRLockouts()
|
||||
end
|
||||
|
||||
function core:UpdateChores()
|
||||
-- Reset data if necessary
|
||||
core:ResetInstances()
|
||||
core:ResetValorPoints()
|
||||
|
||||
local realm = GetRealmName()
|
||||
local name = UnitName('player')
|
||||
local _,_,_,earnedThisWeek = GetCurrencyInfo(396)
|
||||
|
||||
--store Valor Points
|
||||
if vpResetTime ~= nil then
|
||||
db.global[realm][name].valorPoints = {}
|
||||
db.global[realm][name].valorPoints.points = earnedThisWeek
|
||||
db.global[realm][name].valorPoints.resetTime = vpResetTime
|
||||
|
||||
--[[ EVENTS ]]--
|
||||
function core:PLAYER_ENTERING_WORLD()
|
||||
self.vpResetTime = core:FindLockout(Z['Baradin Hold'])
|
||||
end
|
||||
|
||||
function core:CALENDAR_UPDATE_EVENT_LIST()
|
||||
self.vpResetTime = core:FindLockout(Z['Baradin Hold'])
|
||||
end
|
||||
|
||||
function core:UPDATE_INSTANCE_INFO()
|
||||
self.instanceInfoTime = time()
|
||||
core:UpdateRaidLockouts()
|
||||
end
|
||||
|
||||
function core:LFG_UPDATE_RANDOM_INFO()
|
||||
core:UpdateValorPoints()
|
||||
end
|
||||
|
||||
function core:LFG_LOCK_INFO_RECEIVED()
|
||||
core:UpdateLFRLockouts()
|
||||
end
|
||||
|
||||
function core:CURRENCY_DISPLAY_UPDATE()
|
||||
core:UpdateValorPoints()
|
||||
end
|
||||
|
||||
function core:CHAT_MSG_CURRENCY()
|
||||
RequestRaidInfo()
|
||||
RequestLFDPlayerLockInfo()
|
||||
end
|
||||
|
||||
-- Might only fire for encounters with a boss frame.
|
||||
function core:INSTANCE_ENCOUNTER_ENGAGE_UNIT()
|
||||
RequestRaidInfo()
|
||||
RequestLFDPlayerLockInfo()
|
||||
end
|
||||
|
||||
|
||||
--[[ FUNCTIONS ]]--
|
||||
function core:UpdateValorPoints()
|
||||
local _, amount, _, earnedThisWeek = GetCurrencyInfo(396)
|
||||
|
||||
if self.db.global[self.character.realm][self.character.name].valorPoints == nil then
|
||||
self.db.global[self.character.realm][self.character.name].valorPoints = {}
|
||||
end
|
||||
self.db.global[self.character.realm][self.character.name].valorPoints.points = earnedThisWeek
|
||||
self.db.global[self.character.realm][self.character.name].valorPoints.total = amount
|
||||
if self.vpResetTime ~= false then
|
||||
self.db.global[self.character.realm][self.character.name].valorPoints.resetTime = self.vpResetTime
|
||||
end
|
||||
end
|
||||
|
||||
--store Saved Instances
|
||||
local savedInstances = GetNumSavedInstances()
|
||||
for i = 1, savedInstances do
|
||||
local instanceName, _, instanceReset, _, _, _, _, _, _, _, _, defeatedBosses = GetSavedInstanceInfo(i)
|
||||
|
||||
if trackedInstances[instanceName] ~= nil then
|
||||
if instanceReset > 0 then
|
||||
db.global[realm][name].lockouts[instanceName] = {}
|
||||
db.global[realm][name].lockouts[instanceName].defeatedBosses = defeatedBosses
|
||||
db.global[realm][name].lockouts[instanceName].resetTime = time() + instanceReset
|
||||
else
|
||||
db.global[realm][name].lockouts[instanceName] = nil
|
||||
function core:ResetValorPoints()
|
||||
for realm, realmTable in pairs(self.db.global) do
|
||||
for name in pairs(realmTable) do
|
||||
if self.db.global[realm][name].valorPoints.resetTime < time() then
|
||||
self.db.global[realm][name].valorPoints.points = 0
|
||||
self.db.global[realm][name].valorPoints.resetTime = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function core:ResetInstances()
|
||||
for realm,realmTable in pairs(db.global) do
|
||||
function core:UpdateRaidLockouts()
|
||||
local savedInstances = GetNumSavedInstances()
|
||||
for i = 1, savedInstances do
|
||||
local instanceName, _, instanceReset, _, _, _, _, _, _, _, _, defeatedBosses = GetSavedInstanceInfo(i)
|
||||
|
||||
if self.db.profile.instances[instanceName] ~= nil then
|
||||
if instanceReset > 0 then
|
||||
self.db.global[self.character.realm][self.character.name].lockouts[instanceName] = {}
|
||||
self.db.global[self.character.realm][self.character.name].lockouts[instanceName].defeatedBosses = defeatedBosses
|
||||
self.db.global[self.character.realm][self.character.name].lockouts[instanceName].resetTime = self.instanceInfoTime + instanceReset
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function core:ResetRaidLockouts()
|
||||
for realm,realmTable in pairs(self.db.global) do
|
||||
for name in pairs(realmTable) do
|
||||
for instance,instanceTable in pairs(db.global[realm][name].lockouts) do
|
||||
for instance,instanceTable in pairs(self.db.global[realm][name].lockouts) do
|
||||
if instanceTable.resetTime < time() then
|
||||
db.global[realm][name].lockouts[instance] = nil
|
||||
self.db.global[realm][name].lockouts[instance] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function core:ResetValorPoints()
|
||||
for realm,realmTable in pairs(db.global) do
|
||||
function core:UpdateLFRLockouts()
|
||||
local RFDungeonCount = GetNumRFDungeons()
|
||||
|
||||
for i = 1, RFDungeonCount do
|
||||
id, instanceName = GetRFDungeonInfo(i)
|
||||
|
||||
_, defeatedBosses = GetLFGDungeonNumEncounters(id)
|
||||
|
||||
if self.db.profile.lfrs[instanceName] ~= nil then
|
||||
self.db.global[self.character.realm][self.character.name].lfrs[instanceName] = {}
|
||||
self.db.global[self.character.realm][self.character.name].lfrs[instanceName].defeatedBosses = defeatedBosses
|
||||
self.db.global[self.character.realm][self.character.name].lfrs[instanceName].resetTime = self.vpResetTime
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function core:ResetLFRLockouts()
|
||||
for realm,realmTable in pairs(self.db.global) do
|
||||
for name in pairs(realmTable) do
|
||||
if db.global[realm][name].valorPoints.resetTime < time() then
|
||||
db.global[realm][name].valorPoints = {
|
||||
valorPoints = 0,
|
||||
resetTime = 0,
|
||||
}
|
||||
for instance,instanceTable in pairs(self.db.global[realm][name].lfrs) do
|
||||
if instanceTable.resetTime < time() then
|
||||
self.db.global[realm][name].lfrs[instance] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function core:GetNextVPReset()
|
||||
--prepare calendar
|
||||
local currentCalendarSetting = GetCVar('calendarShowResets') -- get current value and store
|
||||
SetCVar('calendarShowResets', 1) -- set it to what we want
|
||||
function core:DrawInstanceOptions()
|
||||
-- Redraw our instance options everytime they are updated.
|
||||
options.args.instances.args = {
|
||||
instance = {
|
||||
name = L['Add instance to track.'],
|
||||
desc = L['Enter an instance on a lockout that you would like ChoreTracker to track.'],
|
||||
type = 'input',
|
||||
order = 1,
|
||||
set = function(info, value)
|
||||
if core:FindLockout(value) then
|
||||
self.db.profile.instances[value] = { }
|
||||
self.db.profile.instances[value].abbreviation = string.sub(value,0,1)
|
||||
self.db.profile.instances[value].enable = true
|
||||
self.db.profile.instances[value].removed = false
|
||||
core:DrawInstanceOptions()
|
||||
else
|
||||
print('Invalid instance')
|
||||
end
|
||||
end,
|
||||
},
|
||||
lfrsHeader = {
|
||||
name = L['Looking for Raid Instances'],
|
||||
type = 'header',
|
||||
order = 100,
|
||||
},
|
||||
instancesHeader = {
|
||||
name = L['Instances'],
|
||||
type = 'header',
|
||||
order = 500,
|
||||
},
|
||||
}
|
||||
local i = 1
|
||||
for instance, abbreviation in pairs(self.db.profile.instances) do
|
||||
if self.db.profile.instances[instance].removed == false then
|
||||
options.args.instances.args[instance .. 'Enable'] = {
|
||||
type = 'toggle',
|
||||
name = instance,
|
||||
order = 500 + (5 * i) + 0,
|
||||
get = function(info) return self.db.profile.instances[instance].enable end,
|
||||
set = function(info, value)
|
||||
self.db.profile.instances[instance].enable = value
|
||||
core:DrawInstanceOptions()
|
||||
end,
|
||||
}
|
||||
options.args.instances.args[instance .. 'Abbreviation'] = {
|
||||
type = 'input',
|
||||
name = '',
|
||||
order = 500 + (5 * i) + 1,
|
||||
width = 'half',
|
||||
get = function(info) return self.db.profile.instances[instance].abbreviation end,
|
||||
set = function(info, value) self.db.profile.instances[instance].abbreviation = value end,
|
||||
}
|
||||
options.args.instances.args[instance .. 'Remove'] = {
|
||||
type = 'execute',
|
||||
name = L['Remove'],
|
||||
order = 500 + (5 * i) + 2,
|
||||
width = 'half',
|
||||
confirm = true,
|
||||
func = function()
|
||||
self.db.profile.instances[instance].removed = true
|
||||
core:DrawInstanceOptions()
|
||||
end,
|
||||
}
|
||||
options.args.instances.args[instance .. 'Spacer'] = {
|
||||
type = 'description',
|
||||
name = '',
|
||||
order = 500 + (5 * i) + 3,
|
||||
}
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
--figure out what time the server resets daily information
|
||||
i = 1
|
||||
for instance, abbreviation in pairs(self.db.profile.lfrs) do
|
||||
if self.db.profile.lfrs[instance].removed == false then
|
||||
options.args.instances.args[instance .. 'Enable'] = {
|
||||
type = 'toggle',
|
||||
name = instance,
|
||||
order = 100 + (5 * i) + 0,
|
||||
get = function(info) return self.db.profile.lfrs[instance].enable end,
|
||||
set = function(info, value)
|
||||
self.db.profile.lfrs[instance].enable = value
|
||||
core:DrawInstanceOptions()
|
||||
end,
|
||||
}
|
||||
options.args.instances.args[instance .. 'Abbreviation'] = {
|
||||
type = 'input',
|
||||
name = '',
|
||||
order = 100 + (5 * i) + 1,
|
||||
width = 'half',
|
||||
get = function(info) return self.db.profile.lfrs[instance].abbreviation end,
|
||||
set = function(info, value) self.db.profile.lfrs[instance].abbreviation = value end,
|
||||
}
|
||||
options.args.instances.args[instance .. 'Remove'] = {
|
||||
type = 'execute',
|
||||
name = L['Remove'],
|
||||
order = 100 + (5 * i) + 2,
|
||||
width = 'half',
|
||||
confirm = true,
|
||||
func = function()
|
||||
self.db.profile.lfrs[instance].removed = true
|
||||
core:DrawInstanceOptions()
|
||||
end,
|
||||
}
|
||||
options.args.instances.args[instance .. 'Spacer'] = {
|
||||
type = 'description',
|
||||
name = '',
|
||||
order = 100 + (5 * i) + 3,
|
||||
}
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function core:FindLockout(instance)
|
||||
-- We need to have access to the instance lockouts on the calendar.
|
||||
local currentCalendarSetting = GetCVar('calendarShowResets')
|
||||
SetCVar('calendarShowResets', 1)
|
||||
|
||||
-- Figure out what time the server resets daily information
|
||||
local questReset = GetQuestResetTime()
|
||||
local resetTime = date('*t', time() + questReset)
|
||||
|
||||
--figure out reset day using next BH lockout
|
||||
-- Figure out reset day using next BH lockout
|
||||
local _, month, day, year = CalendarGetDate()
|
||||
|
||||
local monthOffset = 0
|
||||
local resetDate = nil
|
||||
while resetDate == nil do
|
||||
local resetDate = false
|
||||
while resetDate == false do
|
||||
local todaysEvents = CalendarGetNumDayEvents(monthOffset, day)
|
||||
|
||||
for i = 1,todaysEvents do
|
||||
|
@ -231,7 +529,7 @@ function core:GetNextVPReset()
|
|||
|
||||
local title,hour,minute = CalendarGetDayEvent(monthOffset, day, i)
|
||||
|
||||
if title == zones['Baradin Hold'] then
|
||||
if title == instance then
|
||||
resetDate = { year = year, month = month + monthOffset, day = day }
|
||||
end
|
||||
end
|
||||
|
@ -244,61 +542,219 @@ function core:GetNextVPReset()
|
|||
end
|
||||
end
|
||||
|
||||
--return calendar
|
||||
-- Reset the calendar to the original settings
|
||||
SetCVar('calendarShowResets', currentCalendarSetting)
|
||||
|
||||
--and combine for the reset timestamp
|
||||
if(resetDate ~= nil) then
|
||||
-- And combine for the reset timestamp
|
||||
if(resetDate ~= false) then
|
||||
resetDate.hour = resetTime.hour
|
||||
resetDate.min = resetTime.min
|
||||
resetDate.sec = resetTime.sec
|
||||
|
||||
vpResetTime = time(resetDate)
|
||||
return time(resetDate)
|
||||
else
|
||||
vpResetTime = nil
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function core:DrawTooltip()
|
||||
--create the tooltip header
|
||||
tooltip:AddHeader('')
|
||||
local valorPointColumn = tooltip:AddColumn('LEFT')
|
||||
tooltip:SetCell(1, 1, '')
|
||||
tooltip:SetCell(1, 2, 'VP')
|
||||
local nextColumn = 3
|
||||
for instance,abbreviation in pairs(trackedInstances) do
|
||||
tooltip:SetCell(1, nextColumn, abbreviation, nil, 'CENTER')
|
||||
nextColumn = nextColumn + 1
|
||||
-- UpdateChores before we show the tooltip to make sure we have the most recent data
|
||||
if self.character.level == CURRENT_MAX_LEVEL then
|
||||
-- Should not update without being 100% sure our raid info is correct
|
||||
core:UpdateValorPoints()
|
||||
core:UpdateRaidLockouts()
|
||||
core:UpdateLFRLockouts()
|
||||
end
|
||||
|
||||
for realm in pairs(db.global) do
|
||||
for name in pairs(db.global[realm]) do
|
||||
local characterLine = tooltip:AddLine('')
|
||||
local class = db.global[realm][name].class
|
||||
tooltip:SetCell(characterLine, 1, name, classColors[class], 'LEFT')
|
||||
if self.tooltip then
|
||||
self.tooltip:ClearAllPoints()
|
||||
self.tooltip:Clear()
|
||||
self.tooltip = nil
|
||||
end
|
||||
local columnCount = 2
|
||||
for instance in pairs(self.db.profile.instances) do
|
||||
if self.db.profile.instances[instance].enable == true and self.db.profile.instances[instance].removed == false then
|
||||
columnCount = columnCount + 1
|
||||
end
|
||||
end
|
||||
for instance in pairs(self.db.profile.lfrs) do
|
||||
if self.db.profile.lfrs[instance].enable == true and self.db.profile.lfrs[instance].removed == false then
|
||||
columnCount = columnCount + 1
|
||||
end
|
||||
end
|
||||
self.tooltip = LQT:Acquire('ChoreTrackerTooltip', columnCount, 'LEFT', 'CENTER', 'RIGHT')
|
||||
|
||||
-- Populate a table with the information we want for our tooltip
|
||||
local tooltipTable = {}
|
||||
local currentTable = {}
|
||||
for realm in pairs(self.db.global) do
|
||||
for name in pairs(self.db.global[realm]) do
|
||||
local valorPoints = self.db.global[realm][name].valorPoints.points
|
||||
local class = self.db.global[realm][name].class
|
||||
local totalVp = self.db.global[realm][name].valorPoints.total
|
||||
|
||||
local valorPoints, valorPointColor
|
||||
valorPoints = db.global[realm][name].valorPoints.points
|
||||
if valorPoints == nil then
|
||||
valorPoints = 0
|
||||
end
|
||||
if valorPoints == 980 then
|
||||
valorPointColor = flagColors['red']
|
||||
else
|
||||
valorPointColor = flagColors['green']
|
||||
end
|
||||
tooltip:SetCell(characterLine, 2, valorPoints, valorPointColor, 'RIGHT')
|
||||
local characterTable = { name = name, realm = realm, class = class, valorPoints = valorPoints, totalVp = totalVp }
|
||||
|
||||
local nextColumn = 3
|
||||
for instance,abbreviation in pairs(trackedInstances) do
|
||||
if db.global[realm][name].lockouts[instance] ~= nil then
|
||||
local defeatedBosses = db.global[realm][name].lockouts[instance].defeatedBosses
|
||||
tooltip:SetCell(characterLine, nextColumn, defeatedBosses, flagColors['red'], 'RIGHT')
|
||||
for instance in pairs(self.db.profile.instances) do
|
||||
local defeatedBosses
|
||||
if self.db.global[realm][name].lockouts[instance] ~= nil then
|
||||
defeatedBosses = self.db.global[realm][name].lockouts[instance].defeatedBosses
|
||||
else
|
||||
tooltip:SetCell(characterLine, nextColumn, '0', flagColors['green'], 'RIGHT')
|
||||
defeatedBosses = 0
|
||||
end
|
||||
characterTable[instance] = defeatedBosses
|
||||
end
|
||||
|
||||
for instance in pairs(self.db.profile.lfrs) do
|
||||
local defeatedBosses
|
||||
if self.db.global[realm][name].lfrs[instance] ~= nil then
|
||||
defeatedBosses = self.db.global[realm][name].lfrs[instance].defeatedBosses
|
||||
else
|
||||
defeatedBosses = 0
|
||||
end
|
||||
characterTable[instance] = defeatedBosses
|
||||
end
|
||||
|
||||
if name == UnitName('player') and self.db.profile.currentOnTop == true then
|
||||
currentTable = characterTable
|
||||
else
|
||||
table.insert(tooltipTable, characterTable)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Sort table according to options.
|
||||
local sortTooltip = function(a, b)
|
||||
local aValue, bValue
|
||||
if self.db.profile.sortType == 1 then
|
||||
aValue = a.name:lower()
|
||||
bValue = b.name:lower()
|
||||
elseif self.db.profile.sortType == 2 then
|
||||
aValue = a.valorPoints
|
||||
bValue = b.valorPoints
|
||||
elseif self.db.profile.sortType == 3 then
|
||||
aValue = a.class
|
||||
bValue = b.class
|
||||
end
|
||||
|
||||
if self.db.profile.sortDirection == 1 then
|
||||
return aValue < bValue
|
||||
else
|
||||
return aValue > bValue
|
||||
end
|
||||
end
|
||||
table.sort(tooltipTable, sortTooltip )
|
||||
|
||||
-- Toss the current character on top if it is set that way
|
||||
if self.db.profile.currentOnTop == true then
|
||||
table.insert(tooltipTable, 1, currentTable)
|
||||
end
|
||||
|
||||
-- Create a table for the header; vpPos to decide where to place Valor Points column
|
||||
-- Draw tooltip table then looped through.
|
||||
|
||||
-- Draw the tooltip
|
||||
self.tooltip:AddHeader('')
|
||||
self.tooltip:SetScale(1)
|
||||
local valorPointColumn = self.tooltip:AddColumn('LEFT')
|
||||
self.tooltip:SetCell(1, 1, '')
|
||||
self.tooltip:SetCell(1, 2, 'VP')
|
||||
|
||||
-- Build and sort our headers
|
||||
local headerTable = { }
|
||||
--headerTable['Valor Points'] = { abbreviation = 'VP', enable = true, removed = false, }
|
||||
for instance, instanceInfo in pairs(self.db.profile.instances) do
|
||||
if self.db.profile.instances[instance].enable == true and self.db.profile.instances[instance].removed == false then
|
||||
table.insert(headerTable,instanceInfo)
|
||||
end
|
||||
end
|
||||
for instance, instanceInfo in pairs(self.db.profile.lfrs) do
|
||||
if self.db.profile.lfrs[instance].enable == true and self.db.profile.lfrs[instance].removed == false then
|
||||
table.insert(headerTable,instanceInfo)
|
||||
end
|
||||
end
|
||||
|
||||
local nextColumn = 3
|
||||
for instance,instanceInfo in pairs(headerTable) do
|
||||
self.tooltip:SetCell(1, nextColumn, instanceInfo.abbreviation, nil, 'CENTER')
|
||||
nextColumn = nextColumn + 1
|
||||
end
|
||||
|
||||
if self.db.profile.showTotalVp == true then
|
||||
self.tooltip:SetCell(1, nextColumn, 'Total VP')
|
||||
nextColumn = nextColumn + 1
|
||||
end
|
||||
|
||||
for _,information in pairs(tooltipTable) do
|
||||
if self.db.profile.showServer then
|
||||
information.name = information.name .. '-' .. string.sub(information.realm,0,3)
|
||||
end
|
||||
|
||||
local characterLine = self.tooltip:AddLine('')
|
||||
self.tooltip:SetCell(characterLine, 1, information.name, self.fontObjects[information.class], 'LEFT')
|
||||
|
||||
local valorPointColor
|
||||
if information.valorPoints == MAX_VALOR_POINTS then
|
||||
valorPointColor = self.fontObjects['red']
|
||||
else
|
||||
valorPointColor = self.fontObjects['green']
|
||||
end
|
||||
self.tooltip:SetCell(characterLine, 2, information.valorPoints, valorPointColor, 'RIGHT')
|
||||
|
||||
local nextColumn = 3
|
||||
for instance, abbreviation in pairs(self.db.profile.instances) do
|
||||
if self.db.profile.instances[instance].enable == true and self.db.profile.instances[instance].removed == false then
|
||||
local instanceColor
|
||||
if information[instance] == 0 then
|
||||
instanceColor = self.fontObjects['green']
|
||||
else
|
||||
instanceColor = self.fontObjects['red']
|
||||
end
|
||||
self.tooltip:SetCell(characterLine, nextColumn, information[instance], instanceColor, 'RIGHT')
|
||||
|
||||
nextColumn = nextColumn + 1
|
||||
end
|
||||
end
|
||||
|
||||
for instance, abbreviation in pairs(self.db.profile.lfrs) do
|
||||
if self.db.profile.lfrs[instance].enable == true and self.db.profile.lfrs[instance].removed == false then
|
||||
local instanceColor
|
||||
if information[instance] == 0 then
|
||||
instanceColor = self.fontObjects['green']
|
||||
else
|
||||
instanceColor = self.fontObjects['red']
|
||||
end
|
||||
self.tooltip:SetCell(characterLine, nextColumn, information[instance], instanceColor, 'RIGHT')
|
||||
|
||||
nextColumn = nextColumn + 1
|
||||
end
|
||||
end
|
||||
|
||||
if self.db.profile.showTotalVp then
|
||||
self.tooltip:SetCell(characterLine, nextColumn, information.totalVp, self.fontObjects['green'], 'RIGHT')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--[[ PROFILE UPDATES ]]--
|
||||
function core:LFRProfileUpdate()
|
||||
for realm,realmTable in pairs(self.db.global) do
|
||||
for name in pairs(realmTable) do
|
||||
if self.db.global[realm][name].lfrs == nil then
|
||||
self.db.global[realm][name].lfrs = {}
|
||||
end
|
||||
|
||||
for instance in pairs(self.db.profile.lfrs) do
|
||||
if self.db.global[realm][name].lfrs[instance] == nil then
|
||||
self.db.global[realm][name].lfrs[instance] = {}
|
||||
self.db.global[realm][name].lfrs[instance].defeatedBosses = 0
|
||||
self.db.global[realm][name].lfrs[instance].resetTime = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,4 +1,4 @@
|
|||
## Interface: 42000
|
||||
## Interface: 43000
|
||||
## Title: ChoreTracker
|
||||
## Version: @project-version@
|
||||
## Author: Gaffer
|
||||
|
@ -14,9 +14,20 @@ Libs\AceConsole-3.0\AceConsole-3.0.xml
|
|||
Libs\AceConfig-3.0\AceConfig-3.0.xml
|
||||
Libs\AceDB-3.0\AceDB-3.0.xml
|
||||
Libs\AceEvent-3.0\AceEvent-3.0.xml
|
||||
Libs\AceLocale-3.0\AceLocale-3.0.xml
|
||||
Libs\LibBabble-Zone-3.0\lib.xml
|
||||
Libs\LibDataBroker-1.1\LibDataBroker-1.1.lua
|
||||
Libs\LibDBIcon-1.0\LibDBIcon-1.0.lua
|
||||
Libs\LibQTip-1.0\lib.xml
|
||||
|
||||
Locale\enUS.lua
|
||||
Locale\deDE.lua
|
||||
Locale\esES.lua
|
||||
Locale\esMX.lua
|
||||
Locale\frFR.lua
|
||||
Locale\koKR.lua
|
||||
Locale\ruRU.lua
|
||||
Locale\zhCN.lua
|
||||
Locale\zhTW.lua
|
||||
|
||||
ChoreTracker.lua
|
4
Locale/deDE.lua
Normal file
4
Locale/deDE.lua
Normal file
|
@ -0,0 +1,4 @@
|
|||
local L = LibStub("AceLocale-3.0"):NewLocale("BalerocHealers", "deDE")
|
||||
if not L then return end
|
||||
|
||||
--@localization(locale="deDE", format="lua_additive_table", handle-subnamespaces="concat")@
|
3
Locale/enUS.lua
Normal file
3
Locale/enUS.lua
Normal file
|
@ -0,0 +1,3 @@
|
|||
local L = LibStub('AceLocale-3.0'):NewLocale('ChoreTracker', 'enUS', true, true)
|
||||
|
||||
--@localization(locale='enUS', format='lua_additive_table', same-key-is-true=true, handle-subnamespaces='concat')@
|
4
Locale/esES.lua
Normal file
4
Locale/esES.lua
Normal file
|
@ -0,0 +1,4 @@
|
|||
local L = LibStub("AceLocale-3.0"):NewLocale("BalerocHealers", "esES")
|
||||
if not L then return end
|
||||
|
||||
--@localization(locale="esES", format="lua_additive_table", handle-subnamespaces="concat")@
|
4
Locale/esMX.lua
Normal file
4
Locale/esMX.lua
Normal file
|
@ -0,0 +1,4 @@
|
|||
local L = LibStub("AceLocale-3.0"):NewLocale("BalerocHealers", "esMX")
|
||||
if not L then return end
|
||||
|
||||
--@localization(locale="esMX", format="lua_additive_table", handle-subnamespaces="concat")@
|
4
Locale/frFR.lua
Normal file
4
Locale/frFR.lua
Normal file
|
@ -0,0 +1,4 @@
|
|||
local L = LibStub("AceLocale-3.0"):NewLocale("BalerocHealers", "frFR")
|
||||
if not L then return end
|
||||
|
||||
--@localization(locale="frFR", format="lua_additive_table", handle-subnamespaces="concat")@
|
4
Locale/koKR.lua
Normal file
4
Locale/koKR.lua
Normal file
|
@ -0,0 +1,4 @@
|
|||
local L = LibStub("AceLocale-3.0"):NewLocale("BalerocHealers", "koKR")
|
||||
if not L then return end
|
||||
|
||||
--@localization(locale="koKR", format="lua_additive_table", handle-subnamespaces="concat")@
|
4
Locale/ruRU.lua
Normal file
4
Locale/ruRU.lua
Normal file
|
@ -0,0 +1,4 @@
|
|||
local L = LibStub("AceLocale-3.0"):NewLocale("BalerocHealers", "ruRU")
|
||||
if not L then return end
|
||||
|
||||
--@localization(locale="ruRU", format="lua_additive_table", handle-subnamespaces="concat")@
|
4
Locale/zhCN.lua
Normal file
4
Locale/zhCN.lua
Normal file
|
@ -0,0 +1,4 @@
|
|||
local L = LibStub("AceLocale-3.0"):NewLocale("BalerocHealers", "zhCN")
|
||||
if not L then return end
|
||||
|
||||
--@localization(locale="zhCN", format="lua_additive_table", handle-subnamespaces="concat")@
|
4
Locale/zhTW.lua
Normal file
4
Locale/zhTW.lua
Normal file
|
@ -0,0 +1,4 @@
|
|||
local L = LibStub("AceLocale-3.0"):NewLocale("BalerocHealers", "zhTW")
|
||||
if not L then return end
|
||||
|
||||
--@localization(locale="zhTW", format="lua_additive_table", handle-subnamespaces="concat")@
|
3
README
3
README
|
@ -0,0 +1,3 @@
|
|||
As leveling gets easier in World of Warcraft, more and more people are playing more and more alts. And for every alt you add, there are more chores to be done. You have to do your Molten Front dailies on your Hunter, make sure you get your Priest into a Firelands, get that new level 85 Mage into a BWD, and, of course, knock out a Baradin Hold on every 85. Unfortunately, it is incredibly difficult to keep track of all this.
|
||||
|
||||
ChoreTracker attempts to solve this problem for you by providing a table of all of your characters with their current Valor Points, Raid Instance locks, and more. Make sure you never miss a Chore again!
|
Loading…
Reference in a new issue