local _, addon = ... local SetModelLight = addon.TransitionAPI.SetModelLight; local PAGE_FORMAT = PAGED_LIST_PAGING_FORMAT or "Page %s / %s"; --PRODUCT_CHOICE_PAGE_NUMBER local MAX_PETS = (NUM_PET_STABLE_PAGES and NUM_PET_STABLE_SLOTS and NUM_PET_STABLE_PAGES * NUM_PET_STABLE_SLOTS) or 200; local MAX_ROW = 2; local MAX_COL = 8; local SLOT_PER_PAGE = MAX_ROW * MAX_COL; local format = string.format; local FadeFrame = NarciFadeUI.Fade; local GetStablePetInfo = GetStablePetInfo; local SetPetStablePaperdoll = SetPetStablePaperdoll; local NEW_GetStablePetInfo = C_StableInfo and C_StableInfo.GetStablePetInfo; local MainFrame, PetModel, ModelShadow, Tooltip, SelectionOverlay, PageText, PageControl, DropDownButtons, PetSlots; local TARGET_MODEL_INDEX; local ACTOR_CREATED = false; ----------------------------------------------------- local function SetPetModel(model, index) if SetPetStablePaperdoll then SetPetStablePaperdoll(model, index); elseif NEW_GetStablePetInfo then local petInfo = C_StableInfo.GetStablePetInfo(index); if petInfo and petInfo.displayID then model:SetDisplayInfo(petInfo.displayID); end end end --UI Animations local outQuart = addon.EasingFunctions.outQuart; local animExpand = NarciAPI_CreateAnimationFrame(0.25); animExpand:SetScript("OnUpdate", function(self, elapsed) self.total = self.total + elapsed; local height = outQuart(self.total, self.fromHeight, self.toHeight, self.duration); if self.total >= self.duration then height = self.toHeight; self:Hide(); end self.object:SetHeight(height); end); --Opening/closing animation local cos = math.cos; local pi = math.pi; local function inOutSine(t, b, e, d) return (b - e) / 2 * (cos(pi * t / d) - 1) + b end local animSizing = NarciAPI_CreateAnimationFrame(0.25); animSizing.relativeTo = Narci_ActorPanelPopUp.PetStableToggle; animSizing:SetScript("OnShow", function(self) self.startWidth, self.startHeight = MainFrame:GetSize(); end); local function Sizing_OnUpdate(self, elapsed) self.total = self.total + elapsed; local alpha = self.fromAlpha + self.increment * self.total / self.duration; local height = inOutSine(self.total, self.startHeight, self.endHeight, self.duration); if self.total >= self.duration then alpha = 1; height = self.endHeight; self:Hide(); end MainFrame:SetHeight(height); if alpha > 1 then alpha = 1; elseif alpha < 0 then alpha = 0; end --[[ if ModelShadow then ModelShadow:SetAlpha(alpha); PetModel:SetAlpha(alpha); end MainFrame.PetSlotFrame:SetAlpha(alpha); MainFrame.FilterButton:SetAlpha(alpha); PageControl:SetAlpha(alpha); --]] end animSizing:SetScript("OnUpdate", Sizing_OnUpdate); local function PlayToggleAnimation(state) if animSizing:IsShown() then return end if state then animSizing.endHeight = 224; animSizing.fromAlpha = 0; animSizing.increment = 1; FadeFrame(MainFrame, 0.25, 1); else animSizing.endHeight = 64; animSizing.fromAlpha = 1; animSizing.increment = -1; FadeFrame(MainFrame, 0.2, 0); end animSizing:Show(); end --Model Animation local function SycAnimation(m) PetModel:SetAnimation(0, 0); ModelShadow:SetAnimation(0, 0); end ----------------------------------------------------- local AddButtonScripts = {}; function AddButtonScripts.OnClick(f) MainFrame:ConfirmPet(); end function AddButtonScripts.OnEnter(f) f.Icon:SetVertexColor(1, 1, 1); f.Label:SetTextColor(1, 1, 1); end function AddButtonScripts.OnLeave(f) f.Icon:SetVertexColor(0.6, 0.6 ,0.6); f.Label:SetTextColor(0.8, 0.8, 0.8); end function AddButtonScripts.OnMouseDown(f) f.Icon:SetSize(28, 28); f.Background:SetSize(28, 28); end function AddButtonScripts.OnMouseUp(f) f.Icon:SetSize(32, 32); f.Background:SetSize(32, 32); end local function SortFunc(a, b) --active pet first (index <=5 ) else: icon then index if a[1] > 5 and b[1] > 5 then if a[2] == b[2] then return a[1] < b[1] else return a[2] < b[2] end else return a[1] < b[1] end end local DataProvider = {}; local function DataRetriever_OnUpdate(self, elapsed) self.index = self.index + 1; local petIcon, petName, petLevel, petType, petTalents = GetStablePetInfo(self.index); if petIcon then DataProvider.numPets = DataProvider.numPets + 1; local petTypeIndex = DataProvider:GetPetTypeIndex(petType); DataProvider.data[DataProvider.numPets] = {self.index, petIcon, petName, petTypeIndex}; end if self.index >= MAX_PETS then self:Hide(); DataProvider:OnDataReceived(); end self.t = self.t + elapsed; if self.t > 0.08 then self.t = 0; self.ProgressText:SetText(format(self.progressFormat, self.index)); end end function DataProvider:ClearData() if self.data then wipe(self.data); else self.data = {}; end if self.types then wipe(self.types); wipe(self.typeNames); wipe(self.typeCounts); else self.types = {}; self.typeNames = {}; self.typeCounts = {}; end self.numTypes = 0; self.numPets = 0; end function DataProvider:GetPetTypeIndex(petName) if not self.types[petName] then self.numTypes = self.numTypes + 1; self.types[petName] = self.numTypes; self.typeNames[self.numTypes] = petName; self.typeCounts[self.numTypes] = 1; return self.numTypes; else self.typeCounts[self.numTypes] = self.typeCounts[self.numTypes] + 1; return self.types[petName] end end function DataProvider:GetPetTypeName(petTypeIndex) return self.typeNames[petTypeIndex] end function DataProvider:GetTypeCount(petTypeIndex) return self.typeCounts[petTypeIndex] end function DataProvider:GetNumTypes() return self.numTypes or 0; end function DataProvider:GetNumPets() return self.numPets or 0; end function DataProvider:GetPetName(petIndex) return (self.filteredData[petIndex] and self.filteredData[petIndex][3]) or "Pet" end function DataProvider:UpdatePetData() self:ClearData(); if not self.retriever then self.retriever = CreateFrame("Frame"); self.retriever:Hide(); self.retriever:SetScript("OnUpdate", DataRetriever_OnUpdate); self.retriever.progressFormat = "%s/" .. MAX_PETS; self.retriever.ProgressText = MainFrame.LoadingIndicator.Progress; end self.isProcessing = true; self.retriever:Hide(); self.retriever.index = 0; self.retriever.t = 0; self.retriever:Show(); SelectionOverlay:Hide(); MainFrame.LoadingIndicator:SetAlpha(1); MainFrame.LoadingIndicator:Show(); --Instant Process --[[ local petIcon, petName, petLevel, petType, petTalents, petTypeIndex; local numPets = 0; for i = 1, MAX_PETS do petIcon, petName, petLevel, petType, petTalents = GetStablePetInfo(i); if petIcon then numPets = numPets + 1; petTypeIndex = self:GetPetTypeIndex(petName); self.data[numPets] = {i, petIcon, petName, petTypeIndex}; end end if numPets > 0 then table.sort(self.data, SortFunc); local numPages = math.ceil(numPets / SLOT_PER_PAGE); MainFrame.numPages = numPages; else MainFrame.numPages = 0; end self.filteredData = self.data; --]] end function DataProvider:OnDataReceived() if self.numPets > 0 then table.sort(self.data, SortFunc); local numPages = math.ceil(self.numPets / SLOT_PER_PAGE); MainFrame.numPages = numPages; else MainFrame.numPages = 0; end self.filteredData = self.data; self.isProcessing = nil; FadeFrame(MainFrame.LoadingIndicator, 0.12, 0); MainFrame:UpdatePetSlots(); end function DataProvider:GetPetInfoByIndex(index) return self.filteredData[index]; end function DataProvider:SetFilter(petTypeIndex) local numData = 0; if petTypeIndex then self.filteredData = {}; for i = 1, #self.data do if self.data[i][4] == petTypeIndex then numData = numData + 1; self.filteredData[numData] = self.data[i]; end end else self.filteredData = self.data; numData = #self.data; end return numData end local function SelectFilterDropDownButton(button) for k, b in pairs(DropDownButtons) do if b == button then b.TypeName:SetTextColor(0.92, 0.92, 0.92); else b.TypeName:SetTextColor(0.65, 0.65, 0.65); end end end local function SetUpFilterOptions() local f = MainFrame.FilterDropDown; local numTypes = DataProvider:GetNumTypes(); if MainFrame.rebuiltDropDown then MainFrame.rebuiltDropDown = nil; local typeInfo = {}; for i = 1, numTypes do typeInfo[i] = {i, DataProvider:GetPetTypeName(i)}; end table.sort(typeInfo, function(a, b) return a[2] > b[2] end); if numTypes > 0 then if not DropDownButtons then DropDownButtons = {}; end local textWidth = 0; local maxWidth = 0; local buttons = DropDownButtons; local button; for i = 1, numTypes do button = buttons[i]; if not button then button = CreateFrame("Button", nil, f, "NarciPetTypeDropDownButtonTemplate"); button:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 0, 16 * (i - 1)); buttons[i] = button; end if typeInfo[i] then textWidth = button:SetUp(typeInfo[i][1], typeInfo[i][2]); if textWidth > maxWidth then maxWidth = textWidth; end end button:Show(); end for i = numTypes + 1, #buttons do buttons[i]:Hide(); end --Adjust DropDown width if maxWidth < 96 then maxWidth = 96; end for i = 1, numTypes do buttons[i]:SetButtonWidth(maxWidth); end f:SetSize(maxWidth, numTypes * 16); f.height = numTypes * 16; end end if numTypes > 0 then MainFrame:ToggleDropDown(not f:IsShown()); end end local FilterButtonScripts = {}; function FilterButtonScripts.OnEnter(f) f.Label:SetTextColor(1, 1, 1); f.Highlight:Show(); end function FilterButtonScripts.OnLeave(f) if f.hasFilter then f.Label:SetTextColor(0.25, 0.78, 0.92); else f.Label:SetTextColor(0.8, 0.8, 0.8); end f.Highlight:Hide(); end function FilterButtonScripts:OnClick(f) SetUpFilterOptions(); end function FilterButtonScripts:OnDoubleClick(f) return end local PageButtonScripts = {}; function PageButtonScripts.OnEnter(f) f.Highlight:Show(); end function PageButtonScripts.OnLeave(f) f.Highlight:Hide(); end function PageButtonScripts.OnClick(f) MainFrame:OnMouseWheel(f.increment); end function PageButtonScripts.OnMouseDown(f) f.Icon:SetSize(14, 14); end function PageButtonScripts.OnMouseUp(f) f.Icon:SetSize(16, 16); end function PageButtonScripts.OnEnable(f) f.Icon:SetVertexColor(1, 1, 1); f.Background:SetTexCoord(0.875, 1, 0, 0.125); end function PageButtonScripts.OnDisable(f) f.Icon:SetVertexColor(0.5, 0.5, 0.5); f.Background:SetTexCoord(0.875, 1, 0.125, 0.25); end local RemoveFilterScripts = {}; RemoveFilterScripts.OnMouseDown = PageButtonScripts.OnMouseDown; RemoveFilterScripts.OnMouseUp = PageButtonScripts.OnMouseUp; RemoveFilterScripts.OnEnter = PageButtonScripts.OnEnter; RemoveFilterScripts.OnLeave = PageButtonScripts.OnLeave; function RemoveFilterScripts.OnClick(f) local numData = DataProvider:SetFilter(nil); MainFrame:ResetPage(numData); MainFrame.FilterButton.Label:SetText(FILTER); MainFrame.FilterButton.hasFilter = nil; f:Hide(); SelectFilterDropDownButton(nil); end local FilterDropDownScripts = {}; function FilterDropDownScripts.OnEvent(f) if not (f:IsMouseOver() or (MainFrame.FilterButton:IsMouseOver() and not MainFrame.FilterButton.RemoveFilter:IsMouseOver() ) ) then MainFrame:ToggleDropDown(false); end end function FilterDropDownScripts.OnShow(f) f:RegisterEvent("GLOBAL_MOUSE_DOWN"); end function FilterDropDownScripts.OnHide(f) f:UnregisterEvent("GLOBAL_MOUSE_DOWN"); end NarciPetStableMixin = {}; function NarciPetStableMixin:Init() local SIZE = 24; local row, col = 1, 1; local button; local container = self; PetSlots = {}; for i = 1, MAX_ROW * MAX_COL do button = CreateFrame("Button", nil, self.PetSlotFrame, "NarciPetSlotButtonTemplate"); PetSlots[i] = button; button:SetPoint("BOTTOMLEFT", self, "BOTTOMLEFT", 0 + SIZE * (col - 1), 0 + SIZE * (2 - row)); button.index = i; col = col + 1; if col > MAX_COL then col = 1; row = row + 1; end end self.numSlots = #PetSlots; --Preview Model PetModel = CreateFrame("PlayerModel", nil, container); ModelShadow = CreateFrame("PlayerModel", nil, container); for k, model in pairs( {PetModel, ModelShadow} ) do model:SetKeepModelOnHide(true); model:SetScript("OnModelLoaded", SycAnimation); model:UseModelCenterToTransform(true); model:SetFacing(math.pi/6); model:SetCamDistanceScale(1.3); model:SetPoint("TOPLEFT", self, "TOPLEFT", 0, -16); model:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 0, 64); end SetModelLight(PetModel, true, false, - 0.44699833180028 , 0.72403680806459 , -0.52532198881773, 0.8, 172/255, 172/255, 172/255, 1, 0.8, 0.8, 0.8); local a = 0.1; ModelShadow:SetFogColor(a, a, a); SetModelLight(ModelShadow, false, false); ModelShadow:SetViewTranslation(6, 0); local backdrop = PetModel:CreateTexture(nil, "BACKGROUND"); backdrop:SetPoint("TOPLEFT", PetModel, "TOPLEFT", 0, 0); backdrop:SetPoint("BOTTOMRIGHT", PetModel, "BOTTOMRIGHT", 0, 0); backdrop:SetTexture("Interface/AddOns/Narcissus/Art/Modules/PhotoMode/PetStable/ModelBackground"); --Add Model Button local AddButton = self.AddButton; AddButton.Icon:SetTexture("Interface/AddOns/Narcissus/Art/Modules/PhotoMode/PetStable/AddButton", nil, nil, "TRILINEAR"); AddButton.Icon:SetTexCoord(0.5, 1, 0, 1); AddButton.Background:SetTexture("Interface/AddOns/Narcissus/Art/Modules/PhotoMode/PetStable/AddButton", nil, nil, "TRILINEAR"); AddButton.Background:SetTexCoord(0, 0.5, 0, 1); local offset = 16; AddButton:ClearAllPoints(); AddButton:SetPoint("CENTER", self, "TOP", offset - 192/2, -offset - 16); for methodName, method in pairs(AddButtonScripts) do AddButton:SetScript(methodName, method); end AddButtonScripts.OnLeave(AddButton); --Filter Button; local FilterButton = self.FilterButton; for methodName, method in pairs(FilterButtonScripts) do FilterButton:SetScript(methodName, method); end FilterButtonScripts.OnLeave(FilterButton); local RemoveFilter = FilterButton.RemoveFilter; for methodName, method in pairs(RemoveFilterScripts) do RemoveFilter:SetScript(methodName, method); end --Page Control local LeftButton = PageControl.Left; local RightButton = PageControl.Right; LeftButton.increment = 1; RightButton.increment = -1; for methodName, method in pairs(PageButtonScripts) do LeftButton:SetScript(methodName, method); RightButton:SetScript(methodName, method); end self.Init = nil; end function NarciPetStableMixin:UpdatePetSlots() if self.Init then self:Init(); end self:UpdatePage(); self.rebuiltDropDown = true; PetSlots[1]:Click(); end function NarciPetStableMixin:OnEvent(event) if event then self.requireUpdate = true; end end function NarciPetStableMixin:OnLoad() local _, _, classID = UnitClass("player"); if classID and classID == 3 then MainFrame = self; Tooltip = self.Tooltip; SelectionOverlay = self.SelectionOverlay; PageControl = self.PageControl; PageText = PageControl.PageText; self:RegisterEvent("PET_STABLE_UPDATE"); self.requireUpdate = true; self.page = 1; for methodName, method in pairs(FilterDropDownScripts) do self.FilterDropDown:SetScript(methodName, method); end animExpand.object = self.FilterDropDown; self.LoadingIndicator.ProgressHeader:SetText(Narci.L["PetStable Loading"]); --Update Phantom Popup Layout local popup = Narci_ActorPanelPopUp; popup.BackdropMiddle:SetHeight(104); --88 local npcToggle = popup.BrowserToggle; npcToggle:ClearAllPoints(); npcToggle:SetPoint("CENTER", popup, "CENTER", 0, 8 + 24 * 2); npcToggle:SetHitRectInsets(0, 0, 0, 0); popup.PetStableToggle:Show(); self:SetHeight(64); self:SetAlpha(0); else self:Hide(); end end function NarciPetStableMixin:SelectPet(petIndex) SetPetModel(PetModel, petIndex); SetPetModel(ModelShadow, petIndex); PetModel:SetAnimation(0, 0); ModelShadow:SetAnimation(0, 0); self.selectedPetIndex = petIndex; end function NarciPetStableMixin:ConfirmPet() local petIndex = self.selectedPetIndex; if petIndex then ACTOR_CREATED = true; NarciPhotoModeAPI.OverrideActorInfo(TARGET_MODEL_INDEX, DataProvider:GetPetName(petIndex), nil, self.petIcon); local newActor = self.targetModel; C_Timer.After(0, function() SetPetModel(newActor, self.selectedPetIndex); end); end end function NarciPetStableMixin:UpdatePage() local page = self.page; local hasSelection = false; if self.numPages > 0 then local realIndex; local indexOffset = SLOT_PER_PAGE * (page - 1); local hasPet; for i = 1, self.numSlots do realIndex = i + indexOffset; PetSlots[i]:Disable(); hasPet = PetSlots[i]:SetData( DataProvider:GetPetInfoByIndex(realIndex) ); if not hasSelection and hasPet and realIndex == self.selectedPetIndex then hasSelection = true; SelectionOverlay:ClearAllPoints(); SelectionOverlay:SetPoint("CENTER", PetSlots[i], "CENTER", 0, 0); end end PageText:SetText(format(PAGE_FORMAT, self.page, self.numPages)); PageControl.Right:SetEnabled(self.page < self.numPages); PageControl.Left:SetEnabled(self.page > 1); else for i = 1, self.numSlots do PetSlots[i]:DisableSlot(); end PageText:SetText(format(PAGE_FORMAT, 0, 0)); PageControl.Left:Disable(); PageControl.Right:Disable(); end if hasSelection then SelectionOverlay:Show(); else SelectionOverlay:Hide(); end end function NarciPetStableMixin:ResetPage(numData) self.page = 1; local numPages = math.ceil(numData / SLOT_PER_PAGE); self.numPages = numPages; self:UpdatePage(); end function NarciPetStableMixin:OnMouseWheel(delta) if self.numPages and self.numPages > 0 then if delta < 0 then self.page = self.page + 1; else self.page = self.page - 1; end if self.page > self.numPages then self.page = self.numPages; elseif self.page < 1 then self.page = 1; else self:UpdatePage(); end end end function NarciPetStableMixin:ToggleDropDown(state) if state then FadeFrame(self.FilterDropDown, 0.2, 1); animExpand.fromHeight = 8; animExpand.toHeight = self.FilterDropDown.height; else FadeFrame(self.FilterDropDown, 0.25, 0); animExpand.fromHeight = self.FilterDropDown.height; animExpand.toHeight = 4; end animExpand:Show(); end function NarciPetStableMixin:Open(anchorButton) local PopUp = Narci_ActorPanelPopUp; FadeFrame(PopUp, 0.15, 0); self:ClearAllPoints(); self:SetPoint("TOP", anchorButton, "TOP", 0, 16); Narci_ModelSettings:SetPanelAlpha(0.5, true); local index = PopUp.Index; local isPet = true; self.targetModel = NarciPhotoModeAPI.CreateEmptyModelForNPCBrowser(index, isPet); --Defined in PlayerModel.lua self:SetFrameLevel(76); TARGET_MODEL_INDEX = index; PlayToggleAnimation(true); end function NarciPetStableMixin:Close() PlayToggleAnimation(false); Narci_ModelSettings:SetPanelAlpha(1, true); if not ACTOR_CREATED then NarciPhotoModeAPI.RemoveActor(TARGET_MODEL_INDEX) end ACTOR_CREATED = false; end function NarciPetStableMixin:OnShow() if self.requireUpdate then self.requireUpdate = nil; DataProvider:UpdatePetData(); end end function NarciPetStableMixin:OnHide() self:Hide(); end function NarciPetStableMixin:IsFocused() return self:IsShown() and self:IsMouseOver() end NarciPetSlotButtonMixin = {}; function NarciPetSlotButtonMixin:OnEnter() self:SetHighlight(true); local petType = DataProvider:GetPetTypeName(self.petTypeIndex); if self.petName and petType then Tooltip:ClearAllPoints(); if self.petName == petType then Tooltip.Name:SetText(self.petName); else Tooltip.Name:SetText(self.petName.. " ("..petType..")"); end Tooltip:SetPoint("BOTTOMLEFT", self, "TOPLEFT", 0, 0); Tooltip:Show(); end end function NarciPetSlotButtonMixin:OnLeave() self:SetHighlight(false); Tooltip:Hide(); end function NarciPetSlotButtonMixin:SetHighlight(state) if state then self.Icon:SetVertexColor(1, 1, 1); self.Icon:SetDesaturation(0); else self.Icon:SetVertexColor(0.80, 0.80, 0.80); self.Icon:SetDesaturation(0.2); end end function NarciPetSlotButtonMixin:OnClick() MainFrame:SelectPet(self.index); SelectionOverlay:ClearAllPoints(); SelectionOverlay:SetPoint("CENTER", self, "CENTER", 0, 0); SelectionOverlay:Show(); local AddButton = MainFrame.AddButton; AddButton.Label:SetText(self.petName); local textWidth = AddButton.Label:GetWidth(); if textWidth < 32 then textWidth = 32; end AddButton:SetHitRectInsets(-2, -textWidth - 4, 0, 0); MainFrame.petIcon = self.Icon:GetTexture(); end function NarciPetSlotButtonMixin:SetIcon(texture) self.Icon:SetTexture(texture); self.Icon:SetTexCoord(0.075, 0.925, 0.075, 0.925); self:SetHighlight(false); end function NarciPetSlotButtonMixin:DisableSlot() self:Disable(); self.Icon:SetTexture("Interface/AddOns/Narcissus/Art/Modules/PhotoMode/PetStable/EmptySlot"); self.Icon:SetTexCoord(0, 1, 0, 1); self:SetHighlight(true); self.petName = nil; self.petTypeIndex = nil; end function NarciPetSlotButtonMixin:SetData(data) --data = {index, petIcon, petName, petTypeIndex} if data then self.index = data[1]; self:SetIcon(data[2]); self.petName = data[3]; self.petTypeIndex = data[4]; self:Enable(); return true else self:DisableSlot(); return false end end NarciPetTypeDropDownButtonMixin = {}; function NarciPetTypeDropDownButtonMixin:OnEnter() FadeFrame(self.Highlight, 0.12, 1); end function NarciPetTypeDropDownButtonMixin:OnLeave() FadeFrame(self.Highlight, 0.2, 0); end function NarciPetTypeDropDownButtonMixin:OnClick() local numData = DataProvider:SetFilter(self.petTypeIndex); MainFrame:ResetPage(numData); MainFrame.FilterButton.RemoveFilter:Show(); MainFrame.FilterButton.Label:SetText(self.TypeName:GetText()); MainFrame.FilterButton.Label:SetTextColor(0.25, 0.78, 0.92); MainFrame.FilterButton.hasFilter = true; SelectFilterDropDownButton(self); end function NarciPetTypeDropDownButtonMixin:SetButtonWidth(width) --Min width 96 self:SetWidth(width); self.BackdropCenter:SetWidth(width - 32); end function NarciPetTypeDropDownButtonMixin:SetUp(petTypeIndex, name) if name then self.TypeName:SetText(name); else self.TypeName:SetText( DataProvider:GetPetTypeName(petTypeIndex) ); end self.Count:SetText( DataProvider:GetTypeCount(petTypeIndex) ); self.petTypeIndex = petTypeIndex; return (self.TypeName:GetWidth() + self.Count:GetWidth() + 24); end