local _,rematch = ... local L = rematch.localization local C = rematch.constants local settings = rematch.settings rematch.petCard = RematchPetCard rematch.events:Register(rematch.petCard,"PLAYER_LOGIN",function(self) self.Title:SetText(L["Pet Card"]) -- register cardManager behavior rematch.cardManager:Register("PetCard",self,{ update = self.Update, lockUpdate = self.UpdateLock, pinUpdate = self.UpdatePinButton, shouldShow = self.ShouldShow }) local font,size,flag = self.Content.Top.Name:GetFont() self.Content.Top.Name:SetFont(font,size+1,flag) self.Content.Front.Stats.AltFlipHelp.Text:SetFontObject("GameFontHighlightSmall") self.Content.Front.Stats.AltFlipHelp.Text:SetTextColor(0.6,0.6,0.6) self.Content.Back.Racial.DamageTaken:SetText(L["Damage\nTaken"]) self.Content.Back.Racial.StrongFrom:SetText(L["from"]) self.Content.Back.Racial.WeakFrom:SetText(L["from"]) self.Content.Back.Racial.StrongAbilities:SetText(L["abilities"]) self.Content.Back.Racial.WeakAbilities:SetText(L["abilities"]) local breedSource,breedSourceName = rematch.breedInfo:GetBreedSource() if breedSource then self.Content.Front.Stats.BreedTable.Title:SetText(breedSource=="PetTracker" and L["Possible Breeds"] or L["Stats as \124cff0070ddRare\124r level 25"]) self.Content.Front.Stats.BreedTable.Footer:SetText(format(L["All breed data pulled from %s%s\124r"],C.HEX_WHITE,breedSourceName)) self.Content.Front.Stats.BreedTable.NoBreeds:SetText(L["No known breeds :("]) end self.Content.Front.Stats.Buttons = {} -- lookup table of heights of various sections of the pet card; call petCard:ResetHeights() to reset all section heights to 0 self.heights = { chrome = C.PET_CARD_CHROME_HEIGHT, -- the height of the frame outside the content (titlebar, border) never changes } self:Configure() -- create hook for using pet cards as links hooksecurefunc("SetItemRef",self.SetItemRef) rematch.menus:Register("AbilityMenu",{ {title=rematch.petCard.GetAbilityNameByID}, {text=L["Find Pets With This Ability"], func=rematch.petCard.FindPetsWithAbility}, }) end) -- returns the name of abilityID function rematch.petCard:GetAbilityNameByID(abilityID) return (select(2,C_PetBattles.GetAbilityInfoByID(abilityID))) end -- summons pet view if not visible and searching for ability with abilityID function rematch.petCard:FindPetsWithAbility(abilityID) local abilityName = rematch.petCard:GetAbilityNameByID(abilityID) if abilityName then rematch.layout:SummonView("pets") local exactSearch = '"'..abilityName..'"' rematch.filters:SetSearch(exactSearch) rematch.petsPanel.Top.SearchBox:SetText(exactSearch) rematch.petsPanel:Update() end end function rematch.petCard:Update(petID) if petID then self.petID = petID end -- before building the card, reset all heights to 0; the ultimate size of the card will depend on the height of each section self:ResetHeights() -- if this is a leveling, random or ignored pet card, it can't flip local petInfo = rematch.petInfo:Fetch(self.petID) if not petInfo.name then rematch.petCard:Hide() end if petInfo.isSpecialType then self.hardFlip = false self.softFlip = false end -- update top of card which is always shown, front or back self.Content.Top:Update() -- update back of pet card first, its content height isn't as fluid as the front's self.Content.Back.Source:Update() -- update pet source at top of back self.Content.Back.Racial:Update() -- update pet type details at bottom of back self.Content.Back.Lore:Update() -- update lore in middle of back -- update front of the pet card next, abilities first then do stats is three sections self.Content.Front.Abilities:Update() -- update abilities at bottom of front self.Content.Front.Stats:UpdateBottom() -- update hp/xp statusbar, card-wide collected versions and possible breeds self.Content.Front.Stats:UpdateTop() -- update species name and all stats buttons listed to left beneath it (must come after UpdateBottom to fit rows/columns properly) self.Content.Front.Stats:UpdateArt() -- update level pennant and background for stats self.Content.Front.Stats:UpdateModel() -- update model on front of card -- put a gold border around parts of the card (pet/type icons, abilities) that triggered a search hit self:UpdateSearchHits() -- the tallest side gets to be the height of the card, so it remains the same size when flipped local backHeight = self.heights.chrome + self.heights.top + self.heights.source + self.heights.lore + self.heights.racial local frontHeight = self.heights.chrome + self.heights.top + self.heights.statsTop + self.heights.statsBottom + self.heights.abilities self:SetHeight(max(backHeight,frontHeight)) self:FlipCard() -- show front or back of card self:UpdatePinButton() end -- flips the pet card to the front or back depending on whether flip modifier key is down or soft/hardFlip -- softFlip is when the mouse is over the pet or type icon at the top of the card -- hardFlip is when the pet or type icon at the top of the card were clicked (so it stays flipped until flipped again or dismissed) function rematch.petCard:FlipCard() local petInfo = rematch.petInfo:Fetch(self.petID) -- if flip key is used then show back (unless doing a hardFlip and already showing back; then show front) local isFlipKeyUsed = self:IsFlipKeyUsed() if not petInfo.isSpecialType and (isFlipKeyUsed or self.softFlip or self.hardFlip) and not (isFlipKeyUsed and self.hardFlip) then self.Content.Front:Hide() self.Content.Back:Show() else self.Content.Back:Hide() self.Content.Front:Show() end self.FlipButton:SetShown(not petInfo.isSpecialType and self.hardFlip) -- only show flip button when the card is hard flipped (not modifier/mouseover) end -- if the modifier key going down or up is also the PetCardFlipKey, then update the card to potentially flip it over function rematch.petCard:MODIFIER_STATE_CHANGED(key,down) if self:IsFlipKeyUsed(key) then self:FlipCard() end end -- adjusts size of persistent elements when pet card is minimized or maximized function rematch.petCard:Configure() if settings.PetCardMinimized then self.MinimizeButton:SetIcon("maximize") self.Content.Top:SetHeight(C.PET_CARD_TOP_MINIMIZED_HEIGHT) self.Content.Top.PetIcon:SetSize(C.PET_CARD_TOP_ICON_MINIMIZED_SIZE,C.PET_CARD_TOP_ICON_MINIMIZED_SIZE) self.Content.Top.TypeIcon:SetSize(C.PET_CARD_TOP_ICON_MINIMIZED_SIZE,C.PET_CARD_TOP_ICON_MINIMIZED_SIZE) self.Content.Top.PetIcon:SetPoint("TOPLEFT",4,-3) self.Content.Front.Abilities:SetHeight(C.PET_CARD_ABILITIES_MINIMIZED_HEIGHT) for i=1,6 do self.Content.Front.Abilities.Buttons[i]:SetHeight(28) self.Content.Front.Abilities.Buttons[i].Icon:SetSize(24,24) self.Content.Front.Abilities.Buttons[i].Border:SetSize(28,28) self.Content.Front.Abilities.Buttons[i].TypeDecal:SetSize(40,28) end else self.MinimizeButton:SetIcon("minimize") self.Content.Top:SetHeight(C.PET_CARD_TOP_NORMAL_HEIGHT) self.Content.Top.PetIcon:SetSize(C.PET_CARD_TOP_ICON_NORMAL_SIZE,C.PET_CARD_TOP_ICON_NORMAL_SIZE) self.Content.Top.TypeIcon:SetSize(C.PET_CARD_TOP_ICON_NORMAL_SIZE,C.PET_CARD_TOP_ICON_NORMAL_SIZE) self.Content.Top.PetIcon:SetPoint("TOPLEFT",4,-4) self.Content.Front.Abilities:SetHeight(C.PET_CARD_ABILITIES_NORMAL_HEIGHT) for i=1,6 do self.Content.Front.Abilities.Buttons[i]:SetHeight(32) self.Content.Front.Abilities.Buttons[i].Icon:SetSize(28,28) self.Content.Front.Abilities.Buttons[i].Border:SetSize(32,32) self.Content.Front.Abilities.Buttons[i].TypeDecal:SetSize(46,32) end end end function rematch.petCard:UpdatePinButton() local isPinned = rematch.cardManager:IsCardPinned(self) self.PinButton:SetShown(isPinned) if isPinned then self.FlipButton:SetPoint("TOPLEFT",self.PinButton,"TOPRIGHT") else self.FlipButton:SetPoint("TOPLEFT",1,-1) end end function rematch.petCard:UpdateLock() if rematch.bottombar:IsVisible() then rematch.bottombar:Update() end -- if petsPanel up, select/unselect the card's petID if rematch.petsPanel:IsVisible() then rematch.petsPanel.List:Select("PetCard",rematch.petCard:IsVisible() and rematch.cardManager:IsCardLocked(rematch.petCard) and rematch.petCard.petID) end if rematch.queuePanel:IsVisible() then rematch.queuePanel.List:Select("PetCard",rematch.petCard:IsVisible() and rematch.cardManager:IsCardLocked(rematch.petCard) and rematch.queue:GetPetIndex(rematch.petCard.petID)) end -- if pet is wrapped, locking the pet card (clicking the pet or clicking its link) will unwrap the pet if rematch.cardManager:IsCardLocked(rematch.petCard) then local petID = rematch.petCard.petID local petInfo = rematch.petInfo:Fetch(petID) if petInfo.needsFanfare then rematch.petCard.Content.Front.Stats.PetModel:StartUnwrapAnimation(function() C_PetJournal.ClearFanfare(petID) rematch.frame:Update() -- fix for weird issue where miniloadoutpanel doesn't update rematch.timer:Start(0.5,rematch.frame.Update,rematch.frame) end) end end end --[[ content update functions ]] -- updates the pet icon, type icon and name at the top of the card (always displayed; on neither front nor back) function rematch.petCard.Content.Top:Update() local petInfo = rematch.petInfo:Fetch(rematch.petCard.petID) self.Back:SetDesaturated(not petInfo.isOwned) self.Name:SetText(petInfo.name) self.PetIcon:SetTexture(petInfo.icon) self.TypeIcon:SetTexture(petInfo.suffix and "Interface\\Icons\\Icon_PetFamily_"..petInfo.suffix or petInfo.icon) if settings.ColorPetNames and petInfo.color then self.Name:SetTextColor(petInfo.color.r,petInfo.color.g,petInfo.color.b) else self.Name:SetTextColor(1,0.82,0) end rematch.petCard.heights.top = settings.PetCardMinimized and C.PET_CARD_TOP_MINIMIZED_HEIGHT or C.PET_CARD_TOP_NORMAL_HEIGHT end -- updates the abilities on the bottom front of the card function rematch.petCard.Content.Front.Abilities:Update() local petInfo = rematch.petInfo:Fetch(rematch.petCard.petID) self.Back:SetDesaturated(not petInfo.isOwned) -- check whether this petID should display alternate text instead of abilities local altText if petInfo.idType=="leveling" then altText = L["When this team loads, your current leveling pet will go in this spot."] elseif petInfo.idType=="ignored" then altText = L["When this team loads, this spot will be ignored."] elseif petInfo.idType=="random" then altText = L["When this team loads, a random high level pet will go in this spot."] elseif petInfo.idType=="unnotable" then altText = L["The pets for this target are not recorded due to this target not being notable."] elseif not petInfo.canBattle then altText = BATTLE_PET_CANNOT_BATTLE end self.AltText:SetShown(altText and true or false) if altText then self.AltText:SetText(altText) for i=1,6 do self.Buttons[i]:Hide() end else local abilityList = petInfo.abilityList local teamID,teamAbility1,teamAbility2,teamAbility3 = rematch.petCard:GetTeamInfo() -- using altInfo within to avoid petInfo clobber local buttonIndex = 1 -- some pets (like Gizmo) have abilities at indexes 2,4,6 but not 1,3,5; can't assume abilities are ordered starting at 1 for i=1,6 do local abilityID = abilityList[i] if abilityID then local button = self.Buttons[buttonIndex] local _,name,icon,_,_,_,petType = C_PetBattles.GetAbilityInfoByID(abilityID) if name and icon and petType then button.abilityID = abilityID button.Name:SetText(name) button.Icon:SetTexture(icon) local x = ((petType-1)%4)*0.25 local y = floor((petType-1)/4)*0.25 button.TypeDecal:SetTexCoord(x,x+0.25,y,y+0.171875) button:Show() if teamID then -- if card is shown for a pet in a team, dim the ability if it's not used in the team local compareAbility = (i-1)%3==0 and teamAbility1 or (i-1)%3==1 and teamAbility2 or (i-1)%3==2 and teamAbility3 rematch.petCard:DimAbility(button,compareAbility and compareAbility~=0 and not (abilityID==compareAbility)) -- or compareAbility==0 to have slots with no chosen ability both lit up else rematch.petCard:DimAbility(button,false) end else button.abilityID = nil button:Hide() end buttonIndex = buttonIndex + 1 end end -- hide ability buttons that aren't used for i=buttonIndex,6 do self.Buttons[i].abilityID = nil self.Buttons[i]:Hide() end -- if only 3 or less abilities shown, shift abilities towards center self.Buttons[1]:SetPoint("TOPLEFT",rematch.utils:GetSize(abilityList)<=3 and 63 or 4,-4) end rematch.petCard.heights.abilities = settings.PetCardMinimized and C.PET_CARD_ABILITIES_MINIMIZED_HEIGHT or C.PET_CARD_ABILITIES_NORMAL_HEIGHT end -- dims the ability (if it's not used for a team) if dim is true function rematch.petCard:DimAbility(button,dim) if dim then button:SetAlpha(0.5) button.Name:SetTextColor(0.5,0.5,0.5) button.Icon:SetDesaturated(true) button.Icon:SetVertexColor(0.5,0.5,0.5) button.TypeDecal:SetDesaturated(true) else button:SetAlpha(1) button.Name:SetTextColor(1,0.82,0.5) button.Icon:SetDesaturated(false) button.Icon:SetVertexColor(1,1,1) button.TypeDecal:SetDesaturated(false) end end -- update the top part of stats: species name, stat buttons along left side (or two columns while minimized) function rematch.petCard.Content.Front.Stats:UpdateTop() local petInfo = rematch.petInfo:Fetch(rematch.petCard.petID) local xoff,yoff = C.PET_CARD_STAT_LEFT_MARGIN,-C.PET_CARD_STAT_TOP_MARGIN -- coordinates relative to TOPLEFT -- species name is topmost stat if pet is renamed and separate from others since it can wrap if petInfo.customName then self.SpeciesName:SetText(petInfo.speciesName) yoff = yoff - self.SpeciesName:GetStringHeight() - 2 self.SpeciesName:Show() else self.SpeciesName:Hide() end rematch.petCard:ReleaseStatButtons() -- first look for any wide stats to display at top, these never display in columns when minimized for index,info in ipairs(rematch.petCardStats) do if info.isWide and rematch.utils:Evaluate(info.show,rematch.petCard,petInfo) then local button = rematch.petCard:CreateStatButton(button,index,petInfo) button:SetPoint("TOPLEFT",xoff,yoff) button:Show() yoff = yoff - C.PET_CARD_STAT_HEIGHT - 1 end end -- next count how many remaining stats to display local numStats = 0 for index,info in ipairs(rematch.petCardStats) do if not info.isWide and rematch.utils:Evaluate(info.show,rematch.petCard,petInfo) then numStats = numStats + 1 end end -- next calculate number of rows (mostly for minimized, where there may be two columns) local numRows = numStats -- for maximized cards, number of rows is number of stats if settings.PetCardMinimized then numRows = ceil(numStats/2) -- two columns while minimized --if minimized and stat rows can extend further (card back is taller than front if stats evenly split into two columns), -- adjust numRows to use space local heights = rematch.petCard.heights local minHeight = (heights.source + heights.lore + heights.racial) - (heights.statsBottom + heights.abilities - yoff) if numRows*C.PET_CARD_STAT_HEIGHT < minHeight then numRows = floor(minHeight/(C.PET_CARD_STAT_HEIGHT+1)) end end -- finally place the remaining normal-width stats local restartYOff = yoff -- for returning to on second row local minYOff = yoff -- most extended yOff will determine height of stats local row = 1 for index,info in ipairs(rematch.petCardStats) do if not info.isWide and rematch.utils:Evaluate(info.show,rematch.petCard,petInfo) then local button = rematch.petCard:CreateStatButton(button,index,petInfo) button:SetPoint("TOPLEFT",xoff,yoff) button:Show() yoff = yoff - C.PET_CARD_STAT_HEIGHT - 1 minYOff = min(yoff,minYOff) row = row + 1 if row > numRows then row = 1 xoff = xoff + C.PET_CARD_STAT_WIDTH_MEDIUM + C.PET_CARD_STAT_PADDING yoff = restartYOff end end end -- final height is the most extended y offset (minYOff) or if not minimized, minimium model height local height = 0 if petInfo.isSpecialType then height = settings.PetCardMinimized and 64 or C.PET_CARD_MIN_MODEL_HEIGHT elseif minYOff~=-C.PET_CARD_STAT_TOP_MARGIN then -- if y offset didn't change at all, leave height at 0 if not settings.PetCardMinimized then height = max(-minYOff,C.PET_CARD_MIN_MODEL_HEIGHT) else height = -minYOff end end --rematch.petCard.heights.statsTop = floor((minYOff==-C.PET_CARD_STAT_TOP_MARGIN and 0 or -minYOff)+0.5) rematch.petCard.heights.statsTop = floor(height+0.5) end -- update hp/xp statusbar, card-wide collected versions and possible breeds function rematch.petCard.Content.Front.Stats:UpdateBottom() local petInfo = rematch.petInfo:Fetch(rematch.petCard.petID) -- start laying out bottom of stats at these coordinates and going up local xoff,yoff = C.PET_CARD_STAT_LEFT_MARGIN,C.PET_CARD_STAT_BOTTOM_MARGIN -- coordinates relative to TOPLEFT -- xp bar if pet can level is under level 25 if petInfo.xp and petInfo.maxXp and petInfo.level and petInfo.level<25 then self.XpBar:SetPoint("BOTTOMLEFT",xoff+2,yoff+2) self.XpBar:Show() rematch.utils:UpdateStatusBar(self.XpBar.Bar,petInfo.xp,petInfo.maxXp,C.PET_CARD_STATUS_BAR_WIDTH,C.XP_BAR_COLOR.r,C.XP_BAR_COLOR.g,C.XP_BAR_COLOR.b) self.XpBar.Text:SetText(format("XP: %d/%d (%s)",petInfo.xp,petInfo.maxXp,floor(petInfo.xp*100/petInfo.maxXp+0.5).."%")) self.XpBar.Text:SetShown(settings.PetCardAlwaysShowHPXPText) yoff = yoff + 14 else self.XpBar:Hide() end -- hp bar if pet has health and is injured if petInfo.isInjured or (settings.PetCardAlwaysShowHPBar and petInfo.maxHealth and petInfo.maxHealth>0) then --and petInfo.healthfrontHeight and (backHeight-frontHeight) or 0) + 5 local statsWidth = floor(self:GetWidth()+0.5) heights.fullStats = statsHeight -- background can take up full width/height of stats, whichever is the shorter dimension (bg is square always) local bgSize = min(statsWidth,statsHeight) -- expansion background local expansionCoords = petInfo.expansionID and C.EXPANSION_BG_TEXCOORDS[petInfo.expansionID] if settings.PetCardBackground=="Expansion" and expansionCoords and bgSize > 32 then local left,right,top,bottom = expansionCoords[1],expansionCoords[2],expansionCoords[3],expansionCoords[4] -- the expansion texture is 248px wide and 124px tall. the width never changes, but if the area available -- is less than 125px tall, the texture and its coords needs to be adjusted to cut them short if bgSize < 125 then self.ExpansionBackground:SetHeight(bgSize) self.ExpansionBackground:SetTexCoord(left,right,top,(bottom-top) * (bgSize/125) + top) else self.ExpansionBackground:SetHeight(125) self.ExpansionBackground:SetTexCoord(left,right,top,bottom) end self.ExpansionBackground:Show() else self.ExpansionBackground:Hide() end -- pet icon or portrait background if (settings.PetCardBackground=="Icon" or settings.PetCardBackground=="Portrait") and bgSize > 32 then if settings.PetCardBackground=="Icon" or petInfo.isSpecialType then self.PetBackground:SetTexture(petInfo.icon) else SetPortraitTextureFromCreatureDisplayID(self.PetBackground,petInfo.displayID) end self.FadeMask:SetSize(bgSize,bgSize) self.PetBackground:SetSize(bgSize,bgSize) self.PetBackground:Show() else self.PetBackground:Hide() end -- type icon background if settings.PetCardBackground=="Type" and petInfo.petType and petInfo.suffix and bgSize>32 then self.TypeBackground:SetTexture("Interface\\PetBattles\\PetIcon-"..petInfo.suffix) self.TypeBackground:SetSize(bgSize,bgSize) self.TypeBackground:Show() else self.TypeBackground:Hide() end end function rematch.petCard.Content.Front.Stats:UpdateModel() local petInfo = rematch.petInfo:Fetch(rematch.petCard.petID) -- model is confined to the top part of stats but doesn't need to be square local modelHeight = rematch.petCard.heights.fullStats - rematch.petCard.heights.statsBottom - 6 local modelWidth = max(min(modelHeight,floor(self:GetWidth()+0.5)),C.PET_CARD_MIN_MODEL_WIDTH) if not petInfo.displayID or settings.PetCardMinimized then self.PetModel:Hide() self.AltModel:Hide() self.displayID = nil elseif petInfo.petID~=self.petID or petInfo.displayID~=self.displayID or type(self.displayID)=="string" then self.petID = petInfo.petID self.displayID = petInfo.displayID if petInfo.speciesID then -- if this is an actual pet, use PetModel self.PetModel:SetSize(modelWidth,modelHeight) local modelSceneID = C_PetJournal.GetPetModelSceneInfoBySpeciesID(petInfo.speciesID) self.PetModel:TransitionToModelSceneID(modelSceneID,CAMERA_TRANSITION_TYPE_IMMEDIATE,CAMERA_MODIFICATION_TYPE_MAINTAIN,false) local actor = self.PetModel:GetActorByTag("unwrapped") if actor then actor:SetModelByCreatureDisplayID(petInfo.displayID) actor:SetAnimationBlendOperation(LE_MODEL_BLEND_OPERATION_NONE) actor:SetAnimation(0,-1) end self.AltModel:Hide() self.PetModel:Show() self.PetModel:PrepareForFanfare(petInfo.needsFanfare) elseif type(petInfo.displayID)=="string" then -- this is a named m2 model, use AltModel instead self.AltModel:SetSize(modelWidth,modelHeight) self.AltModel:SetModel(petInfo.displayID) self.AltModel:SetCamDistanceScale(0.45) self.AltModel:SetPosition(0,0,0.25) self.PetModel:Hide() self.AltModel:Show() end end end -- bottom back of the card with pet type name, racial ability and damage taken function rematch.petCard.Content.Back.Racial:Update() local petInfo = rematch.petInfo:Fetch(rematch.petCard.petID) if not petInfo.petType or petInfo.isSpecialType then return 0 -- no info about petTypes that don't exist or aren't an actual pet end self.TypeName:SetText(petInfo.petTypeName) self.TypeIcon:SetTexture("Interface\\PetBattles\\PetIcon-"..petInfo.suffix) self.StrongType:SetTexture("Interface\\PetBattles\\PetIcon-"..PET_TYPE_SUFFIX[C.HINTS_DEFENSE[petInfo.petType][1]]) self.WeakType:SetTexture("Interface\\PetBattles\\PetIcon-"..PET_TYPE_SUFFIX[C.HINTS_DEFENSE[petInfo.petType][2]]) -- some elements hidden when pet card minimized local notMinimized = not settings.PetCardMinimized self.TypeName:SetShown(notMinimized) self.TypeIcon:SetShown(notMinimized) self.TypeNameDoodadLeft:SetShown(notMinimized) self.TypeNameDoodadRight:SetShown(notMinimized) self.Racial:SetShown(notMinimized) self.Back:SetDesaturated(not petInfo.isOwned) -- set height based on whether minimized and height of racial text local height if settings.PetCardMinimized then height = floor(C.PET_CARD_RACIAL_MINIMIZED_HEIGHT+0.5) else self.Racial:SetText(settings.PetCardMinimized and "" or petInfo.passive) height = floor((C.PET_CARD_RACIAL_NORMAL_HEIGHT + self.Racial:GetStringHeight())+0.5) end self:SetHeight(height) rematch.petCard.heights.racial = height end function rematch.petCard.Content.Back.Source:Update() local petInfo = rematch.petInfo:Fetch(rematch.petCard.petID) local sourceText = petInfo.sourceText -- shrink font if source text is very long (some pets like spiders list nearly every zone in the game!) local sourceLength = (sourceText or ""):len() if sourceLength>0 then sourceText = sourceText:gsub("\124n$","") if settings.PetCardMinimized then -- if minimized, strip out newlines if minimized sourceText = sourceText:gsub("\124n"," ") end end if sourceLength>300 or settings.PetCardMinimized then self.Text:SetFontObject("GameFontHighlightSmall") if sourceLength>500 then -- if text is really really long, cut it short sourceText = sourceText:sub(1,500).."..." end else self.Text:SetFontObject("GameFontHighlight") end -- append expansion to the source (unless Show Expansion On Front is checked or there's no expansion) if not settings.PetCardShowExpansionStat and petInfo.expansionName then local padchar = settings.PetCardMinimized and " " or "\n" sourceText = sourceText..padchar.."\124cffffd200Expansion: "..rematch.utils:GetFormattedExpansionName(petInfo.expansionID) end if petInfo.isSpecialType then sourceText = nil elseif not petInfo.isObtainable then sourceText = L["This is an opponent pet."] end self.Text:SetText(sourceText) local height = floor((sourceText and self.Text:GetStringHeight()+C.PET_CARD_STAT_TOP_MARGIN*2+4 or 0)+0.5) self:SetHeight(height) rematch.petCard.heights.source = height end -- updates the middle back section of the card, flavor text about the pet function rematch.petCard.Content.Back.Lore:Update() local petInfo = rematch.petInfo:Fetch(rematch.petCard.petID) local loreText = petInfo.loreText self.Text:SetFontObject(settings.BoringLoreFont and "SystemFont_Med1" or "RematchPetCardLoreFont") self.Text:SetText(loreText) self.Back:SetDesaturated(not petInfo.isOwned) if petInfo.isObtainable then self.Back:SetVertexColor(1,1,1) else self.Back:SetVertexColor(0.25,0.25,0.25) end local height = floor(((loreText and loreText:len()>0) and self.Text:GetStringHeight()+C.PET_CARD_STAT_TOP_MARGIN*2 or 0)+0.5) for _,doodad in pairs(self.CornerDoodads) do -- hide little bracket things if lore section too small doodad:SetShown(height>20) doodad:SetDesaturated(not petInfo.isOwned) end rematch.petCard.heights.lore = height end --[[ pet card supporting functions ]] -- resets all changable heights of pet card sections function rematch.petCard:ResetHeights() self.heights.top = 0 self.heights.source = 0 self.heights.lore = 0 self.heights.racial = 0 self.heights.abilities = 0 self.heights.statsTop = 0 self.heights.statsBottom = 0 end -- returns true if the modifier key assigned to the flip key is down; or if key is given then whether that was a modifier key. -- (MODIFIER_STATE_CHANGED will flip a card based on the flip key going up or down) function rematch.petCard:IsFlipKeyUsed(key) local flipKey = settings.PetCardFlipKey if not key then -- if no key given, then check if a modifier key is down key = (IsAltKeyDown() and "ALT") or (IsShiftKeyDown() and "SHIFT") or (IsControlKeyDown() and "CTRL") end if flipKey=="None" then return false -- if flipkey is "None", don't bother elseif flipKey=="Alt" then return key=="LALT" or key=="RALT" or key=="ALT" elseif flipKey=="Shift" then return key=="LSHIFT" or key=="RSHIFT" or key=="SHIFT" elseif flipKey=="Ctrl" then return key=="LCTRL" or key=="RCTRL" or key=="CTRL" end end -- used by card manager, return true if the subject is a petID that has a card function rematch.petCard:ShouldShow(subject) local petInfo = rematch.petInfo:Fetch(subject) return petInfo.idType~="empty" and petInfo.idType~="unknown" and type(petInfo.name)=="string" end -- returns a formatted list of possible breeds, or nil if not applicable function rematch.petCard:GetPossibleBreedList(petInfo) if petInfo and petInfo.isObtainable and petInfo.canBattle and rematch.breedInfo:GetBreedSource() then local list if not petInfo.possibleBreedNames or #petInfo.possibleBreedNames==0 then list = UNKNOWN else list = table.concat(petInfo.possibleBreedNames,rematch.breedInfo:GetBreedFormat()==C.BREED_FORMAT_ICONS and " " or ", ") end return format("%s: \124cffe5e5e5%s",L["Possible Breeds"],list) end end -- returns a formatted Collected (0/3) along with the list of pets collected (rarity/level/breed) local collectedPets = {} -- reused table of collected pets function rematch.petCard:GetCollectedList(petInfo) if petInfo and petInfo.count and petInfo.isObtainable then local collected = petInfo.countColor..format(ITEM_PET_KNOWN,petInfo.count,petInfo.maxCount) -- Collected (0/3) bit if not petInfo.canBattle or petInfo.count==0 then return collected -- for non-battle or uncollected pets, don't list out levels and breeds, just collected count end wipe(collectedPets) for petID in rematch.roster:AllOwnedPets() do local altInfo = rematch.altInfo:Fetch(petID) if altInfo.speciesID==petInfo.speciesID then if altInfo.breedName then tinsert(collectedPets,format("%s%d %s",altInfo.color.hex,altInfo.level,altInfo.breedName)) else tinsert(collectedPets,format("%s%s %d",altInfo.color.hex,LEVEL,altInfo.level)) end end end return format("%s: %s",collected,table.concat(collectedPets,rematch.breedInfo:GetBreedFormat()==C.BREED_FORMAT_ICONS and " " or ", ")) end end -- releases all stat buttons from the button pool function rematch.petCard:ReleaseStatButtons() for _,button in ipairs(self.Content.Front.Stats.Buttons) do button.isUsed = nil button:Hide() end end -- creates and returns a stat button from the button pool function rematch.petCard:GetStatButton() local parent = self.Content.Front.Stats for _,button in ipairs(parent.Buttons) do if not button.isUsed then button.isUsed = true return button end end -- if reached here, all existing buttons used, create a new one local button = CreateFrame("Button",nil,parent,"RematchPetCardStatTemplate") tinsert(parent.Buttons,button) button.isUsed = true return button end -- fetches a stat button and fills its icon, text to the rematch.petCardStats[statIndex] for the petInfo -- returns the button if fetched so the calling function can anchor it function rematch.petCard:CreateStatButton(button,statIndex,petInfo) local button = rematch.petCard:GetStatButton() local info = rematch.petCardStats[statIndex] assert(type(info)=="table","Malformed stat at index "..(statIndex or "nil")) button:SetID(statIndex) button.Icon:SetTexture(rematch.utils:Evaluate(info.icon,rematch.petCard,petInfo)) local left,right,top,bottom = 0,1,0,1 if info.iconCoords then if type(info.iconCoords)=="function" then left,right,top,bottom = info.iconCoords(rematch.petCard,petInfo) elseif type(info.iconCoords)=="table" and #info.iconCoords==4 then left,right,top,bottom = info.iconCoords[1],info.iconCoords[2],info.iconCoords[3],info.iconCoords[4] end end button.Icon:SetTexCoord(left,right,top,bottom) button.Text:SetWidth(0) button.Text:SetText(rematch.utils:Evaluate(info.value,rematch.petCard,petInfo)) local textWidth = button.Text:GetStringWidth() if textWidth > 175 then -- 175 width max to text to prevent running over edge of card button.Text:SetWidth(175) end button:SetWidth(max(C.PET_CARD_STAT_WIDTH_MEDIUM,20+min(textWidth,175)+2)) return button end -- shows the breed table (tooltip-like frame displaying possible breeds and their stats for each breed) function rematch.petCard:ShowBreedTable(parent) local btable = rematch.petCard.Content.Front.Stats.BreedTable local petInfo = rematch.petInfo:Fetch(self.petID) local breedTable = rematch.breedInfo:GetBreedTable(petInfo.speciesID) local petBreed = petInfo.breedID for _,row in ipairs(btable.Rows) do row:Hide() end btable.Highlight:Hide() for index,info in ipairs(breedTable) do if not btable.Rows[index] then btable.Rows[index] = CreateFrame("Frame",nil,btable,"RematchBreedTableRowTemplate") btable.Rows[index]:SetPoint("TOPLEFT",8,-50-(index-1)*16) end local row = btable.Rows[index] row.Breed:SetText(rematch.breedInfo:GetBreedNameByID(info[1])) row.Health:SetText(info[2]) row.Power:SetText(info[3]) row.Speed:SetText(info[4]) if petBreed==info[1] then -- if breed in row is same as pet card pet, then highlight it btable.Highlight:SetPoint("TOPLEFT",row,2,0) btable.Highlight:SetPoint("BOTTOMRIGHT",row,-2,0) btable.Highlight:Show() end row:Show() end -- if no breeds known, display "No known breeds :(" if #breedTable==0 then btable.NoBreeds:Show() btable:SetHeight(32+87) else -- otherwise adjust height based on number of breeds listed btable.NoBreeds:Hide() btable:SetHeight(16*#breedTable+87) end -- position tooltip-like window next to the parent (breed stat button or possible breeds text) btable:ClearAllPoints() local corner,opposite = rematch.utils:GetCorner(rematch.utils:GetFrameForReference(parent),UIParent) btable:SetPoint(corner,parent,opposite) btable:Show() end function rematch.petCard:HideBreedTable() rematch.petCard.Content.Front.Stats.BreedTable:Hide() end --[[ titlebar button clicks ]] function rematch.petCard.PinButton:OnClick() rematch.cardManager:Unpin(self:GetParent()) end function rematch.petCard.FlipButton:OnClick() rematch.petCard.hardFlip = false rematch.petCard:Update() end function rematch.petCard.MinimizeButton:OnClick() settings.PetCardMinimized = not settings.PetCardMinimized self:GetParent():Configure() self:GetParent():Update() end --[[ script handlers ]] function rematch.petCard:OnMouseDown() rematch.cardManager.OnMouseDown(self) end function rematch.petCard:OnMouseUp() rematch.cardManager.OnMouseUp(self) end function rematch.petCard:OnDoubleClick() self.MinimizeButton:OnClick() end function rematch.petCard:OnShow() rematch.events:Register(self,"MODIFIER_STATE_CHANGED",self.MODIFIER_STATE_CHANGED) end function rematch.petCard:OnHide() rematch.events:Unregister(self,"MODIFIER_STATE_CHANGED") self.softFlip = false self.hardFlip = false rematch.petCard:UpdateLock() end function rematch.petCard.Content.Front.Stats.PossibleBreeds:OnEnter() self.Highlight:Show() rematch.petCard:ShowBreedTable(self) end function rematch.petCard.Content.Front.Stats.PossibleBreeds:OnLeave() self.Highlight:Hide() rematch.petCard:HideBreedTable() end --[[ seach hits ]] function rematch.petCard:UpdateSearchHits() local petInfo = rematch.petInfo:Fetch(self.petID) self.Content.Top.PetIcon.SearchHit:SetShown(self:IsPetNameSearchHit(petInfo)) self.Content.Top.TypeIcon.SearchHit:SetShown(self:IsPetTypeSearchHit(petInfo)) local abilityList = petInfo.abilityList if abilityList then for i=1,#abilityList do self.Content.Front.Abilities.Buttons[i].SearchHit:SetShown(self:IsAbilitySearchHit(petInfo,abilityList[i])) end end end -- returns true if a search is happening and the speciesName, customName or sourceText match the search function rematch.petCard:IsPetNameSearchHit(petInfo) local pattern = rematch.filters:Get("Search","Pattern") if pattern then if petInfo.speciesName and petInfo.speciesName:match(pattern) then return true elseif petInfo.customName and petInfo.customName:match(pattern) then return true elseif petInfo.sourceText and petInfo.sourceText:match(pattern) then return true end end return false end -- returns true if a Type or Tough Vs filter is happening and the pet type is one of the results function rematch.petCard:IsPetTypeSearchHit(petInfo) if petInfo.petType and rematch.filters:Get("Types",petInfo.petType) then return true elseif petInfo.toughVs and rematch.filters:Get("Tough",petInfo.toughVs) then return true end return false end -- returns true if a search is happening and the abilityName or abilityDescription matches the search, -- or a StrongVs or Similar filter is happening and the ability is one of the results function rematch.petCard:IsAbilitySearchHit(petInfo,abilityID) if not abilityID then return false end local pattern = rematch.filters:Get("Search","Pattern") local _,name,_,_,description,_,petType,noHints = C_PetBattles.GetAbilityInfoByID(abilityID) if pattern then if name and name:match(pattern) then return true elseif description and description:match(pattern) then return true end end if petInfo.strongVs and petInfo.strongVs[abilityID] and rematch.filters:Get("Strong",petInfo.strongVs[abilityID]) then return true elseif rematch.filters:Get("Similar",abilityID) then return true end return false end -- returns the teamID,ability1,ability,ability3 for the pet the pet card is anchored to, if any function rematch.petCard:GetTeamInfo() if self:IsVisible() then local relativeTo = rematch.cardManager:GetRelativeTo(rematch.petCard) local teamID = relativeTo and relativeTo.teamID local team = teamID and rematch.savedTeams[teamID] if team then for i=1,3 do if team.pets[i]==self.petID then -- found pet in team, return teamID and abilities used for this pet --local ability1,ability2,ability3 = rematch.petTags:GetAbilities(team.tags[i]) return teamID,rematch.petTags:GetAbilities(team.tags[i]) -- returns teamID,ability1,ability2,ability3 end end -- if reached here, didn't find the pet, just return teamID return teamID end end end -- hook of the function that calls SetItemRef to show the FloatingBattlePetTooltip -- note the dot notation! (SetItemRef doesn't pass a parent frame) function rematch.petCard.SetItemRef(link,text,button) if settings.PetCardForLinks and not IsModifiedClick("CHATLINK") and link:match("battlepet:%d+:%d+:%d+:%d+:%d+:%d+:.+") then FloatingBattlePetTooltip:Hide() local petID = link:match("(BattlePet-%d-[^:]+)") -- pull out petID from link if there is one local petInfo = rematch.petInfo:Fetch(petID) if petInfo.isOwned then link = petID -- the linked pet is owned, show the card for owned pet rather than link end if not rematch.petCard:IsVisible() or rematch.petCard.petID~=link then rematch.cardManager:SetItemRefMode(rematch.petCard) rematch.cardManager:ShowCard(rematch.petCard,link) else rematch.cardManager:HideCard(rematch.petCard) end end end