local _,rematch = ... local L = rematch.localization local C = rematch.constants local settings = rematch.settings rematch.loadTeam = {} local loadPlan = {} -- ordered list of loadouts to change: {slot,petID,ability1,ability2,ability3} local timeout = 0 -- timeout counter to stop trying to load local loadingTeamID -- teamID being loaded -- local functions to perform the load local startLoad, runLoad, finishLoad local getExcludePetIDs -- indexed by pet slot, an issue with the team being loaded (C.UNPLANNED_PET_MISSING for missing pet, C.UNPLANNED_LOW_LEVEL for random pet under 25) local unplanned = {} -- call to load a teamID function rematch.loadTeam:LoadTeamID(teamID) if rematch.loadouts:CantSwapPets() then return -- can't swap pets, leave end if teamID and rematch.savedTeams[teamID] then rematch.rebuild:ValidateTeamID(teamID,true) loadingTeamID = teamID startLoad(teamID) end end -- loads a team by its case-insensitive name and returns the teamID being loaded if one is going to load function rematch.loadTeam:LoadTeamByName(teamName) local teamID = rematch.savedTeams:GetTeamIDByName(teamName:trim()) if teamID then rematch.loadTeam:LoadTeamID(teamID) return teamID end end function rematch.loadTeam:UnloadTeam() settings.currentTeamID = nil rematch.queue:Process() rematch.events:Fire("REMATCH_TEAM_LOADED") end -- returns true if a team is currently loading function rematch.loadTeam:IsTeamLoading() return loadingTeamID and true or false end -- returns the healthiest version of the petID (possibly same petID if LoadHealthiest not enabled) function rematch.loadTeam:FindHealthiestPetID(petID,excludePetIDs) local bestPetID = petID local petInfo = rematch.altInfo:Fetch(petID) -- only looking for a healthier pet if setting enabled, player owns more than 1 of the species and petID injured if settings.LoadHealthiest and petInfo.count>1 then local bestHealth = petInfo.health local speciesID = petInfo.speciesID local maxHealth, power, speed = petInfo.maxHealth, petInfo.power, petInfo.speed for ownedPetID in rematch.roster:AllSpeciesPetIDs(speciesID) do petInfo = rematch.altInfo:Fetch(ownedPetID) if petInfo.speciesID==speciesID and petInfo.isOwned and petInfo.health>bestHealth then -- if LoadHealthiestAny is true, then don't need to match other stats if (settings.LoadHealthiestAny or (petInfo.maxHealth==maxHealth and petInfo.power==power and petInfo.speed==speed)) and (ownedPetID==petID or (excludePetIDs and not excludePetIDs[ownedPetID])) then bestPetID = ownedPetID bestHealth = petInfo.health end end end end if bestPetID and petID~=bestPetID then excludePetIDs[bestPetID] = true -- add this new petID to excluded pets so it's not loaded into another slot end return bestPetID end -- to be called when we want to make sure the already-loaded team has the healthiest pet (leaving battle, revive/bandages) -- note to self: if this ever does anything on a delay, make sure to update rematch.main's delayedPetBattleClose too -- (there's already some potential delay/queue processing for rematch.loadouts:SlotPet(), this is ok) function rematch.loadTeam:AssertHealthiestPet() if settings.LoadHealthiest then local teamID = settings.currentTeamID local team = teamID and rematch.savedTeams[teamID] if team then -- for asserting healthiest pets, just exclude loaded petIDs (team's pets may want back in and shouldn't be excluded) local excludePetIDs = {} for i=1,3 do local petID = C_PetJournal.GetPetLoadOutInfo(i) if petID then excludePetIDs[petID] = true end end for i=1,3 do local loadedPetID = rematch.loadouts:GetLoadoutInfo(i) local petInfo = rematch.petInfo:Fetch(loadedPetID) if petInfo.idType=="pet" and petInfo.isOwned then local newPetID = rematch.loadTeam:FindHealthiestPetID(loadedPetID,excludePetIDs) if newPetID and loadedPetID~=newPetID then rematch.loadouts:SlotPet(i,newPetID) excludePetIDs[newPetID] = true end end end end end end -- sets up the load plan and kicks off loading function startLoad(teamID) wipe(loadPlan) local team = teamID and rematch.savedTeams[teamID] if team then -- if all pets in a team are random, then use lenient rule local randomRules = C.RANDOM_RULES_LENIENT for i=1,3 do if rematch.loadouts:GetSpecialPetIDType(team.pets[slot])~="random" then randomRules = settings.RandomPetRules -- a non-random pet in team, used saved random rules end end -- for random teams, build list of pets to exclude including slotted pets and incoming pets local excludePetIDs = {} for i=1,3 do local petID = C_PetJournal.GetPetLoadOutInfo(i) if petID then excludePetIDs[petID] = true end local petInfo = rematch.petInfo:Fetch(team.pets[i]) if petInfo.idType=="pet" then excludePetIDs[team.pets[i]] = true end end rematch.queue:Update(teamID) -- update queue to the incoming team's preferences local pickIndex = 1 -- 1-3 for leveling pet to load from queue wipe(unplanned) -- add each pet to the load plan for the team for slot=1,3 do local petID = team.pets[slot] rematch.loadouts:SetSlotPetID(slot,petID) -- set slot's petID regardless if it loads for special slots if petID then local petInfo = rematch.petInfo:Fetch(petID) -- every pet being slotted must be a valid owned pet BattlePet-0-etc if petID==0 then -- leveling pet local levelingPetID = rematch.queue:GetTopPick(pickIndex) if levelingPetID then tinsert(loadPlan,{slot,levelingPetID}) -- add leveling pet to load plan excludePetIDs[levelingPetID] = true -- exclude leveling pet from potential randoms elseif settings.QueueRandomWhenEmpty then -- if a leveling pet wasn't found and Random Pet When Queue Empty enabled, pick a random pet local levelingPetID = rematch.randomPets:PickRandomPetID({excludePetIDs=excludePetIDs}) if levelingPetID then tinsert(loadPlan,{slot,levelingPetID}) excludePetIDs[levelingPetID] = true end end pickIndex = pickIndex + 1 elseif petInfo.idType=="pet" and petInfo.isValid and petInfo.isOwned and petInfo.isSummonable then local ability1,ability2,ability3 = rematch.petTags:GetAbilities(team.tags[slot]) local healthiestPetID = rematch.loadTeam:FindHealthiestPetID(petID,excludePetIDs) -- returns same petID if option disabled tinsert(loadPlan,{slot,healthiestPetID,ability1,ability2,ability3}) excludePetIDs[healthiestPetID] = true elseif petInfo.idType=="pet" and not petInfo.isValid then local newPetID = rematch.petTags:FindPetID(team.tags[slot],excludePetIDs) if newPetID then tinsert(loadPlan,{slot,newPetID,ability1,ability2,ability3}) excludePetIDs[newPetID] = true end elseif petInfo.idType=="random" then local petType = tonumber(petID:match("^random:(%d+)")) local randomPetID = rematch.randomPets:PickRandomPetID({petType=petType,rules=randomRules,excludePetIDs=excludePetIDs}) if randomPetID then local petInfo = rematch.petInfo:Fetch(randomPetID) if settings.RandomAbilitiesToo then -- if Random Abilities Too enabled, load random abilities too tinsert(loadPlan,{slot,randomPetID,petInfo.abilityList[1+(random(100)>50 and 3 or 0)],petInfo.abilityList[2+(random(100)>50 and 3 or 0)],petInfo.abilityList[3+(random(100)>50 and 3 or 0)]}) else -- otherwise let game choose abilities and only slot petID tinsert(loadPlan,{slot,randomPetID}) end if settings.WarnWhenRandomNot25 and (not petInfo.level or petInfo.level<25) then unplanned[slot] = {problem=C.UNPLANNED_LOW_LEVEL,petID=randomPetID} end excludePetIDs[randomPetID] = true -- add this random pet to exclude for other slots end elseif not settings.DontWarnMissing then unplanned[slot] = {problem=C.UNPLANNED_PET_MISSING,petID=petID} end end end end timeout = 0 -- start timeout counter runLoad() -- kick off the load end -- goes through the load plan and removes anything that no longer needs to be loaded, returning true if something -- still needs to be loaded; false if all done function updatePlan() local somethingNeedsLoaded = false -- becomes true if something still needs loaded -- go through plan and remove anything that's been loaded; if any plan should be entirely removed, change slot to "remove" for _,plan in ipairs(loadPlan) do local slot,petID,ability1,ability2,ability3 = unpack(plan) if type(slot)~="number" and not (slot==1 or slot==2 or slot==3) then plan[1] = "remove" -- this slot is not valid, remove from plan else local loadedPetID,loadedAbility1,loadedAbility2,loadedAbility3,loadedLocked = C_PetJournal.GetPetLoadOutInfo(slot) if loadedLocked then plan[1] = "remove" -- this slot is locked, remove from plan else if petID and loadedPetID==petID then plan[2] = nil -- pet doesn't need loaded end if not ability1 or ability1==0 or (ability1 and loadedAbility1==ability1) then plan[3] = nil -- ability1 doesn't need loaded end if not ability2 or ability2==0 or (ability2 and loadedAbility2==ability2) then plan[4] = nil -- ability2 doesn't need loaded end if not ability3 or ability3==0 or (ability3 and loadedAbility3==ability3) then plan[5] = nil -- ability3 doesn't need loaded end if not plan[2] and not plan[3] and not plan[4] and not plan[5] then plan[1] = "remove" -- petID and all abilities loaded, remove from plan end end end end -- remove any plans flags for removal for i=#loadPlan,1,-1 do if loadPlan[i][1]=="remove" then tremove(loadPlan,i) else somethingNeedsLoaded = true end end return somethingNeedsLoaded end -- slots the pets planned from startLoad by going through each record and loading it if it's not loaded function runLoad() if timeout