Pet Shop Roblox GUI Template with Buy & Equip Pets
A cartoony pet shop UI with rarity badges, buy buttons, coin balance, and equipped-pet preview panel. Designed for pet collection games, simulators, and RPGs where players can browse, purchase, and equip companion pets. Features 6 pet cards with visual rarity indicators, animated purchase flow, and a dedicated preview panel for the currently equipped pet.

Live preview
Pet Shop
1920×1080Includes real, production-ready Luau logic — not a static mockup.
What's inside
- • 6 pet cards with rarity badges
- • Coin balance header
- • Buy / Equip actions
- • Equipped pet preview
- • Server-side purchase validation
How to use this template
The Pet Shop template is built for pet collection games and simulators. Paste the client Luau into StarterGui and a shop panel appears with six pet cards, each showing a pet icon, rarity badge, and Buy button. The layout uses UIGridLayout so cards arrange in a clean grid that reflows on mobile. Clicking Buy fires a RemoteEvent to the server, which validates the purchase and grants the pet - the server Luau stub shows the validation pattern with MarketplaceService or your own currency system. The coin balance header updates in real time when the player buys. To customize, replace the placeholder pet data with your own pet IDs, icons, and prices. The rarity colors are driven by a lookup table, so adding a new rarity tier is one line. Test the purchase flow in Studio by firing the RemoteEvent manually and confirming the server responds correctly.
Add it to your game in 3 steps
- 1
Copy the Luau
Open the template in the web editor and click Export. Choose LocalScript to copy the full client Luau to your clipboard.
- 2
Paste into StarterGui
In Roblox Studio, right-click StarterGui in the Explorer, insert a LocalScript, and paste the copied Luau. Rename it to match the template.
- 3
Press Play to verify
Click Play in Studio. The GUI should appear exactly as designed. Tweak any Size or Position values in the script if you want to adjust the layout.
1--[[2 Pet Shop System - Client3 Features: 6 pet cards with rarity badges, coin balance, buy/equip, preview panel4 Place in: StarterPlayer > StarterPlayerScripts5--]]67local Players = game:GetService("Players")8local TweenService = game:GetService("TweenService")9local ReplicatedStorage = game:GetService("ReplicatedStorage")10local MarketplaceService = game:GetService("MarketplaceService")1112local player = Players.LocalPlayer13local playerGui = player:WaitForChild("PlayerGui")1415-- Remote Events16local PetShopRemotes = ReplicatedStorage:WaitForChild("PetShopRemotes")17local RequestPets = PetShopRemotes:WaitForChild("RequestPets")18local BuyPet = PetShopRemotes:WaitForChild("BuyPet")19local EquipPet = PetShopRemotes:WaitForChild("EquipPet")20local UnequipPet = PetShopRemotes:WaitForChild("UnequipPet")21local GetCoinBalance = PetShopRemotes:WaitForChild("GetCoinBalance")2223-- ============================================24-- CONFIGURATION25-- ============================================26local CONFIG = {27 AnimSpeed = 0.3,28 CardHoverScale = 1.04,29 PetsPerPage = 6,30 RarityColors = {31 Common = Color3.fromRGB(169, 169, 169),32 Uncommon = Color3.fromRGB(50, 180, 50),33 Rare = Color3.fromRGB(50, 120, 220),34 Epic = Color3.fromRGB(148, 50, 200),35 Legendary = Color3.fromRGB(220, 150, 30),36 Mythic = Color3.fromRGB(220, 50, 80),37 },38 RarityGlows = {39 Common = 1,40 Uncommon = 2,41 Rare = 3,42 Epic = 4,43 Legendary = 5,44 Mythic = 6,45 },46}4748-- ============================================49-- STATE50-- ============================================51local State = {52 IsVisible = false,53 Pets = {},54 OwnedPets = {},55 EquippedPet = nil,56 SelectedPet = nil,57 CoinBalance = 0,58 CurrentFilter = "All",59 PurchasePending = false,60}6162-- ============================================63-- UTILITY64-- ============================================65local function Create(className, properties)66 local instance = Instance.new(className)67 for key, value in pairs(properties or {}) do68 instance[key] = value69 end70 return instance71end7273local function Tween(instance, properties, duration, easingStyle, easingDirection)74 local tween = TweenService:Create(75 instance,76 TweenInfo.new(77 duration or CONFIG.AnimSpeed,78 easingStyle or Enum.EasingStyle.Quad,79 easingDirection or Enum.EasingDirection.Out80 ),81 properties82 )83 tween:Play()84 return tween85end8687local function FormatNumber(num)88 if num >= 1000000 then return string.format("%.1fM", num / 1000000)89 elseif num >= 1000 then return string.format("%.1fK", num / 1000)90 else return tostring(num) end91end9293-- ============================================94-- UI CONSTRUCTION95-- ============================================96local UI = {}9798function UI.Build()99 -- ScreenGui100 local screenGui = Create("ScreenGui", {101 Name = "PetShopGui",102 Parent = playerGui,103 ResetOnSpawn = false,104 ZIndexBehavior = Enum.ZIndexBehavior.Sibling,105 Enabled = false,106 })107 UI.ScreenGui = screenGui108109 -- Background Dim110 local bgDim = Create("Frame", {111 Name = "BackgroundDim",112 Parent = screenGui,113 Size = UDim2.new(1, 0, 1, 0),114 BackgroundColor3 = Color3.fromRGB(0, 0, 0),115 BackgroundTransparency = 0.5,116 BorderSizePixel = 0,117 ZIndex = 1,118 })119120 -- Main Frame121 local mainFrame = Create("Frame", {122 Name = "MainFrame",123 Parent = screenGui,124 AnchorPoint = Vector2.new(0.5, 0.5),125 Position = UDim2.new(0.5, 0, 0.5, 0),126 Size = UDim2.new(0, 650, 0, 450),127 BackgroundColor3 = Color3.fromRGB(50, 45, 65),128 BorderSizePixel = 0,129 ClipsDescendants = true,130 ZIndex = 10,131 })132 UI.MainFrame = mainFrame133134 Create("UICorner", {CornerRadius = UDim.new(0, 16), Parent = mainFrame})135 Create("UIGradient", {136 Color = ColorSequence.new({137 ColorSequenceKeypoint.new(0, Color3.fromRGB(55, 50, 75)),138 ColorSequenceKeypoint.new(1, Color3.fromRGB(42, 38, 58)),139 }),140 Rotation = 135,141 Parent = mainFrame,142 })143144 -- Header Frame145 local headerFrame = Create("Frame", {146 Name = "HeaderFrame",147 Parent = mainFrame,148 Size = UDim2.new(1, 0, 0, 56),149 BackgroundColor3 = Color3.fromRGB(60, 55, 80),150 BorderSizePixel = 0,151 ZIndex = 11,152 })153154 -- Shop Title155 Create("TextLabel", {156 Name = "ShopTitle",157 Parent = headerFrame,158 Position = UDim2.new(0, 18, 0, 0),159 Size = UDim2.new(0, 200, 1, 0),160 BackgroundTransparency = 1,161 Text = "PET SHOP",162 TextColor3 = Color3.fromRGB(255, 220, 100),163 TextSize = 26,164 Font = Enum.Font.GothamBlack,165 TextXAlignment = Enum.TextXAlignment.Left,166 ZIndex = 12,167 })168169 -- Coin Display170 local coinDisplay = Create("Frame", {171 Name = "CoinDisplay",172 Parent = headerFrame,173 Position = UDim2.new(1, -160, 0.5, -17),174 Size = UDim2.new(0, 130, 0, 34),175 BackgroundColor3 = Color3.fromRGB(45, 40, 30),176 BorderSizePixel = 0,177 ZIndex = 12,178 })179 Create("UICorner", {CornerRadius = UDim.new(0, 8), Parent = coinDisplay})180 Create("UIStroke", {Color = Color3.fromRGB(200, 160, 50), Thickness = 1, Parent = coinDisplay})181182 UI.CoinAmount = Create("TextLabel", {183 Name = "CoinAmount",184 Parent = coinDisplay,185 Position = UDim2.new(0, 32, 0, 0),186 Size = UDim2.new(1, -36, 1, 0),187 BackgroundTransparency = 1,188 Text = "12,500",189 TextColor3 = Color3.fromRGB(255, 200, 50),190 TextSize = 18,191 Font = Enum.Font.GothamBold,192 ZIndex = 13,193 })194195 -- Close Button196 local closeButton = Create("TextButton", {197 Name = "CloseButton",198 Parent = headerFrame,199 Position = UDim2.new(1, -42, 0, 10),200 Size = UDim2.new(0, 32, 0, 32),201 BackgroundColor3 = Color3.fromRGB(200, 60, 60),202 Text = "X",203 TextColor3 = Color3.fromRGB(255, 255, 255),204 TextSize = 18,205 Font = Enum.Font.GothamBold,206 ZIndex = 12,207 })208 Create("UICorner", {CornerRadius = UDim.new(0, 8), Parent = closeButton})209210 -- Category Tabs211 local tabsFrame = Create("Frame", {212 Name = "CategoryTabs",213 Parent = mainFrame,214 Position = UDim2.new(0, 0, 0, 56),215 Size = UDim2.new(1, 0, 0, 38),216 BackgroundColor3 = Color3.fromRGB(48, 43, 65),217 BorderSizePixel = 0,218 ZIndex = 11,219 })220 Create("UIListLayout", {221 FillDirection = Enum.FillDirection.Horizontal,222 HorizontalAlignment = Enum.HorizontalAlignment.Center,223 VerticalAlignment = Enum.VerticalAlignment.Center,224 Padding = UDim.new(0, 8),225 Parent = tabsFrame,226 })227228 local tabNames = {"All", "Common", "Rare", "Legendary"}229 UI.Tabs = {}230 for _, tabName in ipairs(tabNames) do231 local tabBtn = Create("TextButton", {232 Name = tabName .. "Tab",233 Parent = tabsFrame,234 Size = UDim2.new(0, 90, 0, 30),235 BackgroundColor3 = tabName == "All" and Color3.fromRGB(80, 70, 110) or Color3.fromRGB(55, 50, 75),236 Text = tabName,237 TextColor3 = Color3.fromRGB(220, 215, 240),238 TextSize = 14,239 Font = Enum.Font.GothamBold,240 ZIndex = 12,241 })242 Create("UICorner", {CornerRadius = UDim.new(0, 8), Parent = tabBtn})243 UI.Tabs[tabName] = tabBtn244 end245246 -- Content Area247 local contentArea = Create("Frame", {248 Name = "ContentArea",249 Parent = mainFrame,250 Position = UDim2.new(0, 0, 0, 94),251 Size = UDim2.new(1, 0, 1, -94),252 BackgroundTransparency = 1,253 ZIndex = 11,254 })255256 -- Pet Grid (Left side)257 local petGrid = Create("ScrollingFrame", {258 Name = "PetGrid",259 Parent = contentArea,260 Position = UDim2.new(0, 10, 0, 0),261 Size = UDim2.new(0, 405, 1, -10),262 BackgroundTransparency = 1,263 ScrollBarThickness = 6,264 ScrollBarImageColor3 = Color3.fromRGB(80, 75, 100),265 CanvasSize = UDim2.new(0, 0, 0, 0),266 ZIndex = 12,267 })268 UI.PetGrid = petGrid269270 Create("UIGridLayout", {271 CellSize = UDim2.new(0, 190, 0, 210),272 CellPadding = UDim2.new(0, 12, 0, 12),273 SortOrder = Enum.SortOrder.Name,274 Parent = petGrid,275 })276277 -- Preview Panel (Right side)278 local previewPanel = Create("Frame", {279 Name = "PreviewPanel",280 Parent = contentArea,281 Position = UDim2.new(0, 420, 0, 5),282 Size = UDim2.new(0, 215, 1, -15),283 BackgroundColor3 = Color3.fromRGB(45, 42, 60),284 BorderSizePixel = 0,285 ZIndex = 12,286 })287 Create("UICorner", {CornerRadius = UDim.new(0, 12), Parent = previewPanel})288289 -- Panel Title290 Create("TextLabel", {291 Name = "PanelTitle",292 Parent = previewPanel,293 Position = UDim2.new(0, 0, 0, 8),294 Size = UDim2.new(1, 0, 0, 26),295 BackgroundTransparency = 1,296 Text = "YOUR PET",297 TextColor3 = Color3.fromRGB(200, 190, 230),298 TextSize = 16,299 Font = Enum.Font.GothamBold,300 ZIndex = 13,301 })302303 -- Preview Image Frame304 local previewImageFrame = Create("Frame", {305 Name = "PreviewImageFrame",306 Parent = previewPanel,307 Position = UDim2.new(0.5, -80, 0, 38),308 Size = UDim2.new(0, 160, 0, 160),309 BackgroundColor3 = Color3.fromRGB(55, 52, 72),310 BorderSizePixel = 0,311 ZIndex = 13,312 })313 Create("UICorner", {CornerRadius = UDim.new(0, 12), Parent = previewImageFrame})314 UI.PreviewImage = Create("ImageLabel", {315 Name = "PreviewImage",316 Parent = previewImageFrame,317 Size = UDim2.new(1, -12, 1, -12),318 Position = UDim2.new(0, 6, 0, 6),319 BackgroundTransparency = 1,320 Image = "",321 ZIndex = 14,322 })323324 -- Equipped Badge325 UI.EquippedBadge = Create("Frame", {326 Name = "EquippedBadge",327 Parent = previewImageFrame,328 Position = UDim2.new(0, 6, 0, 6),329 Size = UDim2.new(0, 70, 0, 22),330 BackgroundColor3 = Color3.fromRGB(50, 180, 80),331 BorderSizePixel = 0,332 Visible = false,333 ZIndex = 15,334 })335 Create("UICorner", {CornerRadius = UDim.new(0, 6), Parent = UI.EquippedBadge})336 Create("TextLabel", {337 Parent = UI.EquippedBadge,338 Size = UDim2.new(1, 0, 1, 0),339 BackgroundTransparency = 1,340 Text = "EQUIPPED",341 TextColor3 = Color3.fromRGB(255, 255, 255),342 TextSize = 11,343 Font = Enum.Font.GothamBold,344 ZIndex = 16,345 })346347 -- Equipped Name348 UI.EquippedName = Create("TextLabel", {349 Name = "EquippedName",350 Parent = previewPanel,351 Position = UDim2.new(0, 0, 0, 205),352 Size = UDim2.new(1, 0, 0, 22),353 BackgroundTransparency = 1,354 Text = "No Pet Equipped",355 TextColor3 = Color3.fromRGB(200, 200, 220),356 TextSize = 16,357 Font = Enum.Font.GothamBold,358 ZIndex = 13,359 })360361 -- Equipped Rarity362 UI.EquippedRarity = Create("TextLabel", {363 Name = "EquippedRarity",364 Parent = previewPanel,365 Position = UDim2.new(0, 0, 0, 228),366 Size = UDim2.new(1, 0, 0, 18),367 BackgroundTransparency = 1,368 Text = "Select a pet",369 TextColor3 = Color3.fromRGB(160, 160, 180),370 TextSize = 13,371 Font = Enum.Font.GothamSemibold,372 ZIndex = 13,373 })374375 -- Equipped Stats Bars376 local statsFrame = Create("Frame", {377 Name = "EquippedStats",378 Parent = previewPanel,379 Position = UDim2.new(0, 12, 0, 255),380 Size = UDim2.new(1, -24, 0, 100),381 BackgroundTransparency = 1,382 ZIndex = 13,383 })384385 local statNames = {"Speed", "Power", "Luck"}386 local statColors = {387 Speed = Color3.fromRGB(50, 180, 220),388 Power = Color3.fromRGB(220, 80, 60),389 Luck = Color3.fromRGB(180, 220, 60),390 }391 UI.StatBars = {}392 for i, statName in ipairs(statNames) do393 local yPos = (i - 1) * 32394 Create("TextLabel", {395 Parent = statsFrame,396 Position = UDim2.new(0, 0, 0, yPos),397 Size = UDim2.new(0, 55, 0, 18),398 BackgroundTransparency = 1,399 Text = statName,400 TextColor3 = Color3.fromRGB(180, 175, 200),401 TextSize = 12,402 Font = Enum.Font.GothamSemibold,403 TextXAlignment = Enum.TextXAlignment.Left,404 ZIndex = 14,405 })406 local barBg = Create("Frame", {407 Parent = statsFrame,408 Position = UDim2.new(0, 58, 0, yPos + 2),409 Size = UDim2.new(1, -60, 0, 14),410 BackgroundColor3 = Color3.fromRGB(35, 32, 48),411 BorderSizePixel = 0,412 ZIndex = 14,413 })414 Create("UICorner", {CornerRadius = UDim.new(0, 7), Parent = barBg})415 local barFill = Create("Frame", {416 Parent = barBg,417 Size = UDim2.new(0, 0, 1, 0),418 BackgroundColor3 = statColors[statName],419 BorderSizePixel = 0,420 ZIndex = 15,421 })422 Create("UICorner", {CornerRadius = UDim.new(0, 7), Parent = barFill})423 UI.StatBars[statName] = barFill424 end425426 -- Equip Action Button427 UI.EquipButton = Create("TextButton", {428 Name = "EquipActionButton",429 Parent = previewPanel,430 Position = UDim2.new(0.5, -80, 1, -48),431 Size = UDim2.new(0, 160, 0, 38),432 BackgroundColor3 = Color3.fromRGB(50, 160, 70),433 Text = "EQUIP",434 TextColor3 = Color3.fromRGB(255, 255, 255),435 TextSize = 16,436 Font = Enum.Font.GothamBold,437 Visible = false,438 ZIndex = 13,439 })440 Create("UICorner", {CornerRadius = UDim.new(0, 10), Parent = UI.EquipButton})441442 -- Unequip Action Button443 UI.UnequipButton = Create("TextButton", {444 Name = "UnequipActionButton",445 Parent = previewPanel,446 Position = UDim2.new(0.5, -80, 1, -48),447 Size = UDim2.new(0, 160, 0, 38),448 BackgroundColor3 = Color3.fromRGB(160, 80, 50),449 Text = "UNEQUIP",450 TextColor3 = Color3.fromRGB(255, 255, 255),451 TextSize = 16,452 Font = Enum.Font.GothamBold,453 Visible = false,454 ZIndex = 13,455 })456 Create("UICorner", {CornerRadius = UDim.new(0, 10), Parent = UI.UnequipButton})457458 -- Purchase Modal459 local purchaseModal = Create("Frame", {460 Name = "PurchaseModal",461 Parent = screenGui,462 AnchorPoint = Vector2.new(0.5, 0.5),463 Position = UDim2.new(0.5, 0, 0.5, 0),464 Size = UDim2.new(0, 340, 0, 280),465 BackgroundColor3 = Color3.fromRGB(45, 42, 62),466 BorderSizePixel = 0,467 Visible = false,468 ZIndex = 200,469 })470 UI.PurchaseModal = purchaseModal471 Create("UICorner", {CornerRadius = UDim.new(0, 16), Parent = purchaseModal})472 Create("UIStroke", {Color = Color3.fromRGB(200, 170, 60), Thickness = 2, Parent = purchaseModal})473474 Create("TextLabel", {475 Name = "ModalTitle",476 Parent = purchaseModal,477 Position = UDim2.new(0, 0, 0, 12),478 Size = UDim2.new(1, 0, 0, 30),479 BackgroundTransparency = 1,480 Text = "CONFIRM PURCHASE",481 TextColor3 = Color3.fromRGB(255, 220, 100),482 TextSize = 20,483 Font = Enum.Font.GothamBlack,484 ZIndex = 201,485 })486 UI.ModalPetImage = Create("ImageLabel", {487 Name = "ModalPetImage",488 Parent = purchaseModal,489 Position = UDim2.new(0.5, -50, 0, 48),490 Size = UDim2.new(0, 100, 0, 100),491 BackgroundTransparency = 1,492 Image = "",493 ZIndex = 201,494 })495 UI.ModalPetName = Create("TextLabel", {496 Name = "ModalPetName",497 Parent = purchaseModal,498 Position = UDim2.new(0, 0, 0, 152),499 Size = UDim2.new(1, 0, 0, 24),500 BackgroundTransparency = 1,501 Text = "Pet Name",502 TextColor3 = Color3.fromRGB(255, 255, 255),503 TextSize = 18,504 Font = Enum.Font.GothamBold,505 ZIndex = 201,506 })507 UI.ModalPrice = Create("TextLabel", {508 Name = "ModalPrice",509 Parent = purchaseModal,510 Position = UDim2.new(0, 0, 0, 178),511 Size = UDim2.new(1, 0, 0, 22),512 BackgroundTransparency = 1,513 Text = "2,500 Coins",514 TextColor3 = Color3.fromRGB(255, 200, 50),515 TextSize = 16,516 Font = Enum.Font.GothamBold,517 ZIndex = 201,518 })519 local confirmBtn = Create("TextButton", {520 Name = "ConfirmButton",521 Parent = purchaseModal,522 Position = UDim2.new(0, 20, 0, 215),523 Size = UDim2.new(0, 135, 0, 40),524 BackgroundColor3 = Color3.fromRGB(50, 180, 80),525 Text = "BUY",526 TextColor3 = Color3.fromRGB(255, 255, 255),527 TextSize = 18,528 Font = Enum.Font.GothamBlack,529 ZIndex = 201,530 })531 Create("UICorner", {CornerRadius = UDim.new(0, 10), Parent = confirmBtn})532 UI.ConfirmPurchaseButton = confirmBtn533534 local cancelBtn = Create("TextButton", {535 Name = "CancelButton",536 Parent = purchaseModal,537 Position = UDim2.new(0, 185, 0, 215),538 Size = UDim2.new(0, 135, 0, 40),539 BackgroundColor3 = Color3.fromRGB(160, 60, 60),540 Text = "CANCEL",541 TextColor3 = Color3.fromRGB(255, 255, 255),542 TextSize = 18,543 Font = Enum.Font.GothamBlack,544 ZIndex = 201,545 })546 Create("UICorner", {CornerRadius = UDim.new(0, 10), Parent = cancelBtn})547 UI.CancelPurchaseButton = cancelBtn548549 -- Notification Frame550 UI.NotificationFrame = Create("Frame", {551 Name = "NotificationFrame",552 Parent = screenGui,553 AnchorPoint = Vector2.new(0.5, 0),554 Position = UDim2.new(0.5, 0, 0, -60),555 Size = UDim2.new(0, 300, 0, 44),556 BackgroundColor3 = Color3.fromRGB(50, 45, 65),557 BorderSizePixel = 0,558 Visible = false,559 ZIndex = 500,560 })561 Create("UICorner", {CornerRadius = UDim.new(0, 10), Parent = UI.NotificationFrame})562 Create("UIStroke", {Color = Color3.fromRGB(80, 180, 80), Thickness = 2, Parent = UI.NotificationFrame})563 UI.NotificationText = Create("TextLabel", {564 Name = "NotificationText",565 Parent = UI.NotificationFrame,566 Size = UDim2.new(1, 0, 1, 0),567 BackgroundTransparency = 1,568 Text = "Purchase successful!",569 TextColor3 = Color3.fromRGB(255, 255, 255),570 TextSize = 15,571 Font = Enum.Font.GothamBold,572 ZIndex = 501,573 })574575 return UI576end577578-- ============================================579-- PET CARD CREATION580-- ============================================581function UI.CreatePetCard(petData, index)582 local rarityColor = CONFIG.RarityColors[petData.Rarity] or CONFIG.RarityColors.Common583 local card = Create("Frame", {584 Name = "PetCard_" .. string.format("%02d", index),585 Parent = UI.PetGrid,586 Size = UDim2.new(0, 190, 0, 210),587 BackgroundColor3 = Color3.fromRGB(52, 48, 70),588 BorderSizePixel = 0,589 ZIndex = 13,590 })591 Create("UICorner", {CornerRadius = UDim.new(0, 12), Parent = card})592 local stroke = Create("UIStroke", {593 Color = rarityColor,594 Thickness = 2,595 Parent = card,596 })597598 -- Pet Image599 local petImage = Create("ImageLabel", {600 Name = "PetImage",601 Parent = card,602 Position = UDim2.new(0.5, -60, 0, 8),603 Size = UDim2.new(0, 120, 0, 100),604 BackgroundTransparency = 1,605 Image = petData.Icon or "",606 ZIndex = 14,607 })608609 -- Rarity Badge610 local badge = Create("Frame", {611 Name = "RarityBadge",612 Parent = card,613 Position = UDim2.new(0, 6, 0, 6),614 Size = UDim2.new(0, 70, 0, 20),615 BackgroundColor3 = rarityColor,616 BorderSizePixel = 0,617 ZIndex = 15,618 })619 Create("UICorner", {CornerRadius = UDim.new(0, 6), Parent = badge})620 Create("TextLabel", {621 Parent = badge,622 Size = UDim2.new(1, 0, 1, 0),623 BackgroundTransparency = 1,624 Text = string.upper(petData.Rarity or "Common"),625 TextColor3 = Color3.fromRGB(255, 255, 255),626 TextSize = 10,627 Font = Enum.Font.GothamBold,628 ZIndex = 16,629 })630631 -- Pet Name632 Create("TextLabel", {633 Name = "PetName",634 Parent = card,635 Position = UDim2.new(0, 0, 0, 114),636 Size = UDim2.new(1, 0, 0, 22),637 BackgroundTransparency = 1,638 Text = petData.Name or "Unknown",639 TextColor3 = Color3.fromRGB(240, 235, 255),640 TextSize = 15,641 Font = Enum.Font.GothamBold,642 ZIndex = 14,643 })644645 -- Pet Stats646 Create("TextLabel", {647 Name = "PetStats",648 Parent = card,649 Position = UDim2.new(0, 0, 0, 136),650 Size = UDim2.new(1, 0, 0, 16),651 BackgroundTransparency = 1,652 Text = string.format("SPD: %d | PWR: %d", petData.Stats.Speed, petData.Stats.Power),653 TextColor3 = Color3.fromRGB(160, 155, 180),654 TextSize = 11,655 Font = Enum.Font.Gotham,656 ZIndex = 14,657 })658659 -- Price / Owned Button660 local priceBtn = Create("TextButton", {661 Name = "PriceButton",662 Parent = card,663 Position = UDim2.new(0.5, -70, 0, 160),664 Size = UDim2.new(0, 140, 0, 36),665 BackgroundColor3 = Color3.fromRGB(55, 130, 70),666 Text = " " .. FormatNumber(petData.Price),667 TextColor3 = Color3.fromRGB(255, 255, 255),668 TextSize = 15,669 Font = Enum.Font.GothamBold,670 ZIndex = 14,671 })672 Create("UICorner", {CornerRadius = UDim.new(0, 8), Parent = priceBtn})673674 return {675 Frame = card,676 Stroke = stroke,677 PetImage = petImage,678 PriceButton = priceBtn,679 Data = petData,680 }681end682683-- ============================================684-- LOGIC685-- ============================================686local Logic = {}687688function Logic.SetupInteractions()689 -- Close button690 UI.MainFrame.HeaderFrame.CloseButton.MouseButton1Click:Connect(function()691 Logic.Hide()692 end)693694 -- Tab filtering695 for tabName, tabBtn in pairs(UI.Tabs) do696 tabBtn.MouseButton1Click:Connect(function()697 Logic.SetFilter(tabName)698 end)699 end700701 -- Purchase buttons702 UI.ConfirmPurchaseButton.MouseButton1Click:Connect(function()703 Logic.ConfirmPurchase()704 end)705 UI.CancelPurchaseButton.MouseButton1Click:Connect(function()706 Logic.HidePurchaseModal()707 end)708709 -- Equip / Unequip710 UI.EquipButton.MouseButton1Click:Connect(function()711 if State.SelectedPet then712 Logic.EquipPet(State.SelectedPet.Id)713 end714 end)715 UI.UnequipButton.MouseButton1Click:Connect(function()716 Logic.UnequipPet()717 end)718end719720function Logic.LoadPets()721 -- In production: local pets = RequestPets:InvokeServer()722 -- Demo data723 State.Pets = {724 {725 Id = "pet_dragon",726 Name = "Fire Dragon",727 Rarity = "Legendary",728 Icon = "rbxassetid://12345",729 Price = 5000,730 Stats = {Speed = 85, Power = 95, Luck = 70},731 Description = "A mighty fire-breathing dragon.",732 },733 {734 Id = "pet_phoenix",735 Name = "Phoenix",736 Rarity = "Legendary",737 Icon = "rbxassetid://12346",738 Price = 4500,739 Stats = {Speed = 90, Power = 80, Luck = 85},740 Description = "Rises from the ashes.",741 },742 {743 Id = "pet_wolf",744 Name = "Shadow Wolf",745 Rarity = "Rare",746 Icon = "rbxassetid://12347",747 Price = 2500,748 Stats = {Speed = 92, Power = 65, Luck = 60},749 Description = "A loyal shadow companion.",750 },751 {752 Id = "pet_cat",753 Name = "Lucky Cat",754 Rarity = "Uncommon",755 Icon = "rbxassetid://12348",756 Price = 1000,757 Stats = {Speed = 60, Power = 40, Luck = 95},758 Description = "Brings good fortune.",759 },760 {761 Id = "pet_dog",762 Name = "Golden Retriever",763 Rarity = "Common",764 Icon = "rbxassetid://12349",765 Price = 500,766 Stats = {Speed = 70, Power = 50, Luck = 65},767 Description = "A faithful friend.",768 },769 {770 Id = "pet_unicorn",771 Name = "Rainbow Unicorn",772 Rarity = "Epic",773 Icon = "rbxassetid://12350",774 Price = 3500,775 Stats = {Speed = 80, Power = 70, Luck = 90},776 Description = "Sparkles with magic.",777 },778 }779780 State.OwnedPets = {781 pet_dog = true, -- Demo: player owns the dog782 }783 State.EquippedPet = "pet_dog"784785 Logic.RefreshPetGrid()786 Logic.RefreshPreview()787end788789function Logic.RefreshPetGrid()790 -- Clear existing cards791 for _, child in ipairs(UI.PetGrid:GetChildren()) do792 if child:IsA("Frame") then child:Destroy() end793 end794 UI.PetCards = {}795796 -- Create cards based on filter797 local index = 0798 for _, pet in ipairs(State.Pets) do799 if State.CurrentFilter == "All" or pet.Rarity == State.CurrentFilter then800 index = index + 1801 local card = UI.CreatePetCard(pet, index)802 table.insert(UI.PetCards, card)803804 -- Setup card interactions805 card.Frame.MouseEnter:Connect(function()806 Tween(card.Frame, {Size = UDim2.new(0, 190 * CONFIG.CardHoverScale, 0, 210 * CONFIG.CardHoverScale)}, 0.15)807 card.Stroke.Thickness = 3 + (CONFIG.RarityGlows[pet.Rarity] or 1)808 end)809 card.Frame.MouseLeave:Connect(function()810 Tween(card.Frame, {Size = UDim2.new(0, 190, 0, 210)}, 0.15)811 card.Stroke.Thickness = 2812 end)813814 card.PriceButton.MouseButton1Click:Connect(function()815 Logic.OnPriceButtonClick(pet)816 end)817818 card.Frame.InputBegan:Connect(function(input)819 if input.UserInputType == Enum.UserInputType.MouseButton1 or820 input.UserInputType == Enum.UserInputType.Touch then821 Logic.SelectPet(pet)822 end823 end)824 end825 end826827 -- Update canvas size828 local rows = math.ceil(index / 2)829 UI.PetGrid.CanvasSize = UDim2.new(0, 0, 0, rows * 222)830end831832function Logic.OnPriceButtonClick(pet)833 local isOwned = State.OwnedPets[pet.Id]834 if isOwned then835 -- If owned, select and equip836 Logic.SelectPet(pet)837 Logic.EquipPet(pet.Id)838 else839 -- If not owned, show purchase modal840 Logic.ShowPurchaseModal(pet)841 end842end843844function Logic.SelectPet(pet)845 State.SelectedPet = pet846 Logic.RefreshPreview()847end848849function Logic.RefreshPreview()850 local pet = State.SelectedPet851 if not pet then852 -- Show equipped pet or empty state853 if State.EquippedPet then854 for _, p in ipairs(State.Pets) do855 if p.Id == State.EquippedPet then856 pet = p857 break858 end859 end860 end861 end862863 if pet then864 UI.PreviewImage.Image = pet.Icon or ""865 UI.EquippedName.Text = pet.Name866 UI.EquippedName.TextColor3 = CONFIG.RarityColors[pet.Rarity] or Color3.fromRGB(255, 255, 255)867 UI.EquippedRarity.Text = pet.Rarity868 UI.EquippedRarity.TextColor3 = CONFIG.RarityColors[pet.Rarity] or Color3.fromRGB(200, 200, 200)869870 -- Update stat bars with animation871 local maxStat = 100872 Tween(UI.StatBars.Speed, {Size = UDim2.new(math.clamp(pet.Stats.Speed / maxStat, 0, 1), 0, 1, 0)}, 0.4)873 Tween(UI.StatBars.Power, {Size = UDim2.new(math.clamp(pet.Stats.Power / maxStat, 0, 1), 0, 1, 0)}, 0.4)874 Tween(UI.StatBars.Luck, {Size = UDim2.new(math.clamp(pet.Stats.Luck / maxStat, 0, 1), 0, 1, 0)}, 0.4)875876 -- Show equipped badge877 local isEquipped = State.EquippedPet == pet.Id878 UI.EquippedBadge.Visible = isEquipped879 UI.EquippedBadge.BackgroundColor3 = CONFIG.RarityColors[pet.Rarity]880881 -- Show/hide equip/unequip buttons882 local isOwned = State.OwnedPets[pet.Id]883 if isEquipped then884 UI.EquipButton.Visible = false885 UI.UnequipButton.Visible = true886 elseif isOwned then887 UI.EquipButton.Visible = true888 UI.UnequipButton.Visible = false889 else890 UI.EquipButton.Visible = false891 UI.UnequipButton.Visible = false892 end893 else894 UI.PreviewImage.Image = ""895 UI.EquippedName.Text = "No Pet Equipped"896 UI.EquippedName.TextColor3 = Color3.fromRGB(200, 200, 220)897 UI.EquippedRarity.Text = "Select a pet"898 UI.EquippedBadge.Visible = false899 UI.EquipButton.Visible = false900 UI.UnequipButton.Visible = false901 Tween(UI.StatBars.Speed, {Size = UDim2.new(0, 0, 1, 0)}, 0.3)902 Tween(UI.StatBars.Power, {Size = UDim2.new(0, 0, 1, 0)}, 0.3)903 Tween(UI.StatBars.Luck, {Size = UDim2.new(0, 0, 1, 0)}, 0.3)904 end905end906907function Logic.SetFilter(filter)908 State.CurrentFilter = filter909910 -- Update tab visuals911 for tabName, tabBtn in pairs(UI.Tabs) do912 tabBtn.BackgroundColor3 = tabName == filter913 and Color3.fromRGB(80, 70, 110)914 or Color3.fromRGB(55, 50, 75)915 end916917 Logic.RefreshPetGrid()918end919920function Logic.ShowPurchaseModal(pet)921 if State.PurchasePending then return end922923 UI.ModalPetImage.Image = pet.Icon or ""924 UI.ModalPetName.Text = pet.Name925 UI.ModalPetName.TextColor3 = CONFIG.RarityColors[pet.Rarity]926 UI.ModalPrice.Text = FormatNumber(pet.Price) .. " Coins"927928 UI.PurchaseModal.Visible = true929 UI.PurchaseModal.Size = UDim2.new(0, 300, 0, 250)930 Tween(UI.PurchaseModal, {Size = UDim2.new(0, 340, 0, 280)}, 0.25, Enum.EasingStyle.Back, Enum.EasingDirection.Out)931end932933function Logic.HidePurchaseModal()934 Tween(UI.PurchaseModal, {Size = UDim2.new(0, 300, 0, 250)}, 0.2)935 task.delay(0.2, function()936 UI.PurchaseModal.Visible = false937 end)938end939940function Logic.ConfirmPurchase()941 if State.PurchasePending then return end942 if not State.SelectedPet then return end943944 State.PurchasePending = true945 UI.ConfirmPurchaseButton.Text = "Buying..."946 UI.ConfirmPurchaseButton.BackgroundColor3 = Color3.fromRGB(100, 100, 100)947948 -- Fire server949 local result = BuyPet:InvokeServer(State.SelectedPet.Id)950951 if result.Success then952 State.OwnedPets[State.SelectedPet.Id] = true953 State.CoinBalance = result.NewBalance or State.CoinBalance954 UI.CoinAmount.Text = FormatNumber(State.CoinBalance)955956 Logic.ShowNotification("Purchase successful! You got " .. State.SelectedPet.Name)957 Logic.RefreshPetGrid()958959 -- Auto-equip960 Logic.EquipPet(State.SelectedPet.Id)961 else962 Logic.ShowNotification(result.Message or "Purchase failed!")963 end964965 UI.ConfirmPurchaseButton.Text = "BUY"966 UI.ConfirmPurchaseButton.BackgroundColor3 = Color3.fromRGB(50, 180, 80)967 State.PurchasePending = false968 Logic.HidePurchaseModal()969end970971function Logic.EquipPet(petId)972 local result = EquipPet:InvokeServer(petId)973 if result.Success then974 State.EquippedPet = petId975 Logic.RefreshPreview()976 Logic.RefreshPetGrid()977 Logic.ShowNotification("Pet equipped!")978 end979end980981function Logic.UnequipPet()982 local result = UnequipPet:InvokeServer()983 if result.Success then984 State.EquippedPet = nil985 Logic.RefreshPreview()986 Logic.ShowNotification("Pet unequipped!")987 end988end989990function Logic.ShowNotification(message)991 UI.NotificationText.Text = message992 UI.NotificationFrame.Visible = true993 UI.NotificationFrame.Position = UDim2.new(0.5, 0, 0, -60)994 Tween(UI.NotificationFrame, {Position = UDim2.new(0.5, 0, 0, 20)}, 0.3, Enum.EasingStyle.Back, Enum.EasingDirection.Out)995996 task.delay(2.5, function()997 Tween(UI.NotificationFrame, {Position = UDim2.new(0.5, 0, 0, -60)}, 0.3)998 task.delay(0.3, function()999 UI.NotificationFrame.Visible = false1000 end)1001 end)1002end10031004function Logic.Show()1005 State.IsVisible = true1006 UI.ScreenGui.Enabled = true1007 UI.MainFrame.Size = UDim2.new(0, 580, 0, 400)1008 Tween(UI.MainFrame, {Size = UDim2.new(0, 650, 0, 450)}, 0.3, Enum.EasingStyle.Back, Enum.EasingDirection.Out)1009 Logic.LoadPets()1010end10111012function Logic.Hide()1013 State.IsVisible = false1014 Tween(UI.MainFrame, {Size = UDim2.new(0, 580, 0, 400)}, 0.2)1015 task.delay(0.2, function()1016 if not State.IsVisible then1017 UI.ScreenGui.Enabled = false1018 end1019 end)1020end10211022-- ============================================1023-- INITIALIZATION1024-- ============================================1025UI.Build()1026Logic.SetupInteractions()10271028-- Show the shop immediately for demo1029Logic.Show()10301031-- Or bind to a key/button:1032-- local function onInputBegan(input, gameProcessed)1033-- if gameProcessed then return end1034-- if input.KeyCode == Enum.KeyCode.P then Logic.Toggle() end1035-- end1036-- UserInputService.InputBegan:Connect(onInputBegan)10371038print("Pet Shop System initialized!")
