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.
575 lines
20 KiB
575 lines
20 KiB
local PetJournalEnhanced = LibStub("AceAddon-3.0"):GetAddon("PetJournalEnhanced")
|
|
local Sorting = PetJournalEnhanced:NewModule("Sorting", "AceEvent-3.0")
|
|
local BreedInfo = LibStub("LibPetBreedInfo-1.0")
|
|
local BREED_HIGH_CONFIDENCE = 2
|
|
local MAX_BALANCED = 1
|
|
local MAX_SPEED = 2
|
|
local MAX_STAMINA = 3
|
|
local MAX_ATTACK = 4
|
|
local ASCENDING = 1
|
|
local DESCENDING = 2
|
|
local USER = nil
|
|
|
|
-- GLOBALS: C_PetJournal PetJournal LE_PET_JOURNAL_FILTER_COLLECTED LE_PET_JOURNAL_FILTER_NOT_COLLECTED PetJournalSearchBox
|
|
|
|
local petMapping = {}
|
|
|
|
local SetPet, GetPet
|
|
do
|
|
local petStore = {}
|
|
function SetPet(pet)
|
|
if pet.isOwned then
|
|
petStore[pet.petID] = pet
|
|
else
|
|
petStore[pet.speciesID] = pet
|
|
end
|
|
end
|
|
|
|
function Sorting:GetPet(petID)
|
|
return petStore[petID]
|
|
end
|
|
end
|
|
|
|
local GetSortFunctions
|
|
do
|
|
local function GetCompareFunc(var,func,direction)
|
|
return function(a,b)
|
|
local order = Sorting.db.global.sorting.order
|
|
local avar = a[var]
|
|
local bvar = b[var]
|
|
if type(avar) == "boolean" then
|
|
avar = avar and 1 or 0
|
|
bvar = bvar and 1 or 0
|
|
end
|
|
|
|
if avar == bvar and func then
|
|
return func(a,b)
|
|
end
|
|
|
|
if direction then
|
|
if direction == ASCENDING then
|
|
return avar < bvar
|
|
elseif direction == DESCENDING then
|
|
return avar > bvar
|
|
end
|
|
elseif order == ASCENDING then
|
|
return avar < bvar
|
|
elseif order == DESCENDING then
|
|
--if not avar or not bvar then print(avar,bvar,var) print(a.name,b.name) end
|
|
return avar > bvar
|
|
end
|
|
end
|
|
end
|
|
|
|
local function ComposeSortFunction(...)
|
|
local args = {...}
|
|
local func = nil
|
|
for i=#args,1,-2 do
|
|
local name = args[i-1];
|
|
local direction = args[i]
|
|
func = GetCompareFunc(name, func, direction)
|
|
end
|
|
return func
|
|
end
|
|
|
|
local sortFunctions = {
|
|
ComposeSortFunction("isOwned", DESCENDING, "level", USER, "name", ASCENDING),
|
|
ComposeSortFunction("isOwned", DESCENDING, "name", USER, "level", DESCENDING),
|
|
ComposeSortFunction("isOwned", DESCENDING, "petType", USER, "level", DESCENDING, "name", ASCENDING),
|
|
ComposeSortFunction("isOwned", DESCENDING, "rarity", USER, "level", DESCENDING, "name", ASCENDING),
|
|
ComposeSortFunction("isOwned", DESCENDING, "maxStat", USER, "level", DESCENDING, "name", ASCENDING),
|
|
ComposeSortFunction("isOwned", DESCENDING, "breed", USER, "level", DESCENDING, "name", ASCENDING),
|
|
}
|
|
|
|
local sortFunctionsFavoritesFirst = {}
|
|
for i=1,#sortFunctions do
|
|
sortFunctionsFavoritesFirst[i] = GetCompareFunc("favorite", sortFunctions[i], DESCENDING)
|
|
end
|
|
|
|
function GetSortFunctions()
|
|
if Sorting.sorting.favoritesFirst then
|
|
return sortFunctionsFavoritesFirst
|
|
else
|
|
return sortFunctions
|
|
end
|
|
end
|
|
end
|
|
|
|
function Sorting:OnInitialize()
|
|
-- self.ZoneFiltering = PetJournalEnhanced:GetModule("ZoneFiltering")
|
|
self.callbacks = LibStub("CallbackHandler-1.0"):New(self)
|
|
|
|
local defaults = {
|
|
global = {
|
|
filtering = {
|
|
rarity = {
|
|
[1] = true,
|
|
[2] = true,
|
|
[3] = true,
|
|
[4] = true
|
|
},
|
|
breed = {
|
|
[3] = true,
|
|
[4] = true,
|
|
[5] = true,
|
|
[6] = true,
|
|
[7] = true,
|
|
[8] = true,
|
|
[9] = true,
|
|
[10] = true,
|
|
[11] = true,
|
|
[12] = true,
|
|
},
|
|
specialization = {
|
|
[1] = true,
|
|
[2] = true,
|
|
[3] = true,
|
|
[4] = true
|
|
},
|
|
level = {
|
|
[1] = true,
|
|
[2] = true,
|
|
[3] = true,
|
|
[4] = true,
|
|
[5] = true
|
|
},
|
|
quantity = { [1] = true, [2] = true, [3] = true },
|
|
currentZone = false,
|
|
canBattle = true,
|
|
cantBattle = true,
|
|
unknownZone = true,
|
|
cantTrade = true,
|
|
canTrade = true,
|
|
abilityType = {
|
|
[1] = true,
|
|
[2] = true,
|
|
[3] = true,
|
|
[3] = true,
|
|
[4] = true,
|
|
[5] = true,
|
|
[6] = true,
|
|
[7] = true,
|
|
[8] = true,
|
|
[9] = true,
|
|
[10] = true
|
|
},
|
|
hiddenSpecies = false,
|
|
favroritesOnly = false,
|
|
},
|
|
sorting = {
|
|
selection = 1,
|
|
order = ASCENDING,
|
|
favoritesFirst = false,
|
|
},
|
|
hiddenSpecies = {},
|
|
}
|
|
}
|
|
local db = LibStub("AceDB-3.0"):New("PetJournalEnhancedDB", {}, true)
|
|
local name = self:GetName()
|
|
self.db = db:RegisterNamespace(name, defaults)
|
|
self.db.global.filtering.unknownZone = true --always reset to true
|
|
self.filtering = self.db.global.filtering
|
|
self.sorting = self.db.global.sorting
|
|
|
|
self:RegisterEvent("ZONE_CHANGED_NEW_AREA")
|
|
self:RegisterEvent("PET_JOURNAL_PET_DELETED")
|
|
|
|
local LibPetJournal = LibStub("LibPetJournal-2.0")
|
|
LibPetJournal.RegisterCallback(self, "PostPetListUpdated", "ScanPets")
|
|
|
|
PetJournalSearchBox:HookScript("OnTextChanged", function() Sorting:SortPets() end)
|
|
hooksecurefunc(C_PetJournal,"SetFavorite", function() Sorting:UpdatePets() end)
|
|
end
|
|
|
|
|
|
function Sorting:IsSpeciesHidden(speciesID)
|
|
--print(speciesID)
|
|
if self.db.global.hiddenSpecies[speciesID] then
|
|
return true
|
|
end
|
|
end
|
|
|
|
function Sorting:SetSpeciesHidden(speciesID, hidden)
|
|
self.db.global.hiddenSpecies[speciesID] = hidden
|
|
end
|
|
|
|
function Sorting:ResetSpeciesHidden()
|
|
self.db.global.hiddenSpecies = {}
|
|
end
|
|
|
|
function Sorting:GetPetByIndex(index)
|
|
return petMapping[index]
|
|
end
|
|
|
|
function Sorting:GetNumPets()
|
|
return #petMapping
|
|
end
|
|
|
|
function Sorting:Reset()
|
|
C_PetJournal.SetFilterChecked(LE_PET_JOURNAL_FILTER_COLLECTED, true)
|
|
C_PetJournal.SetFilterChecked(LE_PET_JOURNAL_FILTER_NOT_COLLECTED, true)
|
|
C_PetJournal.SetAllPetTypesChecked(true)
|
|
C_PetJournal.SetAllPetSourcesChecked(true)
|
|
|
|
self.ZoneFiltering:SetAllFiltered(true)
|
|
|
|
local filtering = self.db.global.filtering
|
|
local sorting = self.db.global.sorting
|
|
|
|
for i=1,#filtering.rarity do
|
|
filtering.rarity[i] = true
|
|
end
|
|
|
|
for i=1,#filtering.abilityType do
|
|
filtering.abilityType[i] = true
|
|
end
|
|
|
|
for i=1,#filtering.level do
|
|
filtering.level[i] = true
|
|
end
|
|
|
|
for i=1,#filtering.specialization do
|
|
filtering.specialization[i] = true
|
|
end
|
|
|
|
for i=1,#filtering.quantity do
|
|
filtering.quantity[i] = true
|
|
end
|
|
|
|
for i=1,#filtering.breed do
|
|
filtering.breed[i] = true
|
|
end
|
|
|
|
filtering.currentZone = false
|
|
filtering.canBattle = true
|
|
filtering.cantBattle = true
|
|
filtering.unknownZone = true
|
|
filtering.canTrade = true
|
|
filtering.cantTrade = true
|
|
filtering.favoritesOnly = false
|
|
|
|
sorting.selection = 2
|
|
sorting.order = ASCENDING
|
|
sorting.favoritesFirst = false
|
|
|
|
self:SortPets()
|
|
end
|
|
|
|
function Sorting:ScanPets()
|
|
self:SortPets()
|
|
end
|
|
|
|
function Sorting:ZONE_CHANGED_NEW_AREA()
|
|
if self.filtering.currentZone then
|
|
self:SortPets()
|
|
end
|
|
end
|
|
|
|
function Sorting:PETJOURNAL_ENHANCED_OPTIONS_UPDATE()
|
|
self:SortPets()
|
|
end
|
|
|
|
function Sorting:PET_JOURNAL_PET_DELETED()
|
|
self:SortPets()
|
|
end
|
|
|
|
do
|
|
--Return highest stat for a pet. Check constants for return values.
|
|
local function GetMaxStat(maxHealth, attack, speed)
|
|
maxHealth = tonumber(maxHealth)
|
|
local stamina = tonumber(math.floor((maxHealth -100)/5))
|
|
attack = tonumber(attack)
|
|
speed = tonumber(speed)
|
|
|
|
if attack > speed and attack > stamina then
|
|
return MAX_ATTACK
|
|
elseif speed > attack and speed > stamina then
|
|
return MAX_SPEED
|
|
elseif stamina > attack and stamina > speed then
|
|
return MAX_STAMINA
|
|
end
|
|
return MAX_BALANCED
|
|
end
|
|
|
|
local function CreatePet(petID, speciesID, isOwned, name, petType, canBattle, tradable, rarity, level, sourceText, maxHealth, attack, speed)
|
|
local pet = {}
|
|
pet.speciesID = speciesID
|
|
pet.petID = petID
|
|
pet.isOwned = isOwned
|
|
pet.name = name
|
|
pet.petType = petType
|
|
pet.canBattle = canBattle
|
|
pet.tradable = tradable
|
|
pet.rarity = rarity or 0
|
|
pet.maxStat = 0
|
|
pet.abilityFilter = 0
|
|
pet.breed = 0
|
|
pet.breedConfidence = 0
|
|
pet.level = level or 0
|
|
pet.sourceText = sourceText
|
|
|
|
if isOwned and canBattle and maxHealth and attack and speed then
|
|
pet.maxStat = GetMaxStat(maxHealth, attack, speed)
|
|
local breed, breedConfidence = BreedInfo:GetBreedByPetID(petID)
|
|
if breed then
|
|
pet.breed, pet.breedConfidence = breed, breedConfidence
|
|
end
|
|
end
|
|
|
|
if canBattle then
|
|
local abilityIDs = C_PetJournal.GetPetAbilityList(pet.speciesID);
|
|
for j=1, #abilityIDs do
|
|
local _, _, abilityType = C_PetJournal.GetPetAbilityInfo(abilityIDs[j]);
|
|
pet.abilityFilter = bit.bor(pet.abilityFilter, 2^abilityType);
|
|
end
|
|
else
|
|
pet.level = 0
|
|
pet.rarity = 0
|
|
pet.petType = 0
|
|
end
|
|
return pet
|
|
end
|
|
|
|
local function UpdatePet(petID, pet, level, favorite, index, rarity)
|
|
pet.owned = C_PetJournal.GetNumCollectedInfo(pet.speciesID)
|
|
pet.favorite = favorite
|
|
pet.index = index
|
|
pet.petID = petID
|
|
|
|
if pet.canBattle and pet.isOwned then
|
|
if pet.breedConfidence < BREED_HIGH_CONFIDENCE and level > pet.level then
|
|
local breed, breedConfidence = BreedInfo:GetBreedByPetID(petID)
|
|
if breed then
|
|
pet.breed, pet.breedConfidence = breed, breedConfidence
|
|
end
|
|
end
|
|
pet.level = level
|
|
pet.rarity = rarity
|
|
end
|
|
end
|
|
|
|
function Sorting:SortPets()
|
|
--local start = debugprofilestop()
|
|
|
|
local numPets = C_PetJournal.GetNumPets(PetJournal.isWild)
|
|
local ZoneFiltering = self.ZoneFiltering
|
|
|
|
wipe(petMapping)
|
|
|
|
local activeFilters = self:GetActiveFilters()
|
|
|
|
for i=1,numPets do
|
|
local petID, speciesID, isOwned, _, level, favorite, _, name, _, petType, _, sourceText, _, _, canBattle, tradable, _ = C_PetJournal.GetPetInfoByIndex(i, PetJournal.isWild)
|
|
local maxHealth, attack, speed, rarity
|
|
if petID then
|
|
_, maxHealth, attack, speed, rarity = C_PetJournal.GetPetStats(petID)
|
|
end
|
|
|
|
local id = nil
|
|
if isOwned then id = petID else id = speciesID end
|
|
local pet = self:GetPet(id)
|
|
|
|
if not pet then
|
|
pet = CreatePet(petID, speciesID, isOwned, name, petType, canBattle, tradable, rarity, level, sourceText, maxHealth, attack, speed)
|
|
SetPet(pet)
|
|
end
|
|
|
|
UpdatePet(petID, pet, level, favorite, i, rarity)
|
|
|
|
--filter pet
|
|
local exclude = false
|
|
for i=1, #activeFilters do
|
|
exclude = activeFilters[i]:exclude(pet)
|
|
if exclude then break end
|
|
end
|
|
|
|
if not exclude then
|
|
table.insert(petMapping,pet)
|
|
end
|
|
end
|
|
|
|
local sortFuncs = GetSortFunctions()
|
|
local sortFunc = sortFuncs[self.sorting.selection]
|
|
table.sort(petMapping, sortFunc)
|
|
self.callbacks:Fire("PETS_SORTED")
|
|
|
|
--local stop = debugprofilestop() - start
|
|
--print(stop)
|
|
end
|
|
Sorting.UpdatePets = Sorting.SortPets
|
|
end
|
|
|
|
do
|
|
local function BitwiseAndTable(tbl)
|
|
local truth = true;
|
|
for k,v in pairs(tbl) do
|
|
truth = truth and v
|
|
end
|
|
return truth
|
|
end
|
|
|
|
local function InitializeFilters()
|
|
|
|
local filtering = Sorting.filtering
|
|
local sorting = Sorting.sorting
|
|
local ZoneFiltering = Sorting.ZoneFiltering
|
|
|
|
|
|
Sorting.filters = {
|
|
--[[
|
|
{
|
|
initialize = function(self) end,
|
|
enabled = function(self) return false end,
|
|
exclude = function(self,pet) return false end
|
|
},
|
|
]]
|
|
{
|
|
name = "can battle",
|
|
enabled = function() return not filtering.canBattle end,
|
|
exclude = function(self, pet) return pet.canBattle end
|
|
},
|
|
{
|
|
name = "favorites only",
|
|
enabled = function() return filtering.favoritesOnly end,
|
|
exclude = function(self, pet)
|
|
if pet.isOwned and not pet.favorite then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
},
|
|
{
|
|
name = "cant battle",
|
|
enabled = function() return not filtering.cantBattle end,
|
|
exclude = function(self, pet) return not pet.canBattle end
|
|
},
|
|
{
|
|
name = "can trade",
|
|
enabled = function() return not filtering.canTrade end,
|
|
exclude = function(self, pet) return pet.tradable end
|
|
},
|
|
{
|
|
name = "cant trade",
|
|
enabled = function() return not filtering.cantTrade end,
|
|
exclude = function(self, pet) return not pet.tradable end
|
|
},
|
|
{
|
|
name = "rarity",
|
|
enabled = function() return not BitwiseAndTable(filtering.rarity) end,
|
|
exclude = function(self, pet) return pet.rarity and pet.rarity > 0 and not filtering.rarity[pet.rarity] end
|
|
},
|
|
{
|
|
name = "quantity",
|
|
enabled = function() return not BitwiseAndTable(filtering.quantity) end,
|
|
exclude = function(self, pet) return pet.owned > 0 and not filtering.quantity[pet.owned] end
|
|
},
|
|
{
|
|
name = "pet spec",
|
|
enabled = function() return not BitwiseAndTable(filtering.specialization) end,
|
|
exclude = function(self, pet) return pet.maxStat > 0 and not filtering.specialization[pet.maxStat] end
|
|
},
|
|
-- {
|
|
-- name = "current zone",
|
|
-- initialize = function(self) self.currentZoneId = C_Map.GetBestMapForUnit("player") end,
|
|
-- enabled = function() return filtering.currentZone end,
|
|
-- exclude = function(self, pet)
|
|
-- local zones = ZoneFiltering:GetZonesBySpeciesID(pet.speciesID)
|
|
-- return (zones == nil or not zones[self.currentZoneId])
|
|
-- end
|
|
-- },
|
|
-- {
|
|
-- name = "unknown zone",
|
|
-- enabled = function() return not filtering.unknownZone end,
|
|
-- exclude = function(self, pet) return ZoneFiltering:GetZonesBySpeciesID(pet.speciesID) == nil end
|
|
-- },
|
|
{
|
|
name = "breed",
|
|
enabled = function() return not BitwiseAndTable(filtering.breed) end,
|
|
exclude = function(self, pet) return pet.breed > 0 and not filtering.breed[pet.breed] end
|
|
},
|
|
--[[
|
|
{
|
|
name = "level",
|
|
enabled = function() return not BitwiseAndTable(filtering.level) end,
|
|
exclude = function(self,pet)
|
|
return pet.level and
|
|
(not filtering.level[1] and pet.level == 1) or
|
|
(not filtering.level[2] and pet.level <= 10 and pet.level >= 2) or
|
|
(not filtering.level[3] and pet.level <= 20 and pet.level >= 11) or
|
|
(not filtering.level[4] and pet.level <= 24 and pet.level >= 20) or
|
|
(not filtering.level[5] and pet.level == 25)
|
|
end
|
|
},
|
|
]]
|
|
{
|
|
name = "ability",
|
|
abilityFilter = 0,
|
|
initialize = function(self)
|
|
self.abilityFilter = 0
|
|
for i=1,#filtering.abilityType do
|
|
if filtering.abilityType[i] then
|
|
self.abilityFilter = bit.bor(self.abilityFilter, 2^i);
|
|
end
|
|
end
|
|
end,
|
|
enabled = function()
|
|
return not BitwiseAndTable(filtering.abilityType)
|
|
end,
|
|
exclude = function(self, pet)
|
|
return pet.canBattle and bit.band(self.abilityFilter, pet.abilityFilter) == 0
|
|
end,
|
|
},
|
|
-- {
|
|
-- name = "zone selection",
|
|
-- enabled = function() return not ZoneFiltering:IsEveryZoneEnabled() end,
|
|
-- exclude = function(self, pet)
|
|
-- local zones = ZoneFiltering:GetZonesBySpeciesID(pet.speciesID)
|
|
-- if zones then
|
|
-- local filtered = false
|
|
-- for k,v in pairs(zones) do
|
|
-- filtered = filtered or ZoneFiltering:GetFiltered(k)
|
|
-- end
|
|
-- return not filtered
|
|
-- end
|
|
-- return false
|
|
-- end
|
|
-- },
|
|
{
|
|
name = "hidden species",
|
|
enabled = function() return not filtering.hiddenSpecies end,
|
|
exclude = function(self, pet)
|
|
return Sorting:IsSpeciesHidden(pet.speciesID)
|
|
end
|
|
},
|
|
}
|
|
|
|
local levelRanges = {{1,1}, {2,10}, {11,20}, {21,24}, {25,25}}
|
|
for i=1,#levelRanges do
|
|
local filter = {
|
|
name = "level "..levelRanges[i][1].."-"..levelRanges[i][2],
|
|
enabled = function() return not filtering.level[i] end,
|
|
exclude = function(self, pet)
|
|
return pet.level and pet.level >= levelRanges[i][1] and pet.level <= levelRanges[i][2]
|
|
end
|
|
}
|
|
table.insert(Sorting.filters, filter)
|
|
end
|
|
end
|
|
|
|
function Sorting:GetActiveFilters()
|
|
if not self.filters then InitializeFilters() end
|
|
local activeFilters = {}
|
|
for i=1, #self.filters do
|
|
if self.filters[i].initialize then
|
|
self.filters[i]:initialize()
|
|
end
|
|
|
|
if self.filters[i].enabled() then
|
|
--print(self.filters[i].name or "Error: no filter name")
|
|
table.insert(activeFilters, self.filters[i])
|
|
end
|
|
end
|
|
return activeFilters
|
|
end
|
|
|
|
end
|
|
|