PetJournal Enhanced

130 - Pets become unsorted after any pet levels

The Sorting:SortPets() function is not called when a battle pets levels up, either in battle or by using a level token. This causes the order of pets to not match your current sort selection. If you are sorting by rarity, for instance, green/white or gray pets will appear in the list where your leveled pet was. More-over, if you go and hunt down the pet you leveled in its new position in the list and try to rename it, it often renames the pet above or below it instead.

In sorting.lua you have SortPets() registered to run on:

    ZONE_CHANGED_NEW_AREA
    PETJOURNAL_ENHANCED_OPTIONS_UPDATE
    PET_JOURNAL_PET_DELETED

I believe you want to swap PET_JOURNAL_PET_DELETED for PET_JOURNAL_LIST_UPDATE. This event is fired when a pet levels, and it is fired when a pet is caged and the PET_JOURNAL_PET_DELETED is fired.

User When Change
Zarillion Aug 16, 2015 at 23:02 UTC Create

You must login to post a comment. Don't have an account? Register to get one!

  • 6 comments
  • Avatar of Phanx Phanx Oct 08, 2015 at 09:24 UTC - 0 likes

    If you want changes to be made in LibPetJournal, rather than in PetJournalEnhanced, you should probably submit a ticket on the library's page, rather than here. LPJ is an independent project by a different author, and it's unlikely the library's author watches the ticket trackers of random addons that use the library for suggestions.

    http://wow.curseforge.com/addons/libpetjournal-2-0/

  • Avatar of joevt joevt Oct 07, 2015 at 23:57 UTC - 0 likes

    Sure, for PJE, sorting every time doesn't take too long.

    But LibPetJournal-2.0 is used by many add-ons. Fixing that will fix those add-ons as well. Those addon's might have an expensive calculation that you would want to run only when a change occurs in the data. So if you remove the other events and only do PJLU, then the code below should do the job. It works pretty well. It doesn't take too long to add the level, rarity, and xp of a 1000 pets.

    function lib.event_frame:PET_JOURNAL_LIST_UPDATE()
        if not IsLoggedIn() then
            return
        end
        
        local total, owned = C_PetJournal.GetNumPets()
    
        local totallqx = 0
        for i = 1,total do
            local petID, _, isOwned = C_PetJournal.GetPetInfoByIndex(i)
            if isOwned then
                local _, _, level, xp = C_PetJournal.GetPetInfoByPetID(petID)
                local _, _, _, _, quality = C_PetJournal.GetPetStats(petID)
                totallqx = totallqx + ((level * 10) + quality) * 10000 + xp
            end
        end
        
        if lib._last_owned ~= owned or lib._totallqx ~= totallqx then
            lib._last_owned = owned
            lib._totallqx = totallqx
            if not lib:LoadPets() then
                lib.event_frame:Show()
                return
            end
        elseif total > lib._last_total then
            return start_background()
        end
        
        lib.callbacks:Fire("PetsUpdated", self)
    end
    
  • Avatar of Phanx Phanx Oct 06, 2015 at 09:09 UTC - 0 likes

    Well, PJE already correctly updates the level displayed in the list when you use a battle stone, so I really don't think you need any new event handlers at all. Just add a call to the sorting function before you call the visual update function, wherever that's happening.

    If you really need to listen for events, PET_JOURNAL_LIST_UPDATE is still going to be less spammy than CLEU if you're anywhere near other players, and since it's unlikely you're going to be looking through your pet journal in the middle of a boss fight, the CPU overhead of scanning the pet list and checking the levels vs checking one argument in CLEU is irrelevant, and is still a better solution because it doesn't require hardcoded data. (If you are looking at pets in combat, then CLEU probably becomes more CPU-intensive due to the sheer volume of events.)

  • Avatar of joevt joevt Oct 06, 2015 at 02:33 UTC - 0 likes

    You can add PET_BATTLE_LEVEL_CHANGED to know when a pet levels due to a pet battle. You might want to also add PET_BATTLE_XP_CHANGED if you sort by both level and XP.

    For battle stones, the only other solution I can think of is to count the pets of each rarity and level during the PET_JOURNAL_LIST_UPDATE event. The reason I went with CLEU is because LibPetJournal-2.0 seems to go out of its way to avoid scanning pets (LoadPets) by scanning only when the Owned value from GetNumPets has changed.

    I called IsLoggedIn because the other event handlers did, but you're right. Since I'm only setting the forceload variable, then it shouldn't matter. The PET_JOURNAL_LIST_UPDATE handler which checks forceload calls IsLoggedIn anyway.

    I agree hardcoding is not the best solution, but there's no other way to tell if a spell affects your battle pet. A substring search of the spell name or icon would be just as hard-coded. The summoned pet GUID doesn't match the target GUID. You could compare the npc ID of the target and the pet and use UnitIsFriend but there might be cases where the npc is not your pet, or the spell is not a level or rarity changing spell.

    So I guess you need to choose whether the overhead of counting 800+ pets for each PET_JOURNAL_LIST_UPDATE event is more preferable than checking the spell of each CLEU event.

    lib.event_frame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
    function lib.event_frame:COMBAT_LOG_EVENT_UNFILTERED(...)
        local timeStamp, event, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags, spellID, spellName = ...
        if event == "SPELL_CAST_SUCCESS" and sourceGUID == UnitGUID("player") and petspells[spellID] then
            forceload = true
        end
    end
    
    lib.event_frame:RegisterEvent("PET_BATTLE_LEVEL_CHANGED")
    function lib.event_frame:PET_BATTLE_LEVEL_CHANGED(...)
        local team, pet, level = ...
        if team == 1 then
            forceload = true
        end
    end
    
    lib.event_frame:RegisterEvent("PET_BATTLE_XP_CHANGED")
    function lib.event_frame:PET_BATTLE_XP_CHANGED(...)
        local team, pet, xp = ...
        if team == 1 then
            forceload = true
        end
    end
    
  • Avatar of Phanx Phanx Oct 05, 2015 at 06:52 UTC - 0 likes

    @joevt:

    Listening to COMBAT_LOG_EVENT_UNFILTERED just to detect when the pet journal list should be resorted sounds like a horrible solution. Do you have any idea how frequently CLEU fires?

    Also, there's no excuse for ever checking IsLoggedIn() in a CLEU handler (or a PET_JOURNAL_LIST_UPDATE handler, or pretty much any event handler for that matter). If those events can even fire before the player is logged in (which I doubt) then the correct solution would be to wait for PLAYER_LOGIN to register for them.

    Finally, hardcoding data is always the worst solution to any problem, especially when hardcoding data doesn't even solve the problem. Battle stones aren't the only way pets can gain levels, and even if they were, watching the combat log would still not be the most efficient solution to the problem.

  • Avatar of joevt joevt Oct 05, 2015 at 01:20 UTC - 0 likes

    LibPetJournal-2.0 fires a PetsUpdated event when PET_JOURNAL_LIST_UPDATE occurs but this occurs too often (when pets don't need to be resorted) so PetJournal Enhanced uses the PostPetListUpdated event from LibPetJournal-2.0.

    The problem with PostPetListUpdated is that it fires only when the number of owned pets changes.

    I think either LibPetJournal-2.0 needs to do the following (or PetJournal Enhanced can do it):

    local forceload = false
    
    lib.event_frame:RegisterEvent("PET_JOURNAL_LIST_UPDATE")
    function lib.event_frame:PET_JOURNAL_LIST_UPDATE()
        if not IsLoggedIn() then
            return
        end
        
        local total, owned = C_PetJournal.GetNumPets()
        if lib._last_owned ~= owned or forceload then
            forceload = false
            lib._last_owned = owned
            if not lib:LoadPets() then
                lib.event_frame:Show()
                return
            end
        elseif total > lib._last_total then
            return start_background()
        end
        
        print("Collectinator PET_JOURNAL_LIST_UPDATE fire PetsUpdated")    
        lib.callbacks:Fire("PetsUpdated", self)
    end
    
    
    local petspells = {
    -- uncommon quality
        [134761] = true, -- "Polished Critter Battle-Stone"
        [134494] = true, -- "Polished Elemental Battle-Stone"
        [134495] = true, -- "Polished Beast Battle-Stone"
        [134496] = true, -- "Polished Battle-Stone"
        [134497] = true, -- "Polished Flying Battle-Stone"
        [134498] = true, -- "Polished Magic Battle-Stone"
        [134499] = true, -- "Polished Aquatic Battle-Stone"
        [134501] = true, -- "Polished Mechanical Battle-Stone"
        [134502] = true, -- "Polished Undead Battle-Stone"
        [134503] = true, -- "Polished Humanoid Battle-Stone"
    
        [134504] = true, -- "Polished Dragonkin Battle-Stone"
    
    -- rare quality
        [134448] = true, -- "Flawless Elemental Battle-Stone"
        [134482] = true, -- "Flawless Beast Battle-Stone"
        [134484] = true, -- "Flawless Critter Battle-Stone"
        [134486] = true, -- "Flawless Flying Battle-Stone"
        [134487] = true, -- "Flawless Magic Battle-Stone"
        [134488] = true, -- "Flawless Aquatic Battle-Stone"
        [134489] = true, -- "Flawless Mechanical Battle-Stone"
        [134490] = true, -- "Flawless Undead Battle-Stone"
        [134491] = true, -- "Flawless Humanoid Battle-Stone"
        [134492] = true, -- "Flawless Dragonkin Battle-Stone"
    
        [134644] = true, -- "Flawless Battle-Stone"
    
    -- epic quality
        [134508] = true, -- "Perfect Aquatic Battle-Stone"
        [134512] = true, -- "Perfect Beast Battle-Stone"
        [134514] = true, -- "Perfect Critter Battle-Stone"
        [134515] = true, -- "Perfect Dragonkin Battle-Stone"
        [134516] = true, -- "Perfect Elemental Battle-Stone"
        [134517] = true, -- "Perfect Flying Battle-Stone"
        [134518] = true, -- "Perfect Humanoid Battle-Stone"
        [134519] = true, -- "Perfect Magic Battle-Stone"
        [134520] = true, -- "Perfect Mechanical Battle-Stone"
        [134521] = true, -- "Perfect Undead Battle-Stone"
    
        [134645] = true, -- "Perfect Battle-Stone"
    
    -- one level
        [162984] = true, -- "Beast Battle-Training Stone"
        [171515] = true, -- "Aquatic Battle-Training Stone"
        [171516] = true, -- "Dragonkin Battle-Training Stone"
        [171517] = true, -- "Humanoid Battle-Training Stone"
        [171518] = true, -- "Flying Battle-Training Stone"
        [171519] = true, -- "Undead Battle-Training Stone"
        [171520] = true, -- "Critter Battle-Training Stone"
        [171521] = true, -- "Magic Battle-Training Stone"
        [171522] = true, -- "Elemental Battle-Training Stone"
        [171523] = true, -- "Mechanical Battle-Training Stone"
    
        [171525] = true, -- "Flawless Battle-Training Stone"
        [162784] = true, -- "Training Battle-Stone of Testing"
    
    -- five levels
        [187567] = true, -- "Fel-Touched Battle-Training Stone"
    
    -- 25 levels
        [166016] = true, -- "Mythical Battle-Pet Stone"
        [181062] = true, -- "Ultimate Battle-Training"
    }
    
    lib.event_frame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
    function lib.event_frame:COMBAT_LOG_EVENT_UNFILTERED(...)
        if not IsLoggedIn() then
            return
        end
        local timeStamp, event, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags, spellID, spellName = ...
        if event == "SPELL_CAST_SUCCESS" and sourceGUID == UnitGUID("player") and petspells[spellID] then
            -- print("pet spell cast occured")
            forceload = true
        end
    end
    

    The above handles all the battle stones and training stones. The LoadPets call fires the PostPetListUpdated event. Additional code might be required for xp gained from pet battles.

    LibPetJounal-2.0 is a library which many add-on's can embed, but only one of them will get loaded, so you need to change them all, or change a stand alone version that you know will get loaded before all the others.

  • 6 comments

Facts

Reported
Aug 16, 2015
Status
New - Issue has not had initial review yet.
Type
Defect - A shortcoming, fault, or imperfection
Priority
Medium - Normal priority.
Votes
0

Reported by

Possible assignees